target/arm: Implement LUTI4 (four registers, 8-bit)
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260609192110.752384-28-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Richard Henderson committed
Jun 9, 2026 at 12:20 UTC
467e3d1e422df7f08c70e4be6b12e932b50afa59
5 files changed
+32
target/arm/cpu-features.h
+5
@@ -1668,6 +1668,11 @@ static inline bool isar_feature_aa64_sme2_f8cvt(const ARMISARegisters *id)
1668
return isar_feature_aa64_sme2(id) && isar_feature_aa64_f8cvt(id);
1669
}
1670
1671
+static inline bool isar_feature_aa64_sme2p1_lutv2(const ARMISARegisters *id)
1672
+{
1673
+ return isar_feature_aa64_sme2p1(id) && isar_feature_aa64_sme_lutv2(id);
1674
+}
1675
+
1676
static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id)
1677
{
1678
return isar_feature_aa64_sve(id) && isar_feature_aa64_sme_sve_i8mm(id);
target/arm/tcg/helper-defs.h
+1
@@ -1120,6 +1120,7 @@ DEF_HELPER_FLAGS_4(sme2_luti4_2b, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
1120
DEF_HELPER_FLAGS_4(sme2_luti4_2h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
1121
DEF_HELPER_FLAGS_4(sme2_luti4_2s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
1122
1123
+DEF_HELPER_FLAGS_4(sme2_luti4_4b, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
1124
DEF_HELPER_FLAGS_4(sme2_luti4_4h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
1125
DEF_HELPER_FLAGS_4(sme2_luti4_4s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
1126
target/arm/tcg/sme.decode
+6
@@ -1014,8 +1014,14 @@ LUTI4_c_2s 1100 0000 1000 101 idx:2 1 10 00 zn:5 .... 0 &lut zd=%zd_ax2
1014
LUTI4_c_4h 1100 0000 1000 101 idx:1 10 01 00 zn:5 ... 00 &lut zd=%zd_ax4
1015
LUTI4_c_4s 1100 0000 1000 101 idx:1 10 10 00 zn:5 ... 00 &lut zd=%zd_ax4
1016
1017
+LUTI4_c_4b 1100 0000 1000 101 1 00 00 00 ....0 ...00 \
1018
+ &lut zd=%zd_ax4 zn=%zn_ax2 idx=0
1019
+
1020
# LUTI4, strided (must check zd alignment)
1021
LUTI4_s_2b 1100 0000 1001 101 idx:2 1 00 00 zn:5 zd:5 &lut
1022
LUTI4_s_2h 1100 0000 1001 101 idx:2 1 01 00 zn:5 zd:5 &lut
1023
1024
LUTI4_s_4h 1100 0000 1001 101 idx:1 10 01 00 zn:5 zd:5 &lut
1025
+
1026
+LUTI4_s_4b 1100 0000 1001 101 1 00 00 00 ....0 zd:5 \
1027
+ &lut zn=%zn_ax2 idx=0
target/arm/tcg/translate-sme.c
+6
@@ -1846,6 +1846,9 @@ TRANS_FEAT(LUTI4_c_2s, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_2s, false)
1846
TRANS_FEAT(LUTI4_c_4h, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_4h, false)
1847
TRANS_FEAT(LUTI4_c_4s, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_4s, false)
1848
1849
+TRANS_FEAT(LUTI4_c_4b, aa64_sme_lutv2, do_lut, a,
1850
+ gen_helper_sme2_luti4_4b, false)
1851
+
1852
static bool do_lut_s4(DisasContext *s, arg_lut *a, gen_helper_gvec_2_ptr *fn)
1853
{
1854
return !(a->zd & 0b01100) && do_lut(s, a, fn, true);
@@ -1866,3 +1869,6 @@ TRANS_FEAT(LUTI4_s_2b, aa64_sme2p1, do_lut_s8, a, gen_helper_sme2_luti4_2b)
1869
TRANS_FEAT(LUTI4_s_2h, aa64_sme2p1, do_lut_s8, a, gen_helper_sme2_luti4_2h)
1870
1871
TRANS_FEAT(LUTI4_s_4h, aa64_sme2p1, do_lut_s4, a, gen_helper_sme2_luti4_4h)
1872
+
1873
+TRANS_FEAT(LUTI4_s_4b, aa64_sme2p1_lutv2, do_lut_s4, a,
1874
+ gen_helper_sme2_luti4_4b)
target/arm/tcg/vec_helper.c
+14
@@ -3345,6 +3345,20 @@ DO_SME2_LUT(4,4,s, 4)
3345
3346
#undef DO_SME2_LUT
3347
3348
+void helper_sme2_luti4_4b(void *zd, void *zn, CPUARMState *env, uint32_t desc)
3349
+{
3350
+ unsigned vl = simd_oprsz(desc);
3351
+ unsigned strided = extract32(desc, SIMD_DATA_SHIFT, 1);
3352
+ unsigned dstride = !strided ? 1 : 4;
3353
+ uint64_t indexes[ARM_MAX_VQ * 4];
3354
+
3355
+ memcpy(&indexes, zn, vl);
3356
+ memcpy((void *)&indexes + vl, zn + sizeof(ARMVectorReg), vl);
3357
+
3358
+ do_lut_b(zd, indexes, (void *)env->za_state.zt0, vl, 0,
3359
+ dstride * sizeof(ARMVectorReg), 4, 32, 4);
3360
+}
3361
+
3362
void HELPER(gvec_luti2_b)(void *vd, void *vn, void *vm, uint32_t desc)
3363
{
3364
unsigned part = simd_data(desc);