1
I don't have anything else queued up at the moment, so this is just
1
Arm queue; not huge but I figured I might as well send it out since
2
Richard's SME patches.
2
I've been doing code review today and there's no queue of unprocessed
3
pullreqs...
3
4
5
thanks
4
-- PMM
6
-- PMM
5
7
6
The following changes since commit 63b38f6c85acd312c2cab68554abf33adf4ee2b3:
8
The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:
7
9
8
Merge tag 'pull-target-arm-20220707' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2022-07-08 06:17:11 +0530)
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)
9
11
10
are available in the Git repository at:
12
are available in the Git repository at:
11
13
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220711
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210112
13
15
14
for you to fetch changes up to f9982ceaf26df27d15547a3a7990a95019e9e3a8:
16
for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:
15
17
16
linux-user/aarch64: Add SME related hwcap entries (2022-07-11 13:43:52 +0100)
18
ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)
17
19
18
----------------------------------------------------------------
20
----------------------------------------------------------------
19
target-arm:
21
target-arm queue:
20
* Implement SME emulation, for both system and linux-user
22
* arm: Support emulation of ARMv8.4-TTST extension
23
* arm: Update cpu.h ID register field definitions
24
* arm: Fix breakage of XScale instruction emulation
25
* hw/net/lan9118: Fix RX Status FIFO PEEK value
26
* npcm7xx: Add ADC and PWM emulation
27
* ui/cocoa: Make "open docs" help menu entry work again when binary
28
is run from the build tree
29
* ui/cocoa: Fix openFile: deprecation on Big Sur
30
* docs: Add qemu-storage-daemon(1) manpage to meson.build
31
* docs: Build and install all the docs in a single manual
21
32
22
----------------------------------------------------------------
33
----------------------------------------------------------------
23
Richard Henderson (45):
34
Hao Wu (6):
24
target/arm: Handle SME in aarch64_cpu_dump_state
35
hw/misc: Add clock converter in NPCM7XX CLK module
25
target/arm: Add infrastructure for disas_sme
36
hw/timer: Refactor NPCM7XX Timer to use CLK clock
26
target/arm: Trap non-streaming usage when Streaming SVE is active
37
hw/adc: Add an ADC module for NPCM7XX
27
target/arm: Mark ADR as non-streaming
38
hw/misc: Add a PWM module for NPCM7XX
28
target/arm: Mark RDFFR, WRFFR, SETFFR as non-streaming
39
hw/misc: Add QTest for NPCM7XX PWM Module
29
target/arm: Mark BDEP, BEXT, BGRP, COMPACT, FEXPA, FTSSEL as non-streaming
40
hw/*: Use type casting for SysBusDevice in NPCM7XX
30
target/arm: Mark PMULL, FMMLA as non-streaming
31
target/arm: Mark FTSMUL, FTMAD, FADDA as non-streaming
32
target/arm: Mark SMMLA, UMMLA, USMMLA as non-streaming
33
target/arm: Mark string/histo/crypto as non-streaming
34
target/arm: Mark gather/scatter load/store as non-streaming
35
target/arm: Mark gather prefetch as non-streaming
36
target/arm: Mark LDFF1 and LDNF1 as non-streaming
37
target/arm: Mark LD1RO as non-streaming
38
target/arm: Add SME enablement checks
39
target/arm: Handle SME in sve_access_check
40
target/arm: Implement SME RDSVL, ADDSVL, ADDSPL
41
target/arm: Implement SME ZERO
42
target/arm: Implement SME MOVA
43
target/arm: Implement SME LD1, ST1
44
target/arm: Export unpredicated ld/st from translate-sve.c
45
target/arm: Implement SME LDR, STR
46
target/arm: Implement SME ADDHA, ADDVA
47
target/arm: Implement FMOPA, FMOPS (non-widening)
48
target/arm: Implement BFMOPA, BFMOPS
49
target/arm: Implement FMOPA, FMOPS (widening)
50
target/arm: Implement SME integer outer product
51
target/arm: Implement PSEL
52
target/arm: Implement REVD
53
target/arm: Implement SCLAMP, UCLAMP
54
target/arm: Reset streaming sve state on exception boundaries
55
target/arm: Enable SME for -cpu max
56
linux-user/aarch64: Clear tpidr2_el0 if CLONE_SETTLS
57
linux-user/aarch64: Reset PSTATE.SM on syscalls
58
linux-user/aarch64: Add SM bit to SVE signal context
59
linux-user/aarch64: Tidy target_restore_sigframe error return
60
linux-user/aarch64: Do not allow duplicate or short sve records
61
linux-user/aarch64: Verify extra record lock succeeded
62
linux-user/aarch64: Move sve record checks into restore
63
linux-user/aarch64: Implement SME signal handling
64
linux-user: Rename sve prctls
65
linux-user/aarch64: Implement PR_SME_GET_VL, PR_SME_SET_VL
66
target/arm: Only set ZEN in reset if SVE present
67
target/arm: Enable SME for user-only
68
linux-user/aarch64: Add SME related hwcap entries
69
41
70
docs/system/arm/emulation.rst | 4 +
42
Leif Lindholm (6):
71
linux-user/aarch64/target_cpu.h | 5 +-
43
target/arm: fix typo in cpu.h ID_AA64PFR1 field name
72
linux-user/aarch64/target_prctl.h | 62 +-
44
target/arm: make ARMCPU.clidr 64-bit
73
target/arm/cpu.h | 7 +
45
target/arm: make ARMCPU.ctr 64-bit
74
target/arm/helper-sme.h | 126 ++++
46
target/arm: add descriptions of CLIDR_EL1, CCSIDR_EL1, CTR_EL0 to cpu.h
75
target/arm/helper-sve.h | 4 +
47
target/arm: add aarch64 ID register fields to cpu.h
76
target/arm/helper.h | 18 +
48
target/arm: add aarch32 ID register fields to cpu.h
77
target/arm/translate-a64.h | 45 ++
49
78
target/arm/translate.h | 16 +
50
Peter Maydell (5):
79
target/arm/sme-fa64.decode | 60 ++
51
docs: Add qemu-storage-daemon(1) manpage to meson.build
80
target/arm/sme.decode | 88 +++
52
docs: Build and install all the docs in a single manual
81
target/arm/sve.decode | 41 +-
53
target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
82
linux-user/aarch64/cpu_loop.c | 9 +
54
hw/net/lan9118: Fix RX Status FIFO PEEK value
83
linux-user/aarch64/signal.c | 243 ++++++--
55
hw/net/lan9118: Add symbolic constants for register offsets
84
linux-user/elfload.c | 20 +
56
85
linux-user/syscall.c | 28 +-
57
Roman Bolshakov (2):
86
target/arm/cpu.c | 35 +-
58
ui/cocoa: Update path to docs in build tree
87
target/arm/cpu64.c | 11 +
59
ui/cocoa: Fix openFile: deprecation on Big Sur
88
target/arm/helper.c | 56 +-
60
89
target/arm/sme_helper.c | 1140 +++++++++++++++++++++++++++++++++++++
61
Rémi Denis-Courmont (2):
90
target/arm/sve_helper.c | 28 +
62
target/arm: ARMv8.4-TTST extension
91
target/arm/translate-a64.c | 103 +++-
63
target/arm: enable Small Translation tables in max CPU
92
target/arm/translate-sme.c | 373 ++++++++++++
64
93
target/arm/translate-sve.c | 393 ++++++++++---
65
docs/conf.py | 46 ++-
94
target/arm/translate-vfp.c | 12 +
66
docs/devel/conf.py | 15 -
95
target/arm/translate.c | 2 +
67
docs/index.html.in | 17 -
96
target/arm/vec_helper.c | 24 +
68
docs/interop/conf.py | 28 --
97
target/arm/meson.build | 3 +
69
docs/meson.build | 65 ++--
98
28 files changed, 2821 insertions(+), 135 deletions(-)
70
docs/specs/conf.py | 16 -
99
create mode 100644 target/arm/sme-fa64.decode
71
docs/system/arm/nuvoton.rst | 4 +-
100
create mode 100644 target/arm/sme.decode
72
docs/system/conf.py | 28 --
101
create mode 100644 target/arm/translate-sme.c
73
docs/tools/conf.py | 37 --
74
docs/user/conf.py | 15 -
75
meson.build | 1 +
76
hw/adc/trace.h | 1 +
77
include/hw/adc/npcm7xx_adc.h | 69 ++++
78
include/hw/arm/npcm7xx.h | 4 +
79
include/hw/misc/npcm7xx_clk.h | 146 ++++++-
80
include/hw/misc/npcm7xx_pwm.h | 105 +++++
81
include/hw/timer/npcm7xx_timer.h | 1 +
82
target/arm/cpu.h | 85 ++++-
83
hw/adc/npcm7xx_adc.c | 301 +++++++++++++++
84
hw/arm/npcm7xx.c | 55 ++-
85
hw/arm/npcm7xx_boards.c | 2 +-
86
hw/mem/npcm7xx_mc.c | 2 +-
87
hw/misc/npcm7xx_clk.c | 807 ++++++++++++++++++++++++++++++++++++++-
88
hw/misc/npcm7xx_gcr.c | 2 +-
89
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++
90
hw/misc/npcm7xx_rng.c | 2 +-
91
hw/net/lan9118.c | 26 +-
92
hw/nvram/npcm7xx_otp.c | 2 +-
93
hw/ssi/npcm7xx_fiu.c | 2 +-
94
hw/timer/npcm7xx_timer.c | 39 +-
95
target/arm/cpu64.c | 1 +
96
target/arm/helper.c | 15 +-
97
target/arm/translate.c | 7 +
98
tests/qtest/npcm7xx_adc-test.c | 377 ++++++++++++++++++
99
tests/qtest/npcm7xx_pwm-test.c | 490 ++++++++++++++++++++++++
100
hw/adc/meson.build | 1 +
101
hw/adc/trace-events | 5 +
102
hw/misc/meson.build | 1 +
103
hw/misc/trace-events | 6 +
104
tests/qtest/meson.build | 4 +-
105
ui/cocoa.m | 7 +-
106
41 files changed, 3124 insertions(+), 263 deletions(-)
107
delete mode 100644 docs/devel/conf.py
108
delete mode 100644 docs/index.html.in
109
delete mode 100644 docs/interop/conf.py
110
delete mode 100644 docs/specs/conf.py
111
delete mode 100644 docs/system/conf.py
112
delete mode 100644 docs/tools/conf.py
113
delete mode 100644 docs/user/conf.py
114
create mode 100644 hw/adc/trace.h
115
create mode 100644 include/hw/adc/npcm7xx_adc.h
116
create mode 100644 include/hw/misc/npcm7xx_pwm.h
117
create mode 100644 hw/adc/npcm7xx_adc.c
118
create mode 100644 hw/misc/npcm7xx_pwm.c
119
create mode 100644 tests/qtest/npcm7xx_adc-test.c
120
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
121
create mode 100644 hw/adc/trace-events
122
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Dump SVCR, plus use the correct access check for Streaming Mode.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220708151540.18136-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/cpu.c | 17 ++++++++++++++++-
11
1 file changed, 16 insertions(+), 1 deletion(-)
12
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.c
16
+++ b/target/arm/cpu.c
17
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
18
int i;
19
int el = arm_current_el(env);
20
const char *ns_status;
21
+ bool sve;
22
23
qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
24
for (i = 0; i < 32; i++) {
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
26
el,
27
psr & PSTATE_SP ? 'h' : 't');
28
29
+ if (cpu_isar_feature(aa64_sme, cpu)) {
30
+ qemu_fprintf(f, " SVCR=%08" PRIx64 " %c%c",
31
+ env->svcr,
32
+ (FIELD_EX64(env->svcr, SVCR, ZA) ? 'Z' : '-'),
33
+ (FIELD_EX64(env->svcr, SVCR, SM) ? 'S' : '-'));
34
+ }
35
if (cpu_isar_feature(aa64_bti, cpu)) {
36
qemu_fprintf(f, " BTYPE=%d", (psr & PSTATE_BTYPE) >> 10);
37
}
38
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
39
qemu_fprintf(f, " FPCR=%08x FPSR=%08x\n",
40
vfp_get_fpcr(env), vfp_get_fpsr(env));
41
42
- if (cpu_isar_feature(aa64_sve, cpu) && sve_exception_el(env, el) == 0) {
43
+ if (cpu_isar_feature(aa64_sme, cpu) && FIELD_EX64(env->svcr, SVCR, SM)) {
44
+ sve = sme_exception_el(env, el) == 0;
45
+ } else if (cpu_isar_feature(aa64_sve, cpu)) {
46
+ sve = sve_exception_el(env, el) == 0;
47
+ } else {
48
+ sve = false;
49
+ }
50
+
51
+ if (sve) {
52
int j, zcr_len = sve_vqm1_for_el(env, el);
53
54
for (i = 0; i <= FFR_PRED_NUM; i++) {
55
--
56
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
This new behaviour is in the ARM pseudocode function
3
This adds for the Small Translation tables extension in AArch64 state.
4
AArch64.CheckFPAdvSIMDEnabled, which applies to AArch32
5
via AArch32.CheckAdvSIMDOrFPEnabled when the EL to which
6
the trap would be delivered is in AArch64 mode.
7
4
8
Given that ARMv9 drops support for AArch32 outside EL0, the trap EL
5
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
9
detection ought to be trivially true, but the pseudocode still contains
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
a number of conditions, and QEMU has not yet committed to dropping A32
11
support for EL[12] when v9 features are present.
12
13
Since the computation of SME_TRAP_NONSTREAMING is necessarily different
14
for the two modes, we might as well preserve bits within TBFLAG_ANY and
15
allocate separate bits within TBFLAG_A32 and TBFLAG_A64 instead.
16
17
Note that DDI0616A.a has typos for bits [22:21] of LD1RO in the table
18
of instructions illegal in streaming mode.
19
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
22
Message-id: 20220708151540.18136-4-richard.henderson@linaro.org
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
8
---
25
target/arm/cpu.h | 7 +++
9
target/arm/cpu.h | 5 +++++
26
target/arm/translate.h | 4 ++
10
target/arm/helper.c | 15 +++++++++++++--
27
target/arm/sme-fa64.decode | 90 ++++++++++++++++++++++++++++++++++++++
11
2 files changed, 18 insertions(+), 2 deletions(-)
28
target/arm/helper.c | 41 +++++++++++++++++
29
target/arm/translate-a64.c | 40 ++++++++++++++++-
30
target/arm/translate-vfp.c | 12 +++++
31
target/arm/translate.c | 2 +
32
target/arm/meson.build | 1 +
33
8 files changed, 195 insertions(+), 2 deletions(-)
34
create mode 100644 target/arm/sme-fa64.decode
35
12
36
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
37
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/cpu.h
15
--- a/target/arm/cpu.h
39
+++ b/target/arm/cpu.h
16
+++ b/target/arm/cpu.h
40
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, HSTR_ACTIVE, 9, 1)
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
41
* the same thing as the current security state of the processor!
18
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
42
*/
19
}
43
FIELD(TBFLAG_A32, NS, 10, 1)
20
44
+/*
21
+static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
45
+ * Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not.
46
+ * This requires an SME trap from AArch32 mode when using NEON.
47
+ */
48
+FIELD(TBFLAG_A32, SME_TRAP_NONSTREAMING, 11, 1)
49
50
/*
51
* Bit usage when in AArch32 state, for M-profile only.
52
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, SMEEXC_EL, 20, 2)
53
FIELD(TBFLAG_A64, PSTATE_SM, 22, 1)
54
FIELD(TBFLAG_A64, PSTATE_ZA, 23, 1)
55
FIELD(TBFLAG_A64, SVL, 24, 4)
56
+/* Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not. */
57
+FIELD(TBFLAG_A64, SME_TRAP_NONSTREAMING, 28, 1)
58
59
/*
60
* Helpers for using the above.
61
diff --git a/target/arm/translate.h b/target/arm/translate.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/translate.h
64
+++ b/target/arm/translate.h
65
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
66
bool pstate_sm;
67
/* True if PSTATE.ZA is set. */
68
bool pstate_za;
69
+ /* True if non-streaming insns should raise an SME Streaming exception. */
70
+ bool sme_trap_nonstreaming;
71
+ /* True if the current instruction is non-streaming. */
72
+ bool is_nonstreaming;
73
/* True if MVE insns are definitely not predicated by VPR or LTPSIZE */
74
bool mve_no_pred;
75
/*
76
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
77
new file mode 100644
78
index XXXXXXX..XXXXXXX
79
--- /dev/null
80
+++ b/target/arm/sme-fa64.decode
81
@@ -XXX,XX +XXX,XX @@
82
+# AArch64 SME allowed instruction decoding
83
+#
84
+# Copyright (c) 2022 Linaro, Ltd
85
+#
86
+# This library is free software; you can redistribute it and/or
87
+# modify it under the terms of the GNU Lesser General Public
88
+# License as published by the Free Software Foundation; either
89
+# version 2.1 of the License, or (at your option) any later version.
90
+#
91
+# This library is distributed in the hope that it will be useful,
92
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
93
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
94
+# Lesser General Public License for more details.
95
+#
96
+# You should have received a copy of the GNU Lesser General Public
97
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
98
+
99
+#
100
+# This file is processed by scripts/decodetree.py
101
+#
102
+
103
+# These patterns are taken from Appendix E1.1 of DDI0616 A.a,
104
+# Arm Architecture Reference Manual Supplement,
105
+# The Scalable Matrix Extension (SME), for Armv9-A
106
+
107
+{
22
+{
108
+ [
23
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
109
+ OK 0-00 1110 0000 0001 0010 11-- ---- ---- # SMOV W|Xd,Vn.B[0]
110
+ OK 0-00 1110 0000 0010 0010 11-- ---- ---- # SMOV W|Xd,Vn.H[0]
111
+ OK 0100 1110 0000 0100 0010 11-- ---- ---- # SMOV Xd,Vn.S[0]
112
+ OK 0000 1110 0000 0001 0011 11-- ---- ---- # UMOV Wd,Vn.B[0]
113
+ OK 0000 1110 0000 0010 0011 11-- ---- ---- # UMOV Wd,Vn.H[0]
114
+ OK 0000 1110 0000 0100 0011 11-- ---- ---- # UMOV Wd,Vn.S[0]
115
+ OK 0100 1110 0000 1000 0011 11-- ---- ---- # UMOV Xd,Vn.D[0]
116
+ ]
117
+ FAIL 0--0 111- ---- ---- ---- ---- ---- ---- # Advanced SIMD vector operations
118
+}
24
+}
119
+
25
+
120
+{
26
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
121
+ [
27
{
122
+ OK 0101 1110 --1- ---- 11-1 11-- ---- ---- # FMULX/FRECPS/FRSQRTS (scalar)
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
123
+ OK 0101 1110 -10- ---- 00-1 11-- ---- ---- # FMULX/FRECPS/FRSQRTS (scalar, FP16)
124
+ OK 01-1 1110 1-10 0001 11-1 10-- ---- ---- # FRECPE/FRSQRTE/FRECPX (scalar)
125
+ OK 01-1 1110 1111 1001 11-1 10-- ---- ---- # FRECPE/FRSQRTE/FRECPX (scalar, FP16)
126
+ ]
127
+ FAIL 01-1 111- ---- ---- ---- ---- ---- ---- # Advanced SIMD single-element operations
128
+}
129
+
130
+FAIL 0-00 110- ---- ---- ---- ---- ---- ---- # Advanced SIMD structure load/store
131
+FAIL 1100 1110 ---- ---- ---- ---- ---- ---- # Advanced SIMD cryptography extensions
132
+FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
133
+
134
+# These are the "avoidance of doubt" final table of Illegal Advanced SIMD instructions
135
+# We don't actually need to include these, as the default is OK.
136
+# -001 111- ---- ---- ---- ---- ---- ---- # Scalar floating-point operations
137
+# --10 110- ---- ---- ---- ---- ---- ---- # Load/store pair of FP registers
138
+# --01 1100 ---- ---- ---- ---- ---- ---- # Load FP register (PC-relative literal)
139
+# --11 1100 --0- ---- ---- ---- ---- ---- # Load/store FP register (unscaled imm)
140
+# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
141
+# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
142
+
143
+FAIL 0000 0100 --1- ---- 1010 ---- ---- ---- # ADR
144
+FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
145
+FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
146
+FAIL 0010 0101 --01 100- 1111 000- ---0 ---- # RDFFR, RDFFRS
147
+FAIL 0010 0101 --10 1--- 1001 ---- ---- ---- # WRFFR, SETFFR
148
+FAIL 0100 0101 --0- ---- 1011 ---- ---- ---- # BDEP, BEXT, BGRP
149
+FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
150
+FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
151
+FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
152
+FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
153
+FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
154
+FAIL 0100 0101 --0- ---- 1001 10-- ---- ---- # SMMLA, UMMLA, USMMLA
155
+FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
156
+FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
157
+FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
158
+FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
159
+FAIL 1000 010- -01- ---- 1--- ---- ---- ---- # SVE 32-bit gather load (vector+imm)
160
+FAIL 1000 0100 0-0- ---- 0--- ---- ---- ---- # SVE 32-bit gather load byte (scalar+vector)
161
+FAIL 1000 0100 1--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load half (scalar+vector)
162
+FAIL 1000 0101 0--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load word (scalar+vector)
163
+FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
164
+FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
165
+FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
166
+FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
167
+FAIL 1100 010- ---- ---- ---- ---- ---- ---- # SVE 64-bit gather load/prefetch
168
+FAIL 1110 010- -00- ---- 001- ---- ---- ---- # SVE2 64-bit scatter NT store (vector+scalar)
169
+FAIL 1110 010- -10- ---- 001- ---- ---- ---- # SVE2 32-bit scatter NT store (vector+scalar)
170
+FAIL 1110 010- ---- ---- 1-0- ---- ---- ---- # SVE scatter store (scalar+32-bit vector)
171
+FAIL 1110 010- ---- ---- 101- ---- ---- ---- # SVE scatter store (misc)
172
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
173
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
174
--- a/target/arm/helper.c
31
--- a/target/arm/helper.c
175
+++ b/target/arm/helper.c
32
+++ b/target/arm/helper.c
176
@@ -XXX,XX +XXX,XX @@ int sme_exception_el(CPUARMState *env, int el)
33
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
177
return 0;
34
{
178
}
35
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
179
36
bool epd, hpd, using16k, using64k;
180
+/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */
37
- int select, tsz, tbi;
181
+static bool sme_fa64(CPUARMState *env, int el)
38
+ int select, tsz, tbi, max_tsz;
182
+{
39
183
+ if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) {
40
if (!regime_has_2_ranges(mmu_idx)) {
184
+ return false;
41
select = 0;
42
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
43
hpd = extract64(tcr, 42, 1);
44
}
45
}
46
- tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
47
+
48
+ if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
49
+ max_tsz = 48 - using64k;
50
+ } else {
51
+ max_tsz = 39;
185
+ }
52
+ }
186
+
53
+
187
+ if (el <= 1 && !el_is_in_host(env, el)) {
54
+ tsz = MIN(tsz, max_tsz);
188
+ if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) {
55
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
189
+ return false;
56
190
+ }
57
/* Present TBI as a composite with TBID. */
191
+ }
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
192
+ if (el <= 2 && arm_is_el2_enabled(env)) {
59
if (!aarch64 || stride == 9) {
193
+ if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) {
60
/* AArch32 or 4KB pages */
194
+ return false;
61
startlevel = 2 - sl0;
195
+ }
196
+ }
197
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
198
+ if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) {
199
+ return false;
200
+ }
201
+ }
202
+
62
+
203
+ return true;
63
+ if (cpu_isar_feature(aa64_st, cpu)) {
204
+}
64
+ startlevel &= 3;
205
+
65
+ }
206
/*
66
} else {
207
* Given that SVE is enabled, return the vector length for EL.
67
/* 16KB or 64KB pages */
208
*/
68
startlevel = 3 - sl0;
209
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
210
DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
211
}
212
213
+ /*
214
+ * The SME exception we are testing for is raised via
215
+ * AArch64.CheckFPAdvSIMDEnabled(), as called from
216
+ * AArch32.CheckAdvSIMDOrFPEnabled().
217
+ */
218
+ if (el == 0
219
+ && FIELD_EX64(env->svcr, SVCR, SM)
220
+ && (!arm_is_el2_enabled(env)
221
+ || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE)))
222
+ && arm_el_is_aa64(env, 1)
223
+ && !sme_fa64(env, el)) {
224
+ DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1);
225
+ }
226
+
227
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
228
}
229
230
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
231
}
232
if (FIELD_EX64(env->svcr, SVCR, SM)) {
233
DP_TBFLAG_A64(flags, PSTATE_SM, 1);
234
+ DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el));
235
}
236
DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA));
237
}
238
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
239
index XXXXXXX..XXXXXXX 100644
240
--- a/target/arm/translate-a64.c
241
+++ b/target/arm/translate-a64.c
242
@@ -XXX,XX +XXX,XX @@ static void do_vec_ld(DisasContext *s, int destidx, int element,
243
* unallocated-encoding checks (otherwise the syndrome information
244
* for the resulting exception will be incorrect).
245
*/
246
-static bool fp_access_check(DisasContext *s)
247
+static bool fp_access_check_only(DisasContext *s)
248
{
249
if (s->fp_excp_el) {
250
assert(!s->fp_access_checked);
251
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
252
return true;
253
}
254
255
+static bool fp_access_check(DisasContext *s)
256
+{
257
+ if (!fp_access_check_only(s)) {
258
+ return false;
259
+ }
260
+ if (s->sme_trap_nonstreaming && s->is_nonstreaming) {
261
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
262
+ syn_smetrap(SME_ET_Streaming, false));
263
+ return false;
264
+ }
265
+ return true;
266
+}
267
+
268
/* Check that SVE access is enabled. If it is, return true.
269
* If not, emit code to generate an appropriate exception and return false.
270
*/
271
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
272
default:
273
g_assert_not_reached();
274
}
275
- if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
276
+ if ((ri->type & ARM_CP_FPU) && !fp_access_check_only(s)) {
277
return;
278
} else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
279
return;
280
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
281
}
282
}
283
284
+/*
285
+ * Include the generated SME FA64 decoder.
286
+ */
287
+
288
+#include "decode-sme-fa64.c.inc"
289
+
290
+static bool trans_OK(DisasContext *s, arg_OK *a)
291
+{
292
+ return true;
293
+}
294
+
295
+static bool trans_FAIL(DisasContext *s, arg_OK *a)
296
+{
297
+ s->is_nonstreaming = true;
298
+ return true;
299
+}
300
+
301
/**
302
* is_guarded_page:
303
* @env: The cpu environment
304
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
305
dc->mte_active[1] = EX_TBFLAG_A64(tb_flags, MTE0_ACTIVE);
306
dc->pstate_sm = EX_TBFLAG_A64(tb_flags, PSTATE_SM);
307
dc->pstate_za = EX_TBFLAG_A64(tb_flags, PSTATE_ZA);
308
+ dc->sme_trap_nonstreaming = EX_TBFLAG_A64(tb_flags, SME_TRAP_NONSTREAMING);
309
dc->vec_len = 0;
310
dc->vec_stride = 0;
311
dc->cp_regs = arm_cpu->cp_regs;
312
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
313
}
314
}
315
316
+ s->is_nonstreaming = false;
317
+ if (s->sme_trap_nonstreaming) {
318
+ disas_sme_fa64(s, insn);
319
+ }
320
+
321
switch (extract32(insn, 25, 4)) {
322
case 0x0:
323
if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
324
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
325
index XXXXXXX..XXXXXXX 100644
326
--- a/target/arm/translate-vfp.c
327
+++ b/target/arm/translate-vfp.c
328
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
329
return false;
330
}
331
332
+ /*
333
+ * Note that rebuild_hflags_a32 has already accounted for being in EL0
334
+ * and the higher EL in A64 mode, etc. Unlike A64 mode, there do not
335
+ * appear to be any insns which touch VFP which are allowed.
336
+ */
337
+ if (s->sme_trap_nonstreaming) {
338
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
339
+ syn_smetrap(SME_ET_Streaming,
340
+ s->base.pc_next - s->pc_curr == 2));
341
+ return false;
342
+ }
343
+
344
if (!s->vfp_enabled && !ignore_vfp_enabled) {
345
assert(!arm_dc_feature(s, ARM_FEATURE_M));
346
unallocated_encoding(s);
347
diff --git a/target/arm/translate.c b/target/arm/translate.c
348
index XXXXXXX..XXXXXXX 100644
349
--- a/target/arm/translate.c
350
+++ b/target/arm/translate.c
351
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
352
dc->vec_len = EX_TBFLAG_A32(tb_flags, VECLEN);
353
dc->vec_stride = EX_TBFLAG_A32(tb_flags, VECSTRIDE);
354
}
355
+ dc->sme_trap_nonstreaming =
356
+ EX_TBFLAG_A32(tb_flags, SME_TRAP_NONSTREAMING);
357
}
358
dc->cp_regs = cpu->cp_regs;
359
dc->features = env->features;
360
diff --git a/target/arm/meson.build b/target/arm/meson.build
361
index XXXXXXX..XXXXXXX 100644
362
--- a/target/arm/meson.build
363
+++ b/target/arm/meson.build
364
@@ -XXX,XX +XXX,XX @@
365
gen = [
366
decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
367
decodetree.process('sme.decode', extra_args: '--decode=disas_sme'),
368
+ decodetree.process('sme-fa64.decode', extra_args: '--static-decode=disas_sme_fa64'),
369
decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
370
decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
371
decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
372
--
69
--
373
2.25.1
70
2.20.1
71
72
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
Note that SME remains effectively disabled for user-only,
3
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
4
because we do not yet set CPACR_EL1.SMEN. This needs to
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
wait until the kernel ABI is implemented.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220708151540.18136-33-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
6
---
12
docs/system/arm/emulation.rst | 4 ++++
7
target/arm/cpu64.c | 1 +
13
target/arm/cpu64.c | 11 +++++++++++
8
1 file changed, 1 insertion(+)
14
2 files changed, 15 insertions(+)
15
9
16
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
17
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/system/arm/emulation.rst
19
+++ b/docs/system/arm/emulation.rst
20
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
21
- FEAT_SHA512 (Advanced SIMD SHA512 instructions)
22
- FEAT_SM3 (Advanced SIMD SM3 instructions)
23
- FEAT_SM4 (Advanced SIMD SM4 instructions)
24
+- FEAT_SME (Scalable Matrix Extension)
25
+- FEAT_SME_FA64 (Full A64 instruction set in Streaming SVE mode)
26
+- FEAT_SME_F64F64 (Double-precision floating-point outer product instructions)
27
+- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product instructions)
28
- FEAT_SPECRES (Speculation restriction instructions)
29
- FEAT_SSBS (Speculative Store Bypass Safe)
30
- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
31
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
10
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
32
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/cpu64.c
12
--- a/target/arm/cpu64.c
34
+++ b/target/arm/cpu64.c
13
+++ b/target/arm/cpu64.c
35
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
14
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
36
*/
15
t = cpu->isar.id_aa64mmfr2;
37
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
16
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
38
t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */
17
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
39
+ t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */
18
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
40
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
19
cpu->isar.id_aa64mmfr2 = t;
41
cpu->isar.id_aa64pfr1 = t;
20
42
21
/* Replicate the same data to the 32-bit id registers. */
43
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
44
t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* FEAT_PMUv3p4 */
45
cpu->isar.id_aa64dfr0 = t;
46
47
+ t = cpu->isar.id_aa64smfr0;
48
+ t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1); /* FEAT_SME */
49
+ t = FIELD_DP64(t, ID_AA64SMFR0, B16F32, 1); /* FEAT_SME */
50
+ t = FIELD_DP64(t, ID_AA64SMFR0, F16F32, 1); /* FEAT_SME */
51
+ t = FIELD_DP64(t, ID_AA64SMFR0, I8I32, 0xf); /* FEAT_SME */
52
+ t = FIELD_DP64(t, ID_AA64SMFR0, F64F64, 1); /* FEAT_SME_F64F64 */
53
+ t = FIELD_DP64(t, ID_AA64SMFR0, I16I64, 0xf); /* FEAT_SME_I16I64 */
54
+ t = FIELD_DP64(t, ID_AA64SMFR0, FA64, 1); /* FEAT_SME_FA64 */
55
+ cpu->isar.id_aa64smfr0 = t;
56
+
57
/* Replicate the same data to the 32-bit id registers. */
58
aa32_max_features(cpu);
59
60
--
22
--
61
2.25.1
23
2.20.1
24
25
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
We can handle both exception entry and exception return by
3
SBSS -> SSBS
4
hooking into aarch64_sve_change_el.
5
4
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20220708151540.18136-32-richard.henderson@linaro.org
9
Message-id: 20210108185154.8108-2-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
target/arm/helper.c | 15 +++++++++++++--
12
target/arm/cpu.h | 2 +-
12
1 file changed, 13 insertions(+), 2 deletions(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
--- a/target/arm/cpu.h
17
+++ b/target/arm/helper.c
18
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
19
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, RAS, 28, 4)
19
return;
20
FIELD(ID_AA64PFR0, SVE, 32, 4)
20
}
21
21
22
FIELD(ID_AA64PFR1, BT, 0, 4)
22
+ old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
23
-FIELD(ID_AA64PFR1, SBSS, 4, 4)
23
+ new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
24
+FIELD(ID_AA64PFR1, SSBS, 4, 4)
24
+
25
FIELD(ID_AA64PFR1, MTE, 8, 4)
25
+ /*
26
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
26
+ * Both AArch64.TakeException and AArch64.ExceptionReturn
27
+ * invoke ResetSVEState when taking an exception from, or
28
+ * returning to, AArch32 state when PSTATE.SM is enabled.
29
+ */
30
+ if (old_a64 != new_a64 && FIELD_EX64(env->svcr, SVCR, SM)) {
31
+ arm_reset_sve_state(env);
32
+ return;
33
+ }
34
+
35
/*
36
* DDI0584A.d sec 3.2: "If SVE instructions are disabled or trapped
37
* at ELx, or not available because the EL is in AArch32 state, then
38
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
39
* we already have the correct register contents when encountering the
40
* vq0->vq0 transition between EL0->EL1.
41
*/
42
- old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
43
old_len = (old_a64 && !sve_exception_el(env, old_el)
44
? sve_vqm1_for_el(env, old_el) : 0);
45
- new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
46
new_len = (new_a64 && !sve_exception_el(env, new_el)
47
? sve_vqm1_for_el(env, new_el) : 0);
48
27
49
--
28
--
50
2.25.1
29
2.20.1
30
31
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The AArch64 view of CLIDR_EL1 extends the ICB field to include also bit
4
32, as well as adding a Ttype<n> field when FEAT_MTE is implemented.
5
Extend the clidr field to be able to hold this context.
6
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
Message-id: 20220708151540.18136-46-richard.henderson@linaro.org
11
Message-id: 20210108185154.8108-3-leif@nuviainc.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
linux-user/elfload.c | 20 ++++++++++++++++++++
14
target/arm/cpu.h | 2 +-
9
1 file changed, 20 insertions(+)
15
1 file changed, 1 insertion(+), 1 deletion(-)
10
16
11
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/linux-user/elfload.c
19
--- a/target/arm/cpu.h
14
+++ b/linux-user/elfload.c
20
+++ b/target/arm/cpu.h
15
@@ -XXX,XX +XXX,XX @@ enum {
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
16
ARM_HWCAP2_A64_RNG = 1 << 16,
22
uint32_t id_afr0;
17
ARM_HWCAP2_A64_BTI = 1 << 17,
23
uint64_t id_aa64afr0;
18
ARM_HWCAP2_A64_MTE = 1 << 18,
24
uint64_t id_aa64afr1;
19
+ ARM_HWCAP2_A64_ECV = 1 << 19,
25
- uint32_t clidr;
20
+ ARM_HWCAP2_A64_AFP = 1 << 20,
26
+ uint64_t clidr;
21
+ ARM_HWCAP2_A64_RPRES = 1 << 21,
27
uint64_t mp_affinity; /* MP ID without feature bits */
22
+ ARM_HWCAP2_A64_MTE3 = 1 << 22,
28
/* The elements of this array are the CCSIDR values for each cache,
23
+ ARM_HWCAP2_A64_SME = 1 << 23,
29
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
24
+ ARM_HWCAP2_A64_SME_I16I64 = 1 << 24,
25
+ ARM_HWCAP2_A64_SME_F64F64 = 1 << 25,
26
+ ARM_HWCAP2_A64_SME_I8I32 = 1 << 26,
27
+ ARM_HWCAP2_A64_SME_F16F32 = 1 << 27,
28
+ ARM_HWCAP2_A64_SME_B16F32 = 1 << 28,
29
+ ARM_HWCAP2_A64_SME_F32F32 = 1 << 29,
30
+ ARM_HWCAP2_A64_SME_FA64 = 1 << 30,
31
};
32
33
#define ELF_HWCAP get_elf_hwcap()
34
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap2(void)
35
GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
36
GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
37
GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
38
+ GET_FEATURE_ID(aa64_sme, (ARM_HWCAP2_A64_SME |
39
+ ARM_HWCAP2_A64_SME_F32F32 |
40
+ ARM_HWCAP2_A64_SME_B16F32 |
41
+ ARM_HWCAP2_A64_SME_F16F32 |
42
+ ARM_HWCAP2_A64_SME_I8I32));
43
+ GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64);
44
+ GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64);
45
+ GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64);
46
47
return hwcaps;
48
}
49
--
30
--
50
2.25.1
31
2.20.1
32
33
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Enable SME, TPIDR2_EL0, and FA64 if supported by the cpu.
3
When FEAT_MTE is implemented, the AArch64 view of CTR_EL0 adds the
4
TminLine field in bits [37:32].
5
Extend the ctr field to be able to hold this context.
4
6
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
7
Message-id: 20220708151540.18136-45-richard.henderson@linaro.org
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20210108185154.8108-4-leif@nuviainc.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
target/arm/cpu.c | 11 +++++++++++
14
target/arm/cpu.h | 2 +-
11
1 file changed, 11 insertions(+)
15
1 file changed, 1 insertion(+), 1 deletion(-)
12
16
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.c
19
--- a/target/arm/cpu.h
16
+++ b/target/arm/cpu.c
20
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
18
CPACR_EL1, ZEN, 3);
22
uint64_t midr;
19
env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
23
uint32_t revidr;
20
}
24
uint32_t reset_fpsid;
21
+ /* and for SME instructions, with default vector length, and TPIDR2 */
25
- uint32_t ctr;
22
+ if (cpu_isar_feature(aa64_sme, cpu)) {
26
+ uint64_t ctr;
23
+ env->cp15.sctlr_el[1] |= SCTLR_EnTP2;
27
uint32_t reset_sctlr;
24
+ env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
28
uint64_t pmceid0;
25
+ CPACR_EL1, SMEN, 3);
29
uint64_t pmceid1;
26
+ env->vfp.smcr_el[1] = cpu->sme_default_vq - 1;
27
+ if (cpu_isar_feature(aa64_sme_fa64, cpu)) {
28
+ env->vfp.smcr_el[1] = FIELD_DP64(env->vfp.smcr_el[1],
29
+ SMCR, FA64, 1);
30
+ }
31
+ }
32
/*
33
* Enable 48-bit address space (TODO: take reserved_va into account).
34
* Enable TBI0 but not TBI1.
35
--
30
--
36
2.25.1
31
2.20.1
32
33
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
There's no reason to set CPACR_EL1.ZEN if SVE disabled.
3
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
4
4
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20210108185154.8108-5-leif@nuviainc.com
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220708151540.18136-44-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
7
---
10
target/arm/cpu.c | 7 +++----
8
target/arm/cpu.h | 31 +++++++++++++++++++++++++++++++
11
1 file changed, 3 insertions(+), 4 deletions(-)
9
1 file changed, 31 insertions(+)
12
10
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.c
13
--- a/target/arm/cpu.h
16
+++ b/target/arm/cpu.c
14
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
15
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_FPCCR, ASPEN, 31, 1)
18
/* and to the FP/Neon instructions */
16
/*
19
env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
17
* System register ID fields.
20
CPACR_EL1, FPEN, 3);
18
*/
21
- /* and to the SVE instructions */
19
+FIELD(CLIDR_EL1, CTYPE1, 0, 3)
22
- env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
20
+FIELD(CLIDR_EL1, CTYPE2, 3, 3)
23
- CPACR_EL1, ZEN, 3);
21
+FIELD(CLIDR_EL1, CTYPE3, 6, 3)
24
- /* with reasonable vector length */
22
+FIELD(CLIDR_EL1, CTYPE4, 9, 3)
25
+ /* and to the SVE instructions, with default vector length */
23
+FIELD(CLIDR_EL1, CTYPE5, 12, 3)
26
if (cpu_isar_feature(aa64_sve, cpu)) {
24
+FIELD(CLIDR_EL1, CTYPE6, 15, 3)
27
+ env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
25
+FIELD(CLIDR_EL1, CTYPE7, 18, 3)
28
+ CPACR_EL1, ZEN, 3);
26
+FIELD(CLIDR_EL1, LOUIS, 21, 3)
29
env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
27
+FIELD(CLIDR_EL1, LOC, 24, 3)
30
}
28
+FIELD(CLIDR_EL1, LOUU, 27, 3)
31
/*
29
+FIELD(CLIDR_EL1, ICB, 30, 3)
30
+
31
+/* When FEAT_CCIDX is implemented */
32
+FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
33
+FIELD(CCSIDR_EL1, CCIDX_ASSOCIATIVITY, 3, 21)
34
+FIELD(CCSIDR_EL1, CCIDX_NUMSETS, 32, 24)
35
+
36
+/* When FEAT_CCIDX is not implemented */
37
+FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
38
+FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
39
+FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
40
+
41
+FIELD(CTR_EL0, IMINLINE, 0, 4)
42
+FIELD(CTR_EL0, L1IP, 14, 2)
43
+FIELD(CTR_EL0, DMINLINE, 16, 4)
44
+FIELD(CTR_EL0, ERG, 20, 4)
45
+FIELD(CTR_EL0, CWG, 24, 4)
46
+FIELD(CTR_EL0, IDC, 28, 1)
47
+FIELD(CTR_EL0, DIC, 29, 1)
48
+FIELD(CTR_EL0, TMINLINE, 32, 6)
49
+
50
FIELD(MIDR_EL1, REVISION, 0, 4)
51
FIELD(MIDR_EL1, PARTNUM, 4, 12)
52
FIELD(MIDR_EL1, ARCHITECTURE, 16, 4)
32
--
53
--
33
2.25.1
54
2.20.1
55
56
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
These prctl set the Streaming SVE vector length, which may
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
be completely different from the Normal SVE vector length.
5
4
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20220708151540.18136-43-richard.henderson@linaro.org
8
Message-id: 20210108185154.8108-6-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
linux-user/aarch64/target_prctl.h | 54 +++++++++++++++++++++++++++++++
11
target/arm/cpu.h | 15 +++++++++++++++
12
linux-user/syscall.c | 16 +++++++++
12
1 file changed, 15 insertions(+)
13
2 files changed, 70 insertions(+)
14
13
15
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/aarch64/target_prctl.h
16
--- a/target/arm/cpu.h
18
+++ b/linux-user/aarch64/target_prctl.h
17
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_get_vl(CPUArchState *env)
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
20
{
19
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
21
ARMCPU *cpu = env_archcpu(env);
20
FIELD(ID_AA64ISAR1, SB, 36, 4)
22
if (cpu_isar_feature(aa64_sve, cpu)) {
21
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
23
+ /* PSTATE.SM is always unset on syscall entry. */
22
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
24
return sve_vq(env) * 16;
23
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
25
}
24
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
26
return -TARGET_EINVAL;
25
27
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
26
FIELD(ID_AA64PFR0, EL0, 0, 4)
28
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
27
FIELD(ID_AA64PFR0, EL1, 4, 4)
29
uint32_t vq, old_vq;
28
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
30
29
FIELD(ID_AA64PFR0, GIC, 24, 4)
31
+ /* PSTATE.SM is always unset on syscall entry. */
30
FIELD(ID_AA64PFR0, RAS, 28, 4)
32
old_vq = sve_vq(env);
31
FIELD(ID_AA64PFR0, SVE, 32, 4)
33
32
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
34
/*
33
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
35
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
34
+FIELD(ID_AA64PFR0, AMU, 44, 4)
36
}
35
+FIELD(ID_AA64PFR0, DIT, 48, 4)
37
#define do_prctl_sve_set_vl do_prctl_sve_set_vl
36
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
38
37
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
39
+static abi_long do_prctl_sme_get_vl(CPUArchState *env)
38
40
+{
39
FIELD(ID_AA64PFR1, BT, 0, 4)
41
+ ARMCPU *cpu = env_archcpu(env);
40
FIELD(ID_AA64PFR1, SSBS, 4, 4)
42
+ if (cpu_isar_feature(aa64_sme, cpu)) {
41
FIELD(ID_AA64PFR1, MTE, 8, 4)
43
+ return sme_vq(env) * 16;
42
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
44
+ }
43
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
45
+ return -TARGET_EINVAL;
44
46
+}
45
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
47
+#define do_prctl_sme_get_vl do_prctl_sme_get_vl
46
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
48
+
47
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
49
+static abi_long do_prctl_sme_set_vl(CPUArchState *env, abi_long arg2)
48
FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
50
+{
49
FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
51
+ /*
50
FIELD(ID_AA64MMFR0, EXS, 44, 4)
52
+ * We cannot support either PR_SME_SET_VL_ONEXEC or PR_SME_VL_INHERIT.
51
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
53
+ * Note the kernel definition of sve_vl_valid allows for VQ=512,
52
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
54
+ * i.e. VL=8192, even though the architectural maximum is VQ=16.
53
55
+ */
54
FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
56
+ if (cpu_isar_feature(aa64_sme, env_archcpu(env))
55
FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
57
+ && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
56
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
58
+ int vq, old_vq;
57
FIELD(ID_AA64MMFR1, PAN, 20, 4)
59
+
58
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
60
+ old_vq = sme_vq(env);
59
FIELD(ID_AA64MMFR1, XNX, 28, 4)
61
+
60
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
62
+ /*
61
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
63
+ * Bound the value of vq, so that we know that it fits into
62
64
+ * the 4-bit field in SMCR_EL1. Because PSTATE.SM is cleared
63
FIELD(ID_AA64MMFR2, CNP, 0, 4)
65
+ * on syscall entry, we are not modifying the current SVE
64
FIELD(ID_AA64MMFR2, UAO, 4, 4)
66
+ * vector length.
65
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
67
+ */
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
68
+ vq = MAX(arg2 / 16, 1);
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
69
+ vq = MIN(vq, 16);
68
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
70
+ env->vfp.smcr_el[1] =
69
+FIELD(ID_AA64DFR0, MTPMU, 48, 4)
71
+ FIELD_DP64(env->vfp.smcr_el[1], SMCR, LEN, vq - 1);
70
72
+
71
FIELD(ID_DFR0, COPDBG, 0, 4)
73
+ /* Delay rebuilding hflags until we know if ZA must change. */
72
FIELD(ID_DFR0, COPSDBG, 4, 4)
74
+ vq = sve_vqm1_for_el_sm(env, 0, true) + 1;
75
+
76
+ if (vq != old_vq) {
77
+ /*
78
+ * PSTATE.ZA state is cleared on any change to SVL.
79
+ * We need not call arm_rebuild_hflags because PSTATE.SM was
80
+ * cleared on syscall entry, so this hasn't changed VL.
81
+ */
82
+ env->svcr = FIELD_DP64(env->svcr, SVCR, ZA, 0);
83
+ arm_rebuild_hflags(env);
84
+ }
85
+ return vq * 16;
86
+ }
87
+ return -TARGET_EINVAL;
88
+}
89
+#define do_prctl_sme_set_vl do_prctl_sme_set_vl
90
+
91
static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
92
{
93
ARMCPU *cpu = env_archcpu(env);
94
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/linux-user/syscall.c
97
+++ b/linux-user/syscall.c
98
@@ -XXX,XX +XXX,XX @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
99
#ifndef PR_SET_SYSCALL_USER_DISPATCH
100
# define PR_SET_SYSCALL_USER_DISPATCH 59
101
#endif
102
+#ifndef PR_SME_SET_VL
103
+# define PR_SME_SET_VL 63
104
+# define PR_SME_GET_VL 64
105
+# define PR_SME_VL_LEN_MASK 0xffff
106
+# define PR_SME_VL_INHERIT (1 << 17)
107
+#endif
108
109
#include "target_prctl.h"
110
111
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
112
#ifndef do_prctl_set_unalign
113
#define do_prctl_set_unalign do_prctl_inval1
114
#endif
115
+#ifndef do_prctl_sme_get_vl
116
+#define do_prctl_sme_get_vl do_prctl_inval0
117
+#endif
118
+#ifndef do_prctl_sme_set_vl
119
+#define do_prctl_sme_set_vl do_prctl_inval1
120
+#endif
121
122
static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
123
abi_long arg3, abi_long arg4, abi_long arg5)
124
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
125
return do_prctl_sve_get_vl(env);
126
case PR_SVE_SET_VL:
127
return do_prctl_sve_set_vl(env, arg2);
128
+ case PR_SME_GET_VL:
129
+ return do_prctl_sme_get_vl(env);
130
+ case PR_SME_SET_VL:
131
+ return do_prctl_sme_set_vl(env, arg2);
132
case PR_PAC_RESET_KEYS:
133
if (arg3 || arg4 || arg5) {
134
return -TARGET_EINVAL;
135
--
73
--
136
2.25.1
74
2.20.1
75
76
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Add "sve" to the sve prctl functions, to distinguish
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
them from the coming "sme" prctls with similar names.
5
4
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20220708151540.18136-42-richard.henderson@linaro.org
8
Message-id: 20210108185154.8108-7-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
linux-user/aarch64/target_prctl.h | 8 ++++----
11
target/arm/cpu.h | 28 ++++++++++++++++++++++++++++
12
linux-user/syscall.c | 12 ++++++------
12
1 file changed, 28 insertions(+)
13
2 files changed, 10 insertions(+), 10 deletions(-)
14
13
15
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/aarch64/target_prctl.h
16
--- a/target/arm/cpu.h
18
+++ b/linux-user/aarch64/target_prctl.h
17
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_ISAR6, DP, 4, 4)
20
#ifndef AARCH64_TARGET_PRCTL_H
19
FIELD(ID_ISAR6, FHM, 8, 4)
21
#define AARCH64_TARGET_PRCTL_H
20
FIELD(ID_ISAR6, SB, 12, 4)
22
21
FIELD(ID_ISAR6, SPECRES, 16, 4)
23
-static abi_long do_prctl_get_vl(CPUArchState *env)
22
+FIELD(ID_ISAR6, BF16, 20, 4)
24
+static abi_long do_prctl_sve_get_vl(CPUArchState *env)
23
+FIELD(ID_ISAR6, I8MM, 24, 4)
25
{
24
26
ARMCPU *cpu = env_archcpu(env);
25
FIELD(ID_MMFR0, VMSA, 0, 4)
27
if (cpu_isar_feature(aa64_sve, cpu)) {
26
FIELD(ID_MMFR0, PMSA, 4, 4)
28
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_get_vl(CPUArchState *env)
27
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR0, AUXREG, 20, 4)
29
}
28
FIELD(ID_MMFR0, FCSE, 24, 4)
30
return -TARGET_EINVAL;
29
FIELD(ID_MMFR0, INNERSHR, 28, 4)
31
}
30
32
-#define do_prctl_get_vl do_prctl_get_vl
31
+FIELD(ID_MMFR1, L1HVDVA, 0, 4)
33
+#define do_prctl_sve_get_vl do_prctl_sve_get_vl
32
+FIELD(ID_MMFR1, L1UNIVA, 4, 4)
34
33
+FIELD(ID_MMFR1, L1HVDSW, 8, 4)
35
-static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
34
+FIELD(ID_MMFR1, L1UNISW, 12, 4)
36
+static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
35
+FIELD(ID_MMFR1, L1HVD, 16, 4)
37
{
36
+FIELD(ID_MMFR1, L1UNI, 20, 4)
38
/*
37
+FIELD(ID_MMFR1, L1TSTCLN, 24, 4)
39
* We cannot support either PR_SVE_SET_VL_ONEXEC or PR_SVE_VL_INHERIT.
38
+FIELD(ID_MMFR1, BPRED, 28, 4)
40
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
39
+
41
}
40
+FIELD(ID_MMFR2, L1HVDFG, 0, 4)
42
return -TARGET_EINVAL;
41
+FIELD(ID_MMFR2, L1HVDBG, 4, 4)
43
}
42
+FIELD(ID_MMFR2, L1HVDRNG, 8, 4)
44
-#define do_prctl_set_vl do_prctl_set_vl
43
+FIELD(ID_MMFR2, HVDTLB, 12, 4)
45
+#define do_prctl_sve_set_vl do_prctl_sve_set_vl
44
+FIELD(ID_MMFR2, UNITLB, 16, 4)
46
45
+FIELD(ID_MMFR2, MEMBARR, 20, 4)
47
static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
46
+FIELD(ID_MMFR2, WFISTALL, 24, 4)
48
{
47
+FIELD(ID_MMFR2, HWACCFLG, 28, 4)
49
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
48
+
50
index XXXXXXX..XXXXXXX 100644
49
FIELD(ID_MMFR3, CMAINTVA, 0, 4)
51
--- a/linux-user/syscall.c
50
FIELD(ID_MMFR3, CMAINTSW, 4, 4)
52
+++ b/linux-user/syscall.c
51
FIELD(ID_MMFR3, BPMAINT, 8, 4)
53
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
52
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
54
#ifndef do_prctl_set_fp_mode
53
FIELD(ID_MMFR4, CCIDX, 24, 4)
55
#define do_prctl_set_fp_mode do_prctl_inval1
54
FIELD(ID_MMFR4, EVT, 28, 4)
56
#endif
55
57
-#ifndef do_prctl_get_vl
56
+FIELD(ID_MMFR5, ETS, 0, 4)
58
-#define do_prctl_get_vl do_prctl_inval0
57
+
59
+#ifndef do_prctl_sve_get_vl
58
FIELD(ID_PFR0, STATE0, 0, 4)
60
+#define do_prctl_sve_get_vl do_prctl_inval0
59
FIELD(ID_PFR0, STATE1, 4, 4)
61
#endif
60
FIELD(ID_PFR0, STATE2, 8, 4)
62
-#ifndef do_prctl_set_vl
61
@@ -XXX,XX +XXX,XX @@ FIELD(ID_PFR1, SEC_FRAC, 20, 4)
63
-#define do_prctl_set_vl do_prctl_inval1
62
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
64
+#ifndef do_prctl_sve_set_vl
63
FIELD(ID_PFR1, GIC, 28, 4)
65
+#define do_prctl_sve_set_vl do_prctl_inval1
64
66
#endif
65
+FIELD(ID_PFR2, CSV3, 0, 4)
67
#ifndef do_prctl_reset_keys
66
+FIELD(ID_PFR2, SSBS, 4, 4)
68
#define do_prctl_reset_keys do_prctl_inval1
67
+FIELD(ID_PFR2, RAS_FRAC, 8, 4)
69
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
68
+
70
case PR_SET_FP_MODE:
69
FIELD(ID_AA64ISAR0, AES, 4, 4)
71
return do_prctl_set_fp_mode(env, arg2);
70
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
72
case PR_SVE_GET_VL:
71
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
73
- return do_prctl_get_vl(env);
72
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
74
+ return do_prctl_sve_get_vl(env);
73
FIELD(ID_DFR0, PERFMON, 24, 4)
75
case PR_SVE_SET_VL:
74
FIELD(ID_DFR0, TRACEFILT, 28, 4)
76
- return do_prctl_set_vl(env, arg2);
75
77
+ return do_prctl_sve_set_vl(env, arg2);
76
+FIELD(ID_DFR1, MTPMU, 0, 4)
78
case PR_PAC_RESET_KEYS:
77
+
79
if (arg3 || arg4 || arg5) {
78
FIELD(DBGDIDR, SE_IMP, 12, 1)
80
return -TARGET_EINVAL;
79
FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
80
FIELD(DBGDIDR, VERSION, 16, 4)
81
--
81
--
82
2.25.1
82
2.20.1
83
84
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
QEMU documentation can't be opened if QEMU is run from build tree
4
because executables are placed in the top of build tree after conversion
5
to meson.
6
7
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210108213815.64678-1-r.bolshakov@yadro.com
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220708151540.18136-39-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
linux-user/aarch64/signal.c | 3 +++
13
ui/cocoa.m | 2 +-
9
1 file changed, 3 insertions(+)
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
15
11
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
16
diff --git a/ui/cocoa.m b/ui/cocoa.m
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/linux-user/aarch64/signal.c
18
--- a/ui/cocoa.m
14
+++ b/linux-user/aarch64/signal.c
19
+++ b/ui/cocoa.m
15
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
20
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
16
__get_user(extra_size,
21
- (void) openDocumentation: (NSString *) filename
17
&((struct target_extra_context *)ctx)->size);
22
{
18
extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
23
/* Where to look for local files */
19
+ if (!extra) {
24
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
20
+ return 1;
25
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
21
+ }
26
NSString *full_file_path;
22
break;
27
23
28
/* iterate thru the possible paths until the file is found */
24
default:
25
--
29
--
26
2.25.1
30
2.20.1
31
32
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In commit 1982e1602d15 we added a new qemu-storage-daemon(1) manpage.
2
At the moment new manpages have to be listed both in the conf.py for
3
Sphinx and also in docs/meson.build for Meson. We forgot the second
4
of those -- correct the omission.
2
5
3
In parse_user_sigframe, the kernel rejects duplicate sve records,
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
or records that are smaller than the header. We were silently
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
allowing these cases to pass, dropping the record.
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20210108161416.21129-2-peter.maydell@linaro.org
10
---
11
docs/meson.build | 1 +
12
1 file changed, 1 insertion(+)
6
13
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/docs/meson.build b/docs/meson.build
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
index XXXXXXX..XXXXXXX 100644
9
Message-id: 20220708151540.18136-38-richard.henderson@linaro.org
16
--- a/docs/meson.build
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
+++ b/docs/meson.build
11
---
18
@@ -XXX,XX +XXX,XX @@ if build_docs
12
linux-user/aarch64/signal.c | 5 ++++-
19
'qemu-img.1': (have_tools ? 'man1' : ''),
13
1 file changed, 4 insertions(+), 1 deletion(-)
20
'qemu-nbd.8': (have_tools ? 'man8' : ''),
21
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
22
+ 'qemu-storage-daemon.1': (have_tools ? 'man1' : ''),
23
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
24
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
25
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
26
--
27
2.20.1
14
28
15
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
29
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/aarch64/signal.c
18
+++ b/linux-user/aarch64/signal.c
19
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
20
break;
21
22
case TARGET_SVE_MAGIC:
23
+ if (sve || size < sizeof(struct target_sve_context)) {
24
+ goto err;
25
+ }
26
if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
27
vq = sve_vq(env);
28
sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
29
- if (!sve && size == sve_size) {
30
+ if (size == sve_size) {
31
sve = (struct target_sve_context *)ctx;
32
break;
33
}
34
--
35
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
When we first converted our documentation to Sphinx, we split it into
2
2
multiple manuals (system, interop, tools, etc), which are all built
3
Fold the return value setting into the goto, so each
3
separately. The primary driver for this was wanting to be able to
4
point of failure need not do both.
4
avoid shipping the 'devel' manual to end-users. However, this is
5
5
working against the grain of the way Sphinx wants to be used and
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
causes some annoyances:
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
* Cross-references between documents become much harder or
8
Message-id: 20220708151540.18136-37-richard.henderson@linaro.org
8
possibly impossible
9
* There is no single index to the whole documentation
10
* Within one manual there's no links or table-of-contents info
11
that lets you easily navigate to the others
12
* The devel manual doesn't get published on the QEMU website
13
(it would be nice to able to refer to it there)
14
15
Merely hiding our developer documentation from end users seems like
16
it's not enough benefit for these costs. Combine all the
17
documentation into a single manual (the same way that the readthedocs
18
site builds it) and install the whole thing. The previous manual
19
divisions remain as the new top level sections in the manual.
20
21
* The per-manual conf.py files are no longer needed
22
* The man_pages[] specifications previously in each per-manual
23
conf.py move to the top level conf.py
24
* docs/meson.build logic is simplified as we now only need to run
25
Sphinx once for the HTML and then once for the manpages5B
26
* The old index.html.in that produced the top-level page with
27
links to each manual is no longer needed
28
29
Unfortunately this means that we now have to build the HTML
30
documentation into docs/manual in the build tree rather than directly
31
into docs/; otherwise it is too awkward to ensure we install only the
32
built manual and not also the dependency info, stamp file, etc. The
33
manual still ends up in the same place in the final installed
34
directory, but anybody who was consulting documentation from within
35
the build tree will have to adjust where they're looking.
36
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
39
Message-id: 20210108161416.21129-3-peter.maydell@linaro.org
10
---
40
---
11
linux-user/aarch64/signal.c | 26 +++++++++++---------------
41
docs/conf.py | 46 ++++++++++++++++++++++++++++++-
12
1 file changed, 11 insertions(+), 15 deletions(-)
42
docs/devel/conf.py | 15 -----------
13
43
docs/index.html.in | 17 ------------
14
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
44
docs/interop/conf.py | 28 -------------------
45
docs/meson.build | 64 +++++++++++++++++---------------------------
46
docs/specs/conf.py | 16 -----------
47
docs/system/conf.py | 28 -------------------
48
docs/tools/conf.py | 37 -------------------------
49
docs/user/conf.py | 15 -----------
50
9 files changed, 70 insertions(+), 196 deletions(-)
51
delete mode 100644 docs/devel/conf.py
52
delete mode 100644 docs/index.html.in
53
delete mode 100644 docs/interop/conf.py
54
delete mode 100644 docs/specs/conf.py
55
delete mode 100644 docs/system/conf.py
56
delete mode 100644 docs/tools/conf.py
57
delete mode 100644 docs/user/conf.py
58
59
diff --git a/docs/conf.py b/docs/conf.py
15
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/aarch64/signal.c
61
--- a/docs/conf.py
17
+++ b/linux-user/aarch64/signal.c
62
+++ b/docs/conf.py
18
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
63
@@ -XXX,XX +XXX,XX @@ latex_documents = [
19
struct target_sve_context *sve = NULL;
64
20
uint64_t extra_datap = 0;
65
# -- Options for manual page output ---------------------------------------
21
bool used_extra = false;
66
# Individual manual/conf.py can override this to create man pages
22
- bool err = false;
67
-man_pages = []
23
int vq = 0, sve_size = 0;
68
+man_pages = [
24
69
+ ('interop/qemu-ga', 'qemu-ga',
25
target_restore_general_frame(env, sf);
70
+ 'QEMU Guest Agent',
26
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
71
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
27
switch (magic) {
72
+ ('interop/qemu-ga-ref', 'qemu-ga-ref',
28
case 0:
73
+ 'QEMU Guest Agent Protocol Reference',
29
if (size != 0) {
74
+ [], 7),
30
- err = true;
75
+ ('interop/qemu-qmp-ref', 'qemu-qmp-ref',
31
- goto exit;
76
+ 'QEMU QMP Reference Manual',
32
+ goto err;
77
+ [], 7),
33
}
78
+ ('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
34
if (used_extra) {
79
+ 'QEMU Storage Daemon QMP Reference Manual',
35
ctx = NULL;
80
+ [], 7),
36
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
81
+ ('system/qemu-manpage', 'qemu',
37
82
+ 'QEMU User Documentation',
38
case TARGET_FPSIMD_MAGIC:
83
+ ['Fabrice Bellard'], 1),
39
if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
84
+ ('system/qemu-block-drivers', 'qemu-block-drivers',
40
- err = true;
85
+ 'QEMU block drivers reference',
41
- goto exit;
86
+ ['Fabrice Bellard and the QEMU Project developers'], 7),
42
+ goto err;
87
+ ('system/qemu-cpu-models', 'qemu-cpu-models',
43
}
88
+ 'QEMU CPU Models',
44
fpsimd = (struct target_fpsimd_context *)ctx;
89
+ ['The QEMU Project developers'], 7),
45
break;
90
+ ('tools/qemu-img', 'qemu-img',
46
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
91
+ 'QEMU disk image utility',
47
break;
92
+ ['Fabrice Bellard'], 1),
48
}
93
+ ('tools/qemu-nbd', 'qemu-nbd',
49
}
94
+ 'QEMU Disk Network Block Device Server',
50
- err = true;
95
+ ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
51
- goto exit;
96
+ ('tools/qemu-pr-helper', 'qemu-pr-helper',
52
+ goto err;
97
+ 'QEMU persistent reservation helper',
53
98
+ [], 8),
54
case TARGET_EXTRA_MAGIC:
99
+ ('tools/qemu-storage-daemon', 'qemu-storage-daemon',
55
if (extra || size != sizeof(struct target_extra_context)) {
100
+ 'QEMU storage daemon',
56
- err = true;
101
+ [], 1),
57
- goto exit;
102
+ ('tools/qemu-trace-stap', 'qemu-trace-stap',
58
+ goto err;
103
+ 'QEMU SystemTap trace tool',
59
}
104
+ [], 1),
60
__get_user(extra_datap,
105
+ ('tools/virtfs-proxy-helper', 'virtfs-proxy-helper',
61
&((struct target_extra_context *)ctx)->datap);
106
+ 'QEMU 9p virtfs proxy filesystem helper',
62
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
107
+ ['M. Mohan Kumar'], 1),
63
/* Unknown record -- we certainly didn't generate it.
108
+ ('tools/virtiofsd', 'virtiofsd',
64
* Did we in fact get out of sync?
109
+ 'QEMU virtio-fs shared file system daemon',
65
*/
110
+ ['Stefan Hajnoczi <stefanha@redhat.com>',
66
- err = true;
111
+ 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
67
- goto exit;
112
+]
68
+ goto err;
113
69
}
114
# -- Options for Texinfo output -------------------------------------------
70
ctx = (void *)ctx + size;
115
71
}
116
diff --git a/docs/devel/conf.py b/docs/devel/conf.py
72
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
117
deleted file mode 100644
73
if (fpsimd) {
118
index XXXXXXX..XXXXXXX
74
target_restore_fpsimd_record(env, fpsimd);
119
--- a/docs/devel/conf.py
75
} else {
120
+++ /dev/null
76
- err = true;
121
@@ -XXX,XX +XXX,XX @@
77
+ goto err;
122
-# -*- coding: utf-8 -*-
78
}
123
-#
79
124
-# QEMU documentation build configuration file for the 'devel' manual.
80
/* SVE data, if present, overwrites FPSIMD data. */
125
-#
81
if (sve) {
126
-# This includes the top level conf file and then makes any necessary tweaks.
82
target_restore_sve_record(env, sve, vq);
127
-import sys
83
}
128
-import os
84
-
129
-
85
- exit:
130
-qemu_docdir = os.path.abspath("..")
86
unlock_user(extra, extra_datap, 0);
131
-parent_config = os.path.join(qemu_docdir, "conf.py")
87
- return err;
132
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
88
+ return 0;
133
-
134
-# This slightly misuses the 'description', but is the best way to get
135
-# the manual title to appear in the sidebar.
136
-html_theme_options['description'] = u'Developer''s Guide'
137
diff --git a/docs/index.html.in b/docs/index.html.in
138
deleted file mode 100644
139
index XXXXXXX..XXXXXXX
140
--- a/docs/index.html.in
141
+++ /dev/null
142
@@ -XXX,XX +XXX,XX @@
143
-<!DOCTYPE html>
144
-<html lang="en">
145
- <head>
146
- <meta charset="UTF-8">
147
- <title>QEMU @VERSION@ Documentation</title>
148
- </head>
149
- <body>
150
- <h1>QEMU @VERSION@ Documentation</h1>
151
- <ul>
152
- <li><a href="system/index.html">System Emulation User's Guide</a></li>
153
- <li><a href="user/index.html">User Mode Emulation User's Guide</a></li>
154
- <li><a href="tools/index.html">Tools Guide</a></li>
155
- <li><a href="interop/index.html">System Emulation Management and Interoperability Guide</a></li>
156
- <li><a href="specs/index.html">System Emulation Guest Hardware Specifications</a></li>
157
- </ul>
158
- </body>
159
-</html>
160
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
161
deleted file mode 100644
162
index XXXXXXX..XXXXXXX
163
--- a/docs/interop/conf.py
164
+++ /dev/null
165
@@ -XXX,XX +XXX,XX @@
166
-# -*- coding: utf-8 -*-
167
-#
168
-# QEMU documentation build configuration file for the 'interop' manual.
169
-#
170
-# This includes the top level conf file and then makes any necessary tweaks.
171
-import sys
172
-import os
173
-
174
-qemu_docdir = os.path.abspath("..")
175
-parent_config = os.path.join(qemu_docdir, "conf.py")
176
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
177
-
178
-# This slightly misuses the 'description', but is the best way to get
179
-# the manual title to appear in the sidebar.
180
-html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
181
-
182
-# One entry per manual page. List of tuples
183
-# (source start file, name, description, authors, manual section).
184
-man_pages = [
185
- ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
186
- ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
187
- ('qemu-ga-ref', 'qemu-ga-ref', 'QEMU Guest Agent Protocol Reference',
188
- [], 7),
189
- ('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual',
190
- [], 7),
191
- ('qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
192
- 'QEMU Storage Daemon QMP Reference Manual', [], 7),
193
-]
194
diff --git a/docs/meson.build b/docs/meson.build
195
index XXXXXXX..XXXXXXX 100644
196
--- a/docs/meson.build
197
+++ b/docs/meson.build
198
@@ -XXX,XX +XXX,XX @@ if build_docs
199
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
200
qapi_gen_depends ]
201
202
- configure_file(output: 'index.html',
203
- input: files('index.html.in'),
204
- configuration: {'VERSION': meson.project_version()},
205
- install_dir: qemu_docdir)
206
- manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ]
207
man_pages = {
208
- 'interop' : {
209
'qemu-ga.8': (have_tools ? 'man8' : ''),
210
'qemu-ga-ref.7': 'man7',
211
'qemu-qmp-ref.7': 'man7',
212
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
213
- },
214
- 'tools': {
215
'qemu-img.1': (have_tools ? 'man1' : ''),
216
'qemu-nbd.8': (have_tools ? 'man8' : ''),
217
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
218
@@ -XXX,XX +XXX,XX @@ if build_docs
219
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
220
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
221
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
222
- },
223
- 'system': {
224
'qemu.1': 'man1',
225
'qemu-block-drivers.7': 'man7',
226
'qemu-cpu-models.7': 'man7'
227
- },
228
}
229
230
sphinxdocs = []
231
sphinxmans = []
232
- foreach manual : manuals
233
- private_dir = meson.current_build_dir() / (manual + '.p')
234
- output_dir = meson.current_build_dir() / manual
235
- input_dir = meson.current_source_dir() / manual
236
237
- this_manual = custom_target(manual + ' manual',
238
+ private_dir = meson.current_build_dir() / 'manual.p'
239
+ output_dir = meson.current_build_dir() / 'manual'
240
+ input_dir = meson.current_source_dir()
89
+
241
+
90
+ err:
242
+ this_manual = custom_target('QEMU manual',
91
+ unlock_user(extra, extra_datap, 0);
243
build_by_default: build_docs,
92
+ return 1;
244
- output: [manual + '.stamp'],
93
}
245
- input: [files('conf.py'), files(manual / 'conf.py')],
94
246
- depfile: manual + '.d',
95
static abi_ulong get_sigframe(struct target_sigaction *ka,
247
+ output: 'docs.stamp',
248
+ input: files('conf.py'),
249
+ depfile: 'docs.d',
250
depend_files: sphinx_extn_depends,
251
command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
252
'-Ddepfile_stamp=@OUTPUT0@',
253
'-b', 'html', '-d', private_dir,
254
input_dir, output_dir])
255
- sphinxdocs += this_manual
256
- if build_docs and manual != 'devel'
257
- install_subdir(output_dir, install_dir: qemu_docdir)
258
- endif
259
+ sphinxdocs += this_manual
260
+ install_subdir(output_dir, install_dir: qemu_docdir, strip_directory: true)
261
262
- these_man_pages = []
263
- install_dirs = []
264
- foreach page, section : man_pages.get(manual, {})
265
- these_man_pages += page
266
- install_dirs += section == '' ? false : get_option('mandir') / section
267
- endforeach
268
- if these_man_pages.length() > 0
269
- sphinxmans += custom_target(manual + ' man pages',
270
- build_by_default: build_docs,
271
- output: these_man_pages,
272
- input: this_manual,
273
- install: build_docs,
274
- install_dir: install_dirs,
275
- command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
276
- input_dir, meson.current_build_dir()])
277
- endif
278
+ these_man_pages = []
279
+ install_dirs = []
280
+ foreach page, section : man_pages
281
+ these_man_pages += page
282
+ install_dirs += section == '' ? false : get_option('mandir') / section
283
endforeach
284
+
285
+ sphinxmans += custom_target('QEMU man pages',
286
+ build_by_default: build_docs,
287
+ output: these_man_pages,
288
+ input: this_manual,
289
+ install: build_docs,
290
+ install_dir: install_dirs,
291
+ command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
292
+ input_dir, meson.current_build_dir()])
293
+
294
alias_target('sphinxdocs', sphinxdocs)
295
alias_target('html', sphinxdocs)
296
alias_target('man', sphinxmans)
297
diff --git a/docs/specs/conf.py b/docs/specs/conf.py
298
deleted file mode 100644
299
index XXXXXXX..XXXXXXX
300
--- a/docs/specs/conf.py
301
+++ /dev/null
302
@@ -XXX,XX +XXX,XX @@
303
-# -*- coding: utf-8 -*-
304
-#
305
-# QEMU documentation build configuration file for the 'specs' manual.
306
-#
307
-# This includes the top level conf file and then makes any necessary tweaks.
308
-import sys
309
-import os
310
-
311
-qemu_docdir = os.path.abspath("..")
312
-parent_config = os.path.join(qemu_docdir, "conf.py")
313
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
314
-
315
-# This slightly misuses the 'description', but is the best way to get
316
-# the manual title to appear in the sidebar.
317
-html_theme_options['description'] = \
318
- u'System Emulation Guest Hardware Specifications'
319
diff --git a/docs/system/conf.py b/docs/system/conf.py
320
deleted file mode 100644
321
index XXXXXXX..XXXXXXX
322
--- a/docs/system/conf.py
323
+++ /dev/null
324
@@ -XXX,XX +XXX,XX @@
325
-# -*- coding: utf-8 -*-
326
-#
327
-# QEMU documentation build configuration file for the 'system' manual.
328
-#
329
-# This includes the top level conf file and then makes any necessary tweaks.
330
-import sys
331
-import os
332
-
333
-qemu_docdir = os.path.abspath("..")
334
-parent_config = os.path.join(qemu_docdir, "conf.py")
335
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
336
-
337
-# This slightly misuses the 'description', but is the best way to get
338
-# the manual title to appear in the sidebar.
339
-html_theme_options['description'] = u'System Emulation User''s Guide'
340
-
341
-# One entry per manual page. List of tuples
342
-# (source start file, name, description, authors, manual section).
343
-man_pages = [
344
- ('qemu-manpage', 'qemu', u'QEMU User Documentation',
345
- ['Fabrice Bellard'], 1),
346
- ('qemu-block-drivers', 'qemu-block-drivers',
347
- u'QEMU block drivers reference',
348
- ['Fabrice Bellard and the QEMU Project developers'], 7),
349
- ('qemu-cpu-models', 'qemu-cpu-models',
350
- u'QEMU CPU Models',
351
- ['The QEMU Project developers'], 7)
352
-]
353
diff --git a/docs/tools/conf.py b/docs/tools/conf.py
354
deleted file mode 100644
355
index XXXXXXX..XXXXXXX
356
--- a/docs/tools/conf.py
357
+++ /dev/null
358
@@ -XXX,XX +XXX,XX @@
359
-# -*- coding: utf-8 -*-
360
-#
361
-# QEMU documentation build configuration file for the 'tools' manual.
362
-#
363
-# This includes the top level conf file and then makes any necessary tweaks.
364
-import sys
365
-import os
366
-
367
-qemu_docdir = os.path.abspath("..")
368
-parent_config = os.path.join(qemu_docdir, "conf.py")
369
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
370
-
371
-# This slightly misuses the 'description', but is the best way to get
372
-# the manual title to appear in the sidebar.
373
-html_theme_options['description'] = \
374
- u'Tools Guide'
375
-
376
-# One entry per manual page. List of tuples
377
-# (source start file, name, description, authors, manual section).
378
-man_pages = [
379
- ('qemu-img', 'qemu-img', u'QEMU disk image utility',
380
- ['Fabrice Bellard'], 1),
381
- ('qemu-storage-daemon', 'qemu-storage-daemon', u'QEMU storage daemon',
382
- [], 1),
383
- ('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server',
384
- ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
385
- ('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper',
386
- [], 8),
387
- ('qemu-trace-stap', 'qemu-trace-stap', u'QEMU SystemTap trace tool',
388
- [], 1),
389
- ('virtfs-proxy-helper', 'virtfs-proxy-helper',
390
- u'QEMU 9p virtfs proxy filesystem helper',
391
- ['M. Mohan Kumar'], 1),
392
- ('virtiofsd', 'virtiofsd', u'QEMU virtio-fs shared file system daemon',
393
- ['Stefan Hajnoczi <stefanha@redhat.com>',
394
- 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
395
-]
396
diff --git a/docs/user/conf.py b/docs/user/conf.py
397
deleted file mode 100644
398
index XXXXXXX..XXXXXXX
399
--- a/docs/user/conf.py
400
+++ /dev/null
401
@@ -XXX,XX +XXX,XX @@
402
-# -*- coding: utf-8 -*-
403
-#
404
-# QEMU documentation build configuration file for the 'user' manual.
405
-#
406
-# This includes the top level conf file and then makes any necessary tweaks.
407
-import sys
408
-import os
409
-
410
-qemu_docdir = os.path.abspath("..")
411
-parent_config = os.path.join(qemu_docdir, "conf.py")
412
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
413
-
414
-# This slightly misuses the 'description', but is the best way to get
415
-# the manual title to appear in the sidebar.
416
-html_theme_options['description'] = u'User Mode Emulation User''s Guide'
96
--
417
--
97
2.25.1
418
2.20.1
419
420
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In commit cd8be50e58f63413c0 we converted the A32 coprocessor
2
insns to decodetree. This accidentally broke XScale/iWMMXt insns,
3
because it moved the handling of "cp insns which are handled
4
by looking up the cp register in the hashtable" from after the
5
call to the legacy disas_xscale_insn() decode to before it,
6
with the result that all XScale/iWMMXt insns now UNDEF.
2
7
3
Move the checks out of the parsing loop and into the
8
Update valid_cp() so that it knows that on XScale cp 0 and 1
4
restore function. This more closely mirrors the code
9
are not standard coprocessor instructions; this will cause
5
structure in the kernel, and is slightly clearer.
10
the decodetree trans_ functions to ignore them, so that
11
execution will correctly get through to the legacy decode again.
6
12
7
Reject rather than silently skip incorrect VL and SVE record sizes,
13
Cc: qemu-stable@nongnu.org
8
bringing our checks in to line with those the kernel does.
14
Reported-by: Guenter Roeck <linux@roeck-us.net>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
18
Message-id: 20210108195157.32067-1-peter.maydell@linaro.org
19
---
20
target/arm/translate.c | 7 +++++++
21
1 file changed, 7 insertions(+)
9
22
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20220708151540.18136-40-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
linux-user/aarch64/signal.c | 51 +++++++++++++++++++++++++------------
16
1 file changed, 35 insertions(+), 16 deletions(-)
17
18
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
19
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
20
--- a/linux-user/aarch64/signal.c
25
--- a/target/arm/translate.c
21
+++ b/linux-user/aarch64/signal.c
26
+++ b/target/arm/translate.c
22
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
27
@@ -XXX,XX +XXX,XX @@ static bool valid_cp(DisasContext *s, int cp)
23
}
28
* only cp14 and cp15 are valid, and other values aren't considered
24
}
29
* to be in the coprocessor-instruction space at all. v8M still
25
30
* permits coprocessors 0..7.
26
-static void target_restore_sve_record(CPUARMState *env,
31
+ * For XScale, we must not decode the XScale cp0, cp1 space as
27
- struct target_sve_context *sve, int vq)
32
+ * a standard coprocessor insn, because we want to fall through to
28
+static bool target_restore_sve_record(CPUARMState *env,
33
+ * the legacy disas_xscale_insn() decoder after decodetree is done.
29
+ struct target_sve_context *sve,
34
*/
30
+ int size)
35
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
31
{
32
- int i, j;
33
+ int i, j, vl, vq;
34
35
- /* Note that SVE regs are stored as a byte stream, with each byte element
36
+ if (!cpu_isar_feature(aa64_sve, env_archcpu(env))) {
37
+ return false;
36
+ return false;
38
+ }
37
+ }
39
+
38
+
40
+ __get_user(vl, &sve->vl);
39
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
41
+ vq = sve_vq(env);
40
!arm_dc_feature(s, ARM_FEATURE_M)) {
42
+
41
return cp >= 14;
43
+ /* Reject mismatched VL. */
44
+ if (vl != vq * TARGET_SVE_VQ_BYTES) {
45
+ return false;
46
+ }
47
+
48
+ /* Accept empty record -- used to clear PSTATE.SM. */
49
+ if (size <= sizeof(*sve)) {
50
+ return true;
51
+ }
52
+
53
+ /* Reject non-empty but incomplete record. */
54
+ if (size < TARGET_SVE_SIG_CONTEXT_SIZE(vq)) {
55
+ return false;
56
+ }
57
+
58
+ /*
59
+ * Note that SVE regs are stored as a byte stream, with each byte element
60
* at a subsequent address. This corresponds to a little-endian load
61
* of our 64-bit hunks.
62
*/
63
@@ -XXX,XX +XXX,XX @@ static void target_restore_sve_record(CPUARMState *env,
64
}
65
}
66
}
67
+ return true;
68
}
69
70
static int target_restore_sigframe(CPUARMState *env,
71
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
72
struct target_sve_context *sve = NULL;
73
uint64_t extra_datap = 0;
74
bool used_extra = false;
75
- int vq = 0, sve_size = 0;
76
+ int sve_size = 0;
77
78
target_restore_general_frame(env, sf);
79
80
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
81
if (sve || size < sizeof(struct target_sve_context)) {
82
goto err;
83
}
84
- if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
85
- vq = sve_vq(env);
86
- sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
87
- if (size == sve_size) {
88
- sve = (struct target_sve_context *)ctx;
89
- break;
90
- }
91
- }
92
- goto err;
93
+ sve = (struct target_sve_context *)ctx;
94
+ sve_size = size;
95
+ break;
96
97
case TARGET_EXTRA_MAGIC:
98
if (extra || size != sizeof(struct target_extra_context)) {
99
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
100
}
101
102
/* SVE data, if present, overwrites FPSIMD data. */
103
- if (sve) {
104
- target_restore_sve_record(env, sve, vq);
105
+ if (sve && !target_restore_sve_record(env, sve, sve_size)) {
106
+ goto err;
107
}
108
unlock_user(extra, extra_datap, 0);
109
return 0;
110
--
42
--
111
2.25.1
43
2.20.1
44
45
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
A copy-and-paste error meant that the return value for register offset 0x44
2
(the RX Status FIFO PEEK register) returned a byte from a bogus offset in
3
the rx status FIFO. Fix the typo.
2
4
3
Make sure to zero the currently reserved fields.
5
Cc: qemu-stable@nongnu.org
6
Fixes: https://bugs.launchpad.net/qemu/+bug/1904954
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210108180401.2263-2-peter.maydell@linaro.org
10
---
11
hw/net/lan9118.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
4
13
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
index XXXXXXX..XXXXXXX 100644
7
Message-id: 20220708151540.18136-36-richard.henderson@linaro.org
16
--- a/hw/net/lan9118.c
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
+++ b/hw/net/lan9118.c
9
---
18
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
10
linux-user/aarch64/signal.c | 9 ++++++++-
19
case 0x40:
11
1 file changed, 8 insertions(+), 1 deletion(-)
20
return rx_status_fifo_pop(s);
21
case 0x44:
22
- return s->rx_status_fifo[s->tx_status_fifo_head];
23
+ return s->rx_status_fifo[s->rx_status_fifo_head];
24
case 0x48:
25
return tx_status_fifo_pop(s);
26
case 0x4c:
27
--
28
2.20.1
12
29
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
30
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
16
+++ b/linux-user/aarch64/signal.c
17
@@ -XXX,XX +XXX,XX @@ struct target_extra_context {
18
struct target_sve_context {
19
struct target_aarch64_ctx head;
20
uint16_t vl;
21
- uint16_t reserved[3];
22
+ uint16_t flags;
23
+ uint16_t reserved[2];
24
/* The actual SVE data immediately follows. It is laid out
25
* according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
26
* the original struct pointer.
27
@@ -XXX,XX +XXX,XX @@ struct target_sve_context {
28
#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
29
(TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
30
31
+#define TARGET_SVE_SIG_FLAG_SM 1
32
+
33
struct target_rt_sigframe {
34
struct target_siginfo info;
35
struct target_ucontext uc;
36
@@ -XXX,XX +XXX,XX @@ static void target_setup_sve_record(struct target_sve_context *sve,
37
{
38
int i, j;
39
40
+ memset(sve, 0, sizeof(*sve));
41
__put_user(TARGET_SVE_MAGIC, &sve->head.magic);
42
__put_user(size, &sve->head.size);
43
__put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
44
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
45
+ __put_user(TARGET_SVE_SIG_FLAG_SM, &sve->flags);
46
+ }
47
48
/* Note that SVE regs are stored as a byte stream, with each byte element
49
* at a subsequent address. This corresponds to a little-endian store
50
--
51
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The lan9118 code mostly uses symbolic constants for register offsets;
2
the exceptions are those which the datasheet doesn't give an official
3
symbolic name to.
2
4
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Add some names for the registers which don't already have them, based
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
on the longer names they are given in the memory map.
5
Message-id: 20220708151540.18136-35-richard.henderson@linaro.org
7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210108180401.2263-3-peter.maydell@linaro.org
7
---
11
---
8
linux-user/aarch64/cpu_loop.c | 9 +++++++++
12
hw/net/lan9118.c | 24 ++++++++++++++++++------
9
1 file changed, 9 insertions(+)
13
1 file changed, 18 insertions(+), 6 deletions(-)
10
14
11
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
15
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/linux-user/aarch64/cpu_loop.c
17
--- a/hw/net/lan9118.c
14
+++ b/linux-user/aarch64/cpu_loop.c
18
+++ b/hw/net/lan9118.c
15
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
19
@@ -XXX,XX +XXX,XX @@ do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
16
20
do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
17
switch (trapnr) {
21
#endif
18
case EXCP_SWI:
22
19
+ /*
23
+/* The tx and rx fifo ports are a range of aliased 32-bit registers */
20
+ * On syscall, PSTATE.ZA is preserved, along with the ZA matrix.
24
+#define RX_DATA_FIFO_PORT_FIRST 0x00
21
+ * PSTATE.SM is cleared, per SMSTOP, which does ResetSVEState.
25
+#define RX_DATA_FIFO_PORT_LAST 0x1f
22
+ */
26
+#define TX_DATA_FIFO_PORT_FIRST 0x20
23
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
27
+#define TX_DATA_FIFO_PORT_LAST 0x3f
24
+ env->svcr = FIELD_DP64(env->svcr, SVCR, SM, 0);
28
+
25
+ arm_rebuild_hflags(env);
29
+#define RX_STATUS_FIFO_PORT 0x40
26
+ arm_reset_sve_state(env);
30
+#define RX_STATUS_FIFO_PEEK 0x44
27
+ }
31
+#define TX_STATUS_FIFO_PORT 0x48
28
ret = do_syscall(env,
32
+#define TX_STATUS_FIFO_PEEK 0x4c
29
env->xregs[8],
33
+
30
env->xregs[0],
34
#define CSR_ID_REV 0x50
35
#define CSR_IRQ_CFG 0x54
36
#define CSR_INT_STS 0x58
37
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
38
offset &= 0xff;
39
40
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
41
- if (offset >= 0x20 && offset < 0x40) {
42
+ if (offset >= TX_DATA_FIFO_PORT_FIRST &&
43
+ offset <= TX_DATA_FIFO_PORT_LAST) {
44
/* TX FIFO */
45
tx_fifo_push(s, val);
46
return;
47
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
48
lan9118_state *s = (lan9118_state *)opaque;
49
50
//DPRINTF("Read reg 0x%02x\n", (int)offset);
51
- if (offset < 0x20) {
52
+ if (offset <= RX_DATA_FIFO_PORT_LAST) {
53
/* RX FIFO */
54
return rx_fifo_pop(s);
55
}
56
switch (offset) {
57
- case 0x40:
58
+ case RX_STATUS_FIFO_PORT:
59
return rx_status_fifo_pop(s);
60
- case 0x44:
61
+ case RX_STATUS_FIFO_PEEK:
62
return s->rx_status_fifo[s->rx_status_fifo_head];
63
- case 0x48:
64
+ case TX_STATUS_FIFO_PORT:
65
return tx_status_fifo_pop(s);
66
- case 0x4c:
67
+ case TX_STATUS_FIFO_PEEK:
68
return s->tx_status_fifo[s->tx_status_fifo_head];
69
case CSR_ID_REV:
70
return 0x01180001;
31
--
71
--
32
2.25.1
72
2.20.1
73
74
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Set the SM bit in the SVE record on signal delivery, create the ZA record.
3
This patch allows NPCM7XX CLK module to compute clocks that are used by
4
Restore SM and ZA state according to the records present on return.
4
other NPCM7XX modules.
5
5
6
Add a new struct NPCM7xxClockConverterState which represents a
7
single converter. Each clock converter in CLK module represents one
8
converter in NPCM7XX CLK Module(PLL, SEL or Divider). Each converter
9
takes one or more input clocks and converts them into one output clock.
10
They form a clock hierarchy in the CLK module and are responsible for
11
outputing clocks for various other modules in an NPCM7XX SoC.
12
13
Each converter has a function pointer called "convert" which represents
14
the unique logic for that converter.
15
16
The clock contains two initialization information: ConverterInitInfo and
17
ConverterConnectionInfo. They represent the vertices and edges in the
18
clock diagram respectively.
19
20
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
22
Signed-off-by: Hao Wu <wuhaotsh@google.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20210108190945.949196-2-wuhaotsh@google.com
8
Message-id: 20220708151540.18136-41-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
26
---
11
linux-user/aarch64/signal.c | 167 +++++++++++++++++++++++++++++++++---
27
include/hw/misc/npcm7xx_clk.h | 140 +++++-
12
1 file changed, 154 insertions(+), 13 deletions(-)
28
hw/misc/npcm7xx_clk.c | 805 +++++++++++++++++++++++++++++++++-
29
2 files changed, 932 insertions(+), 13 deletions(-)
13
30
14
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
15
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/aarch64/signal.c
33
--- a/include/hw/misc/npcm7xx_clk.h
17
+++ b/linux-user/aarch64/signal.c
34
+++ b/include/hw/misc/npcm7xx_clk.h
18
@@ -XXX,XX +XXX,XX @@ struct target_sve_context {
35
@@ -XXX,XX +XXX,XX @@
19
36
#define NPCM7XX_CLK_H
20
#define TARGET_SVE_SIG_FLAG_SM 1
37
21
38
#include "exec/memory.h"
22
+#define TARGET_ZA_MAGIC 0x54366345
39
+#include "hw/clock.h"
23
+
40
#include "hw/sysbus.h"
24
+struct target_za_context {
41
25
+ struct target_aarch64_ctx head;
42
/*
26
+ uint16_t vl;
43
@@ -XXX,XX +XXX,XX @@
27
+ uint16_t reserved[3];
44
28
+ /* The actual ZA data immediately follows. */
45
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
46
47
-typedef struct NPCM7xxCLKState {
48
+/* Maximum amount of clock inputs in a SEL module. */
49
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
50
+
51
+/* PLLs in CLK module. */
52
+typedef enum NPCM7xxClockPLL {
53
+ NPCM7XX_CLOCK_PLL0,
54
+ NPCM7XX_CLOCK_PLL1,
55
+ NPCM7XX_CLOCK_PLL2,
56
+ NPCM7XX_CLOCK_PLLG,
57
+ NPCM7XX_CLOCK_NR_PLLS,
58
+} NPCM7xxClockPLL;
59
+
60
+/* SEL/MUX in CLK module. */
61
+typedef enum NPCM7xxClockSEL {
62
+ NPCM7XX_CLOCK_PIXCKSEL,
63
+ NPCM7XX_CLOCK_MCCKSEL,
64
+ NPCM7XX_CLOCK_CPUCKSEL,
65
+ NPCM7XX_CLOCK_CLKOUTSEL,
66
+ NPCM7XX_CLOCK_UARTCKSEL,
67
+ NPCM7XX_CLOCK_TIMCKSEL,
68
+ NPCM7XX_CLOCK_SDCKSEL,
69
+ NPCM7XX_CLOCK_GFXMSEL,
70
+ NPCM7XX_CLOCK_SUCKSEL,
71
+ NPCM7XX_CLOCK_NR_SELS,
72
+} NPCM7xxClockSEL;
73
+
74
+/* Dividers in CLK module. */
75
+typedef enum NPCM7xxClockDivider {
76
+ NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
77
+ NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
78
+ NPCM7XX_CLOCK_MC_DIVIDER,
79
+ NPCM7XX_CLOCK_AXI_DIVIDER,
80
+ NPCM7XX_CLOCK_AHB_DIVIDER,
81
+ NPCM7XX_CLOCK_AHB3_DIVIDER,
82
+ NPCM7XX_CLOCK_SPI0_DIVIDER,
83
+ NPCM7XX_CLOCK_SPIX_DIVIDER,
84
+ NPCM7XX_CLOCK_APB1_DIVIDER,
85
+ NPCM7XX_CLOCK_APB2_DIVIDER,
86
+ NPCM7XX_CLOCK_APB3_DIVIDER,
87
+ NPCM7XX_CLOCK_APB4_DIVIDER,
88
+ NPCM7XX_CLOCK_APB5_DIVIDER,
89
+ NPCM7XX_CLOCK_CLKOUT_DIVIDER,
90
+ NPCM7XX_CLOCK_UART_DIVIDER,
91
+ NPCM7XX_CLOCK_TIMER_DIVIDER,
92
+ NPCM7XX_CLOCK_ADC_DIVIDER,
93
+ NPCM7XX_CLOCK_MMC_DIVIDER,
94
+ NPCM7XX_CLOCK_SDHC_DIVIDER,
95
+ NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
96
+ NPCM7XX_CLOCK_UTMI_DIVIDER,
97
+ NPCM7XX_CLOCK_NR_DIVIDERS,
98
+} NPCM7xxClockConverter;
99
+
100
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
101
+
102
+/**
103
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
104
+ * @name: The name of the module.
105
+ * @clk: The CLK module that owns this module.
106
+ * @clock_in: The input clock of this module.
107
+ * @clock_out: The output clock of this module.
108
+ * @reg: The control registers for this PLL module.
109
+ */
110
+typedef struct NPCM7xxClockPLLState {
111
+ DeviceState parent;
112
+
113
+ const char *name;
114
+ NPCM7xxCLKState *clk;
115
+ Clock *clock_in;
116
+ Clock *clock_out;
117
+
118
+ int reg;
119
+} NPCM7xxClockPLLState;
120
+
121
+/**
122
+ * struct NPCM7xxClockSELState - A SEL module in CLK module.
123
+ * @name: The name of the module.
124
+ * @clk: The CLK module that owns this module.
125
+ * @input_size: The size of inputs of this module.
126
+ * @clock_in: The input clocks of this module.
127
+ * @clock_out: The output clocks of this module.
128
+ * @offset: The offset of this module in the control register.
129
+ * @len: The length of this module in the control register.
130
+ */
131
+typedef struct NPCM7xxClockSELState {
132
+ DeviceState parent;
133
+
134
+ const char *name;
135
+ NPCM7xxCLKState *clk;
136
+ uint8_t input_size;
137
+ Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
138
+ Clock *clock_out;
139
+
140
+ int offset;
141
+ int len;
142
+} NPCM7xxClockSELState;
143
+
144
+/**
145
+ * struct NPCM7xxClockDividerState - A Divider module in CLK module.
146
+ * @name: The name of the module.
147
+ * @clk: The CLK module that owns this module.
148
+ * @clock_in: The input clock of this module.
149
+ * @clock_out: The output clock of this module.
150
+ * @divide: The function the divider uses to divide the input.
151
+ * @reg: The index of the control register that contains the divisor.
152
+ * @offset: The offset of the divisor in the control register.
153
+ * @len: The length of the divisor in the control register.
154
+ * @divisor: The divisor for a constant divisor
155
+ */
156
+typedef struct NPCM7xxClockDividerState {
157
+ DeviceState parent;
158
+
159
+ const char *name;
160
+ NPCM7xxCLKState *clk;
161
+ Clock *clock_in;
162
+ Clock *clock_out;
163
+
164
+ uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
165
+ union {
166
+ struct {
167
+ int reg;
168
+ int offset;
169
+ int len;
170
+ };
171
+ int divisor;
172
+ };
173
+} NPCM7xxClockDividerState;
174
+
175
+struct NPCM7xxCLKState {
176
SysBusDevice parent;
177
178
MemoryRegion iomem;
179
180
+ /* Clock converters */
181
+ NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
182
+ NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
183
+ NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
184
+
185
uint32_t regs[NPCM7XX_CLK_NR_REGS];
186
187
/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
188
int64_t ref_ns;
189
-} NPCM7xxCLKState;
190
+
191
+ /* The incoming reference clock. */
192
+ Clock *clkref;
29
+};
193
+};
30
+
194
31
+#define TARGET_ZA_SIG_REGS_OFFSET \
195
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
32
+ QEMU_ALIGN_UP(sizeof(struct target_za_context), TARGET_SVE_VQ_BYTES)
196
#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
33
+#define TARGET_ZA_SIG_ZAV_OFFSET(VQ, N) \
197
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
34
+ (TARGET_ZA_SIG_REGS_OFFSET + (VQ) * TARGET_SVE_VQ_BYTES * (N))
198
index XXXXXXX..XXXXXXX 100644
35
+#define TARGET_ZA_SIG_CONTEXT_SIZE(VQ) \
199
--- a/hw/misc/npcm7xx_clk.c
36
+ TARGET_ZA_SIG_ZAV_OFFSET(VQ, VQ * TARGET_SVE_VQ_BYTES)
200
+++ b/hw/misc/npcm7xx_clk.c
37
+
201
@@ -XXX,XX +XXX,XX @@
38
struct target_rt_sigframe {
202
39
struct target_siginfo info;
203
#include "hw/misc/npcm7xx_clk.h"
40
struct target_ucontext uc;
204
#include "hw/timer/npcm7xx_timer.h"
41
@@ -XXX,XX +XXX,XX @@ static void target_setup_end_record(struct target_aarch64_ctx *end)
205
+#include "hw/qdev-clock.h"
206
#include "migration/vmstate.h"
207
#include "qemu/error-report.h"
208
#include "qemu/log.h"
209
@@ -XXX,XX +XXX,XX @@
210
#include "trace.h"
211
#include "sysemu/watchdog.h"
212
213
+/*
214
+ * The reference clock hz, and the SECCNT and CNTR25M registers in this module,
215
+ * is always 25 MHz.
216
+ */
217
+#define NPCM7XX_CLOCK_REF_HZ (25000000)
218
+
219
+/* Register Field Definitions */
220
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
221
+
222
#define PLLCON_LOKI BIT(31)
223
#define PLLCON_LOKS BIT(30)
224
#define PLLCON_PWDEN BIT(12)
225
+#define PLLCON_FBDV(con) extract32((con), 16, 12)
226
+#define PLLCON_OTDV2(con) extract32((con), 13, 3)
227
+#define PLLCON_OTDV1(con) extract32((con), 8, 3)
228
+#define PLLCON_INDV(con) extract32((con), 0, 6)
229
230
enum NPCM7xxCLKRegisters {
231
NPCM7XX_CLK_CLKEN1,
232
@@ -XXX,XX +XXX,XX @@ static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
233
[NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
234
};
235
236
-/* Register Field Definitions */
237
-#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
238
-
239
/* The number of watchdogs that can trigger a reset. */
240
#define NPCM7XX_NR_WATCHDOGS (3)
241
242
+/* Clock converter functions */
243
+
244
+#define TYPE_NPCM7XX_CLOCK_PLL "npcm7xx-clock-pll"
245
+#define NPCM7XX_CLOCK_PLL(obj) OBJECT_CHECK(NPCM7xxClockPLLState, \
246
+ (obj), TYPE_NPCM7XX_CLOCK_PLL)
247
+#define TYPE_NPCM7XX_CLOCK_SEL "npcm7xx-clock-sel"
248
+#define NPCM7XX_CLOCK_SEL(obj) OBJECT_CHECK(NPCM7xxClockSELState, \
249
+ (obj), TYPE_NPCM7XX_CLOCK_SEL)
250
+#define TYPE_NPCM7XX_CLOCK_DIVIDER "npcm7xx-clock-divider"
251
+#define NPCM7XX_CLOCK_DIVIDER(obj) OBJECT_CHECK(NPCM7xxClockDividerState, \
252
+ (obj), TYPE_NPCM7XX_CLOCK_DIVIDER)
253
+
254
+static void npcm7xx_clk_update_pll(void *opaque)
255
+{
256
+ NPCM7xxClockPLLState *s = opaque;
257
+ uint32_t con = s->clk->regs[s->reg];
258
+ uint64_t freq;
259
+
260
+ /* The PLL is grounded if it is not locked yet. */
261
+ if (con & PLLCON_LOKI) {
262
+ freq = clock_get_hz(s->clock_in);
263
+ freq *= PLLCON_FBDV(con);
264
+ freq /= PLLCON_INDV(con) * PLLCON_OTDV1(con) * PLLCON_OTDV2(con);
265
+ } else {
266
+ freq = 0;
267
+ }
268
+
269
+ clock_update_hz(s->clock_out, freq);
270
+}
271
+
272
+static void npcm7xx_clk_update_sel(void *opaque)
273
+{
274
+ NPCM7xxClockSELState *s = opaque;
275
+ uint32_t index = extract32(s->clk->regs[NPCM7XX_CLK_CLKSEL], s->offset,
276
+ s->len);
277
+
278
+ if (index >= s->input_size) {
279
+ qemu_log_mask(LOG_GUEST_ERROR,
280
+ "%s: SEL index: %u out of range\n",
281
+ __func__, index);
282
+ index = 0;
283
+ }
284
+ clock_update_hz(s->clock_out, clock_get_hz(s->clock_in[index]));
285
+}
286
+
287
+static void npcm7xx_clk_update_divider(void *opaque)
288
+{
289
+ NPCM7xxClockDividerState *s = opaque;
290
+ uint32_t freq;
291
+
292
+ freq = s->divide(s);
293
+ clock_update_hz(s->clock_out, freq);
294
+}
295
+
296
+static uint32_t divide_by_constant(NPCM7xxClockDividerState *s)
297
+{
298
+ return clock_get_hz(s->clock_in) / s->divisor;
299
+}
300
+
301
+static uint32_t divide_by_reg_divisor(NPCM7xxClockDividerState *s)
302
+{
303
+ return clock_get_hz(s->clock_in) /
304
+ (extract32(s->clk->regs[s->reg], s->offset, s->len) + 1);
305
+}
306
+
307
+static uint32_t divide_by_reg_divisor_times_2(NPCM7xxClockDividerState *s)
308
+{
309
+ return divide_by_reg_divisor(s) / 2;
310
+}
311
+
312
+static uint32_t shift_by_reg_divisor(NPCM7xxClockDividerState *s)
313
+{
314
+ return clock_get_hz(s->clock_in) >>
315
+ extract32(s->clk->regs[s->reg], s->offset, s->len);
316
+}
317
+
318
+static NPCM7xxClockPLL find_pll_by_reg(enum NPCM7xxCLKRegisters reg)
319
+{
320
+ switch (reg) {
321
+ case NPCM7XX_CLK_PLLCON0:
322
+ return NPCM7XX_CLOCK_PLL0;
323
+ case NPCM7XX_CLK_PLLCON1:
324
+ return NPCM7XX_CLOCK_PLL1;
325
+ case NPCM7XX_CLK_PLLCON2:
326
+ return NPCM7XX_CLOCK_PLL2;
327
+ case NPCM7XX_CLK_PLLCONG:
328
+ return NPCM7XX_CLOCK_PLLG;
329
+ default:
330
+ g_assert_not_reached();
331
+ }
332
+}
333
+
334
+static void npcm7xx_clk_update_all_plls(NPCM7xxCLKState *clk)
335
+{
336
+ int i;
337
+
338
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
339
+ npcm7xx_clk_update_pll(&clk->plls[i]);
340
+ }
341
+}
342
+
343
+static void npcm7xx_clk_update_all_sels(NPCM7xxCLKState *clk)
344
+{
345
+ int i;
346
+
347
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
348
+ npcm7xx_clk_update_sel(&clk->sels[i]);
349
+ }
350
+}
351
+
352
+static void npcm7xx_clk_update_all_dividers(NPCM7xxCLKState *clk)
353
+{
354
+ int i;
355
+
356
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
357
+ npcm7xx_clk_update_divider(&clk->dividers[i]);
358
+ }
359
+}
360
+
361
+static void npcm7xx_clk_update_all_clocks(NPCM7xxCLKState *clk)
362
+{
363
+ clock_update_hz(clk->clkref, NPCM7XX_CLOCK_REF_HZ);
364
+ npcm7xx_clk_update_all_plls(clk);
365
+ npcm7xx_clk_update_all_sels(clk);
366
+ npcm7xx_clk_update_all_dividers(clk);
367
+}
368
+
369
+/* Types of clock sources. */
370
+typedef enum ClockSrcType {
371
+ CLKSRC_REF,
372
+ CLKSRC_PLL,
373
+ CLKSRC_SEL,
374
+ CLKSRC_DIV,
375
+} ClockSrcType;
376
+
377
+typedef struct PLLInitInfo {
378
+ const char *name;
379
+ ClockSrcType src_type;
380
+ int src_index;
381
+ int reg;
382
+ const char *public_name;
383
+} PLLInitInfo;
384
+
385
+typedef struct SELInitInfo {
386
+ const char *name;
387
+ uint8_t input_size;
388
+ ClockSrcType src_type[NPCM7XX_CLK_SEL_MAX_INPUT];
389
+ int src_index[NPCM7XX_CLK_SEL_MAX_INPUT];
390
+ int offset;
391
+ int len;
392
+ const char *public_name;
393
+} SELInitInfo;
394
+
395
+typedef struct DividerInitInfo {
396
+ const char *name;
397
+ ClockSrcType src_type;
398
+ int src_index;
399
+ uint32_t (*divide)(NPCM7xxClockDividerState *s);
400
+ int reg; /* not used when type == CONSTANT */
401
+ int offset; /* not used when type == CONSTANT */
402
+ int len; /* not used when type == CONSTANT */
403
+ int divisor; /* used only when type == CONSTANT */
404
+ const char *public_name;
405
+} DividerInitInfo;
406
+
407
+static const PLLInitInfo pll_init_info_list[] = {
408
+ [NPCM7XX_CLOCK_PLL0] = {
409
+ .name = "pll0",
410
+ .src_type = CLKSRC_REF,
411
+ .reg = NPCM7XX_CLK_PLLCON0,
412
+ },
413
+ [NPCM7XX_CLOCK_PLL1] = {
414
+ .name = "pll1",
415
+ .src_type = CLKSRC_REF,
416
+ .reg = NPCM7XX_CLK_PLLCON1,
417
+ },
418
+ [NPCM7XX_CLOCK_PLL2] = {
419
+ .name = "pll2",
420
+ .src_type = CLKSRC_REF,
421
+ .reg = NPCM7XX_CLK_PLLCON2,
422
+ },
423
+ [NPCM7XX_CLOCK_PLLG] = {
424
+ .name = "pllg",
425
+ .src_type = CLKSRC_REF,
426
+ .reg = NPCM7XX_CLK_PLLCONG,
427
+ },
428
+};
429
+
430
+static const SELInitInfo sel_init_info_list[] = {
431
+ [NPCM7XX_CLOCK_PIXCKSEL] = {
432
+ .name = "pixcksel",
433
+ .input_size = 2,
434
+ .src_type = {CLKSRC_PLL, CLKSRC_REF},
435
+ .src_index = {NPCM7XX_CLOCK_PLLG, 0},
436
+ .offset = 5,
437
+ .len = 1,
438
+ .public_name = "pixel-clock",
439
+ },
440
+ [NPCM7XX_CLOCK_MCCKSEL] = {
441
+ .name = "mccksel",
442
+ .input_size = 4,
443
+ .src_type = {CLKSRC_DIV, CLKSRC_REF, CLKSRC_REF,
444
+ /*MCBPCK, shouldn't be used in normal operation*/
445
+ CLKSRC_REF},
446
+ .src_index = {NPCM7XX_CLOCK_PLL1D2, 0, 0, 0},
447
+ .offset = 12,
448
+ .len = 2,
449
+ .public_name = "mc-phy-clock",
450
+ },
451
+ [NPCM7XX_CLOCK_CPUCKSEL] = {
452
+ .name = "cpucksel",
453
+ .input_size = 4,
454
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
455
+ /*SYSBPCK, shouldn't be used in normal operation*/
456
+ CLKSRC_REF},
457
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0, 0},
458
+ .offset = 0,
459
+ .len = 2,
460
+ .public_name = "system-clock",
461
+ },
462
+ [NPCM7XX_CLOCK_CLKOUTSEL] = {
463
+ .name = "clkoutsel",
464
+ .input_size = 5,
465
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
466
+ CLKSRC_PLL, CLKSRC_DIV},
467
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
468
+ NPCM7XX_CLOCK_PLLG, NPCM7XX_CLOCK_PLL2D2},
469
+ .offset = 18,
470
+ .len = 3,
471
+ .public_name = "tock",
472
+ },
473
+ [NPCM7XX_CLOCK_UARTCKSEL] = {
474
+ .name = "uartcksel",
475
+ .input_size = 4,
476
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
477
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
478
+ NPCM7XX_CLOCK_PLL2D2},
479
+ .offset = 8,
480
+ .len = 2,
481
+ },
482
+ [NPCM7XX_CLOCK_TIMCKSEL] = {
483
+ .name = "timcksel",
484
+ .input_size = 4,
485
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
486
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
487
+ NPCM7XX_CLOCK_PLL2D2},
488
+ .offset = 14,
489
+ .len = 2,
490
+ },
491
+ [NPCM7XX_CLOCK_SDCKSEL] = {
492
+ .name = "sdcksel",
493
+ .input_size = 4,
494
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
495
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
496
+ NPCM7XX_CLOCK_PLL2D2},
497
+ .offset = 6,
498
+ .len = 2,
499
+ },
500
+ [NPCM7XX_CLOCK_GFXMSEL] = {
501
+ .name = "gfxmksel",
502
+ .input_size = 2,
503
+ .src_type = {CLKSRC_REF, CLKSRC_PLL},
504
+ .src_index = {0, NPCM7XX_CLOCK_PLL2},
505
+ .offset = 21,
506
+ .len = 1,
507
+ },
508
+ [NPCM7XX_CLOCK_SUCKSEL] = {
509
+ .name = "sucksel",
510
+ .input_size = 4,
511
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
512
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
513
+ NPCM7XX_CLOCK_PLL2D2},
514
+ .offset = 10,
515
+ .len = 2,
516
+ },
517
+};
518
+
519
+static const DividerInitInfo divider_init_info_list[] = {
520
+ [NPCM7XX_CLOCK_PLL1D2] = {
521
+ .name = "pll1d2",
522
+ .src_type = CLKSRC_PLL,
523
+ .src_index = NPCM7XX_CLOCK_PLL1,
524
+ .divide = divide_by_constant,
525
+ .divisor = 2,
526
+ },
527
+ [NPCM7XX_CLOCK_PLL2D2] = {
528
+ .name = "pll2d2",
529
+ .src_type = CLKSRC_PLL,
530
+ .src_index = NPCM7XX_CLOCK_PLL2,
531
+ .divide = divide_by_constant,
532
+ .divisor = 2,
533
+ },
534
+ [NPCM7XX_CLOCK_MC_DIVIDER] = {
535
+ .name = "mc-divider",
536
+ .src_type = CLKSRC_SEL,
537
+ .src_index = NPCM7XX_CLOCK_MCCKSEL,
538
+ .divide = divide_by_constant,
539
+ .divisor = 2,
540
+ .public_name = "mc-clock"
541
+ },
542
+ [NPCM7XX_CLOCK_AXI_DIVIDER] = {
543
+ .name = "axi-divider",
544
+ .src_type = CLKSRC_SEL,
545
+ .src_index = NPCM7XX_CLOCK_CPUCKSEL,
546
+ .divide = shift_by_reg_divisor,
547
+ .reg = NPCM7XX_CLK_CLKDIV1,
548
+ .offset = 0,
549
+ .len = 1,
550
+ .public_name = "clk2"
551
+ },
552
+ [NPCM7XX_CLOCK_AHB_DIVIDER] = {
553
+ .name = "ahb-divider",
554
+ .src_type = CLKSRC_DIV,
555
+ .src_index = NPCM7XX_CLOCK_AXI_DIVIDER,
556
+ .divide = divide_by_reg_divisor,
557
+ .reg = NPCM7XX_CLK_CLKDIV1,
558
+ .offset = 26,
559
+ .len = 2,
560
+ .public_name = "clk4"
561
+ },
562
+ [NPCM7XX_CLOCK_AHB3_DIVIDER] = {
563
+ .name = "ahb3-divider",
564
+ .src_type = CLKSRC_DIV,
565
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
566
+ .divide = divide_by_reg_divisor,
567
+ .reg = NPCM7XX_CLK_CLKDIV1,
568
+ .offset = 6,
569
+ .len = 5,
570
+ .public_name = "ahb3-spi3-clock"
571
+ },
572
+ [NPCM7XX_CLOCK_SPI0_DIVIDER] = {
573
+ .name = "spi0-divider",
574
+ .src_type = CLKSRC_DIV,
575
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
576
+ .divide = divide_by_reg_divisor,
577
+ .reg = NPCM7XX_CLK_CLKDIV3,
578
+ .offset = 6,
579
+ .len = 5,
580
+ .public_name = "spi0-clock",
581
+ },
582
+ [NPCM7XX_CLOCK_SPIX_DIVIDER] = {
583
+ .name = "spix-divider",
584
+ .src_type = CLKSRC_DIV,
585
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
586
+ .divide = divide_by_reg_divisor,
587
+ .reg = NPCM7XX_CLK_CLKDIV3,
588
+ .offset = 1,
589
+ .len = 5,
590
+ .public_name = "spix-clock",
591
+ },
592
+ [NPCM7XX_CLOCK_APB1_DIVIDER] = {
593
+ .name = "apb1-divider",
594
+ .src_type = CLKSRC_DIV,
595
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
596
+ .divide = shift_by_reg_divisor,
597
+ .reg = NPCM7XX_CLK_CLKDIV2,
598
+ .offset = 24,
599
+ .len = 2,
600
+ .public_name = "apb1-clock",
601
+ },
602
+ [NPCM7XX_CLOCK_APB2_DIVIDER] = {
603
+ .name = "apb2-divider",
604
+ .src_type = CLKSRC_DIV,
605
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
606
+ .divide = shift_by_reg_divisor,
607
+ .reg = NPCM7XX_CLK_CLKDIV2,
608
+ .offset = 26,
609
+ .len = 2,
610
+ .public_name = "apb2-clock",
611
+ },
612
+ [NPCM7XX_CLOCK_APB3_DIVIDER] = {
613
+ .name = "apb3-divider",
614
+ .src_type = CLKSRC_DIV,
615
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
616
+ .divide = shift_by_reg_divisor,
617
+ .reg = NPCM7XX_CLK_CLKDIV2,
618
+ .offset = 28,
619
+ .len = 2,
620
+ .public_name = "apb3-clock",
621
+ },
622
+ [NPCM7XX_CLOCK_APB4_DIVIDER] = {
623
+ .name = "apb4-divider",
624
+ .src_type = CLKSRC_DIV,
625
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
626
+ .divide = shift_by_reg_divisor,
627
+ .reg = NPCM7XX_CLK_CLKDIV2,
628
+ .offset = 30,
629
+ .len = 2,
630
+ .public_name = "apb4-clock",
631
+ },
632
+ [NPCM7XX_CLOCK_APB5_DIVIDER] = {
633
+ .name = "apb5-divider",
634
+ .src_type = CLKSRC_DIV,
635
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
636
+ .divide = shift_by_reg_divisor,
637
+ .reg = NPCM7XX_CLK_CLKDIV2,
638
+ .offset = 22,
639
+ .len = 2,
640
+ .public_name = "apb5-clock",
641
+ },
642
+ [NPCM7XX_CLOCK_CLKOUT_DIVIDER] = {
643
+ .name = "clkout-divider",
644
+ .src_type = CLKSRC_SEL,
645
+ .src_index = NPCM7XX_CLOCK_CLKOUTSEL,
646
+ .divide = divide_by_reg_divisor,
647
+ .reg = NPCM7XX_CLK_CLKDIV2,
648
+ .offset = 16,
649
+ .len = 5,
650
+ .public_name = "clkout",
651
+ },
652
+ [NPCM7XX_CLOCK_UART_DIVIDER] = {
653
+ .name = "uart-divider",
654
+ .src_type = CLKSRC_SEL,
655
+ .src_index = NPCM7XX_CLOCK_UARTCKSEL,
656
+ .divide = divide_by_reg_divisor,
657
+ .reg = NPCM7XX_CLK_CLKDIV1,
658
+ .offset = 16,
659
+ .len = 5,
660
+ .public_name = "uart-clock",
661
+ },
662
+ [NPCM7XX_CLOCK_TIMER_DIVIDER] = {
663
+ .name = "timer-divider",
664
+ .src_type = CLKSRC_SEL,
665
+ .src_index = NPCM7XX_CLOCK_TIMCKSEL,
666
+ .divide = divide_by_reg_divisor,
667
+ .reg = NPCM7XX_CLK_CLKDIV1,
668
+ .offset = 21,
669
+ .len = 5,
670
+ .public_name = "timer-clock",
671
+ },
672
+ [NPCM7XX_CLOCK_ADC_DIVIDER] = {
673
+ .name = "adc-divider",
674
+ .src_type = CLKSRC_DIV,
675
+ .src_index = NPCM7XX_CLOCK_TIMER_DIVIDER,
676
+ .divide = shift_by_reg_divisor,
677
+ .reg = NPCM7XX_CLK_CLKDIV1,
678
+ .offset = 28,
679
+ .len = 3,
680
+ .public_name = "adc-clock",
681
+ },
682
+ [NPCM7XX_CLOCK_MMC_DIVIDER] = {
683
+ .name = "mmc-divider",
684
+ .src_type = CLKSRC_SEL,
685
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
686
+ .divide = divide_by_reg_divisor,
687
+ .reg = NPCM7XX_CLK_CLKDIV1,
688
+ .offset = 11,
689
+ .len = 5,
690
+ .public_name = "mmc-clock",
691
+ },
692
+ [NPCM7XX_CLOCK_SDHC_DIVIDER] = {
693
+ .name = "sdhc-divider",
694
+ .src_type = CLKSRC_SEL,
695
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
696
+ .divide = divide_by_reg_divisor_times_2,
697
+ .reg = NPCM7XX_CLK_CLKDIV2,
698
+ .offset = 0,
699
+ .len = 4,
700
+ .public_name = "sdhc-clock",
701
+ },
702
+ [NPCM7XX_CLOCK_GFXM_DIVIDER] = {
703
+ .name = "gfxm-divider",
704
+ .src_type = CLKSRC_SEL,
705
+ .src_index = NPCM7XX_CLOCK_GFXMSEL,
706
+ .divide = divide_by_constant,
707
+ .divisor = 3,
708
+ .public_name = "gfxm-clock",
709
+ },
710
+ [NPCM7XX_CLOCK_UTMI_DIVIDER] = {
711
+ .name = "utmi-divider",
712
+ .src_type = CLKSRC_SEL,
713
+ .src_index = NPCM7XX_CLOCK_SUCKSEL,
714
+ .divide = divide_by_reg_divisor,
715
+ .reg = NPCM7XX_CLK_CLKDIV2,
716
+ .offset = 8,
717
+ .len = 5,
718
+ .public_name = "utmi-clock",
719
+ },
720
+};
721
+
722
+static void npcm7xx_clk_pll_init(Object *obj)
723
+{
724
+ NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
725
+
726
+ pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
727
+ npcm7xx_clk_update_pll, pll);
728
+ pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
729
+}
730
+
731
+static void npcm7xx_clk_sel_init(Object *obj)
732
+{
733
+ int i;
734
+ NPCM7xxClockSELState *sel = NPCM7XX_CLOCK_SEL(obj);
735
+
736
+ for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
737
+ sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel),
738
+ g_strdup_printf("clock-in[%d]", i),
739
+ npcm7xx_clk_update_sel, sel);
740
+ }
741
+ sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
742
+}
743
+static void npcm7xx_clk_divider_init(Object *obj)
744
+{
745
+ NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
746
+
747
+ div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
748
+ npcm7xx_clk_update_divider, div);
749
+ div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
750
+}
751
+
752
+static void npcm7xx_init_clock_pll(NPCM7xxClockPLLState *pll,
753
+ NPCM7xxCLKState *clk, const PLLInitInfo *init_info)
754
+{
755
+ pll->name = init_info->name;
756
+ pll->clk = clk;
757
+ pll->reg = init_info->reg;
758
+ if (init_info->public_name != NULL) {
759
+ qdev_alias_clock(DEVICE(pll), "clock-out", DEVICE(clk),
760
+ init_info->public_name);
761
+ }
762
+}
763
+
764
+static void npcm7xx_init_clock_sel(NPCM7xxClockSELState *sel,
765
+ NPCM7xxCLKState *clk, const SELInitInfo *init_info)
766
+{
767
+ int input_size = init_info->input_size;
768
+
769
+ sel->name = init_info->name;
770
+ sel->clk = clk;
771
+ sel->input_size = init_info->input_size;
772
+ g_assert(input_size <= NPCM7XX_CLK_SEL_MAX_INPUT);
773
+ sel->offset = init_info->offset;
774
+ sel->len = init_info->len;
775
+ if (init_info->public_name != NULL) {
776
+ qdev_alias_clock(DEVICE(sel), "clock-out", DEVICE(clk),
777
+ init_info->public_name);
778
+ }
779
+}
780
+
781
+static void npcm7xx_init_clock_divider(NPCM7xxClockDividerState *div,
782
+ NPCM7xxCLKState *clk, const DividerInitInfo *init_info)
783
+{
784
+ div->name = init_info->name;
785
+ div->clk = clk;
786
+
787
+ div->divide = init_info->divide;
788
+ if (div->divide == divide_by_constant) {
789
+ div->divisor = init_info->divisor;
790
+ } else {
791
+ div->reg = init_info->reg;
792
+ div->offset = init_info->offset;
793
+ div->len = init_info->len;
794
+ }
795
+ if (init_info->public_name != NULL) {
796
+ qdev_alias_clock(DEVICE(div), "clock-out", DEVICE(clk),
797
+ init_info->public_name);
798
+ }
799
+}
800
+
801
+static Clock *npcm7xx_get_clock(NPCM7xxCLKState *clk, ClockSrcType type,
802
+ int index)
803
+{
804
+ switch (type) {
805
+ case CLKSRC_REF:
806
+ return clk->clkref;
807
+ case CLKSRC_PLL:
808
+ return clk->plls[index].clock_out;
809
+ case CLKSRC_SEL:
810
+ return clk->sels[index].clock_out;
811
+ case CLKSRC_DIV:
812
+ return clk->dividers[index].clock_out;
813
+ default:
814
+ g_assert_not_reached();
815
+ }
816
+}
817
+
818
+static void npcm7xx_connect_clocks(NPCM7xxCLKState *clk)
819
+{
820
+ int i, j;
821
+ Clock *src;
822
+
823
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
824
+ src = npcm7xx_get_clock(clk, pll_init_info_list[i].src_type,
825
+ pll_init_info_list[i].src_index);
826
+ clock_set_source(clk->plls[i].clock_in, src);
827
+ }
828
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
829
+ for (j = 0; j < sel_init_info_list[i].input_size; ++j) {
830
+ src = npcm7xx_get_clock(clk, sel_init_info_list[i].src_type[j],
831
+ sel_init_info_list[i].src_index[j]);
832
+ clock_set_source(clk->sels[i].clock_in[j], src);
833
+ }
834
+ }
835
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
836
+ src = npcm7xx_get_clock(clk, divider_init_info_list[i].src_type,
837
+ divider_init_info_list[i].src_index);
838
+ clock_set_source(clk->dividers[i].clock_in, src);
839
+ }
840
+}
841
+
842
static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
843
{
844
uint32_t reg = offset / sizeof(uint32_t);
845
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
846
*
847
* The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
848
*/
849
- value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
850
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_CLOCK_REF_HZ;
851
break;
852
853
default:
854
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
855
value |= (value & PLLCON_LOKS);
856
}
857
}
858
+ /* Only update PLL when it is locked. */
859
+ if (value & PLLCON_LOKI) {
860
+ npcm7xx_clk_update_pll(&s->plls[find_pll_by_reg(reg)]);
861
+ }
862
+ break;
863
+
864
+ case NPCM7XX_CLK_CLKSEL:
865
+ npcm7xx_clk_update_all_sels(s);
866
+ break;
867
+
868
+ case NPCM7XX_CLK_CLKDIV1:
869
+ case NPCM7XX_CLK_CLKDIV2:
870
+ case NPCM7XX_CLK_CLKDIV3:
871
+ npcm7xx_clk_update_all_dividers(s);
872
break;
873
874
case NPCM7XX_CLK_CNTR25M:
875
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
876
case RESET_TYPE_COLD:
877
memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
878
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
879
+ npcm7xx_clk_update_all_clocks(s);
880
return;
881
}
882
883
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
884
__func__, type);
42
}
885
}
43
886
44
static void target_setup_sve_record(struct target_sve_context *sve,
887
+static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
45
- CPUARMState *env, int vq, int size)
888
+{
46
+ CPUARMState *env, int size)
889
+ int i;
890
+
891
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
892
+
893
+ /* First pass: init all converter modules */
894
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
895
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
896
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
897
+ != NPCM7XX_CLOCK_NR_DIVIDERS);
898
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
899
+ object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
900
+ &s->plls[i], TYPE_NPCM7XX_CLOCK_PLL);
901
+ npcm7xx_init_clock_pll(&s->plls[i], s,
902
+ &pll_init_info_list[i]);
903
+ }
904
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
905
+ object_initialize_child(OBJECT(s), sel_init_info_list[i].name,
906
+ &s->sels[i], TYPE_NPCM7XX_CLOCK_SEL);
907
+ npcm7xx_init_clock_sel(&s->sels[i], s,
908
+ &sel_init_info_list[i]);
909
+ }
910
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
911
+ object_initialize_child(OBJECT(s), divider_init_info_list[i].name,
912
+ &s->dividers[i], TYPE_NPCM7XX_CLOCK_DIVIDER);
913
+ npcm7xx_init_clock_divider(&s->dividers[i], s,
914
+ &divider_init_info_list[i]);
915
+ }
916
+
917
+ /* Second pass: connect converter modules */
918
+ npcm7xx_connect_clocks(s);
919
+
920
+ clock_update_hz(s->clkref, NPCM7XX_CLOCK_REF_HZ);
921
+}
922
+
923
static void npcm7xx_clk_init(Object *obj)
47
{
924
{
48
- int i, j;
925
NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
49
+ int i, j, vq = sve_vq(env);
926
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
50
927
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
51
memset(sve, 0, sizeof(*sve));
928
TYPE_NPCM7XX_CLK, 4 * KiB);
52
__put_user(TARGET_SVE_MAGIC, &sve->head.magic);
929
sysbus_init_mmio(&s->parent, &s->iomem);
53
@@ -XXX,XX +XXX,XX @@ static void target_setup_sve_record(struct target_sve_context *sve,
930
- qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
54
}
931
- NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
55
}
932
}
56
933
57
+static void target_setup_za_record(struct target_za_context *za,
934
-static const VMStateDescription vmstate_npcm7xx_clk = {
58
+ CPUARMState *env, int size)
935
- .name = "npcm7xx-clk",
59
+{
936
+static int npcm7xx_clk_post_load(void *opaque, int version_id)
60
+ int vq = sme_vq(env);
937
+{
61
+ int vl = vq * TARGET_SVE_VQ_BYTES;
938
+ if (version_id >= 1) {
62
+ int i, j;
939
+ NPCM7xxCLKState *clk = opaque;
63
+
940
+
64
+ memset(za, 0, sizeof(*za));
941
+ npcm7xx_clk_update_all_clocks(clk);
65
+ __put_user(TARGET_ZA_MAGIC, &za->head.magic);
942
+ }
66
+ __put_user(size, &za->head.size);
943
+
67
+ __put_user(vl, &za->vl);
944
+ return 0;
68
+
945
+}
69
+ if (size == TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
946
+
70
+ return;
947
+static void npcm7xx_clk_realize(DeviceState *dev, Error **errp)
71
+ }
948
+{
72
+ assert(size == TARGET_ZA_SIG_CONTEXT_SIZE(vq));
949
+ int i;
73
+
950
+ NPCM7xxCLKState *s = NPCM7XX_CLK(dev);
74
+ /*
951
+
75
+ * Note that ZA vectors are stored as a byte stream,
952
+ qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
76
+ * with each byte element at a subsequent address.
953
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
77
+ */
954
+ npcm7xx_clk_init_clock_hierarchy(s);
78
+ for (i = 0; i < vl; ++i) {
955
+
79
+ uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
956
+ /* Realize child devices */
80
+ for (j = 0; j < vq * 2; ++j) {
957
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
81
+ __put_user_e(env->zarray[i].d[j], z + j, le);
958
+ if (!qdev_realize(DEVICE(&s->plls[i]), NULL, errp)) {
959
+ return;
82
+ }
960
+ }
83
+ }
961
+ }
84
+}
962
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
85
+
963
+ if (!qdev_realize(DEVICE(&s->sels[i]), NULL, errp)) {
86
static void target_restore_general_frame(CPUARMState *env,
964
+ return;
87
struct target_rt_sigframe *sf)
965
+ }
966
+ }
967
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
968
+ if (!qdev_realize(DEVICE(&s->dividers[i]), NULL, errp)) {
969
+ return;
970
+ }
971
+ }
972
+}
973
+
974
+static const VMStateDescription vmstate_npcm7xx_clk_pll = {
975
+ .name = "npcm7xx-clock-pll",
976
.version_id = 0,
977
.minimum_version_id = 0,
978
- .fields = (VMStateField[]) {
979
- VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
980
- VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
981
+ .fields = (VMStateField[]) {
982
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockPLLState),
983
VMSTATE_END_OF_LIST(),
984
},
985
};
986
987
+static const VMStateDescription vmstate_npcm7xx_clk_sel = {
988
+ .name = "npcm7xx-clock-sel",
989
+ .version_id = 0,
990
+ .minimum_version_id = 0,
991
+ .fields = (VMStateField[]) {
992
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(clock_in, NPCM7xxClockSELState,
993
+ NPCM7XX_CLK_SEL_MAX_INPUT, 0, vmstate_clock, Clock),
994
+ VMSTATE_END_OF_LIST(),
995
+ },
996
+};
997
+
998
+static const VMStateDescription vmstate_npcm7xx_clk_divider = {
999
+ .name = "npcm7xx-clock-divider",
1000
+ .version_id = 0,
1001
+ .minimum_version_id = 0,
1002
+ .fields = (VMStateField[]) {
1003
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockDividerState),
1004
+ VMSTATE_END_OF_LIST(),
1005
+ },
1006
+};
1007
+
1008
+static const VMStateDescription vmstate_npcm7xx_clk = {
1009
+ .name = "npcm7xx-clk",
1010
+ .version_id = 1,
1011
+ .minimum_version_id = 1,
1012
+ .post_load = npcm7xx_clk_post_load,
1013
+ .fields = (VMStateField[]) {
1014
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
1015
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
1016
+ VMSTATE_CLOCK(clkref, NPCM7xxCLKState),
1017
+ VMSTATE_END_OF_LIST(),
1018
+ },
1019
+};
1020
+
1021
+static void npcm7xx_clk_pll_class_init(ObjectClass *klass, void *data)
1022
+{
1023
+ DeviceClass *dc = DEVICE_CLASS(klass);
1024
+
1025
+ dc->desc = "NPCM7xx Clock PLL Module";
1026
+ dc->vmsd = &vmstate_npcm7xx_clk_pll;
1027
+}
1028
+
1029
+static void npcm7xx_clk_sel_class_init(ObjectClass *klass, void *data)
1030
+{
1031
+ DeviceClass *dc = DEVICE_CLASS(klass);
1032
+
1033
+ dc->desc = "NPCM7xx Clock SEL Module";
1034
+ dc->vmsd = &vmstate_npcm7xx_clk_sel;
1035
+}
1036
+
1037
+static void npcm7xx_clk_divider_class_init(ObjectClass *klass, void *data)
1038
+{
1039
+ DeviceClass *dc = DEVICE_CLASS(klass);
1040
+
1041
+ dc->desc = "NPCM7xx Clock Divider Module";
1042
+ dc->vmsd = &vmstate_npcm7xx_clk_divider;
1043
+}
1044
+
1045
static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
88
{
1046
{
89
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
1047
ResettableClass *rc = RESETTABLE_CLASS(klass);
90
1048
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
91
static bool target_restore_sve_record(CPUARMState *env,
1049
92
struct target_sve_context *sve,
1050
dc->desc = "NPCM7xx Clock Control Registers";
93
- int size)
1051
dc->vmsd = &vmstate_npcm7xx_clk;
94
+ int size, int *svcr)
1052
+ dc->realize = npcm7xx_clk_realize;
1053
rc->phases.enter = npcm7xx_clk_enter_reset;
1054
}
1055
1056
+static const TypeInfo npcm7xx_clk_pll_info = {
1057
+ .name = TYPE_NPCM7XX_CLOCK_PLL,
1058
+ .parent = TYPE_DEVICE,
1059
+ .instance_size = sizeof(NPCM7xxClockPLLState),
1060
+ .instance_init = npcm7xx_clk_pll_init,
1061
+ .class_init = npcm7xx_clk_pll_class_init,
1062
+};
1063
+
1064
+static const TypeInfo npcm7xx_clk_sel_info = {
1065
+ .name = TYPE_NPCM7XX_CLOCK_SEL,
1066
+ .parent = TYPE_DEVICE,
1067
+ .instance_size = sizeof(NPCM7xxClockSELState),
1068
+ .instance_init = npcm7xx_clk_sel_init,
1069
+ .class_init = npcm7xx_clk_sel_class_init,
1070
+};
1071
+
1072
+static const TypeInfo npcm7xx_clk_divider_info = {
1073
+ .name = TYPE_NPCM7XX_CLOCK_DIVIDER,
1074
+ .parent = TYPE_DEVICE,
1075
+ .instance_size = sizeof(NPCM7xxClockDividerState),
1076
+ .instance_init = npcm7xx_clk_divider_init,
1077
+ .class_init = npcm7xx_clk_divider_class_init,
1078
+};
1079
+
1080
static const TypeInfo npcm7xx_clk_info = {
1081
.name = TYPE_NPCM7XX_CLK,
1082
.parent = TYPE_SYS_BUS_DEVICE,
1083
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_clk_info = {
1084
1085
static void npcm7xx_clk_register_type(void)
95
{
1086
{
96
- int i, j, vl, vq;
1087
+ type_register_static(&npcm7xx_clk_pll_info);
97
+ int i, j, vl, vq, flags;
1088
+ type_register_static(&npcm7xx_clk_sel_info);
98
+ bool sm;
1089
+ type_register_static(&npcm7xx_clk_divider_info);
99
1090
type_register_static(&npcm7xx_clk_info);
100
- if (!cpu_isar_feature(aa64_sve, env_archcpu(env))) {
101
+ __get_user(vl, &sve->vl);
102
+ __get_user(flags, &sve->flags);
103
+
104
+ sm = flags & TARGET_SVE_SIG_FLAG_SM;
105
+
106
+ /* The cpu must support Streaming or Non-streaming SVE. */
107
+ if (sm
108
+ ? !cpu_isar_feature(aa64_sme, env_archcpu(env))
109
+ : !cpu_isar_feature(aa64_sve, env_archcpu(env))) {
110
return false;
111
}
112
113
- __get_user(vl, &sve->vl);
114
- vq = sve_vq(env);
115
+ /*
116
+ * Note that we cannot use sve_vq() because that depends on the
117
+ * current setting of PSTATE.SM, not the state to be restored.
118
+ */
119
+ vq = sve_vqm1_for_el_sm(env, 0, sm) + 1;
120
121
/* Reject mismatched VL. */
122
if (vl != vq * TARGET_SVE_VQ_BYTES) {
123
@@ -XXX,XX +XXX,XX @@ static bool target_restore_sve_record(CPUARMState *env,
124
return false;
125
}
126
127
+ *svcr = FIELD_DP64(*svcr, SVCR, SM, sm);
128
+
129
/*
130
* Note that SVE regs are stored as a byte stream, with each byte element
131
* at a subsequent address. This corresponds to a little-endian load
132
@@ -XXX,XX +XXX,XX @@ static bool target_restore_sve_record(CPUARMState *env,
133
return true;
134
}
1091
}
135
1092
type_init(npcm7xx_clk_register_type);
136
+static bool target_restore_za_record(CPUARMState *env,
137
+ struct target_za_context *za,
138
+ int size, int *svcr)
139
+{
140
+ int i, j, vl, vq;
141
+
142
+ if (!cpu_isar_feature(aa64_sme, env_archcpu(env))) {
143
+ return false;
144
+ }
145
+
146
+ __get_user(vl, &za->vl);
147
+ vq = sme_vq(env);
148
+
149
+ /* Reject mismatched VL. */
150
+ if (vl != vq * TARGET_SVE_VQ_BYTES) {
151
+ return false;
152
+ }
153
+
154
+ /* Accept empty record -- used to clear PSTATE.ZA. */
155
+ if (size <= TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
156
+ return true;
157
+ }
158
+
159
+ /* Reject non-empty but incomplete record. */
160
+ if (size < TARGET_ZA_SIG_CONTEXT_SIZE(vq)) {
161
+ return false;
162
+ }
163
+
164
+ *svcr = FIELD_DP64(*svcr, SVCR, ZA, 1);
165
+
166
+ for (i = 0; i < vl; ++i) {
167
+ uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
168
+ for (j = 0; j < vq * 2; ++j) {
169
+ __get_user_e(env->zarray[i].d[j], z + j, le);
170
+ }
171
+ }
172
+ return true;
173
+}
174
+
175
static int target_restore_sigframe(CPUARMState *env,
176
struct target_rt_sigframe *sf)
177
{
178
struct target_aarch64_ctx *ctx, *extra = NULL;
179
struct target_fpsimd_context *fpsimd = NULL;
180
struct target_sve_context *sve = NULL;
181
+ struct target_za_context *za = NULL;
182
uint64_t extra_datap = 0;
183
bool used_extra = false;
184
int sve_size = 0;
185
+ int za_size = 0;
186
+ int svcr = 0;
187
188
target_restore_general_frame(env, sf);
189
190
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
191
sve_size = size;
192
break;
193
194
+ case TARGET_ZA_MAGIC:
195
+ if (za || size < sizeof(struct target_za_context)) {
196
+ goto err;
197
+ }
198
+ za = (struct target_za_context *)ctx;
199
+ za_size = size;
200
+ break;
201
+
202
case TARGET_EXTRA_MAGIC:
203
if (extra || size != sizeof(struct target_extra_context)) {
204
goto err;
205
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
206
}
207
208
/* SVE data, if present, overwrites FPSIMD data. */
209
- if (sve && !target_restore_sve_record(env, sve, sve_size)) {
210
+ if (sve && !target_restore_sve_record(env, sve, sve_size, &svcr)) {
211
goto err;
212
}
213
+ if (za && !target_restore_za_record(env, za, za_size, &svcr)) {
214
+ goto err;
215
+ }
216
+ if (env->svcr != svcr) {
217
+ env->svcr = svcr;
218
+ arm_rebuild_hflags(env);
219
+ }
220
unlock_user(extra, extra_datap, 0);
221
return 0;
222
223
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
224
.total_size = offsetof(struct target_rt_sigframe,
225
uc.tuc_mcontext.__reserved),
226
};
227
- int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
228
+ int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0;
229
+ int sve_size = 0, za_size = 0;
230
struct target_rt_sigframe *frame;
231
struct target_rt_frame_record *fr;
232
abi_ulong frame_addr, return_addr;
233
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
234
&layout);
235
236
/* SVE state needs saving only if it exists. */
237
- if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
238
- vq = sve_vq(env);
239
- sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
240
+ if (cpu_isar_feature(aa64_sve, env_archcpu(env)) ||
241
+ cpu_isar_feature(aa64_sme, env_archcpu(env))) {
242
+ sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(sve_vq(env)), 16);
243
sve_ofs = alloc_sigframe_space(sve_size, &layout);
244
}
245
+ if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
246
+ /* ZA state needs saving only if it is enabled. */
247
+ if (FIELD_EX64(env->svcr, SVCR, ZA)) {
248
+ za_size = TARGET_ZA_SIG_CONTEXT_SIZE(sme_vq(env));
249
+ } else {
250
+ za_size = TARGET_ZA_SIG_CONTEXT_SIZE(0);
251
+ }
252
+ za_ofs = alloc_sigframe_space(za_size, &layout);
253
+ }
254
255
if (layout.extra_ofs) {
256
/* Reserve space for the extra end marker. The standard end marker
257
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
258
target_setup_end_record((void *)frame + layout.extra_end_ofs);
259
}
260
if (sve_ofs) {
261
- target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
262
+ target_setup_sve_record((void *)frame + sve_ofs, env, sve_size);
263
+ }
264
+ if (za_ofs) {
265
+ target_setup_za_record((void *)frame + za_ofs, env, za_size);
266
}
267
268
/* Set up the stack frame for unwinding. */
269
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
270
env->btype = 2;
271
}
272
273
+ /*
274
+ * Invoke the signal handler with both SM and ZA disabled.
275
+ * When clearing SM, ResetSVEState, per SMSTOP.
276
+ */
277
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
278
+ arm_reset_sve_state(env);
279
+ }
280
+ if (env->svcr) {
281
+ env->svcr = 0;
282
+ arm_rebuild_hflags(env);
283
+ }
284
+
285
if (info) {
286
tswap_siginfo(&frame->info, info);
287
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
288
--
1093
--
289
2.25.1
1094
2.20.1
1095
1096
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
We can reuse the SVE functions for implementing moves to/from
3
This patch makes NPCM7XX Timer to use a the timer clock generated by the
4
horizontal tile slices, but we need new ones for moves to/from
4
CLK module instead of the magic number TIMER_REF_HZ.
5
vertical tile slices.
6
5
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210108190945.949196-3-wuhaotsh@google.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220708151540.18136-20-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/helper-sme.h | 12 +++
13
include/hw/misc/npcm7xx_clk.h | 6 -----
13
target/arm/helper-sve.h | 2 +
14
include/hw/timer/npcm7xx_timer.h | 1 +
14
target/arm/translate-a64.h | 8 ++
15
hw/arm/npcm7xx.c | 5 ++++
15
target/arm/translate.h | 5 ++
16
hw/timer/npcm7xx_timer.c | 39 +++++++++++++++-----------------
16
target/arm/sme.decode | 15 ++++
17
4 files changed, 24 insertions(+), 27 deletions(-)
17
target/arm/sme_helper.c | 151 ++++++++++++++++++++++++++++++++++++-
18
target/arm/sve_helper.c | 12 +++
19
target/arm/translate-sme.c | 127 +++++++++++++++++++++++++++++++
20
8 files changed, 331 insertions(+), 1 deletion(-)
21
18
22
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
19
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
23
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper-sme.h
21
--- a/include/hw/misc/npcm7xx_clk.h
25
+++ b/target/arm/helper-sme.h
22
+++ b/include/hw/misc/npcm7xx_clk.h
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
23
@@ -XXX,XX +XXX,XX @@
27
DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
24
#include "hw/clock.h"
28
25
#include "hw/sysbus.h"
29
DEF_HELPER_FLAGS_3(sme_zero, TCG_CALL_NO_RWG, void, env, i32, i32)
26
27
-/*
28
- * The reference clock frequency for the timer modules, and the SECCNT and
29
- * CNTR25M registers in this module, is always 25 MHz.
30
- */
31
-#define NPCM7XX_TIMER_REF_HZ (25000000)
32
-
33
/*
34
* Number of registers in our device state structure. Don't change this without
35
* incrementing the version_id in the vmstate.
36
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/timer/npcm7xx_timer.h
39
+++ b/include/hw/timer/npcm7xx_timer.h
40
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
41
42
uint32_t tisr;
43
44
+ Clock *clock;
45
NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
46
NPCM7xxWatchdogTimer watchdog_timer;
47
};
48
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/arm/npcm7xx.c
51
+++ b/hw/arm/npcm7xx.c
52
@@ -XXX,XX +XXX,XX @@
53
#include "hw/char/serial.h"
54
#include "hw/loader.h"
55
#include "hw/misc/unimp.h"
56
+#include "hw/qdev-clock.h"
57
#include "hw/qdev-properties.h"
58
#include "qapi/error.h"
59
#include "qemu/units.h"
60
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
61
int first_irq;
62
int j;
63
64
+ /* Connect the timer clock. */
65
+ qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
66
+ DEVICE(&s->clk), "timer-clock"));
30
+
67
+
31
+/* Move to/from vertical array slices, i.e. columns, so 'c'. */
68
sysbus_realize(sbd, &error_abort);
32
+DEF_HELPER_FLAGS_4(sme_mova_cz_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
69
sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
33
+DEF_HELPER_FLAGS_4(sme_mova_zc_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
70
34
+DEF_HELPER_FLAGS_4(sme_mova_cz_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
71
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
35
+DEF_HELPER_FLAGS_4(sme_mova_zc_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_4(sme_mova_cz_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
+DEF_HELPER_FLAGS_4(sme_mova_zc_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(sme_mova_cz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(sme_mova_zc_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_4(sme_mova_cz_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
41
+DEF_HELPER_FLAGS_4(sme_mova_zc_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
42
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
43
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper-sve.h
73
--- a/hw/timer/npcm7xx_timer.c
45
+++ b/target/arm/helper-sve.h
74
+++ b/hw/timer/npcm7xx_timer.c
46
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_sel_zpzz_s, TCG_CALL_NO_RWG,
75
@@ -XXX,XX +XXX,XX @@
47
void, ptr, ptr, ptr, ptr, i32)
76
#include "qemu/osdep.h"
48
DEF_HELPER_FLAGS_5(sve_sel_zpzz_d, TCG_CALL_NO_RWG,
77
49
void, ptr, ptr, ptr, ptr, i32)
78
#include "hw/irq.h"
50
+DEF_HELPER_FLAGS_5(sve_sel_zpzz_q, TCG_CALL_NO_RWG,
79
+#include "hw/qdev-clock.h"
51
+ void, ptr, ptr, ptr, ptr, i32)
80
#include "hw/qdev-properties.h"
52
81
-#include "hw/misc/npcm7xx_clk.h"
53
DEF_HELPER_FLAGS_5(sve2_addp_zpzz_b, TCG_CALL_NO_RWG,
82
#include "hw/timer/npcm7xx_timer.h"
54
void, ptr, ptr, ptr, ptr, i32)
83
#include "migration/vmstate.h"
55
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
84
#include "qemu/bitops.h"
56
index XXXXXXX..XXXXXXX 100644
85
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
57
--- a/target/arm/translate-a64.h
86
/* Convert a timer cycle count to a time interval in nanoseconds. */
58
+++ b/target/arm/translate-a64.h
87
static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
59
@@ -XXX,XX +XXX,XX @@ static inline int pred_gvec_reg_size(DisasContext *s)
88
{
60
return size_for_gvec(pred_full_reg_size(s));
89
- int64_t ns = count;
90
+ int64_t ticks = count;
91
92
- ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
93
- ns *= npcm7xx_tcsr_prescaler(t->tcsr);
94
+ ticks *= npcm7xx_tcsr_prescaler(t->tcsr);
95
96
- return ns;
97
+ return clock_ticks_to_ns(t->ctrl->clock, ticks);
61
}
98
}
62
99
63
+/* Return a newly allocated pointer to the predicate register. */
100
/* Convert a time interval in nanoseconds to a timer cycle count. */
64
+static inline TCGv_ptr pred_full_reg_ptr(DisasContext *s, int regno)
101
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
65
+{
102
{
66
+ TCGv_ptr ret = tcg_temp_new_ptr();
103
- int64_t count;
67
+ tcg_gen_addi_ptr(ret, cpu_env, pred_full_reg_offset(s, regno));
104
-
68
+ return ret;
105
- count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
69
+}
106
- count /= npcm7xx_tcsr_prescaler(t->tcsr);
70
+
107
-
71
bool disas_sve(DisasContext *, uint32_t);
108
- return count;
72
bool disas_sme(DisasContext *, uint32_t);
109
+ return ns / clock_ticks_to_ns(t->ctrl->clock,
73
110
+ npcm7xx_tcsr_prescaler(t->tcsr));
74
diff --git a/target/arm/translate.h b/target/arm/translate.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/translate.h
77
+++ b/target/arm/translate.h
78
@@ -XXX,XX +XXX,XX @@ static inline int plus_2(DisasContext *s, int x)
79
return x + 2;
80
}
111
}
81
112
82
+static inline int plus_12(DisasContext *s, int x)
113
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
83
+{
114
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
84
+ return x + 12;
115
static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
85
+}
116
int64_t cycles)
86
+
87
static inline int times_2(DisasContext *s, int x)
88
{
117
{
89
return x * 2;
118
- uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
90
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
119
- int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
91
index XXXXXXX..XXXXXXX 100644
120
+ int64_t ticks = cycles * npcm7xx_watchdog_timer_prescaler(t);
92
--- a/target/arm/sme.decode
121
+ int64_t ns = clock_ticks_to_ns(t->ctrl->clock, ticks);
93
+++ b/target/arm/sme.decode
122
94
@@ -XXX,XX +XXX,XX @@
123
/*
95
### SME Misc
124
* The reset function always clears the current timer. The caller of the
96
125
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
97
ZERO 11000000 00 001 00000000000 imm:8
126
*/
98
+
127
npcm7xx_timer_clear(&t->base_timer);
99
+### SME Move into/from Array
128
100
+
129
- ns *= prescaler;
101
+%mova_rs 13:2 !function=plus_12
130
t->base_timer.remaining_ns = ns;
102
+&mova esz rs pg zr za_imm v:bool to_vec:bool
103
+
104
+MOVA 11000000 esz:2 00000 0 v:1 .. pg:3 zr:5 0 za_imm:4 \
105
+ &mova to_vec=0 rs=%mova_rs
106
+MOVA 11000000 11 00000 1 v:1 .. pg:3 zr:5 0 za_imm:4 \
107
+ &mova to_vec=0 rs=%mova_rs esz=4
108
+
109
+MOVA 11000000 esz:2 00001 0 v:1 .. pg:3 0 za_imm:4 zr:5 \
110
+ &mova to_vec=1 rs=%mova_rs
111
+MOVA 11000000 11 00001 1 v:1 .. pg:3 0 za_imm:4 zr:5 \
112
+ &mova to_vec=1 rs=%mova_rs esz=4
113
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/sme_helper.c
116
+++ b/target/arm/sme_helper.c
117
@@ -XXX,XX +XXX,XX @@
118
119
#include "qemu/osdep.h"
120
#include "cpu.h"
121
-#include "internals.h"
122
+#include "tcg/tcg-gvec-desc.h"
123
#include "exec/helper-proto.h"
124
+#include "qemu/int128.h"
125
+#include "vec_internal.h"
126
127
/* ResetSVEState */
128
void arm_reset_sve_state(CPUARMState *env)
129
@@ -XXX,XX +XXX,XX @@ void helper_sme_zero(CPUARMState *env, uint32_t imm, uint32_t svl)
130
}
131
}
132
}
131
}
133
+
132
134
+
133
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
135
+/*
134
qemu_irq_lower(s->watchdog_timer.irq);
136
+ * When considering the ZA storage as an array of elements of
137
+ * type T, the index within that array of the Nth element of
138
+ * a vertical slice of a tile can be calculated like this,
139
+ * regardless of the size of type T. This is because the tiles
140
+ * are interleaved, so if type T is size N bytes then row 1 of
141
+ * the tile is N rows away from row 0. The division by N to
142
+ * convert a byte offset into an array index and the multiplication
143
+ * by N to convert from vslice-index-within-the-tile to
144
+ * the index within the ZA storage cancel out.
145
+ */
146
+#define tile_vslice_index(i) ((i) * sizeof(ARMVectorReg))
147
+
148
+/*
149
+ * When doing byte arithmetic on the ZA storage, the element
150
+ * byteoff bytes away in a tile vertical slice is always this
151
+ * many bytes away in the ZA storage, regardless of the
152
+ * size of the tile element, assuming that byteoff is a multiple
153
+ * of the element size. Again this is because of the interleaving
154
+ * of the tiles. For instance if we have 1 byte per element then
155
+ * each row of the ZA storage has one byte of the vslice data,
156
+ * and (counting from 0) byte 8 goes in row 8 of the storage
157
+ * at offset (8 * row-size-in-bytes).
158
+ * If we have 8 bytes per element then each row of the ZA storage
159
+ * has 8 bytes of the data, but there are 8 interleaved tiles and
160
+ * so byte 8 of the data goes into row 1 of the tile,
161
+ * which is again row 8 of the storage, so the offset is still
162
+ * (8 * row-size-in-bytes). Similarly for other element sizes.
163
+ */
164
+#define tile_vslice_offset(byteoff) ((byteoff) * sizeof(ARMVectorReg))
165
+
166
+
167
+/*
168
+ * Move Zreg vector to ZArray column.
169
+ */
170
+#define DO_MOVA_C(NAME, TYPE, H) \
171
+void HELPER(NAME)(void *za, void *vn, void *vg, uint32_t desc) \
172
+{ \
173
+ int i, oprsz = simd_oprsz(desc); \
174
+ for (i = 0; i < oprsz; ) { \
175
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
176
+ do { \
177
+ if (pg & 1) { \
178
+ *(TYPE *)(za + tile_vslice_offset(i)) = *(TYPE *)(vn + H(i)); \
179
+ } \
180
+ i += sizeof(TYPE); \
181
+ pg >>= sizeof(TYPE); \
182
+ } while (i & 15); \
183
+ } \
184
+}
185
+
186
+DO_MOVA_C(sme_mova_cz_b, uint8_t, H1)
187
+DO_MOVA_C(sme_mova_cz_h, uint16_t, H1_2)
188
+DO_MOVA_C(sme_mova_cz_s, uint32_t, H1_4)
189
+
190
+void HELPER(sme_mova_cz_d)(void *za, void *vn, void *vg, uint32_t desc)
191
+{
192
+ int i, oprsz = simd_oprsz(desc) / 8;
193
+ uint8_t *pg = vg;
194
+ uint64_t *n = vn;
195
+ uint64_t *a = za;
196
+
197
+ for (i = 0; i < oprsz; i++) {
198
+ if (pg[H1(i)] & 1) {
199
+ a[tile_vslice_index(i)] = n[i];
200
+ }
201
+ }
202
+}
203
+
204
+void HELPER(sme_mova_cz_q)(void *za, void *vn, void *vg, uint32_t desc)
205
+{
206
+ int i, oprsz = simd_oprsz(desc) / 16;
207
+ uint16_t *pg = vg;
208
+ Int128 *n = vn;
209
+ Int128 *a = za;
210
+
211
+ /*
212
+ * Int128 is used here simply to copy 16 bytes, and to simplify
213
+ * the address arithmetic.
214
+ */
215
+ for (i = 0; i < oprsz; i++) {
216
+ if (pg[H2(i)] & 1) {
217
+ a[tile_vslice_index(i)] = n[i];
218
+ }
219
+ }
220
+}
221
+
222
+#undef DO_MOVA_C
223
+
224
+/*
225
+ * Move ZArray column to Zreg vector.
226
+ */
227
+#define DO_MOVA_Z(NAME, TYPE, H) \
228
+void HELPER(NAME)(void *vd, void *za, void *vg, uint32_t desc) \
229
+{ \
230
+ int i, oprsz = simd_oprsz(desc); \
231
+ for (i = 0; i < oprsz; ) { \
232
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
233
+ do { \
234
+ if (pg & 1) { \
235
+ *(TYPE *)(vd + H(i)) = *(TYPE *)(za + tile_vslice_offset(i)); \
236
+ } \
237
+ i += sizeof(TYPE); \
238
+ pg >>= sizeof(TYPE); \
239
+ } while (i & 15); \
240
+ } \
241
+}
242
+
243
+DO_MOVA_Z(sme_mova_zc_b, uint8_t, H1)
244
+DO_MOVA_Z(sme_mova_zc_h, uint16_t, H1_2)
245
+DO_MOVA_Z(sme_mova_zc_s, uint32_t, H1_4)
246
+
247
+void HELPER(sme_mova_zc_d)(void *vd, void *za, void *vg, uint32_t desc)
248
+{
249
+ int i, oprsz = simd_oprsz(desc) / 8;
250
+ uint8_t *pg = vg;
251
+ uint64_t *d = vd;
252
+ uint64_t *a = za;
253
+
254
+ for (i = 0; i < oprsz; i++) {
255
+ if (pg[H1(i)] & 1) {
256
+ d[i] = a[tile_vslice_index(i)];
257
+ }
258
+ }
259
+}
260
+
261
+void HELPER(sme_mova_zc_q)(void *vd, void *za, void *vg, uint32_t desc)
262
+{
263
+ int i, oprsz = simd_oprsz(desc) / 16;
264
+ uint16_t *pg = vg;
265
+ Int128 *d = vd;
266
+ Int128 *a = za;
267
+
268
+ /*
269
+ * Int128 is used here simply to copy 16 bytes, and to simplify
270
+ * the address arithmetic.
271
+ */
272
+ for (i = 0; i < oprsz; i++, za += sizeof(ARMVectorReg)) {
273
+ if (pg[H2(i)] & 1) {
274
+ d[i] = a[tile_vslice_index(i)];
275
+ }
276
+ }
277
+}
278
+
279
+#undef DO_MOVA_Z
280
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
281
index XXXXXXX..XXXXXXX 100644
282
--- a/target/arm/sve_helper.c
283
+++ b/target/arm/sve_helper.c
284
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_sel_zpzz_d)(void *vd, void *vn, void *vm,
285
}
286
}
135
}
287
136
288
+void HELPER(sve_sel_zpzz_q)(void *vd, void *vn, void *vm,
137
-static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
289
+ void *vg, uint32_t desc)
138
+static void npcm7xx_timer_init(Object *obj)
290
+{
291
+ intptr_t i, opr_sz = simd_oprsz(desc) / 16;
292
+ Int128 *d = vd, *n = vn, *m = vm;
293
+ uint16_t *pg = vg;
294
+
295
+ for (i = 0; i < opr_sz; i += 1) {
296
+ d[i] = (pg[H2(i)] & 1 ? n : m)[i];
297
+ }
298
+}
299
+
300
/* Two operand comparison controlled by a predicate.
301
* ??? It is very tempting to want to be able to expand this inline
302
* with x86 instructions, e.g.
303
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
304
index XXXXXXX..XXXXXXX 100644
305
--- a/target/arm/translate-sme.c
306
+++ b/target/arm/translate-sme.c
307
@@ -XXX,XX +XXX,XX @@
308
#include "decode-sme.c.inc"
309
310
311
+/*
312
+ * Resolve tile.size[index] to a host pointer, where tile and index
313
+ * are always decoded together, dependent on the element size.
314
+ */
315
+static TCGv_ptr get_tile_rowcol(DisasContext *s, int esz, int rs,
316
+ int tile_index, bool vertical)
317
+{
318
+ int tile = tile_index >> (4 - esz);
319
+ int index = esz == MO_128 ? 0 : extract32(tile_index, 0, 4 - esz);
320
+ int pos, len, offset;
321
+ TCGv_i32 tmp;
322
+ TCGv_ptr addr;
323
+
324
+ /* Compute the final index, which is Rs+imm. */
325
+ tmp = tcg_temp_new_i32();
326
+ tcg_gen_trunc_tl_i32(tmp, cpu_reg(s, rs));
327
+ tcg_gen_addi_i32(tmp, tmp, index);
328
+
329
+ /* Prepare a power-of-two modulo via extraction of @len bits. */
330
+ len = ctz32(streaming_vec_reg_size(s)) - esz;
331
+
332
+ if (vertical) {
333
+ /*
334
+ * Compute the byte offset of the index within the tile:
335
+ * (index % (svl / size)) * size
336
+ * = (index % (svl >> esz)) << esz
337
+ * Perform the power-of-two modulo via extraction of the low @len bits.
338
+ * Perform the multiply by shifting left by @pos bits.
339
+ * Perform these operations simultaneously via deposit into zero.
340
+ */
341
+ pos = esz;
342
+ tcg_gen_deposit_z_i32(tmp, tmp, pos, len);
343
+
344
+ /*
345
+ * For big-endian, adjust the indexed column byte offset within
346
+ * the uint64_t host words that make up env->zarray[].
347
+ */
348
+ if (HOST_BIG_ENDIAN && esz < MO_64) {
349
+ tcg_gen_xori_i32(tmp, tmp, 8 - (1 << esz));
350
+ }
351
+ } else {
352
+ /*
353
+ * Compute the byte offset of the index within the tile:
354
+ * (index % (svl / size)) * (size * sizeof(row))
355
+ * = (index % (svl >> esz)) << (esz + log2(sizeof(row)))
356
+ */
357
+ pos = esz + ctz32(sizeof(ARMVectorReg));
358
+ tcg_gen_deposit_z_i32(tmp, tmp, pos, len);
359
+
360
+ /* Row slices are always aligned and need no endian adjustment. */
361
+ }
362
+
363
+ /* The tile byte offset within env->zarray is the row. */
364
+ offset = tile * sizeof(ARMVectorReg);
365
+
366
+ /* Include the byte offset of zarray to make this relative to env. */
367
+ offset += offsetof(CPUARMState, zarray);
368
+ tcg_gen_addi_i32(tmp, tmp, offset);
369
+
370
+ /* Add the byte offset to env to produce the final pointer. */
371
+ addr = tcg_temp_new_ptr();
372
+ tcg_gen_ext_i32_ptr(addr, tmp);
373
+ tcg_temp_free_i32(tmp);
374
+ tcg_gen_add_ptr(addr, addr, cpu_env);
375
+
376
+ return addr;
377
+}
378
+
379
static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
380
{
139
{
381
if (!dc_isar_feature(aa64_sme, s)) {
140
- NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
382
@@ -XXX,XX +XXX,XX @@ static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
141
- SysBusDevice *sbd = &s->parent;
383
}
142
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
384
return true;
143
+ DeviceState *dev = DEVICE(obj);
144
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
145
int i;
146
NPCM7xxWatchdogTimer *w;
147
148
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
149
npcm7xx_watchdog_timer_expired, w);
150
sysbus_init_irq(sbd, &w->irq);
151
152
- memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
153
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_timer_ops, s,
154
TYPE_NPCM7XX_TIMER, 4 * KiB);
155
sysbus_init_mmio(sbd, &s->iomem);
156
qdev_init_gpio_out_named(dev, &w->reset_signal,
157
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
158
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
385
}
159
}
386
+
160
387
+static bool trans_MOVA(DisasContext *s, arg_MOVA *a)
161
static const VMStateDescription vmstate_npcm7xx_base_timer = {
388
+{
162
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
389
+ static gen_helper_gvec_4 * const h_fns[5] = {
163
390
+ gen_helper_sve_sel_zpzz_b, gen_helper_sve_sel_zpzz_h,
164
static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
391
+ gen_helper_sve_sel_zpzz_s, gen_helper_sve_sel_zpzz_d,
165
.name = "npcm7xx-timer-ctrl",
392
+ gen_helper_sve_sel_zpzz_q
166
- .version_id = 1,
393
+ };
167
- .minimum_version_id = 1,
394
+ static gen_helper_gvec_3 * const cz_fns[5] = {
168
+ .version_id = 2,
395
+ gen_helper_sme_mova_cz_b, gen_helper_sme_mova_cz_h,
169
+ .minimum_version_id = 2,
396
+ gen_helper_sme_mova_cz_s, gen_helper_sme_mova_cz_d,
170
.fields = (VMStateField[]) {
397
+ gen_helper_sme_mova_cz_q,
171
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
398
+ };
172
+ VMSTATE_CLOCK(clock, NPCM7xxTimerCtrlState),
399
+ static gen_helper_gvec_3 * const zc_fns[5] = {
173
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
400
+ gen_helper_sme_mova_zc_b, gen_helper_sme_mova_zc_h,
174
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
401
+ gen_helper_sme_mova_zc_s, gen_helper_sme_mova_zc_d,
175
NPCM7xxTimer),
402
+ gen_helper_sme_mova_zc_q,
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
403
+ };
177
QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
404
+
178
405
+ TCGv_ptr t_za, t_zr, t_pg;
179
dc->desc = "NPCM7xx Timer Controller";
406
+ TCGv_i32 t_desc;
180
- dc->realize = npcm7xx_timer_realize;
407
+ int svl;
181
dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
408
+
182
rc->phases.enter = npcm7xx_timer_enter_reset;
409
+ if (!dc_isar_feature(aa64_sme, s)) {
183
rc->phases.hold = npcm7xx_timer_hold_reset;
410
+ return false;
184
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_timer_info = {
411
+ }
185
.parent = TYPE_SYS_BUS_DEVICE,
412
+ if (!sme_smza_enabled_check(s)) {
186
.instance_size = sizeof(NPCM7xxTimerCtrlState),
413
+ return true;
187
.class_init = npcm7xx_timer_class_init,
414
+ }
188
+ .instance_init = npcm7xx_timer_init,
415
+
189
};
416
+ t_za = get_tile_rowcol(s, a->esz, a->rs, a->za_imm, a->v);
190
417
+ t_zr = vec_full_reg_ptr(s, a->zr);
191
static void npcm7xx_timer_register_type(void)
418
+ t_pg = pred_full_reg_ptr(s, a->pg);
419
+
420
+ svl = streaming_vec_reg_size(s);
421
+ t_desc = tcg_constant_i32(simd_desc(svl, svl, 0));
422
+
423
+ if (a->v) {
424
+ /* Vertical slice -- use sme mova helpers. */
425
+ if (a->to_vec) {
426
+ zc_fns[a->esz](t_zr, t_za, t_pg, t_desc);
427
+ } else {
428
+ cz_fns[a->esz](t_za, t_zr, t_pg, t_desc);
429
+ }
430
+ } else {
431
+ /* Horizontal slice -- reuse sve sel helpers. */
432
+ if (a->to_vec) {
433
+ h_fns[a->esz](t_zr, t_za, t_zr, t_pg, t_desc);
434
+ } else {
435
+ h_fns[a->esz](t_za, t_zr, t_za, t_pg, t_desc);
436
+ }
437
+ }
438
+
439
+ tcg_temp_free_ptr(t_za);
440
+ tcg_temp_free_ptr(t_zr);
441
+ tcg_temp_free_ptr(t_pg);
442
+
443
+ return true;
444
+}
445
--
192
--
446
2.25.1
193
2.20.1
194
195
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
We cannot reuse the SVE functions for LD[1-4] and ST[1-4],
3
The ADC is part of NPCM7XX Module. Its behavior is controled by the
4
because those functions accept only a Zreg register number.
4
ADC_CON register. It converts one of the eight analog inputs into a
5
For SME, we want to pass a pointer into ZA storage.
5
digital input and stores it in the ADC_DATA register when enabled.
6
6
7
Users can alter input value by using qom-set QMP command.
8
9
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
12
Message-id: 20210108190945.949196-4-wuhaotsh@google.com
13
[PMM: Added missing hw/adc/trace.h file]
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220708151540.18136-21-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
target/arm/helper-sme.h | 82 +++++
17
docs/system/arm/nuvoton.rst | 2 +-
13
target/arm/sme.decode | 9 +
18
meson.build | 1 +
14
target/arm/sme_helper.c | 595 +++++++++++++++++++++++++++++++++++++
19
hw/adc/trace.h | 1 +
15
target/arm/translate-sme.c | 70 +++++
20
include/hw/adc/npcm7xx_adc.h | 69 ++++++
16
4 files changed, 756 insertions(+)
21
include/hw/arm/npcm7xx.h | 2 +
22
hw/adc/npcm7xx_adc.c | 301 ++++++++++++++++++++++++++
23
hw/arm/npcm7xx.c | 24 ++-
24
tests/qtest/npcm7xx_adc-test.c | 377 +++++++++++++++++++++++++++++++++
25
hw/adc/meson.build | 1 +
26
hw/adc/trace-events | 5 +
27
tests/qtest/meson.build | 3 +-
28
11 files changed, 783 insertions(+), 3 deletions(-)
29
create mode 100644 hw/adc/trace.h
30
create mode 100644 include/hw/adc/npcm7xx_adc.h
31
create mode 100644 hw/adc/npcm7xx_adc.c
32
create mode 100644 tests/qtest/npcm7xx_adc-test.c
33
create mode 100644 hw/adc/trace-events
17
34
18
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
35
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
19
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper-sme.h
37
--- a/docs/system/arm/nuvoton.rst
21
+++ b/target/arm/helper-sme.h
38
+++ b/docs/system/arm/nuvoton.rst
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sme_mova_cz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
@@ -XXX,XX +XXX,XX @@ Supported devices
23
DEF_HELPER_FLAGS_4(sme_mova_zc_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
40
* Random Number Generator (RNG)
24
DEF_HELPER_FLAGS_4(sme_mova_cz_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
41
* USB host (USBH)
25
DEF_HELPER_FLAGS_4(sme_mova_zc_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
42
* GPIO controller
26
+
43
+ * Analog to Digital Converter (ADC)
27
+DEF_HELPER_FLAGS_5(sme_ld1b_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
44
28
+DEF_HELPER_FLAGS_5(sme_ld1b_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
45
Missing devices
29
+DEF_HELPER_FLAGS_5(sme_ld1b_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
46
---------------
30
+DEF_HELPER_FLAGS_5(sme_ld1b_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
47
@@ -XXX,XX +XXX,XX @@ Missing devices
31
+
48
* USB device (USBD)
32
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
49
* SMBus controller (SMBF)
33
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
50
* Peripheral SPI controller (PSPI)
34
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
51
- * Analog to Digital Converter (ADC)
35
+DEF_HELPER_FLAGS_5(sme_ld1h_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
52
* SD/MMC host
36
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
53
* PECI interface
37
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
54
* Pulse Width Modulation (PWM)
38
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
55
diff --git a/meson.build b/meson.build
39
+DEF_HELPER_FLAGS_5(sme_ld1h_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
40
+
41
+DEF_HELPER_FLAGS_5(sme_ld1s_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
42
+DEF_HELPER_FLAGS_5(sme_ld1s_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
43
+DEF_HELPER_FLAGS_5(sme_ld1s_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
44
+DEF_HELPER_FLAGS_5(sme_ld1s_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
45
+DEF_HELPER_FLAGS_5(sme_ld1s_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
46
+DEF_HELPER_FLAGS_5(sme_ld1s_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_5(sme_ld1s_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_5(sme_ld1s_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
49
+
50
+DEF_HELPER_FLAGS_5(sme_ld1d_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
51
+DEF_HELPER_FLAGS_5(sme_ld1d_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
52
+DEF_HELPER_FLAGS_5(sme_ld1d_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_5(sme_ld1d_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
54
+DEF_HELPER_FLAGS_5(sme_ld1d_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
55
+DEF_HELPER_FLAGS_5(sme_ld1d_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
56
+DEF_HELPER_FLAGS_5(sme_ld1d_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
57
+DEF_HELPER_FLAGS_5(sme_ld1d_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
58
+
59
+DEF_HELPER_FLAGS_5(sme_ld1q_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_5(sme_ld1q_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
61
+DEF_HELPER_FLAGS_5(sme_ld1q_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
62
+DEF_HELPER_FLAGS_5(sme_ld1q_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
63
+DEF_HELPER_FLAGS_5(sme_ld1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
64
+DEF_HELPER_FLAGS_5(sme_ld1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
65
+DEF_HELPER_FLAGS_5(sme_ld1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
66
+DEF_HELPER_FLAGS_5(sme_ld1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
67
+
68
+DEF_HELPER_FLAGS_5(sme_st1b_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
69
+DEF_HELPER_FLAGS_5(sme_st1b_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
70
+DEF_HELPER_FLAGS_5(sme_st1b_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
71
+DEF_HELPER_FLAGS_5(sme_st1b_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
72
+
73
+DEF_HELPER_FLAGS_5(sme_st1h_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
74
+DEF_HELPER_FLAGS_5(sme_st1h_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
75
+DEF_HELPER_FLAGS_5(sme_st1h_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
76
+DEF_HELPER_FLAGS_5(sme_st1h_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
77
+DEF_HELPER_FLAGS_5(sme_st1h_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_5(sme_st1h_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
79
+DEF_HELPER_FLAGS_5(sme_st1h_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
80
+DEF_HELPER_FLAGS_5(sme_st1h_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
81
+
82
+DEF_HELPER_FLAGS_5(sme_st1s_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
83
+DEF_HELPER_FLAGS_5(sme_st1s_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
84
+DEF_HELPER_FLAGS_5(sme_st1s_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
85
+DEF_HELPER_FLAGS_5(sme_st1s_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
86
+DEF_HELPER_FLAGS_5(sme_st1s_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
87
+DEF_HELPER_FLAGS_5(sme_st1s_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
88
+DEF_HELPER_FLAGS_5(sme_st1s_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
89
+DEF_HELPER_FLAGS_5(sme_st1s_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
90
+
91
+DEF_HELPER_FLAGS_5(sme_st1d_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
92
+DEF_HELPER_FLAGS_5(sme_st1d_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
93
+DEF_HELPER_FLAGS_5(sme_st1d_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
94
+DEF_HELPER_FLAGS_5(sme_st1d_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
95
+DEF_HELPER_FLAGS_5(sme_st1d_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
96
+DEF_HELPER_FLAGS_5(sme_st1d_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
97
+DEF_HELPER_FLAGS_5(sme_st1d_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
98
+DEF_HELPER_FLAGS_5(sme_st1d_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
99
+
100
+DEF_HELPER_FLAGS_5(sme_st1q_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
101
+DEF_HELPER_FLAGS_5(sme_st1q_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
102
+DEF_HELPER_FLAGS_5(sme_st1q_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
103
+DEF_HELPER_FLAGS_5(sme_st1q_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
104
+DEF_HELPER_FLAGS_5(sme_st1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
105
+DEF_HELPER_FLAGS_5(sme_st1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
106
+DEF_HELPER_FLAGS_5(sme_st1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
107
+DEF_HELPER_FLAGS_5(sme_st1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
108
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
109
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
110
--- a/target/arm/sme.decode
57
--- a/meson.build
111
+++ b/target/arm/sme.decode
58
+++ b/meson.build
112
@@ -XXX,XX +XXX,XX @@ MOVA 11000000 esz:2 00001 0 v:1 .. pg:3 0 za_imm:4 zr:5 \
59
@@ -XXX,XX +XXX,XX @@ if have_system
113
&mova to_vec=1 rs=%mova_rs
60
'chardev',
114
MOVA 11000000 11 00001 1 v:1 .. pg:3 0 za_imm:4 zr:5 \
61
'hw/9pfs',
115
&mova to_vec=1 rs=%mova_rs esz=4
62
'hw/acpi',
116
+
63
+ 'hw/adc',
117
+### SME Memory
64
'hw/alpha',
118
+
65
'hw/arm',
119
+&ldst esz rs pg rn rm za_imm v:bool st:bool
66
'hw/audio',
120
+
67
diff --git a/hw/adc/trace.h b/hw/adc/trace.h
121
+LDST1 1110000 0 esz:2 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
68
new file mode 100644
122
+ &ldst rs=%mova_rs
69
index XXXXXXX..XXXXXXX
123
+LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
70
--- /dev/null
124
+ &ldst esz=4 rs=%mova_rs
71
+++ b/hw/adc/trace.h
125
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
72
@@ -0,0 +1 @@
73
+#include "trace/trace-hw_adc.h"
74
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/include/hw/adc/npcm7xx_adc.h
79
@@ -XXX,XX +XXX,XX @@
80
+/*
81
+ * Nuvoton NPCM7xx ADC Module
82
+ *
83
+ * Copyright 2020 Google LLC
84
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
86
+ * under the terms of the GNU General Public License as published by the
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
89
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ */
95
+#ifndef NPCM7XX_ADC_H
96
+#define NPCM7XX_ADC_H
97
+
98
+#include "hw/clock.h"
99
+#include "hw/irq.h"
100
+#include "hw/sysbus.h"
101
+#include "qemu/timer.h"
102
+
103
+#define NPCM7XX_ADC_NUM_INPUTS 8
104
+/**
105
+ * This value should not be changed unless write_adc_calibration function in
106
+ * hw/arm/npcm7xx.c is also changed.
107
+ */
108
+#define NPCM7XX_ADC_NUM_CALIB 2
109
+
110
+/**
111
+ * struct NPCM7xxADCState - Analog to Digital Converter Module device state.
112
+ * @parent: System bus device.
113
+ * @iomem: Memory region through which registers are accessed.
114
+ * @conv_timer: The timer counts down remaining cycles for the conversion.
115
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
116
+ * @con: The Control Register.
117
+ * @data: The Data Buffer.
118
+ * @clock: The ADC Clock.
119
+ * @adci: The input voltage in units of uV. 1uv = 1e-6V.
120
+ * @vref: The external reference voltage.
121
+ * @iref: The internal reference voltage, initialized at launch time.
122
+ * @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
123
+ */
124
+typedef struct {
125
+ SysBusDevice parent;
126
+
127
+ MemoryRegion iomem;
128
+
129
+ QEMUTimer conv_timer;
130
+
131
+ qemu_irq irq;
132
+ uint32_t con;
133
+ uint32_t data;
134
+ Clock *clock;
135
+
136
+ /* Voltages are in unit of uV. 1V = 1000000uV. */
137
+ uint32_t adci[NPCM7XX_ADC_NUM_INPUTS];
138
+ uint32_t vref;
139
+ uint32_t iref;
140
+
141
+ uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
142
+} NPCM7xxADCState;
143
+
144
+#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
145
+#define NPCM7XX_ADC(obj) \
146
+ OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
147
+
148
+#endif /* NPCM7XX_ADC_H */
149
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
126
index XXXXXXX..XXXXXXX 100644
150
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/sme_helper.c
151
--- a/include/hw/arm/npcm7xx.h
128
+++ b/target/arm/sme_helper.c
152
+++ b/include/hw/arm/npcm7xx.h
129
@@ -XXX,XX +XXX,XX @@
153
@@ -XXX,XX +XXX,XX @@
130
154
#define NPCM7XX_H
131
#include "qemu/osdep.h"
155
132
#include "cpu.h"
156
#include "hw/boards.h"
133
+#include "internals.h"
157
+#include "hw/adc/npcm7xx_adc.h"
134
#include "tcg/tcg-gvec-desc.h"
158
#include "hw/cpu/a9mpcore.h"
135
#include "exec/helper-proto.h"
159
#include "hw/gpio/npcm7xx_gpio.h"
136
+#include "exec/cpu_ldst.h"
160
#include "hw/mem/npcm7xx_mc.h"
137
+#include "exec/exec-all.h"
161
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
138
#include "qemu/int128.h"
162
NPCM7xxGCRState gcr;
139
#include "vec_internal.h"
163
NPCM7xxCLKState clk;
140
+#include "sve_ldst_internal.h"
164
NPCM7xxTimerCtrlState tim[3];
141
165
+ NPCM7xxADCState adc;
142
/* ResetSVEState */
166
NPCM7xxOTPState key_storage;
143
void arm_reset_sve_state(CPUARMState *env)
167
NPCM7xxOTPState fuse_array;
144
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_mova_zc_q)(void *vd, void *za, void *vg, uint32_t desc)
168
NPCM7xxMCState mc;
169
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
170
new file mode 100644
171
index XXXXXXX..XXXXXXX
172
--- /dev/null
173
+++ b/hw/adc/npcm7xx_adc.c
174
@@ -XXX,XX +XXX,XX @@
175
+/*
176
+ * Nuvoton NPCM7xx ADC Module
177
+ *
178
+ * Copyright 2020 Google LLC
179
+ *
180
+ * This program is free software; you can redistribute it and/or modify it
181
+ * under the terms of the GNU General Public License as published by the
182
+ * Free Software Foundation; either version 2 of the License, or
183
+ * (at your option) any later version.
184
+ *
185
+ * This program is distributed in the hope that it will be useful, but WITHOUT
186
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
187
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
188
+ * for more details.
189
+ */
190
+
191
+#include "qemu/osdep.h"
192
+#include "hw/adc/npcm7xx_adc.h"
193
+#include "hw/qdev-clock.h"
194
+#include "hw/qdev-properties.h"
195
+#include "hw/registerfields.h"
196
+#include "migration/vmstate.h"
197
+#include "qemu/log.h"
198
+#include "qemu/module.h"
199
+#include "qemu/timer.h"
200
+#include "qemu/units.h"
201
+#include "trace.h"
202
+
203
+REG32(NPCM7XX_ADC_CON, 0x0)
204
+REG32(NPCM7XX_ADC_DATA, 0x4)
205
+
206
+/* Register field definitions. */
207
+#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
208
+#define NPCM7XX_ADC_CON_INT_EN BIT(21)
209
+#define NPCM7XX_ADC_CON_REFSEL BIT(19)
210
+#define NPCM7XX_ADC_CON_INT BIT(18)
211
+#define NPCM7XX_ADC_CON_EN BIT(17)
212
+#define NPCM7XX_ADC_CON_RST BIT(16)
213
+#define NPCM7XX_ADC_CON_CONV BIT(14)
214
+#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
215
+
216
+#define NPCM7XX_ADC_MAX_RESULT 1023
217
+#define NPCM7XX_ADC_DEFAULT_IREF 2000000
218
+#define NPCM7XX_ADC_CONV_CYCLES 20
219
+#define NPCM7XX_ADC_RESET_CYCLES 10
220
+#define NPCM7XX_ADC_R0_INPUT 500000
221
+#define NPCM7XX_ADC_R1_INPUT 1500000
222
+
223
+static void npcm7xx_adc_reset(NPCM7xxADCState *s)
224
+{
225
+ timer_del(&s->conv_timer);
226
+ s->con = 0x000c0001;
227
+ s->data = 0x00000000;
228
+}
229
+
230
+static uint32_t npcm7xx_adc_convert(uint32_t input, uint32_t ref)
231
+{
232
+ uint32_t result;
233
+
234
+ result = input * (NPCM7XX_ADC_MAX_RESULT + 1) / ref;
235
+ if (result > NPCM7XX_ADC_MAX_RESULT) {
236
+ result = NPCM7XX_ADC_MAX_RESULT;
237
+ }
238
+
239
+ return result;
240
+}
241
+
242
+static uint32_t npcm7xx_adc_prescaler(NPCM7xxADCState *s)
243
+{
244
+ return 2 * (NPCM7XX_ADC_CON_DIV(s->con) + 1);
245
+}
246
+
247
+static void npcm7xx_adc_start_timer(Clock *clk, QEMUTimer *timer,
248
+ uint32_t cycles, uint32_t prescaler)
249
+{
250
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
251
+ int64_t ticks = cycles;
252
+ int64_t ns;
253
+
254
+ ticks *= prescaler;
255
+ ns = clock_ticks_to_ns(clk, ticks);
256
+ ns += now;
257
+ timer_mod(timer, ns);
258
+}
259
+
260
+static void npcm7xx_adc_start_convert(NPCM7xxADCState *s)
261
+{
262
+ uint32_t prescaler = npcm7xx_adc_prescaler(s);
263
+
264
+ npcm7xx_adc_start_timer(s->clock, &s->conv_timer, NPCM7XX_ADC_CONV_CYCLES,
265
+ prescaler);
266
+}
267
+
268
+static void npcm7xx_adc_convert_done(void *opaque)
269
+{
270
+ NPCM7xxADCState *s = opaque;
271
+ uint32_t input = NPCM7XX_ADC_CON_MUX(s->con);
272
+ uint32_t ref = (s->con & NPCM7XX_ADC_CON_REFSEL)
273
+ ? s->iref : s->vref;
274
+
275
+ if (input >= NPCM7XX_ADC_NUM_INPUTS) {
276
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid input: %u\n",
277
+ __func__, input);
278
+ return;
279
+ }
280
+ s->data = npcm7xx_adc_convert(s->adci[input], ref);
281
+ if (s->con & NPCM7XX_ADC_CON_INT_EN) {
282
+ s->con |= NPCM7XX_ADC_CON_INT;
283
+ qemu_irq_raise(s->irq);
284
+ }
285
+ s->con &= ~NPCM7XX_ADC_CON_CONV;
286
+}
287
+
288
+static void npcm7xx_adc_calibrate(NPCM7xxADCState *adc)
289
+{
290
+ adc->calibration_r_values[0] = npcm7xx_adc_convert(NPCM7XX_ADC_R0_INPUT,
291
+ adc->iref);
292
+ adc->calibration_r_values[1] = npcm7xx_adc_convert(NPCM7XX_ADC_R1_INPUT,
293
+ adc->iref);
294
+}
295
+
296
+static void npcm7xx_adc_write_con(NPCM7xxADCState *s, uint32_t new_con)
297
+{
298
+ uint32_t old_con = s->con;
299
+
300
+ /* Write ADC_INT to 1 to clear it */
301
+ if (new_con & NPCM7XX_ADC_CON_INT) {
302
+ new_con &= ~NPCM7XX_ADC_CON_INT;
303
+ qemu_irq_lower(s->irq);
304
+ } else if (old_con & NPCM7XX_ADC_CON_INT) {
305
+ new_con |= NPCM7XX_ADC_CON_INT;
306
+ }
307
+
308
+ s->con = new_con;
309
+
310
+ if (s->con & NPCM7XX_ADC_CON_RST) {
311
+ npcm7xx_adc_reset(s);
312
+ return;
313
+ }
314
+
315
+ if ((s->con & NPCM7XX_ADC_CON_EN)) {
316
+ if (s->con & NPCM7XX_ADC_CON_CONV) {
317
+ if (!(old_con & NPCM7XX_ADC_CON_CONV)) {
318
+ npcm7xx_adc_start_convert(s);
319
+ }
320
+ } else {
321
+ timer_del(&s->conv_timer);
322
+ }
323
+ }
324
+}
325
+
326
+static uint64_t npcm7xx_adc_read(void *opaque, hwaddr offset, unsigned size)
327
+{
328
+ uint64_t value = 0;
329
+ NPCM7xxADCState *s = opaque;
330
+
331
+ switch (offset) {
332
+ case A_NPCM7XX_ADC_CON:
333
+ value = s->con;
334
+ break;
335
+
336
+ case A_NPCM7XX_ADC_DATA:
337
+ value = s->data;
338
+ break;
339
+
340
+ default:
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
343
+ __func__, offset);
344
+ break;
345
+ }
346
+
347
+ trace_npcm7xx_adc_read(DEVICE(s)->canonical_path, offset, value);
348
+ return value;
349
+}
350
+
351
+static void npcm7xx_adc_write(void *opaque, hwaddr offset, uint64_t v,
352
+ unsigned size)
353
+{
354
+ NPCM7xxADCState *s = opaque;
355
+
356
+ trace_npcm7xx_adc_write(DEVICE(s)->canonical_path, offset, v);
357
+ switch (offset) {
358
+ case A_NPCM7XX_ADC_CON:
359
+ npcm7xx_adc_write_con(s, v);
360
+ break;
361
+
362
+ case A_NPCM7XX_ADC_DATA:
363
+ qemu_log_mask(LOG_GUEST_ERROR,
364
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
365
+ __func__, offset);
366
+ break;
367
+
368
+ default:
369
+ qemu_log_mask(LOG_GUEST_ERROR,
370
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
371
+ __func__, offset);
372
+ break;
373
+ }
374
+
375
+}
376
+
377
+static const struct MemoryRegionOps npcm7xx_adc_ops = {
378
+ .read = npcm7xx_adc_read,
379
+ .write = npcm7xx_adc_write,
380
+ .endianness = DEVICE_LITTLE_ENDIAN,
381
+ .valid = {
382
+ .min_access_size = 4,
383
+ .max_access_size = 4,
384
+ .unaligned = false,
385
+ },
386
+};
387
+
388
+static void npcm7xx_adc_enter_reset(Object *obj, ResetType type)
389
+{
390
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
391
+
392
+ npcm7xx_adc_reset(s);
393
+}
394
+
395
+static void npcm7xx_adc_hold_reset(Object *obj)
396
+{
397
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
398
+
399
+ qemu_irq_lower(s->irq);
400
+}
401
+
402
+static void npcm7xx_adc_init(Object *obj)
403
+{
404
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
406
+ int i;
407
+
408
+ sysbus_init_irq(sbd, &s->irq);
409
+
410
+ timer_init_ns(&s->conv_timer, QEMU_CLOCK_VIRTUAL,
411
+ npcm7xx_adc_convert_done, s);
412
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
413
+ TYPE_NPCM7XX_ADC, 4 * KiB);
414
+ sysbus_init_mmio(sbd, &s->iomem);
415
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
416
+
417
+ for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
418
+ object_property_add_uint32_ptr(obj, "adci[*]",
419
+ &s->adci[i], OBJ_PROP_FLAG_WRITE);
420
+ }
421
+ object_property_add_uint32_ptr(obj, "vref",
422
+ &s->vref, OBJ_PROP_FLAG_WRITE);
423
+ npcm7xx_adc_calibrate(s);
424
+}
425
+
426
+static const VMStateDescription vmstate_npcm7xx_adc = {
427
+ .name = "npcm7xx-adc",
428
+ .version_id = 0,
429
+ .minimum_version_id = 0,
430
+ .fields = (VMStateField[]) {
431
+ VMSTATE_TIMER(conv_timer, NPCM7xxADCState),
432
+ VMSTATE_UINT32(con, NPCM7xxADCState),
433
+ VMSTATE_UINT32(data, NPCM7xxADCState),
434
+ VMSTATE_CLOCK(clock, NPCM7xxADCState),
435
+ VMSTATE_UINT32_ARRAY(adci, NPCM7xxADCState, NPCM7XX_ADC_NUM_INPUTS),
436
+ VMSTATE_UINT32(vref, NPCM7xxADCState),
437
+ VMSTATE_UINT32(iref, NPCM7xxADCState),
438
+ VMSTATE_UINT16_ARRAY(calibration_r_values, NPCM7xxADCState,
439
+ NPCM7XX_ADC_NUM_CALIB),
440
+ VMSTATE_END_OF_LIST(),
441
+ },
442
+};
443
+
444
+static Property npcm7xx_timer_properties[] = {
445
+ DEFINE_PROP_UINT32("iref", NPCM7xxADCState, iref, NPCM7XX_ADC_DEFAULT_IREF),
446
+ DEFINE_PROP_END_OF_LIST(),
447
+};
448
+
449
+static void npcm7xx_adc_class_init(ObjectClass *klass, void *data)
450
+{
451
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
452
+ DeviceClass *dc = DEVICE_CLASS(klass);
453
+
454
+ dc->desc = "NPCM7xx ADC Module";
455
+ dc->vmsd = &vmstate_npcm7xx_adc;
456
+ rc->phases.enter = npcm7xx_adc_enter_reset;
457
+ rc->phases.hold = npcm7xx_adc_hold_reset;
458
+
459
+ device_class_set_props(dc, npcm7xx_timer_properties);
460
+}
461
+
462
+static const TypeInfo npcm7xx_adc_info = {
463
+ .name = TYPE_NPCM7XX_ADC,
464
+ .parent = TYPE_SYS_BUS_DEVICE,
465
+ .instance_size = sizeof(NPCM7xxADCState),
466
+ .class_init = npcm7xx_adc_class_init,
467
+ .instance_init = npcm7xx_adc_init,
468
+};
469
+
470
+static void npcm7xx_adc_register_types(void)
471
+{
472
+ type_register_static(&npcm7xx_adc_info);
473
+}
474
+
475
+type_init(npcm7xx_adc_register_types);
476
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
477
index XXXXXXX..XXXXXXX 100644
478
--- a/hw/arm/npcm7xx.c
479
+++ b/hw/arm/npcm7xx.c
480
@@ -XXX,XX +XXX,XX @@
481
#define NPCM7XX_EHCI_BA (0xf0806000)
482
#define NPCM7XX_OHCI_BA (0xf0807000)
483
484
+/* ADC Module */
485
+#define NPCM7XX_ADC_BA (0xf000c000)
486
+
487
/* Internal AHB SRAM */
488
#define NPCM7XX_RAM3_BA (0xc0008000)
489
#define NPCM7XX_RAM3_SZ (4 * KiB)
490
@@ -XXX,XX +XXX,XX @@
491
#define NPCM7XX_ROM_BA (0xffff0000)
492
#define NPCM7XX_ROM_SZ (64 * KiB)
493
494
+
495
/* Clock configuration values to be fixed up when bypassing bootloader */
496
497
/* Run PLL1 at 1600 MHz */
498
@@ -XXX,XX +XXX,XX @@
499
* interrupts.
500
*/
501
enum NPCM7xxInterrupt {
502
+ NPCM7XX_ADC_IRQ = 0,
503
NPCM7XX_UART0_IRQ = 2,
504
NPCM7XX_UART1_IRQ,
505
NPCM7XX_UART2_IRQ,
506
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
507
sizeof(value));
145
}
508
}
146
509
147
#undef DO_MOVA_Z
510
+static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
148
+
511
+{
512
+ /* Both ADC and the fuse array must have realized. */
513
+ QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4);
514
+ npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values,
515
+ NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values));
516
+}
517
+
518
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
519
{
520
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
521
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
522
TYPE_NPCM7XX_FUSE_ARRAY);
523
object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
524
object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
525
+ object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC);
526
527
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
528
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
529
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
530
sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
531
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
532
533
+ /* ADC Modules. Cannot fail. */
534
+ qdev_connect_clock_in(DEVICE(&s->adc), "clock", qdev_get_clock_out(
535
+ DEVICE(&s->clk), "adc-clock"));
536
+ sysbus_realize(SYS_BUS_DEVICE(&s->adc), &error_abort);
537
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, NPCM7XX_ADC_BA);
538
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
539
+ npcm7xx_irq(s, NPCM7XX_ADC_IRQ));
540
+ npcm7xx_write_adc_calibration(s);
541
+
542
/* Timer Modules (TIM). Cannot fail. */
543
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
544
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
545
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
546
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
547
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
548
create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
549
- create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
550
create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
551
create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
552
create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
553
diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c
554
new file mode 100644
555
index XXXXXXX..XXXXXXX
556
--- /dev/null
557
+++ b/tests/qtest/npcm7xx_adc-test.c
558
@@ -XXX,XX +XXX,XX @@
149
+/*
559
+/*
150
+ * Clear elements in a tile slice comprising len bytes.
560
+ * QTests for Nuvoton NPCM7xx ADCModules.
561
+ *
562
+ * Copyright 2020 Google LLC
563
+ *
564
+ * This program is free software; you can redistribute it and/or modify it
565
+ * under the terms of the GNU General Public License as published by the
566
+ * Free Software Foundation; either version 2 of the License, or
567
+ * (at your option) any later version.
568
+ *
569
+ * This program is distributed in the hope that it will be useful, but WITHOUT
570
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
571
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
572
+ * for more details.
151
+ */
573
+ */
152
+
574
+
153
+typedef void ClearFn(void *ptr, size_t off, size_t len);
575
+#include "qemu/osdep.h"
154
+
576
+#include "qemu/bitops.h"
155
+static void clear_horizontal(void *ptr, size_t off, size_t len)
577
+#include "qemu/timer.h"
156
+{
578
+#include "libqos/libqtest.h"
157
+ memset(ptr + off, 0, len);
579
+#include "qapi/qmp/qdict.h"
158
+}
580
+
159
+
581
+#define REF_HZ (25000000)
160
+static void clear_vertical_b(void *vptr, size_t off, size_t len)
582
+
161
+{
583
+#define CON_OFFSET 0x0
162
+ for (size_t i = 0; i < len; ++i) {
584
+#define DATA_OFFSET 0x4
163
+ *(uint8_t *)(vptr + tile_vslice_offset(i + off)) = 0;
585
+
164
+ }
586
+#define NUM_INPUTS 8
165
+}
587
+#define DEFAULT_IREF 2000000
166
+
588
+#define CONV_CYCLES 20
167
+static void clear_vertical_h(void *vptr, size_t off, size_t len)
589
+#define RESET_CYCLES 10
168
+{
590
+#define R0_INPUT 500000
169
+ for (size_t i = 0; i < len; i += 2) {
591
+#define R1_INPUT 1500000
170
+ *(uint16_t *)(vptr + tile_vslice_offset(i + off)) = 0;
592
+#define MAX_RESULT 1023
171
+ }
593
+
172
+}
594
+#define DEFAULT_CLKDIV 5
173
+
595
+
174
+static void clear_vertical_s(void *vptr, size_t off, size_t len)
596
+#define FUSE_ARRAY_BA 0xf018a000
175
+{
597
+#define FCTL_OFFSET 0x14
176
+ for (size_t i = 0; i < len; i += 4) {
598
+#define FST_OFFSET 0x0
177
+ *(uint32_t *)(vptr + tile_vslice_offset(i + off)) = 0;
599
+#define FADDR_OFFSET 0x4
178
+ }
600
+#define FDATA_OFFSET 0x8
179
+}
601
+#define ADC_CALIB_ADDR 24
180
+
602
+#define FUSE_READ 0x2
181
+static void clear_vertical_d(void *vptr, size_t off, size_t len)
603
+
182
+{
604
+/* Register field definitions. */
183
+ for (size_t i = 0; i < len; i += 8) {
605
+#define CON_MUX(rv) ((rv) << 24)
184
+ *(uint64_t *)(vptr + tile_vslice_offset(i + off)) = 0;
606
+#define CON_INT_EN BIT(21)
185
+ }
607
+#define CON_REFSEL BIT(19)
186
+}
608
+#define CON_INT BIT(18)
187
+
609
+#define CON_EN BIT(17)
188
+static void clear_vertical_q(void *vptr, size_t off, size_t len)
610
+#define CON_RST BIT(16)
189
+{
611
+#define CON_CONV BIT(14)
190
+ for (size_t i = 0; i < len; i += 16) {
612
+#define CON_DIV(rv) extract32(rv, 1, 8)
191
+ memset(vptr + tile_vslice_offset(i + off), 0, 16);
613
+
192
+ }
614
+#define FST_RDST BIT(1)
193
+}
615
+#define FDATA_MASK 0xff
194
+
616
+
195
+/*
617
+#define MAX_ERROR 10000
196
+ * Copy elements from an array into a tile slice comprising len bytes.
618
+#define MIN_CALIB_INPUT 100000
197
+ */
619
+#define MAX_CALIB_INPUT 1800000
198
+
620
+
199
+typedef void CopyFn(void *dst, const void *src, size_t len);
621
+static const uint32_t input_list[] = {
200
+
622
+ 100000,
201
+static void copy_horizontal(void *dst, const void *src, size_t len)
623
+ 500000,
202
+{
624
+ 1000000,
203
+ memcpy(dst, src, len);
625
+ 1500000,
204
+}
626
+ 1800000,
205
+
627
+ 2000000,
206
+static void copy_vertical_b(void *vdst, const void *vsrc, size_t len)
628
+};
207
+{
629
+
208
+ const uint8_t *src = vsrc;
630
+static const uint32_t vref_list[] = {
209
+ uint8_t *dst = vdst;
631
+ 2000000,
210
+ size_t i;
632
+ 2200000,
211
+
633
+ 2500000,
212
+ for (i = 0; i < len; ++i) {
634
+};
213
+ dst[tile_vslice_index(i)] = src[i];
635
+
214
+ }
636
+static const uint32_t iref_list[] = {
215
+}
637
+ 1800000,
216
+
638
+ 1900000,
217
+static void copy_vertical_h(void *vdst, const void *vsrc, size_t len)
639
+ 2000000,
218
+{
640
+ 2100000,
219
+ const uint16_t *src = vsrc;
641
+ 2200000,
220
+ uint16_t *dst = vdst;
642
+};
221
+ size_t i;
643
+
222
+
644
+static const uint32_t div_list[] = {0, 1, 3, 7, 15};
223
+ for (i = 0; i < len / 2; ++i) {
645
+
224
+ dst[tile_vslice_index(i)] = src[i];
646
+typedef struct ADC {
225
+ }
647
+ int irq;
226
+}
648
+ uint64_t base_addr;
227
+
649
+} ADC;
228
+static void copy_vertical_s(void *vdst, const void *vsrc, size_t len)
650
+
229
+{
651
+ADC adc = {
230
+ const uint32_t *src = vsrc;
652
+ .irq = 0,
231
+ uint32_t *dst = vdst;
653
+ .base_addr = 0xf000c000
232
+ size_t i;
654
+};
233
+
655
+
234
+ for (i = 0; i < len / 4; ++i) {
656
+static uint32_t adc_read_con(QTestState *qts, const ADC *adc)
235
+ dst[tile_vslice_index(i)] = src[i];
657
+{
236
+ }
658
+ return qtest_readl(qts, adc->base_addr + CON_OFFSET);
237
+}
659
+}
238
+
660
+
239
+static void copy_vertical_d(void *vdst, const void *vsrc, size_t len)
661
+static void adc_write_con(QTestState *qts, const ADC *adc, uint32_t value)
240
+{
662
+{
241
+ const uint64_t *src = vsrc;
663
+ qtest_writel(qts, adc->base_addr + CON_OFFSET, value);
242
+ uint64_t *dst = vdst;
664
+}
243
+ size_t i;
665
+
244
+
666
+static uint32_t adc_read_data(QTestState *qts, const ADC *adc)
245
+ for (i = 0; i < len / 8; ++i) {
667
+{
246
+ dst[tile_vslice_index(i)] = src[i];
668
+ return qtest_readl(qts, adc->base_addr + DATA_OFFSET);
247
+ }
669
+}
248
+}
670
+
249
+
671
+static uint32_t adc_calibrate(uint32_t measured, uint32_t *rv)
250
+static void copy_vertical_q(void *vdst, const void *vsrc, size_t len)
672
+{
251
+{
673
+ return R0_INPUT + (R1_INPUT - R0_INPUT) * (int32_t)(measured - rv[0])
252
+ for (size_t i = 0; i < len; i += 16) {
674
+ / (int32_t)(rv[1] - rv[0]);
253
+ memcpy(vdst + tile_vslice_offset(i), vsrc + i, 16);
675
+}
254
+ }
676
+
255
+}
677
+static void adc_qom_set(QTestState *qts, const ADC *adc,
256
+
678
+ const char *name, uint32_t value)
257
+/*
679
+{
258
+ * Host and TLB primitives for vertical tile slice addressing.
680
+ QDict *response;
259
+ */
681
+ const char *path = "/machine/soc/adc";
260
+
682
+
261
+#define DO_LD(NAME, TYPE, HOST, TLB) \
683
+ g_test_message("Setting properties %s of %s with value %u",
262
+static inline void sme_##NAME##_v_host(void *za, intptr_t off, void *host) \
684
+ name, path, value);
263
+{ \
685
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
264
+ TYPE val = HOST(host); \
686
+ " 'arguments': { 'path': %s, 'property': %s, 'value': %u}}",
265
+ *(TYPE *)(za + tile_vslice_offset(off)) = val; \
687
+ path, name, value);
266
+} \
688
+ /* The qom set message returns successfully. */
267
+static inline void sme_##NAME##_v_tlb(CPUARMState *env, void *za, \
689
+ g_assert_true(qdict_haskey(response, "return"));
268
+ intptr_t off, target_ulong addr, uintptr_t ra) \
690
+}
269
+{ \
691
+
270
+ TYPE val = TLB(env, useronly_clean_ptr(addr), ra); \
692
+static void adc_write_input(QTestState *qts, const ADC *adc,
271
+ *(TYPE *)(za + tile_vslice_offset(off)) = val; \
693
+ uint32_t index, uint32_t value)
272
+}
694
+{
273
+
695
+ char name[100];
274
+#define DO_ST(NAME, TYPE, HOST, TLB) \
696
+
275
+static inline void sme_##NAME##_v_host(void *za, intptr_t off, void *host) \
697
+ sprintf(name, "adci[%u]", index);
276
+{ \
698
+ adc_qom_set(qts, adc, name, value);
277
+ TYPE val = *(TYPE *)(za + tile_vslice_offset(off)); \
699
+}
278
+ HOST(host, val); \
700
+
279
+} \
701
+static void adc_write_vref(QTestState *qts, const ADC *adc, uint32_t value)
280
+static inline void sme_##NAME##_v_tlb(CPUARMState *env, void *za, \
702
+{
281
+ intptr_t off, target_ulong addr, uintptr_t ra) \
703
+ adc_qom_set(qts, adc, "vref", value);
282
+{ \
704
+}
283
+ TYPE val = *(TYPE *)(za + tile_vslice_offset(off)); \
705
+
284
+ TLB(env, useronly_clean_ptr(addr), val, ra); \
706
+static uint32_t adc_calculate_output(uint32_t input, uint32_t ref)
285
+}
707
+{
286
+
708
+ uint32_t output;
287
+/*
709
+
288
+ * The ARMVectorReg elements are stored in host-endian 64-bit units.
710
+ g_assert_cmpuint(input, <=, ref);
289
+ * For 128-bit quantities, the sequence defined by the Elem[] pseudocode
711
+ output = (input * (MAX_RESULT + 1)) / ref;
290
+ * corresponds to storing the two 64-bit pieces in little-endian order.
712
+ if (output > MAX_RESULT) {
291
+ */
713
+ output = MAX_RESULT;
292
+#define DO_LDQ(HNAME, VNAME, BE, HOST, TLB) \
714
+ }
293
+static inline void HNAME##_host(void *za, intptr_t off, void *host) \
715
+
294
+{ \
716
+ return output;
295
+ uint64_t val0 = HOST(host), val1 = HOST(host + 8); \
717
+}
296
+ uint64_t *ptr = za + off; \
718
+
297
+ ptr[0] = BE ? val1 : val0, ptr[1] = BE ? val0 : val1; \
719
+static uint32_t adc_prescaler(QTestState *qts, const ADC *adc)
298
+} \
720
+{
299
+static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
721
+ uint32_t div = extract32(adc_read_con(qts, adc), 1, 8);
300
+{ \
722
+
301
+ HNAME##_host(za, tile_vslice_offset(off), host); \
723
+ return 2 * (div + 1);
302
+} \
724
+}
303
+static inline void HNAME##_tlb(CPUARMState *env, void *za, intptr_t off, \
725
+
304
+ target_ulong addr, uintptr_t ra) \
726
+static int64_t adc_calculate_steps(uint32_t cycles, uint32_t prescale,
305
+{ \
727
+ uint32_t clkdiv)
306
+ uint64_t val0 = TLB(env, useronly_clean_ptr(addr), ra); \
728
+{
307
+ uint64_t val1 = TLB(env, useronly_clean_ptr(addr + 8), ra); \
729
+ return (NANOSECONDS_PER_SECOND / (REF_HZ >> clkdiv)) * cycles * prescale;
308
+ uint64_t *ptr = za + off; \
730
+}
309
+ ptr[0] = BE ? val1 : val0, ptr[1] = BE ? val0 : val1; \
731
+
310
+} \
732
+static void adc_wait_conv_finished(QTestState *qts, const ADC *adc,
311
+static inline void VNAME##_v_tlb(CPUARMState *env, void *za, intptr_t off, \
733
+ uint32_t clkdiv)
312
+ target_ulong addr, uintptr_t ra) \
734
+{
313
+{ \
735
+ uint32_t prescaler = adc_prescaler(qts, adc);
314
+ HNAME##_tlb(env, za, tile_vslice_offset(off), addr, ra); \
315
+}
316
+
317
+#define DO_STQ(HNAME, VNAME, BE, HOST, TLB) \
318
+static inline void HNAME##_host(void *za, intptr_t off, void *host) \
319
+{ \
320
+ uint64_t *ptr = za + off; \
321
+ HOST(host, ptr[BE]); \
322
+ HOST(host + 1, ptr[!BE]); \
323
+} \
324
+static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
325
+{ \
326
+ HNAME##_host(za, tile_vslice_offset(off), host); \
327
+} \
328
+static inline void HNAME##_tlb(CPUARMState *env, void *za, intptr_t off, \
329
+ target_ulong addr, uintptr_t ra) \
330
+{ \
331
+ uint64_t *ptr = za + off; \
332
+ TLB(env, useronly_clean_ptr(addr), ptr[BE], ra); \
333
+ TLB(env, useronly_clean_ptr(addr + 8), ptr[!BE], ra); \
334
+} \
335
+static inline void VNAME##_v_tlb(CPUARMState *env, void *za, intptr_t off, \
336
+ target_ulong addr, uintptr_t ra) \
337
+{ \
338
+ HNAME##_tlb(env, za, tile_vslice_offset(off), addr, ra); \
339
+}
340
+
341
+DO_LD(ld1b, uint8_t, ldub_p, cpu_ldub_data_ra)
342
+DO_LD(ld1h_be, uint16_t, lduw_be_p, cpu_lduw_be_data_ra)
343
+DO_LD(ld1h_le, uint16_t, lduw_le_p, cpu_lduw_le_data_ra)
344
+DO_LD(ld1s_be, uint32_t, ldl_be_p, cpu_ldl_be_data_ra)
345
+DO_LD(ld1s_le, uint32_t, ldl_le_p, cpu_ldl_le_data_ra)
346
+DO_LD(ld1d_be, uint64_t, ldq_be_p, cpu_ldq_be_data_ra)
347
+DO_LD(ld1d_le, uint64_t, ldq_le_p, cpu_ldq_le_data_ra)
348
+
349
+DO_LDQ(sve_ld1qq_be, sme_ld1q_be, 1, ldq_be_p, cpu_ldq_be_data_ra)
350
+DO_LDQ(sve_ld1qq_le, sme_ld1q_le, 0, ldq_le_p, cpu_ldq_le_data_ra)
351
+
352
+DO_ST(st1b, uint8_t, stb_p, cpu_stb_data_ra)
353
+DO_ST(st1h_be, uint16_t, stw_be_p, cpu_stw_be_data_ra)
354
+DO_ST(st1h_le, uint16_t, stw_le_p, cpu_stw_le_data_ra)
355
+DO_ST(st1s_be, uint32_t, stl_be_p, cpu_stl_be_data_ra)
356
+DO_ST(st1s_le, uint32_t, stl_le_p, cpu_stl_le_data_ra)
357
+DO_ST(st1d_be, uint64_t, stq_be_p, cpu_stq_be_data_ra)
358
+DO_ST(st1d_le, uint64_t, stq_le_p, cpu_stq_le_data_ra)
359
+
360
+DO_STQ(sve_st1qq_be, sme_st1q_be, 1, stq_be_p, cpu_stq_be_data_ra)
361
+DO_STQ(sve_st1qq_le, sme_st1q_le, 0, stq_le_p, cpu_stq_le_data_ra)
362
+
363
+#undef DO_LD
364
+#undef DO_ST
365
+#undef DO_LDQ
366
+#undef DO_STQ
367
+
368
+/*
369
+ * Common helper for all contiguous predicated loads.
370
+ */
371
+
372
+static inline QEMU_ALWAYS_INLINE
373
+void sme_ld1(CPUARMState *env, void *za, uint64_t *vg,
374
+ const target_ulong addr, uint32_t desc, const uintptr_t ra,
375
+ const int esz, uint32_t mtedesc, bool vertical,
376
+ sve_ldst1_host_fn *host_fn,
377
+ sve_ldst1_tlb_fn *tlb_fn,
378
+ ClearFn *clr_fn,
379
+ CopyFn *cpy_fn)
380
+{
381
+ const intptr_t reg_max = simd_oprsz(desc);
382
+ const intptr_t esize = 1 << esz;
383
+ intptr_t reg_off, reg_last;
384
+ SVEContLdSt info;
385
+ void *host;
386
+ int flags;
387
+
388
+ /* Find the active elements. */
389
+ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, esize)) {
390
+ /* The entire predicate was false; no load occurs. */
391
+ clr_fn(za, 0, reg_max);
392
+ return;
393
+ }
394
+
395
+ /* Probe the page(s). Exit with exception for any invalid page. */
396
+ sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_LOAD, ra);
397
+
398
+ /* Handle watchpoints for all active elements. */
399
+ sve_cont_ldst_watchpoints(&info, env, vg, addr, esize, esize,
400
+ BP_MEM_READ, ra);
401
+
736
+
402
+ /*
737
+ /*
403
+ * Handle mte checks for all active elements.
738
+ * ADC should takes roughly 20 cycles to convert one sample. So we assert it
404
+ * Since TBI must be set for MTE, !mtedesc => !mte_active.
739
+ * should take 10~30 cycles here.
405
+ */
740
+ */
406
+ if (mtedesc) {
741
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES / 2, prescaler,
407
+ sve_cont_ldst_mte_check(&info, env, vg, addr, esize, esize,
742
+ clkdiv));
408
+ mtedesc, ra);
743
+ /* ADC is still converting. */
409
+ }
744
+ g_assert_true(adc_read_con(qts, adc) & CON_CONV);
410
+
745
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES, prescaler, clkdiv));
411
+ flags = info.page[0].flags | info.page[1].flags;
746
+ /* ADC has finished conversion. */
412
+ if (unlikely(flags != 0)) {
747
+ g_assert_false(adc_read_con(qts, adc) & CON_CONV);
413
+#ifdef CONFIG_USER_ONLY
748
+}
414
+ g_assert_not_reached();
749
+
415
+#else
750
+/* Check ADC can be reset to default value. */
416
+ /*
751
+static void test_init(gconstpointer adc_p)
417
+ * At least one page includes MMIO.
752
+{
418
+ * Any bus operation can fail with cpu_transaction_failed,
753
+ const ADC *adc = adc_p;
419
+ * which for ARM will raise SyncExternal. Perform the load
754
+
420
+ * into scratch memory to preserve register state until the end.
755
+ QTestState *qts = qtest_init("-machine quanta-gsj");
421
+ */
756
+ adc_write_con(qts, adc, CON_REFSEL | CON_INT);
422
+ ARMVectorReg scratch = { };
757
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_REFSEL);
423
+
758
+ qtest_quit(qts);
424
+ reg_off = info.reg_off_first[0];
759
+}
425
+ reg_last = info.reg_off_last[1];
760
+
426
+ if (reg_last < 0) {
761
+/* Check ADC can convert from an internal reference. */
427
+ reg_last = info.reg_off_split;
762
+static void test_convert_internal(gconstpointer adc_p)
428
+ if (reg_last < 0) {
763
+{
429
+ reg_last = info.reg_off_last[0];
764
+ const ADC *adc = adc_p;
765
+ uint32_t index, input, output, expected_output;
766
+ QTestState *qts = qtest_init("-machine quanta-gsj");
767
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
768
+
769
+ for (index = 0; index < NUM_INPUTS; ++index) {
770
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
771
+ input = input_list[i];
772
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
773
+
774
+ adc_write_input(qts, adc, index, input);
775
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
776
+ CON_EN | CON_CONV);
777
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
778
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) |
779
+ CON_REFSEL | CON_EN);
780
+ g_assert_false(qtest_get_irq(qts, adc->irq));
781
+ output = adc_read_data(qts, adc);
782
+ g_assert_cmpuint(output, ==, expected_output);
783
+ }
784
+ }
785
+
786
+ qtest_quit(qts);
787
+}
788
+
789
+/* Check ADC can convert from an external reference. */
790
+static void test_convert_external(gconstpointer adc_p)
791
+{
792
+ const ADC *adc = adc_p;
793
+ uint32_t index, input, vref, output, expected_output;
794
+ QTestState *qts = qtest_init("-machine quanta-gsj");
795
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
796
+
797
+ for (index = 0; index < NUM_INPUTS; ++index) {
798
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
799
+ for (size_t j = 0; j < ARRAY_SIZE(vref_list); ++j) {
800
+ input = input_list[i];
801
+ vref = vref_list[j];
802
+ expected_output = adc_calculate_output(input, vref);
803
+
804
+ adc_write_input(qts, adc, index, input);
805
+ adc_write_vref(qts, adc, vref);
806
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT | CON_EN |
807
+ CON_CONV);
808
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
809
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
810
+ CON_MUX(index) | CON_EN);
811
+ g_assert_false(qtest_get_irq(qts, adc->irq));
812
+ output = adc_read_data(qts, adc);
813
+ g_assert_cmpuint(output, ==, expected_output);
430
+ }
814
+ }
431
+ }
815
+ }
432
+
816
+ }
433
+ do {
817
+
434
+ uint64_t pg = vg[reg_off >> 6];
818
+ qtest_quit(qts);
435
+ do {
819
+}
436
+ if ((pg >> (reg_off & 63)) & 1) {
820
+
437
+ tlb_fn(env, &scratch, reg_off, addr + reg_off, ra);
821
+/* Check ADC interrupt files if and only if CON_INT_EN is set. */
438
+ }
822
+static void test_interrupt(gconstpointer adc_p)
439
+ reg_off += esize;
823
+{
440
+ } while (reg_off & 63);
824
+ const ADC *adc = adc_p;
441
+ } while (reg_off <= reg_last);
825
+ uint32_t index, input, output, expected_output;
442
+
826
+ QTestState *qts = qtest_init("-machine quanta-gsj");
443
+ cpy_fn(za, &scratch, reg_max);
827
+
444
+ return;
828
+ index = 1;
445
+#endif
829
+ input = input_list[1];
446
+ }
830
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
447
+
831
+
448
+ /* The entire operation is in RAM, on valid pages. */
832
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
449
+
833
+ adc_write_input(qts, adc, index, input);
450
+ reg_off = info.reg_off_first[0];
834
+ g_assert_false(qtest_get_irq(qts, adc->irq));
451
+ reg_last = info.reg_off_last[0];
835
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT_EN | CON_REFSEL | CON_INT
452
+ host = info.page[0].host;
836
+ | CON_EN | CON_CONV);
453
+
837
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
454
+ if (!vertical) {
838
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) | CON_INT_EN
455
+ memset(za, 0, reg_max);
839
+ | CON_REFSEL | CON_INT | CON_EN);
456
+ } else if (reg_off) {
840
+ g_assert_true(qtest_get_irq(qts, adc->irq));
457
+ clr_fn(za, 0, reg_off);
841
+ output = adc_read_data(qts, adc);
458
+ }
842
+ g_assert_cmpuint(output, ==, expected_output);
459
+
843
+
460
+ while (reg_off <= reg_last) {
844
+ qtest_quit(qts);
461
+ uint64_t pg = vg[reg_off >> 6];
845
+}
462
+ do {
846
+
463
+ if ((pg >> (reg_off & 63)) & 1) {
847
+/* Check ADC is reset after setting ADC_RST for 10 ADC cycles. */
464
+ host_fn(za, reg_off, host + reg_off);
848
+static void test_reset(gconstpointer adc_p)
465
+ } else if (vertical) {
849
+{
466
+ clr_fn(za, reg_off, esize);
850
+ const ADC *adc = adc_p;
851
+ QTestState *qts = qtest_init("-machine quanta-gsj");
852
+
853
+ for (size_t i = 0; i < ARRAY_SIZE(div_list); ++i) {
854
+ uint32_t div = div_list[i];
855
+
856
+ adc_write_con(qts, adc, CON_INT | CON_EN | CON_RST | CON_DIV(div));
857
+ qtest_clock_step(qts, adc_calculate_steps(RESET_CYCLES,
858
+ adc_prescaler(qts, adc), DEFAULT_CLKDIV));
859
+ g_assert_false(adc_read_con(qts, adc) & CON_EN);
860
+ }
861
+ qtest_quit(qts);
862
+}
863
+
864
+/* Check ADC Calibration works as desired. */
865
+static void test_calibrate(gconstpointer adc_p)
866
+{
867
+ int i, j;
868
+ const ADC *adc = adc_p;
869
+
870
+ for (j = 0; j < ARRAY_SIZE(iref_list); ++j) {
871
+ uint32_t iref = iref_list[j];
872
+ uint32_t expected_rv[] = {
873
+ adc_calculate_output(R0_INPUT, iref),
874
+ adc_calculate_output(R1_INPUT, iref),
875
+ };
876
+ char buf[100];
877
+ QTestState *qts;
878
+
879
+ sprintf(buf, "-machine quanta-gsj -global npcm7xx-adc.iref=%u", iref);
880
+ qts = qtest_init(buf);
881
+
882
+ /* Check the converted value is correct using the calibration value. */
883
+ for (i = 0; i < ARRAY_SIZE(input_list); ++i) {
884
+ uint32_t input;
885
+ uint32_t output;
886
+ uint32_t expected_output;
887
+ uint32_t calibrated_voltage;
888
+ uint32_t index = 0;
889
+
890
+ input = input_list[i];
891
+ /* Calibration only works for input range 0.1V ~ 1.8V. */
892
+ if (input < MIN_CALIB_INPUT || input > MAX_CALIB_INPUT) {
893
+ continue;
467
+ }
894
+ }
468
+ reg_off += esize;
895
+ expected_output = adc_calculate_output(input, iref);
469
+ } while (reg_off <= reg_last && (reg_off & 63));
896
+
470
+ }
897
+ adc_write_input(qts, adc, index, input);
471
+
898
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
472
+ /*
899
+ CON_EN | CON_CONV);
473
+ * Use the slow path to manage the cross-page misalignment.
900
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
474
+ * But we know this is RAM and cannot trap.
901
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
475
+ */
902
+ CON_REFSEL | CON_MUX(index) | CON_EN);
476
+ reg_off = info.reg_off_split;
903
+ output = adc_read_data(qts, adc);
477
+ if (unlikely(reg_off >= 0)) {
904
+ g_assert_cmpuint(output, ==, expected_output);
478
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
905
+
479
+ }
906
+ calibrated_voltage = adc_calibrate(output, expected_rv);
480
+
907
+ g_assert_cmpuint(calibrated_voltage, >, input - MAX_ERROR);
481
+ reg_off = info.reg_off_first[1];
908
+ g_assert_cmpuint(calibrated_voltage, <, input + MAX_ERROR);
482
+ if (unlikely(reg_off >= 0)) {
483
+ reg_last = info.reg_off_last[1];
484
+ host = info.page[1].host;
485
+
486
+ do {
487
+ uint64_t pg = vg[reg_off >> 6];
488
+ do {
489
+ if ((pg >> (reg_off & 63)) & 1) {
490
+ host_fn(za, reg_off, host + reg_off);
491
+ } else if (vertical) {
492
+ clr_fn(za, reg_off, esize);
493
+ }
494
+ reg_off += esize;
495
+ } while (reg_off & 63);
496
+ } while (reg_off <= reg_last);
497
+ }
498
+}
499
+
500
+static inline QEMU_ALWAYS_INLINE
501
+void sme_ld1_mte(CPUARMState *env, void *za, uint64_t *vg,
502
+ target_ulong addr, uint32_t desc, uintptr_t ra,
503
+ const int esz, bool vertical,
504
+ sve_ldst1_host_fn *host_fn,
505
+ sve_ldst1_tlb_fn *tlb_fn,
506
+ ClearFn *clr_fn,
507
+ CopyFn *cpy_fn)
508
+{
509
+ uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
510
+ int bit55 = extract64(addr, 55, 1);
511
+
512
+ /* Remove mtedesc from the normal sve descriptor. */
513
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
514
+
515
+ /* Perform gross MTE suppression early. */
516
+ if (!tbi_check(desc, bit55) ||
517
+ tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
518
+ mtedesc = 0;
519
+ }
520
+
521
+ sme_ld1(env, za, vg, addr, desc, ra, esz, mtedesc, vertical,
522
+ host_fn, tlb_fn, clr_fn, cpy_fn);
523
+}
524
+
525
+#define DO_LD(L, END, ESZ) \
526
+void HELPER(sme_ld1##L##END##_h)(CPUARMState *env, void *za, void *vg, \
527
+ target_ulong addr, uint32_t desc) \
528
+{ \
529
+ sme_ld1(env, za, vg, addr, desc, GETPC(), ESZ, 0, false, \
530
+ sve_ld1##L##L##END##_host, sve_ld1##L##L##END##_tlb, \
531
+ clear_horizontal, copy_horizontal); \
532
+} \
533
+void HELPER(sme_ld1##L##END##_v)(CPUARMState *env, void *za, void *vg, \
534
+ target_ulong addr, uint32_t desc) \
535
+{ \
536
+ sme_ld1(env, za, vg, addr, desc, GETPC(), ESZ, 0, true, \
537
+ sme_ld1##L##END##_v_host, sme_ld1##L##END##_v_tlb, \
538
+ clear_vertical_##L, copy_vertical_##L); \
539
+} \
540
+void HELPER(sme_ld1##L##END##_h_mte)(CPUARMState *env, void *za, void *vg, \
541
+ target_ulong addr, uint32_t desc) \
542
+{ \
543
+ sme_ld1_mte(env, za, vg, addr, desc, GETPC(), ESZ, false, \
544
+ sve_ld1##L##L##END##_host, sve_ld1##L##L##END##_tlb, \
545
+ clear_horizontal, copy_horizontal); \
546
+} \
547
+void HELPER(sme_ld1##L##END##_v_mte)(CPUARMState *env, void *za, void *vg, \
548
+ target_ulong addr, uint32_t desc) \
549
+{ \
550
+ sme_ld1_mte(env, za, vg, addr, desc, GETPC(), ESZ, true, \
551
+ sme_ld1##L##END##_v_host, sme_ld1##L##END##_v_tlb, \
552
+ clear_vertical_##L, copy_vertical_##L); \
553
+}
554
+
555
+DO_LD(b, , MO_8)
556
+DO_LD(h, _be, MO_16)
557
+DO_LD(h, _le, MO_16)
558
+DO_LD(s, _be, MO_32)
559
+DO_LD(s, _le, MO_32)
560
+DO_LD(d, _be, MO_64)
561
+DO_LD(d, _le, MO_64)
562
+DO_LD(q, _be, MO_128)
563
+DO_LD(q, _le, MO_128)
564
+
565
+#undef DO_LD
566
+
567
+/*
568
+ * Common helper for all contiguous predicated stores.
569
+ */
570
+
571
+static inline QEMU_ALWAYS_INLINE
572
+void sme_st1(CPUARMState *env, void *za, uint64_t *vg,
573
+ const target_ulong addr, uint32_t desc, const uintptr_t ra,
574
+ const int esz, uint32_t mtedesc, bool vertical,
575
+ sve_ldst1_host_fn *host_fn,
576
+ sve_ldst1_tlb_fn *tlb_fn)
577
+{
578
+ const intptr_t reg_max = simd_oprsz(desc);
579
+ const intptr_t esize = 1 << esz;
580
+ intptr_t reg_off, reg_last;
581
+ SVEContLdSt info;
582
+ void *host;
583
+ int flags;
584
+
585
+ /* Find the active elements. */
586
+ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, esize)) {
587
+ /* The entire predicate was false; no store occurs. */
588
+ return;
589
+ }
590
+
591
+ /* Probe the page(s). Exit with exception for any invalid page. */
592
+ sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_STORE, ra);
593
+
594
+ /* Handle watchpoints for all active elements. */
595
+ sve_cont_ldst_watchpoints(&info, env, vg, addr, esize, esize,
596
+ BP_MEM_WRITE, ra);
597
+
598
+ /*
599
+ * Handle mte checks for all active elements.
600
+ * Since TBI must be set for MTE, !mtedesc => !mte_active.
601
+ */
602
+ if (mtedesc) {
603
+ sve_cont_ldst_mte_check(&info, env, vg, addr, esize, esize,
604
+ mtedesc, ra);
605
+ }
606
+
607
+ flags = info.page[0].flags | info.page[1].flags;
608
+ if (unlikely(flags != 0)) {
609
+#ifdef CONFIG_USER_ONLY
610
+ g_assert_not_reached();
611
+#else
612
+ /*
613
+ * At least one page includes MMIO.
614
+ * Any bus operation can fail with cpu_transaction_failed,
615
+ * which for ARM will raise SyncExternal. We cannot avoid
616
+ * this fault and will leave with the store incomplete.
617
+ */
618
+ reg_off = info.reg_off_first[0];
619
+ reg_last = info.reg_off_last[1];
620
+ if (reg_last < 0) {
621
+ reg_last = info.reg_off_split;
622
+ if (reg_last < 0) {
623
+ reg_last = info.reg_off_last[0];
624
+ }
625
+ }
909
+ }
626
+
910
+
627
+ do {
911
+ qtest_quit(qts);
628
+ uint64_t pg = vg[reg_off >> 6];
912
+ }
629
+ do {
913
+}
630
+ if ((pg >> (reg_off & 63)) & 1) {
914
+
631
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
915
+static void adc_add_test(const char *name, const ADC* wd,
632
+ }
916
+ GTestDataFunc fn)
633
+ reg_off += esize;
917
+{
634
+ } while (reg_off & 63);
918
+ g_autofree char *full_name = g_strdup_printf("npcm7xx_adc/%s", name);
635
+ } while (reg_off <= reg_last);
919
+ qtest_add_data_func(full_name, wd, fn);
636
+ return;
920
+}
637
+#endif
921
+#define add_test(name, td) adc_add_test(#name, td, test_##name)
638
+ }
922
+
639
+
923
+int main(int argc, char **argv)
640
+ reg_off = info.reg_off_first[0];
924
+{
641
+ reg_last = info.reg_off_last[0];
925
+ g_test_init(&argc, &argv, NULL);
642
+ host = info.page[0].host;
926
+
643
+
927
+ add_test(init, &adc);
644
+ while (reg_off <= reg_last) {
928
+ add_test(convert_internal, &adc);
645
+ uint64_t pg = vg[reg_off >> 6];
929
+ add_test(convert_external, &adc);
646
+ do {
930
+ add_test(interrupt, &adc);
647
+ if ((pg >> (reg_off & 63)) & 1) {
931
+ add_test(reset, &adc);
648
+ host_fn(za, reg_off, host + reg_off);
932
+ add_test(calibrate, &adc);
649
+ }
933
+
650
+ reg_off += 1 << esz;
934
+ return g_test_run();
651
+ } while (reg_off <= reg_last && (reg_off & 63));
935
+}
652
+ }
936
diff --git a/hw/adc/meson.build b/hw/adc/meson.build
653
+
654
+ /*
655
+ * Use the slow path to manage the cross-page misalignment.
656
+ * But we know this is RAM and cannot trap.
657
+ */
658
+ reg_off = info.reg_off_split;
659
+ if (unlikely(reg_off >= 0)) {
660
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
661
+ }
662
+
663
+ reg_off = info.reg_off_first[1];
664
+ if (unlikely(reg_off >= 0)) {
665
+ reg_last = info.reg_off_last[1];
666
+ host = info.page[1].host;
667
+
668
+ do {
669
+ uint64_t pg = vg[reg_off >> 6];
670
+ do {
671
+ if ((pg >> (reg_off & 63)) & 1) {
672
+ host_fn(za, reg_off, host + reg_off);
673
+ }
674
+ reg_off += 1 << esz;
675
+ } while (reg_off & 63);
676
+ } while (reg_off <= reg_last);
677
+ }
678
+}
679
+
680
+static inline QEMU_ALWAYS_INLINE
681
+void sme_st1_mte(CPUARMState *env, void *za, uint64_t *vg, target_ulong addr,
682
+ uint32_t desc, uintptr_t ra, int esz, bool vertical,
683
+ sve_ldst1_host_fn *host_fn,
684
+ sve_ldst1_tlb_fn *tlb_fn)
685
+{
686
+ uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
687
+ int bit55 = extract64(addr, 55, 1);
688
+
689
+ /* Remove mtedesc from the normal sve descriptor. */
690
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
691
+
692
+ /* Perform gross MTE suppression early. */
693
+ if (!tbi_check(desc, bit55) ||
694
+ tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
695
+ mtedesc = 0;
696
+ }
697
+
698
+ sme_st1(env, za, vg, addr, desc, ra, esz, mtedesc,
699
+ vertical, host_fn, tlb_fn);
700
+}
701
+
702
+#define DO_ST(L, END, ESZ) \
703
+void HELPER(sme_st1##L##END##_h)(CPUARMState *env, void *za, void *vg, \
704
+ target_ulong addr, uint32_t desc) \
705
+{ \
706
+ sme_st1(env, za, vg, addr, desc, GETPC(), ESZ, 0, false, \
707
+ sve_st1##L##L##END##_host, sve_st1##L##L##END##_tlb); \
708
+} \
709
+void HELPER(sme_st1##L##END##_v)(CPUARMState *env, void *za, void *vg, \
710
+ target_ulong addr, uint32_t desc) \
711
+{ \
712
+ sme_st1(env, za, vg, addr, desc, GETPC(), ESZ, 0, true, \
713
+ sme_st1##L##END##_v_host, sme_st1##L##END##_v_tlb); \
714
+} \
715
+void HELPER(sme_st1##L##END##_h_mte)(CPUARMState *env, void *za, void *vg, \
716
+ target_ulong addr, uint32_t desc) \
717
+{ \
718
+ sme_st1_mte(env, za, vg, addr, desc, GETPC(), ESZ, false, \
719
+ sve_st1##L##L##END##_host, sve_st1##L##L##END##_tlb); \
720
+} \
721
+void HELPER(sme_st1##L##END##_v_mte)(CPUARMState *env, void *za, void *vg, \
722
+ target_ulong addr, uint32_t desc) \
723
+{ \
724
+ sme_st1_mte(env, za, vg, addr, desc, GETPC(), ESZ, true, \
725
+ sme_st1##L##END##_v_host, sme_st1##L##END##_v_tlb); \
726
+}
727
+
728
+DO_ST(b, , MO_8)
729
+DO_ST(h, _be, MO_16)
730
+DO_ST(h, _le, MO_16)
731
+DO_ST(s, _be, MO_32)
732
+DO_ST(s, _le, MO_32)
733
+DO_ST(d, _be, MO_64)
734
+DO_ST(d, _le, MO_64)
735
+DO_ST(q, _be, MO_128)
736
+DO_ST(q, _le, MO_128)
737
+
738
+#undef DO_ST
739
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
740
index XXXXXXX..XXXXXXX 100644
937
index XXXXXXX..XXXXXXX 100644
741
--- a/target/arm/translate-sme.c
938
--- a/hw/adc/meson.build
742
+++ b/target/arm/translate-sme.c
939
+++ b/hw/adc/meson.build
743
@@ -XXX,XX +XXX,XX @@ static bool trans_MOVA(DisasContext *s, arg_MOVA *a)
940
@@ -1 +1,2 @@
744
941
softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
745
return true;
942
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
746
}
943
diff --git a/hw/adc/trace-events b/hw/adc/trace-events
747
+
944
new file mode 100644
748
+static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
945
index XXXXXXX..XXXXXXX
749
+{
946
--- /dev/null
750
+ typedef void GenLdSt1(TCGv_env, TCGv_ptr, TCGv_ptr, TCGv, TCGv_i32);
947
+++ b/hw/adc/trace-events
751
+
948
@@ -XXX,XX +XXX,XX @@
752
+ /*
949
+# See docs/devel/tracing.txt for syntax documentation.
753
+ * Indexed by [esz][be][v][mte][st], which is (except for load/store)
950
+
754
+ * also the order in which the elements appear in the function names,
951
+# npcm7xx_adc.c
755
+ * and so how we must concatenate the pieces.
952
+npcm7xx_adc_read(const char *id, uint64_t offset, uint32_t value) " %s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
756
+ */
953
+npcm7xx_adc_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
757
+
954
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
758
+#define FN_LS(F) { gen_helper_sme_ld1##F, gen_helper_sme_st1##F }
955
index XXXXXXX..XXXXXXX 100644
759
+#define FN_MTE(F) { FN_LS(F), FN_LS(F##_mte) }
956
--- a/tests/qtest/meson.build
760
+#define FN_HV(F) { FN_MTE(F##_h), FN_MTE(F##_v) }
957
+++ b/tests/qtest/meson.build
761
+#define FN_END(L, B) { FN_HV(L), FN_HV(B) }
958
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
762
+
959
['prom-env-test', 'boot-serial-test']
763
+ static GenLdSt1 * const fns[5][2][2][2][2] = {
960
764
+ FN_END(b, b),
961
qtests_npcm7xx = \
765
+ FN_END(h_le, h_be),
962
- ['npcm7xx_gpio-test',
766
+ FN_END(s_le, s_be),
963
+ ['npcm7xx_adc-test',
767
+ FN_END(d_le, d_be),
964
+ 'npcm7xx_gpio-test',
768
+ FN_END(q_le, q_be),
965
'npcm7xx_rng-test',
769
+ };
966
'npcm7xx_timer-test',
770
+
967
'npcm7xx_watchdog_timer-test']
771
+#undef FN_LS
772
+#undef FN_MTE
773
+#undef FN_HV
774
+#undef FN_END
775
+
776
+ TCGv_ptr t_za, t_pg;
777
+ TCGv_i64 addr;
778
+ int svl, desc = 0;
779
+ bool be = s->be_data == MO_BE;
780
+ bool mte = s->mte_active[0];
781
+
782
+ if (!dc_isar_feature(aa64_sme, s)) {
783
+ return false;
784
+ }
785
+ if (!sme_smza_enabled_check(s)) {
786
+ return true;
787
+ }
788
+
789
+ t_za = get_tile_rowcol(s, a->esz, a->rs, a->za_imm, a->v);
790
+ t_pg = pred_full_reg_ptr(s, a->pg);
791
+ addr = tcg_temp_new_i64();
792
+
793
+ tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), a->esz);
794
+ tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
795
+
796
+ if (mte) {
797
+ desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s));
798
+ desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
799
+ desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
800
+ desc = FIELD_DP32(desc, MTEDESC, WRITE, a->st);
801
+ desc = FIELD_DP32(desc, MTEDESC, SIZEM1, (1 << a->esz) - 1);
802
+ desc <<= SVE_MTEDESC_SHIFT;
803
+ } else {
804
+ addr = clean_data_tbi(s, addr);
805
+ }
806
+ svl = streaming_vec_reg_size(s);
807
+ desc = simd_desc(svl, svl, desc);
808
+
809
+ fns[a->esz][be][a->v][mte][a->st](cpu_env, t_za, t_pg, addr,
810
+ tcg_constant_i32(desc));
811
+
812
+ tcg_temp_free_ptr(t_za);
813
+ tcg_temp_free_ptr(t_pg);
814
+ tcg_temp_free_i64(addr);
815
+ return true;
816
+}
817
--
968
--
818
2.25.1
969
2.20.1
970
971
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This includes the build rules for the decoder, and the
3
The PWM module is part of NPCM7XX module. Each NPCM7XX module has two
4
new file for translation, but excludes any instructions.
4
identical PWM modules. Each module contains 4 PWM entries. Each PWM has
5
two outputs: frequency and duty_cycle. Both are computed using inputs
6
from software side.
5
7
8
This module does not model detail pulse signals since it is expensive.
9
It also does not model interrupts and watchdogs that are dependant on
10
the detail models. The interfaces for these are left in the module so
11
that anyone in need for these functionalities can implement on their
12
own.
13
14
The user can read the duty cycle and frequency using qom-get command.
15
16
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
19
Message-id: 20210108190945.949196-5-wuhaotsh@google.com
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
22
---
11
target/arm/translate-a64.h | 1 +
23
docs/system/arm/nuvoton.rst | 2 +-
12
target/arm/sme.decode | 20 ++++++++++++++++++++
24
include/hw/arm/npcm7xx.h | 2 +
13
target/arm/translate-a64.c | 7 ++++++-
25
include/hw/misc/npcm7xx_pwm.h | 105 +++++++
14
target/arm/translate-sme.c | 35 +++++++++++++++++++++++++++++++++++
26
hw/arm/npcm7xx.c | 26 +-
15
target/arm/meson.build | 2 ++
27
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++++++++++
16
5 files changed, 64 insertions(+), 1 deletion(-)
28
hw/misc/meson.build | 1 +
17
create mode 100644 target/arm/sme.decode
29
hw/misc/trace-events | 6 +
18
create mode 100644 target/arm/translate-sme.c
30
7 files changed, 689 insertions(+), 3 deletions(-)
31
create mode 100644 include/hw/misc/npcm7xx_pwm.h
32
create mode 100644 hw/misc/npcm7xx_pwm.c
19
33
20
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
34
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
21
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/translate-a64.h
36
--- a/docs/system/arm/nuvoton.rst
23
+++ b/target/arm/translate-a64.h
37
+++ b/docs/system/arm/nuvoton.rst
24
@@ -XXX,XX +XXX,XX @@ static inline int pred_gvec_reg_size(DisasContext *s)
38
@@ -XXX,XX +XXX,XX @@ Supported devices
25
}
39
* USB host (USBH)
26
40
* GPIO controller
27
bool disas_sve(DisasContext *, uint32_t);
41
* Analog to Digital Converter (ADC)
28
+bool disas_sme(DisasContext *, uint32_t);
42
+ * Pulse Width Modulation (PWM)
29
43
30
void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
44
Missing devices
31
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
45
---------------
32
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
46
@@ -XXX,XX +XXX,XX @@ Missing devices
47
* Peripheral SPI controller (PSPI)
48
* SD/MMC host
49
* PECI interface
50
- * Pulse Width Modulation (PWM)
51
* Tachometer
52
* PCI and PCIe root complex and bridges
53
* VDM and MCTP support
54
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/hw/arm/npcm7xx.h
57
+++ b/include/hw/arm/npcm7xx.h
58
@@ -XXX,XX +XXX,XX @@
59
#include "hw/mem/npcm7xx_mc.h"
60
#include "hw/misc/npcm7xx_clk.h"
61
#include "hw/misc/npcm7xx_gcr.h"
62
+#include "hw/misc/npcm7xx_pwm.h"
63
#include "hw/misc/npcm7xx_rng.h"
64
#include "hw/nvram/npcm7xx_otp.h"
65
#include "hw/timer/npcm7xx_timer.h"
66
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
67
NPCM7xxCLKState clk;
68
NPCM7xxTimerCtrlState tim[3];
69
NPCM7xxADCState adc;
70
+ NPCM7xxPWMState pwm[2];
71
NPCM7xxOTPState key_storage;
72
NPCM7xxOTPState fuse_array;
73
NPCM7xxMCState mc;
74
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
33
new file mode 100644
75
new file mode 100644
34
index XXXXXXX..XXXXXXX
76
index XXXXXXX..XXXXXXX
35
--- /dev/null
77
--- /dev/null
36
+++ b/target/arm/sme.decode
78
+++ b/include/hw/misc/npcm7xx_pwm.h
37
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@
38
+# AArch64 SME instruction descriptions
80
+/*
39
+#
81
+ * Nuvoton NPCM7xx PWM Module
40
+# Copyright (c) 2022 Linaro, Ltd
82
+ *
41
+#
83
+ * Copyright 2020 Google LLC
42
+# This library is free software; you can redistribute it and/or
84
+ *
43
+# modify it under the terms of the GNU Lesser General Public
85
+ * This program is free software; you can redistribute it and/or modify it
44
+# License as published by the Free Software Foundation; either
86
+ * under the terms of the GNU General Public License as published by the
45
+# version 2.1 of the License, or (at your option) any later version.
87
+ * Free Software Foundation; either version 2 of the License, or
46
+#
88
+ * (at your option) any later version.
47
+# This library is distributed in the hope that it will be useful,
89
+ *
48
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
49
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50
+# Lesser General Public License for more details.
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51
+#
93
+ * for more details.
52
+# You should have received a copy of the GNU Lesser General Public
94
+ */
53
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
95
+#ifndef NPCM7XX_PWM_H
54
+
96
+#define NPCM7XX_PWM_H
55
+#
97
+
56
+# This file is processed by scripts/decodetree.py
98
+#include "hw/clock.h"
57
+#
99
+#include "hw/sysbus.h"
58
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
100
+#include "hw/irq.h"
101
+
102
+/* Each PWM module holds 4 PWM channels. */
103
+#define NPCM7XX_PWM_PER_MODULE 4
104
+
105
+/*
106
+ * Number of registers in one pwm module. Don't change this without increasing
107
+ * the version_id in vmstate.
108
+ */
109
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
110
+
111
+/*
112
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
113
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
114
+ * value of 100,000 the duty cycle for that PWM is 10%.
115
+ */
116
+#define NPCM7XX_PWM_MAX_DUTY 1000000
117
+
118
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
119
+
120
+/**
121
+ * struct NPCM7xxPWM - The state of a single PWM channel.
122
+ * @module: The PWM module that contains this channel.
123
+ * @irq: GIC interrupt line to fire on expiration if enabled.
124
+ * @running: Whether this PWM channel is generating output.
125
+ * @inverted: Whether this PWM channel is inverted.
126
+ * @index: The index of this PWM channel.
127
+ * @cnr: The counter register.
128
+ * @cmr: The comparator register.
129
+ * @pdr: The data register.
130
+ * @pwdr: The watchdog register.
131
+ * @freq: The frequency of this PWM channel.
132
+ * @duty: The duty cycle of this PWM channel. One unit represents
133
+ * 1/NPCM7XX_MAX_DUTY cycles.
134
+ */
135
+typedef struct NPCM7xxPWM {
136
+ NPCM7xxPWMState *module;
137
+
138
+ qemu_irq irq;
139
+
140
+ bool running;
141
+ bool inverted;
142
+
143
+ uint8_t index;
144
+ uint32_t cnr;
145
+ uint32_t cmr;
146
+ uint32_t pdr;
147
+ uint32_t pwdr;
148
+
149
+ uint32_t freq;
150
+ uint32_t duty;
151
+} NPCM7xxPWM;
152
+
153
+/**
154
+ * struct NPCM7xxPWMState - Pulse Width Modulation device state.
155
+ * @parent: System bus device.
156
+ * @iomem: Memory region through which registers are accessed.
157
+ * @clock: The PWM clock.
158
+ * @pwm: The PWM channels owned by this module.
159
+ * @ppr: The prescaler register.
160
+ * @csr: The clock selector register.
161
+ * @pcr: The control register.
162
+ * @pier: The interrupt enable register.
163
+ * @piir: The interrupt indication register.
164
+ */
165
+struct NPCM7xxPWMState {
166
+ SysBusDevice parent;
167
+
168
+ MemoryRegion iomem;
169
+
170
+ Clock *clock;
171
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
172
+
173
+ uint32_t ppr;
174
+ uint32_t csr;
175
+ uint32_t pcr;
176
+ uint32_t pier;
177
+ uint32_t piir;
178
+};
179
+
180
+#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
181
+#define NPCM7XX_PWM(obj) \
182
+ OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_NPCM7XX_PWM)
183
+
184
+#endif /* NPCM7XX_PWM_H */
185
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
59
index XXXXXXX..XXXXXXX 100644
186
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate-a64.c
187
--- a/hw/arm/npcm7xx.c
61
+++ b/target/arm/translate-a64.c
188
+++ b/hw/arm/npcm7xx.c
62
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
189
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
190
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
191
NPCM7XX_EHCI_IRQ = 61,
192
NPCM7XX_OHCI_IRQ = 62,
193
+ NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
194
+ NPCM7XX_PWM1_IRQ, /* PWM module 1 */
195
NPCM7XX_GPIO0_IRQ = 116,
196
NPCM7XX_GPIO1_IRQ,
197
NPCM7XX_GPIO2_IRQ,
198
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
199
0xb8000000, /* CS3 */
200
};
201
202
+/* Register base address for each PWM Module */
203
+static const hwaddr npcm7xx_pwm_addr[] = {
204
+ 0xf0103000,
205
+ 0xf0104000,
206
+};
207
+
208
static const struct {
209
hwaddr regs_addr;
210
uint32_t unconnected_pins;
211
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
212
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
213
TYPE_NPCM7XX_FIU);
63
}
214
}
64
215
+
65
switch (extract32(insn, 25, 4)) {
216
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
66
- case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
217
+ object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
67
+ case 0x0:
218
+ }
68
+ if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
219
}
69
+ unallocated_encoding(s);
220
70
+ }
221
static void npcm7xx_realize(DeviceState *dev, Error **errp)
71
+ break;
222
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
72
+ case 0x1: case 0x3: /* UNALLOCATED */
223
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
73
unallocated_encoding(s);
224
npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
74
break;
225
75
case 0x2:
226
+ /* PWM Modules. Cannot fail. */
76
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
227
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
228
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
229
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
230
+
231
+ qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
232
+ DEVICE(&s->clk), "apb3-clock"));
233
+ sysbus_realize(sbd, &error_abort);
234
+ sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
235
+ sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
236
+ }
237
+
238
/*
239
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
240
* specified, but this is a programming error.
241
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
242
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
243
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
244
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
245
- create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
246
- create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
247
create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
248
create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
249
create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
250
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
77
new file mode 100644
251
new file mode 100644
78
index XXXXXXX..XXXXXXX
252
index XXXXXXX..XXXXXXX
79
--- /dev/null
253
--- /dev/null
80
+++ b/target/arm/translate-sme.c
254
+++ b/hw/misc/npcm7xx_pwm.c
81
@@ -XXX,XX +XXX,XX @@
255
@@ -XXX,XX +XXX,XX @@
82
+/*
256
+/*
83
+ * AArch64 SME translation
257
+ * Nuvoton NPCM7xx PWM Module
84
+ *
258
+ *
85
+ * Copyright (c) 2022 Linaro, Ltd
259
+ * Copyright 2020 Google LLC
86
+ *
260
+ *
87
+ * This library is free software; you can redistribute it and/or
261
+ * This program is free software; you can redistribute it and/or modify it
88
+ * modify it under the terms of the GNU Lesser General Public
262
+ * under the terms of the GNU General Public License as published by the
89
+ * License as published by the Free Software Foundation; either
263
+ * Free Software Foundation; either version 2 of the License, or
90
+ * version 2.1 of the License, or (at your option) any later version.
264
+ * (at your option) any later version.
91
+ *
265
+ *
92
+ * This library is distributed in the hope that it will be useful,
266
+ * This program is distributed in the hope that it will be useful, but WITHOUT
93
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
267
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
94
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
268
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
95
+ * Lesser General Public License for more details.
269
+ * for more details.
96
+ *
97
+ * You should have received a copy of the GNU Lesser General Public
98
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
99
+ */
270
+ */
100
+
271
+
101
+#include "qemu/osdep.h"
272
+#include "qemu/osdep.h"
102
+#include "cpu.h"
273
+#include "hw/irq.h"
103
+#include "tcg/tcg-op.h"
274
+#include "hw/qdev-clock.h"
104
+#include "tcg/tcg-op-gvec.h"
275
+#include "hw/qdev-properties.h"
105
+#include "tcg/tcg-gvec-desc.h"
276
+#include "hw/misc/npcm7xx_pwm.h"
106
+#include "translate.h"
277
+#include "hw/registerfields.h"
107
+#include "exec/helper-gen.h"
278
+#include "migration/vmstate.h"
108
+#include "translate-a64.h"
279
+#include "qemu/bitops.h"
109
+#include "fpu/softfloat.h"
280
+#include "qemu/error-report.h"
110
+
281
+#include "qemu/log.h"
111
+
282
+#include "qemu/module.h"
112
+/*
283
+#include "qemu/units.h"
113
+ * Include the generated decoder.
284
+#include "trace.h"
114
+ */
285
+
115
+
286
+REG32(NPCM7XX_PWM_PPR, 0x00);
116
+#include "decode-sme.c.inc"
287
+REG32(NPCM7XX_PWM_CSR, 0x04);
117
diff --git a/target/arm/meson.build b/target/arm/meson.build
288
+REG32(NPCM7XX_PWM_PCR, 0x08);
289
+REG32(NPCM7XX_PWM_CNR0, 0x0c);
290
+REG32(NPCM7XX_PWM_CMR0, 0x10);
291
+REG32(NPCM7XX_PWM_PDR0, 0x14);
292
+REG32(NPCM7XX_PWM_CNR1, 0x18);
293
+REG32(NPCM7XX_PWM_CMR1, 0x1c);
294
+REG32(NPCM7XX_PWM_PDR1, 0x20);
295
+REG32(NPCM7XX_PWM_CNR2, 0x24);
296
+REG32(NPCM7XX_PWM_CMR2, 0x28);
297
+REG32(NPCM7XX_PWM_PDR2, 0x2c);
298
+REG32(NPCM7XX_PWM_CNR3, 0x30);
299
+REG32(NPCM7XX_PWM_CMR3, 0x34);
300
+REG32(NPCM7XX_PWM_PDR3, 0x38);
301
+REG32(NPCM7XX_PWM_PIER, 0x3c);
302
+REG32(NPCM7XX_PWM_PIIR, 0x40);
303
+REG32(NPCM7XX_PWM_PWDR0, 0x44);
304
+REG32(NPCM7XX_PWM_PWDR1, 0x48);
305
+REG32(NPCM7XX_PWM_PWDR2, 0x4c);
306
+REG32(NPCM7XX_PWM_PWDR3, 0x50);
307
+
308
+/* Register field definitions. */
309
+#define NPCM7XX_PPR(rv, index) extract32((rv), npcm7xx_ppr_base[index], 8)
310
+#define NPCM7XX_CSR(rv, index) extract32((rv), npcm7xx_csr_base[index], 3)
311
+#define NPCM7XX_CH(rv, index) extract32((rv), npcm7xx_ch_base[index], 4)
312
+#define NPCM7XX_CH_EN BIT(0)
313
+#define NPCM7XX_CH_INV BIT(2)
314
+#define NPCM7XX_CH_MOD BIT(3)
315
+
316
+/* Offset of each PWM channel's prescaler in the PPR register. */
317
+static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
318
+/* Offset of each PWM channel's clock selector in the CSR register. */
319
+static const int npcm7xx_csr_base[] = { 0, 4, 8, 12 };
320
+/* Offset of each PWM channel's control variable in the PCR register. */
321
+static const int npcm7xx_ch_base[] = { 0, 8, 12, 16 };
322
+
323
+static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
324
+{
325
+ uint32_t ppr;
326
+ uint32_t csr;
327
+ uint32_t freq;
328
+
329
+ if (!p->running) {
330
+ return 0;
331
+ }
332
+
333
+ csr = NPCM7XX_CSR(p->module->csr, p->index);
334
+ ppr = NPCM7XX_PPR(p->module->ppr, p->index);
335
+ freq = clock_get_hz(p->module->clock);
336
+ freq /= ppr + 1;
337
+ /* csr can only be 0~4 */
338
+ if (csr > 4) {
339
+ qemu_log_mask(LOG_GUEST_ERROR,
340
+ "%s: invalid csr value %u\n",
341
+ __func__, csr);
342
+ csr = 4;
343
+ }
344
+ /* freq won't be changed if csr == 4. */
345
+ if (csr < 4) {
346
+ freq >>= csr + 1;
347
+ }
348
+
349
+ return freq / (p->cnr + 1);
350
+}
351
+
352
+static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
353
+{
354
+ uint64_t duty;
355
+
356
+ if (p->running) {
357
+ if (p->cnr == 0) {
358
+ duty = 0;
359
+ } else if (p->cmr >= p->cnr) {
360
+ duty = NPCM7XX_PWM_MAX_DUTY;
361
+ } else {
362
+ duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
363
+ }
364
+ } else {
365
+ duty = 0;
366
+ }
367
+
368
+ if (p->inverted) {
369
+ duty = NPCM7XX_PWM_MAX_DUTY - duty;
370
+ }
371
+
372
+ return duty;
373
+}
374
+
375
+static void npcm7xx_pwm_update_freq(NPCM7xxPWM *p)
376
+{
377
+ uint32_t freq = npcm7xx_pwm_calculate_freq(p);
378
+
379
+ if (freq != p->freq) {
380
+ trace_npcm7xx_pwm_update_freq(DEVICE(p->module)->canonical_path,
381
+ p->index, p->freq, freq);
382
+ p->freq = freq;
383
+ }
384
+}
385
+
386
+static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
387
+{
388
+ uint32_t duty = npcm7xx_pwm_calculate_duty(p);
389
+
390
+ if (duty != p->duty) {
391
+ trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
392
+ p->index, p->duty, duty);
393
+ p->duty = duty;
394
+ }
395
+}
396
+
397
+static void npcm7xx_pwm_update_output(NPCM7xxPWM *p)
398
+{
399
+ npcm7xx_pwm_update_freq(p);
400
+ npcm7xx_pwm_update_duty(p);
401
+}
402
+
403
+static void npcm7xx_pwm_write_ppr(NPCM7xxPWMState *s, uint32_t new_ppr)
404
+{
405
+ int i;
406
+ uint32_t old_ppr = s->ppr;
407
+
408
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ppr_base) != NPCM7XX_PWM_PER_MODULE);
409
+ s->ppr = new_ppr;
410
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
411
+ if (NPCM7XX_PPR(old_ppr, i) != NPCM7XX_PPR(new_ppr, i)) {
412
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
413
+ }
414
+ }
415
+}
416
+
417
+static void npcm7xx_pwm_write_csr(NPCM7xxPWMState *s, uint32_t new_csr)
418
+{
419
+ int i;
420
+ uint32_t old_csr = s->csr;
421
+
422
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_csr_base) != NPCM7XX_PWM_PER_MODULE);
423
+ s->csr = new_csr;
424
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
425
+ if (NPCM7XX_CSR(old_csr, i) != NPCM7XX_CSR(new_csr, i)) {
426
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
427
+ }
428
+ }
429
+}
430
+
431
+static void npcm7xx_pwm_write_pcr(NPCM7xxPWMState *s, uint32_t new_pcr)
432
+{
433
+ int i;
434
+ bool inverted;
435
+ uint32_t pcr;
436
+ NPCM7xxPWM *p;
437
+
438
+ s->pcr = new_pcr;
439
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ch_base) != NPCM7XX_PWM_PER_MODULE);
440
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
441
+ p = &s->pwm[i];
442
+ pcr = NPCM7XX_CH(new_pcr, i);
443
+ inverted = pcr & NPCM7XX_CH_INV;
444
+
445
+ /*
446
+ * We only run a PWM channel with toggle mode. Single-shot mode does not
447
+ * generate frequency and duty-cycle values.
448
+ */
449
+ if ((pcr & NPCM7XX_CH_EN) && (pcr & NPCM7XX_CH_MOD)) {
450
+ if (p->running) {
451
+ /* Re-run this PWM channel if inverted changed. */
452
+ if (p->inverted ^ inverted) {
453
+ p->inverted = inverted;
454
+ npcm7xx_pwm_update_duty(p);
455
+ }
456
+ } else {
457
+ /* Run this PWM channel. */
458
+ p->running = true;
459
+ p->inverted = inverted;
460
+ npcm7xx_pwm_update_output(p);
461
+ }
462
+ } else {
463
+ /* Clear this PWM channel. */
464
+ p->running = false;
465
+ p->inverted = inverted;
466
+ npcm7xx_pwm_update_output(p);
467
+ }
468
+ }
469
+
470
+}
471
+
472
+static hwaddr npcm7xx_cnr_index(hwaddr offset)
473
+{
474
+ switch (offset) {
475
+ case A_NPCM7XX_PWM_CNR0:
476
+ return 0;
477
+ case A_NPCM7XX_PWM_CNR1:
478
+ return 1;
479
+ case A_NPCM7XX_PWM_CNR2:
480
+ return 2;
481
+ case A_NPCM7XX_PWM_CNR3:
482
+ return 3;
483
+ default:
484
+ g_assert_not_reached();
485
+ }
486
+}
487
+
488
+static hwaddr npcm7xx_cmr_index(hwaddr offset)
489
+{
490
+ switch (offset) {
491
+ case A_NPCM7XX_PWM_CMR0:
492
+ return 0;
493
+ case A_NPCM7XX_PWM_CMR1:
494
+ return 1;
495
+ case A_NPCM7XX_PWM_CMR2:
496
+ return 2;
497
+ case A_NPCM7XX_PWM_CMR3:
498
+ return 3;
499
+ default:
500
+ g_assert_not_reached();
501
+ }
502
+}
503
+
504
+static hwaddr npcm7xx_pdr_index(hwaddr offset)
505
+{
506
+ switch (offset) {
507
+ case A_NPCM7XX_PWM_PDR0:
508
+ return 0;
509
+ case A_NPCM7XX_PWM_PDR1:
510
+ return 1;
511
+ case A_NPCM7XX_PWM_PDR2:
512
+ return 2;
513
+ case A_NPCM7XX_PWM_PDR3:
514
+ return 3;
515
+ default:
516
+ g_assert_not_reached();
517
+ }
518
+}
519
+
520
+static hwaddr npcm7xx_pwdr_index(hwaddr offset)
521
+{
522
+ switch (offset) {
523
+ case A_NPCM7XX_PWM_PWDR0:
524
+ return 0;
525
+ case A_NPCM7XX_PWM_PWDR1:
526
+ return 1;
527
+ case A_NPCM7XX_PWM_PWDR2:
528
+ return 2;
529
+ case A_NPCM7XX_PWM_PWDR3:
530
+ return 3;
531
+ default:
532
+ g_assert_not_reached();
533
+ }
534
+}
535
+
536
+static uint64_t npcm7xx_pwm_read(void *opaque, hwaddr offset, unsigned size)
537
+{
538
+ NPCM7xxPWMState *s = opaque;
539
+ uint64_t value = 0;
540
+
541
+ switch (offset) {
542
+ case A_NPCM7XX_PWM_CNR0:
543
+ case A_NPCM7XX_PWM_CNR1:
544
+ case A_NPCM7XX_PWM_CNR2:
545
+ case A_NPCM7XX_PWM_CNR3:
546
+ value = s->pwm[npcm7xx_cnr_index(offset)].cnr;
547
+ break;
548
+
549
+ case A_NPCM7XX_PWM_CMR0:
550
+ case A_NPCM7XX_PWM_CMR1:
551
+ case A_NPCM7XX_PWM_CMR2:
552
+ case A_NPCM7XX_PWM_CMR3:
553
+ value = s->pwm[npcm7xx_cmr_index(offset)].cmr;
554
+ break;
555
+
556
+ case A_NPCM7XX_PWM_PDR0:
557
+ case A_NPCM7XX_PWM_PDR1:
558
+ case A_NPCM7XX_PWM_PDR2:
559
+ case A_NPCM7XX_PWM_PDR3:
560
+ value = s->pwm[npcm7xx_pdr_index(offset)].pdr;
561
+ break;
562
+
563
+ case A_NPCM7XX_PWM_PWDR0:
564
+ case A_NPCM7XX_PWM_PWDR1:
565
+ case A_NPCM7XX_PWM_PWDR2:
566
+ case A_NPCM7XX_PWM_PWDR3:
567
+ value = s->pwm[npcm7xx_pwdr_index(offset)].pwdr;
568
+ break;
569
+
570
+ case A_NPCM7XX_PWM_PPR:
571
+ value = s->ppr;
572
+ break;
573
+
574
+ case A_NPCM7XX_PWM_CSR:
575
+ value = s->csr;
576
+ break;
577
+
578
+ case A_NPCM7XX_PWM_PCR:
579
+ value = s->pcr;
580
+ break;
581
+
582
+ case A_NPCM7XX_PWM_PIER:
583
+ value = s->pier;
584
+ break;
585
+
586
+ case A_NPCM7XX_PWM_PIIR:
587
+ value = s->piir;
588
+ break;
589
+
590
+ default:
591
+ qemu_log_mask(LOG_GUEST_ERROR,
592
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
593
+ __func__, offset);
594
+ break;
595
+ }
596
+
597
+ trace_npcm7xx_pwm_read(DEVICE(s)->canonical_path, offset, value);
598
+ return value;
599
+}
600
+
601
+static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
602
+ uint64_t v, unsigned size)
603
+{
604
+ NPCM7xxPWMState *s = opaque;
605
+ NPCM7xxPWM *p;
606
+ uint32_t value = v;
607
+
608
+ trace_npcm7xx_pwm_write(DEVICE(s)->canonical_path, offset, value);
609
+ switch (offset) {
610
+ case A_NPCM7XX_PWM_CNR0:
611
+ case A_NPCM7XX_PWM_CNR1:
612
+ case A_NPCM7XX_PWM_CNR2:
613
+ case A_NPCM7XX_PWM_CNR3:
614
+ p = &s->pwm[npcm7xx_cnr_index(offset)];
615
+ p->cnr = value;
616
+ npcm7xx_pwm_update_output(p);
617
+ break;
618
+
619
+ case A_NPCM7XX_PWM_CMR0:
620
+ case A_NPCM7XX_PWM_CMR1:
621
+ case A_NPCM7XX_PWM_CMR2:
622
+ case A_NPCM7XX_PWM_CMR3:
623
+ p = &s->pwm[npcm7xx_cmr_index(offset)];
624
+ p->cmr = value;
625
+ npcm7xx_pwm_update_output(p);
626
+ break;
627
+
628
+ case A_NPCM7XX_PWM_PDR0:
629
+ case A_NPCM7XX_PWM_PDR1:
630
+ case A_NPCM7XX_PWM_PDR2:
631
+ case A_NPCM7XX_PWM_PDR3:
632
+ qemu_log_mask(LOG_GUEST_ERROR,
633
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
634
+ __func__, offset);
635
+ break;
636
+
637
+ case A_NPCM7XX_PWM_PWDR0:
638
+ case A_NPCM7XX_PWM_PWDR1:
639
+ case A_NPCM7XX_PWM_PWDR2:
640
+ case A_NPCM7XX_PWM_PWDR3:
641
+ qemu_log_mask(LOG_UNIMP,
642
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
643
+ __func__, offset);
644
+ break;
645
+
646
+ case A_NPCM7XX_PWM_PPR:
647
+ npcm7xx_pwm_write_ppr(s, value);
648
+ break;
649
+
650
+ case A_NPCM7XX_PWM_CSR:
651
+ npcm7xx_pwm_write_csr(s, value);
652
+ break;
653
+
654
+ case A_NPCM7XX_PWM_PCR:
655
+ npcm7xx_pwm_write_pcr(s, value);
656
+ break;
657
+
658
+ case A_NPCM7XX_PWM_PIER:
659
+ qemu_log_mask(LOG_UNIMP,
660
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
661
+ __func__, offset);
662
+ break;
663
+
664
+ case A_NPCM7XX_PWM_PIIR:
665
+ qemu_log_mask(LOG_UNIMP,
666
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
667
+ __func__, offset);
668
+ break;
669
+
670
+ default:
671
+ qemu_log_mask(LOG_GUEST_ERROR,
672
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
673
+ __func__, offset);
674
+ break;
675
+ }
676
+}
677
+
678
+static const struct MemoryRegionOps npcm7xx_pwm_ops = {
679
+ .read = npcm7xx_pwm_read,
680
+ .write = npcm7xx_pwm_write,
681
+ .endianness = DEVICE_LITTLE_ENDIAN,
682
+ .valid = {
683
+ .min_access_size = 4,
684
+ .max_access_size = 4,
685
+ .unaligned = false,
686
+ },
687
+};
688
+
689
+static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
690
+{
691
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
692
+ int i;
693
+
694
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
695
+ NPCM7xxPWM *p = &s->pwm[i];
696
+
697
+ p->cnr = 0x00000000;
698
+ p->cmr = 0x00000000;
699
+ p->pdr = 0x00000000;
700
+ p->pwdr = 0x00000000;
701
+ }
702
+
703
+ s->ppr = 0x00000000;
704
+ s->csr = 0x00000000;
705
+ s->pcr = 0x00000000;
706
+ s->pier = 0x00000000;
707
+ s->piir = 0x00000000;
708
+}
709
+
710
+static void npcm7xx_pwm_hold_reset(Object *obj)
711
+{
712
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
713
+ int i;
714
+
715
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
716
+ qemu_irq_lower(s->pwm[i].irq);
717
+ }
718
+}
719
+
720
+static void npcm7xx_pwm_init(Object *obj)
721
+{
722
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
723
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
724
+ int i;
725
+
726
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
727
+ NPCM7xxPWM *p = &s->pwm[i];
728
+ p->module = s;
729
+ p->index = i;
730
+ sysbus_init_irq(sbd, &p->irq);
731
+ }
732
+
733
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
734
+ TYPE_NPCM7XX_PWM, 4 * KiB);
735
+ sysbus_init_mmio(sbd, &s->iomem);
736
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
737
+
738
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
739
+ object_property_add_uint32_ptr(obj, "freq[*]",
740
+ &s->pwm[i].freq, OBJ_PROP_FLAG_READ);
741
+ object_property_add_uint32_ptr(obj, "duty[*]",
742
+ &s->pwm[i].duty, OBJ_PROP_FLAG_READ);
743
+ }
744
+}
745
+
746
+static const VMStateDescription vmstate_npcm7xx_pwm = {
747
+ .name = "npcm7xx-pwm",
748
+ .version_id = 0,
749
+ .minimum_version_id = 0,
750
+ .fields = (VMStateField[]) {
751
+ VMSTATE_BOOL(running, NPCM7xxPWM),
752
+ VMSTATE_BOOL(inverted, NPCM7xxPWM),
753
+ VMSTATE_UINT8(index, NPCM7xxPWM),
754
+ VMSTATE_UINT32(cnr, NPCM7xxPWM),
755
+ VMSTATE_UINT32(cmr, NPCM7xxPWM),
756
+ VMSTATE_UINT32(pdr, NPCM7xxPWM),
757
+ VMSTATE_UINT32(pwdr, NPCM7xxPWM),
758
+ VMSTATE_UINT32(freq, NPCM7xxPWM),
759
+ VMSTATE_UINT32(duty, NPCM7xxPWM),
760
+ VMSTATE_END_OF_LIST(),
761
+ },
762
+};
763
+
764
+static const VMStateDescription vmstate_npcm7xx_pwm_module = {
765
+ .name = "npcm7xx-pwm-module",
766
+ .version_id = 0,
767
+ .minimum_version_id = 0,
768
+ .fields = (VMStateField[]) {
769
+ VMSTATE_CLOCK(clock, NPCM7xxPWMState),
770
+ VMSTATE_STRUCT_ARRAY(pwm, NPCM7xxPWMState,
771
+ NPCM7XX_PWM_PER_MODULE, 0, vmstate_npcm7xx_pwm,
772
+ NPCM7xxPWM),
773
+ VMSTATE_UINT32(ppr, NPCM7xxPWMState),
774
+ VMSTATE_UINT32(csr, NPCM7xxPWMState),
775
+ VMSTATE_UINT32(pcr, NPCM7xxPWMState),
776
+ VMSTATE_UINT32(pier, NPCM7xxPWMState),
777
+ VMSTATE_UINT32(piir, NPCM7xxPWMState),
778
+ VMSTATE_END_OF_LIST(),
779
+ },
780
+};
781
+
782
+static void npcm7xx_pwm_class_init(ObjectClass *klass, void *data)
783
+{
784
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
785
+ DeviceClass *dc = DEVICE_CLASS(klass);
786
+
787
+ dc->desc = "NPCM7xx PWM Controller";
788
+ dc->vmsd = &vmstate_npcm7xx_pwm_module;
789
+ rc->phases.enter = npcm7xx_pwm_enter_reset;
790
+ rc->phases.hold = npcm7xx_pwm_hold_reset;
791
+}
792
+
793
+static const TypeInfo npcm7xx_pwm_info = {
794
+ .name = TYPE_NPCM7XX_PWM,
795
+ .parent = TYPE_SYS_BUS_DEVICE,
796
+ .instance_size = sizeof(NPCM7xxPWMState),
797
+ .class_init = npcm7xx_pwm_class_init,
798
+ .instance_init = npcm7xx_pwm_init,
799
+};
800
+
801
+static void npcm7xx_pwm_register_type(void)
802
+{
803
+ type_register_static(&npcm7xx_pwm_info);
804
+}
805
+type_init(npcm7xx_pwm_register_type);
806
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
118
index XXXXXXX..XXXXXXX 100644
807
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/meson.build
808
--- a/hw/misc/meson.build
120
+++ b/target/arm/meson.build
809
+++ b/hw/misc/meson.build
121
@@ -XXX,XX +XXX,XX @@
810
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
122
gen = [
811
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
123
decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
812
'npcm7xx_clk.c',
124
+ decodetree.process('sme.decode', extra_args: '--decode=disas_sme'),
813
'npcm7xx_gcr.c',
125
decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
814
+ 'npcm7xx_pwm.c',
126
decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
815
'npcm7xx_rng.c',
127
decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
128
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
129
'sme_helper.c',
130
'translate-a64.c',
131
'translate-sve.c',
132
+ 'translate-sme.c',
133
))
816
))
134
817
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
135
arm_softmmu_ss = ss.source_set()
818
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
819
index XXXXXXX..XXXXXXX 100644
820
--- a/hw/misc/trace-events
821
+++ b/hw/misc/trace-events
822
@@ -XXX,XX +XXX,XX @@ npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
823
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
824
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
825
826
+# npcm7xx_pwm.c
827
+npcm7xx_pwm_read(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
828
+npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
829
+npcm7xx_pwm_update_freq(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Freq: old_freq: %u, new_freq: %u"
830
+npcm7xx_pwm_update_duty(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Duty: old_duty: %u, new_duty: %u"
831
+
832
# stm32f4xx_syscfg.c
833
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
834
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
136
--
835
--
137
2.25.1
836
2.20.1
837
838
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark ADR as a non-streaming instruction, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Removing entries from sme-fa64.decode is an easy way to see
7
what remains to be done.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220708151540.18136-5-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/translate.h | 7 +++++++
15
target/arm/sme-fa64.decode | 1 -
16
target/arm/translate-sve.c | 8 ++++----
17
3 files changed, 11 insertions(+), 5 deletions(-)
18
19
diff --git a/target/arm/translate.h b/target/arm/translate.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate.h
22
+++ b/target/arm/translate.h
23
@@ -XXX,XX +XXX,XX @@ uint64_t asimd_imm_const(uint32_t imm, int cmode, int op);
24
static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
25
{ return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); }
26
27
+#define TRANS_FEAT_NONSTREAMING(NAME, FEAT, FUNC, ...) \
28
+ static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
29
+ { \
30
+ s->is_nonstreaming = true; \
31
+ return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); \
32
+ }
33
+
34
#endif /* TARGET_ARM_TRANSLATE_H */
35
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/sme-fa64.decode
38
+++ b/target/arm/sme-fa64.decode
39
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
40
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
41
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
42
43
-FAIL 0000 0100 --1- ---- 1010 ---- ---- ---- # ADR
44
FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
45
FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
46
FAIL 0010 0101 --01 100- 1111 000- ---0 ---- # RDFFR, RDFFRS
47
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-sve.c
50
+++ b/target/arm/translate-sve.c
51
@@ -XXX,XX +XXX,XX @@ static bool do_adr(DisasContext *s, arg_rrri *a, gen_helper_gvec_3 *fn)
52
return gen_gvec_ool_zzz(s, fn, a->rd, a->rn, a->rm, a->imm);
53
}
54
55
-TRANS_FEAT(ADR_p32, aa64_sve, do_adr, a, gen_helper_sve_adr_p32)
56
-TRANS_FEAT(ADR_p64, aa64_sve, do_adr, a, gen_helper_sve_adr_p64)
57
-TRANS_FEAT(ADR_s32, aa64_sve, do_adr, a, gen_helper_sve_adr_s32)
58
-TRANS_FEAT(ADR_u32, aa64_sve, do_adr, a, gen_helper_sve_adr_u32)
59
+TRANS_FEAT_NONSTREAMING(ADR_p32, aa64_sve, do_adr, a, gen_helper_sve_adr_p32)
60
+TRANS_FEAT_NONSTREAMING(ADR_p64, aa64_sve, do_adr, a, gen_helper_sve_adr_p64)
61
+TRANS_FEAT_NONSTREAMING(ADR_s32, aa64_sve, do_adr, a, gen_helper_sve_adr_s32)
62
+TRANS_FEAT_NONSTREAMING(ADR_u32, aa64_sve, do_adr, a, gen_helper_sve_adr_u32)
63
64
/*
65
*** SVE Integer Misc - Unpredicated Group
66
--
67
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-6-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 2 --
12
target/arm/translate-sve.c | 9 ++++++---
13
2 files changed, 6 insertions(+), 5 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
21
FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
22
FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
23
-FAIL 0010 0101 --01 100- 1111 000- ---0 ---- # RDFFR, RDFFRS
24
-FAIL 0010 0101 --10 1--- 1001 ---- ---- ---- # WRFFR, SETFFR
25
FAIL 0100 0101 --0- ---- 1011 ---- ---- ---- # BDEP, BEXT, BGRP
26
FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
27
FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
28
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-sve.c
31
+++ b/target/arm/translate-sve.c
32
@@ -XXX,XX +XXX,XX @@ static bool do_predset(DisasContext *s, int esz, int rd, int pat, bool setflag)
33
TRANS_FEAT(PTRUE, aa64_sve, do_predset, a->esz, a->rd, a->pat, a->s)
34
35
/* Note pat == 31 is #all, to set all elements. */
36
-TRANS_FEAT(SETFFR, aa64_sve, do_predset, 0, FFR_PRED_NUM, 31, false)
37
+TRANS_FEAT_NONSTREAMING(SETFFR, aa64_sve,
38
+ do_predset, 0, FFR_PRED_NUM, 31, false)
39
40
/* Note pat == 32 is #unimp, to set no elements. */
41
TRANS_FEAT(PFALSE, aa64_sve, do_predset, 0, a->rd, 32, false)
42
@@ -XXX,XX +XXX,XX @@ static bool trans_RDFFR_p(DisasContext *s, arg_RDFFR_p *a)
43
.rd = a->rd, .pg = a->pg, .s = a->s,
44
.rn = FFR_PRED_NUM, .rm = FFR_PRED_NUM,
45
};
46
+
47
+ s->is_nonstreaming = true;
48
return trans_AND_pppp(s, &alt_a);
49
}
50
51
-TRANS_FEAT(RDFFR, aa64_sve, do_mov_p, a->rd, FFR_PRED_NUM)
52
-TRANS_FEAT(WRFFR, aa64_sve, do_mov_p, FFR_PRED_NUM, a->rn)
53
+TRANS_FEAT_NONSTREAMING(RDFFR, aa64_sve, do_mov_p, a->rd, FFR_PRED_NUM)
54
+TRANS_FEAT_NONSTREAMING(WRFFR, aa64_sve, do_mov_p, FFR_PRED_NUM, a->rn)
55
56
static bool do_pfirst_pnext(DisasContext *s, arg_rr_esz *a,
57
void (*gen_fn)(TCGv_i32, TCGv_ptr,
58
--
59
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-7-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 3 ---
12
target/arm/translate-sve.c | 22 ++++++++++++----------
13
2 files changed, 12 insertions(+), 13 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
24
-FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
25
-FAIL 0100 0101 --0- ---- 1011 ---- ---- ---- # BDEP, BEXT, BGRP
26
FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
27
FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
28
FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
29
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate-sve.c
32
+++ b/target/arm/translate-sve.c
33
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_2 * const fexpa_fns[4] = {
34
NULL, gen_helper_sve_fexpa_h,
35
gen_helper_sve_fexpa_s, gen_helper_sve_fexpa_d,
36
};
37
-TRANS_FEAT(FEXPA, aa64_sve, gen_gvec_ool_zz,
38
- fexpa_fns[a->esz], a->rd, a->rn, 0)
39
+TRANS_FEAT_NONSTREAMING(FEXPA, aa64_sve, gen_gvec_ool_zz,
40
+ fexpa_fns[a->esz], a->rd, a->rn, 0)
41
42
static gen_helper_gvec_3 * const ftssel_fns[4] = {
43
NULL, gen_helper_sve_ftssel_h,
44
gen_helper_sve_ftssel_s, gen_helper_sve_ftssel_d,
45
};
46
-TRANS_FEAT(FTSSEL, aa64_sve, gen_gvec_ool_arg_zzz, ftssel_fns[a->esz], a, 0)
47
+TRANS_FEAT_NONSTREAMING(FTSSEL, aa64_sve, gen_gvec_ool_arg_zzz,
48
+ ftssel_fns[a->esz], a, 0)
49
50
/*
51
*** SVE Predicate Logical Operations Group
52
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(TRN2_q, aa64_sve_f64mm, gen_gvec_ool_arg_zzz,
53
static gen_helper_gvec_3 * const compact_fns[4] = {
54
NULL, NULL, gen_helper_sve_compact_s, gen_helper_sve_compact_d
55
};
56
-TRANS_FEAT(COMPACT, aa64_sve, gen_gvec_ool_arg_zpz, compact_fns[a->esz], a, 0)
57
+TRANS_FEAT_NONSTREAMING(COMPACT, aa64_sve, gen_gvec_ool_arg_zpz,
58
+ compact_fns[a->esz], a, 0)
59
60
/* Call the helper that computes the ARM LastActiveElement pseudocode
61
* function, scaled by the element size. This includes the not found
62
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const bext_fns[4] = {
63
gen_helper_sve2_bext_b, gen_helper_sve2_bext_h,
64
gen_helper_sve2_bext_s, gen_helper_sve2_bext_d,
65
};
66
-TRANS_FEAT(BEXT, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
67
- bext_fns[a->esz], a, 0)
68
+TRANS_FEAT_NONSTREAMING(BEXT, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
69
+ bext_fns[a->esz], a, 0)
70
71
static gen_helper_gvec_3 * const bdep_fns[4] = {
72
gen_helper_sve2_bdep_b, gen_helper_sve2_bdep_h,
73
gen_helper_sve2_bdep_s, gen_helper_sve2_bdep_d,
74
};
75
-TRANS_FEAT(BDEP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
76
- bdep_fns[a->esz], a, 0)
77
+TRANS_FEAT_NONSTREAMING(BDEP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
78
+ bdep_fns[a->esz], a, 0)
79
80
static gen_helper_gvec_3 * const bgrp_fns[4] = {
81
gen_helper_sve2_bgrp_b, gen_helper_sve2_bgrp_h,
82
gen_helper_sve2_bgrp_s, gen_helper_sve2_bgrp_d,
83
};
84
-TRANS_FEAT(BGRP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
85
- bgrp_fns[a->esz], a, 0)
86
+TRANS_FEAT_NONSTREAMING(BGRP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
87
+ bgrp_fns[a->esz], a, 0)
88
89
static gen_helper_gvec_3 * const cadd_fns[4] = {
90
gen_helper_sve2_cadd_b, gen_helper_sve2_cadd_h,
91
--
92
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-8-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 2 --
12
target/arm/translate-sve.c | 24 +++++++++++++++---------
13
2 files changed, 15 insertions(+), 11 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
24
-FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
25
FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
26
FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
27
FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
28
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-sve.c
31
+++ b/target/arm/translate-sve.c
32
@@ -XXX,XX +XXX,XX @@ static bool do_trans_pmull(DisasContext *s, arg_rrr_esz *a, bool sel)
33
gen_helper_gvec_pmull_q, gen_helper_sve2_pmull_h,
34
NULL, gen_helper_sve2_pmull_d,
35
};
36
- if (a->esz == 0
37
- ? !dc_isar_feature(aa64_sve2_pmull128, s)
38
- : !dc_isar_feature(aa64_sve, s)) {
39
+
40
+ if (a->esz == 0) {
41
+ if (!dc_isar_feature(aa64_sve2_pmull128, s)) {
42
+ return false;
43
+ }
44
+ s->is_nonstreaming = true;
45
+ } else if (!dc_isar_feature(aa64_sve, s)) {
46
return false;
47
}
48
return gen_gvec_ool_arg_zzz(s, fns[a->esz], a, sel);
49
@@ -XXX,XX +XXX,XX @@ DO_ZPZZ_FP(FMINP, aa64_sve2, sve2_fminp_zpzz)
50
* SVE Integer Multiply-Add (unpredicated)
51
*/
52
53
-TRANS_FEAT(FMMLA_s, aa64_sve_f32mm, gen_gvec_fpst_zzzz, gen_helper_fmmla_s,
54
- a->rd, a->rn, a->rm, a->ra, 0, FPST_FPCR)
55
-TRANS_FEAT(FMMLA_d, aa64_sve_f64mm, gen_gvec_fpst_zzzz, gen_helper_fmmla_d,
56
- a->rd, a->rn, a->rm, a->ra, 0, FPST_FPCR)
57
+TRANS_FEAT_NONSTREAMING(FMMLA_s, aa64_sve_f32mm, gen_gvec_fpst_zzzz,
58
+ gen_helper_fmmla_s, a->rd, a->rn, a->rm, a->ra,
59
+ 0, FPST_FPCR)
60
+TRANS_FEAT_NONSTREAMING(FMMLA_d, aa64_sve_f64mm, gen_gvec_fpst_zzzz,
61
+ gen_helper_fmmla_d, a->rd, a->rn, a->rm, a->ra,
62
+ 0, FPST_FPCR)
63
64
static gen_helper_gvec_4 * const sqdmlal_zzzw_fns[] = {
65
NULL, gen_helper_sve2_sqdmlal_zzzw_h,
66
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(BFDOT_zzzz, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
67
TRANS_FEAT(BFDOT_zzxz, aa64_sve_bf16, gen_gvec_ool_arg_zzxz,
68
gen_helper_gvec_bfdot_idx, a)
69
70
-TRANS_FEAT(BFMMLA, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
71
- gen_helper_gvec_bfmmla, a, 0)
72
+TRANS_FEAT_NONSTREAMING(BFMMLA, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
73
+ gen_helper_gvec_bfmmla, a, 0)
74
75
static bool do_BFMLAL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sel)
76
{
77
--
78
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-9-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 3 ---
12
target/arm/translate-sve.c | 15 +++++++++++----
13
2 files changed, 11 insertions(+), 7 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
24
-FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
25
-FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
26
FAIL 0100 0101 --0- ---- 1001 10-- ---- ---- # SMMLA, UMMLA, USMMLA
27
FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
28
FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
29
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate-sve.c
32
+++ b/target/arm/translate-sve.c
33
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const ftmad_fns[4] = {
34
NULL, gen_helper_sve_ftmad_h,
35
gen_helper_sve_ftmad_s, gen_helper_sve_ftmad_d,
36
};
37
-TRANS_FEAT(FTMAD, aa64_sve, gen_gvec_fpst_zzz,
38
- ftmad_fns[a->esz], a->rd, a->rn, a->rm, a->imm,
39
- a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR)
40
+TRANS_FEAT_NONSTREAMING(FTMAD, aa64_sve, gen_gvec_fpst_zzz,
41
+ ftmad_fns[a->esz], a->rd, a->rn, a->rm, a->imm,
42
+ a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR)
43
44
/*
45
*** SVE Floating Point Accumulating Reduction Group
46
@@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a)
47
if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) {
48
return false;
49
}
50
+ s->is_nonstreaming = true;
51
if (!sve_access_check(s)) {
52
return true;
53
}
54
@@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a)
55
DO_FP3(FADD_zzz, fadd)
56
DO_FP3(FSUB_zzz, fsub)
57
DO_FP3(FMUL_zzz, fmul)
58
-DO_FP3(FTSMUL, ftsmul)
59
DO_FP3(FRECPS, recps)
60
DO_FP3(FRSQRTS, rsqrts)
61
62
#undef DO_FP3
63
64
+static gen_helper_gvec_3_ptr * const ftsmul_fns[4] = {
65
+ NULL, gen_helper_gvec_ftsmul_h,
66
+ gen_helper_gvec_ftsmul_s, gen_helper_gvec_ftsmul_d
67
+};
68
+TRANS_FEAT_NONSTREAMING(FTSMUL, aa64_sve, gen_gvec_fpst_arg_zzz,
69
+ ftsmul_fns[a->esz], a, 0)
70
+
71
/*
72
*** SVE Floating Point Arithmetic - Predicated Group
73
*/
74
--
75
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-10-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 1 -
12
target/arm/translate-sve.c | 12 ++++++------
13
2 files changed, 6 insertions(+), 7 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0100 0101 --0- ---- 1001 10-- ---- ---- # SMMLA, UMMLA, USMMLA
24
FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
25
FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
26
FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
31
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FMLALT_zzxw, aa64_sve2, do_FMLAL_zzxw, a, false, true)
32
TRANS_FEAT(FMLSLB_zzxw, aa64_sve2, do_FMLAL_zzxw, a, true, false)
33
TRANS_FEAT(FMLSLT_zzxw, aa64_sve2, do_FMLAL_zzxw, a, true, true)
34
35
-TRANS_FEAT(SMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
36
- gen_helper_gvec_smmla_b, a, 0)
37
-TRANS_FEAT(USMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
38
- gen_helper_gvec_usmmla_b, a, 0)
39
-TRANS_FEAT(UMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
40
- gen_helper_gvec_ummla_b, a, 0)
41
+TRANS_FEAT_NONSTREAMING(SMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
42
+ gen_helper_gvec_smmla_b, a, 0)
43
+TRANS_FEAT_NONSTREAMING(USMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
44
+ gen_helper_gvec_usmmla_b, a, 0)
45
+TRANS_FEAT_NONSTREAMING(UMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
46
+ gen_helper_gvec_ummla_b, a, 0)
47
48
TRANS_FEAT(BFDOT_zzzz, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
49
gen_helper_gvec_bfdot, a, 0)
50
--
51
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-11-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 1 -
12
target/arm/translate-sve.c | 35 ++++++++++++++++++-----------------
13
2 files changed, 18 insertions(+), 18 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
24
FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
25
FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
26
FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
31
@@ -XXX,XX +XXX,XX @@ DO_SVE2_ZZZ_NARROW(RSUBHNT, rsubhnt)
32
static gen_helper_gvec_flags_4 * const match_fns[4] = {
33
gen_helper_sve2_match_ppzz_b, gen_helper_sve2_match_ppzz_h, NULL, NULL
34
};
35
-TRANS_FEAT(MATCH, aa64_sve2, do_ppzz_flags, a, match_fns[a->esz])
36
+TRANS_FEAT_NONSTREAMING(MATCH, aa64_sve2, do_ppzz_flags, a, match_fns[a->esz])
37
38
static gen_helper_gvec_flags_4 * const nmatch_fns[4] = {
39
gen_helper_sve2_nmatch_ppzz_b, gen_helper_sve2_nmatch_ppzz_h, NULL, NULL
40
};
41
-TRANS_FEAT(NMATCH, aa64_sve2, do_ppzz_flags, a, nmatch_fns[a->esz])
42
+TRANS_FEAT_NONSTREAMING(NMATCH, aa64_sve2, do_ppzz_flags, a, nmatch_fns[a->esz])
43
44
static gen_helper_gvec_4 * const histcnt_fns[4] = {
45
NULL, NULL, gen_helper_sve2_histcnt_s, gen_helper_sve2_histcnt_d
46
};
47
-TRANS_FEAT(HISTCNT, aa64_sve2, gen_gvec_ool_arg_zpzz,
48
- histcnt_fns[a->esz], a, 0)
49
+TRANS_FEAT_NONSTREAMING(HISTCNT, aa64_sve2, gen_gvec_ool_arg_zpzz,
50
+ histcnt_fns[a->esz], a, 0)
51
52
-TRANS_FEAT(HISTSEG, aa64_sve2, gen_gvec_ool_arg_zzz,
53
- a->esz == 0 ? gen_helper_sve2_histseg : NULL, a, 0)
54
+TRANS_FEAT_NONSTREAMING(HISTSEG, aa64_sve2, gen_gvec_ool_arg_zzz,
55
+ a->esz == 0 ? gen_helper_sve2_histseg : NULL, a, 0)
56
57
DO_ZPZZ_FP(FADDP, aa64_sve2, sve2_faddp_zpzz)
58
DO_ZPZZ_FP(FMAXNMP, aa64_sve2, sve2_fmaxnmp_zpzz)
59
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(SQRDCMLAH_zzzz, aa64_sve2, gen_gvec_ool_zzzz,
60
TRANS_FEAT(USDOT_zzzz, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
61
a->esz == 2 ? gen_helper_gvec_usdot_b : NULL, a, 0)
62
63
-TRANS_FEAT(AESMC, aa64_sve2_aes, gen_gvec_ool_zz,
64
- gen_helper_crypto_aesmc, a->rd, a->rd, a->decrypt)
65
+TRANS_FEAT_NONSTREAMING(AESMC, aa64_sve2_aes, gen_gvec_ool_zz,
66
+ gen_helper_crypto_aesmc, a->rd, a->rd, a->decrypt)
67
68
-TRANS_FEAT(AESE, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
69
- gen_helper_crypto_aese, a, false)
70
-TRANS_FEAT(AESD, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
71
- gen_helper_crypto_aese, a, true)
72
+TRANS_FEAT_NONSTREAMING(AESE, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
73
+ gen_helper_crypto_aese, a, false)
74
+TRANS_FEAT_NONSTREAMING(AESD, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
75
+ gen_helper_crypto_aese, a, true)
76
77
-TRANS_FEAT(SM4E, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
78
- gen_helper_crypto_sm4e, a, 0)
79
-TRANS_FEAT(SM4EKEY, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
80
- gen_helper_crypto_sm4ekey, a, 0)
81
+TRANS_FEAT_NONSTREAMING(SM4E, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
82
+ gen_helper_crypto_sm4e, a, 0)
83
+TRANS_FEAT_NONSTREAMING(SM4EKEY, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
84
+ gen_helper_crypto_sm4ekey, a, 0)
85
86
-TRANS_FEAT(RAX1, aa64_sve2_sha3, gen_gvec_fn_arg_zzz, gen_gvec_rax1, a)
87
+TRANS_FEAT_NONSTREAMING(RAX1, aa64_sve2_sha3, gen_gvec_fn_arg_zzz,
88
+ gen_gvec_rax1, a)
89
90
TRANS_FEAT(FCVTNT_sh, aa64_sve2, gen_gvec_fpst_arg_zpz,
91
gen_helper_sve2_fcvtnt_sh, a, 0, FPST_FPCR)
92
--
93
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-12-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 9 ---------
12
target/arm/translate-sve.c | 6 ++++++
13
2 files changed, 6 insertions(+), 9 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
24
FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
25
FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
26
-FAIL 1000 010- -01- ---- 1--- ---- ---- ---- # SVE 32-bit gather load (vector+imm)
27
-FAIL 1000 0100 0-0- ---- 0--- ---- ---- ---- # SVE 32-bit gather load byte (scalar+vector)
28
-FAIL 1000 0100 1--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load half (scalar+vector)
29
-FAIL 1000 0101 0--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load word (scalar+vector)
30
FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
31
FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
32
FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
33
FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
34
FAIL 1100 010- ---- ---- ---- ---- ---- ---- # SVE 64-bit gather load/prefetch
35
-FAIL 1110 010- -00- ---- 001- ---- ---- ---- # SVE2 64-bit scatter NT store (vector+scalar)
36
-FAIL 1110 010- -10- ---- 001- ---- ---- ---- # SVE2 32-bit scatter NT store (vector+scalar)
37
-FAIL 1110 010- ---- ---- 1-0- ---- ---- ---- # SVE scatter store (scalar+32-bit vector)
38
-FAIL 1110 010- ---- ---- 101- ---- ---- ---- # SVE scatter store (misc)
39
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate-sve.c
42
+++ b/target/arm/translate-sve.c
43
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a)
44
if (!dc_isar_feature(aa64_sve, s)) {
45
return false;
46
}
47
+ s->is_nonstreaming = true;
48
if (!sve_access_check(s)) {
49
return true;
50
}
51
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a)
52
if (!dc_isar_feature(aa64_sve, s)) {
53
return false;
54
}
55
+ s->is_nonstreaming = true;
56
if (!sve_access_check(s)) {
57
return true;
58
}
59
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNT1_zprz(DisasContext *s, arg_LD1_zprz *a)
60
if (!dc_isar_feature(aa64_sve2, s)) {
61
return false;
62
}
63
+ s->is_nonstreaming = true;
64
if (!sve_access_check(s)) {
65
return true;
66
}
67
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a)
68
if (!dc_isar_feature(aa64_sve, s)) {
69
return false;
70
}
71
+ s->is_nonstreaming = true;
72
if (!sve_access_check(s)) {
73
return true;
74
}
75
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a)
76
if (!dc_isar_feature(aa64_sve, s)) {
77
return false;
78
}
79
+ s->is_nonstreaming = true;
80
if (!sve_access_check(s)) {
81
return true;
82
}
83
@@ -XXX,XX +XXX,XX @@ static bool trans_STNT1_zprz(DisasContext *s, arg_ST1_zprz *a)
84
if (!dc_isar_feature(aa64_sve2, s)) {
85
return false;
86
}
87
+ s->is_nonstreaming = true;
88
if (!sve_access_check(s)) {
89
return true;
90
}
91
--
92
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as a non-streaming instructions, which should trap if full
4
a64 support is not enabled in streaming mode. In this case, introduce
5
PRF_ns (prefetch non-streaming) to handle the checks.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220708151540.18136-13-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/sme-fa64.decode | 3 ---
13
target/arm/sve.decode | 10 +++++-----
14
target/arm/translate-sve.c | 11 +++++++++++
15
3 files changed, 16 insertions(+), 8 deletions(-)
16
17
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/sme-fa64.decode
20
+++ b/target/arm/sme-fa64.decode
21
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
22
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
23
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
24
25
-FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
26
-FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
27
FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
28
FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
29
FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
30
FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
31
-FAIL 1100 010- ---- ---- ---- ---- ---- ---- # SVE 64-bit gather load/prefetch
32
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/sve.decode
35
+++ b/target/arm/sve.decode
36
@@ -XXX,XX +XXX,XX @@ LD1RO_zpri 1010010 .. 01 0.... 001 ... ..... ..... \
37
@rpri_load_msz nreg=0
38
39
# SVE 32-bit gather prefetch (scalar plus 32-bit scaled offsets)
40
-PRF 1000010 00 -1 ----- 0-- --- ----- 0 ----
41
+PRF_ns 1000010 00 -1 ----- 0-- --- ----- 0 ----
42
43
# SVE 32-bit gather prefetch (vector plus immediate)
44
-PRF 1000010 -- 00 ----- 111 --- ----- 0 ----
45
+PRF_ns 1000010 -- 00 ----- 111 --- ----- 0 ----
46
47
# SVE contiguous prefetch (scalar plus immediate)
48
PRF 1000010 11 1- ----- 0-- --- ----- 0 ----
49
@@ -XXX,XX +XXX,XX @@ LD1_zpiz 1100010 .. 01 ..... 1.. ... ..... ..... \
50
@rpri_g_load esz=3
51
52
# SVE 64-bit gather prefetch (scalar plus 64-bit scaled offsets)
53
-PRF 1100010 00 11 ----- 1-- --- ----- 0 ----
54
+PRF_ns 1100010 00 11 ----- 1-- --- ----- 0 ----
55
56
# SVE 64-bit gather prefetch (scalar plus unpacked 32-bit scaled offsets)
57
-PRF 1100010 00 -1 ----- 0-- --- ----- 0 ----
58
+PRF_ns 1100010 00 -1 ----- 0-- --- ----- 0 ----
59
60
# SVE 64-bit gather prefetch (vector plus immediate)
61
-PRF 1100010 -- 00 ----- 111 --- ----- 0 ----
62
+PRF_ns 1100010 -- 00 ----- 111 --- ----- 0 ----
63
64
### SVE Memory Store Group
65
66
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate-sve.c
69
+++ b/target/arm/translate-sve.c
70
@@ -XXX,XX +XXX,XX @@ static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a)
71
return true;
72
}
73
74
+static bool trans_PRF_ns(DisasContext *s, arg_PRF_ns *a)
75
+{
76
+ if (!dc_isar_feature(aa64_sve, s)) {
77
+ return false;
78
+ }
79
+ /* Prefetch is a nop within QEMU. */
80
+ s->is_nonstreaming = true;
81
+ (void)sve_access_check(s);
82
+ return true;
83
+}
84
+
85
/*
86
* Move Prefix
87
*
88
--
89
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-14-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 2 --
12
target/arm/translate-sve.c | 2 ++
13
2 files changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
24
-FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
25
FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
26
FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
31
@@ -XXX,XX +XXX,XX @@ static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a)
32
if (!dc_isar_feature(aa64_sve, s)) {
33
return false;
34
}
35
+ s->is_nonstreaming = true;
36
if (sve_access_check(s)) {
37
TCGv_i64 addr = new_tmp_a64(s);
38
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
39
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a)
40
if (!dc_isar_feature(aa64_sve, s)) {
41
return false;
42
}
43
+ s->is_nonstreaming = true;
44
if (sve_access_check(s)) {
45
int vsz = vec_full_reg_size(s);
46
int elements = vsz >> dtype_esz[a->dtype];
47
--
48
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-15-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 3 ---
12
target/arm/translate-sve.c | 2 ++
13
2 files changed, 2 insertions(+), 3 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --0- ---- ---- ---- ---- ---- # Load/store FP register (unscaled imm)
21
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
22
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
23
-
24
-FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
25
-FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
26
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/translate-sve.c
29
+++ b/target/arm/translate-sve.c
30
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1RO_zprr(DisasContext *s, arg_rprr_load *a)
31
if (a->rm == 31) {
32
return false;
33
}
34
+ s->is_nonstreaming = true;
35
if (sve_access_check(s)) {
36
TCGv_i64 addr = new_tmp_a64(s);
37
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
38
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1RO_zpri(DisasContext *s, arg_rpri_load *a)
39
if (!dc_isar_feature(aa64_sve_f64mm, s)) {
40
return false;
41
}
42
+ s->is_nonstreaming = true;
43
if (sve_access_check(s)) {
44
TCGv_i64 addr = new_tmp_a64(s);
45
tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), a->imm * 32);
46
--
47
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
These functions will be used to verify that the cpu
4
is in the correct state for a given instruction.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-16-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-a64.h | 21 +++++++++++++++++++++
12
target/arm/translate-a64.c | 34 ++++++++++++++++++++++++++++++++++
13
2 files changed, 55 insertions(+)
14
15
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.h
18
+++ b/target/arm/translate-a64.h
19
@@ -XXX,XX +XXX,XX @@ void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v);
20
bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
21
unsigned int imms, unsigned int immr);
22
bool sve_access_check(DisasContext *s);
23
+bool sme_enabled_check(DisasContext *s);
24
+bool sme_enabled_check_with_svcr(DisasContext *s, unsigned);
25
+
26
+/* This function corresponds to CheckStreamingSVEEnabled. */
27
+static inline bool sme_sm_enabled_check(DisasContext *s)
28
+{
29
+ return sme_enabled_check_with_svcr(s, R_SVCR_SM_MASK);
30
+}
31
+
32
+/* This function corresponds to CheckSMEAndZAEnabled. */
33
+static inline bool sme_za_enabled_check(DisasContext *s)
34
+{
35
+ return sme_enabled_check_with_svcr(s, R_SVCR_ZA_MASK);
36
+}
37
+
38
+/* Note that this function corresponds to CheckStreamingSVEAndZAEnabled. */
39
+static inline bool sme_smza_enabled_check(DisasContext *s)
40
+{
41
+ return sme_enabled_check_with_svcr(s, R_SVCR_SM_MASK | R_SVCR_ZA_MASK);
42
+}
43
+
44
TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
45
TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
46
bool tag_checked, int log2_size);
47
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-a64.c
50
+++ b/target/arm/translate-a64.c
51
@@ -XXX,XX +XXX,XX @@ static bool sme_access_check(DisasContext *s)
52
return true;
53
}
54
55
+/* This function corresponds to CheckSMEEnabled. */
56
+bool sme_enabled_check(DisasContext *s)
57
+{
58
+ /*
59
+ * Note that unlike sve_excp_el, we have not constrained sme_excp_el
60
+ * to be zero when fp_excp_el has priority. This is because we need
61
+ * sme_excp_el by itself for cpregs access checks.
62
+ */
63
+ if (!s->fp_excp_el || s->sme_excp_el < s->fp_excp_el) {
64
+ s->fp_access_checked = true;
65
+ return sme_access_check(s);
66
+ }
67
+ return fp_access_check_only(s);
68
+}
69
+
70
+/* Common subroutine for CheckSMEAnd*Enabled. */
71
+bool sme_enabled_check_with_svcr(DisasContext *s, unsigned req)
72
+{
73
+ if (!sme_enabled_check(s)) {
74
+ return false;
75
+ }
76
+ if (FIELD_EX64(req, SVCR, SM) && !s->pstate_sm) {
77
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
78
+ syn_smetrap(SME_ET_NotStreaming, false));
79
+ return false;
80
+ }
81
+ if (FIELD_EX64(req, SVCR, ZA) && !s->pstate_za) {
82
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
83
+ syn_smetrap(SME_ET_InactiveZA, false));
84
+ return false;
85
+ }
86
+ return true;
87
+}
88
+
89
/*
90
* This utility function is for doing register extension with an
91
* optional shift. You will likely want to pass a temporary for the
92
--
93
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The pseudocode for CheckSVEEnabled gains a check for Streaming
4
SVE mode, and for SME present but SVE absent.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-17-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-a64.c | 22 ++++++++++++++++------
12
1 file changed, 16 insertions(+), 6 deletions(-)
13
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
19
return true;
20
}
21
22
-/* Check that SVE access is enabled. If it is, return true.
23
+/*
24
+ * Check that SVE access is enabled. If it is, return true.
25
* If not, emit code to generate an appropriate exception and return false.
26
+ * This function corresponds to CheckSVEEnabled().
27
*/
28
bool sve_access_check(DisasContext *s)
29
{
30
- if (s->sve_excp_el) {
31
- assert(!s->sve_access_checked);
32
- s->sve_access_checked = true;
33
-
34
+ if (s->pstate_sm || !dc_isar_feature(aa64_sve, s)) {
35
+ assert(dc_isar_feature(aa64_sme, s));
36
+ if (!sme_sm_enabled_check(s)) {
37
+ goto fail_exit;
38
+ }
39
+ } else if (s->sve_excp_el) {
40
gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
41
syn_sve_access_trap(), s->sve_excp_el);
42
- return false;
43
+ goto fail_exit;
44
}
45
s->sve_access_checked = true;
46
return fp_access_check(s);
47
+
48
+ fail_exit:
49
+ /* Assert that we only raise one exception per instruction. */
50
+ assert(!s->sve_access_checked);
51
+ s->sve_access_checked = true;
52
+ return false;
53
}
54
55
/*
56
--
57
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
We add a qtest for the PWM in the previous patch. It proves it works as
4
expected.
5
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210108190945.949196-6-wuhaotsh@google.com
5
Message-id: 20220708151540.18136-24-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/helper-sme.h | 5 +++
13
tests/qtest/npcm7xx_pwm-test.c | 490 +++++++++++++++++++++++++++++++++
9
target/arm/sme.decode | 11 +++++
14
tests/qtest/meson.build | 1 +
10
target/arm/sme_helper.c | 90 ++++++++++++++++++++++++++++++++++++++
15
2 files changed, 491 insertions(+)
11
target/arm/translate-sme.c | 31 +++++++++++++
16
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
12
4 files changed, 137 insertions(+)
13
17
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
18
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
15
index XXXXXXX..XXXXXXX 100644
19
new file mode 100644
16
--- a/target/arm/helper-sme.h
20
index XXXXXXX..XXXXXXX
17
+++ b/target/arm/helper-sme.h
21
--- /dev/null
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sme_st1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i
22
+++ b/tests/qtest/npcm7xx_pwm-test.c
19
DEF_HELPER_FLAGS_5(sme_st1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
23
@@ -XXX,XX +XXX,XX @@
20
DEF_HELPER_FLAGS_5(sme_st1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
24
+/*
21
DEF_HELPER_FLAGS_5(sme_st1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
25
+ * QTests for Nuvoton NPCM7xx PWM Modules.
22
+
26
+ *
23
+DEF_HELPER_FLAGS_5(sme_addha_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
+ * Copyright 2020 Google LLC
24
+DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
28
+ *
25
+DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
29
+ * This program is free software; you can redistribute it and/or modify it
26
+DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
30
+ * under the terms of the GNU General Public License as published by the
27
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
31
+ * Free Software Foundation; either version 2 of the License, or
28
index XXXXXXX..XXXXXXX 100644
32
+ * (at your option) any later version.
29
--- a/target/arm/sme.decode
33
+ *
30
+++ b/target/arm/sme.decode
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
31
@@ -XXX,XX +XXX,XX @@ LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
32
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
33
LDR 1110000 100 0 000000 .. 000 ..... 0 .... @ldstr
37
+ * for more details.
34
STR 1110000 100 1 000000 .. 000 ..... 0 .... @ldstr
38
+ */
35
+
39
+
36
+### SME Add Vector to Array
40
+#include "qemu/osdep.h"
37
+
41
+#include "qemu/bitops.h"
38
+&adda zad zn pm pn
42
+#include "libqos/libqtest.h"
39
+@adda_32 ........ .. ..... . pm:3 pn:3 zn:5 ... zad:2 &adda
43
+#include "qapi/qmp/qdict.h"
40
+@adda_64 ........ .. ..... . pm:3 pn:3 zn:5 .. zad:3 &adda
44
+#include "qapi/qmp/qnum.h"
41
+
45
+
42
+ADDHA_s 11000000 10 01000 0 ... ... ..... 000 .. @adda_32
46
+#define REF_HZ 25000000
43
+ADDVA_s 11000000 10 01000 1 ... ... ..... 000 .. @adda_32
47
+
44
+ADDHA_d 11000000 11 01000 0 ... ... ..... 00 ... @adda_64
48
+/* Register field definitions. */
45
+ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
49
+#define CH_EN BIT(0)
46
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
50
+#define CH_INV BIT(2)
47
index XXXXXXX..XXXXXXX 100644
51
+#define CH_MOD BIT(3)
48
--- a/target/arm/sme_helper.c
52
+
49
+++ b/target/arm/sme_helper.c
53
+/* Registers shared between all PWMs in a module */
50
@@ -XXX,XX +XXX,XX @@ DO_ST(q, _be, MO_128)
54
+#define PPR 0x00
51
DO_ST(q, _le, MO_128)
55
+#define CSR 0x04
52
56
+#define PCR 0x08
53
#undef DO_ST
57
+#define PIER 0x3c
54
+
58
+#define PIIR 0x40
55
+void HELPER(sme_addha_s)(void *vzda, void *vzn, void *vpn,
59
+
56
+ void *vpm, uint32_t desc)
60
+/* CLK module related */
57
+{
61
+#define CLK_BA 0xf0801000
58
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
62
+#define CLKSEL 0x04
59
+ uint64_t *pn = vpn, *pm = vpm;
63
+#define CLKDIV1 0x08
60
+ uint32_t *zda = vzda, *zn = vzn;
64
+#define CLKDIV2 0x2c
61
+
65
+#define PLLCON0 0x0c
62
+ for (row = 0; row < oprsz; ) {
66
+#define PLLCON1 0x10
63
+ uint64_t pa = pn[row >> 4];
67
+#define PLL_INDV(rv) extract32((rv), 0, 6)
64
+ do {
68
+#define PLL_FBDV(rv) extract32((rv), 16, 12)
65
+ if (pa & 1) {
69
+#define PLL_OTDV1(rv) extract32((rv), 8, 3)
66
+ for (col = 0; col < oprsz; ) {
70
+#define PLL_OTDV2(rv) extract32((rv), 13, 3)
67
+ uint64_t pb = pm[col >> 4];
71
+#define APB3CKDIV(rv) extract32((rv), 28, 2)
68
+ do {
72
+#define CLK2CKDIV(rv) extract32((rv), 0, 1)
69
+ if (pb & 1) {
73
+#define CLK4CKDIV(rv) extract32((rv), 26, 2)
70
+ zda[tile_vslice_index(row) + H4(col)] += zn[H4(col)];
74
+#define CPUCKSEL(rv) extract32((rv), 0, 2)
71
+ }
75
+
72
+ pb >>= 4;
76
+#define MAX_DUTY 1000000
73
+ } while (++col & 15);
77
+
74
+ }
78
+typedef struct PWMModule {
75
+ }
79
+ int irq;
76
+ pa >>= 4;
80
+ uint64_t base_addr;
77
+ } while (++row & 15);
81
+} PWMModule;
78
+ }
82
+
79
+}
83
+typedef struct PWM {
80
+
84
+ uint32_t cnr_offset;
81
+void HELPER(sme_addha_d)(void *vzda, void *vzn, void *vpn,
85
+ uint32_t cmr_offset;
82
+ void *vpm, uint32_t desc)
86
+ uint32_t pdr_offset;
83
+{
87
+ uint32_t pwdr_offset;
84
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
88
+} PWM;
85
+ uint8_t *pn = vpn, *pm = vpm;
89
+
86
+ uint64_t *zda = vzda, *zn = vzn;
90
+typedef struct TestData {
87
+
91
+ const PWMModule *module;
88
+ for (row = 0; row < oprsz; ++row) {
92
+ const PWM *pwm;
89
+ if (pn[H1(row)] & 1) {
93
+} TestData;
90
+ for (col = 0; col < oprsz; ++col) {
94
+
91
+ if (pm[H1(col)] & 1) {
95
+static const PWMModule pwm_module_list[] = {
92
+ zda[tile_vslice_index(row) + col] += zn[col];
96
+ {
97
+ .irq = 93,
98
+ .base_addr = 0xf0103000
99
+ },
100
+ {
101
+ .irq = 94,
102
+ .base_addr = 0xf0104000
103
+ }
104
+};
105
+
106
+static const PWM pwm_list[] = {
107
+ {
108
+ .cnr_offset = 0x0c,
109
+ .cmr_offset = 0x10,
110
+ .pdr_offset = 0x14,
111
+ .pwdr_offset = 0x44,
112
+ },
113
+ {
114
+ .cnr_offset = 0x18,
115
+ .cmr_offset = 0x1c,
116
+ .pdr_offset = 0x20,
117
+ .pwdr_offset = 0x48,
118
+ },
119
+ {
120
+ .cnr_offset = 0x24,
121
+ .cmr_offset = 0x28,
122
+ .pdr_offset = 0x2c,
123
+ .pwdr_offset = 0x4c,
124
+ },
125
+ {
126
+ .cnr_offset = 0x30,
127
+ .cmr_offset = 0x34,
128
+ .pdr_offset = 0x38,
129
+ .pwdr_offset = 0x50,
130
+ },
131
+};
132
+
133
+static const int ppr_base[] = { 0, 0, 8, 8 };
134
+static const int csr_base[] = { 0, 4, 8, 12 };
135
+static const int pcr_base[] = { 0, 8, 12, 16 };
136
+
137
+static const uint32_t ppr_list[] = {
138
+ 0,
139
+ 1,
140
+ 10,
141
+ 100,
142
+ 255, /* Max possible value. */
143
+};
144
+
145
+static const uint32_t csr_list[] = {
146
+ 0,
147
+ 1,
148
+ 2,
149
+ 3,
150
+ 4, /* Max possible value. */
151
+};
152
+
153
+static const uint32_t cnr_list[] = {
154
+ 0,
155
+ 1,
156
+ 50,
157
+ 100,
158
+ 150,
159
+ 200,
160
+ 1000,
161
+ 10000,
162
+ 65535, /* Max possible value. */
163
+};
164
+
165
+static const uint32_t cmr_list[] = {
166
+ 0,
167
+ 1,
168
+ 10,
169
+ 50,
170
+ 100,
171
+ 150,
172
+ 200,
173
+ 1000,
174
+ 10000,
175
+ 65535, /* Max possible value. */
176
+};
177
+
178
+/* Returns the index of the PWM module. */
179
+static int pwm_module_index(const PWMModule *module)
180
+{
181
+ ptrdiff_t diff = module - pwm_module_list;
182
+
183
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_module_list));
184
+
185
+ return diff;
186
+}
187
+
188
+/* Returns the index of the PWM entry. */
189
+static int pwm_index(const PWM *pwm)
190
+{
191
+ ptrdiff_t diff = pwm - pwm_list;
192
+
193
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_list));
194
+
195
+ return diff;
196
+}
197
+
198
+static uint64_t pwm_qom_get(QTestState *qts, const char *path, const char *name)
199
+{
200
+ QDict *response;
201
+
202
+ g_test_message("Getting properties %s from %s", name, path);
203
+ response = qtest_qmp(qts, "{ 'execute': 'qom-get',"
204
+ " 'arguments': { 'path': %s, 'property': %s}}",
205
+ path, name);
206
+ /* The qom set message returns successfully. */
207
+ g_assert_true(qdict_haskey(response, "return"));
208
+ return qnum_get_uint(qobject_to(QNum, qdict_get(response, "return")));
209
+}
210
+
211
+static uint64_t pwm_get_freq(QTestState *qts, int module_index, int pwm_index)
212
+{
213
+ char path[100];
214
+ char name[100];
215
+
216
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
217
+ sprintf(name, "freq[%d]", pwm_index);
218
+
219
+ return pwm_qom_get(qts, path, name);
220
+}
221
+
222
+static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index)
223
+{
224
+ char path[100];
225
+ char name[100];
226
+
227
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
228
+ sprintf(name, "duty[%d]", pwm_index);
229
+
230
+ return pwm_qom_get(qts, path, name);
231
+}
232
+
233
+static uint32_t get_pll(uint32_t con)
234
+{
235
+ return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con)
236
+ * PLL_OTDV2(con));
237
+}
238
+
239
+static uint64_t read_pclk(QTestState *qts)
240
+{
241
+ uint64_t freq = REF_HZ;
242
+ uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL);
243
+ uint32_t pllcon;
244
+ uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1);
245
+ uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2);
246
+
247
+ switch (CPUCKSEL(clksel)) {
248
+ case 0:
249
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON0);
250
+ freq = get_pll(pllcon);
251
+ break;
252
+ case 1:
253
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON1);
254
+ freq = get_pll(pllcon);
255
+ break;
256
+ case 2:
257
+ break;
258
+ case 3:
259
+ break;
260
+ default:
261
+ g_assert_not_reached();
262
+ }
263
+
264
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
265
+
266
+ return freq;
267
+}
268
+
269
+static uint32_t pwm_selector(uint32_t csr)
270
+{
271
+ switch (csr) {
272
+ case 0:
273
+ return 2;
274
+ case 1:
275
+ return 4;
276
+ case 2:
277
+ return 8;
278
+ case 3:
279
+ return 16;
280
+ case 4:
281
+ return 1;
282
+ default:
283
+ g_assert_not_reached();
284
+ }
285
+}
286
+
287
+static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
288
+ uint32_t cnr)
289
+{
290
+ return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
291
+}
292
+
293
+static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
294
+{
295
+ uint64_t duty;
296
+
297
+ if (cnr == 0) {
298
+ /* PWM is stopped. */
299
+ duty = 0;
300
+ } else if (cmr >= cnr) {
301
+ duty = MAX_DUTY;
302
+ } else {
303
+ duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
304
+ }
305
+
306
+ if (inverted) {
307
+ duty = MAX_DUTY - duty;
308
+ }
309
+
310
+ return duty;
311
+}
312
+
313
+static uint32_t pwm_read(QTestState *qts, const TestData *td, unsigned offset)
314
+{
315
+ return qtest_readl(qts, td->module->base_addr + offset);
316
+}
317
+
318
+static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
319
+ uint32_t value)
320
+{
321
+ qtest_writel(qts, td->module->base_addr + offset, value);
322
+}
323
+
324
+static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
325
+{
326
+ return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
327
+}
328
+
329
+static void pwm_write_ppr(QTestState *qts, const TestData *td, uint32_t value)
330
+{
331
+ pwm_write(qts, td, PPR, value << ppr_base[pwm_index(td->pwm)]);
332
+}
333
+
334
+static uint32_t pwm_read_csr(QTestState *qts, const TestData *td)
335
+{
336
+ return extract32(pwm_read(qts, td, CSR), csr_base[pwm_index(td->pwm)], 3);
337
+}
338
+
339
+static void pwm_write_csr(QTestState *qts, const TestData *td, uint32_t value)
340
+{
341
+ pwm_write(qts, td, CSR, value << csr_base[pwm_index(td->pwm)]);
342
+}
343
+
344
+static uint32_t pwm_read_pcr(QTestState *qts, const TestData *td)
345
+{
346
+ return extract32(pwm_read(qts, td, PCR), pcr_base[pwm_index(td->pwm)], 4);
347
+}
348
+
349
+static void pwm_write_pcr(QTestState *qts, const TestData *td, uint32_t value)
350
+{
351
+ pwm_write(qts, td, PCR, value << pcr_base[pwm_index(td->pwm)]);
352
+}
353
+
354
+static uint32_t pwm_read_cnr(QTestState *qts, const TestData *td)
355
+{
356
+ return pwm_read(qts, td, td->pwm->cnr_offset);
357
+}
358
+
359
+static void pwm_write_cnr(QTestState *qts, const TestData *td, uint32_t value)
360
+{
361
+ pwm_write(qts, td, td->pwm->cnr_offset, value);
362
+}
363
+
364
+static uint32_t pwm_read_cmr(QTestState *qts, const TestData *td)
365
+{
366
+ return pwm_read(qts, td, td->pwm->cmr_offset);
367
+}
368
+
369
+static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
370
+{
371
+ pwm_write(qts, td, td->pwm->cmr_offset, value);
372
+}
373
+
374
+/* Check pwm registers can be reset to default value */
375
+static void test_init(gconstpointer test_data)
376
+{
377
+ const TestData *td = test_data;
378
+ QTestState *qts = qtest_init("-machine quanta-gsj");
379
+ int module = pwm_module_index(td->module);
380
+ int pwm = pwm_index(td->pwm);
381
+
382
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
383
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
384
+
385
+ qtest_quit(qts);
386
+}
387
+
388
+/* One-shot mode should not change frequency and duty cycle. */
389
+static void test_oneshot(gconstpointer test_data)
390
+{
391
+ const TestData *td = test_data;
392
+ QTestState *qts = qtest_init("-machine quanta-gsj");
393
+ int module = pwm_module_index(td->module);
394
+ int pwm = pwm_index(td->pwm);
395
+ uint32_t ppr, csr, pcr;
396
+ int i, j;
397
+
398
+ pcr = CH_EN;
399
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
400
+ ppr = ppr_list[i];
401
+ pwm_write_ppr(qts, td, ppr);
402
+
403
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
404
+ csr = csr_list[j];
405
+ pwm_write_csr(qts, td, csr);
406
+ pwm_write_pcr(qts, td, pcr);
407
+
408
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
409
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
410
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
411
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
412
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
413
+ }
414
+ }
415
+
416
+ qtest_quit(qts);
417
+}
418
+
419
+/* In toggle mode, the PWM generates correct outputs. */
420
+static void test_toggle(gconstpointer test_data)
421
+{
422
+ const TestData *td = test_data;
423
+ QTestState *qts = qtest_init("-machine quanta-gsj");
424
+ int module = pwm_module_index(td->module);
425
+ int pwm = pwm_index(td->pwm);
426
+ uint32_t ppr, csr, pcr, cnr, cmr;
427
+ int i, j, k, l;
428
+ uint64_t expected_freq, expected_duty;
429
+
430
+ pcr = CH_EN | CH_MOD;
431
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
432
+ ppr = ppr_list[i];
433
+ pwm_write_ppr(qts, td, ppr);
434
+
435
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
436
+ csr = csr_list[j];
437
+ pwm_write_csr(qts, td, csr);
438
+
439
+ for (k = 0; k < ARRAY_SIZE(cnr_list); ++k) {
440
+ cnr = cnr_list[k];
441
+ pwm_write_cnr(qts, td, cnr);
442
+
443
+ for (l = 0; l < ARRAY_SIZE(cmr_list); ++l) {
444
+ cmr = cmr_list[l];
445
+ pwm_write_cmr(qts, td, cmr);
446
+ expected_freq = pwm_compute_freq(qts, ppr, csr, cnr);
447
+ expected_duty = pwm_compute_duty(cnr, cmr, false);
448
+
449
+ pwm_write_pcr(qts, td, pcr);
450
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
451
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
452
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
453
+ g_assert_cmpuint(pwm_read_cnr(qts, td), ==, cnr);
454
+ g_assert_cmpuint(pwm_read_cmr(qts, td), ==, cmr);
455
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm),
456
+ ==, expected_duty);
457
+ if (expected_duty != 0 && expected_duty != 100) {
458
+ /* Duty cycle with 0 or 100 doesn't need frequency. */
459
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm),
460
+ ==, expected_freq);
461
+ }
462
+
463
+ /* Test inverted mode */
464
+ expected_duty = pwm_compute_duty(cnr, cmr, true);
465
+ pwm_write_pcr(qts, td, pcr | CH_INV);
466
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr | CH_INV);
467
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm),
468
+ ==, expected_duty);
469
+ if (expected_duty != 0 && expected_duty != 100) {
470
+ /* Duty cycle with 0 or 100 doesn't need frequency. */
471
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm),
472
+ ==, expected_freq);
473
+ }
474
+
93
+ }
475
+ }
94
+ }
476
+ }
95
+ }
477
+ }
96
+ }
478
+ }
97
+}
479
+
98
+
480
+ qtest_quit(qts);
99
+void HELPER(sme_addva_s)(void *vzda, void *vzn, void *vpn,
481
+}
100
+ void *vpm, uint32_t desc)
482
+
101
+{
483
+static void pwm_add_test(const char *name, const TestData* td,
102
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
484
+ GTestDataFunc fn)
103
+ uint64_t *pn = vpn, *pm = vpm;
485
+{
104
+ uint32_t *zda = vzda, *zn = vzn;
486
+ g_autofree char *full_name = g_strdup_printf(
105
+
487
+ "npcm7xx_pwm/module[%d]/pwm[%d]/%s", pwm_module_index(td->module),
106
+ for (row = 0; row < oprsz; ) {
488
+ pwm_index(td->pwm), name);
107
+ uint64_t pa = pn[row >> 4];
489
+ qtest_add_data_func(full_name, td, fn);
108
+ do {
490
+}
109
+ if (pa & 1) {
491
+#define add_test(name, td) pwm_add_test(#name, td, test_##name)
110
+ uint32_t zn_row = zn[H4(row)];
492
+
111
+ for (col = 0; col < oprsz; ) {
493
+int main(int argc, char **argv)
112
+ uint64_t pb = pm[col >> 4];
494
+{
113
+ do {
495
+ TestData test_data_list[ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list)];
114
+ if (pb & 1) {
496
+
115
+ zda[tile_vslice_index(row) + H4(col)] += zn_row;
497
+ g_test_init(&argc, &argv, NULL);
116
+ }
498
+
117
+ pb >>= 4;
499
+ for (int i = 0; i < ARRAY_SIZE(pwm_module_list); ++i) {
118
+ } while (++col & 15);
500
+ for (int j = 0; j < ARRAY_SIZE(pwm_list); ++j) {
119
+ }
501
+ TestData *td = &test_data_list[i * ARRAY_SIZE(pwm_list) + j];
120
+ }
502
+
121
+ pa >>= 4;
503
+ td->module = &pwm_module_list[i];
122
+ } while (++row & 15);
504
+ td->pwm = &pwm_list[j];
123
+ }
505
+
124
+}
506
+ add_test(init, td);
125
+
507
+ add_test(oneshot, td);
126
+void HELPER(sme_addva_d)(void *vzda, void *vzn, void *vpn,
508
+ add_test(toggle, td);
127
+ void *vpm, uint32_t desc)
128
+{
129
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
130
+ uint8_t *pn = vpn, *pm = vpm;
131
+ uint64_t *zda = vzda, *zn = vzn;
132
+
133
+ for (row = 0; row < oprsz; ++row) {
134
+ if (pn[H1(row)] & 1) {
135
+ uint64_t zn_row = zn[row];
136
+ for (col = 0; col < oprsz; ++col) {
137
+ if (pm[H1(col)] & 1) {
138
+ zda[tile_vslice_index(row) + col] += zn_row;
139
+ }
140
+ }
141
+ }
509
+ }
142
+ }
510
+ }
143
+}
511
+
144
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
512
+ return g_test_run();
513
+}
514
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
145
index XXXXXXX..XXXXXXX 100644
515
index XXXXXXX..XXXXXXX 100644
146
--- a/target/arm/translate-sme.c
516
--- a/tests/qtest/meson.build
147
+++ b/target/arm/translate-sme.c
517
+++ b/tests/qtest/meson.build
148
@@ -XXX,XX +XXX,XX @@ static bool do_ldst_r(DisasContext *s, arg_ldstr *a, GenLdStR *fn)
518
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
149
519
qtests_npcm7xx = \
150
TRANS_FEAT(LDR, aa64_sme, do_ldst_r, a, gen_sve_ldr)
520
['npcm7xx_adc-test',
151
TRANS_FEAT(STR, aa64_sme, do_ldst_r, a, gen_sve_str)
521
'npcm7xx_gpio-test',
152
+
522
+ 'npcm7xx_pwm-test',
153
+static bool do_adda(DisasContext *s, arg_adda *a, MemOp esz,
523
'npcm7xx_rng-test',
154
+ gen_helper_gvec_4 *fn)
524
'npcm7xx_timer-test',
155
+{
525
'npcm7xx_watchdog_timer-test']
156
+ int svl = streaming_vec_reg_size(s);
157
+ uint32_t desc = simd_desc(svl, svl, 0);
158
+ TCGv_ptr za, zn, pn, pm;
159
+
160
+ if (!sme_smza_enabled_check(s)) {
161
+ return true;
162
+ }
163
+
164
+ /* Sum XZR+zad to find ZAd. */
165
+ za = get_tile_rowcol(s, esz, 31, a->zad, false);
166
+ zn = vec_full_reg_ptr(s, a->zn);
167
+ pn = pred_full_reg_ptr(s, a->pn);
168
+ pm = pred_full_reg_ptr(s, a->pm);
169
+
170
+ fn(za, zn, pn, pm, tcg_constant_i32(desc));
171
+
172
+ tcg_temp_free_ptr(za);
173
+ tcg_temp_free_ptr(zn);
174
+ tcg_temp_free_ptr(pn);
175
+ tcg_temp_free_ptr(pm);
176
+ return true;
177
+}
178
+
179
+TRANS_FEAT(ADDHA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addha_s)
180
+TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
181
+TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
182
+TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
183
--
526
--
184
2.25.1
527
2.20.1
528
529
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
These SME instructions are nominally within the SVE decode space,
3
A device shouldn't access its parent object which is QOM internal.
4
so we add them to sve.decode and translate-sve.c.
4
Instead it should use type cast for this purporse. This patch fixes this
5
issue for all NPCM7XX Devices.
5
6
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210108190945.949196-7-wuhaotsh@google.com
8
Message-id: 20220708151540.18136-18-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
target/arm/translate-a64.h | 12 ++++++++++++
12
hw/arm/npcm7xx_boards.c | 2 +-
12
target/arm/sve.decode | 5 ++++-
13
hw/mem/npcm7xx_mc.c | 2 +-
13
target/arm/translate-sve.c | 38 ++++++++++++++++++++++++++++++++++++++
14
hw/misc/npcm7xx_clk.c | 2 +-
14
3 files changed, 54 insertions(+), 1 deletion(-)
15
hw/misc/npcm7xx_gcr.c | 2 +-
16
hw/misc/npcm7xx_rng.c | 2 +-
17
hw/nvram/npcm7xx_otp.c | 2 +-
18
hw/ssi/npcm7xx_fiu.c | 2 +-
19
7 files changed, 7 insertions(+), 7 deletions(-)
15
20
16
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
17
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-a64.h
23
--- a/hw/arm/npcm7xx_boards.c
19
+++ b/target/arm/translate-a64.h
24
+++ b/hw/arm/npcm7xx_boards.c
20
@@ -XXX,XX +XXX,XX @@ static inline int vec_full_reg_size(DisasContext *s)
25
@@ -XXX,XX +XXX,XX @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
21
return s->vl;
26
uint32_t hw_straps)
27
{
28
NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
29
- MachineClass *mc = &nmc->parent;
30
+ MachineClass *mc = MACHINE_CLASS(nmc);
31
Object *obj;
32
33
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
34
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/mem/npcm7xx_mc.c
37
+++ b/hw/mem/npcm7xx_mc.c
38
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
39
40
memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
41
NPCM7XX_MC_REGS_SIZE);
42
- sysbus_init_mmio(&s->parent, &s->mmio);
43
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
22
}
44
}
23
45
24
+/* Return the byte size of the vector register, SVL / 8. */
46
static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
25
+static inline int streaming_vec_reg_size(DisasContext *s)
47
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
26
+{
48
index XXXXXXX..XXXXXXX 100644
27
+ return s->svl;
49
--- a/hw/misc/npcm7xx_clk.c
28
+}
50
+++ b/hw/misc/npcm7xx_clk.c
29
+
51
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
30
/*
52
31
* Return the offset info CPUARMState of the predicate vector register Pn.
53
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
32
* Note for this purpose, FFR is P16.
54
TYPE_NPCM7XX_CLK, 4 * KiB);
33
@@ -XXX,XX +XXX,XX @@ static inline int pred_full_reg_size(DisasContext *s)
55
- sysbus_init_mmio(&s->parent, &s->iomem);
34
return s->vl >> 3;
56
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
35
}
57
}
36
58
37
+/* Return the byte size of the predicate register, SVL / 64. */
59
static int npcm7xx_clk_post_load(void *opaque, int version_id)
38
+static inline int streaming_pred_reg_size(DisasContext *s)
60
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
39
+{
40
+ return s->svl >> 3;
41
+}
42
+
43
/*
44
* Round up the size of a register to a size allowed by
45
* the tcg vector infrastructure. Any operation which uses this
46
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
47
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/sve.decode
62
--- a/hw/misc/npcm7xx_gcr.c
49
+++ b/target/arm/sve.decode
63
+++ b/hw/misc/npcm7xx_gcr.c
50
@@ -XXX,XX +XXX,XX @@ INDEX_ri 00000100 esz:2 1 imm:s5 010001 rn:5 rd:5
64
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_init(Object *obj)
51
# SVE index generation (register start, register increment)
65
52
INDEX_rr 00000100 .. 1 ..... 010011 ..... ..... @rd_rn_rm
66
memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
53
67
TYPE_NPCM7XX_GCR, 4 * KiB);
54
-### SVE Stack Allocation Group
68
- sysbus_init_mmio(&s->parent, &s->iomem);
55
+### SVE / Streaming SVE Stack Allocation Group
69
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
56
70
}
57
# SVE stack frame adjustment
71
58
ADDVL 00000100 001 ..... 01010 ...... ..... @rd_rn_i6
72
static const VMStateDescription vmstate_npcm7xx_gcr = {
59
+ADDSVL 00000100 001 ..... 01011 ...... ..... @rd_rn_i6
73
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
60
ADDPL 00000100 011 ..... 01010 ...... ..... @rd_rn_i6
61
+ADDSPL 00000100 011 ..... 01011 ...... ..... @rd_rn_i6
62
63
# SVE stack frame size
64
RDVL 00000100 101 11111 01010 imm:s6 rd:5
65
+RDSVL 00000100 101 11111 01011 imm:s6 rd:5
66
67
### SVE Bitwise Shift - Unpredicated Group
68
69
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
70
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/translate-sve.c
75
--- a/hw/misc/npcm7xx_rng.c
72
+++ b/target/arm/translate-sve.c
76
+++ b/hw/misc/npcm7xx_rng.c
73
@@ -XXX,XX +XXX,XX @@ static bool trans_ADDVL(DisasContext *s, arg_ADDVL *a)
77
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_rng_init(Object *obj)
74
return true;
78
79
memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs",
80
NPCM7XX_RNG_REGS_SIZE);
81
- sysbus_init_mmio(&s->parent, &s->iomem);
82
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
75
}
83
}
76
84
77
+static bool trans_ADDSVL(DisasContext *s, arg_ADDSVL *a)
85
static const VMStateDescription vmstate_npcm7xx_rng = {
78
+{
86
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
79
+ if (!dc_isar_feature(aa64_sme, s)) {
87
index XXXXXXX..XXXXXXX 100644
80
+ return false;
88
--- a/hw/nvram/npcm7xx_otp.c
81
+ }
89
+++ b/hw/nvram/npcm7xx_otp.c
82
+ if (sme_enabled_check(s)) {
90
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
83
+ TCGv_i64 rd = cpu_reg_sp(s, a->rd);
84
+ TCGv_i64 rn = cpu_reg_sp(s, a->rn);
85
+ tcg_gen_addi_i64(rd, rn, a->imm * streaming_vec_reg_size(s));
86
+ }
87
+ return true;
88
+}
89
+
90
static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
91
{
91
{
92
if (!dc_isar_feature(aa64_sve, s)) {
92
NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
93
@@ -XXX,XX +XXX,XX @@ static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
93
NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
94
return true;
94
- SysBusDevice *sbd = &s->parent;
95
}
95
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
96
96
97
+static bool trans_ADDSPL(DisasContext *s, arg_ADDSPL *a)
97
memset(s->array, 0, sizeof(s->array));
98
+{
98
99
+ if (!dc_isar_feature(aa64_sme, s)) {
99
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
100
+ return false;
100
index XXXXXXX..XXXXXXX 100644
101
+ }
101
--- a/hw/ssi/npcm7xx_fiu.c
102
+ if (sme_enabled_check(s)) {
102
+++ b/hw/ssi/npcm7xx_fiu.c
103
+ TCGv_i64 rd = cpu_reg_sp(s, a->rd);
103
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_fiu_hold_reset(Object *obj)
104
+ TCGv_i64 rn = cpu_reg_sp(s, a->rn);
104
static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
105
+ tcg_gen_addi_i64(rd, rn, a->imm * streaming_pred_reg_size(s));
106
+ }
107
+ return true;
108
+}
109
+
110
static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
111
{
105
{
112
if (!dc_isar_feature(aa64_sve, s)) {
106
NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
113
@@ -XXX,XX +XXX,XX @@ static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
107
- SysBusDevice *sbd = &s->parent;
114
return true;
108
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
115
}
109
int i;
116
110
117
+static bool trans_RDSVL(DisasContext *s, arg_RDSVL *a)
111
if (s->cs_count <= 0) {
118
+{
119
+ if (!dc_isar_feature(aa64_sme, s)) {
120
+ return false;
121
+ }
122
+ if (sme_enabled_check(s)) {
123
+ TCGv_i64 reg = cpu_reg(s, a->rd);
124
+ tcg_gen_movi_i64(reg, a->imm * streaming_vec_reg_size(s));
125
+ }
126
+ return true;
127
+}
128
+
129
/*
130
*** SVE Compute Vector Address Group
131
*/
132
--
112
--
133
2.25.1
113
2.20.1
114
115
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220708151540.18136-19-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/helper-sme.h | 2 ++
9
target/arm/sme.decode | 4 ++++
10
target/arm/sme_helper.c | 25 +++++++++++++++++++++++++
11
target/arm/translate-sme.c | 13 +++++++++++++
12
4 files changed, 44 insertions(+)
13
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sme.h
17
+++ b/target/arm/helper-sme.h
18
@@ -XXX,XX +XXX,XX @@
19
20
DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
21
DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
22
+
23
+DEF_HELPER_FLAGS_3(sme_zero, TCG_CALL_NO_RWG, void, env, i32, i32)
24
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/sme.decode
27
+++ b/target/arm/sme.decode
28
@@ -XXX,XX +XXX,XX @@
29
#
30
# This file is processed by scripts/decodetree.py
31
#
32
+
33
+### SME Misc
34
+
35
+ZERO 11000000 00 001 00000000000 imm:8
36
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/sme_helper.c
39
+++ b/target/arm/sme_helper.c
40
@@ -XXX,XX +XXX,XX @@ void helper_set_pstate_za(CPUARMState *env, uint32_t i)
41
memset(env->zarray, 0, sizeof(env->zarray));
42
}
43
}
44
+
45
+void helper_sme_zero(CPUARMState *env, uint32_t imm, uint32_t svl)
46
+{
47
+ uint32_t i;
48
+
49
+ /*
50
+ * Special case clearing the entire ZA space.
51
+ * This falls into the CONSTRAINED UNPREDICTABLE zeroing of any
52
+ * parts of the ZA storage outside of SVL.
53
+ */
54
+ if (imm == 0xff) {
55
+ memset(env->zarray, 0, sizeof(env->zarray));
56
+ return;
57
+ }
58
+
59
+ /*
60
+ * Recall that ZAnH.D[m] is spread across ZA[n+8*m],
61
+ * so each row is discontiguous within ZA[].
62
+ */
63
+ for (i = 0; i < svl; i++) {
64
+ if (imm & (1 << (i % 8))) {
65
+ memset(&env->zarray[i], 0, svl);
66
+ }
67
+ }
68
+}
69
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/translate-sme.c
72
+++ b/target/arm/translate-sme.c
73
@@ -XXX,XX +XXX,XX @@
74
*/
75
76
#include "decode-sme.c.inc"
77
+
78
+
79
+static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
80
+{
81
+ if (!dc_isar_feature(aa64_sme, s)) {
82
+ return false;
83
+ }
84
+ if (sme_za_enabled_check(s)) {
85
+ gen_helper_sme_zero(cpu_env, tcg_constant_i32(a->imm),
86
+ tcg_constant_i32(streaming_vec_reg_size(s)));
87
+ }
88
+ return true;
89
+}
90
--
91
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Add a TCGv_ptr base argument, which will be cpu_env for SVE.
4
We will reuse this for SME save and restore array insns.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-22-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-a64.h | 3 +++
12
target/arm/translate-sve.c | 48 ++++++++++++++++++++++++++++----------
13
2 files changed, 39 insertions(+), 12 deletions(-)
14
15
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.h
18
+++ b/target/arm/translate-a64.h
19
@@ -XXX,XX +XXX,XX @@ void gen_gvec_xar(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
20
uint32_t rm_ofs, int64_t shift,
21
uint32_t opr_sz, uint32_t max_sz);
22
23
+void gen_sve_ldr(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int imm);
24
+void gen_sve_str(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int imm);
25
+
26
#endif /* TARGET_ARM_TRANSLATE_A64_H */
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
31
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(UCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz,
32
* The load should begin at the address Rn + IMM.
33
*/
34
35
-static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
36
+void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
37
+ int len, int rn, int imm)
38
{
39
int len_align = QEMU_ALIGN_DOWN(len, 8);
40
int len_remain = len % 8;
41
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
42
t0 = tcg_temp_new_i64();
43
for (i = 0; i < len_align; i += 8) {
44
tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
45
- tcg_gen_st_i64(t0, cpu_env, vofs + i);
46
+ tcg_gen_st_i64(t0, base, vofs + i);
47
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
48
}
49
tcg_temp_free_i64(t0);
50
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
51
clean_addr = new_tmp_a64_local(s);
52
tcg_gen_mov_i64(clean_addr, t0);
53
54
+ if (base != cpu_env) {
55
+ TCGv_ptr b = tcg_temp_local_new_ptr();
56
+ tcg_gen_mov_ptr(b, base);
57
+ base = b;
58
+ }
59
+
60
gen_set_label(loop);
61
62
t0 = tcg_temp_new_i64();
63
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
64
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
65
66
tp = tcg_temp_new_ptr();
67
- tcg_gen_add_ptr(tp, cpu_env, i);
68
+ tcg_gen_add_ptr(tp, base, i);
69
tcg_gen_addi_ptr(i, i, 8);
70
tcg_gen_st_i64(t0, tp, vofs);
71
tcg_temp_free_ptr(tp);
72
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
73
74
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
75
tcg_temp_free_ptr(i);
76
+
77
+ if (base != cpu_env) {
78
+ tcg_temp_free_ptr(base);
79
+ assert(len_remain == 0);
80
+ }
81
}
82
83
/*
84
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
85
default:
86
g_assert_not_reached();
87
}
88
- tcg_gen_st_i64(t0, cpu_env, vofs + len_align);
89
+ tcg_gen_st_i64(t0, base, vofs + len_align);
90
tcg_temp_free_i64(t0);
91
}
92
}
93
94
/* Similarly for stores. */
95
-static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
96
+void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
97
+ int len, int rn, int imm)
98
{
99
int len_align = QEMU_ALIGN_DOWN(len, 8);
100
int len_remain = len % 8;
101
@@ -XXX,XX +XXX,XX @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
102
103
t0 = tcg_temp_new_i64();
104
for (i = 0; i < len_align; i += 8) {
105
- tcg_gen_ld_i64(t0, cpu_env, vofs + i);
106
+ tcg_gen_ld_i64(t0, base, vofs + i);
107
tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ);
108
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
109
}
110
@@ -XXX,XX +XXX,XX @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
111
clean_addr = new_tmp_a64_local(s);
112
tcg_gen_mov_i64(clean_addr, t0);
113
114
+ if (base != cpu_env) {
115
+ TCGv_ptr b = tcg_temp_local_new_ptr();
116
+ tcg_gen_mov_ptr(b, base);
117
+ base = b;
118
+ }
119
+
120
gen_set_label(loop);
121
122
t0 = tcg_temp_new_i64();
123
tp = tcg_temp_new_ptr();
124
- tcg_gen_add_ptr(tp, cpu_env, i);
125
+ tcg_gen_add_ptr(tp, base, i);
126
tcg_gen_ld_i64(t0, tp, vofs);
127
tcg_gen_addi_ptr(i, i, 8);
128
tcg_temp_free_ptr(tp);
129
@@ -XXX,XX +XXX,XX @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
130
131
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
132
tcg_temp_free_ptr(i);
133
+
134
+ if (base != cpu_env) {
135
+ tcg_temp_free_ptr(base);
136
+ assert(len_remain == 0);
137
+ }
138
}
139
140
/* Predicate register stores can be any multiple of 2. */
141
if (len_remain) {
142
t0 = tcg_temp_new_i64();
143
- tcg_gen_ld_i64(t0, cpu_env, vofs + len_align);
144
+ tcg_gen_ld_i64(t0, base, vofs + len_align);
145
146
switch (len_remain) {
147
case 2:
148
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_zri(DisasContext *s, arg_rri *a)
149
if (sve_access_check(s)) {
150
int size = vec_full_reg_size(s);
151
int off = vec_full_reg_offset(s, a->rd);
152
- do_ldr(s, off, size, a->rn, a->imm * size);
153
+ gen_sve_ldr(s, cpu_env, off, size, a->rn, a->imm * size);
154
}
155
return true;
156
}
157
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_pri(DisasContext *s, arg_rri *a)
158
if (sve_access_check(s)) {
159
int size = pred_full_reg_size(s);
160
int off = pred_full_reg_offset(s, a->rd);
161
- do_ldr(s, off, size, a->rn, a->imm * size);
162
+ gen_sve_ldr(s, cpu_env, off, size, a->rn, a->imm * size);
163
}
164
return true;
165
}
166
@@ -XXX,XX +XXX,XX @@ static bool trans_STR_zri(DisasContext *s, arg_rri *a)
167
if (sve_access_check(s)) {
168
int size = vec_full_reg_size(s);
169
int off = vec_full_reg_offset(s, a->rd);
170
- do_str(s, off, size, a->rn, a->imm * size);
171
+ gen_sve_str(s, cpu_env, off, size, a->rn, a->imm * size);
172
}
173
return true;
174
}
175
@@ -XXX,XX +XXX,XX @@ static bool trans_STR_pri(DisasContext *s, arg_rri *a)
176
if (sve_access_check(s)) {
177
int size = pred_full_reg_size(s);
178
int off = pred_full_reg_offset(s, a->rd);
179
- do_str(s, off, size, a->rn, a->imm * size);
180
+ gen_sve_str(s, cpu_env, off, size, a->rn, a->imm * size);
181
}
182
return true;
183
}
184
--
185
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
We can reuse the SVE functions for LDR and STR, passing in the
4
base of the ZA vector and a zero offset.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-23-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme.decode | 7 +++++++
12
target/arm/translate-sme.c | 24 ++++++++++++++++++++++++
13
2 files changed, 31 insertions(+)
14
15
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme.decode
18
+++ b/target/arm/sme.decode
19
@@ -XXX,XX +XXX,XX @@ LDST1 1110000 0 esz:2 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
20
&ldst rs=%mova_rs
21
LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
22
&ldst esz=4 rs=%mova_rs
23
+
24
+&ldstr rv rn imm
25
+@ldstr ....... ... . ...... .. ... rn:5 . imm:4 \
26
+ &ldstr rv=%mova_rs
27
+
28
+LDR 1110000 100 0 000000 .. 000 ..... 0 .... @ldstr
29
+STR 1110000 100 1 000000 .. 000 ..... 0 .... @ldstr
30
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-sme.c
33
+++ b/target/arm/translate-sme.c
34
@@ -XXX,XX +XXX,XX @@ static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
35
tcg_temp_free_i64(addr);
36
return true;
37
}
38
+
39
+typedef void GenLdStR(DisasContext *, TCGv_ptr, int, int, int, int);
40
+
41
+static bool do_ldst_r(DisasContext *s, arg_ldstr *a, GenLdStR *fn)
42
+{
43
+ int svl = streaming_vec_reg_size(s);
44
+ int imm = a->imm;
45
+ TCGv_ptr base;
46
+
47
+ if (!sme_za_enabled_check(s)) {
48
+ return true;
49
+ }
50
+
51
+ /* ZA[n] equates to ZA0H.B[n]. */
52
+ base = get_tile_rowcol(s, MO_8, a->rv, imm, false);
53
+
54
+ fn(s, base, 0, svl, a->rn, imm * svl);
55
+
56
+ tcg_temp_free_ptr(base);
57
+ return true;
58
+}
59
+
60
+TRANS_FEAT(LDR, aa64_sme, do_ldst_r, a, gen_sve_ldr)
61
+TRANS_FEAT(STR, aa64_sme, do_ldst_r, a, gen_sve_str)
62
--
63
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20220708151540.18136-25-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/helper-sme.h | 5 +++
9
target/arm/sme.decode | 9 +++++
10
target/arm/sme_helper.c | 69 ++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-sme.c | 32 ++++++++++++++++++
12
4 files changed, 115 insertions(+)
13
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sme.h
17
+++ b/target/arm/helper-sme.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sme_addha_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
+
23
+DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
24
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
27
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/sme.decode
30
+++ b/target/arm/sme.decode
31
@@ -XXX,XX +XXX,XX @@ ADDHA_s 11000000 10 01000 0 ... ... ..... 000 .. @adda_32
32
ADDVA_s 11000000 10 01000 1 ... ... ..... 000 .. @adda_32
33
ADDHA_d 11000000 11 01000 0 ... ... ..... 00 ... @adda_64
34
ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
35
+
36
+### SME Outer Product
37
+
38
+&op zad zn zm pm pn sub:bool
39
+@op_32 ........ ... zm:5 pm:3 pn:3 zn:5 sub:1 .. zad:2 &op
40
+@op_64 ........ ... zm:5 pm:3 pn:3 zn:5 sub:1 . zad:3 &op
41
+
42
+FMOPA_s 10000000 100 ..... ... ... ..... . 00 .. @op_32
43
+FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
44
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/sme_helper.c
47
+++ b/target/arm/sme_helper.c
48
@@ -XXX,XX +XXX,XX @@
49
#include "exec/cpu_ldst.h"
50
#include "exec/exec-all.h"
51
#include "qemu/int128.h"
52
+#include "fpu/softfloat.h"
53
#include "vec_internal.h"
54
#include "sve_ldst_internal.h"
55
56
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_addva_d)(void *vzda, void *vzn, void *vpn,
57
}
58
}
59
}
60
+
61
+void HELPER(sme_fmopa_s)(void *vza, void *vzn, void *vzm, void *vpn,
62
+ void *vpm, void *vst, uint32_t desc)
63
+{
64
+ intptr_t row, col, oprsz = simd_maxsz(desc);
65
+ uint32_t neg = simd_data(desc) << 31;
66
+ uint16_t *pn = vpn, *pm = vpm;
67
+ float_status fpst;
68
+
69
+ /*
70
+ * Make a copy of float_status because this operation does not
71
+ * update the cumulative fp exception status. It also produces
72
+ * default nans.
73
+ */
74
+ fpst = *(float_status *)vst;
75
+ set_default_nan_mode(true, &fpst);
76
+
77
+ for (row = 0; row < oprsz; ) {
78
+ uint16_t pa = pn[H2(row >> 4)];
79
+ do {
80
+ if (pa & 1) {
81
+ void *vza_row = vza + tile_vslice_offset(row);
82
+ uint32_t n = *(uint32_t *)(vzn + H1_4(row)) ^ neg;
83
+
84
+ for (col = 0; col < oprsz; ) {
85
+ uint16_t pb = pm[H2(col >> 4)];
86
+ do {
87
+ if (pb & 1) {
88
+ uint32_t *a = vza_row + H1_4(col);
89
+ uint32_t *m = vzm + H1_4(col);
90
+ *a = float32_muladd(n, *m, *a, 0, vst);
91
+ }
92
+ col += 4;
93
+ pb >>= 4;
94
+ } while (col & 15);
95
+ }
96
+ }
97
+ row += 4;
98
+ pa >>= 4;
99
+ } while (row & 15);
100
+ }
101
+}
102
+
103
+void HELPER(sme_fmopa_d)(void *vza, void *vzn, void *vzm, void *vpn,
104
+ void *vpm, void *vst, uint32_t desc)
105
+{
106
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
107
+ uint64_t neg = (uint64_t)simd_data(desc) << 63;
108
+ uint64_t *za = vza, *zn = vzn, *zm = vzm;
109
+ uint8_t *pn = vpn, *pm = vpm;
110
+ float_status fpst = *(float_status *)vst;
111
+
112
+ set_default_nan_mode(true, &fpst);
113
+
114
+ for (row = 0; row < oprsz; ++row) {
115
+ if (pn[H1(row)] & 1) {
116
+ uint64_t *za_row = &za[tile_vslice_index(row)];
117
+ uint64_t n = zn[row] ^ neg;
118
+
119
+ for (col = 0; col < oprsz; ++col) {
120
+ if (pm[H1(col)] & 1) {
121
+ uint64_t *a = &za_row[col];
122
+ *a = float64_muladd(n, zm[col], *a, 0, &fpst);
123
+ }
124
+ }
125
+ }
126
+ }
127
+}
128
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/target/arm/translate-sme.c
131
+++ b/target/arm/translate-sme.c
132
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(ADDHA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addha_s)
133
TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
134
TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
135
TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
136
+
137
+static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
138
+ gen_helper_gvec_5_ptr *fn)
139
+{
140
+ int svl = streaming_vec_reg_size(s);
141
+ uint32_t desc = simd_desc(svl, svl, a->sub);
142
+ TCGv_ptr za, zn, zm, pn, pm, fpst;
143
+
144
+ if (!sme_smza_enabled_check(s)) {
145
+ return true;
146
+ }
147
+
148
+ /* Sum XZR+zad to find ZAd. */
149
+ za = get_tile_rowcol(s, esz, 31, a->zad, false);
150
+ zn = vec_full_reg_ptr(s, a->zn);
151
+ zm = vec_full_reg_ptr(s, a->zm);
152
+ pn = pred_full_reg_ptr(s, a->pn);
153
+ pm = pred_full_reg_ptr(s, a->pm);
154
+ fpst = fpstatus_ptr(FPST_FPCR);
155
+
156
+ fn(za, zn, zm, pn, pm, fpst, tcg_constant_i32(desc));
157
+
158
+ tcg_temp_free_ptr(za);
159
+ tcg_temp_free_ptr(zn);
160
+ tcg_temp_free_ptr(pn);
161
+ tcg_temp_free_ptr(pm);
162
+ tcg_temp_free_ptr(fpst);
163
+ return true;
164
+}
165
+
166
+TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
167
+TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
168
--
169
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20220708151540.18136-26-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/helper-sme.h | 2 ++
9
target/arm/sme.decode | 2 ++
10
target/arm/sme_helper.c | 56 ++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-sme.c | 30 ++++++++++++++++++++
12
4 files changed, 90 insertions(+)
13
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sme.h
17
+++ b/target/arm/helper-sme.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
19
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
21
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
22
+DEF_HELPER_FLAGS_6(sme_bfmopa, TCG_CALL_NO_RWG,
23
+ void, ptr, ptr, ptr, ptr, ptr, i32)
24
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/sme.decode
27
+++ b/target/arm/sme.decode
28
@@ -XXX,XX +XXX,XX @@ ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
29
30
FMOPA_s 10000000 100 ..... ... ... ..... . 00 .. @op_32
31
FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
32
+
33
+BFMOPA 10000001 100 ..... ... ... ..... . 00 .. @op_32
34
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/sme_helper.c
37
+++ b/target/arm/sme_helper.c
38
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_fmopa_d)(void *vza, void *vzn, void *vzm, void *vpn,
39
}
40
}
41
}
42
+
43
+/*
44
+ * Alter PAIR as needed for controlling predicates being false,
45
+ * and for NEG on an enabled row element.
46
+ */
47
+static inline uint32_t f16mop_adj_pair(uint32_t pair, uint32_t pg, uint32_t neg)
48
+{
49
+ /*
50
+ * The pseudocode uses a conditional negate after the conditional zero.
51
+ * It is simpler here to unconditionally negate before conditional zero.
52
+ */
53
+ pair ^= neg;
54
+ if (!(pg & 1)) {
55
+ pair &= 0xffff0000u;
56
+ }
57
+ if (!(pg & 4)) {
58
+ pair &= 0x0000ffffu;
59
+ }
60
+ return pair;
61
+}
62
+
63
+void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
64
+ void *vpm, uint32_t desc)
65
+{
66
+ intptr_t row, col, oprsz = simd_maxsz(desc);
67
+ uint32_t neg = simd_data(desc) * 0x80008000u;
68
+ uint16_t *pn = vpn, *pm = vpm;
69
+
70
+ for (row = 0; row < oprsz; ) {
71
+ uint16_t prow = pn[H2(row >> 4)];
72
+ do {
73
+ void *vza_row = vza + tile_vslice_offset(row);
74
+ uint32_t n = *(uint32_t *)(vzn + H1_4(row));
75
+
76
+ n = f16mop_adj_pair(n, prow, neg);
77
+
78
+ for (col = 0; col < oprsz; ) {
79
+ uint16_t pcol = pm[H2(col >> 4)];
80
+ do {
81
+ if (prow & pcol & 0b0101) {
82
+ uint32_t *a = vza_row + H1_4(col);
83
+ uint32_t m = *(uint32_t *)(vzm + H1_4(col));
84
+
85
+ m = f16mop_adj_pair(m, pcol, 0);
86
+ *a = bfdotadd(*a, n, m);
87
+
88
+ col += 4;
89
+ pcol >>= 4;
90
+ }
91
+ } while (col & 15);
92
+ }
93
+ row += 4;
94
+ prow >>= 4;
95
+ } while (row & 15);
96
+ }
97
+}
98
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/target/arm/translate-sme.c
101
+++ b/target/arm/translate-sme.c
102
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
103
TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
104
TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
105
106
+static bool do_outprod(DisasContext *s, arg_op *a, MemOp esz,
107
+ gen_helper_gvec_5 *fn)
108
+{
109
+ int svl = streaming_vec_reg_size(s);
110
+ uint32_t desc = simd_desc(svl, svl, a->sub);
111
+ TCGv_ptr za, zn, zm, pn, pm;
112
+
113
+ if (!sme_smza_enabled_check(s)) {
114
+ return true;
115
+ }
116
+
117
+ /* Sum XZR+zad to find ZAd. */
118
+ za = get_tile_rowcol(s, esz, 31, a->zad, false);
119
+ zn = vec_full_reg_ptr(s, a->zn);
120
+ zm = vec_full_reg_ptr(s, a->zm);
121
+ pn = pred_full_reg_ptr(s, a->pn);
122
+ pm = pred_full_reg_ptr(s, a->pm);
123
+
124
+ fn(za, zn, zm, pn, pm, tcg_constant_i32(desc));
125
+
126
+ tcg_temp_free_ptr(za);
127
+ tcg_temp_free_ptr(zn);
128
+ tcg_temp_free_ptr(pn);
129
+ tcg_temp_free_ptr(pm);
130
+ return true;
131
+}
132
+
133
static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
134
gen_helper_gvec_5_ptr *fn)
135
{
136
@@ -XXX,XX +XXX,XX @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
137
138
TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
139
TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
140
+
141
+/* TODO: FEAT_EBF16 */
142
+TRANS_FEAT(BFMOPA, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_bfmopa)
143
--
144
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20220708151540.18136-27-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/helper-sme.h | 2 ++
9
target/arm/sme.decode | 1 +
10
target/arm/sme_helper.c | 74 ++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-sme.c | 1 +
12
4 files changed, 78 insertions(+)
13
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sme.h
17
+++ b/target/arm/helper-sme.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
22
+DEF_HELPER_FLAGS_7(sme_fmopa_h, TCG_CALL_NO_RWG,
23
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
24
DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
25
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
26
DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
27
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/sme.decode
30
+++ b/target/arm/sme.decode
31
@@ -XXX,XX +XXX,XX @@ FMOPA_s 10000000 100 ..... ... ... ..... . 00 .. @op_32
32
FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
33
34
BFMOPA 10000001 100 ..... ... ... ..... . 00 .. @op_32
35
+FMOPA_h 10000001 101 ..... ... ... ..... . 00 .. @op_32
36
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/sme_helper.c
39
+++ b/target/arm/sme_helper.c
40
@@ -XXX,XX +XXX,XX @@ static inline uint32_t f16mop_adj_pair(uint32_t pair, uint32_t pg, uint32_t neg)
41
return pair;
42
}
43
44
+static float32 f16_dotadd(float32 sum, uint32_t e1, uint32_t e2,
45
+ float_status *s_std, float_status *s_odd)
46
+{
47
+ float64 e1r = float16_to_float64(e1 & 0xffff, true, s_std);
48
+ float64 e1c = float16_to_float64(e1 >> 16, true, s_std);
49
+ float64 e2r = float16_to_float64(e2 & 0xffff, true, s_std);
50
+ float64 e2c = float16_to_float64(e2 >> 16, true, s_std);
51
+ float64 t64;
52
+ float32 t32;
53
+
54
+ /*
55
+ * The ARM pseudocode function FPDot performs both multiplies
56
+ * and the add with a single rounding operation. Emulate this
57
+ * by performing the first multiply in round-to-odd, then doing
58
+ * the second multiply as fused multiply-add, and rounding to
59
+ * float32 all in one step.
60
+ */
61
+ t64 = float64_mul(e1r, e2r, s_odd);
62
+ t64 = float64r32_muladd(e1c, e2c, t64, 0, s_std);
63
+
64
+ /* This conversion is exact, because we've already rounded. */
65
+ t32 = float64_to_float32(t64, s_std);
66
+
67
+ /* The final accumulation step is not fused. */
68
+ return float32_add(sum, t32, s_std);
69
+}
70
+
71
+void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn,
72
+ void *vpm, void *vst, uint32_t desc)
73
+{
74
+ intptr_t row, col, oprsz = simd_maxsz(desc);
75
+ uint32_t neg = simd_data(desc) * 0x80008000u;
76
+ uint16_t *pn = vpn, *pm = vpm;
77
+ float_status fpst_odd, fpst_std;
78
+
79
+ /*
80
+ * Make a copy of float_status because this operation does not
81
+ * update the cumulative fp exception status. It also produces
82
+ * default nans. Make a second copy with round-to-odd -- see above.
83
+ */
84
+ fpst_std = *(float_status *)vst;
85
+ set_default_nan_mode(true, &fpst_std);
86
+ fpst_odd = fpst_std;
87
+ set_float_rounding_mode(float_round_to_odd, &fpst_odd);
88
+
89
+ for (row = 0; row < oprsz; ) {
90
+ uint16_t prow = pn[H2(row >> 4)];
91
+ do {
92
+ void *vza_row = vza + tile_vslice_offset(row);
93
+ uint32_t n = *(uint32_t *)(vzn + H1_4(row));
94
+
95
+ n = f16mop_adj_pair(n, prow, neg);
96
+
97
+ for (col = 0; col < oprsz; ) {
98
+ uint16_t pcol = pm[H2(col >> 4)];
99
+ do {
100
+ if (prow & pcol & 0b0101) {
101
+ uint32_t *a = vza_row + H1_4(col);
102
+ uint32_t m = *(uint32_t *)(vzm + H1_4(col));
103
+
104
+ m = f16mop_adj_pair(m, pcol, 0);
105
+ *a = f16_dotadd(*a, n, m, &fpst_std, &fpst_odd);
106
+
107
+ col += 4;
108
+ pcol >>= 4;
109
+ }
110
+ } while (col & 15);
111
+ }
112
+ row += 4;
113
+ prow >>= 4;
114
+ } while (row & 15);
115
+ }
116
+}
117
+
118
void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
119
void *vpm, uint32_t desc)
120
{
121
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/target/arm/translate-sme.c
124
+++ b/target/arm/translate-sme.c
125
@@ -XXX,XX +XXX,XX @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
126
return true;
127
}
128
129
+TRANS_FEAT(FMOPA_h, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_h)
130
TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
131
TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
132
133
--
134
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This is SMOPA, SUMOPA, USMOPA_s, UMOPA, for both Int8 and Int16.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220708151540.18136-28-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/helper-sme.h | 16 ++++++++
11
target/arm/sme.decode | 10 +++++
12
target/arm/sme_helper.c | 82 ++++++++++++++++++++++++++++++++++++++
13
target/arm/translate-sme.c | 10 +++++
14
4 files changed, 118 insertions(+)
15
16
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper-sme.h
19
+++ b/target/arm/helper-sme.h
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
21
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
22
DEF_HELPER_FLAGS_6(sme_bfmopa, TCG_CALL_NO_RWG,
23
void, ptr, ptr, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_6(sme_smopa_s, TCG_CALL_NO_RWG,
25
+ void, ptr, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_6(sme_umopa_s, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_6(sme_sumopa_s, TCG_CALL_NO_RWG,
29
+ void, ptr, ptr, ptr, ptr, ptr, i32)
30
+DEF_HELPER_FLAGS_6(sme_usmopa_s, TCG_CALL_NO_RWG,
31
+ void, ptr, ptr, ptr, ptr, ptr, i32)
32
+DEF_HELPER_FLAGS_6(sme_smopa_d, TCG_CALL_NO_RWG,
33
+ void, ptr, ptr, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_6(sme_umopa_d, TCG_CALL_NO_RWG,
35
+ void, ptr, ptr, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_6(sme_sumopa_d, TCG_CALL_NO_RWG,
37
+ void, ptr, ptr, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_6(sme_usmopa_d, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, ptr, ptr, i32)
40
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/sme.decode
43
+++ b/target/arm/sme.decode
44
@@ -XXX,XX +XXX,XX @@ FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
45
46
BFMOPA 10000001 100 ..... ... ... ..... . 00 .. @op_32
47
FMOPA_h 10000001 101 ..... ... ... ..... . 00 .. @op_32
48
+
49
+SMOPA_s 1010000 0 10 0 ..... ... ... ..... . 00 .. @op_32
50
+SUMOPA_s 1010000 0 10 1 ..... ... ... ..... . 00 .. @op_32
51
+USMOPA_s 1010000 1 10 0 ..... ... ... ..... . 00 .. @op_32
52
+UMOPA_s 1010000 1 10 1 ..... ... ... ..... . 00 .. @op_32
53
+
54
+SMOPA_d 1010000 0 11 0 ..... ... ... ..... . 0 ... @op_64
55
+SUMOPA_d 1010000 0 11 1 ..... ... ... ..... . 0 ... @op_64
56
+USMOPA_d 1010000 1 11 0 ..... ... ... ..... . 0 ... @op_64
57
+UMOPA_d 1010000 1 11 1 ..... ... ... ..... . 0 ... @op_64
58
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/sme_helper.c
61
+++ b/target/arm/sme_helper.c
62
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
63
} while (row & 15);
64
}
65
}
66
+
67
+typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
68
+
69
+static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
70
+ uint8_t *pn, uint8_t *pm,
71
+ uint32_t desc, IMOPFn *fn)
72
+{
73
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
74
+ bool neg = simd_data(desc);
75
+
76
+ for (row = 0; row < oprsz; ++row) {
77
+ uint8_t pa = pn[H1(row)];
78
+ uint64_t *za_row = &za[tile_vslice_index(row)];
79
+ uint64_t n = zn[row];
80
+
81
+ for (col = 0; col < oprsz; ++col) {
82
+ uint8_t pb = pm[H1(col)];
83
+ uint64_t *a = &za_row[col];
84
+
85
+ *a = fn(n, zm[col], *a, pa & pb, neg);
86
+ }
87
+ }
88
+}
89
+
90
+#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
91
+static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
92
+{ \
93
+ uint32_t sum0 = 0, sum1 = 0; \
94
+ /* Apply P to N as a mask, making the inactive elements 0. */ \
95
+ n &= expand_pred_b(p); \
96
+ sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
97
+ sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
98
+ sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
99
+ sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
100
+ sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
101
+ sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
102
+ sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
103
+ sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
104
+ if (neg) { \
105
+ sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
106
+ } else { \
107
+ sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
108
+ } \
109
+ return ((uint64_t)sum1 << 32) | sum0; \
110
+}
111
+
112
+#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
113
+static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
114
+{ \
115
+ uint64_t sum = 0; \
116
+ /* Apply P to N as a mask, making the inactive elements 0. */ \
117
+ n &= expand_pred_h(p); \
118
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
119
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
120
+ sum += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
121
+ sum += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
122
+ return neg ? a - sum : a + sum; \
123
+}
124
+
125
+DEF_IMOP_32(smopa_s, int8_t, int8_t)
126
+DEF_IMOP_32(umopa_s, uint8_t, uint8_t)
127
+DEF_IMOP_32(sumopa_s, int8_t, uint8_t)
128
+DEF_IMOP_32(usmopa_s, uint8_t, int8_t)
129
+
130
+DEF_IMOP_64(smopa_d, int16_t, int16_t)
131
+DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
132
+DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
133
+DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
134
+
135
+#define DEF_IMOPH(NAME) \
136
+ void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
137
+ void *vpm, uint32_t desc) \
138
+ { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
139
+
140
+DEF_IMOPH(smopa_s)
141
+DEF_IMOPH(umopa_s)
142
+DEF_IMOPH(sumopa_s)
143
+DEF_IMOPH(usmopa_s)
144
+DEF_IMOPH(smopa_d)
145
+DEF_IMOPH(umopa_d)
146
+DEF_IMOPH(sumopa_d)
147
+DEF_IMOPH(usmopa_d)
148
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/target/arm/translate-sme.c
151
+++ b/target/arm/translate-sme.c
152
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_f
153
154
/* TODO: FEAT_EBF16 */
155
TRANS_FEAT(BFMOPA, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_bfmopa)
156
+
157
+TRANS_FEAT(SMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_smopa_s)
158
+TRANS_FEAT(UMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_umopa_s)
159
+TRANS_FEAT(SUMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_sumopa_s)
160
+TRANS_FEAT(USMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_usmopa_s)
161
+
162
+TRANS_FEAT(SMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_smopa_d)
163
+TRANS_FEAT(UMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_umopa_d)
164
+TRANS_FEAT(SUMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_sumopa_d)
165
+TRANS_FEAT(USMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_usmopa_d)
166
--
167
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This is an SVE instruction that operates using the SVE vector
4
length but that it is present only if SME is implemented.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-29-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sve.decode | 20 +++++++++++++
12
target/arm/translate-sve.c | 57 ++++++++++++++++++++++++++++++++++++++
13
2 files changed, 77 insertions(+)
14
15
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sve.decode
18
+++ b/target/arm/sve.decode
19
@@ -XXX,XX +XXX,XX @@ BFMLALT_zzxw 01100100 11 1 ..... 0100.1 ..... ..... @rrxr_3a esz=2
20
21
### SVE2 floating-point bfloat16 dot-product (indexed)
22
BFDOT_zzxz 01100100 01 1 ..... 010000 ..... ..... @rrxr_2 esz=2
23
+
24
+### SVE broadcast predicate element
25
+
26
+&psel esz pd pn pm rv imm
27
+%psel_rv 16:2 !function=plus_12
28
+%psel_imm_b 22:2 19:2
29
+%psel_imm_h 22:2 20:1
30
+%psel_imm_s 22:2
31
+%psel_imm_d 23:1
32
+@psel ........ .. . ... .. .. pn:4 . pm:4 . pd:4 \
33
+ &psel rv=%psel_rv
34
+
35
+PSEL 00100101 .. 1 ..1 .. 01 .... 0 .... 0 .... \
36
+ @psel esz=0 imm=%psel_imm_b
37
+PSEL 00100101 .. 1 .10 .. 01 .... 0 .... 0 .... \
38
+ @psel esz=1 imm=%psel_imm_h
39
+PSEL 00100101 .. 1 100 .. 01 .... 0 .... 0 .... \
40
+ @psel esz=2 imm=%psel_imm_s
41
+PSEL 00100101 .1 1 000 .. 01 .... 0 .... 0 .... \
42
+ @psel esz=3 imm=%psel_imm_d
43
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/translate-sve.c
46
+++ b/target/arm/translate-sve.c
47
@@ -XXX,XX +XXX,XX @@ static bool do_BFMLAL_zzxw(DisasContext *s, arg_rrxr_esz *a, bool sel)
48
49
TRANS_FEAT(BFMLALB_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, false)
50
TRANS_FEAT(BFMLALT_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, true)
51
+
52
+static bool trans_PSEL(DisasContext *s, arg_psel *a)
53
+{
54
+ int vl = vec_full_reg_size(s);
55
+ int pl = pred_gvec_reg_size(s);
56
+ int elements = vl >> a->esz;
57
+ TCGv_i64 tmp, didx, dbit;
58
+ TCGv_ptr ptr;
59
+
60
+ if (!dc_isar_feature(aa64_sme, s)) {
61
+ return false;
62
+ }
63
+ if (!sve_access_check(s)) {
64
+ return true;
65
+ }
66
+
67
+ tmp = tcg_temp_new_i64();
68
+ dbit = tcg_temp_new_i64();
69
+ didx = tcg_temp_new_i64();
70
+ ptr = tcg_temp_new_ptr();
71
+
72
+ /* Compute the predicate element. */
73
+ tcg_gen_addi_i64(tmp, cpu_reg(s, a->rv), a->imm);
74
+ if (is_power_of_2(elements)) {
75
+ tcg_gen_andi_i64(tmp, tmp, elements - 1);
76
+ } else {
77
+ tcg_gen_remu_i64(tmp, tmp, tcg_constant_i64(elements));
78
+ }
79
+
80
+ /* Extract the predicate byte and bit indices. */
81
+ tcg_gen_shli_i64(tmp, tmp, a->esz);
82
+ tcg_gen_andi_i64(dbit, tmp, 7);
83
+ tcg_gen_shri_i64(didx, tmp, 3);
84
+ if (HOST_BIG_ENDIAN) {
85
+ tcg_gen_xori_i64(didx, didx, 7);
86
+ }
87
+
88
+ /* Load the predicate word. */
89
+ tcg_gen_trunc_i64_ptr(ptr, didx);
90
+ tcg_gen_add_ptr(ptr, ptr, cpu_env);
91
+ tcg_gen_ld8u_i64(tmp, ptr, pred_full_reg_offset(s, a->pm));
92
+
93
+ /* Extract the predicate bit and replicate to MO_64. */
94
+ tcg_gen_shr_i64(tmp, tmp, dbit);
95
+ tcg_gen_andi_i64(tmp, tmp, 1);
96
+ tcg_gen_neg_i64(tmp, tmp);
97
+
98
+ /* Apply to either copy the source, or write zeros. */
99
+ tcg_gen_gvec_ands(MO_64, pred_full_reg_offset(s, a->pd),
100
+ pred_full_reg_offset(s, a->pn), tmp, pl, pl);
101
+
102
+ tcg_temp_free_i64(tmp);
103
+ tcg_temp_free_i64(dbit);
104
+ tcg_temp_free_i64(didx);
105
+ tcg_temp_free_ptr(ptr);
106
+ return true;
107
+}
108
--
109
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This is an SVE instruction that operates using the SVE vector
4
length but that it is present only if SME is implemented.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-30-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper-sve.h | 2 ++
12
target/arm/sve.decode | 1 +
13
target/arm/sve_helper.c | 16 ++++++++++++++++
14
target/arm/translate-sve.c | 2 ++
15
4 files changed, 21 insertions(+)
16
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-sve.h
20
+++ b/target/arm/helper-sve.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_revh_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
23
DEF_HELPER_FLAGS_4(sve_revw_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
25
+DEF_HELPER_FLAGS_4(sme_revd_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
+
27
DEF_HELPER_FLAGS_4(sve_rbit_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
DEF_HELPER_FLAGS_4(sve_rbit_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
DEF_HELPER_FLAGS_4(sve_rbit_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/sve.decode
33
+++ b/target/arm/sve.decode
34
@@ -XXX,XX +XXX,XX @@ REVB 00000101 .. 1001 00 100 ... ..... ..... @rd_pg_rn
35
REVH 00000101 .. 1001 01 100 ... ..... ..... @rd_pg_rn
36
REVW 00000101 .. 1001 10 100 ... ..... ..... @rd_pg_rn
37
RBIT 00000101 .. 1001 11 100 ... ..... ..... @rd_pg_rn
38
+REVD 00000101 00 1011 10 100 ... ..... ..... @rd_pg_rn_e0
39
40
# SVE vector splice (predicated, destructive)
41
SPLICE 00000101 .. 101 100 100 ... ..... ..... @rdn_pg_rm
42
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/sve_helper.c
45
+++ b/target/arm/sve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_ZPZ_D(sve_revh_d, uint64_t, hswap64)
47
48
DO_ZPZ_D(sve_revw_d, uint64_t, wswap64)
49
50
+void HELPER(sme_revd_q)(void *vd, void *vn, void *vg, uint32_t desc)
51
+{
52
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
53
+ uint64_t *d = vd, *n = vn;
54
+ uint8_t *pg = vg;
55
+
56
+ for (i = 0; i < opr_sz; i += 2) {
57
+ if (pg[H1(i)] & 1) {
58
+ uint64_t n0 = n[i + 0];
59
+ uint64_t n1 = n[i + 1];
60
+ d[i + 0] = n1;
61
+ d[i + 1] = n0;
62
+ }
63
+ }
64
+}
65
+
66
DO_ZPZ(sve_rbit_b, uint8_t, H1, revbit8)
67
DO_ZPZ(sve_rbit_h, uint16_t, H1_2, revbit16)
68
DO_ZPZ(sve_rbit_s, uint32_t, H1_4, revbit32)
69
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/translate-sve.c
72
+++ b/target/arm/translate-sve.c
73
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(REVH, aa64_sve, gen_gvec_ool_arg_zpz, revh_fns[a->esz], a, 0)
74
TRANS_FEAT(REVW, aa64_sve, gen_gvec_ool_arg_zpz,
75
a->esz == 3 ? gen_helper_sve_revw_d : NULL, a, 0)
76
77
+TRANS_FEAT(REVD, aa64_sme, gen_gvec_ool_arg_zpz, gen_helper_sme_revd_q, a, 0)
78
+
79
TRANS_FEAT(SPLICE, aa64_sve, gen_gvec_ool_arg_zpzz,
80
gen_helper_sve_splice, a, a->esz)
81
82
--
83
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This is an SVE instruction that operates using the SVE vector
4
length but that it is present only if SME is implemented.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-31-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.h | 18 +++++++
12
target/arm/sve.decode | 5 ++
13
target/arm/translate-sve.c | 102 +++++++++++++++++++++++++++++++++++++
14
target/arm/vec_helper.c | 24 +++++++++
15
4 files changed, 149 insertions(+)
16
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
20
+++ b/target/arm/helper.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(gvec_bfmlal, TCG_CALL_NO_RWG,
22
DEF_HELPER_FLAGS_6(gvec_bfmlal_idx, TCG_CALL_NO_RWG,
23
void, ptr, ptr, ptr, ptr, ptr, i32)
24
25
+DEF_HELPER_FLAGS_5(gvec_sclamp_b, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_5(gvec_sclamp_h, TCG_CALL_NO_RWG,
28
+ void, ptr, ptr, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_5(gvec_sclamp_s, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_5(gvec_sclamp_d, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+
34
+DEF_HELPER_FLAGS_5(gvec_uclamp_b, TCG_CALL_NO_RWG,
35
+ void, ptr, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_5(gvec_uclamp_h, TCG_CALL_NO_RWG,
37
+ void, ptr, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_5(gvec_uclamp_s, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_5(gvec_uclamp_d, TCG_CALL_NO_RWG,
41
+ void, ptr, ptr, ptr, ptr, i32)
42
+
43
#ifdef TARGET_AARCH64
44
#include "helper-a64.h"
45
#include "helper-sve.h"
46
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/sve.decode
49
+++ b/target/arm/sve.decode
50
@@ -XXX,XX +XXX,XX @@ PSEL 00100101 .. 1 100 .. 01 .... 0 .... 0 .... \
51
@psel esz=2 imm=%psel_imm_s
52
PSEL 00100101 .1 1 000 .. 01 .... 0 .... 0 .... \
53
@psel esz=3 imm=%psel_imm_d
54
+
55
+### SVE clamp
56
+
57
+SCLAMP 01000100 .. 0 ..... 110000 ..... ..... @rda_rn_rm
58
+UCLAMP 01000100 .. 0 ..... 110001 ..... ..... @rda_rn_rm
59
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/translate-sve.c
62
+++ b/target/arm/translate-sve.c
63
@@ -XXX,XX +XXX,XX @@ static bool trans_PSEL(DisasContext *s, arg_psel *a)
64
tcg_temp_free_ptr(ptr);
65
return true;
66
}
67
+
68
+static void gen_sclamp_i32(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_i32 a)
69
+{
70
+ tcg_gen_smax_i32(d, a, n);
71
+ tcg_gen_smin_i32(d, d, m);
72
+}
73
+
74
+static void gen_sclamp_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 a)
75
+{
76
+ tcg_gen_smax_i64(d, a, n);
77
+ tcg_gen_smin_i64(d, d, m);
78
+}
79
+
80
+static void gen_sclamp_vec(unsigned vece, TCGv_vec d, TCGv_vec n,
81
+ TCGv_vec m, TCGv_vec a)
82
+{
83
+ tcg_gen_smax_vec(vece, d, a, n);
84
+ tcg_gen_smin_vec(vece, d, d, m);
85
+}
86
+
87
+static void gen_sclamp(unsigned vece, uint32_t d, uint32_t n, uint32_t m,
88
+ uint32_t a, uint32_t oprsz, uint32_t maxsz)
89
+{
90
+ static const TCGOpcode vecop[] = {
91
+ INDEX_op_smin_vec, INDEX_op_smax_vec, 0
92
+ };
93
+ static const GVecGen4 ops[4] = {
94
+ { .fniv = gen_sclamp_vec,
95
+ .fno = gen_helper_gvec_sclamp_b,
96
+ .opt_opc = vecop,
97
+ .vece = MO_8 },
98
+ { .fniv = gen_sclamp_vec,
99
+ .fno = gen_helper_gvec_sclamp_h,
100
+ .opt_opc = vecop,
101
+ .vece = MO_16 },
102
+ { .fni4 = gen_sclamp_i32,
103
+ .fniv = gen_sclamp_vec,
104
+ .fno = gen_helper_gvec_sclamp_s,
105
+ .opt_opc = vecop,
106
+ .vece = MO_32 },
107
+ { .fni8 = gen_sclamp_i64,
108
+ .fniv = gen_sclamp_vec,
109
+ .fno = gen_helper_gvec_sclamp_d,
110
+ .opt_opc = vecop,
111
+ .vece = MO_64,
112
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64 }
113
+ };
114
+ tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, &ops[vece]);
115
+}
116
+
117
+TRANS_FEAT(SCLAMP, aa64_sme, gen_gvec_fn_arg_zzzz, gen_sclamp, a)
118
+
119
+static void gen_uclamp_i32(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_i32 a)
120
+{
121
+ tcg_gen_umax_i32(d, a, n);
122
+ tcg_gen_umin_i32(d, d, m);
123
+}
124
+
125
+static void gen_uclamp_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 a)
126
+{
127
+ tcg_gen_umax_i64(d, a, n);
128
+ tcg_gen_umin_i64(d, d, m);
129
+}
130
+
131
+static void gen_uclamp_vec(unsigned vece, TCGv_vec d, TCGv_vec n,
132
+ TCGv_vec m, TCGv_vec a)
133
+{
134
+ tcg_gen_umax_vec(vece, d, a, n);
135
+ tcg_gen_umin_vec(vece, d, d, m);
136
+}
137
+
138
+static void gen_uclamp(unsigned vece, uint32_t d, uint32_t n, uint32_t m,
139
+ uint32_t a, uint32_t oprsz, uint32_t maxsz)
140
+{
141
+ static const TCGOpcode vecop[] = {
142
+ INDEX_op_umin_vec, INDEX_op_umax_vec, 0
143
+ };
144
+ static const GVecGen4 ops[4] = {
145
+ { .fniv = gen_uclamp_vec,
146
+ .fno = gen_helper_gvec_uclamp_b,
147
+ .opt_opc = vecop,
148
+ .vece = MO_8 },
149
+ { .fniv = gen_uclamp_vec,
150
+ .fno = gen_helper_gvec_uclamp_h,
151
+ .opt_opc = vecop,
152
+ .vece = MO_16 },
153
+ { .fni4 = gen_uclamp_i32,
154
+ .fniv = gen_uclamp_vec,
155
+ .fno = gen_helper_gvec_uclamp_s,
156
+ .opt_opc = vecop,
157
+ .vece = MO_32 },
158
+ { .fni8 = gen_uclamp_i64,
159
+ .fniv = gen_uclamp_vec,
160
+ .fno = gen_helper_gvec_uclamp_d,
161
+ .opt_opc = vecop,
162
+ .vece = MO_64,
163
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64 }
164
+ };
165
+ tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, &ops[vece]);
166
+}
167
+
168
+TRANS_FEAT(UCLAMP, aa64_sme, gen_gvec_fn_arg_zzzz, gen_uclamp, a)
169
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
170
index XXXXXXX..XXXXXXX 100644
171
--- a/target/arm/vec_helper.c
172
+++ b/target/arm/vec_helper.c
173
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_bfmlal_idx)(void *vd, void *vn, void *vm,
174
}
175
clear_tail(d, opr_sz, simd_maxsz(desc));
176
}
177
+
178
+#define DO_CLAMP(NAME, TYPE) \
179
+void HELPER(NAME)(void *d, void *n, void *m, void *a, uint32_t desc) \
180
+{ \
181
+ intptr_t i, opr_sz = simd_oprsz(desc); \
182
+ for (i = 0; i < opr_sz; i += sizeof(TYPE)) { \
183
+ TYPE aa = *(TYPE *)(a + i); \
184
+ TYPE nn = *(TYPE *)(n + i); \
185
+ TYPE mm = *(TYPE *)(m + i); \
186
+ TYPE dd = MIN(MAX(aa, nn), mm); \
187
+ *(TYPE *)(d + i) = dd; \
188
+ } \
189
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
190
+}
191
+
192
+DO_CLAMP(gvec_sclamp_b, int8_t)
193
+DO_CLAMP(gvec_sclamp_h, int16_t)
194
+DO_CLAMP(gvec_sclamp_s, int32_t)
195
+DO_CLAMP(gvec_sclamp_d, int64_t)
196
+
197
+DO_CLAMP(gvec_uclamp_b, uint8_t)
198
+DO_CLAMP(gvec_uclamp_h, uint16_t)
199
+DO_CLAMP(gvec_uclamp_s, uint32_t)
200
+DO_CLAMP(gvec_uclamp_d, uint64_t)
201
--
202
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
ui/cocoa.m:1188:44: warning: 'openFile:' is deprecated: first deprecated in macOS 11.0 - Use -[NSWorkspace openURL:] instead.
4
[-Wdeprecated-declarations]
5
if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
6
^
7
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWorkspace.h:350:1: note:
8
'openFile:' has been explicitly marked deprecated here
9
- (BOOL)openFile:(NSString *)fullPath API_DEPRECATED("Use -[NSWorkspace openURL:] instead.", macos(10.0, 11.0));
10
^
11
12
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20210102150718.47618-1-r.bolshakov@yadro.com
5
Message-id: 20220708151540.18136-34-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
16
---
8
linux-user/aarch64/target_cpu.h | 5 ++++-
17
ui/cocoa.m | 5 ++++-
9
1 file changed, 4 insertions(+), 1 deletion(-)
18
1 file changed, 4 insertions(+), 1 deletion(-)
10
19
11
diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
12
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
13
--- a/linux-user/aarch64/target_cpu.h
22
--- a/ui/cocoa.m
14
+++ b/linux-user/aarch64/target_cpu.h
23
+++ b/ui/cocoa.m
15
@@ -XXX,XX +XXX,XX @@ static inline void cpu_clone_regs_parent(CPUARMState *env, unsigned flags)
24
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
16
25
/* Where to look for local files */
17
static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
26
NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
18
{
27
NSString *full_file_path;
19
- /* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
28
+ NSURL *full_file_url;
20
+ /*
29
21
+ * Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
30
/* iterate thru the possible paths until the file is found */
22
* different from AArch32 Linux, which uses TPIDRRO.
31
int index;
23
*/
32
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
24
env->cp15.tpidr_el[0] = newtls;
33
full_file_path = [full_file_path stringByDeletingLastPathComponent];
25
+ /* TPIDR2_EL0 is cleared with CLONE_SETTLS. */
34
full_file_path = [NSString stringWithFormat: @"%@/%@%@", full_file_path,
26
+ env->cp15.tpidr2_el0 = 0;
35
path_array[index], filename];
27
}
36
- if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
28
37
+ full_file_url = [NSURL fileURLWithPath: full_file_path
29
static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
38
+ isDirectory: false];
39
+ if ([[NSWorkspace sharedWorkspace] openURL: full_file_url] == YES) {
40
return;
41
}
42
}
30
--
43
--
31
2.25.1
44
2.20.1
45
46
diff view generated by jsdifflib