mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 13:15:31 +00:00
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. Backports commit 6d60c67a1a03be32c3342aff6604cdc5095088d1 from qemu
This commit is contained in:
parent
8d726490ff
commit
87c8c0fde7
|
@ -3110,6 +3110,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 */
|
||||
|
|
|
@ -13213,6 +13213,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;
|
||||
}
|
||||
|
|
|
@ -3528,6 +3528,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(s->uc, v7m.fpccr[M_REG_S]);
|
||||
if (s->v8m_secure) {
|
||||
tcg_gen_ori_i32(tcg_ctx, tmp, tmp, R_V7M_FPCCR_S_MASK);
|
||||
} else {
|
||||
tcg_gen_andi_i32(tcg_ctx, tmp, tmp, ~R_V7M_FPCCR_S_MASK);
|
||||
}
|
||||
store_cpu_field(s, 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):
|
||||
|
@ -13520,6 +13539,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;
|
||||
|
||||
|
|
|
@ -39,6 +39,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