target/arm: Set FPCCR.S when executing M-profile floating point insns
The M-profile FPCCR.S bit indicates the security status of the floating point context. In the pseudocode ExecuteFPCheck() function it is unconditionally set to match the current security state whenever a floating point instruction is executed. Implement this by adding a new TB flag which tracks whether FPCCR.S is different from the current security state, so that we only need to emit the code to update it in the less-common case when it is not already set correctly. Note that we will add the handling for the other work done by ExecuteFPCheck() in later commits. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190416125744.27770-19-peter.maydell@linaro.org
This commit is contained in:
parent
ea7ac69d12
commit
6d60c67a1a
|
@ -3153,6 +3153,8 @@ FIELD(TBFLAG_A32, NS, 6, 1)
|
|||
FIELD(TBFLAG_A32, VFPEN, 7, 1)
|
||||
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
|
||||
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
|
||||
/* For M profile only, set if FPCCR.S does not match current security state */
|
||||
FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
|
||||
/* For M profile only, Handler (ie not Thread) mode */
|
||||
FIELD(TBFLAG_A32, HANDLER, 21, 1)
|
||||
/* For M profile only, whether we should generate stack-limit checks */
|
||||
|
|
|
@ -13417,6 +13417,11 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||
flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
|
||||
}
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
|
||||
FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
|
||||
}
|
||||
|
||||
*pflags = flags;
|
||||
*cs_base = 0;
|
||||
}
|
||||
|
|
|
@ -3421,6 +3421,25 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
|
|||
}
|
||||
}
|
||||
|
||||
if (arm_dc_feature(s, ARM_FEATURE_M)) {
|
||||
/* Handle M-profile lazy FP state mechanics */
|
||||
|
||||
/* Update ownership of FP context: set FPCCR.S to match current state */
|
||||
if (s->v8m_fpccr_s_wrong) {
|
||||
TCGv_i32 tmp;
|
||||
|
||||
tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
|
||||
if (s->v8m_secure) {
|
||||
tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
|
||||
} else {
|
||||
tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
|
||||
}
|
||||
store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
|
||||
/* Don't need to do this for any further FP insns in this TB */
|
||||
s->v8m_fpccr_s_wrong = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (extract32(insn, 28, 4) == 0xf) {
|
||||
/*
|
||||
* Encodings with T=1 (Thumb) or unconditional (ARM):
|
||||
|
@ -13341,6 +13360,7 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
|||
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
|
||||
regime_is_secure(env, dc->mmu_idx);
|
||||
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
|
||||
dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
|
||||
dc->cp_regs = cpu->cp_regs;
|
||||
dc->features = env->features;
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ typedef struct DisasContext {
|
|||
bool v7m_handler_mode;
|
||||
bool v8m_secure; /* true if v8M and we're in Secure mode */
|
||||
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
|
||||
bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
|
||||
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
|
||||
* so that top level loop can generate correct syndrome information.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue