aboutsummaryrefslogtreecommitdiff
path: root/asm/inline.rs
diff options
context:
space:
mode:
authorGravatar Adam Greig <adam@adamgreig.com> 2020-12-02 14:09:33 +0000
committerGravatar Adam Greig <adam@adamgreig.com> 2020-12-02 14:18:24 +0000
commit3b184eaa0abf147d607f918985bdffd6abe31a51 (patch)
treea6d563deedb3abb80fdbe9426d7cda310b8569fd /asm/inline.rs
parent3a3a812f53d9bb66f3fe042a514f813734eac4c6 (diff)
downloadcortex-m-3b184eaa0abf147d607f918985bdffd6abe31a51.tar.gz
cortex-m-3b184eaa0abf147d607f918985bdffd6abe31a51.tar.zst
cortex-m-3b184eaa0abf147d607f918985bdffd6abe31a51.zip
asm.bootstrap: only set CONTROL.SPSEL, mark as divergent
Diffstat (limited to 'asm/inline.rs')
-rw-r--r--asm/inline.rs22
1 files changed, 14 insertions, 8 deletions
diff --git a/asm/inline.rs b/asm/inline.rs
index bba5e6e..f2014f8 100644
--- a/asm/inline.rs
+++ b/asm/inline.rs
@@ -182,17 +182,23 @@ pub unsafe fn __sh_syscall(mut nr: u32, arg: u32) -> u32 {
nr
}
-/// Bootstrap: ensure we are using the main stack, then write `msp` to MSP and jump to `rv`.
+/// Set CONTROL.SPSEL to 0, write `msp` to MSP, branch to `rv`.
#[inline(always)]
-pub unsafe fn __bootstrap(msp: u32, rv: u32) {
+pub unsafe fn __bootstrap(msp: u32, rv: u32) -> ! {
asm!(
- "msr CONTROL, {}",
+ "mrs {tmp}, CONTROL",
+ "bics {tmp}, {spsel}",
+ "msr CONTROL, {tmp}",
"isb",
- "msr MSP, {}",
- "bx {}",
- in(reg) 0,
- in(reg) msp,
- in(reg) rv,
+ "msr MSP, {msp}",
+ "bx {rv}",
+ // `out(reg) _` is not permitted in a `noreturn` asm! call,
+ // so instead use `in(reg) 0` and don't restore it afterwards.
+ tmp = in(reg) 0,
+ spsel = in(reg) 2,
+ msp = in(reg) msp,
+ rv = in(reg) rv,
+ options(noreturn),
);
}