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, PartialEq)]
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> AsRef<R> for NonRspGpr<R> {
100    fn as_ref(&self) -> &R {
101        &self.0
102    }
103}
104
105impl<R: AsReg> AsMut<R> for NonRspGpr<R> {
106    fn as_mut(&mut self) -> &mut R {
107        &mut self.0
108    }
109}
110
111impl<R: AsReg> From<R> for NonRspGpr<R> {
112    fn from(reg: R) -> NonRspGpr<R> {
113        NonRspGpr(reg)
114    }
115}
116
117/// Encode x64 registers.
118pub mod enc {
119    use super::Size;
120
121    pub const RAX: u8 = 0;
122    pub const RCX: u8 = 1;
123    pub const RDX: u8 = 2;
124    pub const RBX: u8 = 3;
125    pub const RSP: u8 = 4;
126    pub const RBP: u8 = 5;
127    pub const RSI: u8 = 6;
128    pub const RDI: u8 = 7;
129    pub const R8: u8 = 8;
130    pub const R9: u8 = 9;
131    pub const R10: u8 = 10;
132    pub const R11: u8 = 11;
133    pub const R12: u8 = 12;
134    pub const R13: u8 = 13;
135    pub const R14: u8 = 14;
136    pub const R15: u8 = 15;
137
138    /// Return the name of a GPR encoding (`enc`) at the given `size`.
139    ///
140    /// # Panics
141    ///
142    /// This function will panic if the encoding is not a valid x64 register.
143    pub fn to_string(enc: u8, size: Size) -> &'static str {
144        use Size::{Byte, Doubleword, Quadword, Word};
145        match enc {
146            RAX => match size {
147                Byte => "%al",
148                Word => "%ax",
149                Doubleword => "%eax",
150                Quadword => "%rax",
151            },
152            RBX => match size {
153                Byte => "%bl",
154                Word => "%bx",
155                Doubleword => "%ebx",
156                Quadword => "%rbx",
157            },
158            RCX => match size {
159                Byte => "%cl",
160                Word => "%cx",
161                Doubleword => "%ecx",
162                Quadword => "%rcx",
163            },
164            RDX => match size {
165                Byte => "%dl",
166                Word => "%dx",
167                Doubleword => "%edx",
168                Quadword => "%rdx",
169            },
170            RSI => match size {
171                Byte => "%sil",
172                Word => "%si",
173                Doubleword => "%esi",
174                Quadword => "%rsi",
175            },
176            RDI => match size {
177                Byte => "%dil",
178                Word => "%di",
179                Doubleword => "%edi",
180                Quadword => "%rdi",
181            },
182            RBP => match size {
183                Byte => "%bpl",
184                Word => "%bp",
185                Doubleword => "%ebp",
186                Quadword => "%rbp",
187            },
188            RSP => match size {
189                Byte => "%spl",
190                Word => "%sp",
191                Doubleword => "%esp",
192                Quadword => "%rsp",
193            },
194            R8 => match size {
195                Byte => "%r8b",
196                Word => "%r8w",
197                Doubleword => "%r8d",
198                Quadword => "%r8",
199            },
200            R9 => match size {
201                Byte => "%r9b",
202                Word => "%r9w",
203                Doubleword => "%r9d",
204                Quadword => "%r9",
205            },
206            R10 => match size {
207                Byte => "%r10b",
208                Word => "%r10w",
209                Doubleword => "%r10d",
210                Quadword => "%r10",
211            },
212            R11 => match size {
213                Byte => "%r11b",
214                Word => "%r11w",
215                Doubleword => "%r11d",
216                Quadword => "%r11",
217            },
218            R12 => match size {
219                Byte => "%r12b",
220                Word => "%r12w",
221                Doubleword => "%r12d",
222                Quadword => "%r12",
223            },
224            R13 => match size {
225                Byte => "%r13b",
226                Word => "%r13w",
227                Doubleword => "%r13d",
228                Quadword => "%r13",
229            },
230            R14 => match size {
231                Byte => "%r14b",
232                Word => "%r14w",
233                Doubleword => "%r14d",
234                Quadword => "%r14",
235            },
236            R15 => match size {
237                Byte => "%r15b",
238                Word => "%r15w",
239                Doubleword => "%r15d",
240                Quadword => "%r15",
241            },
242            _ => panic!("%invalid{enc}"),
243        }
244    }
245}