target/arm: Split vfp_access_check() into A and M versions
vfp_access_check and its helper routine full_vfp_access_check() has gradually grown and is now an awkward mix of A-profile only and M-profile only pieces. Refactor it into an A-profile only and an M-profile only version, taking advantage of the fact that now the only direct call to full_vfp_access_check() is in A-profile-only code. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210618141019.10671-7-peter.maydell@linaro.org
This commit is contained in:
parent
95aceeeac9
commit
e8cedaf779
|
@ -188,18 +188,40 @@ static void gen_update_fp_context(DisasContext *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that VFP access is enabled. If it is, do the necessary
|
* Check that VFP access is enabled, A-profile specific version.
|
||||||
* M-profile lazy-FP handling and then return true.
|
*
|
||||||
* If not, emit code to generate an appropriate exception and
|
* If VFP is enabled, return true. If not, emit code to generate an
|
||||||
* return false.
|
* appropriate exception and return false.
|
||||||
* The ignore_vfp_enabled argument specifies that we should ignore
|
* The ignore_vfp_enabled argument specifies that we should ignore
|
||||||
* whether VFP is enabled via FPEXC[EN]: this should be true for FMXR/FMRX
|
* whether VFP is enabled via FPEXC.EN: this should be true for FMXR/FMRX
|
||||||
* accesses to FPSID, FPEXC, MVFR0, MVFR1, MVFR2, and false for all other insns.
|
* accesses to FPSID, FPEXC, MVFR0, MVFR1, MVFR2, and false for all other insns.
|
||||||
*/
|
*/
|
||||||
static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
|
static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
|
||||||
|
{
|
||||||
|
if (s->fp_excp_el) {
|
||||||
|
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
|
||||||
|
syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s->vfp_enabled && !ignore_vfp_enabled) {
|
||||||
|
assert(!arm_dc_feature(s, ARM_FEATURE_M));
|
||||||
|
unallocated_encoding(s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that VFP access is enabled, M-profile specific version.
|
||||||
|
*
|
||||||
|
* If VFP is enabled, do the necessary M-profile lazy-FP handling and then
|
||||||
|
* return true. If not, emit code to generate an appropriate exception and
|
||||||
|
* return false.
|
||||||
|
*/
|
||||||
|
static bool vfp_access_check_m(DisasContext *s)
|
||||||
{
|
{
|
||||||
if (s->fp_excp_el) {
|
if (s->fp_excp_el) {
|
||||||
if (arm_dc_feature(s, ARM_FEATURE_M)) {
|
|
||||||
/*
|
/*
|
||||||
* M-profile mostly catches the "FPU disabled" case early, in
|
* M-profile mostly catches the "FPU disabled" case early, in
|
||||||
* disas_m_nocp(), but a few insns (eg LCTP, WLSTP, DLSTP)
|
* disas_m_nocp(), but a few insns (eg LCTP, WLSTP, DLSTP)
|
||||||
|
@ -209,21 +231,9 @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
|
||||||
*/
|
*/
|
||||||
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
|
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
|
||||||
syn_uncategorized(), s->fp_excp_el);
|
syn_uncategorized(), s->fp_excp_el);
|
||||||
} else {
|
|
||||||
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
|
|
||||||
syn_fp_access_trap(1, 0xe, false),
|
|
||||||
s->fp_excp_el);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->vfp_enabled && !ignore_vfp_enabled) {
|
|
||||||
assert(!arm_dc_feature(s, ARM_FEATURE_M));
|
|
||||||
unallocated_encoding(s);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arm_dc_feature(s, ARM_FEATURE_M)) {
|
|
||||||
/* Handle M-profile lazy FP state mechanics */
|
/* Handle M-profile lazy FP state mechanics */
|
||||||
|
|
||||||
/* Trigger lazy-state preservation if necessary */
|
/* Trigger lazy-state preservation if necessary */
|
||||||
|
@ -231,7 +241,6 @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
|
||||||
|
|
||||||
/* Update ownership of FP context and create new FP context if needed */
|
/* Update ownership of FP context and create new FP context if needed */
|
||||||
gen_update_fp_context(s);
|
gen_update_fp_context(s);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +251,11 @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
|
||||||
*/
|
*/
|
||||||
bool vfp_access_check(DisasContext *s)
|
bool vfp_access_check(DisasContext *s)
|
||||||
{
|
{
|
||||||
return full_vfp_access_check(s, false);
|
if (arm_dc_feature(s, ARM_FEATURE_M)) {
|
||||||
|
return vfp_access_check_m(s);
|
||||||
|
} else {
|
||||||
|
return vfp_access_check_a(s, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
|
static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
|
||||||
|
@ -732,7 +745,11 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!full_vfp_access_check(s, ignore_vfp_enabled)) {
|
/*
|
||||||
|
* Call vfp_access_check_a() directly, because we need to tell
|
||||||
|
* it to ignore FPEXC.EN for some register accesses.
|
||||||
|
*/
|
||||||
|
if (!vfp_access_check_a(s, ignore_vfp_enabled)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue