From 5d537aee9e68ade8701f8995135b38a9d3c7f97f Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 24 May 2026 21:22:13 +0000 Subject: gpr register size in real/protected mode --- CHANGELOG | 14 ++++++++------ src/protected_mode/mod.rs | 6 +++++- src/real_mode/mod.rs | 6 +++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 55af456..b36e7f6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,12 +15,14 @@ access size, fixing the prior behavior of reporting no memory access size at all * table load/store instructions (lgdt, lidt, lldt, sgdt, sidt, sldt) have correct (mode-dependent) memory access sizes, rather than incorrectly varying on operand-size overrides. -* 64-bit mode: mov seg-to-reg uses 32-bit GPRs for the destination rather than 16-bit. - * this is more accurate to the semantic of the instruction, which is why other disassemblers - report it this way; for register destinations specifically the segment selector is - zero-extended to 64 bits for storage. writing to "eax" in this way implies the 32->64 bit - zero-extend, whereas writing to "ax" does not imply any zero-extension. mov reg-to-seg - is unchanged and uses a 16-bit form for source GPR. +* mov seg-to-reg has more careful destination GPR selection. + * 64-bit: use 32-bit GPRs for the destination rather than 16-bit. + - this is more accurate to the semantic of the instruction, which is why other disassemblers + report it this way; for register destinations specifically the segment selector is + zero-extended to 64 bits for storage. writing to "eax" in this way implies the 32->64 bit + zero-extend, whereas writing to "ax" does not imply any zero-extension. mov reg-to-seg + is unchanged and uses a 16-bit form for source GPR. + * 32-bit, 16-bit: use 32-bit or 16-bit GPRs as requested by mode and operand size prefixes. * fix pextr{b,w,d,q} and extractps first and second operands being backwards. * reject 0f0d prefetch/nop with a register operand, which was incorrectly decoded before. * maskmovq and maskmovdqu now have their implicit memory access size reported correctly. diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 3540aa3..4736352 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -7946,7 +7946,11 @@ fn read_operands< instruction.operand_count = 2; if mem_oper == OperandSpec::RegMMM { - instruction.regs[1].bank = RegisterBank::D; + if instruction.prefixes.operand_size() { + instruction.regs[1].bank = RegisterBank::W; + } else { + instruction.regs[1].bank = RegisterBank::D; + } } else { instruction.mem_size = 2; } diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 715db85..097f6e5 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -7988,7 +7988,11 @@ fn read_operands< instruction.operand_count = 2; if mem_oper == OperandSpec::RegMMM { - instruction.regs[1].bank = RegisterBank::W; + if !instruction.prefixes.operand_size() { + instruction.regs[1].bank = RegisterBank::W; + } else { + instruction.regs[1].bank = RegisterBank::D; + } } else { instruction.mem_size = 2; } -- cgit v1.1