@samitouri / QOSamiQemu / commits / 5fbdd62ee2

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 +}