1 use super::{InlineAsmArch, InlineAsmType}
;
2 use crate::spec
::Target
;
3 use rustc_macros
::HashStable_Generic
;
7 Arm ArmInlineAsmRegClass
{
21 impl ArmInlineAsmRegClass
{
22 pub fn valid_modifiers(self, _arch
: super::InlineAsmArch
) -> &'
static [char] {
24 Self::qreg
| Self::qreg_low8
| Self::qreg_low4
=> &['e'
, 'f'
],
29 pub fn suggest_class(self, _arch
: InlineAsmArch
, _ty
: InlineAsmType
) -> Option
<Self> {
33 pub fn suggest_modifier(
37 ) -> Option
<(char, &'
static str)> {
41 pub fn default_modifier(self, _arch
: InlineAsmArch
) -> Option
<(char, &'
static str)> {
45 pub fn supported_types(
48 ) -> &'
static [(InlineAsmType
, Option
<&'
static str>)] {
50 Self::reg
| Self::reg_thumb
=> types
! { _: I8, I16, I32, F32; }
,
51 Self::sreg
| Self::sreg_low16
=> types
! { "vfp2": I32, F32; }
,
52 Self::dreg
| Self::dreg_low16
| Self::dreg_low8
=> types
! {
53 "vfp2": I64
, F64
, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
55 Self::qreg
| Self::qreg_low8
| Self::qreg_low4
=> types
! {
56 "neon": VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4);
62 // This uses the same logic as useR7AsFramePointer in LLVM
63 fn frame_pointer_is_r7(mut has_feature
: impl FnMut(&str) -> bool
, target
: &Target
) -> bool
{
64 target
.options
.is_like_osx
|| (!target
.options
.is_like_windows
&& has_feature("thumb-mode"))
69 has_feature
: impl FnMut(&str) -> bool
,
72 ) -> Result
<(), &'
static str> {
73 if !frame_pointer_is_r7(has_feature
, target
) {
74 Err("the frame pointer (r11) cannot be used as an operand for inline asm")
82 has_feature
: impl FnMut(&str) -> bool
,
85 ) -> Result
<(), &'
static str> {
86 if frame_pointer_is_r7(has_feature
, target
) {
87 Err("the frame pointer (r7) cannot be used as an operand for inline asm")
94 Arm ArmInlineAsmReg ArmInlineAsmRegClass
{
95 r0
: reg
, reg_thumb
= ["r0", "a1"],
96 r1
: reg
, reg_thumb
= ["r1", "a2"],
97 r2
: reg
, reg_thumb
= ["r2", "a3"],
98 r3
: reg
, reg_thumb
= ["r3", "a4"],
99 r4
: reg
, reg_thumb
= ["r4", "v1"],
100 r5
: reg
, reg_thumb
= ["r5", "v2"],
101 r7
: reg
, reg_thumb
= ["r7", "v4"] % frame_pointer_r7
,
102 r8
: reg
= ["r8", "v5"],
103 r9
: reg
= ["r9", "v6", "rfp"],
104 r10
: reg
= ["r10", "sl"],
105 r11
: reg
= ["r11", "fp"] % frame_pointer_r11
,
106 r12
: reg
= ["r12", "ip"],
107 r14
: reg
= ["r14", "lr"],
108 s0
: sreg
, sreg_low16
= ["s0"],
109 s1
: sreg
, sreg_low16
= ["s1"],
110 s2
: sreg
, sreg_low16
= ["s2"],
111 s3
: sreg
, sreg_low16
= ["s3"],
112 s4
: sreg
, sreg_low16
= ["s4"],
113 s5
: sreg
, sreg_low16
= ["s5"],
114 s6
: sreg
, sreg_low16
= ["s6"],
115 s7
: sreg
, sreg_low16
= ["s7"],
116 s8
: sreg
, sreg_low16
= ["s8"],
117 s9
: sreg
, sreg_low16
= ["s9"],
118 s10
: sreg
, sreg_low16
= ["s10"],
119 s11
: sreg
, sreg_low16
= ["s11"],
120 s12
: sreg
, sreg_low16
= ["s12"],
121 s13
: sreg
, sreg_low16
= ["s13"],
122 s14
: sreg
, sreg_low16
= ["s14"],
123 s15
: sreg
, sreg_low16
= ["s15"],
140 d0
: dreg
, dreg_low16
, dreg_low8
= ["d0"],
141 d1
: dreg
, dreg_low16
, dreg_low8
= ["d1"],
142 d2
: dreg
, dreg_low16
, dreg_low8
= ["d2"],
143 d3
: dreg
, dreg_low16
, dreg_low8
= ["d3"],
144 d4
: dreg
, dreg_low16
, dreg_low8
= ["d4"],
145 d5
: dreg
, dreg_low16
, dreg_low8
= ["d5"],
146 d6
: dreg
, dreg_low16
, dreg_low8
= ["d6"],
147 d7
: dreg
, dreg_low16
, dreg_low8
= ["d7"],
148 d8
: dreg
, dreg_low16
= ["d8"],
149 d9
: dreg
, dreg_low16
= ["d9"],
150 d10
: dreg
, dreg_low16
= ["d10"],
151 d11
: dreg
, dreg_low16
= ["d11"],
152 d12
: dreg
, dreg_low16
= ["d12"],
153 d13
: dreg
, dreg_low16
= ["d13"],
154 d14
: dreg
, dreg_low16
= ["d14"],
155 d15
: dreg
, dreg_low16
= ["d15"],
172 q0
: qreg
, qreg_low8
, qreg_low4
= ["q0"],
173 q1
: qreg
, qreg_low8
, qreg_low4
= ["q1"],
174 q2
: qreg
, qreg_low8
, qreg_low4
= ["q2"],
175 q3
: qreg
, qreg_low8
, qreg_low4
= ["q3"],
176 q4
: qreg
, qreg_low8
= ["q4"],
177 q5
: qreg
, qreg_low8
= ["q5"],
178 q6
: qreg
, qreg_low8
= ["q6"],
179 q7
: qreg
, qreg_low8
= ["q7"],
188 #error = ["r6", "v3"] =>
189 "r6 is used internally by LLVM and cannot be used as an operand for inline asm",
190 #error = ["r13", "sp"] =>
191 "the stack pointer cannot be used as an operand for inline asm",
192 #error = ["r15", "pc"] =>
193 "the program pointer cannot be used as an operand for inline asm",
197 impl ArmInlineAsmReg
{
200 out
: &mut dyn fmt
::Write
,
201 _arch
: InlineAsmArch
,
202 modifier
: Option
<char>,
204 // Only qreg is allowed to have modifiers. This should have been
205 // validated already by now.
206 if let Some(modifier
) = modifier
{
207 let index
= self as u32 - Self::q0
as u32;
209 let index
= index
* 2 + (modifier
== 'f'
) as u32;
210 write
!(out
, "d{}", index
)
212 out
.write_str(self.name())
216 pub fn overlapping_regs(self, mut cb
: impl FnMut(ArmInlineAsmReg
)) {
219 macro_rules
! reg_conflicts
{
222 $q
:ident
: $d0
:ident $d1
:ident
: $s0
:ident $s1
:ident $s2
:ident $s3
:ident
225 $q_high
:ident
: $d0_high
:ident $d1_high
:ident
248 Self::$s0
| Self::$s1
=> {
252 Self::$s2
| Self::$s3
=> {
262 Self::$d0_high
| Self::$d1_high
=> {
271 // ARM's floating-point register file is interesting in that it can be
272 // viewed as 16 128-bit registers, 32 64-bit registers or 32 32-bit
273 // registers. Because these views overlap, the registers of different
274 // widths will conflict (e.g. d0 overlaps with s0 and s1, and q1
275 // overlaps with d2 and d3).
277 // See section E1.3.1 of the ARM Architecture Reference Manual for
278 // ARMv8-A for more details.
280 q0
: d0 d1
: s0 s1 s2 s3
,
281 q1
: d2 d3
: s4 s5 s6 s7
,
282 q2
: d4 d5
: s8 s9 s10 s11
,
283 q3
: d6 d7
: s12 s13 s14 s15
,
284 q4
: d8 d9
: s16 s17 s18 s19
,
285 q5
: d10 d11
: s20 s21 s22 s23
,
286 q6
: d12 d13
: s24 s25 s26 s27
,
287 q7
: d14 d15
: s28 s29 s30 s31
;