aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/mem.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem.rs')
-rw-r--r--src/mem.rs116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/mem.rs b/src/mem.rs
new file mode 100644
index 0000000..6a87eb8
--- /dev/null
+++ b/src/mem.rs
@@ -0,0 +1,116 @@
+//! Definition of different addressing modes and memory operande used as input
+//! and ouput operands in various instructions.
+
+use crate::Reg64;
+
+#[derive(Clone, Copy)]
+pub(crate) enum AddrMode {
+ /// An indirect memory operand, eg `mov [rax], rcx`.
+ Indirect,
+ /// An indirect memory operand with additional displacement, eg `mov [rax + 0x10], rcx`.
+ IndirectDisp,
+ /// An indirect memory operand in the form base + index, eg `mov [rax + rcx], rdx`.
+ IndirectBaseIndex,
+}
+
+/// Trait to interact with memory operands.
+pub(crate) trait Mem {
+ /// Get the addressing mode [`AddrMode`] of the memory operand.
+ fn mode(&self) -> AddrMode;
+
+ /// Get the base address register of the memory operand.
+ fn base(&self) -> Reg64;
+
+ /// Get the index register of the memory operand.
+ fn index(&self) -> Reg64;
+
+ /// Get the displacement of the memory operand.
+ fn disp(&self) -> i32;
+
+ /// Check if memory operand is 64 bit.
+ fn is_64() -> bool;
+}
+
+macro_rules! impl_mem {
+ ($(#[$doc:meta] $name:ident)+) => {
+ $(
+ #[$doc]
+ pub struct $name {
+ mode: AddrMode,
+ base: Reg64,
+ index: Reg64,
+ disp: i32,
+ }
+
+ impl Mem for $name {
+ fn mode(&self) -> AddrMode {
+ self.mode
+ }
+
+ fn base(&self) -> Reg64 {
+ self.base
+ }
+
+ fn index(&self) -> Reg64 {
+ self.index
+ }
+
+ fn disp(&self) -> i32 {
+ self.disp
+ }
+
+ fn is_64() -> bool {
+ use std::any::TypeId;
+ TypeId::of::<Self>() == TypeId::of::<Mem64>()
+ }
+ }
+
+ impl $name {
+ /// Create a memory operand with `indirect` addressing mode.
+ /// For example `mov [rax], rcx`.
+ pub fn indirect(base: Reg64) -> Self {
+ Self {
+ mode: AddrMode::Indirect,
+ base,
+ index: Reg64::rax, /* zero index */
+ disp: 0,
+ }
+ }
+
+ /// Create a memory operand with `indirect + displacement`
+ /// addressing mode.
+ /// For example `mov [rax + 0x10], rcx`.
+ pub fn indirect_disp(base: Reg64, disp: i32) -> Self {
+ Self {
+ mode: AddrMode::IndirectDisp,
+ base,
+ index: Reg64::rax, /* zero index */
+ disp,
+ }
+ }
+
+ /// Create a memory operand with `base + index` addressing mode.
+ /// For example `mov [rax + rcx], rdx`.
+ pub fn indirect_base_index(base: Reg64, index: Reg64) -> Self {
+ Self {
+ mode: AddrMode::IndirectBaseIndex,
+ base,
+ index,
+ disp: 0,
+ }
+ }
+ }
+ )+
+ }
+}
+
+impl_mem!(
+ /// A memory operand with `byte` size (8 bit).
+ Mem8
+ /// A memory operand with `word` size (16 bit).
+ Mem16
+ /// A memory operand with `dword` size (32 bit).
+ Mem32
+ /// A memory operand with `qword` size (64 bit).
+ Mem64
+);