armv7-a/r: use SRS and RFE for exception handler

This commit is contained in:
zhangyuan21
2022-09-09 12:10:28 +08:00
committed by Masayuki Ishikawa
parent 8b8534c4b4
commit 3b889d820f
4 changed files with 162 additions and 224 deletions
+5 -4
View File
@@ -66,10 +66,8 @@
#define REG_R12 (12)
#define REG_R13 (13)
#define REG_R14 (14)
#define REG_R15 (15)
#define REG_CPSR (16)
#define ARM_CONTEXT_REGS (17)
#define ARM_CONTEXT_REGS (15)
/* If the MCU supports a floating point unit, then it will be necessary
* to save the state of the FPU status register and data registers on
@@ -162,9 +160,12 @@
# define FPU_CONTEXT_REGS (0)
#endif
#define REG_R15 (ARM_CONTEXT_REGS + FPU_CONTEXT_REGS)
#define REG_CPSR (REG_R15 + 1)
/* The total number of registers saved by software */
#define XCPTCONTEXT_REGS (ARM_CONTEXT_REGS + FPU_CONTEXT_REGS)
#define XCPTCONTEXT_REGS (REG_CPSR + 1)
#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS)
/* Friendly register names */
+5 -4
View File
@@ -66,10 +66,8 @@
#define REG_R12 (12)
#define REG_R13 (13)
#define REG_R14 (14)
#define REG_R15 (15)
#define REG_CPSR (16)
#define ARM_CONTEXT_REGS (17)
#define ARM_CONTEXT_REGS (15)
/* If the MCU supports a floating point unit, then it will be necessary
* to save the state of the FPU status register and data registers on
@@ -162,9 +160,12 @@
# define FPU_CONTEXT_REGS (0)
#endif
#define REG_R15 (ARM_CONTEXT_REGS + FPU_CONTEXT_REGS)
#define REG_CPSR (REG_R15 + 1)
/* The total number of registers saved by software */
#define XCPTCONTEXT_REGS (ARM_CONTEXT_REGS + FPU_CONTEXT_REGS)
#define XCPTCONTEXT_REGS (REG_CPSR + 1)
#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS)
/* Friendly register names */
+76 -108
View File
@@ -171,6 +171,12 @@
.type arm_vectorirq, %function
arm_vectorirq:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
sub lr, lr, #4
srsdb sp, #PSR_MODE_SYS
/* Switch to SYS mode */
#ifdef CONFIG_ARMV7A_DECODEFIQ
@@ -186,24 +192,15 @@ arm_vectorirq:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_IRQ /* Switch back IRQ mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
sub r3, lr, #4
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -265,18 +262,16 @@ arm_vectorirq:
* context switch is required.
*/
/* Restore the CPSR, IRQ mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is IRQ mode */
mov r14, r0 /* (IRQ) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (IRQ) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 7
.Lirqstacktop:
@@ -299,6 +294,11 @@ arm_vectorirq:
.type arm_vectorsvc, %function
arm_vectorsvc:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
srsdb sp, #PSR_MODE_SYS
/* Switch to SYS mode */
#ifdef CONFIG_ARMV7A_DECODEFIQ
@@ -314,24 +314,15 @@ arm_vectorsvc:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_SVC /* Switch back SVC mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
mov r3, r14 /* Save r14 as the PC as well */
mrs r4, spsr /* Get the saved CPSR */
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -395,18 +386,16 @@ arm_vectorsvc:
* context switch is required.
*/
/* Restore the CPSR, SYS mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is SVC mode */
mov r14, r0 /* (SVC) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (SVC) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
.size arm_vectorsvc, . - arm_vectorsvc
.align 5
@@ -427,6 +416,12 @@ arm_vectorsvc:
.type arm_vectordata, %function
arm_vectordata:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
sub lr, lr, #8
srsdb sp, #PSR_MODE_SYS
/* Switch to SYS mode */
#ifdef CONFIG_ARMV7A_DECODEFIQ
@@ -442,24 +437,15 @@ arm_vectordata:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_ABT /* Switch back ABT mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
sub r3, lr, #8
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -498,18 +484,16 @@ arm_vectordata:
* context switch is required.
*/
/* Restore the CPSR, ABT mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is ABT mode */
mov r14, r0 /* (ABT) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (ABT) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
.size arm_vectordata, . - arm_vectordata
.align 5
@@ -530,6 +514,12 @@ arm_vectordata:
.type arm_vectorprefetch, %function
arm_vectorprefetch:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
sub lr, lr, #4
srsdb sp, #PSR_MODE_SYS
cpsid if, #PSR_MODE_SYS /* Switch to SYS mode */
/* Create a context structure. First set aside a stack frame
@@ -539,24 +529,15 @@ arm_vectorprefetch:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_ABT /* Switch back ABT mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
sub r3, lr, #4
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -595,18 +576,16 @@ arm_vectorprefetch:
* context switch is required.
*/
/* Restore the CPSR, ABT mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is ABT mode */
mov r14, r0 /* (ABT) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (ABT) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
.size arm_vectorprefetch, . - arm_vectorprefetch
.align 5
@@ -625,6 +604,11 @@ arm_vectorprefetch:
.type arm_vectorundefinsn, %function
arm_vectorundefinsn:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
srsdb sp, #PSR_MODE_SYS
cpsid if, #PSR_MODE_SYS /* Switch to SYS mode */
/* Create a context structure. First set aside a stack frame
@@ -634,24 +618,15 @@ arm_vectorundefinsn:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_UND /* Switch back UND mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
mov r3, lr
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -688,18 +663,16 @@ arm_vectorundefinsn:
* context switch is required.
*/
/* Restore the CPSR, UND mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is UND mode */
mov r14, r0 /* (UND) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (UND) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
.size arm_vectorundefinsn, . - arm_vectorundefinsn
.align 5
@@ -721,6 +694,12 @@ arm_vectorundefinsn:
arm_vectorfiq:
#ifdef CONFIG_ARMV7A_DECODEFIQ
/* Save the LR and SPSR onto the SYS mode stack before switch. */
sub lr, lr, #4
srsdb sp, #PSR_MODE_SYS
cpsid if, #PSR_MODE_SYS /* Switch to SYS mode */
/* Create a context structure. First set aside a stack frame
@@ -730,24 +709,15 @@ arm_vectorfiq:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_FIQ /* Switch back FIQ mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
sub r3, lr, #4
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -796,18 +766,16 @@ arm_vectorfiq:
* context switch is required.
*/
/* Restore the CPSR, FIQ mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is FIQ mode */
mov r14, r0 /* (FIQ) r14=Register storage area */
ldmia r14!, {r0-r7} /* Restore common r0-r7 */
ldmia r14, {r8-r14}^ /* Restore user mode r8-r14 */
add r14, r14, #(4*7) /* (FIQ) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 7
.Lfiqstacktop:
+76 -108
View File
@@ -125,6 +125,12 @@
.type arm_vectorirq, %function
arm_vectorirq:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
sub lr, lr, #4
srsdb sp, #PSR_MODE_SYS
/* Switch to SYS mode */
#ifdef CONFIG_ARMV7A_DECODEFIQ
@@ -140,24 +146,15 @@ arm_vectorirq:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_IRQ /* Switch back IRQ mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
sub r3, lr, #4
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -219,18 +216,16 @@ arm_vectorirq:
* context switch is required.
*/
/* Restore the CPSR, IRQ mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is IRQ mode */
mov r14, r0 /* (IRQ) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (IRQ) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
#if CONFIG_ARCH_INTERRUPTSTACK > 7
.Lirqstacktop:
@@ -253,6 +248,11 @@ arm_vectorirq:
.type arm_vectorsvc, %function
arm_vectorsvc:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
srsdb sp, #PSR_MODE_SYS
/* Switch to SYS mode */
#ifdef CONFIG_ARMV7A_DECODEFIQ
@@ -268,24 +268,15 @@ arm_vectorsvc:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_SVC /* Switch back SVC mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
mov r3, r14 /* Save r14 as the PC as well */
mrs r4, spsr /* Get the saved CPSR */
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -349,18 +340,16 @@ arm_vectorsvc:
* context switch is required.
*/
/* Restore the CPSR, SYS mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is SVC mode */
mov r14, r0 /* (SVC) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (SVC) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
.size arm_vectorsvc, . - arm_vectorsvc
.align 5
@@ -381,6 +370,12 @@ arm_vectorsvc:
.type arm_vectordata, %function
arm_vectordata:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
sub lr, lr, #8
srsdb sp, #PSR_MODE_SYS
/* Switch to SYS mode */
#ifdef CONFIG_ARMV7A_DECODEFIQ
@@ -396,24 +391,15 @@ arm_vectordata:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_ABT /* Switch back ABT mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
sub r3, lr, #8
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -452,18 +438,16 @@ arm_vectordata:
* context switch is required.
*/
/* Restore the CPSR, ABT mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is ABT mode */
mov r14, r0 /* (ABT) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (ABT) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
.size arm_vectordata, . - arm_vectordata
.align 5
@@ -484,6 +468,12 @@ arm_vectordata:
.type arm_vectorprefetch, %function
arm_vectorprefetch:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
sub lr, lr, #4
srsdb sp, #PSR_MODE_SYS
cpsid if, #PSR_MODE_SYS /* Switch to SYS mode */
/* Create a context structure. First set aside a stack frame
@@ -493,24 +483,15 @@ arm_vectorprefetch:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_ABT /* Switch back ABT mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
sub r3, lr, #4
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -549,18 +530,16 @@ arm_vectorprefetch:
* context switch is required.
*/
/* Restore the CPSR, ABT mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is ABT mode */
mov r14, r0 /* (ABT) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (ABT) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
.size arm_vectorprefetch, . - arm_vectorprefetch
.align 5
@@ -579,6 +558,11 @@ arm_vectorprefetch:
.type arm_vectorundefinsn, %function
arm_vectorundefinsn:
/* Save the LR and SPSR onto the SYS mode stack before switch. */
srsdb sp, #PSR_MODE_SYS
cpsid if, #PSR_MODE_SYS /* Switch to SYS mode */
/* Create a context structure. First set aside a stack frame
@@ -588,24 +572,15 @@ arm_vectorundefinsn:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_UND /* Switch back UND mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
mov r3, lr
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -642,18 +617,16 @@ arm_vectorundefinsn:
* context switch is required.
*/
/* Restore the CPSR, UND mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is UND mode */
mov r14, r0 /* (UND) r14=Register storage area */
ldmia r14!, {r0-r12} /* Restore common r0-r12 */
ldmia r14, {r13, r14}^ /* Restore user mode r13/r14 */
add r14, r14, #(4*2) /* (UND) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
.size arm_vectorundefinsn, . - arm_vectorundefinsn
.align 5
@@ -675,6 +648,12 @@ arm_vectorundefinsn:
arm_vectorfiq:
#ifdef CONFIG_ARMV7R_DECODEFIQ
/* Save the LR and SPSR onto the SYS mode stack before switch. */
sub lr, lr, #4
srsdb sp, #PSR_MODE_SYS
cpsid if, #PSR_MODE_SYS /* Switch to SYS mode */
/* Create a context structure. First set aside a stack frame
@@ -684,24 +663,15 @@ arm_vectorfiq:
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SYS mode regs */
cps #PSR_MODE_FIQ /* Switch back FIQ mode */
/* Get the values for r15(pc) and CPSR in r3 and r4 */
sub r3, lr, #4
mrs r4, spsr
cps #PSR_MODE_SYS /* Then switch back to SYS mode */
/* Get the correct values of USR/SYS r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Save r13(sp), r14(lr), r15(pc), and the CPSR */
/* Save r13(sp), r14(lr) */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
stmia r0, {r1-r2}
#ifdef CONFIG_ARCH_FPU
/* Save the state of the floating point registers. */
@@ -750,18 +720,16 @@ arm_vectorfiq:
* context switch is required.
*/
/* Restore the CPSR, FIQ mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the return SPSR */
msr spsr_cxsf, r1 /* Set the return mode SPSR */
/* Life is simple when everything is FIQ mode */
mov r14, r0 /* (FIQ) r14=Register storage area */
ldmia r14!, {r0-r7} /* Restore common r0-r7 */
ldmia r14, {r8-r14}^ /* Restore user mode r8-r14 */
add r14, r14, #(4*7) /* (FIQ) r14=address of r15 storage */
ldmia r14, {r15}^ /* Return */
/* Restore the CPSR, SYS mode registers and return. */
add r14, r14, #(4*(REG_R15-REG_R13))
rfeia r14
#if CONFIG_ARCH_INTERRUPTSTACK > 7
.Lfiqstacktop: