target/i386: fix memory opsize for Mov to/from Seg
This commit fixes an issue with MOV instructions (0x8C and 0x8E)
involving segment registers; MOV to segment register's source is
16-bit, while MOV from segment register has to explicitly set the
memory operand size to 16 bits. Introduce a new flag
X86_SPECIAL_Op0_Mw to handle this specification correctly.
Signed-off-by: Xinyu Li <lixinyu20s@ict.ac.cn>
Message-ID: <20240602100528.2135717-1-lixinyu20s@ict.ac.cn>
Fixes: 5e9e21bcc4
("target/i386: move 60-BF opcodes to new decoder", 2024-05-07)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
da7c95920d
commit
0683fff1cf
@ -202,6 +202,7 @@
|
||||
#define avx_movx .special = X86_SPECIAL_AVXExtMov,
|
||||
#define sextT0 .special = X86_SPECIAL_SExtT0,
|
||||
#define zextT0 .special = X86_SPECIAL_ZExtT0,
|
||||
#define op0_Mw .special = X86_SPECIAL_Op0_Mw,
|
||||
|
||||
#define vex1 .vex_class = 1,
|
||||
#define vex1_rep3 .vex_class = 1, .vex_special = X86_VEX_REPScalar,
|
||||
@ -1576,9 +1577,10 @@ static const X86OpEntry opcodes_root[256] = {
|
||||
[0x89] = X86_OP_ENTRY3(MOV, E,v, G,v, None, None),
|
||||
[0x8A] = X86_OP_ENTRY3(MOV, G,b, E,b, None, None),
|
||||
[0x8B] = X86_OP_ENTRY3(MOV, G,v, E,v, None, None),
|
||||
[0x8C] = X86_OP_ENTRY3(MOV, E,v, S,w, None, None),
|
||||
/* Missing in Table A-2: memory destination is always 16-bit. */
|
||||
[0x8C] = X86_OP_ENTRY3(MOV, E,v, S,w, None, None, op0_Mw),
|
||||
[0x8D] = X86_OP_ENTRY3(LEA, G,v, M,v, None, None, noseg),
|
||||
[0x8E] = X86_OP_ENTRY3(MOV, S,w, E,v, None, None),
|
||||
[0x8E] = X86_OP_ENTRY3(MOV, S,w, E,w, None, None),
|
||||
[0x8F] = X86_OP_GROUPw(group1A, E,v),
|
||||
|
||||
[0x98] = X86_OP_ENTRY1(CBW, 0,v), /* rAX */
|
||||
@ -2514,6 +2516,13 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
|
||||
s->override = -1;
|
||||
break;
|
||||
|
||||
case X86_SPECIAL_Op0_Mw:
|
||||
assert(decode.op[0].unit == X86_OP_INT);
|
||||
if (decode.op[0].has_ea) {
|
||||
decode.op[0].ot = MO_16;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -203,6 +203,9 @@ typedef enum X86InsnSpecial {
|
||||
/* When loaded into s->T0, register operand 1 is zero/sign extended. */
|
||||
X86_SPECIAL_SExtT0,
|
||||
X86_SPECIAL_ZExtT0,
|
||||
|
||||
/* Memory operand size of MOV from segment register is MO_16 */
|
||||
X86_SPECIAL_Op0_Mw,
|
||||
} X86InsnSpecial;
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user