@samitouri / QOSamiQemu / commits / e22eb3e0c7

target/arm: Implement FIRSTP, LASTP

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

Richard Henderson committed Jun 17, 2026 at 21:07 UTC e22eb3e0c7c2bc01f51ef839e5b7220ae08e9d5b
4 files changed +92
target/arm/tcg/helper-sve-defs.h
+3
@@ -961,6 +961,9 @@ DEF_HELPER_FLAGS_4(sve_brkns, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
961 DEF_HELPER_FLAGS_3(sve_cntp, TCG_CALL_NO_RWG, i64, ptr, ptr, i32)
962 DEF_HELPER_FLAGS_2(sve2p1_cntp_c, TCG_CALL_NO_RWG_SE, i64, i32, i32)
963
964 +DEF_HELPER_FLAGS_3(sve_firstp, TCG_CALL_NO_RWG_SE, i64, ptr, ptr, i32)
965 +DEF_HELPER_FLAGS_3(sve_lastp, TCG_CALL_NO_RWG_SE, i64, ptr, ptr, i32)
966 +
967 DEF_HELPER_FLAGS_3(sve_whilel, TCG_CALL_NO_RWG, i32, ptr, i32, i32)
968 DEF_HELPER_FLAGS_3(sve_whileg, TCG_CALL_NO_RWG, i32, ptr, i32, i32)
969
target/arm/tcg/sve.decode
+3
@@ -852,6 +852,9 @@ BRKN 00100101 0. 01100001 .... 0 .... 0 .... @pd_pg_pn_s
852 CNTP 00100101 .. 100 000 10 .... 0 .... ..... @rd_pg4_pn
853 CNTP_c 00100101 esz:2 100 000 10 000 vl:1 1 rn:4 rd:5
854
855 +FIRSTP 00100101 .. 100 001 10 .... 0 .... ..... @rd_pg4_pn
856 +LASTP 00100101 .. 100 010 10 .... 0 .... ..... @rd_pg4_pn
857 +
858 # SVE inc/dec register by predicate count
859 INCDECP_r 00100101 .. 10110 d:1 10001 00 .... ..... @incdec_pred u=1
860
target/arm/tcg/sve_helper.c
+30
@@ -4328,6 +4328,36 @@ uint64_t HELPER(sve2p1_cntp_c)(uint32_t png, uint32_t desc)
4328 return count >> p.lg2_stride;
4329 }
4330
4331 +uint64_t HELPER(sve_firstp)(void *vn, void *vg, uint32_t pred_desc)
4332 +{
4333 + intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
4334 + intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
4335 + uint64_t *n = vn, *g = vg, mask = pred_esz_masks[esz];
4336 +
4337 + for (intptr_t i = 0; i < words; ++i) {
4338 + uint64_t t = n[i] & g[i] & mask;
4339 + if (t) {
4340 + return (i * 64 + ctz64(t)) >> esz;
4341 + }
4342 + }
4343 + return -1;
4344 +}
4345 +
4346 +uint64_t HELPER(sve_lastp)(void *vn, void *vg, uint32_t pred_desc)
4347 +{
4348 + intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
4349 + intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
4350 + uint64_t *n = vn, *g = vg, mask = pred_esz_masks[esz];
4351 +
4352 + for (intptr_t i = words - 1; i >= 0; --i) {
4353 + uint64_t t = n[i] & g[i] & mask;
4354 + if (t) {
4355 + return (i * 64 + (63 - clz64(t))) >> esz;
4356 + }
4357 + }
4358 + return -1;
4359 +}
4360 +
4361 /* C.f. Arm pseudocode EncodePredCount */
4362 static uint64_t encode_pred_count(uint32_t elements, uint32_t count,
4363 uint32_t esz, bool invert)
target/arm/tcg/translate-sve.c
+56
@@ -3481,6 +3481,62 @@ static bool trans_SINCDECP_z(DisasContext *s, arg_incdec2_pred *a)
3481 return true;
3482 }
3483
3484 +static bool do_firstp_lastp(DisasContext *s, arg_rpr_esz *a, bool firstp)
3485 +{
3486 + if (sve_access_check(s)) {
3487 + unsigned psz = pred_full_reg_size(s);
3488 + TCGv_i64 v = cpu_reg(s, a->rd);
3489 +
3490 + if (psz <= 8) {
3491 + uint64_t psz_mask;
3492 +
3493 + tcg_gen_ld_i64(v, tcg_env, pred_full_reg_offset(s, a->rn));
3494 + if (a->rn != a->pg) {
3495 + TCGv_i64 g = tcg_temp_new_i64();
3496 + tcg_gen_ld_i64(g, tcg_env, pred_full_reg_offset(s, a->pg));
3497 + tcg_gen_and_i64(v, v, g);
3498 + }
3499 +
3500 + /*
3501 + * Reduce the pred_esz_masks value simply to reduce the
3502 + * size of the code generated here.
3503 + */
3504 + psz_mask = MAKE_64BIT_MASK(0, psz * 8);
3505 + tcg_gen_andi_i64(v, v, pred_esz_masks[a->esz] & psz_mask);
3506 +
3507 + if (firstp) {
3508 + tcg_gen_ctzi_i64(v, v, -1);
3509 + } else {
3510 + tcg_gen_clzi_i64(v, v, 64);
3511 + tcg_gen_subfi_i64(v, 63, v);
3512 + }
3513 + tcg_gen_sari_i64(v, v, a->esz);
3514 + } else {
3515 + TCGv_ptr t_pn = tcg_temp_new_ptr();
3516 + TCGv_ptr t_pg = tcg_temp_new_ptr();
3517 + unsigned desc = 0;
3518 + TCGv_i32 t_desc;
3519 +
3520 + desc = FIELD_DP32(desc, PREDDESC, OPRSZ, psz);
3521 + desc = FIELD_DP32(desc, PREDDESC, ESZ, a->esz);
3522 +
3523 + tcg_gen_addi_ptr(t_pn, tcg_env, pred_full_reg_offset(s, a->rn));
3524 + tcg_gen_addi_ptr(t_pg, tcg_env, pred_full_reg_offset(s, a->pg));
3525 + t_desc = tcg_constant_i32(desc);
3526 +
3527 + if (firstp) {
3528 + gen_helper_sve_firstp(v, t_pn, t_pg, t_desc);
3529 + } else {
3530 + gen_helper_sve_lastp(v, t_pn, t_pg, t_desc);
3531 + }
3532 + }
3533 + }
3534 + return true;
3535 +}
3536 +
3537 +TRANS_FEAT(FIRSTP, aa64_sme2p2_or_sve2p2, do_firstp_lastp, a, true)
3538 +TRANS_FEAT(LASTP, aa64_sme2p2_or_sve2p2, do_firstp_lastp, a, false)
3539 +
3540 /*
3541 *** SVE Integer Compare Scalars Group
3542 */