mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-23 05:25:11 +00:00
target/arm: Activate M-profile floating point context when FPCCR.ASPEN is set
The M-profile FPCCR.ASPEN bit indicates that automatic floating-point context preservation is enabled. Before executing any floating-point instruction, if FPCCR.ASPEN is set and the CONTROL FPCA/SFPA bits indicate that there is no active floating point context then we must create a new context (by initializing FPSCR and setting FPCA/SFPA to indicate that the context is now active). In the pseudocode this is handled by ExecuteFPCheck(). Implement this with a new TB flag which tracks whether we need to create a new FP context. Backports commit 6000531e19964756673a5f4b694a649ef883605a from qemu
This commit is contained in:
parent
87c8c0fde7
commit
719231b4c0
|
@ -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 we must create a new FP context */
|
||||
FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 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 */
|
||||
|
|
|
@ -13218,6 +13218,19 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||
flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
|
||||
}
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M) &&
|
||||
(env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
|
||||
(!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
|
||||
(env->v7m.secure &&
|
||||
!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
|
||||
/*
|
||||
* ASPEN is set, but FPCA/SFPA indicate that there is no active
|
||||
* FP context; we must create a new FP context before executing
|
||||
* any FP insn.
|
||||
*/
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
|
||||
}
|
||||
|
||||
*pflags = flags;
|
||||
*cs_base = 0;
|
||||
}
|
||||
|
|
|
@ -3545,6 +3545,33 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
|
|||
/* Don't need to do this for any further FP insns in this TB */
|
||||
s->v8m_fpccr_s_wrong = false;
|
||||
}
|
||||
|
||||
if (s->v7m_new_fp_ctxt_needed) {
|
||||
/*
|
||||
* Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA
|
||||
* and the FPSCR.
|
||||
*/
|
||||
TCGv_i32 control, fpscr;
|
||||
uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
|
||||
|
||||
fpscr = load_cpu_field(s->uc, v7m.fpdscr[s->v8m_secure]);
|
||||
gen_helper_vfp_set_fpscr(tcg_ctx, tcg_ctx->cpu_env, fpscr);
|
||||
tcg_temp_free_i32(tcg_ctx, fpscr);
|
||||
/*
|
||||
* We don't need to arrange to end the TB, because the only
|
||||
* parts of FPSCR which we cache in the TB flags are the VECLEN
|
||||
* and VECSTRIDE, and those don't exist for M-profile.
|
||||
*/
|
||||
|
||||
if (s->v8m_secure) {
|
||||
bits |= R_V7M_CONTROL_SFPA_MASK;
|
||||
}
|
||||
control = load_cpu_field(s->uc, v7m.control[M_REG_S]);
|
||||
tcg_gen_ori_i32(tcg_ctx, control, control, bits);
|
||||
store_cpu_field(s, control, v7m.control[M_REG_S]);
|
||||
/* Don't need to do this for any further FP insns in this TB */
|
||||
s->v7m_new_fp_ctxt_needed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (extract32(insn, 28, 4) == 0xf) {
|
||||
|
|
|
@ -40,6 +40,7 @@ typedef struct DisasContext {
|
|||
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 */
|
||||
bool v7m_new_fp_ctxt_needed; /* ASPEN set but no active FP context */
|
||||
/* 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