@samitouri / QOSamiQemu / commits / 9972384eb3

target/arm: Implement FEAT_FAMINMAX for SVE

Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260522220306.235200-5-richard.henderson@linaro.org [PMM: add comments for TRANS_ macros] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Richard Henderson committed May 22, 2026 at 15:02 UTC 9972384eb3a7bd2dfed7e16d3d0caaecf2d80631
6 files changed +67
target/arm/cpu-features.h
+11
@@ -1568,6 +1568,11 @@ static inline bool isar_feature_aa64_sme_or_sve2(const ARMISARegisters *id)
1568 return isar_feature_aa64_sme(id) || isar_feature_aa64_sve2(id);
1569 }
1570
1571 +static inline bool isar_feature_aa64_sme2_or_sve2(const ARMISARegisters *id)
1572 +{
1573 + return isar_feature_aa64_sme2(id) || isar_feature_aa64_sve2(id);
1574 +}
1575 +
1576 static inline bool isar_feature_aa64_sme_or_sve2p1(const ARMISARegisters *id)
1577 {
1578 return isar_feature_aa64_sme(id) || isar_feature_aa64_sve2p1(id);
@@ -1608,6 +1613,12 @@ static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id)
1613 return isar_feature_aa64_sve(id) && isar_feature_aa64_sme_sve_bf16(id);
1614 }
1615
1616 +static inline bool
1617 +isar_feature_aa64_sme2_or_sve2_faminmax(const ARMISARegisters *id)
1618 +{
1619 + return isar_feature_aa64_sme2_or_sve2(id) && isar_feature_aa64_faminmax(id);
1620 +}
1621 +
1622 /*
1623 * Feature tests for "does this exist in either 32-bit or 64-bit?"
1624 */
target/arm/tcg/helper-sve-defs.h
+14
@@ -3180,3 +3180,17 @@ DEF_HELPER_FLAGS_5(sve2p1_st1ss_le_c, TCG_CALL_NO_WG, void, env, ptr, tl, i32, i
3180 DEF_HELPER_FLAGS_5(sve2p1_st1ss_be_c, TCG_CALL_NO_WG, void, env, ptr, tl, i32, i64)
3181 DEF_HELPER_FLAGS_5(sve2p1_st1dd_le_c, TCG_CALL_NO_WG, void, env, ptr, tl, i32, i64)
3182 DEF_HELPER_FLAGS_5(sve2p1_st1dd_be_c, TCG_CALL_NO_WG, void, env, ptr, tl, i32, i64)
3183 +
3184 +DEF_HELPER_FLAGS_6(sve2_famax_h, TCG_CALL_NO_RWG,
3185 + void, ptr, ptr, ptr, ptr, fpst, i32)
3186 +DEF_HELPER_FLAGS_6(sve2_famax_s, TCG_CALL_NO_RWG,
3187 + void, ptr, ptr, ptr, ptr, fpst, i32)
3188 +DEF_HELPER_FLAGS_6(sve2_famax_d, TCG_CALL_NO_RWG,
3189 + void, ptr, ptr, ptr, ptr, fpst, i32)
3190 +
3191 +DEF_HELPER_FLAGS_6(sve2_famin_h, TCG_CALL_NO_RWG,
3192 + void, ptr, ptr, ptr, ptr, fpst, i32)
3193 +DEF_HELPER_FLAGS_6(sve2_famin_s, TCG_CALL_NO_RWG,
3194 + void, ptr, ptr, ptr, ptr, fpst, i32)
3195 +DEF_HELPER_FLAGS_6(sve2_famin_d, TCG_CALL_NO_RWG,
3196 + void, ptr, ptr, ptr, ptr, fpst, i32)
target/arm/tcg/sve.decode
+2
@@ -1130,6 +1130,8 @@ FSCALE 01100101 .. 00 1001 100 ... ..... ..... @rdn_pg_rm
1130 FMULX 01100101 .. 00 1010 100 ... ..... ..... @rdn_pg_rm
1131 FDIV 01100101 .. 00 1100 100 ... ..... ..... @rdm_pg_rn # FDIVR
1132 FDIV 01100101 .. 00 1101 100 ... ..... ..... @rdn_pg_rm
1133 +FAMAX 01100101 .. 00 1110 100 ... ..... ..... @rdn_pg_rm
1134 +FAMIN 01100101 .. 00 1111 100 ... ..... ..... @rdn_pg_rm
1135
1136 # SVE floating-point arithmetic with immediate (predicated)
1137 FADD_zpzi 01100101 .. 011 000 100 ... 0000 . ..... @rdn_i1
target/arm/tcg/sve_helper.c
+8
@@ -4750,6 +4750,14 @@ DO_ZPZZ_FP(sve_fmulx_h, uint16_t, H1_2, helper_advsimd_mulxh)
4750 DO_ZPZZ_FP(sve_fmulx_s, uint32_t, H1_4, helper_vfp_mulxs)
4751 DO_ZPZZ_FP(sve_fmulx_d, uint64_t, H1_8, helper_vfp_mulxd)
4752
4753 +DO_ZPZZ_FP(sve2_famax_h, uint16_t, H1_2, float16_famax)
4754 +DO_ZPZZ_FP(sve2_famax_s, uint32_t, H1_4, float32_famax)
4755 +DO_ZPZZ_FP(sve2_famax_d, uint64_t, H1_8, float64_famax)
4756 +
4757 +DO_ZPZZ_FP(sve2_famin_h, uint16_t, H1_2, float16_famin)
4758 +DO_ZPZZ_FP(sve2_famin_s, uint32_t, H1_4, float32_famin)
4759 +DO_ZPZZ_FP(sve2_famin_d, uint64_t, H1_8, float64_famin)
4760 +
4761 #undef DO_ZPZZ_FP
4762
4763 /* Three-operand expander, with one scalar operand, controlled by
target/arm/tcg/translate-sve.c
+20
@@ -4254,6 +4254,26 @@ DO_ZPZZ_FP(FSCALE, aa64_sme_or_sve, sve_fscalbn)
4254 DO_ZPZZ_FP(FDIV, aa64_sme_or_sve, sve_fdiv)
4255 DO_ZPZZ_FP(FMULX, aa64_sme_or_sve, sve_fmulx)
4256
4257 +static gen_helper_gvec_4_ptr * const sve2_famax_zpzz_fns[4] = {
4258 + NULL,
4259 + gen_helper_sve2_famax_h,
4260 + gen_helper_sve2_famax_s,
4261 + gen_helper_sve2_famax_d
4262 +};
4263 +TRANS_FEAT_STREAMING_SME2(FAMAX, aa64_sme2_or_sve2_faminmax,
4264 + gen_gvec_fpst_arg_zpzz,
4265 + sve2_famax_zpzz_fns[a->esz], a)
4266 +
4267 +static gen_helper_gvec_4_ptr * const sve2_famin_zpzz_fns[4] = {
4268 + NULL,
4269 + gen_helper_sve2_famin_h,
4270 + gen_helper_sve2_famin_s,
4271 + gen_helper_sve2_famin_d
4272 +};
4273 +TRANS_FEAT_STREAMING_SME2(FAMIN, aa64_sme2_or_sve2_faminmax,
4274 + gen_gvec_fpst_arg_zpzz,
4275 + sve2_famin_zpzz_fns[a->esz], a)
4276 +
4277 typedef void gen_helper_sve_fp2scalar(TCGv_ptr, TCGv_ptr, TCGv_ptr,
4278 TCGv_i64, TCGv_ptr, TCGv_i32);
4279
target/arm/tcg/translate.h
+12
@@ -865,6 +865,7 @@ static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst)
865 static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
866 { return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); }
867
868 +/* For SVE insns which are not valid in Streaming SVE mode */
869 #define TRANS_FEAT_NONSTREAMING(NAME, FEAT, FUNC, ...) \
870 static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
871 { \
@@ -872,4 +873,15 @@ static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst)
873 return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); \
874 }
875
876 +/*
877 + * For SVE insns which are only valid in Streaming SVE mode when
878 + * SME2 is implemented
879 + */
880 +#define TRANS_FEAT_STREAMING_SME2(NAME, FEAT, FUNC, ...) \
881 + static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
882 + { \
883 + s->is_nonstreaming = !dc_isar_feature(aa64_sme2, s); \
884 + return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); \
885 + }
886 +
887 #endif /* TARGET_ARM_TRANSLATE_H */