+ /* Save registers */
+ stmfd sp!, {r4 - r11, lr}
+ /* Save old stack pointer */
+ str sp, [r1]
+ /* Load new stack pointer */
+ ldr sp, [r0]
+ /* Load new registers */
+ ldmfd sp!, {r4 - r11, pc}
+
+#if CONFIG_KERN_PREEMPT
+
+/* ARM interrupt mode with IRQ and FIQ disabled */
+#define ARM_IRQ_MODE 0xD2
+/* ARM supervisor mode with IRQ and FIQ disabled */
+#define ARM_SVC_MODE 0xD3
+
+.globl asm_irq_switch_context
+asm_irq_switch_context:
+ /* Return if preemption is not needed */
+ bl proc_needPreempt
+ cmp r0, #0
+ ldmeqfd sp!, {r0 - r3, ip, pc}^
+
+ /* Otherwise restore regs used by the ISR */
+ ldmfd sp!, {r0 - r3, ip, lr}
+
+ /* Save current process context */
+ msr cpsr_c, #ARM_SVC_MODE
+ stmfd sp!, {r0 - r3, ip, lr}
+
+ /* Save lr_irq and spsr_irq in process stack */
+ msr cpsr_c, #ARM_IRQ_MODE
+ mov r0, lr
+ mrs r1, spsr
+ msr cpsr_c, #ARM_SVC_MODE
+ stmfd sp!, {r0, r1}
+
+ /* Perform the context switch */
+ bl proc_preempt