]>
Commit | Line | Data |
---|---|---|
f9f354fc | 1 | use super::{InlineAsmArch, InlineAsmType}; |
5e7ed085 | 2 | use crate::spec::{RelocModel, Target}; |
064997fb | 3 | use rustc_data_structures::fx::FxHashSet; |
f9f354fc | 4 | use rustc_macros::HashStable_Generic; |
5099ac24 | 5 | use rustc_span::Symbol; |
f9f354fc XL |
6 | use std::fmt; |
7 | ||
8 | def_reg_class! { | |
9 | AArch64 AArch64InlineAsmRegClass { | |
10 | reg, | |
11 | vreg, | |
12 | vreg_low16, | |
136023e0 | 13 | preg, |
f9f354fc XL |
14 | } |
15 | } | |
16 | ||
17 | impl AArch64InlineAsmRegClass { | |
18 | pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { | |
19 | match self { | |
20 | Self::reg => &['w', 'x'], | |
21 | Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v'], | |
136023e0 | 22 | Self::preg => &[], |
f9f354fc XL |
23 | } |
24 | } | |
25 | ||
26 | pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> { | |
27 | None | |
28 | } | |
29 | ||
30 | pub fn suggest_modifier( | |
31 | self, | |
32 | _arch: InlineAsmArch, | |
33 | ty: InlineAsmType, | |
34 | ) -> Option<(char, &'static str)> { | |
35 | match self { | |
36 | Self::reg => match ty.size().bits() { | |
37 | 64 => None, | |
38 | _ => Some(('w', "w0")), | |
39 | }, | |
40 | Self::vreg | Self::vreg_low16 => match ty.size().bits() { | |
41 | 8 => Some(('b', "b0")), | |
42 | 16 => Some(('h', "h0")), | |
43 | 32 => Some(('s', "s0")), | |
44 | 64 => Some(('d', "d0")), | |
45 | 128 => Some(('q', "q0")), | |
46 | _ => None, | |
47 | }, | |
136023e0 | 48 | Self::preg => None, |
f9f354fc XL |
49 | } |
50 | } | |
51 | ||
52 | pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { | |
53 | match self { | |
54 | Self::reg => Some(('x', "x0")), | |
55 | Self::vreg | Self::vreg_low16 => Some(('v', "v0")), | |
136023e0 | 56 | Self::preg => None, |
f9f354fc XL |
57 | } |
58 | } | |
59 | ||
60 | pub fn supported_types( | |
61 | self, | |
62 | _arch: InlineAsmArch, | |
5099ac24 | 63 | ) -> &'static [(InlineAsmType, Option<Symbol>)] { |
f9f354fc XL |
64 | match self { |
65 | Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, | |
66 | Self::vreg | Self::vreg_low16 => types! { | |
5e7ed085 | 67 | neon: I8, I16, I32, I64, F32, F64, |
f9f354fc XL |
68 | VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1), |
69 | VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); | |
70 | }, | |
136023e0 | 71 | Self::preg => &[], |
f9f354fc XL |
72 | } |
73 | } | |
74 | } | |
75 | ||
5e7ed085 | 76 | pub fn target_reserves_x18(target: &Target) -> bool { |
923072b8 | 77 | target.os == "android" || target.os == "fuchsia" || target.is_like_osx || target.is_like_windows |
5e7ed085 FG |
78 | } |
79 | ||
80 | fn reserved_x18( | |
a2a8927a | 81 | _arch: InlineAsmArch, |
5e7ed085 | 82 | _reloc_model: RelocModel, |
5099ac24 | 83 | _target_features: &FxHashSet<Symbol>, |
a2a8927a | 84 | target: &Target, |
5099ac24 | 85 | _is_clobber: bool, |
a2a8927a | 86 | ) -> Result<(), &'static str> { |
5e7ed085 | 87 | if target_reserves_x18(target) { |
a2a8927a XL |
88 | Err("x18 is a reserved register on this target") |
89 | } else { | |
90 | Ok(()) | |
91 | } | |
92 | } | |
93 | ||
f9f354fc XL |
94 | def_regs! { |
95 | AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass { | |
96 | x0: reg = ["x0", "w0"], | |
97 | x1: reg = ["x1", "w1"], | |
98 | x2: reg = ["x2", "w2"], | |
99 | x3: reg = ["x3", "w3"], | |
100 | x4: reg = ["x4", "w4"], | |
101 | x5: reg = ["x5", "w5"], | |
102 | x6: reg = ["x6", "w6"], | |
103 | x7: reg = ["x7", "w7"], | |
104 | x8: reg = ["x8", "w8"], | |
105 | x9: reg = ["x9", "w9"], | |
106 | x10: reg = ["x10", "w10"], | |
107 | x11: reg = ["x11", "w11"], | |
108 | x12: reg = ["x12", "w12"], | |
109 | x13: reg = ["x13", "w13"], | |
110 | x14: reg = ["x14", "w14"], | |
111 | x15: reg = ["x15", "w15"], | |
112 | x16: reg = ["x16", "w16"], | |
113 | x17: reg = ["x17", "w17"], | |
a2a8927a | 114 | x18: reg = ["x18", "w18"] % reserved_x18, |
f9f354fc XL |
115 | x20: reg = ["x20", "w20"], |
116 | x21: reg = ["x21", "w21"], | |
117 | x22: reg = ["x22", "w22"], | |
118 | x23: reg = ["x23", "w23"], | |
119 | x24: reg = ["x24", "w24"], | |
120 | x25: reg = ["x25", "w25"], | |
121 | x26: reg = ["x26", "w26"], | |
122 | x27: reg = ["x27", "w27"], | |
123 | x28: reg = ["x28", "w28"], | |
17df50a5 | 124 | x30: reg = ["x30", "w30", "lr", "wlr"], |
136023e0 XL |
125 | v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0", "z0"], |
126 | v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1", "z1"], | |
127 | v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2", "z2"], | |
128 | v3: vreg, vreg_low16 = ["v3", "b3", "h3", "s3", "d3", "q3", "z3"], | |
129 | v4: vreg, vreg_low16 = ["v4", "b4", "h4", "s4", "d4", "q4", "z4"], | |
130 | v5: vreg, vreg_low16 = ["v5", "b5", "h5", "s5", "d5", "q5", "z5"], | |
131 | v6: vreg, vreg_low16 = ["v6", "b6", "h6", "s6", "d6", "q6", "z6"], | |
132 | v7: vreg, vreg_low16 = ["v7", "b7", "h7", "s7", "d7", "q7", "z7"], | |
133 | v8: vreg, vreg_low16 = ["v8", "b8", "h8", "s8", "d8", "q8", "z8"], | |
134 | v9: vreg, vreg_low16 = ["v9", "b9", "h9", "s9", "d9", "q9", "z9"], | |
135 | v10: vreg, vreg_low16 = ["v10", "b10", "h10", "s10", "d10", "q10", "z10"], | |
136 | v11: vreg, vreg_low16 = ["v11", "b11", "h11", "s11", "d11", "q11", "z11"], | |
137 | v12: vreg, vreg_low16 = ["v12", "b12", "h12", "s12", "d12", "q12", "z12"], | |
138 | v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13", "z13"], | |
139 | v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14", "z14"], | |
140 | v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15", "z15"], | |
141 | v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"], | |
142 | v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"], | |
143 | v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"], | |
144 | v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"], | |
145 | v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"], | |
146 | v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"], | |
147 | v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"], | |
148 | v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"], | |
149 | v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"], | |
150 | v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"], | |
151 | v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"], | |
152 | v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"], | |
153 | v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"], | |
154 | v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"], | |
155 | v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"], | |
156 | v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"], | |
157 | p0: preg = ["p0"], | |
158 | p1: preg = ["p1"], | |
159 | p2: preg = ["p2"], | |
160 | p3: preg = ["p3"], | |
161 | p4: preg = ["p4"], | |
162 | p5: preg = ["p5"], | |
163 | p6: preg = ["p6"], | |
164 | p7: preg = ["p7"], | |
165 | p8: preg = ["p8"], | |
166 | p9: preg = ["p9"], | |
167 | p10: preg = ["p10"], | |
168 | p11: preg = ["p11"], | |
169 | p12: preg = ["p12"], | |
170 | p13: preg = ["p13"], | |
171 | p14: preg = ["p14"], | |
172 | p15: preg = ["p15"], | |
173 | ffr: preg = ["ffr"], | |
17df50a5 XL |
174 | #error = ["x19", "w19"] => |
175 | "x19 is used internally by LLVM and cannot be used as an operand for inline asm", | |
176 | #error = ["x29", "w29", "fp", "wfp"] => | |
f9f354fc XL |
177 | "the frame pointer cannot be used as an operand for inline asm", |
178 | #error = ["sp", "wsp"] => | |
179 | "the stack pointer cannot be used as an operand for inline asm", | |
180 | #error = ["xzr", "wzr"] => | |
181 | "the zero register cannot be used as an operand for inline asm", | |
182 | } | |
183 | } | |
184 | ||
185 | impl AArch64InlineAsmReg { | |
186 | pub fn emit( | |
187 | self, | |
188 | out: &mut dyn fmt::Write, | |
189 | _arch: InlineAsmArch, | |
190 | modifier: Option<char>, | |
191 | ) -> fmt::Result { | |
192 | let (prefix, index) = if (self as u32) < Self::v0 as u32 { | |
193 | (modifier.unwrap_or('x'), self as u32 - Self::x0 as u32) | |
194 | } else { | |
195 | (modifier.unwrap_or('v'), self as u32 - Self::v0 as u32) | |
196 | }; | |
197 | assert!(index < 32); | |
9c376795 | 198 | write!(out, "{prefix}{index}") |
f9f354fc XL |
199 | } |
200 | } |