aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-05-03 13:54:02 -0700
committeriximeow <me@iximeow.net>2020-05-03 13:54:02 -0700
commit876fc7449cf862e7ffe788885fb7d4209ad2eb5d (patch)
treeab66916f6bfae21dab417372fcf9b3ae7fce547f
parentc9df7910c914d04644aee660d48de1245467f384 (diff)
add width() to ask width of an x86 operand
this is largely wrong for memory operands, which require more invasive changes
-rw-r--r--src/long_mode/mod.rs106
-rw-r--r--src/protected_mode/mod.rs85
-rw-r--r--test/long_mode/mod.rs1
-rw-r--r--test/long_mode/operand.rs17
-rw-r--r--test/protected_mode/mod.rs1
-rw-r--r--test/protected_mode/operand.rs16
6 files changed, 222 insertions, 4 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 3319141..05eee0a 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -179,6 +179,21 @@ impl RegSpec {
}
#[inline]
+ pub fn ecx() -> RegSpec {
+ RegSpec { bank: RegisterBank::D, num: 1 }
+ }
+
+ #[inline]
+ pub fn edx() -> RegSpec {
+ RegSpec { bank: RegisterBank::D, num: 2 }
+ }
+
+ #[inline]
+ pub fn ebx() -> RegSpec {
+ RegSpec { bank: RegisterBank::D, num: 3 }
+ }
+
+ #[inline]
pub fn ax() -> RegSpec {
RegSpec { bank: RegisterBank::W, num: 0 }
}
@@ -197,6 +212,66 @@ impl RegSpec {
pub fn cl() -> RegSpec {
RegSpec { bank: RegisterBank::B, num: 1 }
}
+
+ #[inline]
+ pub fn ah() -> RegSpec {
+ RegSpec { bank: RegisterBank::B, num: 4 }
+ }
+
+ #[inline]
+ pub fn ch() -> RegSpec {
+ RegSpec { bank: RegisterBank::B, num: 5 }
+ }
+
+ #[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
+ }
+ }
+ }
}
#[allow(non_camel_case_types)]
@@ -361,6 +436,37 @@ impl Operand {
}
}
}
+
+ pub fn width(&self) -> u8 {
+ match self {
+ Operand::Nothing => {
+ panic!("non-operand does not have a size");
+ }
+ Operand::Register(reg) => {
+ reg.width()
+ }
+ Operand::ImmediateI8(_) |
+ Operand::ImmediateU8(_) => {
+ 1
+ }
+ Operand::ImmediateI16(_) |
+ Operand::ImmediateU16(_) => {
+ 2
+ }
+ Operand::ImmediateI32(_) |
+ Operand::ImmediateU32(_) => {
+ 4
+ }
+ Operand::ImmediateI64(_) |
+ Operand::ImmediateU64(_) => {
+ 8
+ }
+ // memory operands
+ _ => {
+ 8
+ }
+ }
+ }
}
#[test]
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index 2a32a91..76af3a1 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -145,13 +145,13 @@ impl RegSpec {
}
#[inline]
- pub fn bx() -> RegSpec {
- RegSpec { bank: RegisterBank::W, num: 3 }
+ pub fn ebx() -> RegSpec {
+ RegSpec { bank: RegisterBank::D, num: 3 }
}
#[inline]
- pub fn ebx() -> RegSpec {
- RegSpec { bank: RegisterBank::D, num: 3 }
+ pub fn bx() -> RegSpec {
+ RegSpec { bank: RegisterBank::W, num: 3 }
}
#[inline]
@@ -193,6 +193,56 @@ impl RegSpec {
pub fn cl() -> RegSpec {
RegSpec { bank: RegisterBank::B, num: 1 }
}
+
+ #[inline]
+ pub fn ah() -> RegSpec {
+ RegSpec { bank: RegisterBank::B, num: 4 }
+ }
+
+ #[inline]
+ pub fn ch() -> RegSpec {
+ RegSpec { bank: RegisterBank::B, num: 5 }
+ }
+
+ #[inline]
+ pub fn width(&self) -> u8 {
+ match self.bank {
+ RegisterBank::D => 4,
+ RegisterBank::W => 2,
+ RegisterBank::B => 1,
+ RegisterBank::CR |
+ RegisterBank::DR => {
+ 4
+ },
+ RegisterBank::S => {
+ 2
+ },
+ RegisterBank::EIP => {
+ 4
+ }
+ RegisterBank::EFlags => {
+ 4
+ }
+ RegisterBank::X => {
+ 16
+ }
+ RegisterBank::Y => {
+ 32
+ }
+ RegisterBank::Z => {
+ 64
+ }
+ RegisterBank::ST => {
+ 10
+ }
+ RegisterBank::MM => {
+ 8
+ }
+ RegisterBank::K => {
+ 8
+ }
+ }
+ }
}
#[allow(non_camel_case_types)]
@@ -347,6 +397,33 @@ impl Operand {
}
}
}
+
+ pub fn width(&self) -> u8 {
+ match self {
+ Operand::Nothing => {
+ panic!("non-operand does not have a size");
+ }
+ Operand::Register(reg) => {
+ reg.width()
+ }
+ Operand::ImmediateI8(_) |
+ Operand::ImmediateU8(_) => {
+ 1
+ }
+ Operand::ImmediateI16(_) |
+ Operand::ImmediateU16(_) => {
+ 2
+ }
+ Operand::ImmediateI32(_) |
+ Operand::ImmediateU32(_) => {
+ 4
+ }
+ // memory operands
+ _ => {
+ 4
+ }
+ }
+ }
}
#[test]
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index addaae4..2fbe4fb 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1,4 +1,5 @@
mod regspec;
+mod operand;
use std::fmt::Write;
diff --git a/test/long_mode/operand.rs b/test/long_mode/operand.rs
new file mode 100644
index 0000000..885c6d1
--- /dev/null
+++ b/test/long_mode/operand.rs
@@ -0,0 +1,17 @@
+use yaxpeax_arch::{Decoder, LengthedInstruction};
+use yaxpeax_x86::long_mode::{DecodeError, InstDecoder, Opcode};
+
+#[test]
+fn register_widths() {
+ assert_eq!(Operand::Register(RegSpec::rsp()).width(), 8);
+ assert_eq!(Operand::Register(RegSpec::esp()).width(), 4);
+ assert_eq!(Operand::Register(RegSpec::sp()).width(), 2);
+ assert_eq!(Operand::Register(RegSpec::cl()).width(), 1);
+ assert_eq!(Operand::Register(RegSpec::ch()).width(), 1);
+ assert_eq!(Operand::Register(RegSpec::gs()).width(), 2);
+}
+
+#[test]
+fn memory_widths() {
+ assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), 8);
+}
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index 37a3b24..ab3cdc8 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -1,4 +1,5 @@
mod regspec;
+mod operand;
use std::fmt::Write;
diff --git a/test/protected_mode/operand.rs b/test/protected_mode/operand.rs
new file mode 100644
index 0000000..08a24be
--- /dev/null
+++ b/test/protected_mode/operand.rs
@@ -0,0 +1,16 @@
+use yaxpeax_arch::{Decoder, LengthedInstruction};
+use yaxpeax_x86::long_mode::{DecodeError, InstDecoder, Opcode};
+
+#[test]
+fn register_widths() {
+ assert_eq!(Operand::Register(RegSpec::esp()).width(), 4);
+ assert_eq!(Operand::Register(RegSpec::sp()).width(), 2);
+ assert_eq!(Operand::Register(RegSpec::cl()).width(), 1);
+ assert_eq!(Operand::Register(RegSpec::ch()).width(), 1);
+ assert_eq!(Operand::Register(RegSpec::gs()).width(), 2);
+}
+
+#[test]
+fn memory_widths() {
+ assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), 4);
+}