These use the W bit to encode the operand width, but otherwise fairly
straightforward.
Signed-off-by: Paul Brook <paul@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