e2k: Add pshufw instr.

This commit is contained in:
Denis Drakhnia 2021-01-16 12:10:53 +02:00 committed by Denis Drakhnia
parent dc9b17e91a
commit 06471fe869
3 changed files with 95 additions and 72 deletions

View File

@ -25,7 +25,6 @@ DEF_HELPER_1(break_restore_state, void, env)
DEF_HELPER_2(setwd, void, env, i32)
DEF_HELPER_2(probe_read_access, int, env, tl)
DEF_HELPER_2(probe_write_access, int, env, tl)
DEF_HELPER_3(packed_shuffle_i64, i64, i64, i64, i64)
DEF_HELPER_1(aau_load_program, void, env)
DEF_HELPER_3(mova_ptr, tl, env, int, int)
@ -96,6 +95,10 @@ DEF_HELPER_2(packsshb, i64, i64, i64)
DEF_HELPER_2(packsswh, i64, i64, i64)
DEF_HELPER_2(packushb, i64, i64, i64)
/* Packed shuffle */
DEF_HELPER_3(pshufb, i64, i64, i64, i64)
DEF_HELPER_3(pshufw, i64, i64, i64, i32)
/* Packed uncategorized */
DEF_HELPER_2(psadbw, i64, i64, i64)
DEF_HELPER_2(pavgusb, i64, i64, i64)

View File

@ -41,75 +41,6 @@ typedef union {
#define satub(x) MIN(MAX(x, 0), 255)
#define satuh(x) MIN(MAX(x, 0), 65535)
uint64_t HELPER(packed_shuffle_i64)(uint64_t src1, uint64_t src2, uint64_t src3)
{
vec64 ret, s1, s2, s3;
unsigned int i;
s1.ud[0] = src1;
s2.ud[0] = src2;
s3.ud[0] = src3;
for (i = 0; i < 8; i++) {
uint8_t desc = s3.ub[i];
int index = extract8(desc, 0, 3);
uint8_t byte;
if (desc < 0x80) {
if (desc & 0x08) {
byte = s1.ub[index];
} else {
byte = s2.ub[index];
}
switch(desc >> 5) {
case 0x1:
byte = reverse_bits(byte);
break;
case 0x2:
if ((byte & 0x80) != 0) {
byte = 0xff;
} else {
byte = 0;
}
break;
case 0x3:
if ((byte & 1) != 0) {
byte = 0xff;
} else {
byte = 0;
}
break;
default:
break;
}
if (desc & 0x10) {
byte = ~byte;
}
} else {
switch(desc >> 6) {
case 0xa:
byte = 0x7f;
break;
case 0xc:
byte = 0x80;
break;
case 0xe:
byte = 0xff;
break;
default:
byte = 0;
break;
}
}
ret.ub[i] = byte;
}
return ret.ud[0];
}
#define GEN_HELPER_PACKED(name, type, code) \
uint64_t HELPER(name)(uint64_t src1, uint64_t src2) \
{ \
@ -242,3 +173,84 @@ GEN_HELPER_PACKED(pmovmskpd, sd, MOVMASK(ub, sd))
GEN_HELPER_PACKED(packsshb, sh, PACK(sb, sh, satsb))
GEN_HELPER_PACKED(packushb, uh, PACK(ub, sh, satub))
GEN_HELPER_PACKED(packsswh, sw, PACK(sh, sw, satsh))
uint64_t HELPER(pshufb)(uint64_t src1, uint64_t src2, uint64_t src3)
{
vec64 ret, s1, s2, s3;
unsigned int i;
s1.ud[0] = src1;
s2.ud[0] = src2;
s3.ud[0] = src3;
for (i = 0; i < 8; i++) {
uint8_t desc = s3.ub[i];
int index = extract8(desc, 0, 3);
uint8_t byte;
if (desc < 0x80) {
if (desc & 0x08) {
byte = s1.ub[index];
} else {
byte = s2.ub[index];
}
switch(desc >> 5) {
case 0x1:
byte = reverse_bits(byte);
break;
case 0x2:
if ((byte & 0x80) != 0) {
byte = 0xff;
} else {
byte = 0;
}
break;
case 0x3:
if ((byte & 1) != 0) {
byte = 0xff;
} else {
byte = 0;
}
break;
default:
break;
}
if (desc & 0x10) {
byte = ~byte;
}
} else {
switch(desc >> 6) {
case 0xa:
byte = 0x7f;
break;
case 0xc:
byte = 0x80;
break;
case 0xe:
byte = 0xff;
break;
default:
byte = 0;
break;
}
}
ret.ub[i] = byte;
}
return ret.ud[0];
}
uint64_t HELPER(pshufw)(uint64_t src1, uint64_t src2, uint32_t imm8)
{
int i;
vec64 s1 = { .ud[0] = src1 }, s2 = { .ud[0] = src2 }, dst;
for (i = 0; i < vec64_uw; i++) {
int sel = (imm8 >> (i * 2)) & 0x3;
int j = sel & 1;
dst.uw[i] = sel > 1 ? s1.uw[j] : s2.uw[j];
}
return dst.ud[0];
}

View File

@ -1910,6 +1910,14 @@ static inline void gen_pextrh(TCGv_i64 ret, TCGv_i64 src1,
}
}
static inline void gen_pshufw(TCGv_i64 ret, TCGv_i64 src1,
TCGv_i64 src2, int i)
{
TCGv_i32 imm8 = tcg_const_i32(i);
gen_helper_pshufw(ret, src1, src2, imm8);
tcg_temp_free_i32(imm8);
}
static void gen_aad_tag(TCGv_i64 ret, TCGv_i32 tag)
{
TCGv_i32 t0 = tcg_temp_new_i32();
@ -3101,6 +3109,7 @@ static void gen_op(DisasContext *ctx, Instr *instr)
case OP_PSRLQH: gen_alopf11_dddi(instr, gen_psrlqh); break;
case OP_PINSH: gen_alopf11_dddi(instr, gen_pinsh); break;
case OP_PEXTRH: gen_alopf11_dddi(instr, gen_pextrh); break;
case OP_PSHUFW: gen_alopf11_dddi(instr, gen_pshufw); break;
case OP_GETTAGS: gen_gettag_i32(instr); break;
case OP_GETTAGD: gen_gettag_i64(instr); break;
case OP_PUTTAGS: gen_puttag_i32(instr); break;
@ -3311,7 +3320,6 @@ static void gen_op(DisasContext *ctx, Instr *instr)
case OP_PFCMPNLTD:
case OP_PFCMPNLED:
case OP_PFCMPODD:
case OP_PSHUFW:
case OP_PUNPCKHBH:
case OP_PUNPCKHHW:
case OP_PUNPCKHWD:
@ -4275,7 +4283,7 @@ static void gen_pfcmb1(DisasContext *ctx, Instr *instr)
case 0x4d:
if (is_chan_0134(instr->chan) && ctx->version >= 2) {
/* pshufb */
gen_alopf21_i64(ctx, instr, gen_helper_packed_shuffle_i64);
gen_alopf21_i64(ctx, instr, gen_helper_pshufb);
return;
}
break;