diff options
Diffstat (limited to 'asm/inline.rs')
-rw-r--r-- | asm/inline.rs | 22 |
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), ); } |