📄 serlasm.s
字号:
TTL Angel serialiser support > serlasm.s ; ; This file provides veneers used by the serialiser module, as ; well as some globaly needed functions. ; ; $Revision: 1.13.4.1 $ ; $Author: rivimey $ ; $Date: 1997/12/10 18:50:16 $ ; ; Copyright Advanced RISC Machines Limited, 1995. ; All Rights Reserved ; KEEP GET listopts.s ; standard listing control GET lolevel.s ; automatically built manifest definitions GET macros.s ; standard assembler support GET target.s ; target specific manifests EXPORT Angel_EnterSVC EXPORT Angel_ExitToUSR EXPORT Angel_DisableInterruptsFromSVC EXPORT Angel_EnableInterruptsFromSVC EXPORT Angel_RestoreInterruptsFromSVC EXPORT angel_ReadBankedRegs AREA |serlasm|,CODE,PIC,READONLY ; See serlock.h for the interface to these functions. IMPORT Angel_StackBase IMPORT angel_SVCEntryFlag IMPORT __rt_asm_fatalerror ; error reporting via suppasm.s Angel_EnterSVC ; a1-a4 and ip may be corrupted under the APCS MRS a1, CPSR AND a2, a1, #ModeMask CMP a2, #USRmode BEQ WasUSRMode CMP a2, #SVCmodeInappropriateModeError BEQ WasSVCMode ADR a1, imdmsg B __rt_asm_fatalerrorimdmsg DCB "Inappropriate Mode\n" ALIGN WasSVCMode ; Just disable IRQ and FIQ and note SVC entry from SVC MOV a2, #1 LDR a3, =angel_SVCEntryFlag STR a2, [a3] ORR a1, a1, #IRQDisable + FIQDisable MSR CPSR_cxsf, a1 MOV pc, lr WasUSRMode ; The SWI does everthing for us - except note that entry was from USR MOV a2, #0 LDR a3, =angel_SVCEntryFlag STR a2, [a3] LDR a1, =angel_SWIreason_EnterSVC DCD angel_SWI_ARM ; Get into SVC with IRQ and FIQ disabled MOV pc, lr ; Return to caller ; On entry we check to see whether angel_SVCEntryFlag is ; 0 => Entry to SVC was from USR mode ; 1 => Entry to SVC was from SVC mode ; and return in that modeAngel_ExitToUSR ; a1-a4 and ip may be corrupted under the APCS LDR a3, =angel_SVCEntryFlag LDR a2, [a3] CMP a2, #0 BNE ReturnInSVCMode ; The standard return to USR case follows ... MOV a2, lr MOV a3, sp LDR sp, =Angel_StackBase ; Reset SVC sp to the empty SVC stack LDR sp, [sp] ADD sp, sp, #Angel_SVCStackOffset STMFD a3, {a3} SUB a3, a3, #4 LDMFD a3, {sp}^ MRS a1 ,CPSR BIC a1, a1, #ModeMask + IRQDisable + FIQDisable ORR a1, a1, #USRmode MSR CPSR_cxsf, a1 MOV pc, a2ReturnInSVCMode MRS a1, CPSR BIC a1, a1, #IRQDisable + FIQDisable MSR CPSR_cxsf, a1 MOV pc, lr ; On entry a1 = address of the regblock, a2 = the mode ; We must be called in USR mode - by debugos.c most likely.angel_ReadBankedRegs CMP a2, #USRmode BNE PrivModeCase STR r13, [a1, #Angel_RegBlock_R0offset + (13*4)] STR r14, [a1, #Angel_RegBlock_R0offset + (14*4)] MOV pc, lrPrivModeCase ; Write r8-r14 + spsr (in case it was FIQ mode MOV a4, a1 LDR a1, =angel_SWIreason_EnterSVC DCD angel_SWI_ARM ; Get into SVC with IRQ and FIQ disabled MSR CPSR_cxsf, a2 ADD a3, a4, #Angel_RegBlock_R0offset + (8*4) STMIA a3, {r8-r14} MRS a3, SPSR STR a3, [a4, #Angel_RegBlock_SPSRoffset] MOV a2, #USRmode MSR CPSR_cxsf, a2 NOP MOV pc, lr Angel_DisableInterruptsFromSVC MRS a1, CPSR IF (FIQ_SAFETYLEVEL >= FIQ_NeverUsesSerialiser_DoesNotReschedule) ORR a2, a1, #IRQDisable ELSE ORR a2, a1, #IRQDisable + FIQDisable ENDIF MSR CPSR_cxsf, a2 MOV pc, lrAngel_EnableInterruptsFromSVC MRS a1, CPSR BIC a2, a1, #IRQDisable + FIQDisable MSR CPSR_cxsf, a2 MOV pc, lrAngel_RestoreInterruptsFromSVC MSR CPSR_cxsf, a1 MOV pc, lr ; **************************************************************** IF :DEF: MINIMAL_ANGEL :LAND: MINIMAL_ANGEL<>0 ; Don't need all the serialiser-specific stuff ELSE IMPORT Angel_MutexSharedTempRegBlocks IMPORT angel_SerialiseTaskCore EXPORT Angel_SerialiseTask ; For the interface details of this pseudo function refer to ; serlock.h. For the details of the actual function ; angel_SerialiseTaskCore see serlock.cAngel_SerialiseTask ; r0 (a1) = called_by_yield ; r1 (a2) = fn ; r2 (a3) = state ; r3 (a4) = empty_stack ; Flatten the stack of whatever mode we were called in MOV sp, r3 ; Get into SVC and disable IRQ and FIQ IF :DEF: ASSERT_ENABLED :LAND: ASSERT_ENABLED <> 0 ; Check we are not in USR mode MRS r4, CPSR AND r4, r4, #ModeMask CMP r4, #USRmode BNE NotUsrMode ADR a1, serlusrmsg B __rt_asm_fatalerrorserlusrmsg DCB "Serialise in USR mode\n" ALIGNNotUsrMode ENDIF IF (FIQ_SAFETYLEVEL >= \ FIQ_NeverUsesSerialiser_DoesNotReschedule_HasNoBreakpoints) MOV r4, #SVCmode + IRQDisable ELSE MOV r4, #SVCmode + IRQDisable + FIQDisable ENDIF MSR cpsr_cxsf, r4 ; Set up desired_regblock (pc and r0 only at this point) LDR r4, =Angel_MutexSharedTempRegBlocks ADD r4, r4, #Angel_RegBlockSize STR r1, [r4, #Angel_RegBlock_R0offset + (15*4)] STR r2, [r4, #Angel_RegBlock_R0offset] MOV r1, r4 ; This is 2nd arg to angel_SerialiseTaskCore ; Note that at this point the SVC stack may be in any of the ; following states: ; * Empty Angel_SVCStack - if no task of WantsLock priority ; is running, and the application is not using the SVC stack ; * Non empty Angel_SVCStack - if a task with WantsLock priority ; is running (this will call of serialise task will be due ; to another packet arriving). ; * Application SVC stack ; ; However, using the Application SVC stack is not acceptable ; since it may not be large enough, or indeed r13 may have been ; corrupted. Therefore we must spot sp outside the range ; Angel_SVCStack - Angel_SVCStackLimit and if that is the case ; the it must be the Application stack in use, so switch to ; the Angel_SVCStack (which is empty in this case). LDR r4, =Angel_StackBase LDR r4, [r4] ADD sl, r4, #Angel_SVCStackLimitOffset ADD r4, r4, #Angel_SVCStackOffset CMP sp, sl BCC StackNotSetUp ; sp < Angel_SVCStackLimit CMP sp, r4 BLS StackIsSetUp ; sp <= Angel_SVCStackStackNotSetUp MOV sp, r4 StackIsSetUp ; Call angel_SerialiseTaskCore and set up lr to "return" to ; angel_NextTask. LDR lr, =angel_NextTask LDR r4, =angel_SerialiseTaskCore MOV pc, r4 ; **************************************************************** EXPORT angel_StartTask EXPORT angel_StartTask_NonSVCEntry ; For the interface details of this pseudo function refer to ; serlock.c ; ; What makes this all tricky is that we must completely finish with ; regblock before making any mode switch as the modes switch may ; enable interrupts, which can potentially corrupt regblock!angel_StartTask ; r0 (a1) = regblock ; This code resumes, restoring all regs from the regblock ; It works for all modes (!!!) (inc FIQ, and SVC, SYS and USR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -