dynasmrt/
x64.rs

1//! Runtime support for the x64 architecture assembling target.
2//!
3//! The x64 instruction set features variable-length instructions and
4//! relative relocations up to 32 bits in size.
5//!
6//! The core relocation behaviour for this architecture is provided by the [`X64Relocation`] type.
7//!
8//! Next to that, this module contains the following:
9//!
10//! ## Type aliases
11//!
12//! Several specialized type aliases of the generic [`Assembler`] are provided as these are by far the most common usecase.
13//!
14//! ## Enums
15//!
16//! There are enumerator of every logically distinct register family usable in x64. 
17//! These enums implement the [`Register`] trait and their discriminant values match their numeric encoding in dynamic register literals.
18//! Some of these are re-exported from the x86 architecture.
19//!
20//! *Note: The presence of some registers listed here is purely what is encodable. Check the relevant architecture documentation to find what is architecturally valid.*
21
22use crate::relocations::{Relocation, RelocationSize, RelocationKind, ImpossibleRelocation};
23use crate::Register;
24
25use std::hash::Hash;
26
27
28/// Relocation implementation for the x64 architecture.
29#[derive(Debug, Clone)]
30pub struct X64Relocation {
31    size: RelocationSize,
32}
33
34impl Relocation for X64Relocation {
35    type Encoding = (u8,);
36    fn from_encoding(encoding: Self::Encoding) -> Self {
37        Self {
38            size: RelocationSize::from_encoding(encoding.0),
39        }
40    }
41    fn from_size(size: RelocationSize) -> Self {
42        Self {
43            size,
44        }
45    }
46    fn size(&self) -> usize {
47        self.size.size()
48    }
49    fn write_value(&self, buf: &mut [u8], value: isize) -> Result<(), ImpossibleRelocation> {
50        self.size.write_value(buf, value)
51    }
52    fn read_value(&self, buf: &[u8]) -> isize {
53        self.size.read_value(buf)
54    }
55    fn kind(&self) -> RelocationKind {
56        RelocationKind::Relative
57    }
58    fn page_size() -> usize {
59        4096
60    }
61}
62
63/// An x64 Assembler. This is aliased here for backwards compatability.
64pub type Assembler = crate::Assembler<X64Relocation>;
65/// An x64 AssemblyModifier. This is aliased here for backwards compatability.
66pub type AssemblyModifier<'a> = crate::Modifier<'a, X64Relocation>;
67/// An x64 UncommittedModifier. This is aliased here for backwards compatability.
68pub type UncommittedModifier<'a> = crate::UncommittedModifier<'a>;
69
70
71/// 1, 2, 4 or 8-byte general purpose "quad-word" registers.
72///
73/// RIP does not appear here as it cannot be addressed dynamically.
74#[allow(missing_docs)]
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
76pub enum Rq {
77    RAX = 0x0, RCX = 0x1, RDX = 0x2, RBX = 0x3,
78    RSP = 0x4, RBP = 0x5, RSI = 0x6, RDI = 0x7,
79    R8  = 0x8, R9  = 0x9, R10 = 0xA, R11 = 0xB,
80    R12 = 0xC, R13 = 0xD, R14 = 0xE, R15 = 0xF,
81}
82reg_impls!(Rq);
83
84/// 16 or 32-byte SSE registers.
85#[allow(missing_docs)]
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
87pub enum Rx {
88    XMM0  = 0x0, XMM1  = 0x1, XMM2  = 0x2, XMM3  = 0x3,
89    XMM4  = 0x4, XMM5  = 0x5, XMM6  = 0x6, XMM7  = 0x7,
90    XMM8  = 0x8, XMM9  = 0x9, XMM10 = 0xA, XMM11 = 0xB,
91    XMM12 = 0xC, XMM13 = 0xD, XMM14 = 0xE, XMM15 = 0xF,
92}
93reg_impls!(Rx);
94
95/// 8-byte control registers.
96#[allow(missing_docs)]
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
98pub enum RC {
99    CR0  = 0x0, CR1  = 0x1, CR2  = 0x2, CR3  = 0x3,
100    CR4  = 0x4, CR5  = 0x5, CR6  = 0x6, CR7  = 0x7,
101    CR8  = 0x8, CR9  = 0x9, CR10 = 0xA, CR11 = 0xB,
102    CR12 = 0xC, CR13 = 0xD, CR14 = 0xE, CR15 = 0xF,
103}
104reg_impls!(RC);
105
106// The other register families are the same as 32-bit X86. (Although access size for Debug regs is 8-byte)
107pub use crate::x86::{Rh, Rf, Rm, Rs, RD, RB};
108
109#[cfg(test)]
110mod tests {
111    use super::Rq::*;
112    use crate::Register;
113
114    #[test]
115    fn reg_code() {
116        assert_eq!(RAX.code(), 0);
117    }
118
119    #[test]
120    fn reg_code_from() {
121        assert_eq!(u8::from(R11), 11);
122    }
123}