summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-07-08 20:45:11 +0530
committerPeter Maydell <peter.maydell@linaro.org>2022-07-11 13:19:35 +0100
commit285b1d5fcef3ef352333f08bde669551054fbee4 (patch)
treecd068150fc2e5212f79bdd9348f6b36dedea1bb8 /target
parent3d74825f4d68a54cf1cd772dda8b502695b2d783 (diff)
target/arm: Handle SME in sve_access_check
The pseudocode for CheckSVEEnabled gains a check for Streaming SVE mode, and for SME present but SVE absent. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220708151540.18136-17-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/translate-a64.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index b16d81bf19..b7b64f7358 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1183,21 +1183,31 @@ static bool fp_access_check(DisasContext *s)
return true;
}
-/* Check that SVE access is enabled. If it is, 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.
+ * This function corresponds to CheckSVEEnabled().
*/
bool sve_access_check(DisasContext *s)
{
- if (s->sve_excp_el) {
- assert(!s->sve_access_checked);
- s->sve_access_checked = true;
-
+ if (s->pstate_sm || !dc_isar_feature(aa64_sve, s)) {
+ assert(dc_isar_feature(aa64_sme, s));
+ if (!sme_sm_enabled_check(s)) {
+ goto fail_exit;
+ }
+ } else if (s->sve_excp_el) {
gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
syn_sve_access_trap(), s->sve_excp_el);
- return false;
+ goto fail_exit;
}
s->sve_access_checked = true;
return fp_access_check(s);
+
+ fail_exit:
+ /* Assert that we only raise one exception per instruction. */
+ assert(!s->sve_access_checked);
+ s->sve_access_checked = true;
+ return false;
}
/*