mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 17:23:56 -06:00
target/arm: Implement MVE FP max/min across vector
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 <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
2c8cb5888e
commit
29f80e7d83
4 changed files with 102 additions and 6 deletions
|
@ -3112,3 +3112,47 @@ DO_2OP_FP_ACC_SCALAR(vfma_scalarh, 2, float16, float16_muladd)
|
|||
DO_2OP_FP_ACC_SCALAR(vfma_scalars, 4, float32, float32_muladd)
|
||||
DO_2OP_FP_ACC_SCALAR(vfmas_scalarh, 2, float16, DO_VFMAS_SCALARH)
|
||||
DO_2OP_FP_ACC_SCALAR(vfmas_scalars, 4, float32, DO_VFMAS_SCALARS)
|
||||
|
||||
/* Floating point max/min across vector. */
|
||||
#define DO_FP_VMAXMINV(OP, ESIZE, TYPE, 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; \
|
||||
TYPE ra = (TYPE)ra_in; \
|
||||
float_status *fpst = (ESIZE == 2) ? \
|
||||
&env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
|
||||
if (mask & 1) { \
|
||||
TYPE v = m[H##ESIZE(e)]; \
|
||||
if (TYPE##_is_signaling_nan(ra, fpst)) { \
|
||||
ra = TYPE##_silence_nan(ra, fpst); \
|
||||
float_raise(float_flag_invalid, fpst); \
|
||||
} \
|
||||
if (TYPE##_is_signaling_nan(v, fpst)) { \
|
||||
v = TYPE##_silence_nan(v, fpst); \
|
||||
float_raise(float_flag_invalid, fpst); \
|
||||
} \
|
||||
if (ABS) { \
|
||||
v = TYPE##_abs(v); \
|
||||
} \
|
||||
ra = FN(ra, v, fpst); \
|
||||
} \
|
||||
} \
|
||||
mve_advance_vpt(env); \
|
||||
return ra; \
|
||||
} \
|
||||
|
||||
#define NOP(X) (X)
|
||||
|
||||
DO_FP_VMAXMINV(vmaxnmvh, 2, float16, false, float16_maxnum)
|
||||
DO_FP_VMAXMINV(vmaxnmvs, 4, float32, false, float32_maxnum)
|
||||
DO_FP_VMAXMINV(vminnmvh, 2, float16, false, float16_minnum)
|
||||
DO_FP_VMAXMINV(vminnmvs, 4, float32, false, float32_minnum)
|
||||
DO_FP_VMAXMINV(vmaxnmavh, 2, float16, true, float16_maxnum)
|
||||
DO_FP_VMAXMINV(vmaxnmavs, 4, float32, true, float32_maxnum)
|
||||
DO_FP_VMAXMINV(vminnmavh, 2, float16, true, float16_minnum)
|
||||
DO_FP_VMAXMINV(vminnmavs, 4, float32, true, float32_minnum)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue