summaryrefslogtreecommitdiffstats
path: root/target/arm/translate.c
diff options
context:
space:
mode:
authorPeter Maydell2021-09-13 11:54:31 +0200
committerPeter Maydell2021-09-21 17:28:27 +0200
commit267022139753777bffaf3181fba1da679234d5d3 (patch)
tree38394d6eaed6c9d48147bd732b963afcc64115e5 /target/arm/translate.c
parenttarget/arm: Enforce that FPDSCR.LTPSIZE is 4 on inbound migration (diff)
downloadqemu-267022139753777bffaf3181fba1da679234d5d3.tar.gz
qemu-267022139753777bffaf3181fba1da679234d5d3.tar.xz
qemu-267022139753777bffaf3181fba1da679234d5d3.zip
target/arm: Add TB flag for "MVE insns not predicated"
Our current codegen for MVE always calls out to helper functions, because some byte lanes might be predicated. The common case is that in fact there is no predication active and all lanes should be updated together, so we can produce better code by detecting that and using the TCG generic vector infrastructure. Add a TB flag that is set when we can guarantee that there is no active MVE predication, and a bool in the DisasContext. Subsequent patches will use this flag to generate improved code for some instructions. In most cases when the predication state changes we simply end the TB after that instruction. For the code called from vfp_access_check() that handles lazy state preservation and creating a new FP context, we can usually avoid having to try to end the TB because luckily the new value of the flag following the register changes in those sequences doesn't depend on any runtime decisions. We do have to end the TB if the guest has enabled lazy FP state preservation but not automatic state preservation, but this is an odd corner case that is not going to be common in real-world code. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210913095440.13462-4-peter.maydell@linaro.org
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r--target/arm/translate.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c
index cf31e0237d..f7086c66a5 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8496,6 +8496,7 @@ static bool trans_DLS(DisasContext *s, arg_DLS *a)
/* DLSTP: set FPSCR.LTPSIZE */
tmp = tcg_const_i32(a->size);
store_cpu_field(tmp, v7m.ltpsize);
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
}
return true;
}
@@ -8561,6 +8562,10 @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
assert(ok);
tmp = tcg_const_i32(a->size);
store_cpu_field(tmp, v7m.ltpsize);
+ /*
+ * LTPSIZE updated, but MVE_NO_PRED will always be the same thing (0)
+ * when we take this upcoming exit from this TB, so gen_jmp_tb() is OK.
+ */
}
gen_jmp_tb(s, s->base.pc_next, 1);
@@ -8743,6 +8748,8 @@ static bool trans_VCTP(DisasContext *s, arg_VCTP *a)
gen_helper_mve_vctp(cpu_env, masklen);
tcg_temp_free_i32(masklen);
tcg_temp_free_i32(rn_shifted);
+ /* This insn updates predication bits */
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
mve_update_eci(s);
return true;
}
@@ -9413,6 +9420,7 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
dc->v7m_new_fp_ctxt_needed =
EX_TBFLAG_M32(tb_flags, NEW_FP_CTXT_NEEDED);
dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT);
+ dc->mve_no_pred = EX_TBFLAG_M32(tb_flags, MVE_NO_PRED);
} else {
dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B);