target/arm: Move FPU/SVE/SME access checks up above ARM_CP_SPECIAL_MASK check

In handle_sys() we don't do the check for whether the register is
marked as needing an FPU/SVE/SME access check until after we've
handled the special cases covered by ARM_CP_SPECIAL_MASK.  This is
conceptually the wrong way around, because if for example we happen
to implement an FPU-access-checked register as ARM_CP_NOP, we should
do the access check first.

Move the access checks up so they are with all the other access
checks, not sandwiched between the special-case read/write handling
and the normal-case read/write handling. This doesn't change
behaviour at the moment, because we happen not to define any
cpregs with both ARM_CPU_{FPU,SVE,SME} and one of the cases
dealt with by ARM_CP_SPECIAL_MASK.

Moving this code also means we have the correct place to put the
FEAT_NV/FEAT_NV2 access handling, which should come after the access
checks and before we try to do any read/write action.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Miguel Luis <miguel.luis@oracle.com>
This commit is contained in:
Peter Maydell 2024-01-09 14:43:48 +00:00
parent 83aea11db0
commit 44572fc984

View File

@ -2190,6 +2190,14 @@ static void handle_sys(DisasContext *s, bool isread,
gen_a64_update_pc(s, 0); gen_a64_update_pc(s, 0);
} }
if ((ri->type & ARM_CP_FPU) && !fp_access_check_only(s)) {
return;
} else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
return;
} else if ((ri->type & ARM_CP_SME) && !sme_access_check(s)) {
return;
}
/* Handle special cases first */ /* Handle special cases first */
switch (ri->type & ARM_CP_SPECIAL_MASK) { switch (ri->type & ARM_CP_SPECIAL_MASK) {
case 0: case 0:
@ -2268,13 +2276,6 @@ static void handle_sys(DisasContext *s, bool isread,
default: default:
g_assert_not_reached(); g_assert_not_reached();
} }
if ((ri->type & ARM_CP_FPU) && !fp_access_check_only(s)) {
return;
} else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
return;
} else if ((ri->type & ARM_CP_SME) && !sme_access_check(s)) {
return;
}
if (ri->type & ARM_CP_IO) { if (ri->type & ARM_CP_IO) {
/* I/O operations must end the TB here (whether read or write) */ /* I/O operations must end the TB here (whether read or write) */