target/arm: Implement FMOP4 (widening, 4-way fp8 to fp32)
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260702204314.79224-8-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Richard Henderson committed
Jul 2, 2026 at 13:43 UTC
aa3a898dce7947ef938c1953d9c6186ad7d6abe9
5 files changed
+46
target/arm/cpu-features.h
+5
@@ -1822,6 +1822,11 @@ static inline bool isar_feature_aa64_sme_mop4_f64f64(const ARMISARegisters *id)
1822
return isar_feature_aa64_sme_mop4(id) && isar_feature_aa64_sme_f64f64(id);
1823
}
1824
1825
+static inline bool isar_feature_aa64_sme_mop4_f8f32(const ARMISARegisters *id)
1826
+{
1827
+ return isar_feature_aa64_sme_mop4(id) && isar_feature_aa64_sme_f8f32(id);
1828
+}
1829
+
1830
/*
1831
* Feature tests for "does this exist in either 32-bit or 64-bit?"
1832
*/
target/arm/tcg/fp8_helper.c
+16
@@ -973,3 +973,19 @@ void HELPER(sme_fvdot_idx_hb)(void *vd, void *vn, void *vm,
973
} while (++i & 7);
974
} while (i < elements);
975
}
976
+
977
+static void inner_fmop4a_sb(void *vd, void *vn, void *vm, void *vinfo)
978
+{
979
+ float32 *d = vd;
980
+ uint32_t *n = vn, *m = vm;
981
+ FP8MulContext *ctx = vinfo;
982
+
983
+ *d = f8dotadd_s(*n, *m, 4, *d, ctx);
984
+}
985
+
986
+void HELPER(sme_fmop4a_sb)(void *vza, void *vzn, void *vzm,
987
+ CPUArchState *env, uint32_t desc)
988
+{
989
+ FP8MulContext ctx = fp8_mul_start(env, -1);
990
+ sme_mop4(vza, vzn, vzm, &ctx, desc, sizeof(float32), inner_fmop4a_sb);
991
+}
target/arm/tcg/helper-fp8-defs.h
+2
@@ -44,3 +44,5 @@ DEF_HELPER_FLAGS_7(sme_fmopa_hb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, ptr,
44
45
DEF_HELPER_FLAGS_5(sme_fvdot_idx_sb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
46
DEF_HELPER_FLAGS_5(sme_fvdot_idx_hb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
47
+
48
+DEF_HELPER_FLAGS_5(sme_fmop4a_sb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
target/arm/tcg/sme.decode
+5
@@ -1101,6 +1101,9 @@ LUTI4_s_4b 1100 0000 1001 101 1 00 00 00 ....0 zd:5 \
1101
@mop4_o3 .... .... ... m:1 .... .... .. n:1 ... . s:1 . zad:3 \
1102
&mop4 zm=%mop4_zm zn=%mop4_zn
1103
1104
+@mop4_o2_s0 .... .... ... m:1 .... .... .. n:1 ... . ... zad:2 \
1105
+ &mop4 zm=%mop4_zm zn=%mop4_zn s=0
1106
+
1107
BFMOP4_hh 1000 0001 001. ...0 0000 00.. ..0. 100. @mop4_o1
1108
FMOP4_hh 1000 0001 000. ...0 0000 00.. ..0. 100. @mop4_o1
1109
FMOP4_ss 1000 0000 000. ...0 0000 00.. ..0. 00.. @mop4_o2
@@ -1108,3 +1111,5 @@ FMOP4_dd 1000 0000 110. ...0 0000 00.. ..0. 1... @mop4_o3
1111
1112
BFMOP4_sh 1000 0001 000. ...0 0000 00.. ..0. 00.. @mop4_o2
1113
FMOP4_sh 1000 0001 001. ...0 0000 00.. ..0. 00.. @mop4_o2
1114
+
1115
+FMOP4A_sb 1000 0000 001. ...0 0000 00.. ..00 00.. @mop4_o2_s0
target/arm/tcg/translate-sme.c
+18
@@ -2072,3 +2072,21 @@ static gen_helper_gvec_3_ptr * const fmop4_sh[3] = {
2072
gen_helper_sme_ah_fmop4s_sh
2073
};
2074
TRANS_FEAT(FMOP4_sh, aa64_sme_mop4, do_mop4_fp, a, MO_32, FPST_ENV, fmop4_sh)
2075
+
2076
+static bool do_mop4_fp8(DisasContext *s, arg_mop4 *a, MemOp esz,
2077
+ gen_helper_gvec_3_ptr *fn)
2078
+{
2079
+ if (fpmr_access_check(s) && sme_smza_enabled_check(s)) {
2080
+ int svl = streaming_vec_reg_size(s);
2081
+ uint32_t desc = simd_desc(svl, svl, (a->m << 1) | a->n);
2082
+ TCGv_ptr za = get_tile(s, esz, a->zad);
2083
+ TCGv_ptr zn = vec_full_reg_ptr(s, a->zn);
2084
+ TCGv_ptr zm = vec_full_reg_ptr(s, a->zm);
2085
+
2086
+ fn(za, zn, zm, tcg_env, tcg_constant_i32(desc));
2087
+ }
2088
+ return true;
2089
+}
2090
+
2091
+TRANS_FEAT(FMOP4A_sb, aa64_sme_mop4_f8f32,
2092
+ do_mop4_fp8, a, MO_32, gen_helper_sme_fmop4a_sb)