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 vsreg,
16 cr,
17 ctr,
18 lr,
19 xer,
20 }
21}
22
23impl PowerPCInlineAsmRegClass {
24 pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
25 &[]
26 }
27
28 pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
29 None
30 }
31
32 pub fn suggest_modifier(
33 self,
34 _arch: InlineAsmArch,
35 _ty: InlineAsmType,
36 ) -> Option<ModifierInfo> {
37 None
38 }
39
40 pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
41 None
42 }
43
44 pub fn supported_types(
45 self,
46 arch: InlineAsmArch,
47 ) -> &'static [(InlineAsmType, Option<Symbol>)] {
48 match self {
49 Self::reg | Self::reg_nonzero => {
50 if arch == InlineAsmArch::PowerPC {
51 types! { _: I8, I16, I32; }
52 } else {
53 types! { _: I8, I16, I32, I64; }
54 }
55 }
56 Self::freg => types! { _: F32, F64; },
57 Self::vreg => types! {
59 altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4);
60 vsx: F32, F64, VecI64(2), VecF64(2);
61 },
62 Self::vsreg => types! {
64 vsx: F32, F64, VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
65 },
66 Self::cr | Self::ctr | Self::lr | Self::xer => &[],
67 }
68 }
69}
70
71fn reserved_r13(
72 arch: InlineAsmArch,
73 _reloc_model: RelocModel,
74 _target_features: &FxIndexSet<Symbol>,
75 target: &Target,
76 _is_clobber: bool,
77) -> Result<(), &'static str> {
78 if target.is_like_aix && arch == InlineAsmArch::PowerPC {
79 Ok(())
80 } else {
81 Err("r13 is a reserved register on this target")
82 }
83}
84
85fn reserved_v20to31(
86 _arch: InlineAsmArch,
87 _reloc_model: RelocModel,
88 _target_features: &FxIndexSet<Symbol>,
89 target: &Target,
90 _is_clobber: bool,
91) -> Result<(), &'static str> {
92 if target.is_like_aix {
93 match &*target.options.abi {
94 "vec-default" => Err("v20-v31 (vs52-vs63) are reserved on vec-default ABI"),
95 "vec-extabi" => Ok(()),
96 _ => unreachable!("unrecognized AIX ABI"),
97 }
98 } else {
99 Ok(())
100 }
101}
102
103def_regs! {
104 PowerPC PowerPCInlineAsmReg PowerPCInlineAsmRegClass {
105 r0: reg = ["r0", "0"],
106 r3: reg, reg_nonzero = ["r3", "3"],
107 r4: reg, reg_nonzero = ["r4", "4"],
108 r5: reg, reg_nonzero = ["r5", "5"],
109 r6: reg, reg_nonzero = ["r6", "6"],
110 r7: reg, reg_nonzero = ["r7", "7"],
111 r8: reg, reg_nonzero = ["r8", "8"],
112 r9: reg, reg_nonzero = ["r9", "9"],
113 r10: reg, reg_nonzero = ["r10", "10"],
114 r11: reg, reg_nonzero = ["r11", "11"],
115 r12: reg, reg_nonzero = ["r12", "12"],
116 r13: reg, reg_nonzero = ["r13", "13"] % reserved_r13,
117 r14: reg, reg_nonzero = ["r14", "14"],
118 r15: reg, reg_nonzero = ["r15", "15"],
119 r16: reg, reg_nonzero = ["r16", "16"],
120 r17: reg, reg_nonzero = ["r17", "17"],
121 r18: reg, reg_nonzero = ["r18", "18"],
122 r19: reg, reg_nonzero = ["r19", "19"],
123 r20: reg, reg_nonzero = ["r20", "20"],
124 r21: reg, reg_nonzero = ["r21", "21"],
125 r22: reg, reg_nonzero = ["r22", "22"],
126 r23: reg, reg_nonzero = ["r23", "23"],
127 r24: reg, reg_nonzero = ["r24", "24"],
128 r25: reg, reg_nonzero = ["r25", "25"],
129 r26: reg, reg_nonzero = ["r26", "26"],
130 r27: reg, reg_nonzero = ["r27", "27"],
131 r28: reg, reg_nonzero = ["r28", "28"],
132 f0: freg = ["f0", "fr0"],
133 f1: freg = ["f1", "fr1"],
134 f2: freg = ["f2", "fr2"],
135 f3: freg = ["f3", "fr3"],
136 f4: freg = ["f4", "fr4"],
137 f5: freg = ["f5", "fr5"],
138 f6: freg = ["f6", "fr6"],
139 f7: freg = ["f7", "fr7"],
140 f8: freg = ["f8", "fr8"],
141 f9: freg = ["f9", "fr9"],
142 f10: freg = ["f10", "fr10"],
143 f11: freg = ["f11", "fr11"],
144 f12: freg = ["f12", "fr12"],
145 f13: freg = ["f13", "fr13"],
146 f14: freg = ["f14", "fr14"],
147 f15: freg = ["f15", "fr15"],
148 f16: freg = ["f16", "fr16"],
149 f17: freg = ["f17", "fr17"],
150 f18: freg = ["f18", "fr18"],
151 f19: freg = ["f19", "fr19"],
152 f20: freg = ["f20", "fr20"],
153 f21: freg = ["f21", "fr21"],
154 f22: freg = ["f22", "fr22"],
155 f23: freg = ["f23", "fr23"],
156 f24: freg = ["f24", "fr24"],
157 f25: freg = ["f25", "fr25"],
158 f26: freg = ["f26", "fr26"],
159 f27: freg = ["f27", "fr27"],
160 f28: freg = ["f28", "fr28"],
161 f29: freg = ["f29", "fr29"],
162 f30: freg = ["f30", "fr30"],
163 f31: freg = ["f31", "fr31"],
164 v0: vreg = ["v0"],
165 v1: vreg = ["v1"],
166 v2: vreg = ["v2"],
167 v3: vreg = ["v3"],
168 v4: vreg = ["v4"],
169 v5: vreg = ["v5"],
170 v6: vreg = ["v6"],
171 v7: vreg = ["v7"],
172 v8: vreg = ["v8"],
173 v9: vreg = ["v9"],
174 v10: vreg = ["v10"],
175 v11: vreg = ["v11"],
176 v12: vreg = ["v12"],
177 v13: vreg = ["v13"],
178 v14: vreg = ["v14"],
179 v15: vreg = ["v15"],
180 v16: vreg = ["v16"],
181 v17: vreg = ["v17"],
182 v18: vreg = ["v18"],
183 v19: vreg = ["v19"],
184 v20: vreg = ["v20"] % reserved_v20to31,
185 v21: vreg = ["v21"] % reserved_v20to31,
186 v22: vreg = ["v22"] % reserved_v20to31,
187 v23: vreg = ["v23"] % reserved_v20to31,
188 v24: vreg = ["v24"] % reserved_v20to31,
189 v25: vreg = ["v25"] % reserved_v20to31,
190 v26: vreg = ["v26"] % reserved_v20to31,
191 v27: vreg = ["v27"] % reserved_v20to31,
192 v28: vreg = ["v28"] % reserved_v20to31,
193 v29: vreg = ["v29"] % reserved_v20to31,
194 v30: vreg = ["v30"] % reserved_v20to31,
195 v31: vreg = ["v31"] % reserved_v20to31,
196 vs0: vsreg = ["vs0"],
197 vs1: vsreg = ["vs1"],
198 vs2: vsreg = ["vs2"],
199 vs3: vsreg = ["vs3"],
200 vs4: vsreg = ["vs4"],
201 vs5: vsreg = ["vs5"],
202 vs6: vsreg = ["vs6"],
203 vs7: vsreg = ["vs7"],
204 vs8: vsreg = ["vs8"],
205 vs9: vsreg = ["vs9"],
206 vs10: vsreg = ["vs10"],
207 vs11: vsreg = ["vs11"],
208 vs12: vsreg = ["vs12"],
209 vs13: vsreg = ["vs13"],
210 vs14: vsreg = ["vs14"],
211 vs15: vsreg = ["vs15"],
212 vs16: vsreg = ["vs16"],
213 vs17: vsreg = ["vs17"],
214 vs18: vsreg = ["vs18"],
215 vs19: vsreg = ["vs19"],
216 vs20: vsreg = ["vs20"],
217 vs21: vsreg = ["vs21"],
218 vs22: vsreg = ["vs22"],
219 vs23: vsreg = ["vs23"],
220 vs24: vsreg = ["vs24"],
221 vs25: vsreg = ["vs25"],
222 vs26: vsreg = ["vs26"],
223 vs27: vsreg = ["vs27"],
224 vs28: vsreg = ["vs28"],
225 vs29: vsreg = ["vs29"],
226 vs30: vsreg = ["vs30"],
227 vs31: vsreg = ["vs31"],
228 vs32: vsreg = ["vs32"],
229 vs33: vsreg = ["vs33"],
230 vs34: vsreg = ["vs34"],
231 vs35: vsreg = ["vs35"],
232 vs36: vsreg = ["vs36"],
233 vs37: vsreg = ["vs37"],
234 vs38: vsreg = ["vs38"],
235 vs39: vsreg = ["vs39"],
236 vs40: vsreg = ["vs40"],
237 vs41: vsreg = ["vs41"],
238 vs42: vsreg = ["vs42"],
239 vs43: vsreg = ["vs43"],
240 vs44: vsreg = ["vs44"],
241 vs45: vsreg = ["vs45"],
242 vs46: vsreg = ["vs46"],
243 vs47: vsreg = ["vs47"],
244 vs48: vsreg = ["vs48"],
245 vs49: vsreg = ["vs49"],
246 vs50: vsreg = ["vs50"],
247 vs51: vsreg = ["vs51"],
248 vs52: vsreg = ["vs52"] % reserved_v20to31,
250 vs53: vsreg = ["vs53"] % reserved_v20to31,
251 vs54: vsreg = ["vs54"] % reserved_v20to31,
252 vs55: vsreg = ["vs55"] % reserved_v20to31,
253 vs56: vsreg = ["vs56"] % reserved_v20to31,
254 vs57: vsreg = ["vs57"] % reserved_v20to31,
255 vs58: vsreg = ["vs58"] % reserved_v20to31,
256 vs59: vsreg = ["vs59"] % reserved_v20to31,
257 vs60: vsreg = ["vs60"] % reserved_v20to31,
258 vs61: vsreg = ["vs61"] % reserved_v20to31,
259 vs62: vsreg = ["vs62"] % reserved_v20to31,
260 vs63: vsreg = ["vs63"] % reserved_v20to31,
261 cr: cr = ["cr"],
262 cr0: cr = ["cr0"],
263 cr1: cr = ["cr1"],
264 cr2: cr = ["cr2"],
265 cr3: cr = ["cr3"],
266 cr4: cr = ["cr4"],
267 cr5: cr = ["cr5"],
268 cr6: cr = ["cr6"],
269 cr7: cr = ["cr7"],
270 ctr: ctr = ["ctr"],
271 lr: lr = ["lr"],
272 xer: xer = ["xer"],
273 #error = ["r1", "1", "sp"] =>
274 "the stack pointer cannot be used as an operand for inline asm",
275 #error = ["r2", "2"] =>
276 "r2 is a system reserved register and cannot be used as an operand for inline asm",
277 #error = ["r29", "29"] =>
278 "r29 is used internally by LLVM and cannot be used as an operand for inline asm",
279 #error = ["r30", "30"] =>
280 "r30 is used internally by LLVM and cannot be used as an operand for inline asm",
281 #error = ["r31", "31", "fp"] =>
282 "the frame pointer cannot be used as an operand for inline asm",
283 #error = ["vrsave"] =>
284 "the vrsave register cannot be used as an operand for inline asm",
285 }
286}
287
288impl PowerPCInlineAsmReg {
289 pub fn emit(
290 self,
291 out: &mut dyn fmt::Write,
292 _arch: InlineAsmArch,
293 _modifier: Option<char>,
294 ) -> fmt::Result {
295 macro_rules! do_emit {
296 (
297 $($(($reg:ident, $value:literal)),*;)*
298 ) => {
299 out.write_str(match self {
300 $($(Self::$reg => $value,)*)*
301 })
302 };
303 }
304 do_emit! {
306 (r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7");
307 (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r13, "13"), (r14, "14"), (r15, "15");
308 (r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23");
309 (r24, "24"), (r25, "25"), (r26, "26"), (r27, "27"), (r28, "28");
310 (f0, "0"), (f1, "1"), (f2, "2"), (f3, "3"), (f4, "4"), (f5, "5"), (f6, "6"), (f7, "7");
311 (f8, "8"), (f9, "9"), (f10, "10"), (f11, "11"), (f12, "12"), (f13, "13"), (f14, "14"), (f15, "15");
312 (f16, "16"), (f17, "17"), (f18, "18"), (f19, "19"), (f20, "20"), (f21, "21"), (f22, "22"), (f23, "23");
313 (f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31");
314 (v0, "0"), (v1, "1"), (v2, "2"), (v3, "3"), (v4, "4"), (v5, "5"), (v6, "6"), (v7, "7");
315 (v8, "8"), (v9, "9"), (v10, "10"), (v11, "11"), (v12, "12"), (v13, "13"), (v14, "14"), (v15, "15");
316 (v16, "16"), (v17, "17"), (v18, "18"), (v19, "19"), (v20, "20"), (v21, "21"), (v22, "22"), (v23, "23");
317 (v24, "24"), (v25, "25"), (v26, "26"), (v27, "27"), (v28, "28"), (v29, "29"), (v30, "30"), (v31, "31");
318 (vs0, "0"), (vs1, "1"), (vs2, "2"), (vs3, "3"), (vs4, "4"), (vs5, "5"), (vs6, "6"), (vs7, "7"),
319 (vs8, "8"), (vs9, "9"), (vs10, "10"), (vs11, "11"), (vs12, "12"), (vs13, "13"), (vs14, "14"),
320 (vs15, "15"), (vs16, "16"), (vs17, "17"), (vs18, "18"), (vs19, "19"), (vs20, "20"), (vs21, "21"),
321 (vs22, "22"), (vs23, "23"), (vs24, "24"), (vs25, "25"), (vs26, "26"), (vs27, "27"), (vs28, "28"),
322 (vs29, "29"), (vs30, "30"), (vs31, "31"), (vs32, "32"), (vs33, "33"), (vs34, "34"), (vs35, "35"),
323 (vs36, "36"), (vs37, "37"), (vs38, "38"), (vs39, "39"), (vs40, "40"), (vs41, "41"), (vs42, "42"),
324 (vs43, "43"), (vs44, "44"), (vs45, "45"), (vs46, "46"), (vs47, "47"), (vs48, "48"), (vs49, "49"),
325 (vs50, "50"), (vs51, "51"), (vs52, "52"), (vs53, "53"), (vs54, "54"), (vs55, "55"), (vs56, "56"),
326 (vs57, "57"), (vs58, "58"), (vs59, "59"), (vs60, "60"), (vs61, "61"), (vs62, "62"), (vs63, "63"),
327 (cr, "cr");
328 (cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7");
329 (ctr, "ctr");
330 (lr, "lr");
331 (xer, "xer");
332 }
333 }
334
335 pub fn overlapping_regs(self, mut cb: impl FnMut(PowerPCInlineAsmReg)) {
336 macro_rules! reg_conflicts {
337 (
338 $(
339 $full:ident : $($field:ident)*
340 ),*;
341 ) => {
342 match self {
343 $(
344 Self::$full => {
345 cb(Self::$full);
346 $(cb(Self::$field);)*
347 }
348 $(Self::$field)|* => {
349 cb(Self::$full);
350 cb(self);
351 }
352 )*
353 r => cb(r),
354 }
355 };
356 }
357 reg_conflicts! {
358 cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7,
359 vs0 : f0,
361 vs1 : f1,
362 vs2 : f2,
363 vs3 : f3,
364 vs4 : f4,
365 vs5 : f5,
366 vs6 : f6,
367 vs7 : f7,
368 vs8 : f8,
369 vs9 : f9,
370 vs10 : f10,
371 vs11 : f11,
372 vs12 : f12,
373 vs13 : f13,
374 vs14 : f14,
375 vs15 : f15,
376 vs16 : f16,
377 vs17 : f17,
378 vs18 : f18,
379 vs19 : f19,
380 vs20 : f20,
381 vs21 : f21,
382 vs22 : f22,
383 vs23 : f23,
384 vs24 : f24,
385 vs25 : f25,
386 vs26 : f26,
387 vs27 : f27,
388 vs28 : f28,
389 vs29 : f29,
390 vs30 : f30,
391 vs31 : f31,
392 vs32 : v0,
394 vs33 : v1,
395 vs34 : v2,
396 vs35 : v3,
397 vs36 : v4,
398 vs37 : v5,
399 vs38 : v6,
400 vs39 : v7,
401 vs40 : v8,
402 vs41 : v9,
403 vs42 : v10,
404 vs43 : v11,
405 vs44 : v12,
406 vs45 : v13,
407 vs46 : v14,
408 vs47 : v15,
409 vs48 : v16,
410 vs49 : v17,
411 vs50 : v18,
412 vs51 : v19,
413 vs52 : v20,
414 vs53 : v21,
415 vs54 : v22,
416 vs55 : v23,
417 vs56 : v24,
418 vs57 : v25,
419 vs58 : v26,
420 vs59 : v27,
421 vs60 : v28,
422 vs61 : v29,
423 vs62 : v30,
424 vs63 : v31;
425 }
426 }
431}