📄 except.s
字号:
NotAngelOSAbort IF DEBUG <> 0 ; or PORTING IMPORT Angel_IsApplicationBlocked IMPORT |Image$$RO$$Base| ; start of code area IMPORT |Image$$RO$$Limit| ; end of code area ; If appl blocked, this can't be an appl abort... STMIA sp!, {r0-r3,r12,lr} BL Angel_IsApplicationBlocked CMP r0, #0 LDMIA sp!, {r0-r3,r12,lr} BNE AbtInAngelCode LDR r1, =|Image$$RO$$Base| CMP lr, r1 BLO AbtNotAngelCode LDR r1, =|Image$$RO$$Limit| CMP lr, r1 BHI AbtNotAngelCodeAbtInAngelCode ; A data or prefetch abort in Angel ... oops! ; Note: the test code above misses out a check for the ; relocating code in the ROM etc. MOV a2, lr ; parameter for msg FatalError "Abort encountered in Angel code at pc=%p.\n" AbtNotAngelCode ; For a data abort, we need to subtract 8 to get back to the address ; at which the aborted instruction was loaded; we have already subtracted ; 4 in EXCEPTENTRY_PART1; now do the other 4. LDR r2, =ADP_Stopped_DataAbort CMP r2, r6 SUBEQ r14, r14, #4 ; r0 already has the regblock pointer -- load r2 with the ; reason code from r6 and report back to the debugger. MOV r2, r6 B CallSerialiseTask ENDIF ; not Minimal Angel ENDIF ; **************************************************************** ; ; void HandlerUndef() ; ; ------------------------------------------- ; ; Vector handler function for the Undefined instruction vector. ; When compiled into EmbeddedICE (ICEMAN) the exception simply means ; that the code is broken; hence we just ignore it! ; ; Angel uses undefined instructions to implement breakpoints for the ; debugger, as well as the possibility that the user has inserted their ; own undefines which are to be trapped by the debugger. So the handler ; must check which instruction code caused the exception. The only ; difference here, however, is which of the ADP_Stopped reason codes ; is used to report this event to the debugger. ; ; The code to check the breakpoint is complicated slightly by the ; requirement to check for both Thumb and ARM breakpoints, although ; the entry and exit actions are the same in both cases. ; ; The helper function CallSerialiseTask is used to call the serialiser ; with appropriate args to report the exception. ; ; If the exception was caused by a breakpoint instruction, the debugger ; should rewrite it with the correct instruction before returning here ; to continue execution. ; ; Entry: r14 = <address of undef>+4 ; r13 = empty_undef_stack ; cpsr_mode = UNDmode ; ; Exit: <via Serialiser, does not return directly> ; ; ------------------------------------------- HandlerUndef IF MINIMAL_ANGEL<>0 ;; we're not supposed to be handling this, so don't SUBS pc, lr, #4 ELSE EXCEPTENTRY UNDmode, Angel_GlobalRegBlock + (RB_UNDEF * Angel_RegBlockSize) ; The value of r14 has been decremented by 4, i.e. referring to the ; undefined instruction. r0 points at (the start of) the regblock ; referred to in the entry macro. ; 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 and Thumb). IF DEBUG <> 0 STMFD sp!, {r0-r3,lr} MOV r1, #0 MOV r2, #DL_UndefSave BL Angel_DebugLog LDMFD sp!, {r0-r3,lr} ENDIF IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 MRS r0, SPSR ; read CPSR of mode we were in... 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 B BreakPointInstruction 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 ; This is executed for both an ARM and Thumb breakpoint LDR r0, =Angel_GlobalRegBlock + (RB_UNDEF * Angel_RegBlockSize) LDR r2, =ADP_Stopped_BreakPoint B CallSerialiseTaskUnrecognisedInstruction LDR r0, =Angel_GlobalRegBlock + (RB_UNDEF * Angel_RegBlockSize) LDR r2, =ADP_Stopped_UndefinedInstr B CallSerialiseTask ENDIF ; End of MINIMAL ANGEL ; ************************************************************* ; ; void HandlerSWI() ; ; ------------------------------------------- ; ; ; ; 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, r1} ; Disable interrupts. The FIQ handler 'knows' that SWI has problems ; here and will return as soon as it realizes a FIQ has been taken ; around here. EnsureFIQDisabled cpsr, r0 ; We have to check that the SWI we hit was indeed the Angel SWI ; ; This initial code is designed to be interrupt-safe, although we ; don't re-enable IRQ (which would be disabled on entry to the SWI ; automatically). IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 MRS r1, SPSR TST r1, #Tbit BEQ CompareWithARMSWI1 LDRH r1, [r14, #-2] ; load the Thumb instruction BIC r1, r1, #0xff00 CMP r1, #angel_SWI_THUMB BNE ComplexSWI B CheckSimpleSWI ENDIF ; THUMB_SUPPORTCompareWithARMSWI1 LDR r1, [r14, #-4] ; load the ARM instruction LDR r0, =angel_SWI_ARM ; load SWI number (+ SWI instr. code) BIC r1, r1, #0xFF000000 ; condition & instr. code, which shouldn't be compared. EORS r0, r0, r1 ; If the values are the same, we'll end up with zero BNE ComplexSWI ; ... fall through to 'simple' SWI case ;; ; is this Angel SWI a "Simple" one -- that is, it doesn't call the ; scheduler and is fast.CheckSimpleSWI LDR r0, [sp] ; load original value of r0 from stack CMP r0, #angel_SWIreason_EnterSVC BNE NotEnterSVC ; check for other simple SWI's.DoSWIEnterSVC ; Handle the EnterSVC SWI. See "ARM SDT Reference Manual" $8.3 for what ; docs exist on this. ; Basically: enter with r0 == angel_SWIreason_EnterSVC ; mode == USR mode ; sp == Angel/Appl USR stack ; ; exit with r0 <= address of a routine to return to ; USR mode ; mode <= SVC mode with IRQ, FIQ disabled ; sp_svc <= sp_usr ; ; The SDT Reference Manual guarantees that r1 - r3 are preserved by ; Angel when an Angel system call is made, so other regs can be used. ; ; ----- ; Angel additionally allows one level of nesting, so that if ; entered in SVC mode, the return routine will return in SVC mode. ; ; As written this code will allow entry in any privileged mode, and ; return in SVC mode as stated above. ; ; However, the return routine (Angel_ExitToUSR) will not return to ; the previous mode, but to SVC mode instead, with the wrong stack. MRS r1, SPSR ; mode we came from ; Accessing other modes depends on the mode AND r1, r1, #ModeMaskUFIS CMP r1, #USRmode :AND: ModeMaskUFIS CMPNE r1, #SYSmode :AND: ModeMaskUFIS BNE EnterSVCfromPriv ; Now either we came from USR or SYS mode. ; Write USR or SYS sp on the entry stack over saved r0. ; Original SVC SP IS LOST! STMIA sp, {sp}^ IF HANDLE_INTERRUPTS_ON_FIQ = 0 ; Not handling interrupts on FIQ, so we didn't disable FIQ ; at the start of the handler. Do so now, so we return with ; both interrupt sources disabled. MRS r0, cpsr ORR r0, r0, #FIQDisable MSR cpsr_cf, r0 ENDIF ; jump to exit code to load r0 with it's correct value. B ReturnFromEnterSVC EnterSVCfromPriv ; we have called the EnterSVC SWI in a privileged mode. ; r0 is the angel_SWIreason_EnterSVC code number, ; r1 is the masked mode we came from ; neither values are needed any more. MRS r1, cpsr ; need a copy of SVC CPSR MRS r0, spsr ; get CPSR we came from ... IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 ; If we came from thumb state, don't (try to) return there just ; yet! BIC r0, r0, #Tbit ENDIF ; In any mode, don't return to 26 bit mode (0x10), and don't ; enable interrupts just yet. ORR r0, r0, #InterruptMask + 0x10 MSR cpsr_cf, r0 ; switch to the mode we came from AND r0, r0, #ModeMaskUFIS ; NOTE: If the spsr was _already_ SVCmode, the value we save has ; to be adjusted for data put on the stack by the SWI! CMP r0, #SVCmode :AND: ModeMaskUFIS MOV r0, sp ; take a copy of this mode's SP ADDEQ r0, r0, #8 IF HANDLE_INTERRUPTS_ON_FIQ = 0 ; Not handling interrupts on FIQ, so we didn't disable FIQ ; at the start of the handler. Do so now, so we return with ; both interrupt sources disabled. ORR r1, r1, #FIQDisable ENDIF MSR cpsr_cf, r1 ; switch back to SVC mode STMIA sp, {r0} ; Store out the USR or SYS stack pointer ; now in SVC mode with sp_svc <= sp_<other mode> ; fall through to exit code to return to the caller in this state.ReturnFromEnterSVC ; Set the stack back to that at the beginning of the SWI. LDMFD sp!, {r0, r1} MOV sp, r0 ; put other mode's SP in here. MRS r0, spsr ; We need to find out if the system was in ; Thumb state in its original operation ; We could be returning to a Thumb code segment so we must use the ; correct return method for Thumb ie BX rn [ :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 TST r0, #Tbit BNE SVCThumb ] ; Set r0 to the address of Angel_ExitToUser LDR r0, =Angel_ExitToUSR ; Resume in SVC mode with interrupts disabled. MOV pc, lr [ :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0SVCThumb ; Set r0 to the address of Angel_ExitToUser LDR r0, =Angel_ExitToUSR ; Push r0 and the lr (for the return) on to the stack STMFD sp!, {r0, lr} ; Set bit 0 to 1 for the change to Thumb State ADR r0, SVCRettoThumb+1 BX r0 CODE16SVCRettoThumb ; And do the return BX - now in SVC mode retaining the stack info POP {r0, pc} ALIGN CODE32 ] NotEnterSVC CMP r0, #angel_SWIreason_SysElapsed CMPNE r0, #angel_SWIreason_SysTickFreq BNE NotSimpleSWI ; Reason code: SYS_TICKFREQ: ; Purpose: Returns the number of elapsed target 'ticks' since the ; support code started executing. Ticks are defined by ; SYS_TICKFREQ. (If the target cannot define the length of ; a tick, it may still supply SYS_ELAPSED.) ; Reason code: SYS_TICKFREQ ; Purpose: Define a tick frequency. (The natural implementation is ; to have a software model specify one core cycle as one tick, ; and for Angel to return Timer1 ticks) ; Both these are recognised but not implemented by Angel. Return -1 ; to indicate failure. LogInfo "except.s", 756, LOG_EXCEPT, "Sys Elapsed/Tickfreq\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -