cranelift_assembler_x64/
gpr.rs

1//! Pure register operands; see [`Gpr`].
2
3use crate::AsReg;
4
5/// A general purpose x64 register (e.g., `%rax`).
6///
7/// This container wraps true register type `R` to allow users to specify their
8/// own; by default this will use `u8`.
9#[derive(Clone, Copy, Debug, PartialEq)]
10pub struct Gpr<R: AsReg = u8>(pub(crate) R);
11
12impl<R: AsReg> Gpr<R> {
13    /// Create a [`Gpr`] that may be real (immediately emit-able in machine
14    /// code) or virtual (waiting for register allocation).
15    pub fn new(reg: R) -> Self {
16        Self(reg)
17    }
18
19    /// Return the register's hardware encoding; the underlying type `R` _must_
20    /// be a real register at this point.
21    ///
22    /// # Panics
23    ///
24    /// Panics if the register is not a valid x64 register.
25    pub fn enc(&self) -> u8 {
26        let enc = self.0.enc();
27        assert!(enc < 16, "invalid register: {enc}");
28        enc
29    }
30
31    /// Return the register name at the given `size`.
32    pub fn to_string(&self, size: Size) -> String {
33        self.0.to_string(Some(size))
34    }
35}
36
37impl<R: AsReg> AsRef<R> for Gpr<R> {
38    fn as_ref(&self) -> &R {
39        &self.0
40    }
41}
42
43impl<R: AsReg> AsMut<R> for Gpr<R> {
44    fn as_mut(&mut self) -> &mut R {
45        &mut self.0
46    }
47}
48
49impl<R: AsReg> From<R> for Gpr<R> {
50    fn from(reg: R) -> Gpr<R> {
51        Gpr(reg)
52    }
53}
54
55/// A single x64 register encoding can access a different number of bits.
56#[derive(Copy, Clone, Debug)]
57pub enum Size {
58    /// An 8-bit access.
59    Byte,
60    /// A 16-bit access.
61    Word,
62    /// A 32-bit access.
63    Doubleword,
64    /// A 64-bit access.
65    Quadword,
66}
67
68/// Like [`Gpr`], but with `%rsp` disallowed.
69///
70/// This is due to avoid special cases of REX encodings, see Intel SDM Vol. 2A,
71/// table 2-5.
72#[derive(Clone, Copy, Debug)]
73pub struct NonRspGpr<R: AsReg>(R);
74
75impl<R: AsReg> NonRspGpr<R> {
76    /// See [`Gpr::new`].
77    pub fn new(reg: R) -> Self {
78        Self(reg)
79    }
80
81    /// See [`Gpr::to_string`].
82    pub fn to_string(&self, size: Size) -> String {
83        self.0.to_string(Some(size))
84    }
85
86    /// See [`Gpr::enc`].
87    ///
88    /// # Panics
89    ///
90    /// Panics if the register is invalid or `%rsp`.
91    pub fn enc(&self) -> u8 {
92        let enc = self.0.enc();
93        assert!(enc < 16, "invalid register: {enc}");
94        assert_ne!(enc, enc::RSP, "invalid register: %rsp");
95        enc
96    }
97}
98
99impl<R: AsReg> AsMut<R> for NonRspGpr<R> {
100    fn as_mut(&mut self) -> &mut R {
101        &mut self.0
102    }
103}
104
105impl<R: AsReg> From<R> for NonRspGpr<R> {
106    fn from(reg: R) -> NonRspGpr<R> {
107        NonRspGpr(reg)
108    }
109}
110
111/// Encode x64 registers.
112pub mod enc {
113    use super::Size;
114
115    pub const RAX: u8 = 0;
116    pub const RCX: u8 = 1;
117    pub const RDX: u8 = 2;
118    pub const RBX: u8 = 3;
119    pub const RSP: u8 = 4;
120    pub const RBP: u8 = 5;
121    pub const RSI: u8 = 6;
122    pub const RDI: u8 = 7;
123    pub const R8: u8 = 8;
124    pub const R9: u8 = 9;
125    pub const R10: u8 = 10;
126    pub const R11: u8 = 11;
127    pub const R12: u8 = 12;
128    pub const R13: u8 = 13;
129    pub const R14: u8 = 14;
130    pub const R15: u8 = 15;
131
132    /// Return the name of a GPR encoding (`enc`) at the given `size`.
133    ///
134    /// # Panics
135    ///
136    /// This function will panic if the encoding is not a valid x64 register.
137    pub fn to_string(enc: u8, size: Size) -> &'static str {
138        use Size::{Byte, Doubleword, Quadword, Word};
139        match enc {
140            RAX => match size {
141                Byte => "%al",
142                Word => "%ax",
143                Doubleword => "%eax",
144                Quadword => "%rax",
145            },
146            RBX => match size {
147                Byte => "%bl",
148                Word => "%bx",
149                Doubleword => "%ebx",
150                Quadword => "%rbx",
151            },
152            RCX => match size {
153                Byte => "%cl",
154                Word => "%cx",
155                Doubleword => "%ecx",
156                Quadword => "%rcx",
157            },
158            RDX => match size {
159                Byte => "%dl",
160                Word => "%dx",
161                Doubleword => "%edx",
162                Quadword => "%rdx",
163            },
164            RSI => match size {
165                Byte => "%sil",
166                Word => "%si",
167                Doubleword => "%esi",
168                Quadword => "%rsi",
169            },
170            RDI => match size {
171                Byte => "%dil",
172                Word => "%di",
173                Doubleword => "%edi",
174                Quadword => "%rdi",
175            },
176            RBP => match size {
177                Byte => "%bpl",
178                Word => "%bp",
179                Doubleword => "%ebp",
180                Quadword => "%rbp",
181            },
182            RSP => match size {
183                Byte => "%spl",
184                Word => "%sp",
185                Doubleword => "%esp",
186                Quadword => "%rsp",
187            },
188            R8 => match size {
189                Byte => "%r8b",
190                Word => "%r8w",
191                Doubleword => "%r8d",
192                Quadword => "%r8",
193            },
194            R9 => match size {
195                Byte => "%r9b",
196                Word => "%r9w",
197                Doubleword => "%r9d",
198                Quadword => "%r9",
199            },
200            R10 => match size {
201                Byte => "%r10b",
202                Word => "%r10w",
203                Doubleword => "%r10d",
204                Quadword => "%r10",
205            },
206            R11 => match size {
207                Byte => "%r11b",
208                Word => "%r11w",
209                Doubleword => "%r11d",
210                Quadword => "%r11",
211            },
212            R12 => match size {
213                Byte => "%r12b",
214                Word => "%r12w",
215                Doubleword => "%r12d",
216                Quadword => "%r12",
217            },
218            R13 => match size {
219                Byte => "%r13b",
220                Word => "%r13w",
221                Doubleword => "%r13d",
222                Quadword => "%r13",
223            },
224            R14 => match size {
225                Byte => "%r14b",
226                Word => "%r14w",
227                Doubleword => "%r14d",
228                Quadword => "%r14",
229            },
230            R15 => match size {
231                Byte => "%r15b",
232                Word => "%r15w",
233                Doubleword => "%r15d",
234                Quadword => "%r15",
235            },
236            _ => panic!("%invalid{enc}"),
237        }
238    }
239}