Skip to content

Commit 78d7814

Browse files
committed
Tidy up some inline asm and add compiler fences where appropriate
1 parent b05a24e commit 78d7814

15 files changed

+76
-66
lines changed

asm/inline.rs

Lines changed: 76 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
//! All of these functions should be blanket-`unsafe`. `cortex-m` provides safe wrappers where
77
//! applicable.
88
9+
use core::sync::atomic::{Ordering, compiler_fence};
10+
911
#[inline(always)]
1012
pub unsafe fn __bkpt() {
1113
asm!("bkpt");
@@ -20,45 +22,58 @@ pub unsafe fn __control_r() -> u32 {
2022

2123
#[inline(always)]
2224
pub unsafe fn __control_w(w: u32) {
23-
asm!("msr CONTROL, {}", in(reg) w);
25+
// ISB is required after writing to CONTROL,
26+
// per ARM architectural requirements (see Application Note 321).
27+
asm!("msr CONTROL, {}", "isb", in(reg) w);
28+
29+
// Ensure instructions are not reordered around the CONTROL update.
30+
compiler_fence(Ordering::SeqCst);
2431
}
2532

2633
#[inline(always)]
2734
pub unsafe fn __cpsid() {
2835
asm!("cpsid i");
36+
37+
// Ensure no subsequent instructions are reordered to before interrupts are disabled.
38+
compiler_fence(Ordering::SeqCst);
2939
}
3040

3141
#[inline(always)]
3242
pub unsafe fn __cpsie() {
43+
// Ensure no preceeding instructions are reordered to after interrupts are enabled.
44+
compiler_fence(Ordering::SeqCst);
45+
3346
asm!("cpsie i");
3447
}
3548

3649
#[inline(always)]
3750
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);
51+
// Use local labels to avoid R_ARM_THM_JUMP8 relocations which fail on thumbv6m.
52+
asm!(
53+
"1:",
54+
"nop",
55+
"subs {}, #1",
56+
"bne 1b",
57+
in(reg) cyc
58+
);
4659
}
4760

48-
// FIXME do we need compiler fences here or should we expect them in the caller?
4961
#[inline(always)]
5062
pub unsafe fn __dmb() {
51-
asm!("dmb 0xF");
63+
asm!("dmb");
64+
compiler_fence(Ordering::AcqRel);
5265
}
5366

5467
#[inline(always)]
5568
pub unsafe fn __dsb() {
56-
asm!("dsb 0xF");
69+
asm!("dsb");
70+
compiler_fence(Ordering::SeqCst);
5771
}
5872

5973
#[inline(always)]
6074
pub unsafe fn __isb() {
61-
asm!("isb 0xF");
75+
asm!("isb");
76+
compiler_fence(Ordering::SeqCst);
6277
}
6378

6479
#[inline(always)]
@@ -93,28 +108,28 @@ pub unsafe fn __nop() {
93108
#[inline(always)]
94109
pub unsafe fn __pc_r() -> u32 {
95110
let r;
96-
asm!("mov {}, R15", out(reg) r);
111+
asm!("mov {}, pc", out(reg) r);
97112
r
98113
}
99114

100115
// NOTE: No FFI shim, this requires inline asm.
101116
#[inline(always)]
102117
pub unsafe fn __pc_w(val: u32) {
103-
asm!("mov R15, {}", in(reg) val);
118+
asm!("mov pc, {}", in(reg) val);
104119
}
105120

106121
// NOTE: No FFI shim, this requires inline asm.
107122
#[inline(always)]
108123
pub unsafe fn __lr_r() -> u32 {
109124
let r;
110-
asm!("mov {}, R14", out(reg) r);
125+
asm!("mov {}, lr", out(reg) r);
111126
r
112127
}
113128

114129
// NOTE: No FFI shim, this requires inline asm.
115130
#[inline(always)]
116131
pub unsafe fn __lr_w(val: u32) {
117-
asm!("mov R14, {}", in(reg) val);
132+
asm!("mov lr, {}", in(reg) val);
118133
}
119134

120135
#[inline(always)]
@@ -161,6 +176,8 @@ pub unsafe fn __wfi() {
161176
pub use self::v7m::*;
162177
#[cfg(any(armv7m, armv8m_main))]
163178
mod v7m {
179+
use core::sync::atomic::{Ordering, compiler_fence};
180+
164181
#[inline(always)]
165182
pub unsafe fn __basepri_max(val: u8) {
166183
asm!("msr BASEPRI_MAX, {}", in(reg) val);
@@ -185,45 +202,42 @@ mod v7m {
185202
r
186203
}
187204

188-
// FIXME: compiler_fences necessary?
189205
#[inline(always)]
190206
pub unsafe fn __enable_icache() {
191207
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") _,
208+
"ldr {0}, =0xE000ED14", // CCR
209+
"mrs {2}, PRIMASK", // save critical nesting info
210+
"cpsid i", // mask interrupts
211+
"ldr {1}, [{0}]", // read CCR
212+
"orr.w {1}, {1}, #(1 << 17)", // Set bit 17, IC
213+
"str {1}, [{0}]", // write it back
214+
"dsb", // ensure store completes
215+
"isb", // synchronize pipeline
216+
"msr PRIMASK, {2}", // unnest critical section
217+
out(reg) _,
218+
out(reg) _,
219+
out(reg) _,
206220
);
221+
compiler_fence(Ordering::SeqCst);
207222
}
208223

209224
#[inline(always)]
210225
pub unsafe fn __enable_dcache() {
211226
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") _,
227+
"ldr {0}, =0xE000ED14", // CCR
228+
"mrs {2}, PRIMASK", // save critical nesting info
229+
"cpsid i", // mask interrupts
230+
"ldr {1}, [{0}]", // read CCR
231+
"orr.w {1}, {1}, #(1 << 16)", // Set bit 16, DC
232+
"str {1}, [{0}]", // write it back
233+
"dsb", // ensure store completes
234+
"isb", // synchronize pipeline
235+
"msr PRIMASK, {2}", // unnest critical section
236+
out(reg) _,
237+
out(reg) _,
238+
out(reg) _,
226239
);
240+
compiler_fence(Ordering::SeqCst);
227241
}
228242
}
229243

@@ -234,34 +248,30 @@ mod v7em {
234248
#[inline(always)]
235249
pub unsafe fn __basepri_max_cm7_r0p1(val: u8) {
236250
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-
",
251+
"mrs {1}, PRIMASK",
252+
"cpsid i",
253+
"tst.w {1}, #1",
254+
"msr BASEPRI_MAX, {0}",
255+
"it ne",
256+
"bxne lr",
257+
"cpsie i",
246258
in(reg) val,
247-
out("r1") _,
259+
out(reg) _,
248260
);
249261
}
250262

251263
#[inline(always)]
252264
pub unsafe fn __basepri_w_cm7_r0p1(val: u8) {
253265
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-
",
266+
"mrs {1}, PRIMASK",
267+
"cpsid i",
268+
"tst.w {1}, #1",
269+
"msr BASEPRI, {0}",
270+
"it ne",
271+
"bxne lr",
272+
"cpsie i",
263273
in(reg) val,
264-
out("r1") _,
274+
out(reg) _,
265275
);
266276
}
267277
}

bin/thumbv6m-none-eabi-lto.a

492 Bytes
Binary file not shown.

bin/thumbv6m-none-eabi.a

924 Bytes
Binary file not shown.

bin/thumbv7em-none-eabi-lto.a

-916 Bytes
Binary file not shown.

bin/thumbv7em-none-eabi.a

1004 Bytes
Binary file not shown.

bin/thumbv7em-none-eabihf-lto.a

-900 Bytes
Binary file not shown.

bin/thumbv7em-none-eabihf.a

972 Bytes
Binary file not shown.

bin/thumbv7m-none-eabi-lto.a

-552 Bytes
Binary file not shown.

bin/thumbv7m-none-eabi.a

1000 Bytes
Binary file not shown.

bin/thumbv8m.base-none-eabi-lto.a

552 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)