mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-02 09:51:07 +00:00
target/arm: Recover 4 bits from TBFLAGs
We had completely run out of TBFLAG bits. Split A- and M-profile bits into two overlapping buckets. This results in 4 free bits. We used to initialize all of the a32 and m32 fields in DisasContext by assignment, in arm_tr_init_disas_context. Now we only initialize either the a32 or m32 by assignment, because the bits overlap in tbflags. So zero the entire structure in gen_intermediate_code. Backports commit 79cabf1f473ca6e9fa0727f64ed9c2a84a36f0aa from qemu
This commit is contained in:
parent
153d7aadd5
commit
be3c71fb8b
|
@ -3096,6 +3096,17 @@ typedef ARMCPU ArchCPU;
|
|||
* in 32 or 64 bit mode. The meaning of the other bits depends on that.
|
||||
* We put flags which are shared between 32 and 64 bit mode at the top
|
||||
* of the word, and flags which apply to only one mode at the bottom.
|
||||
*
|
||||
* 31 21 18 14 9 0
|
||||
* +--------------+-----+-----+----------+--------------+
|
||||
* | | | TBFLAG_A32 | |
|
||||
* | | +-----+----------+ TBFLAG_AM32 |
|
||||
* | TBFLAG_ANY | |TBFLAG_M32| |
|
||||
* | | +-------------------------|
|
||||
* | | | TBFLAG_A64 |
|
||||
* +--------------+-----------+-------------------------+
|
||||
* 31 21 14 0
|
||||
*
|
||||
*/
|
||||
FIELD(TBFLAG_ANY, AARCH64_STATE, 31, 1)
|
||||
FIELD(TBFLAG_ANY, MMUIDX, 28, 3)
|
||||
|
@ -3104,45 +3115,53 @@ FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1)
|
|||
/* Target EL if we take a floating-point-disabled exception */
|
||||
FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2)
|
||||
FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
|
||||
/*
|
||||
* For A-profile only, target EL for debug exceptions.
|
||||
* Note that this overlaps with the M-profile-only HANDLER and STACKCHECK bits.
|
||||
*/
|
||||
/* For A-profile only, target EL for debug exceptions. */
|
||||
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 21, 2)
|
||||
|
||||
/* Bit usage when in AArch32 state: */
|
||||
FIELD(TBFLAG_A32, THUMB, 0, 1)
|
||||
FIELD(TBFLAG_A32, VECLEN, 1, 3)
|
||||
FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
|
||||
/*
|
||||
* Bit usage when in AArch32 state, both A- and M-profile.
|
||||
*/
|
||||
FIELD(TBFLAG_AM32, CONDEXEC, 0, 8) /* Not cached. */
|
||||
FIELD(TBFLAG_AM32, THUMB, 8, 1) /* Not cached. */
|
||||
/*
|
||||
* Bit usage when in AArch32 state, for A-profile only.
|
||||
*/
|
||||
FIELD(TBFLAG_A32, VECLEN, 9, 3) /* Not cached. */
|
||||
FIELD(TBFLAG_A32, VECSTRIDE, 12, 2) /* Not cached. */
|
||||
|
||||
/*
|
||||
* We store the bottom two bits of the CPAR as TB flags and handle
|
||||
* checks on the other bits at runtime. This shares the same bits as
|
||||
* VECSTRIDE, which is OK as no XScale CPU has VFP.
|
||||
*/
|
||||
FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
|
||||
FIELD(TBFLAG_A32, XSCALE_CPAR, 12, 2)
|
||||
FIELD(TBFLAG_A32, VFPEN, 14, 1) /* Partially cached, minus FPEXC. */
|
||||
FIELD(TBFLAG_A32, SCTLR_B, 15, 1)
|
||||
FIELD(TBFLAG_A32, HSTR_ACTIVE, 16, 1)
|
||||
/*
|
||||
* Indicates whether cp register reads and writes by guest code should access
|
||||
* the secure or nonsecure bank of banked registers; note that this is not
|
||||
* the same thing as the current security state of the processor!
|
||||
*/
|
||||
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)
|
||||
FIELD(TBFLAG_A32, HSTR_ACTIVE, 17, 1)
|
||||
FIELD(TBFLAG_A32, NS, 17, 1)
|
||||
|
||||
/* For M profile only, set if FPCCR.LSPACT is set */
|
||||
FIELD(TBFLAG_A32, LSPACT, 18, 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 */
|
||||
FIELD(TBFLAG_A32, HANDLER, 21, 1)
|
||||
/* For M profile only, whether we should generate stack-limit checks */
|
||||
FIELD(TBFLAG_A32, STACKCHECK, 22, 1)
|
||||
/*
|
||||
* Bit usage when in AArch32 state, for M-profile only.
|
||||
*/
|
||||
/* Handler (ie not Thread) mode */
|
||||
FIELD(TBFLAG_M32, HANDLER, 9, 1)
|
||||
/* Whether we should generate stack-limit checks */
|
||||
FIELD(TBFLAG_M32, STACKCHECK, 10, 1)
|
||||
/* Set if FPCCR.LSPACT is set */
|
||||
FIELD(TBFLAG_M32, LSPACT, 11, 1) /* Not cached. */
|
||||
/* Set if we must create a new FP context */
|
||||
FIELD(TBFLAG_M32, NEW_FP_CTXT_NEEDED, 12, 1) /* Not cached. */
|
||||
/* Set if FPCCR.S does not match current security state */
|
||||
FIELD(TBFLAG_M32, FPCCR_S_WRONG, 13, 1) /* Not cached. */
|
||||
|
||||
/* Bit usage when in AArch64 state */
|
||||
/*
|
||||
* Bit usage when in AArch64 state
|
||||
*/
|
||||
FIELD(TBFLAG_A64, TBII, 0, 2)
|
||||
FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2)
|
||||
FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
|
||||
|
|
|
@ -11263,10 +11263,10 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||
}
|
||||
} else {
|
||||
*pc = env->regs[15];
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
|
||||
flags = FIELD_DP32(flags, TBFLAG_AM32, THUMB, env->thumb);
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len);
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride);
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
|
||||
flags = FIELD_DP32(flags, TBFLAG_AM32, CONDEXEC, env->condexec_bits);
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
|
||||
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
|
||||
|
@ -11314,7 +11314,7 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||
flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el);
|
||||
|
||||
if (arm_v7m_is_handler_mode(env)) {
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
|
||||
flags = FIELD_DP32(flags, TBFLAG_M32, HANDLER, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -11325,12 +11325,12 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||
arm_feature(env, ARM_FEATURE_M) &&
|
||||
!((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
|
||||
(env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
|
||||
flags = FIELD_DP32(flags, TBFLAG_M32, 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);
|
||||
flags = FIELD_DP32(flags, TBFLAG_M32, FPCCR_S_WRONG, 1);
|
||||
}
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M) &&
|
||||
|
@ -11343,14 +11343,14 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||
* 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);
|
||||
flags = FIELD_DP32(flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED, 1);
|
||||
}
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
|
||||
|
||||
if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
|
||||
flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
|
||||
flags = FIELD_DP32(flags, TBFLAG_M32, LSPACT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11160,38 +11160,48 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
|||
*/
|
||||
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
|
||||
!arm_el_is_aa64(env, 3);
|
||||
dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
|
||||
dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
|
||||
dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
|
||||
dc->thumb = FIELD_EX32(tb_flags, TBFLAG_AM32, THUMB);
|
||||
dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
|
||||
condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
|
||||
condexec = FIELD_EX32(tb_flags, TBFLAG_AM32, CONDEXEC);
|
||||
dc->condexec_mask = (condexec & 0xf) << 1;
|
||||
dc->condexec_cond = condexec >> 4;
|
||||
|
||||
core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
|
||||
dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
|
||||
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
dc->user = (dc->current_el == 0);
|
||||
#endif
|
||||
dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
|
||||
dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
|
||||
dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
|
||||
dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
|
||||
if (arm_feature(env, ARM_FEATURE_XSCALE)) {
|
||||
dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
|
||||
dc->vec_stride = 0;
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
dc->vfp_enabled = 1;
|
||||
dc->be_data = MO_TE;
|
||||
dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_M32, HANDLER);
|
||||
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_M32, STACKCHECK);
|
||||
dc->v8m_fpccr_s_wrong =
|
||||
FIELD_EX32(tb_flags, TBFLAG_M32, FPCCR_S_WRONG);
|
||||
dc->v7m_new_fp_ctxt_needed =
|
||||
FIELD_EX32(tb_flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED);
|
||||
dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_M32, LSPACT);
|
||||
} else {
|
||||
dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
|
||||
dc->c15_cpar = 0;
|
||||
dc->be_data =
|
||||
FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
|
||||
dc->debug_target_el =
|
||||
FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
|
||||
dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
|
||||
dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
|
||||
dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
|
||||
dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
|
||||
if (arm_feature(env, ARM_FEATURE_XSCALE)) {
|
||||
dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
|
||||
} else {
|
||||
dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
|
||||
dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
|
||||
}
|
||||
}
|
||||
dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
|
||||
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->v7m_new_fp_ctxt_needed =
|
||||
FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
|
||||
dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
|
||||
dc->cp_regs = cpu->cp_regs;
|
||||
dc->features = env->features;
|
||||
|
||||
|
@ -11213,9 +11223,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
|||
dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
|
||||
dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
|
||||
dc->is_ldex = false;
|
||||
if (!arm_feature(env, ARM_FEATURE_M)) {
|
||||
dc->debug_target_el = FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
|
||||
}
|
||||
|
||||
dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
|
||||
|
||||
|
@ -11676,10 +11683,10 @@ static const TranslatorOps thumb_translator_ops = {
|
|||
/* generate intermediate code for basic block 'tb'. */
|
||||
void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
|
||||
{
|
||||
DisasContext dc;
|
||||
DisasContext dc = {};
|
||||
const TranslatorOps *ops = &arm_translator_ops;
|
||||
|
||||
if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
|
||||
if (FIELD_EX32(tb->flags, TBFLAG_AM32, THUMB)) {
|
||||
ops = &thumb_translator_ops;
|
||||
}
|
||||
#ifdef TARGET_AARCH64
|
||||
|
|
Loading…
Reference in a new issue