summaryrefslogtreecommitdiff
path: root/target/arm/translate-a64.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-07-08 20:44:58 +0530
committerPeter Maydell <peter.maydell@linaro.org>2022-07-11 13:19:35 +0100
commit75fe83564a2e41ac4bfcee72b1d9a590ddd46ebe (patch)
tree4e3f50a66066442f92b4cc8dbebcfa2285875436 /target/arm/translate-a64.c
parente67cd1cac26181873496e5fb2464dbeb038e0fcd (diff)
target/arm: Trap non-streaming usage when Streaming SVE is active
This new behaviour is in the ARM pseudocode function AArch64.CheckFPAdvSIMDEnabled, which applies to AArch32 via AArch32.CheckAdvSIMDOrFPEnabled when the EL to which the trap would be delivered is in AArch64 mode. Given that ARMv9 drops support for AArch32 outside EL0, the trap EL detection ought to be trivially true, but the pseudocode still contains a number of conditions, and QEMU has not yet committed to dropping A32 support for EL[12] when v9 features are present. Since the computation of SME_TRAP_NONSTREAMING is necessarily different for the two modes, we might as well preserve bits within TBFLAG_ANY and allocate separate bits within TBFLAG_A32 and TBFLAG_A64 instead. Note that DDI0616A.a has typos for bits [22:21] of LD1RO in the table of instructions illegal in streaming mode. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220708151540.18136-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/translate-a64.c')
-rw-r--r--target/arm/translate-a64.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index a5f8a6c771..7fab7f64f8 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1155,7 +1155,7 @@ static void do_vec_ld(DisasContext *s, int destidx, int element,
* unallocated-encoding checks (otherwise the syndrome information
* for the resulting exception will be incorrect).
*/
-static bool fp_access_check(DisasContext *s)
+static bool fp_access_check_only(DisasContext *s)
{
if (s->fp_excp_el) {
assert(!s->fp_access_checked);
@@ -1170,6 +1170,19 @@ static bool fp_access_check(DisasContext *s)
return true;
}
+static bool fp_access_check(DisasContext *s)
+{
+ if (!fp_access_check_only(s)) {
+ return false;
+ }
+ if (s->sme_trap_nonstreaming && s->is_nonstreaming) {
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
+ syn_smetrap(SME_ET_Streaming, false));
+ return false;
+ }
+ return true;
+}
+
/* Check that SVE access is enabled. If it is, return true.
* If not, emit code to generate an appropriate exception and return false.
*/
@@ -1994,7 +2007,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
default:
g_assert_not_reached();
}
- if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
+ if ((ri->type & ARM_CP_FPU) && !fp_access_check_only(s)) {
return;
} else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
return;
@@ -14530,6 +14543,23 @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
}
}
+/*
+ * Include the generated SME FA64 decoder.
+ */
+
+#include "decode-sme-fa64.c.inc"
+
+static bool trans_OK(DisasContext *s, arg_OK *a)
+{
+ return true;
+}
+
+static bool trans_FAIL(DisasContext *s, arg_OK *a)
+{
+ s->is_nonstreaming = true;
+ return true;
+}
+
/**
* is_guarded_page:
* @env: The cpu environment
@@ -14657,6 +14687,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->mte_active[1] = EX_TBFLAG_A64(tb_flags, MTE0_ACTIVE);
dc->pstate_sm = EX_TBFLAG_A64(tb_flags, PSTATE_SM);
dc->pstate_za = EX_TBFLAG_A64(tb_flags, PSTATE_ZA);
+ dc->sme_trap_nonstreaming = EX_TBFLAG_A64(tb_flags, SME_TRAP_NONSTREAMING);
dc->vec_len = 0;
dc->vec_stride = 0;
dc->cp_regs = arm_cpu->cp_regs;
@@ -14805,6 +14836,11 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
}
}
+ s->is_nonstreaming = false;
+ if (s->sme_trap_nonstreaming) {
+ disas_sme_fa64(s, insn);
+ }
+
switch (extract32(insn, 25, 4)) {
case 0x0:
if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {