target/i386: Add CHECK_NO_VEX

Reject invalid VEX encodings on MMX instructions.

Signed-off-by: Paul Brook <paul@nowt.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20220424220204.2493824-7-paul@nowt.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paul Brook 2022-04-24 23:01:28 +01:00 committed by Paolo Bonzini
parent 7f32690243
commit 71964f1b69

View File

@ -3186,6 +3186,12 @@ static const struct SSEOpHelper_table7 sse_op_table7[256] = {
#undef BLENDV_OP #undef BLENDV_OP
#undef SPECIAL_OP #undef SPECIAL_OP
/* VEX prefix not allowed */
#define CHECK_NO_VEX(s) do { \
if (s->prefix & PREFIX_VEX) \
goto illegal_op; \
} while (0)
static void gen_sse(CPUX86State *env, DisasContext *s, int b, static void gen_sse(CPUX86State *env, DisasContext *s, int b,
target_ulong pc_start) target_ulong pc_start)
{ {
@ -3272,6 +3278,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
b |= (b1 << 8); b |= (b1 << 8);
switch(b) { switch(b) {
case 0x0e7: /* movntq */ case 0x0e7: /* movntq */
CHECK_NO_VEX(s);
if (mod == 3) { if (mod == 3) {
goto illegal_op; goto illegal_op;
} }
@ -3307,6 +3314,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
} }
break; break;
case 0x6e: /* movd mm, ea */ case 0x6e: /* movd mm, ea */
CHECK_NO_VEX(s);
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
if (s->dflag == MO_64) { if (s->dflag == MO_64) {
gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0); gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
@ -3338,6 +3346,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
} }
break; break;
case 0x6f: /* movq mm, ea */ case 0x6f: /* movq mm, ea */
CHECK_NO_VEX(s);
if (mod != 3) { if (mod != 3) {
gen_lea_modrm(env, s, modrm); gen_lea_modrm(env, s, modrm);
gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx)); gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
@ -3473,6 +3482,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
break; break;
case 0x178: case 0x178:
case 0x378: case 0x378:
CHECK_NO_VEX(s);
{ {
int bit_index, field_length; int bit_index, field_length;
@ -3492,6 +3502,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
} }
break; break;
case 0x7e: /* movd ea, mm */ case 0x7e: /* movd ea, mm */
CHECK_NO_VEX(s);
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
if (s->dflag == MO_64) { if (s->dflag == MO_64) {
tcg_gen_ld_i64(s->T0, cpu_env, tcg_gen_ld_i64(s->T0, cpu_env,
@ -3532,6 +3543,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1))); gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
break; break;
case 0x7f: /* movq ea, mm */ case 0x7f: /* movq ea, mm */
CHECK_NO_VEX(s);
if (mod != 3) { if (mod != 3) {
gen_lea_modrm(env, s, modrm); gen_lea_modrm(env, s, modrm);
gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx)); gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
@ -3614,6 +3626,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
offsetof(CPUX86State, xmm_t0.ZMM_L(1))); offsetof(CPUX86State, xmm_t0.ZMM_L(1)));
op1_offset = offsetof(CPUX86State,xmm_t0); op1_offset = offsetof(CPUX86State,xmm_t0);
} else { } else {
CHECK_NO_VEX(s);
tcg_gen_movi_tl(s->T0, val); tcg_gen_movi_tl(s->T0, val);
tcg_gen_st32_tl(s->T0, cpu_env, tcg_gen_st32_tl(s->T0, cpu_env,
offsetof(CPUX86State, mmx_t0.MMX_L(0))); offsetof(CPUX86State, mmx_t0.MMX_L(0)));
@ -3653,6 +3666,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
break; break;
case 0x02a: /* cvtpi2ps */ case 0x02a: /* cvtpi2ps */
case 0x12a: /* cvtpi2pd */ case 0x12a: /* cvtpi2pd */
CHECK_NO_VEX(s);
gen_helper_enter_mmx(cpu_env); gen_helper_enter_mmx(cpu_env);
if (mod != 3) { if (mod != 3) {
gen_lea_modrm(env, s, modrm); gen_lea_modrm(env, s, modrm);
@ -3698,6 +3712,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
case 0x12c: /* cvttpd2pi */ case 0x12c: /* cvttpd2pi */
case 0x02d: /* cvtps2pi */ case 0x02d: /* cvtps2pi */
case 0x12d: /* cvtpd2pi */ case 0x12d: /* cvtpd2pi */
CHECK_NO_VEX(s);
gen_helper_enter_mmx(cpu_env); gen_helper_enter_mmx(cpu_env);
if (mod != 3) { if (mod != 3) {
gen_lea_modrm(env, s, modrm); gen_lea_modrm(env, s, modrm);
@ -3771,6 +3786,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
tcg_gen_st16_tl(s->T0, cpu_env, tcg_gen_st16_tl(s->T0, cpu_env,
offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val))); offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
} else { } else {
CHECK_NO_VEX(s);
val &= 3; val &= 3;
tcg_gen_st16_tl(s->T0, cpu_env, tcg_gen_st16_tl(s->T0, cpu_env,
offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val))); offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
@ -3810,6 +3826,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
} }
break; break;
case 0x2d6: /* movq2dq */ case 0x2d6: /* movq2dq */
CHECK_NO_VEX(s);
gen_helper_enter_mmx(cpu_env); gen_helper_enter_mmx(cpu_env);
rm = (modrm & 7); rm = (modrm & 7);
gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)), gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)),
@ -3817,6 +3834,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1))); gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)));
break; break;
case 0x3d6: /* movdq2q */ case 0x3d6: /* movdq2q */
CHECK_NO_VEX(s);
gen_helper_enter_mmx(cpu_env); gen_helper_enter_mmx(cpu_env);
rm = (modrm & 7) | REX_B(s); rm = (modrm & 7) | REX_B(s);
gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx), gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx),
@ -3831,6 +3849,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm)); tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm));
gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0); gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0);
} else { } else {
CHECK_NO_VEX(s);
rm = (modrm & 7); rm = (modrm & 7);
tcg_gen_addi_ptr(s->ptr0, cpu_env, tcg_gen_addi_ptr(s->ptr0, cpu_env,
offsetof(CPUX86State, fpregs[rm].mmx)); offsetof(CPUX86State, fpregs[rm].mmx));
@ -3901,6 +3920,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
op6->fn[b1].op1(cpu_env, s->ptr0, s->ptr1); op6->fn[b1].op1(cpu_env, s->ptr0, s->ptr1);
} else { } else {
CHECK_NO_VEX(s);
if ((op6->flags & SSE_OPF_MMX) == 0) { if ((op6->flags & SSE_OPF_MMX) == 0) {
goto unknown_op; goto unknown_op;
} }
@ -3934,6 +3954,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
case 0x3f0: /* crc32 Gd,Eb */ case 0x3f0: /* crc32 Gd,Eb */
case 0x3f1: /* crc32 Gd,Ey */ case 0x3f1: /* crc32 Gd,Ey */
do_crc32: do_crc32:
CHECK_NO_VEX(s);
if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) { if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
goto illegal_op; goto illegal_op;
} }
@ -3956,6 +3977,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
case 0x1f0: /* crc32 or movbe */ case 0x1f0: /* crc32 or movbe */
case 0x1f1: case 0x1f1:
CHECK_NO_VEX(s);
/* For these insns, the f3 prefix is supposed to have priority /* For these insns, the f3 prefix is supposed to have priority
over the 66 prefix, but that's not what we implement above over the 66 prefix, but that's not what we implement above
setting b1. */ setting b1. */
@ -3965,6 +3987,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
/* FALLTHRU */ /* FALLTHRU */
case 0x0f0: /* movbe Gy,My */ case 0x0f0: /* movbe Gy,My */
case 0x0f1: /* movbe My,Gy */ case 0x0f1: /* movbe My,Gy */
CHECK_NO_VEX(s);
if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) { if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
goto illegal_op; goto illegal_op;
} }
@ -4131,6 +4154,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
case 0x1f6: /* adcx Gy, Ey */ case 0x1f6: /* adcx Gy, Ey */
case 0x2f6: /* adox Gy, Ey */ case 0x2f6: /* adox Gy, Ey */
CHECK_NO_VEX(s);
if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) { if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
goto illegal_op; goto illegal_op;
} else { } else {
@ -4436,6 +4460,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
} }
if (b1 == 0) { if (b1 == 0) {
CHECK_NO_VEX(s);
/* MMX */ /* MMX */
if ((op7->flags & SSE_OPF_MMX) == 0) { if ((op7->flags & SSE_OPF_MMX) == 0) {
goto illegal_op; goto illegal_op;
@ -4582,6 +4607,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
op2_offset = ZMM_OFFSET(rm); op2_offset = ZMM_OFFSET(rm);
} }
} else { } else {
CHECK_NO_VEX(s);
op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
if (mod != 3) { if (mod != 3) {
gen_lea_modrm(env, s, modrm); gen_lea_modrm(env, s, modrm);