@samitouri / QOSamiQemu / commits / dbbcf746c2

target/arm: Implement FEAT_FAMINMAX for AdvSIMD

Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260522220306.235200-3-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Richard Henderson committed May 22, 2026 at 15:02 UTC dbbcf746c2b080cc719cacba5a3785915950183f
6 files changed +76
target/arm/cpu-features.h
+5
@@ -1062,6 +1062,11 @@ static inline bool isar_feature_aa64_ats1a(const ARMISARegisters *id)
1062 return FIELD_EX64_IDREG(id, ID_AA64ISAR2, ATS1A);
1063 }
1064
1065 +static inline bool isar_feature_aa64_faminmax(const ARMISARegisters *id)
1066 +{
1067 + return FIELD_EX64_IDREG(id, ID_AA64ISAR3, FAMINMAX) != 0;
1068 +}
1069 +
1070 static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
1071 {
1072 /* We always set the AdvSIMD and FP fields identically. */
target/arm/tcg/a64.decode
+5
@@ -1193,6 +1193,11 @@ RSUBHN 0.10 1110 ..1 ..... 01100 0 ..... ..... @qrrr_e
1193 PMULL_p8 0.00 1110 001 ..... 11100 0 ..... ..... @qrrr_b
1194 PMULL_p64 0.00 1110 111 ..... 11100 0 ..... ..... @qrrr_b
1195
1196 +FAMAX 0.00 1110 110 ..... 00011 1 ..... ..... @qrrr_h
1197 +FAMAX 0.00 1110 1.1 ..... 11011 1 ..... ..... @qrrr_sd
1198 +FAMIN 0.10 1110 110 ..... 00011 1 ..... ..... @qrrr_h
1199 +FAMIN 0.10 1110 1.1 ..... 11011 1 ..... ..... @qrrr_sd
1200 +
1201 ### Advanced SIMD scalar x indexed element
1202
1203 FMUL_si 0101 1111 00 .. .... 1001 . 0 ..... ..... @rrx_h
target/arm/tcg/helper-a64-defs.h
+7
@@ -145,6 +145,13 @@ DEF_HELPER_FLAGS_5(gvec_fmulx_idx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst,
145 DEF_HELPER_FLAGS_5(gvec_fmulx_idx_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
146 DEF_HELPER_FLAGS_5(gvec_fmulx_idx_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
147
148 +DEF_HELPER_FLAGS_5(gvec_famax_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
149 +DEF_HELPER_FLAGS_5(gvec_famin_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
150 +DEF_HELPER_FLAGS_5(gvec_famax_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
151 +DEF_HELPER_FLAGS_5(gvec_famin_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
152 +DEF_HELPER_FLAGS_5(gvec_famax_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
153 +DEF_HELPER_FLAGS_5(gvec_famin_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
154 +
155 #ifndef CONFIG_USER_ONLY
156 DEF_HELPER_2(exception_return, void, env, i64)
157 #endif
target/arm/tcg/translate-a64.c
+14
@@ -6475,6 +6475,20 @@ static gen_helper_gvec_3_ptr * const f_vector_fminnmp[3] = {
6475 };
6476 TRANS(FMINNMP_v, do_fp3_vector, a, 0, f_vector_fminnmp)
6477
6478 +static gen_helper_gvec_3_ptr * const f_vector_famax[3] = {
6479 + gen_helper_gvec_famax_h,
6480 + gen_helper_gvec_famax_s,
6481 + gen_helper_gvec_famax_d,
6482 +};
6483 +TRANS_FEAT(FAMAX, aa64_faminmax, do_fp3_vector, a, 0, f_vector_famax)
6484 +
6485 +static gen_helper_gvec_3_ptr * const f_vector_famin[3] = {
6486 + gen_helper_gvec_famin_h,
6487 + gen_helper_gvec_famin_s,
6488 + gen_helper_gvec_famin_d,
6489 +};
6490 +TRANS_FEAT(FAMIN, aa64_faminmax, do_fp3_vector, a, 0, f_vector_famin)
6491 +
6492 static bool do_fmlal(DisasContext *s, arg_qrrr_e *a, bool is_s, bool is_2)
6493 {
6494 if (fp_access_check(s)) {
target/arm/tcg/vec_helper64.c
+38
@@ -8,6 +8,7 @@
8
9 #include "qemu/osdep.h"
10 #include "cpu.h"
11 +#include "internals.h"
12 #include "helper.h"
13 #include "helper-a64.h"
14 #include "helper-sme.h"
@@ -140,3 +141,40 @@ void HELPER(simd_tblx)(void *vd, void *vm, CPUARMState *env, uint32_t desc)
141 memcpy(vd, &result, 16);
142 clear_tail(vd, oprsz, simd_maxsz(desc));
143 }
144 +
145 +/*
146 + * Use float_minmax_ismag to get the absolute value min/max.
147 + * Avoid float_minmax_is{num,number} so that we get normal NaN processing.
148 + * If the result is not a nan, take the absolute value.
149 + *
150 + * Note this operation squashes FZ, FIZ, and AH to 0.
151 + */
152 +#define DO_FAMINMAX(NAME, TYPE, MIN) \
153 +TYPE TYPE##_##NAME(TYPE a, TYPE b, float_status *s) \
154 +{ \
155 + float_status local = *s; \
156 + set_flush_to_zero(false, &local); \
157 + set_flush_inputs_to_zero(false, &local); \
158 + arm_set_default_fp_behaviours(&local); \
159 + TYPE r = TYPE##_minmax(a, b, &local, MIN | float_minmax_ismag); \
160 + if (!TYPE##_is_any_nan(r)) { \
161 + r = TYPE##_abs(r); \
162 + } \
163 + float_raise(get_float_exception_flags(&local) \
164 + & ~float_flag_input_denormal_used, s); \
165 + return r; \
166 +}
167 +
168 +DO_FAMINMAX(famax, float16, 0)
169 +DO_FAMINMAX(famin, float16, float_minmax_ismin)
170 +DO_FAMINMAX(famax, float32, 0)
171 +DO_FAMINMAX(famin, float32, float_minmax_ismin)
172 +DO_FAMINMAX(famax, float64, 0)
173 +DO_FAMINMAX(famin, float64, float_minmax_ismin)
174 +
175 +DO_3OP(gvec_famax_h, float16_famax, float16)
176 +DO_3OP(gvec_famin_h, float16_famin, float16)
177 +DO_3OP(gvec_famax_s, float32_famax, float32)
178 +DO_3OP(gvec_famin_s, float32_famin, float32)
179 +DO_3OP(gvec_famax_d, float64_famax, float64)
180 +DO_3OP(gvec_famin_d, float64_famin, float64)
target/arm/tcg/vec_internal.h
+7
@@ -342,6 +342,13 @@ bfloat16 helper_sme2_ah_fmin_b16(bfloat16 a, bfloat16 b, float_status *fpst);
342 float32 sve_f16_to_f32(float16 f, float_status *fpst);
343 float16 sve_f32_to_f16(float32 f, float_status *fpst);
344
345 +float16 float16_famax(float16, float16, float_status *);
346 +float16 float16_famin(float16, float16, float_status *);
347 +float32 float32_famax(float32, float32, float_status *);
348 +float32 float32_famin(float32, float32, float_status *);
349 +float64 float64_famax(float64, float64, float_status *);
350 +float64 float64_famin(float64, float64, float_status *);
351 +
352 /*
353 * Decode helper functions for predicate as counter.
354 */