diff --git a/target/e2k/helper.h b/target/e2k/helper.h index db416b13d3..d299f654e0 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -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) diff --git a/target/e2k/helper_vec.c b/target/e2k/helper_vec.c index 70028ad663..155151d3bb 100644 --- a/target/e2k/helper_vec.c +++ b/target/e2k/helper_vec.c @@ -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]; +} diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 2a8261c8d9..ca9308cb43 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -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;