//! 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::() == TypeId::of::() } } 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 );