1use std::fmt;
2
3use rustc_data_structures::fx::FxIndexSet;
4use rustc_span::Symbol;
5
6use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
7use crate::spec::{RelocModel, Target};
8
9def_reg_class! {
10 PowerPC PowerPCInlineAsmRegClass {
11 reg,
12 reg_nonzero,
13 freg,
14 vreg,
15 cr,
16 xer,
17 }
18}
19
20impl PowerPCInlineAsmRegClass {
21 pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
22 &[]
23 }
24
25 pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
26 None
27 }
28
29 pub fn suggest_modifier(
30 self,
31 _arch: InlineAsmArch,
32 _ty: InlineAsmType,
33 ) -> Option<ModifierInfo> {
34 None
35 }
36
37 pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
38 None
39 }
40
41 pub fn supported_types(
42 self,
43 arch: InlineAsmArch,
44 ) -> &'static [(InlineAsmType, Option<Symbol>)] {
45 match self {
46 Self::reg | Self::reg_nonzero => {
47 if arch == InlineAsmArch::PowerPC {
48 types! { _: I8, I16, I32; }
49 } else {
50 types! { _: I8, I16, I32, I64; }
51 }
52 }
53 Self::freg => types! { _: F32, F64; },
54 Self::vreg => types! {
56 altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4);
57 vsx: F32, F64, VecI64(2), VecF64(2);
58 },
59 Self::cr | Self::xer => &[],
60 }
61 }
62}
63
64fn reserved_r13(
65 arch: InlineAsmArch,
66 _reloc_model: RelocModel,
67 _target_features: &FxIndexSet<Symbol>,
68 target: &Target,
69 _is_clobber: bool,
70) -> Result<(), &'static str> {
71 if target.is_like_aix && arch == InlineAsmArch::PowerPC {
72 Ok(())
73 } else {
74 Err("r13 is a reserved register on this target")
75 }
76}
77
78fn reserved_v20to31(
79 _arch: InlineAsmArch,
80 _reloc_model: RelocModel,
81 _target_features: &FxIndexSet<Symbol>,
82 target: &Target,
83 _is_clobber: bool,
84) -> Result<(), &'static str> {
85 if target.is_like_aix {
86 match &*target.options.abi {
87 "vec-default" => Err("v20-v31 are reserved on vec-default ABI"),
88 "vec-extabi" => Ok(()),
89 _ => unreachable!("unrecognized AIX ABI"),
90 }
91 } else {
92 Ok(())
93 }
94}
95
96def_regs! {
97 PowerPC PowerPCInlineAsmReg PowerPCInlineAsmRegClass {
98 r0: reg = ["r0", "0"],
99 r3: reg, reg_nonzero = ["r3", "3"],
100 r4: reg, reg_nonzero = ["r4", "4"],
101 r5: reg, reg_nonzero = ["r5", "5"],
102 r6: reg, reg_nonzero = ["r6", "6"],
103 r7: reg, reg_nonzero = ["r7", "7"],
104 r8: reg, reg_nonzero = ["r8", "8"],
105 r9: reg, reg_nonzero = ["r9", "9"],
106 r10: reg, reg_nonzero = ["r10", "10"],
107 r11: reg, reg_nonzero = ["r11", "11"],
108 r12: reg, reg_nonzero = ["r12", "12"],
109 r13: reg, reg_nonzero = ["r13", "13"] % reserved_r13,
110 r14: reg, reg_nonzero = ["r14", "14"],
111 r15: reg, reg_nonzero = ["r15", "15"],
112 r16: reg, reg_nonzero = ["r16", "16"],
113 r17: reg, reg_nonzero = ["r17", "17"],
114 r18: reg, reg_nonzero = ["r18", "18"],
115 r19: reg, reg_nonzero = ["r19", "19"],
116 r20: reg, reg_nonzero = ["r20", "20"],
117 r21: reg, reg_nonzero = ["r21", "21"],
118 r22: reg, reg_nonzero = ["r22", "22"],
119 r23: reg, reg_nonzero = ["r23", "23"],
120 r24: reg, reg_nonzero = ["r24", "24"],
121 r25: reg, reg_nonzero = ["r25", "25"],
122 r26: reg, reg_nonzero = ["r26", "26"],
123 r27: reg, reg_nonzero = ["r27", "27"],
124 r28: reg, reg_nonzero = ["r28", "28"],
125 f0: freg = ["f0", "fr0"],
126 f1: freg = ["f1", "fr1"],
127 f2: freg = ["f2", "fr2"],
128 f3: freg = ["f3", "fr3"],
129 f4: freg = ["f4", "fr4"],
130 f5: freg = ["f5", "fr5"],
131 f6: freg = ["f6", "fr6"],
132 f7: freg = ["f7", "fr7"],
133 f8: freg = ["f8", "fr8"],
134 f9: freg = ["f9", "fr9"],
135 f10: freg = ["f10", "fr10"],
136 f11: freg = ["f11", "fr11"],
137 f12: freg = ["f12", "fr12"],
138 f13: freg = ["f13", "fr13"],
139 f14: freg = ["f14", "fr14"],
140 f15: freg = ["f15", "fr15"],
141 f16: freg = ["f16", "fr16"],
142 f17: freg = ["f17", "fr17"],
143 f18: freg = ["f18", "fr18"],
144 f19: freg = ["f19", "fr19"],
145 f20: freg = ["f20", "fr20"],
146 f21: freg = ["f21", "fr21"],
147 f22: freg = ["f22", "fr22"],
148 f23: freg = ["f23", "fr23"],
149 f24: freg = ["f24", "fr24"],
150 f25: freg = ["f25", "fr25"],
151 f26: freg = ["f26", "fr26"],
152 f27: freg = ["f27", "fr27"],
153 f28: freg = ["f28", "fr28"],
154 f29: freg = ["f29", "fr29"],
155 f30: freg = ["f30", "fr30"],
156 f31: freg = ["f31", "fr31"],
157 v0: vreg = ["v0"],
158 v1: vreg = ["v1"],
159 v2: vreg = ["v2"],
160 v3: vreg = ["v3"],
161 v4: vreg = ["v4"],
162 v5: vreg = ["v5"],
163 v6: vreg = ["v6"],
164 v7: vreg = ["v7"],
165 v8: vreg = ["v8"],
166 v9: vreg = ["v9"],
167 v10: vreg = ["v10"],
168 v11: vreg = ["v11"],
169 v12: vreg = ["v12"],
170 v13: vreg = ["v13"],
171 v14: vreg = ["v14"],
172 v15: vreg = ["v15"],
173 v16: vreg = ["v16"],
174 v17: vreg = ["v17"],
175 v18: vreg = ["v18"],
176 v19: vreg = ["v19"],
177 v20: vreg = ["v20"] % reserved_v20to31,
178 v21: vreg = ["v21"] % reserved_v20to31,
179 v22: vreg = ["v22"] % reserved_v20to31,
180 v23: vreg = ["v23"] % reserved_v20to31,
181 v24: vreg = ["v24"] % reserved_v20to31,
182 v25: vreg = ["v25"] % reserved_v20to31,
183 v26: vreg = ["v26"] % reserved_v20to31,
184 v27: vreg = ["v27"] % reserved_v20to31,
185 v28: vreg = ["v28"] % reserved_v20to31,
186 v29: vreg = ["v29"] % reserved_v20to31,
187 v30: vreg = ["v30"] % reserved_v20to31,
188 v31: vreg = ["v31"] % reserved_v20to31,
189 cr: cr = ["cr"],
190 cr0: cr = ["cr0"],
191 cr1: cr = ["cr1"],
192 cr2: cr = ["cr2"],
193 cr3: cr = ["cr3"],
194 cr4: cr = ["cr4"],
195 cr5: cr = ["cr5"],
196 cr6: cr = ["cr6"],
197 cr7: cr = ["cr7"],
198 xer: xer = ["xer"],
199 #error = ["r1", "1", "sp"] =>
200 "the stack pointer cannot be used as an operand for inline asm",
201 #error = ["r2", "2"] =>
202 "r2 is a system reserved register and cannot be used as an operand for inline asm",
203 #error = ["r29", "29"] =>
204 "r29 is used internally by LLVM and cannot be used as an operand for inline asm",
205 #error = ["r30", "30"] =>
206 "r30 is used internally by LLVM and cannot be used as an operand for inline asm",
207 #error = ["r31", "31", "fp"] =>
208 "the frame pointer cannot be used as an operand for inline asm",
209 #error = ["lr"] =>
210 "the link register cannot be used as an operand for inline asm",
211 #error = ["ctr"] =>
212 "the counter register cannot be used as an operand for inline asm",
213 #error = ["vrsave"] =>
214 "the vrsave register cannot be used as an operand for inline asm",
215 }
216}
217
218impl PowerPCInlineAsmReg {
219 pub fn emit(
220 self,
221 out: &mut dyn fmt::Write,
222 _arch: InlineAsmArch,
223 _modifier: Option<char>,
224 ) -> fmt::Result {
225 macro_rules! do_emit {
226 (
227 $($(($reg:ident, $value:literal)),*;)*
228 ) => {
229 out.write_str(match self {
230 $($(Self::$reg => $value,)*)*
231 })
232 };
233 }
234 do_emit! {
236 (r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7");
237 (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r13, "13"), (r14, "14"), (r15, "15");
238 (r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23");
239 (r24, "24"), (r25, "25"), (r26, "26"), (r27, "27"), (r28, "28");
240 (f0, "0"), (f1, "1"), (f2, "2"), (f3, "3"), (f4, "4"), (f5, "5"), (f6, "6"), (f7, "7");
241 (f8, "8"), (f9, "9"), (f10, "10"), (f11, "11"), (f12, "12"), (f13, "13"), (f14, "14"), (f15, "15");
242 (f16, "16"), (f17, "17"), (f18, "18"), (f19, "19"), (f20, "20"), (f21, "21"), (f22, "22"), (f23, "23");
243 (f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31");
244 (v0, "0"), (v1, "1"), (v2, "2"), (v3, "3"), (v4, "4"), (v5, "5"), (v6, "6"), (v7, "7");
245 (v8, "8"), (v9, "9"), (v10, "10"), (v11, "11"), (v12, "12"), (v13, "13"), (v14, "14"), (v15, "15");
246 (v16, "16"), (v17, "17"), (v18, "18"), (v19, "19"), (v20, "20"), (v21, "21"), (v22, "22"), (v23, "23");
247 (v24, "24"), (v25, "25"), (v26, "26"), (v27, "27"), (v28, "28"), (v29, "29"), (v30, "30"), (v31, "31");
248 (cr, "cr");
249 (cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7");
250 (xer, "xer");
251 }
252 }
253
254 pub fn overlapping_regs(self, mut cb: impl FnMut(PowerPCInlineAsmReg)) {
255 macro_rules! reg_conflicts {
256 (
257 $(
258 $full:ident : $($field:ident)*
259 ),*;
260 ) => {
261 match self {
262 $(
263 Self::$full => {
264 cb(Self::$full);
265 $(cb(Self::$field);)*
266 }
267 $(Self::$field)|* => {
268 cb(Self::$full);
269 cb(self);
270 }
271 )*
272 r => cb(r),
273 }
274 };
275 }
276 reg_conflicts! {
277 cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7;
278 }
279 }
281}