Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/arm/tcg/helper-sve.h | 2 + target/arm/tcg/sve_helper.c | 82 ++++++++++++++++++++++++++++++++++ target/arm/tcg/translate-sve.c | 36 +++++++++++++++ target/arm/tcg/sve.decode | 6 +++ 4 files changed, 126 insertions(+)
diff --git a/target/arm/tcg/helper-sve.h b/target/arm/tcg/helper-sve.h index 5f5ecc2e0d..ec82d0a4e7 100644 --- a/target/arm/tcg/helper-sve.h +++ b/target/arm/tcg/helper-sve.h @@ -2953,3 +2953,5 @@ DEF_HELPER_FLAGS_4(sve2p1_uminqv_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(sve2p1_uminqv_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(sve2p1_uminqv_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(sve2p1_uminqv_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_3(pext, TCG_CALL_NO_RWG, void, ptr, i32, i32) diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index 382c471aaa..eaf9363c0a 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -7839,3 +7839,85 @@ DO_FCVTLT(sve2_fcvtlt_sd, uint64_t, uint32_t, H1_8, H1_4, float32_to_float64) #undef DO_FCVTLT #undef DO_FCVTNT + +void HELPER(pext)(void *vd, uint32_t png, uint32_t desc) +{ + int pl = FIELD_EX32(desc, PREDDESC, OPRSZ); + int vl = pl * 8; + unsigned v_esz = FIELD_EX32(desc, PREDDESC, ESZ); + int part = FIELD_EX32(desc, PREDDESC, DATA); + unsigned p_esz; + uint64_t p_mask; + int p_count; + bool p_invert; + + /* C.f. Arm pseudocode CounterToPredicate. */ + if ((png & 0xf) == 0) { + /* Canonical false predicate. */ + goto zeros; + } + p_esz = ctz32(png); + + /* + * maxbit = log2(pl * 4) + * = log2(vl / 8 * 4) + * = log2(vl / 2) + * = log2(vl) - 1 + * maxbit_mask = ones<maxbit:0> + * = (1 << (maxbit + 1)) - 1 + * = (1 << (log2(vl) - 1 + 1)) - 1 + * = (1 << log2(vl)) - 1 + * = pow2ceil(vl) - 1 + * Note that we keep count in bytes, not elements. + */ + p_count = (png & (pow2ceil(vl) - 1)) >> 1; + p_invert = (png >> 15) & 1; + + /* + * If the esz encoded into the predicate is not larger than the + * vector operation esz, then the expanded predicate bit will + * be true for all vector elements. If the predicate esz is + * larger than the vector esz, then only even multiples can be + * true, and the rest will be false. This can be easily represented + * by taking the maximum esz for the pred_esz_mask. + */ + p_mask = pred_esz_masks[MAX(v_esz, p_esz)]; + + if (p_count == 0) { + if (p_invert) { + /* Canonical true predicate: invert count zero. */ + goto ones; + } + /* Non-canonical false predicate. */ + goto zeros; + } + + /* Adjust for the portion of the 4*VL counter to be extracted. */ + p_count -= vl * part; + + if (p_invert) { + if (p_count >= 0) { + goto ones; + } + if (p_count + vl <= 0) { + goto zeros; + } + do_whileg(vd, p_mask, p_count + vl, vl); + } else { + if (p_count <= 0) { + goto zeros; + } + if (p_count >= vl) { + goto ones; + } + do_whilel(vd, p_mask, p_count, vl); + } + return; + + ones: + do_whilel(vd, p_mask, vl, vl); + return; + zeros: + memset(vd, 0, ROUND_UP(pl, 8)); + return; +} diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index ade4914aba..98799298ba 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -3319,6 +3319,42 @@ static bool trans_WHILE_ptr(DisasContext *s, arg_WHILE_ptr *a) return true; } +static bool do_pext(DisasContext *s, arg_pext *a, int n) +{ + TCGv_i32 t_png; + TCGv_ptr t_pd; + int pl; + + if (!sve_access_check(s)) { + return true; + } + + t_png = tcg_temp_new_i32(); + tcg_gen_ld16u_i32(t_png, tcg_env, + pred_full_reg_offset(s, a->rn) ^ + (HOST_BIG_ENDIAN ? 6 : 0)); + + t_pd = tcg_temp_new_ptr(); + pl = pred_full_reg_size(s); + + for (int i = 0; i < n; ++i) { + int rd = (a->rd + i) % 16; + int part = a->imm * n + i; + unsigned desc = 0; + + desc = FIELD_DP32(desc, PREDDESC, OPRSZ, pl); + desc = FIELD_DP32(desc, PREDDESC, ESZ, a->esz); + desc = FIELD_DP32(desc, PREDDESC, DATA, part); + + tcg_gen_addi_ptr(t_pd, tcg_env, pred_full_reg_offset(s, rd)); + gen_helper_pext(t_pd, t_png, tcg_constant_i32(desc)); + } + return true; +} + +TRANS_FEAT(PEXT_1, aa64_sme2_or_sve2p1, do_pext, a, 1) +TRANS_FEAT(PEXT_2, aa64_sme2_or_sve2p1, do_pext, a, 2) + /* *** SVE Integer Wide Immediate - Unpredicated Group */ diff --git a/target/arm/tcg/sve.decode b/target/arm/tcg/sve.decode index f16764a947..39d7a29c06 100644 --- a/target/arm/tcg/sve.decode +++ b/target/arm/tcg/sve.decode @@ -60,6 +60,7 @@ %rn_ax2 6:4 !function=times_2 %pnd 0:3 !function=plus_8 +%pnn 5:3 !function=plus_8 ########################################################################### # Named attribute sets. These are used to make nice(er) names @@ -823,6 +824,11 @@ WHILE_lt_cnt4 00100101 .. 1 ..... 0110 . 1 ..... 1 . ... @while_cnt WHILE_gt_cnt2 00100101 .. 1 ..... 0100 . 0 ..... 1 . ... @while_cnt WHILE_gt_cnt4 00100101 .. 1 ..... 0110 . 0 ..... 1 . ... @while_cnt +# SVE2.1 extract mask predicate from predicate-as-counter +&pext rd rn esz imm +PEXT_1 00100101 esz:2 1 00000 0111 00 imm:2 ... 1 rd:4 &pext rn=%pnn +PEXT_2 00100101 esz:2 1 00000 0111 010 imm:1 ... 1 rd:4 &pext rn=%pnn + ### SVE Integer Wide Immediate - Unpredicated Group # SVE broadcast floating-point immediate (unpredicated) -- 2.43.0