aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2026-05-24 21:22:13 +0000
committeriximeow <me@iximeow.net>2026-05-25 02:02:11 +0000
commit5d537aee9e68ade8701f8995135b38a9d3c7f97f (patch)
treee6fd79adaff2739dc640f0f2755eb89daa5630cf
parent0363fd684c98ea08d8a9ee3a6f09d5c07e80d55c (diff)
gpr register size in real/protected mode
-rw-r--r--CHANGELOG14
-rw-r--r--src/protected_mode/mod.rs6
-rw-r--r--src/real_mode/mod.rs6
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;
}