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