From 90257a4f35efef15380f45339fecc348e762acc6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 1 Sep 2021 09:02:36 +0100 Subject: target/arm: Implement MVE VMAXNMA and VMINNMA Implement the MVE VMAXNMA and VMINNMA insns; these are 2-operand, but the destination register must be the same as one of the source registers. We defer the decode of the size in bit 28 to the individual insn patterns rather than doing it in the format, because otherwise we would have a single insn pattern that overlapped with two groups (eg VMAXNMA with the VMULH_S and VMULH_U groups). Having two insn patterns per insn seems clearer than a complex multilevel nesting of overlapping and non-overlapping groups. Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell --- target/arm/helper-mve.h | 6 ++++++ target/arm/mve.decode | 11 +++++++++++ target/arm/mve_helper.c | 23 +++++++++++++++++++++++ target/arm/translate-mve.c | 2 ++ 4 files changed, 42 insertions(+) diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h index 7395040..57ab3f7 100644 --- a/target/arm/helper-mve.h +++ b/target/arm/helper-mve.h @@ -428,6 +428,12 @@ DEF_HELPER_FLAGS_4(mve_vmaxnms, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) DEF_HELPER_FLAGS_4(mve_vminnmh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) DEF_HELPER_FLAGS_4(mve_vminnms, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) +DEF_HELPER_FLAGS_4(mve_vmaxnmah, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) +DEF_HELPER_FLAGS_4(mve_vmaxnmas, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) + +DEF_HELPER_FLAGS_4(mve_vminnmah, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) +DEF_HELPER_FLAGS_4(mve_vminnmas, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) + DEF_HELPER_FLAGS_4(mve_vfcadd90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) DEF_HELPER_FLAGS_4(mve_vfcadd90s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr) diff --git a/target/arm/mve.decode b/target/arm/mve.decode index 403381e..b0622e1 100644 --- a/target/arm/mve.decode +++ b/target/arm/mve.decode @@ -130,6 +130,11 @@ @2op_fp_size_rev .... .... .... .... .... .... .... .... &2op \ qd=%qd qn=%qn qm=%qm size=%2op_fp_size_rev +# 2-operand, but Qd and Qn share a field. Size is in bit 28, but we +# don't decode it in this format +@vmaxnma .... .... .... .... .... .... .... .... &2op \ + qd=%qd qn=%qd qm=%qm + # Vector loads and stores # Widening loads and narrowing stores: @@ -199,6 +204,8 @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op # The VSHLL T2 encoding is not a @2op pattern, but is here because it # overlaps what would be size=0b11 VMULH/VRMULH { + VMAXNMA 111 0 1110 0 . 11 1111 ... 0 1110 1 0 . 0 ... 1 @vmaxnma size=2 + VSHLL_BS 111 0 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b VSHLL_BS 111 0 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_h @@ -211,6 +218,8 @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op } { + VMAXNMA 111 1 1110 0 . 11 1111 ... 0 1110 1 0 . 0 ... 1 @vmaxnma size=1 + VSHLL_BU 111 1 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b VSHLL_BU 111 1 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_h @@ -221,6 +230,7 @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op } { + VMINNMA 111 0 1110 0 . 11 1111 ... 1 1110 1 0 . 0 ... 1 @vmaxnma size=2 VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h @@ -233,6 +243,7 @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op } { + VMINNMA 111 1 1110 0 . 11 1111 ... 1 1110 1 0 . 0 ... 1 @vmaxnma size=1 VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c index e478408..a6ad894 100644 --- a/target/arm/mve_helper.c +++ b/target/arm/mve_helper.c @@ -2855,6 +2855,29 @@ DO_2OP_FP_ALL(vfabd, abd) DO_2OP_FP_ALL(vmaxnm, maxnum) DO_2OP_FP_ALL(vminnm, minnum) +static inline float16 float16_maxnuma(float16 a, float16 b, float_status *s) +{ + return float16_maxnum(float16_abs(a), float16_abs(b), s); +} + +static inline float32 float32_maxnuma(float32 a, float32 b, float_status *s) +{ + return float32_maxnum(float32_abs(a), float32_abs(b), s); +} + +static inline float16 float16_minnuma(float16 a, float16 b, float_status *s) +{ + return float16_minnum(float16_abs(a), float16_abs(b), s); +} + +static inline float32 float32_minnuma(float32 a, float32 b, float_status *s) +{ + return float32_minnum(float32_abs(a), float32_abs(b), s); +} + +DO_2OP_FP_ALL(vmaxnma, maxnuma) +DO_2OP_FP_ALL(vminnma, minnuma) + #define DO_VCADD_FP(OP, ESIZE, TYPE, FN0, FN1) \ void HELPER(glue(mve_, OP))(CPUARMState *env, \ void *vd, void *vn, void *vm) \ diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c index d62ed1f..4d702da 100644 --- a/target/arm/translate-mve.c +++ b/target/arm/translate-mve.c @@ -864,6 +864,8 @@ DO_2OP_FP(VCMLA0, vcmla0) DO_2OP_FP(VCMLA90, vcmla90) DO_2OP_FP(VCMLA180, vcmla180) DO_2OP_FP(VCMLA270, vcmla270) +DO_2OP_FP(VMAXNMA, vmaxnma) +DO_2OP_FP(VMINNMA, vminnma) static bool do_2op_scalar(DisasContext *s, arg_2scalar *a, MVEGenTwoOpScalarFn fn) -- cgit v1.1