diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c index 0eca96e29c..77b9f0db33 100644 --- a/target/arm/translate-mve.c +++ b/target/arm/translate-mve.c @@ -64,6 +64,16 @@ static TCGv_ptr mve_qreg_ptr(unsigned reg) return ret; } +static bool mve_no_predication(DisasContext *s) +{ + /* + * Return true if we are executing the entire MVE instruction + * with no predication or partial-execution, and so we can safely + * use an inline TCG vector implementation. + */ + return s->eci == 0 && s->mve_no_pred; +} + static bool mve_check_qreg_bank(DisasContext *s, int qmask) { /* @@ -774,7 +784,8 @@ static bool trans_VNEG_fp(DisasContext *s, arg_1op *a) return do_1op(s, a, fns[a->size]); } -static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn) +static bool do_2op_vec(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn, + GVecGen3Fn *vecfn) { TCGv_ptr qd, qn, qm; @@ -787,28 +798,38 @@ static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn) return true; } - qd = mve_qreg_ptr(a->qd); - qn = mve_qreg_ptr(a->qn); - qm = mve_qreg_ptr(a->qm); - fn(cpu_env, qd, qn, qm); - tcg_temp_free_ptr(qd); - tcg_temp_free_ptr(qn); - tcg_temp_free_ptr(qm); + if (vecfn && mve_no_predication(s)) { + vecfn(a->size, mve_qreg_offset(a->qd), mve_qreg_offset(a->qn), + mve_qreg_offset(a->qm), 16, 16); + } else { + qd = mve_qreg_ptr(a->qd); + qn = mve_qreg_ptr(a->qn); + qm = mve_qreg_ptr(a->qm); + fn(cpu_env, qd, qn, qm); + tcg_temp_free_ptr(qd); + tcg_temp_free_ptr(qn); + tcg_temp_free_ptr(qm); + } mve_update_eci(s); return true; } -#define DO_LOGIC(INSN, HELPER) \ +static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn *fn) +{ + return do_2op_vec(s, a, fn, NULL); +} + +#define DO_LOGIC(INSN, HELPER, VECFN) \ static bool trans_##INSN(DisasContext *s, arg_2op *a) \ { \ - return do_2op(s, a, HELPER); \ + return do_2op_vec(s, a, HELPER, VECFN); \ } -DO_LOGIC(VAND, gen_helper_mve_vand) -DO_LOGIC(VBIC, gen_helper_mve_vbic) -DO_LOGIC(VORR, gen_helper_mve_vorr) -DO_LOGIC(VORN, gen_helper_mve_vorn) -DO_LOGIC(VEOR, gen_helper_mve_veor) +DO_LOGIC(VAND, gen_helper_mve_vand, tcg_gen_gvec_and) +DO_LOGIC(VBIC, gen_helper_mve_vbic, tcg_gen_gvec_andc) +DO_LOGIC(VORR, gen_helper_mve_vorr, tcg_gen_gvec_or) +DO_LOGIC(VORN, gen_helper_mve_vorn, tcg_gen_gvec_orc) +DO_LOGIC(VEOR, gen_helper_mve_veor, tcg_gen_gvec_xor) static bool trans_VPSEL(DisasContext *s, arg_2op *a) {