summaryrefslogtreecommitdiff
path: root/arch/arm/lib/vectors.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/lib/vectors.S')
-rw-r--r--arch/arm/lib/vectors.S21
1 files changed, 20 insertions, 1 deletions
diff --git a/arch/arm/lib/vectors.S b/arch/arm/lib/vectors.S
index 7cf7d1636f5..843f9b9c281 100644
--- a/arch/arm/lib/vectors.S
+++ b/arch/arm/lib/vectors.S
@@ -240,6 +240,18 @@ IRQ_STACK_START_IN:
movs pc, lr @ jump to next instruction & switch modes.
.endm
+ .macro get_bad_stack_swi
+ sub r13, r13, #4 @ space on current stack for scratch reg.
+ str r0, [r13] @ save R0's value.
+ ldr r0, IRQ_STACK_START_IN @ get data regions start
+ str lr, [r0] @ save caller lr in position 0 of saved stack
+ mrs lr, spsr @ get the spsr
+ str lr, [r0, #4] @ save spsr in position 1 of saved stack
+ ldr lr, [r0] @ restore lr
+ ldr r0, [r13] @ restore r0
+ add r13, r13, #4 @ pop stack entry
+ .endm
+
.macro get_irq_stack @ setup IRQ stack
ldr sp, IRQ_STACK_START
.endm
@@ -260,9 +272,16 @@ undefined_instruction:
.align 5
software_interrupt:
- get_bad_stack
+ get_bad_stack_swi
bad_save_user_regs
bl do_software_interrupt
+#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
+ ldmia sp, {r0 - lr}^ @ Calling r0 - lr
+ mov r0, r0
+ ldr lr, [sp, #S_PC] @ Get PC
+ add sp, sp, #S_FRAME_SIZE
+ movs pc, lr @ return & move spsr_svc into cpsr
+#endif
.align 5
prefetch_abort: