📄 except.s
字号:
ADD r0, r0, #Angel_RegBlock_R0offset + (8*4) STMIA r0, {r8-r12} ; r8-r12 are not banked between USR and UND ADD r0, r0, #(13*4) - (8*4) IF :DEF: STRONGARM_REV1OR2 MCR MMUCP, 0, r0, c0, c0, 0 ENDIF STMIA r0, {r13,r14}^ ; Store out the USR r13 and r14 SUB r0, r0, #Angel_RegBlock_R0offset + (13*4)RegsNowSaved ; We have to check that the undefined instruction we hit ; was indeed the Angel Undefined instruction ; ; Clearly this uses different code for Thumb and ARM states ; but make the Thumb support code removable ; ; Note that r14_und has been adjusted to point to the undef ; (ARM or Thumb). IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 MRS r0, SPSR TST r0, #Tbit BEQ CompareWithARMBreakPoint LDRH r0, [r14] ; load the Thumb instruction MOV r1, #angel_BreakPointInstruction_THUMB :AND: 0xff00 ORR r1, r1, #angel_BreakPointInstruction_THUMB :AND: 0xff CMP r0, r1 BNE UnrecognisedInstruction BEQ NormalBreakpoint ; Skip over the check for Vector Hit case ENDIFCompareWithARMBreakPoint LDR r0, [r14] ; load the ARM instruction LDR r1, =angel_BreakPointInstruction_ARM CMP r0, r1 BNE UnrecognisedInstruction ; We now know it is Angel's Undefined instruction ; r0 = r1 = The undefined instruction ; lr = address of the undefined instruction ; spsr = unchanged ; sp = FD UND stack (currently empty)BreakPointInstruction ; We must check to see if it is a special case - a breakpoint ; in DefaultExceptionTable, which actually means it is an ; exception (there are no real handlers for the other exceptions). ; ; This little piece of code only every has to deal with ARM undefs LDR r0, =DefaultExceptionTable SUB r1, r14, r0 ; r1 = addr of Breakpoint - start of table MOV r1, r1, ASR #2 ; r1 is now the index into DefaultExceptionTable CMP r1, #7 BGT NormalBreakpoint ; Not in this table CMP r1, #0 BLT NormalBreakpoint ; Not in this table B VectorHitNormalBreakpoint ; This is executed for both an ARM and Thumb breakpoint LDR r2, =ADP_Stopped_BreakPointCallSerialiseTask ; Now prepare to call Angel_SerialiseTask ; r0 and r2 are set up by caller ; ; SerialiseTask expects: ; r0 = called_by_yield ; r1 = fn ; r2 = type (already set up) ; r3 = empty_stack MOV r0, #0 LDR r1, =angelOS_ThreadStopped MOV r3, sp B Angel_SerialiseTask ; and angelOS_ThreadStopped will execute when SerialiseTask ; allows it toUnrecognisedInstruction LDR r2, =ADP_Stopped_UndefinedInstr B CallSerialiseTaskVectorHit ; r1 is the index into the DefaultExceptionTable. ; sp = UND sp - currently empty ; ; If this is a data abort, and Angel was in the process of ; performing a data access, which aborted then we must ; unwind the abort and return to that code, setting a flag ; so it knows what has happened. ; ; In all other cases just report the problem to the debugger. CMP r1, #4 ; Data Abort vector BNE ReportToDebugger IMPORT memory_is_being_accessed IMPORT memory_access_aborted IMPORT angel_StartTask_NonSVCEntry LDR r0, =memory_is_being_accessed LDR r0, [r0] CMP r0, #0 BEQ ReportToDebugger ; Not due to Angel Aborting! ; Now we know that it is either angelOS_MemRead or angelOS_MemWrite ; that has aborted. These both run in User32 mode, and if aborted ; then we went into Abort32 mode, storing the real pc, cpsr ; in the abort regs. This will in turn have gone through the ; table of undefined instructions and hence got into under32 mode, ; which is where we are now. Thus we have to read the Abort regs ; and put them into the saved register block and then restart ; using that block. ; Indicate an abort has happened LDR r0, =memory_access_aborted MOV r1, #1 STR r1, [r0] ; Get into abort mode MRS r1, CPSR BIC r1, r1, #ModeMask ORR r1, r1, #ABTmode MSR CPSR_cxsf, r1 LDR r0, =Angel_MutexSharedTempRegBlocks ; We have to get r13 and r14 from the USR bank ! ADD r1, r0, #Angel_RegBlock_R0offset + (4*13) IF :DEF: STRONGARM_REV1OR2 MCR MMUCP, 0, r0, c0, c0, 0 ENDIF STMIA r1, {r13,r14}^ ; USR bank version ; Put SPSR, and pc into the saved registers block ; Adjust PC by 4 - This relies on MemRead / MemWrite being written ; in ARM code not Thumb code. SUB r2, r14, #4 STR r2, [r0, #Angel_RegBlock_R0offset + (4*15)] ; original pc MRS r2, SPSR STR r2, [r0, #Angel_RegBlock_CPSRoffset] ; original cpsr B angel_StartTask_NonSVCEntry ReportToDebugger LDR r2, =ADP_Stopped_BranchThroughZero ADD r2, r2, r1 B CallSerialiseTask ENDIF ; End of ICEMAN_LEVEL_3 IMPORT Angel_SerialiseTask DefaultExceptionTable DCD angel_BreakPointInstruction_ARM ; 00 - Reset DCD angel_BreakPointInstruction_ARM ; 04 - Undefined instructions DCD angel_BreakPointInstruction_ARM ; 08 - SWI instructions DCD angel_BreakPointInstruction_ARM ; 0C - Instruction fetch aborts DCD angel_BreakPointInstruction_ARM ; 10 - Data access aborts DCD angel_BreakPointInstruction_ARM ; 14 - Reserved DCD angel_BreakPointInstruction_ARM ; 18 - IRQ interrupts DCD angel_BreakPointInstruction_ARM ; 1C - FIQ interrupts ; ************************************************************* ; See discussion above HandlerUndef for limitations which also ; apply to this handler. ; in: SVC mode; IRQs disabled; FIQs undefined ; r13 = FD stack ; r14 = address of SWI instruction + 4 ; All other registers must be preserved IMPORT angelOS_SemiHostingEnabled EXPORT HandlerSWIHandlerSWI STMFD sp!, {r0} ; Disable interrupts MRS r0, CPSR IF (FIQ_SAFETYLEVEL >= FIQ_NeverUsesSerialiser_DoesNotReschedule) ORR r0, r0, #IRQDisable ELSE ORR r0, r0, #IRQDisable + FIQDisable ENDIF MSR CPSR_cxsf, r0 NOP ; Save the state of the callee (can be any mode) into a regblock ; This means r0-r15, and cpsr ; Can do r0-r7, pc, cpsr for all modes LDR r0, =Angel_MutexSharedTempRegBlocks ADD r0, r0, #Angel_RegBlock_R0offset + (1*4) STMIA r0, {r1-r7} ; r1-r7 are never banked SUB r0, r0, #Angel_RegBlock_R0offset + (1*4) LDMFD sp!, {r1} STR r1, [r0, #Angel_RegBlock_R0offset] ; original r0 MRS r1, SPSR STR r1, [r0, #Angel_RegBlock_CPSRoffset] ; original cpsr IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 TST r1, #Tbit SUBEQ r14, r14, #4 ; Adjust for ARM instruction SUBNE r14, r14, #2 ; Adjust for Thumb instruction ELSE SUB r14, r14, #4 ; Adjust to point to the SWI ENDIF STR r14, [r0, #Angel_RegBlock_R0offset + (15*4)] ; pc ; Accessing other modes depends on the mode AND r1, r1, #ModeMask CMP r1, #USRmode BEQ SWIWasInUSRMode CMP r1, #SYSmode BEQ SWIWasInUSRMode ; Deal with non USR mode case IF (FIQ_SAFETYLEVEL >= \ FIQ_NeverUsesSerialiser_DoesNotReschedule_HasNoBreakpoints) ORR r1, r1, #IRQDisable ELSE ORR r1, r1, #IRQDisable + FIQDisable ENDIF MSR CPSR_cxsf, r1 ; Now we are in the appropriate mode ADD r0, r0, #Angel_RegBlock_R0offset + (8*4) STMIA r0, {r8-r14} ; r8-r12 may be banked - now saved SUB r0, r0, #Angel_RegBlock_R0offset + (8*4) MRS r2, SPSR STR r2, [r0, #Angel_RegBlock_SPSRoffset] ; Get back into SVC BIC r1, r1, #ModeMask ORR r1, r1, #SVCmode MSR CPSR_cxsf, r1 B RegsNowSaved2SWIWasInUSRMode ADD r0, r0, #Angel_RegBlock_R0offset + (8*4) STMIA r0, {r8-r12} ; r8-r12 are not banked between USR and SVC ADD r0, r0, #(13*4) - (8*4) IF :DEF: STRONGARM_REV1OR2 MCR MMUCP, 0, r0, c0, c0, 0 ENDIF STMIA r0, {r13,r14}^ ; Store out the USR r13 and r14 SUB r0, r0, #Angel_RegBlock_R0offset + (13*4)RegsNowSaved2 ; r0 = &Angel_MutexSharedTempRegBlocks[0] ; r1,r2, = corrupt ; r3-r12 unmodified ; r13 = SVC stack ; r14 = adjusted to point to SWI ; We have to check that the SWI we hit was indeed the Angel SWI ; ; Clearly this uses different code for Thumb and ARM states ; but make the Thumb support code removable IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 MRS r2, SPSR TST r2, #Tbit BEQ CompareWithARMSWI LDRH r2, [r14] ; load the Thumb instruction MOV r1, #angel_SWI_THUMB :AND: 0xff00 ORR r1, r1, #angel_SWI_THUMB :AND: 0xff CMP r2, r1 BNE UnrecognisedSWI BEQ AngelSWI ENDIFCompareWithARMSWI LDR r2, [r14] ; load the ARM instruction BIC r2, r2, #0xFF000000 ; Only compare the SWI numbers LDR r1, =angel_SWI_ARM BIC r1, r1, #0xFF000000 ; Only compare the SWI numbers CMP r2, r1 BNE UnrecognisedSWI AngelSWI ; We now know it is our SWI, so we have to interpret the reason code ; which was in r0. ; ; Here we assume that r0 still addresses regblock ; LDR r1, [r0, #Angel_RegBlock_R0offset] ; original r0 IF (:LNOT: :DEF: MINIMAL_ANGEL) :LOR: MINIMAL_ANGEL = 0 ; Only recognise the C Library SWIs if Semihosting is enabled LDR r2, =angelOS_SemiHostingEnabled LDR r2, [r2] CMP r2, #0 IF :DEF: ICEMAN_LEVEL_3 ; We quietly ignore CLib codes, so first carry on as if semihosting... ELSE BEQ NonCLibReasonCode ENDIF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -