diff options
Diffstat (limited to 'target/arm/translate-a64.c')
-rw-r--r-- | target/arm/translate-a64.c | 22 |
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; } /* |