1 //! 32-bit ARM ISA definitions: registers.
2 
3 use regalloc::{RealRegUniverse, Reg, RegClass, RegClassInfo, Writable, NUM_REG_CLASSES};
4 
5 use std::string::ToString;
6 
7 /// Get a reference to a GPR.
rreg(num: u8) -> Reg8 pub fn rreg(num: u8) -> Reg {
9     assert!(num < 16);
10     Reg::new_real(RegClass::I32, num, num)
11 }
12 
13 /// Get a writable reference to a GPR.
writable_rreg(num: u8) -> Writable<Reg>14 pub fn writable_rreg(num: u8) -> Writable<Reg> {
15     Writable::from_reg(rreg(num))
16 }
17 
18 /// Get a reference to the program counter (r15).
pc_reg() -> Reg19 pub fn pc_reg() -> Reg {
20     rreg(15)
21 }
22 
23 /// Get a writable reference to the program counter.
writable_pc_reg() -> Writable<Reg>24 pub fn writable_pc_reg() -> Writable<Reg> {
25     Writable::from_reg(pc_reg())
26 }
27 
28 /// Get a reference to the link register (r14).
lr_reg() -> Reg29 pub fn lr_reg() -> Reg {
30     rreg(14)
31 }
32 
33 /// Get a writable reference to the link register.
writable_lr_reg() -> Writable<Reg>34 pub fn writable_lr_reg() -> Writable<Reg> {
35     Writable::from_reg(lr_reg())
36 }
37 
38 /// Get a reference to the stack pointer (r13).
sp_reg() -> Reg39 pub fn sp_reg() -> Reg {
40     rreg(13)
41 }
42 
43 /// Get a writable reference to the stack pointer.
writable_sp_reg() -> Writable<Reg>44 pub fn writable_sp_reg() -> Writable<Reg> {
45     Writable::from_reg(sp_reg())
46 }
47 
48 /// Get a reference to the intra-procedure-call scratch register (r12),
49 /// which is used as a temporary register.
ip_reg() -> Reg50 pub fn ip_reg() -> Reg {
51     rreg(12)
52 }
53 
54 /// Get a writable reference to the Intra-Procedure-call scratch register.
writable_ip_reg() -> Writable<Reg>55 pub fn writable_ip_reg() -> Writable<Reg> {
56     Writable::from_reg(ip_reg())
57 }
58 
59 /// Get a reference to the frame pointer register (r11).
fp_reg() -> Reg60 pub fn fp_reg() -> Reg {
61     rreg(11)
62 }
63 
64 /// Get a writable reference to the frame-pointer register.
writable_fp_reg() -> Writable<Reg>65 pub fn writable_fp_reg() -> Writable<Reg> {
66     Writable::from_reg(fp_reg())
67 }
68 
69 /// Get a reference to the second temp register. We need this in some edge cases
70 /// where we need both the ip and another temporary.
71 ///
72 /// We use r10 for this role.
tmp2_reg() -> Reg73 pub fn tmp2_reg() -> Reg {
74     rreg(10)
75 }
76 
77 /// Get a writable reference to the tmp2 reg.
writable_tmp2_reg() -> Writable<Reg>78 pub fn writable_tmp2_reg() -> Writable<Reg> {
79     Writable::from_reg(tmp2_reg())
80 }
81 
82 /// Create the register universe.
83 /// Use only GPR for now.
create_reg_universe() -> RealRegUniverse84 pub fn create_reg_universe() -> RealRegUniverse {
85     let mut regs = vec![];
86     let mut allocable_by_class = [None; NUM_REG_CLASSES];
87 
88     let r_reg_base = 0u8;
89     let r_reg_count = 10; // to exclude r10, fp, ip, sp, lr  and pc.
90     for i in 0..r_reg_count {
91         let reg = Reg::new_real(
92             RegClass::I32,
93             /* enc = */ i,
94             /* index = */ r_reg_base + i,
95         )
96         .to_real_reg();
97         let name = format!("r{}", i);
98         regs.push((reg, name));
99     }
100     let r_reg_last = r_reg_base + r_reg_count - 1;
101 
102     allocable_by_class[RegClass::I32.rc_to_usize()] = Some(RegClassInfo {
103         first: r_reg_base as usize,
104         last: r_reg_last as usize,
105         suggested_scratch: None,
106     });
107 
108     // Other regs, not available to the allocator.
109     let allocable = regs.len();
110     regs.push((tmp2_reg().to_real_reg(), "r10".to_string()));
111     regs.push((fp_reg().to_real_reg(), "fp".to_string()));
112     regs.push((ip_reg().to_real_reg(), "ip".to_string()));
113     regs.push((sp_reg().to_real_reg(), "sp".to_string()));
114     regs.push((lr_reg().to_real_reg(), "lr".to_string()));
115     regs.push((pc_reg().to_real_reg(), "pc".to_string()));
116 
117     // The indices in the register structs must match their
118     // actual indices in the array.
119     for (i, reg) in regs.iter().enumerate() {
120         assert_eq!(i, reg.0.get_index());
121     }
122 
123     RealRegUniverse {
124         regs,
125         allocable,
126         allocable_by_class,
127     }
128 }
129