diff options
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r-- | target/arm/translate.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c index ffaa4f1..f0332ac 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -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; |