target/arm: Implement FTMOPA (widening, 4-way, FP8 to FP32)
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260713230244.70174-8-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Richard Henderson committed
Aug 11, 2026 at 20:14 UTC
1c7b4f9db3ed05a09431e3e1363b4af47c28df2b
7 files changed
+67
target/arm/cpu-features.h
+5
@@ -1857,6 +1857,11 @@ static inline bool isar_feature_aa64_sme_tmop_f8f16(const ARMISARegisters *id)
1857
return isar_feature_aa64_sme_tmop(id) && isar_feature_aa64_sme_f8f16(id);
1858
}
1859
1860
+static inline bool isar_feature_aa64_sme_tmop_f8f32(const ARMISARegisters *id)
1861
+{
1862
+ return isar_feature_aa64_sme_tmop(id) && isar_feature_aa64_sme_f8f32(id);
1863
+}
1864
+
1865
/*
1866
* Feature tests for "does this exist in either 32-bit or 64-bit?"
1867
*/
target/arm/tcg/fp8_helper.c
+7
@@ -1048,3 +1048,10 @@ void HELPER(sme_ftmopa_hb)(void *vza, void *vzn, void *vzm, void *vzk,
1048
}
1049
}
1050
}
1051
+
1052
+void HELPER(sme_ftmopa_sb)(void *vza, void *vzn, void *vzm, void *vzk,
1053
+ CPUArchState *env, uint32_t desc)
1054
+{
1055
+ FP8MulContext ctx = fp8_mul_start(env, 0xf);
1056
+ sme_tmop_4way_sb(vza, vzn, vzm, vzk, &ctx, desc, inner_fmop4a_sb);
1057
+}
target/arm/tcg/helper-fp8-defs.h
+1
@@ -49,3 +49,4 @@ DEF_HELPER_FLAGS_5(sme_fmop4a_sb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32
49
DEF_HELPER_FLAGS_5(sme_fmop4a_hb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
50
51
DEF_HELPER_FLAGS_6(sme_ftmopa_hb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
52
+DEF_HELPER_FLAGS_6(sme_ftmopa_sb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
target/arm/tcg/sme.decode
+1
@@ -1150,3 +1150,4 @@ BFTMOPA_sh 1000 0001 010 ..... 000 ... .... .. 00 .. @tmop_o2
1150
FTMOPA_sh 1000 0001 011 ..... 000 ... .... .. 00 .. @tmop_o2
1151
1152
FTMOPA_hb 1000 0000 011 ..... 000 ... .... .. 100 . @tmop_o1
1153
+FTMOPA_sb 1000 0000 011 ..... 000 ... .... .. 00 .. @tmop_o2
target/arm/tcg/sme_helper.c
+44
@@ -2723,6 +2723,50 @@ static void sme_tmop_2way_sh(uint32_t *za, uint16_t *zn0, uint32_t *zm,
2723
}
2724
}
2725
2726
+void sme_tmop_4way_sb(uint32_t *za, uint8_t *zn0, uint32_t *zm,
2727
+ uint64_t *zk, void *fn_opaque, uint32_t desc,
2728
+ void (*fn)(void *, void *, void *, void *))
2729
+{
2730
+ intptr_t oprsz = simd_maxsz(desc);
2731
+ intptr_t dim = oprsz >> MO_32;
2732
+ intptr_t index = simd_data(desc);
2733
+ intptr_t ctrl_base = (index * oprsz) >> 1;
2734
+ uint8_t *zn1 = zn0 + sizeof(ARMVectorReg);
2735
+
2736
+ for (intptr_t row = 0; row < dim; row++) {
2737
+ uint32_t *za_row = za + tile_vslice_offset(row);
2738
+
2739
+ for (intptr_t col = 0; col < dim; col++) {
2740
+ uint32_t *e2 = zm + H4(col);
2741
+ uint32_t *e3 = za_row + H4(col);
2742
+ uint16_t e1l = 0, e1h = 0;
2743
+ uint32_t e1;
2744
+
2745
+ /*
2746
+ * Eight control bits select two elements from each row.
2747
+ * The elements may be non-contiguous, so assemble them
2748
+ * locally into e1.
2749
+ * Pseudo-code has a triple loop running forward, with a
2750
+ * test for (i < 2) to limit construction to 2 elements.
2751
+ * Easier to run a single loop backward, shifting extra
2752
+ * elements off the top.
2753
+ */
2754
+ uint64_t this_ctrl = extractn(zk, ctrl_base + col * 8, 8);
2755
+ for (int e = 3; e >= 0; e--) {
2756
+ if (this_ctrl & (0x01 << e)) {
2757
+ e1l = (e1l << 8) | zn0[H1(4 * row + e)];
2758
+ }
2759
+ if (this_ctrl & (0x10 << e)) {
2760
+ e1h = (e1h << 8) | zn1[H1(4 * row + e)];
2761
+ }
2762
+ }
2763
+ e1 = (e1h << 16) | e1l;
2764
+
2765
+ fn(e3, &e1, e2, fn_opaque);
2766
+ }
2767
+ }
2768
+}
2769
+
2770
static void inner_fmop4a_hh(void *vd, void *vn, void *vm, void *vinfo)
2771
{
2772
float16 *d = vd, *n = vn, *m = vm;
target/arm/tcg/translate-sme.c
+2
@@ -2179,3 +2179,5 @@ static bool do_tmop_fp8(DisasContext *s, arg_tmop *a, MemOp esz,
2179
2180
TRANS_FEAT(FTMOPA_hb, aa64_sme_tmop_f8f16, do_tmop_fp8,
2181
a, MO_16, gen_helper_sme_ftmopa_hb)
2182
+TRANS_FEAT(FTMOPA_sb, aa64_sme_tmop_f8f32, do_tmop_fp8,
2183
+ a, MO_32, gen_helper_sme_ftmopa_sb)
target/arm/tcg/vec_internal.h
+7
@@ -555,4 +555,11 @@ void sme_mop4(void *vza, void *vzn, void *vzm, void *fn_opaque,
555
uint32_t desc, size_t esize,
556
void (*fn)(void *, void *, void *, void *));
557
558
+/*
559
+ * Perform SME sparse outer product, 4-way, 8 to 32-bit.
560
+ */
561
+void sme_tmop_4way_sb(uint32_t *za, uint8_t *zn0, uint32_t *zm,
562
+ uint64_t *zk, void *fn_opaque, uint32_t desc,
563
+ void (*fn)(void *, void *, void *, void *));
564
+
565
#endif /* TARGET_ARM_VEC_INTERNAL_H */