Re: [PATCH for-6.2 45/53] target/arm: Implement MVE FP max/min across vector

2021-07-30 Thread Richard Henderson

On 7/29/21 1:15 AM, Peter Maydell wrote:
  
  {

+  VMAXNMAV   1110 1110 1110  11 00    0 0 . 0 ... 0 @vmaxnmv size=2
+  VMINNMAV   1110 1110 1110  11 00    1 0 . 0 ... 0 @vmaxnmv size=2
+  VMAXNMV1110 1110 1110  11 10    0 0 . 0 ... 0 @vmaxnmv size=2
+  VMINNMV1110 1110 1110  11 10    1 0 . 0 ... 0 @vmaxnmv size=2
VMAXV_S1110 1110 1110  .. 10    0 0 . 0 ... 0 @vmaxv
VMINV_S1110 1110 1110  .. 10    1 0 . 0 ... 0 @vmaxv
VMAXAV 1110 1110 1110  .. 00    0 0 . 0 ... 0 @vmaxv


Looks like we could usefully have two [] blocks in here, for these 4 insns, and the 
previous 4 minmax.




+#define DO_FP_VMAXMINV(OP, ESIZE, TYPE, FTYPE, ABS, FN) \


Drop TYPE and just use FTYPE.

Otherwise,
Reviewed-by: Richard Henderson 


r~



[PATCH for-6.2 45/53] target/arm: Implement MVE FP max/min across vector

2021-07-29 Thread Peter Maydell
Implement the MVE VMAXNMV, VMINNMV, VMAXNMAV, VMINNMAV insns.  These
calculate the maximum or minimum of floating point elements across a
vector, starting with a value in a general purpose register and
returning the result there.

The pseudocode silences a possible SNaN in the accumulating result
on every iteration (by calling FPConvertNaN), but we do it only
on the input ra, because if none of the inputs to float*_maxnum
or float*_minnum are SNaNs then the result can't be an SNaN.

Note that we can't use the float*_maxnuma() etc functions we defined
earlier for VMAXNMA and VMINNMA, because we mustn't take the absolute
value of the starting general-purpose register value, which could be
negative.

Signed-off-by: Peter Maydell 
---
 target/arm/helper-mve.h| 12 +++
 target/arm/mve.decode  | 12 +++
 target/arm/mve_helper.c| 44 ++
 target/arm/translate-mve.c | 20 +
 4 files changed, 88 insertions(+)

diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
index cb7b6423239..47fd18dddbf 100644
--- a/target/arm/helper-mve.h
+++ b/target/arm/helper-mve.h
@@ -614,6 +614,18 @@ DEF_HELPER_FLAGS_3(mve_vminavb, TCG_CALL_NO_WG, i32, env, 
ptr, i32)
 DEF_HELPER_FLAGS_3(mve_vminavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
 DEF_HELPER_FLAGS_3(mve_vminavw, TCG_CALL_NO_WG, i32, env, ptr, i32)
 
+DEF_HELPER_FLAGS_3(mve_vmaxnmvh, TCG_CALL_NO_WG, i32, env, ptr, i32)
+DEF_HELPER_FLAGS_3(mve_vmaxnmvs, TCG_CALL_NO_WG, i32, env, ptr, i32)
+
+DEF_HELPER_FLAGS_3(mve_vminnmvh, TCG_CALL_NO_WG, i32, env, ptr, i32)
+DEF_HELPER_FLAGS_3(mve_vminnmvs, TCG_CALL_NO_WG, i32, env, ptr, i32)
+
+DEF_HELPER_FLAGS_3(mve_vmaxnmavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
+DEF_HELPER_FLAGS_3(mve_vmaxnmavs, TCG_CALL_NO_WG, i32, env, ptr, i32)
+
+DEF_HELPER_FLAGS_3(mve_vminnmavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
+DEF_HELPER_FLAGS_3(mve_vminnmavs, TCG_CALL_NO_WG, i32, env, ptr, i32)
+
 DEF_HELPER_FLAGS_3(mve_vaddlv_s, TCG_CALL_NO_WG, i64, env, ptr, i64)
 DEF_HELPER_FLAGS_3(mve_vaddlv_u, TCG_CALL_NO_WG, i64, env, ptr, i64)
 
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
index d2bd6815bc3..1a18c3b8eeb 100644
--- a/target/arm/mve.decode
+++ b/target/arm/mve.decode
@@ -137,6 +137,10 @@
 @vmaxnma          &2op \
   qd=%qd qn=%qd qm=%qm
 
+# Here also we don't decode the bit 28 size in the format to avoid
+# awkward nested overlap groups
+@vmaxnmv      rda:4    &vmaxv qm=%qm
+
 @2op_fp_scalar        rm:4 &2scalar \
qd=%qd qn=%qn size=%2op_fp_scalar_size
 
@@ -440,6 +444,10 @@ VMLADAV_S1110 1110   ... 0 ... .  . 0 . 0 
... 1 @vmladav_nosz
 VMLADAV_U 1110   ... 0 ... .  . 0 . 0 ... 1 @vmladav_nosz
 
 {
+  VMAXNMAV   1110 1110 1110  11 00    0 0 . 0 ... 0 @vmaxnmv size=2
+  VMINNMAV   1110 1110 1110  11 00    1 0 . 0 ... 0 @vmaxnmv size=2
+  VMAXNMV1110 1110 1110  11 10    0 0 . 0 ... 0 @vmaxnmv size=2
+  VMINNMV1110 1110 1110  11 10    1 0 . 0 ... 0 @vmaxnmv size=2
   VMAXV_S1110 1110 1110  .. 10    0 0 . 0 ... 0 @vmaxv
   VMINV_S1110 1110 1110  .. 10    1 0 . 0 ... 0 @vmaxv
   VMAXAV 1110 1110 1110  .. 00    0 0 . 0 ... 0 @vmaxv
@@ -449,6 +457,10 @@ VMLADAV_U 1110   ... 0 ... .  . 0 . 0 
... 1 @vmladav_nosz
 }
 
 {
+  VMAXNMAV    1110 1110  11 00    0 0 . 0 ... 0 @vmaxnmv size=1
+  VMINNMAV    1110 1110  11 00    1 0 . 0 ... 0 @vmaxnmv size=1
+  VMAXNMV 1110 1110  11 10    0 0 . 0 ... 0 @vmaxnmv size=1
+  VMINNMV 1110 1110  11 10    1 0 . 0 ... 0 @vmaxnmv size=1
   VMAXV_U 1110 1110  .. 10    0 0 . 0 ... 0 @vmaxv
   VMINV_U 1110 1110  .. 10    1 0 . 0 ... 0 @vmaxv
   VMLADAV_U   1110   ... 0 ... .  . 0 . 0 ... 0 @vmladav_nosz
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
index 3b243aaefa2..6a73134c74a 100644
--- a/target/arm/mve_helper.c
+++ b/target/arm/mve_helper.c
@@ -3117,3 +3117,47 @@ DO_2OP_FP_ACC_SCALAR(vfma_scalarh, 2, uint16_t, 
float16_muladd)
 DO_2OP_FP_ACC_SCALAR(vfma_scalars, 4, uint32_t, float32_muladd)
 DO_2OP_FP_ACC_SCALAR(vfmas_scalarh, 2, uint16_t, DO_VFMAS_SCALARH)
 DO_2OP_FP_ACC_SCALAR(vfmas_scalars, 4, uint32_t, DO_VFMAS_SCALARS)
+
+/* Floating point max/min across vector. */
+#define DO_FP_VMAXMINV(OP, ESIZE, TYPE, FTYPE, ABS, FN) \
+uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
+uint32_t ra_in) \
+{   \
+uint16_t mask = mve_element_mask(env);  \
+unsigned e; \
+TYPE *m = vm;