:TITLE[MesaP--Alto.mode.only]; *Last edited: 17 August 1981 by Fiala *Process Microcode; *PSB format MC[CleanUpOffset,1]; MC[TimeOffset,2]; MC[FlagsOffset,3]; MC[FrameOffset,4]; MC[Priority,7]; MC[WaitingOnCV,10]; MC[AbortPending,40]; MC[TimeoutAllowed,100]; MC[EnterFailed,100000]; MC[SizePSB,5]; *Monitor Lock format MC[LockBit,100000]; *Condition Variable format MC[WWBit,100000]; *Constants MC[CleanQueue1,0]; MC[CleanQueue2,1]; MC[NegInfinity,100000]; MC[CVBase,40]; MC[TimerBit,20]; MC[TimeLocation,344]; *Dispatch bas address Set[ProcessDisp,LShift[prPage,10]]; %PRFlags holds opcode dispatch values and general flags. Its interpretation is: bit 0 0 => Clean Queue 1 1 => Clean Queue 2 bit 10 0 => Requeue not done 1 => Requeue done bits 16,17 0 => Notify 1 => Broadcast 2 => Naked Notify 3 => not used bits 12-15 Opcode Dispatch All flag constants except NakedNotifyFlags are cycled right 1 in order to set bit 0 if necessary. % *Flag values MC[MEFlags, 0]; * Dispatch to 0 SET[MEloc, 0]; MC[MREFlags, 21]; * Dispatch to 2, Clean Queue 2 SET[MREloc, 2]; MC[MXWFlags, 51]; * Dispatch to 5, Clean Queue 2 SET[MXWloc, 5]; MC[MXDFlags, 61]; * Dispatch to 6, Clean Queue 2 SET[MXDloc, 6]; MC[NOTIFYFlags, 100]; * Dispatch to 10, Clean Queue 1, Notify MC[BCASTFlags, 102]; * Dispatch to 10, Clean Queue 1, Broadcast SET[WakeHeadloc, 10]; MC[REQFlags, 130]; * Dispatch to 13 SET[REQloc, 13]; MC[NakedNotifyFlags, 2]; * Clean Queue 1, Naked Notify, not cycled MC[RequeueOccured, 200]; *Requeue occured, not cycled @ME: PRFlags ← MEFlags, Goto[CheckLong1], Opcode[1]; *Monitor Lock @MRE: PRFlags ← MREFlags, Goto[CheckLong2], Opcode[2]; *CV, Lock @MXW: PRFlags ← MXWFlags, Opcode[3]; *Time, CV, Lock MXWx: T ← Stack&-1; Process ← T, Goto[CheckLong2]; @MXD: PRFlags ← MXDFlags, Goto[CheckLong1], Opcode[4]; *Monitor Lock @NOTIFY: PRFlags ← NOTIFYFlags, Goto[CheckLong1], Opcode[5]; *CV @BCAST: PRFlags ← BCASTFlags, Goto[CheckLong1], Opcode[6]; *CV @REQUEUE: PRFlags ← REQFlags, Goto[MXWx], Opcode[7]; *Process, Q1, Q2 ***Should use MDShi literally here rather than fixing it up in a way that ***makes the LH and RH .ne.; also should start with LH[MDShi] if going to ***do the fixup as shown. FixQueue2: T ← Queue2hi ← (Lsh[Queue2hi,10]) + T + 1; Queue2hi ← (FixVA[Queue2hi]) or T; T ← Stack&-1; TtoQueue2: Queue2 ← T, Return; CheckLong2: T ← 373C; *StkP value for two long pointer operands (4). T ← (NStkP) xor T; *Check for stack size of 4. T ← RHMask[MDShi], DblGoto[Short2,Long2,ALU#0]; CheckLong1: T ← 375C; *StkP value for one long pointer operand (2). T ← (NStkP) xor T; *Check for stack size of 2. T ← RHMask[MDShi], DblGoto[Short1,Long1,ALU#0]; Short2: Queue2hi ← T, Call[FixQueue2]; T ← RHMask[MDShi], Goto[Short1]; Long2: T ← Stack&-1; Queue2hi ← T, Call[FixQueue2]; T ← Stack&-1, Goto[Short1]; Long1: T ← Stack&-1; Short1: Queue1Hi ← T; T ← Stack&-1, Task; Queue1 ← T; LU ← (Queue1hi) or T; T ← Queue1hi, Skip[ALU=0]; T ← Queue1hi ← (Lsh[Queue1hi,10]) + T + 1; Queue1hi ← (FixVA[Queue1hi]) or T; LoadPage[prPage]; *Process dispatch Dispatch[PRFlags,11,4], GotoP[.+1]; OnPage[prPage]; PRFlags ← Rcy[PRFlags,1], Disp[MEnter]; ************************************************************************* * Monitor Enter; * * Input * Queue1 Base register pointing at monitor queue * * Temps * MQ process handle * * Constants * CurrentPSB 21B, address of CurrentPSB * LockBit 100000B, lock bit of Monitor Lock * ************************************************************************* MEnter: T ← CurrentPSB, Call[Queue1ToMQ], At[ProcessDisp,MEloc]; LU ← MQ, Skip[R<0]; PFetch1[PBase,Process], Goto[MREnterFailed]; *Locked MQ ← (MQ) and not (LockBit), Call[MQToQueue1]; MRENoAbort: Stack&+1 ← 1C; * even location PrTail: LoadPage[opPage0]; Goto[P4Tail]; ************************************************************************* * Monitor ReEnter; * * Input * Queue1 Base register pointing at monitor queue * Queue2 Base register pointing at condition queue * * Temps * PBase Base register of PSBs * Process process handle * RTemp1 temp * * Constants * LockBit 100000B, lock bit of Monitor Lock * CleanUpOffset 1, offset of cleanup link in PSB * FlagsOffset 3, offset of flags and priority in PSB * CurrentPSB 21B, address of CurrentPSB * sProcessTrap 17B, offset of sProcessTrap in SD * ************************************************************************* MREnter: T ← CurrentPSB, Call[Queue1ToMQ], At[ProcessDisp, MREloc]; Call[PBaseToProcess]; LU ← MQ, Goto[MREnterFailed,R>=0]; * ignore ww bit UseCTask, Call[CleanUpQueue]; * Clean up Queue1 MQ ← (MQ) and not (LockBit), Call[MQToQueue1]; T ← (Process) + (CleanUpOffset), Call[ZeroToPBase]; T ← (Process) + (FlagsOffset), Call[PBaseToRTemp1]; LU ← (RTemp1) and (AbortPending); Goto[MRENoAbort,ALU=0]; T ← sProcessTrap; PRTrap: LoadPage[opPage3]; GotoP[kfcr]; MREnterFailed: T ← Queue1hi; Queue2hi ← T, LoadPage[opPage0]; T ← Queue1, Call[TtoQueue2]; T ← (MDShi) or (1C), Call[ReadyInQueue1]; T ← (Process) + (FlagsOffset), Call[PBaseToRTemp1]; RTemp1 ← (RTemp1) or (EnterFailed), Call[RTemp1ToPBase]; Goto[RequeueOp]; ************************************************************************* * Monitor Exit and Depart; * * Input * Queue1 Base register pointing at monitor queue * ************************************************************************* MXDepart: UseCTask, Call[ExitMon], At[ProcessDisp, MXDloc]; LU ← (PRFlags) and (200C), Goto[ReSchedule]; ************************************************************************* * Exit Monitor; * * Input * Queue1 Base register pointing at monitor queue * * Temps * PBase Base register of PSBs * MQ process handle * Process process handle * EMLink Return link * * Constants * LockBit 100000B, lock bit of Monitor Lock * ************************************************************************* ExitMon: T ← APCTask&APC, Call[Queue1ToMQ]; EMLink ← T; T ← MQ ← (MQ) and not (LockBit); Goto[EMUnlock,ALU=0]; PFetch1[PBase, Process], Call[ReadyInQueue2]; UseCTask, Call[RequeueSub]; PFetch1[Queue1,MQ,0]; EMUnlock: MQ ← (MQ) or (LockBit); PStore1[Queue1,MQ,0]; APCTask&APC ← EMLink, Goto[PRRet]; ************************************************************************* * Monitor Exit and Wait; * * Input * Queue2 Base register pointing at condition queue * Queue1 Base register pointing at monitor queue * Process Timeout value * * Temps * PBase Base register of PSBs * MQ process handle * PRTime holds timeout value * RTemp1 process handle * * Constants * WWBit 100000B, ww bit of Condition * LockBit 100000B, lock bit of Monitor Lock * CleanUpOffset 1, offset of cleanup link in PSB * TimeOffset 2, offset of flags and priority in PSB * FlagsOffset 3, offset of flags and priority in PSB * WaitingOnCV 10B, WaitingOnCV bit of PSB * AbortPending 40B, AbortPending bit of PSB * TimeoutAllowed 100B, TimeoutAllowed bit of PSB * CurrentPSB 21B, address of CurrentPSB * TimeLocation 344B, address of Timeout time in Memory * ************************************************************************* MXWait: T ← Process, At[ProcessDisp,MXWloc]; PRTime ← T, UseCTask, Call[CleanUpQueue]; T ← QTemp, Call[SwapQTempAndQ2]; UseCTask, Call[ExitMon]; T ← CurrentPSB, Call[PBaseToProcess]; T ← (Process) + (FlagsOffset), Call[PBaseToRTemp1]; LU ← (RTemp1) and (AbortPending); Goto[MXWReSched,ALU#0]; PFetch1[QTemp,MQ,0]; MQ ← (MQ) and not (WWBit), Goto[MXWOntoCV,R>=0]; PStore1[QTemp,MQ,0], Call[PRRet]; LU ← (PRFlags) and (200C), Goto[ReSchedule]; MXWOntoCV: LU ← PRTime; RTemp1 ← (RTemp1) or (WaitingOnCV), Goto[MXWHaveTime,ALU=0]; T ← TimeLocation; PFetch1[PBase,CurrentTime]; T ← CurrentTime; PRTime ← (PRTime) + T; Goto[MXWHaveTimex,ALU#0]; PRTime ← (PRTime) + 1; MXWHaveTime: nop; MXWHaveTimex: T ← (MDShi) or (1C), Call[ReadyInQueue1]; T ← QTemp, Call[SwapQTempAndQ2]; T ← (Process) + (FlagsOffset), Call[RTemp1ToPBase]; UseCTask, Call[RequeueSub]; T ← (Process) + (TimeOffset); PStore1[PBase,PRTime]; MXWReSched: LU ← (PRFlags) and (200C), Goto[ReSchedule]; SwapQTempAndQ2: MNBR ← Queue2, Queue2 ← T, NoRegILockOK; T ← MNBR; QTemp ← T; T ← QTemphi; MNBR ← Queue2hi, Queue2hi ← T, NoRegILockOK; T ← MNBR; QTemphi ← T, Return; ************************************************************************* * Notify Broadcast; * * Input * Queue1 Base register of queue to be notified * * Temps * PBase Base register of PSBs * MQ process handle * RTemp1 process handle * Process process handle * PRTime Did something * PRFlags flags * * Constants * WWBit 100000B, ww bit of Condition * NegInfinity 100000B * FlagsOffset 3, offset of cleanup link in PSB * WaitingOnCV 10B, WaitingOnCV bit in PSB * ************************************************************************* WakeHead: UseCTask, Call[CleanUpQueue], At[ProcessDisp,WakeHeadloc]; WHLoop: Call[Queue1ToMQ]; MQ ← T ← (MQ) and not (WWBit); PRTime ← Zero, Skip[ALU#0]; LU ← LdF[PRFlags,16,1], Goto[WHExit]; PFetch1[PBase,Process], Call[ReadyInQueue2]; T ← (Process) + (FlagsOffset), Call[PBaseToRTemp1]; RTemp1 ← (RTemp1) and not (WaitingOnCV), Call[RTemp1ToPBase]; PRTime ← (PRTime) + 1, UseCTask, Call[RequeueSub]; LU ← LdF[PRFlags,16,1], Skip[R Even]; Goto[WHLoop]; WHExit: LU ← (PRFlags) and (200C), Goto[ReSchedule,ALU=0]; LU ← PRTime, Skip[R Odd]; MQ ← WWBit, Call[MQToQueue1]; IntLevel ← (IntLevel) + 1, LoadPage[opPage0]; Goto[CheckCV]; ************************************************************************* * Requeue; * * calling instruction must include UseCTask * * Input * Queue1 Base register pointing at queue * Queue2 Base register pointing at queue * Process process handle * * Output * ReSched BOOLEAN * * Temps * PBase Base register of PSBs * Prev process handle * RTemp Process.link until insert, then Process.priority * RTemp1 process handle, priority * MQ process handle, priority * RLink Return address * * Constants * CleanUpOffset 1, offset of cleanup link in PSB * FlagsOffset 3, offset of flags and priority in PSB * Priority 7, priority bits * RequeueOccured 200B * ************************************************************************* RequeueOp: UseCTask, Call[RequeueSub], At[ProcessDisp,REQloc]; LU ← (PRFlags) and (200C), Goto[ReSchedule]; RequeueSub: T ← APCTask&APC; RLink ← T; T ← Process, Call[PBaseToRTemp]; LU ← (RTemp) - T; LU ← Queue1hi, Skip[ALU#0]; *only one process Prev ← Zero, Goto[RQFixCV]; Prev ← T, Skip[ALU=0]; *Queue1 NIL, T = Process PFetch1[Queue1,Prev,0]; T ← Prev; RQLoop1x: Prev ← T, Call[PBaseToRTemp1]; T ← RTemp1; LU ← (Process) - T; Goto[RQLoop1x,ALU#0]; T ← Prev; Call[RTempToPBase]; *RTemp has Process.link RQFixCV:LU ← Queue1hi; T ← (Process) + (CleanUpOffset), Skip[ALU#0]; PStore1[PBase,RTemp], Goto[RQInsrt]; RQHaveQ1: PFetch1[Queue1,RTemp1,0]; T ← Process, Call[PRRet]; LU ← (RTemp1) - T; Skip[ALU#0]; PStore1[Queue1,Prev,0], Call[PRRet]; RQInsrt:PFetch1[Queue2,Prev,0], Call[PRRet]; LU ← Prev; T ← Process, Goto[RQNilPP,ALU=0]; T ← (Process) + (FlagsOffset), Call[PBaseToRTemp]; T ← (Prev) + (FlagsOffset), Call[PBaseToRTemp1]; T ← LdF[RTemp,15,3]; *priority LU ← (LdF[RTemp1,15,3]) - T, Call[RQLp2S]; RQLoop2:T ← (RTemp1) + (FlagsOffset); PFetch1[PBase,MQ]; T ← LdF[RTemp,15,3]; LU ← (LdF[MQ,15,3]) - T; T ← RTemp1, Skip[ALU<0]; Prev ← T, Goto[PBaseToRTemp1]; RQInsrtHere: T ← Process, Call[RTemp1ToPBase]; T ← Prev, Call[ProcessToPBase]; RQRet: T ← (Process) + (TimeOffset), Call[ZeroToPBase]; APCTask&APC ← RLink; PRFlags ← (PRFlags) or (RequeueOccured), Return; RQNilPP:PStore1[PBase,Process]; PStore1[Queue2,Process,0], Goto[RQRet]; RQLp2S: T ← Prev, Goto[PBaseToRTemp1,ALU<0]; PFetch1[PBase,RTemp1]; PStore1[Queue2,Process,0], Goto[RQinsrtHere]; ************************************************************************* * CleanUpQueue; * this routine cleans up a queue which may possibly * have been left in a mess by Requeue. * * calling instruction must include UseCTask * * Input * PRFlags even => clean Queue1, odd => clean Queue2 * * Temps * PBase Base register of PSBs * RTemp process handle * RTemp1 process handle * MNBR process handle * RLink Return address * * Constants * WWBit 100000B, ww bit of Condition * CleanUpOffset 1, offset of cleanup link in PSB * ************************************************************************* CleanUpQueue: T ← APCTask&APC; RLink ← T, Call[CQueueToRTemp]; * get pointer to tail RTemp ← (RTemp) and not (WWBit); * ignore ww bit T ← (RTemp) + (CleanUpOffset), Goto[CURet,ALU=0]; PFetch1[PBase,RTemp1], Call[PRRet]; * get head of queue LU ← T ← RTemp1; LU ← (RTemp) - T, Skip[ALU#0]; APCTask&APC ← RLink, Goto[PRRet]; RTemp ← T, Skip[ALU#0]; CUEmpty: RTemp ← Zero, Goto[CUFixCV]; CULoop: T ← (RTemp) + (CleanUpOffset), Call[PBaseToRTemp1]; *get head of queue LU ← T ← RTemp1; LU ← (RTemp) - T, Skip[ALU=0]; RTemp ← T, DblGoto[CUEmpty,CULoop,ALU=0]; T ← MNBR ← RTemp; CULoop2: RTemp ← T, Call[PBaseToRTemp1]; T ← RTemp1; LU ← (MNBR) - T; CUFixCV:LU ← PRFlags, Goto[CULoop2,ALU#0]; APCTask&APC ← RLink, Skip[ALU<0]; PStore1[Queue1,RTemp,0], Return; PStore1[Queue2,RTemp,0], Return; CURet: APCTask&APC ← RLink, Goto[PRRet]; CQueueToRTemp: LU ← PRFlags, Skip[R<0]; PFetch1[Queue1,RTemp,0], Return; PFetch1[Queue2,RTemp,0], Return; ************************************************************************* * ReSchedule; * * Input * lu (PRFlags) and (200C) * * Temps * PBase Base register of PSBs * RTemp process handle * RTemp1 process handle * MNBR process handle * RLink Return address * * Constants * EnterFailed 100000B, EnterFailed bit of PSB * CleanUpOffset 1, offset of cleanup link in PSB * FlagsOffset 3, offset of priority and flags in PSB * FrameOffset 4, offset of frame in PSB * CleanUpOffset 1, offset of cleanup link in PSB * Priority 7, priority bits in PSB * StkPOffset 10B, offset of stack pointer in state vector * DestOffset 11B, offset of dest in state vector * CurrentPSB 21B, Current process * ReadyQ 22B, Ready queue * CurrentState 23B, Current state * ************************************************************************* ReSchedule: T ← CurrentState, Goto[PrTail,ALU=0]; Nop; IntReSch: LoadPage[opPage3]; PFetch1[PBase,xfTemp], CallP[SavePCInFrame]; LoadPage[xfPage1]; UseCTask, CallP[SaveState]; T ← CurrentPSB, Call[PBaseToRTemp1]; *RTemp1 ← currentPSB T ← (RTemp1) + (FrameOffset); PStore1[PBase,LOCAL]; IdleIntRS: T ← ReadyQ; PFetch1[PBase,RTemp1], Call[PRRet]; LU ← T ← RTemp1; LU ← xfWDC, Goto[NoneReady,ALU=0]; PFetch1[PBase,Process]; *Process ← readylist.link *Setup for new process T ← (Process) + (FlagsOffset), Call[PBaseToRTemp1]; RTemp ← xfAV; T ← (RTemp) + (FirstStateVector), Call[PBaseToRTemp]; T ← LdF[RTemp1,15,3], Task; *Priority xfTemp ← T; xfTemp ← (Lsh[xfTemp,2]) + T; T ← (Lsh[xfTemp,1]) + T; *13b*priority RTemp ← (RTemp) + T; RTemp1 ← (RTemp1) and not (EnterFailed), Goto[NoEnterFailed,R>=0]; T ← (Process) + (FlagsOffset), Call[RTemp1ToPBase]; T ← RTemp, Call[ZeroToPBase]; * stack[0] ← 0; RTemp1 ← 1C; * stkp ← 1 T ← (RTemp) + (StkPOffset), Call[RTemp1ToPBase]; NoEnterFailed: T ← (Process) + (FrameOffset); PFetch1[PBase,RTemp1]; T ← (RTemp) + (DestOffset), Call[RTemp1ToPBase]; T ← CurrentPSB, Call[ProcessToPBase]; * currentPSB ← process T ← CurrentState, Call[RTempToPBase]; T ← RTemp, LoadPage[xfPage1]; xfTemp ← T, GotoP[LoadStateNF]; NoneReady: T ← sWakeupError, Goto[PRTrap,ALU#0]; IntType ← T ← Zero; *PC backup amount, StkP value for MIPend Call[IdleLoop]; IdleLoop: Goto[MIPend,IntPending]; PRRet: Return; *Get here with StkP in T (0 if from IdleLoop), PC backup amount in IntType. MIPend: RTemp1 ← IP[RSImage]C; *Clear IntPending StkP ← RTemp1, RTemp1 ← T, NoRegILockOK; T ← Stack ← (Stack) and not (IntPendingBit); StkP ← RTemp1, RS232 ← T; T ← IntType; *back up the PC T ← (PCFreg) - T, Goto[NoBackup,ALU=0]; *When PCF is 10b, BitBlt has done PC←PC+4, PCF←0, so PCF-1 can be negative; *In this situation we have to do PC←PC-4 and PCF←7. The code below also *allows MIPend to be called by opcodes longer than 1 byte (CSUM). RTemp1 ← T, Goto[BackNoOvf,ALU>=0]; PCB ← (PCB) - (4C); PFetch4[PCB,IBuf,0]; BackNoOvf: PCF ← RTemp1; NoBackup: LU ← xfWDC; *Check (NWW#0 & xfWDC=0) T ← NWW, Skip[ALU=0]; Return; NWW ← Zero, Skip[ALU#0]; NWW ← T, Return; :IF[CacheLocals]; ************************** *We are going to cause the interrupt; refill cache in case BitBlt interrupt PFetch4[LOCAL,LocalCache0,4], Task; ***Should task here when CacheLocals=0*** :ENDIF; ************************************ PRFlags ← Zero; WW ← T, LoadPage[opPage0]; *Promote NWW into WW LU ← LdF[WW,13,1], Goto[Interrupt]; PBaseToProcess: PFetch1[PBase,Process], Return; ProcessToPBase: PStore1[PBase,Process], Return; PBaseToRTemp: PFetch1[PBase,RTemp], Return; RTempToPBase: PStore1[PBase,RTemp], Return; PBaseToRTemp1: PFetch1[PBase,RTemp1], Goto[PRRet]; RTemp1ToPBase: PStore1[PBase,RTemp1], Goto[PRRet]; Queue1ToMQ: PFetch1[Queue1,MQ,0], Goto[PRRet]; MQToQueue1: PStore1[Queue1,MQ,0], Goto[PRRet]; ZeroToPBase: PStore1[PBase,RZero], Return; ReadyInQueue1: Queue1hi ← T; Queue1 ← ReadyQ, Return; ReadyInQueue2: T ← (MDShi) or (1c); Queue2hi ← T; Queue2 ← ReadyQ, Return; ************************************************************************* * Interrupt Processing; * * Input * WW Wakeups Waiting register * TickCount number of ticks until scaning PSBs required * CurrentTime current time * * Temps * IntLevel pointer to CV array elements * IntType even => idle loop interrupt * ITemp temp * ITemp1 temp * * Constants * WWBit 100000B, ww bit of Condition * TimeOffset 2, offset of time in PSB * FlagsOffset 3, offset of flags and priority in PSB * WaitingOnCV 10B, WaitingOnCV bit of PSB * NakedNotifyFlags * ************************************************************************* OnPage[opPage0]; Interrupt: WW ← (WW) and not (TimerBit), Goto[TimerInterrupt,ALU#0]; IntLevel ← CVBase; CheckCV:Call[.+1]; WW ← Rsh[WW,1], Goto[IntThisCV,R Odd]; Goto[IntDone,ALU=0]; *load page for done IntLevel ← (IntLevel) + 1, Return; IntThisCV: T ← IntLevel, Call[IntPBaseToQueue1]; LU ← Queue1; T ← (MDShi) or (1C), Skip[ALU#0]; *T ← ReadyQueuehi IntLevel ← (IntLevel) + 1, Goto[CheckCV]; Queue1hi ← T, LoadPage[prPage]; PRFlags ← (PRFlags) or (NakedNotifyFlags), Goto[WakeHead]; IntDone: LU ← IntType, LoadPage[prPage]; *Load page for done T ← CurrentState, DblGotoP[IntReSch,IdleIntRS,ALU#0]; TimerInterrupt: TickCount ← (TickCount) - 1; IntLevel ← CVBase, Goto[CheckCV,ALU#0]; ITemp ← xfAV; T ← ITemp ← (ITemp) + (FirstProcess), Call[IntPBaseToProcess]; T ← (ITemp) + 1; PFetch1[PBase,ITemp1]; T ← TimeLocation, Call[IntPBaseToCurrentTime]; CurrentTime ← (CurrentTime) + 1, Call[IntCurrentTimeToPBase]; Nop; TLoop: T ← (Process) + (TimeOffset); *Can't have call before this PFetch1[PBase,ITemp], Call[P4Ret]; LU ← T ← ITemp; LU ← (CurrentTime) - T, Goto[CheckEnd,ALU=0]; T ← (MDShi) or (1C), Skip[ALU=0]; Goto[CheckEnd]; *Timeout Queue2 ← ReadyQ; Queue1Hi ← Zero; Queue2Hi ← T, LoadPage[prPage]; *Make Queue2 the ReadyQueue UseCTask, Call[RequeueSub]; T ← (Process) + (FlagsOffset), Call[IntPBaseToQueue1]; Queue1 ← (Queue1) and not (WaitingOnCV); PStore1[PBase,Queue1]; CheckEnd: T ← Process ← (Process) + (SizePSB); LU ← (ITemp1) - T; TickCount ← 3C, Goto[TLoop,ALU>=0]; Goto[CheckCV]; IntPBaseToProcess: PFetch1[PBase,Process], Goto[P4Ret]; IntPBaseToQueue1: PFetch1[PBase,Queue1], Goto[P4Ret]; IntPBaseToCurrentTime: PFetch1[PBase,CurrentTime], Goto[P4Ret]; IntCurrentTimeToPBase: PStore1[PBase,CurrentTime], Goto[P4Ret]; P4Ret: Return; :END[MesaP];