Delegated PMU writes compare the full-write mask with -1 in its C type,
rejecting valid RV32 writes. Counter widths and high-half access checks
also use MXLEN, so RV32 S-mode on an RV64 CPU cannot access the high half
and low-half counter writes overwrite all 64 bits.
Use the current XLEN for delegated masks, counter widths and high-half
checks, as required by Smcsrind. Keep MXLEN for direct counter accesses
and retain the 64-bit selector merge mask to preserve the unwritten half.
Test RV32 CPUs in both system emulators and RV32 S-mode on an RV64 CPU,
including half preservation, machine MINH and RV64 M-mode alias accesses.
Fixes: 6247dc2ef70b ("target/riscv: Add counter delegation/configuration
support")
Fixes: c9efdb7b63a4 ("target/riscv: Combine mhpmevent and mhpmeventh")
Link: https://docs.riscv.org/reference/isa/v20260120/priv/indirect-csr.html
Signed-off-by: TANG Tiancheng <[email protected]>
---
target/riscv/tcg/csr.c | 40 +++---
target/riscv/tcg/pmu.c | 6 +-
target/riscv/tcg/pmu.h | 3 +-
tests/tcg/riscv32/smcdeleg-rv32.S | 115 +++++++++++++++++
tests/tcg/riscv32/system/meson.build | 7 ++
tests/tcg/riscv64/smcdeleg-sxl32.S | 233 +++++++++++++++++++++++++++++++++++
tests/tcg/riscv64/system/meson.build | 31 +++++
7 files changed, 412 insertions(+), 23 deletions(-)
diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index
f9f43a9c12e1afdbdf6c7202c167988389963c10..ec6cc6081cb1aa43dc8ee0755b1a4eba1b63350d
100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -1357,10 +1357,10 @@ static uint64_t
riscv_pmu_ctr_get_fixed_counters_val(CPURISCVState *env,
}
static RISCVException riscv_pmu_write_ctr(CPURISCVState *env, target_ulong val,
- uint32_t ctr_idx)
+ uint32_t ctr_idx, RISCVMXL xl)
{
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
- bool rv32 = riscv_cpu_mxl(env) == MXL_RV32;
+ bool rv32 = xl == MXL_RV32;
int deposit_size = rv32 ? 32 : 64;
uint64_t ctr;
@@ -1418,7 +1418,7 @@ static RISCVException write_mhpmcounter(CPURISCVState
*env, int csrno,
{
int ctr_idx = csrno - CSR_MCYCLE;
- return riscv_pmu_write_ctr(env, val, ctr_idx);
+ return riscv_pmu_write_ctr(env, val, ctr_idx, riscv_cpu_mxl(env));
}
static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno,
@@ -1430,10 +1430,11 @@ static RISCVException write_mhpmcounterh(CPURISCVState
*env, int csrno,
}
RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
- bool upper_half, uint32_t ctr_idx)
+ bool upper_half, uint32_t ctr_idx,
+ RISCVMXL xl)
{
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
- bool rv32 = riscv_cpu_mxl(env) == MXL_RV32;
+ bool rv32 = xl == MXL_RV32;
int start = upper_half ? 32 : 0;
int length = rv32 ? 32 : 64;
uint64_t ctr_val;
@@ -1482,7 +1483,7 @@ static RISCVException read_hpmcounter(CPURISCVState *env,
int csrno,
return RISCV_EXCP_ILLEGAL_INST;
}
- return riscv_pmu_read_ctr(env, val, false, ctr_index);
+ return riscv_pmu_read_ctr(env, val, false, ctr_index, riscv_cpu_mxl(env));
}
static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno,
@@ -1498,21 +1499,23 @@ static RISCVException read_hpmcounterh(CPURISCVState
*env, int csrno,
return RISCV_EXCP_ILLEGAL_INST;
}
- return riscv_pmu_read_ctr(env, val, true, ctr_index);
+ return riscv_pmu_read_ctr(env, val, true, ctr_index, riscv_cpu_mxl(env));
}
static int rmw_cd_mhpmcounter(CPURISCVState *env, int ctr_idx,
target_ulong *val, target_ulong new_val,
target_ulong wr_mask)
{
- if (wr_mask != 0 && wr_mask != -1) {
+ uint64_t xlen_mask = env->xl == MXL_RV32 ? UINT32_MAX : UINT64_MAX;
+
+ if (wr_mask != 0 && wr_mask != xlen_mask) {
return -EINVAL;
}
if (!wr_mask && val) {
- riscv_pmu_read_ctr(env, val, false, ctr_idx);
+ riscv_pmu_read_ctr(env, val, false, ctr_idx, env->xl);
} else if (wr_mask) {
- riscv_pmu_write_ctr(env, new_val, ctr_idx);
+ riscv_pmu_write_ctr(env, new_val, ctr_idx, env->xl);
} else {
return -EINVAL;
}
@@ -1524,12 +1527,12 @@ static int rmw_cd_mhpmcounterh(CPURISCVState *env, int
ctr_idx,
target_ulong *val, target_ulong new_val,
target_ulong wr_mask)
{
- if (wr_mask != 0 && wr_mask != -1) {
+ if (wr_mask != 0 && wr_mask != UINT32_MAX) {
return -EINVAL;
}
if (!wr_mask && val) {
- riscv_pmu_read_ctr(env, val, true, ctr_idx);
+ riscv_pmu_read_ctr(env, val, true, ctr_idx, env->xl);
} else if (wr_mask) {
riscv_pmu_write_ctrh(env, new_val, ctr_idx);
} else {
@@ -1544,8 +1547,9 @@ static int rmw_cd_mhpmevent(CPURISCVState *env, int
ctr_idx,
uint64_t wr_mask)
{
uint64_t mhpmevt_val = env->mhpmevent_val[ctr_idx];
+ uint64_t xlen_mask = env->xl == MXL_RV32 ? UINT32_MAX : UINT64_MAX;
- if (wr_mask != 0 && wr_mask != -1) {
+ if (wr_mask != 0 && wr_mask != xlen_mask) {
return -EINVAL;
}
@@ -1573,7 +1577,7 @@ static int rmw_cd_mhpmeventh(CPURISCVState *env, int
ctr_idx,
uint64_t mhpmevt_val = env->mhpmevent_val[ctr_idx];
uint32_t mhpmevth_val = extract64(mhpmevt_val, 32, 32);
- if (wr_mask != 0 && wr_mask != -1) {
+ if (wr_mask != 0 && wr_mask != UINT32_MAX) {
return -EINVAL;
}
@@ -1630,10 +1634,6 @@ static int rmw_cd_ctr_cfgh(CPURISCVState *env, int
cfg_index, target_ulong *val,
{
uint64_t cfgh;
- if (riscv_cpu_mxl(env) != MXL_RV32) {
- return RISCV_EXCP_ILLEGAL_INST;
- }
-
switch (cfg_index) {
case 0: /* CYCLECFGH */
cfgh = extract64(env->mcyclecfg, 32, 32);
@@ -2809,9 +2809,9 @@ static int rmw_xireg_cd(CPURISCVState *env, int csrno,
goto done;
}
- /* sireg4 and sireg5 provides access RV32 only CSRs */
+ /* Delegated high halves are accessible only when the current XLEN is 32.
*/
if (((csrno == CSR_SIREG5) || (csrno == CSR_SIREG4)) &&
- (riscv_cpu_mxl(env) != MXL_RV32)) {
+ env->xl != MXL_RV32) {
ret = RISCV_EXCP_ILLEGAL_INST;
goto done;
}
diff --git a/target/riscv/tcg/pmu.c b/target/riscv/tcg/pmu.c
index
ea0ffe41258d4dbef9dc952655e6301c14ba1d23..54fff2ba49c1034d5fa6db1c7b19ff59003cd1e1
100644
--- a/target/riscv/tcg/pmu.c
+++ b/target/riscv/tcg/pmu.c
@@ -372,10 +372,12 @@ static void pmu_timer_trigger_irq_counter(RISCVCPU *cpu,
uint32_t ctr_idx)
return;
}
- riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctr_val, false, ctr_idx);
+ riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctr_val, false, ctr_idx,
+ riscv_cpu_mxl(env));
ctr_val = counter->mhpmcounter_val;
if (riscv_cpu_mxl(env) == MXL_RV32) {
- riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctrh_val, true, ctr_idx);
+ riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctrh_val, true, ctr_idx,
+ riscv_cpu_mxl(env));
curr_ctr_val = curr_ctr_val | (curr_ctrh_val << 32);
}
diff --git a/target/riscv/tcg/pmu.h b/target/riscv/tcg/pmu.h
index
339a4b3ac09c4a91cddd9250824284203b16b4fa..bf2e8373474d471d914f8801c55d2f6ffbb5cdd3
100644
--- a/target/riscv/tcg/pmu.h
+++ b/target/riscv/tcg/pmu.h
@@ -38,6 +38,7 @@ void riscv_pmu_update_fixed_ctrs(CPURISCVState *env,
privilege_mode_t newpriv,
bool new_virt);
void riscv_pmu_decr_instret(CPURISCVState *env);
RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
- bool upper_half, uint32_t ctr_idx);
+ bool upper_half, uint32_t ctr_idx,
+ RISCVMXL xl);
#endif /* RISCV_PMU_H */
diff --git a/tests/tcg/riscv32/smcdeleg-rv32.S
b/tests/tcg/riscv32/smcdeleg-rv32.S
new file mode 100644
index
0000000000000000000000000000000000000000..7b7c1db5bd3cbb59397a573adf0f7d685a1db3d8
--- /dev/null
+++ b/tests/tcg/riscv32/smcdeleg-rv32.S
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* RV32 delegated PMU registers, in both RV32 and RV64 emulators. */
+
+/* CSR numbers for older assemblers. */
+#define CSR_SISELECT 0x150
+#define CSR_SIREG 0x151
+#define CSR_SIREG2 0x152
+#define CSR_SIREG4 0x155
+#define CSR_SIREG5 0x156
+#define CSR_MENVCFGH 0x31a
+#define CSR_MHPMEVENT3H 0x723
+
+ .option norvc
+ .option norelax
+
+ .text
+ .global _start
+_start:
+ /* Unexpected exceptions report the current check number. */
+ li t4, 1
+ lla t0, fail
+ csrw mtvec, t0
+ li t0, 8 /* Stop HPM3 so reads are exact. */
+ csrw mcountinhibit, t0
+ csrw mcounteren, t0
+ li t0, 1 << 28 /* menvcfgh.CDE */
+ csrw CSR_MENVCFGH, t0
+ li t0, 0x43 /* siselect: counter 3 */
+ csrw CSR_SISELECT, t0
+ li t0, 0x12345678
+ csrw mhpmcounter3h, t0
+ li t0, 1 /* HW_CPU_CYCLES */
+ csrw mhpmevent3, t0
+ li t0, 0xc0000000 /* OF | MINH */
+ csrw CSR_MHPMEVENT3H, t0
+
+ /* sireg writes the low half without changing the high half. */
+ li t0, 0x2468ace0
+ csrw CSR_SIREG, t0
+ csrr t1, CSR_SIREG
+ bne t0, t1, fail
+ csrr t1, mhpmcounter3
+ bne t0, t1, fail
+ li t0, 0x12345678
+ csrr t1, mhpmcounter3h
+ bne t0, t1, fail
+
+ /* sireg4 writes the high half without changing the low half. */
+ li t4, 2
+ li t0, 0xfedcba98
+ csrw CSR_SIREG4, t0
+ csrr t1, CSR_SIREG4
+ bne t0, t1, fail
+ csrr t1, mhpmcounter3h
+ bne t0, t1, fail
+ li t0, 0x2468ace0
+ csrr t1, mhpmcounter3
+ bne t0, t1, fail
+
+ /* sireg5 clears OF and sets SINH, but cannot change machine MINH. */
+ li t4, 3
+ li t0, 0x20000000 /* SINH */
+ csrw CSR_SIREG5, t0
+ csrr t1, CSR_SIREG5
+ bne t0, t1, fail
+ li t0, 0x60000000 /* MINH | SINH */
+ csrr t1, CSR_MHPMEVENT3H
+ bne t0, t1, fail
+ li t0, 1
+ csrr t1, mhpmevent3
+ bne t0, t1, fail
+
+ /* sireg2 changes the event without changing those high-half bits. */
+ li t4, 4
+ li t0, 2 /* HW_INSTRUCTIONS */
+ csrw CSR_SIREG2, t0
+ csrr t1, mhpmevent3
+ bne t0, t1, fail
+ li t0, 0x60000000
+ csrr t1, CSR_MHPMEVENT3H
+ bne t0, t1, fail
+
+ /* Event replacement must also preserve OF when it is set. */
+ li t4, 5
+ li t0, 0xe0000000 /* OF | MINH | SINH */
+ csrw CSR_MHPMEVENT3H, t0
+ li t0, 1 /* HW_CPU_CYCLES */
+ csrw mhpmevent3, t0
+ li t0, 2 /* HW_INSTRUCTIONS */
+ csrw CSR_SIREG2, t0
+ csrr t1, mhpmevent3
+ bne t0, t1, fail
+ li t0, 0xe0000000
+ csrr t1, CSR_MHPMEVENT3H
+ bne t0, t1, fail
+
+ /* Selecting event zero must also leave the high half unchanged. */
+ li t4, 6
+ csrw CSR_SIREG2, zero
+ csrr t1, mhpmevent3
+ bnez t1, fail
+ csrr t1, CSR_MHPMEVENT3H
+ bne t0, t1, fail
+
+ li t0, 0x5555 /* FINISHER_PASS */
+ j finish
+fail:
+ slli t0, t4, 16
+ li t1, 0x3333 /* FINISHER_FAIL with check number */
+ or t0, t0, t1
+finish:
+ li t1, 0x100000 /* virt test device */
+ sw t0, 0(t1)
+ j .
diff --git a/tests/tcg/riscv32/system/meson.build
b/tests/tcg/riscv32/system/meson.build
index
5f417c0c51e17840072104812f5854dfb65d1d06..800c754093e275cd25be7878a96a8c551f73dbce
100644
--- a/tests/tcg/riscv32/system/meson.build
+++ b/tests/tcg/riscv32/system/meson.build
@@ -36,6 +36,13 @@ tests += {
},
}
+tests += {
+ 'smcdeleg-rv32.S': {
+ 'cflags': cflags,
+ 'qemu_args': ['-cpu', 'max', qemu_args],
+ },
+}
+
if 'qemu-system-riscv32' in emulators
tcg_tests += {
'riscv32-softmmu': {
diff --git a/tests/tcg/riscv64/smcdeleg-sxl32.S
b/tests/tcg/riscv64/smcdeleg-sxl32.S
new file mode 100644
index
0000000000000000000000000000000000000000..3c5fc2b174c8f18988943f6b4bb9c07ca5dcd53d
--- /dev/null
+++ b/tests/tcg/riscv64/smcdeleg-sxl32.S
@@ -0,0 +1,233 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* CSR numbers for older assemblers. */
+#define CSR_SISELECT 0x150
+#define CSR_SIREG 0x151
+#define CSR_SIREG2 0x152
+#define CSR_SIREG4 0x155
+#define CSR_SIREG5 0x156
+#define CSR_MENVCFG 0x30a
+#define CSR_MSTATEEN0 0x30c
+#define CSR_MCYCLECFG 0x321
+#define CSR_MINSTRETCFG 0x322
+
+/*
+ * Exercise delegated PMU registers with MXLEN=64 and SXLEN=32.
+ * Build separately for counter low halves, counter high halves and configs
+ * so a failure in one access path does not hide failures in the others.
+ */
+
+ .option norvc
+ .option norelax
+
+ /* RV64 'li' can emit ADDIW, which is illegal in the RV32 blocks. */
+ .macro load32 reg, value
+ lui \reg, %hi(\value)
+ addi \reg, \reg, %lo(\value)
+ .endm
+
+ /* Enter RV32 S-mode; the ECALL trap below returns to M-mode. */
+ .macro enter_s32 label
+ li a0, 0
+ li a5, 9 /* Expected exception: S-mode ECALL. */
+ li t0, 3 << 11
+ csrc mstatus, t0
+ li t0, 1 << 11
+ csrs mstatus, t0 /* MPP=S */
+ lla t0, \label
+ csrw mepc, t0
+ mret
+ .endm
+
+ /* Each alias must be 64-bit in M-mode, even while SXLEN is 32. */
+ .macro check_m64_alias csr
+ li t0, 0x1234567811223344
+ csrw CSR_SIREG, t0
+ csrr t1, \csr
+ bne t0, t1, fail
+ csrr t1, CSR_SIREG
+ bne t0, t1, fail
+
+ /* High-half aliases must still trap when the current XLEN is 64. */
+ li a0, 0
+ li a5, 2 /* Expect illegal instruction. */
+ li s9, 0
+ csrr t0, CSR_SIREG4
+ csrr t0, CSR_SIREG5
+ li t0, 2
+ bne s9, t0, fail /* Both accesses must have trapped. */
+ .endm
+
+ .macro check_counter index, csr
+ li s10, \index + 1 /* Counter-specific failure code. */
+ li t0, 0x40 + \index
+ csrw CSR_SISELECT, t0
+ check_m64_alias \csr
+ enter_s32 .Ls_counter\@
+.Ls_counter\@:
+#ifdef TEST_HIGH_HALF
+ csrr t0, CSR_SIREG4 /* sireg4: original high half */
+ load32 t1, 0x12345678
+ bne t0, t1, .Ls_fail\@
+ load32 t0, 0x07654321
+ csrw CSR_SIREG4, t0
+ csrr t1, CSR_SIREG4
+ bne t0, t1, .Ls_fail\@
+ /* A high-half write must preserve the low half. */
+ csrr t0, CSR_SIREG
+ load32 t1, 0x11223344
+#else
+ csrr t0, CSR_SIREG /* sireg: original low half */
+ load32 t1, 0x11223344
+ bne t0, t1, .Ls_fail\@
+ load32 t0, 0x55667788
+ csrw CSR_SIREG, t0
+ csrr t1, CSR_SIREG
+#endif
+ bne t0, t1, .Ls_fail\@
+ li a0, 0
+ j .Ls_done\@
+.Ls_fail\@:
+ mv a0, s10
+.Ls_done\@:
+ ecall
+
+ /* Read the complete machine counter to check the unwritten half. */
+ csrr t0, \csr
+#ifdef TEST_HIGH_HALF
+ li t1, 0x0765432111223344
+#else
+ li t1, 0x1234567855667788
+#endif
+ bne t0, t1, fail
+ .endm
+
+ .macro check_config index, csr, old_low, new_low
+ li s10, \index + 1
+ li t0, 0x40 + \index
+ csrw CSR_SISELECT, t0
+ li t0, 0x6000000000000000 | \old_low /* MINH | SINH */
+ csrw \csr, t0
+ enter_s32 .Ls_config\@
+.Ls_config\@:
+ csrr t0, CSR_SIREG2 /* sireg2: config/selector low half */
+ li t1, \old_low
+ bne t0, t1, .Lcfg_fail\@
+ li t0, \new_low
+ csrw CSR_SIREG2, t0
+ csrr t1, CSR_SIREG2
+ bne t0, t1, .Lcfg_fail\@
+
+ /* Low-half writes preserve the high half; MINH reads as zero. */
+ csrr t0, CSR_SIREG5
+ li t1, 0x20000000 /* SINH, without MINH */
+ bne t0, t1, .Lcfg_fail\@
+ li t0, 0x10000000 /* Replace SINH with UINH. */
+ csrw CSR_SIREG5, t0
+ csrr t1, CSR_SIREG5
+ bne t0, t1, .Lcfg_fail\@
+ csrr t0, CSR_SIREG2
+ li t1, \new_low
+ bne t0, t1, .Lcfg_fail\@
+ li a0, 0
+ j .Lcfg_done\@
+.Lcfg_fail\@:
+ mv a0, s10
+.Lcfg_done\@:
+ ecall
+
+ /* Both the low half and the machine-only MINH bit must be retained. */
+ csrr t0, \csr
+ li t1, 0x5000000000000000 | \new_low /* MINH | UINH */
+ bne t0, t1, fail
+ .endm
+
+ .text
+ .global _start
+_start:
+ li s10, 31 /* Setup failure. */
+ lla t0, trap
+ csrw mtvec, t0
+ csrw medeleg, zero
+ csrw mie, zero
+ li t0, -1
+ /* Freeze counters for exact comparisons. */
+ csrw mcountinhibit, t0
+ csrw mcounteren, t0
+ csrw pmpaddr0, t0
+ li t0, 0x1f /* Allow S-mode access to RAM. */
+ csrw pmpcfg0, t0
+ li t0, 1 << 60
+ csrw CSR_MENVCFG, t0 /* CDE */
+ /* mstateen0: allow indirect CSRs. */
+ csrw CSR_MSTATEEN0, t0
+
+ /* Select RV32 for lower privilege modes; M-mode remains RV64. */
+ csrr t0, mstatus
+ li t1, (3 << 34) | (3 << 32)
+ not t1, t1
+ and t0, t0, t1
+ li t1, (1 << 34) | (1 << 32)
+ or t0, t0, t1
+ csrw mstatus, t0
+ csrr t0, mstatus
+ srli t0, t0, 34
+ andi t0, t0, 3
+ li t1, 1
+ bne t0, t1, fail
+
+#ifdef TEST_CONFIG
+ check_config 0, CSR_MCYCLECFG, 0, 0
+ check_config 2, CSR_MINSTRETCFG, 0, 0
+ /* mhpmevent3: cycles -> instructions */
+ check_config 3, mhpmevent3, 1, 2
+#else
+ li t0, 1
+ csrw mhpmevent3, t0 /* HPM3 counts cycles. */
+ li t0, 2
+ csrw mhpmevent4, t0 /* HPM4 counts instructions. */
+ /* HPM5 has no selected event. */
+ csrw mhpmevent5, zero
+ check_counter 0, mcycle
+ check_counter 2, minstret
+ check_counter 3, mhpmcounter3
+ check_counter 4, mhpmcounter4
+ check_counter 5, mhpmcounter5
+#endif
+ li a0, 0
+ j exit
+
+ .balign 4
+trap:
+ csrr t0, mcause
+ bne t0, a5, fail
+ bnez a0, exit
+ addi s9, s9, 1
+ csrr t0, mepc
+ /* Zero-extend the RV32 trap PC for physical addressing in M-mode. */
+ slli t0, t0, 32
+ srli t0, t0, 32
+ addi t0, t0, 4
+ csrw mepc, t0
+ li t0, 3 << 11
+ csrs mstatus, t0 /* Resume in M-mode. */
+ mret
+
+fail:
+ mv a0, s10
+exit:
+ lla a1, semiargs
+ li t0, 0x20026 /* ADP_Stopped_ApplicationExit */
+ sd t0, 0(a1)
+ sd a0, 8(a1)
+ li a0, 0x20 /* TARGET_SYS_EXIT_EXTENDED */
+ .balign 16
+ slli zero, zero, 0x1f
+ ebreak
+ srai zero, zero, 0x7
+ j .
+
+ .data
+ .balign 16
+semiargs:
+ .space 16
diff --git a/tests/tcg/riscv64/system/meson.build
b/tests/tcg/riscv64/system/meson.build
index
5d91381c62d77ae7e37c129112d6367f692df660..cfb868c45704e210e8fe951be0cbb752b589d51d
100644
--- a/tests/tcg/riscv64/system/meson.build
+++ b/tests/tcg/riscv64/system/meson.build
@@ -61,6 +61,37 @@ tests += {
}
}
+# Exercise RV32 CSRs with the RV64 emulator's 64-bit target_ulong.
+tests += {
+ '../riscv32/smcdeleg-rv32.S': {
+ 'cflags': cflags + ['-march=rv32im_zicsr', '-mabi=ilp32'],
+ 'qemu_args': ['-cpu', 'rv32,smcdeleg=true,ssccfg=true,sscofpmf=true',
qemu_args],
+ },
+}
+
+tests += {
+ 'smcdeleg-sxl32.S': {
+ 'cflags': cflags,
+ 'qemu_args': ['-cpu', 'max', qemu_args],
+ },
+}
+
+tests += {
+ 'smcdeleg-sxl32.S': {
+ 'exe_name': 'smcdeleg-sxl32-high',
+ 'cflags': cflags + ['-DTEST_HIGH_HALF'],
+ 'qemu_args': ['-cpu', 'max', qemu_args],
+ },
+}
+
+tests += {
+ 'smcdeleg-sxl32.S': {
+ 'exe_name': 'smcdeleg-sxl32-cfg',
+ 'cflags': cflags + ['-DTEST_CONFIG'],
+ 'qemu_args': ['-cpu', 'max', qemu_args],
+ },
+}
+
tests += {
'sscofpmf-overflow.S': {
'cflags': cflags,
--
2.43.0