Commit 9f94fd68c8 for qemu.org
commit 9f94fd68c89bed9bd59019a0bb2ad7d2e5458bcf
Author: Paolo Bonzini <pbonzini@redhat.com>
Date: Sat Oct 10 12:00:17 2026 +0200
target/i386/tcg: reject VEX.NP for MMX instructions
MMX instructions do not have a VEX encoding, so reject VEX instructions
with no prefix for instructions that use X86_SPECIAL_MMX.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 2756953c74..65fd402c17 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -2425,6 +2425,12 @@ static void decode_modrm(DisasContext *s, CPUX86State *env,
decode->mem = (AddressParts){ def_seg, base, index, scale, disp };
}
+static bool is_mmx(const DisasContext *s, const X86OpEntry *e)
+{
+ return (e->special == X86_SPECIAL_MMX &&
+ !(s->prefix & (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA)));
+}
+
static bool decode_op_size(DisasContext *s, X86OpEntry *e, X86OpSize size, MemOp *ot)
{
switch (size) {
@@ -2470,8 +2476,7 @@ static bool decode_op_size(DisasContext *s, X86OpEntry *e, X86OpSize size, MemOp
return true;
case X86_SIZE_dq: /* SSE/AVX 128-bit */
- if (e->special == X86_SPECIAL_MMX &&
- !(s->prefix & (PREFIX_DATA | PREFIX_REPZ | PREFIX_REPNZ))) {
+ if (is_mmx(s, e)) {
*ot = MO_64;
return true;
}
@@ -2489,8 +2494,7 @@ static bool decode_op_size(DisasContext *s, X86OpEntry *e, X86OpSize size, MemOp
return true;
case X86_SIZE_x: /* 128/256-bit, based on operand size */
- if (e->special == X86_SPECIAL_MMX &&
- !(s->prefix & (PREFIX_DATA | PREFIX_REPZ | PREFIX_REPNZ))) {
+ if (is_mmx(s, e)) {
*ot = MO_64;
return true;
}
@@ -2605,8 +2609,7 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
goto get_reg;
case X86_TYPE_V: /* reg in the modrm byte selects an XMM/YMM register */
- if (decode->e.special == X86_SPECIAL_MMX &&
- !(s->prefix & (PREFIX_DATA | PREFIX_REPZ | PREFIX_REPNZ))) {
+ if (is_mmx(s, &decode->e)) {
op->unit = X86_OP_MMX;
} else {
op->unit = X86_OP_SSE;
@@ -2625,8 +2628,7 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
goto get_modrm;
case X86_TYPE_W: /* XMM/YMM modrm operand */
- if (decode->e.special == X86_SPECIAL_MMX &&
- !(s->prefix & (PREFIX_DATA | PREFIX_REPZ | PREFIX_REPNZ))) {
+ if (is_mmx(s, &decode->e)) {
op->unit = X86_OP_MMX;
} else {
op->unit = X86_OP_SSE;
@@ -2638,8 +2640,7 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
goto get_modrm_reg;
case X86_TYPE_U: /* R/M in the modrm byte selects an XMM/YMM register */
- if (decode->e.special == X86_SPECIAL_MMX &&
- !(s->prefix & (PREFIX_DATA | PREFIX_REPZ | PREFIX_REPNZ))) {
+ if (is_mmx(s, &decode->e)) {
op->unit = X86_OP_MMX;
} else {
op->unit = X86_OP_SSE;
@@ -3135,12 +3136,15 @@ static bool validate_vex(DisasContext *s, X86DecodedInsn *decode)
case 4:
case 5:
case 7:
- if (s->prefix & PREFIX_VEX) {
+ if (is_mmx(s, e)) {
+ if (s->prefix & PREFIX_VEX) {
+ goto illegal;
+ }
+ } else if (s->prefix & PREFIX_VEX) {
if (!(s->flags & HF_AVX_EN_MASK)) {
goto illegal;
}
- } else if (e->special != X86_SPECIAL_MMX ||
- (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA))) {
+ } else {
if (!(s->flags & HF_OSFXSR_MASK)) {
goto illegal;
}
@@ -3694,8 +3698,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
}
}
- if (decode.e.special == X86_SPECIAL_MMX &&
- !(s->prefix & (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA))) {
+ if (is_mmx(s, &decode.e)) {
gen_helper_enter_mmx(tcg_env);
}