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