{File name: Process.mc bj 18-Jan-88 23:44:16 fix comments at PEnd:, comment out MesaIntBr's bj 7-Jan-88 16:20:50 temporarily put back in stackerr checking code. Trow 9-Nov-87 21:15:03 Add interrupt check at Enqueue, Reschedule. Trow 9-Nov-87 20:22:51 Eliminate uTickCount at Scan. Trow 9-Nov-87 17:22:10 Split memory reference at FreeState. BJackson 9-Nov-87 14:37:28 quick fix for interrupts. Trow 5-Nov-87 0:15:49 Fix interrupt at IdleLoop. Trow 22-Oct-87 21:56:08 Change XwdDisp to XdwDisp. BJackson 22-Oct-87 3:29:43 use "map.rd" instead of "30". Trow 13-Oct-87 15:27:07 Reverse targets 1 and 2 of XwdDisp. Fiala 15-May-86 19:15:45 Fixes for 4MB storage in map. Noted following problems for future: 1) QRead tested XDirtyDisp and proceeded only if flags were ok for a write but did a read and set map flags only for a read. 2) QWrite formerly or'ed 0A0 into the map flags instead of 0B0 like all other writes; I changed it to be 30 for the new format, like all other writes. ***Note Kiku also has these bugs (if bugs). Frandeen September 29, 1981 9:26 AM: Fix CancelBR at MREAbort+1. Frandeen August 20, 1981 2:20 PM: Fix for new assembler. Sandman March 26, 1981 10:43 AM to fix timing restrictions Sandman March 26, 1981 3:53 PM Change Wait to check condition.abortable Created: February 13, 1981 1:12 PM, Description: Dandelion Process Microcode, Author: Sandman, } {***************************************************************************** Definitions *****************************************************************************} {Xfer defs} Set[xtPSwitch, 0]; Set[L2.RSStashr,09]; Set[L2.Pop0Incr1or2, 0 {00xx}]; {also in Jump.mc} {Offsets and Magic locations} Set[PSB.link, 0]; Set[PSB.link.vector, 1]; Set[PSB.flags, 1]; Set[PSB.flags.waiting, 2]; Set[PSB.context, 2]; Set[PSB.timeout, 3]; 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.timeout, 2]; Set[PDA.state, 10'b]; Set[PDA.interrupt, 20'b]; Set[PDA.lastCV, 36'b]; Set[PDA.fault, 60'b]; Set[PSBSize, 4]; Set[StartPsbM4, 74'b]; { 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, 0]; Set[pMR, 1]; Set[pMX, 2]; Set[pMW, 9]; Set[pNC, 4]; Set[pBC, 5]; Set[pREQ, 8]; 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]; { Same as L2.MRE4} {PRead Returns} Set[L2.LP0, 0]; Set[L2.MRE3, 1]; Set[L2.DQ2, 4]; Set[L2.NQ1, 6]; Set[L2.WH2, 7]; Set[L2.NQ3, 8]; Set[L2.RS3, 9]; Set[L2.LP1, 0A]; Set[L2.AS0, 0B]; Set[L2.NQ0, 0C]; {also QRead} Set[L2.LP2, 0D]; Set[L2.TS0, 0E]; Set[L2.TS2, 0F]; {PMRead Returns} Set[L2.WH0, 0]; {0 MOD 2} Set[L2.RS0, 2]; {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.RS0, 2]; {also PMRead} Set[L2.RS2, 0]; {0 MOD 2} Set[L2.SP0, 1]; Set[L2.EF0, 3]; Set[L2.LP5, 4]; Set[L2.DQ5, 5]; Set[L2.MW2, 6]; {also PWrite, QRead} {PWrite Returns} Set[L2.WH1, 0]; Set[L2.SP1, 1]; {1 MOD 4; paired with L2.ASS0} Set[L2.PSS0, 2]; Set[L2.AAS0, 3]; {3 MOD 4; contains SP1} Set[L2.NQ4, 4]; Set[L2.FS0, 5]; Set[L2.MW2, 6]; {also PFetch, QRead} Set[L2.DQ0, 7]; {3 MOD 4; also QRead} Set[L2.AAS1, 9]; Set[L2.PSS1, 8]; Set[L2.SP2, 0A]; Set[L2.LP3, 0B]; Set[L2.FS1, 0C]; {QRead Returns} Set[L2.MRE4, 0]; {Same as L2.Trap} Set[L2.CQ0, 1]; Set[L2.MRE0, 2]; Set[L2.ME0, 4]; {also QWrite} Set[L2.EM0, 5]; Set[L2.MW2, 6]; {also PFetch, PWrite} Set[L2.DQ0, 7]; {3 MOD 4; also PWrite} Set[L2.BC0, 8]; Set[L2.RQ0, 9]; Set[L2.F0, 0A]; Set[L2.NQ0, 0C]; {also PRead} {QWrite Returns} Set[L2.ME0, 4]; {also QRead} Set[L2.MRE1, 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.EM1, 7]; {3 MOD 4} Set[L2.INT2, 8]; Set[L2.CQ4, 9]; {1 MOD 2} Set[L2.NQ8, 0A]; {Requeue Returns} Set[rhT.PT, 0]; {Must be zero} Set[rhT.BCast, 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]; {***************************************************************************** Opcodes *****************************************************************************} @ME: Rx _ pME, push, GOTO[Check1], c1, opcode[1]; @MR: Rx _ pMR, push, GOTO[Check2], c1, opcode[2]; @MW: Rx _ pMW, c1, opcode[3]; MWx: TT _ ErrnIBnStkp, push, XDisp, c2; {bj} STK _ TOS, pop, DISP4[Test2, 8], c3; { STK _ TOS, pop, BRANCH[Short2of2, Long2of2, 0D], c3; } @MD: Rx _ pMX, push, GOTO[Check1], c1, opcode[4]; @NC: Rx _ pNC, push, GOTO[Check1], c1, opcode[5]; @BC: Rx _ pBC, push, GOTO[Check1], c1, opcode[6]; @REQ: Rx _ pREQ, GOTO[MWx], c1, opcode[7]; Check1: TT _ ErrnIBnStkp, XDisp, c2; { rhT _ 0, STK _ TOS, BRANCH[Long1of1, Short1of1, 0E], c3; Long1of1: T _ STK, pop, GOTO[Got1], c1; Short1of1: T _ UvMDS, GOTO[Got1], c1; } {bj} rhT _ 0, STK _ TOS, DISP4[Test1, 8], c3; Test1: T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[ 8,10,Test1]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[ 9,10,Test1]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[0A,10,Test1]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[0B,10,Test1]; T _ STK, pop, GOTO[Got1], c1, at[0C,10,Test1]; T _ UvMDS, GOTO[Got1], c1, at[0D,10,Test1]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[0E,10,Test1]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[0F,10,Test1]; {bj} Got1: UvQ1Hi _ T, c2; T _ STK, pop, c3; UvQ1 _ T, pop, GOTO[SaveRegs], c1; {bj} BadStack: TT _ UvPCpage, L1_0, GOTO[StashPC0], c2; Check2: TT _ ErrnIBnStkp, XDisp, c2; rhT _ 0, STK _ TOS, DISP4[Test2, 8], c3; Test2: T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[ 8,10,Test2]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[ 9,10,Test2]; T _ STK, pop, GOTO[Got2], c1, at[0A,10,Test2]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[0B,10,Test2]; T _ UvMDS, GOTO[Got2], c1, at[0C,10,Test2]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[0D,10,Test2]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[0E,10,Test2]; T _ sStackError, L2_L2.TRAPStashr, GOTO[BadStack], c1, at[0F,10,Test2]; {bj} { Check2: TT _ ErrnIBnStkp, XDisp, c2; rhT _ 0, STK _ TOS, BRANCH[Short2of2, Long2of2, 0D], c3; Long2of2: T _ STK, pop, GOTO[Got2], c1; Short2of2: T _ UvMDS, GOTO[Got2], c1; } Got2: UvQ2Hi _ T, c2; T _ STK, pop, c3; UvQ2 _ T, c1; uStkDepth _ TT, YDisp, c2; rhT _ 0, BRANCH[Short1of2, Long1of2, 0D], c3; Long1of2: T _ STK, pop, GOTO[Got1], c1; Short1of2: T _ UvMDS, GOTO[Got1], 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, DISP3[Enter], c3; PRestart: uFaultParm0 _ G, c3; TOS _ ~uStkDepth, c1; stackP _ TOS, TOS _ pFault, c2; TT _ uPFlags, XDisp, c3; G _ rhG, L2Disp, BRANCH[PFa, PFb, 7], c1; PFa: uFaultParm1 _ G, pop, BRANCH[PTrap, PFault], c2; PFb: uFaultParm1 _ G, 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 _ TT, L2_L2.ME0{QRRets, QWRets}, c1, at[pME,10,Enter]; G _ UvQ1, CALL[Q1Read3], c2; Map _ UvQ2 _ [rhG, G], push, BRANCH[MEUnLocked, MELocked, 2], c1, at[L2.ME0,10,QRRets]; MEUnLocked: T _ T or Monitor.lock, push, CALL[QWrite3], c2; TOS _ 1, c3, at[L2.ME0,10,QWRets]; STK _ TOS, pop, GOTO[PTail2]{L not used}, c1; MELocked: PC _ uPSB, pop, c2; EnterFailed: L _ UvQ1Hi, L2_L2.EF0{PFRets}, c3; Map _ Q _ [rhPC, PC+PSB.link], c1; rhG _ PDAHi, G _ PDA.ready, CALL[PFetch3], c2; Rx _ MD or Rx, c3, at[L2.EF0,10,PFRets]; MAR _ [rhTT, PC+PSB.link], c1; MDR _ Rx or u8000, 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: uStkDepth _ TT, L2_L2.MRE0{QRRets}, c1, at[pMR,10,Enter]; G _ UvQ1, CALL[Q1Read3], c2; PC _ uPSB, BRANCH[MREUnLocked, MRELocked, 2], c1, at[L2.MRE0,10,QRRets]; MRELocked: UvQ2 _ G, GOTO[EnterFailed], c2; MREUnLocked: G _ UvQ2, c2; rhG _ UvQ2Hi, c3; Map _ [rhG, G], L2_L2.CQ0{QRRets}, c1; TOS _ T, CALL[QRead3], c2; PC _ uPSB, c3, at[pMR,10,CQRets]; Map _ Q _ [rhPC, PC or PSB.flags], L2_L2.MRE3{PRRets}, c1; Rx _ uPMask, CALL[PRead3], c2; MAR _ [rhTT, PC+PSB.flags], L2_L2.MRE4{QRRets}, c1, at[L2.MRE3,10,PRRets]; MDR _ Ybus _ T and ~Rx, YDisp, CANCELBR[$,0], c2; AbortNotOK: rhG _ UvQ1Hi, BRANCH[MRENoAbort, MREAbort, 0E], c3; MRENoAbort: Map _ [rhG, G], L2_L2.MRE1{QWRets}, c1; {write locked monitor} T _ TOS or Monitor.lock, push, CALL[QWrite3], c2; TOS _ 1, push, c3, at[L2.MRE1,10,QWRets]; STK _ TOS, pop, GOTO[PTail2]{L not used}, c1; MREAbort: Rx _ pTrap, CALL[Q2Read2], c1; [] _ T and Condition.abortable, NZeroBr, CANCELBR[$,3], c1, at[L2.MRE4,10,QRRets]; G _ UvQ1, BRANCH[AbortNotOK, PRestart], c2; {***************************************************************************** Monitor Exit and Depart opcode Entry: UvQ1Hi,,UvQ1 hold virtual address of monitor lock to be exited Exit: *****************************************************************************} Depart: uStkDepth _ TT, L2_L2.EM0{QRRets}, c1, at[pMX,10,Enter]; G _ UvQ1, CALL[Q1Read3], c2; MXDExit: 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, at[L2.EM0,10,QRRets]; T _ T and ~Monitor.lock, CALL[QWrite3], c2; T _ T and Q, ZeroBr, rhT _ rhT.EM{NQRets}, c3, at[L2.EM1,10,QWRets]; Map _ Q _ [rhPC, T+PSB.link], L2_L2.EM2{PMRets}, BRANCH[EMa, EMb], c1; EMa: UvQ2 _ PDA.ready, CALL[PMRead3], c2; L _ PDAHi, c1, at[L2.EM2,10,PMRRets]; PC _ T, L2_L2.DQ0{QRRets}, CALL[CallDQ], c2; EMb: Xbus _ uPFlags, XLDisp, c2, at[rhT.EM,10,NQRets]; PC _ uPSB, BRANCH[MXDExit, MWExit, 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, at[pMW,10,CQRets]; Rx _ UvQ2, c1; UvQTemp _ Rx, c2; Rx _ UvQ2Hi, c3; Map _ [rhG, G], L2_L2.EM0{QRRets}, c1; UvQTempHi _ Rx, CALL[QRead3], c2; MWExit: rhG _ G _ UvQTempHi, c1; UvQ2Hi _ G, c2; G _ UvQTemp, L2_L2.MW2{QRRets, PFRets, PWRets}, c3; Map _ UvQ2 _ [rhG, G], CALL[QRead2], c1; Map _ Q _ [rhPC, PC or PSB.flags], CANCELBR[PFetch2,3], c1, at[L2.MW2,10,QRRets]; TOS _ MD, XLDisp, c3, at[L2.MW2,10,PFRets]; [] _ T and Condition.abortable, ZeroBr, BRANCH[MWa, MWb, 2], c1; MWa: Rx _ uPTC, CANCELBR[MWd, 1], c2; MWb: Rx _ uPTC, BRANCH[MWc, MWd], c2; MWc: GOTO[PTail1], c3; MWd: Xbus _ T LRot0, XLDisp, c3; TT _ uTicks, ZeroBr, BRANCH[MWNoWW, MWWW, 2], c1; MWNoWW: rhG _ PDAHi, G _ PDA.ready, BRANCH[MWMakeTime, MWHaveTime], c2; MWHaveTime: Xbus _ 0, XDisp, GOTO[MWWriteTime], c3; MWMakeTime: TT _ TT + Rx, ZeroBr, c3; MWWriteTime: Map _ Q _ [rhPC, PC or PSB.timeout], BRANCH[MWTimeOK, MWIncTime], c1; MWTimeOK: T _ TT, rhT _ rhT.PT{NQRets}, CALL[PWrite3], c2; MWIncTime: T _ 0 + 0 + 1, rhT _ rhT.PT{NQRets}, CALL[PWrite3], c2; T _ TOS or PSB.flags.waiting, L2_L2.DQ0{QRRets, PWRets}, c3, at[L2.MW2,10,PWRets]; Map _ Q _ [rhPC, PC or PSB.flags], CALL[PWrite2]; CALL[QRead1], c3, at[L2.DQ0,10,PWRets]; MWWW: L2_L2.MW3{QWRets}, CANCELBR[$,1], c2; T _ T and ~Condition.wakeup, CALL[QWrite1], c3; GOTO[PTail1], c3, at[L2.MW3,10,QWRets]; {***************************************************************************** Notify opcode Entry: UvQ1Hi,,UvQ1 hold virtual address of condition to be notified Exit: *****************************************************************************} Notify: uStkDepth _ TT, L2_L2.CQ0{QRRets}, CALL[CleanFirst], c1, at[pNC,10,Enter]; T _ T and Q, ZeroBr, L2_L2.WH0{PMRRets}, c3, at[pNC,10,CQRets]; Map _ Q _ [rhPC, T+PSB.link], BRANCH[DoNotify, NoNotify], c1; DoNotify: L _ PDAHi, CALL[PMRead3], c2; NoNotify: TT _ uPFlags, GOTO[PTail3], {L not used} c2; {***************************************************************************** Broadcast opcode Entry: UvQ1Hi,,UvQ1 hold virtual address of condition to be broadcast Exit: *****************************************************************************} BCast: uStkDepth _ TT, L2_L2.CQ0{QRRets}, CALL[CleanFirst], c1, at[pBC,10,Enter]; BCe: rhT _ rhT.BCast{NQRets}, T _ T and Q, ZeroBr, c3, at[pBC,10,CQRets]; BCd: Map _ Q _ [rhPC, T+PSB.link], L2_L2.WH0{PMRRets}, BRANCH[BCa, BCb], c1; BCa: L _ PDAHi, CALL[PMRead3], c2; BCb: rhT _ 0, GOTO[PTail0], c2; BCc: G _ UvQ1, L2_L2.BC0{QRRets}, c2, at[rhT.BCast,10,NQRets]; rhG _ UvQ1Hi, CALL[QRead1], c3; CANCELBR[$,3], c1, at[L2.BC0,10,QRRets]; 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, at[L2.WH0,10,PMRRets]; T _ 0, UvQ2 _ PDA.ready, CALL[PWrite3], c2; PC _ Q - PSB.timeout, L2_L2.WH2{PRRets}, c3, at[L2.WH1,10,PWRets]; Map _ Q _ [rhPC, PC or PSB.flags], CALL[PRead2], c1; MAR _ [rhTT, PC+PSB.flags], c1, at[L2.WH2,10,PRRets]; 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, at[L2.RQ0,10,QRRets]; 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; {***************************************************************************** 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, at[L2.DQ0,10,QRRets]; DQx: Rx _ T, CALL[PMRead3], c2; {Fetch[@psb.link]} TOS _ uPFlags, c1, at[L2.DQ1,10,PMRRets]; 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, at[L2.DQ2,10,PRRets]; [] _ 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, at[L2.DQ5,10,PFRets]; MAR _ [rhTT, PC+PSB.flags], c1; MDR _ T or uPsbLink, CANCELBR[$,0], c2; DQm: {db} G _ UvQ2, {MesaIntBr,}{bj} GOTO[Enqueue], c3, at[L2.DQ4,10,QWRets]; {***************************************************************************** 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, at[L2.NQ0,10,PRRets]; L _ T and uPPMask, CALL[Q2Read3], c2; Q _ T and uPMask, ZeroBr, CANCELBR[$,3], c1, at[L2.NQ0,10,QRRets]; 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, at[L2.NQ8,10,QWRets]; 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, Ufsi _ T, c1, at[L2.NQ1,10,PRRets]; [] _ 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, at[L2.NQ2,10,QWRets]; NQd: Map _ Q _ [rhPC, Rx+PSB.link], CALL[PRead2], c1; TT _ T and uPPMask, c1, at[L2.NQ3,10,PRRets]; [] _ L - TT - 1, CarryBr, c2; Q _ ~uPMask, BRANCH[NQf, NQg], c3; NQf: TOS _ Rx, c1; Ufsi _ 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 Ufsi, L2_L2.NQ4{PWRets}, c3; Map _ Q _ [rhPC, TOS+PSB.link], c1; T _ T or PC, CALL[PWrite3], c2; Xbus _ rhT, XDisp, c3, at[L2.NQ4,10,PWRets]; 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 *****************************************************************************} PTail0: Noop, c3; PTail1: L _ UrL, c1; PTail2: TT _ uPFlags, c2, at[rhT.PT,10,NQRets]; PTail3: G _ UrG, L0_L0.JRemap, c3; rhG _ UrGHi, c1; PC _ UrPC, L2_L2.RSStashr{StashRets}, c2; rhRx _ TT LRot12, XDisp, c3; PTNormal: DISP4[PEnd], c1; PEnd: PC _ PC + PC16, IBDisp, GOTO[SimpleEnd], c2, at[0,10]; {***not possible, 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_L1r.Refill, GOTO[IntRet], 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]; TT _ UvPCpage, L1 _ 1, GOTO[StashPC1], c2, at[8,10,PEnd]; {***not possible, 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_L1r.Refill, GOTO[IntRet], c2, at[0C,10,PEnd]; TT _ UvPCpage, L1 _ 0, GOTO[StashPC0], c2, at[0D,10,PEnd]; {db} {MesaIntBr,}{bj} GOTO[Reschedule], c2, at[0E,10,PEnd]; GOTO[SPIdle], {was in idle loop} c2, at[0F,10,PEnd]; SimpleEnd: rhPC _ UrPCHi, DISPNI[OpTable], c3; Reschedule: {db} PC _ uPSB, BRANCH[SaveProcess, RescheduleInt], c3, at[L2.RSStashr,10,StashRets]; IntRet: TOS _ STK, pop, BRANCH[PCPageOK, IncPage, 1], c3; PCPageOK: Xbus _ rhRx, XDisp, Q _ 0, L2_L2.Pop0Incr1or2, c1; PageOKx: TT _ UvPCpage, BRANCH[FastEasy, SlowEasy, 7], c2; FastEasy: rhTT _ UvChigh, GOTO[RReMap], c3; SlowEasy: Q _ UvC, L1_0, c3; L2_L2.RSStashr{StashRets}, GOTO[StashPCa1], c1; IncPage: Rx _ LRot1 ErrnIBnStkp, c1; Xbus _ Rx LRot0, XwdDisp, c2; TT _ UvPCpage, DISP2[IBState], c3; IBState: Xbus _ rhRx, XDisp, Q _ 0, L2_L2.Pop0Incr1or2, GOTO[PageOKx], c1, at[0,4,IBState]; Xbus _ rhRx, XDisp, Q _ 0, L2_L2.Pop0Incr1or2, GOTO[PageOKx], c1, at[1,4,IBState]; Xbus _ rhRx, XDisp, Q _ 0, L2_L2.Pop0Incr1or2, GOTO[PageOKx], c1, at[2,4,IBState]; Xbus _ rhRx, XDisp, Q _ 0, L2_L2.Pop0Incr1or2, c1, at[3,4,IBState]; TT _ TT + 0FF + 1, BRANCH[FastEasy, SlowEasy, 7], c2; SPIdle: G _ PDA.lastCV{for interrupts}, L2_L2.RS0{PMRRets, PFRets}, c3, at[L2.SP2,10,PWRets]; SPRet: Map _ Q _ [rhPC, PDA.ready], CALL[PMRead2], c1; Map _ Q _ [rhPC, T+PSB.link], ZeroBr, c1, at[L2.RS0,10,PMRRets]; UreturnPC _ T, BRANCH[PFetch3, BusyWaita], c2; PC _ MD and Q, L2_L2.RS2{PFRets}, c3, at[L2.RS0,10,PFRets]; RSe: {bj} RegDef[uHelp, U, 5F]; z1: [] _ uHelp xor PC, ZeroBr, ,c1; z2: BRANCH[z3a, z3b], ,c2; z3a: GOTO[z4], ,c3; z3b: GOTO[z4], ,c3; z4: Map _ Q _ [rhPC, PC{+PSB.link}], uPSB _ PC, CALL[PFetch2], c1; T _ MD, XLDisp, c3, at[L2.RS2,10,PFRets]; uPsbLink _ T, BRANCH[RSa, RSb, 2], c1; RSb: GOTO[RSc], c2; RSa: T _ T and uPPMask, c2; 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, at[L2.RS3,10,PRRets]; [] _ UreturnPC xor PC, ZeroBr, BRANCH[RSc, RSd], c2; RSd: PC _ uPsbLink and Q, BRANCH[RSe, BusyWaitb], c3; RSc: uPCValid _ 0, L _ 0, CANCELBR[LoadProcess,1], c3; BusyWaita: Noop, c3; BusyWaitb: T _ pIdle, c1; [] _ uWDC, NZeroBr, c2; IdleLoop: uPFlags _ T, MesaIntBr, BRANCH[$, WakeError], c3; {db} BRANCH[NoInt, IdleInt {InterruptsDaybreak}], c1; NoInt: GOTO[IdleLoop], c2; WakeError: T _ sWakeupError, 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], L2_L2.SP0{PFRets}, c1; TOS _ PSB.link.vector, CALL[PFetch3], c2; T _ MD or TOS, L3Disp, c3, at[L2.SP0,10,PFRets]; MAR _ [rhTT, PC+PSB.link], BRANCH[SPa, SPb, 2], c1; SPa: MDR _ T and ~PSB.link.vector, GOTO[SPc], c2; SPb: MDR _ T, T _ T and uPPMask, c2; T _ T LRot4, GOTO[AllocAndSave], c3; AASRet: T _ TOS, L2_L2.SP2{PWRets}, c3, at[L2.SP1,10,PWRets]; SPd: Map _ Q _ [rhPC, PC or PSB.context], CALL[PWrite2], c1; SPc: T _ UvL, L2_L2.SP2{PWRets}, GOTO[SPd], c3; {***************************************************************************** LoadProcess subroutine Entry: Ufsi has state vector of saved process if fault L has 0 Exit: Returns to EFCHaveLink Register Usage *****************************************************************************} LoadProcess: Map _ Q _ [rhPC, PC or PSB.context], L2_L2.LP0{PRRets}, c1; rhT _ xtPSwitch, stackP _ 0, CALL[PRead3], c2; Q _ T + State.word, c1, at[L2.LP0,10,PRRets]; Xbus _ uPsbLink, TOS _ T, XLDisp, L2_L2.LP2{PRRets}, c2; Rx _ uPsbLink, NegBr, BRANCH[LPa, LPb, 2], c3; LPa: MAR _ [rhTT, PC+PSB.link], BRANCH[LPc, LPd], c1; LPd: MDR _ Rx and ~u8000, push, c2; push, c3; STK _ 0, pop, c1; LPc: TT _ T, c2; Ybus _ TT, YDisp, c3; LPe: Map _ Q _ [rhMDS, TT], UvL _ TT, L0_L0.XFStartRead, DISP4[XferFrame, 0C], c1; LPb: Map _ Q _ [rhPC, Q], CANCELBR[PRead2, 1], c1; FSRet: TOS _ TOS + State.frame, L2_L2.LP5{PFRets}, c3, at[L2.FS0,10,PWRets]; Map _ Q _ [rhPC, TOS], CALL[PFetch2], c1; TT _ MD, XDisp, GOTO[LPe], c3, at[L2.LP5,10,PFRets]; {***************************************************************************** FreeState subroutine Entry: T has priority TOS has state Exit: Register Usage T, Q, rhTT, TT, TOS *****************************************************************************} {db} FreeState: Map _ Q _ [rhPC, PDA.state or T], c1; Noop, c2; TT _ rhTT _ MD, c3; MAR _ [rhTT, Q + 0], c1; Noop, c2; T _ MD, c3; MAR _ [rhTT, Q + 0], c1; MDR _ TOS, c2; L2 _ L2.FS0 {PWRets}, c3; Map _ Q _ [rhPC, TOS], c1; stackP _ uStkDepth, CALL[PWrite3], c2; {db} {***************************************************************************** AllocAndSave subroutine Entry: T has priority Exit: TOS has state Register Usage T, Q, rhRx, Rx, TOS, uTemp *****************************************************************************} AllocAndSave: Map _ Q _ [rhPC, PDA.state or T], L2_L2.AS0{PRRets}, c1; uTemp _ Q, CALL[PRead3], c2; Map _ Q _ [rhPC, T], c1, at[L2.AS0,10,PRRets]; 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, T _ Q + State.word, c2; G _ ~ErrnIBnStkp, c3; Map _ Q _ [rhPC, T], L2_L2.PSS0{PWRets}, c1; T _ 0F and G, CALL[PWrite3], c2; [] _ T - cSSm2, CarryBr, c3, at[L2.PSS0,10,PWRets]; stackP _ Rx _ T + 2, BRANCH[PSSstore, PSScarry], c1; PSScarry: stackP _ Rx _ cSS, c2; Noop, c3; Noop, c1; PSSstore: Q _ Q - State.word, c2; Q _ Q + Rx, push, L2_L2.PSS1{PWRets}, c3; PSSloop: Map _ Q _ [rhPC, Q-1], BRANCH[$,PSSRet], c1; T _ STK, pop, CALL[PWrite3], c2; Rx _ Rx - 1, ZeroBr, GOTO[PSSloop], c3, at[L2.PSS1,10,PWRets]; PSSRet: T _ UvL, L3Disp, c2; Q _ TOS + State.frame, L2_L2.SP1{PWRets}, BRANCH[AASa, AASb, 1], c3; AASa: Map _ Q _ [rhPC, Q], CALL[PWrite2], c1; AASb: Map _ Q _ [rhPC, Q], CALL[PWrite2], c1; T _ uFaultParm0, L2_L2.AAS1{PWRets}, c3, at[L2.AAS0,10,PWRets]; Map _ Q _ [rhPC, Q+1], CALL[PWrite2], c1; T _ uFaultParm1, L2_L2.SP1{PWRets}, c3, at[L2.AAS1,10,PWRets]; Map _ Q _ [rhPC, Q+1], CALL[PWrite2], c1; {***************************************************************************** PLoadStack subroutine Entry: T has state.word TOS has stack pointer Exit: TOS has stack pointer T has priority Returns to FreeState Register Usage T, rhTT, TT, Q, Rx, TOS *****************************************************************************} PLoadStack: uStkDepth _ T, c1, at[L2.LP2,10,PRRets]; rhTT _ T LRot8, c2; TT _ rhTT, c3; T _ T and 0F, c1; Q _ T - cSSm1, CarryBr, c2; Q _ Q + cSSp1, BRANCH[LPload, LPcarry], c3; LPcarry: Q _ cSS, c1; Noop, c2; Noop, c3; LPload: UBrkByte _ TT, Rx _ Q, c1; Q _ TOS - 1, GOTO[PLPa], c2; LPloop: Map _ Q _ [rhPC, Q+1], c1; G _ uPsbLink, c2; rhTT _ TT _ MD, c3; MAR _ [rhTT, Q+0], c1; Rx _ Rx - 1, ZeroBr, c2; PLPa: T _ MD, STK _ T, push, BRANCH[LPloop, LPdone], LOOPHOLE[mdok], c3; LPdone: STK _ T, c1; T _ G LRot4, c2; T _ T and 7, GOTO[FreeState], c3; {***************************************************************************** Interrupt Handler Entry: CALLing sequence has done Rx _ pInt, GOTO[SaveRegs]; Exit: Register Usage *****************************************************************************} Interrupt: Rx _ uWP, c1, at[pIntLoc,10,Enter]; {db} {ClrIntErr}, 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; {db} Map _ UvQ1 _ [rhG, Q], BRANCH[Int, Scan], c1; Int: uIntLevel _ G, G _ Q, L2_L2.CQ0{QRRets}, CALL[QRead3], c2; rhT _ rhT.IntNN{NQRets}, Q _ T and Q, ZeroBr, c3, at[pIntLoc,10,CQRets]; 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, at[L2.INT2,10,QWRets]; Rx _ uWW, NZeroBr, c1; CheckNext: G _ G - 2, BRANCH[IntDone, CVLoop], c2; IntDone: T _ UrPC, GOTO[PTail1], c3; IntDidNN: GOTO[INTc], c2, at[rhT.IntNN,10,NQRets]; {***************************************************************************** Fault Handler Entry: T has FaultIndex*2 parameters stored in uFaultParm0 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; CALL[QRead1], c3; rhT _ rhT.FaultNN{NQRets}, c2, at[rhT.Fault,10,NQRets]; 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, at[L2.F0,10,QRRets]; 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, at[rhT.FaultNN,10,NQRets]; {***************************************************************************** Check For Timeouts Entry: Exit: Register Usage *****************************************************************************} {db ***** CheckTime: TT _ LShift1 uTickCount, XDisp, c2; uTickCount _ TT, BRANCH[Scan, NoScan, 0B], c3; NoScan: T _ UrPC, c1; GOTO[PTail0], c2; ***** db} Scan: Noop, c2; Noop, c3; T _ uPTC, L0_L0.SrcNull, c1; T _ T + 1, c2; uPTC _ T, L2_L2.TS0{PRRets}, c3; Map _ Q _ [rhPC, PDA.count], c1; G _ PDAHi, CALL[PRead3], c2; TT _ T, c1, at[L2.TS0,10,PRRets]; PC _ StartPsbM4, c2; UvQ2Hi _ G, c3; UvQ2 _ PDA.ready, GOTO[CheckEndx], c1; TSLoop: Map _ Q _ [rhPC, PC or PSB.timeout], L2_L2.TS2{PRRets}, c1; uBLTTemp _ TT, CALL[PRead3], c2; Q _ T, ZeroBr, c1, at[L2.TS2,10,PRRets]; [] _ Q xor uPTC, NZeroBr, BRANCH[CanTimeout, NoTimeout], c2; CanTimeout: T _ uBLTTemp, BRANCH[Timeout, CheckEnd], c3; Timeout: MAR _ [rhTT, PC+PSB.flags], c1; CANCELBR[$,0], c2; T _ MD, c3; MAR _ [rhTT, PC+PSB.flags], c1; MDR _ T and ~PSB.flags.waiting, CANCELBR[$,0], c2; rhT _ rhT.TS{NQRets}, c3; MAR _ [rhTT, PC+PSB.timeout], c1; MDR _ 0, CANCELBR[$,0], c2; GOTO[Dequeue], c3; GOTO[NoTimeout], c2, at[rhT.TS,10,NQRets]; NoTimeout: T _ uBLTTemp, CANCELBR[CheckEnd,1], c3; CheckEnd: TT _ T - 1, ZeroBr, c1; CheckEndx: T _ UrPC, BRANCH[TSNotDone, TSDone], c2; TSNotDone: PC _ PC + PSBSize, GOTO[TSLoop], c3; TSDone: {db uTickCount _ L xor ~L, GOTO[PTail1], c3; db} {db} GOTO[PTail1], 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, CANCELBR[$,3], c1, at[L2.CQ0,10,QRRets]; 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, at[L2.CQ1,10,PMRRets]; 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, at[L2.CQ2,10,PMRRets]; 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, at[L2.CQ3,10,PMRRets]; 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, at[L2.CQ4,10,QWRets]; 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: {db} TT _ rhTT _ MD, XdwDisp, c3; QR: MAR _ [rhTT, G + 0], DISP2[QRMpFx], c1; QRMpFx: GOTO[QRMpFx1], c2, at[0, 4, QRMpFx]; {db} GOTO[QRMpFx1], c2, at[1, 4, QRMpFx]; GOTO[QRMpFx1], c2, at[3, 4, QRMpFx]; {db} Q _ uPMask, L2Disp, c2, at[2, 4, QRMpFx]; T _ MD, XLDisp, RET[QRRets], c3; QRMpFx1: {db} Xbus _ TT LRot0, XdwDisp, c3; Map _ [rhG, G], DISP2[QRFlgFx], c1; QRFlgFx: {db} MDR _ TT or map.referenced, GOTO[QRx], c2, at[0,4,QRFlgFx]; {db} MDR _ TT or map.referenced, GOTO[QRx], c2, at[2,4,QRFlgFx]; {db} T _ qWriteProtect, L2_L2.Fault, GOTO[PRestart], c2, at[1,4,QRFlgFx]; T _ qPageFault, L2_L2.Fault, GOTO[PRestart], c2, at[3,4,QRFlgFx]; QRx: Xbus _ rdw.x10, 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: {db} TT _ MD, rhTT _ MD, XdwDisp, c3; QW: MAR _ [rhTT, G + 0], DISP2[QWMpFx], L2Disp, c1; QWMpFx: CANCELBR[QWMpFx1,0F], c2, at[0, 4, QWMpFx]; {db} CANCELBR[QWMpFx1,0F], c2, at[1, 4, QWMpFx]; CANCELBR[QWMpFx1,0F], c2, at[3, 4, QWMpFx]; QWMpOk: {db} MDR _ T, RET[QWRets], c2, at[2, 4, QWMpFx]; QWMpFx1: {db} Xbus _ TT LRot0, XdwDisp, c3; Map _ [rhG, G], DISP2[QWFlgFx], c1; QWFlgFx: {bj} MDR _ TT or map.rd, GOTO[QWx], c2, at[0,4,QWFlgFx]; {db} MDR _ TT or map.rd, GOTO[QWx], c2, at[2,4,QWFlgFx]; {db} T _ qWriteProtect, L2_L2.Fault, GOTO[PRestart], c2, at[1,4,QWFlgFx]; T _ qPageFault, L2_L2.Fault, GOTO[PRestart], c2, at[3,4,QWFlgFx]; QWx: Xbus _ rdw.x10, XDisp, GOTO[QW], c3;