[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v4 14/40] target/arm: Recover 4 bits from TBFLAGs
From: |
Alex Bennée |
Subject: |
Re: [PATCH v4 14/40] target/arm: Recover 4 bits from TBFLAGs |
Date: |
Wed, 04 Dec 2019 11:43:30 +0000 |
User-agent: |
mu4e 1.3.5; emacs 27.0.50 |
Richard Henderson <address@hidden> writes:
> We had completely run out of TBFLAG bits.
> Split A- and M-profile bits into two overlapping buckets.
> This results in 4 free bits.
>
> Signed-off-by: Richard Henderson <address@hidden>
> ---
> target/arm/cpu.h | 52 ++++++++++++++++++++++++---------------
> target/arm/helper.c | 17 ++++++-------
> target/arm/translate.c | 56 +++++++++++++++++++++++-------------------
> 3 files changed, 70 insertions(+), 55 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 28259be733..ae9fc1ded3 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -3188,38 +3188,50 @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
> */
> FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 21, 2)
I'm not sure if this visual aid helps but here you go:
* 31 20 19 16 15 10 9 0
* +----------------------+--------+-------------+--------------+
* | | | TBFLAG_A64 |
* | | +--+-------------+--------------+
* | TBFLAG_ANY | | TBFLAG_A32 | |
* | | +-----+----------+ TBFLAG_AM32 |
* | | |TBFLAG_M32| |
* +----------------------+-----------+----------+--------------+
>
> -/* Bit usage when in AArch32 state: */
> -FIELD(TBFLAG_A32, THUMB, 0, 1) /* Not cached. */
> -FIELD(TBFLAG_A32, VECLEN, 1, 3) /* Not cached. */
> -FIELD(TBFLAG_A32, VECSTRIDE, 4, 2) /* Not cached. */
> +/*
> + * 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.
> * Not cached, because VECLEN+VECSTRIDE are not cached.
> */
> -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)
> /*
> * 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) /* Partially cached, minus FPEXC. */
> -FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */
> -FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
> -/* For M profile only, set if FPCCR.LSPACT is set */
> -FIELD(TBFLAG_A32, LSPACT, 18, 1) /* Not cached. */
> -/* For M profile only, set if we must create a new FP context */
> -FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1) /* Not cached. */
> -/* For M profile only, set if FPCCR.S does not match current security state
> */
> -FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1) /* Not cached. */
> -/* 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)
> +FIELD(TBFLAG_A32, NS, 16, 1)
>
> -/* Bit usage when in AArch64 state */
> +/*
> + * 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
> + */
> FIELD(TBFLAG_A64, TBII, 0, 2)
> FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2)
> FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 5172843667..ec5c7fa325 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -11207,11 +11207,8 @@ static uint32_t rebuild_hflags_m32(CPUARMState *env,
> int fp_el,
> {
> uint32_t flags = 0;
>
> - /* v8M always enables the fpu. */
> - flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
> -
> if (arm_v7m_is_handler_mode(env)) {
> - flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
> + flags = FIELD_DP32(flags, TBFLAG_M32, HANDLER, 1);
> }
>
> /*
> @@ -11222,7 +11219,7 @@ static uint32_t rebuild_hflags_m32(CPUARMState *env,
> int fp_el,
> if (arm_feature(env, ARM_FEATURE_V8) &&
> !((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);
> }
>
> return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
> @@ -11385,7 +11382,7 @@ void cpu_get_tb_cpu_state(CPUARMState *env,
> target_ulong *pc,
> 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 ((env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
> @@ -11397,12 +11394,12 @@ void cpu_get_tb_cpu_state(CPUARMState *env,
> target_ulong *pc,
> * 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);
> + flags = FIELD_DP32(flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED, 1);
> }
>
> 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);
> }
> } else {
> /*
> @@ -11423,8 +11420,8 @@ void cpu_get_tb_cpu_state(CPUARMState *env,
> target_ulong *pc,
> }
> }
>
> - flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
> - flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
> + flags = FIELD_DP32(flags, TBFLAG_AM32, THUMB, env->thumb);
> + flags = FIELD_DP32(flags, TBFLAG_AM32, CONDEXEC, env->condexec_bits);
> pstate_for_ss = env->uncached_cpsr;
> }
>
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 51ea99e6f9..cd757165e1 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -10841,37 +10841,46 @@ 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->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
> - condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
> + dc->thumb = FIELD_EX32(tb_flags, TBFLAG_AM32, THUMB);
> + 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->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;
>
> @@ -10893,9 +10902,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;
>
> @@ -11332,10 +11338,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 = { };
We seemed to have dropped an initialise here which seems unrelated.
Otherwise:
Reviewed-by: Alex Bennée <address@hidden>
> 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
--
Alex Bennée
- Re: [PATCH v4 09/40] target/arm: Rename ARMMMUIdx_S2NS to ARMMMUIdx_Stage2, (continued)
[PATCH v4 16/40] target/arm: Rearrange ARMMMUIdxBit, Richard Henderson, 2019/12/02
[PATCH v4 26/40] target/arm: Update define_one_arm_cp_reg_with_opaque for VHE, Richard Henderson, 2019/12/02