diff options
Diffstat (limited to 'src/long_mode')
| -rw-r--r-- | src/long_mode/mod.rs | 230 | 
1 files changed, 166 insertions, 64 deletions
| diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 3d6dc2b..23213ec 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -9,14 +9,24 @@ use yaxpeax_arch::{AddressDiff, Decoder, LengthedInstruction};  #[cfg(feature="use-serde")]  #[derive(Copy, Clone, Debug, PartialOrd, Ord, Eq, PartialEq, Serialize, Deserialize)]  pub struct RegSpec { -    pub num: u8, -    pub bank: RegisterBank +    num: u8, +    bank: RegisterBank  }  #[cfg(not(feature="use-serde"))]  #[derive(Copy, Clone, Debug, PartialOrd, Ord, Eq, PartialEq)]  pub struct RegSpec { -    pub num: u8, -    pub bank: RegisterBank +    num: u8, +    bank: RegisterBank +} + +impl RegSpec { +    pub fn num(&self) -> u8 { +        self.num +    } + +    pub fn class(&self) -> RegisterClass { +        RegisterClass { kind: self.bank } +    }  }  use core::hash::Hash; @@ -257,53 +267,39 @@ impl RegSpec {      }      #[inline] +    pub fn r8b() -> RegSpec { +        RegSpec { bank: RegisterBank::rB, num: 8 } +    } + +    #[inline] +    pub fn zmm0() -> RegSpec { +        RegSpec { bank: RegisterBank::Z, num: 0 } +    } + +    #[inline] +    pub fn ymm0() -> RegSpec { +        RegSpec { bank: RegisterBank::Y, num: 0 } +    } + +    #[inline] +    pub fn xmm0() -> RegSpec { +        RegSpec { bank: RegisterBank::X, num: 0 } +    } + +    #[inline] +    pub fn st0() -> RegSpec { +        RegSpec { bank: RegisterBank::ST, num: 0 } +    } + +    #[inline] +    pub fn mm0() -> RegSpec { +        RegSpec { bank: RegisterBank::MM, num: 0 } +    } + +    /// return the size of this register, in bytes +    #[inline]      pub fn width(&self) -> u8 { -        match self.bank { -            RegisterBank::Q => 8, -            RegisterBank::D => 4, -            RegisterBank::W => 2, -            RegisterBank::B | -            RegisterBank::rB => { -                1 -            }, -            RegisterBank::CR | -            RegisterBank::DR => { -                8 -            }, -            RegisterBank::S => { -                2 -            }, -            RegisterBank::EIP => { -                4 -            } -            RegisterBank::RIP => { -                8 -            } -            RegisterBank::EFlags => { -                4 -            } -            RegisterBank::RFlags => { -                8 -            } -            RegisterBank::X => { -                16 -            } -            RegisterBank::Y => { -                32 -            } -            RegisterBank::Z => { -                64 -            } -            RegisterBank::ST => { -                10 -            } -            RegisterBank::MM => { -                8 -            } -            RegisterBank::K => { -                8 -            } -        } +        self.class().width()      }  } @@ -439,6 +435,7 @@ impl Operand {              }          }      } +      pub fn is_memory(&self) -> bool {          match self {              Operand::DisplacementU32(_) | @@ -508,20 +505,125 @@ fn operand_size() {      // assert_eq!(core::mem::size_of::<Instruction>(), 40);  } +#[cfg(feature="use-serde")] +#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub struct RegisterClass { +    kind: RegisterBank, +} + +#[cfg(not(feature="use-serde"))] +#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub struct RegisterClass { +    kind: RegisterBank, +} + +const REGISTER_CLASS_NAMES: &[&'static str] = &[ +    "qword", +    "BUG. PLEASE REPORT.", +    "dword", +    "BUG. PLEASE REPORT.", +    "word", +    "BUG. PLEASE REPORT.", +    "byte", +    "BUG. PLEASE REPORT.", +    "rex-byte", +    "BUG. PLEASE REPORT.", +    "cr", +    "BUG. PLEASE REPORT.", +    "dr", +    "BUG. PLEASE REPORT.", +    "segment", +    "xmm", +    "BUG. PLEASE REPORT.", +    "BUG. PLEASE REPORT.", +    "BUG. PLEASE REPORT.", +    "ymm", +    "BUG. PLEASE REPORT.", +    "BUG. PLEASE REPORT.", +    "BUG. PLEASE REPORT.", +    "zmm", +    "BUG. PLEASE REPORT.", +    "BUG. PLEASE REPORT.", +    "BUG. PLEASE REPORT.", +    "x87-stack", +    "mmx", +    "k", +    "eip", +    "rip", +    "eflags", +    "rflags", +]; + +impl RegisterClass { +    pub fn name(&self) -> &'static str { +        REGISTER_CLASS_NAMES[self.kind as usize] +    } + +    pub fn width(&self) -> u8 { +        match self.kind { +            RegisterBank::Q => 8, +            RegisterBank::D => 4, +            RegisterBank::W => 2, +            RegisterBank::B | +            RegisterBank::rB => { +                1 +            }, +            RegisterBank::CR | +            RegisterBank::DR => { +                8 +            }, +            RegisterBank::S => { +                2 +            }, +            RegisterBank::EIP => { +                4 +            } +            RegisterBank::RIP => { +                8 +            } +            RegisterBank::EFlags => { +                4 +            } +            RegisterBank::RFlags => { +                8 +            } +            RegisterBank::X => { +                16 +            } +            RegisterBank::Y => { +                32 +            } +            RegisterBank::Z => { +                64 +            } +            RegisterBank::ST => { +                10 +            } +            RegisterBank::MM => { +                8 +            } +            RegisterBank::K => { +                8 +            } +        } +    } +} +  #[allow(non_camel_case_types)]  #[cfg(feature="use-serde")]  #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)] -pub enum RegisterBank { +enum RegisterBank {      Q = 0, D = 2, W = 4, B = 6, rB = 8, // Quadword, Dword, Word, Byte      CR = 10, DR = 12, S = 14, EIP = 30, RIP = 31, EFlags = 32, RFlags = 33,  // Control reg, Debug reg, Selector, ...      X = 15, Y = 19, Z = 23,    // XMM, YMM, ZMM      ST = 27, MM = 28,     // ST, MM regs (x87, mmx)      K = 29, // AVX512 mask registers  } +  #[allow(non_camel_case_types)]  #[cfg(not(feature="use-serde"))]  #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] -pub enum RegisterBank { +enum RegisterBank {      Q = 0, D = 2, W = 4, B = 6, rB = 8, // Quadword, Dword, Word, Byte      CR = 10, DR = 12, S = 14, EIP = 30, RIP = 31, EFlags = 32, RFlags = 33,  // Control reg, Debug reg, Selector, ...      X = 15, Y = 19, Z = 23,    // XMM, YMM, ZMM @@ -1565,7 +1667,7 @@ pub struct Instruction {      operands: [OperandSpec; 4],      imm: u64,      disp: u64, -    pub opcode: Opcode, +    opcode: Opcode,  }  impl yaxpeax_arch::Instruction for Instruction { @@ -3079,25 +3181,25 @@ impl Default for Instruction {  }  impl Instruction { +    pub fn opcode(&self) -> Opcode { +        self.opcode +    } +      pub fn operand(&self, i: u8) -> Operand {          assert!(i < 4);          Operand::from_spec(self, self.operands[i as usize])      }      pub fn operand_count(&self) -> u8 { -        let mut i = 0; -        for op in self.operands.iter() { -            if let OperandSpec::Nothing = op { -                return i; -            } else { -                i += 1; -            } -        } -        return i; +        self.operand_count      }      pub fn operand_present(&self, i: u8) -> bool {          assert!(i < 4); +        if i >= self.operand_count { +            return false; +        } +          if let OperandSpec::Nothing = self.operands[i as usize] {              false          } else { @@ -3245,7 +3347,7 @@ impl Prefixes {      #[inline]      pub fn lock(&self) -> bool { self.bits & 0x4 == 4 }      #[inline] -    fn cs(&mut self) { self.segment = Segment::CS } +    pub fn cs(&mut self) { self.segment = Segment::CS }      #[inline]      fn set_cs(&mut self) { self.segment = Segment::CS }      #[inline] @@ -3520,7 +3622,7 @@ impl OperandCodeBuilder {  //   ---------------------------> read modr/m?  #[repr(u16)]  #[derive(Copy, Clone, Debug, PartialEq)] -pub enum OperandCode { +enum OperandCode {      Ivs = OperandCodeBuilder::new().special_case(25).bits(),      I_3 = OperandCodeBuilder::new().special_case(27).bits(),      Nothing = OperandCodeBuilder::new().special_case(28).bits(), | 
