📄 excalib.s
字号:
SUB lr,lr,#8/* save regs in save area */ STMIB sp,{r0-r3,lr}/* set r0 -> exception vector and join main thread */ MOV r0,#EXC_OFF_DATA B L$excEnterCommon/**************************************************************************** excEnterPrefetchAbort - enter a prefetch abort exception** This routine is installed on the Prefetch Abort exception vector* by excVecInit.** This routine can NEVER be called from C.** SEE ALSO: excVecInit(2)* void excEnterPrefetchAbort ()* INTERNAL* MODE = ABORT32* IRQs disabled* sp -> register save area (see excEnterCommon)*/_ARM_FUNCTION(excEnterPrefetchAbort)/* adjust return address so it points to instruction that faulted */ SUB lr,lr,#4/* save regs in save area */ STMIB sp,{r0-r3,lr}/* set r0 -> exception vector and join main thread */ MOV r0,#EXC_OFF_PREFETCH B L$excEnterCommon/**************************************************************************** excEnterUndef - enter an undefined instruction exception** This routine is installed on the Undefined Instruction vector* by excVecInit.** This routine can NEVER be called from C.** SEE ALSO: excVecInit(2)* void excEnterUndef ()* INTERNAL* MODE = UNDEF32* IRQs disabled* sp -> register save area (see excEnterCommon)*/_ARM_FUNCTION(excEnterUndef)#if (ARM_THUMB)/* save regs in save area */ STMIB sp,{r0-r3}/* adjust return address so it points to instruction that faulted */ MRS r0,spsr /* get PSR of faulting code */ TSTS r0,#T_BIT /* Thumb state? */ SUBNE lr,lr,#2 /* ..yes */ SUBEQ lr,lr,#4 /* ..no, ARM */ STR lr,[sp,#5*4] /* store in save area */#else /* adjust return address so it points to instruction that faulted */ SUB lr,lr,#4/* save regs in save area */ STMIB sp,{r0-r3,lr}#endif/* set r0 -> exception vector and join main thread */ MOV r0,#EXC_OFF_UNDEF /* FALL THROUGH to excEnterCommon *//********************************************************************************* excEnterCommon - enter an exception handler** Control passes to this routine from the exception vectors, after the address* in lr has been adjusted to point to the faulting instruction.** This routine can NEVER be called from C.** void excEnterCommon ()* INTERNAL** The exception modes of the ARM have their own stack pointers. However,* VxWorks exception handlers expect to be called in the context of the faulting* task so this veneer switches to SVC mode, saving necessary context in an* exception stack frame.* The exception stack pointers are only used to point to a few words* for register saving. THIS IS NOT A STACK and should not be used as one.* It is laid out as follows** -------------------------------* | SPSR | r0 | r1 | r2 | r3 | lr |* -------------------------------* ^* | sp points here*** Entry:* r0 -> exception vector* lr -> faulting instruction**/L$excEnterCommon:/* save SPSR in save area */ MRS r3,spsr STR r3,[sp]/* * save sp in non-banked reg so can access saved registers after * switching to SVC mode */ MOV r2,sp/* switch to SVC mode with interrupts (IRQs) disabled */ MRS r3,cpsr BIC r1,r3,#MASK_MODE ORR r1,r1,#MODE_SVC32 | I_BIT MSR cpsr,r1L$excEnterCommon2:/* **** INTERRUPTS DISABLED * * MODE = SVC32 * r0 -> exception vector * r1 = [scratch] * r2 -> where exception mode SPSR,r0-r3,lr are saved * r3 = CPSR of exception mode * lr = svc_lr at time of exception * * save the following * exception vector address * svc_sp * sp of exception mode (save area pointer) * CPSR of exception mode * NOTE: if anything else gets added to this, the stack * addressing later will need adjusting */ MOV r1,sp STMFD sp!,{r0-r3}/* * put registers of faulting task on stack in order defined * in REG_SET so can pass pointer to C handler */ LDR r1,[r2,#4*5] /* get LR of exception mode */ LDR r3,[r2] /* get SPSR of exception mode */ STMFD sp!,{r1,r3} SUB sp,sp,#4*(14-4+1) /* make room for r4..r14 *//* * check for USR mode exception - SYSTEM is handled as other modes * r3 = SPSR of exception mode */ TSTS r3,#MASK_SUBMODE STMEQIA sp,{r4-r14}^ /* EQ => USR mode */ BEQ L$regsSaved/* * not USR mode so must change to mode to get sp,lr * SYSTEM mode is also handled this way (but needn't be) * r3 = PSR of faulting mode */ MOV r1,sp /* r1 -> where to put regs */ MRS r0,cpsr /* save current mode */ ORR r3,r3,#I_BIT BIC r3,r3,#T_BIT MSR cpsr,r3/* in faulting mode - interrupts still disabled */ STMIA r1,{r4-r14} /* save regs *//* * check if it's SVC mode and, if so, overwrite stored sp * stack pointed to by r3 contains * r4..r14, PC, PSR of faulting mode * address of exception vector * svc_sp at time of exception * sp of exception mode * CPSR of exception mode */ AND r3,r3,#MASK_SUBMODE /* examine mode bits */ TEQS r3,#MODE_SVC32 & MASK_SUBMODE /* SVC? */ LDREQ r3,[r1,#4*(11+3)] /* yes, get org svc_sp */ STREQ r3,[r1,#4*(13-4)] /* and overwrite *//* switch back to SVC mode with interrupts still disabled (r0) */ MSR cpsr,r0/* back in SVC mode - interrupts still disabled */L$regsSaved:/* transfer r0-r3 to stack */ LDMIB r2,{r0-r3} /* get other regs */ STMFD sp!,{r0-r3}/* * exception save area can now be reused * stack contains * r0..r14, PC, PSR of faulting mode * address of exception vector * svc_sp at time of exception * sp of exception mode * CPSR of exception mode * interrupts still disabled * * restore interrupt state of faulting code */ LDR r0,[sp,#4*16] /* get PSR */ BIC r0,r0,#MASK_MODE /* clear mode bits */ ORR r0,r0,#MODE_SVC32 /* select svc32 */ MSR cpsr,r0 /* and write it to CPSR *//* **** INTERRUPTS RESTORED to how they were when exception occurred * * call generic exception handler */ MOV r1,sp /* r1 -> REG_SET */ ADD r0,r1,#4*15 /* r0 -> ESF (PC, PSR, vector) */ LDR fp,[r1,#4*11]#if (ARM_THUMB) LDR r12,L$_excExcContinue /* call C routine to continue */ BL FUNC(arm_call_via_r12) /* returns in ARM state */#else BL FUNC(excExcContinue) /* call C routine to continue */#endif/* exception handler returned (in SVC32) - disable interrupts (IRQs) again */ MRS r0,cpsr ORR r0,r0,#I_BIT MSR cpsr,r0/* **** INTERRUPTS DISABLED * * restore regs from stack, putting some into the exception save area */ LDR r2,[sp,#4*19] /* r2 -> exception save area */ LDMFD sp!,{r3-r6} /* get r0-r3 */ STMIB r2,{r3-r6}/* determine mode in which exception occurred so can restore regs */ LDR r3,[sp,#4*(16-4)] /* get PSR of faulting mode */ TSTS r3,#MASK_SUBMODE LDMEQIA sp,{r4-r14}^ /* EQ => USR mode */ BEQ L$regsRestored/* * exception was not in USR mode so switch to mode to restore regs * r0 = PSR we can use to return to this mode * r3 = PSR of faulting mode */ MOV r1,sp /* r1 -> from where to load regs */ ORR r3,r3,#I_BIT BIC r3,r3,#T_BIT MSR cpsr,r3/* * in faulting mode - interrupts still disabled * r1 -> svc stack where r4-r14 are stored */ LDMIA r1,{r4-r14} /* load regs *//* * If it's SVC mode, reset sp as we've just overwritten it * The correct value is in r1 */ AND r3,r3,#MASK_SUBMODE /* examine mode bits */ TEQS r3,#MODE_SVC32 & MASK_SUBMODE /* SVC? */ MOVEQ sp,r1/* switch back to SVC mode with interrupts still disabled (r0) */ MSR cpsr,r0/* back in SVC mode - interrupts still disabled */L$regsRestored:/* r4..r14 of faulting mode now restored */ ADD sp,sp,#4*(14-4+1) /* strip r4..r14 from stack */ LDMFD sp!,{r1,r3} /* get LR and SPSR of exception mode */ STR r1,[r2,#4*5] /* save LR in exception save area */ STR r3,[r2] /* ..with SPSR *//* get the remaining stuff off the stack */ LDMFD sp!,{r0-r3}/* * r0 = address of exception vector - discarded * r1 = svc_sp at time of exception - discarded * r2 = sp of exception mode * r3 = CPSR of exception mode * * switch back to exception mode */ MSR cpsr,r3/* * back in exception mode * restore remaining registers and return to task that faulted */ LDR r0,[r2] MSR spsr,r0 LDMIB r2,{r0-r3,pc}^
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -