These use the W bit to encode the operand width, but otherwise fairly straightforward.
Signed-off-by: Paul Brook <p...@nowt.org> --- target/i386/ops_sse.h | 17 +++++++++++++++++ target/i386/ops_sse_header.h | 6 ++++++ target/i386/tcg/translate.c | 17 +++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 9b92b9790a..8f2bd48394 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -3195,6 +3195,23 @@ void glue(helper_vpermilps_imm, SUFFIX)(CPUX86State *env, #endif } +#if SHIFT == 1 +#define FPSRLVD(x, c) (c < 32 ? ((x) >> c) : 0) +#define FPSRLVQ(x, c) (c < 64 ? ((x) >> c) : 0) +#define FPSRAVD(x, c) ((int32_t)(x) >> (c < 64 ? c : 31)) +#define FPSRAVQ(x, c) ((int64_t)(x) >> (c < 64 ? c : 63)) +#define FPSLLVD(x, c) (c < 32 ? ((x) << c) : 0) +#define FPSLLVQ(x, c) (c < 64 ? ((x) << c) : 0) +#endif + +SSE_HELPER_L(helper_vpsrlvd, FPSRLVD) +SSE_HELPER_L(helper_vpsravd, FPSRAVD) +SSE_HELPER_L(helper_vpsllvd, FPSLLVD) + +SSE_HELPER_Q(helper_vpsrlvq, FPSRLVQ) +SSE_HELPER_Q(helper_vpsravq, FPSRAVQ) +SSE_HELPER_Q(helper_vpsllvq, FPSLLVQ) + #if SHIFT == 2 void glue(helper_vbroadcastdq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h index c52169a030..20db6c4240 100644 --- a/target/i386/ops_sse_header.h +++ b/target/i386/ops_sse_header.h @@ -421,6 +421,12 @@ DEF_HELPER_4(glue(vpermilpd, SUFFIX), void, env, Reg, Reg, Reg) DEF_HELPER_4(glue(vpermilps, SUFFIX), void, env, Reg, Reg, Reg) DEF_HELPER_4(glue(vpermilpd_imm, SUFFIX), void, env, Reg, Reg, i32) DEF_HELPER_4(glue(vpermilps_imm, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(vpsrlvd, SUFFIX), void, env, Reg, Reg, Reg) +DEF_HELPER_4(glue(vpsravd, SUFFIX), void, env, Reg, Reg, Reg) +DEF_HELPER_4(glue(vpsllvd, SUFFIX), void, env, Reg, Reg, Reg) +DEF_HELPER_4(glue(vpsrlvq, SUFFIX), void, env, Reg, Reg, Reg) +DEF_HELPER_4(glue(vpsravq, SUFFIX), void, env, Reg, Reg, Reg) +DEF_HELPER_4(glue(vpsllvq, SUFFIX), void, env, Reg, Reg, Reg) #if SHIFT == 2 DEF_HELPER_3(glue(vbroadcastdq, SUFFIX), void, env, Reg, Reg) DEF_HELPER_1(vzeroall, void, env) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 358c3ecb0b..4990470083 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3293,6 +3293,9 @@ static const struct SSEOpHelper_table6 sse_op_table6[256] = { [0x40] = BINARY_OP(pmulld, SSE41, SSE_OPF_MMX), #define gen_helper_phminposuw_ymm NULL [0x41] = UNARY_OP(phminposuw, SSE41, 0), + [0x45] = BINARY_OP(vpsrlvd, AVX, SSE_OPF_AVX2), + [0x46] = BINARY_OP(vpsravd, AVX, SSE_OPF_AVX2), + [0x47] = BINARY_OP(vpsllvd, AVX, SSE_OPF_AVX2), /* vpbroadcastd */ [0x58] = UNARY_OP(vbroadcastl, AVX, SSE_OPF_SCALAR | SSE_OPF_MMX), /* vpbroadcastq */ @@ -3357,6 +3360,15 @@ static const struct SSEOpHelper_table7 sse_op_table7[256] = { #undef BLENDV_OP #undef SPECIAL_OP +#define SSE_OP(name) \ + {gen_helper_ ## name ##_xmm, gen_helper_ ## name ##_ymm} +static const SSEFunc_0_eppp sse_op_table8[3][2] = { + SSE_OP(vpsrlvq), + SSE_OP(vpsravq), + SSE_OP(vpsllvq), +}; +#undef SSE_OP + /* VEX prefix not allowed */ #define CHECK_NO_VEX(s) do { \ if (s->prefix & PREFIX_VEX) \ @@ -4439,6 +4451,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_temp_free_ptr(mask); } else { SSEFunc_0_eppp fn = op6.fn[b1].op2; + if (REX_W(s)) { + if (b >= 0x45 && b <= 0x47) { + fn = sse_op_table8[b - 0x45][b1 - 1]; + } + } fn(cpu_env, s->ptr0, s->ptr2, s->ptr1); } } -- 2.36.0