target/arm: Implement FMLALL (multiple and single vector)
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260618041517.573469-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Richard Henderson committed
Jun 17, 2026 at 21:15 UTC
0c728a8d1f352498e37ed0d5902d6f618ba1262a
2 files changed
+53
target/arm/tcg/sme.decode
+4
@@ -445,6 +445,10 @@ FMLS_n1_h 11000001 001 1 .... 0 .. 111 ..... 01 ... @azz_nx1_o3 n=4
445
FMLS_n1_s 11000001 001 1 .... 0 .. 110 ..... 01 ... @azz_nx1_o3 n=4
446
FMLS_n1_d 11000001 011 1 .... 0 .. 110 ..... 01 ... @azz_nx1_o3 n=4
447
448
+FMLALL_n1_b 11000001 001 1 .... 0 .. 001 ..... 000 .. @azz_nx1_o2x4 n=1
449
+FMLALL_n1_b 11000001 001 0 .... 0 .. 000 ..... 0001 . @azz_nx1_o1x4 n=2
450
+FMLALL_n1_b 11000001 001 1 .... 0 .. 000 ..... 0001 . @azz_nx1_o1x4 n=4
451
+
452
### SME2 Multi-vector Multiple Array Vectors
453
454
%zn_ax2 6:4 !function=times_2
target/arm/tcg/translate-sme.c
+49
@@ -1059,6 +1059,47 @@ static bool do_azz_acc_fp(DisasContext *s, int nreg, int nsel,
1059
return true;
1060
}
1061
1062
+static bool do_azz_acc_fp8(DisasContext *s, int nreg, int nsel,
1063
+ int rv, int off, int zn, int zm,
1064
+ int data, int shsel, bool multi,
1065
+ gen_helper_gvec_3_ptr *fn)
1066
+{
1067
+ /*
1068
+ * TODO: Could plausibly reuse do_azz_acc_fp, after the fpmr check,
1069
+ * but the fp8 helpers were written without a separate addend operand.
1070
+ */
1071
+ if (fpmr_access_check(s) && sme_smza_enabled_check(s)) {
1072
+ int svl = streaming_vec_reg_size(s);
1073
+ int vstride = svl / nreg;
1074
+ TCGv_ptr t_za = get_zarray(s, rv, off, nreg, nsel);
1075
+ TCGv_ptr t;
1076
+
1077
+ t = tcg_temp_new_ptr();
1078
+
1079
+ for (int r = 0; r < nreg; ++r) {
1080
+ TCGv_ptr t_zn = vec_full_reg_ptr(s, zn);
1081
+ TCGv_ptr t_zm = vec_full_reg_ptr(s, zm);
1082
+
1083
+ for (int i = 0; i < nsel; ++i) {
1084
+ int o_za = (r * vstride + i) * sizeof(ARMVectorReg);
1085
+ int desc = simd_desc(svl, svl, data | (i << shsel));
1086
+
1087
+ tcg_gen_addi_ptr(t, t_za, o_za);
1088
+ fn(t, t_zn, t_zm, tcg_env, tcg_constant_i32(desc));
1089
+ }
1090
+
1091
+ /*
1092
+ * For multiple-and-single vectors, Zn may wrap.
1093
+ * For multiple vectors, both Zn and Zm are aligned.
1094
+ */
1095
+ zn = (zn + 1) % 32;
1096
+ zm += multi;
1097
+ }
1098
+ }
1099
+ return true;
1100
+}
1101
+
1102
+
1103
static bool do_fmlal(DisasContext *s, arg_azz_n *a, bool sub, bool multi)
1104
{
1105
return do_azz_acc_fp(s, a->n, 2, a->rv, a->off, a->zn, a->zm,
@@ -1071,6 +1112,14 @@ TRANS_FEAT(FMLSL_n1, aa64_sme2, do_fmlal, a, true, false)
1112
TRANS_FEAT(FMLAL_nn, aa64_sme2, do_fmlal, a, false, true)
1113
TRANS_FEAT(FMLSL_nn, aa64_sme2, do_fmlal, a, true, true)
1114
1115
+static bool do_fmlall_fp8(DisasContext *s, arg_azz_n *a, bool multi)
1116
+{
1117
+ return do_azz_acc_fp8(s, a->n, 4, a->rv, a->off, a->zn, a->zm,
1118
+ 0, 0, multi, gen_helper_gvec_fmla_sb);
1119
+}
1120
+
1121
+TRANS_FEAT(FMLALL_n1_b, aa64_sme_f8f32, do_fmlall_fp8, a, false)
1122
+
1123
static bool do_fmlal_nx(DisasContext *s, arg_azx_n *a, bool sub)
1124
{
1125
return do_azz_acc_fp(s, a->n, 2, a->rv, a->off, a->zn, a->zm,