1
I don't have anything else queued up at the moment, so this is just
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
Richard's SME patches.
3
2
4
-- PMM
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
5
6
The following changes since commit 63b38f6c85acd312c2cab68554abf33adf4ee2b3:
7
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)
9
4
10
are available in the Git repository at:
5
are available in the Git repository at:
11
6
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220711
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
13
8
14
for you to fetch changes up to f9982ceaf26df27d15547a3a7990a95019e9e3a8:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
15
10
16
linux-user/aarch64: Add SME related hwcap entries (2022-07-11 13:43:52 +0100)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
17
12
18
----------------------------------------------------------------
13
----------------------------------------------------------------
19
target-arm:
14
target-arm queue:
20
* Implement SME emulation, for both system and linux-user
15
* Implement FEAT_ECV
16
* STM32L4x5: Implement GPIO device
17
* Fix 32-bit SMOPA
18
* Refactor v7m related code from cpu32.c into its own file
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
21
20
22
----------------------------------------------------------------
21
----------------------------------------------------------------
23
Richard Henderson (45):
22
Inès Varhol (3):
24
target/arm: Handle SME in aarch64_cpu_dump_state
23
hw/gpio: Implement STM32L4x5 GPIO
25
target/arm: Add infrastructure for disas_sme
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
26
target/arm: Trap non-streaming usage when Streaming SVE is active
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
27
target/arm: Mark ADR as non-streaming
28
target/arm: Mark RDFFR, WRFFR, SETFFR as non-streaming
29
target/arm: Mark BDEP, BEXT, BGRP, COMPACT, FEXPA, FTSSEL as non-streaming
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
26
70
docs/system/arm/emulation.rst | 4 +
27
Peter Maydell (9):
71
linux-user/aarch64/target_cpu.h | 5 +-
28
target/arm: Move some register related defines to internals.h
72
linux-user/aarch64/target_prctl.h | 62 +-
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
73
target/arm/cpu.h | 7 +
30
target/arm: use FIELD macro for CNTHCTL bit definitions
74
target/arm/helper-sme.h | 126 ++++
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
75
target/arm/helper-sve.h | 4 +
32
target/arm: Implement new FEAT_ECV trap bits
76
target/arm/helper.h | 18 +
33
target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
77
target/arm/translate-a64.h | 45 ++
34
target/arm: Implement FEAT_ECV CNTPOFF_EL2 handling
78
target/arm/translate.h | 16 +
35
target/arm: Enable FEAT_ECV for 'max' CPU
79
target/arm/sme-fa64.decode | 60 ++
36
hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
80
target/arm/sme.decode | 88 +++
37
81
target/arm/sve.decode | 41 +-
38
Richard Henderson (1):
82
linux-user/aarch64/cpu_loop.c | 9 +
39
target/arm: Fix 32-bit SMOPA
83
linux-user/aarch64/signal.c | 243 ++++++--
40
84
linux-user/elfload.c | 20 +
41
Thomas Huth (1):
85
linux-user/syscall.c | 28 +-
42
target/arm: Move v7m-related code from cpu32.c into a separate file
86
target/arm/cpu.c | 35 +-
43
87
target/arm/cpu64.c | 11 +
44
MAINTAINERS | 1 +
88
target/arm/helper.c | 56 +-
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
89
target/arm/sme_helper.c | 1140 +++++++++++++++++++++++++++++++++++++
46
docs/system/arm/emulation.rst | 1 +
90
target/arm/sve_helper.c | 28 +
47
include/hw/arm/stm32l4x5_soc.h | 2 +
91
target/arm/translate-a64.c | 103 +++-
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
92
target/arm/translate-sme.c | 373 ++++++++++++
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
93
target/arm/translate-sve.c | 393 ++++++++++---
50
include/hw/rtc/sun4v-rtc.h | 2 +-
94
target/arm/translate-vfp.c | 12 +
51
target/arm/cpu-features.h | 10 +
95
target/arm/translate.c | 2 +
52
target/arm/cpu.h | 129 +--------
96
target/arm/vec_helper.c | 24 +
53
target/arm/internals.h | 151 ++++++++++
97
target/arm/meson.build | 3 +
54
hw/arm/stm32l4x5_soc.c | 71 ++++-
98
28 files changed, 2821 insertions(+), 135 deletions(-)
55
hw/gpio/stm32l4x5_gpio.c | 477 ++++++++++++++++++++++++++++++++
99
create mode 100644 target/arm/sme-fa64.decode
56
hw/misc/stm32l4x5_syscfg.c | 1 +
100
create mode 100644 target/arm/sme.decode
57
hw/rtc/sun4v-rtc.c | 2 +-
101
create mode 100644 target/arm/translate-sme.c
58
target/arm/helper.c | 189 ++++++++++++-
59
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++
60
target/arm/tcg/cpu32.c | 261 ------------------
61
target/arm/tcg/cpu64.c | 1 +
62
target/arm/tcg/sme_helper.c | 77 +++---
63
tests/qtest/stm32l4x5_gpio-test.c | 551 +++++++++++++++++++++++++++++++++++++
64
tests/tcg/aarch64/sme-smopa-1.c | 47 ++++
65
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++
66
hw/arm/Kconfig | 3 +-
67
hw/gpio/Kconfig | 3 +
68
hw/gpio/meson.build | 1 +
69
hw/gpio/trace-events | 6 +
70
target/arm/meson.build | 3 +
71
target/arm/tcg/meson.build | 3 +
72
target/arm/trace-events | 1 +
73
tests/qtest/meson.build | 3 +-
74
tests/tcg/aarch64/Makefile.target | 2 +-
75
31 files changed, 1962 insertions(+), 456 deletions(-)
76
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
77
create mode 100644 hw/gpio/stm32l4x5_gpio.c
78
create mode 100644 target/arm/tcg/cpu-v7m.c
79
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
80
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
81
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
82
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
cpu.h has a lot of #defines relating to CPU register fields.
2
Most of these aren't actually used outside target/arm code,
3
so there's no point in cluttering up the cpu.h file with them.
4
Move some easy ones to internals.h.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220708151540.18136-46-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20240301183219.2424889-2-peter.maydell@linaro.org
7
---
10
---
8
linux-user/elfload.c | 20 ++++++++++++++++++++
11
target/arm/cpu.h | 128 -----------------------------------------
9
1 file changed, 20 insertions(+)
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 128 insertions(+), 128 deletions(-)
10
14
11
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/linux-user/elfload.c
17
--- a/target/arm/cpu.h
14
+++ b/linux-user/elfload.c
18
+++ b/target/arm/cpu.h
15
@@ -XXX,XX +XXX,XX @@ enum {
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
16
ARM_HWCAP2_A64_RNG = 1 << 16,
20
uint64_t ctl; /* Timer Control register */
17
ARM_HWCAP2_A64_BTI = 1 << 17,
21
} ARMGenericTimer;
18
ARM_HWCAP2_A64_MTE = 1 << 18,
22
19
+ ARM_HWCAP2_A64_ECV = 1 << 19,
23
-#define VTCR_NSW (1u << 29)
20
+ ARM_HWCAP2_A64_AFP = 1 << 20,
24
-#define VTCR_NSA (1u << 30)
21
+ ARM_HWCAP2_A64_RPRES = 1 << 21,
25
-#define VSTCR_SW VTCR_NSW
22
+ ARM_HWCAP2_A64_MTE3 = 1 << 22,
26
-#define VSTCR_SA VTCR_NSA
23
+ ARM_HWCAP2_A64_SME = 1 << 23,
27
-
24
+ ARM_HWCAP2_A64_SME_I16I64 = 1 << 24,
28
/* Define a maximum sized vector register.
25
+ ARM_HWCAP2_A64_SME_F64F64 = 1 << 25,
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
26
+ ARM_HWCAP2_A64_SME_I8I32 = 1 << 26,
30
* For 64-bit, this is a 2048-bit SVE register.
27
+ ARM_HWCAP2_A64_SME_F16F32 = 1 << 27,
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
28
+ ARM_HWCAP2_A64_SME_B16F32 = 1 << 28,
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
29
+ ARM_HWCAP2_A64_SME_F32F32 = 1 << 29,
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
30
+ ARM_HWCAP2_A64_SME_FA64 = 1 << 30,
34
31
};
35
-/* Bit definitions for CPACR (AArch32 only) */
32
36
-FIELD(CPACR, CP10, 20, 2)
33
#define ELF_HWCAP get_elf_hwcap()
37
-FIELD(CPACR, CP11, 22, 2)
34
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap2(void)
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
35
GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
36
GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
40
-FIELD(CPACR, ASEDIS, 31, 1)
37
GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
41
-
38
+ GET_FEATURE_ID(aa64_sme, (ARM_HWCAP2_A64_SME |
42
-/* Bit definitions for CPACR_EL1 (AArch64 only) */
39
+ ARM_HWCAP2_A64_SME_F32F32 |
43
-FIELD(CPACR_EL1, ZEN, 16, 2)
40
+ ARM_HWCAP2_A64_SME_B16F32 |
44
-FIELD(CPACR_EL1, FPEN, 20, 2)
41
+ ARM_HWCAP2_A64_SME_F16F32 |
45
-FIELD(CPACR_EL1, SMEN, 24, 2)
42
+ ARM_HWCAP2_A64_SME_I8I32));
46
-FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
43
+ GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64);
47
-
44
+ GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64);
48
-/* Bit definitions for HCPTR (AArch32 only) */
45
+ GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64);
49
-FIELD(HCPTR, TCP10, 10, 1)
46
50
-FIELD(HCPTR, TCP11, 11, 1)
47
return hwcaps;
51
-FIELD(HCPTR, TASE, 15, 1)
48
}
52
-FIELD(HCPTR, TTA, 20, 1)
53
-FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
54
-FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
55
-
56
-/* Bit definitions for CPTR_EL2 (AArch64 only) */
57
-FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
58
-FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
59
-FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
60
-FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
61
-FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
62
-FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
63
-FIELD(CPTR_EL2, TTA, 28, 1)
64
-FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
65
-FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
66
-
67
-/* Bit definitions for CPTR_EL3 (AArch64 only) */
68
-FIELD(CPTR_EL3, EZ, 8, 1)
69
-FIELD(CPTR_EL3, TFP, 10, 1)
70
-FIELD(CPTR_EL3, ESM, 12, 1)
71
-FIELD(CPTR_EL3, TTA, 20, 1)
72
-FIELD(CPTR_EL3, TAM, 30, 1)
73
-FIELD(CPTR_EL3, TCPAC, 31, 1)
74
-
75
-#define MDCR_MTPME (1U << 28)
76
-#define MDCR_TDCC (1U << 27)
77
-#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
78
-#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
79
-#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
80
-#define MDCR_EPMAD (1U << 21)
81
-#define MDCR_EDAD (1U << 20)
82
-#define MDCR_TTRF (1U << 19)
83
-#define MDCR_STE (1U << 18) /* MDCR_EL3 */
84
-#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
85
-#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
86
-#define MDCR_SDD (1U << 16)
87
-#define MDCR_SPD (3U << 14)
88
-#define MDCR_TDRA (1U << 11)
89
-#define MDCR_TDOSA (1U << 10)
90
-#define MDCR_TDA (1U << 9)
91
-#define MDCR_TDE (1U << 8)
92
-#define MDCR_HPME (1U << 7)
93
-#define MDCR_TPM (1U << 6)
94
-#define MDCR_TPMCR (1U << 5)
95
-#define MDCR_HPMN (0x1fU)
96
-
97
-/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
98
-#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
99
- MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
100
- MDCR_STE | MDCR_SPME | MDCR_SPD)
101
-
102
#define CPSR_M (0x1fU)
103
#define CPSR_T (1U << 5)
104
#define CPSR_F (1U << 6)
105
@@ -XXX,XX +XXX,XX @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
106
#define XPSR_NZCV CPSR_NZCV
107
#define XPSR_IT CPSR_IT
108
109
-#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
110
-#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
111
-#define TTBCR_PD0 (1U << 4)
112
-#define TTBCR_PD1 (1U << 5)
113
-#define TTBCR_EPD0 (1U << 7)
114
-#define TTBCR_IRGN0 (3U << 8)
115
-#define TTBCR_ORGN0 (3U << 10)
116
-#define TTBCR_SH0 (3U << 12)
117
-#define TTBCR_T1SZ (3U << 16)
118
-#define TTBCR_A1 (1U << 22)
119
-#define TTBCR_EPD1 (1U << 23)
120
-#define TTBCR_IRGN1 (3U << 24)
121
-#define TTBCR_ORGN1 (3U << 26)
122
-#define TTBCR_SH1 (1U << 28)
123
-#define TTBCR_EAE (1U << 31)
124
-
125
-FIELD(VTCR, T0SZ, 0, 6)
126
-FIELD(VTCR, SL0, 6, 2)
127
-FIELD(VTCR, IRGN0, 8, 2)
128
-FIELD(VTCR, ORGN0, 10, 2)
129
-FIELD(VTCR, SH0, 12, 2)
130
-FIELD(VTCR, TG0, 14, 2)
131
-FIELD(VTCR, PS, 16, 3)
132
-FIELD(VTCR, VS, 19, 1)
133
-FIELD(VTCR, HA, 21, 1)
134
-FIELD(VTCR, HD, 22, 1)
135
-FIELD(VTCR, HWU59, 25, 1)
136
-FIELD(VTCR, HWU60, 26, 1)
137
-FIELD(VTCR, HWU61, 27, 1)
138
-FIELD(VTCR, HWU62, 28, 1)
139
-FIELD(VTCR, NSW, 29, 1)
140
-FIELD(VTCR, NSA, 30, 1)
141
-FIELD(VTCR, DS, 32, 1)
142
-FIELD(VTCR, SL2, 33, 1)
143
-
144
/* Bit definitions for ARMv8 SPSR (PSTATE) format.
145
* Only these are valid when in AArch64 mode; in
146
* AArch32 mode SPSRs are basically CPSR-format.
147
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
148
#define HCR_TWEDEN (1ULL << 59)
149
#define HCR_TWEDEL MAKE_64BIT_MASK(60, 4)
150
151
-#define HCRX_ENAS0 (1ULL << 0)
152
-#define HCRX_ENALS (1ULL << 1)
153
-#define HCRX_ENASR (1ULL << 2)
154
-#define HCRX_FNXS (1ULL << 3)
155
-#define HCRX_FGTNXS (1ULL << 4)
156
-#define HCRX_SMPME (1ULL << 5)
157
-#define HCRX_TALLINT (1ULL << 6)
158
-#define HCRX_VINMI (1ULL << 7)
159
-#define HCRX_VFNMI (1ULL << 8)
160
-#define HCRX_CMOW (1ULL << 9)
161
-#define HCRX_MCE2 (1ULL << 10)
162
-#define HCRX_MSCEN (1ULL << 11)
163
-
164
-#define HPFAR_NS (1ULL << 63)
165
-
166
#define SCR_NS (1ULL << 0)
167
#define SCR_IRQ (1ULL << 1)
168
#define SCR_FIQ (1ULL << 2)
169
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
170
#define SCR_GPF (1ULL << 48)
171
#define SCR_NSE (1ULL << 62)
172
173
-#define HSTR_TTEE (1 << 16)
174
-#define HSTR_TJDBX (1 << 17)
175
-
176
-#define CNTHCTL_CNTVMASK (1 << 18)
177
-#define CNTHCTL_CNTPMASK (1 << 19)
178
-
179
/* Return the current FPSCR value. */
180
uint32_t vfp_get_fpscr(CPUARMState *env);
181
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
182
diff --git a/target/arm/internals.h b/target/arm/internals.h
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/internals.h
185
+++ b/target/arm/internals.h
186
@@ -XXX,XX +XXX,XX @@ FIELD(DBGWCR, WT, 20, 1)
187
FIELD(DBGWCR, MASK, 24, 5)
188
FIELD(DBGWCR, SSCE, 29, 1)
189
190
+#define VTCR_NSW (1u << 29)
191
+#define VTCR_NSA (1u << 30)
192
+#define VSTCR_SW VTCR_NSW
193
+#define VSTCR_SA VTCR_NSA
194
+
195
+/* Bit definitions for CPACR (AArch32 only) */
196
+FIELD(CPACR, CP10, 20, 2)
197
+FIELD(CPACR, CP11, 22, 2)
198
+FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
199
+FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
200
+FIELD(CPACR, ASEDIS, 31, 1)
201
+
202
+/* Bit definitions for CPACR_EL1 (AArch64 only) */
203
+FIELD(CPACR_EL1, ZEN, 16, 2)
204
+FIELD(CPACR_EL1, FPEN, 20, 2)
205
+FIELD(CPACR_EL1, SMEN, 24, 2)
206
+FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
207
+
208
+/* Bit definitions for HCPTR (AArch32 only) */
209
+FIELD(HCPTR, TCP10, 10, 1)
210
+FIELD(HCPTR, TCP11, 11, 1)
211
+FIELD(HCPTR, TASE, 15, 1)
212
+FIELD(HCPTR, TTA, 20, 1)
213
+FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
214
+FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
215
+
216
+/* Bit definitions for CPTR_EL2 (AArch64 only) */
217
+FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
218
+FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
219
+FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
220
+FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
221
+FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
222
+FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
223
+FIELD(CPTR_EL2, TTA, 28, 1)
224
+FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
225
+FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
226
+
227
+/* Bit definitions for CPTR_EL3 (AArch64 only) */
228
+FIELD(CPTR_EL3, EZ, 8, 1)
229
+FIELD(CPTR_EL3, TFP, 10, 1)
230
+FIELD(CPTR_EL3, ESM, 12, 1)
231
+FIELD(CPTR_EL3, TTA, 20, 1)
232
+FIELD(CPTR_EL3, TAM, 30, 1)
233
+FIELD(CPTR_EL3, TCPAC, 31, 1)
234
+
235
+#define MDCR_MTPME (1U << 28)
236
+#define MDCR_TDCC (1U << 27)
237
+#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
238
+#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
239
+#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
240
+#define MDCR_EPMAD (1U << 21)
241
+#define MDCR_EDAD (1U << 20)
242
+#define MDCR_TTRF (1U << 19)
243
+#define MDCR_STE (1U << 18) /* MDCR_EL3 */
244
+#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
245
+#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
246
+#define MDCR_SDD (1U << 16)
247
+#define MDCR_SPD (3U << 14)
248
+#define MDCR_TDRA (1U << 11)
249
+#define MDCR_TDOSA (1U << 10)
250
+#define MDCR_TDA (1U << 9)
251
+#define MDCR_TDE (1U << 8)
252
+#define MDCR_HPME (1U << 7)
253
+#define MDCR_TPM (1U << 6)
254
+#define MDCR_TPMCR (1U << 5)
255
+#define MDCR_HPMN (0x1fU)
256
+
257
+/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
258
+#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
259
+ MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
260
+ MDCR_STE | MDCR_SPME | MDCR_SPD)
261
+
262
+#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
263
+#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
264
+#define TTBCR_PD0 (1U << 4)
265
+#define TTBCR_PD1 (1U << 5)
266
+#define TTBCR_EPD0 (1U << 7)
267
+#define TTBCR_IRGN0 (3U << 8)
268
+#define TTBCR_ORGN0 (3U << 10)
269
+#define TTBCR_SH0 (3U << 12)
270
+#define TTBCR_T1SZ (3U << 16)
271
+#define TTBCR_A1 (1U << 22)
272
+#define TTBCR_EPD1 (1U << 23)
273
+#define TTBCR_IRGN1 (3U << 24)
274
+#define TTBCR_ORGN1 (3U << 26)
275
+#define TTBCR_SH1 (1U << 28)
276
+#define TTBCR_EAE (1U << 31)
277
+
278
+FIELD(VTCR, T0SZ, 0, 6)
279
+FIELD(VTCR, SL0, 6, 2)
280
+FIELD(VTCR, IRGN0, 8, 2)
281
+FIELD(VTCR, ORGN0, 10, 2)
282
+FIELD(VTCR, SH0, 12, 2)
283
+FIELD(VTCR, TG0, 14, 2)
284
+FIELD(VTCR, PS, 16, 3)
285
+FIELD(VTCR, VS, 19, 1)
286
+FIELD(VTCR, HA, 21, 1)
287
+FIELD(VTCR, HD, 22, 1)
288
+FIELD(VTCR, HWU59, 25, 1)
289
+FIELD(VTCR, HWU60, 26, 1)
290
+FIELD(VTCR, HWU61, 27, 1)
291
+FIELD(VTCR, HWU62, 28, 1)
292
+FIELD(VTCR, NSW, 29, 1)
293
+FIELD(VTCR, NSA, 30, 1)
294
+FIELD(VTCR, DS, 32, 1)
295
+FIELD(VTCR, SL2, 33, 1)
296
+
297
+#define HCRX_ENAS0 (1ULL << 0)
298
+#define HCRX_ENALS (1ULL << 1)
299
+#define HCRX_ENASR (1ULL << 2)
300
+#define HCRX_FNXS (1ULL << 3)
301
+#define HCRX_FGTNXS (1ULL << 4)
302
+#define HCRX_SMPME (1ULL << 5)
303
+#define HCRX_TALLINT (1ULL << 6)
304
+#define HCRX_VINMI (1ULL << 7)
305
+#define HCRX_VFNMI (1ULL << 8)
306
+#define HCRX_CMOW (1ULL << 9)
307
+#define HCRX_MCE2 (1ULL << 10)
308
+#define HCRX_MSCEN (1ULL << 11)
309
+
310
+#define HPFAR_NS (1ULL << 63)
311
+
312
+#define HSTR_TTEE (1 << 16)
313
+#define HSTR_TJDBX (1 << 17)
314
+
315
+#define CNTHCTL_CNTVMASK (1 << 18)
316
+#define CNTHCTL_CNTPMASK (1 << 19)
317
+
318
/* We use a few fake FSR values for internal purposes in M profile.
319
* M profile cores don't have A/R format FSRs, but currently our
320
* get_phys_addr() code assumes A/R profile and reports failures via
49
--
321
--
50
2.25.1
322
2.34.1
323
324
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
delivering the exception to EL2 with the wrong syndrome.
2
4
3
Add a TCGv_ptr base argument, which will be cpu_env for SVE.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
We will reuse this for SME save and restore array insns.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
8
---
9
target/arm/helper.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
5
11
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
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
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.h
14
--- a/target/arm/helper.c
18
+++ b/target/arm/translate-a64.h
15
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ void gen_gvec_xar(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
20
uint32_t rm_ofs, int64_t shift,
17
return CP_ACCESS_OK;
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
}
18
}
82
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
83
/*
20
- return CP_ACCESS_TRAP;
84
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
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
}
22
}
92
}
23
return CP_ACCESS_OK;
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
}
24
}
184
--
25
--
185
2.25.1
26
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
We prefer the FIELD macro over ad-hoc #defines for register bits;
2
switch CNTHCTL to that style before we add any more bits.
2
3
3
This new behaviour is in the ARM pseudocode function
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
AArch64.CheckFPAdvSIMDEnabled, which applies to AArch32
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
via AArch32.CheckAdvSIMDOrFPEnabled when the EL to which
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
the trap would be delivered is in AArch64 mode.
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
8
---
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
10
target/arm/helper.c | 9 ++++-----
11
2 files changed, 29 insertions(+), 7 deletions(-)
7
12
8
Given that ARMv9 drops support for AArch32 outside EL0, the trap EL
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
9
detection ought to be trivially true, but the pseudocode still contains
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>
24
---
25
target/arm/cpu.h | 7 +++
26
target/arm/translate.h | 4 ++
27
target/arm/sme-fa64.decode | 90 ++++++++++++++++++++++++++++++++++++++
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
36
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/internals.h
39
+++ b/target/arm/cpu.h
16
+++ b/target/arm/internals.h
40
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, HSTR_ACTIVE, 9, 1)
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
41
* the same thing as the current security state of the processor!
18
#define HSTR_TTEE (1 << 16)
42
*/
19
#define HSTR_TJDBX (1 << 17)
43
FIELD(TBFLAG_A32, NS, 10, 1)
20
21
-#define CNTHCTL_CNTVMASK (1 << 18)
22
-#define CNTHCTL_CNTPMASK (1 << 19)
44
+/*
23
+/*
45
+ * Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not.
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
46
+ * This requires an SME trap from AArch32 mode when using NEON.
25
+ * have different bit definitions, and EL1PCTEN might be
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
27
+ * disambiguate if necessary.
47
+ */
28
+ */
48
+FIELD(TBFLAG_A32, SME_TRAP_NONSTREAMING, 11, 1)
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
49
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
50
/*
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
51
* Bit usage when in AArch32 state, for M-profile only.
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
52
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, SMEEXC_EL, 20, 2)
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
53
FIELD(TBFLAG_A64, PSTATE_SM, 22, 1)
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
54
FIELD(TBFLAG_A64, PSTATE_ZA, 23, 1)
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
55
FIELD(TBFLAG_A64, SVL, 24, 4)
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
56
+/* Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not. */
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
57
+FIELD(TBFLAG_A64, SME_TRAP_NONSTREAMING, 28, 1)
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
58
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
59
/*
40
+FIELD(CNTHCTL, ECV, 12, 1)
60
* Helpers for using the above.
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
61
diff --git a/target/arm/translate.h b/target/arm/translate.h
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
62
index XXXXXXX..XXXXXXX 100644
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
63
--- a/target/arm/translate.h
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
64
+++ b/target/arm/translate.h
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
65
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
46
+FIELD(CNTHCTL, CNTVMASK, 18, 1)
66
bool pstate_sm;
47
+FIELD(CNTHCTL, CNTPMASK, 19, 1)
67
/* True if PSTATE.ZA is set. */
48
68
bool pstate_za;
49
/* We use a few fake FSR values for internal purposes in M profile.
69
+ /* True if non-streaming insns should raise an SME Streaming exception. */
50
* M profile cores don't have A/R format FSRs, but currently our
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
+{
108
+ [
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
+}
119
+
120
+{
121
+ [
122
+ OK 0101 1110 --1- ---- 11-1 11-- ---- ---- # FMULX/FRECPS/FRSQRTS (scalar)
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
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
173
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
174
--- a/target/arm/helper.c
53
--- a/target/arm/helper.c
175
+++ b/target/arm/helper.c
54
+++ b/target/arm/helper.c
176
@@ -XXX,XX +XXX,XX @@ int sme_exception_el(CPUARMState *env, int el)
55
@@ -XXX,XX +XXX,XX @@ static void gt_update_irq(ARMCPU *cpu, int timeridx)
177
return 0;
56
* It is RES0 in Secure and NonSecure state.
178
}
57
*/
179
58
if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
180
+/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */
59
- ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
181
+static bool sme_fa64(CPUARMState *env, int el)
60
- (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
182
+{
61
+ ((timeridx == GTIMER_VIRT && (cnthctl & R_CNTHCTL_CNTVMASK_MASK)) ||
183
+ if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) {
62
+ (timeridx == GTIMER_PHYS && (cnthctl & R_CNTHCTL_CNTPMASK_MASK)))) {
184
+ return false;
63
irqstate = 0;
185
+ }
186
+
187
+ if (el <= 1 && !el_is_in_host(env, el)) {
188
+ if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) {
189
+ return false;
190
+ }
191
+ }
192
+ if (el <= 2 && arm_is_el2_enabled(env)) {
193
+ if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) {
194
+ return false;
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
+
203
+ return true;
204
+}
205
+
206
/*
207
* Given that SVE is enabled, return the vector length for EL.
208
*/
209
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
210
DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
211
}
64
}
212
65
213
+ /*
66
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
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
{
67
{
249
if (s->fp_excp_el) {
68
ARMCPU *cpu = env_archcpu(env);
250
assert(!s->fp_access_checked);
69
uint32_t oldval = env->cp15.cnthctl_el2;
251
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
70
-
252
return true;
71
raw_write(env, ri, value);
253
}
72
254
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
255
+static bool fp_access_check(DisasContext *s)
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
256
+{
75
gt_update_irq(cpu, GTIMER_VIRT);
257
+ if (!fp_access_check_only(s)) {
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
258
+ return false;
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
259
+ }
78
gt_update_irq(cpu, GTIMER_PHYS);
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
}
79
}
282
}
80
}
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
--
81
--
373
2.25.1
82
2.34.1
83
84
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
This is not strictly architecturally required, but it is how we've
3
tended to implement registers more recently.
2
4
3
We can handle both exception entry and exception return by
5
In particular, bits [19:18] are only present with FEAT_RME,
4
hooking into aarch64_sve_change_el.
6
and bits [17:12] will only be present with FEAT_ECV.
5
7
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-32-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
10
---
11
---
11
target/arm/helper.c | 15 +++++++++++++--
12
target/arm/helper.c | 18 ++++++++++++++++++
12
1 file changed, 13 insertions(+), 2 deletions(-)
13
1 file changed, 18 insertions(+)
13
14
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
19
return;
20
{
20
}
21
ARMCPU *cpu = env_archcpu(env);
21
22
uint32_t oldval = env->cp15.cnthctl_el2;
22
+ old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
23
+ uint32_t valid_mask =
23
+ new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
26
+ R_CNTHCTL_EVNTEN_MASK |
27
+ R_CNTHCTL_EVNTDIR_MASK |
28
+ R_CNTHCTL_EVNTI_MASK |
29
+ R_CNTHCTL_EL0VTEN_MASK |
30
+ R_CNTHCTL_EL0PTEN_MASK |
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
32
+ R_CNTHCTL_EL1PTEN_MASK;
24
+
33
+
25
+ /*
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
26
+ * Both AArch64.TakeException and AArch64.ExceptionReturn
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
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
+ }
36
+ }
34
+
37
+
35
/*
38
+ /* Clear RES0 bits */
36
* DDI0584A.d sec 3.2: "If SVE instructions are disabled or trapped
39
+ value &= valid_mask;
37
* at ELx, or not available because the EL is in AArch32 state, then
40
+
38
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
41
raw_write(env, ri, value);
39
* we already have the correct register contents when encountering the
42
40
* vq0->vq0 transition between EL0->EL1.
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
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
49
--
44
--
50
2.25.1
45
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
* four new trap bits for various counter and timer registers
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
scaling of the event stream. This is a no-op for us, because we don't
5
implement the event stream (our WFE is a NOP): all we need to do is
6
allow CNTHCTL_EL2.ENVTIS to be read and written.
7
* extensions to PMSCR_EL1.PCT, PMSCR_EL2.PCT, TRFCR_EL1.TS and
8
TRFCR_EL2.TS: these are all no-ops for us, because we don't implement
9
FEAT_SPE or FEAT_TRF.
10
* new registers CNTPCTSS_EL0 and NCTVCTSS_EL0 which are
11
"self-sychronizing" views of the CNTPCT_EL0 and CNTVCT_EL0, meaning
12
that no barriers are needed around their accesses. For us these
13
are just the same as the normal views, because all our sysregs are
14
inherently self-sychronizing.
2
15
3
We can reuse the SVE functions for implementing moves to/from
16
In this commit we implement the trap handling and permit the new
4
horizontal tile slices, but we need new ones for moves to/from
17
CNTHCTL_EL2 bits to be written.
5
vertical tile slices.
6
18
7
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>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
11
---
22
---
12
target/arm/helper-sme.h | 12 +++
23
target/arm/cpu-features.h | 5 ++++
13
target/arm/helper-sve.h | 2 +
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
14
target/arm/translate-a64.h | 8 ++
25
2 files changed, 51 insertions(+), 5 deletions(-)
15
target/arm/translate.h | 5 ++
16
target/arm/sme.decode | 15 ++++
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
26
22
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
23
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper-sme.h
29
--- a/target/arm/cpu-features.h
25
+++ b/target/arm/helper-sme.h
30
+++ b/target/arm/cpu-features.h
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
27
DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
28
29
DEF_HELPER_FLAGS_3(sme_zero, TCG_CALL_NO_RWG, void, env, i32, i32)
30
+
31
+/* Move to/from vertical array slices, i.e. columns, so 'c'. */
32
+DEF_HELPER_FLAGS_4(sme_mova_cz_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_4(sme_mova_zc_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(sme_mova_cz_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
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
44
--- a/target/arm/helper-sve.h
45
+++ b/target/arm/helper-sve.h
46
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_sel_zpzz_s, TCG_CALL_NO_RWG,
47
void, ptr, ptr, ptr, ptr, i32)
48
DEF_HELPER_FLAGS_5(sve_sel_zpzz_d, TCG_CALL_NO_RWG,
49
void, ptr, ptr, ptr, ptr, i32)
50
+DEF_HELPER_FLAGS_5(sve_sel_zpzz_q, TCG_CALL_NO_RWG,
51
+ void, ptr, ptr, ptr, ptr, i32)
52
53
DEF_HELPER_FLAGS_5(sve2_addp_zpzz_b, TCG_CALL_NO_RWG,
54
void, ptr, ptr, ptr, ptr, i32)
55
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-a64.h
58
+++ b/target/arm/translate-a64.h
59
@@ -XXX,XX +XXX,XX @@ static inline int pred_gvec_reg_size(DisasContext *s)
60
return size_for_gvec(pred_full_reg_size(s));
61
}
33
}
62
34
63
+/* Return a newly allocated pointer to the predicate register. */
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
64
+static inline TCGv_ptr pred_full_reg_ptr(DisasContext *s, int regno)
65
+{
36
+{
66
+ TCGv_ptr ret = tcg_temp_new_ptr();
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
67
+ tcg_gen_addi_ptr(ret, cpu_env, pred_full_reg_offset(s, regno));
68
+ return ret;
69
+}
38
+}
70
+
39
+
71
bool disas_sve(DisasContext *, uint32_t);
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
72
bool disas_sme(DisasContext *, uint32_t);
41
{
73
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
74
diff --git a/target/arm/translate.h b/target/arm/translate.h
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
75
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/translate.h
45
--- a/target/arm/helper.c
77
+++ b/target/arm/translate.h
46
+++ b/target/arm/helper.c
78
@@ -XXX,XX +XXX,XX @@ static inline int plus_2(DisasContext *s, int x)
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
79
return x + 2;
48
: !extract32(env->cp15.cnthctl_el2, 0, 1))) {
49
return CP_ACCESS_TRAP_EL2;
50
}
51
+ if (has_el2 && timeridx == GTIMER_VIRT) {
52
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVCT)) {
53
+ return CP_ACCESS_TRAP_EL2;
54
+ }
55
+ }
56
break;
57
}
58
return CP_ACCESS_OK;
59
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
60
}
61
}
62
}
63
+ if (has_el2 && timeridx == GTIMER_VIRT) {
64
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVT)) {
65
+ return CP_ACCESS_TRAP_EL2;
66
+ }
67
+ }
68
break;
69
}
70
return CP_ACCESS_OK;
71
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
if (cpu_isar_feature(aa64_rme, cpu)) {
73
valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
74
}
75
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
76
+ valid_mask |=
77
+ R_CNTHCTL_EL1TVT_MASK |
78
+ R_CNTHCTL_EL1TVCT_MASK |
79
+ R_CNTHCTL_EL1NVPCT_MASK |
80
+ R_CNTHCTL_EL1NVVCT_MASK |
81
+ R_CNTHCTL_EVNTIS_MASK;
82
+ }
83
84
/* Clear RES0 bits */
85
value &= valid_mask;
86
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
87
{
88
if (arm_current_el(env) == 1) {
89
/* This must be a FEAT_NV access */
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
91
return CP_ACCESS_OK;
92
}
93
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
95
return CP_ACCESS_OK;
80
}
96
}
81
97
82
+static inline int plus_12(DisasContext *s, int x)
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
83
+{
100
+{
84
+ return x + 12;
101
+ if (arm_current_el(env) == 1) {
102
+ /* This must be a FEAT_NV access with NVx == 101 */
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
104
+ return CP_ACCESS_TRAP_EL2;
105
+ }
106
+ }
107
+ return e2h_access(env, ri, isread);
85
+}
108
+}
86
+
109
+
87
static inline int times_2(DisasContext *s, int x)
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
88
{
111
+ bool isread)
89
return x * 2;
112
+{
90
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
113
+ if (arm_current_el(env) == 1) {
91
index XXXXXXX..XXXXXXX 100644
114
+ /* This must be a FEAT_NV access with NVx == 101 */
92
--- a/target/arm/sme.decode
115
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVVCT)) {
93
+++ b/target/arm/sme.decode
116
+ return CP_ACCESS_TRAP_EL2;
94
@@ -XXX,XX +XXX,XX @@
117
+ }
95
### SME Misc
118
+ }
96
119
+ return e2h_access(env, ri, isread);
97
ZERO 11000000 00 001 00000000000 imm:8
98
+
99
+### SME Move into/from Array
100
+
101
+%mova_rs 13:2 !function=plus_12
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
}
133
+
134
+
135
+/*
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
+}
120
+}
185
+
121
+
186
+DO_MOVA_C(sme_mova_cz_b, uint8_t, H1)
122
/* Test if system register redirection is to occur in the current state. */
187
+DO_MOVA_C(sme_mova_cz_h, uint16_t, H1_2)
123
static bool redirect_for_e2h(CPUARMState *env)
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
}
287
288
+void HELPER(sve_sel_zpzz_q)(void *vd, void *vn, void *vm,
289
+ void *vg, uint32_t desc)
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
{
124
{
381
if (!dc_isar_feature(aa64_sme, s)) {
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
382
@@ -XXX,XX +XXX,XX @@ static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
383
}
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
384
return true;
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
385
}
129
- .access = PL2_RW, .accessfn = e2h_access,
386
+
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
387
+static bool trans_MOVA(DisasContext *s, arg_MOVA *a)
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
388
+{
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
389
+ static gen_helper_gvec_4 * const h_fns[5] = {
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
390
+ gen_helper_sve_sel_zpzz_b, gen_helper_sve_sel_zpzz_h,
134
{ .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
391
+ gen_helper_sve_sel_zpzz_s, gen_helper_sve_sel_zpzz_d,
135
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
392
+ gen_helper_sve_sel_zpzz_q
136
.type = ARM_CP_IO | ARM_CP_ALIAS,
393
+ };
137
- .access = PL2_RW, .accessfn = e2h_access,
394
+ static gen_helper_gvec_3 * const cz_fns[5] = {
138
+ .access = PL2_RW, .accessfn = access_el1nvvct,
395
+ gen_helper_sme_mova_cz_b, gen_helper_sme_mova_cz_h,
139
.nv2_redirect_offset = 0x170 | NV2_REDIR_NO_NV1,
396
+ gen_helper_sme_mova_cz_s, gen_helper_sme_mova_cz_d,
140
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
397
+ gen_helper_sme_mova_cz_q,
141
.writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
398
+ };
142
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
399
+ static gen_helper_gvec_3 * const zc_fns[5] = {
143
.type = ARM_CP_IO | ARM_CP_ALIAS,
400
+ gen_helper_sme_mova_zc_b, gen_helper_sme_mova_zc_h,
144
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
401
+ gen_helper_sme_mova_zc_s, gen_helper_sme_mova_zc_d,
145
.nv2_redirect_offset = 0x178 | NV2_REDIR_NO_NV1,
402
+ gen_helper_sme_mova_zc_q,
146
- .access = PL2_RW, .accessfn = e2h_access,
403
+ };
147
+ .access = PL2_RW, .accessfn = access_el1nvpct,
404
+
148
.writefn = gt_phys_cval_write, .raw_writefn = raw_write },
405
+ TCGv_ptr t_za, t_zr, t_pg;
149
{ .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
406
+ TCGv_i32 t_desc;
150
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
407
+ int svl;
151
.type = ARM_CP_IO | ARM_CP_ALIAS,
408
+
152
.nv2_redirect_offset = 0x168 | NV2_REDIR_NO_NV1,
409
+ if (!dc_isar_feature(aa64_sme, s)) {
153
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
410
+ return false;
154
- .access = PL2_RW, .accessfn = e2h_access,
411
+ }
155
+ .access = PL2_RW, .accessfn = access_el1nvvct,
412
+ if (!sme_smza_enabled_check(s)) {
156
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
413
+ return true;
157
#endif
414
+ }
158
};
415
+
416
+ t_za = get_tile_rowcol(s, a->esz, a->rs, a->za_imm, a->v);
417
+ t_zr = vec_full_reg_ptr(s, a->zr);
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
--
159
--
446
2.25.1
160
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
defined, which are "self-synchronized" views of the physical and
3
virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers
4
(meaning that no barriers are needed around accesses to them to
5
ensure that reads of them do not occur speculatively and out-of-order
6
with other instructions).
2
7
3
Mark these as a non-streaming instructions, which should trap
8
For QEMU, all our system registers are self-synchronized, so we can
4
if full a64 support is not enabled in streaming mode.
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
10
to the new register encodings.
5
11
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
This means we now implement all the functionality required for
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
8
Message-id: 20220708151540.18136-9-richard.henderson@linaro.org
14
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
10
---
18
---
11
target/arm/sme-fa64.decode | 3 ---
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-sve.c | 15 +++++++++++----
20
1 file changed, 43 insertions(+)
13
2 files changed, 11 insertions(+), 7 deletions(-)
14
21
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
24
--- a/target/arm/helper.c
18
+++ b/target/arm/sme-fa64.decode
25
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
27
},
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
};
28
};
37
-TRANS_FEAT(FTMAD, aa64_sve, gen_gvec_fpst_zzz,
29
38
- ftmad_fns[a->esz], a->rd, a->rn, a->rm, a->imm,
30
+/*
39
- a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR)
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
40
+TRANS_FEAT_NONSTREAMING(FTMAD, aa64_sve, gen_gvec_fpst_zzz,
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
41
+ ftmad_fns[a->esz], a->rd, a->rn, a->rm, a->imm,
33
+ * so our implementations here are identical to the normal registers.
42
+ a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR)
34
+ */
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
38
+ .accessfn = gt_vct_access,
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
40
+ },
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
43
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
44
+ .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
45
+ },
46
+ { .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
47
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
48
+ .accessfn = gt_pct_access,
49
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
50
+ },
51
+ { .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
52
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
53
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
54
+ .accessfn = gt_pct_access, .readfn = gt_cnt_read,
55
+ },
56
+};
57
+
58
#else
43
59
44
/*
60
/*
45
*** SVE Floating Point Accumulating Reduction Group
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
46
@@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a)
62
},
47
if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) {
63
};
48
return false;
64
65
+/*
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
67
+ * is exposed to userspace by Linux.
68
+ */
69
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
70
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
71
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
72
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
73
+ .readfn = gt_virt_cnt_read,
74
+ },
75
+};
76
+
77
#endif
78
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
49
}
83
}
50
+ s->is_nonstreaming = true;
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
51
if (!sve_access_check(s)) {
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
52
return true;
86
+ }
53
}
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
54
@@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a)
88
ARMCPRegInfo vapa_cp_reginfo[] = {
55
DO_FP3(FADD_zzz, fadd)
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
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
--
90
--
75
2.25.1
91
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
that it controls a hypervisor-adjustable offset made to the physical
4
counter and timer.
2
5
3
These SME instructions are nominally within the SVE decode space,
6
Implement the handling for this register, which includes control/trap
4
so we add them to sve.decode and translate-sve.c.
7
bits in SCR_EL3 and CNTHCTL_EL2.
5
8
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-18-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
10
---
12
---
11
target/arm/translate-a64.h | 12 ++++++++++++
13
target/arm/cpu-features.h | 5 +++
12
target/arm/sve.decode | 5 ++++-
14
target/arm/cpu.h | 1 +
13
target/arm/translate-sve.c | 38 ++++++++++++++++++++++++++++++++++++++
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
14
3 files changed, 54 insertions(+), 1 deletion(-)
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
15
18
16
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
19
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-a64.h
21
--- a/target/arm/cpu-features.h
19
+++ b/target/arm/translate-a64.h
22
+++ b/target/arm/cpu-features.h
20
@@ -XXX,XX +XXX,XX @@ static inline int vec_full_reg_size(DisasContext *s)
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
21
return s->vl;
24
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
22
}
25
}
23
26
24
+/* Return the byte size of the vector register, SVL / 8. */
27
+static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
25
+static inline int streaming_vec_reg_size(DisasContext *s)
26
+{
28
+{
27
+ return s->svl;
29
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
28
+}
30
+}
29
+
31
+
30
/*
32
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
31
* Return the offset info CPUARMState of the predicate vector register Pn.
33
{
32
* Note for this purpose, FFR is P16.
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
33
@@ -XXX,XX +XXX,XX @@ static inline int pred_full_reg_size(DisasContext *s)
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
34
return s->vl >> 3;
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
40
uint64_t c14_cntkctl; /* Timer Control register */
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
50
+++ b/target/arm/helper.c
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
52
if (cpu_isar_feature(aa64_rme, cpu)) {
53
valid_mask |= SCR_NSE | SCR_GPF;
54
}
55
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
56
+ valid_mask |= SCR_ECVEN;
57
+ }
58
} else {
59
valid_mask &= ~(SCR_RW | SCR_ST);
60
if (cpu_isar_feature(aa32_ras, cpu)) {
61
@@ -XXX,XX +XXX,XX @@ void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
62
gt_update_irq(cpu, GTIMER_PHYS);
35
}
63
}
36
64
37
+/* Return the byte size of the predicate register, SVL / 64. */
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
38
+static inline int streaming_pred_reg_size(DisasContext *s)
39
+{
66
+{
40
+ return s->svl >> 3;
67
+ if ((env->cp15.scr_el3 & SCR_ECVEN) &&
68
+ FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, ECV) &&
69
+ arm_is_el2_enabled(env) &&
70
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
71
+ return env->cp15.cntpoff_el2;
72
+ }
73
+ return 0;
41
+}
74
+}
42
+
75
+
43
/*
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
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
48
--- a/target/arm/sve.decode
49
+++ b/target/arm/sve.decode
50
@@ -XXX,XX +XXX,XX @@ INDEX_ri 00000100 esz:2 1 imm:s5 010001 rn:5 rd:5
51
# SVE index generation (register start, register increment)
52
INDEX_rr 00000100 .. 1 ..... 010011 ..... ..... @rd_rn_rm
53
54
-### SVE Stack Allocation Group
55
+### SVE / Streaming SVE Stack Allocation Group
56
57
# SVE stack frame adjustment
58
ADDVL 00000100 001 ..... 01010 ...... ..... @rd_rn_i6
59
+ADDSVL 00000100 001 ..... 01011 ...... ..... @rd_rn_i6
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
71
--- a/target/arm/translate-sve.c
72
+++ b/target/arm/translate-sve.c
73
@@ -XXX,XX +XXX,XX @@ static bool trans_ADDVL(DisasContext *s, arg_ADDVL *a)
74
return true;
75
}
76
77
+static bool trans_ADDSVL(DisasContext *s, arg_ADDSVL *a)
78
+{
77
+{
79
+ if (!dc_isar_feature(aa64_sme, s)) {
78
+ if (arm_current_el(env) >= 2) {
80
+ return false;
79
+ return 0;
81
+ }
80
+ }
82
+ if (sme_enabled_check(s)) {
81
+ return gt_phys_raw_cnt_offset(env);
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
+}
82
+}
89
+
83
+
90
static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
91
{
85
{
92
if (!dc_isar_feature(aa64_sve, s)) {
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
93
@@ -XXX,XX +XXX,XX @@ static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
94
return true;
88
* reset timer to when ISTATUS next has to change
89
*/
90
uint64_t offset = timeridx == GTIMER_VIRT ?
91
- cpu->env.cp15.cntvoff_el2 : 0;
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
93
uint64_t count = gt_get_countervalue(&cpu->env);
94
/* Note that this must be unsigned 64 bit arithmetic: */
95
int istatus = count - offset >= gt->cval;
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
97
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
{
100
- return gt_get_countervalue(env);
101
+ return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
95
}
102
}
96
103
97
+static bool trans_ADDSPL(DisasContext *s, arg_ADDSPL *a)
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
106
case GTIMER_HYPVIRT:
107
offset = gt_virt_cnt_offset(env);
108
break;
109
+ case GTIMER_PHYS:
110
+ offset = gt_phys_cnt_offset(env);
111
+ break;
112
}
113
114
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
115
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
case GTIMER_HYPVIRT:
117
offset = gt_virt_cnt_offset(env);
118
break;
119
+ case GTIMER_PHYS:
120
+ offset = gt_phys_cnt_offset(env);
121
+ break;
122
}
123
124
trace_arm_gt_tval_write(timeridx, value);
125
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
R_CNTHCTL_EL1NVVCT_MASK |
127
R_CNTHCTL_EVNTIS_MASK;
128
}
129
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
130
+ valid_mask |= R_CNTHCTL_ECV_MASK;
131
+ }
132
133
/* Clear RES0 bits */
134
value &= valid_mask;
135
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
136
},
137
};
138
139
+static CPAccessResult gt_cntpoff_access(CPUARMState *env,
140
+ const ARMCPRegInfo *ri,
141
+ bool isread)
98
+{
142
+{
99
+ if (!dc_isar_feature(aa64_sme, s)) {
143
+ if (arm_current_el(env) == 2 && !(env->cp15.scr_el3 & SCR_ECVEN)) {
100
+ return false;
144
+ return CP_ACCESS_TRAP_EL3;
101
+ }
145
+ }
102
+ if (sme_enabled_check(s)) {
146
+ return CP_ACCESS_OK;
103
+ TCGv_i64 rd = cpu_reg_sp(s, a->rd);
104
+ TCGv_i64 rn = cpu_reg_sp(s, a->rn);
105
+ tcg_gen_addi_i64(rd, rn, a->imm * streaming_pred_reg_size(s));
106
+ }
107
+ return true;
108
+}
147
+}
109
+
148
+
110
static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
111
{
150
+ uint64_t value)
112
if (!dc_isar_feature(aa64_sve, s)) {
113
@@ -XXX,XX +XXX,XX @@ static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
114
return true;
115
}
116
117
+static bool trans_RDSVL(DisasContext *s, arg_RDSVL *a)
118
+{
151
+{
119
+ if (!dc_isar_feature(aa64_sme, s)) {
152
+ ARMCPU *cpu = env_archcpu(env);
120
+ return false;
153
+
121
+ }
154
+ trace_arm_gt_cntpoff_write(value);
122
+ if (sme_enabled_check(s)) {
155
+ raw_write(env, ri, value);
123
+ TCGv_i64 reg = cpu_reg(s, a->rd);
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
124
+ tcg_gen_movi_i64(reg, a->imm * streaming_vec_reg_size(s));
125
+ }
126
+ return true;
127
+}
157
+}
128
+
158
+
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
164
+ .nv2_redirect_offset = 0x1a8,
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
166
+};
167
#else
168
129
/*
169
/*
130
*** SVE Compute Vector Address Group
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
131
*/
171
if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
172
define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
173
}
174
+#ifndef CONFIG_USER_ONLY
175
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
176
+ define_one_arm_cp_reg(cpu, &gen_timer_cntpoff_reginfo);
177
+ }
178
+#endif
179
if (arm_feature(env, ARM_FEATURE_VAPA)) {
180
ARMCPRegInfo vapa_cp_reginfo[] = {
181
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/trace-events
185
+++ b/target/arm/trace-events
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
192
193
# kvm.c
132
--
194
--
133
2.25.1
195
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Enable all FEAT_ECV features on the 'max' CPU.
2
2
3
Note that SME remains effectively disabled for user-only,
4
because we do not yet set CPACR_EL1.SMEN. This needs to
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>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
11
---
7
---
12
docs/system/arm/emulation.rst | 4 ++++
8
docs/system/arm/emulation.rst | 1 +
13
target/arm/cpu64.c | 11 +++++++++++
9
target/arm/tcg/cpu64.c | 1 +
14
2 files changed, 15 insertions(+)
10
2 files changed, 2 insertions(+)
15
11
16
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/system/arm/emulation.rst
14
--- a/docs/system/arm/emulation.rst
19
+++ b/docs/system/arm/emulation.rst
15
+++ b/docs/system/arm/emulation.rst
20
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
21
- FEAT_SHA512 (Advanced SIMD SHA512 instructions)
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
22
- FEAT_SM3 (Advanced SIMD SM3 instructions)
18
- FEAT_DoubleFault (Double Fault Extension)
23
- FEAT_SM4 (Advanced SIMD SM4 instructions)
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
24
+- FEAT_SME (Scalable Matrix Extension)
20
+- FEAT_ECV (Enhanced Counter Virtualization)
25
+- FEAT_SME_FA64 (Full A64 instruction set in Streaming SVE mode)
21
- FEAT_EPAC (Enhanced pointer authentication)
26
+- FEAT_SME_F64F64 (Double-precision floating-point outer product instructions)
22
- FEAT_ETS (Enhanced Translation Synchronization)
27
+- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product instructions)
23
- FEAT_EVT (Enhanced Virtualization Traps)
28
- FEAT_SPECRES (Speculation restriction instructions)
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
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
32
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/cpu64.c
26
--- a/target/arm/tcg/cpu64.c
34
+++ b/target/arm/cpu64.c
27
+++ b/target/arm/tcg/cpu64.c
35
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
36
*/
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
37
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
38
t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
39
+ t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
40
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
33
cpu->isar.id_aa64mmfr0 = t;
41
cpu->isar.id_aa64pfr1 = t;
34
42
35
t = cpu->isar.id_aa64mmfr1;
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
--
36
--
61
2.25.1
37
2.34.1
38
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
We cannot reuse the SVE functions for LD[1-4] and ST[1-4],
3
Features supported :
4
because those functions accept only a Zreg register number.
4
- the 8 STM32L4x5 GPIOs are initialized with their reset values
5
For SME, we want to pass a pointer into ZA storage.
5
(except IDR, see below)
6
- input mode : setting a pin in input mode "externally" (using input
7
irqs) results in an out irq (transmitted to SYSCFG)
8
- output mode : setting a bit in ODR sets the corresponding out irq
9
(if this line is configured in output mode)
10
- pull-up, pull-down
11
- push-pull, open-drain
6
12
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Difference with the real GPIOs :
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
- Alternate Function and Analog mode aren't implemented :
9
Message-id: 20220708151540.18136-21-richard.henderson@linaro.org
15
pins in AF/Analog behave like pins in input mode
16
- floating pins stay at their last value
17
- register IDR reset values differ from the real one :
18
values are coherent with the other registers reset values
19
and the fact that AF/Analog modes aren't implemented
20
- setting I/O output speed isn't supported
21
- locking port bits isn't supported
22
- ADC function isn't supported
23
- GPIOH has 16 pins instead of 2 pins
24
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective
25
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
29
Acked-by: Alistair Francis <alistair.francis@wdc.com>
30
Message-id: 20240305210444.310665-2-ines.varhol@telecom-paris.fr
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
32
---
12
target/arm/helper-sme.h | 82 +++++
33
MAINTAINERS | 1 +
13
target/arm/sme.decode | 9 +
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
14
target/arm/sme_helper.c | 595 +++++++++++++++++++++++++++++++++++++
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
15
target/arm/translate-sme.c | 70 +++++
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
16
4 files changed, 756 insertions(+)
37
hw/gpio/Kconfig | 3 +
38
hw/gpio/meson.build | 1 +
39
hw/gpio/trace-events | 6 +
40
7 files changed, 559 insertions(+), 1 deletion(-)
41
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
42
create mode 100644 hw/gpio/stm32l4x5_gpio.c
17
43
18
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
44
diff --git a/MAINTAINERS b/MAINTAINERS
19
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper-sme.h
46
--- a/MAINTAINERS
21
+++ b/target/arm/helper-sme.h
47
+++ b/MAINTAINERS
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sme_mova_cz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
23
DEF_HELPER_FLAGS_4(sme_mova_zc_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
49
F: hw/misc/stm32l4x5_exti.c
24
DEF_HELPER_FLAGS_4(sme_mova_cz_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
50
F: hw/misc/stm32l4x5_syscfg.c
25
DEF_HELPER_FLAGS_4(sme_mova_zc_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
51
F: hw/misc/stm32l4x5_rcc.c
26
+
52
+F: hw/gpio/stm32l4x5_gpio.c
27
+DEF_HELPER_FLAGS_5(sme_ld1b_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
53
F: include/hw/*/stm32l4x5_*.h
28
+DEF_HELPER_FLAGS_5(sme_ld1b_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
54
29
+DEF_HELPER_FLAGS_5(sme_ld1b_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
55
B-L475E-IOT01A IoT Node
30
+DEF_HELPER_FLAGS_5(sme_ld1b_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
31
+
32
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
33
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
34
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
35
+DEF_HELPER_FLAGS_5(sme_ld1h_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
36
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
37
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
38
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
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
57
index XXXXXXX..XXXXXXX 100644
110
--- a/target/arm/sme.decode
58
--- a/docs/system/arm/b-l475e-iot01a.rst
111
+++ b/target/arm/sme.decode
59
+++ b/docs/system/arm/b-l475e-iot01a.rst
112
@@ -XXX,XX +XXX,XX @@ MOVA 11000000 esz:2 00001 0 v:1 .. pg:3 0 za_imm:4 zr:5 \
60
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
113
&mova to_vec=1 rs=%mova_rs
61
- STM32L4x5 EXTI (Extended interrupts and events controller)
114
MOVA 11000000 11 00001 1 v:1 .. pg:3 0 za_imm:4 zr:5 \
62
- STM32L4x5 SYSCFG (System configuration controller)
115
&mova to_vec=1 rs=%mova_rs esz=4
63
- STM32L4x5 RCC (Reset and clock control)
116
+
64
+- STM32L4x5 GPIOs (General-purpose I/Os)
117
+### SME Memory
65
118
+
66
Missing devices
119
+&ldst esz rs pg rn rm za_imm v:bool st:bool
67
"""""""""""""""
120
+
68
@@ -XXX,XX +XXX,XX @@ Missing devices
121
+LDST1 1110000 0 esz:2 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
69
The B-L475E-IOT01A does *not* support the following devices:
122
+ &ldst rs=%mova_rs
70
123
+LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
71
- Serial ports (UART)
124
+ &ldst esz=4 rs=%mova_rs
72
-- General-purpose I/Os (GPIO)
125
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
73
- Analog to Digital Converter (ADC)
126
index XXXXXXX..XXXXXXX 100644
74
- SPI controller
127
--- a/target/arm/sme_helper.c
75
- Timer controller (TIMER)
128
+++ b/target/arm/sme_helper.c
76
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
77
new file mode 100644
78
index XXXXXXX..XXXXXXX
79
--- /dev/null
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
129
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
130
131
#include "qemu/osdep.h"
132
#include "cpu.h"
133
+#include "internals.h"
134
#include "tcg/tcg-gvec-desc.h"
135
#include "exec/helper-proto.h"
136
+#include "exec/cpu_ldst.h"
137
+#include "exec/exec-all.h"
138
#include "qemu/int128.h"
139
#include "vec_internal.h"
140
+#include "sve_ldst_internal.h"
141
142
/* ResetSVEState */
143
void arm_reset_sve_state(CPUARMState *env)
144
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_mova_zc_q)(void *vd, void *za, void *vg, uint32_t desc)
145
}
146
147
#undef DO_MOVA_Z
148
+
149
+/*
82
+/*
150
+ * Clear elements in a tile slice comprising len bytes.
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
84
+ *
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
87
+ *
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
151
+ */
92
+ */
152
+
93
+
153
+typedef void ClearFn(void *ptr, size_t off, size_t len);
154
+
155
+static void clear_horizontal(void *ptr, size_t off, size_t len)
156
+{
157
+ memset(ptr + off, 0, len);
158
+}
159
+
160
+static void clear_vertical_b(void *vptr, size_t off, size_t len)
161
+{
162
+ for (size_t i = 0; i < len; ++i) {
163
+ *(uint8_t *)(vptr + tile_vslice_offset(i + off)) = 0;
164
+ }
165
+}
166
+
167
+static void clear_vertical_h(void *vptr, size_t off, size_t len)
168
+{
169
+ for (size_t i = 0; i < len; i += 2) {
170
+ *(uint16_t *)(vptr + tile_vslice_offset(i + off)) = 0;
171
+ }
172
+}
173
+
174
+static void clear_vertical_s(void *vptr, size_t off, size_t len)
175
+{
176
+ for (size_t i = 0; i < len; i += 4) {
177
+ *(uint32_t *)(vptr + tile_vslice_offset(i + off)) = 0;
178
+ }
179
+}
180
+
181
+static void clear_vertical_d(void *vptr, size_t off, size_t len)
182
+{
183
+ for (size_t i = 0; i < len; i += 8) {
184
+ *(uint64_t *)(vptr + tile_vslice_offset(i + off)) = 0;
185
+ }
186
+}
187
+
188
+static void clear_vertical_q(void *vptr, size_t off, size_t len)
189
+{
190
+ for (size_t i = 0; i < len; i += 16) {
191
+ memset(vptr + tile_vslice_offset(i + off), 0, 16);
192
+ }
193
+}
194
+
195
+/*
94
+/*
196
+ * Copy elements from an array into a tile slice comprising len bytes.
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
197
+ */
98
+ */
198
+
99
+
199
+typedef void CopyFn(void *dst, const void *src, size_t len);
100
+#ifndef HW_STM32L4X5_GPIO_H
200
+
101
+#define HW_STM32L4X5_GPIO_H
201
+static void copy_horizontal(void *dst, const void *src, size_t len)
102
+
202
+{
103
+#include "hw/sysbus.h"
203
+ memcpy(dst, src, len);
104
+#include "qom/object.h"
204
+}
105
+
205
+
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
206
+static void copy_vertical_b(void *vdst, const void *vsrc, size_t len)
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
207
+{
108
+
208
+ const uint8_t *src = vsrc;
109
+#define GPIO_NUM_PINS 16
209
+ uint8_t *dst = vdst;
110
+
210
+ size_t i;
111
+struct Stm32l4x5GpioState {
211
+
112
+ SysBusDevice parent_obj;
212
+ for (i = 0; i < len; ++i) {
113
+
213
+ dst[tile_vslice_index(i)] = src[i];
114
+ MemoryRegion mmio;
214
+ }
115
+
215
+}
116
+ /* GPIO registers */
216
+
117
+ uint32_t moder;
217
+static void copy_vertical_h(void *vdst, const void *vsrc, size_t len)
118
+ uint32_t otyper;
218
+{
119
+ uint32_t ospeedr;
219
+ const uint16_t *src = vsrc;
120
+ uint32_t pupdr;
220
+ uint16_t *dst = vdst;
121
+ uint32_t idr;
221
+ size_t i;
122
+ uint32_t odr;
222
+
123
+ uint32_t lckr;
223
+ for (i = 0; i < len / 2; ++i) {
124
+ uint32_t afrl;
224
+ dst[tile_vslice_index(i)] = src[i];
125
+ uint32_t afrh;
225
+ }
126
+ uint32_t ascr;
226
+}
127
+
227
+
128
+ /* GPIO registers reset values */
228
+static void copy_vertical_s(void *vdst, const void *vsrc, size_t len)
129
+ uint32_t moder_reset;
229
+{
130
+ uint32_t ospeedr_reset;
230
+ const uint32_t *src = vsrc;
131
+ uint32_t pupdr_reset;
231
+ uint32_t *dst = vdst;
132
+
232
+ size_t i;
133
+ /*
233
+
134
+ * External driving of pins.
234
+ for (i = 0; i < len / 4; ++i) {
135
+ * The pins can be set externally through the device
235
+ dst[tile_vslice_index(i)] = src[i];
136
+ * anonymous input GPIOs lines under certain conditions.
236
+ }
137
+ * The pin must not be in push-pull output mode,
237
+}
138
+ * and can't be set high in open-drain mode.
238
+
139
+ * Pins driven externally and configured to
239
+static void copy_vertical_d(void *vdst, const void *vsrc, size_t len)
140
+ * output mode will in general be "disconnected"
240
+{
141
+ * (see `get_gpio_pinmask_to_disconnect()`)
241
+ const uint64_t *src = vsrc;
142
+ */
242
+ uint64_t *dst = vdst;
143
+ uint16_t disconnected_pins;
243
+ size_t i;
144
+ uint16_t pins_connected_high;
244
+
145
+
245
+ for (i = 0; i < len / 8; ++i) {
146
+ char *name;
246
+ dst[tile_vslice_index(i)] = src[i];
147
+ Clock *clk;
247
+ }
148
+ qemu_irq pin[GPIO_NUM_PINS];
248
+}
149
+};
249
+
150
+
250
+static void copy_vertical_q(void *vdst, const void *vsrc, size_t len)
151
+#endif
251
+{
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
252
+ for (size_t i = 0; i < len; i += 16) {
153
new file mode 100644
253
+ memcpy(vdst + tile_vslice_offset(i), vsrc + i, 16);
154
index XXXXXXX..XXXXXXX
254
+ }
155
--- /dev/null
255
+}
156
+++ b/hw/gpio/stm32l4x5_gpio.c
256
+
157
@@ -XXX,XX +XXX,XX @@
257
+/*
158
+/*
258
+ * Host and TLB primitives for vertical tile slice addressing.
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
160
+ *
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
163
+ *
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
165
+ *
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
167
+ * See the COPYING file in the top-level directory.
259
+ */
168
+ */
260
+
169
+
261
+#define DO_LD(NAME, TYPE, HOST, TLB) \
262
+static inline void sme_##NAME##_v_host(void *za, intptr_t off, void *host) \
263
+{ \
264
+ TYPE val = HOST(host); \
265
+ *(TYPE *)(za + tile_vslice_offset(off)) = val; \
266
+} \
267
+static inline void sme_##NAME##_v_tlb(CPUARMState *env, void *za, \
268
+ intptr_t off, target_ulong addr, uintptr_t ra) \
269
+{ \
270
+ TYPE val = TLB(env, useronly_clean_ptr(addr), ra); \
271
+ *(TYPE *)(za + tile_vslice_offset(off)) = val; \
272
+}
273
+
274
+#define DO_ST(NAME, TYPE, HOST, TLB) \
275
+static inline void sme_##NAME##_v_host(void *za, intptr_t off, void *host) \
276
+{ \
277
+ TYPE val = *(TYPE *)(za + tile_vslice_offset(off)); \
278
+ HOST(host, val); \
279
+} \
280
+static inline void sme_##NAME##_v_tlb(CPUARMState *env, void *za, \
281
+ intptr_t off, target_ulong addr, uintptr_t ra) \
282
+{ \
283
+ TYPE val = *(TYPE *)(za + tile_vslice_offset(off)); \
284
+ TLB(env, useronly_clean_ptr(addr), val, ra); \
285
+}
286
+
287
+/*
170
+/*
288
+ * The ARMVectorReg elements are stored in host-endian 64-bit units.
171
+ * The reference used is the STMicroElectronics RM0351 Reference manual
289
+ * For 128-bit quantities, the sequence defined by the Elem[] pseudocode
172
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
290
+ * corresponds to storing the two 64-bit pieces in little-endian order.
173
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
291
+ */
174
+ */
292
+#define DO_LDQ(HNAME, VNAME, BE, HOST, TLB) \
175
+
293
+static inline void HNAME##_host(void *za, intptr_t off, void *host) \
176
+#include "qemu/osdep.h"
294
+{ \
177
+#include "qemu/log.h"
295
+ uint64_t val0 = HOST(host), val1 = HOST(host + 8); \
178
+#include "hw/gpio/stm32l4x5_gpio.h"
296
+ uint64_t *ptr = za + off; \
179
+#include "hw/irq.h"
297
+ ptr[0] = BE ? val1 : val0, ptr[1] = BE ? val0 : val1; \
180
+#include "hw/qdev-clock.h"
298
+} \
181
+#include "hw/qdev-properties.h"
299
+static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
182
+#include "qapi/visitor.h"
300
+{ \
183
+#include "qapi/error.h"
301
+ HNAME##_host(za, tile_vslice_offset(off), host); \
184
+#include "migration/vmstate.h"
302
+} \
185
+#include "trace.h"
303
+static inline void HNAME##_tlb(CPUARMState *env, void *za, intptr_t off, \
186
+
304
+ target_ulong addr, uintptr_t ra) \
187
+#define GPIO_MODER 0x00
305
+{ \
188
+#define GPIO_OTYPER 0x04
306
+ uint64_t val0 = TLB(env, useronly_clean_ptr(addr), ra); \
189
+#define GPIO_OSPEEDR 0x08
307
+ uint64_t val1 = TLB(env, useronly_clean_ptr(addr + 8), ra); \
190
+#define GPIO_PUPDR 0x0C
308
+ uint64_t *ptr = za + off; \
191
+#define GPIO_IDR 0x10
309
+ ptr[0] = BE ? val1 : val0, ptr[1] = BE ? val0 : val1; \
192
+#define GPIO_ODR 0x14
310
+} \
193
+#define GPIO_BSRR 0x18
311
+static inline void VNAME##_v_tlb(CPUARMState *env, void *za, intptr_t off, \
194
+#define GPIO_LCKR 0x1C
312
+ target_ulong addr, uintptr_t ra) \
195
+#define GPIO_AFRL 0x20
313
+{ \
196
+#define GPIO_AFRH 0x24
314
+ HNAME##_tlb(env, za, tile_vslice_offset(off), addr, ra); \
197
+#define GPIO_BRR 0x28
315
+}
198
+#define GPIO_ASCR 0x2C
316
+
199
+
317
+#define DO_STQ(HNAME, VNAME, BE, HOST, TLB) \
200
+/* 0b11111111_11111111_00000000_00000000 */
318
+static inline void HNAME##_host(void *za, intptr_t off, void *host) \
201
+#define RESERVED_BITS_MASK 0xFFFF0000
319
+{ \
202
+
320
+ uint64_t *ptr = za + off; \
203
+static void update_gpio_idr(Stm32l4x5GpioState *s);
321
+ HOST(host, ptr[BE]); \
204
+
322
+ HOST(host + 1, ptr[!BE]); \
205
+static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
323
+} \
206
+{
324
+static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
207
+ return extract32(s->pupdr, 2 * pin, 2) == 1;
325
+{ \
208
+}
326
+ HNAME##_host(za, tile_vslice_offset(off), host); \
209
+
327
+} \
210
+static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
328
+static inline void HNAME##_tlb(CPUARMState *env, void *za, intptr_t off, \
211
+{
329
+ target_ulong addr, uintptr_t ra) \
212
+ return extract32(s->pupdr, 2 * pin, 2) == 2;
330
+{ \
213
+}
331
+ uint64_t *ptr = za + off; \
214
+
332
+ TLB(env, useronly_clean_ptr(addr), ptr[BE], ra); \
215
+static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
333
+ TLB(env, useronly_clean_ptr(addr + 8), ptr[!BE], ra); \
216
+{
334
+} \
217
+ return extract32(s->moder, 2 * pin, 2) == 1;
335
+static inline void VNAME##_v_tlb(CPUARMState *env, void *za, intptr_t off, \
218
+}
336
+ target_ulong addr, uintptr_t ra) \
219
+
337
+{ \
220
+static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
338
+ HNAME##_tlb(env, za, tile_vslice_offset(off), addr, ra); \
221
+{
339
+}
222
+ return extract32(s->otyper, pin, 1) == 1;
340
+
223
+}
341
+DO_LD(ld1b, uint8_t, ldub_p, cpu_ldub_data_ra)
224
+
342
+DO_LD(ld1h_be, uint16_t, lduw_be_p, cpu_lduw_be_data_ra)
225
+static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
343
+DO_LD(ld1h_le, uint16_t, lduw_le_p, cpu_lduw_le_data_ra)
226
+{
344
+DO_LD(ld1s_be, uint32_t, ldl_be_p, cpu_ldl_be_data_ra)
227
+ return extract32(s->otyper, pin, 1) == 0;
345
+DO_LD(ld1s_le, uint32_t, ldl_le_p, cpu_ldl_le_data_ra)
228
+}
346
+DO_LD(ld1d_be, uint64_t, ldq_be_p, cpu_ldq_be_data_ra)
229
+
347
+DO_LD(ld1d_le, uint64_t, ldq_le_p, cpu_ldq_le_data_ra)
230
+static void stm32l4x5_gpio_reset_hold(Object *obj)
348
+
231
+{
349
+DO_LDQ(sve_ld1qq_be, sme_ld1q_be, 1, ldq_be_p, cpu_ldq_be_data_ra)
232
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
350
+DO_LDQ(sve_ld1qq_le, sme_ld1q_le, 0, ldq_le_p, cpu_ldq_le_data_ra)
233
+
351
+
234
+ s->moder = s->moder_reset;
352
+DO_ST(st1b, uint8_t, stb_p, cpu_stb_data_ra)
235
+ s->otyper = 0x00000000;
353
+DO_ST(st1h_be, uint16_t, stw_be_p, cpu_stw_be_data_ra)
236
+ s->ospeedr = s->ospeedr_reset;
354
+DO_ST(st1h_le, uint16_t, stw_le_p, cpu_stw_le_data_ra)
237
+ s->pupdr = s->pupdr_reset;
355
+DO_ST(st1s_be, uint32_t, stl_be_p, cpu_stl_be_data_ra)
238
+ s->idr = 0x00000000;
356
+DO_ST(st1s_le, uint32_t, stl_le_p, cpu_stl_le_data_ra)
239
+ s->odr = 0x00000000;
357
+DO_ST(st1d_be, uint64_t, stq_be_p, cpu_stq_be_data_ra)
240
+ s->lckr = 0x00000000;
358
+DO_ST(st1d_le, uint64_t, stq_le_p, cpu_stq_le_data_ra)
241
+ s->afrl = 0x00000000;
359
+
242
+ s->afrh = 0x00000000;
360
+DO_STQ(sve_st1qq_be, sme_st1q_be, 1, stq_be_p, cpu_stq_be_data_ra)
243
+ s->ascr = 0x00000000;
361
+DO_STQ(sve_st1qq_le, sme_st1q_le, 0, stq_le_p, cpu_stq_le_data_ra)
244
+
362
+
245
+ s->disconnected_pins = 0xFFFF;
363
+#undef DO_LD
246
+ s->pins_connected_high = 0x0000;
364
+#undef DO_ST
247
+ update_gpio_idr(s);
365
+#undef DO_LDQ
248
+}
366
+#undef DO_STQ
249
+
367
+
250
+static void stm32l4x5_gpio_set(void *opaque, int line, int level)
368
+/*
251
+{
369
+ * Common helper for all contiguous predicated loads.
252
+ Stm32l4x5GpioState *s = opaque;
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
+
402
+ /*
253
+ /*
403
+ * Handle mte checks for all active elements.
254
+ * The pin isn't set if line is configured in output mode
404
+ * Since TBI must be set for MTE, !mtedesc => !mte_active.
255
+ * except if level is 0 and the output is open-drain.
256
+ * This way there will be no short-circuit prone situations.
405
+ */
257
+ */
406
+ if (mtedesc) {
258
+ if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
407
+ sve_cont_ldst_mte_check(&info, env, vg, addr, esize, esize,
259
+ qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
408
+ mtedesc, ra);
260
+ line);
409
+ }
261
+ return;
410
+
262
+ }
411
+ flags = info.page[0].flags | info.page[1].flags;
263
+
412
+ if (unlikely(flags != 0)) {
264
+ s->disconnected_pins &= ~(1 << line);
413
+#ifdef CONFIG_USER_ONLY
265
+ if (level) {
414
+ g_assert_not_reached();
266
+ s->pins_connected_high |= (1 << line);
415
+#else
267
+ } else {
416
+ /*
268
+ s->pins_connected_high &= ~(1 << line);
417
+ * At least one page includes MMIO.
269
+ }
418
+ * Any bus operation can fail with cpu_transaction_failed,
270
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
419
+ * which for ARM will raise SyncExternal. Perform the load
271
+ s->pins_connected_high);
420
+ * into scratch memory to preserve register state until the end.
272
+ update_gpio_idr(s);
421
+ */
273
+}
422
+ ARMVectorReg scratch = { };
274
+
423
+
275
+
424
+ reg_off = info.reg_off_first[0];
276
+static void update_gpio_idr(Stm32l4x5GpioState *s)
425
+ reg_last = info.reg_off_last[1];
277
+{
426
+ if (reg_last < 0) {
278
+ uint32_t new_idr_mask = 0;
427
+ reg_last = info.reg_off_split;
279
+ uint32_t new_idr = s->odr;
428
+ if (reg_last < 0) {
280
+ uint32_t old_idr = s->idr;
429
+ reg_last = info.reg_off_last[0];
281
+ int new_pin_state, old_pin_state;
282
+
283
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
284
+ if (is_output(s, i)) {
285
+ if (is_push_pull(s, i)) {
286
+ new_idr_mask |= (1 << i);
287
+ } else if (!(s->odr & (1 << i))) {
288
+ /* open-drain ODR 0 */
289
+ new_idr_mask |= (1 << i);
290
+ /* open-drain ODR 1 */
291
+ } else if (!(s->disconnected_pins & (1 << i)) &&
292
+ !(s->pins_connected_high & (1 << i))) {
293
+ /* open-drain ODR 1 with pin connected low */
294
+ new_idr_mask |= (1 << i);
295
+ new_idr &= ~(1 << i);
296
+ /* open-drain ODR 1 with unactive pin */
297
+ } else if (is_pull_up(s, i)) {
298
+ new_idr_mask |= (1 << i);
299
+ } else if (is_pull_down(s, i)) {
300
+ new_idr_mask |= (1 << i);
301
+ new_idr &= ~(1 << i);
302
+ }
303
+ /*
304
+ * The only case left is for open-drain ODR 1
305
+ * with unactive pin without pull-up or pull-down :
306
+ * the value is floating.
307
+ */
308
+ /* input or analog mode with connected pin */
309
+ } else if (!(s->disconnected_pins & (1 << i))) {
310
+ if (s->pins_connected_high & (1 << i)) {
311
+ /* pin high */
312
+ new_idr_mask |= (1 << i);
313
+ new_idr |= (1 << i);
314
+ } else {
315
+ /* pin low */
316
+ new_idr_mask |= (1 << i);
317
+ new_idr &= ~(1 << i);
318
+ }
319
+ /* input or analog mode with disconnected pin */
320
+ } else {
321
+ if (is_pull_up(s, i)) {
322
+ /* pull-up */
323
+ new_idr_mask |= (1 << i);
324
+ new_idr |= (1 << i);
325
+ } else if (is_pull_down(s, i)) {
326
+ /* pull-down */
327
+ new_idr_mask |= (1 << i);
328
+ new_idr &= ~(1 << i);
329
+ }
330
+ /*
331
+ * The only case left is for a disconnected pin
332
+ * without pull-up or pull-down :
333
+ * the value is floating.
334
+ */
335
+ }
336
+ }
337
+
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
340
+
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
342
+ if (new_idr_mask & (1 << i)) {
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
345
+ if (new_pin_state > old_pin_state) {
346
+ qemu_irq_raise(s->pin[i]);
347
+ } else if (new_pin_state < old_pin_state) {
348
+ qemu_irq_lower(s->pin[i]);
430
+ }
349
+ }
431
+ }
350
+ }
432
+
351
+ }
433
+ do {
352
+}
434
+ uint64_t pg = vg[reg_off >> 6];
435
+ do {
436
+ if ((pg >> (reg_off & 63)) & 1) {
437
+ tlb_fn(env, &scratch, reg_off, addr + reg_off, ra);
438
+ }
439
+ reg_off += esize;
440
+ } while (reg_off & 63);
441
+ } while (reg_off <= reg_last);
442
+
443
+ cpy_fn(za, &scratch, reg_max);
444
+ return;
445
+#endif
446
+ }
447
+
448
+ /* The entire operation is in RAM, on valid pages. */
449
+
450
+ reg_off = info.reg_off_first[0];
451
+ reg_last = info.reg_off_last[0];
452
+ host = info.page[0].host;
453
+
454
+ if (!vertical) {
455
+ memset(za, 0, reg_max);
456
+ } else if (reg_off) {
457
+ clr_fn(za, 0, reg_off);
458
+ }
459
+
460
+ while (reg_off <= reg_last) {
461
+ uint64_t pg = vg[reg_off >> 6];
462
+ do {
463
+ if ((pg >> (reg_off & 63)) & 1) {
464
+ host_fn(za, reg_off, host + reg_off);
465
+ } else if (vertical) {
466
+ clr_fn(za, reg_off, esize);
467
+ }
468
+ reg_off += esize;
469
+ } while (reg_off <= reg_last && (reg_off & 63));
470
+ }
471
+
472
+ /*
473
+ * Use the slow path to manage the cross-page misalignment.
474
+ * But we know this is RAM and cannot trap.
475
+ */
476
+ reg_off = info.reg_off_split;
477
+ if (unlikely(reg_off >= 0)) {
478
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
479
+ }
480
+
481
+ reg_off = info.reg_off_first[1];
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
+
353
+
567
+/*
354
+/*
568
+ * Common helper for all contiguous predicated stores.
355
+ * Return mask of pins that are both configured in output
356
+ * mode and externally driven (except pins in open-drain
357
+ * mode externally set to 0).
569
+ */
358
+ */
570
+
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
571
+static inline QEMU_ALWAYS_INLINE
360
+{
572
+void sme_st1(CPUARMState *env, void *za, uint64_t *vg,
361
+ uint32_t pins_to_disconnect = 0;
573
+ const target_ulong addr, uint32_t desc, const uintptr_t ra,
362
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
574
+ const int esz, uint32_t mtedesc, bool vertical,
363
+ /* for each connected pin in output mode */
575
+ sve_ldst1_host_fn *host_fn,
364
+ if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
576
+ sve_ldst1_tlb_fn *tlb_fn)
365
+ /* if either push-pull or high level */
577
+{
366
+ if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
578
+ const intptr_t reg_max = simd_oprsz(desc);
367
+ pins_to_disconnect |= (1 << i);
579
+ const intptr_t esize = 1 << esz;
368
+ qemu_log_mask(LOG_GUEST_ERROR,
580
+ intptr_t reg_off, reg_last;
369
+ "Line %d can't be driven externally\n",
581
+ SVEContLdSt info;
370
+ i);
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
+ }
371
+ }
625
+ }
372
+ }
626
+
373
+ }
627
+ do {
374
+ return pins_to_disconnect;
628
+ uint64_t pg = vg[reg_off >> 6];
375
+}
629
+ do {
376
+
630
+ if ((pg >> (reg_off & 63)) & 1) {
377
+/*
631
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
378
+ * Set field `disconnected_pins` and call `update_gpio_idr()`
632
+ }
379
+ */
633
+ reg_off += esize;
380
+static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
634
+ } while (reg_off & 63);
381
+{
635
+ } while (reg_off <= reg_last);
382
+ s->disconnected_pins |= lines;
636
+ return;
383
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
637
+#endif
384
+ s->pins_connected_high);
638
+ }
385
+ update_gpio_idr(s);
639
+
386
+}
640
+ reg_off = info.reg_off_first[0];
387
+
641
+ reg_last = info.reg_off_last[0];
388
+static void disconnected_pins_set(Object *obj, Visitor *v,
642
+ host = info.page[0].host;
389
+ const char *name, void *opaque, Error **errp)
643
+
390
+{
644
+ while (reg_off <= reg_last) {
391
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
645
+ uint64_t pg = vg[reg_off >> 6];
392
+ uint16_t value;
646
+ do {
393
+ if (!visit_type_uint16(v, name, &value, errp)) {
647
+ if ((pg >> (reg_off & 63)) & 1) {
394
+ return;
648
+ host_fn(za, reg_off, host + reg_off);
395
+ }
649
+ }
396
+ disconnect_gpio_pins(s, value);
650
+ reg_off += 1 << esz;
397
+}
651
+ } while (reg_off <= reg_last && (reg_off & 63));
398
+
652
+ }
399
+static void disconnected_pins_get(Object *obj, Visitor *v,
653
+
400
+ const char *name, void *opaque, Error **errp)
654
+ /*
401
+{
655
+ * Use the slow path to manage the cross-page misalignment.
402
+ visit_type_uint16(v, name, (uint16_t *)opaque, errp);
656
+ * But we know this is RAM and cannot trap.
403
+}
657
+ */
404
+
658
+ reg_off = info.reg_off_split;
405
+static void clock_freq_get(Object *obj, Visitor *v,
659
+ if (unlikely(reg_off >= 0)) {
406
+ const char *name, void *opaque, Error **errp)
660
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
407
+{
661
+ }
408
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
662
+
409
+ uint32_t clock_freq_hz = clock_get_hz(s->clk);
663
+ reg_off = info.reg_off_first[1];
410
+ visit_type_uint32(v, name, &clock_freq_hz, errp);
664
+ if (unlikely(reg_off >= 0)) {
411
+}
665
+ reg_last = info.reg_off_last[1];
412
+
666
+ host = info.page[1].host;
413
+static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
667
+
414
+ uint64_t val64, unsigned int size)
668
+ do {
415
+{
669
+ uint64_t pg = vg[reg_off >> 6];
416
+ Stm32l4x5GpioState *s = opaque;
670
+ do {
417
+
671
+ if ((pg >> (reg_off & 63)) & 1) {
418
+ uint32_t value = val64;
672
+ host_fn(za, reg_off, host + reg_off);
419
+ trace_stm32l4x5_gpio_write(s->name, addr, val64);
673
+ }
420
+
674
+ reg_off += 1 << esz;
421
+ switch (addr) {
675
+ } while (reg_off & 63);
422
+ case GPIO_MODER:
676
+ } while (reg_off <= reg_last);
423
+ s->moder = value;
677
+ }
424
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
678
+}
425
+ qemu_log_mask(LOG_UNIMP,
679
+
426
+ "%s: Analog and AF modes aren't supported\n\
680
+static inline QEMU_ALWAYS_INLINE
427
+ Analog and AF mode behave like input mode\n",
681
+void sme_st1_mte(CPUARMState *env, void *za, uint64_t *vg, target_ulong addr,
428
+ __func__);
682
+ uint32_t desc, uintptr_t ra, int esz, bool vertical,
429
+ return;
683
+ sve_ldst1_host_fn *host_fn,
430
+ case GPIO_OTYPER:
684
+ sve_ldst1_tlb_fn *tlb_fn)
431
+ s->otyper = value & ~RESERVED_BITS_MASK;
685
+{
432
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
686
+ uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
433
+ return;
687
+ int bit55 = extract64(addr, 55, 1);
434
+ case GPIO_OSPEEDR:
688
+
435
+ qemu_log_mask(LOG_UNIMP,
689
+ /* Remove mtedesc from the normal sve descriptor. */
436
+ "%s: Changing I/O output speed isn't supported\n\
690
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
437
+ I/O speed is already maximal\n",
691
+
438
+ __func__);
692
+ /* Perform gross MTE suppression early. */
439
+ s->ospeedr = value;
693
+ if (!tbi_check(desc, bit55) ||
440
+ return;
694
+ tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
441
+ case GPIO_PUPDR:
695
+ mtedesc = 0;
442
+ s->pupdr = value;
696
+ }
443
+ update_gpio_idr(s);
697
+
444
+ return;
698
+ sme_st1(env, za, vg, addr, desc, ra, esz, mtedesc,
445
+ case GPIO_IDR:
699
+ vertical, host_fn, tlb_fn);
446
+ qemu_log_mask(LOG_UNIMP,
700
+}
447
+ "%s: GPIO->IDR is read-only\n",
701
+
448
+ __func__);
702
+#define DO_ST(L, END, ESZ) \
449
+ return;
703
+void HELPER(sme_st1##L##END##_h)(CPUARMState *env, void *za, void *vg, \
450
+ case GPIO_ODR:
704
+ target_ulong addr, uint32_t desc) \
451
+ s->odr = value & ~RESERVED_BITS_MASK;
705
+{ \
452
+ update_gpio_idr(s);
706
+ sme_st1(env, za, vg, addr, desc, GETPC(), ESZ, 0, false, \
453
+ return;
707
+ sve_st1##L##L##END##_host, sve_st1##L##L##END##_tlb); \
454
+ case GPIO_BSRR: {
708
+} \
455
+ uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
709
+void HELPER(sme_st1##L##END##_v)(CPUARMState *env, void *za, void *vg, \
456
+ uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
710
+ target_ulong addr, uint32_t desc) \
457
+ /* If both BSx and BRx are set, BSx has priority.*/
711
+{ \
458
+ s->odr &= ~bits_to_reset;
712
+ sme_st1(env, za, vg, addr, desc, GETPC(), ESZ, 0, true, \
459
+ s->odr |= bits_to_set;
713
+ sme_st1##L##END##_v_host, sme_st1##L##END##_v_tlb); \
460
+ update_gpio_idr(s);
714
+} \
461
+ return;
715
+void HELPER(sme_st1##L##END##_h_mte)(CPUARMState *env, void *za, void *vg, \
462
+ }
716
+ target_ulong addr, uint32_t desc) \
463
+ case GPIO_LCKR:
717
+{ \
464
+ qemu_log_mask(LOG_UNIMP,
718
+ sme_st1_mte(env, za, vg, addr, desc, GETPC(), ESZ, false, \
465
+ "%s: Locking port bits configuration isn't supported\n",
719
+ sve_st1##L##L##END##_host, sve_st1##L##L##END##_tlb); \
466
+ __func__);
720
+} \
467
+ s->lckr = value & ~RESERVED_BITS_MASK;
721
+void HELPER(sme_st1##L##END##_v_mte)(CPUARMState *env, void *za, void *vg, \
468
+ return;
722
+ target_ulong addr, uint32_t desc) \
469
+ case GPIO_AFRL:
723
+{ \
470
+ qemu_log_mask(LOG_UNIMP,
724
+ sme_st1_mte(env, za, vg, addr, desc, GETPC(), ESZ, true, \
471
+ "%s: Alternate functions aren't supported\n",
725
+ sme_st1##L##END##_v_host, sme_st1##L##END##_v_tlb); \
472
+ __func__);
726
+}
473
+ s->afrl = value;
727
+
474
+ return;
728
+DO_ST(b, , MO_8)
475
+ case GPIO_AFRH:
729
+DO_ST(h, _be, MO_16)
476
+ qemu_log_mask(LOG_UNIMP,
730
+DO_ST(h, _le, MO_16)
477
+ "%s: Alternate functions aren't supported\n",
731
+DO_ST(s, _be, MO_32)
478
+ __func__);
732
+DO_ST(s, _le, MO_32)
479
+ s->afrh = value;
733
+DO_ST(d, _be, MO_64)
480
+ return;
734
+DO_ST(d, _le, MO_64)
481
+ case GPIO_BRR: {
735
+DO_ST(q, _be, MO_128)
482
+ uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
736
+DO_ST(q, _le, MO_128)
483
+ s->odr &= ~bits_to_reset;
737
+
484
+ update_gpio_idr(s);
738
+#undef DO_ST
485
+ return;
739
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
486
+ }
487
+ case GPIO_ASCR:
488
+ qemu_log_mask(LOG_UNIMP,
489
+ "%s: ADC function isn't supported\n",
490
+ __func__);
491
+ s->ascr = value & ~RESERVED_BITS_MASK;
492
+ return;
493
+ default:
494
+ qemu_log_mask(LOG_GUEST_ERROR,
495
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
496
+ }
497
+}
498
+
499
+static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
500
+ unsigned int size)
501
+{
502
+ Stm32l4x5GpioState *s = opaque;
503
+
504
+ trace_stm32l4x5_gpio_read(s->name, addr);
505
+
506
+ switch (addr) {
507
+ case GPIO_MODER:
508
+ return s->moder;
509
+ case GPIO_OTYPER:
510
+ return s->otyper;
511
+ case GPIO_OSPEEDR:
512
+ return s->ospeedr;
513
+ case GPIO_PUPDR:
514
+ return s->pupdr;
515
+ case GPIO_IDR:
516
+ return s->idr;
517
+ case GPIO_ODR:
518
+ return s->odr;
519
+ case GPIO_BSRR:
520
+ return 0;
521
+ case GPIO_LCKR:
522
+ return s->lckr;
523
+ case GPIO_AFRL:
524
+ return s->afrl;
525
+ case GPIO_AFRH:
526
+ return s->afrh;
527
+ case GPIO_BRR:
528
+ return 0;
529
+ case GPIO_ASCR:
530
+ return s->ascr;
531
+ default:
532
+ qemu_log_mask(LOG_GUEST_ERROR,
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
534
+ return 0;
535
+ }
536
+}
537
+
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
539
+ .read = stm32l4x5_gpio_read,
540
+ .write = stm32l4x5_gpio_write,
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
542
+ .impl = {
543
+ .min_access_size = 4,
544
+ .max_access_size = 4,
545
+ .unaligned = false,
546
+ },
547
+ .valid = {
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
551
+ },
552
+};
553
+
554
+static void stm32l4x5_gpio_init(Object *obj)
555
+{
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
557
+
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
559
+ TYPE_STM32L4X5_GPIO, 0x400);
560
+
561
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
562
+
563
+ qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
564
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
565
+
566
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
567
+
568
+ object_property_add(obj, "disconnected-pins", "uint16",
569
+ disconnected_pins_get, disconnected_pins_set,
570
+ NULL, &s->disconnected_pins);
571
+ object_property_add(obj, "clock-freq-hz", "uint32",
572
+ clock_freq_get, NULL, NULL, NULL);
573
+}
574
+
575
+static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
576
+{
577
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
578
+ if (!clock_has_source(s->clk)) {
579
+ error_setg(errp, "GPIO: clk input must be connected");
580
+ return;
581
+ }
582
+}
583
+
584
+static const VMStateDescription vmstate_stm32l4x5_gpio = {
585
+ .name = TYPE_STM32L4X5_GPIO,
586
+ .version_id = 1,
587
+ .minimum_version_id = 1,
588
+ .fields = (VMStateField[]){
589
+ VMSTATE_UINT32(moder, Stm32l4x5GpioState),
590
+ VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
591
+ VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
592
+ VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
593
+ VMSTATE_UINT32(idr, Stm32l4x5GpioState),
594
+ VMSTATE_UINT32(odr, Stm32l4x5GpioState),
595
+ VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
596
+ VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
597
+ VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
598
+ VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
599
+ VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
600
+ VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
601
+ VMSTATE_END_OF_LIST()
602
+ }
603
+};
604
+
605
+static Property stm32l4x5_gpio_properties[] = {
606
+ DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
607
+ DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
608
+ DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
609
+ DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
610
+ DEFINE_PROP_END_OF_LIST(),
611
+};
612
+
613
+static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
614
+{
615
+ DeviceClass *dc = DEVICE_CLASS(klass);
616
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
617
+
618
+ device_class_set_props(dc, stm32l4x5_gpio_properties);
619
+ dc->vmsd = &vmstate_stm32l4x5_gpio;
620
+ dc->realize = stm32l4x5_gpio_realize;
621
+ rc->phases.hold = stm32l4x5_gpio_reset_hold;
622
+}
623
+
624
+static const TypeInfo stm32l4x5_gpio_types[] = {
625
+ {
626
+ .name = TYPE_STM32L4X5_GPIO,
627
+ .parent = TYPE_SYS_BUS_DEVICE,
628
+ .instance_size = sizeof(Stm32l4x5GpioState),
629
+ .instance_init = stm32l4x5_gpio_init,
630
+ .class_init = stm32l4x5_gpio_class_init,
631
+ },
632
+};
633
+
634
+DEFINE_TYPES(stm32l4x5_gpio_types)
635
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
740
index XXXXXXX..XXXXXXX 100644
636
index XXXXXXX..XXXXXXX 100644
741
--- a/target/arm/translate-sme.c
637
--- a/hw/gpio/Kconfig
742
+++ b/target/arm/translate-sme.c
638
+++ b/hw/gpio/Kconfig
743
@@ -XXX,XX +XXX,XX @@ static bool trans_MOVA(DisasContext *s, arg_MOVA *a)
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
744
640
745
return true;
641
config SIFIVE_GPIO
746
}
642
bool
747
+
643
+
748
+static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
644
+config STM32L4X5_GPIO
749
+{
645
+ bool
750
+ typedef void GenLdSt1(TCGv_env, TCGv_ptr, TCGv_ptr, TCGv, TCGv_i32);
646
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
751
+
647
index XXXXXXX..XXXXXXX 100644
752
+ /*
648
--- a/hw/gpio/meson.build
753
+ * Indexed by [esz][be][v][mte][st], which is (except for load/store)
649
+++ b/hw/gpio/meson.build
754
+ * also the order in which the elements appear in the function names,
650
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
755
+ * and so how we must concatenate the pieces.
651
'bcm2835_gpio.c',
756
+ */
652
'bcm2838_gpio.c'
757
+
653
))
758
+#define FN_LS(F) { gen_helper_sme_ld1##F, gen_helper_sme_st1##F }
654
+system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
759
+#define FN_MTE(F) { FN_LS(F), FN_LS(F##_mte) }
655
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
760
+#define FN_HV(F) { FN_MTE(F##_h), FN_MTE(F##_v) }
656
system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
761
+#define FN_END(L, B) { FN_HV(L), FN_HV(B) }
657
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
762
+
658
index XXXXXXX..XXXXXXX 100644
763
+ static GenLdSt1 * const fns[5][2][2][2][2] = {
659
--- a/hw/gpio/trace-events
764
+ FN_END(b, b),
660
+++ b/hw/gpio/trace-events
765
+ FN_END(h_le, h_be),
661
@@ -XXX,XX +XXX,XX @@ sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " val
766
+ FN_END(s_le, s_be),
662
# aspeed_gpio.c
767
+ FN_END(d_le, d_be),
663
aspeed_gpio_read(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
768
+ FN_END(q_le, q_be),
664
aspeed_gpio_write(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
769
+ };
665
+
770
+
666
+# stm32l4x5_gpio.c
771
+#undef FN_LS
667
+stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
772
+#undef FN_MTE
668
+stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
773
+#undef FN_HV
669
+stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
774
+#undef FN_END
670
+stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
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
--
671
--
818
2.25.1
672
2.34.1
673
674
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Move the checks out of the parsing loop and into the
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
restore function. This more closely mirrors the code
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
structure in the kernel, and is slightly clearer.
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Reject rather than silently skip incorrect VL and SVE record sizes,
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
bringing our checks in to line with those the kernel does.
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
9
---
15
linux-user/aarch64/signal.c | 51 +++++++++++++++++++++++++------------
10
include/hw/arm/stm32l4x5_soc.h | 2 +
16
1 file changed, 35 insertions(+), 16 deletions(-)
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
17
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
18
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
19
index XXXXXXX..XXXXXXX 100644
14
hw/misc/stm32l4x5_syscfg.c | 1 +
20
--- a/linux-user/aarch64/signal.c
15
hw/arm/Kconfig | 3 +-
21
+++ b/linux-user/aarch64/signal.c
16
6 files changed, 63 insertions(+), 18 deletions(-)
22
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
17
23
}
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/stm32l4x5_soc.h
21
+++ b/include/hw/arm/stm32l4x5_soc.h
22
@@ -XXX,XX +XXX,XX @@
23
#include "hw/misc/stm32l4x5_syscfg.h"
24
#include "hw/misc/stm32l4x5_exti.h"
25
#include "hw/misc/stm32l4x5_rcc.h"
26
+#include "hw/gpio/stm32l4x5_gpio.h"
27
#include "qom/object.h"
28
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
32
Stm32l4x5SyscfgState syscfg;
33
Stm32l4x5RccState rcc;
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
35
36
MemoryRegion sram1;
37
MemoryRegion sram2;
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
42
@@ -XXX,XX +XXX,XX @@
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
45
46
+#define NUM_GPIOS 8
47
#define GPIO_NUM_PINS 16
48
49
struct Stm32l4x5GpioState {
50
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/hw/misc/stm32l4x5_syscfg.h
53
+++ b/include/hw/misc/stm32l4x5_syscfg.h
54
@@ -XXX,XX +XXX,XX @@
55
56
#include "hw/sysbus.h"
57
#include "qom/object.h"
58
+#include "hw/gpio/stm32l4x5_gpio.h"
59
60
#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
61
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
62
63
-#define NUM_GPIOS 8
64
-#define GPIO_NUM_PINS 16
65
#define SYSCFG_NUM_EXTICR 4
66
67
struct Stm32l4x5SyscfgState {
68
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/arm/stm32l4x5_soc.c
71
+++ b/hw/arm/stm32l4x5_soc.c
72
@@ -XXX,XX +XXX,XX @@
73
#include "sysemu/sysemu.h"
74
#include "hw/or-irq.h"
75
#include "hw/arm/stm32l4x5_soc.h"
76
+#include "hw/gpio/stm32l4x5_gpio.h"
77
#include "hw/qdev-clock.h"
78
#include "hw/misc/unimp.h"
79
80
@@ -XXX,XX +XXX,XX @@ static const int exti_or_gate1_lines_in[EXTI_OR_GATE1_NUM_LINES_IN] = {
81
16, 35, 36, 37, 38,
82
};
83
84
+static const struct {
85
+ uint32_t addr;
86
+ uint32_t moder_reset;
87
+ uint32_t ospeedr_reset;
88
+ uint32_t pupdr_reset;
89
+} stm32l4x5_gpio_cfg[NUM_GPIOS] = {
90
+ { 0x48000000, 0xABFFFFFF, 0x0C000000, 0x64000000 },
91
+ { 0x48000400, 0xFFFFFEBF, 0x00000000, 0x00000100 },
92
+ { 0x48000800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
93
+ { 0x48000C00, 0xFFFFFFFF, 0x00000000, 0x00000000 },
94
+ { 0x48001000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
95
+ { 0x48001400, 0xFFFFFFFF, 0x00000000, 0x00000000 },
96
+ { 0x48001800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
97
+ { 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
98
+};
99
+
100
static void stm32l4x5_soc_initfn(Object *obj)
101
{
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
104
}
105
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
106
object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
107
+
108
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
109
+ g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
110
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
111
+ }
24
}
112
}
25
113
26
-static void target_restore_sve_record(CPUARMState *env,
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
27
- struct target_sve_context *sve, int vq)
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
28
+static bool target_restore_sve_record(CPUARMState *env,
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
29
+ struct target_sve_context *sve,
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
30
+ int size)
118
MemoryRegion *system_memory = get_system_memory();
31
{
119
- DeviceState *armv7m;
32
- int i, j;
120
+ DeviceState *armv7m, *dev;
33
+ int i, j, vl, vq;
121
SysBusDevice *busdev;
34
122
+ uint32_t pin_index;
35
- /* Note that SVE regs are stored as a byte stream, with each byte element
123
36
+ if (!cpu_isar_feature(aa64_sve, env_archcpu(env))) {
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
37
+ return false;
125
sc->flash_size, errp)) {
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
127
return;
128
}
129
130
+ /* GPIOs */
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
133
+ dev = DEVICE(&s->gpio[i]);
134
+ qdev_prop_set_string(dev, "name", name);
135
+ qdev_prop_set_uint32(dev, "mode-reset",
136
+ stm32l4x5_gpio_cfg[i].moder_reset);
137
+ qdev_prop_set_uint32(dev, "ospeed-reset",
138
+ stm32l4x5_gpio_cfg[i].ospeedr_reset);
139
+ qdev_prop_set_uint32(dev, "pupd-reset",
140
+ stm32l4x5_gpio_cfg[i].pupdr_reset);
141
+ busdev = SYS_BUS_DEVICE(&s->gpio[i]);
142
+ g_free(name);
143
+ name = g_strdup_printf("gpio%c-out", 'a' + i);
144
+ qdev_connect_clock_in(DEVICE(&s->gpio[i]), "clk",
145
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
146
+ if (!sysbus_realize(busdev, errp)) {
147
+ return;
148
+ }
149
+ sysbus_mmio_map(busdev, 0, stm32l4x5_gpio_cfg[i].addr);
38
+ }
150
+ }
39
+
151
+
40
+ __get_user(vl, &sve->vl);
152
/* System configuration controller */
41
+ vq = sve_vq(env);
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
42
+
154
if (!sysbus_realize(busdev, errp)) {
43
+ /* Reject mismatched VL. */
155
return;
44
+ if (vl != vq * TARGET_SVE_VQ_BYTES) {
156
}
45
+ return false;
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
158
- /*
159
- * TODO: when the GPIO device is implemented, connect it
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
161
- * GPIO_NUM_PINS.
162
- */
163
+
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
166
+ pin_index = GPIO_NUM_PINS * i + j;
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
169
+ pin_index));
170
+ }
46
+ }
171
+ }
47
+
172
48
+ /* Accept empty record -- used to clear PSTATE.SM. */
173
/* EXTI device */
49
+ if (size <= sizeof(*sve)) {
174
busdev = SYS_BUS_DEVICE(&s->exti);
50
+ return true;
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
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
}
176
}
66
}
177
}
67
+ return true;
178
68
}
179
- for (unsigned i = 0; i < 16; i++) {
69
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
70
static int target_restore_sigframe(CPUARMState *env,
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
71
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
72
struct target_sve_context *sve = NULL;
183
}
73
uint64_t extra_datap = 0;
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
74
bool used_extra = false;
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
75
- int vq = 0, sve_size = 0;
186
76
+ int sve_size = 0;
187
/* AHB2 BUS */
77
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
78
target_restore_general_frame(env, sf);
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
79
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
80
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
81
if (sve || size < sizeof(struct target_sve_context)) {
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
82
goto err;
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
83
}
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
84
- if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
85
- vq = sve_vq(env);
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
86
- sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
87
- if (size == sve_size) {
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
88
- sve = (struct target_sve_context *)ctx;
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
89
- break;
200
index XXXXXXX..XXXXXXX 100644
90
- }
201
--- a/hw/misc/stm32l4x5_syscfg.c
91
- }
202
+++ b/hw/misc/stm32l4x5_syscfg.c
92
- goto err;
203
@@ -XXX,XX +XXX,XX @@
93
+ sve = (struct target_sve_context *)ctx;
204
#include "hw/irq.h"
94
+ sve_size = size;
205
#include "migration/vmstate.h"
95
+ break;
206
#include "hw/misc/stm32l4x5_syscfg.h"
96
207
+#include "hw/gpio/stm32l4x5_gpio.h"
97
case TARGET_EXTRA_MAGIC:
208
98
if (extra || size != sizeof(struct target_extra_context)) {
209
#define SYSCFG_MEMRMP 0x00
99
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
210
#define SYSCFG_CFGR1 0x04
100
}
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
101
212
index XXXXXXX..XXXXXXX 100644
102
/* SVE data, if present, overwrites FPSIMD data. */
213
--- a/hw/arm/Kconfig
103
- if (sve) {
214
+++ b/hw/arm/Kconfig
104
- target_restore_sve_record(env, sve, vq);
215
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
105
+ if (sve && !target_restore_sve_record(env, sve, sve_size)) {
216
bool
106
+ goto err;
217
select ARM_V7M
107
}
218
select OR_IRQ
108
unlock_user(extra, extra_datap, 0);
219
- select STM32L4X5_SYSCFG
109
return 0;
220
select STM32L4X5_EXTI
221
+ select STM32L4X5_SYSCFG
222
select STM32L4X5_RCC
223
+ select STM32L4X5_GPIO
224
225
config XLNX_ZYNQMP_ARM
226
bool
110
--
227
--
111
2.25.1
228
2.34.1
229
230
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Enable SME, TPIDR2_EL0, and FA64 if supported by the cpu.
3
The testcase contains :
4
- `test_idr_reset_value()` :
5
Checks the reset values of MODER, OTYPER, PUPDR, ODR and IDR.
6
- `test_gpio_output_mode()` :
7
Checks that writing a bit in register ODR results in the corresponding
8
pin rising or lowering, if this pin is configured in output mode.
9
- `test_gpio_input_mode()` :
10
Checks that a input pin set high or low externally results
11
in the pin rising and lowering.
12
- `test_pull_up_pull_down()` :
13
Checks that a floating pin in pull-up/down mode is actually high/down.
14
- `test_push_pull()` :
15
Checks that a pin set externally is disconnected when configured in
16
push-pull output mode, and can't be set externally while in this mode.
17
- `test_open_drain()` :
18
Checks that a pin set externally high is disconnected when configured
19
in open-drain output mode, and can't be set high while in this mode.
20
- `test_bsrr_brr()` :
21
Checks that writing to BSRR and BRR has the desired result in ODR.
22
- `test_clock_enable()` :
23
Checks that GPIO clock is at the right frequency after enabling it.
4
24
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Acked-by: Thomas Huth <thuth@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
7
Message-id: 20220708151540.18136-45-richard.henderson@linaro.org
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
30
---
10
target/arm/cpu.c | 11 +++++++++++
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
11
1 file changed, 11 insertions(+)
32
tests/qtest/meson.build | 3 +-
33
2 files changed, 553 insertions(+), 1 deletion(-)
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
12
35
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
37
new file mode 100644
38
index XXXXXXX..XXXXXXX
39
--- /dev/null
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
41
@@ -XXX,XX +XXX,XX @@
42
+/*
43
+ * QTest testcase for STM32L4x5_GPIO
44
+ *
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
47
+ *
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
49
+ * See the COPYING file in the top-level directory.
50
+ */
51
+
52
+#include "qemu/osdep.h"
53
+#include "libqtest-single.h"
54
+
55
+#define GPIO_BASE_ADDR 0x48000000
56
+#define GPIO_SIZE 0x400
57
+#define NUM_GPIOS 8
58
+#define NUM_GPIO_PINS 16
59
+
60
+#define GPIO_A 0x48000000
61
+#define GPIO_B 0x48000400
62
+#define GPIO_C 0x48000800
63
+#define GPIO_D 0x48000C00
64
+#define GPIO_E 0x48001000
65
+#define GPIO_F 0x48001400
66
+#define GPIO_G 0x48001800
67
+#define GPIO_H 0x48001C00
68
+
69
+#define MODER 0x00
70
+#define OTYPER 0x04
71
+#define PUPDR 0x0C
72
+#define IDR 0x10
73
+#define ODR 0x14
74
+#define BSRR 0x18
75
+#define BRR 0x28
76
+
77
+#define MODER_INPUT 0
78
+#define MODER_OUTPUT 1
79
+
80
+#define PUPDR_NONE 0
81
+#define PUPDR_PULLUP 1
82
+#define PUPDR_PULLDOWN 2
83
+
84
+#define OTYPER_PUSH_PULL 0
85
+#define OTYPER_OPEN_DRAIN 1
86
+
87
+const uint32_t moder_reset[NUM_GPIOS] = {
88
+ 0xABFFFFFF,
89
+ 0xFFFFFEBF,
90
+ 0xFFFFFFFF,
91
+ 0xFFFFFFFF,
92
+ 0xFFFFFFFF,
93
+ 0xFFFFFFFF,
94
+ 0xFFFFFFFF,
95
+ 0x0000000F
96
+};
97
+
98
+const uint32_t pupdr_reset[NUM_GPIOS] = {
99
+ 0x64000000,
100
+ 0x00000100,
101
+ 0x00000000,
102
+ 0x00000000,
103
+ 0x00000000,
104
+ 0x00000000,
105
+ 0x00000000,
106
+ 0x00000000
107
+};
108
+
109
+const uint32_t idr_reset[NUM_GPIOS] = {
110
+ 0x0000A000,
111
+ 0x00000010,
112
+ 0x00000000,
113
+ 0x00000000,
114
+ 0x00000000,
115
+ 0x00000000,
116
+ 0x00000000,
117
+ 0x00000000
118
+};
119
+
120
+static uint32_t gpio_readl(unsigned int gpio, unsigned int offset)
121
+{
122
+ return readl(gpio + offset);
123
+}
124
+
125
+static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value)
126
+{
127
+ writel(gpio + offset, value);
128
+}
129
+
130
+static void gpio_set_bit(unsigned int gpio, unsigned int reg,
131
+ unsigned int pin, uint32_t value)
132
+{
133
+ uint32_t mask = 0xFFFFFFFF & ~(0x1 << pin);
134
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin);
135
+}
136
+
137
+static void gpio_set_2bits(unsigned int gpio, unsigned int reg,
138
+ unsigned int pin, uint32_t value)
139
+{
140
+ uint32_t offset = 2 * pin;
141
+ uint32_t mask = 0xFFFFFFFF & ~(0x3 << offset);
142
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset);
143
+}
144
+
145
+static unsigned int get_gpio_id(uint32_t gpio_addr)
146
+{
147
+ return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE;
148
+}
149
+
150
+static void gpio_set_irq(unsigned int gpio, int num, int level)
151
+{
152
+ g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c",
153
+ get_gpio_id(gpio) + 'a');
154
+ qtest_set_irq_in(global_qtest, name, NULL, num, level);
155
+}
156
+
157
+static void disconnect_all_pins(unsigned int gpio)
158
+{
159
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
160
+ get_gpio_id(gpio) + 'a');
161
+ QDict *r;
162
+
163
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': "
164
+ "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }",
165
+ path, 0xFFFF);
166
+ g_assert_false(qdict_haskey(r, "error"));
167
+ qobject_unref(r);
168
+}
169
+
170
+static uint32_t get_disconnected_pins(unsigned int gpio)
171
+{
172
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
173
+ get_gpio_id(gpio) + 'a');
174
+ uint32_t disconnected_pins = 0;
175
+ QDict *r;
176
+
177
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':"
178
+ " { 'path': %s, 'property': 'disconnected-pins'} }", path);
179
+ g_assert_false(qdict_haskey(r, "error"));
180
+ disconnected_pins = qdict_get_int(r, "return");
181
+ qobject_unref(r);
182
+ return disconnected_pins;
183
+}
184
+
185
+static uint32_t reset(uint32_t gpio, unsigned int offset)
186
+{
187
+ switch (offset) {
188
+ case MODER:
189
+ return moder_reset[get_gpio_id(gpio)];
190
+ case PUPDR:
191
+ return pupdr_reset[get_gpio_id(gpio)];
192
+ case IDR:
193
+ return idr_reset[get_gpio_id(gpio)];
194
+ }
195
+ return 0x0;
196
+}
197
+
198
+static void system_reset(void)
199
+{
200
+ QDict *r;
201
+ r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
202
+ g_assert_false(qdict_haskey(r, "error"));
203
+ qobject_unref(r);
204
+}
205
+
206
+static void test_idr_reset_value(void)
207
+{
208
+ /*
209
+ * Checks that the values in MODER, OTYPER, PUPDR and ODR
210
+ * after reset are correct, and that the value in IDR is
211
+ * coherent.
212
+ * Since AF and analog modes aren't implemented, IDR reset
213
+ * values aren't the same as with a real board.
214
+ *
215
+ * Register IDR contains the actual values of all GPIO pins.
216
+ * Its value depends on the pins' configuration
217
+ * (intput/output/analog : register MODER, push-pull/open-drain :
218
+ * register OTYPER, pull-up/pull-down/none : register PUPDR)
219
+ * and on the values stored in register ODR
220
+ * (in case the pin is in output mode).
221
+ */
222
+
223
+ gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
224
+ gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
225
+ gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
226
+ gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
227
+
228
+ gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
229
+ gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
230
+ gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
231
+ gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
232
+
233
+ gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
234
+ gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
235
+ gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
236
+ gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
237
+
238
+ gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
239
+ gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
240
+ gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
241
+ gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
242
+
243
+ system_reset();
244
+
245
+ uint32_t moder = gpio_readl(GPIO_A, MODER);
246
+ uint32_t odr = gpio_readl(GPIO_A, ODR);
247
+ uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
248
+ uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
249
+ uint32_t idr = gpio_readl(GPIO_A, IDR);
250
+ /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
251
+ /* here AF is the same as Analog and Input mode */
252
+ g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
253
+ g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
254
+ g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
255
+ /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
256
+ g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
257
+ /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
258
+ g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
259
+
260
+ moder = gpio_readl(GPIO_B, MODER);
261
+ odr = gpio_readl(GPIO_B, ODR);
262
+ otyper = gpio_readl(GPIO_B, OTYPER);
263
+ pupdr = gpio_readl(GPIO_B, PUPDR);
264
+ idr = gpio_readl(GPIO_B, IDR);
265
+ /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
266
+ /* here AF is the same as Analog and Input mode */
267
+ g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
268
+ g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
269
+ g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
270
+ /* ... 5: neither, 4: pull-up, 3: neither ... */
271
+ g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
272
+ /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
273
+ g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
274
+
275
+ moder = gpio_readl(GPIO_C, MODER);
276
+ odr = gpio_readl(GPIO_C, ODR);
277
+ otyper = gpio_readl(GPIO_C, OTYPER);
278
+ pupdr = gpio_readl(GPIO_C, PUPDR);
279
+ idr = gpio_readl(GPIO_C, IDR);
280
+ /* Analog, same as Input mode*/
281
+ g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
282
+ g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
283
+ g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
284
+ /* no pull-up or pull-down */
285
+ g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
286
+ /* reset value */
287
+ g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
288
+
289
+ moder = gpio_readl(GPIO_H, MODER);
290
+ odr = gpio_readl(GPIO_H, ODR);
291
+ otyper = gpio_readl(GPIO_H, OTYPER);
292
+ pupdr = gpio_readl(GPIO_H, PUPDR);
293
+ idr = gpio_readl(GPIO_H, IDR);
294
+ /* Analog, same as Input mode */
295
+ g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
296
+ g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
297
+ g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
298
+ /* no pull-up or pull-down */
299
+ g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
300
+ /* reset value */
301
+ g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
302
+}
303
+
304
+static void test_gpio_output_mode(const void *data)
305
+{
306
+ /*
307
+ * Checks that setting a bit in ODR sets the corresponding
308
+ * GPIO line high : it should set the right bit in IDR
309
+ * and send an irq to syscfg.
310
+ * Additionally, it checks that values written to ODR
311
+ * when not in output mode are stored and not discarded.
312
+ */
313
+ unsigned int pin = ((uint64_t)data) & 0xF;
314
+ uint32_t gpio = ((uint64_t)data) >> 32;
315
+ unsigned int gpio_id = get_gpio_id(gpio);
316
+
317
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
318
+
319
+ /* Set a bit in ODR and check nothing happens */
320
+ gpio_set_bit(gpio, ODR, pin, 1);
321
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
322
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
323
+
324
+ /* Configure the relevant line as output and check the pin is high */
325
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
326
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
327
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
328
+
329
+ /* Reset the bit in ODR and check the pin is low */
330
+ gpio_set_bit(gpio, ODR, pin, 0);
331
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
332
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
333
+
334
+ /* Clean the test */
335
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
336
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
337
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
338
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
339
+}
340
+
341
+static void test_gpio_input_mode(const void *data)
342
+{
343
+ /*
344
+ * Test that setting a line high/low externally sets the
345
+ * corresponding GPIO line high/low : it should set the
346
+ * right bit in IDR and send an irq to syscfg.
347
+ */
348
+ unsigned int pin = ((uint64_t)data) & 0xF;
349
+ uint32_t gpio = ((uint64_t)data) >> 32;
350
+ unsigned int gpio_id = get_gpio_id(gpio);
351
+
352
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
353
+
354
+ /* Configure a line as input, raise it, and check that the pin is high */
355
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
356
+ gpio_set_irq(gpio, pin, 1);
357
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
358
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
359
+
360
+ /* Lower the line and check that the pin is low */
361
+ gpio_set_irq(gpio, pin, 0);
362
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
363
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
364
+
365
+ /* Clean the test */
366
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
367
+ disconnect_all_pins(gpio);
368
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
369
+}
370
+
371
+static void test_pull_up_pull_down(const void *data)
372
+{
373
+ /*
374
+ * Test that a floating pin with pull-up sets the pin
375
+ * high and vice-versa.
376
+ */
377
+ unsigned int pin = ((uint64_t)data) & 0xF;
378
+ uint32_t gpio = ((uint64_t)data) >> 32;
379
+ unsigned int gpio_id = get_gpio_id(gpio);
380
+
381
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
382
+
383
+ /* Configure a line as input with pull-up, check the line is set high */
384
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
385
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
386
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
387
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
388
+
389
+ /* Configure the line with pull-down, check the line is low */
390
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
391
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
392
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
393
+
394
+ /* Clean the test */
395
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
396
+ gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
397
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
398
+}
399
+
400
+static void test_push_pull(const void *data)
401
+{
402
+ /*
403
+ * Test that configuring a line in push-pull output mode
404
+ * disconnects the pin, that the pin can't be set or reset
405
+ * externally afterwards.
406
+ */
407
+ unsigned int pin = ((uint64_t)data) & 0xF;
408
+ uint32_t gpio = ((uint64_t)data) >> 32;
409
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
410
+
411
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
412
+
413
+ /* Setting a line high externally, configuring it in push-pull output */
414
+ /* And checking the pin was disconnected */
415
+ gpio_set_irq(gpio, pin, 1);
416
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
417
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
418
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
419
+
420
+ /* Setting a line low externally, configuring it in push-pull output */
421
+ /* And checking the pin was disconnected */
422
+ gpio_set_irq(gpio2, pin, 0);
423
+ gpio_set_bit(gpio2, ODR, pin, 1);
424
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
425
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
426
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
427
+
428
+ /* Trying to set a push-pull output pin, checking it doesn't work */
429
+ gpio_set_irq(gpio, pin, 1);
430
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
431
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
432
+
433
+ /* Trying to reset a push-pull output pin, checking it doesn't work */
434
+ gpio_set_irq(gpio2, pin, 0);
435
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
436
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
437
+
438
+ /* Clean the test */
439
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
440
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
441
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
442
+}
443
+
444
+static void test_open_drain(const void *data)
445
+{
446
+ /*
447
+ * Test that configuring a line in open-drain output mode
448
+ * disconnects a pin set high externally and that the pin
449
+ * can't be set high externally while configured in open-drain.
450
+ *
451
+ * However a pin set low externally shouldn't be disconnected,
452
+ * and it can be set low externally when in open-drain mode.
453
+ */
454
+ unsigned int pin = ((uint64_t)data) & 0xF;
455
+ uint32_t gpio = ((uint64_t)data) >> 32;
456
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
457
+
458
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
459
+
460
+ /* Setting a line high externally, configuring it in open-drain output */
461
+ /* And checking the pin was disconnected */
462
+ gpio_set_irq(gpio, pin, 1);
463
+ gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN);
464
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
465
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
466
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
467
+
468
+ /* Setting a line low externally, configuring it in open-drain output */
469
+ /* And checking the pin wasn't disconnected */
470
+ gpio_set_irq(gpio2, pin, 0);
471
+ gpio_set_bit(gpio2, ODR, pin, 1);
472
+ gpio_set_bit(gpio2, OTYPER, pin, OTYPER_OPEN_DRAIN);
473
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
474
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
475
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
476
+ reset(gpio2, IDR) & ~(1 << pin));
477
+
478
+ /* Trying to set a open-drain output pin, checking it doesn't work */
479
+ gpio_set_irq(gpio, pin, 1);
480
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
481
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
482
+
483
+ /* Trying to reset a open-drain output pin, checking it works */
484
+ gpio_set_bit(gpio, ODR, pin, 1);
485
+ gpio_set_irq(gpio, pin, 0);
486
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
487
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
488
+ reset(gpio2, IDR) & ~(1 << pin));
489
+
490
+ /* Clean the test */
491
+ disconnect_all_pins(gpio2);
492
+ gpio_writel(gpio2, OTYPER, reset(gpio2, OTYPER));
493
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
494
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
495
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR));
496
+ disconnect_all_pins(gpio);
497
+ gpio_writel(gpio, OTYPER, reset(gpio, OTYPER));
498
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
499
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
500
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
501
+}
502
+
503
+static void test_bsrr_brr(const void *data)
504
+{
505
+ /*
506
+ * Test that writing a '1' in BSS and BSRR
507
+ * has the desired effect on ODR.
508
+ * In BSRR, BSx has priority over BRx.
509
+ */
510
+ unsigned int pin = ((uint64_t)data) & 0xF;
511
+ uint32_t gpio = ((uint64_t)data) >> 32;
512
+
513
+ gpio_writel(gpio, BSRR, (1 << pin));
514
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
515
+
516
+ gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS)));
517
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
518
+
519
+ gpio_writel(gpio, BSRR, (1 << pin));
520
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
521
+
522
+ gpio_writel(gpio, BRR, (1 << pin));
523
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
524
+
525
+ /* BSx should have priority over BRx */
526
+ gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS)));
527
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
528
+
529
+ gpio_writel(gpio, BRR, (1 << pin));
530
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
531
+
532
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
533
+}
534
+
535
+int main(int argc, char **argv)
536
+{
537
+ int ret;
538
+
539
+ g_test_init(&argc, &argv, NULL);
540
+ g_test_set_nonfatal_assertions();
541
+ qtest_add_func("stm32l4x5/gpio/test_idr_reset_value",
542
+ test_idr_reset_value);
543
+ /*
544
+ * The inputs for the tests (gpio and pin) can be changed,
545
+ * but the tests don't work for pins that are high at reset
546
+ * (GPIOA15, GPIO13 and GPIOB5).
547
+ * Specifically, rising the pin then checking `get_irq()`
548
+ * is problematic since the pin was already high.
549
+ */
550
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode",
551
+ (void *)((uint64_t)GPIO_C << 32 | 5),
552
+ test_gpio_output_mode);
553
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode",
554
+ (void *)((uint64_t)GPIO_H << 32 | 3),
555
+ test_gpio_output_mode);
556
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1",
557
+ (void *)((uint64_t)GPIO_D << 32 | 6),
558
+ test_gpio_input_mode);
559
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2",
560
+ (void *)((uint64_t)GPIO_C << 32 | 10),
561
+ test_gpio_input_mode);
562
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1",
563
+ (void *)((uint64_t)GPIO_B << 32 | 5),
564
+ test_pull_up_pull_down);
565
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down2",
566
+ (void *)((uint64_t)GPIO_F << 32 | 1),
567
+ test_pull_up_pull_down);
568
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull1",
569
+ (void *)((uint64_t)GPIO_G << 32 | 6),
570
+ test_push_pull);
571
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull2",
572
+ (void *)((uint64_t)GPIO_H << 32 | 3),
573
+ test_push_pull);
574
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain1",
575
+ (void *)((uint64_t)GPIO_C << 32 | 4),
576
+ test_open_drain);
577
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain2",
578
+ (void *)((uint64_t)GPIO_E << 32 | 11),
579
+ test_open_drain);
580
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr1",
581
+ (void *)((uint64_t)GPIO_A << 32 | 12),
582
+ test_bsrr_brr);
583
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
584
+ (void *)((uint64_t)GPIO_D << 32 | 0),
585
+ test_bsrr_brr);
586
+
587
+ qtest_start("-machine b-l475e-iot01a");
588
+ ret = g_test_run();
589
+ qtest_end();
590
+
591
+ return ret;
592
+}
593
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
14
index XXXXXXX..XXXXXXX 100644
594
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.c
595
--- a/tests/qtest/meson.build
16
+++ b/target/arm/cpu.c
596
+++ b/tests/qtest/meson.build
17
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
18
CPACR_EL1, ZEN, 3);
598
qtests_stm32l4x5 = \
19
env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
599
['stm32l4x5_exti-test',
20
}
600
'stm32l4x5_syscfg-test',
21
+ /* and for SME instructions, with default vector length, and TPIDR2 */
601
- 'stm32l4x5_rcc-test']
22
+ if (cpu_isar_feature(aa64_sme, cpu)) {
602
+ 'stm32l4x5_rcc-test',
23
+ env->cp15.sctlr_el[1] |= SCTLR_EnTP2;
603
+ 'stm32l4x5_gpio-test']
24
+ env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
604
25
+ CPACR_EL1, SMEN, 3);
605
qtests_arm = \
26
+ env->vfp.smcr_el[1] = cpu->sme_default_vq - 1;
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
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
--
607
--
36
2.25.1
608
2.34.1
609
610
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Set the SM bit in the SVE record on signal delivery, create the ZA record.
3
While the 8-bit input elements are sequential in the input vector,
4
Restore SM and ZA state according to the records present on return.
4
the 32-bit output elements are not sequential in the output matrix.
5
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
7
Cc: qemu-stable@nongnu.org
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-41-richard.henderson@linaro.org
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
14
---
11
linux-user/aarch64/signal.c | 167 +++++++++++++++++++++++++++++++++---
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
12
1 file changed, 154 insertions(+), 13 deletions(-)
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
13
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
14
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
18
tests/tcg/aarch64/Makefile.target | 2 +-
19
4 files changed, 147 insertions(+), 33 deletions(-)
20
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
21
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
22
23
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
15
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/aarch64/signal.c
25
--- a/target/arm/tcg/sme_helper.c
17
+++ b/linux-user/aarch64/signal.c
26
+++ b/target/arm/tcg/sme_helper.c
18
@@ -XXX,XX +XXX,XX @@ struct target_sve_context {
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
19
20
#define TARGET_SVE_SIG_FLAG_SM 1
21
22
+#define TARGET_ZA_MAGIC 0x54366345
23
+
24
+struct target_za_context {
25
+ struct target_aarch64_ctx head;
26
+ uint16_t vl;
27
+ uint16_t reserved[3];
28
+ /* The actual ZA data immediately follows. */
29
+};
30
+
31
+#define TARGET_ZA_SIG_REGS_OFFSET \
32
+ QEMU_ALIGN_UP(sizeof(struct target_za_context), TARGET_SVE_VQ_BYTES)
33
+#define TARGET_ZA_SIG_ZAV_OFFSET(VQ, N) \
34
+ (TARGET_ZA_SIG_REGS_OFFSET + (VQ) * TARGET_SVE_VQ_BYTES * (N))
35
+#define TARGET_ZA_SIG_CONTEXT_SIZE(VQ) \
36
+ TARGET_ZA_SIG_ZAV_OFFSET(VQ, VQ * TARGET_SVE_VQ_BYTES)
37
+
38
struct target_rt_sigframe {
39
struct target_siginfo info;
40
struct target_ucontext uc;
41
@@ -XXX,XX +XXX,XX @@ static void target_setup_end_record(struct target_aarch64_ctx *end)
42
}
43
44
static void target_setup_sve_record(struct target_sve_context *sve,
45
- CPUARMState *env, int vq, int size)
46
+ CPUARMState *env, int size)
47
{
48
- int i, j;
49
+ int i, j, vq = sve_vq(env);
50
51
memset(sve, 0, sizeof(*sve));
52
__put_user(TARGET_SVE_MAGIC, &sve->head.magic);
53
@@ -XXX,XX +XXX,XX @@ static void target_setup_sve_record(struct target_sve_context *sve,
54
}
28
}
55
}
29
}
56
30
57
+static void target_setup_za_record(struct target_za_context *za,
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
58
+ CPUARMState *env, int size)
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
34
+ uint8_t *pn, uint8_t *pm,
35
+ uint32_t desc, IMOPFn32 *fn)
59
+{
36
+{
60
+ int vq = sme_vq(env);
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
61
+ int vl = vq * TARGET_SVE_VQ_BYTES;
38
+ bool neg = simd_data(desc);
62
+ int i, j;
39
63
+
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
64
+ memset(za, 0, sizeof(*za));
41
- uint8_t *pn, uint8_t *pm,
65
+ __put_user(TARGET_ZA_MAGIC, &za->head.magic);
42
- uint32_t desc, IMOPFn *fn)
66
+ __put_user(size, &za->head.size);
43
+ for (row = 0; row < oprsz; ++row) {
67
+ __put_user(vl, &za->vl);
44
+ uint8_t pa = (pn[H1(row >> 1)] >> ((row & 1) * 4)) & 0xf;
68
+
45
+ uint32_t *za_row = &za[tile_vslice_index(row)];
69
+ if (size == TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
46
+ uint32_t n = zn[H4(row)];
70
+ return;
47
+
71
+ }
48
+ for (col = 0; col < oprsz; ++col) {
72
+ assert(size == TARGET_ZA_SIG_CONTEXT_SIZE(vq));
49
+ uint8_t pb = pm[H1(col >> 1)] >> ((col & 1) * 4);
73
+
50
+ uint32_t *a = &za_row[H4(col)];
74
+ /*
51
+
75
+ * Note that ZA vectors are stored as a byte stream,
52
+ *a = fn(n, zm[H4(col)], *a, pa & pb, neg);
76
+ * with each byte element at a subsequent address.
77
+ */
78
+ for (i = 0; i < vl; ++i) {
79
+ uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
80
+ for (j = 0; j < vq * 2; ++j) {
81
+ __put_user_e(env->zarray[i].d[j], z + j, le);
82
+ }
53
+ }
83
+ }
54
+ }
84
+}
55
+}
85
+
56
+
86
static void target_restore_general_frame(CPUARMState *env,
57
+typedef uint64_t IMOPFn64(uint64_t, uint64_t, uint64_t, uint8_t, bool);
87
struct target_rt_sigframe *sf)
58
+static inline void do_imopa_d(uint64_t *za, uint64_t *zn, uint64_t *zm,
59
+ uint8_t *pn, uint8_t *pm,
60
+ uint32_t desc, IMOPFn64 *fn)
88
{
61
{
89
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
90
63
bool neg = simd_data(desc);
91
static bool target_restore_sve_record(CPUARMState *env,
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
92
struct target_sve_context *sve,
93
- int size)
94
+ int size, int *svcr)
95
{
96
- int i, j, vl, vq;
97
+ int i, j, vl, vq, flags;
98
+ bool sm;
99
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
}
65
}
135
66
136
+static bool target_restore_za_record(CPUARMState *env,
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
137
+ struct target_za_context *za,
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
138
+ int size, int *svcr)
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
70
{ \
71
- uint32_t sum0 = 0, sum1 = 0; \
72
+ uint32_t sum = 0; \
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
74
n &= expand_pred_b(p); \
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
83
- if (neg) { \
84
- sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
85
- } else { \
86
- sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
87
- } \
88
- return ((uint64_t)sum1 << 32) | sum0; \
89
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
90
+ sum += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
91
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
92
+ sum += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
93
+ return neg ? a - sum : a + sum; \
94
}
95
96
#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
97
@@ -XXX,XX +XXX,XX @@ DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
98
DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
99
DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
100
101
-#define DEF_IMOPH(NAME) \
102
- void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
103
- void *vpm, uint32_t desc) \
104
- { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
105
+#define DEF_IMOPH(NAME, S) \
106
+ void HELPER(sme_##NAME##_##S)(void *vza, void *vzn, void *vzm, \
107
+ void *vpn, void *vpm, uint32_t desc) \
108
+ { do_imopa_##S(vza, vzn, vzm, vpn, vpm, desc, NAME##_##S); }
109
110
-DEF_IMOPH(smopa_s)
111
-DEF_IMOPH(umopa_s)
112
-DEF_IMOPH(sumopa_s)
113
-DEF_IMOPH(usmopa_s)
114
-DEF_IMOPH(smopa_d)
115
-DEF_IMOPH(umopa_d)
116
-DEF_IMOPH(sumopa_d)
117
-DEF_IMOPH(usmopa_d)
118
+DEF_IMOPH(smopa, s)
119
+DEF_IMOPH(umopa, s)
120
+DEF_IMOPH(sumopa, s)
121
+DEF_IMOPH(usmopa, s)
122
+
123
+DEF_IMOPH(smopa, d)
124
+DEF_IMOPH(umopa, d)
125
+DEF_IMOPH(sumopa, d)
126
+DEF_IMOPH(usmopa, d)
127
diff --git a/tests/tcg/aarch64/sme-smopa-1.c b/tests/tcg/aarch64/sme-smopa-1.c
128
new file mode 100644
129
index XXXXXXX..XXXXXXX
130
--- /dev/null
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
132
@@ -XXX,XX +XXX,XX @@
133
+#include <stdio.h>
134
+#include <string.h>
135
+
136
+int main()
139
+{
137
+{
140
+ int i, j, vl, vq;
138
+ static const int cmp[4][4] = {
141
+
139
+ { 110, 134, 158, 182 },
142
+ if (!cpu_isar_feature(aa64_sme, env_archcpu(env))) {
140
+ { 390, 478, 566, 654 },
143
+ return false;
141
+ { 670, 822, 974, 1126 },
144
+ }
142
+ { 950, 1166, 1382, 1598 }
145
+
143
+ };
146
+ __get_user(vl, &za->vl);
144
+ int dst[4][4];
147
+ vq = sme_vq(env);
145
+ int *tmp = &dst[0][0];
148
+
146
+
149
+ /* Reject mismatched VL. */
147
+ asm volatile(
150
+ if (vl != vq * TARGET_SVE_VQ_BYTES) {
148
+ ".arch armv8-r+sme\n\t"
151
+ return false;
149
+ "smstart\n\t"
152
+ }
150
+ "index z0.b, #0, #1\n\t"
153
+
151
+ "movprfx z1, z0\n\t"
154
+ /* Accept empty record -- used to clear PSTATE.ZA. */
152
+ "add z1.b, z1.b, #16\n\t"
155
+ if (size <= TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
153
+ "ptrue p0.b\n\t"
156
+ return true;
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
157
+ }
155
+ "ptrue p0.s, vl4\n\t"
158
+
156
+ "mov w12, #0\n\t"
159
+ /* Reject non-empty but incomplete record. */
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
160
+ if (size < TARGET_ZA_SIG_CONTEXT_SIZE(vq)) {
158
+ "add %0, %0, #16\n\t"
161
+ return false;
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
162
+ }
160
+ "add %0, %0, #16\n\t"
163
+
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
164
+ *svcr = FIELD_DP64(*svcr, SVCR, ZA, 1);
162
+ "add %0, %0, #16\n\t"
165
+
163
+ "st1w { za0h.s[w12, #3] }, p0, [%0]\n\t"
166
+ for (i = 0; i < vl; ++i) {
164
+ "smstop"
167
+ uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
165
+ : "+r"(tmp) : : "memory");
168
+ for (j = 0; j < vq * 2; ++j) {
166
+
169
+ __get_user_e(env->zarray[i].d[j], z + j, le);
167
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
168
+ return 0;
169
+ }
170
+
171
+ /* See above for correct results. */
172
+ for (int i = 0; i < 4; ++i) {
173
+ for (int j = 0; j < 4; ++j) {
174
+ printf("%6d", dst[i][j]);
170
+ }
175
+ }
171
+ }
176
+ printf("\n");
172
+ return true;
177
+ }
178
+ return 1;
173
+}
179
+}
174
+
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
175
static int target_restore_sigframe(CPUARMState *env,
181
new file mode 100644
176
struct target_rt_sigframe *sf)
182
index XXXXXXX..XXXXXXX
177
{
183
--- /dev/null
178
struct target_aarch64_ctx *ctx, *extra = NULL;
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
179
struct target_fpsimd_context *fpsimd = NULL;
185
@@ -XXX,XX +XXX,XX @@
180
struct target_sve_context *sve = NULL;
186
+#include <stdio.h>
181
+ struct target_za_context *za = NULL;
187
+#include <string.h>
182
uint64_t extra_datap = 0;
188
+
183
bool used_extra = false;
189
+int main()
184
int sve_size = 0;
190
+{
185
+ int za_size = 0;
191
+ static const long cmp[4][4] = {
186
+ int svcr = 0;
192
+ { 110, 134, 158, 182 },
187
193
+ { 390, 478, 566, 654 },
188
target_restore_general_frame(env, sf);
194
+ { 670, 822, 974, 1126 },
189
195
+ { 950, 1166, 1382, 1598 }
190
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
196
+ };
191
sve_size = size;
197
+ long dst[4][4];
192
break;
198
+ long *tmp = &dst[0][0];
193
199
+ long svl;
194
+ case TARGET_ZA_MAGIC:
200
+
195
+ if (za || size < sizeof(struct target_za_context)) {
201
+ /* Validate that we have a wide enough vector for 4 elements. */
196
+ goto err;
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
197
+ }
203
+ if (svl < 32) {
198
+ za = (struct target_za_context *)ctx;
204
+ return 0;
199
+ za_size = size;
205
+ }
200
+ break;
206
+
201
+
207
+ asm volatile(
202
case TARGET_EXTRA_MAGIC:
208
+ "smstart\n\t"
203
if (extra || size != sizeof(struct target_extra_context)) {
209
+ "index z0.h, #0, #1\n\t"
204
goto err;
210
+ "movprfx z1, z0\n\t"
205
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
211
+ "add z1.h, z1.h, #16\n\t"
206
}
212
+ "ptrue p0.b\n\t"
207
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
208
/* SVE data, if present, overwrites FPSIMD data. */
214
+ "ptrue p0.d, vl4\n\t"
209
- if (sve && !target_restore_sve_record(env, sve, sve_size)) {
215
+ "mov w12, #0\n\t"
210
+ if (sve && !target_restore_sve_record(env, sve, sve_size, &svcr)) {
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
211
goto err;
217
+ "add %0, %0, #32\n\t"
212
}
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
213
+ if (za && !target_restore_za_record(env, za, za_size, &svcr)) {
219
+ "mov w12, #2\n\t"
214
+ goto err;
220
+ "add %0, %0, #32\n\t"
215
+ }
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
216
+ if (env->svcr != svcr) {
222
+ "add %0, %0, #32\n\t"
217
+ env->svcr = svcr;
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
218
+ arm_rebuild_hflags(env);
224
+ "smstop"
219
+ }
225
+ : "+r"(tmp) : : "memory");
220
unlock_user(extra, extra_datap, 0);
226
+
221
return 0;
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
222
228
+ return 0;
223
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
229
+ }
224
.total_size = offsetof(struct target_rt_sigframe,
230
+
225
uc.tuc_mcontext.__reserved),
231
+ /* See above for correct results. */
226
};
232
+ for (int i = 0; i < 4; ++i) {
227
- int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
233
+ for (int j = 0; j < 4; ++j) {
228
+ int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0;
234
+ printf("%6ld", dst[i][j]);
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
+ }
235
+ }
252
+ za_ofs = alloc_sigframe_space(za_size, &layout);
236
+ printf("\n");
253
+ }
237
+ }
254
238
+ return 1;
255
if (layout.extra_ofs) {
239
+}
256
/* Reserve space for the extra end marker. The standard end marker
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
257
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
241
index XXXXXXX..XXXXXXX 100644
258
target_setup_end_record((void *)frame + layout.extra_end_ofs);
242
--- a/tests/tcg/aarch64/Makefile.target
259
}
243
+++ b/tests/tcg/aarch64/Makefile.target
260
if (sve_ofs) {
244
@@ -XXX,XX +XXX,XX @@ endif
261
- target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
245
262
+ target_setup_sve_record((void *)frame + sve_ofs, env, sve_size);
246
# SME Tests
263
+ }
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
264
+ if (za_ofs) {
248
-AARCH64_TESTS += sme-outprod1
265
+ target_setup_za_record((void *)frame + za_ofs, env, za_size);
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
266
}
250
endif
267
251
268
/* Set up the stack frame for unwinding. */
252
# System Registers Tests
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
--
253
--
289
2.25.1
254
2.34.1
255
256
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The sun4v RTC device model added under commit a0e893039cf2ce0 in 2016
2
was unfortunately added with a license of GPL-v3-or-later, which is
3
not compatible with other QEMU code which has a GPL-v2-only license.
2
4
3
Mark these as a non-streaming instructions, which should trap
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
4
if full a64 support is not enabled in streaming mode.
6
to make it compatible with the rest of QEMU.
5
7
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220708151540.18136-8-richard.henderson@linaro.org
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
16
Acked-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20240223161300.938542-1-peter.maydell@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
19
---
11
target/arm/sme-fa64.decode | 2 --
20
include/hw/rtc/sun4v-rtc.h | 2 +-
12
target/arm/translate-sve.c | 24 +++++++++++++++---------
21
hw/rtc/sun4v-rtc.c | 2 +-
13
2 files changed, 15 insertions(+), 11 deletions(-)
22
2 files changed, 2 insertions(+), 2 deletions(-)
14
23
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
26
--- a/include/hw/rtc/sun4v-rtc.h
18
+++ b/target/arm/sme-fa64.decode
27
+++ b/include/hw/rtc/sun4v-rtc.h
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
28
@@ -XXX,XX +XXX,XX @@
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
29
*
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
30
* Copyright (c) 2016 Artyom Tarasenko
22
31
*
23
-FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
24
-FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
25
FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
34
* version.
26
FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
35
*/
27
FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
36
28
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
29
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-sve.c
39
--- a/hw/rtc/sun4v-rtc.c
31
+++ b/target/arm/translate-sve.c
40
+++ b/hw/rtc/sun4v-rtc.c
32
@@ -XXX,XX +XXX,XX @@ static bool do_trans_pmull(DisasContext *s, arg_rrr_esz *a, bool sel)
41
@@ -XXX,XX +XXX,XX @@
33
gen_helper_gvec_pmull_q, gen_helper_sve2_pmull_h,
42
*
34
NULL, gen_helper_sve2_pmull_d,
43
* Copyright (c) 2016 Artyom Tarasenko
35
};
44
*
36
- if (a->esz == 0
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
37
- ? !dc_isar_feature(aa64_sve2_pmull128, s)
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
38
- : !dc_isar_feature(aa64_sve, s)) {
47
* version.
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
*/
48
*/
52
49
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
--
50
--
78
2.25.1
51
2.34.1
52
53
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
This includes the build rules for the decoder, and the
3
Move the code to a separate file so that we do not have to compile
4
new file for translation, but excludes any instructions.
4
it anymore if CONFIG_ARM_V7M is not set.
5
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Message-id: 20240308141051.536599-2-thuth@redhat.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>
8
Message-id: 20220708151540.18136-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/translate-a64.h | 1 +
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
12
target/arm/sme.decode | 20 ++++++++++++++++++++
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
13
target/arm/translate-a64.c | 7 ++++++-
13
target/arm/meson.build | 3 +
14
target/arm/translate-sme.c | 35 +++++++++++++++++++++++++++++++++++
14
target/arm/tcg/meson.build | 3 +
15
target/arm/meson.build | 2 ++
15
4 files changed, 296 insertions(+), 261 deletions(-)
16
5 files changed, 64 insertions(+), 1 deletion(-)
16
create mode 100644 target/arm/tcg/cpu-v7m.c
17
create mode 100644 target/arm/sme.decode
18
create mode 100644 target/arm/translate-sme.c
19
17
20
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
18
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/translate-a64.h
23
+++ b/target/arm/translate-a64.h
24
@@ -XXX,XX +XXX,XX @@ static inline int pred_gvec_reg_size(DisasContext *s)
25
}
26
27
bool disas_sve(DisasContext *, uint32_t);
28
+bool disas_sme(DisasContext *, uint32_t);
29
30
void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
31
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
32
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
33
new file mode 100644
19
new file mode 100644
34
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
35
--- /dev/null
21
--- /dev/null
36
+++ b/target/arm/sme.decode
22
+++ b/target/arm/tcg/cpu-v7m.c
37
@@ -XXX,XX +XXX,XX @@
38
+# AArch64 SME instruction descriptions
39
+#
40
+# Copyright (c) 2022 Linaro, Ltd
41
+#
42
+# This library is free software; you can redistribute it and/or
43
+# modify it under the terms of the GNU Lesser General Public
44
+# License as published by the Free Software Foundation; either
45
+# version 2.1 of the License, or (at your option) any later version.
46
+#
47
+# This library is distributed in the hope that it will be useful,
48
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
49
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
50
+# Lesser General Public License for more details.
51
+#
52
+# You should have received a copy of the GNU Lesser General Public
53
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
54
+
55
+#
56
+# This file is processed by scripts/decodetree.py
57
+#
58
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate-a64.c
61
+++ b/target/arm/translate-a64.c
62
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
63
}
64
65
switch (extract32(insn, 25, 4)) {
66
- case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
67
+ case 0x0:
68
+ if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
69
+ unallocated_encoding(s);
70
+ }
71
+ break;
72
+ case 0x1: case 0x3: /* UNALLOCATED */
73
unallocated_encoding(s);
74
break;
75
case 0x2:
76
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
77
new file mode 100644
78
index XXXXXXX..XXXXXXX
79
--- /dev/null
80
+++ b/target/arm/translate-sme.c
81
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
82
+/*
24
+/*
83
+ * AArch64 SME translation
25
+ * QEMU ARMv7-M TCG-only CPUs.
84
+ *
26
+ *
85
+ * Copyright (c) 2022 Linaro, Ltd
27
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
86
+ *
28
+ *
87
+ * This library is free software; you can redistribute it and/or
29
+ * This code is licensed under the GNU GPL v2 or later.
88
+ * modify it under the terms of the GNU Lesser General Public
89
+ * License as published by the Free Software Foundation; either
90
+ * version 2.1 of the License, or (at your option) any later version.
91
+ *
30
+ *
92
+ * This library is distributed in the hope that it will be useful,
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
93
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
94
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95
+ * Lesser General Public License 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
+ */
32
+ */
100
+
33
+
101
+#include "qemu/osdep.h"
34
+#include "qemu/osdep.h"
102
+#include "cpu.h"
35
+#include "cpu.h"
103
+#include "tcg/tcg-op.h"
36
+#include "hw/core/tcg-cpu-ops.h"
104
+#include "tcg/tcg-op-gvec.h"
37
+#include "internals.h"
105
+#include "tcg/tcg-gvec-desc.h"
38
+
106
+#include "translate.h"
39
+#if !defined(CONFIG_USER_ONLY)
107
+#include "exec/helper-gen.h"
40
+
108
+#include "translate-a64.h"
41
+#include "hw/intc/armv7m_nvic.h"
109
+#include "fpu/softfloat.h"
42
+
110
+
43
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
111
+
44
+{
112
+/*
45
+ CPUClass *cc = CPU_GET_CLASS(cs);
113
+ * Include the generated decoder.
46
+ ARMCPU *cpu = ARM_CPU(cs);
114
+ */
47
+ CPUARMState *env = &cpu->env;
115
+
48
+ bool ret = false;
116
+#include "decode-sme.c.inc"
49
+
50
+ /*
51
+ * ARMv7-M interrupt masking works differently than -A or -R.
52
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
53
+ * masking FIQ and IRQ interrupts, an exception is taken only
54
+ * if it is higher priority than the current execution priority
55
+ * (which depends on state like BASEPRI, FAULTMASK and the
56
+ * currently active exception).
57
+ */
58
+ if (interrupt_request & CPU_INTERRUPT_HARD
59
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
60
+ cs->exception_index = EXCP_IRQ;
61
+ cc->tcg_ops->do_interrupt(cs);
62
+ ret = true;
63
+ }
64
+ return ret;
65
+}
66
+
67
+#endif /* !CONFIG_USER_ONLY */
68
+
69
+static void cortex_m0_initfn(Object *obj)
70
+{
71
+ ARMCPU *cpu = ARM_CPU(obj);
72
+ set_feature(&cpu->env, ARM_FEATURE_V6);
73
+ set_feature(&cpu->env, ARM_FEATURE_M);
74
+
75
+ cpu->midr = 0x410cc200;
76
+
77
+ /*
78
+ * These ID register values are not guest visible, because
79
+ * we do not implement the Main Extension. They must be set
80
+ * to values corresponding to the Cortex-M0's implemented
81
+ * features, because QEMU generally controls its emulation
82
+ * by looking at ID register fields. We use the same values as
83
+ * for the M3.
84
+ */
85
+ cpu->isar.id_pfr0 = 0x00000030;
86
+ cpu->isar.id_pfr1 = 0x00000200;
87
+ cpu->isar.id_dfr0 = 0x00100000;
88
+ cpu->id_afr0 = 0x00000000;
89
+ cpu->isar.id_mmfr0 = 0x00000030;
90
+ cpu->isar.id_mmfr1 = 0x00000000;
91
+ cpu->isar.id_mmfr2 = 0x00000000;
92
+ cpu->isar.id_mmfr3 = 0x00000000;
93
+ cpu->isar.id_isar0 = 0x01141110;
94
+ cpu->isar.id_isar1 = 0x02111000;
95
+ cpu->isar.id_isar2 = 0x21112231;
96
+ cpu->isar.id_isar3 = 0x01111110;
97
+ cpu->isar.id_isar4 = 0x01310102;
98
+ cpu->isar.id_isar5 = 0x00000000;
99
+ cpu->isar.id_isar6 = 0x00000000;
100
+}
101
+
102
+static void cortex_m3_initfn(Object *obj)
103
+{
104
+ ARMCPU *cpu = ARM_CPU(obj);
105
+ set_feature(&cpu->env, ARM_FEATURE_V7);
106
+ set_feature(&cpu->env, ARM_FEATURE_M);
107
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
108
+ cpu->midr = 0x410fc231;
109
+ cpu->pmsav7_dregion = 8;
110
+ cpu->isar.id_pfr0 = 0x00000030;
111
+ cpu->isar.id_pfr1 = 0x00000200;
112
+ cpu->isar.id_dfr0 = 0x00100000;
113
+ cpu->id_afr0 = 0x00000000;
114
+ cpu->isar.id_mmfr0 = 0x00000030;
115
+ cpu->isar.id_mmfr1 = 0x00000000;
116
+ cpu->isar.id_mmfr2 = 0x00000000;
117
+ cpu->isar.id_mmfr3 = 0x00000000;
118
+ cpu->isar.id_isar0 = 0x01141110;
119
+ cpu->isar.id_isar1 = 0x02111000;
120
+ cpu->isar.id_isar2 = 0x21112231;
121
+ cpu->isar.id_isar3 = 0x01111110;
122
+ cpu->isar.id_isar4 = 0x01310102;
123
+ cpu->isar.id_isar5 = 0x00000000;
124
+ cpu->isar.id_isar6 = 0x00000000;
125
+}
126
+
127
+static void cortex_m4_initfn(Object *obj)
128
+{
129
+ ARMCPU *cpu = ARM_CPU(obj);
130
+
131
+ set_feature(&cpu->env, ARM_FEATURE_V7);
132
+ set_feature(&cpu->env, ARM_FEATURE_M);
133
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
134
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
135
+ cpu->midr = 0x410fc240; /* r0p0 */
136
+ cpu->pmsav7_dregion = 8;
137
+ cpu->isar.mvfr0 = 0x10110021;
138
+ cpu->isar.mvfr1 = 0x11000011;
139
+ cpu->isar.mvfr2 = 0x00000000;
140
+ cpu->isar.id_pfr0 = 0x00000030;
141
+ cpu->isar.id_pfr1 = 0x00000200;
142
+ cpu->isar.id_dfr0 = 0x00100000;
143
+ cpu->id_afr0 = 0x00000000;
144
+ cpu->isar.id_mmfr0 = 0x00000030;
145
+ cpu->isar.id_mmfr1 = 0x00000000;
146
+ cpu->isar.id_mmfr2 = 0x00000000;
147
+ cpu->isar.id_mmfr3 = 0x00000000;
148
+ cpu->isar.id_isar0 = 0x01141110;
149
+ cpu->isar.id_isar1 = 0x02111000;
150
+ cpu->isar.id_isar2 = 0x21112231;
151
+ cpu->isar.id_isar3 = 0x01111110;
152
+ cpu->isar.id_isar4 = 0x01310102;
153
+ cpu->isar.id_isar5 = 0x00000000;
154
+ cpu->isar.id_isar6 = 0x00000000;
155
+}
156
+
157
+static void cortex_m7_initfn(Object *obj)
158
+{
159
+ ARMCPU *cpu = ARM_CPU(obj);
160
+
161
+ set_feature(&cpu->env, ARM_FEATURE_V7);
162
+ set_feature(&cpu->env, ARM_FEATURE_M);
163
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
164
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
165
+ cpu->midr = 0x411fc272; /* r1p2 */
166
+ cpu->pmsav7_dregion = 8;
167
+ cpu->isar.mvfr0 = 0x10110221;
168
+ cpu->isar.mvfr1 = 0x12000011;
169
+ cpu->isar.mvfr2 = 0x00000040;
170
+ cpu->isar.id_pfr0 = 0x00000030;
171
+ cpu->isar.id_pfr1 = 0x00000200;
172
+ cpu->isar.id_dfr0 = 0x00100000;
173
+ cpu->id_afr0 = 0x00000000;
174
+ cpu->isar.id_mmfr0 = 0x00100030;
175
+ cpu->isar.id_mmfr1 = 0x00000000;
176
+ cpu->isar.id_mmfr2 = 0x01000000;
177
+ cpu->isar.id_mmfr3 = 0x00000000;
178
+ cpu->isar.id_isar0 = 0x01101110;
179
+ cpu->isar.id_isar1 = 0x02112000;
180
+ cpu->isar.id_isar2 = 0x20232231;
181
+ cpu->isar.id_isar3 = 0x01111131;
182
+ cpu->isar.id_isar4 = 0x01310132;
183
+ cpu->isar.id_isar5 = 0x00000000;
184
+ cpu->isar.id_isar6 = 0x00000000;
185
+}
186
+
187
+static void cortex_m33_initfn(Object *obj)
188
+{
189
+ ARMCPU *cpu = ARM_CPU(obj);
190
+
191
+ set_feature(&cpu->env, ARM_FEATURE_V8);
192
+ set_feature(&cpu->env, ARM_FEATURE_M);
193
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
194
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
195
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
196
+ cpu->midr = 0x410fd213; /* r0p3 */
197
+ cpu->pmsav7_dregion = 16;
198
+ cpu->sau_sregion = 8;
199
+ cpu->isar.mvfr0 = 0x10110021;
200
+ cpu->isar.mvfr1 = 0x11000011;
201
+ cpu->isar.mvfr2 = 0x00000040;
202
+ cpu->isar.id_pfr0 = 0x00000030;
203
+ cpu->isar.id_pfr1 = 0x00000210;
204
+ cpu->isar.id_dfr0 = 0x00200000;
205
+ cpu->id_afr0 = 0x00000000;
206
+ cpu->isar.id_mmfr0 = 0x00101F40;
207
+ cpu->isar.id_mmfr1 = 0x00000000;
208
+ cpu->isar.id_mmfr2 = 0x01000000;
209
+ cpu->isar.id_mmfr3 = 0x00000000;
210
+ cpu->isar.id_isar0 = 0x01101110;
211
+ cpu->isar.id_isar1 = 0x02212000;
212
+ cpu->isar.id_isar2 = 0x20232232;
213
+ cpu->isar.id_isar3 = 0x01111131;
214
+ cpu->isar.id_isar4 = 0x01310132;
215
+ cpu->isar.id_isar5 = 0x00000000;
216
+ cpu->isar.id_isar6 = 0x00000000;
217
+ cpu->clidr = 0x00000000;
218
+ cpu->ctr = 0x8000c000;
219
+}
220
+
221
+static void cortex_m55_initfn(Object *obj)
222
+{
223
+ ARMCPU *cpu = ARM_CPU(obj);
224
+
225
+ set_feature(&cpu->env, ARM_FEATURE_V8);
226
+ set_feature(&cpu->env, ARM_FEATURE_V8_1M);
227
+ set_feature(&cpu->env, ARM_FEATURE_M);
228
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
229
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
230
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
231
+ cpu->midr = 0x410fd221; /* r0p1 */
232
+ cpu->revidr = 0;
233
+ cpu->pmsav7_dregion = 16;
234
+ cpu->sau_sregion = 8;
235
+ /* These are the MVFR* values for the FPU + full MVE configuration */
236
+ cpu->isar.mvfr0 = 0x10110221;
237
+ cpu->isar.mvfr1 = 0x12100211;
238
+ cpu->isar.mvfr2 = 0x00000040;
239
+ cpu->isar.id_pfr0 = 0x20000030;
240
+ cpu->isar.id_pfr1 = 0x00000230;
241
+ cpu->isar.id_dfr0 = 0x10200000;
242
+ cpu->id_afr0 = 0x00000000;
243
+ cpu->isar.id_mmfr0 = 0x00111040;
244
+ cpu->isar.id_mmfr1 = 0x00000000;
245
+ cpu->isar.id_mmfr2 = 0x01000000;
246
+ cpu->isar.id_mmfr3 = 0x00000011;
247
+ cpu->isar.id_isar0 = 0x01103110;
248
+ cpu->isar.id_isar1 = 0x02212000;
249
+ cpu->isar.id_isar2 = 0x20232232;
250
+ cpu->isar.id_isar3 = 0x01111131;
251
+ cpu->isar.id_isar4 = 0x01310132;
252
+ cpu->isar.id_isar5 = 0x00000000;
253
+ cpu->isar.id_isar6 = 0x00000000;
254
+ cpu->clidr = 0x00000000; /* caches not implemented */
255
+ cpu->ctr = 0x8303c003;
256
+}
257
+
258
+static const TCGCPUOps arm_v7m_tcg_ops = {
259
+ .initialize = arm_translate_init,
260
+ .synchronize_from_tb = arm_cpu_synchronize_from_tb,
261
+ .debug_excp_handler = arm_debug_excp_handler,
262
+ .restore_state_to_opc = arm_restore_state_to_opc,
263
+
264
+#ifdef CONFIG_USER_ONLY
265
+ .record_sigsegv = arm_cpu_record_sigsegv,
266
+ .record_sigbus = arm_cpu_record_sigbus,
267
+#else
268
+ .tlb_fill = arm_cpu_tlb_fill,
269
+ .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
270
+ .do_interrupt = arm_v7m_cpu_do_interrupt,
271
+ .do_transaction_failed = arm_cpu_do_transaction_failed,
272
+ .do_unaligned_access = arm_cpu_do_unaligned_access,
273
+ .adjust_watchpoint_address = arm_adjust_watchpoint_address,
274
+ .debug_check_watchpoint = arm_debug_check_watchpoint,
275
+ .debug_check_breakpoint = arm_debug_check_breakpoint,
276
+#endif /* !CONFIG_USER_ONLY */
277
+};
278
+
279
+static void arm_v7m_class_init(ObjectClass *oc, void *data)
280
+{
281
+ ARMCPUClass *acc = ARM_CPU_CLASS(oc);
282
+ CPUClass *cc = CPU_CLASS(oc);
283
+
284
+ acc->info = data;
285
+ cc->tcg_ops = &arm_v7m_tcg_ops;
286
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
287
+}
288
+
289
+static const ARMCPUInfo arm_v7m_cpus[] = {
290
+ { .name = "cortex-m0", .initfn = cortex_m0_initfn,
291
+ .class_init = arm_v7m_class_init },
292
+ { .name = "cortex-m3", .initfn = cortex_m3_initfn,
293
+ .class_init = arm_v7m_class_init },
294
+ { .name = "cortex-m4", .initfn = cortex_m4_initfn,
295
+ .class_init = arm_v7m_class_init },
296
+ { .name = "cortex-m7", .initfn = cortex_m7_initfn,
297
+ .class_init = arm_v7m_class_init },
298
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
299
+ .class_init = arm_v7m_class_init },
300
+ { .name = "cortex-m55", .initfn = cortex_m55_initfn,
301
+ .class_init = arm_v7m_class_init },
302
+};
303
+
304
+static void arm_v7m_cpu_register_types(void)
305
+{
306
+ size_t i;
307
+
308
+ for (i = 0; i < ARRAY_SIZE(arm_v7m_cpus); ++i) {
309
+ arm_cpu_register(&arm_v7m_cpus[i]);
310
+ }
311
+}
312
+
313
+type_init(arm_v7m_cpu_register_types)
314
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
315
index XXXXXXX..XXXXXXX 100644
316
--- a/target/arm/tcg/cpu32.c
317
+++ b/target/arm/tcg/cpu32.c
318
@@ -XXX,XX +XXX,XX @@
319
#include "hw/boards.h"
320
#endif
321
#include "cpregs.h"
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
323
-#include "hw/intc/armv7m_nvic.h"
324
-#endif
325
326
327
/* Share AArch32 -cpu max features with AArch64. */
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
331
332
-#if !defined(CONFIG_USER_ONLY)
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
334
-{
335
- CPUClass *cc = CPU_GET_CLASS(cs);
336
- ARMCPU *cpu = ARM_CPU(cs);
337
- CPUARMState *env = &cpu->env;
338
- bool ret = false;
339
-
340
- /*
341
- * ARMv7-M interrupt masking works differently than -A or -R.
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
343
- * masking FIQ and IRQ interrupts, an exception is taken only
344
- * if it is higher priority than the current execution priority
345
- * (which depends on state like BASEPRI, FAULTMASK and the
346
- * currently active exception).
347
- */
348
- if (interrupt_request & CPU_INTERRUPT_HARD
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
350
- cs->exception_index = EXCP_IRQ;
351
- cc->tcg_ops->do_interrupt(cs);
352
- ret = true;
353
- }
354
- return ret;
355
-}
356
-#endif /* !CONFIG_USER_ONLY */
357
-
358
static void arm926_initfn(Object *obj)
359
{
360
ARMCPU *cpu = ARM_CPU(obj);
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
363
}
364
365
-static void cortex_m0_initfn(Object *obj)
366
-{
367
- ARMCPU *cpu = ARM_CPU(obj);
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
369
- set_feature(&cpu->env, ARM_FEATURE_M);
370
-
371
- cpu->midr = 0x410cc200;
372
-
373
- /*
374
- * These ID register values are not guest visible, because
375
- * we do not implement the Main Extension. They must be set
376
- * to values corresponding to the Cortex-M0's implemented
377
- * features, because QEMU generally controls its emulation
378
- * by looking at ID register fields. We use the same values as
379
- * for the M3.
380
- */
381
- cpu->isar.id_pfr0 = 0x00000030;
382
- cpu->isar.id_pfr1 = 0x00000200;
383
- cpu->isar.id_dfr0 = 0x00100000;
384
- cpu->id_afr0 = 0x00000000;
385
- cpu->isar.id_mmfr0 = 0x00000030;
386
- cpu->isar.id_mmfr1 = 0x00000000;
387
- cpu->isar.id_mmfr2 = 0x00000000;
388
- cpu->isar.id_mmfr3 = 0x00000000;
389
- cpu->isar.id_isar0 = 0x01141110;
390
- cpu->isar.id_isar1 = 0x02111000;
391
- cpu->isar.id_isar2 = 0x21112231;
392
- cpu->isar.id_isar3 = 0x01111110;
393
- cpu->isar.id_isar4 = 0x01310102;
394
- cpu->isar.id_isar5 = 0x00000000;
395
- cpu->isar.id_isar6 = 0x00000000;
396
-}
397
-
398
-static void cortex_m3_initfn(Object *obj)
399
-{
400
- ARMCPU *cpu = ARM_CPU(obj);
401
- set_feature(&cpu->env, ARM_FEATURE_V7);
402
- set_feature(&cpu->env, ARM_FEATURE_M);
403
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
404
- cpu->midr = 0x410fc231;
405
- cpu->pmsav7_dregion = 8;
406
- cpu->isar.id_pfr0 = 0x00000030;
407
- cpu->isar.id_pfr1 = 0x00000200;
408
- cpu->isar.id_dfr0 = 0x00100000;
409
- cpu->id_afr0 = 0x00000000;
410
- cpu->isar.id_mmfr0 = 0x00000030;
411
- cpu->isar.id_mmfr1 = 0x00000000;
412
- cpu->isar.id_mmfr2 = 0x00000000;
413
- cpu->isar.id_mmfr3 = 0x00000000;
414
- cpu->isar.id_isar0 = 0x01141110;
415
- cpu->isar.id_isar1 = 0x02111000;
416
- cpu->isar.id_isar2 = 0x21112231;
417
- cpu->isar.id_isar3 = 0x01111110;
418
- cpu->isar.id_isar4 = 0x01310102;
419
- cpu->isar.id_isar5 = 0x00000000;
420
- cpu->isar.id_isar6 = 0x00000000;
421
-}
422
-
423
-static void cortex_m4_initfn(Object *obj)
424
-{
425
- ARMCPU *cpu = ARM_CPU(obj);
426
-
427
- set_feature(&cpu->env, ARM_FEATURE_V7);
428
- set_feature(&cpu->env, ARM_FEATURE_M);
429
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
430
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
431
- cpu->midr = 0x410fc240; /* r0p0 */
432
- cpu->pmsav7_dregion = 8;
433
- cpu->isar.mvfr0 = 0x10110021;
434
- cpu->isar.mvfr1 = 0x11000011;
435
- cpu->isar.mvfr2 = 0x00000000;
436
- cpu->isar.id_pfr0 = 0x00000030;
437
- cpu->isar.id_pfr1 = 0x00000200;
438
- cpu->isar.id_dfr0 = 0x00100000;
439
- cpu->id_afr0 = 0x00000000;
440
- cpu->isar.id_mmfr0 = 0x00000030;
441
- cpu->isar.id_mmfr1 = 0x00000000;
442
- cpu->isar.id_mmfr2 = 0x00000000;
443
- cpu->isar.id_mmfr3 = 0x00000000;
444
- cpu->isar.id_isar0 = 0x01141110;
445
- cpu->isar.id_isar1 = 0x02111000;
446
- cpu->isar.id_isar2 = 0x21112231;
447
- cpu->isar.id_isar3 = 0x01111110;
448
- cpu->isar.id_isar4 = 0x01310102;
449
- cpu->isar.id_isar5 = 0x00000000;
450
- cpu->isar.id_isar6 = 0x00000000;
451
-}
452
-
453
-static void cortex_m7_initfn(Object *obj)
454
-{
455
- ARMCPU *cpu = ARM_CPU(obj);
456
-
457
- set_feature(&cpu->env, ARM_FEATURE_V7);
458
- set_feature(&cpu->env, ARM_FEATURE_M);
459
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
460
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
461
- cpu->midr = 0x411fc272; /* r1p2 */
462
- cpu->pmsav7_dregion = 8;
463
- cpu->isar.mvfr0 = 0x10110221;
464
- cpu->isar.mvfr1 = 0x12000011;
465
- cpu->isar.mvfr2 = 0x00000040;
466
- cpu->isar.id_pfr0 = 0x00000030;
467
- cpu->isar.id_pfr1 = 0x00000200;
468
- cpu->isar.id_dfr0 = 0x00100000;
469
- cpu->id_afr0 = 0x00000000;
470
- cpu->isar.id_mmfr0 = 0x00100030;
471
- cpu->isar.id_mmfr1 = 0x00000000;
472
- cpu->isar.id_mmfr2 = 0x01000000;
473
- cpu->isar.id_mmfr3 = 0x00000000;
474
- cpu->isar.id_isar0 = 0x01101110;
475
- cpu->isar.id_isar1 = 0x02112000;
476
- cpu->isar.id_isar2 = 0x20232231;
477
- cpu->isar.id_isar3 = 0x01111131;
478
- cpu->isar.id_isar4 = 0x01310132;
479
- cpu->isar.id_isar5 = 0x00000000;
480
- cpu->isar.id_isar6 = 0x00000000;
481
-}
482
-
483
-static void cortex_m33_initfn(Object *obj)
484
-{
485
- ARMCPU *cpu = ARM_CPU(obj);
486
-
487
- set_feature(&cpu->env, ARM_FEATURE_V8);
488
- set_feature(&cpu->env, ARM_FEATURE_M);
489
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
490
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
491
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
492
- cpu->midr = 0x410fd213; /* r0p3 */
493
- cpu->pmsav7_dregion = 16;
494
- cpu->sau_sregion = 8;
495
- cpu->isar.mvfr0 = 0x10110021;
496
- cpu->isar.mvfr1 = 0x11000011;
497
- cpu->isar.mvfr2 = 0x00000040;
498
- cpu->isar.id_pfr0 = 0x00000030;
499
- cpu->isar.id_pfr1 = 0x00000210;
500
- cpu->isar.id_dfr0 = 0x00200000;
501
- cpu->id_afr0 = 0x00000000;
502
- cpu->isar.id_mmfr0 = 0x00101F40;
503
- cpu->isar.id_mmfr1 = 0x00000000;
504
- cpu->isar.id_mmfr2 = 0x01000000;
505
- cpu->isar.id_mmfr3 = 0x00000000;
506
- cpu->isar.id_isar0 = 0x01101110;
507
- cpu->isar.id_isar1 = 0x02212000;
508
- cpu->isar.id_isar2 = 0x20232232;
509
- cpu->isar.id_isar3 = 0x01111131;
510
- cpu->isar.id_isar4 = 0x01310132;
511
- cpu->isar.id_isar5 = 0x00000000;
512
- cpu->isar.id_isar6 = 0x00000000;
513
- cpu->clidr = 0x00000000;
514
- cpu->ctr = 0x8000c000;
515
-}
516
-
517
-static void cortex_m55_initfn(Object *obj)
518
-{
519
- ARMCPU *cpu = ARM_CPU(obj);
520
-
521
- set_feature(&cpu->env, ARM_FEATURE_V8);
522
- set_feature(&cpu->env, ARM_FEATURE_V8_1M);
523
- set_feature(&cpu->env, ARM_FEATURE_M);
524
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
525
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
526
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
527
- cpu->midr = 0x410fd221; /* r0p1 */
528
- cpu->revidr = 0;
529
- cpu->pmsav7_dregion = 16;
530
- cpu->sau_sregion = 8;
531
- /* These are the MVFR* values for the FPU + full MVE configuration */
532
- cpu->isar.mvfr0 = 0x10110221;
533
- cpu->isar.mvfr1 = 0x12100211;
534
- cpu->isar.mvfr2 = 0x00000040;
535
- cpu->isar.id_pfr0 = 0x20000030;
536
- cpu->isar.id_pfr1 = 0x00000230;
537
- cpu->isar.id_dfr0 = 0x10200000;
538
- cpu->id_afr0 = 0x00000000;
539
- cpu->isar.id_mmfr0 = 0x00111040;
540
- cpu->isar.id_mmfr1 = 0x00000000;
541
- cpu->isar.id_mmfr2 = 0x01000000;
542
- cpu->isar.id_mmfr3 = 0x00000011;
543
- cpu->isar.id_isar0 = 0x01103110;
544
- cpu->isar.id_isar1 = 0x02212000;
545
- cpu->isar.id_isar2 = 0x20232232;
546
- cpu->isar.id_isar3 = 0x01111131;
547
- cpu->isar.id_isar4 = 0x01310132;
548
- cpu->isar.id_isar5 = 0x00000000;
549
- cpu->isar.id_isar6 = 0x00000000;
550
- cpu->clidr = 0x00000000; /* caches not implemented */
551
- cpu->ctr = 0x8303c003;
552
-}
553
-
554
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
555
/* Dummy the TCM region regs for the moment */
556
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
557
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
558
cpu->reset_sctlr = 0x00000078;
559
}
560
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
562
- .initialize = arm_translate_init,
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
564
- .debug_excp_handler = arm_debug_excp_handler,
565
- .restore_state_to_opc = arm_restore_state_to_opc,
566
-
567
-#ifdef CONFIG_USER_ONLY
568
- .record_sigsegv = arm_cpu_record_sigsegv,
569
- .record_sigbus = arm_cpu_record_sigbus,
570
-#else
571
- .tlb_fill = arm_cpu_tlb_fill,
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
579
-#endif /* !CONFIG_USER_ONLY */
580
-};
581
-
582
-static void arm_v7m_class_init(ObjectClass *oc, void *data)
583
-{
584
- ARMCPUClass *acc = ARM_CPU_CLASS(oc);
585
- CPUClass *cc = CPU_CLASS(oc);
586
-
587
- acc->info = data;
588
- cc->tcg_ops = &arm_v7m_tcg_ops;
589
- cc->gdb_core_xml_file = "arm-m-profile.xml";
590
-}
591
-
592
#ifndef TARGET_AARCH64
593
/*
594
* -cpu max: a CPU with as many features enabled as our emulation supports.
595
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
596
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
597
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
598
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
599
- { .name = "cortex-m0", .initfn = cortex_m0_initfn,
600
- .class_init = arm_v7m_class_init },
601
- { .name = "cortex-m3", .initfn = cortex_m3_initfn,
602
- .class_init = arm_v7m_class_init },
603
- { .name = "cortex-m4", .initfn = cortex_m4_initfn,
604
- .class_init = arm_v7m_class_init },
605
- { .name = "cortex-m7", .initfn = cortex_m7_initfn,
606
- .class_init = arm_v7m_class_init },
607
- { .name = "cortex-m33", .initfn = cortex_m33_initfn,
608
- .class_init = arm_v7m_class_init },
609
- { .name = "cortex-m55", .initfn = cortex_m55_initfn,
610
- .class_init = arm_v7m_class_init },
611
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
612
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
613
{ .name = "cortex-r52", .initfn = cortex_r52_initfn },
117
diff --git a/target/arm/meson.build b/target/arm/meson.build
614
diff --git a/target/arm/meson.build b/target/arm/meson.build
118
index XXXXXXX..XXXXXXX 100644
615
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/meson.build
616
--- a/target/arm/meson.build
120
+++ b/target/arm/meson.build
617
+++ b/target/arm/meson.build
121
@@ -XXX,XX +XXX,XX @@
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
122
gen = [
619
'ptw.c',
123
decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
620
))
124
+ decodetree.process('sme.decode', extra_args: '--decode=disas_sme'),
621
125
decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
622
+arm_user_ss = ss.source_set()
126
decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
623
+
127
decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
624
subdir('hvf')
625
626
if 'CONFIG_TCG' in config_all_accel
627
@@ -XXX,XX +XXX,XX @@ endif
628
629
target_arch += {'arm': arm_ss}
630
target_system_arch += {'arm': arm_system_ss}
631
+target_user_arch += {'arm': arm_user_ss}
632
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
633
index XXXXXXX..XXXXXXX 100644
634
--- a/target/arm/tcg/meson.build
635
+++ b/target/arm/tcg/meson.build
128
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
636
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
129
'sme_helper.c',
637
arm_system_ss.add(files(
130
'translate-a64.c',
638
'psci.c',
131
'translate-sve.c',
132
+ 'translate-sme.c',
133
))
639
))
134
640
+
135
arm_softmmu_ss = ss.source_set()
641
+arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
642
+arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
136
--
643
--
137
2.25.1
644
2.34.1
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-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
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
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
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220708151540.18136-24-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/helper-sme.h | 5 +++
9
target/arm/sme.decode | 11 +++++
10
target/arm/sme_helper.c | 90 ++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-sme.c | 31 +++++++++++++
12
4 files changed, 137 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_st1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i
19
DEF_HELPER_FLAGS_5(sme_st1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
20
DEF_HELPER_FLAGS_5(sme_st1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
21
DEF_HELPER_FLAGS_5(sme_st1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
22
+
23
+DEF_HELPER_FLAGS_5(sme_addha_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, 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 @@ LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
32
33
LDR 1110000 100 0 000000 .. 000 ..... 0 .... @ldstr
34
STR 1110000 100 1 000000 .. 000 ..... 0 .... @ldstr
35
+
36
+### SME Add Vector to Array
37
+
38
+&adda zad zn pm pn
39
+@adda_32 ........ .. ..... . pm:3 pn:3 zn:5 ... zad:2 &adda
40
+@adda_64 ........ .. ..... . pm:3 pn:3 zn:5 .. zad:3 &adda
41
+
42
+ADDHA_s 11000000 10 01000 0 ... ... ..... 000 .. @adda_32
43
+ADDVA_s 11000000 10 01000 1 ... ... ..... 000 .. @adda_32
44
+ADDHA_d 11000000 11 01000 0 ... ... ..... 00 ... @adda_64
45
+ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
46
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/sme_helper.c
49
+++ b/target/arm/sme_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_ST(q, _be, MO_128)
51
DO_ST(q, _le, MO_128)
52
53
#undef DO_ST
54
+
55
+void HELPER(sme_addha_s)(void *vzda, void *vzn, void *vpn,
56
+ void *vpm, uint32_t desc)
57
+{
58
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
59
+ uint64_t *pn = vpn, *pm = vpm;
60
+ uint32_t *zda = vzda, *zn = vzn;
61
+
62
+ for (row = 0; row < oprsz; ) {
63
+ uint64_t pa = pn[row >> 4];
64
+ do {
65
+ if (pa & 1) {
66
+ for (col = 0; col < oprsz; ) {
67
+ uint64_t pb = pm[col >> 4];
68
+ do {
69
+ if (pb & 1) {
70
+ zda[tile_vslice_index(row) + H4(col)] += zn[H4(col)];
71
+ }
72
+ pb >>= 4;
73
+ } while (++col & 15);
74
+ }
75
+ }
76
+ pa >>= 4;
77
+ } while (++row & 15);
78
+ }
79
+}
80
+
81
+void HELPER(sme_addha_d)(void *vzda, void *vzn, void *vpn,
82
+ void *vpm, uint32_t desc)
83
+{
84
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
85
+ uint8_t *pn = vpn, *pm = vpm;
86
+ uint64_t *zda = vzda, *zn = vzn;
87
+
88
+ for (row = 0; row < oprsz; ++row) {
89
+ if (pn[H1(row)] & 1) {
90
+ for (col = 0; col < oprsz; ++col) {
91
+ if (pm[H1(col)] & 1) {
92
+ zda[tile_vslice_index(row) + col] += zn[col];
93
+ }
94
+ }
95
+ }
96
+ }
97
+}
98
+
99
+void HELPER(sme_addva_s)(void *vzda, void *vzn, void *vpn,
100
+ void *vpm, uint32_t desc)
101
+{
102
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
103
+ uint64_t *pn = vpn, *pm = vpm;
104
+ uint32_t *zda = vzda, *zn = vzn;
105
+
106
+ for (row = 0; row < oprsz; ) {
107
+ uint64_t pa = pn[row >> 4];
108
+ do {
109
+ if (pa & 1) {
110
+ uint32_t zn_row = zn[H4(row)];
111
+ for (col = 0; col < oprsz; ) {
112
+ uint64_t pb = pm[col >> 4];
113
+ do {
114
+ if (pb & 1) {
115
+ zda[tile_vslice_index(row) + H4(col)] += zn_row;
116
+ }
117
+ pb >>= 4;
118
+ } while (++col & 15);
119
+ }
120
+ }
121
+ pa >>= 4;
122
+ } while (++row & 15);
123
+ }
124
+}
125
+
126
+void HELPER(sme_addva_d)(void *vzda, void *vzn, void *vpn,
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
+ }
142
+ }
143
+}
144
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/target/arm/translate-sme.c
147
+++ b/target/arm/translate-sme.c
148
@@ -XXX,XX +XXX,XX @@ static bool do_ldst_r(DisasContext *s, arg_ldstr *a, GenLdStR *fn)
149
150
TRANS_FEAT(LDR, aa64_sme, do_ldst_r, a, gen_sve_ldr)
151
TRANS_FEAT(STR, aa64_sme, do_ldst_r, a, gen_sve_str)
152
+
153
+static bool do_adda(DisasContext *s, arg_adda *a, MemOp esz,
154
+ gen_helper_gvec_4 *fn)
155
+{
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
--
184
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
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-34-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
linux-user/aarch64/target_cpu.h | 5 ++++-
9
1 file changed, 4 insertions(+), 1 deletion(-)
10
11
diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/linux-user/aarch64/target_cpu.h
14
+++ b/linux-user/aarch64/target_cpu.h
15
@@ -XXX,XX +XXX,XX @@ static inline void cpu_clone_regs_parent(CPUARMState *env, unsigned flags)
16
17
static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
18
{
19
- /* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
20
+ /*
21
+ * Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
22
* different from AArch32 Linux, which uses TPIDRRO.
23
*/
24
env->cp15.tpidr_el[0] = newtls;
25
+ /* TPIDR2_EL0 is cleared with CLONE_SETTLS. */
26
+ env->cp15.tpidr2_el0 = 0;
27
}
28
29
static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
30
--
31
2.25.1
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-35-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
linux-user/aarch64/cpu_loop.c | 9 +++++++++
9
1 file changed, 9 insertions(+)
10
11
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/linux-user/aarch64/cpu_loop.c
14
+++ b/linux-user/aarch64/cpu_loop.c
15
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
16
17
switch (trapnr) {
18
case EXCP_SWI:
19
+ /*
20
+ * On syscall, PSTATE.ZA is preserved, along with the ZA matrix.
21
+ * PSTATE.SM is cleared, per SMSTOP, which does ResetSVEState.
22
+ */
23
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
24
+ env->svcr = FIELD_DP64(env->svcr, SVCR, SM, 0);
25
+ arm_rebuild_hflags(env);
26
+ arm_reset_sve_state(env);
27
+ }
28
ret = do_syscall(env,
29
env->xregs[8],
30
env->xregs[0],
31
--
32
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Make sure to zero the currently reserved fields.
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-36-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/aarch64/signal.c | 9 ++++++++-
11
1 file changed, 8 insertions(+), 1 deletion(-)
12
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
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
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Fold the return value setting into the goto, so each
4
point of failure need not do both.
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-37-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
linux-user/aarch64/signal.c | 26 +++++++++++---------------
12
1 file changed, 11 insertions(+), 15 deletions(-)
13
14
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/aarch64/signal.c
17
+++ b/linux-user/aarch64/signal.c
18
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
19
struct target_sve_context *sve = NULL;
20
uint64_t extra_datap = 0;
21
bool used_extra = false;
22
- bool err = false;
23
int vq = 0, sve_size = 0;
24
25
target_restore_general_frame(env, sf);
26
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
27
switch (magic) {
28
case 0:
29
if (size != 0) {
30
- err = true;
31
- goto exit;
32
+ goto err;
33
}
34
if (used_extra) {
35
ctx = NULL;
36
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
37
38
case TARGET_FPSIMD_MAGIC:
39
if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
40
- err = true;
41
- goto exit;
42
+ goto err;
43
}
44
fpsimd = (struct target_fpsimd_context *)ctx;
45
break;
46
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
47
break;
48
}
49
}
50
- err = true;
51
- goto exit;
52
+ goto err;
53
54
case TARGET_EXTRA_MAGIC:
55
if (extra || size != sizeof(struct target_extra_context)) {
56
- err = true;
57
- goto exit;
58
+ goto err;
59
}
60
__get_user(extra_datap,
61
&((struct target_extra_context *)ctx)->datap);
62
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
63
/* Unknown record -- we certainly didn't generate it.
64
* Did we in fact get out of sync?
65
*/
66
- err = true;
67
- goto exit;
68
+ goto err;
69
}
70
ctx = (void *)ctx + size;
71
}
72
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
73
if (fpsimd) {
74
target_restore_fpsimd_record(env, fpsimd);
75
} else {
76
- err = true;
77
+ goto err;
78
}
79
80
/* SVE data, if present, overwrites FPSIMD data. */
81
if (sve) {
82
target_restore_sve_record(env, sve, vq);
83
}
84
-
85
- exit:
86
unlock_user(extra, extra_datap, 0);
87
- return err;
88
+ return 0;
89
+
90
+ err:
91
+ unlock_user(extra, extra_datap, 0);
92
+ return 1;
93
}
94
95
static abi_ulong get_sigframe(struct target_sigaction *ka,
96
--
97
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
In parse_user_sigframe, the kernel rejects duplicate sve records,
4
or records that are smaller than the header. We were silently
5
allowing these cases to pass, dropping the record.
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-38-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/aarch64/signal.c | 5 ++++-
13
1 file changed, 4 insertions(+), 1 deletion(-)
14
15
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
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
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-39-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
linux-user/aarch64/signal.c | 3 +++
9
1 file changed, 3 insertions(+)
10
11
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/linux-user/aarch64/signal.c
14
+++ b/linux-user/aarch64/signal.c
15
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
16
__get_user(extra_size,
17
&((struct target_extra_context *)ctx)->size);
18
extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
19
+ if (!extra) {
20
+ return 1;
21
+ }
22
break;
23
24
default:
25
--
26
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Add "sve" to the sve prctl functions, to distinguish
4
them from the coming "sme" prctls with similar names.
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-42-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
linux-user/aarch64/target_prctl.h | 8 ++++----
12
linux-user/syscall.c | 12 ++++++------
13
2 files changed, 10 insertions(+), 10 deletions(-)
14
15
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/aarch64/target_prctl.h
18
+++ b/linux-user/aarch64/target_prctl.h
19
@@ -XXX,XX +XXX,XX @@
20
#ifndef AARCH64_TARGET_PRCTL_H
21
#define AARCH64_TARGET_PRCTL_H
22
23
-static abi_long do_prctl_get_vl(CPUArchState *env)
24
+static abi_long do_prctl_sve_get_vl(CPUArchState *env)
25
{
26
ARMCPU *cpu = env_archcpu(env);
27
if (cpu_isar_feature(aa64_sve, cpu)) {
28
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_get_vl(CPUArchState *env)
29
}
30
return -TARGET_EINVAL;
31
}
32
-#define do_prctl_get_vl do_prctl_get_vl
33
+#define do_prctl_sve_get_vl do_prctl_sve_get_vl
34
35
-static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
36
+static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
37
{
38
/*
39
* We cannot support either PR_SVE_SET_VL_ONEXEC or PR_SVE_VL_INHERIT.
40
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
41
}
42
return -TARGET_EINVAL;
43
}
44
-#define do_prctl_set_vl do_prctl_set_vl
45
+#define do_prctl_sve_set_vl do_prctl_sve_set_vl
46
47
static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
48
{
49
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/linux-user/syscall.c
52
+++ b/linux-user/syscall.c
53
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
54
#ifndef do_prctl_set_fp_mode
55
#define do_prctl_set_fp_mode do_prctl_inval1
56
#endif
57
-#ifndef do_prctl_get_vl
58
-#define do_prctl_get_vl do_prctl_inval0
59
+#ifndef do_prctl_sve_get_vl
60
+#define do_prctl_sve_get_vl do_prctl_inval0
61
#endif
62
-#ifndef do_prctl_set_vl
63
-#define do_prctl_set_vl do_prctl_inval1
64
+#ifndef do_prctl_sve_set_vl
65
+#define do_prctl_sve_set_vl do_prctl_inval1
66
#endif
67
#ifndef do_prctl_reset_keys
68
#define do_prctl_reset_keys do_prctl_inval1
69
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
70
case PR_SET_FP_MODE:
71
return do_prctl_set_fp_mode(env, arg2);
72
case PR_SVE_GET_VL:
73
- return do_prctl_get_vl(env);
74
+ return do_prctl_sve_get_vl(env);
75
case PR_SVE_SET_VL:
76
- return do_prctl_set_vl(env, arg2);
77
+ return do_prctl_sve_set_vl(env, arg2);
78
case PR_PAC_RESET_KEYS:
79
if (arg3 || arg4 || arg5) {
80
return -TARGET_EINVAL;
81
--
82
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
These prctl set the Streaming SVE vector length, which may
4
be completely different from the Normal SVE vector length.
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-43-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
linux-user/aarch64/target_prctl.h | 54 +++++++++++++++++++++++++++++++
12
linux-user/syscall.c | 16 +++++++++
13
2 files changed, 70 insertions(+)
14
15
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/aarch64/target_prctl.h
18
+++ b/linux-user/aarch64/target_prctl.h
19
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_get_vl(CPUArchState *env)
20
{
21
ARMCPU *cpu = env_archcpu(env);
22
if (cpu_isar_feature(aa64_sve, cpu)) {
23
+ /* PSTATE.SM is always unset on syscall entry. */
24
return sve_vq(env) * 16;
25
}
26
return -TARGET_EINVAL;
27
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
28
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
29
uint32_t vq, old_vq;
30
31
+ /* PSTATE.SM is always unset on syscall entry. */
32
old_vq = sve_vq(env);
33
34
/*
35
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
36
}
37
#define do_prctl_sve_set_vl do_prctl_sve_set_vl
38
39
+static abi_long do_prctl_sme_get_vl(CPUArchState *env)
40
+{
41
+ ARMCPU *cpu = env_archcpu(env);
42
+ if (cpu_isar_feature(aa64_sme, cpu)) {
43
+ return sme_vq(env) * 16;
44
+ }
45
+ return -TARGET_EINVAL;
46
+}
47
+#define do_prctl_sme_get_vl do_prctl_sme_get_vl
48
+
49
+static abi_long do_prctl_sme_set_vl(CPUArchState *env, abi_long arg2)
50
+{
51
+ /*
52
+ * We cannot support either PR_SME_SET_VL_ONEXEC or PR_SME_VL_INHERIT.
53
+ * Note the kernel definition of sve_vl_valid allows for VQ=512,
54
+ * i.e. VL=8192, even though the architectural maximum is VQ=16.
55
+ */
56
+ if (cpu_isar_feature(aa64_sme, env_archcpu(env))
57
+ && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
58
+ int vq, old_vq;
59
+
60
+ old_vq = sme_vq(env);
61
+
62
+ /*
63
+ * Bound the value of vq, so that we know that it fits into
64
+ * the 4-bit field in SMCR_EL1. Because PSTATE.SM is cleared
65
+ * on syscall entry, we are not modifying the current SVE
66
+ * vector length.
67
+ */
68
+ vq = MAX(arg2 / 16, 1);
69
+ vq = MIN(vq, 16);
70
+ env->vfp.smcr_el[1] =
71
+ FIELD_DP64(env->vfp.smcr_el[1], SMCR, LEN, vq - 1);
72
+
73
+ /* Delay rebuilding hflags until we know if ZA must change. */
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
--
136
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
There's no reason to set CPACR_EL1.ZEN if SVE disabled.
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-44-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/cpu.c | 7 +++----
11
1 file changed, 3 insertions(+), 4 deletions(-)
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 arm_cpu_reset(DeviceState *dev)
18
/* and to the FP/Neon instructions */
19
env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
20
CPACR_EL1, FPEN, 3);
21
- /* and to the SVE instructions */
22
- env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
23
- CPACR_EL1, ZEN, 3);
24
- /* with reasonable vector length */
25
+ /* and to the SVE instructions, with default vector length */
26
if (cpu_isar_feature(aa64_sve, cpu)) {
27
+ env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
28
+ CPACR_EL1, ZEN, 3);
29
env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
30
}
31
/*
32
--
33
2.25.1
diff view generated by jsdifflib