target/arm: Implement LUTI2, LUTI4 for SME2/SME2p1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20250704142112.1018902-101-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
ec2d970965
commit
a19b104f84
4 changed files with 210 additions and 0 deletions
|
|
@ -1188,3 +1188,27 @@ DEF_HELPER_FLAGS_4(gvec_uminp_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
|||
|
||||
DEF_HELPER_FLAGS_3(gvec_urecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_ursqrte_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sme2_luti2_1b, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti2_1h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti2_1s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sme2_luti2_2b, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti2_2h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti2_2s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sme2_luti2_4b, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti2_4h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti2_4s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sme2_luti4_1b, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti4_1h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti4_1s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sme2_luti4_2b, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti4_2h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti4_2s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sme2_luti4_4b, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti4_4h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
DEF_HELPER_FLAGS_4(sme2_luti4_4s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
|
||||
|
|
|
|||
|
|
@ -945,3 +945,45 @@ ZERO_za 11000000 000011 110 .. 0000000000 00. \
|
|||
&zero_za ngrp=2 nvec=4 rv=%mova_rv off=%off1_x4
|
||||
ZERO_za 11000000 000011 111 .. 0000000000 00. \
|
||||
&zero_za ngrp=4 nvec=4 rv=%mova_rv off=%off1_x4
|
||||
|
||||
### SME Lookup Table Read
|
||||
|
||||
&lut zd zn idx
|
||||
|
||||
# LUTI2, consecutive
|
||||
LUTI2_c_1b 1100 0000 1100 11 idx:4 00 00 zn:5 zd:5 &lut
|
||||
LUTI2_c_1h 1100 0000 1100 11 idx:4 01 00 zn:5 zd:5 &lut
|
||||
LUTI2_c_1s 1100 0000 1100 11 idx:4 10 00 zn:5 zd:5 &lut
|
||||
|
||||
LUTI2_c_2b 1100 0000 1000 11 idx:3 1 00 00 zn:5 .... 0 &lut zd=%zd_ax2
|
||||
LUTI2_c_2h 1100 0000 1000 11 idx:3 1 01 00 zn:5 .... 0 &lut zd=%zd_ax2
|
||||
LUTI2_c_2s 1100 0000 1000 11 idx:3 1 10 00 zn:5 .... 0 &lut zd=%zd_ax2
|
||||
|
||||
LUTI2_c_4b 1100 0000 1000 11 idx:2 10 00 00 zn:5 ... 00 &lut zd=%zd_ax4
|
||||
LUTI2_c_4h 1100 0000 1000 11 idx:2 10 01 00 zn:5 ... 00 &lut zd=%zd_ax4
|
||||
LUTI2_c_4s 1100 0000 1000 11 idx:2 10 10 00 zn:5 ... 00 &lut zd=%zd_ax4
|
||||
|
||||
# LUTI2, strided (must check zd alignment)
|
||||
LUTI2_s_2b 1100 0000 1001 11 idx:3 1 00 00 zn:5 zd:5 &lut
|
||||
LUTI2_s_2h 1100 0000 1001 11 idx:3 1 01 00 zn:5 zd:5 &lut
|
||||
|
||||
LUTI2_s_4b 1100 0000 1001 11 idx:2 10 00 00 zn:5 zd:5 &lut
|
||||
LUTI2_s_4h 1100 0000 1001 11 idx:2 10 01 00 zn:5 zd:5 &lut
|
||||
|
||||
# LUTI4, consecutive
|
||||
LUTI4_c_1b 1100 0000 1100 101 idx:3 00 00 zn:5 zd:5 &lut
|
||||
LUTI4_c_1h 1100 0000 1100 101 idx:3 01 00 zn:5 zd:5 &lut
|
||||
LUTI4_c_1s 1100 0000 1100 101 idx:3 10 00 zn:5 zd:5 &lut
|
||||
|
||||
LUTI4_c_2b 1100 0000 1000 101 idx:2 1 00 00 zn:5 .... 0 &lut zd=%zd_ax2
|
||||
LUTI4_c_2h 1100 0000 1000 101 idx:2 1 01 00 zn:5 .... 0 &lut zd=%zd_ax2
|
||||
LUTI4_c_2s 1100 0000 1000 101 idx:2 1 10 00 zn:5 .... 0 &lut zd=%zd_ax2
|
||||
|
||||
LUTI4_c_4h 1100 0000 1000 101 idx:1 10 01 00 zn:5 ... 00 &lut zd=%zd_ax4
|
||||
LUTI4_c_4s 1100 0000 1000 101 idx:1 10 10 00 zn:5 ... 00 &lut zd=%zd_ax4
|
||||
|
||||
# LUTI4, strided (must check zd alignment)
|
||||
LUTI4_s_2b 1100 0000 1001 101 idx:2 1 00 00 zn:5 zd:5 &lut
|
||||
LUTI4_s_2h 1100 0000 1001 101 idx:2 1 01 00 zn:5 zd:5 &lut
|
||||
|
||||
LUTI4_s_4h 1100 0000 1001 101 idx:1 10 01 00 zn:5 zd:5 &lut
|
||||
|
|
|
|||
|
|
@ -1697,3 +1697,59 @@ static bool trans_SEL(DisasContext *s, arg_SEL *a)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_lut(DisasContext *s, arg_lut *a,
|
||||
gen_helper_gvec_2_ptr *fn, bool strided)
|
||||
{
|
||||
if (sme_sm_enabled_check(s) && sme2_zt0_enabled_check(s)) {
|
||||
int svl = streaming_vec_reg_size(s);
|
||||
tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, a->zd),
|
||||
vec_full_reg_offset(s, a->zn),
|
||||
tcg_env, svl, svl, strided | (a->idx << 1), fn);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS_FEAT(LUTI2_c_1b, aa64_sme2, do_lut, a, gen_helper_sme2_luti2_1b, false)
|
||||
TRANS_FEAT(LUTI2_c_1h, aa64_sme2, do_lut, a, gen_helper_sme2_luti2_1h, false)
|
||||
TRANS_FEAT(LUTI2_c_1s, aa64_sme2, do_lut, a, gen_helper_sme2_luti2_1s, false)
|
||||
|
||||
TRANS_FEAT(LUTI2_c_2b, aa64_sme2, do_lut, a, gen_helper_sme2_luti2_2b, false)
|
||||
TRANS_FEAT(LUTI2_c_2h, aa64_sme2, do_lut, a, gen_helper_sme2_luti2_2h, false)
|
||||
TRANS_FEAT(LUTI2_c_2s, aa64_sme2, do_lut, a, gen_helper_sme2_luti2_2s, false)
|
||||
|
||||
TRANS_FEAT(LUTI2_c_4b, aa64_sme2, do_lut, a, gen_helper_sme2_luti2_4b, false)
|
||||
TRANS_FEAT(LUTI2_c_4h, aa64_sme2, do_lut, a, gen_helper_sme2_luti2_4h, false)
|
||||
TRANS_FEAT(LUTI2_c_4s, aa64_sme2, do_lut, a, gen_helper_sme2_luti2_4s, false)
|
||||
|
||||
TRANS_FEAT(LUTI4_c_1b, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_1b, false)
|
||||
TRANS_FEAT(LUTI4_c_1h, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_1h, false)
|
||||
TRANS_FEAT(LUTI4_c_1s, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_1s, false)
|
||||
|
||||
TRANS_FEAT(LUTI4_c_2b, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_2b, false)
|
||||
TRANS_FEAT(LUTI4_c_2h, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_2h, false)
|
||||
TRANS_FEAT(LUTI4_c_2s, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_2s, false)
|
||||
|
||||
TRANS_FEAT(LUTI4_c_4h, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_4h, false)
|
||||
TRANS_FEAT(LUTI4_c_4s, aa64_sme2, do_lut, a, gen_helper_sme2_luti4_4s, false)
|
||||
|
||||
static bool do_lut_s4(DisasContext *s, arg_lut *a, gen_helper_gvec_2_ptr *fn)
|
||||
{
|
||||
return !(a->zd & 0b01100) && do_lut(s, a, fn, true);
|
||||
}
|
||||
|
||||
static bool do_lut_s8(DisasContext *s, arg_lut *a, gen_helper_gvec_2_ptr *fn)
|
||||
{
|
||||
return !(a->zd & 0b01000) && do_lut(s, a, fn, true);
|
||||
}
|
||||
|
||||
TRANS_FEAT(LUTI2_s_2b, aa64_sme2p1, do_lut_s8, a, gen_helper_sme2_luti2_2b)
|
||||
TRANS_FEAT(LUTI2_s_2h, aa64_sme2p1, do_lut_s8, a, gen_helper_sme2_luti2_2h)
|
||||
|
||||
TRANS_FEAT(LUTI2_s_4b, aa64_sme2p1, do_lut_s4, a, gen_helper_sme2_luti2_4b)
|
||||
TRANS_FEAT(LUTI2_s_4h, aa64_sme2p1, do_lut_s4, a, gen_helper_sme2_luti2_4h)
|
||||
|
||||
TRANS_FEAT(LUTI4_s_2b, aa64_sme2p1, do_lut_s8, a, gen_helper_sme2_luti4_2b)
|
||||
TRANS_FEAT(LUTI4_s_2h, aa64_sme2p1, do_lut_s8, a, gen_helper_sme2_luti4_2h)
|
||||
|
||||
TRANS_FEAT(LUTI4_s_4h, aa64_sme2p1, do_lut_s4, a, gen_helper_sme2_luti4_4h)
|
||||
|
|
|
|||
|
|
@ -3443,3 +3443,91 @@ void HELPER(gvec_ursqrte_s)(void *vd, void *vn, uint32_t desc)
|
|||
}
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc));
|
||||
}
|
||||
|
||||
static inline void do_lut_b(void *zd, uint64_t *indexes, uint64_t *table,
|
||||
unsigned elements, unsigned segbase,
|
||||
unsigned dstride, unsigned isize,
|
||||
unsigned tsize, unsigned nreg)
|
||||
{
|
||||
for (unsigned r = 0; r < nreg; ++r) {
|
||||
uint8_t *dst = zd + dstride * r;
|
||||
unsigned base = segbase + r * elements;
|
||||
|
||||
for (unsigned e = 0; e < elements; ++e) {
|
||||
unsigned index = extractn(indexes, (base + e) * isize, isize);
|
||||
dst[H1(e)] = extractn(table, index * tsize, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void do_lut_h(void *zd, uint64_t *indexes, uint64_t *table,
|
||||
unsigned elements, unsigned segbase,
|
||||
unsigned dstride, unsigned isize,
|
||||
unsigned tsize, unsigned nreg)
|
||||
{
|
||||
for (unsigned r = 0; r < nreg; ++r) {
|
||||
uint16_t *dst = zd + dstride * r;
|
||||
unsigned base = segbase + r * elements;
|
||||
|
||||
for (unsigned e = 0; e < elements; ++e) {
|
||||
unsigned index = extractn(indexes, (base + e) * isize, isize);
|
||||
dst[H2(e)] = extractn(table, index * tsize, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void do_lut_s(void *zd, uint64_t *indexes, uint32_t *table,
|
||||
unsigned elements, unsigned segbase,
|
||||
unsigned dstride, unsigned isize,
|
||||
unsigned tsize, unsigned nreg)
|
||||
{
|
||||
for (unsigned r = 0; r < nreg; ++r) {
|
||||
uint32_t *dst = zd + dstride * r;
|
||||
unsigned base = segbase + r * elements;
|
||||
|
||||
for (unsigned e = 0; e < elements; ++e) {
|
||||
unsigned index = extractn(indexes, (base + e) * isize, isize);
|
||||
dst[H4(e)] = table[H4(index)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define DO_SME2_LUT(ISIZE, NREG, SUFF, ESIZE) \
|
||||
void helper_sme2_luti##ISIZE##_##NREG##SUFF \
|
||||
(void *zd, void *zn, CPUARMState *env, uint32_t desc) \
|
||||
{ \
|
||||
unsigned vl = simd_oprsz(desc); \
|
||||
unsigned strided = extract32(desc, SIMD_DATA_SHIFT, 1); \
|
||||
unsigned idx = extract32(desc, SIMD_DATA_SHIFT + 1, 4); \
|
||||
unsigned elements = vl / ESIZE; \
|
||||
unsigned dstride = (!strided ? 1 : NREG == 4 ? 4 : 8); \
|
||||
unsigned segments = (ESIZE * 8) / (ISIZE * NREG); \
|
||||
unsigned segment = idx & (segments - 1); \
|
||||
ARMVectorReg indexes; \
|
||||
memcpy(&indexes, zn, vl); \
|
||||
do_lut_##SUFF(zd, indexes.d, (void *)env->za_state.zt0, elements, \
|
||||
segment * NREG * elements, \
|
||||
dstride * sizeof(ARMVectorReg), ISIZE, 32, NREG); \
|
||||
}
|
||||
|
||||
DO_SME2_LUT(2,1,b, 1)
|
||||
DO_SME2_LUT(2,1,h, 2)
|
||||
DO_SME2_LUT(2,1,s, 4)
|
||||
DO_SME2_LUT(2,2,b, 1)
|
||||
DO_SME2_LUT(2,2,h, 2)
|
||||
DO_SME2_LUT(2,2,s, 4)
|
||||
DO_SME2_LUT(2,4,b, 1)
|
||||
DO_SME2_LUT(2,4,h, 2)
|
||||
DO_SME2_LUT(2,4,s, 4)
|
||||
|
||||
DO_SME2_LUT(4,1,b, 1)
|
||||
DO_SME2_LUT(4,1,h, 2)
|
||||
DO_SME2_LUT(4,1,s, 4)
|
||||
DO_SME2_LUT(4,2,b, 1)
|
||||
DO_SME2_LUT(4,2,h, 2)
|
||||
DO_SME2_LUT(4,2,s, 4)
|
||||
DO_SME2_LUT(4,4,b, 1)
|
||||
DO_SME2_LUT(4,4,h, 2)
|
||||
DO_SME2_LUT(4,4,s, 4)
|
||||
|
||||
#undef DO_SME2_LUT
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue