cranelift_codegen/isa/aarch64/inst/
regs.rs1#![expect(missing_docs, reason = "fields mostly self-describing")]
3
4use crate::isa::aarch64::inst::OperandSize;
5use crate::isa::aarch64::inst::ScalarSize;
6use crate::isa::aarch64::inst::VectorSize;
7use crate::machinst::RealReg;
8use crate::machinst::{Reg, RegClass, Writable};
9use regalloc2::PReg;
10use regalloc2::VReg;
11
12use alloc::string::{String, ToString};
13
14pub const PINNED_REG: u8 = 21;
21
22pub const fn xreg(num: u8) -> Reg {
25 Reg::from_real_reg(xreg_preg(num))
26}
27
28pub(crate) const fn xreg_preg(num: u8) -> PReg {
30 assert!(num < 31);
31 PReg::new(num as usize, RegClass::Int)
32}
33
34pub fn writable_xreg(num: u8) -> Writable<Reg> {
36 Writable::from_reg(xreg(num))
37}
38
39pub const fn vreg(num: u8) -> Reg {
41 Reg::from_real_reg(vreg_preg(num))
42}
43
44pub(crate) const fn vreg_preg(num: u8) -> PReg {
46 assert!(num < 32);
47 PReg::new(num as usize, RegClass::Float)
48}
49
50pub fn writable_vreg(num: u8) -> Writable<Reg> {
52 Writable::from_reg(vreg(num))
53}
54
55pub fn zero_reg() -> Reg {
57 let preg = PReg::new(31, RegClass::Int);
58 Reg::from(VReg::new(preg.index(), RegClass::Int))
59}
60
61pub fn writable_zero_reg() -> Writable<Reg> {
63 Writable::from_reg(zero_reg())
64}
65
66pub fn stack_reg() -> Reg {
68 let preg = PReg::new(31 + 32, RegClass::Int);
80 Reg::from(VReg::new(preg.index(), RegClass::Int))
81}
82
83pub fn writable_stack_reg() -> Writable<Reg> {
85 Writable::from_reg(stack_reg())
86}
87
88pub fn link_reg() -> Reg {
90 xreg(30)
91}
92
93pub fn pinned_reg() -> Reg {
95 xreg(PINNED_REG)
96}
97
98pub fn writable_link_reg() -> Writable<Reg> {
100 Writable::from_reg(link_reg())
101}
102
103pub fn fp_reg() -> Reg {
105 xreg(29)
106}
107
108pub fn writable_fp_reg() -> Writable<Reg> {
110 Writable::from_reg(fp_reg())
111}
112
113pub fn spilltmp_reg() -> Reg {
123 xreg(16)
124}
125
126pub fn writable_spilltmp_reg() -> Writable<Reg> {
128 Writable::from_reg(spilltmp_reg())
129}
130
131pub fn tmp2_reg() -> Reg {
137 xreg(17)
138}
139
140pub fn writable_tmp2_reg() -> Writable<Reg> {
142 Writable::from_reg(tmp2_reg())
143}
144
145fn show_ireg(reg: RealReg) -> String {
150 match reg.hw_enc() {
151 29 => "fp".to_string(),
152 30 => "lr".to_string(),
153 31 => "xzr".to_string(),
154 63 => "sp".to_string(),
155 x => {
156 debug_assert!(x < 29);
157 format!("x{x}")
158 }
159 }
160}
161
162fn show_vreg(reg: RealReg) -> String {
163 format!("v{}", reg.hw_enc() & 31)
164}
165
166fn show_reg(reg: Reg) -> String {
167 if let Some(rreg) = reg.to_real_reg() {
168 match rreg.class() {
169 RegClass::Int => show_ireg(rreg),
170 RegClass::Float => show_vreg(rreg),
171 RegClass::Vector => unreachable!(),
172 }
173 } else {
174 format!("%{reg:?}")
175 }
176}
177
178pub fn pretty_print_reg(reg: Reg) -> String {
179 show_reg(reg)
180}
181
182fn show_reg_sized(reg: Reg, size: OperandSize) -> String {
183 match reg.class() {
184 RegClass::Int => show_ireg_sized(reg, size),
185 RegClass::Float => show_reg(reg),
186 RegClass::Vector => unreachable!(),
187 }
188}
189
190pub fn pretty_print_reg_sized(reg: Reg, size: OperandSize) -> String {
191 show_reg_sized(reg, size)
192}
193
194pub fn show_ireg_sized(reg: Reg, size: OperandSize) -> String {
197 let mut s = show_reg(reg);
198 if reg.class() != RegClass::Int || !size.is32() {
199 return s;
201 }
202
203 if reg.class() == RegClass::Int && size.is32() && s.starts_with("x") {
205 s = "w".to_string() + &s[1..];
206 }
207
208 s
209}
210
211pub fn show_vreg_scalar(reg: Reg, size: ScalarSize) -> String {
213 let mut s = show_reg(reg);
214 if reg.class() != RegClass::Float {
215 return s;
217 }
218
219 if s.starts_with("v") {
221 let replacement = match size {
222 ScalarSize::Size8 => "b",
223 ScalarSize::Size16 => "h",
224 ScalarSize::Size32 => "s",
225 ScalarSize::Size64 => "d",
226 ScalarSize::Size128 => "q",
227 };
228 s.replace_range(0..1, replacement);
229 }
230
231 s
232}
233
234pub fn show_vreg_vector(reg: Reg, size: VectorSize) -> String {
236 assert_eq!(RegClass::Float, reg.class());
237 let mut s = show_reg(reg);
238
239 let suffix = match size {
240 VectorSize::Size8x8 => ".8b",
241 VectorSize::Size8x16 => ".16b",
242 VectorSize::Size16x4 => ".4h",
243 VectorSize::Size16x8 => ".8h",
244 VectorSize::Size32x2 => ".2s",
245 VectorSize::Size32x4 => ".4s",
246 VectorSize::Size64x2 => ".2d",
247 };
248
249 s.push_str(suffix);
250 s
251}
252
253pub fn show_vreg_element(reg: Reg, idx: u8, size: ScalarSize) -> String {
255 assert_eq!(RegClass::Float, reg.class());
256 let s = show_reg(reg);
257 let suffix = match size {
258 ScalarSize::Size8 => ".b",
259 ScalarSize::Size16 => ".h",
260 ScalarSize::Size32 => ".s",
261 ScalarSize::Size64 => ".d",
262 _ => panic!("Unexpected vector element size: {size:?}"),
263 };
264 format!("{s}{suffix}[{idx}]")
265}
266
267pub fn pretty_print_ireg(reg: Reg, size: OperandSize) -> String {
268 show_ireg_sized(reg, size)
269}
270
271pub fn pretty_print_vreg_scalar(reg: Reg, size: ScalarSize) -> String {
272 show_vreg_scalar(reg, size)
273}
274
275pub fn pretty_print_vreg_vector(reg: Reg, size: VectorSize) -> String {
276 show_vreg_vector(reg, size)
277}
278
279pub fn pretty_print_vreg_element(reg: Reg, idx: usize, size: ScalarSize) -> String {
280 show_vreg_element(reg, idx as u8, size)
281}