diff options
author | iximeow <me@iximeow.net> | 2024-06-24 12:48:45 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2024-06-24 12:48:45 -0700 |
commit | 1b8019d5b39a05c109399b8628a1082bfec79755 (patch) | |
tree | 2183199b4da0ec1cf3d88f9f1b75498e0d86da27 | |
parent | b8a294db5ae6831c54be368e41fa8418a6f73bcb (diff) |
rename most operand variants, make them structy rather than tupley
-rw-r--r-- | CHANGELOG | 39 | ||||
-rw-r--r-- | src/lib.rs | 4 | ||||
-rw-r--r-- | src/long_mode/display.rs | 76 | ||||
-rw-r--r-- | src/long_mode/mod.rs | 493 | ||||
-rw-r--r-- | src/protected_mode/display.rs | 76 | ||||
-rw-r--r-- | src/protected_mode/mod.rs | 483 | ||||
-rw-r--r-- | src/real_mode/display.rs | 76 | ||||
-rw-r--r-- | src/real_mode/mod.rs | 487 | ||||
-rw-r--r-- | test/long_mode/operand.rs | 16 | ||||
-rw-r--r-- | test/protected_mode/operand.rs | 12 |
10 files changed, 868 insertions, 894 deletions
@@ -1,7 +1,44 @@ -## 1.3.0 +## 2.0.0 * upgrade to `yaxpeax-arch 0.3.1`, which brings with it a deprecation of the `Colorize` and `ShowContextual` traits. +* because common use of yaxpeax-x86 involves using both this crate and + `yaxpeax-arch`, moving to a newer major version of `yaxpeax-arch` is a major + version bump of `yaxpeax-x86` as well. so, 2.0.0! + +changes: + +* `Operand` variants have had their naming made more consistent. + - many variants starting with "Reg" actually describe a memory access. they + now begin with "Mem" instead. + - several variants mentioned "Scale" in their name, but not "Index", even + though they use an index register. they now do. + - several variants mentioned their constituent parts out of order. for + example, "RegIndexBaseScaleDisp", even though the parts were specified as + base, then index, then scale, then displacement. these names have been + adjusted to reflect the order of their fields, which is roughly the order + those fields are shown when printed. + - `DisplacementU*` operands have always been access to memory at the absolute + address they specify. their names are now `AbsoluteU*` +* `Operand`, across the board, now uses struct-style enum variants, rather than tuple-style. +* the two changes together mean an operand that was + `RegIndexBaseScaleDisp(reg, reg, u8, i32)` + is now + `MemBaseIndexScaleDisp { base, index, scale, disp }` + and similar for other variants. +* two operand kinds, and their masked variants, were never actually constructed, and have been deleted. + - long ago yaxpeax-x86 returned different Operand variants when an index + register was used with scale 1, to hint that no scaling actually occurred. + this was eventually changed to return a scaling Operand variant with + scale==1, but the old variants remained. + - RegIndexBase has been removed + - RegIndexBaseDisp has been removed +* `Prefixes::selects_cs()` has been moved to `Prefixes::cs()`, and the old + useless functions are no more. `inst.prefixes().cs()` is finally a reasonable + way to determine if an instruction reads or writes through the cs prefix. + +fixes: + * fix 32-bit call/jmp not respecting 66 prefix if set - such cases use 16-bit operands, but decoded as if they used 32-bit operands. @@ -35,10 +35,10 @@ //! #[cfg(features="fmt")] //! assert_eq!("xor eax, dword [rcx]", inst.to_string()); //! -//! assert_eq!(Operand::Register(RegSpec::eax()), inst.operand(0)); +//! assert_eq!(Operand::Register { reg: RegSpec::eax() }, inst.operand(0)); //! #[cfg(features="fmt")] //! assert_eq!("eax", inst.operand(0).to_string()); -//! assert_eq!(Operand::RegDeref(RegSpec::rcx()), inst.operand(1)); +//! assert_eq!(Operand::MemDeref { base: RegSpec::rcx() }, inst.operand(1)); //! //! // an operand in isolation does not know the size of memory it references, if any //! #[cfg(features="fmt")] diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index 6cf2def..469bb90 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -430,9 +430,9 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } #[cfg_attr(not(feature="profiling"), inline(always))] #[cfg_attr(feature="profiling", inline(never))] - fn visit_disp(&mut self, reg: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_disp(&mut self, base: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error> { self.f.write_char('[')?; - self.f.write_reg(reg)?; + self.f.write_reg(base)?; self.f.write_fixed_size(" ")?; { @@ -447,23 +447,23 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } self.f.write_fixed_size("]") } - fn visit_deref(&mut self, reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref(&mut self, base: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(reg)?; + self.f.write_reg(base)?; self.f.write_fixed_size("]") } - fn visit_reg_scale(&mut self, reg: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale(&mut self, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(reg)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size("]")?; Ok(()) } - fn visit_reg_scale_disp(&mut self, reg: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp(&mut self, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(reg)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size(" ")?; @@ -480,7 +480,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } self.f.write_char(']') } - fn visit_index_base_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -489,7 +489,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size("]") } - fn visit_index_base_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -510,9 +510,9 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } self.f.write_fixed_size("]") } - fn visit_reg_disp_masked(&mut self, spec: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_disp_masked(&mut self, base: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_char('[')?; - self.f.write_reg(spec)?; + self.f.write_reg(base)?; self.f.write_char(' ')?; let mut v = disp as u32; if disp < 0 { @@ -528,18 +528,18 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_reg_deref_masked(&mut self, spec: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref_masked(&mut self, base: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(spec)?; + self.f.write_reg(base)?; self.f.write_fixed_size("]")?; self.f.write_char('{')?; self.f.write_reg(mask_reg)?; self.f.write_char('}')?; Ok(()) } - fn visit_reg_scale_masked(&mut self, spec: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_masked(&mut self, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(spec)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size("]")?; @@ -548,9 +548,9 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_reg_scale_disp_masked(&mut self, spec: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp_masked(&mut self, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(spec)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size(" ")?; @@ -568,7 +568,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -579,7 +579,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -599,7 +599,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -612,7 +612,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -3860,7 +3860,7 @@ pub(crate) fn contextualize_c<T: DisplaySink>(instr: &Instruction, out: &mut T) let mut out = yaxpeax_arch::display::FmtSink::new(out); use core::fmt::Write; match op { - Operand::ImmediateI8(rel) => { + Operand::ImmediateI8 { imm: rel } => { let rel = if rel >= 0 { out.write_str("$+")?; rel as u8 @@ -3870,7 +3870,7 @@ pub(crate) fn contextualize_c<T: DisplaySink>(instr: &Instruction, out: &mut T) }; out.write_prefixed_u8(rel) } - Operand::ImmediateI32(rel) => { + Operand::ImmediateI32 { imm: rel } => { let rel = if rel >= 0 { out.write_str("$+")?; rel as u32 @@ -4272,10 +4272,10 @@ impl<'a, F: DisplaySink> super::OperandVisitor for RelativeBranchPrinter<'a, F> fn visit_reg(&mut self, _reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_deref(&mut self, _reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref(&mut self, _base: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_disp(&mut self, _reg: RegSpec, _disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_disp(&mut self, _base: RegSpec, _disp: i32) -> Result<Self::Ok, Self::Error> { Ok(false) } #[cfg_attr(feature="profiling", inline(never))] @@ -4338,16 +4338,16 @@ impl<'a, F: DisplaySink> super::OperandVisitor for RelativeBranchPrinter<'a, F> fn visit_abs_u64(&mut self, _imm: u64) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale(&mut self, _reg: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale(&mut self, _index: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale_disp(&mut self, _reg: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp(&mut self, _index: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale_disp(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { Ok(false) } fn visit_other(&mut self) -> Result<Self::Ok, Self::Error> { @@ -4362,28 +4362,28 @@ impl<'a, F: DisplaySink> super::OperandVisitor for RelativeBranchPrinter<'a, F> fn visit_reg_mask_merge_sae_noround(&mut self, _spec: RegSpec, _mask: RegSpec, _merge_mode: MergeMode) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_disp_masked(&mut self, _spec: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_disp_masked(&mut self, _base: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_deref_masked(&mut self, _spec: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref_masked(&mut self, _base: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale_masked(&mut self, _spec: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_masked(&mut self, _index: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale_disp_masked(&mut self, _spec: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp_masked(&mut self, _index: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_masked(&mut self, _base: RegSpec, _index: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_masked(&mut self, _base: RegSpec, _index: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } } diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 0aaa35f..6dabd6d 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -368,91 +368,81 @@ enum SizeCode { #[non_exhaustive] pub enum Operand { /// a sign-extended byte - ImmediateI8(i8), + ImmediateI8 { imm: i8 }, /// a zero-extended byte - ImmediateU8(u8), + ImmediateU8 { imm: u8 }, /// a sign-extended word - ImmediateI16(i16), + ImmediateI16 { imm: i16 }, /// a zero-extended word - ImmediateU16(u16), + ImmediateU16 { imm: u16 }, /// a sign-extended dword - ImmediateI32(i32), + ImmediateI32 { imm: i32 }, /// a zero-extended dword - ImmediateU32(u32), + ImmediateU32 { imm: u32 }, /// a sign-extended qword - ImmediateI64(i64), + ImmediateI64 { imm: i64 }, /// a zero-extended qword - ImmediateU64(u64), + ImmediateU64 { imm: u64 }, /// a bare register operand, such as `rcx`. - Register(RegSpec), + Register { reg: RegSpec }, /// an `avx512` register operand with optional mask register and merge mode, such as /// `zmm3{k4}{z}`. /// /// if the mask register is `k0`, there is no masking applied, and the default x86 operation is /// `MergeMode::Merge`. - RegisterMaskMerge(RegSpec, RegSpec, MergeMode), + RegisterMaskMerge { reg: RegSpec, mask: RegSpec, merge: MergeMode }, /// an `avx512` register operand with optional mask register, merge mode, and suppressed /// exceptions, such as `zmm3{k4}{z}{rd-sae}`. /// /// if the mask register is `k0`, there is no masking applied, and the default x86 operation is /// `MergeMode::Merge`. - RegisterMaskMergeSae(RegSpec, RegSpec, MergeMode, SaeMode), + RegisterMaskMergeSae { reg: RegSpec, mask: RegSpec, merge: MergeMode, sae: SaeMode }, /// an `avx512` register operand with optional mask register, merge mode, and suppressed /// exceptions, with no overridden rounding mode, such as `zmm3{k4}{z}{sae}`. /// /// if the mask register is `k0`, there is no masking applied, and the default x86 operation is /// `MergeMode::Merge`. - RegisterMaskMergeSaeNoround(RegSpec, RegSpec, MergeMode), + RegisterMaskMergeSaeNoround { reg: RegSpec, mask: RegSpec, merge: MergeMode }, /// a memory access to a literal dword address. it's extremely rare that a well-formed x86 /// instruction uses this mode. as an example, `[0x1133]` - DisplacementU32(u32), + AbsoluteU32 { addr: u32 }, /// a memory access to a literal qword address. it's relatively rare that a well-formed x86 /// instruction uses this mode, but plausible. for example, `gs:[0x14]`. segment overrides, /// however, are maintained on the instruction itself. - DisplacementU64(u64), + AbsoluteU64 { addr: u64 }, /// a simple dereference of the address held in some register. for example: `[rsi]`. - RegDeref(RegSpec), + MemDeref { base: RegSpec }, /// a dereference of the address held in some register with offset. for example: `[rsi + 0x14]`. - RegDisp(RegSpec, i32), + Disp { base: RegSpec, disp: i32 }, /// a dereference of the address held in some register scaled by 1, 2, 4, or 8. this is almost always used with the `lea` instruction. for example: `[rdx * 4]`. - RegScale(RegSpec, u8), - /// a dereference of the address from summing two registers. for example: `[rbp + rax]` - RegIndexBase(RegSpec, RegSpec), - /// a dereference of the address from summing two registers with offset. for example: `[rdi + rcx + 0x40]` - RegIndexBaseDisp(RegSpec, RegSpec, i32), + MemIndexScale { index: RegSpec, scale: u8 }, /// a dereference of the address held in some register scaled by 1, 2, 4, or 8 with offset. this is almost always used with the `lea` instruction. for example: `[rax * 4 + 0x30]`. - RegScaleDisp(RegSpec, u8, i32), + MemIndexScaleDisp { index: RegSpec, scale: u8, disp: i32 }, /// a dereference of the address from summing a register and index register scaled by 1, 2, 4, /// or 8. for /// example: `[rsi + rcx * 4]` - RegIndexBaseScale(RegSpec, RegSpec, u8), + MemBaseIndexScale { base: RegSpec, index: RegSpec, scale: u8 }, /// a dereference of the address from summing a register and index register scaled by 1, 2, 4, /// or 8, with offset. for /// example: `[rsi + rcx * 4 + 0x1234]` - RegIndexBaseScaleDisp(RegSpec, RegSpec, u8, i32), + MemBaseIndexScaleDisp { base: RegSpec, index: RegSpec, scale: u8, disp: i32 }, /// an `avx512` dereference of register with optional masking. for example: `[rdx]{k3}` - RegDerefMasked(RegSpec, RegSpec), + MemDerefMasked { base: RegSpec, mask: RegSpec }, /// an `avx512` dereference of register plus offset, with optional masking. for example: `[rsp + 0x40]{k3}` - RegDispMasked(RegSpec, i32, RegSpec), + DispMasked { base: RegSpec, disp: i32, mask: RegSpec }, /// an `avx512` dereference of a register scaled by 1, 2, 4, or 8, with optional masking. this /// seems extraordinarily unlikely to occur in practice. for example: `[rsi * 4]{k2}` - RegScaleMasked(RegSpec, u8, RegSpec), - /// an `avx512` dereference of a register plus index scaled by 1, 2, 4, or 8, with optional masking. - /// for example: `[rsi + rax * 4]{k6}` - RegIndexBaseMasked(RegSpec, RegSpec, RegSpec), - /// an `avx512` dereference of a register plus offset, with optional masking. for example: - /// `[rsi + rax + 0x1313]{k6}` - RegIndexBaseDispMasked(RegSpec, RegSpec, i32, RegSpec), + MemIndexScaleMasked { index: RegSpec, scale: u8, mask: RegSpec }, /// an `avx512` dereference of a register scaled by 1, 2, 4, or 8 plus offset, with optional /// masking. this seems extraordinarily unlikely to occur in practice. for example: `[rsi * /// 4 + 0x1357]{k2}` - RegScaleDispMasked(RegSpec, u8, i32, RegSpec), + MemIndexScaleDispMasked { index: RegSpec, scale: u8, disp: i32, mask: RegSpec }, /// an `avx512` dereference of a register plus index scaled by 1, 2, 4, or 8, with optional /// masking. for example: `[rsi + rax * 4]{k6}` - RegIndexBaseScaleMasked(RegSpec, RegSpec, u8, RegSpec), + MemBaseIndexScaleMasked { base: RegSpec, index: RegSpec, scale: u8, mask: RegSpec }, /// an `avx512` dereference of a register plus index scaled by 1, 2, 4, or 8 and offset, with /// optional masking. for example: `[rsi + rax * 4 + 0x1313]{k6}` - RegIndexBaseScaleDispMasked(RegSpec, RegSpec, u8, i32, RegSpec), + MemBaseIndexScaleDispMasked { base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask: RegSpec }, /// no operand. it is a bug for `yaxpeax-x86` to construct an `Operand` of this kind for public /// use; the instruction's `operand_count` should be reduced so as to make this invisible to /// library clients. @@ -466,11 +456,11 @@ impl OperandSpec { OperandSpec::RegMMM => OperandSpec::RegMMM_maskmerge, OperandSpec::RegVex => OperandSpec::RegVex_maskmerge, OperandSpec::Deref => OperandSpec::Deref_mask, - OperandSpec::RegDisp => OperandSpec::RegDisp_mask, - OperandSpec::RegScale => OperandSpec::RegScale_mask, - OperandSpec::RegScaleDisp => OperandSpec::RegScaleDisp_mask, - OperandSpec::RegIndexBaseScale => OperandSpec::RegIndexBaseScale_mask, - OperandSpec::RegIndexBaseScaleDisp => OperandSpec::RegIndexBaseScaleDisp_mask, + OperandSpec::Disp => OperandSpec::Disp_mask, + OperandSpec::MemIndexScale => OperandSpec::MemIndexScale_mask, + OperandSpec::MemIndexScaleDisp => OperandSpec::MemIndexScaleDisp_mask, + OperandSpec::MemBaseIndexScale => OperandSpec::MemBaseIndexScale_mask, + OperandSpec::MemBaseIndexScaleDisp => OperandSpec::MemBaseIndexScaleDisp_mask, o => o, } } @@ -551,10 +541,10 @@ pub trait OperandVisitor { fn visit_reg(&mut self, reg: RegSpec) -> Result<Self::Ok, Self::Error>; fn visit_deref(&mut self, reg: RegSpec) -> Result<Self::Ok, Self::Error>; fn visit_disp(&mut self, reg: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale(&mut self, reg: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale_disp(&mut self, reg: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale(&mut self, reg: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale_disp(&mut self, reg: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; fn visit_i8(&mut self, imm: i8) -> Result<Self::Ok, Self::Error>; fn visit_u8(&mut self, imm: u8) -> Result<Self::Ok, Self::Error>; fn visit_i16(&mut self, imm: i16) -> Result<Self::Ok, Self::Error>; @@ -568,14 +558,14 @@ pub trait OperandVisitor { fn visit_reg_mask_merge(&mut self, base: RegSpec, mask: RegSpec, merge_mode: MergeMode) -> Result<Self::Ok, Self::Error>; fn visit_reg_mask_merge_sae(&mut self, base: RegSpec, mask: RegSpec, merge_mode: MergeMode, sae_mode: SaeMode) -> Result<Self::Ok, Self::Error>; fn visit_reg_mask_merge_sae_noround(&mut self, base: RegSpec, mask: RegSpec, merge_mode: MergeMode) -> Result<Self::Ok, Self::Error>; - fn visit_reg_disp_masked(&mut self, base: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_reg_deref_masked(&mut self, base: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale_masked(&mut self, base: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale_disp_masked(&mut self, base: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_disp_masked(&mut self, base: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_deref_masked(&mut self, base: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale_masked(&mut self, base: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale_disp_masked(&mut self, base: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; fn visit_other(&mut self) -> Result<Self::Ok, Self::Error>; } @@ -588,140 +578,140 @@ impl Operand { } // the register in modrm_rrr OperandSpec::RegRRR => { - Operand::Register(inst.regs[0]) + Operand::Register { reg: inst.regs[0] } } OperandSpec::RegRRR_maskmerge => { - Operand::RegisterMaskMerge( - inst.regs[0], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMerge { + reg: inst.regs[0], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::RegRRR_maskmerge_sae => { - Operand::RegisterMaskMergeSae( - inst.regs[0], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - SaeMode::from(inst.prefixes.evex_unchecked().vex().l(), inst.prefixes.evex_unchecked().lp()), - ) + Operand::RegisterMaskMergeSae { + reg: inst.regs[0], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + sae: SaeMode::from(inst.prefixes.evex_unchecked().vex().l(), inst.prefixes.evex_unchecked().lp()), + } } OperandSpec::RegRRR_maskmerge_sae_noround => { - Operand::RegisterMaskMergeSaeNoround( - inst.regs[0], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMergeSaeNoround { + reg: inst.regs[0], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } // the register in modrm_mmm (eg modrm mod bits were 11) OperandSpec::RegMMM => { - Operand::Register(inst.regs[1]) + Operand::Register { reg: inst.regs[1] } } OperandSpec::RegMMM_maskmerge => { - Operand::RegisterMaskMerge( - inst.regs[1], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMerge { + reg: inst.regs[1], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::RegMMM_maskmerge_sae_noround => { - Operand::RegisterMaskMergeSaeNoround( - inst.regs[1], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMergeSaeNoround { + reg: inst.regs[1], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::RegVex => { - Operand::Register(inst.regs[3]) + Operand::Register { reg: inst.regs[3]} } OperandSpec::RegVex_maskmerge => { - Operand::RegisterMaskMerge( - inst.regs[3], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMerge { + reg: inst.regs[3], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::Reg4 => { - Operand::Register(RegSpec { num: inst.imm as u8, bank: inst.regs[3].bank }) - } - OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8), - OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8), - OperandSpec::ImmI16 => Operand::ImmediateI16(inst.imm as i16), - OperandSpec::ImmU16 => Operand::ImmediateU16(inst.imm as u16), - OperandSpec::ImmI32 => Operand::ImmediateI32(inst.imm as i32), - OperandSpec::ImmI64 => Operand::ImmediateI64(inst.imm as i64), - OperandSpec::ImmInDispField => Operand::ImmediateU16(inst.disp as u16), - OperandSpec::DispU32 => Operand::DisplacementU32(inst.disp as u32), - OperandSpec::DispU64 => Operand::DisplacementU64(inst.disp as u64), + Operand::Register { reg: RegSpec { num: inst.imm as u8, bank: inst.regs[3].bank }} + } + OperandSpec::ImmI8 => Operand::ImmediateI8 { imm: inst.imm as i8 }, + OperandSpec::ImmU8 => Operand::ImmediateU8 { imm: inst.imm as u8 }, + OperandSpec::ImmI16 => Operand::ImmediateI16 { imm: inst.imm as i16 }, + OperandSpec::ImmU16 => Operand::ImmediateU16 { imm: inst.imm as u16 }, + OperandSpec::ImmI32 => Operand::ImmediateI32 { imm: inst.imm as i32 }, + OperandSpec::ImmI64 => Operand::ImmediateI64 { imm: inst.imm as i64 }, + OperandSpec::ImmInDispField => Operand::ImmediateU16 { imm: inst.disp as u16 }, + OperandSpec::DispU32 => Operand::AbsoluteU32 { addr: inst.disp as u32 }, + OperandSpec::DispU64 => Operand::AbsoluteU64 { addr: inst.disp as u64 }, OperandSpec::Deref => { - Operand::RegDeref(inst.regs[1]) + Operand::MemDeref { base: inst.regs[1] } } OperandSpec::Deref_esi => { - Operand::RegDeref(RegSpec::esi()) + Operand::MemDeref { base: RegSpec::esi() } } OperandSpec::Deref_edi => { - Operand::RegDeref(RegSpec::edi()) + Operand::MemDeref { base: RegSpec::edi() } } OperandSpec::Deref_rsi => { - Operand::RegDeref(RegSpec::rsi()) + Operand::MemDeref { base: RegSpec::rsi() } } OperandSpec::Deref_rdi => { - Operand::RegDeref(RegSpec::rdi()) + Operand::MemDeref { base: RegSpec::rdi() } } - OperandSpec::RegDisp => { - Operand::RegDisp(inst.regs[1], inst.disp as i32) + OperandSpec::Disp => { + Operand::Disp { base: inst.regs[1], disp: inst.disp as i32 } } - OperandSpec::RegScale => { - Operand::RegScale(inst.regs[2], inst.scale) + OperandSpec::MemIndexScale => { + Operand::MemIndexScale { index: inst.regs[2], scale: inst.scale } } - OperandSpec::RegScaleDisp => { - Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32) + OperandSpec::MemIndexScaleDisp => { + Operand::MemIndexScaleDisp { index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } - OperandSpec::RegIndexBaseScale => { - Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale) + OperandSpec::MemBaseIndexScale => { + Operand::MemBaseIndexScale { base: inst.regs[1], index: inst.regs[2], scale: inst.scale } } - OperandSpec::RegIndexBaseScaleDisp => { - Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32) + OperandSpec::MemBaseIndexScaleDisp => { + Operand::MemBaseIndexScaleDisp { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } OperandSpec::Deref_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegDerefMasked(inst.regs[1], RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemDerefMasked { base: inst.regs[1], mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegDeref(inst.regs[1]) + Operand::MemDeref { base: inst.regs[1] } } } - OperandSpec::RegDisp_mask => { + OperandSpec::Disp_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegDispMasked(inst.regs[1], inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::DispMasked { base: inst.regs[1], disp: inst.disp as i32, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegDisp(inst.regs[1], inst.disp as i32) + Operand::Disp { base: inst.regs[1], disp: inst.disp as i32 } } } - OperandSpec::RegScale_mask => { + OperandSpec::MemIndexScale_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegScaleMasked(inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemIndexScaleMasked { index: inst.regs[2], scale: inst.scale, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegScale(inst.regs[2], inst.scale) + Operand::MemIndexScale { index: inst.regs[2], scale: inst.scale } } } - OperandSpec::RegScaleDisp_mask => { + OperandSpec::MemIndexScaleDisp_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegScaleDispMasked(inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemIndexScaleDispMasked { index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32) + Operand::MemIndexScaleDisp { index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } } - OperandSpec::RegIndexBaseScale_mask => { + OperandSpec::MemBaseIndexScale_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegIndexBaseScaleMasked(inst.regs[1], inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemBaseIndexScaleMasked { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale) + Operand::MemBaseIndexScale { base: inst.regs[1], index: inst.regs[2], scale: inst.scale } } } - OperandSpec::RegIndexBaseScaleDisp_mask => { + OperandSpec::MemBaseIndexScaleDisp_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegIndexBaseScaleDispMasked(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemBaseIndexScaleDispMasked { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32) + Operand::MemBaseIndexScaleDisp { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } } } @@ -733,38 +723,34 @@ impl Operand { /// memory. pub fn is_memory(&self) -> bool { match self { - Operand::DisplacementU32(_) | - Operand::DisplacementU64(_) | - Operand::RegDeref(_) | - Operand::RegDisp(_, _) | - Operand::RegScale(_, _) | - Operand::RegIndexBase(_, _) | - Operand::RegIndexBaseDisp(_, _, _) | - Operand::RegScaleDisp(_, _, _) | - Operand::RegIndexBaseScale(_, _, _) | - Operand::RegIndexBaseScaleDisp(_, _, _, _) | - Operand::RegDerefMasked(_, _) | - Operand::RegDispMasked(_, _, _) | - Operand::RegScaleMasked(_, _, _) | - Operand::RegIndexBaseMasked(_, _, _) | - Operand::RegIndexBaseDispMasked(_, _, _, _) | - Operand::RegScaleDispMasked(_, _, _, _) | - Operand::RegIndexBaseScaleMasked(_, _, _, _) | - Operand::RegIndexBaseScaleDispMasked(_, _, _, _, _) => { + Operand::AbsoluteU32 { .. } | + Operand::AbsoluteU64 { .. } | + Operand::MemDeref { .. } | + Operand::Disp { .. } | + Operand::MemIndexScale { .. } | + Operand::MemIndexScaleDisp { .. } | + Operand::MemBaseIndexScale { .. } | + Operand::MemBaseIndexScaleDisp { .. } | + Operand::MemDerefMasked { .. } | + Operand::DispMasked { .. } | + Operand::MemIndexScaleMasked { .. } | + Operand::MemIndexScaleDispMasked { .. } | + Operand::MemBaseIndexScaleMasked { .. } | + Operand::MemBaseIndexScaleDispMasked { .. } => { true }, - Operand::ImmediateI8(_) | - Operand::ImmediateU8(_) | - Operand::ImmediateI16(_) | - Operand::ImmediateU16(_) | - Operand::ImmediateU32(_) | - Operand::ImmediateI32(_) | - Operand::ImmediateU64(_) | - Operand::ImmediateI64(_) | - Operand::Register(_) | - Operand::RegisterMaskMerge(_, _, _) | - Operand::RegisterMaskMergeSae(_, _, _, _) | - Operand::RegisterMaskMergeSaeNoround(_, _, _) | + Operand::ImmediateI8 { .. } | + Operand::ImmediateU8 { .. } | + Operand::ImmediateI16 { .. } | + Operand::ImmediateU16 { .. } | + Operand::ImmediateU32 { .. } | + Operand::ImmediateI32 { .. } | + Operand::ImmediateU64 { .. } | + Operand::ImmediateI64 { .. } | + Operand::Register { .. } | + Operand::RegisterMaskMerge { .. } | + Operand::RegisterMaskMergeSae { .. } | + Operand::RegisterMaskMergeSaeNoround { .. } | Operand::Nothing => { false } @@ -776,26 +762,26 @@ impl Operand { /// `Operand` came from; `None` here means the authoritative width is `instr.mem_size()`. pub fn width(&self) -> Option<u8> { match self { - Operand::Register(reg) => { + Operand::Register { reg } => { Some(reg.width()) } - Operand::RegisterMaskMerge(reg, _, _) => { + Operand::RegisterMaskMerge { reg, .. } => { Some(reg.width()) } - Operand::ImmediateI8(_) | - Operand::ImmediateU8(_) => { + Operand::ImmediateI8 { .. } | + Operand::ImmediateU8 { .. } => { Some(1) } - Operand::ImmediateI16(_) | - Operand::ImmediateU16(_) => { + Operand::ImmediateI16 { .. } | + Operand::ImmediateU16 { .. } => { Some(2) } - Operand::ImmediateI32(_) | - Operand::ImmediateU32(_) => { + Operand::ImmediateI32 { .. } | + Operand::ImmediateU32 { .. } => { Some(4) } - Operand::ImmediateI64(_) | - Operand::ImmediateU64(_) => { + Operand::ImmediateI64 { .. } | + Operand::ImmediateU64 { .. } => { Some(8) } // memory operands or `Nothing` @@ -813,42 +799,38 @@ impl Operand { Operand::Nothing => { visitor.visit_other() } - Operand::Register(reg) => { + Operand::Register { reg } => { visitor.visit_reg(*reg) } - Operand::RegDeref(reg) => { - visitor.visit_deref(*reg) - } - Operand::RegDisp(reg, disp) => { - visitor.visit_disp(*reg, *disp) - } - Operand::ImmediateI8(imm) => visitor.visit_i8(*imm), - Operand::ImmediateU8(imm) => visitor.visit_u8(*imm), - Operand::ImmediateI16(imm) => visitor.visit_i16(*imm), - Operand::ImmediateU16(imm) => visitor.visit_u16(*imm), - Operand::ImmediateI32(imm) => visitor.visit_i32(*imm), - Operand::ImmediateU32(imm) => visitor.visit_u32(*imm), - Operand::ImmediateI64(imm) => visitor.visit_i64(*imm), - Operand::ImmediateU64(imm) => visitor.visit_u64(*imm), - Operand::DisplacementU32(disp) => visitor.visit_abs_u32(*disp), - Operand::DisplacementU64(disp) => visitor.visit_abs_u64(*disp), - Operand::RegScale(reg, scale) => visitor.visit_reg_scale(*reg, *scale), - Operand::RegScaleDisp(reg, scale, disp) => visitor.visit_reg_scale_disp(*reg, *scale, *disp), - Operand::RegIndexBase(_, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegIndexBaseDisp(_, _, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegIndexBaseScale(base, index, scale) => visitor.visit_index_base_scale(*base, *index, *scale), - Operand::RegIndexBaseScaleDisp(base, index, scale, disp) => visitor.visit_index_base_scale_disp(*base, *index, *scale, *disp), - Operand::RegisterMaskMerge(reg, mask, merge) => visitor.visit_reg_mask_merge(*reg, *mask, *merge), - Operand::RegisterMaskMergeSae(reg, mask, merge, sae) => visitor.visit_reg_mask_merge_sae(*reg, *mask, *merge, *sae), - Operand::RegisterMaskMergeSaeNoround(reg, mask, merge) => visitor.visit_reg_mask_merge_sae_noround(*reg, *mask, *merge), - Operand::RegDerefMasked(reg, mask) => visitor.visit_reg_deref_masked(*reg, *mask), - Operand::RegDispMasked(reg, disp, mask) => visitor.visit_reg_disp_masked(*reg, *disp, *mask), - Operand::RegScaleMasked(reg, scale, mask) => visitor.visit_reg_scale_masked(*reg, *scale, *mask), - Operand::RegIndexBaseMasked(_, _, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegIndexBaseDispMasked(_, _, _, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegScaleDispMasked(base, scale, disp, mask) => visitor.visit_reg_scale_disp_masked(*base, *scale, *disp, *mask), - Operand::RegIndexBaseScaleMasked(base, index, scale, mask) => visitor.visit_index_base_scale_masked(*base, *index, *scale, *mask), - Operand::RegIndexBaseScaleDispMasked(base, index, scale, disp, mask) => visitor.visit_index_base_scale_disp_masked(*base, *index, *scale, *disp, *mask), + Operand::MemDeref { base } => { + visitor.visit_deref(*base) + } + Operand::Disp { base, disp } => { + visitor.visit_disp(*base, *disp) + } + Operand::ImmediateI8 { imm } => visitor.visit_i8(*imm), + Operand::ImmediateU8 { imm } => visitor.visit_u8(*imm), + Operand::ImmediateI16 { imm } => visitor.visit_i16(*imm), + Operand::ImmediateU16 { imm } => visitor.visit_u16(*imm), + Operand::ImmediateI32 { imm } => visitor.visit_i32(*imm), + Operand::ImmediateU32 { imm } => visitor.visit_u32(*imm), + Operand::ImmediateI64 { imm } => visitor.visit_i64(*imm), + Operand::ImmediateU64 { imm } => visitor.visit_u64(*imm), + Operand::AbsoluteU32 { addr } => visitor.visit_abs_u32(*addr), + Operand::AbsoluteU64 { addr } => visitor.visit_abs_u64(*addr), + Operand::MemIndexScale { index, scale } => visitor.visit_index_scale(*index, *scale), + Operand::MemIndexScaleDisp { index, scale, disp } => visitor.visit_index_scale_disp(*index, *scale, *disp), + Operand::MemBaseIndexScale { base, index, scale } => visitor.visit_base_index_scale(*base, *index, *scale), + Operand::MemBaseIndexScaleDisp { base, index, scale, disp } => visitor.visit_base_index_scale_disp(*base, *index, *scale, *disp), + Operand::RegisterMaskMerge { reg, mask, merge } => visitor.visit_reg_mask_merge(*reg, *mask, *merge), + Operand::RegisterMaskMergeSae { reg, mask, merge, sae } => visitor.visit_reg_mask_merge_sae(*reg, *mask, *merge, *sae), + Operand::RegisterMaskMergeSaeNoround { reg, mask, merge } => visitor.visit_reg_mask_merge_sae_noround(*reg, *mask, *merge), + Operand::MemDerefMasked { base, mask } => visitor.visit_deref_masked(*base, *mask), + Operand::DispMasked { base, disp, mask } => visitor.visit_disp_masked(*base, *disp, *mask), + Operand::MemIndexScaleMasked { index, scale, mask } => visitor.visit_index_scale_masked(*index, *scale, *mask), + Operand::MemIndexScaleDispMasked { index, scale, disp, mask } => visitor.visit_index_scale_disp_masked(*index, *scale, *disp, *mask), + Operand::MemBaseIndexScaleMasked { base, index, scale, mask } => visitor.visit_base_index_scale_masked(*base, *index, *scale, *mask), + Operand::MemBaseIndexScaleDispMasked { base, index, scale, disp, mask } => visitor.visit_base_index_scale_disp_masked(*base, *index, *scale, *disp, *mask), } } } @@ -941,16 +923,16 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[ /// } /// } /// -/// if let Operand::Register(regspec) = instruction.operand(0) { +/// if let Operand::Register { reg } = instruction.operand(0) { /// #[cfg(feature="fmt")] -/// println!("first operand is {}", regspec); -/// show_register_class_info(regspec.class()); +/// println!("first operand is {}", reg); +/// show_register_class_info(reg.class()); /// } /// -/// if let Operand::Register(regspec) = instruction.operand(1) { +/// if let Operand::Register { reg } = instruction.operand(1) { /// #[cfg(feature="fmt")] -/// println!("first operand is {}", regspec); -/// show_register_class_info(regspec.class()); +/// println!("first operand is {}", reg); +/// show_register_class_info(reg.class()); /// } /// ``` /// @@ -2753,17 +2735,17 @@ enum OperandSpec { Deref_edi = 0x90, Deref_rsi = 0x91, Deref_rdi = 0x92, - RegDisp = 0x93, - RegScale = 0x94, - RegScaleDisp = 0x95, - RegIndexBaseScale = 0x96, - RegIndexBaseScaleDisp = 0x97, + Disp = 0x93, + MemIndexScale = 0x94, + MemIndexScaleDisp = 0x95, + MemBaseIndexScale = 0x96, + MemBaseIndexScaleDisp = 0x97, Deref_mask = 0xce, - RegDisp_mask = 0xd3, - RegScale_mask = 0xd4, - RegScaleDisp_mask = 0xd5, - RegIndexBaseScale_mask = 0xd6, - RegIndexBaseScaleDisp_mask = 0xd7, + Disp_mask = 0xd3, + MemIndexScale_mask = 0xd4, + MemIndexScaleDisp_mask = 0xd5, + MemBaseIndexScale_mask = 0xd6, + MemBaseIndexScaleDisp_mask = 0xd7, } // the Hash, Eq, and PartialEq impls here are possibly misleading. @@ -4471,7 +4453,7 @@ impl Instruction { // visitor.visit_other() visitor.visit_deref(RegSpec::rdi()) } - OperandSpec::RegDisp => { + OperandSpec::Disp => { visitor.visit_disp(self.regs[1], self.disp as i32) } OperandSpec::RegRRR_maskmerge => { @@ -4526,61 +4508,58 @@ impl Instruction { OperandSpec::ImmInDispField => visitor.visit_u16(self.disp as u16), OperandSpec::DispU32 => visitor.visit_abs_u32(self.disp as u32), OperandSpec::DispU64 => visitor.visit_abs_u64(self.disp as u64), - OperandSpec::RegScale => { - visitor.visit_reg_scale(self.regs[2], self.scale) + OperandSpec::MemIndexScale => { + visitor.visit_index_scale(self.regs[2], self.scale) } - OperandSpec::RegScaleDisp => { - visitor.visit_reg_scale_disp(self.regs[2], self.scale, self.disp as i32) + OperandSpec::MemIndexScaleDisp => { + visitor.visit_index_scale_disp(self.regs[2], self.scale, self.disp as i32) } - OperandSpec::RegIndexBaseScale => { - visitor.visit_index_base_scale(self.regs[1], self.regs[2], self.scale) - /* - Operand::RegIndexBaseScale(self.regs[1], self.regs[2], self.scale) - */ + OperandSpec::MemBaseIndexScale => { + visitor.visit_base_index_scale(self.regs[1], self.regs[2], self.scale) } - OperandSpec::RegIndexBaseScaleDisp => { - visitor.visit_index_base_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) + OperandSpec::MemBaseIndexScaleDisp => { + visitor.visit_base_index_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) } OperandSpec::Deref_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_deref_masked(self.regs[1], RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_deref_masked(self.regs[1], RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { visitor.visit_deref(self.regs[1]) } } - OperandSpec::RegDisp_mask => { + OperandSpec::Disp_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_disp_masked(self.regs[1], self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_disp_masked(self.regs[1], self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { visitor.visit_disp(self.regs[1], self.disp as i32) } } - OperandSpec::RegScale_mask => { + OperandSpec::MemIndexScale_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_scale_masked(self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_index_scale_masked(self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_reg_scale(self.regs[2], self.scale) + visitor.visit_index_scale(self.regs[2], self.scale) } } - OperandSpec::RegScaleDisp_mask => { + OperandSpec::MemIndexScaleDisp_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_scale_disp_masked(self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_index_scale_disp_masked(self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_reg_scale_disp(self.regs[2], self.scale, self.disp as i32) + visitor.visit_index_scale_disp(self.regs[2], self.scale, self.disp as i32) } } - OperandSpec::RegIndexBaseScale_mask => { + OperandSpec::MemBaseIndexScale_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_index_base_scale_masked(self.regs[1], self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_base_index_scale_masked(self.regs[1], self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_index_base_scale(self.regs[1], self.regs[2], self.scale) + visitor.visit_base_index_scale(self.regs[1], self.regs[2], self.scale) } } - OperandSpec::RegIndexBaseScaleDisp_mask => { + OperandSpec::MemBaseIndexScaleDisp_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_index_base_scale_disp_masked(self.regs[1], self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_base_index_scale_disp_masked(self.regs[1], self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_index_base_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) + visitor.visit_base_index_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) } } } @@ -6253,7 +6232,7 @@ fn read_sib< InnerDescription::Misc("mod bits select no base register") .with_id(sib_start + 0) ); - OperandSpec::RegScale + OperandSpec::MemIndexScale } else { sink.record( modrm_start + 6, @@ -6261,7 +6240,7 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScale + OperandSpec::MemBaseIndexScale } } } else { @@ -6280,7 +6259,7 @@ fn read_sib< InnerDescription::RegisterNumber("iii", instr.regs[2].num & 0b111, instr.regs[2]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScale + OperandSpec::MemBaseIndexScale } } @@ -6314,7 +6293,7 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegDisp + OperandSpec::Disp } } else { sink.record( @@ -6330,7 +6309,7 @@ fn read_sib< InnerDescription::Misc("mod bits select no base register, [index+disp] only") .with_id(sib_start + 0) ); - OperandSpec::RegScaleDisp + OperandSpec::MemIndexScaleDisp } else { sink.record( modrm_start + 6, @@ -6338,7 +6317,7 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScaleDisp + OperandSpec::MemBaseIndexScaleDisp } } } else { @@ -6355,7 +6334,7 @@ fn read_sib< InnerDescription::Misc("iii + rex.x selects no index register") .with_id(sib_start + 0) ); - OperandSpec::RegDisp + OperandSpec::Disp } else { sink.record( sib_start + 3, @@ -6363,7 +6342,7 @@ fn read_sib< InnerDescription::RegisterNumber("iii", instr.regs[2].num & 0b111, instr.regs[2]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScaleDisp + OperandSpec::MemBaseIndexScaleDisp } } }; @@ -6449,7 +6428,7 @@ fn read_M< OperandSpec::Deref } else { instr.disp = disp as i64 as u64; - OperandSpec::RegDisp + OperandSpec::Disp } } else { sink.record( @@ -6491,7 +6470,7 @@ fn read_M< OperandSpec::Deref } else { instr.disp = disp as i64 as u64; - OperandSpec::RegDisp + OperandSpec::Disp } } }; diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs index dc31dbf..1629b4e 100644 --- a/src/protected_mode/display.rs +++ b/src/protected_mode/display.rs @@ -406,9 +406,9 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } #[cfg_attr(not(feature="profiling"), inline(always))] #[cfg_attr(feature="profiling", inline(never))] - fn visit_disp(&mut self, reg: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_disp(&mut self, base: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error> { self.f.write_char('[')?; - self.f.write_reg(reg)?; + self.f.write_reg(base)?; self.f.write_fixed_size(" ")?; { @@ -423,23 +423,23 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } self.f.write_fixed_size("]") } - fn visit_deref(&mut self, reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref(&mut self, base: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(reg)?; + self.f.write_reg(base)?; self.f.write_fixed_size("]") } - fn visit_reg_scale(&mut self, reg: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale(&mut self, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(reg)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size("]")?; Ok(()) } - fn visit_reg_scale_disp(&mut self, reg: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp(&mut self, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(reg)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size(" ")?; @@ -456,7 +456,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } self.f.write_char(']') } - fn visit_index_base_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -465,7 +465,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size("]") } - fn visit_index_base_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -486,9 +486,9 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } self.f.write_fixed_size("]") } - fn visit_reg_disp_masked(&mut self, spec: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_disp_masked(&mut self, base: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_char('[')?; - self.f.write_reg(spec)?; + self.f.write_reg(base)?; self.f.write_char(' ')?; let mut v = disp as u32; if disp < 0 { @@ -504,18 +504,18 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_reg_deref_masked(&mut self, spec: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref_masked(&mut self, base: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(spec)?; + self.f.write_reg(base)?; self.f.write_fixed_size("]")?; self.f.write_char('{')?; self.f.write_reg(mask_reg)?; self.f.write_char('}')?; Ok(()) } - fn visit_reg_scale_masked(&mut self, spec: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_masked(&mut self, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(spec)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size("]")?; @@ -524,9 +524,9 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_reg_scale_disp_masked(&mut self, spec: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp_masked(&mut self, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(spec)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size(" ")?; @@ -544,7 +544,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -555,7 +555,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -575,7 +575,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -588,7 +588,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -2420,7 +2420,7 @@ pub(crate) fn contextualize_c<T: DisplaySink>(instr: &Instruction, out: &mut T) let mut out = yaxpeax_arch::display::FmtSink::new(out); use core::fmt::Write; match op { - Operand::ImmediateI8(rel) => { + Operand::ImmediateI8 { imm: rel } => { let rel = if rel >= 0 { out.write_str("$+")?; rel as u8 @@ -2430,7 +2430,7 @@ pub(crate) fn contextualize_c<T: DisplaySink>(instr: &Instruction, out: &mut T) }; out.write_prefixed_u8(rel) } - Operand::ImmediateI32(rel) => { + Operand::ImmediateI32 { imm: rel } => { let rel = if rel >= 0 { out.write_str("$+")?; rel as u32 @@ -2824,10 +2824,10 @@ impl<'a, F: DisplaySink> super::OperandVisitor for RelativeBranchPrinter<'a, F> fn visit_reg(&mut self, _reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_deref(&mut self, _reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref(&mut self, _base: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_disp(&mut self, _reg: RegSpec, _disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_disp(&mut self, _base: RegSpec, _disp: i32) -> Result<Self::Ok, Self::Error> { Ok(false) } #[cfg_attr(feature="profiling", inline(never))] @@ -2884,16 +2884,16 @@ impl<'a, F: DisplaySink> super::OperandVisitor for RelativeBranchPrinter<'a, F> fn visit_abs_u32(&mut self, _imm: u32) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale(&mut self, _reg: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale(&mut self, _index: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale_disp(&mut self, _reg: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp(&mut self, _index: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale_disp(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { Ok(false) } fn visit_other(&mut self) -> Result<Self::Ok, Self::Error> { @@ -2908,28 +2908,28 @@ impl<'a, F: DisplaySink> super::OperandVisitor for RelativeBranchPrinter<'a, F> fn visit_reg_mask_merge_sae_noround(&mut self, _spec: RegSpec, _mask: RegSpec, _merge_mode: MergeMode) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_disp_masked(&mut self, _spec: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_disp_masked(&mut self, _base: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_deref_masked(&mut self, _spec: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref_masked(&mut self, _base: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale_masked(&mut self, _spec: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_masked(&mut self, _index: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale_disp_masked(&mut self, _spec: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp_masked(&mut self, _index: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_masked(&mut self, _base: RegSpec, _index: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_masked(&mut self, _base: RegSpec, _index: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } fn visit_absolute_far_address(&mut self, _segment: u16, _address: u32) -> Result<Self::Ok, Self::Error> { diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 154a746..081be20 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -306,87 +306,77 @@ enum SizeCode { #[non_exhaustive] pub enum Operand { /// a sign-extended byte - ImmediateI8(i8), + ImmediateI8 { imm: i8 }, /// a zero-extended byte - ImmediateU8(u8), + ImmediateU8 { imm: u8 }, /// a sign-extended word - ImmediateI16(i16), + ImmediateI16 { imm: i16 }, /// a zero-extended word - ImmediateU16(u16), + ImmediateU16 { imm: u16 }, /// a sign-extended dword - ImmediateI32(i32), + ImmediateI32 { imm: i32 }, /// a zero-extended dword - ImmediateU32(u32), + ImmediateU32 { imm: u32 }, /// a bare register operand, such as `rcx`. - Register(RegSpec), + Register { reg: RegSpec }, /// an `avx512` register operand with optional mask register and merge mode, such as /// `zmm3{k4}{z}`. /// /// if the mask register is `k0`, there is no masking applied, and the default x86 operation is /// `MergeMode::Merge`. - RegisterMaskMerge(RegSpec, RegSpec, MergeMode), + RegisterMaskMerge { reg: RegSpec, mask: RegSpec, merge: MergeMode }, /// an `avx512` register operand with optional mask register, merge mode, and suppressed /// exceptions, such as `zmm3{k4}{z}{rd-sae}`. /// /// if the mask register is `k0`, there is no masking applied, and the default x86 operation is /// `MergeMode::Merge`. - RegisterMaskMergeSae(RegSpec, RegSpec, MergeMode, SaeMode), + RegisterMaskMergeSae { reg: RegSpec, mask: RegSpec, merge: MergeMode, sae: SaeMode }, /// an `avx512` register operand with optional mask register, merge mode, and suppressed /// exceptions, with no overridden rounding mode, such as `zmm3{k4}{z}{sae}`. /// /// if the mask register is `k0`, there is no masking applied, and the default x86 operation is /// `MergeMode::Merge`. - RegisterMaskMergeSaeNoround(RegSpec, RegSpec, MergeMode), + RegisterMaskMergeSaeNoround { reg: RegSpec, mask: RegSpec, merge: MergeMode }, /// a memory access to a literal word address. it's extremely rare that a well-formed x86 /// instruction uses this mode. as an example, `[0x1133]` - DisplacementU16(u16), + AbsoluteU16 { addr: u16 }, /// a memory access to a literal qword address. it's relatively rare that a well-formed x86 /// instruction uses this mode, but plausible. for example, `fs:[0x14]`. segment overrides, /// however, are maintained on the instruction itself. - DisplacementU32(u32), + AbsoluteU32 { addr: u32 }, /// a simple dereference of the address held in some register. for example: `[esi]`. - RegDeref(RegSpec), + MemDeref { base: RegSpec }, /// a dereference of the address held in some register with offset. for example: `[esi + 0x14]`. - RegDisp(RegSpec, i32), + Disp { base: RegSpec, disp: i32 }, /// a dereference of the address held in some register scaled by 1, 2, 4, or 8. this is almost always used with the `lea` instruction. for example: `[edx * 4]`. - RegScale(RegSpec, u8), - /// a dereference of the address from summing two registers. for example: `[ebp + rax]` - RegIndexBase(RegSpec, RegSpec), - /// a dereference of the address from summing two registers with offset. for example: `[edi + ecx + 0x40]` - RegIndexBaseDisp(RegSpec, RegSpec, i32), + MemIndexScale { index: RegSpec, scale: u8 }, /// a dereference of the address held in some register scaled by 1, 2, 4, or 8 with offset. this is almost always used with the `lea` instruction. for example: `[eax * 4 + 0x30]`. - RegScaleDisp(RegSpec, u8, i32), + MemIndexScaleDisp { index: RegSpec, scale: u8, disp: i32 }, /// a dereference of the address from summing a register and index register scaled by 1, 2, 4, /// or 8. for /// example: `[esi + ecx * 4]` - RegIndexBaseScale(RegSpec, RegSpec, u8), + MemBaseIndexScale { base: RegSpec, index: RegSpec, scale: u8 }, /// a dereference of the address from summing a register and index register scaled by 1, 2, 4, /// or 8, with offset. for /// example: `[esi + ecx * 4 + 0x1234]` - RegIndexBaseScaleDisp(RegSpec, RegSpec, u8, i32), + MemBaseIndexScaleDisp { base: RegSpec, index: RegSpec, scale: u8, disp: i32 }, /// an `avx512` dereference of register with optional masking. for example: `[edx]{k3}` - RegDerefMasked(RegSpec, RegSpec), + MemDerefMasked { base: RegSpec, mask: RegSpec }, /// an `avx512` dereference of register plus offset, with optional masking. for example: `[esp + 0x40]{k3}` - RegDispMasked(RegSpec, i32, RegSpec), + DispMasked { base: RegSpec, disp: i32, mask: RegSpec }, /// an `avx512` dereference of a register scaled by 1, 2, 4, or 8, with optional masking. this /// seems extraordinarily unlikely to occur in practice. for example: `[esi * 4]{k2}` - RegScaleMasked(RegSpec, u8, RegSpec), - /// an `avx512` dereference of a register plus index scaled by 1, 2, 4, or 8, with optional masking. - /// for example: `[esi + eax * 4]{k6}` - RegIndexBaseMasked(RegSpec, RegSpec, RegSpec), - /// an `avx512` dereference of a register plus offset, with optional masking. for example: - /// `[esi + eax + 0x1313]{k6}` - RegIndexBaseDispMasked(RegSpec, RegSpec, i32, RegSpec), + MemIndexScaleMasked { index: RegSpec, scale: u8, mask: RegSpec }, /// an `avx512` dereference of a register scaled by 1, 2, 4, or 8 plus offset, with optional /// masking. this seems extraordinarily unlikely to occur in practice. for example: `[esi * /// 4 + 0x1357]{k2}` - RegScaleDispMasked(RegSpec, u8, i32, RegSpec), + MemIndexScaleDispMasked { index: RegSpec, scale: u8, disp: i32, mask: RegSpec }, /// an `avx512` dereference of a register plus index scaled by 1, 2, 4, or 8, with optional /// masking. for example: `[esi + eax * 4]{k6}` - RegIndexBaseScaleMasked(RegSpec, RegSpec, u8, RegSpec), + MemBaseIndexScaleMasked { base: RegSpec, index: RegSpec, scale: u8, mask: RegSpec }, /// an `avx512` dereference of a register plus index scaled by 1, 2, 4, or 8 and offset, with /// optional masking. for example: `[esi + eax * 4 + 0x1313]{k6}` - RegIndexBaseScaleDispMasked(RegSpec, RegSpec, u8, i32, RegSpec), + MemBaseIndexScaleDispMasked { base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask: RegSpec }, /// no operand. it is a bug for `yaxpeax-x86` to construct an `Operand` of this kind for public /// use; the instruction's `operand_count` should be reduced so as to make this invisible to /// library clients. @@ -403,11 +393,11 @@ impl OperandSpec { OperandSpec::RegMMM => OperandSpec::RegMMM_maskmerge, OperandSpec::RegVex => OperandSpec::RegVex_maskmerge, OperandSpec::Deref => OperandSpec::Deref_mask, - OperandSpec::RegDisp => OperandSpec::RegDisp_mask, - OperandSpec::RegScale => OperandSpec::RegScale_mask, - OperandSpec::RegScaleDisp => OperandSpec::RegScaleDisp_mask, - OperandSpec::RegIndexBaseScale => OperandSpec::RegIndexBaseScale_mask, - OperandSpec::RegIndexBaseScaleDisp => OperandSpec::RegIndexBaseScaleDisp_mask, + OperandSpec::Disp => OperandSpec::Disp_mask, + OperandSpec::MemIndexScale => OperandSpec::MemIndexScale_mask, + OperandSpec::MemIndexScaleDisp => OperandSpec::MemIndexScaleDisp_mask, + OperandSpec::MemBaseIndexScale => OperandSpec::MemBaseIndexScale_mask, + OperandSpec::MemBaseIndexScaleDisp => OperandSpec::MemBaseIndexScaleDisp_mask, o => o, } } @@ -487,10 +477,10 @@ pub trait OperandVisitor { fn visit_reg(&mut self, reg: RegSpec) -> Result<Self::Ok, Self::Error>; fn visit_deref(&mut self, reg: RegSpec) -> Result<Self::Ok, Self::Error>; fn visit_disp(&mut self, reg: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale(&mut self, reg: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale_disp(&mut self, reg: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale(&mut self, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale_disp(&mut self, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; fn visit_i8(&mut self, imm: i8) -> Result<Self::Ok, Self::Error>; fn visit_u8(&mut self, imm: u8) -> Result<Self::Ok, Self::Error>; fn visit_i16(&mut self, imm: i16) -> Result<Self::Ok, Self::Error>; @@ -502,14 +492,14 @@ pub trait OperandVisitor { fn visit_reg_mask_merge(&mut self, base: RegSpec, mask: RegSpec, merge_mode: MergeMode) -> Result<Self::Ok, Self::Error>; fn visit_reg_mask_merge_sae(&mut self, base: RegSpec, mask: RegSpec, merge_mode: MergeMode, sae_mode: SaeMode) -> Result<Self::Ok, Self::Error>; fn visit_reg_mask_merge_sae_noround(&mut self, base: RegSpec, mask: RegSpec, merge_mode: MergeMode) -> Result<Self::Ok, Self::Error>; - fn visit_reg_disp_masked(&mut self, base: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_reg_deref_masked(&mut self, base: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale_masked(&mut self, base: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale_disp_masked(&mut self, base: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_disp_masked(&mut self, base: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_deref_masked(&mut self, base: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale_masked(&mut self, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale_disp_masked(&mut self, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; fn visit_absolute_far_address(&mut self, segment: u16, address: u32) -> Result<Self::Ok, Self::Error>; fn visit_other(&mut self) -> Result<Self::Ok, Self::Error>; @@ -523,139 +513,139 @@ impl Operand { } // the register in regs[0] OperandSpec::RegRRR => { - Operand::Register(inst.regs[0]) + Operand::Register { reg: inst.regs[0] } } OperandSpec::RegRRR_maskmerge => { - Operand::RegisterMaskMerge( - inst.regs[0], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMerge { + reg: inst.regs[0], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::RegRRR_maskmerge_sae => { - Operand::RegisterMaskMergeSae( - inst.regs[0], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - SaeMode::from(inst.prefixes.evex_unchecked().vex().l(), inst.prefixes.evex_unchecked().lp()), - ) + Operand::RegisterMaskMergeSae { + reg: inst.regs[0], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + sae: SaeMode::from(inst.prefixes.evex_unchecked().vex().l(), inst.prefixes.evex_unchecked().lp()), + } } OperandSpec::RegRRR_maskmerge_sae_noround => { - Operand::RegisterMaskMergeSaeNoround( - inst.regs[0], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMergeSaeNoround { + reg: inst.regs[0], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } // the register in regs[1] (eg modrm mod bits were 11) OperandSpec::RegMMM => { - Operand::Register(inst.regs[1]) + Operand::Register { reg: inst.regs[1] } } OperandSpec::RegMMM_maskmerge => { - Operand::RegisterMaskMerge( - inst.regs[1], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMerge { + reg: inst.regs[1], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::RegMMM_maskmerge_sae_noround => { - Operand::RegisterMaskMergeSaeNoround( - inst.regs[1], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMergeSaeNoround { + reg: inst.regs[1], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::RegVex => { - Operand::Register(inst.regs[3]) + Operand::Register { reg: inst.regs[3] } } OperandSpec::RegVex_maskmerge => { - Operand::RegisterMaskMerge( - inst.regs[3], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMerge { + reg: inst.regs[3], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::Reg4 => { - Operand::Register(RegSpec { num: inst.imm as u8, bank: inst.regs[3].bank }) - } - OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8), - OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8), - OperandSpec::ImmI16 => Operand::ImmediateI16(inst.imm as i16), - OperandSpec::ImmU16 => Operand::ImmediateU16(inst.imm as u16), - OperandSpec::ImmI32 => Operand::ImmediateI32(inst.imm as i32), - OperandSpec::ImmInDispField => Operand::ImmediateU16(inst.disp as u16), - OperandSpec::DispU16 => Operand::DisplacementU16(inst.disp as u16), - OperandSpec::DispU32 => Operand::DisplacementU32(inst.disp), + Operand::Register { reg: RegSpec { num: inst.imm as u8, bank: inst.regs[3].bank }} + } + OperandSpec::ImmI8 => Operand::ImmediateI8 { imm: inst.imm as i8 }, + OperandSpec::ImmU8 => Operand::ImmediateU8 { imm: inst.imm as u8 }, + OperandSpec::ImmI16 => Operand::ImmediateI16 { imm: inst.imm as i16 }, + OperandSpec::ImmU16 => Operand::ImmediateU16 { imm: inst.imm as u16 }, + OperandSpec::ImmI32 => Operand::ImmediateI32 { imm: inst.imm as i32 }, + OperandSpec::ImmInDispField => Operand::ImmediateU16 { imm: inst.disp as u16 }, + OperandSpec::DispU16 => Operand::AbsoluteU16 { addr: inst.disp as u16 }, + OperandSpec::DispU32 => Operand::AbsoluteU32 { addr: inst.disp }, OperandSpec::Deref => { - Operand::RegDeref(inst.regs[1]) + Operand::MemDeref { base: inst.regs[1] } } OperandSpec::Deref_si => { - Operand::RegDeref(RegSpec::si()) + Operand::MemDeref { base: RegSpec::si() } } OperandSpec::Deref_di => { - Operand::RegDeref(RegSpec::di()) + Operand::MemDeref { base: RegSpec::di() } } OperandSpec::Deref_esi => { - Operand::RegDeref(RegSpec::esi()) + Operand::MemDeref { base: RegSpec::esi() } } OperandSpec::Deref_edi => { - Operand::RegDeref(RegSpec::edi()) + Operand::MemDeref { base: RegSpec::edi() } } - OperandSpec::RegDisp => { - Operand::RegDisp(inst.regs[1], inst.disp as i32) + OperandSpec::Disp => { + Operand::Disp { base: inst.regs[1], disp: inst.disp as i32 } } - OperandSpec::RegScale => { - Operand::RegScale(inst.regs[2], inst.scale) + OperandSpec::MemIndexScale => { + Operand::MemIndexScale { index: inst.regs[2], scale: inst.scale } } - OperandSpec::RegScaleDisp => { - Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32) + OperandSpec::MemIndexScaleDisp => { + Operand::MemIndexScaleDisp { index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } - OperandSpec::RegIndexBaseScale => { - Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale) + OperandSpec::MemBaseIndexScale => { + Operand::MemBaseIndexScale { base: inst.regs[1], index: inst.regs[2], scale: inst.scale } } - OperandSpec::RegIndexBaseScaleDisp => { - Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32) + OperandSpec::MemBaseIndexScaleDisp => { + Operand::MemBaseIndexScaleDisp { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } OperandSpec::Deref_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegDerefMasked(inst.regs[1], RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemDerefMasked { base: inst.regs[1], mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegDeref(inst.regs[1]) + Operand::MemDeref { base: inst.regs[1] } } } - OperandSpec::RegDisp_mask => { + OperandSpec::Disp_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegDispMasked(inst.regs[1], inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::DispMasked { base: inst.regs[1], disp: inst.disp as i32, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegDisp(inst.regs[1], inst.disp as i32) + Operand::Disp { base: inst.regs[1], disp: inst.disp as i32 } } } - OperandSpec::RegScale_mask => { + OperandSpec::MemIndexScale_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegScaleMasked(inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemIndexScaleMasked { index: inst.regs[2], scale: inst.scale, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegScale(inst.regs[2], inst.scale) + Operand::MemIndexScale { index: inst.regs[2], scale: inst.scale } } } - OperandSpec::RegScaleDisp_mask => { + OperandSpec::MemIndexScaleDisp_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegScaleDispMasked(inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemIndexScaleDispMasked { index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32) + Operand::MemIndexScaleDisp { index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } } - OperandSpec::RegIndexBaseScale_mask => { + OperandSpec::MemBaseIndexScale_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegIndexBaseScaleMasked(inst.regs[1], inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemBaseIndexScaleMasked { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale) + Operand::MemBaseIndexScale { base: inst.regs[1], index: inst.regs[2], scale: inst.scale } } } - OperandSpec::RegIndexBaseScaleDisp_mask => { + OperandSpec::MemBaseIndexScaleDisp_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegIndexBaseScaleDispMasked(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemBaseIndexScaleDispMasked { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32) + Operand::MemBaseIndexScaleDisp { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } } OperandSpec::AbsoluteFarAddress => { @@ -672,36 +662,32 @@ impl Operand { /// memory. pub fn is_memory(&self) -> bool { match self { - Operand::DisplacementU16(_) | - Operand::DisplacementU32(_) | - Operand::RegDeref(_) | - Operand::RegDisp(_, _) | - Operand::RegScale(_, _) | - Operand::RegIndexBase(_, _) | - Operand::RegIndexBaseDisp(_, _, _) | - Operand::RegScaleDisp(_, _, _) | - Operand::RegIndexBaseScale(_, _, _) | - Operand::RegIndexBaseScaleDisp(_, _, _, _) | - Operand::RegDerefMasked(_, _) | - Operand::RegDispMasked(_, _, _) | - Operand::RegScaleMasked(_, _, _) | - Operand::RegIndexBaseMasked(_, _, _) | - Operand::RegIndexBaseDispMasked(_, _, _, _) | - Operand::RegScaleDispMasked(_, _, _, _) | - Operand::RegIndexBaseScaleMasked(_, _, _, _) | - Operand::RegIndexBaseScaleDispMasked(_, _, _, _, _) => { + Operand::AbsoluteU16 { .. } | + Operand::AbsoluteU32 { .. } | + Operand::MemDeref { .. } | + Operand::Disp { .. } | + Operand::MemIndexScale { .. } | + Operand::MemIndexScaleDisp { .. } | + Operand::MemBaseIndexScale { .. } | + Operand::MemBaseIndexScaleDisp { .. } | + Operand::MemDerefMasked { .. } | + Operand::DispMasked { .. } | + Operand::MemIndexScaleMasked { .. } | + Operand::MemIndexScaleDispMasked { .. } | + Operand::MemBaseIndexScaleMasked { .. } | + Operand::MemBaseIndexScaleDispMasked { .. } => { true }, - Operand::ImmediateI8(_) | - Operand::ImmediateU8(_) | - Operand::ImmediateI16(_) | - Operand::ImmediateU16(_) | - Operand::ImmediateU32(_) | - Operand::ImmediateI32(_) | - Operand::Register(_) | - Operand::RegisterMaskMerge(_, _, _) | - Operand::RegisterMaskMergeSae(_, _, _, _) | - Operand::RegisterMaskMergeSaeNoround(_, _, _) | + Operand::ImmediateI8 { .. } | + Operand::ImmediateU8 { .. } | + Operand::ImmediateI16 { .. } | + Operand::ImmediateU16 { .. } | + Operand::ImmediateU32 { .. } | + Operand::ImmediateI32 { .. } | + Operand::Register { .. } | + Operand::RegisterMaskMerge { .. } | + Operand::RegisterMaskMergeSae { .. } | + Operand::RegisterMaskMergeSaeNoround { .. } | Operand::AbsoluteFarAddress { .. } | Operand::Nothing => { false @@ -714,22 +700,22 @@ impl Operand { /// `Operand` came from; `None` here means the authoritative width is `instr.mem_size()`. pub fn width(&self) -> Option<u8> { match self { - Operand::Register(reg) => { + Operand::Register { reg } => { Some(reg.width()) } - Operand::RegisterMaskMerge(reg, _, _) => { + Operand::RegisterMaskMerge { reg, .. } => { Some(reg.width()) } - Operand::ImmediateI8(_) | - Operand::ImmediateU8(_) => { + Operand::ImmediateI8 { .. } | + Operand::ImmediateU8 { .. } => { Some(1) } - Operand::ImmediateI16(_) | - Operand::ImmediateU16(_) => { + Operand::ImmediateI16 { .. } | + Operand::ImmediateU16 { .. } => { Some(2) } - Operand::ImmediateI32(_) | - Operand::ImmediateU32(_) => { + Operand::ImmediateI32 { .. } | + Operand::ImmediateU32 { .. } => { Some(4) } // memory operands or `Nothing` @@ -747,40 +733,36 @@ impl Operand { Operand::Nothing => { visitor.visit_other() } - Operand::Register(reg) => { + Operand::Register { reg } => { visitor.visit_reg(*reg) } - Operand::RegDeref(reg) => { - visitor.visit_deref(*reg) - } - Operand::RegDisp(reg, disp) => { - visitor.visit_disp(*reg, *disp) - } - Operand::ImmediateI8(imm) => visitor.visit_i8(*imm), - Operand::ImmediateU8(imm) => visitor.visit_u8(*imm), - Operand::ImmediateI16(imm) => visitor.visit_i16(*imm), - Operand::ImmediateU16(imm) => visitor.visit_u16(*imm), - Operand::ImmediateI32(imm) => visitor.visit_i32(*imm), - Operand::ImmediateU32(imm) => visitor.visit_u32(*imm), - Operand::DisplacementU16(disp) => visitor.visit_abs_u16(*disp), - Operand::DisplacementU32(disp) => visitor.visit_abs_u32(*disp), - Operand::RegScale(reg, scale) => visitor.visit_reg_scale(*reg, *scale), - Operand::RegScaleDisp(reg, scale, disp) => visitor.visit_reg_scale_disp(*reg, *scale, *disp), - Operand::RegIndexBase(_, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegIndexBaseDisp(_, _, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegIndexBaseScale(base, index, scale) => visitor.visit_index_base_scale(*base, *index, *scale), - Operand::RegIndexBaseScaleDisp(base, index, scale, disp) => visitor.visit_index_base_scale_disp(*base, *index, *scale, *disp), - Operand::RegisterMaskMerge(reg, mask, merge) => visitor.visit_reg_mask_merge(*reg, *mask, *merge), - Operand::RegisterMaskMergeSae(reg, mask, merge, sae) => visitor.visit_reg_mask_merge_sae(*reg, *mask, *merge, *sae), - Operand::RegisterMaskMergeSaeNoround(reg, mask, merge) => visitor.visit_reg_mask_merge_sae_noround(*reg, *mask, *merge), - Operand::RegDerefMasked(reg, mask) => visitor.visit_reg_deref_masked(*reg, *mask), - Operand::RegDispMasked(reg, disp, mask) => visitor.visit_reg_disp_masked(*reg, *disp, *mask), - Operand::RegScaleMasked(reg, scale, mask) => visitor.visit_reg_scale_masked(*reg, *scale, *mask), - Operand::RegIndexBaseMasked(_, _, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegIndexBaseDispMasked(_, _, _, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegScaleDispMasked(base, scale, disp, mask) => visitor.visit_reg_scale_disp_masked(*base, *scale, *disp, *mask), - Operand::RegIndexBaseScaleMasked(base, index, scale, mask) => visitor.visit_index_base_scale_masked(*base, *index, *scale, *mask), - Operand::RegIndexBaseScaleDispMasked(base, index, scale, disp, mask) => visitor.visit_index_base_scale_disp_masked(*base, *index, *scale, *disp, *mask), + Operand::MemDeref { base } => { + visitor.visit_deref(*base) + } + Operand::Disp { base, disp } => { + visitor.visit_disp(*base, *disp) + } + Operand::ImmediateI8 { imm } => visitor.visit_i8(*imm), + Operand::ImmediateU8 { imm } => visitor.visit_u8(*imm), + Operand::ImmediateI16 { imm } => visitor.visit_i16(*imm), + Operand::ImmediateU16 { imm } => visitor.visit_u16(*imm), + Operand::ImmediateI32 { imm } => visitor.visit_i32(*imm), + Operand::ImmediateU32 { imm } => visitor.visit_u32(*imm), + Operand::AbsoluteU16 { addr } => visitor.visit_abs_u16(*addr), + Operand::AbsoluteU32 { addr } => visitor.visit_abs_u32(*addr), + Operand::MemIndexScale { index, scale } => visitor.visit_index_scale(*index, *scale), + Operand::MemIndexScaleDisp { index, scale, disp } => visitor.visit_index_scale_disp(*index, *scale, *disp), + Operand::MemBaseIndexScale { base, index, scale } => visitor.visit_base_index_scale(*base, *index, *scale), + Operand::MemBaseIndexScaleDisp { base, index, scale, disp } => visitor.visit_base_index_scale_disp(*base, *index, *scale, *disp), + Operand::RegisterMaskMerge { reg, mask, merge } => visitor.visit_reg_mask_merge(*reg, *mask, *merge), + Operand::RegisterMaskMergeSae { reg, mask, merge, sae } => visitor.visit_reg_mask_merge_sae(*reg, *mask, *merge, *sae), + Operand::RegisterMaskMergeSaeNoround { reg, mask, merge } => visitor.visit_reg_mask_merge_sae_noround(*reg, *mask, *merge), + Operand::MemDerefMasked { base, mask } => visitor.visit_deref_masked(*base, *mask), + Operand::DispMasked { base, disp, mask } => visitor.visit_disp_masked(*base, *disp, *mask), + Operand::MemIndexScaleMasked { index, scale, mask } => visitor.visit_index_scale_masked(*index, *scale, *mask), + Operand::MemIndexScaleDispMasked { index, scale, disp, mask } => visitor.visit_index_scale_disp_masked(*index, *scale, *disp, *mask), + Operand::MemBaseIndexScaleMasked { base, index, scale, mask } => visitor.visit_base_index_scale_masked(*base, *index, *scale, *mask), + Operand::MemBaseIndexScaleDispMasked { base, index, scale, disp, mask } => visitor.visit_base_index_scale_disp_masked(*base, *index, *scale, *disp, *mask), Operand::AbsoluteFarAddress { segment, address } => visitor.visit_absolute_far_address(*segment, *address), } } @@ -865,16 +847,16 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[ /// } /// } /// -/// if let Operand::Register(regspec) = instruction.operand(0) { +/// if let Operand::Register { reg } = instruction.operand(0) { /// #[cfg(feature="fmt")] -/// println!("first operand is {}", regspec); -/// show_register_class_info(regspec.class()); +/// println!("first operand is {}", reg); +/// show_register_class_info(reg.class()); /// } /// -/// if let Operand::Register(regspec) = instruction.operand(1) { +/// if let Operand::Register { reg } = instruction.operand(1) { /// #[cfg(feature="fmt")] -/// println!("first operand is {}", regspec); -/// show_register_class_info(regspec.class()); +/// println!("second operand is {}", reg); +/// show_register_class_info(reg.class()); /// } /// ``` /// @@ -2667,17 +2649,17 @@ enum OperandSpec { Deref_di = 0x90, Deref_esi = 0x91, Deref_edi = 0x92, - RegDisp = 0x93, - RegScale = 0x94, - RegScaleDisp = 0x95, - RegIndexBaseScale = 0x96, - RegIndexBaseScaleDisp = 0x97, + Disp = 0x93, + MemIndexScale = 0x94, + MemIndexScaleDisp = 0x95, + MemBaseIndexScale = 0x96, + MemBaseIndexScaleDisp = 0x97, Deref_mask = 0xce, - RegDisp_mask = 0xd3, - RegScale_mask = 0xd4, - RegScaleDisp_mask = 0xd5, - RegIndexBaseScale_mask = 0xd6, - RegIndexBaseScaleDisp_mask = 0xd7, + Disp_mask = 0xd3, + MemIndexScale_mask = 0xd4, + MemIndexScaleDisp_mask = 0xd5, + MemBaseIndexScale_mask = 0xd6, + MemBaseIndexScaleDisp_mask = 0xd7, // u16:u{16,32} immediate address for a far call AbsoluteFarAddress = 0x18, } @@ -4385,7 +4367,7 @@ impl Instruction { // visitor.visit_other() visitor.visit_deref(RegSpec::edi()) } - OperandSpec::RegDisp => { + OperandSpec::Disp => { visitor.visit_disp(self.regs[1], self.disp as i32) } OperandSpec::RegRRR_maskmerge => { @@ -4439,61 +4421,58 @@ impl Instruction { OperandSpec::ImmInDispField => visitor.visit_u16(self.disp as u16), OperandSpec::DispU16 => visitor.visit_abs_u16(self.disp as u16), OperandSpec::DispU32 => visitor.visit_abs_u32(self.disp as u32), - OperandSpec::RegScale => { - visitor.visit_reg_scale(self.regs[2], self.scale) + OperandSpec::MemIndexScale => { + visitor.visit_index_scale(self.regs[2], self.scale) } - OperandSpec::RegScaleDisp => { - visitor.visit_reg_scale_disp(self.regs[2], self.scale, self.disp as i32) + OperandSpec::MemIndexScaleDisp => { + visitor.visit_index_scale_disp(self.regs[2], self.scale, self.disp as i32) } - OperandSpec::RegIndexBaseScale => { - visitor.visit_index_base_scale(self.regs[1], self.regs[2], self.scale) - /* - Operand::RegIndexBaseScale(self.regs[1], self.regs[2], self.scale) - */ + OperandSpec::MemBaseIndexScale => { + visitor.visit_base_index_scale(self.regs[1], self.regs[2], self.scale) } - OperandSpec::RegIndexBaseScaleDisp => { - visitor.visit_index_base_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) + OperandSpec::MemBaseIndexScaleDisp => { + visitor.visit_base_index_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) } OperandSpec::Deref_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_deref_masked(self.regs[1], RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_deref_masked(self.regs[1], RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { visitor.visit_deref(self.regs[1]) } } - OperandSpec::RegDisp_mask => { + OperandSpec::Disp_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_disp_masked(self.regs[1], self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_disp_masked(self.regs[1], self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { visitor.visit_disp(self.regs[1], self.disp as i32) } } - OperandSpec::RegScale_mask => { + OperandSpec::MemIndexScale_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_scale_masked(self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_index_scale_masked(self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_reg_scale(self.regs[2], self.scale) + visitor.visit_index_scale(self.regs[2], self.scale) } } - OperandSpec::RegScaleDisp_mask => { + OperandSpec::MemIndexScaleDisp_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_scale_disp_masked(self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_index_scale_disp_masked(self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_reg_scale_disp(self.regs[2], self.scale, self.disp as i32) + visitor.visit_index_scale_disp(self.regs[2], self.scale, self.disp as i32) } } - OperandSpec::RegIndexBaseScale_mask => { + OperandSpec::MemBaseIndexScale_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_index_base_scale_masked(self.regs[1], self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_base_index_scale_masked(self.regs[1], self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_index_base_scale(self.regs[1], self.regs[2], self.scale) + visitor.visit_base_index_scale(self.regs[1], self.regs[2], self.scale) } } - OperandSpec::RegIndexBaseScaleDisp_mask => { + OperandSpec::MemBaseIndexScaleDisp_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_index_base_scale_disp_masked(self.regs[1], self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_base_index_scale_disp_masked(self.regs[1], self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_index_base_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) + visitor.visit_base_index_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) } } OperandSpec::AbsoluteFarAddress => { @@ -6155,7 +6134,7 @@ fn read_sib< InnerDescription::Misc("mod bits select no base register") .with_id(sib_start + 0) ); - OperandSpec::RegScale + OperandSpec::MemIndexScale } else { sink.record( modrm_start + 6, @@ -6163,7 +6142,7 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScale + OperandSpec::MemBaseIndexScale } } } else { @@ -6182,7 +6161,7 @@ fn read_sib< InnerDescription::RegisterNumber("iii", instr.regs[2].num, instr.regs[2]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScale + OperandSpec::MemBaseIndexScale } } @@ -6216,7 +6195,7 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegDisp + OperandSpec::Disp } } else { sink.record( @@ -6232,7 +6211,7 @@ fn read_sib< InnerDescription::Misc("mod bits select no base register, [index+disp] only") .with_id(sib_start + 0) ); - OperandSpec::RegScaleDisp + OperandSpec::MemIndexScaleDisp } else { sink.record( modrm_start + 6, @@ -6240,7 +6219,7 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScaleDisp + OperandSpec::MemBaseIndexScaleDisp } } } else { @@ -6257,7 +6236,7 @@ fn read_sib< InnerDescription::Misc("iii selects no index register") .with_id(sib_start + 0) ); - OperandSpec::RegDisp + OperandSpec::Disp } else { sink.record( sib_start + 3, @@ -6265,7 +6244,7 @@ fn read_sib< InnerDescription::RegisterNumber("iii", instr.regs[2].num, instr.regs[2]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScaleDisp + OperandSpec::MemBaseIndexScaleDisp } } }; @@ -6375,7 +6354,7 @@ fn read_M_16bit< Ok(OperandSpec::Deref) } else { instr.scale = 1; - Ok(OperandSpec::RegIndexBaseScale) + Ok(OperandSpec::MemBaseIndexScale) } }, 0b01 => { @@ -6396,13 +6375,13 @@ fn read_M_16bit< ); if mmm > 3 { if instr.disp != 0 { - Ok(OperandSpec::RegDisp) + Ok(OperandSpec::Disp) } else { Ok(OperandSpec::Deref) } } else { instr.scale = 1; - Ok(OperandSpec::RegIndexBaseScaleDisp) + Ok(OperandSpec::MemBaseIndexScaleDisp) } }, 0b10 => { @@ -6423,13 +6402,13 @@ fn read_M_16bit< ); if mmm > 3 { if instr.disp != 0 { - Ok(OperandSpec::RegDisp) + Ok(OperandSpec::Disp) } else { Ok(OperandSpec::Deref) } } else { instr.scale = 1; - Ok(OperandSpec::RegIndexBaseScaleDisp) + Ok(OperandSpec::MemBaseIndexScaleDisp) } }, _ => { @@ -6523,7 +6502,7 @@ fn read_M< OperandSpec::Deref } else { instr.disp = disp as i32 as u32; - OperandSpec::RegDisp + OperandSpec::Disp } } }; diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs index 38f95bb..bea11fc 100644 --- a/src/real_mode/display.rs +++ b/src/real_mode/display.rs @@ -406,9 +406,9 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } #[cfg_attr(not(feature="profiling"), inline(always))] #[cfg_attr(feature="profiling", inline(never))] - fn visit_disp(&mut self, reg: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_disp(&mut self, base: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error> { self.f.write_char('[')?; - self.f.write_reg(reg)?; + self.f.write_reg(base)?; self.f.write_fixed_size(" ")?; { @@ -423,23 +423,23 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } self.f.write_fixed_size("]") } - fn visit_deref(&mut self, reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref(&mut self, base: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(reg)?; + self.f.write_reg(base)?; self.f.write_fixed_size("]") } - fn visit_reg_scale(&mut self, reg: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale(&mut self, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(reg)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size("]")?; Ok(()) } - fn visit_reg_scale_disp(&mut self, reg: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp(&mut self, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(reg)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size(" ")?; @@ -456,7 +456,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } self.f.write_char(']') } - fn visit_index_base_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -465,7 +465,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size("]") } - fn visit_index_base_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -486,9 +486,9 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> } self.f.write_fixed_size("]") } - fn visit_reg_disp_masked(&mut self, spec: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_disp_masked(&mut self, base: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_char('[')?; - self.f.write_reg(spec)?; + self.f.write_reg(base)?; self.f.write_char(' ')?; let mut v = disp as u32; if disp < 0 { @@ -504,18 +504,18 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_reg_deref_masked(&mut self, spec: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref_masked(&mut self, base: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(spec)?; + self.f.write_reg(base)?; self.f.write_fixed_size("]")?; self.f.write_char('{')?; self.f.write_reg(mask_reg)?; self.f.write_char('}')?; Ok(()) } - fn visit_reg_scale_masked(&mut self, spec: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_masked(&mut self, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(spec)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size("]")?; @@ -524,9 +524,9 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_reg_scale_disp_masked(&mut self, spec: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp_masked(&mut self, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; - self.f.write_reg(spec)?; + self.f.write_reg(index)?; self.f.write_fixed_size(" * ")?; self.f.write_char((0x30 + scale) as char)?; // translate scale=1 to '1', scale=2 to '2', etc self.f.write_fixed_size(" ")?; @@ -544,7 +544,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -555,7 +555,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -575,7 +575,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -588,7 +588,7 @@ impl <T: DisplaySink> super::OperandVisitor for DisplayingOperandVisitor<'_, T> self.f.write_char('}')?; Ok(()) } - fn visit_index_base_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { self.f.write_fixed_size("[")?; self.f.write_reg(base)?; self.f.write_fixed_size(" + ")?; @@ -2420,7 +2420,7 @@ pub(crate) fn contextualize_c<T: DisplaySink>(instr: &Instruction, out: &mut T) let mut out = yaxpeax_arch::display::FmtSink::new(out); use core::fmt::Write; match op { - Operand::ImmediateI8(rel) => { + Operand::ImmediateI8 { imm: rel } => { let rel = if rel >= 0 { out.write_str("$+")?; rel as u8 @@ -2430,7 +2430,7 @@ pub(crate) fn contextualize_c<T: DisplaySink>(instr: &Instruction, out: &mut T) }; out.write_prefixed_u8(rel) } - Operand::ImmediateI32(rel) => { + Operand::ImmediateI32 { imm: rel } => { let rel = if rel >= 0 { out.write_str("$+")?; rel as u32 @@ -2824,10 +2824,10 @@ impl<'a, F: DisplaySink> super::OperandVisitor for RelativeBranchPrinter<'a, F> fn visit_reg(&mut self, _reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_deref(&mut self, _reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref(&mut self, _base: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_disp(&mut self, _reg: RegSpec, _disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_disp(&mut self, _base: RegSpec, _disp: i32) -> Result<Self::Ok, Self::Error> { Ok(false) } #[cfg_attr(feature="profiling", inline(never))] @@ -2884,16 +2884,16 @@ impl<'a, F: DisplaySink> super::OperandVisitor for RelativeBranchPrinter<'a, F> fn visit_abs_u32(&mut self, _imm: u32) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale(&mut self, _reg: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale(&mut self, _index: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale_disp(&mut self, _reg: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp(&mut self, _index: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale_disp(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32) -> Result<Self::Ok, Self::Error> { Ok(false) } fn visit_other(&mut self) -> Result<Self::Ok, Self::Error> { @@ -2908,28 +2908,28 @@ impl<'a, F: DisplaySink> super::OperandVisitor for RelativeBranchPrinter<'a, F> fn visit_reg_mask_merge_sae_noround(&mut self, _spec: RegSpec, _mask: RegSpec, _merge_mode: MergeMode) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_disp_masked(&mut self, _spec: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_disp_masked(&mut self, _base: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_deref_masked(&mut self, _spec: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_deref_masked(&mut self, _base: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale_masked(&mut self, _spec: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_masked(&mut self, _index: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_reg_scale_disp_masked(&mut self, _spec: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_index_scale_disp_masked(&mut self, _index: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_masked(&mut self, _base: RegSpec, _index: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_masked(&mut self, _base: RegSpec, _index: RegSpec, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } - fn visit_index_base_scale_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { + fn visit_base_index_scale_disp_masked(&mut self, _base: RegSpec, _index: RegSpec, _scale: u8, _disp: i32, _mask_reg: RegSpec) -> Result<Self::Ok, Self::Error> { Ok(false) } fn visit_absolute_far_address(&mut self, _segment: u16, _address: u32) -> Result<Self::Ok, Self::Error> { diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index b29cd1a..b06a525 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -306,87 +306,77 @@ enum SizeCode { #[non_exhaustive] pub enum Operand { /// a sign-extended byte - ImmediateI8(i8), + ImmediateI8 { imm: i8 }, /// a zero-extended byte - ImmediateU8(u8), + ImmediateU8 { imm: u8 }, /// a sign-extended word - ImmediateI16(i16), + ImmediateI16 { imm: i16 }, /// a zero-extended word - ImmediateU16(u16), + ImmediateU16 { imm: u16 }, /// a sign-extended dword - ImmediateI32(i32), + ImmediateI32 { imm: i32 }, /// a zero-extended dword - ImmediateU32(u32), + ImmediateU32 { imm: u32 }, /// a bare register operand, such as `rcx`. - Register(RegSpec), + Register { reg: RegSpec }, /// an `avx512` register operand with optional mask register and merge mode, such as /// `zmm3{k4}{z}`. /// /// if the mask register is `k0`, there is no masking applied, and the default x86 operation is /// `MergeMode::Merge`. - RegisterMaskMerge(RegSpec, RegSpec, MergeMode), + RegisterMaskMerge { reg: RegSpec, mask: RegSpec, merge: MergeMode }, /// an `avx512` register operand with optional mask register, merge mode, and suppressed /// exceptions, such as `zmm3{k4}{z}{rd-sae}`. /// /// if the mask register is `k0`, there is no masking applied, and the default x86 operation is /// `MergeMode::Merge`. - RegisterMaskMergeSae(RegSpec, RegSpec, MergeMode, SaeMode), + RegisterMaskMergeSae { reg: RegSpec, mask: RegSpec, merge: MergeMode, sae: SaeMode }, /// an `avx512` register operand with optional mask register, merge mode, and suppressed /// exceptions, with no overridden rounding mode, such as `zmm3{k4}{z}{sae}`. /// /// if the mask register is `k0`, there is no masking applied, and the default x86 operation is /// `MergeMode::Merge`. - RegisterMaskMergeSaeNoround(RegSpec, RegSpec, MergeMode), + RegisterMaskMergeSaeNoround { reg: RegSpec, mask: RegSpec, merge: MergeMode }, /// a memory access to a literal word address. it's extremely rare that a well-formed x86 /// instruction uses this mode. as an example, `[0x1133]` - DisplacementU16(u16), + AbsoluteU16 { addr: u16 }, /// a memory access to a literal qword address. it's relatively rare that a well-formed x86 /// instruction uses this mode, but plausible. for example, `fs:[0x14]`. segment overrides, /// however, are maintained on the instruction itself. - DisplacementU32(u32), + AbsoluteU32 { addr: u32 }, /// a simple dereference of the address held in some register. for example: `[esi]`. - RegDeref(RegSpec), + MemDeref { base: RegSpec }, /// a dereference of the address held in some register with offset. for example: `[esi + 0x14]`. - RegDisp(RegSpec, i32), + MemDisp { base: RegSpec, disp: i32 }, /// a dereference of the address held in some register scaled by 1, 2, 4, or 8. this is almost always used with the `lea` instruction. for example: `[edx * 4]`. - RegScale(RegSpec, u8), - /// a dereference of the address from summing two registers. for example: `[ebp + rax]` - RegIndexBase(RegSpec, RegSpec), - /// a dereference of the address from summing two registers with offset. for example: `[edi + ecx + 0x40]` - RegIndexBaseDisp(RegSpec, RegSpec, i32), + MemIndexScale { index: RegSpec, scale: u8 }, /// a dereference of the address held in some register scaled by 1, 2, 4, or 8 with offset. this is almost always used with the `lea` instruction. for example: `[eax * 4 + 0x30]`. - RegScaleDisp(RegSpec, u8, i32), + MemIndexScaleDisp { index: RegSpec, scale: u8, disp: i32 }, /// a dereference of the address from summing a register and index register scaled by 1, 2, 4, /// or 8. for /// example: `[esi + ecx * 4]` - RegIndexBaseScale(RegSpec, RegSpec, u8), + MemBaseIndexScale { base: RegSpec, index: RegSpec, scale: u8 }, /// a dereference of the address from summing a register and index register scaled by 1, 2, 4, /// or 8, with offset. for /// example: `[esi + ecx * 4 + 0x1234]` - RegIndexBaseScaleDisp(RegSpec, RegSpec, u8, i32), + MemBaseIndexScaleDisp { base: RegSpec, index: RegSpec, scale: u8, disp: i32 }, /// an `avx512` dereference of register with optional masking. for example: `[edx]{k3}` - RegDerefMasked(RegSpec, RegSpec), + MemDerefMasked { base: RegSpec, mask: RegSpec }, /// an `avx512` dereference of register plus offset, with optional masking. for example: `[esp + 0x40]{k3}` - RegDispMasked(RegSpec, i32, RegSpec), + MemDispMasked { base: RegSpec, disp: i32, mask: RegSpec }, /// an `avx512` dereference of a register scaled by 1, 2, 4, or 8, with optional masking. this /// seems extraordinarily unlikely to occur in practice. for example: `[esi * 4]{k2}` - RegScaleMasked(RegSpec, u8, RegSpec), - /// an `avx512` dereference of a register plus index scaled by 1, 2, 4, or 8, with optional masking. - /// for example: `[esi + eax * 4]{k6}` - RegIndexBaseMasked(RegSpec, RegSpec, RegSpec), - /// an `avx512` dereference of a register plus offset, with optional masking. for example: - /// `[esi + eax + 0x1313]{k6}` - RegIndexBaseDispMasked(RegSpec, RegSpec, i32, RegSpec), + MemIndexScaleMasked { index: RegSpec, scale: u8, mask: RegSpec }, /// an `avx512` dereference of a register scaled by 1, 2, 4, or 8 plus offset, with optional /// masking. this seems extraordinarily unlikely to occur in practice. for example: `[esi * /// 4 + 0x1357]{k2}` - RegScaleDispMasked(RegSpec, u8, i32, RegSpec), + MemIndexScaleDispMasked { index: RegSpec, scale: u8, disp: i32, mask: RegSpec }, /// an `avx512` dereference of a register plus index scaled by 1, 2, 4, or 8, with optional /// masking. for example: `[esi + eax * 4]{k6}` - RegIndexBaseScaleMasked(RegSpec, RegSpec, u8, RegSpec), + MemBaseIndexScaleMasked { base: RegSpec, index: RegSpec, scale: u8, mask: RegSpec }, /// an `avx512` dereference of a register plus index scaled by 1, 2, 4, or 8 and offset, with /// optional masking. for example: `[esi + eax * 4 + 0x1313]{k6}` - RegIndexBaseScaleDispMasked(RegSpec, RegSpec, u8, i32, RegSpec), + MemBaseIndexScaleDispMasked { base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask: RegSpec }, /// no operand. it is a bug for `yaxpeax-x86` to construct an `Operand` of this kind for public /// use; the instruction's `operand_count` should be reduced so as to make this invisible to /// library clients. @@ -403,11 +393,11 @@ impl OperandSpec { OperandSpec::RegMMM => OperandSpec::RegMMM_maskmerge, OperandSpec::RegVex => OperandSpec::RegVex_maskmerge, OperandSpec::Deref => OperandSpec::Deref_mask, - OperandSpec::RegDisp => OperandSpec::RegDisp_mask, - OperandSpec::RegScale => OperandSpec::RegScale_mask, - OperandSpec::RegScaleDisp => OperandSpec::RegScaleDisp_mask, - OperandSpec::RegIndexBaseScale => OperandSpec::RegIndexBaseScale_mask, - OperandSpec::RegIndexBaseScaleDisp => OperandSpec::RegIndexBaseScaleDisp_mask, + OperandSpec::Disp => OperandSpec::Disp_mask, + OperandSpec::MemIndexScale => OperandSpec::MemIndexScale_mask, + OperandSpec::MemIndexScaleDisp => OperandSpec::MemIndexScaleDisp_mask, + OperandSpec::MemBaseIndexScale => OperandSpec::MemBaseIndexScale_mask, + OperandSpec::MemBaseIndexScaleDisp => OperandSpec::MemBaseIndexScaleDisp_mask, o => o, } } @@ -485,12 +475,12 @@ pub trait OperandVisitor { type Error; fn visit_reg(&mut self, reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_deref(&mut self, reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_disp(&mut self, reg: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale(&mut self, reg: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale_disp(&mut self, reg: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; + fn visit_deref(&mut self, base: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_disp(&mut self, base: RegSpec, disp: i32) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale(&mut self, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale(&mut self, base: RegSpec, index: RegSpec, scale: u8) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale_disp(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale_disp(&mut self, index: RegSpec, scale: u8, disp: i32) -> Result<Self::Ok, Self::Error>; fn visit_i8(&mut self, imm: i8) -> Result<Self::Ok, Self::Error>; fn visit_u8(&mut self, imm: u8) -> Result<Self::Ok, Self::Error>; fn visit_i16(&mut self, imm: i16) -> Result<Self::Ok, Self::Error>; @@ -502,14 +492,14 @@ pub trait OperandVisitor { fn visit_reg_mask_merge(&mut self, base: RegSpec, mask: RegSpec, merge_mode: MergeMode) -> Result<Self::Ok, Self::Error>; fn visit_reg_mask_merge_sae(&mut self, base: RegSpec, mask: RegSpec, merge_mode: MergeMode, sae_mode: SaeMode) -> Result<Self::Ok, Self::Error>; fn visit_reg_mask_merge_sae_noround(&mut self, base: RegSpec, mask: RegSpec, merge_mode: MergeMode) -> Result<Self::Ok, Self::Error>; - fn visit_reg_disp_masked(&mut self, base: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_reg_deref_masked(&mut self, base: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale_masked(&mut self, base: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_reg_scale_disp_masked(&mut self, base: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; - fn visit_index_base_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_disp_masked(&mut self, base: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_deref_masked(&mut self, base: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale_masked(&mut self, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_index_scale_disp_masked(&mut self, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_masked(&mut self, base: RegSpec, index: RegSpec, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_disp_masked(&mut self, base: RegSpec, index: RegSpec, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; + fn visit_base_index_scale_disp_masked(&mut self, base: RegSpec, index: RegSpec, scale: u8, disp: i32, mask_reg: RegSpec) -> Result<Self::Ok, Self::Error>; fn visit_absolute_far_address(&mut self, segment: u16, address: u32) -> Result<Self::Ok, Self::Error>; fn visit_other(&mut self) -> Result<Self::Ok, Self::Error>; @@ -523,139 +513,139 @@ impl Operand { } // the register in regs[0] OperandSpec::RegRRR => { - Operand::Register(inst.regs[0]) + Operand::Register { reg: inst.regs[0] } } OperandSpec::RegRRR_maskmerge => { - Operand::RegisterMaskMerge( - inst.regs[0], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMerge { + reg: inst.regs[0], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::RegRRR_maskmerge_sae => { - Operand::RegisterMaskMergeSae( - inst.regs[0], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - SaeMode::from(inst.prefixes.evex_unchecked().vex().l(), inst.prefixes.evex_unchecked().lp()), - ) + Operand::RegisterMaskMergeSae { + reg: inst.regs[0], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + sae: SaeMode::from(inst.prefixes.evex_unchecked().vex().l(), inst.prefixes.evex_unchecked().lp()), + } } OperandSpec::RegRRR_maskmerge_sae_noround => { - Operand::RegisterMaskMergeSaeNoround( - inst.regs[0], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMergeSaeNoround { + reg: inst.regs[0], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } // the register in regs[1] (eg modrm mod bits were 11) OperandSpec::RegMMM => { - Operand::Register(inst.regs[1]) + Operand::Register { reg: inst.regs[1] } } OperandSpec::RegMMM_maskmerge => { - Operand::RegisterMaskMerge( - inst.regs[1], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMerge { + reg: inst.regs[1], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::RegMMM_maskmerge_sae_noround => { - Operand::RegisterMaskMergeSaeNoround( - inst.regs[1], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMergeSaeNoround { + reg: inst.regs[1], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::RegVex => { - Operand::Register(inst.regs[3]) + Operand::Register { reg: inst.regs[3] } } OperandSpec::RegVex_maskmerge => { - Operand::RegisterMaskMerge( - inst.regs[3], - RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), - MergeMode::from(inst.prefixes.evex_unchecked().merge()), - ) + Operand::RegisterMaskMerge { + reg: inst.regs[3], + mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()), + merge: MergeMode::from(inst.prefixes.evex_unchecked().merge()), + } } OperandSpec::Reg4 => { - Operand::Register(RegSpec { num: inst.imm as u8, bank: inst.regs[3].bank }) - } - OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8), - OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8), - OperandSpec::ImmI16 => Operand::ImmediateI16(inst.imm as i16), - OperandSpec::ImmU16 => Operand::ImmediateU16(inst.imm as u16), - OperandSpec::ImmI32 => Operand::ImmediateI32(inst.imm as i32), - OperandSpec::ImmInDispField => Operand::ImmediateU16(inst.disp as u16), - OperandSpec::DispU16 => Operand::DisplacementU16(inst.disp as u16), - OperandSpec::DispU32 => Operand::DisplacementU32(inst.disp), + Operand::Register { reg: RegSpec { num: inst.imm as u8, bank: inst.regs[3].bank } } + } + OperandSpec::ImmI8 => Operand::ImmediateI8 { imm: inst.imm as i8 }, + OperandSpec::ImmU8 => Operand::ImmediateU8 { imm: inst.imm as u8 }, + OperandSpec::ImmI16 => Operand::ImmediateI16 { imm: inst.imm as i16 }, + OperandSpec::ImmU16 => Operand::ImmediateU16 { imm: inst.imm as u16 }, + OperandSpec::ImmI32 => Operand::ImmediateI32 { imm: inst.imm as i32 }, + OperandSpec::ImmInDispField => Operand::ImmediateU16 { imm: inst.disp as u16 }, + OperandSpec::DispU16 => Operand::AbsoluteU16 { addr: inst.disp as u16 }, + OperandSpec::DispU32 => Operand::AbsoluteU32 { addr: inst.disp }, OperandSpec::Deref => { - Operand::RegDeref(inst.regs[1]) + Operand::MemDeref { base: inst.regs[1] } } OperandSpec::Deref_si => { - Operand::RegDeref(RegSpec::si()) + Operand::MemDeref { base: RegSpec::si() } } OperandSpec::Deref_di => { - Operand::RegDeref(RegSpec::di()) + Operand::MemDeref { base: RegSpec::di() } } OperandSpec::Deref_esi => { - Operand::RegDeref(RegSpec::esi()) + Operand::MemDeref { base: RegSpec::esi() } } OperandSpec::Deref_edi => { - Operand::RegDeref(RegSpec::edi()) + Operand::MemDeref { base: RegSpec::edi() } } - OperandSpec::RegDisp => { - Operand::RegDisp(inst.regs[1], inst.disp as i32) + OperandSpec::Disp => { + Operand::MemDisp { base: inst.regs[1], disp: inst.disp as i32 } } - OperandSpec::RegScale => { - Operand::RegScale(inst.regs[2], inst.scale) + OperandSpec::MemIndexScale => { + Operand::MemIndexScale { index: inst.regs[2], scale: inst.scale } } - OperandSpec::RegScaleDisp => { - Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32) + OperandSpec::MemIndexScaleDisp => { + Operand::MemIndexScaleDisp { index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } - OperandSpec::RegIndexBaseScale => { - Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale) + OperandSpec::MemBaseIndexScale => { + Operand::MemBaseIndexScale { base: inst.regs[1], index: inst.regs[2], scale: inst.scale } } - OperandSpec::RegIndexBaseScaleDisp => { - Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32) + OperandSpec::MemBaseIndexScaleDisp => { + Operand::MemBaseIndexScaleDisp { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } OperandSpec::Deref_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegDerefMasked(inst.regs[1], RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemDerefMasked { base: inst.regs[1], mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegDeref(inst.regs[1]) + Operand::MemDeref { base: inst.regs[1] } } } - OperandSpec::RegDisp_mask => { + OperandSpec::Disp_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegDispMasked(inst.regs[1], inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemDispMasked { base: inst.regs[1], disp: inst.disp as i32, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegDisp(inst.regs[1], inst.disp as i32) + Operand::MemDisp { base: inst.regs[1], disp: inst.disp as i32 } } } - OperandSpec::RegScale_mask => { + OperandSpec::MemIndexScale_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegScaleMasked(inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemIndexScaleMasked { index: inst.regs[2], scale: inst.scale, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegScale(inst.regs[2], inst.scale) + Operand::MemIndexScale { index: inst.regs[2], scale: inst.scale } } } - OperandSpec::RegScaleDisp_mask => { + OperandSpec::MemIndexScaleDisp_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegScaleDispMasked(inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemIndexScaleDispMasked { index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32) + Operand::MemIndexScaleDisp { index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } } - OperandSpec::RegIndexBaseScale_mask => { + OperandSpec::MemBaseIndexScale_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegIndexBaseScaleMasked(inst.regs[1], inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemBaseIndexScaleMasked { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale) + Operand::MemBaseIndexScale { base: inst.regs[1], index: inst.regs[2], scale: inst.scale } } } - OperandSpec::RegIndexBaseScaleDisp_mask => { + OperandSpec::MemBaseIndexScaleDisp_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegIndexBaseScaleDispMasked(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) + Operand::MemBaseIndexScaleDispMasked { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32, mask: RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()) } } else { - Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32) + Operand::MemBaseIndexScaleDisp { base: inst.regs[1], index: inst.regs[2], scale: inst.scale, disp: inst.disp as i32 } } } OperandSpec::AbsoluteFarAddress => { @@ -672,36 +662,32 @@ impl Operand { /// memory. pub fn is_memory(&self) -> bool { match self { - Operand::DisplacementU16(_) | - Operand::DisplacementU32(_) | - Operand::RegDeref(_) | - Operand::RegDisp(_, _) | - Operand::RegScale(_, _) | - Operand::RegIndexBase(_, _) | - Operand::RegIndexBaseDisp(_, _, _) | - Operand::RegScaleDisp(_, _, _) | - Operand::RegIndexBaseScale(_, _, _) | - Operand::RegIndexBaseScaleDisp(_, _, _, _) | - Operand::RegDerefMasked(_, _) | - Operand::RegDispMasked(_, _, _) | - Operand::RegScaleMasked(_, _, _) | - Operand::RegIndexBaseMasked(_, _, _) | - Operand::RegIndexBaseDispMasked(_, _, _, _) | - Operand::RegScaleDispMasked(_, _, _, _) | - Operand::RegIndexBaseScaleMasked(_, _, _, _) | - Operand::RegIndexBaseScaleDispMasked(_, _, _, _, _) => { + Operand::AbsoluteU16 { .. } | + Operand::AbsoluteU32 { .. } | + Operand::MemDeref { .. } | + Operand::MemDisp { .. } | + Operand::MemIndexScale { .. } | + Operand::MemIndexScaleDisp { .. } | + Operand::MemBaseIndexScale { .. } | + Operand::MemBaseIndexScaleDisp { .. } | + Operand::MemDerefMasked { .. } | + Operand::MemDispMasked { .. } | + Operand::MemIndexScaleMasked { .. } | + Operand::MemIndexScaleDispMasked { .. } | + Operand::MemBaseIndexScaleMasked { .. } | + Operand::MemBaseIndexScaleDispMasked { .. } => { true }, - Operand::ImmediateI8(_) | - Operand::ImmediateU8(_) | - Operand::ImmediateI16(_) | - Operand::ImmediateU16(_) | - Operand::ImmediateU32(_) | - Operand::ImmediateI32(_) | - Operand::Register(_) | - Operand::RegisterMaskMerge(_, _, _) | - Operand::RegisterMaskMergeSae(_, _, _, _) | - Operand::RegisterMaskMergeSaeNoround(_, _, _) | + Operand::ImmediateI8 { .. } | + Operand::ImmediateU8 { .. } | + Operand::ImmediateI16 { .. } | + Operand::ImmediateU16 { .. } | + Operand::ImmediateU32 { .. } | + Operand::ImmediateI32 { .. } | + Operand::Register { .. } | + Operand::RegisterMaskMerge { .. } | + Operand::RegisterMaskMergeSae { .. } | + Operand::RegisterMaskMergeSaeNoround { .. } | Operand::AbsoluteFarAddress { .. } | Operand::Nothing => { false @@ -714,22 +700,22 @@ impl Operand { /// `Operand` came from; `None` here means the authoritative width is `instr.mem_size()`. pub fn width(&self) -> Option<u8> { match self { - Operand::Register(reg) => { + Operand::Register { reg } => { Some(reg.width()) } - Operand::RegisterMaskMerge(reg, _, _) => { + Operand::RegisterMaskMerge { reg, .. } => { Some(reg.width()) } - Operand::ImmediateI8(_) | - Operand::ImmediateU8(_) => { + Operand::ImmediateI8 { .. } | + Operand::ImmediateU8 { .. } => { Some(1) } - Operand::ImmediateI16(_) | - Operand::ImmediateU16(_) => { + Operand::ImmediateI16 { .. } | + Operand::ImmediateU16 { .. } => { Some(2) } - Operand::ImmediateI32(_) | - Operand::ImmediateU32(_) => { + Operand::ImmediateI32 { .. } | + Operand::ImmediateU32 { .. } => { Some(4) } // memory operands or `Nothing` @@ -747,40 +733,36 @@ impl Operand { Operand::Nothing => { visitor.visit_other() } - Operand::Register(reg) => { + Operand::Register { reg } => { visitor.visit_reg(*reg) } - Operand::RegDeref(reg) => { - visitor.visit_deref(*reg) - } - Operand::RegDisp(reg, disp) => { - visitor.visit_disp(*reg, *disp) - } - Operand::ImmediateI8(imm) => visitor.visit_i8(*imm), - Operand::ImmediateU8(imm) => visitor.visit_u8(*imm), - Operand::ImmediateI16(imm) => visitor.visit_i16(*imm), - Operand::ImmediateU16(imm) => visitor.visit_u16(*imm), - Operand::ImmediateI32(imm) => visitor.visit_i32(*imm), - Operand::ImmediateU32(imm) => visitor.visit_u32(*imm), - Operand::DisplacementU16(disp) => visitor.visit_abs_u16(*disp), - Operand::DisplacementU32(disp) => visitor.visit_abs_u32(*disp), - Operand::RegScale(reg, scale) => visitor.visit_reg_scale(*reg, *scale), - Operand::RegScaleDisp(reg, scale, disp) => visitor.visit_reg_scale_disp(*reg, *scale, *disp), - Operand::RegIndexBase(_, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegIndexBaseDisp(_, _, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegIndexBaseScale(base, index, scale) => visitor.visit_index_base_scale(*base, *index, *scale), - Operand::RegIndexBaseScaleDisp(base, index, scale, disp) => visitor.visit_index_base_scale_disp(*base, *index, *scale, *disp), - Operand::RegisterMaskMerge(reg, mask, merge) => visitor.visit_reg_mask_merge(*reg, *mask, *merge), - Operand::RegisterMaskMergeSae(reg, mask, merge, sae) => visitor.visit_reg_mask_merge_sae(*reg, *mask, *merge, *sae), - Operand::RegisterMaskMergeSaeNoround(reg, mask, merge) => visitor.visit_reg_mask_merge_sae_noround(*reg, *mask, *merge), - Operand::RegDerefMasked(reg, mask) => visitor.visit_reg_deref_masked(*reg, *mask), - Operand::RegDispMasked(reg, disp, mask) => visitor.visit_reg_disp_masked(*reg, *disp, *mask), - Operand::RegScaleMasked(reg, scale, mask) => visitor.visit_reg_scale_masked(*reg, *scale, *mask), - Operand::RegIndexBaseMasked(_, _, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegIndexBaseDispMasked(_, _, _, _) => { /* not actually reachable anymore */ visitor.visit_other() }, - Operand::RegScaleDispMasked(base, scale, disp, mask) => visitor.visit_reg_scale_disp_masked(*base, *scale, *disp, *mask), - Operand::RegIndexBaseScaleMasked(base, index, scale, mask) => visitor.visit_index_base_scale_masked(*base, *index, *scale, *mask), - Operand::RegIndexBaseScaleDispMasked(base, index, scale, disp, mask) => visitor.visit_index_base_scale_disp_masked(*base, *index, *scale, *disp, *mask), + Operand::MemDeref { base } => { + visitor.visit_deref(*base) + } + Operand::MemDisp { base, disp } => { + visitor.visit_disp(*base, *disp) + } + Operand::ImmediateI8 { imm } => visitor.visit_i8(*imm), + Operand::ImmediateU8 { imm } => visitor.visit_u8(*imm), + Operand::ImmediateI16 { imm } => visitor.visit_i16(*imm), + Operand::ImmediateU16 { imm } => visitor.visit_u16(*imm), + Operand::ImmediateI32 { imm } => visitor.visit_i32(*imm), + Operand::ImmediateU32 { imm } => visitor.visit_u32(*imm), + Operand::AbsoluteU16 { addr } => visitor.visit_abs_u16(*addr), + Operand::AbsoluteU32 { addr } => visitor.visit_abs_u32(*addr), + Operand::MemIndexScale { index, scale } => visitor.visit_index_scale(*index, *scale), + Operand::MemIndexScaleDisp { index, scale, disp } => visitor.visit_index_scale_disp(*index, *scale, *disp), + Operand::MemBaseIndexScale { base, index, scale } => visitor.visit_base_index_scale(*base, *index, *scale), + Operand::MemBaseIndexScaleDisp { base, index, scale, disp } => visitor.visit_base_index_scale_disp(*base, *index, *scale, *disp), + Operand::RegisterMaskMerge { reg, mask, merge } => visitor.visit_reg_mask_merge(*reg, *mask, *merge), + Operand::RegisterMaskMergeSae { reg, mask, merge, sae } => visitor.visit_reg_mask_merge_sae(*reg, *mask, *merge, *sae), + Operand::RegisterMaskMergeSaeNoround { reg, mask, merge } => visitor.visit_reg_mask_merge_sae_noround(*reg, *mask, *merge), + Operand::MemDerefMasked { base, mask } => visitor.visit_deref_masked(*base, *mask), + Operand::MemDispMasked { base, disp, mask } => visitor.visit_disp_masked(*base, *disp, *mask), + Operand::MemIndexScaleMasked { index, scale, mask } => visitor.visit_index_scale_masked(*index, *scale, *mask), + Operand::MemIndexScaleDispMasked { index, scale, disp, mask } => visitor.visit_index_scale_disp_masked(*index, *scale, *disp, *mask), + Operand::MemBaseIndexScaleMasked { base, index, scale, mask } => visitor.visit_base_index_scale_masked(*base, *index, *scale, *mask), + Operand::MemBaseIndexScaleDispMasked { base, index, scale, disp, mask } => visitor.visit_base_index_scale_disp_masked(*base, *index, *scale, *disp, *mask), Operand::AbsoluteFarAddress { segment, address } => visitor.visit_absolute_far_address(*segment, *address), } } @@ -865,16 +847,16 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[ /// } /// } /// -/// if let Operand::Register(regspec) = instruction.operand(0) { +/// if let Operand::Register { reg } = instruction.operand(0) { /// #[cfg(feature="fmt")] -/// println!("first operand is {}", regspec); -/// show_register_class_info(regspec.class()); +/// println!("first operand is {}", reg); +/// show_register_class_info(reg.class()); /// } /// -/// if let Operand::Register(regspec) = instruction.operand(1) { +/// if let Operand::Register { reg } = instruction.operand(1) { /// #[cfg(feature="fmt")] -/// println!("first operand is {}", regspec); -/// show_register_class_info(regspec.class()); +/// println!("second operand is {}", reg); +/// show_register_class_info(reg.class()); /// } /// ``` /// @@ -2667,17 +2649,17 @@ enum OperandSpec { Deref_di = 0x90, Deref_esi = 0x91, Deref_edi = 0x92, - RegDisp = 0x93, - RegScale = 0x94, - RegScaleDisp = 0x95, - RegIndexBaseScale = 0x96, - RegIndexBaseScaleDisp = 0x97, + Disp = 0x93, + MemIndexScale = 0x94, + MemIndexScaleDisp = 0x95, + MemBaseIndexScale = 0x96, + MemBaseIndexScaleDisp = 0x97, Deref_mask = 0xce, - RegDisp_mask = 0xd3, - RegScale_mask = 0xd4, - RegScaleDisp_mask = 0xd5, - RegIndexBaseScale_mask = 0xd6, - RegIndexBaseScaleDisp_mask = 0xd7, + Disp_mask = 0xd3, + MemIndexScale_mask = 0xd4, + MemIndexScaleDisp_mask = 0xd5, + MemBaseIndexScale_mask = 0xd6, + MemBaseIndexScaleDisp_mask = 0xd7, // u16:u{16,32} immediate address for a far call AbsoluteFarAddress = 0x18, } @@ -4385,7 +4367,7 @@ impl Instruction { // visitor.visit_other() visitor.visit_deref(RegSpec::edi()) } - OperandSpec::RegDisp => { + OperandSpec::Disp => { visitor.visit_disp(self.regs[1], self.disp as i32) } OperandSpec::RegRRR_maskmerge => { @@ -4439,61 +4421,58 @@ impl Instruction { OperandSpec::ImmInDispField => visitor.visit_u16(self.disp as u16), OperandSpec::DispU16 => visitor.visit_abs_u16(self.disp as u16), OperandSpec::DispU32 => visitor.visit_abs_u32(self.disp as u32), - OperandSpec::RegScale => { - visitor.visit_reg_scale(self.regs[2], self.scale) + OperandSpec::MemIndexScale => { + visitor.visit_index_scale(self.regs[2], self.scale) } - OperandSpec::RegScaleDisp => { - visitor.visit_reg_scale_disp(self.regs[2], self.scale, self.disp as i32) + OperandSpec::MemIndexScaleDisp => { + visitor.visit_index_scale_disp(self.regs[2], self.scale, self.disp as i32) } - OperandSpec::RegIndexBaseScale => { - visitor.visit_index_base_scale(self.regs[1], self.regs[2], self.scale) - /* - Operand::RegIndexBaseScale(self.regs[1], self.regs[2], self.scale) - */ + OperandSpec::MemBaseIndexScale => { + visitor.visit_base_index_scale(self.regs[1], self.regs[2], self.scale) } - OperandSpec::RegIndexBaseScaleDisp => { - visitor.visit_index_base_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) + OperandSpec::MemBaseIndexScaleDisp => { + visitor.visit_base_index_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) } OperandSpec::Deref_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_deref_masked(self.regs[1], RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_deref_masked(self.regs[1], RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { visitor.visit_deref(self.regs[1]) } } - OperandSpec::RegDisp_mask => { + OperandSpec::Disp_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_disp_masked(self.regs[1], self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_disp_masked(self.regs[1], self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { visitor.visit_disp(self.regs[1], self.disp as i32) } } - OperandSpec::RegScale_mask => { + OperandSpec::MemIndexScale_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_scale_masked(self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_index_scale_masked(self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_reg_scale(self.regs[2], self.scale) + visitor.visit_index_scale(self.regs[2], self.scale) } } - OperandSpec::RegScaleDisp_mask => { + OperandSpec::MemIndexScaleDisp_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_reg_scale_disp_masked(self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_index_scale_disp_masked(self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_reg_scale_disp(self.regs[2], self.scale, self.disp as i32) + visitor.visit_index_scale_disp(self.regs[2], self.scale, self.disp as i32) } } - OperandSpec::RegIndexBaseScale_mask => { + OperandSpec::MemBaseIndexScale_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_index_base_scale_masked(self.regs[1], self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_base_index_scale_masked(self.regs[1], self.regs[2], self.scale, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_index_base_scale(self.regs[1], self.regs[2], self.scale) + visitor.visit_base_index_scale(self.regs[1], self.regs[2], self.scale) } } - OperandSpec::RegIndexBaseScaleDisp_mask => { + OperandSpec::MemBaseIndexScaleDisp_mask => { if self.prefixes.evex_unchecked().mask_reg() != 0 { - visitor.visit_index_base_scale_disp_masked(self.regs[1], self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) + visitor.visit_base_index_scale_disp_masked(self.regs[1], self.regs[2], self.scale, self.disp as i32, RegSpec::mask(self.prefixes.evex_unchecked().mask_reg())) } else { - visitor.visit_index_base_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) + visitor.visit_base_index_scale_disp(self.regs[1], self.regs[2], self.scale, self.disp as i32) } } OperandSpec::AbsoluteFarAddress => { @@ -6155,7 +6134,7 @@ fn read_sib< InnerDescription::Misc("mod bits select no base register") .with_id(sib_start + 0) ); - OperandSpec::RegScale + OperandSpec::MemIndexScale } else { sink.record( modrm_start + 6, @@ -6163,7 +6142,7 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScale + OperandSpec::MemBaseIndexScale } } } else { @@ -6182,7 +6161,7 @@ fn read_sib< InnerDescription::RegisterNumber("iii", instr.regs[2].num, instr.regs[2]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScale + OperandSpec::MemBaseIndexScale } } @@ -6216,7 +6195,7 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegDisp + OperandSpec::Disp } } else { sink.record( @@ -6232,7 +6211,7 @@ fn read_sib< InnerDescription::Misc("mod bits select no base register, [index+disp] only") .with_id(sib_start + 0) ); - OperandSpec::RegScaleDisp + OperandSpec::MemIndexScaleDisp } else { sink.record( modrm_start + 6, @@ -6240,7 +6219,7 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScaleDisp + OperandSpec::MemBaseIndexScaleDisp } } } else { @@ -6257,7 +6236,7 @@ fn read_sib< InnerDescription::Misc("iii selects no index register") .with_id(sib_start + 0) ); - OperandSpec::RegDisp + OperandSpec::Disp } else { sink.record( sib_start + 3, @@ -6265,7 +6244,7 @@ fn read_sib< InnerDescription::RegisterNumber("iii", instr.regs[2].num, instr.regs[2]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScaleDisp + OperandSpec::MemBaseIndexScaleDisp } } }; @@ -6375,7 +6354,7 @@ fn read_M_16bit< Ok(OperandSpec::Deref) } else { instr.scale = 1; - Ok(OperandSpec::RegIndexBaseScale) + Ok(OperandSpec::MemBaseIndexScale) } }, 0b01 => { @@ -6396,13 +6375,13 @@ fn read_M_16bit< ); if mmm > 3 { if instr.disp != 0 { - Ok(OperandSpec::RegDisp) + Ok(OperandSpec::Disp) } else { Ok(OperandSpec::Deref) } } else { instr.scale = 1; - Ok(OperandSpec::RegIndexBaseScaleDisp) + Ok(OperandSpec::MemBaseIndexScaleDisp) } }, 0b10 => { @@ -6423,13 +6402,13 @@ fn read_M_16bit< ); if mmm > 3 { if instr.disp != 0 { - Ok(OperandSpec::RegDisp) + Ok(OperandSpec::Disp) } else { Ok(OperandSpec::Deref) } } else { instr.scale = 1; - Ok(OperandSpec::RegIndexBaseScaleDisp) + Ok(OperandSpec::MemBaseIndexScaleDisp) } }, _ => { @@ -6525,7 +6504,7 @@ fn read_M< OperandSpec::Deref } else { instr.disp = disp as i32 as u32; - OperandSpec::RegDisp + OperandSpec::Disp } } }; diff --git a/test/long_mode/operand.rs b/test/long_mode/operand.rs index a47e6c8..0faa1c3 100644 --- a/test/long_mode/operand.rs +++ b/test/long_mode/operand.rs @@ -3,19 +3,19 @@ use yaxpeax_x86::MemoryAccessSize; #[test] fn register_widths() { - assert_eq!(Operand::Register(RegSpec::rsp()).width(), Some(8)); - assert_eq!(Operand::Register(RegSpec::esp()).width(), Some(4)); - assert_eq!(Operand::Register(RegSpec::sp()).width(), Some(2)); - assert_eq!(Operand::Register(RegSpec::cl()).width(), Some(1)); - assert_eq!(Operand::Register(RegSpec::ch()).width(), Some(1)); - assert_eq!(Operand::Register(RegSpec::gs()).width(), Some(2)); + assert_eq!(Operand::Register { reg: RegSpec::rsp() }.width(), Some(8)); + assert_eq!(Operand::Register { reg: RegSpec::esp() }.width(), Some(4)); + assert_eq!(Operand::Register { reg: RegSpec::sp() }.width(), Some(2)); + assert_eq!(Operand::Register { reg: RegSpec::cl() }.width(), Some(1)); + assert_eq!(Operand::Register { reg: RegSpec::ch() }.width(), Some(1)); + assert_eq!(Operand::Register { reg: RegSpec::gs() }.width(), Some(2)); } #[test] fn memory_widths() { // the register operand directly doesn't report a size - it comes from the `Instruction` for - // which this is an operand. - assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), None); + // which this is an operand . + assert_eq!(Operand::MemDeref { base: RegSpec::rsp() }.width(), None); fn mem_size_of(data: &[u8]) -> MemoryAccessSize { let decoder = InstDecoder::default(); diff --git a/test/protected_mode/operand.rs b/test/protected_mode/operand.rs index 6eb9ba5..78a34b4 100644 --- a/test/protected_mode/operand.rs +++ b/test/protected_mode/operand.rs @@ -3,18 +3,18 @@ use yaxpeax_x86::MemoryAccessSize; #[test] fn register_widths() { - assert_eq!(Operand::Register(RegSpec::esp()).width(), Some(4)); - assert_eq!(Operand::Register(RegSpec::sp()).width(), Some(2)); - assert_eq!(Operand::Register(RegSpec::cl()).width(), Some(1)); - assert_eq!(Operand::Register(RegSpec::ch()).width(), Some(1)); - assert_eq!(Operand::Register(RegSpec::gs()).width(), Some(2)); + assert_eq!(Operand::Register { reg: RegSpec::esp() }.width(), Some(4)); + assert_eq!(Operand::Register { reg: RegSpec::sp() }.width(), Some(2)); + assert_eq!(Operand::Register { reg: RegSpec::cl() }.width(), Some(1)); + assert_eq!(Operand::Register { reg: RegSpec::ch() }.width(), Some(1)); + assert_eq!(Operand::Register { reg: RegSpec::gs() }.width(), Some(2)); } #[test] fn memory_widths() { // the register operand directly doesn't report a size - it comes from the `Instruction` for // which this is an operand. - assert_eq!(Operand::RegDeref(RegSpec::esp()).width(), None); + assert_eq!(Operand::MemDeref { base: RegSpec::esp() }.width(), None); fn mem_size_of(data: &[u8]) -> MemoryAccessSize { let decoder = InstDecoder::default(); |