target/arm: Implement LUTI2, LUTI4 for AdvSIMD
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260609192110.752384-22-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Richard Henderson committed
Jun 9, 2026 at 12:20 UTC
5fbdd62ee22f929400a623b4a1725dea83b6da70
4 files changed
+101
target/arm/tcg/a64.decode
+6
@@ -1355,6 +1355,12 @@ EXT_q 0110 1110 00 0 rm:5 0 imm:4 0 rn:5 rd:5
1355
1356
TBL_TBX 0 q:1 00 1110 000 rm:5 0 len:2 tbx:1 00 rn:5 rd:5
1357
1358
+LUTI2_1b 0100 1110 100 rm:5 0 idx:2 100 rn:5 rd:5 &rrx_e esz=0
1359
+LUTI2_1h 0100 1110 110 rm:5 0 idx:3 00 rn:5 rd:5 &rrx_e esz=1
1360
+
1361
+LUTI4_1b 0100 1110 010 rm:5 0 idx:1 1000 rn:5 rd:5 &rrx_e esz=0
1362
+LUTI4_2h 0100 1110 010 rm:5 0 idx:2 100 rn:5 rd:5 &rrx_e esz=1
1363
+
1364
# Advanced SIMD Permute
1365
1366
UZP1 0.00 1110 .. 0 ..... 0 001 10 ..... ..... @qrrr_e
target/arm/tcg/helper-defs.h
+5
@@ -1122,3 +1122,8 @@ DEF_HELPER_FLAGS_4(sme2_luti4_2s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
1122
1123
DEF_HELPER_FLAGS_4(sme2_luti4_4h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
1124
DEF_HELPER_FLAGS_4(sme2_luti4_4s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
1125
+
1126
+DEF_HELPER_FLAGS_4(gvec_luti2_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
1127
+DEF_HELPER_FLAGS_4(gvec_luti2_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
1128
+DEF_HELPER_FLAGS_4(gvec_luti4_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
1129
+DEF_HELPER_FLAGS_4(gvec_luti4_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
target/arm/tcg/translate-a64.c
+38
@@ -5502,6 +5502,44 @@ static bool trans_TBL_TBX(DisasContext *s, arg_TBL_TBX *a)
5502
return true;
5503
}
5504
5505
+static bool do_lut_1(DisasContext *s, arg_rrx_e *a, gen_helper_gvec_3 *fn)
5506
+{
5507
+ if (fp_access_check(s)) {
5508
+ gen_gvec_op3_ool(s, true, a->rd, a->rn, a->rm, a->idx, fn);
5509
+ }
5510
+ return true;
5511
+}
5512
+
5513
+TRANS_FEAT(LUTI2_1b, aa64_lut, do_lut_1, a, gen_helper_gvec_luti2_b)
5514
+TRANS_FEAT(LUTI2_1h, aa64_lut, do_lut_1, a, gen_helper_gvec_luti2_h)
5515
+TRANS_FEAT(LUTI4_1b, aa64_lut, do_lut_1, a, gen_helper_gvec_luti4_b)
5516
+
5517
+static bool trans_LUTI4_2h(DisasContext *s, arg_rrx_e *a)
5518
+{
5519
+ if (!dc_isar_feature(aa64_lut, s)) {
5520
+ return false;
5521
+ }
5522
+ if (fp_access_check(s)) {
5523
+ /*
5524
+ * (Ab)use preg_tmp to merge two disjoint 128-bit quantities
5525
+ * into a sequential 256-bit table.
5526
+ */
5527
+ QEMU_BUILD_BUG_ON(sizeof_field(CPUARMState, vfp.preg_tmp) < 32);
5528
+ unsigned tmp_ofs = offsetof(CPUARMState, vfp.preg_tmp);
5529
+ unsigned rn0_ofs = vec_full_reg_offset(s, a->rn);
5530
+ unsigned rn1_ofs = vec_full_reg_offset(s, (a->rn + 1) % 32);
5531
+
5532
+ tcg_gen_gvec_mov(MO_64, tmp_ofs, rn0_ofs, 16, 16);
5533
+ tcg_gen_gvec_mov(MO_64, tmp_ofs + 16, rn1_ofs, 16, 16);
5534
+
5535
+ tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), tmp_ofs,
5536
+ vec_full_reg_offset(s, a->rm),
5537
+ 16, vec_full_reg_size(s),
5538
+ a->idx, gen_helper_gvec_luti4_h);
5539
+ }
5540
+ return true;
5541
+}
5542
+
5543
typedef int simd_permute_idx_fn(int i, int part, int elements);
5544
5545
static bool do_simd_permute(DisasContext *s, arg_qrrr_e *a,
target/arm/tcg/vec_helper.c
+52
@@ -3344,3 +3344,55 @@ DO_SME2_LUT(4,4,h, 2)
3344
DO_SME2_LUT(4,4,s, 4)
3345
3346
#undef DO_SME2_LUT
3347
+
3348
+void HELPER(gvec_luti2_b)(void *vd, void *vn, void *vm, uint32_t desc)
3349
+{
3350
+ unsigned part = simd_data(desc);
3351
+ unsigned vl = simd_oprsz(desc);
3352
+ unsigned elements = vl / 1;
3353
+ unsigned ibase = elements * part;
3354
+ ARMVectorReg scratch;
3355
+
3356
+ do_lut_b(&scratch, vm, vn, elements, ibase, 0, 2, 8, 1);
3357
+ memcpy(vd, &scratch, vl);
3358
+ clear_tail(vd, vl, simd_maxsz(desc));
3359
+}
3360
+
3361
+void HELPER(gvec_luti2_h)(void *vd, void *vn, void *vm, uint32_t desc)
3362
+{
3363
+ unsigned part = simd_data(desc);
3364
+ unsigned vl = simd_oprsz(desc);
3365
+ unsigned elements = vl / 2;
3366
+ unsigned ibase = elements * part;
3367
+ ARMVectorReg scratch;
3368
+
3369
+ do_lut_h(&scratch, vm, vn, elements, ibase, 0, 2, 16, 1);
3370
+ memcpy(vd, &scratch, vl);
3371
+ clear_tail(vd, vl, simd_maxsz(desc));
3372
+}
3373
+
3374
+void HELPER(gvec_luti4_b)(void *vd, void *vn, void *vm, uint32_t desc)
3375
+{
3376
+ unsigned part = simd_data(desc);
3377
+ unsigned vl = simd_oprsz(desc);
3378
+ unsigned elements = vl / 1;
3379
+ unsigned ibase = elements * part;
3380
+ ARMVectorReg scratch;
3381
+
3382
+ do_lut_b(&scratch, vm, vn, elements, ibase, 0, 4, 8, 1);
3383
+ memcpy(vd, &scratch, vl);
3384
+ clear_tail(vd, vl, simd_maxsz(desc));
3385
+}
3386
+
3387
+void HELPER(gvec_luti4_h)(void *vd, void *vn, void *vm, uint32_t desc)
3388
+{
3389
+ unsigned part = simd_data(desc);
3390
+ unsigned vl = simd_oprsz(desc);
3391
+ unsigned elements = vl / 2;
3392
+ unsigned ibase = elements * part;
3393
+ ARMVectorReg scratch;
3394
+
3395
+ do_lut_h(&scratch, vm, vn, elements, ibase, 0, 4, 16, 1);
3396
+ memcpy(vd, &scratch, vl);
3397
+ clear_tail(vd, vl, simd_maxsz(desc));
3398
+}