aboutsummaryrefslogtreecommitdiff
path: root/src/long_mode/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/long_mode/mod.rs')
-rw-r--r--src/long_mode/mod.rs230
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(),