Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/src/isa/s390x/inst/regs.rs
1693 views
1
//! S390x ISA definitions: registers.
2
3
use alloc::string::String;
4
use regalloc2::PReg;
5
6
use crate::isa::s390x::inst::{RegPair, WritableRegPair};
7
use crate::machinst::*;
8
9
//=============================================================================
10
// Registers, the Universe thereof, and printing
11
12
/// Get a reference to a GPR (integer register).
13
pub const fn gpr(num: u8) -> Reg {
14
Reg::from_real_reg(gpr_preg(num))
15
}
16
17
pub(crate) const fn gpr_preg(num: u8) -> PReg {
18
assert!(num < 16);
19
PReg::new(num as usize, RegClass::Int)
20
}
21
22
/// Get a writable reference to a GPR.
23
pub fn writable_gpr(num: u8) -> Writable<Reg> {
24
Writable::from_reg(gpr(num))
25
}
26
27
/// Get a reference to a VR (vector register).
28
pub const fn vr(num: u8) -> Reg {
29
Reg::from_real_reg(vr_preg(num))
30
}
31
32
pub(crate) const fn vr_preg(num: u8) -> PReg {
33
assert!(num < 32);
34
PReg::new(num as usize, RegClass::Float)
35
}
36
37
/// Get a writable reference to a VR.
38
pub fn writable_vr(num: u8) -> Writable<Reg> {
39
Writable::from_reg(vr(num))
40
}
41
42
/// Test whether a vector register is overlapping an FPR.
43
pub fn is_fpr(r: Reg) -> bool {
44
let r = r.to_real_reg().unwrap();
45
assert!(r.class() == RegClass::Float);
46
return r.hw_enc() < 16;
47
}
48
49
/// Get a reference to the stack-pointer register.
50
pub fn stack_reg() -> Reg {
51
gpr(15)
52
}
53
54
/// Get a writable reference to the stack-pointer register.
55
pub fn writable_stack_reg() -> Writable<Reg> {
56
Writable::from_reg(stack_reg())
57
}
58
59
/// Get a reference to the first temporary, sometimes "spill temporary", register. This register is
60
/// used to compute the address of a spill slot when a direct offset addressing mode from FP is not
61
/// sufficient (+/- 2^11 words). We exclude this register from regalloc and reserve it for this
62
/// purpose for simplicity; otherwise we need a multi-stage analysis where we first determine how
63
/// many spill slots we have, then perhaps remove the reg from the pool and recompute regalloc.
64
///
65
/// We use r1 for this because it's a scratch register but is slightly special (used for linker
66
/// veneers). We're free to use it as long as we don't expect it to live through call instructions.
67
pub fn spilltmp_reg() -> Reg {
68
gpr(1)
69
}
70
71
/// Get a writable reference to the spilltmp reg.
72
pub fn writable_spilltmp_reg() -> Writable<Reg> {
73
Writable::from_reg(spilltmp_reg())
74
}
75
76
pub fn zero_reg() -> Reg {
77
gpr(0)
78
}
79
80
pub fn show_reg(reg: Reg) -> String {
81
if let Some(rreg) = reg.to_real_reg() {
82
match rreg.class() {
83
RegClass::Int => format!("%r{}", rreg.hw_enc()),
84
RegClass::Float => format!("%v{}", rreg.hw_enc()),
85
RegClass::Vector => unreachable!(),
86
}
87
} else {
88
format!("%{reg:?}")
89
}
90
}
91
92
pub fn maybe_show_fpr(reg: Reg) -> Option<String> {
93
if let Some(rreg) = reg.to_real_reg() {
94
if is_fpr(reg) {
95
return Some(format!("%f{}", rreg.hw_enc()));
96
}
97
}
98
None
99
}
100
101
pub fn pretty_print_reg(reg: Reg) -> String {
102
show_reg(reg)
103
}
104
105
pub fn pretty_print_regpair(pair: RegPair) -> String {
106
let hi = pair.hi;
107
let lo = pair.lo;
108
if let Some(hi_reg) = hi.to_real_reg() {
109
if let Some(lo_reg) = lo.to_real_reg() {
110
assert!(
111
hi_reg.hw_enc() + 1 == lo_reg.hw_enc(),
112
"Invalid regpair: {} {}",
113
show_reg(hi),
114
show_reg(lo)
115
);
116
return show_reg(hi);
117
}
118
}
119
120
format!("{}/{}", show_reg(hi), show_reg(lo))
121
}
122
123
pub fn pretty_print_fp_regpair(pair: RegPair) -> String {
124
let hi = pair.hi;
125
let lo = pair.lo;
126
if let Some(hi_reg) = hi.to_real_reg() {
127
if let Some(lo_reg) = lo.to_real_reg() {
128
assert!(
129
hi_reg.hw_enc() + 2 == lo_reg.hw_enc(),
130
"Invalid regpair: {} {}",
131
show_reg(hi),
132
show_reg(lo)
133
);
134
return maybe_show_fpr(hi).unwrap();
135
}
136
}
137
138
format!("{}/{}", show_reg(hi), show_reg(lo))
139
}
140
141
pub fn pretty_print_reg_mod(rd: Writable<Reg>, ri: Reg) -> String {
142
let output = rd.to_reg();
143
let input = ri;
144
if output == input {
145
show_reg(output)
146
} else {
147
format!("{}<-{}", show_reg(output), show_reg(input))
148
}
149
}
150
151
pub fn pretty_print_regpair_mod(rd: WritableRegPair, ri: RegPair) -> String {
152
let rd_hi = rd.hi.to_reg();
153
let rd_lo = rd.lo.to_reg();
154
let ri_hi = ri.hi;
155
let ri_lo = ri.lo;
156
if rd_hi == ri_hi {
157
show_reg(rd_hi)
158
} else {
159
format!(
160
"{}/{}<-{}/{}",
161
show_reg(rd_hi),
162
show_reg(rd_lo),
163
show_reg(ri_hi),
164
show_reg(ri_lo)
165
)
166
}
167
}
168
169
pub fn pretty_print_regpair_mod_lo(rd: WritableRegPair, ri: Reg) -> String {
170
let rd_hi = rd.hi.to_reg();
171
let rd_lo = rd.lo.to_reg();
172
if rd_lo == ri {
173
show_reg(rd_hi)
174
} else {
175
format!(
176
"{}/{}<-_/{}",
177
show_reg(rd_hi),
178
show_reg(rd_lo),
179
show_reg(ri),
180
)
181
}
182
}
183
184
pub fn pretty_print_fpr(reg: Reg) -> (String, Option<String>) {
185
(show_reg(reg), maybe_show_fpr(reg))
186
}
187
188