@@ -46,6 +46,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
DEF_HELPER_2(exception_internal, noreturn, env, i32)
DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32)
+DEF_HELPER_3(exception_advsimdfp_access, noreturn, env, i32, i32)
DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
DEF_HELPER_1(setend, void, env)
@@ -337,6 +337,15 @@ static inline void gen_exception(int excp, uint32_t syndrome,
tcg_constant_i32(target_el));
}
+static inline void gen_exception_advsimdfp_access(DisasContext *s,
+ uint32_t syndrome)
+{
+ gen_helper_exception_advsimdfp_access(cpu_env,
+ tcg_constant_i32(syndrome),
+ tcg_constant_i32(s->fp_excp_el));
+ s->base.is_jmp = DISAS_NORETURN;
+}
+
/* Generate an architectural singlestep exception */
static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
{
@@ -34,16 +34,8 @@ void raise_exception(CPUARMState *env, uint32_t excp,
CPUState *cs = env_cpu(env);
if (target_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
- /*
- * Redirect NS EL1 exceptions to NS EL2. These are reported with
- * their original syndrome register value, with the exception of
- * SIMD/FP access traps, which are reported as uncategorized
- * (see DDI0478C.a D1.10.4)
- */
+ /* Redirect NS EL1 exceptions to NS EL2. */
target_el = 2;
- if (syn_get_ec(syndrome) == EC_ADVSIMDFPACCESSTRAP) {
- syndrome = syn_uncategorized();
- }
}
assert(!excp_is_internal(excp));
@@ -384,6 +376,28 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
raise_exception(env, excp, syndrome, target_el);
}
+/* Raise an exception with EC_ADVSIMDFPACCESS. */
+void HELPER(exception_advsimdfp_access)(CPUARMState *env,
+ uint32_t syndrome, uint32_t target_el)
+{
+ if (target_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
+ /*
+ * SIMD/FP access traps, when re-routed to EL2, are reported with
+ * uncategorized syndrome. See DDI0487H.a rule RJNBTN.
+ */
+ target_el = 2;
+ syndrome = syn_uncategorized();
+ } else if (arm_el_is_aa64(env, target_el)) {
+ /*
+ * From AArch32, we will have filled in TA and/or COPROC for use
+ * by aa32 HSR. But in aa64 ESR_ELx, the low 20 bits are RES0.
+ */
+ syndrome &= 0xfff00000;
+ }
+
+ raise_exception(env, EXCP_UDEF, syndrome, target_el);
+}
+
/* Raise an EXCP_BKPT with the specified syndrome register value,
* targeting the correct exception level for debug exceptions.
*/
@@ -1161,9 +1161,8 @@ static bool fp_access_check(DisasContext *s)
assert(!s->fp_access_checked);
s->fp_access_checked = true;
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
- syn_fp_access_trap(1, 0xe, false, 0),
- s->fp_excp_el);
+ gen_a64_set_pc_im(s->pc_curr);
+ gen_exception_advsimdfp_access(s, syn_fp_access_trap(1, 0xe, false, 0));
return false;
}
s->fp_access_checked = true;
@@ -230,7 +230,9 @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa;
uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc);
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
+ gen_set_condexec(s);
+ gen_set_pc_im(s, s->pc_curr);
+ gen_exception_advsimdfp_access(s, syn);
return false;
}
Create helper_exception_advsimdfp_access to handle both the routing and the syndrome contents, depending on the eventual target EL and mode. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/arm/helper.h | 1 + target/arm/translate.h | 9 +++++++++ target/arm/op_helper.c | 32 +++++++++++++++++++++++--------- target/arm/translate-a64.c | 5 ++--- target/arm/translate-vfp.c | 4 +++- 5 files changed, 38 insertions(+), 13 deletions(-)