cranelift_assembler_x64/
gpr.rs

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