@samitouri / QOSamiQemu / commits / e921da8b98

target/arm: Implement FTMOPA (widening, 2-way, FP8 to FP16)

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

Richard Henderson committed Aug 11, 2026 at 20:14 UTC e921da8b98f0be99edf973e3d623d79ac2cd3705
5 files changed +64
target/arm/cpu-features.h
+5
@@ -1852,6 +1852,11 @@ static inline bool isar_feature_aa64_sme_tmop_f16f16(const ARMISARegisters *id)
1852 return isar_feature_aa64_sme_tmop(id) && isar_feature_aa64_sme_f16f16(id);
1853 }
1854
1855 +static inline bool isar_feature_aa64_sme_tmop_f8f16(const ARMISARegisters *id)
1856 +{
1857 + return isar_feature_aa64_sme_tmop(id) && isar_feature_aa64_sme_f8f16(id);
1858 +}
1859 +
1860 /*
1861 * Feature tests for "does this exist in either 32-bit or 64-bit?"
1862 */
target/arm/tcg/fp8_helper.c
+43
@@ -1005,3 +1005,46 @@ void HELPER(sme_fmop4a_hb)(void *vza, void *vzn, void *vzm,
1005 FP8MulContext ctx = fp8_mul_start(env, 0xf);
1006 sme_mop4(vza, vzn, vzm, &ctx, desc, sizeof(float16), inner_fmop4a_hb);
1007 }
1008 +
1009 +void HELPER(sme_ftmopa_hb)(void *vza, void *vzn, void *vzm, void *vzk,
1010 + CPUArchState *env, uint32_t desc)
1011 +{
1012 + FP8MulContext ctx = fp8_mul_start(env, 0xf);
1013 + intptr_t oprsz = simd_maxsz(desc);
1014 + intptr_t dim = oprsz >> MO_16;
1015 + intptr_t index = simd_data(desc);
1016 + intptr_t ctrl_base = (index * oprsz) >> 1;
1017 + uint8_t *zn0 = vzn, *zn1 = vzn + sizeof(ARMVectorReg);
1018 + uint16_t *za = vza, *zm = vzm;
1019 + uint64_t *zk = vzk;
1020 +
1021 + for (intptr_t row = 0; row < dim; row++) {
1022 + uint16_t *za_row = za + tile_vslice_offset(row);
1023 +
1024 + for (intptr_t col = 0; col < dim; col++) {
1025 + uint16_t e2 = zm[H2(col)];
1026 + uint16_t *e3 = za_row + H2(col);
1027 + uint16_t e1 = 0;
1028 +
1029 + /*
1030 + * Four control bits select two elements. The two elements
1031 + * may be non-contiguous, so assemble them locally into e1.
1032 + * Pseudo-code has a double loop running forward, with a
1033 + * test for (i < 2) to limit construction to 2 elements.
1034 + * Easier to run a single loop backward, shifting extra
1035 + * elements off the top of our uint16_t.
1036 + */
1037 + uint64_t this_ctrl = extractn(zk, ctrl_base + col * 4, 4);
1038 + for (int i = 3; i >= 0; i--) {
1039 + if (this_ctrl & (1 << i)) {
1040 + bool e = i & 1;
1041 + bool r = i & 2;
1042 + uint8_t *p = (r ? zn1 : zn0) + H1(2 * row + e);
1043 + e1 = (e1 << 8) | *p;
1044 + }
1045 + }
1046 +
1047 + *e3 = f8dotadd_h(e1, e2, 2, *e3, &ctx);
1048 + }
1049 + }
1050 +}
target/arm/tcg/helper-fp8-defs.h
+2
@@ -47,3 +47,5 @@ DEF_HELPER_FLAGS_5(sme_fvdot_idx_hb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env,
47
48 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)
target/arm/tcg/sme.decode
+2
@@ -1148,3 +1148,5 @@ FTMOPA_ss 1000 0000 010 ..... 000 ... .... .. 00 .. @tmop_o2
1148
1149 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
target/arm/tcg/translate-sme.c
+12
@@ -2167,3 +2167,15 @@ TRANS_FEAT(BFTMOPA_sh, aa64_sme_tmop, do_tmop_fp,
2167 a, MO_32, FPST_ENV, gen_helper_sme_bftmopa_sh)
2168 TRANS_FEAT(FTMOPA_sh, aa64_sme_tmop, do_tmop_fp,
2169 a, MO_32, FPST_ENV, gen_helper_sme_ftmopa_sh)
2170 +
2171 +static bool do_tmop_fp8(DisasContext *s, arg_tmop *a, MemOp esz,
2172 + gen_helper_gvec_4_ptr *fn)
2173 +{
2174 + if (!fpmr_access_check(s)) {
2175 + return true;
2176 + }
2177 + return do_tmop_fp(s, a, esz, FPST_ENV, fn);
2178 +}
2179 +
2180 +TRANS_FEAT(FTMOPA_hb, aa64_sme_tmop_f8f16, do_tmop_fp8,
2181 + a, MO_16, gen_helper_sme_ftmopa_hb)