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