aboutsummaryrefslogtreecommitdiff
path: root/src/long_mode/mod.rs
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2026-03-27 06:32:04 +0000
committeriximeow <me@iximeow.net>2026-05-25 00:59:27 +0000
commit35358d573bccd0776e55187564ccd6c72c9f9c34 (patch)
tree43d93572e271a36aec5f3d54c0a0a86ddf7d4c33 /src/long_mode/mod.rs
parent8a2dd6bcf37a3ebb43e2153a306cf0250637c116 (diff)
push/pop for segment registers has implicit memory access
Diffstat (limited to 'src/long_mode/mod.rs')
-rw-r--r--src/long_mode/mod.rs15
1 files changed, 15 insertions, 0 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index f3b4dc0..500c9f9 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -8915,11 +8915,26 @@ fn read_operands<
instruction.regs[0] = RegSpec::fs();
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operand_count = 1;
+
+ // good grief. from the SDM:
+ //
+ // > If the source operand is a segment register (16 bits) and the operand size is
+ // > 64-bits, a zeroextended value is pushed on the stack; if the operand size is
+ // > 32-bits, either a zero-extended value is pushed on the stack or the segment selector
+ // > is written on the stack using a 16-bit move
+ //
+ // the memory size here really depends on the `Default` bit in the CS descriptor. if
+ // the default operand size is 64 bits (basically every long-mode code), the acccess is
+ // 8 bytes (zero extended). if the default operand size is 32 bits, this is more complex.
+ instruction.mem_size = 8;
}
OperandCase::GS => {
instruction.regs[0] = RegSpec::gs();
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operand_count = 1;
+
+ // see the comment on mem size as written in OperandCase::FS
+ instruction.mem_size = 8;
}
OperandCase::AL_Ib => {
instruction.regs[0] =