rustc_target/asm/
powerpc.rs

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            // FIXME: vsx also supports integers?: https://github.com/rust-lang/rust/pull/131551#discussion_r1862535963
58            Self::vreg => types! {
59                altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4);
60                vsx: F32, F64, VecI64(2), VecF64(2);
61            },
62            // VSX is a superset of altivec.
63            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 - vs63 are aliases of v20-v31.
249        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        // Strip off the leading prefix.
305        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            // f0-f31 overlap half of each of vs0-vs32.
360            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-v63 are aliases of v0-v31
393            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        // For more detail on how vsx, vmx (altivec), fpr, and mma registers overlap
427        // see OpenPOWER ISA 3.1C, Book I, Section 7.2.1.1 through 7.2.1.3.
428        //
429        // https://files.openpower.foundation/s/9izgC5Rogi5Ywmm
430    }
431}