gen_exception_internal(EXCP_EXCEPTION_EXIT);
}
- s->is_jmp = DISAS_EXIT;
+ static inline void gen_bxns(DisasContext *s, int rm)
+ {
+ TCGv_i32 var = load_reg(s, rm);
+
+ /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
+ * we need to sync state before calling it, but:
+ * - we don't need to do gen_set_pc_im() because the bxns helper will
+ * always set the PC itself
+ * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
+ * unless it's outside an IT block or the last insn in an IT block,
+ * so we know that condexec == 0 (already set at the top of the TB)
+ * is correct in the non-UNPREDICTABLE cases, and we can choose
+ * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
+ */
+ gen_helper_v7m_bxns(cpu_env, var);
+ tcg_temp_free_i32(var);
++ s->base.is_jmp = DISAS_EXIT;
+ }
+
/* Variant of store_reg which uses branch&exchange logic when storing
to r15 in ARM architecture v7 and above. The source must be a temporary
and will be marked as dead. */
#if !defined(CONFIG_USER_ONLY)
dc->user = (dc->current_el == 0);
#endif
- dc->ns = ARM_TBFLAG_NS(tb->flags);
- dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(tb->flags);
- dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
- dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
- dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
- dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
- dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(tb->flags);
+ dc->ns = ARM_TBFLAG_NS(dc->base.tb->flags);
+ dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
+ dc->vfp_enabled = ARM_TBFLAG_VFPEN(dc->base.tb->flags);
+ dc->vec_len = ARM_TBFLAG_VECLEN(dc->base.tb->flags);
+ dc->vec_stride = ARM_TBFLAG_VECSTRIDE(dc->base.tb->flags);
+ dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(dc->base.tb->flags);
+ dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(dc->base.tb->flags);
+ dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
+ regime_is_secure(env, dc->mmu_idx);
dc->cp_regs = cpu->cp_regs;
dc->features = env->features;