Skip to content

Commit a357297

Browse files
Merge asm implementations
1 parent 54f541c commit a357297

35 files changed

+603
-754
lines changed

asm/inline.rs

Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
//! Inline assembly implementing the routines exposed in `cortex_m::asm`.
2+
//!
3+
//! If the `inline-asm` feature is enabled, these functions will be directly called by the
4+
//! `cortex-m` wrappers. Otherwise, `cortex-m` links against them via prebuilt archives.
5+
//!
6+
//! All of these functions should be blanket-`unsafe`. `cortex-m` provides safe wrappers where
7+
//! applicable.
8+
9+
#[inline(always)]
10+
pub unsafe fn __bkpt() {
11+
asm!("bkpt");
12+
}
13+
14+
#[inline(always)]
15+
pub unsafe fn __control_r() -> u32 {
16+
let r;
17+
asm!("mrs {}, CONTROL", out(reg) r);
18+
r
19+
}
20+
21+
#[inline(always)]
22+
pub unsafe fn __control_w(w: u32) {
23+
asm!("msr CONTROL, {}", in(reg) w);
24+
}
25+
26+
#[inline(always)]
27+
pub unsafe fn __cpsid() {
28+
asm!("cpsid i");
29+
}
30+
31+
#[inline(always)]
32+
pub unsafe fn __cpsie() {
33+
asm!("cpsie i");
34+
}
35+
36+
#[inline(always)]
37+
pub unsafe fn __delay(cyc: u32) {
38+
asm!("
39+
1:
40+
nop
41+
subs {}, #1
42+
bne 1b
43+
// Branch to 1 instead of delay does not generate R_ARM_THM_JUMP8 relocation, which breaks
44+
// linking on the thumbv6m-none-eabi target
45+
", in(reg) cyc);
46+
}
47+
48+
// FIXME do we need compiler fences here or should we expect them in the caller?
49+
#[inline(always)]
50+
pub unsafe fn __dmb() {
51+
asm!("dmb 0xF");
52+
}
53+
54+
#[inline(always)]
55+
pub unsafe fn __dsb() {
56+
asm!("dsb 0xF");
57+
}
58+
59+
#[inline(always)]
60+
pub unsafe fn __isb() {
61+
asm!("isb 0xF");
62+
}
63+
64+
#[inline(always)]
65+
pub unsafe fn __msp_r() -> u32 {
66+
let r;
67+
asm!("mrs {}, MSP", out(reg) r);
68+
r
69+
}
70+
71+
#[inline(always)]
72+
pub unsafe fn __msp_w(val: u32) {
73+
asm!("msr MSP, {}", in(reg) val);
74+
}
75+
76+
// NOTE: No FFI shim, this requires inline asm.
77+
#[inline(always)]
78+
pub unsafe fn __apsr_r() -> u32 {
79+
let r;
80+
asm!("mrs {}, APSR", out(reg) r);
81+
r
82+
}
83+
84+
#[inline(always)]
85+
pub unsafe fn __nop() {
86+
// NOTE: This is a `pure` asm block, but applying that option allows the compiler to eliminate
87+
// the nop entirely (or to collapse multiple subsequent ones). Since the user probably wants N
88+
// nops when they call `nop` N times, let's not add that option.
89+
asm!("nop");
90+
}
91+
92+
// NOTE: No FFI shim, this requires inline asm.
93+
#[inline(always)]
94+
pub unsafe fn __pc_r() -> u32 {
95+
let r;
96+
asm!("mov {}, R15", out(reg) r);
97+
r
98+
}
99+
100+
// NOTE: No FFI shim, this requires inline asm.
101+
#[inline(always)]
102+
pub unsafe fn __pc_w(val: u32) {
103+
asm!("mov R15, {}", in(reg) val);
104+
}
105+
106+
// NOTE: No FFI shim, this requires inline asm.
107+
#[inline(always)]
108+
pub unsafe fn __lr_r() -> u32 {
109+
let r;
110+
asm!("mov {}, R14", out(reg) r);
111+
r
112+
}
113+
114+
// NOTE: No FFI shim, this requires inline asm.
115+
#[inline(always)]
116+
pub unsafe fn __lr_w(val: u32) {
117+
asm!("mov R14, {}", in(reg) val);
118+
}
119+
120+
#[inline(always)]
121+
pub unsafe fn __primask_r() -> u32 {
122+
let r;
123+
asm!("mrs {}, PRIMASK", out(reg) r);
124+
r
125+
}
126+
127+
#[inline(always)]
128+
pub unsafe fn __psp_r() -> u32 {
129+
let r;
130+
asm!("mrs {}, PSP", out(reg) r);
131+
r
132+
}
133+
134+
#[inline(always)]
135+
pub unsafe fn __psp_w(val: u32) {
136+
asm!("msr PSP, {}", in(reg) val);
137+
}
138+
139+
#[inline(always)]
140+
pub unsafe fn __sev() {
141+
asm!("sev");
142+
}
143+
144+
#[inline(always)]
145+
pub unsafe fn __udf() -> ! {
146+
asm!("udf #0", options(noreturn));
147+
}
148+
149+
#[inline(always)]
150+
pub unsafe fn __wfe() {
151+
asm!("wfe");
152+
}
153+
154+
#[inline(always)]
155+
pub unsafe fn __wfi() {
156+
asm!("wfi");
157+
}
158+
159+
// v7m *AND* v8m.main, but *NOT* v8m.base
160+
#[cfg(any(armv7m, armv8m_main))]
161+
pub use self::v7m::*;
162+
#[cfg(any(armv7m, armv8m_main))]
163+
mod v7m {
164+
#[inline(always)]
165+
pub unsafe fn __basepri_max(val: u8) {
166+
asm!("msr BASEPRI_MAX, {}", in(reg) val);
167+
}
168+
169+
#[inline(always)]
170+
pub unsafe fn __basepri_r() -> u8 {
171+
let r;
172+
asm!("mrs {}, BASEPRI", out(reg) r);
173+
r
174+
}
175+
176+
#[inline(always)]
177+
pub unsafe fn __basepri_w(val: u8) {
178+
asm!("msr BASEPRI, {}", in(reg) val);
179+
}
180+
181+
#[inline(always)]
182+
pub unsafe fn __faultmask_r() -> u32 {
183+
let r;
184+
asm!("mrs {}, FAULTMASK", out(reg) r);
185+
r
186+
}
187+
188+
// FIXME: compiler_fences necessary?
189+
#[inline(always)]
190+
pub unsafe fn __enable_icache() {
191+
asm!(
192+
"
193+
ldr r0, =0xE000ED14 @ CCR
194+
mrs r2, PRIMASK @ save critical nesting info
195+
cpsid i @ mask interrupts
196+
ldr r1, [r0] @ read CCR
197+
orr.w r1, r1, #(1 << 17) @ Set bit 17, IC
198+
str r1, [r0] @ write it back
199+
dsb @ ensure store completes
200+
isb @ synchronize pipeline
201+
msr PRIMASK, r2 @ unnest critical section
202+
",
203+
out("r0") _,
204+
out("r1") _,
205+
out("r2") _,
206+
);
207+
}
208+
209+
#[inline(always)]
210+
pub unsafe fn __enable_dcache() {
211+
asm!(
212+
"
213+
ldr r0, =0xE000ED14 @ CCR
214+
mrs r2, PRIMASK @ save critical nesting info
215+
cpsid i @ mask interrupts
216+
ldr r1, [r0] @ read CCR
217+
orr.w r1, r1, #(1 << 16) @ Set bit 16, DC
218+
str r1, [r0] @ write it back
219+
dsb @ ensure store completes
220+
isb @ synchronize pipeline
221+
msr PRIMASK, r2 @ unnest critical section
222+
",
223+
out("r0") _,
224+
out("r1") _,
225+
out("r2") _,
226+
);
227+
}
228+
}
229+
230+
#[cfg(armv7em)]
231+
pub use self::v7em::*;
232+
#[cfg(armv7em)]
233+
mod v7em {
234+
#[inline(always)]
235+
pub unsafe fn __basepri_max_cm7_r0p1(val: u8) {
236+
asm!(
237+
"
238+
mrs r1, PRIMASK
239+
cpsid i
240+
tst.w r1, #1
241+
msr BASEPRI_MAX, {}
242+
it ne
243+
bxne lr
244+
cpsie i
245+
",
246+
in(reg) val,
247+
out("r1") _,
248+
);
249+
}
250+
251+
#[inline(always)]
252+
pub unsafe fn __basepri_w_cm7_r0p1(val: u8) {
253+
asm!(
254+
"
255+
mrs r1, PRIMASK
256+
cpsid i
257+
tst.w r1, #1
258+
msr BASEPRI, {}
259+
it ne
260+
bxne lr
261+
cpsie i
262+
",
263+
in(reg) val,
264+
out("r1") _,
265+
);
266+
}
267+
}
268+
269+
#[cfg(armv8m)]
270+
pub use self::v8m::*;
271+
/// Baseline and Mainline.
272+
#[cfg(armv8m)]
273+
mod v8m {
274+
#[inline(always)]
275+
pub unsafe fn __tt(mut target: u32) -> u32 {
276+
asm!("tt {target}, {target}", target = inout(reg) target);
277+
target
278+
}
279+
280+
#[inline(always)]
281+
pub unsafe fn __ttt(mut target: u32) -> u32 {
282+
asm!("ttt {target}, {target}", target = inout(reg) target);
283+
target
284+
}
285+
286+
#[inline(always)]
287+
pub unsafe fn __tta(mut target: u32) -> u32 {
288+
asm!("tta {target}, {target}", target = inout(reg) target);
289+
target
290+
}
291+
292+
#[inline(always)]
293+
pub unsafe fn __ttat(mut target: u32) -> u32 {
294+
asm!("ttat {target}, {target}", target = inout(reg) target);
295+
target
296+
}
297+
}
298+
299+
#[cfg(armv8m_main)]
300+
pub use self::v8m_main::*;
301+
/// Mainline only.
302+
#[cfg(armv8m_main)]
303+
mod v8m_main {
304+
#[inline(always)]
305+
pub unsafe fn __msplim_r() -> u32 {
306+
let r;
307+
asm!("mrs {}, MSPLIM", out(reg) r);
308+
r
309+
}
310+
311+
#[inline(always)]
312+
pub unsafe fn __msplim_w(val: u32) {
313+
asm!("msr MSPLIM, {}", in(reg) val);
314+
}
315+
316+
#[inline(always)]
317+
pub unsafe fn __psplim_r() -> u32 {
318+
let r;
319+
asm!("mrs {}, PSPLIM", out(reg) r);
320+
r
321+
}
322+
323+
#[inline(always)]
324+
pub unsafe fn __psplim_w(val: u32) {
325+
asm!("msr PSPLIM, {}", in(reg) val);
326+
}
327+
}
328+
329+
#[cfg(has_fpu)]
330+
pub use self::fpu::*;
331+
/// All targets with FPU.
332+
#[cfg(has_fpu)]
333+
mod fpu {
334+
#[inline(always)]
335+
pub unsafe fn __fpscr_r() -> u32 {
336+
let r;
337+
asm!("vmrs {}, fpscr", out(reg) r);
338+
r
339+
}
340+
341+
#[inline(always)]
342+
pub unsafe fn __fpscr_w(val: u32) {
343+
asm!("vmsr fpscr, {}", in(reg) val);
344+
}
345+
}

0 commit comments

Comments
 (0)