📄 windalib.s
字号:
* idle state because doWork will make subroutine calls that use the stack. We* don't want to be on another tasks stack, we can't be on the interrupt* stack because intCnt == 0, and any interrupt would muck our stack.*/ .ent idleidle:#ifdef WV_INSTRUMENTATION /* * windview instrumentation - BEGIN * enter idle state * */ lw t1, evtAction /* is instrumentation on? */ beqz t1, noInstIdle HAZARD_VR5400 mfc0 t2, C0_SR li t1, ~SR_INT_ENABLE and t1, t1, t2 mtc0 t1, C0_SR /* LOCK INTERRUPTS */ HAZARD_INTERRUPT lw t0, wvEvtClass /* is instrumentation on? */ li t1, WV_CLASS_1_ON /* is instrumentation on? */ and t0, t0, t1 bne t1, t0, trgCheckIdle SETFRAME(idle,0) subu sp,FRAMESZ(idle) li a0, EVENT_WIND_EXIT_IDLE lw t1, _func_evtLogT0 jal t1 /* call evtLogT0 routine */noInstIdleRestore: addu sp, FRAMESZ(idle)trgCheckIdle: lw t0, trgEvtClass li t1, TRG_CLASS_1_ON and t0, t0, t1 bne t1, t0, noInstIdle SETFRAME(idle,0) subu sp,FRAMESZ(idle) li a0, EVENT_WIND_EXIT_IDLE li a1, TRG_CLASS1_INDEX li a2, 0x0 lw t1, _func_trgCheck jal t1 /* call trgCheck routine */ addu sp, FRAMESZ(idle)noInstIdle: /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION */ lw t2, taskSrDefault /* load default SR value */ li t0, 1 /* load idle flag to reg */ HAZARD_VR5400 mtc0 t2, C0_SR /* UNLOCK INTERRUPTS */ sw t0, kernelIsIdle /* set idle flag for spyLib */idleLoop: lw t1, workQIsEmpty /* if work queue is still empty */ bne zero, t1, idleLoop /* keep hanging around */ sw zero, kernelIsIdle /* unset idle flag for spyLib */ j doWork /* go do the work */ .end idle/********************************************************************************* doSwapHooks - execute the tasks' swap hooks** S-regs are used for variables that must be preserved across* procedure calls. We need not restore the S-regs because* kernelState = TRUE, so we will never overwrite them due* to an interrupt thread, and all registers are now available* for use at this point (tcb's acurrately saved).*/doSwapHooks: SETFRAME(doSwapHooks,0) subu sp, FRAMESZ(doSwapHooks) /* make room for 2 params and ra */ move s0, t0 /* load pointer to old tcb */ move s1, t1 /* load pointer to new tcb */ la s2, taskSwapTable /* get adrs of task switch rtn list */ move s3, t3 /* put mask in saved reg */ li s4, 0x10000 /* load ending condition into reg */ j doSwapShift /* jump into the loop */doSwapHook: move a0, s0 /* pass taskIdPrevious */ move a1, s1 /* pass taskIdCurrent */ lw t1, -4(s2) /* get task switch rtn into t1 */ jal t1 /* call routine */doSwapShift: andi t2, s3, 0x8000 /* mask bit set ? */ sll s3, 1 /* shift swapMask bit pattern left */ addi s2, 4 /* increment taskSwapTable */ bne zero, t2, doSwapHook /* yes, call SwapHook */ blt s3, s4, doSwapShift /* if mask > 0x8000 all done */ addi sp, FRAMESZ(doSwapHooks) /* clean up stack */ move t1, s1 /* restore t1 with taskIdCurrent */ lw t0, taskSwitchTable /* any global switch hooks? */ beq zero, t0, dispatch /* if no then dispatch taskIdCurrent */ j doSwitchFromSwap /* do switch routines from swap *//********************************************************************************* doSwitchHooks - execute the global switch hooks*/doSwitchHooks: move s0, t0 /* load pointer to old tcb */ move s1, t1 /* load pointer to new tcb */doSwitchFromSwap: SETFRAME(doSwitchHooks,0) subu sp, FRAMESZ(doSwitchHooks) /* make room for 2 params and ra */ la s2, taskSwitchTable /* get adrs of task switch rtn list */ lw t1, 0(s2) /* get task switch rtn into t1 */doSwitchHook: move a0, s0 /* pass taskIdPrevious */ move a1, s1 /* pass taskIdCurrent */ jal t1 /* call routine */ addu s2, 4 /* bump to next task switch routine */ lw t1, 0(s2) /* get next task switch rtn */ bne zero, t1, doSwitchHook /* loop */ move t1, s1 /* restore t1 with taskIdCurrent */ addu sp, FRAMESZ(doSwitchHooks) /* clean up stack */ j dispatch /* dispatch task *//********************************************************************************* doWork - empty the work queue* doWorkUnlock - unlock interrupts and empty the work queue** For doWorkUnlock, t0 must contain the value of the R3k SR before* interrupts were locked. We do not need to preserve the ra on a* stack in these cases because state has been fully preserved at * this point.**/doWorkUnlock: HAZARD_VR5400 mtc0 t0, C0_SR /* UNLOCK interrupts */doWork: jal workQDoWork /* empty the work queue */ lw t0, taskIdCurrent /* put taskIdCurrent into t0 */ lw t1, readyQHead /* get highest task to t1 */ beq zero, t1, idle /* nobody is ready so spin */ beq t0, t1, dispatch /* if the same dispatch */ j switchTasks /* not same, do switch */#else /* PORTABLE portable version of windExit() and windLoadContext() *//********************************************************************************* windExitInt - exit kernel routine from interrupt level** windExit branches here if exiting kernel routine from int level* No rescheduling is necessary because the ISR will exit via intExit, and* intExit does the necessary rescheduling.*/windExitIntWork: SETFRAME(windExitIntWork,0) subu sp, FRAMESZ(windExitIntWork) /* need some stack */ SW ra, FRAMERA(windExitIntWork)(sp) /* save ra */ mtc0 t2, C0_SR /* UNLOCK INTS */ jal workQDoWork /* empty the work queue */ LW ra, FRAMERA(windExitIntWork)(sp) /* restore ra */ addu sp, FRAMESZ(windExitIntWork) /* restore stack */ .ent windExitIntwindExitInt: mfc0 t2, C0_SR HAZARD_CP_READ li t1, ~SR_INT_ENABLE and t1, t1, t2 mtc0 t1, C0_SR /* LOCK INTERRUPTS */ HAZARD_INTERRUPT lw t0, workQIsEmpty /* test for work to do */ beq zero, t0, windExitIntWork /* workQueue is not empty */ move v0, zero /* return OK */ sw zero, kernelState /* else release exclusion */ mtc0 t2, C0_SR /* UNLOCK INTERRUPTS */ j ra /* back to calling task */ .end windExitInt/******************************************************************************** windExit - PORTABLE VERSION of task level exit from kernel** This is the way out of kernel mutual exclusion. If a higher priority task* than the current task is ready, then we invoke the rescheduler. We* also invoke the rescheduler if any interrupts have occured which have added* work to the windWorkList. If rescheduling is necessary,* the context of the calling task is saved with the PC pointing at the* next instruction after the jsr to this routine. The SP in the tcb is* modified to ignore the return address on the stack. Thus the context saved* is as if this routine was never called.** NOMANUAL* void windExit ()*/ .ent windExitwindExit: lw t0,intCnt /* (intCnt == 0) == task code */ bne zero, t0, windExitInt /* exiting interrupt code? */taskCode: lw t0, taskIdCurrent /* move taskIdCurrent into t0 */ lw t1, readyQHead /* compare highest ready task */ beq t0, t1, checkWorkQ /* if same then check workQ */ lw t2, WIND_TCB_LOCK_CNT(t0) /* allowed to switch tasks? */ beq zero, t2, saveTaskContext /* if yes, save task context */ lw t2, WIND_TCB_STATUS(t0) /* is task ready to run? */ bne zero, t2, saveTaskContext /* we blocked while taskLocked*/checkWorkQ: mfc0 t2, C0_SR HAZARD_CP_READ li t1, ~SR_INT_ENABLE and t1, t1, t2 mtc0 t1, C0_SR /* LOCK INTERRUPTS */ HAZARD_INTERRUPT lw k0, workQIsEmpty /* test for work to do */ beq zero, k0, saveTaskContextUL /* workQueue is not empty */ sw zero, kernelState /* else release exclusion */ mtc0 t2, C0_SR /* UNLOCK INTERRUPTS */ move v0, zero /* return OK */ j ra /* back to calling task */saveTaskContextUL: mtc0 t2, C0_SR /* UNLOCK INTERRUPTS */saveTaskContext: lw t1, errno HAZARD_VR5400 mfc0 t2, C0_SR /* make sure we have sr */ HAZARD_CP_READ sw t1, WIND_TCB_ERRNO(t0) /* save errno */ SW sp, WIND_TCB_SP(t0) /* save stack pointer */ sw ra, WIND_TCB_PC(t0) /* save ra to be new PC after call to here */ sw t2, WIND_TCB_SR(t0) /* save SR in entirety */ /* load saved registers */ /* less volatile t0-t9 */ SW zero, WIND_TCB_V0(t0) /* windExit() returns OK */ mflo t1 SW t1, WIND_TCB_LO(t0) mfhi t2 SW t2, WIND_TCB_HI(t0)0: SW s0, WIND_TCB_S0(t0) SW s1, WIND_TCB_S1(t0) SW s2, WIND_TCB_S2(t0) SW s3, WIND_TCB_S3(t0) SW s4, WIND_TCB_S4(t0) SW s5, WIND_TCB_S5(t0) SW s6, WIND_TCB_S6(t0) SW s7, WIND_TCB_S7(t0) SW s8, WIND_TCB_S8(t0) j reschedule /* goto rescheduler */ .end windExit/********************************************************************************* windLoadContext - load the register context from the control block** The registers of the current executing task, (the one reschedule chose),* are restored from the control block. This means that all registers * are available for usage since the prior task context was saved* before reschedule was called. There is no exception stack frame in the * MIPS architecture so none is simulated in doing the context switch.* Previous interrupt state and new context is restored. For R3k processors* a jump to PC places us in the new context. For all other ISA's, switching to* the new context is accomplished via an 'eret' and the EPC. ** Interrupts are locked on entry to this routine so moving the old status * register to the processor with a mtc0 will re-enable interrupts if previously * enabled. This is not an issue for non-R3k processors because the EXL bit is * being set in anticipation of the 'eret'. Interrupts are disabled by virtue of* it being set.** K1 and K0 are available for kernel use but ONLY in non-interruptible sections.** NOMANUAL* void windLoadContext ()*/ .ent windLoadContextwindLoadContext: lw t0, taskIdCurrent /* current tid */ lw t1, WIND_TCB_ERRNO(t0) /* read errno */ LW a0, WIND_TCB_A0(t0) /* restore saved registers */ LW a1, WIND_TCB_A1(t0) LW a2, WIND_TCB_A2(t0) LW a3, WIND_TCB_A3(t0) sw t1, errno /* save errno */ LW v0, WIND_TCB_V0(t0) LW v1, WIND_TCB_V1(t0) LW t1, WIND_TCB_T1(t0) LW t2, WIND_TCB_T2(t0) LW t3, WIND_TCB_LO(t0) LW t4, WIND_TCB_HI(t0) mtlo t3 mthi t40: LW t3, WIND_TCB_T3(t0) LW t4, WIND_TCB_T4(t0) LW t5, WIND_TCB_T5(t0) LW t6, WIND_TCB_T6(t0) LW t7, WIND_TCB_T7(t0) LW s0, WIND_TCB_S0(t0) LW s1, WIND_TCB_S1(t0) LW s2, WIND_TCB_S2(t0) LW s3, WIND_TCB_S3(t0) LW s4, WIND_TCB_S4(t0) LW s5, WIND_TCB_S5(t0) LW s6, WIND_TCB_S6(t0) LW s7, WIND_TCB_S7(t0) LW t8, WIND_TCB_T8(t0) LW t9, WIND_TCB_T9(t0) LW s8, WIND_TCB_S8(t0) LW ra, WIND_TCB_RA(t0) /* restore return addr */ lw k1, WIND_TCB_SR(t0) /* load status register */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -