📄 except.s
字号:
; Now we know semihosting is switched on LDR r2, =angel_SWIreason_CLibBase CMP r1, r2 BCC NonCLibReasonCode ; orig r0 < angel_SWIreason_CLibBase LDR r2, =angel_SWIreason_CLibLimit CMP r1, r2 BHI NonCLibReasonCode ; orig r0 > angel_SWIreason_CLibLimit IF :DEF: ICEMAN_LEVEL_3 ; ..and now we know it is a CLib code, return immediately MOV r0, #1 ; r0 = 1 as a dummy return code ADD r14, r14, #4 ; readjust r14, iceman is never in Thumb mode MOVS pc, r14 ELSE ; carry on with CLib processing... ; Now we know it is a CLib SWI IMPORT SysLibraryHandlerSysLibraryCall LDR r2, =SysLibraryHandler ; Fall through to DoIndirectCall ... ENDIF ELSE ; minimal angel B NonCLibReasonCode ENDIF ; We expect the SVC stack to be empty ; r2 contains the address of the function to be called indirectly ; ; We have to leave the SVC stack empty and also finish with ; regblock before switching mode, as this will (almost definitely) ; enable interrupts which can blow away the SVC stack. ; However, we can put stuff on the callers stack temporarily! ; ; So we put the caller's CPSR, caller's r1-r3, caller's lr ; and the address of the instruction after the SWI on the ; application stack. ; We can then restore all the potentially unbanked registers ; and execute the indirectly called functionDoIndirectCall IMPORT Angel_StackBase ; Set up caller's stack LDR r3, [r0, #Angel_RegBlock_R0offset + (13*4)] MRS r6, SPSR ; original CPSR ADD r0, r0, #Angel_RegBlock_R0offset + (1*4) LDMIA r0, {r7-r9} ; original r1-r3 SUB r0, r0, #Angel_RegBlock_R0offset + (1*4) LDR r10, [r0, #Angel_RegBlock_R0offset + (14*4)] ; caller's lr IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 TST r6, #Tbit ADDEQ r11, r14, #4 ; RE-Adjust for ARM instruction ADDNE r11, r14, #2 ; RE-Adjust for Thumb instruction ELSE ADD r11, r14, #4 ; RE-Adjust to point after SWI ENDIF STMFD r3!, {r6-r11} ; Put them on callers Stack IF :DEF: STRONGARM_REV1OR2 MCR MMUCP, 0, r0, c0, c0, 0 ENDIF STMFD r3, {r13,r14}^ ; Put USR r13 and r14 on Stack MOV r6, #USRmode ; We call the fn in USR mode (32 bit code) SUB r3, r3, #8 MSR SPSR_cxsf, r6 ; Set up USR r13 and r14 for the indirectly called function STR r3, [r0, #Angel_RegBlock_R0offset + (13*4)] ; callers r13 LDR r3, =ApplicationModeIndirectReturnVeneer STR r3, [r0, #Angel_RegBlock_R0offset + (14*4)] ; callers r14 ADD r0, r0, #Angel_RegBlock_R0offset + (13*4) LDMIA r0, {r13,r14}^ ; Load the USR r13 and r14 (!!!) SUB r0, r0, #(13*4) ; wind back to r0 ; Force the SVC stack to use the Angel SVC stack, no matter ; what it was before. LDR r13, =Angel_StackBase LDR r13, [r13] ADD r13, r13, #Angel_SVCStackOffset ; The problem here is that all angel SWI C code is compiled as ; swst so it needs a valid r10 as a stack limit check. ; If someone has used r10 as a general purpose register they will ; have destroyed this functionality and will cause Angel to fail ; We must put a valid sl in r10 at this point ; The first thing we must do is take a local copy of the user r10 ; from the stored copy of the user stack (in r0) LDR r10, [r0, #(10*4)] ; r10 from the stack LDR r11, =SavedR10 ; get the address of the local variable STR r10, [r11] ; and store it there ; Restore r0-r12 (unbanked regs) - keeping fn to call in r14 MOV r14, r2 LDMIA r0, {r0-r12} STMFD sp, {r13}^ ; bring in the User Stack pointer LDR r10, [sp,#-4] SUB r10, r10, #Angel_SVCStackSize ; put the limit at the size ; We now have a valid sl for Angel to use - The user info is ; reinstated in ReturnSVC ; And leap into the indirectly called routine in USR mode MOVS pc, lr ; This gets called when the indirectly called fn returns ; we will have eight values on the stack (nearest first): ; * r13,r14 for USR Mode prior to the indirectly called ; fn. This is only needed if the CPSR at the time ; of the SWI was NOT USR. ; * CPSR at time of SWI ; * r1-r3 values to reinstate ; * LR value to reinstate ; * address of instruction after the SWI (return there!) ; This veneer has to return to either ARM or Thumb code ; depending on what the CPSR on the stack indicates. It also ; needs to be able to return to USR or SVC mode code, but is ; entered always in USR mode. ; Note that we want to restore the PSR flags on return too.ApplicationModeIndirectReturnVeneer ; See if SWI was not from USR mode ; If so restore USR mode r13, r14 after getting into proper mode LDR r1, [sp, #8] ; Get saved CPSR AND r1, r1, #ModeMask CMP r1, #USRmode CMPNE r1, #SYSmode ADDEQ sp, sp, #8 BEQ AnyModeReturn ; Non USR mode case - we need to gain privileged mode again LDR r1, [sp, #8] ; Get saved CPSR MOV r2, r0 MOV r3, sp LDR r0, =angel_SWIreason_EnterSVC DCD angel_SWI_ARM ;; Response to MLS 1965 to ensure that thumb SWI calls return ;; correctly when not called from user mode IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT <> 0 BIC r1, r1, #Tbit ; Ensure we don't switch in Thumb Mode ENDIF MSR CPSR_cxsf, r1 ; Switch into desired mode MOV r0, r2 MOV sp, r3 ; Restore stack LDMFD sp, {r13, r14}^ ; Restore USR mode r13 and r14 NOP ADD sp, sp, #8AnyModeReturn LDR r14, [sp, #0] ; Get saved CPSR IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 TST r14, #Tbit ENDIF ADD sp, sp, #4 ; Finished with the cpsr on the stack LDMFD sp!, {r1-r3} ; Restore old r1-r3 ; Here we must retain the applications r10 if sl wasn't being used ; so we must get it back from the saved location LDR r10, =SavedR10 ; we must reinstate the app r10 LDR r10, [r10] ; get it from the saved location IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 BEQ ARMCodeReturn MSR cpsr_f, lr ; Restore flags LDMFD sp!, {lr} ; Restore old lr STMFD sp!, {r0} ; Need a work register (must be r0-r7 - not r14) ADR r0, SwitchToThumbLabel+1 BX r0SwitchToThumbLabel CODE16 POP {r0, pc} CODE32 ALIGN ENDIFARMCodeReturn MSR cpsr_f, lr ; Restore flags LDMFD sp!, {lr, pc} ; Return to ARM code ; ********************************************************** ; Deal with cases other than the semi-hosted CLib SWI ; r0 = our regblock with the saved regs stored ; r1 = the original r0 when we get hereNonCLibReasonCode LDR r2, =angel_SWIreason_EnterSVC CMP r1, r2 BEQ ReturnSVC IF (:LNOT: :DEF: MINIMAL_ANGEL) :LOR: MINIMAL_ANGEL = 0 IF :LNOT: (:DEF: JTAG_ADP_SUPPORTED :LOR: :DEF: ICEMAN_LEVEL_3) LDR r2, =angel_SWIreason_ApplDevice CMP r1, r2 BEQ ApplDeviceSWI ENDIF ENDIF IF :DEF: LATE_STARTUP :LAND: LATE_STARTUP <> 0 LDR r2, =angel_SWIreason_LateStartup CMP r1, r2 BEQ LateStartupSWI ENDIF LDR r2, =angel_SWIreason_ReportException CMP r1, r2 BNE UnrecognisedSWI ; Fall through to ReportException ReportException IF :DEF: ICEMAN_LEVEL_3 :LOR: (:DEF: MINIMAL_ANGEL :LAND: MINIMAL_ANGEL<>0) ; We cannot report an exception within ICEMan B ReportException ELSE ; The ADP_Stopped code was in r1 before the SWI happened LDR r2, [r0, #Angel_RegBlock_R0offset + (1*4)] B CallSerialiseTask ENDIFReturnSVC ; The SVC stack is empty. We have to return in SVC mode with ; IRQ and FIQ disabled. r0-r13 and r14 should be reinstated from ; regblock (ie. the stack remains the caller's stack) ; Execution will resume from the instruction after the SWI ; ; We will return with r0 set to the address of Angel_ExitToUser ; LDR r2, [r0, #Angel_RegBlock_R0offset + (13*4)] ; get callers sp LDR r3, [r0, #Angel_RegBlock_R0offset + (15*4)] ; PC (pts to SWI) MRS r4, SPSR IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 TST r4, #Tbit ADDEQ r3, r14, #4 ; RE-Adjust for ARM instruction ADDNE r3, r14, #2 ; RE-Adjust for Thumb instruction ELSE ADD r3, r14, #4 ; RE-Adjust to point after UNDEF ENDIF STMFD sp!, {r2-r3} ; Push Caller sp and pc onto SVC stack ; Restore r1-12 and r14 ADD r0, r0, #Angel_RegBlock_R0offset + (1*4) LDMIA r0, {r1-r12} SUB r0, r0, #Angel_RegBlock_R0offset + (1*4) LDR r14, [r0, #Angel_RegBlock_R0offset + (14*4)] LDR r0, [r0, #Angel_RegBlock_CPSRoffset] MSR CPSR_f, r0 ; Only reinstate the flag values ! ; Set r0 to the address of Angel_ExitToUser IMPORT Angel_ExitToUSR LDR r0, =Angel_ExitToUSR ; Restore sp and resume LDMFD sp, {sp, pc} ; And now the application executes in SVC mode with its own stack ; and interrupts disabled. IF (:LNOT: :DEF: MINIMAL_ANGEL) :LOR: MINIMAL_ANGEL = 0 IF :LNOT: (:DEF: JTAG_ADP_SUPPORTED :LOR: :DEF: ICEMAN_LEVEL_3) ApplDeviceSWI LDR r2, =angel_ApplDeviceHandler B DoIndirectCall ENDIF ENDIF IF :DEF: LATE_STARTUP :LAND: LATE_STARTUP <> 0LateStartupSWI LDR r2, =angel_LateBootInit B DoIndirectCall ENDIF UnrecognisedSWI IF :DEF: ICEMAN_LEVEL_3 :LOR: (:DEF: MINIMAL_ANGEL :LAND: MINIMAL_ANGEL<>0) ; We cannot report an unrecognised SWI within ICEMan B UnrecognisedSWI ELSE LDR r2, =ADP_Stopped_SoftwareInterrupt B CallSerialiseTask ENDIF AREA except_reg_save,DATA, READWRITESavedR10 DCD 0 END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -