target/arm: Rearrange {sve,fp}_check_access assert

We want to ensure that access is checked by the time we ask
for a specific fp/vector register.  We want to ensure that
we do not emit two lots of code to raise an exception.

But sometimes it's difficult to cleanly organize the code
such that we never pass through sve_check_access exactly once.
Allow multiple calls so long as the result is true, that is,
no exception to be raised.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20200815013145.539409-5-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2020-08-28 10:02:47 +01:00 committed by Peter Maydell
parent 28c4da31be
commit 8a40fe5f1b
2 changed files with 17 additions and 11 deletions

View File

@ -1156,18 +1156,18 @@ 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 inline bool fp_access_check(DisasContext *s)
static bool fp_access_check(DisasContext *s)
{
assert(!s->fp_access_checked);
s->fp_access_checked = true;
if (s->fp_excp_el) {
assert(!s->fp_access_checked);
s->fp_access_checked = true;
if (!s->fp_excp_el) {
return true;
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
return false;
}
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
return false;
s->fp_access_checked = true;
return true;
}
/* Check that SVE access is enabled. If it is, return true.
@ -1176,10 +1176,14 @@ static inline bool fp_access_check(DisasContext *s)
bool sve_access_check(DisasContext *s)
{
if (s->sve_excp_el) {
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_sve_access_trap(),
s->sve_excp_el);
assert(!s->sve_access_checked);
s->sve_access_checked = true;
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
syn_sve_access_trap(), s->sve_excp_el);
return false;
}
s->sve_access_checked = true;
return fp_access_check(s);
}
@ -14529,6 +14533,7 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
s->base.pc_next += 4;
s->fp_access_checked = false;
s->sve_access_checked = false;
if (dc_isar_feature(aa64_bti, s)) {
if (s->base.num_insns == 1) {

View File

@ -64,6 +64,7 @@ typedef struct DisasContext {
* that it is set at the point where we actually touch the FP regs.
*/
bool fp_access_checked;
bool sve_access_checked;
/* ARMv8 single-step state (this is distinct from the QEMU gdbstub
* single-step support).
*/