From 0683fff1cf7d495e50955a946bf59f8b9c20c3f1 Mon Sep 17 00:00:00 2001 From: Xinyu Li Date: Sun, 2 Jun 2024 18:05:28 +0800 Subject: [PATCH] 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 Message-ID: <20240602100528.2135717-1-lixinyu20s@ict.ac.cn> Fixes: 5e9e21bcc4d ("target/i386: move 60-BF opcodes to new decoder", 2024-05-07) Signed-off-by: Paolo Bonzini --- target/i386/tcg/decode-new.c.inc | 13 +++++++++++-- target/i386/tcg/decode-new.h | 3 +++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 0ec849b003..0ff0866e8f 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -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; } diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index 51ef0e621b..1f90cf9640 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -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; /*