Implement the MVE VFMA and VFMS insns. Signed-off-by: Peter Maydell <peter.mayd...@linaro.org> --- target/arm/helper-mve.h | 6 ++++++ target/arm/mve.decode | 3 +++ target/arm/mve_helper.c | 36 ++++++++++++++++++++++++++++++++++++ target/arm/translate-mve.c | 2 ++ 4 files changed, 47 insertions(+)
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h index 42eba8ea96d..c230610d25c 100644 --- a/target/arm/helper-mve.h +++ b/target/arm/helper-mve.h @@ -434,6 +434,12 @@ DEF_HELPER_FLAGS_4(mve_vfcadd90s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) DEF_HELPER_FLAGS_4(mve_vfcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) DEF_HELPER_FLAGS_4(mve_vfcadd270s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) +DEF_HELPER_FLAGS_4(mve_vfmah, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) +DEF_HELPER_FLAGS_4(mve_vfmas, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) + +DEF_HELPER_FLAGS_4(mve_vfmsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) +DEF_HELPER_FLAGS_4(mve_vfmss, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) + DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) diff --git a/target/arm/mve.decode b/target/arm/mve.decode index c728c7089ac..3a2056f6b34 100644 --- a/target/arm/mve.decode +++ b/target/arm/mve.decode @@ -639,3 +639,6 @@ VMINNM 1111 1111 0 . 1 . ... 0 ... 0 1111 . 1 . 1 ... 0 @2op_fp VCADD90_fp 1111 1100 1 . 0 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev VCADD270_fp 1111 1101 1 . 0 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev + +VFMA 1110 1111 0 . 0 . ... 0 ... 0 1100 . 1 . 1 ... 0 @2op_fp +VFMS 1110 1111 0 . 1 . ... 0 ... 0 1100 . 1 . 1 ... 0 @2op_fp diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c index fd6ff167849..0146137d18f 100644 --- a/target/arm/mve_helper.c +++ b/target/arm/mve_helper.c @@ -2899,3 +2899,39 @@ DO_VCADD_FP(vfcadd90h, 2, uint16_t, float16_sub, float16_add) DO_VCADD_FP(vfcadd90s, 4, uint32_t, float32_sub, float32_add) DO_VCADD_FP(vfcadd270h, 2, uint16_t, float16_add, float16_sub) DO_VCADD_FP(vfcadd270s, 4, uint32_t, float32_add, float32_sub) + +#define DO_VFMA(OP, ESIZE, TYPE, FN) \ + void HELPER(glue(mve_, OP))(CPUARMState *env, \ + void *vd, void *vn, void *vm) \ + { \ + TYPE *d = vd, *n = vn, *m = vm; \ + TYPE r; \ + uint16_t mask = mve_element_mask(env); \ + unsigned e; \ + float_status *fpst; \ + float_status scratch_fpst; \ + for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \ + if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \ + continue; \ + } \ + fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \ + &env->vfp.standard_fp_status; \ + if (!(mask & 1)) { \ + /* We need the result but without updating flags */ \ + scratch_fpst = *fpst; \ + fpst = &scratch_fpst; \ + } \ + r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], d[H##ESIZE(e)], \ + 0, fpst); \ + mergemask(&d[H##ESIZE(e)], r, mask); \ + } \ + mve_advance_vpt(env); \ + } + +#define DO_VFMS16(N, M, D, F, S) float16_muladd(float16_chs(N), M, D, F, S) +#define DO_VFMS32(N, M, D, F, S) float32_muladd(float32_chs(N), M, D, F, S) + +DO_VFMA(vfmah, 2, uint16_t, float16_muladd) +DO_VFMA(vfmas, 4, uint32_t, float32_muladd) +DO_VFMA(vfmsh, 2, uint16_t, DO_VFMS16) +DO_VFMA(vfmss, 4, uint32_t, DO_VFMS32) diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c index 6203e3ff916..d61abc6d46f 100644 --- a/target/arm/translate-mve.c +++ b/target/arm/translate-mve.c @@ -854,6 +854,8 @@ DO_2OP_FP(VMAXNM, vmaxnm) DO_2OP_FP(VMINNM, vminnm) DO_2OP_FP(VCADD90_fp, vfcadd90) DO_2OP_FP(VCADD270_fp, vfcadd270) +DO_2OP_FP(VFMA, vfma) +DO_2OP_FP(VFMS, vfms) static bool do_2op_scalar(DisasContext *s, arg_2scalar *a, MVEGenTwoOpScalarFn fn) -- 2.20.1