1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
// assembly-output: emit-asm
// compile-flags: -O
// compile-flags: --target aarch64-unknown-linux-gnu
// needs-llvm-components: aarch64
#![feature(no_core, lang_items, rustc_attrs)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register)]
#[rustc_builtin_macro]
macro_rules! asm {
() => {};
}
#[rustc_builtin_macro]
macro_rules! stringify {
() => {};
}
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
impl Copy for i32 {}
macro_rules! check {
($func:ident $reg:ident $code:literal) => {
// -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0
#[no_mangle]
pub unsafe extern "C" fn $func() -> i32 {
// Hack to avoid function merging
extern "Rust" {
fn dont_merge(s: &str);
}
dont_merge(stringify!($func));
let y;
asm!($code, out($reg) y);
y
}
};
}
// CHECK-LABEL: reg:
// CHECK: //APP
// CHECK: mov x0, x0
// CHECK: //NO_APP
check!(reg reg "mov {0}, {0}");
// CHECK-LABEL: reg_w:
// CHECK: //APP
// CHECK: mov w0, w0
// CHECK: //NO_APP
check!(reg_w reg "mov {0:w}, {0:w}");
// CHECK-LABEL: reg_x:
// CHECK: //APP
// CHECK: mov x0, x0
// CHECK: //NO_APP
check!(reg_x reg "mov {0:x}, {0:x}");
// CHECK-LABEL: vreg:
// CHECK: //APP
// CHECK: add v0.4s, v0.4s, v0.4s
// CHECK: //NO_APP
check!(vreg vreg "add {0}.4s, {0}.4s, {0}.4s");
// CHECK-LABEL: vreg_b:
// CHECK: //APP
// CHECK: ldr b0, [x0]
// CHECK: //NO_APP
check!(vreg_b vreg "ldr {:b}, [x0]");
// CHECK-LABEL: vreg_h:
// CHECK: //APP
// CHECK: ldr h0, [x0]
// CHECK: //NO_APP
check!(vreg_h vreg "ldr {:h}, [x0]");
// CHECK-LABEL: vreg_s:
// CHECK: //APP
// CHECK: ldr s0, [x0]
// CHECK: //NO_APP
check!(vreg_s vreg "ldr {:s}, [x0]");
// CHECK-LABEL: vreg_d:
// CHECK: //APP
// CHECK: ldr d0, [x0]
// CHECK: //NO_APP
check!(vreg_d vreg "ldr {:d}, [x0]");
// CHECK-LABEL: vreg_q:
// CHECK: //APP
// CHECK: ldr q0, [x0]
// CHECK: //NO_APP
check!(vreg_q vreg "ldr {:q}, [x0]");
// CHECK-LABEL: vreg_v:
// CHECK: //APP
// CHECK: add v0.4s, v0.4s, v0.4s
// CHECK: //NO_APP
check!(vreg_v vreg "add {0:v}.4s, {0:v}.4s, {0:v}.4s");
// CHECK-LABEL: vreg_low16:
// CHECK: //APP
// CHECK: add v0.4s, v0.4s, v0.4s
// CHECK: //NO_APP
check!(vreg_low16 vreg_low16 "add {0}.4s, {0}.4s, {0}.4s");
// CHECK-LABEL: vreg_low16_b:
// CHECK: //APP
// CHECK: ldr b0, [x0]
// CHECK: //NO_APP
check!(vreg_low16_b vreg_low16 "ldr {:b}, [x0]");
// CHECK-LABEL: vreg_low16_h:
// CHECK: //APP
// CHECK: ldr h0, [x0]
// CHECK: //NO_APP
check!(vreg_low16_h vreg_low16 "ldr {:h}, [x0]");
// CHECK-LABEL: vreg_low16_s:
// CHECK: //APP
// CHECK: ldr s0, [x0]
// CHECK: //NO_APP
check!(vreg_low16_s vreg_low16 "ldr {:s}, [x0]");
// CHECK-LABEL: vreg_low16_d:
// CHECK: //APP
// CHECK: ldr d0, [x0]
// CHECK: //NO_APP
check!(vreg_low16_d vreg_low16 "ldr {:d}, [x0]");
// CHECK-LABEL: vreg_low16_q:
// CHECK: //APP
// CHECK: ldr q0, [x0]
// CHECK: //NO_APP
check!(vreg_low16_q vreg_low16 "ldr {:q}, [x0]");
// CHECK-LABEL: vreg_low16_v:
// CHECK: //APP
// CHECK: add v0.4s, v0.4s, v0.4s
// CHECK: //NO_APP
check!(vreg_low16_v vreg_low16 "add {0:v}.4s, {0:v}.4s, {0:v}.4s");
|