1 use super::{InlineAsmArch, InlineAsmType}
;
2 use crate::spec
::Target
;
3 use rustc_data_structures
::stable_set
::FxHashSet
;
4 use rustc_macros
::HashStable_Generic
;
5 use rustc_span
::{sym, Symbol}
;
9 Arm ArmInlineAsmRegClass
{
22 impl ArmInlineAsmRegClass
{
23 pub fn valid_modifiers(self, _arch
: super::InlineAsmArch
) -> &'
static [char] {
25 Self::qreg
| Self::qreg_low8
| Self::qreg_low4
=> &['e'
, 'f'
],
30 pub fn suggest_class(self, _arch
: InlineAsmArch
, _ty
: InlineAsmType
) -> Option
<Self> {
34 pub fn suggest_modifier(
38 ) -> Option
<(char, &'
static str)> {
42 pub fn default_modifier(self, _arch
: InlineAsmArch
) -> Option
<(char, &'
static str)> {
46 pub fn supported_types(
49 ) -> &'
static [(InlineAsmType
, Option
<Symbol
>)] {
51 Self::reg
=> types
! { _: I8, I16, I32, F32; }
,
52 Self::sreg
| Self::sreg_low16
=> types
! { vfp2: I32, F32; }
,
53 Self::dreg
| Self::dreg_low16
| Self::dreg_low8
=> types
! {
54 vfp2
: I64
, F64
, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
56 Self::qreg
| Self::qreg_low8
| Self::qreg_low4
=> types
! {
57 neon
: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4);
63 // This uses the same logic as useR7AsFramePointer in LLVM
64 fn frame_pointer_is_r7(target_features
: &FxHashSet
<Symbol
>, target
: &Target
) -> bool
{
65 target
.is_like_osx
|| (!target
.is_like_windows
&& target_features
.contains(&sym
::thumb_mode
))
70 target_features
: &FxHashSet
<Symbol
>,
73 ) -> Result
<(), &'
static str> {
74 not_thumb1(arch
, target_features
, target
, is_clobber
)?
;
76 if !frame_pointer_is_r7(target_features
, target
) {
77 Err("the frame pointer (r11) cannot be used as an operand for inline asm")
85 target_features
: &FxHashSet
<Symbol
>,
88 ) -> Result
<(), &'
static str> {
89 if frame_pointer_is_r7(target_features
, target
) {
90 Err("the frame pointer (r7) cannot be used as an operand for inline asm")
98 target_features
: &FxHashSet
<Symbol
>,
101 ) -> Result
<(), &'
static str> {
103 && target_features
.contains(&sym
::thumb_mode
)
104 && !target_features
.contains(&sym
::thumb2
)
106 Err("high registers (r8+) can only be used as clobbers in Thumb-1 code")
114 target_features
: &FxHashSet
<Symbol
>,
117 ) -> Result
<(), &'
static str> {
118 not_thumb1(arch
, target_features
, target
, is_clobber
)?
;
120 // We detect this using the reserved-r9 feature instead of using the target
121 // because the relocation model can be changed with compiler options.
122 if target_features
.contains(&sym
::reserved_r9
) {
123 Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
130 Arm ArmInlineAsmReg ArmInlineAsmRegClass
{
131 r0
: reg
= ["r0", "a1"],
132 r1
: reg
= ["r1", "a2"],
133 r2
: reg
= ["r2", "a3"],
134 r3
: reg
= ["r3", "a4"],
135 r4
: reg
= ["r4", "v1"],
136 r5
: reg
= ["r5", "v2"],
137 r7
: reg
= ["r7", "v4"] % frame_pointer_r7
,
138 r8
: reg
= ["r8", "v5"] % not_thumb1
,
139 r9
: reg
= ["r9", "v6", "rfp"] % reserved_r9
,
140 r10
: reg
= ["r10", "sl"] % not_thumb1
,
141 r11
: reg
= ["r11", "fp"] % frame_pointer_r11
,
142 r12
: reg
= ["r12", "ip"] % not_thumb1
,
143 r14
: reg
= ["r14", "lr"] % not_thumb1
,
144 s0
: sreg
, sreg_low16
= ["s0"],
145 s1
: sreg
, sreg_low16
= ["s1"],
146 s2
: sreg
, sreg_low16
= ["s2"],
147 s3
: sreg
, sreg_low16
= ["s3"],
148 s4
: sreg
, sreg_low16
= ["s4"],
149 s5
: sreg
, sreg_low16
= ["s5"],
150 s6
: sreg
, sreg_low16
= ["s6"],
151 s7
: sreg
, sreg_low16
= ["s7"],
152 s8
: sreg
, sreg_low16
= ["s8"],
153 s9
: sreg
, sreg_low16
= ["s9"],
154 s10
: sreg
, sreg_low16
= ["s10"],
155 s11
: sreg
, sreg_low16
= ["s11"],
156 s12
: sreg
, sreg_low16
= ["s12"],
157 s13
: sreg
, sreg_low16
= ["s13"],
158 s14
: sreg
, sreg_low16
= ["s14"],
159 s15
: sreg
, sreg_low16
= ["s15"],
176 d0
: dreg
, dreg_low16
, dreg_low8
= ["d0"],
177 d1
: dreg
, dreg_low16
, dreg_low8
= ["d1"],
178 d2
: dreg
, dreg_low16
, dreg_low8
= ["d2"],
179 d3
: dreg
, dreg_low16
, dreg_low8
= ["d3"],
180 d4
: dreg
, dreg_low16
, dreg_low8
= ["d4"],
181 d5
: dreg
, dreg_low16
, dreg_low8
= ["d5"],
182 d6
: dreg
, dreg_low16
, dreg_low8
= ["d6"],
183 d7
: dreg
, dreg_low16
, dreg_low8
= ["d7"],
184 d8
: dreg
, dreg_low16
= ["d8"],
185 d9
: dreg
, dreg_low16
= ["d9"],
186 d10
: dreg
, dreg_low16
= ["d10"],
187 d11
: dreg
, dreg_low16
= ["d11"],
188 d12
: dreg
, dreg_low16
= ["d12"],
189 d13
: dreg
, dreg_low16
= ["d13"],
190 d14
: dreg
, dreg_low16
= ["d14"],
191 d15
: dreg
, dreg_low16
= ["d15"],
208 q0
: qreg
, qreg_low8
, qreg_low4
= ["q0"],
209 q1
: qreg
, qreg_low8
, qreg_low4
= ["q1"],
210 q2
: qreg
, qreg_low8
, qreg_low4
= ["q2"],
211 q3
: qreg
, qreg_low8
, qreg_low4
= ["q3"],
212 q4
: qreg
, qreg_low8
= ["q4"],
213 q5
: qreg
, qreg_low8
= ["q5"],
214 q6
: qreg
, qreg_low8
= ["q6"],
215 q7
: qreg
, qreg_low8
= ["q7"],
224 #error = ["r6", "v3"] =>
225 "r6 is used internally by LLVM and cannot be used as an operand for inline asm",
226 #error = ["r13", "sp"] =>
227 "the stack pointer cannot be used as an operand for inline asm",
228 #error = ["r15", "pc"] =>
229 "the program pointer cannot be used as an operand for inline asm",
233 impl ArmInlineAsmReg
{
236 out
: &mut dyn fmt
::Write
,
237 _arch
: InlineAsmArch
,
238 modifier
: Option
<char>,
240 // Only qreg is allowed to have modifiers. This should have been
241 // validated already by now.
242 if let Some(modifier
) = modifier
{
243 let index
= self as u32 - Self::q0
as u32;
245 let index
= index
* 2 + (modifier
== 'f'
) as u32;
246 write
!(out
, "d{}", index
)
248 out
.write_str(self.name())
252 pub fn overlapping_regs(self, mut cb
: impl FnMut(ArmInlineAsmReg
)) {
255 macro_rules
! reg_conflicts
{
258 $q
:ident
: $d0
:ident $d1
:ident
: $s0
:ident $s1
:ident $s2
:ident $s3
:ident
261 $q_high
:ident
: $d0_high
:ident $d1_high
:ident
284 Self::$s0
| Self::$s1
=> {
288 Self::$s2
| Self::$s3
=> {
298 Self::$d0_high
| Self::$d1_high
=> {
307 // ARM's floating-point register file is interesting in that it can be
308 // viewed as 16 128-bit registers, 32 64-bit registers or 32 32-bit
309 // registers. Because these views overlap, the registers of different
310 // widths will conflict (e.g. d0 overlaps with s0 and s1, and q1
311 // overlaps with d2 and d3).
313 // See section E1.3.1 of the ARM Architecture Reference Manual for
314 // ARMv8-A for more details.
316 q0
: d0 d1
: s0 s1 s2 s3
,
317 q1
: d2 d3
: s4 s5 s6 s7
,
318 q2
: d4 d5
: s8 s9 s10 s11
,
319 q3
: d6 d7
: s12 s13 s14 s15
,
320 q4
: d8 d9
: s16 s17 s18 s19
,
321 q5
: d10 d11
: s20 s21 s22 s23
,
322 q6
: d12 d13
: s24 s25 s26 s27
,
323 q7
: d14 d15
: s28 s29 s30 s31
;