{Process.mc, HGM,  4-Nov-84  3:00:50

HGM, 28-Nov-83  7:04:41, Check MesaInt at LoadProcess

HGM, 27-Sep-83 20:58:54, Merge In Dicentra fixes
	Check MesaInt at SaveProcess+Enqueue (Long SDLC path)
	Check MesaInt in Process Timeout Scan
	Turn off MInt from IdleLoop (to catch lost interrupts)
	FreeState used MDR←, ←MD quirk.
	Deleted several LOOPHOLE[mdok]s (1 left)
	Patched IdleLoop for Dicentra Interrupts



File name:  Process.mc
Description: Dandelion Process Microcode,
Author: Sandman,
Created: February 13, 1981  1:12 PM,
Johnsson 30-Aug-83  9:03:43 new instruction set
Daniels   5-Aug-83 16:04:37 new instruction set
Sandman  February 24, 1982 add Set Process Priority inst, bum 1 uinst
Sandman  January 18, 1982  12:30 PM fix ibempty, pccross, interrupt, no switch
Sandman  8-Dec-81 20:54:29 Correct PC/Stack fixup on faults
Sandman November 17, 1981  10:34 AM New instruction set
Sandman March 26, 1981  10:43 AM to fix timing restrictions
Sandman March 26, 1981  3:53 PM Change Wait to check condition.abortable
}

{*****************************************************************************
Definitions
*****************************************************************************}

Set[L2.Pop0IncrX, 0  {00xx}]; {also in Jump.mc} 

{Offsets and Magic locations}
Set[PSB.link, 0];
Set[PSB.link.preempted, 1];
Set[PSB.link.permanent, 2];
Set[PSB.link.enterfailed, 4];
Set[PSB.flags, 1];
Set[PSB.flags.waiting, 2];
Set[PSB.context, 2];
Set[PSB.timeout, 3];
Set[PSB.mds, 4];
Set[PSB.SIZE, 8];
Set[Condition.wakeup, 1];
Set[Condition.abortable, 2];
Set[Monitor.lock, 1];
Set[FaultQueue.condition, 1];
Set[PDAHi, 1];
Set[PDA.ready, 0];
Set[PDA.count, 1];
Set[PDA.state, 10'b];
Set[PDA.interrupt, 20'b];
Set[PDA.lastCV, 36'b];
Set[PDA.fault, 60'b];
Set[StartPSB, 100'b];
Set[StartPSBMinus1Times2, Lshift[Sub[StartPSB,PSB.SIZE],1]];

{
uPFlags holds opcode dispatch values and general flags.  Its encoding:
	Bit    Meaning
	8	    0: no Requeue, 1: Requeue occured
	9	    Interrupt
	10	    Process Trap
	11	    PCValid
	12-15  Opcode dispatch
}

{Flag values}
Set[pME, 10]; Set[pMELoc, 0];
Set[pMR, 1];
Set[pMX, 12]; Set[pMXLoc, 2]
Set[pMW, 9];
Set[pNC, 4];
Set[pBC, 5];
Set[pREQ, 8];
Set[pSPP, 0A];
Set[pInt, 47]; Set[pIntLoc, 7];  {Also in Dandelion.df}
Set[pIdle, 77]; {pIdle MOD 16 = pInt MOD 16 = pIntLoc}
Set[pFault, 3];
Set[pFaultPC, 0D3];
Set[pFaultNoPC, 0E3];
Set[pTrap, 20];

Set[cPCInvalid, 10];
Set[cRequeueFlag, 80];

Set[L3.Normal, 0];
Set[L3.Interrupt, 1];
Set[L3.Fault, 3];

Set[L0.SrcOK, 0];
Set[L0.SrcNull, 1];

Set[L2.Fault, 1];
Set[L2.Trap, 0];{also L2.MR4 in QRead}

MacroDef[PRr, at[#1,10,PRRets]];
MacroDef[PMRr, at[#1,10,PMRRets]];
MacroDef[PFr, at[#1,10,PFRets]];
MacroDef[PWr, at[#1,10,PWRets]];
MacroDef[QRr, at[#1,10,QRRets]];
MacroDef[QWr, at[#1,10,QWRets]];
MacroDef[NQr, at[#1,10,NQRets]];
MacroDef[CQr, at[#1,10,CQRets]];

{PRead Returns}
Set[L2.LP0, 0];
Set[L2.MR3, 1];
Set[L2.NQ0, 2]; {also QRead}
Set[L2.DQ2, 4];
Set[L2.NQ1, 5];
Set[L2.MW2, 6]; {also PFetch, PWrite, QRead}
Set[L2.WH2, 7];
Set[L2.NQ3, 8];
Set[L2.RS3, 9];
Set[L2.LP1, 0A];{also PWRets}
Set[L2.AS0, 0B];
Set[L2.PLS0, 0C];
Set[L2.LP2, 0D];
Set[L2.TS0, 0E];
Set[L2.TS2, 0F];


{PMRead Returns}

Set[L2.WH0, 0]; {0 MOD 2}
Set[L2.RS0, 1]; {also PFetch}
Set[L2.DQ1, 3]; {3 MOD 4}
Set[L2.EM2, 4]; {0 MOD 2; also NQRets}
Set[L2.CQ3, 5];
Set[L2.CQ2, 6]; {0 MOD 2}
Set[L2.CQ1, 7]; {3 MOD 4}


{PFetch Returns}

Set[L2.RS2, 0]; {0 MOD 2}
Set[L2.RS0, 1]; {also PMRead}
Set[L2.SP0, 2]; {2 MOD 4}
Set[L2.SP1, 3]; {3 MOD 4; tied to L2.SP0}
Set[L2.LP5, 4];
Set[L2.DQ5, 5];
Set[L2.MW1, 6]; {also PRead, PWrite, QRead}
Set[L2.TS1, 7];
Set[L2.SPP, 8];
Set[L2.EF0, 9];
Set[L2.LP6, 0A];


{PWrite Returns}

Set[L2.WH1, 0];
Set[L2.DQ0, 7]; {3 MOD 4; also QRead}
Set[L2.AAS1, 9];
Set[L2.LP1, 0A]; {also PRead}
Set[L2.NQ4, 4];
Set[L2.SP2, 5];
Set[L2.MW2, 6]; {also PRead, QRead}
Set[L2.PSS0, 2];
Set[L2.PSS1, 8];
Set[L2.SP3, 1]; {1 MOD 4; paired with L2.ASS0}
Set[L2.AAS0, 3]; {3 MOD 4; contains SP1}
Set[L2.LP3, 0B];
Set[L2.FS1, 0C];
Set[L2.FreeState, 0D];{0F, paired with L2.FS0}
Set[L2.FS0, 0F];{0F, paired with FreeState}


{QRead Returns}

Set[L2.ME0, 4]; {also QWrite}
Set[L2.DQ0, 7]; {3 MOD 4; also PWrite}
Set[L2.MR0, 3];
Set[L2.CQ0, 1];
Set[L2.MR4, 0]; {also L2.Trap}
Set[L2.EM0, 5];
Set[L2.MW2, 6]; {also PRead, PWrite}
Set[L2.NQ0, 2]; {also PRead}
Set[L2.BC0, 8];
Set[L2.RQ0, 9];
Set[L2.F0, 0A];


{QWrite Returns}

Set[L2.ME0, 4]; {also QRead}
Set[L2.MR1, 1]; {also PRead}
Set[L2.DQ4, 2]; {0 MOD 2; DQm; paired with DQl}
{DQl has 3}
Set[L2.NQ2, 0];
Set[L2.MW3, 5]; {1 MOD 2}
Set[L2.NQ8, 6];
Set[L2.EM1, 7]; {3 MOD 4}
Set[L2.INT2, 8];
Set[L2.CQ4, 9]; {1 MOD 2}


{Requeue Returns}

Set[rhT.PT, 0]; {Must be zero}
Set[rhT.BC, 1];
Set[rhT.IntNN, 2];
Set[rhT.TS, 3];
{4 contains EMa}
Set[rhT.EM, 5]; {paired with EMa}
Set[rhT.Fault, 6];
Set[rhT.FaultNN, 7];


{*****************************************************************************
Monitor Entry
*****************************************************************************}

@ME:	T ← STK, push, L2←0,					c1, opcode[361'b];
	rhTT ← TOS LRot0, STK ← TOS,					c2;
MEf:	UvQ1Hi ← TOS, pop,						c3;
	
	Map ← [rhTT, T], L1←L1.Push, TT ← Monitor.lock,			c1;
	UvQ2 ← T, L0←L0.ME,						c2;
	rhRx ← Rx ← MD, XDirtyDisp, pop,				c3;
	
	MAR ← [rhRx, T+0], BRANCH[MEa, MEb, 1],		c1, WLMFRet[L0.ME];
MEb:	TOS ← 1, L2Disp,						c2;
	Q ← MD or TT, XLDisp, BRANCH[MEc, MXa],				c3;
	
MEc:	MAR ← [rhRx, T+0], BRANCH[MEe, MEd, 2],				c1;
MEe:	MDR ← Q, IBDisp,						c2;
MEg:	PC ← PC + PC16, DISPNI[OpTable],				c3;

MEa:	Q ← T, GOTO[WLMapFix],						c2;
MEd:	Rx ← pME, pop, GOTO[Long1b],					c2;
	
{*****************************************************************************
Monitor Exit
*****************************************************************************}

@MX:	T ← STK, push, L2←1,					c1, opcode[362'b];
	rhTT ← TOS LRot0, STK ← TOS, GOTO[MEf],				c2;
	
MXa:	MAR ← [rhRx, T+0], CANCELBR[$,3],				c1;
	MDR ← Q and ~Monitor.lock,					c2;
	[] ← Q and uPMask, ZeroBr,					c3;

	BRANCH[MXb, MXc],						c1;
MXc:	PC ← PC + PC16, IBDisp, GOTO[SLa],				c2;
MXb:	Rx ← pMX, pop, GOTO[Long1b],					c2;
	


{*****************************************************************************
Opcodes
*****************************************************************************}
@MW:	Rx ← pMW, GOTO[Long2],				c1, at[2,10,ESC0n];
@MR:	Rx ← pMR, push, GOTO[Long2],			c1, at[3,10,ESC0n];
@NC:	Rx ← pNC, push, GOTO[Long1],			c1, at[4,10,ESC0n];
@BC:	Rx ← pBC, push, GOTO[Long1],			c1, at[5,10,ESC0n];
@REQ:	Rx ← pREQ, GOTO[Long2],				c1, at[6,10,ESC0n];
@SPP:	Rx ← pSPP, GOTO[Long1a],			c1, at[0F,10,ESC0n];

Long2:	T ← STK, pop, L0←0,						c2;
	UvQ2Hi ← T, L0Disp, GOTO[Long2a],				c3;

Long2a:	T ← STK, pop, BRANCH[Long2b, Long1a],				c1;
Long2b:	UvQ2 ← T,							c2;
	TT ← 2,								c3;

	uStkDepth ← TT,							c1;
Long1:	T ← STK, pop, L0←1,						c2;
	UvQ1Hi ← T, L0Disp, GOTO[Long2a],				c3;

Long1a:	PC ← PC - 1, pop,						c2;
Long1b:	UvQ1 ← T							c3;

	rhT ← rhT.PT,							c1;
SaveRegs:
	UrL ← L,							c2;
	UrG ← G, G ← rhG,						c3;

	UrGHi ← G,							c1;
	UrPC ← PC, PC ← rhPC,						c2;
	UrPCHi ← PC,							c3;

	L0←L0.SrcOK, G ← PDA.lastCV{for interrupts},			c1;
	uPFlags ← Rx, YDisp, L3←L3.Normal,				c2;
	rhPC ← PDAHi, DISP4[Enter],					c3;

PRestart:
	uFaultParm0 ← G,						c3;

	stackP ← uStkDepth,						c1;
	TOS ← pFault,							c2;
	TT ← uPFlags, XDisp, push,					c3;

	G ← rhG, L2Disp, push, BRANCH[PFa, PFb, 7],			c1;
PFa:	uFaultParm1 ← G, BRANCH[PTrap, PFault],				c2;
PFb:	uFaultParm1 ← G, push, BRANCH[PTrap, PFault],			c2;
PTrap:	uPFlags ← Rx, GOTO[PTail1],					c3;
PFault:	uPFlags ← TOS, GOTO[Fault],					c3;


{*****************************************************************************
Monitor Entry opcode
    Entry:
	UvQ1Hi,,UvQ1 hold virtual address of monitor lock to be entered
    Exit:
*****************************************************************************}
Enter:	uStkDepth ← 0,					c1, at[pMELoc,10,Enter];
	PC ← uPSB,							c2;
EnterFailed:
	L ← UvQ1Hi, L2←L2.EF0{PFRets},					c3;

EFa:	Map ← Q ← [rhPC, PC+PSB.link],					c1;
	rhG ← PDAHi, G ← PDA.ready, CALL[PFetch3],			c2;
	Rx ← MD,						c3, PFr[L2.EF0];

	MAR ← [rhTT, PC+PSB.link],					c1;
	MDR ← Rx or PSB.link.enterfailed, L2←L2.DQ0{QRRets},		c2;
CallDQ:	UvQ2Hi ← L, CALL[QRead1],					c3;

{*****************************************************************************
Monitor ReEnter opcode 
    Entry:
	UvQ1Hi,,UvQ1 hold virtual address of monitor lock to be entered
	UvQ2Hi,,UvQ2 hold virtual address of condition variable just left
    Exit:
*****************************************************************************}
ReEnter:	G ← UvQ1, L2←L2.MR0{QRRets},		c1, at[pMR,10,Enter];
	CALL[Q1Read3],							c2;

	PC ← uPSB, BRANCH[MRa, MRb, 2],				c1, QRr[L2.MR0];

MRb:	UvQ2 ← G, GOTO[EnterFailed],					c2;

MRa:	G ← UvQ2,							c2;
	rhG ← UvQ2Hi,							c3;

	Map ← [rhG, G], L2←L2.CQ0{QRRets},				c1;
	TOS ← T, CALL[QRead3],						c2;
	PC ← uPSB,						c3, CQr[pMR];

	Map ← Q ← [rhPC, PC or PSB.flags], L2←L2.MR3{PRRets},		c1;
	Rx ← uPMask, CALL[PRead3],					c2;

	MAR ← [rhTT, PC+PSB.flags], L2←L2.MR4{QRRets},		c1, PRr[L2.MR3];
	MDR ← Ybus ← T and ~Rx, YDisp, CANCELBR[$,0],			c2;
MRe:	rhG ← UvQ1Hi, BRANCH[MRc, MRd, 0E],				c3;

MRc:	Map ← [rhG, G], L2←L2.MR1{QWRets},				c1; {write locked monitor}
	T ← TOS or Monitor.lock, push, CALL[QWrite3],			c2;
	TOS ← 1, push,	c3, QWr[L2.MR1];

	STK ← TOS, pop, GOTO[PTail2]{L not used},			c1;

MRd:	Rx ← pTrap, CALL[Q2Read2],					c1;

	[] ← T and Condition.abortable, NZeroBr, CANCELBR[$,3],	c1, QRr[L2.MR4];
	G ← UvQ1, BRANCH[MRe, PRestart],				c2;


{*****************************************************************************
Monitor Exit and Depart opcode 
    Entry:
	UvQ1Hi,,UvQ1 hold virtual address of monitor lock to be exited
    Exit:
*****************************************************************************}
Depart:	G ← UvQ1, L2←L2.EM0{QRRets},			c1, at[pMXLoc,10,Enter];
	uStkDepth ← 0, CALL[Q1Read3],					c2;

MXx:	L ← UrL, GOTO[PTail2],						c1;


{*****************************************************************************
Exit Monitor Subroutine 
   Entry:
	rhG,,G hold virtual address of monitor lock to be exited
	T has monitor lock
    Exit:
*****************************************************************************}
ExitMonitor:
	Map ← [rhG, G], L2←L2.EM1{QWRets}, CANCELBR[$,3],	c1, QRr[L2.EM0];
	T ← T and ~Monitor.lock, CALL[QWrite3],				c2;
	T ← T and Q, ZeroBr, rhT ← rhT.EM{NQRets},		c3, QWr[L2.EM1];

	Map ← Q ← [rhPC, T+PSB.link], L2←L2.EM2{PMRets}, BRANCH[EMa, EMb],	c1;
EMa:	UvQ2 ← PDA.ready, CALL[PMRead3],				c2;

	L ← PDAHi,						c1, PMRr[L2.EM2];
	PC ← T, L2←L2.DQ0{QRRets}, CALL[CallDQ],			c2;

EMb:	Xbus ← uPFlags, XLDisp,					c2, NQr[rhT.EM];
	PC ← uPSB, BRANCH[MXx, MWa, 2],					c3;


{*****************************************************************************
Monitor Exit and Wait opcode 
    Entry:
	UvQ1Hi,,UvQ1 hold virtual address of monitor lock to be exited
	UvQ2Hi,,UvQ2 hold virtual address of condition on which to wait
	TOS holds timeout value
    Exit:
*****************************************************************************}
Wait:	uTicks ← TOS, L2←L2.CQ0{QRRets}, CALL[CleanSecond],	c1, at[pMW,10,Enter];

	rhG ← UvQ1Hi,						c3, CQr[pMW];

	Rx ← UvQ2,							c1;
	UvQTemp ← Rx,							c2;
	Rx ← UvQ2Hi,							c3;

	Map ← [rhG, G], L2←L2.EM0{QRRets},				c1;
	UvQTempHi ← Rx, CALL[QRead3],					c2;

MWa:	rhG ← G ← UvQTempHi,						c1;
	UvQ2Hi ← G,							c2;
	G ← UvQTemp, L2←L2.MW2{QRRets, PFRets},				c3;

	Map ← UvQ2 ← [rhG, G], CALL[QRead2],				c1;

	Map ← Q ← [rhPC, PC or PSB.flags], CANCELBR[PFetch2,3],	c1, QRr[L2.MW2];
	TOS ← MD, XLDisp,					c3, PFr[L2.MW2];

	[] ← T and Condition.abortable, ZeroBr, BRANCH[MWb, MWc, 2],	c1;
MWb:	Rx ← uPTC, CANCELBR[MWe, 1],					c2;
MWc:	Rx ← uPTC, BRANCH[MWd, MWe],					c2;
MWd:	GOTO[PTail1],							c3;
MWe:	Xbus ← T LRot0, XLDisp,						c3;

	L ← uTicks, ZeroBr, BRANCH[MWNoWW, MWWW, 2],			c1;
MWNoWW:	G ← PDA.ready, BRANCH[MWMakeTime, MWHaveTime],			c2;
MWHaveTime:
	Xbus ← 0, XDisp, GOTO[MWWriteTime],				c3;
MWMakeTime:
	L ← L + Rx, ZeroBr,						c3;

MWWriteTime:
	MAR ← [rhTT, PC + PSB.timeout], BRANCH[MWOK, MWInc],		c1;
MWOK:	MDR ← L, T ← 0+0+1, rhT←rhT.PT, CANCELBR[MWf,0],		c2;
MWInc:	MDR ← T ← 0+0+1, rhT←rhT.PT, CANCELBR[MWf,0],			c2;
MWf:	UvQ1Hi ← T, L2←L2.DQ0{QRRets},					c3;

	MAR ← [rhTT, PC + PSB.flags],					c1;
	MDR ← TOS or PSB.flags.waiting, CANCELBR[Q1Read3,0],		c2;

MWWW:	L2←L2.MW3{QWRets}, CANCELBR[$,1],				c2;
	T ← T and ~Condition.wakeup, CALL[QWrite1],			c3;

	GOTO[PTail1],						c3, QWr[L2.MW3];


{*****************************************************************************
Notify opcode 
    Entry:
	UvQ1Hi,,UvQ1 hold virtual address of condition to be notified
    Exit:
*****************************************************************************}
Notify:	uStkDepth ← 0, L2←L2.CQ0{QRRets}, CALL[CleanFirst],	c1, at[pNC,10,Enter];

	T ← T and Q, ZeroBr, L2←L2.WH0{PMRRets},		c3, CQr[pNC];

	Map ← Q ← [rhPC, T+PSB.link], BRANCH[NCa, NCb],			c1;
NCa:	L ← PDAHi, CALL[PMRead3],					c2;
NCb:	TT ← uPFlags, GOTO[PTail3], {L not used}			c2;


{*****************************************************************************
Broadcast opcode 
    Entry:
	UvQ1Hi,,UvQ1 hold virtual address of condition to be broadcast
    Exit:
*****************************************************************************}
BCast:	uStkDepth ← 0, L2←L2.CQ0{QRRets}, CALL[CleanFirst],	c1, at[pBC,10,Enter];

BCe:	rhT ← rhT.BC{NQRets}, T ← T and Q, ZeroBr,		c3, CQr[pBC];

BCd:	Map ← Q ← [rhPC, T+PSB.link], L2←L2.WH0{PMRRets}, BRANCH[BCa, BCb],	c1;
BCa:	L ← PDAHi, CALL[PMRead3],					c2;
BCb:	rhT ← rhT.PT, GOTO[MWd],					c2;

BCc:	G ← UvQ1, L2←L2.BC0{QRRets},				c2, NQr[rhT.BC];
	rhG ← UvQ1Hi, CALL[QRead1],					c3;

	CANCELBR[$,3],						c1, QRr[L2.BC0];
	GOTO[BCe],							c2;


{*****************************************************************************
WakeHead subroutine 
    Entry:	rhG, G contains virtual address of condition to wake
	T contains queue.tail.link
	L has PDAHi
    Exit:
*****************************************************************************}
WakeHead:
	Map ← Q ← [rhPC, T or PSB.timeout], L2←L2.WH1{PWRets},	c1, PMRr[L2.WH0];
	T ← 0, UvQ2 ← PDA.ready, CALL[PWrite3],				c2;
	PC ← Q - PSB.timeout, L2←L2.WH2{PRRets},		c3, PWr[L2.WH1];

	Map ← Q ← [rhPC, PC or PSB.flags], CALL[PRead2],		c1;

	MAR ← [rhTT, PC+PSB.flags],				c1, PRr[L2.WH2];
	MDR ← T and ~PSB.flags.waiting, L2←L2.DQ0{QRRets}, CANCELBR[CallDQ,0],	c2;


{*****************************************************************************
Requeue opcode 
    Entry:
	UvQ1Hi,,UvQ1 hold virtual address of source queue
	UvQ2Hi,,UvQ2 hold virtual address of destination queue
	TOS has process
    Exit:
*****************************************************************************}
Requeue:
	PC ← TOS, L2←L2.RQ0{QRRets}, CALL[Q2Read2],		c1, at[pREQ,10,Enter];

	G ← UvQ1, L2←L2.DQ0{QRRets}, CANCELBR[$,3],		c1, QRr[L2.RQ0];
	rhG ← UvQ1Hi, [] ← G or UvQ1Hi, ZeroBr,				c2;
	L0←L0.SrcOK, BRANCH[QRead1, RQa],				c3;

RQa:	Map ← Q ← [rhPC, PC+PSB.link], L2←L2.DQ1{PMRRets}, GOTO[DQx],	c1;


 
{*****************************************************************************
Set Process Priority opcode 
    Entry:
	TOS has priority
    Exit:
*****************************************************************************}
SetPP:	TOS ← LRot1 TOS and 7, L2←L2.SPP{PFRets},		c1, at[pSPP,10,Enter];
	Rx ← ~uPPMask,							c2;
	PC ← uPSB, GOTO[EFa],						c3;

	Rx ← Rx and MD,						c3, PFr[L2.SPP];

	UvQ2 ← PDA.ready,						c1;
	L ← PDAHi,							c2;
	TOS ← TOS LRot12,						c3;

	MAR ← [rhTT, PC+PSB.link],					c1;
	MDR ← TOS or Rx, L2←L2.DQ0{QRRets}, GOTO[CallDQ],		c2;

{*****************************************************************************
Dequeue subroutine: 
    Entry:
	rhT # 0 => src = NIL
	UvQ1Hi,,UvQ1 has src
	PC has process
    Exit:
	Returns to NQ

    Register Usage
	PC = process
	T = temp
	TOS = prev
	Rx has queue
	UvLPhigh has psb.link
*****************************************************************************}
Dequeue:
	Map ← Q ← [rhPC, PC+PSB.link], L2←L2.DQ1{PMRRets}, CANCELBR[$, 3],	c1, QRr[L2.DQ0];
DQx:	Rx ← T, CALL[PMRead3],						c2;

	TOS ← uPFlags,						c1, PMRr[L2.DQ1];
	TOS ← TOS or cRequeueFlag,					c2;
	uPFlags ← TOS, L0Disp,						c3;

	[] ← T - PC, ZeroBr, BRANCH[DQa, DQb]				c1;

DQa:	TOS ← 0, uPsbLink ← T, BRANCH[DQc, DQd],			c2;{src#NIL}
DQb:	TOS ← 0, uPsbLink ← T, BRANCH[DQe, DQf],			c2;{src=NIL}

DQc:	TOS ← Rx and uPMask2, GOTO[DQg],			c3;{link.next#psb}
DQd:	T ← Rx and uPMask2, GOTO[DQj],				c3;{link.next=psb}

DQe:	TOS ← PC, GOTO[DQg],					c3;{link.next#psb}
DQf:	GOTO[DQk],						c3;{link.next=psb}

DQg:	Map ← Q ← [rhPC, TOS+PSB.link], L2←L2.DQ2{PRRets},		c1;
DQgh:	TOS ← Q, CALL[PRead3],						c2;

	Q ← T and uPMask,					c1, PRr[L2.DQ2];
	[] ← Q - PC, ZeroBr,						c2;
	T ← T and ~uPMask, BRANCH[DQh, DQi],				c3;

DQh:	Map ← Q ← [rhPC, Q+PSB.link], L2←L2.DQ2{PRRets}, GOTO[DQgh],	c1;

DQi:	MAR ← [rhTT, TOS+PSB.link],					c1;
	MDR ← T or uPsbLink, L0Disp,					c2;
	T ← Rx and uPMask2, BRANCH[DQj, DQk],				c3;

DQj:	[] ← T - PC, ZeroBr,						c1;
	T ← Rx and ~uPMask2, BRANCH[DQm, DQl],				c2;
DQl:	T ← TOS or T, L2←L2.DQ4{QWRets},				c3;

	Map ← [rhG, G], CALL[QWrite2],					c1;	

DQk:	Map ← Q ← [rhPC, PC or PSB.flags], L2←L2.DQ5{PFRets},		c1;
	T ← ~uPMask, CALL[PFetch3],					c2;
	T ← MD and T,							c3, PFr[L2.DQ5];

	MAR ← [rhTT, PC+PSB.flags],					c1;
	MDR ← T or uPsbLink, CANCELBR[$,0],				c2;
DQm:	G ← UvQ2, MesaIntBr, GOTO[Enqueue],			c3, QWr[L2.DQ4];


{*****************************************************************************
Enqueue subroutine: 
    Entry:
	UvQ2Hi,,UvQ2 has dst
	PC has process
	rhT has return
    Exit:
    Register Usage
	L has process.priority
	T = temp
	TOS = prev
	Rx = queue, prev
*****************************************************************************}
Enqueue:
	Map ← Q ← [rhPC, PC+PSB.link], L2←L2.NQ0{QRRets, PRRets}, BRANCH[$, EnqueueInt], c1;
	Rx ← uPPMask, CALL[PRead3],					c2;

	UreturnPC ← T,						c1, PRr[L2.NQ0];
	L ← T and uPPMask, CALL[Q2Read3],				c2;

	Q ← T and uPMask, ZeroBr, CANCELBR[$,3],		c1, QRr[L2.NQ0];
	T ← T and ~uPMask, BRANCH[NQb, NQc],				c2;

NQc:	T ←  T or PC, L2←L2.NQ8{QWRets},				c3;

	Map ← [rhG, G],							c1;
	Q ← ~uPMask, CALL[QWrite3],					c2;
	T ← Q and UreturnPC, L2←L2.NQ4{PWRets},			c3, QWr[L2.NQ8];

	Map ← Q ← [rhPC, PC+PSB.link],					c1;
	T ← T or PC, CALL[PWrite3],					c2;

NQb:	TOS ← Q, uTemp ← T, L2←L2.NQ1{PRRets},				c3;

	Map ← Q ← [rhPC, TOS+PSB.link],					c1;
	uPsbLink ← T or PC, CALL[PRead3],				c2;

	Rx ← T and Rx, uT ← T,				c1, PRr[L2.NQ1];
	[] ← Rx - L, CarryBr, L2←L2.NQ3{PRRets},			c2;
NQi:	Rx ← T and uPMask, BRANCH[NQd, NQe],				c3;

NQe:	Map ← [rhG, G], L2←L2.NQ2{QWRets},				c1;
	T ← uPsbLink, CALL[QWrite3],					c2;
	Q ← ~uPMask, GOTO[NQg],					c3, QWr[L2.NQ2];

NQd:	Map ← Q ← [rhPC, Rx+PSB.link], CALL[PRead2],			c1;

	TT ← T and uPPMask,					c1, PRr[L2.NQ3];
	[] ← L - TT - 1, CarryBr,					c2;
	Q ← ~uPMask, BRANCH[NQf, NQg],					c3;

NQf:	TOS ← Rx,							c1;
	uT ← T, GOTO[NQi],						c2;

NQg:	Map ← [rhPC, PC+PSB.link],					c1;
	T ← Q and UreturnPC,						c2;
	TT ← rhTT ← MD,							c3;

	MAR ← [rhTT, PC+PSB.link],					c1;
	MDR ← T or Rx,							c2;
	T ← Q and uT, L2←L2.NQ4{PWRets},				c3;

	Map ← Q ← [rhPC, TOS+PSB.link],					c1;
	T ← T or PC, CALL[PWrite3],					c2;
	Xbus ← rhT, XDisp,					c3, PWr[L2.NQ4];

NQRet:	L ← UrL, DISP2[NQRets],						c1;


{*****************************************************************************
Reschedule 
    Entry:
	uPFlags.0: reSchedulePending BOOLEAN
	uPFlags.1..3: 0: Opcode, 2: Trap, 4: Interrupt, 7: Idle,
		5: Fault, 6: FaultNoPC
    Exit:
    Register Usage
*****************************************************************************}

PTail1:	L ← UrL,							c1;
PTail2:	TT ← uPFlags,						c2, NQr[rhT.PT];
PTail3:	G ← UrG, L0←L0.JRemap,						c3;

	rhG ← UrGHi,							c1;
	PC ← UrPC, L2←L2.RSSpc, 					c2;
	rhRx ← TT LRot12, XDisp,					c3;

PTNormal:
	TT ← UvPCpage, DISP4[PEnd],					c1;
PEnd:	PC ← PC + 1, IBDisp, GOTO[PDispNI],			c2, at[0,10];
	PC ← PC + PC16, IBDisp, GOTO[PDispNI],			c2, at[1,10,PEnd];
	T ← sProcessTrap, GOTO[Trapc3],				c2, at[2,10,PEnd];
	{not possible,						c2, at[3,10,PEnd]};
	[] ← PC - 1, PgCrOvDisp, push, L1←L1.Refill, GOTO[PInt],	c2, at[4,10,PEnd];
	{not possible to have fault but no requeue,		c2, at[5,10,PEnd]};
	{not possible to have fault but no requeue,		c2, at[6,10,PEnd];}
	GOTO[SPIdle], {was in idle loop}			c2, at[7,10,PEnd];
	L1 ← 2, GOTO[StashPC2],					c2, at[8,10,PEnd];
	L1 ← 1, GOTO[StashPC1],					c2, at[9,10,PEnd];
	T ← sProcessTrap, GOTO[Trapc3],				c2, at[0A,10,PEnd];
	{not possible,						c2, at[0B,10,PEnd]};
	[] ← PC - 1, PgCrOvDisp, push, L1←L1.Refill, GOTO[PInt],	c2, at[0C,10,PEnd];
	L1 ← 0, GOTO[StashPC0],					c2, at[0D,10,PEnd];
	MesaIntBr, GOTO[Reschedule],				c2, at[0E,10,PEnd];
	GOTO[SPIdle], {was in idle loop}			c2, at[0F,10,PEnd];

PDispNI:
	rhPC ← UrPCHi, DISPNI[OpTable],					c3;

Reschedule:	PC ← uPSB, L3Disp, BRANCH[SaveProcess, RescheduleInt],	c3, SPCr[L2.RSSpc];

PInt:	TOS ← STK, pop, BRANCH[PInta, PIntb, 1],			c3;

PInta:	Xbus ← rhRx, XDisp, Q ← 0, L2←L2.Pop0IncrX,			c1;
PIntc:	T ← PC, BRANCH[PIntd, PInte, 7],				c2;
PIntd:	rhTT ← UvChigh, GOTO[RReMap],					c3;
PInte:	Q ← UvC, L1←0,							c3;

	L2←L2.RSSpc, GOTO[StashPCa1],					c1;

PIntb:	TT ← 30,							c1;
	Ybus ← ~ErrnIBnStkp and TT, ZeroBr,				c2;
	TT ← UvPCpage, BRANCH[PIntf, PIntg],				c3;

PIntf:	Xbus ← rhRx, XDisp, Q ← 0, L2←L2.Pop0IncrX, GOTO[PIntc],	c1;
PIntg:	TT ← TT + 0FF + 1,						c1;
	push, GOTO[PInt],						c2;


SPIdle:	G ← PDA.lastCV{for interrupts}, L2←L2.RS0{PMRRets, PFRets},	c3;

SPRet:	Map ← Q ← [rhPC, PDA.ready], CALL[PMRead2],			c1;

	Map ← Q ← [rhPC, T+PSB.link], ZeroBr,			c1, PMRr[L2.RS0];
	UreturnPC ← T, BRANCH[PFetch3, BusyWaita],			c2;
	PC ← MD and Q, L2←L2.RS2{PFRets},			c3, PFr[L2.RS0];

PRSe:	Map ← Q ← [rhPC, PC{+PSB.link}], uPSB ← PC, CALL[PFetch2],	c1;
	T ← MD, XDisp,						c3, PFr[L2.RS2];

	uPsbLink ← T, L1 ← 0C, DISP4[PRSa, 0C],			c1;
PRSa:	T ← RRot1 T and uPPMask, GOTO[PRSb],		c2, at[0C,10,PRSa];
	GOTO[PRSc],					c2, at[0D,10,PRSa];
	GOTO[PRSc],					c2, at[0E,10,PRSa];
	GOTO[PRSc],					c2, at[0F,10,PRSa];

PRSb:	T ← T LRot4, L2←L2.RS3{PRRets},					c3;

	Map ← Q ← [rhPC, PDA.state or T], CALL[PRead2],			c1;

	[] ← T, ZeroBr, L2←L2.RS2{PFRets},			c1, PRr[L2.RS3];
	[] ← UreturnPC xor PC, ZeroBr, BRANCH[PRSc, PRSd],		c2;
	
PRSc:	MesaIntBr, CANCELBR[LoadProcess,1],				c3;
PRSd:	PC ← uPsbLink and Q, BRANCH[PRSe, BusyWaitb],			c3;

BusyWaita:	Noop,							c3;

BusyWaitb:	T ← pIdle,						c1;
	[] ← uWDC, NZeroBr,						c2;
IdleLoop:	uPFlags ← T, MesaIntBr, BRANCH[$, WakeError],		c3;

IdleLoopBranch:
	Rx ← uWP, BRANCH[NoInt, IdleInt {InterruptsDicentra}],		c1;
NoInt:	GOTO[IdleLoop],							c2;

WakeError:	T ← sRescheduleError, CANCELBR[$, 1],			c1;
	GOTO[TrapGo],							c2;


{*****************************************************************************
SaveProcess subroutine
    Entry:
	L3 has preemption booleon: 0 => FALSE, 1 => TRUE
    Exit:
    Register Usage
*****************************************************************************}

SaveProcess:
	Map←Q←[rhPC,PC+PSB.link], BRANCH[SPa,SPb,2], L2←L2.SP0{PFRets},	c1;
SPa:	TOS ← ~PSB.link.preempted, CALL[PFetch3],			c2;
SPb:	TOS ← PSB.link.preempted, CALL[PFetch3],			c2;
	T ← MD and TOS, XDisp, GOTO[SPd],			c3, PFr[L2.SP0];
	T ← MD or TOS, XDisp, GOTO[SPc],			c3, PFr[L2.SP1];

SPc:	MAR ← [rhTT, PC+PSB.context], BRANCH[SPe, SPf, 0D],		c1;
SPe:	TT ← RRot1 T and uPPMask, CANCELBR[$,0],			c2;
	TT ← TT LRot4, GOTO[AllocSV],					c3;

SPf:	G ← ~ErrnIBnStkp, CANCELBR[$,0], L2←1,				c2;
	TOS ← MD, uPsbLink ← T, GOTO[DSKg],				c3;

SPd:	MAR ← [rhTT, PC+PSB.context], BRANCH[SPi, SPh, 0D],		c1;
SPh:	uPsbLink ← T, CANCELBR[$,0],					c2;
	TOS ← MD,							c3;

	GOTO[PSSe],							c1;

SPi:	MDR ← UvL, CANCELBR[$,0],					c2;
	uPsbLink ← T, GOTO[SPj],					c3;

PSSRet:	T ← TOS, L2←L2.SP2{PWRets},				c3, PWr[L2.SP3];

SPg:	Map ← Q ← [rhPC, PC or PSB.context], CALL[PWrite2],		c1;
	Noop,							c3, PWr[L2.SP2];

SPj:	MAR ← [rhTT, PC+PSB.link],					c1;
	MDR ← uPsbLink, GOTO[SPIdle],					c2;

{*****************************************************************************
AllocAndSave subroutine
    Entry:	T has priority
    Exit:	TOS has state
    Register Usage
	T, Q, rhRx, Rx, TOS, uTemp
*****************************************************************************}

AllocSV:
	Map ← Q ← [rhPC, PDA.state or TT], L2←L2.AS0{PRRets},		c1;
	uTemp ← Q,							c2;
	rhTT ← TT ← MD, uPsbLink ← T, CALL[PR],				c3;

	Map ← Q ← [rhPC, T],					c1, PRr[L2.AS0];
	TOS ← Q,							c2;
	rhRx ← Rx ← MD,							c3;

	MAR ← [rhRx, T+0],						c1;
	T ← uTemp,							c2;
	Rx ← MD,							c3;

	MAR ← [rhTT, T+0],						c1;
	MDR ← Rx,							c2;
	G ← ~ErrnIBnStkp, L2←1, GOTO[DSKg],				c3;

PSSf:	G ← 0F and G,							c1;
	T ← G or T,							c2;
	Q ← State.word, L2←L2.PSS0{PWRets},				c3;

	Map ← Q ← [rhPC, TOS + Q], CALL[PWrite2],			c1;
	T ← G + 4, NibCarryBr,					c3, PWr[L2.PSS0];

	Q ← Q - State.word, BRANCH[PSSa, PSSb],				c1;
PSSa:	stackP ← G ← G + 2, GOTO[PSSc],					c2;
PSSb:	stackP ← G ← 0E, GOTO[PSSc],					c2;
PSSc:	Q ← Q + G, push, L2←L2.PSS1,					c3;

PSSg:	Map ← Q ← [rhPC, Q - 1], BRANCH[PSSd, PSSe],			c1;
PSSd:	T ← STK, pop, CALL[PWrite3],					c2;
	G ← G - 1, ZeroBr, GOTO[PSSg],				c3, PWr[L2.PSS1];

PSSe:	T ← UvL, L3Disp,						c2;
	Q ← TOS+State.frame, L2←L2.SP3{PWRets}, BRANCH[AASa, AASb, 1],	c3;

AASa:	Map ← Q ← [rhPC, Q], CALL[PWrite2], pop,			c1;
AASb:	Map ← Q ← [rhPC, Q], CALL[PWrite2], pop,			c1;

	T ← uFaultParm0, L2←L2.AAS1{PWRets},			c3, PWr[L2.AAS0];

	Map ← Q ← [rhPC, Q+1], CALL[PWrite2],				c1;
	T ← uFaultParm1, L2←L2.SP3{PWRets},			c3, PWr[L2.AAS1];

	Map ← Q ← [rhPC, Q+1], CALL[PWrite2],				c1;



{*****************************************************************************
LoadProcess subroutine
    Entry:	L has 0
    Exit:	Returns to EFCHaveLink
    Register Usage
*****************************************************************************}

LoadProcess:
	Map ← Q ← [rhPC, PC or PSB.context], BRANCH[$, LoadProcessInt],	c1;
	uPCValid ← 0, L ← 0,						c2;
	rhTT ← TT ← MD,							c3;
	
	MAR ← [rhTT, Q + 0],						c1;
	L1Disp, Q ← ~PSB.link.preempted,				c2;
	TOS ← MD, DISP4[LPa, 0C],					c3;

LPa:	T ← uPsbLink, XDisp, GOTO[LPb],				c1, at[0C,10,LPa];
	MAR ← [rhTT, PC], GOTO[PLS],				c1, at[0D,10,LPa];
	MAR ← [rhTT, PC], GOTO[PLS],				c1, at[0E,10,LPa];
	MAR ← [rhTT, PC], GOTO[PLS],				c1, at[0F,10,LPa];

LPb:	stackP ← 0, rhT ← xtPSwitch, BRANCH[LPd, LPe, 0B],		c2;
LPd:	T ← TOS, GOTO[LPf],						c3;
LPe:	T ← T and ~PSB.link.enterfailed, push,				c3;

	Map ← Q ← [rhPC, PC or PSB.link], push, L2←L2.LP1{PW},		c1;
	STK ← 0, pop, CALL[PWrite3],					c2;
	T ← TOS, GOTO[LPf],					c3, PWr[L2.LP1];

LPx:	TOS ← TOS + State.frame, L2←L2.LP6{PFets},		c3, PWr[L2.FS0];

	Map ← Q ← [rhPC, TOS], CALL[PFetch2],				c1;
	T ← MD,							c3, PFr[L2.LP6];

LPf:	Map ← Q ← [rhPC, PC or PSB.mds], L2←L2.LP5{PF},			c1;
	UvL ← T, CALL[PFetch3],						c2;
	rhMDS ← TOS ← MD, LOOPHOLE[mdok],			c3, PFr[L2.LP5];

	UvMDS ← Q ← TOS,						c1;
	Rx ← XferType.pSwitch, L1←L1.Xfer,				c2;
	uXferType ← Rx, GOTO[XFER],					c3;


{*****************************************************************************
PLoadStack subroutine
    Entry:	T has state.word
	TOS has stack pointer
    Exit:	TOS has state pointer
	G has priority
	Returns to FreeState
    Register Usage
	T, rhTT, TT, Q, Rx, TOS
*****************************************************************************}

PLS:	MDR ← uPsbLink and Q, CANCELBR[$,0],				c2;
	Q ← State.word,							c3;

	Map ← Q ← [rhPC, TOS + Q], L2←L2.PLS0{PR},			c1;
	stackP ← 0, rhT ← xtPSwitch, CALL[PRead3],			c2;

	TT ← T LRot8, STK ← T, push,				c1, PRr[L2.PLS0];
	TT ← TT and 0FF,						c2;
	T ← T + 4, NibCarryBr,						c3;

	UBrkByte ← TT, BRANCH[PLSa, PLSb],				c1;
PLSa:	T ← T and 0F, GOTO[PLSc],					c2;
PLSb:	T ← 10, GOTO[PLSc],						c2;
PLSc:	Rx ← T - 2,							c3;

	Map ← Q ← [rhPC, TOS],						c1;
PLSf:	G ← RRot1 uPsbLink,						c2;
	rhTT ← TT ← MD,							c3;

	MAR ← [rhTT, Q+0],						c1;
	Rx ← Rx - 1, ZeroBr,						c2;
	T ← MD, STK ← T, push, BRANCH[PLSd, PLSe],			c3;

PLSd:	Map ← Q ← [rhPC, Q+1], GOTO[PLSf],				c1;

PLSe:	STK ← T, L1Disp,						c1;
	stackP ← uBlock0, BRANCH[FreeState, LPx, 0D],			c2;


{*****************************************************************************
FreeState subroutine
*****************************************************************************}

FreeState:
	T ← G LRot4,							c3;

	Map ← Q ← [rhPC, PDA.state],					c1;
	Rx ← T and 7,							c2;
	TT ← rhTT ← MD,							c3;

	MAR ← [rhTT, Q + Rx],						c1;
	CANCELBR[$,0], 							c2;
	T ← MD,								c3;

	MAR ← [rhTT, Q + Rx],						c1;
	MDR ← TOS, CANCELBR[$,0], 					c2;
	L2←L2.FS0{PWRets},						c3;

	Map ← Q ← [rhPC, TOS], CALL[PWrite2],				c1;


{*****************************************************************************
Interrupt Handler 
    Entry:
	CALLing sequence has done Rx ← pInt, GOTO[SaveRegs];
    Exit:
    Register Usage
*****************************************************************************}
Interrupt:	Rx ← uWP,					c1, at[pIntLoc,10,Enter];
Interruptx:	uWP ← 0, L3←L3.Interrupt,				c2;
CVLoop:	Rx ← RShift1 Rx, Xbus ← Rx LRot0, XLDisp,			c3;

	uWW ← Rx, NZeroBr, BRANCH[CheckNext, IntThisCV, 2],		c1;
IntThisCV:	Q ← PDA.interrupt + G, CANCELBR[$,1],			c2;
	[] ← G, rhG ← PDAHi, ZeroBr,					c3;

	Map ← UvQ1 ← [rhG, Q], BRANCH[Int, CheckTime],			c1;
Int:	uIntLevel ← G, G ← Q, L2←L2.CQ0{QRRets}, CALL[QRead3],		c2;

	rhT ← rhT.IntNN{NQRets}, Q ← T and Q, ZeroBr,		c3, CQr[pIntLoc];

	Map ← Q ← [rhPC, Q+PSB.link], L2←L2.WH0{PRRets}, BRANCH[INTa, INTb],	c1;
INTa:	L ← PDAHi, L0←L0.SrcOK, CALL[PMRead3], {Do Naked Notify}	c2;
INTb:	L2←L2.INT2{QWRets},						c2;
	T ← T or 1, CALL[QWrite1],					c3;

INTc:	G ← uIntLevel,						c3, QWr[L2.INT2];

	Rx ← uWW, NZeroBr,						c1;
CheckNext:	G ← G - 2, BRANCH[IntDone, CVLoop],			c2;
IntDone:	GOTO[PTail1],						c3;
	
IntDidNN:	GOTO[INTc],					c2, NQr[rhT.IntNN];


{*****************************************************************************
Fault Handler 
    Entry:	T has FaultIndex*2
	parameters stored in uFaultPram0 and uFaultParm1
	CALLing sequence has done Rx ← pFault, GOTO[SaveRegs];
    Exit:
    Register Usage
*****************************************************************************}
Fault:	UvQ2 ← T, L3←L3.Fault,					c1, at[pFault,10,Enter];
	rhG ← G ← PDAHi,						c2;
	UvQ2Hi ← G, G ← PDA.ready,					c3;

	PC ← uPSB, L2←L2.DQ0{QRRets},					c1;
	rhT ← rhT.Fault{NQRets},					c2;
	rhPC ← PDAHi, CALL[QRead1],					c3;

	rhT ← rhT.FaultNN{NQRets},				c2, NQr[rhT.Fault];
	G ← UvQ2, L2←L2.F0{QRRets},					c3;

	Map ← G ← [rhG, G+FaultQueue.condition],			c1;
	UvQ2 ← PDA.ready, CALL[QRead3],					c2;

	Map ← Q ← [rhPC, T and Q], ZeroBr, CANCELBR[$,3],	c1, QRr[L2.F0];
	L ← PDAHi, L2←L2.WH0{PMRRets}, BRANCH[PMRead3, Fb],		c2;
Fb:	PC ← Q or Condition.wakeup,					c3;

	MAR ← [rhTT, G+0],						c1;
	MDR ← PC, T ← uPCValid, NZeroBr,				c2;
Fc:	BRANCH[Fd, Fe],							c3;

Fd:	TT ← pFaultNoPC, GOTO[Ff],					c1;
Fe:	TT ← pFaultPC, GOTO[Ff],					c1;
Ff:	L ← UrL, GOTO[PTail3],						c2;

FaultDidNN:	[] ← uPCValid, NZeroBr, GOTO[Fc],		c2, NQr[rhT.FaultNN];


{*****************************************************************************
Check For Timeouts 
    Entry:
    Exit:
    Register Usage
*****************************************************************************}
CheckTime:	TT ← LShift1 uTickCount, XDisp,				c2;
	uTickCount ← TT, BRANCH[Scan, PTail1, 0B],			c3;

Scan:	L ← uPTC, L0←L0.SrcNull,					c1;
	L ← L + 1,							c2;
	uPTC ← L, L2←L2.TS0{PRRets},					c3;

	Map ← Q ← [rhPC, PDA.count],					c1;
	PC ← StartPSB, CALL[PRead3],					c2;

	T ← T LRot4,						c1, PRr[L2.TS0];
	L ← T + StartPSBMinus1Times2,					c2;
TSe:	uStkDepth ← L, L2←L2.TS2{PRRets},				c3;

	Map ← Q ← [rhPC, PC or PSB.timeout],CALL[PRead2],		c1;

	Q ← T, ZeroBr,						c1, PRr[L2.TS2];
	[] ← Q xor uPTC, NZeroBr, BRANCH[TSa, TSb],			c2;
TSa:	Q ← PC + PC, MesaIntBr, BRANCH[TSc, TSd],			c3;

{Kick this one}
TSc:	MAR ← [rhTT, PC+PSB.timeout], CANCELBR[$, 1]			c1;
	MDR ← 0, rhT ← rhT.TS{NQRets}, CANCELBR[$,0],			c2;
	G ← PDAHi, L2←L2.TS1{PFRets},					c3;
	
	MAR ← [rhTT, PC + PSB.flags],					c1;
	CANCELBR[$,0],							c2;
	T ← MD, UvQ2Hi ← G,						c3;

	MAR ← [rhTT, PC + PSB.flags],					c1;
	MDR ← T and ~PSB.flags.waiting, CANCELBR[$,0],			c2;
	UvQ2 ← PDA.ready, GOTO[Dequeue],				c3;

	L ← uStkDepth,						c2, NQr[rhT.TS];
TSb:	Q ← PC + PC, MesaIntBr, CANCELBR[TSd, 1],			c3;

{ScanInt smashes lots of registers...}
TSd:	[] ← Q xor uStkDepth, ZeroBr, BRANCH[$, ScanInt{InterruptsDicentra}], c1;
	PC ← PC + PSB.SIZE, BRANCH[TSe, TSf],				c2;
TSf:	uTickCount ← L xor ~L,						c3;

	[] ← uWP, NZeroBr,						c1;
	G ← PDA.lastCV, BRANCH[$, IntDuringScan],			c2;
	GOTO[PTail1],							c3;
	
IntDuringScan:
	GOTO[Interrupt],						c3;



{*****************************************************************************
CleanupQueue subroutine 
    Entry:
	calling instruction in c1
	L2 holds L2.CQ0{QRRets}
	returns to uPFlags
    Exit:
	T holds condition queue
	G holds UvQ1	
    Register Usage
	PC = process
	T = cleanup or link
	Rx = head of queue
	UreturnPC = condition and ~uPMask
	MUST NOT USE L or TOS
*****************************************************************************}

CleanFirst:	G ← UvQ1, CALL[Q1Read3],				c2;
CleanSecond:
	G ← UvQ2, CALL[Q2Read3],					c2;

	PC ← T and Q, ZeroBr, rhPC ← PDAHi, CANCELBR[$,3],	c1, QRr[L2.CQ0];
	T ← T and ~uPMask, BRANCH[CQNE, CQEmpty],			c2;
CQNE:	T ← T and ~Condition.wakeup, L2←L2.CQ1{PMRRets},					c3;

	Map ← Q ← [rhPC, PC or PSB.flags],				c1;
	UreturnPC ← T, CALL[PMRead3],					c2;

	[] ← T, ZeroBr, L2←L2.CQ4{QWRets},			c1, PMRr[L2.CQ1];
CQLoop1:	[] ← T - PC, ZeroBr, BRANCH[$, CQClean],					c2;
	[] ← T, ZeroBr, BRANCH[$, CQMakeEmpty],				c3;

	Map ← Q ← [rhPC, T or PSB.flags], L2←L2.CQ2{PMRRets}, BRANCH[$, CQHead],	c1;
	PC ← T, CALL[PMRead3],						c2;

	L2←L2.CQ4{QWRets}, GOTO[CQLoop1],			c1, PMRr[L2.CQ2];

CQHead:	Rx ← PC,							c2;
	L2←L2.CQ3{PMRRets},						c3;

CQLoop2:	Map ← Q ← [rhPC, PC], CALL[PMRead2],			c1;

	[] ← T - Rx, ZeroBr, L2←L2.CQ4{QWRets},			c1, PMRr[L2.CQ3];
	BRANCH[$, CQFoundTail],						c2;
	PC ← T, L2←L2.CQ3{PMRRets}, GOTO[CQLoop2],			c3;

CQFoundTail:
	T ← UreturnPC or PC, CALL[QWrite1],				c3;

CQMakeEmpty:
	Map ← [rhG, G], CANCELBR[$,1],					c1;
	T ← UreturnPC, CALL[QWrite3],					c2;
CQClean:	T ← PC, CANCELBR[CQRet,1], GOTO[CQRet],			c3;

CQEmpty:	T ← 0, GOTO[CQRet],					c3;
	GOTO[CQRet],						c3, QWr[L2.CQ4];

CQRet:	Xbus ← uPFlags, XDisp,						c1;
	G ← UvQ1, DISP4[CQRets],					c2;


{*****************************************************************************
PRead subroutine: 
      Entry:
	c2, c3 => Q has virtual address; Map reference started by caller
	L2 holds return
      Exit State:
	T has memory data
	rhTT, TT, has real address
	Q has uPMask
	returnee executed on c1
*****************************************************************************}
PRead2:	Noop,								c2;
PRead3:	TT ← rhTT ← MD,							c3;

PR:	MAR ← [rhTT, Q + 0],						c1;
	Q ← uPMask, L2Disp,						c2;
	T ← MD, DISP4[PRRets],						c3;

{*****************************************************************************
PMRead subroutine: 
      Entry:
	c2, c3 => Q has virtual address; Map reference started by caller
	L2 holds return
      Exit State:
	T has memory data and uPMask
	rhTT, TT, has real address
	Q has uPMask
	returnee executed on c1
*****************************************************************************}
PMRead2:	Noop,							c2;
PMRead3:	TT ← rhTT ← MD,						c3;

PMR:	MAR ← [rhTT, Q + 0],						c1;
	Q ← uPMask, L2Disp,						c2;
	T ← MD and Q, DISP4[PMRRets],					c3;

{*****************************************************************************
PFetch subroutine: 
      Entry:
	c2, c3 => Q has virtual address; Map reference started by caller
	L2 holds return
      Exit State:
	rhTT, TT, has real address
	Q has uPMask
	memory reference started
	returnee executed on c3
*****************************************************************************}
PFetch2:	Noop,							c2;
PFetch3:	TT ← rhTT ← MD,						c3;

	MAR ← [rhTT, Q + 0], L2Disp,					c1;
	Q ← uPMask, DISP4[PFRets],					c2;

{*****************************************************************************
PWrite subroutine: 
      Entry:
	Q has virtual address
	calling instruction executed on c1 => Map reference started by caller
	T has data to be written
	L2 holds return
      Exit State:
	T has memory data
	rhTT, TT, Q has real address
	returnee executed on c3
*****************************************************************************}
PWrite2:	Noop,							c2;
PWrite3:	TT ← rhTT ← MD,						c3;

PW:	MAR ← [rhTT, Q + 0], L2Disp,					c1;
	MDR ← T, RET[PWRets], 						c2;


{*****************************************************************************
QRead subroutine: 
      Entry:
	rhG,,G has virtual address
	L2 holds return
      Exit State:
	rhG, G has virtual address
	T has MD and 77777B
	XLDisp pending on MD to save ww bit
	returnee executed on c1
*****************************************************************************}
QRead1:	Map ← [rhG, G],							c1;
QRead2:	Noop,								c2;
QRead3:	TT ← rhTT ← MD, XDirtyDisp,					c3;

QR:	MAR ← [rhTT, G + 0], BRANCH[QRMpFx, QRMpOk, 1],			c1;
QRMpOk:	Q ← uPMask, L2Disp,						c2;
	T ← MD, XLDisp, RET[QRRets],					c3;

QRMpFx:	Noop,								c2;
	Xbus ← TT LRot0, XwdDisp,					c3;

	Map ← [rhG, G], DISP2[QRFlgFx],					c1;
QRFlgFx:	MDR ← TT or 10, GOTO[QRx],			c2, at[0,4,QRFlgFx];
	MDR ← TT or 10, GOTO[QRx],				c2, at[1,4,QRFlgFx];
	T ← qWriteProtect, L2←L2.Fault, GOTO[PRestart],		c2, at[2,4,QRFlgFx];
	T ← qPageFault, L2←L2.Fault, GOTO[PRestart],		c2, at[3,4,QRFlgFx];
QRx:	Xbus ← 2, XDisp, GOTO[QR],					c3;


{*****************************************************************************
Q1Read subroutine: 
      Entry:
	UvQ1Hi, UvQ1 has virtual address
	calling instruction executed on c1
	L2 holds return
      Exit State:
	same as QRead
*****************************************************************************}
Q1Read3:	rhG ← UvQ1Hi, GOTO[QRead1],				c3;

{*****************************************************************************
Q2Read subroutine: 
      Entry:
	UvQ2Hi, UvQ2 has virtual address
	calling instruction executed on c1
	L2 holds return
      Exit State:
	same as QRead
*****************************************************************************}
Q2Read2:	G ← UvQ2,						c2;
Q2Read3:	rhG ← UvQ2Hi, GOTO[QRead1],				c3;


{*****************************************************************************
QWrite subroutine: 
      Entry:
	rhG, G has virtual address
	L2 holds return
	T has data to be written
      Exit State:
	rhG, G has virtual address
	returnee executed on c3
*****************************************************************************}
QWrite1:	Map ← [rhG, G],						c1;
QWrite2:	Noop,							c2;
QWrite3:	TT ← MD, rhTT ← MD, XDirtyDisp,				c3;

QW:	MAR ← [rhTT, G + 0], BRANCH[QWMpFx, QWMpOk, 1], L2Disp,		c1;
QWMpOk:	MDR ← T, RET[QWRets],						c2;
QWMpFx:	CANCELBR[$,0F], 						c2;
	Xbus ← TT LRot0, XwdDisp, 					c3;

	Map ← [rhG, G], DISP2[QWFlgFx],					c1;
QWFlgFx:	MDR ← TT or 0A0, GOTO[QWx],			c2, at[0,4,QWFlgFx];
	MDR ← TT or 0A0, GOTO[QWx],				c2, at[1,4,QWFlgFx];
	T ← qWriteProtect, L2←L2.Fault, GOTO[PRestart],		c2, at[2,4,QWFlgFx];
	T ← qPageFault, L2←L2.Fault, GOTO[PRestart],		c2, at[3,4,QWFlgFx];
QWx:	Xbus ← 2, XDisp, GOTO[QW],					c3;


{END}