diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/long_mode/mod.rs | 15 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 27 | ||||
| -rw-r--r-- | src/real_mode/mod.rs | 27 |
3 files changed, 69 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] = diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 0df8cee..10bc9d6 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -8679,31 +8679,58 @@ fn read_operands< instruction.regs[0] = RegSpec::cs(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; + + // see the comment on mem size as written in OperandCase::FS + instruction.mem_size = 2; } OperandCase::DS => { instruction.regs[0] = RegSpec::ds(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; + + // see the comment on mem size as written in OperandCase::FS + instruction.mem_size = 2; } OperandCase::ES => { instruction.regs[0] = RegSpec::es(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; + + // see the comment on mem size as written in OperandCase::FS + instruction.mem_size = 2; } OperandCase::SS => { instruction.regs[0] = RegSpec::ss(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; + + // see the comment on mem size as written in OperandCase::FS + instruction.mem_size = 2; } OperandCase::FS => { 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 zero-extended 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 all 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 = 4; } 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 = 4; } OperandCase::AL_Ib => { instruction.regs[0] = diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index c11cf00..7ac4c2e 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -8724,31 +8724,58 @@ fn read_operands< instruction.regs[0] = RegSpec::cs(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; + + // see the comment on mem size as written in OperandCase::FS + instruction.mem_size = 2; } OperandCase::DS => { instruction.regs[0] = RegSpec::ds(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; + + // see the comment on mem size as written in OperandCase::FS + instruction.mem_size = 2; } OperandCase::ES => { instruction.regs[0] = RegSpec::es(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; + + // see the comment on mem size as written in OperandCase::FS + instruction.mem_size = 2; } OperandCase::SS => { instruction.regs[0] = RegSpec::ss(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; + + // see the comment on mem size as written in OperandCase::FS + instruction.mem_size = 2; } OperandCase::FS => { 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 zero-extended 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 all 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 = 2; } 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 = 2; } OperandCase::AL_Ib => { instruction.regs[0] = |
