target/arm: Implement SVE2 MATCH, NMATCH

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Stephen Long <steplong@quicinc.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210525010358.152808-34-richard.henderson@linaro.org
Message-Id: <20200415145915.2859-1-steplong@quicinc.com>
[rth: Expanded comment for do_match2]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Stephen Long 2021-05-24 18:02:59 -07:00 committed by Peter Maydell
parent 911cdc6d79
commit e0ae6ec383
4 changed files with 101 additions and 0 deletions

View File

@ -2509,6 +2509,16 @@ DEF_HELPER_FLAGS_3(sve2_uqrshrnt_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
DEF_HELPER_FLAGS_3(sve2_uqrshrnt_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
DEF_HELPER_FLAGS_3(sve2_uqrshrnt_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(sve2_match_ppzz_b, TCG_CALL_NO_RWG,
i32, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(sve2_match_ppzz_h, TCG_CALL_NO_RWG,
i32, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(sve2_nmatch_ppzz_b, TCG_CALL_NO_RWG,
i32, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(sve2_nmatch_ppzz_h, TCG_CALL_NO_RWG,
i32, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_6(sve2_faddp_zpzz_h, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_6(sve2_faddp_zpzz_s, TCG_CALL_NO_RWG,

View File

@ -1320,6 +1320,11 @@ UQSHRNT 01000101 .. 1 ..... 00 1101 ..... ..... @rd_rn_tszimm_shr
UQRSHRNB 01000101 .. 1 ..... 00 1110 ..... ..... @rd_rn_tszimm_shr
UQRSHRNT 01000101 .. 1 ..... 00 1111 ..... ..... @rd_rn_tszimm_shr
### SVE2 Character Match
MATCH 01000101 .. 1 ..... 100 ... ..... 0 .... @pd_pg_rn_rm
NMATCH 01000101 .. 1 ..... 100 ... ..... 1 .... @pd_pg_rn_rm
## SVE2 floating-point pairwise operations
FADDP 01100100 .. 010 00 0 100 ... ..... ..... @rdn_pg_rm

View File

@ -6847,3 +6847,67 @@ void HELPER(sve2_nbsl)(void *vd, void *vn, void *vm, void *vk, uint32_t desc)
d[i] = ~((n[i] & k[i]) | (m[i] & ~k[i]));
}
}
/*
* Returns true if m0 or m1 contains the low uint8_t/uint16_t in n.
* See hasless(v,1) from
* https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
*/
static inline bool do_match2(uint64_t n, uint64_t m0, uint64_t m1, int esz)
{
int bits = 8 << esz;
uint64_t ones = dup_const(esz, 1);
uint64_t signs = ones << (bits - 1);
uint64_t cmp0, cmp1;
cmp1 = dup_const(esz, n);
cmp0 = cmp1 ^ m0;
cmp1 = cmp1 ^ m1;
cmp0 = (cmp0 - ones) & ~cmp0;
cmp1 = (cmp1 - ones) & ~cmp1;
return (cmp0 | cmp1) & signs;
}
static inline uint32_t do_match(void *vd, void *vn, void *vm, void *vg,
uint32_t desc, int esz, bool nmatch)
{
uint16_t esz_mask = pred_esz_masks[esz];
intptr_t opr_sz = simd_oprsz(desc);
uint32_t flags = PREDTEST_INIT;
intptr_t i, j, k;
for (i = 0; i < opr_sz; i += 16) {
uint64_t m0 = *(uint64_t *)(vm + i);
uint64_t m1 = *(uint64_t *)(vm + i + 8);
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)) & esz_mask;
uint16_t out = 0;
for (j = 0; j < 16; j += 8) {
uint64_t n = *(uint64_t *)(vn + i + j);
for (k = 0; k < 8; k += 1 << esz) {
if (pg & (1 << (j + k))) {
bool o = do_match2(n >> (k * 8), m0, m1, esz);
out |= (o ^ nmatch) << (j + k);
}
}
}
*(uint16_t *)(vd + H1_2(i >> 3)) = out;
flags = iter_predtest_fwd(out, pg, flags);
}
return flags;
}
#define DO_PPZZ_MATCH(NAME, ESZ, INV) \
uint32_t HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
{ \
return do_match(vd, vn, vm, vg, desc, ESZ, INV); \
}
DO_PPZZ_MATCH(sve2_match_ppzz_b, MO_8, false)
DO_PPZZ_MATCH(sve2_match_ppzz_h, MO_16, false)
DO_PPZZ_MATCH(sve2_nmatch_ppzz_b, MO_8, true)
DO_PPZZ_MATCH(sve2_nmatch_ppzz_h, MO_16, true)
#undef DO_PPZZ_MATCH

View File

@ -7462,6 +7462,28 @@ static bool trans_UQRSHRNT(DisasContext *s, arg_rri_esz *a)
return do_sve2_shr_narrow(s, a, ops);
}
static bool do_sve2_ppzz_flags(DisasContext *s, arg_rprr_esz *a,
gen_helper_gvec_flags_4 *fn)
{
if (!dc_isar_feature(aa64_sve2, s)) {
return false;
}
return do_ppzz_flags(s, a, fn);
}
#define DO_SVE2_PPZZ_MATCH(NAME, name) \
static bool trans_##NAME(DisasContext *s, arg_rprr_esz *a) \
{ \
static gen_helper_gvec_flags_4 * const fns[4] = { \
gen_helper_sve2_##name##_ppzz_b, gen_helper_sve2_##name##_ppzz_h, \
NULL, NULL \
}; \
return do_sve2_ppzz_flags(s, a, fns[a->esz]); \
}
DO_SVE2_PPZZ_MATCH(MATCH, match)
DO_SVE2_PPZZ_MATCH(NMATCH, nmatch)
static bool do_sve2_zpzz_fp(DisasContext *s, arg_rprr_esz *a,
gen_helper_gvec_4_ptr *fn)
{