@@ -65,7 +65,7 @@ TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
static inline void assert_fp_access_checked(DisasContext *s)
{
#ifdef CONFIG_DEBUG_TCG
- if (unlikely(!s->fp_access_checked || s->fp_excp_el)) {
+ if (unlikely(s->fp_access_checked <= 0)) {
fprintf(stderr, "target-arm: FP access check missing for "
"instruction 0x%08x\n", s->insn);
abort();
@@ -92,15 +92,19 @@ typedef struct DisasContext {
bool aarch64;
bool thumb;
bool lse2;
- /* Because unallocated encodings generate different exception syndrome
+ /*
+ * Because unallocated encodings generate different exception syndrome
* information from traps due to FP being disabled, we can't do a single
* "is fp access disabled" check at a high level in the decode tree.
* To help in catching bugs where the access check was forgotten in some
* code path, we set this flag when the access check is done, and assert
* that it is set at the point where we actually touch the FP regs.
+ * 0: not checked,
+ * 1: checked, access ok
+ * -1: checked, access denied
*/
- bool fp_access_checked;
- bool sve_access_checked;
+ int8_t fp_access_checked;
+ int8_t sve_access_checked;
/* ARMv8 single-step state (this is distinct from the QEMU gdbstub
* single-step support).
*/
@@ -1381,14 +1381,14 @@ static bool fp_access_check_only(DisasContext *s)
{
if (s->fp_excp_el) {
assert(!s->fp_access_checked);
- s->fp_access_checked = true;
+ s->fp_access_checked = -1;
gen_exception_insn_el(s, 0, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, false, 0),
s->fp_excp_el);
return false;
}
- s->fp_access_checked = true;
+ s->fp_access_checked = 1;
return true;
}
@@ -1465,13 +1465,13 @@ bool sve_access_check(DisasContext *s)
syn_sve_access_trap(), s->sve_excp_el);
goto fail_exit;
}
- s->sve_access_checked = true;
+ s->sve_access_checked = 1;
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;
+ s->sve_access_checked = -1;
return false;
}
@@ -1500,8 +1500,9 @@ bool sme_enabled_check(DisasContext *s)
* sme_excp_el by itself for cpregs access checks.
*/
if (!s->fp_excp_el || s->sme_excp_el < s->fp_excp_el) {
- s->fp_access_checked = true;
- return sme_access_check(s);
+ bool ret = sme_access_check(s);
+ s->fp_access_checked = (ret ? 1 : -1);
+ return ret;
}
return fp_access_check_only(s);
}
@@ -10257,8 +10258,8 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
s->insn = insn;
s->base.pc_next = pc + 4;
- s->fp_access_checked = false;
- s->sve_access_checked = false;
+ s->fp_access_checked = 0;
+ s->sve_access_checked = 0;
if (s->pstate_il) {
/*