diff options
| author | iximeow <me@iximeow.net> | 2026-03-09 16:36:00 +0000 |
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2026-05-25 00:59:27 +0000 |
| commit | 8a2dd6bcf37a3ebb43e2153a306cf0250637c116 (patch) | |
| tree | 44530b543f6718a6c709abf7c35f431f053beea8 | |
| parent | 63582532b8014d59117a8929afd1f7725bc1b469 (diff) | |
pushf, popf, enter, leave, xlat all have implicit memory access
also add "is_masked" to operand spec
| -rw-r--r-- | CHANGELOG | 5 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 14 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 14 | ||||
| -rw-r--r-- | src/real_mode/mod.rs | 14 | ||||
| -rw-r--r-- | test/long_mode/operand.rs | 8 | ||||
| -rw-r--r-- | test/protected_mode/operand.rs | 8 | ||||
| -rw-r--r-- | test/real_mode/operand.rs | 8 |
7 files changed, 66 insertions, 5 deletions
@@ -7,8 +7,9 @@ even when their corresponding extension is not selected. * added uarch-specific decoders for Zen 2, Zen 3, Zen 4, and Zen 5 * removed 3DNow support from AMD uarch-specific decoders after K10 -* push-immediate now reports a correct memory access side, fixing the prior - behavior of reporting to memory access size at all +* push-immediate, pushf, popf, enter, leave, and xlat now all report a correct memory + access size, fixing the prior behavior of reporting no memory access size at + all ## 2.0.0 diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 0ffc9f5..f3b4dc0 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -474,6 +474,9 @@ impl OperandSpec { fn is_memory(&self) -> bool { (*self as u8) & 0x80 != 0 } + fn is_masked(&self) -> bool { + (*self as u8) & 0x40 != 0 + } } /// an `avx512` merging mode. @@ -6619,8 +6622,15 @@ fn read_operands< instruction.mem_size = 8; } else if instruction.opcode == Opcode::RETF { instruction.mem_size = 10; + } else if instruction.opcode == Opcode::POPF { + instruction.mem_size = 8; + } else if instruction.opcode == Opcode::PUSHF { + instruction.mem_size = 8; + } else if instruction.opcode == Opcode::LEAVE { + instruction.mem_size = 8; + } else if instruction.opcode == Opcode::XLAT { + instruction.mem_size = 1; } - // TODO: leave? instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Ok(()); @@ -7102,6 +7112,8 @@ fn read_operands< instruction.imm = read_num(words, 1)? as u64; instruction.operands[0] = OperandSpec::ImmInDispField; instruction.operands[1] = OperandSpec::ImmU8; + // because there is an implied push of the adjusted base pointer + instruction.mem_size = 8; instruction.operand_count = 2; } OperandCase::Fw => { diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 6f052c6..0df8cee 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -409,6 +409,9 @@ impl OperandSpec { fn is_memory(&self) -> bool { (*self as u8) & 0x80 != 0 } + fn is_masked(&self) -> bool { + (*self as u8) & 0x40 != 0 + } } /// an `avx512` merging mode. /// @@ -6445,8 +6448,15 @@ fn read_operands< instruction.mem_size = 4; } else if instruction.opcode == Opcode::RETF { instruction.mem_size = 6; + } else if instruction.opcode == Opcode::POPF { + instruction.mem_size = 4; + } else if instruction.opcode == Opcode::PUSHF { + instruction.mem_size = 4; + } else if instruction.opcode == Opcode::LEAVE { + instruction.mem_size = 4; + } else if instruction.opcode == Opcode::XLAT { + instruction.mem_size = 1; } - // TODO: leave? instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Ok(()); @@ -6993,6 +7003,8 @@ fn read_operands< instruction.imm = read_num(words, 1)? as u32; instruction.operands[0] = OperandSpec::ImmInDispField; instruction.operands[1] = OperandSpec::ImmU8; + // because there is an implied push of the adjusted base pointer + instruction.mem_size = 4; instruction.operand_count = 2; } OperandCase::Fw => { diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 42a0b03..c11cf00 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -409,6 +409,9 @@ impl OperandSpec { fn is_memory(&self) -> bool { (*self as u8) & 0x80 != 0 } + fn is_masked(&self) -> bool { + (*self as u8) & 0x40 != 0 + } } /// an `avx512` merging mode. /// @@ -6482,8 +6485,15 @@ fn read_operands< instruction.mem_size = 2; } else if instruction.opcode == Opcode::RETF { instruction.mem_size = 4; + } else if instruction.opcode == Opcode::POPF { + instruction.mem_size = 2; + } else if instruction.opcode == Opcode::PUSHF { + instruction.mem_size = 2; + } else if instruction.opcode == Opcode::LEAVE { + instruction.mem_size = 2; + } else if instruction.opcode == Opcode::XLAT { + instruction.mem_size = 1; } - // TODO: leave? instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Ok(()); @@ -7032,6 +7042,8 @@ fn read_operands< instruction.imm = read_num(words, 1)? as u32; instruction.operands[0] = OperandSpec::ImmInDispField; instruction.operands[1] = OperandSpec::ImmU8; + // because there is an implied push of the adjusted base pointer + instruction.mem_size = 2; instruction.operand_count = 2; } OperandCase::Fw => { diff --git a/test/long_mode/operand.rs b/test/long_mode/operand.rs index b94d39f..10c4deb 100644 --- a/test/long_mode/operand.rs +++ b/test/long_mode/operand.rs @@ -53,4 +53,12 @@ fn test_implied_memory_width() { // operand-size prefixed call and jump still reads 8 bytes (prefix ignored) assert_eq!(mem_size_of(&[0x66, 0xff, 0x10]), Some(8)); assert_eq!(mem_size_of(&[0x66, 0xff, 0x20]), Some(8)); + // pushf + assert_eq!(mem_size_of(&[0x9c]), Some(8)); + // popf + assert_eq!(mem_size_of(&[0x9d]), Some(8)); + // leave + assert_eq!(mem_size_of(&[0xc9]), Some(8)); + // xlat + assert_eq!(mem_size_of(&[0xd7]), Some(1)); } diff --git a/test/protected_mode/operand.rs b/test/protected_mode/operand.rs index 78a34b4..fe9b54a 100644 --- a/test/protected_mode/operand.rs +++ b/test/protected_mode/operand.rs @@ -47,4 +47,12 @@ fn test_implied_memory_width() { // two bytes. assert_eq!(mem_size_of(&[0x66, 0xff, 0x10]), Some(2)); assert_eq!(mem_size_of(&[0x66, 0xff, 0x20]), Some(2)); + // pushf + assert_eq!(mem_size_of(&[0x9c]), Some(4)); + // popf + assert_eq!(mem_size_of(&[0x9d]), Some(4)); + // leave + assert_eq!(mem_size_of(&[0xc9]), Some(4)); + // xlat + assert_eq!(mem_size_of(&[0xd7]), Some(1)); } diff --git a/test/real_mode/operand.rs b/test/real_mode/operand.rs index 7f2b72e..e0f59e1 100644 --- a/test/real_mode/operand.rs +++ b/test/real_mode/operand.rs @@ -20,4 +20,12 @@ fn test_implied_memory_width() { // four bytes. assert_eq!(mem_size_of(&[0x66, 0xff, 0x10]), Some(4)); assert_eq!(mem_size_of(&[0x66, 0xff, 0x20]), Some(4)); + // pushf + assert_eq!(mem_size_of(&[0x9c]), Some(2)); + // popf + assert_eq!(mem_size_of(&[0x9d]), Some(2)); + // leave + assert_eq!(mem_size_of(&[0xc9]), Some(2)); + // xlat + assert_eq!(mem_size_of(&[0xd7]), Some(1)); } |
