target/loongarch: Implement xvshuf xvperm{i} xvshuf4i

This patch includes:
- XVSHUF.{B/H/W/D};
- XVPERM.W;
- XVSHUF4i.{B/H/W/D};
- XVPERMI.{W/D/Q};
- XVEXTRINS.{B/H/W/D}.

Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20230914022645.1151356-55-gaosong@loongson.cn>
This commit is contained in:
Song Gao 2023-09-14 10:26:42 +08:00
parent ad2921482c
commit 513e88a24d
No known key found for this signature in database
GPG Key ID: 40A2FFF239263EDF
5 changed files with 175 additions and 46 deletions

View File

@ -2574,3 +2574,24 @@ INSN_LASX(xvilvh_b, vvv)
INSN_LASX(xvilvh_h, vvv)
INSN_LASX(xvilvh_w, vvv)
INSN_LASX(xvilvh_d, vvv)
INSN_LASX(xvshuf_b, vvvv)
INSN_LASX(xvshuf_h, vvv)
INSN_LASX(xvshuf_w, vvv)
INSN_LASX(xvshuf_d, vvv)
INSN_LASX(xvperm_w, vvv)
INSN_LASX(xvshuf4i_b, vv_i)
INSN_LASX(xvshuf4i_h, vv_i)
INSN_LASX(xvshuf4i_w, vv_i)
INSN_LASX(xvshuf4i_d, vv_i)
INSN_LASX(xvpermi_w, vv_i)
INSN_LASX(xvpermi_d, vv_i)
INSN_LASX(xvpermi_q, vv_i)
INSN_LASX(xvextrins_d, vv_i)
INSN_LASX(xvextrins_w, vv_i)
INSN_LASX(xvextrins_h, vv_i)
INSN_LASX(xvextrins_b, vv_i)

View File

@ -709,7 +709,10 @@ DEF_HELPER_FLAGS_4(vshuf4i_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vshuf4i_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vshuf4i_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vperm_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vpermi_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vpermi_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vpermi_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vextrins_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vextrins_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)

View File

@ -61,6 +61,10 @@ static bool gen_xxxx_ptr(DisasContext *ctx, arg_vvvv *a,
static bool gen_vvvv_vl(DisasContext *ctx, arg_vvvv *a, uint32_t oprsz,
gen_helper_gvec_4 *fn)
{
if (!check_vec(ctx, oprsz)) {
return true;
}
tcg_gen_gvec_4_ool(vec_full_offset(a->vd),
vec_full_offset(a->vj),
vec_full_offset(a->vk),
@ -72,13 +76,15 @@ static bool gen_vvvv_vl(DisasContext *ctx, arg_vvvv *a, uint32_t oprsz,
static bool gen_vvvv(DisasContext *ctx, arg_vvvv *a,
gen_helper_gvec_4 *fn)
{
if (!check_vec(ctx, 16)) {
return true;
}
return gen_vvvv_vl(ctx, a, 16, fn);
}
static bool gen_xxxx(DisasContext *ctx, arg_vvvv *a,
gen_helper_gvec_4 *fn)
{
return gen_vvvv_vl(ctx, a, 32, fn);
}
static bool gen_vvv_ptr_vl(DisasContext *ctx, arg_vvv *a, uint32_t oprsz,
gen_helper_gvec_3_ptr *fn)
{
@ -5218,17 +5224,33 @@ TRANS(vshuf_b, LSX, gen_vvvv, gen_helper_vshuf_b)
TRANS(vshuf_h, LSX, gen_vvv, gen_helper_vshuf_h)
TRANS(vshuf_w, LSX, gen_vvv, gen_helper_vshuf_w)
TRANS(vshuf_d, LSX, gen_vvv, gen_helper_vshuf_d)
TRANS(xvshuf_b, LASX, gen_xxxx, gen_helper_vshuf_b)
TRANS(xvshuf_h, LASX, gen_xxx, gen_helper_vshuf_h)
TRANS(xvshuf_w, LASX, gen_xxx, gen_helper_vshuf_w)
TRANS(xvshuf_d, LASX, gen_xxx, gen_helper_vshuf_d)
TRANS(vshuf4i_b, LSX, gen_vv_i, gen_helper_vshuf4i_b)
TRANS(vshuf4i_h, LSX, gen_vv_i, gen_helper_vshuf4i_h)
TRANS(vshuf4i_w, LSX, gen_vv_i, gen_helper_vshuf4i_w)
TRANS(vshuf4i_d, LSX, gen_vv_i, gen_helper_vshuf4i_d)
TRANS(xvshuf4i_b, LASX, gen_xx_i, gen_helper_vshuf4i_b)
TRANS(xvshuf4i_h, LASX, gen_xx_i, gen_helper_vshuf4i_h)
TRANS(xvshuf4i_w, LASX, gen_xx_i, gen_helper_vshuf4i_w)
TRANS(xvshuf4i_d, LASX, gen_xx_i, gen_helper_vshuf4i_d)
TRANS(xvperm_w, LASX, gen_xxx, gen_helper_vperm_w)
TRANS(vpermi_w, LSX, gen_vv_i, gen_helper_vpermi_w)
TRANS(xvpermi_w, LASX, gen_xx_i, gen_helper_vpermi_w)
TRANS(xvpermi_d, LASX, gen_xx_i, gen_helper_vpermi_d)
TRANS(xvpermi_q, LASX, gen_xx_i, gen_helper_vpermi_q)
TRANS(vextrins_b, LSX, gen_vv_i, gen_helper_vextrins_b)
TRANS(vextrins_h, LSX, gen_vv_i, gen_helper_vextrins_h)
TRANS(vextrins_w, LSX, gen_vv_i, gen_helper_vextrins_w)
TRANS(vextrins_d, LSX, gen_vv_i, gen_helper_vextrins_d)
TRANS(xvextrins_b, LASX, gen_xx_i, gen_helper_vextrins_b)
TRANS(xvextrins_h, LASX, gen_xx_i, gen_helper_vextrins_h)
TRANS(xvextrins_w, LASX, gen_xx_i, gen_helper_vextrins_w)
TRANS(xvextrins_d, LASX, gen_xx_i, gen_helper_vextrins_d)
static bool trans_vld(DisasContext *ctx, arg_vr_i *a)
{

View File

@ -2039,3 +2039,24 @@ xvilvh_b 0111 01010001 11000 ..... ..... ..... @vvv
xvilvh_h 0111 01010001 11001 ..... ..... ..... @vvv
xvilvh_w 0111 01010001 11010 ..... ..... ..... @vvv
xvilvh_d 0111 01010001 11011 ..... ..... ..... @vvv
xvshuf_b 0000 11010110 ..... ..... ..... ..... @vvvv
xvshuf_h 0111 01010111 10101 ..... ..... ..... @vvv
xvshuf_w 0111 01010111 10110 ..... ..... ..... @vvv
xvshuf_d 0111 01010111 10111 ..... ..... ..... @vvv
xvperm_w 0111 01010111 11010 ..... ..... ..... @vvv
xvshuf4i_b 0111 01111001 00 ........ ..... ..... @vv_ui8
xvshuf4i_h 0111 01111001 01 ........ ..... ..... @vv_ui8
xvshuf4i_w 0111 01111001 10 ........ ..... ..... @vv_ui8
xvshuf4i_d 0111 01111001 11 ........ ..... ..... @vv_ui8
xvpermi_w 0111 01111110 01 ........ ..... ..... @vv_ui8
xvpermi_d 0111 01111110 10 ........ ..... ..... @vv_ui8
xvpermi_q 0111 01111110 11 ........ ..... ..... @vv_ui8
xvextrins_d 0111 01111000 00 ........ ..... ..... @vv_ui8
xvextrins_w 0111 01111000 01 ........ ..... ..... @vv_ui8
xvextrins_h 0111 01111000 10 ........ ..... ..... @vv_ui8
xvextrins_b 0111 01111000 11 ........ ..... ..... @vv_ui8

View File

@ -3381,57 +3381,65 @@ VILVH(vilvh_h, 32, H)
VILVH(vilvh_w, 64, W)
VILVH(vilvh_d, 128, D)
#define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03))
void HELPER(vshuf_b)(void *vd, void *vj, void *vk, void *va, uint32_t desc)
{
int i, m;
VReg temp;
int i, j, m;
VReg temp = {};
VReg *Vd = (VReg *)vd;
VReg *Vj = (VReg *)vj;
VReg *Vk = (VReg *)vk;
VReg *Va = (VReg *)va;
int oprsz = simd_oprsz(desc);
m = LSX_LEN/8;
for (i = 0; i < m ; i++) {
m = LSX_LEN / 8;
for (i = 0; i < (oprsz / 16) * m; i++) {
j = i < m ? 0 : 1;
uint64_t k = (uint8_t)Va->B(i) % (2 * m);
temp.B(i) = k < m ? Vk->B(k) : Vj->B(k - m);
temp.B(i) = k < m ? Vk->B(k + j * m): Vj->B(k + (j - 1) * m);
}
*Vd = temp;
}
#define VSHUF(NAME, BIT, E) \
void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
{ \
int i, m; \
VReg temp; \
VReg *Vd = (VReg *)vd; \
VReg *Vj = (VReg *)vj; \
VReg *Vk = (VReg *)vk; \
\
m = LSX_LEN/BIT; \
for (i = 0; i < m; i++) { \
uint64_t k = ((uint8_t) Vd->E(i)) % (2 * m); \
temp.E(i) = k < m ? Vk->E(k) : Vj->E(k - m); \
} \
*Vd = temp; \
#define VSHUF(NAME, BIT, E) \
void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
{ \
int i, j, m; \
VReg temp = {}; \
VReg *Vd = (VReg *)vd; \
VReg *Vj = (VReg *)vj; \
VReg *Vk = (VReg *)vk; \
int oprsz = simd_oprsz(desc); \
\
m = LSX_LEN / BIT; \
for (i = 0; i < (oprsz / 16) * m; i++) { \
j = i < m ? 0 : 1; \
uint64_t k = ((uint8_t)Vd->E(i)) % (2 * m); \
temp.E(i) = k < m ? Vk->E(k + j * m) : Vj->E(k + (j - 1) * m); \
} \
*Vd = temp; \
}
VSHUF(vshuf_h, 16, H)
VSHUF(vshuf_w, 32, W)
VSHUF(vshuf_d, 64, D)
#define VSHUF4I(NAME, BIT, E) \
void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
{ \
int i; \
VReg temp; \
VReg *Vd = (VReg *)vd; \
VReg *Vj = (VReg *)vj; \
\
for (i = 0; i < LSX_LEN/BIT; i++) { \
temp.E(i) = Vj->E(((i) & 0xfc) + (((imm) >> \
(2 * ((i) & 0x03))) & 0x03)); \
} \
*Vd = temp; \
#define VSHUF4I(NAME, BIT, E) \
void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
{ \
int i, j, max; \
VReg temp = {}; \
VReg *Vd = (VReg *)vd; \
VReg *Vj = (VReg *)vj; \
int oprsz = simd_oprsz(desc); \
\
max = LSX_LEN / BIT; \
for (i = 0; i < oprsz / (BIT / 8); i++) { \
j = i < max ? 1 : 2; \
temp.E(i) = Vj->E(SHF_POS(i - ((j -1)* max), imm) + (j - 1) * max); \
} \
*Vd = temp; \
}
VSHUF4I(vshuf4i_b, 8, B)
@ -3440,38 +3448,92 @@ VSHUF4I(vshuf4i_w, 32, W)
void HELPER(vshuf4i_d)(void *vd, void *vj, uint64_t imm, uint32_t desc)
{
int i;
VReg temp = {};
VReg *Vd = (VReg *)vd;
VReg *Vj = (VReg *)vj;
int oprsz = simd_oprsz(desc);
VReg temp;
temp.D(0) = (imm & 2 ? Vj : Vd)->D(imm & 1);
temp.D(1) = (imm & 8 ? Vj : Vd)->D((imm >> 2) & 1);
for (i = 0; i < oprsz / 16; i++) {
temp.D(2 * i) = (imm & 2 ? Vj : Vd)->D((imm & 1) + 2 * i);
temp.D(2 * i + 1) = (imm & 8 ? Vj : Vd)->D(((imm >> 2) & 1) + 2 * i);
}
*Vd = temp;
}
void HELPER(vperm_w)(void *vd, void *vj, void *vk, uint32_t desc)
{
int i, m;
VReg temp = {};
VReg *Vd = (VReg *)vd;
VReg *Vj = (VReg *)vj;
VReg *Vk = (VReg *)vk;
m = LASX_LEN / 32;
for (i = 0; i < m ; i++) {
uint64_t k = (uint8_t)Vk->W(i) % 8;
temp.W(i) = Vj->W(k);
}
*Vd = temp;
}
void HELPER(vpermi_w)(void *vd, void *vj, uint64_t imm, uint32_t desc)
{
int i;
VReg temp = {};
VReg *Vd = (VReg *)vd;
VReg *Vj = (VReg *)vj;
int oprsz = simd_oprsz(desc);
for (i = 0; i < oprsz / 16; i++) {
temp.W(4 * i) = Vj->W((imm & 0x3) + 4 * i);
temp.W(4 * i + 1) = Vj->W(((imm >> 2) & 0x3) + 4 * i);
temp.W(4 * i + 2) = Vd->W(((imm >> 4) & 0x3) + 4 * i);
temp.W(4 * i + 3) = Vd->W(((imm >> 6) & 0x3) + 4 * i);
}
*Vd = temp;
}
void HELPER(vpermi_d)(void *vd, void *vj, uint64_t imm, uint32_t desc)
{
VReg temp = {};
VReg *Vd = (VReg *)vd;
VReg *Vj = (VReg *)vj;
temp.D(0) = Vj->D(imm & 0x3);
temp.D(1) = Vj->D((imm >> 2) & 0x3);
temp.D(2) = Vj->D((imm >> 4) & 0x3);
temp.D(3) = Vj->D((imm >> 6) & 0x3);
*Vd = temp;
}
void HELPER(vpermi_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
{
int i;
VReg temp;
VReg *Vd = (VReg *)vd;
VReg *Vj = (VReg *)vj;
temp.W(0) = Vj->W(imm & 0x3);
temp.W(1) = Vj->W((imm >> 2) & 0x3);
temp.W(2) = Vd->W((imm >> 4) & 0x3);
temp.W(3) = Vd->W((imm >> 6) & 0x3);
for (i = 0; i < 2; i++, imm >>= 4) {
temp.Q(i) = (imm & 2 ? Vd: Vj)->Q(imm & 1);
}
*Vd = temp;
}
#define VEXTRINS(NAME, BIT, E, MASK) \
void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
{ \
int ins, extr; \
int i, ins, extr, max; \
VReg *Vd = (VReg *)vd; \
VReg *Vj = (VReg *)vj; \
int oprsz = simd_oprsz(desc); \
\
max = LSX_LEN / BIT; \
ins = (imm >> 4) & MASK; \
extr = imm & MASK; \
Vd->E(ins) = Vj->E(extr); \
for (i = 0; i < oprsz / 16; i++) { \
Vd->E(ins + i * max) = Vj->E(extr + i * max); \
} \
}
VEXTRINS(vextrins_b, 8, B, 0xf)