diff --git a/qemu/target/arm/translate-vfp.inc.c b/qemu/target/arm/translate-vfp.inc.c index c9a36c2e..4c25d172 100644 --- a/qemu/target/arm/translate-vfp.inc.c +++ b/qemu/target/arm/translate-vfp.inc.c @@ -83,6 +83,34 @@ static inline long vfp_f16_offset(unsigned reg, bool top) return offs; } +/* + * Generate code for M-profile lazy FP state preservation if needed; + * this corresponds to the pseudocode PreserveFPState() function. + */ +static void gen_preserve_fp_state(DisasContext *s) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + + if (s->v7m_lspact) { + /* + * Lazy state saving affects external memory and also the NVIC, + * so we must mark it as an IO operation for icount (and cause + * this to be the last insn in the TB). + */ + if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { + s->base.is_jmp = DISAS_UPDATE_EXIT; + gen_io_start(tcg_ctx); + } + gen_helper_v7m_preserve_fp_state(tcg_ctx, tcg_ctx->cpu_env); + /* + * If the preserve_fp_state helper doesn't throw an exception + * then it will clear LSPACT; we don't need to repeat this for + * any further FP insns in this TB. + */ + s->v7m_lspact = false; + } +} + /* * Check that VFP access is enabled. If it is, do the necessary * M-profile lazy-FP handling and then return true. @@ -115,24 +143,7 @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled) /* Handle M-profile lazy FP state mechanics */ /* Trigger lazy-state preservation if necessary */ - if (s->v7m_lspact) { - /* - * Lazy state saving affects external memory and also the NVIC, - * so we must mark it as an IO operation for icount (and cause - * this to be the last insn in the TB). - */ - if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { - s->base.is_jmp = DISAS_UPDATE_EXIT; - gen_io_start(tcg_ctx); - } - gen_helper_v7m_preserve_fp_state(tcg_ctx, tcg_ctx->cpu_env); - /* - * If the preserve_fp_state helper doesn't throw an exception - * then it will clear LSPACT; we don't need to repeat this for - * any further FP insns in this TB. - */ - s->v7m_lspact = false; - } + gen_preserve_fp_state(s); /* Update ownership of FP context: set FPCCR.S to match current state */ if (s->v8m_fpccr_s_wrong) {