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