Skip to main content

cranelift_codegen/isa/x64/inst/
regs.rs

1//! Register definitions for regalloc2.
2//!
3//! We define 16 GPRs, with indices equal to the hardware encoding,
4//! and 16 XMM registers.
5//!
6//! Note also that we make use of pinned VRegs to refer to PRegs.
7
8use crate::machinst::Reg;
9use alloc::string::String;
10use alloc::string::ToString;
11use cranelift_assembler_x64::{gpr, xmm};
12use regalloc2::{PReg, RegClass, VReg};
13
14// Constructors for Regs.
15
16const fn gpr(enc: u8) -> Reg {
17    let preg = gpr_preg(enc);
18    Reg::from_virtual_reg(VReg::new(preg.index(), RegClass::Int))
19}
20pub(crate) const fn gpr_preg(enc: u8) -> PReg {
21    PReg::new(enc as usize, RegClass::Int)
22}
23
24pub(crate) const fn rax() -> Reg {
25    gpr(gpr::enc::RAX)
26}
27pub(crate) const fn rcx() -> Reg {
28    gpr(gpr::enc::RCX)
29}
30pub(crate) const fn rdx() -> Reg {
31    gpr(gpr::enc::RDX)
32}
33pub(crate) const fn rbx() -> Reg {
34    gpr(gpr::enc::RBX)
35}
36pub(crate) const fn rsp() -> Reg {
37    gpr(gpr::enc::RSP)
38}
39pub(crate) const fn rbp() -> Reg {
40    gpr(gpr::enc::RBP)
41}
42pub(crate) const fn rsi() -> Reg {
43    gpr(gpr::enc::RSI)
44}
45pub(crate) const fn rdi() -> Reg {
46    gpr(gpr::enc::RDI)
47}
48pub(crate) const fn r8() -> Reg {
49    gpr(gpr::enc::R8)
50}
51pub(crate) const fn r9() -> Reg {
52    gpr(gpr::enc::R9)
53}
54pub(crate) const fn r10() -> Reg {
55    gpr(gpr::enc::R10)
56}
57pub(crate) const fn r11() -> Reg {
58    gpr(gpr::enc::R11)
59}
60pub(crate) const fn r12() -> Reg {
61    gpr(gpr::enc::R12)
62}
63pub(crate) const fn r13() -> Reg {
64    gpr(gpr::enc::R13)
65}
66pub(crate) const fn r14() -> Reg {
67    gpr(gpr::enc::R14)
68}
69pub(crate) const fn r15() -> Reg {
70    gpr(gpr::enc::R15)
71}
72
73/// The pinned register on this architecture.
74/// It must be the same as Spidermonkey's HeapReg, as found in this file.
75/// https://searchfox.org/mozilla-central/source/js/src/jit/x64/Assembler-x64.h#99
76pub(crate) const PINNED_REG: u8 = gpr::enc::R15;
77pub(crate) const fn pinned_reg() -> Reg {
78    gpr(PINNED_REG)
79}
80
81const fn fpr(enc: u8) -> Reg {
82    let preg = fpr_preg(enc);
83    Reg::from_virtual_reg(VReg::new(preg.index(), RegClass::Float))
84}
85
86pub(crate) const fn fpr_preg(enc: u8) -> PReg {
87    PReg::new(enc as usize, RegClass::Float)
88}
89
90pub(crate) const fn xmm0() -> Reg {
91    fpr(xmm::enc::XMM0)
92}
93pub(crate) const fn xmm1() -> Reg {
94    fpr(xmm::enc::XMM1)
95}
96pub(crate) const fn xmm2() -> Reg {
97    fpr(xmm::enc::XMM2)
98}
99pub(crate) const fn xmm3() -> Reg {
100    fpr(xmm::enc::XMM3)
101}
102pub(crate) const fn xmm4() -> Reg {
103    fpr(xmm::enc::XMM4)
104}
105pub(crate) const fn xmm5() -> Reg {
106    fpr(xmm::enc::XMM5)
107}
108pub(crate) const fn xmm6() -> Reg {
109    fpr(xmm::enc::XMM6)
110}
111pub(crate) const fn xmm7() -> Reg {
112    fpr(xmm::enc::XMM7)
113}
114pub(crate) const fn xmm8() -> Reg {
115    fpr(xmm::enc::XMM8)
116}
117pub(crate) const fn xmm9() -> Reg {
118    fpr(xmm::enc::XMM9)
119}
120pub(crate) const fn xmm10() -> Reg {
121    fpr(xmm::enc::XMM10)
122}
123pub(crate) const fn xmm11() -> Reg {
124    fpr(xmm::enc::XMM11)
125}
126pub(crate) const fn xmm12() -> Reg {
127    fpr(xmm::enc::XMM12)
128}
129pub(crate) const fn xmm13() -> Reg {
130    fpr(xmm::enc::XMM13)
131}
132pub(crate) const fn xmm14() -> Reg {
133    fpr(xmm::enc::XMM14)
134}
135pub(crate) const fn xmm15() -> Reg {
136    fpr(xmm::enc::XMM15)
137}
138
139// N.B.: this is not an `impl PrettyPrint for Reg` because it is
140// specific to x64; other backends have analogous functions. The
141// disambiguation happens statically by virtue of higher-level,
142// x64-specific, types calling the right `pretty_print_reg`. (In other
143// words, we can't pretty-print a `Reg` all by itself in a build that
144// may have multiple backends; but we can pretty-print one as part of
145// an x64 Inst or x64 RegMemImm.)
146pub fn pretty_print_reg(reg: Reg, size: u8) -> String {
147    if let Some(rreg) = reg.to_real_reg() {
148        let enc = rreg.hw_enc();
149        let name = match rreg.class() {
150            RegClass::Int => {
151                let size = match size {
152                    8 => gpr::Size::Quadword,
153                    4 => gpr::Size::Doubleword,
154                    2 => gpr::Size::Word,
155                    1 => gpr::Size::Byte,
156                    _ => unreachable!("invalid size"),
157                };
158                gpr::enc::to_string(enc, size)
159            }
160            RegClass::Float => xmm::enc::to_string(enc),
161            RegClass::Vector => unreachable!(),
162        };
163        name.to_string()
164    } else {
165        let mut name = format!("%{reg:?}");
166        // Add size suffixes to GPR virtual registers at narrower widths.
167        if reg.class() == RegClass::Int && size != 8 {
168            name.push_str(match size {
169                4 => "l",
170                2 => "w",
171                1 => "b",
172                _ => unreachable!("invalid size"),
173            });
174        }
175        name
176    }
177}