target/i386: ignore misplaced REX prefixes

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2024-07-10 23:24:22 +02:00
parent ac2c4d3aed
commit 336dbe8e99

View file

@ -2542,7 +2542,13 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
s->has_modrm = false;
s->prefix = 0;
next_byte:
next_byte:;
#ifdef TARGET_X86_64
/* clear any REX prefix followed by other prefixes. */
int rex;
rex = -1;
next_byte_rex:
#endif
b = x86_ldub_code(env, s);
/* Collect prefixes. */
@ -2585,13 +2591,12 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
#ifdef TARGET_X86_64
case 0x40 ... 0x4f:
if (CODE64(s)) {
/* REX prefix */
s->prefix |= PREFIX_REX;
s->vex_w = (b >> 3) & 1;
s->rex_r = (b & 0x4) << 1;
s->rex_x = (b & 0x2) << 2;
s->rex_b = (b & 0x1) << 3;
goto next_byte;
/*
* REX prefix; ignored unless it is the last prefix, so
* for now just stash it
*/
rex = b;
goto next_byte_rex;
}
break;
#endif
@ -2618,10 +2623,13 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
/* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ
| PREFIX_LOCK | PREFIX_DATA | PREFIX_REX)) {
| PREFIX_LOCK | PREFIX_DATA)) {
goto illegal_op;
}
#ifdef TARGET_X86_64
if (rex != -1) {
goto illegal_op;
}
s->rex_r = (~vex2 >> 4) & 8;
#endif
if (b == 0xc5) {
@ -2661,6 +2669,16 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
/* Post-process prefixes. */
if (CODE64(s)) {
#ifdef TARGET_X86_64
if (rex != -1) {
s->prefix |= PREFIX_REX;
s->vex_w = (rex >> 3) & 1;
s->rex_r = (rex & 0x4) << 1;
s->rex_x = (rex & 0x2) << 2;
s->rex_b = (rex & 0x1) << 3;
}
#endif
/*
* In 64-bit mode, the default data size is 32-bit. Select 64-bit
* data with rex_w, and 16-bit data with 0x66; rex_w takes precedence