use core::arch::global_asm;
global_asm!(r#"
.macro ExceptionEntry
cpsid i
mov r0, lr
movs r1, #0x0F // Check which mode we just came from
ands r0, r1
cmp r0, #0xD // if we came from something other than thread mode/process stack,
bne 2f // skip stacking the rest of the registers and move on
// stack the registers
push {{r4, r5, r6, r7}} // push r4-r7
mov r0, r8
mov r1, r9
mov r2, r10
mov r3, r11
push {{r0, r1, r2, r3}} // push r8-r11
mrs r0, PSP // grab the process stack pointer
push {{r0}} // push PSP
sub sp, #32 // reserve space for the next eight registers
mov r1, sp // copy the stack pointer
ldm r0!, {{r4, r5, r6, r7}} // load r0-r3
stm r1!, {{r4, r5, r6, r7}} // store r0-r3
ldm r0!, {{r4, r5, r6, r7}} // load r12, lr, pc, xpsr
stm r1!, {{r4, r5, r6, r7}} // save r12, lr, pc, xpsr
mov r0, sp // get address of TaskRegisters struct
b 3f
// Don't stack, provide None
2: movs r0, #0
3: push {{lr}} // save LR
.endm
"#);
global_asm!(r#"
.macro ExceptionExit
pop {{r0}} // restore LR
mov lr, r0 // copy to LR
movs r1, #0xF
ands r0, r1
cmp r0, #0xD // check if we were using the process stack
bne 2f // and if not, skip unstacking
ldr r0, [sp, #0x20] // load PSP from the TaskRegisters struct
msr PSP, r0 // Store it back in its register
pop {{r4, r5, r6, r7}} // load r0-r3
stm r0!, {{r4, r5, r6, r7}} // store r0-r3
pop {{r4, r5, r6, r7}} // load r12, lr, pc, xpsr
stm r0!, {{r4, r5, r6, r7}} // store r12, lr, pc, xpsr
add sp, #4 // skip the stack value we already got
pop {{r4, r5, r6, r7}}
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
pop {{r4, r5, r6, r7}}
2: cpsie i
bx lr
.endm
"#);