📄 taskmacs.s
字号:
SUBT Macros for serialiser/exception handling > taskmacs.s ; --------------------------------------------------------------------- ; ; $Revision: 1.1 $ ; $Author: rivimey $ ; $Date: 1999/03/11 11:53:48 $ ; ; Copyright Advanced RISC Machines Limited, 1995. ; All Rights Reserved ; --------------------------------------------------------------------- ASSERT (listopts_s)old_opt SETA {OPT} OPT (opt_off) ; disable listing of include files ; --------------------------------------------------------------------- [ (:LNOT: :DEF: taskmacs_s) GBLL taskmacs_staskmacs_s SETL {TRUE} ; define the register block structure: ^ 0RegOffsR0 # 4 ; offs: 0RegOffsPC # 4RegOffsSPSRfiq # 4 ; offs: 8RegOffsR8fiq # 4RegOffsR9fiq # 4RegOffsR10fiq # 4RegOffsR11fiq # 4RegOffsR12fiq # 4RegOffsR13fiq # 4RegOffsR14fiq # 4RegOffsSPSRirq # 4 ; offs: 40 (x28)RegOffsR13irq # 4RegOffsR14irq # 4RegOffsSPSRsvc # 4 ; offs: 52 (x34)RegOffsR13svc # 4RegOffsR14svc # 4RegOffsSPSRabt # 4 ; offs: 64 (x40)RegOffsR13abt # 4RegOffsR14abt # 4RegOffsSPSRund # 4 ; offs: 76 (x4c)RegOffsR13und # 4RegOffsR14und # 4RegOffsCPSR # 4 ; offs: 88 (x58)RegOffsR1 # 4RegOffsR2 # 4RegOffsR3 # 4RegOffsR4 # 4RegOffsR5 # 4RegOffsR6 # 4RegOffsR7 # 4RegOffsR8usr # 4 ; offs: 120 (x78)RegOffsR9usr # 4RegOffsR10usr # 4RegOffsR11usr # 4RegOffsR12usr # 4RegOffsR13usr # 4RegOffsR14usr # 4RegBlockSize # 0 ; size: 148 (x94) ^ 0 ; Codes for the Angel_DebugLog code IF DEBUG <> 0DL_StartTask EQU 1DL_QueueTask EQU 2DL_IntHandler EQU 3DL_SaveTask EQU 4DL_YieldSave EQU 5DL_SWISave EQU 6DL_UndefSave EQU 7DL_WaitSave EQU 8DL_AbortSave EQU 9DL_DeleteTask EQU 10 ENDIF MACRO R13LookupTable ; r13 offsets by mode, offset by 2 words (see code in EXCEPTEXIT) DCB RegOffsR13usr - RegOffsSPSRfiq DCB RegOffsR13fiq - RegOffsSPSRfiq DCB RegOffsR13irq - RegOffsSPSRfiq DCB RegOffsR13svc - RegOffsSPSRfiq DCB 0, 0, 0 DCB RegOffsR13abt - RegOffsSPSRfiq DCB 0, 0, 0 DCB RegOffsR13und - RegOffsSPSRfiq DCB 0, 0, 0 DCB RegOffsR13usr - RegOffsSPSRfiq ; sys mode MEND ; --------------------------------------------------------------------- ; STOREMODE ; ----------- ; ; STOREMODE modenum ; ; Using $temp1, $temp2 as scratch, transfer a register frame {spsr, r13, r14} ; to the memory at $basereg from the registers for mode $modenum. Increment ; r0 over the register block. $cpsrreg has a 'blank' copy of the CPSR, which ; should have ints disabled and the mode bits zeroed. ; MACRO STOREMODE $modenum, $basereg, $cpsrreg, $temp1, $temp2 ORR $temp1, $cpsrreg, $modenum MSR cpsr_cf, $temp1 MRS $temp2, spsr STMIA $basereg!, {$temp2, r13, r14} MEND ; --------------------------------------------------------------------- ; EXCEPTENTRY_PART1 ; ----------- ; EXCEPTENTRY_PART1 $handler, $regblock ; ; Code to handle exception handler entry. Parameters include the handler ; mode (e.g. IRQmode) and the address to store the registers. ; ; On Entry: ; sp_<entry mode> should point at an FD stack of a few words. ; CPSR is assumed to have IRQ disabled (as will be the case for ; all exception handlers). ; ; On Exit: ; r0 will be left pointing into the regblock. r7 contains the original ; value of the CPSR; both are needed by EXCEPTENTRY_PART2. ; ; After this call, code may use r4-r6 to pass information through to the ; code after the EXCEPTENTRY_PART2. Other registers, especially other ; modes registers, should be left well alone. Be aware that the whole ; sequence is performed interrupts-disabled. ; MACRO EXCEPTENTRY_PART1 $handler, $regblock STMFD sp!, {r0} ; save r0 ... MRS r0, cpsr IF $handler <> FIQmode ORR r0, r0, #FIQDisable ; disable FIQ's for the moment. MSR cpsr_cf, r0 ENDIF STMFD sp!, {r0, r8} ; cpsr and r8 on exception handler stack ; ; save the unbanked regs -- use r8 to address the save area while ; we're saving r0 to r7, then move to use r0 for the banked registers ; LDR r8, =$regblock + RegOffsCPSR MRS r0, spsr ; use the SPSR as the saved CPSR value. STMIA r8, {r0-r7} ; save cpsr along with r1-7 SUB r0, r8, #RegOffsCPSR ; move base from banked r8 into unbanked r0 ; r0 now addresses RegOffsR0 LDMFD sp!, {r7, r8} ; get orig cpsr, r8 from stack LDMFD sp!, {r1} ; get orig r0 from stack ; ; arrange for r14 to point to the 'right' place to return to; it is stored ; in the location used to restore PC from, as well as in the 'r14' slot. ; IF $handler = FIQmode :LOR: $handler = IRQmode SUB r14, r14, #4 ENDIF IF $handler = UNDmode SUB r14, r14, #4 ; This is correct for ARM state only, Thumb State requires ; the LR readjusting for the Thumb increments ( +2) IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0 MRS r2, spsr ; Test for Thumb state in the saved status register TST r2, #Tbit ADDNE r14, r14, #2 ; If Thumb set, add 2 to the lr ENDIF ; Thumb Support ENDIF ; Undef Handler IF $handler = ABTmode ; The offset of 4 is ok assuming that we accept the abort and continue rather ; than trying to fix it, which is OK in Angel as it stands. ; ; If Angel is changed such that data aborts must be retried, code must be ; inserted to distinguish the data abort from a prefetch abort and subtract ; #8 rather than #4 before retrying the instruction. SUB r14, r14, #4 ENDIF MEND ; --------------------------------------------------------------------- ; EXCEPTENTRY_PART2 ; ----------- ; EXCEPTENTRY_PART2 ; ; Code to complete exception handler entry. Theis code performs the ; handler-independent part of the sequence, saving the various modes' ; registers to the regblock. USR mode has already been done. This macro ; must be entered in a privileged mode, and EXCEPTENTRY_PART1 must have ; been called to set up 'r0' and the other parts of the regblock. ; ; On Entry: ; r0 must point to the start of the FIQ register block in the regblock ; structure. r0 - r14usr have been saved. r7 contains the original ; value of the CPSR. r4 - r6 may contain useful info and must be ; preserved. ; ; On Exit: ; r0 will be left pointing at the base of the regblock, which will. ; contain the CPU register state on entry to ENTEREXCEPT_PART1. MACRO EXCEPTENTRY_PART2 STMIA r0!, {r1, r14} ; save r0, lr (as return PC) in memory ADD r2, r0, #RegOffsR8usr - RegOffsSPSRfiq STMIA r2, {r8-r14}^ ; save USR mode registers ; have now saved unbanked registers. Cycle through the modes and save ; the banked ones MRS r1, cpsr ; make a copy of cpsr with mode bits zero BIC r1, r1, #ModeMask ; so we can OR in the right value. ORR r2, r1, #FIQmode ; MSR cpsr_cf, r2 ; shift to FIQ mode MRS r3, spsr ; get SPSRfiq STMIA r0!, {r3, r8-r14} ; save FIQ's banked registers ; save the state for the other modes... (input r0, r1, uses r2, r3) STOREMODE #IRQmode, r0, r1, r2, r3 STOREMODE #SVCmode, r0, r1, r2, r3 STOREMODE #ABTmode, r0, r1, r2, r3 STOREMODE #UNDmode, r0, r1, r2, r3 ; restore the mode back to that on entry to the handler ; (we kept the cpsr we saved in r7 in the LDMFD) MSR cpsr_cf, r7 ; restore r0 to point at the start of the regblock again. SUB r0, r0, #RegOffsCPSR MEND ; --------------------------------------------------------------------- ; EXCEPTENTRY ; ----------- ; EXCEPTENTRY $handler, $regblock ; ; Code to handle exception handler entry. Parameters include the handler ; mode (e.g. IRQmode) and the address to store the registers. ; ; On Entry: ; sp_<entry mode> should point at an FD stack of a few words. ; CPSR is assumed to have IRQ disabled (as will be the case for ; all exception handlers). ; ; On Exit: ; r0 will be left pointing at the base of the regblock. ; MACRO EXCEPTENTRY $handler, $regblock EXCEPTENTRY_PART1 $handler, $regblock EXCEPTENTRY_PART2 MEND ; --------------------------------------------------------------------- ; SAVETASK ; ----------- ; SAVETASK $regblock, $inregzero ; ; Code to save the task context. This differs from the EXCEPTENTRY ; macro in that it assumes that we start in SVC mode. The task ; resumes at the address specified in LR on entry. ; ; On Entry: ; sp_<entry mode> should point at an FD stack of a few words. ; CPSR is assumed to specify a privileged mode. ; $regblock is the address to store the registers, if a constant. ; $inregzero is a flag - ; if non-zero, the regblock address is in R0 on entry ; if zero, the regblock address is defined by parameter 1 ; ; On Exit: ; r0 will be left pointing at the base of the regblock. ; MACRO SAVETASK $regblock, $inregzero STMFD sp!, {r0} ; save r0 ... MRS r0, cpsr STMFD sp!, {r0, r8} ; cpsr and r8 on current mode's stack ;; ENTER CRITICAL SECTION! ORR r0, r0, #IRQDisable + FIQDisable MSR cpsr_cf, r0 ; ; save the unbanked regs -- use r8 to address the save area while ; we're saving r0 to r7, then move to use r0 for the banked registers ; IF $inregzero <> 0 LDR r8, [sp, #8] ; load original r0, the ptr to regblock, ADD r8, r8, #RegOffsCPSR ; from stack and add offset... ELSE LDR r8, =$regblock + RegOffsCPSR ; else it's a macro parameter ENDIF MRS r0, spsr ; use the SPSR as the saved CPSR value.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -