{ File name CommonSubs.mc Fiala 16-May-86 10:51:08 Changes for 4 MB storage. Frandeen August 20, 1981 2:20 PM: Fix for new assembler. Johnsson, January 20, 1981 10:22 AM Charnley, October 8, 1980 9:23 AM Garner, April 11, 1980 4:52 PM Description: Emulator Subroutines Author: don charnley Created: March 28, 1980 } { codes used for L0 indicate where to return from fixing the map flags return is relative to RMapFixCaller } { codes used for L1 indicate how to reset state if page fault encountered return is relative to RFixForTrap } { codes used for L1 indicate return from CycleMask } { codes used for L2 indicate where to return from remapping a Local or Global return is relative to LGRemapCaller } { codes used for L3 indicate where virtual address is } { Read Map Update Subroutines } {Timing: 4 cycles} {Enter at cycle 3, returns to cycle1} {returns thru L0 if map fixed ok} {returns thru L1 if wants to trap} {uses L3 to distinguish where virtual address is} RLMapFix: Xbus ← Rx LRot0,XwdDisp, L3 ← L3.rhTT.Q ,c3; RLMapFixx: Map ← [rhTT,Q], DISP2[RFixRFlags] ,c1; RMapFix: Xbus ← Rx LRot0,XwdDisp, L3 ← L3.rhMDS.Q ,c3; Map ← [rhMDS,Q], DISP2[RFixRFlags] ,c1; RFixRFlags: MDR ← Rx or 10, L0Disp, GOTO[ReRead] ,c2, at[0,4]; MDR ← Rx or 10, L0Disp, GOTO[ReRead] ,c2, at[1,4,RFixRFlags]; MDR ← Rx or 10, L0Disp, GOTO[ReRead], ,c2, at[2,4,RFixRFlags]; IBEmptyTrap: T ← qPageFault, L1Disp, GOTO[RTrap] ,c2, at[3,4,RFixRFlags]; ReRead: Xbus ← 1, XDisp, RET[RMapFixCaller] ,c3; RTrap: push, RET[RFixForTrap] ,c3; { Local and Global Remap Subroutines } {Timing: 9 cycles (3 clicks), + 2 clicks if flags need fixing } {Enter at cycle 1, returns to cycle1} {returns thru L2 if all ok, thru LGRemapCaller} {returns thru L1 {from RLMapFix} if wants to trap, thru FixForTrap} {assumes caller executed "TT ← UvL/UvG"} { USES TT, Rx, rhRx, rhMDS, and Q} LGRemap: TT ← TT + 0FF + 1 ,c1; Noop ,c2; Noop ,c3; Map ← [rhMDS,TT] ,c1; Noop ,c2; Rx ← rhRx ← MD, XRefBr ,c3; LGRefetch: MAR ← [rhRx,Q + 0], BRANCH[LGMapUD,$] ,c1; L2Disp ,c2; rhTT ← TT ← MD, RET[LGRemapCaller] ,c3; LGMapUD: Noop {code duplicated to protect L0} ,c2; Xbus ← Rx LRot0,XwdDisp, L3 ← L3.rhMDS.TT ,c3; Map ← [rhMDS,TT], DISP2[LGFixRFlags] ,c1; LGFixRFlags: MDR ← Rx or 10, GOTO[LGReRead] ,c2, at[0,4]; MDR ← Rx or 10, GOTO[LGReRead] ,c2, at[1,4,LGFixRFlags]; MDR ← Rx or 10, GOTO[LGReRead], ,c2, at[2,4,LGFixRFlags]; T ← qPageFault, L1Disp, GOTO[RTrap] ,c2, at[3,4,LGFixRFlags]; LGReRead: Xbus ← 1, XDisp, GOTO[LGRefetch] ,c3; { Write Map Update Subroutines } {Timing: 4 cycles} {Enter at cycle 3, returns to cycle1} {returns thru L0 if map fixed ok} {returns thru L1 if wants to trap} WLMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhTT.Q, c3; Map ← [rhTT, Q], DISP2[FixWFlags], c1; WMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhMDS.Q, c3; Map ← [rhMDS, Q], DISP2[FixWFlags], c1; FixWFlags: MDR ← Rx or 30, L0Disp, GOTO[ReWrite], c2, at[0,4]; MDR ← Rx or 30, L0Disp, GOTO[ReWrite], c2, at[1,4,FixWFlags]; T ← qWriteProtect, L1Disp, GOTO[WTrap], c2, at[2,4,FixWFlags]; T ← qPageFault, L1Disp, GOTO[WTrap], c2, at[3,4,FixWFlags]; ReWrite: Xbus ← 1, XDisp, RET[WMapFixCaller], c3; WTrap: push, RET[WFixForTrap], c3; { Read Map Update Subroutines } {Timing: 4 cycles} {Enter at cycle 3, returns to cycle1} {returns thru L0 if map fixed ok} {returns thru L1 if wants to trap} {uses L3 to distinguish where virtual address is} {LGxMapFix must be at[1,2]. See EMapUD in Refill.mc} RLxMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhTT.Q ,c3; Map ← [rhTT, Q], DISP2[RxFixRFlags] ,c1; RxMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhMDS.Q ,c3; Map ← [rhMDS,Q], DISP2[RxFixRFlags] ,c1; LGxMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhTT.TT ,c3, at[1,2]; Map ← [rhTT,TT], DISP2[RxFixRFlags] ,c1; RxFixRFlags: MDR ← Rx or 10, L0Disp, GOTO[RexRead] ,c2, at[0,4]; MDR ← Rx or 10, L0Disp, GOTO[RexRead] ,c2, at[1,4,RxFixRFlags]; MDR ← Rx or 10, L0Disp, GOTO[RexRead], ,c2, at[2,4,RxFixRFlags]; T ← qPageFault, L1Disp, GOTO[RTrap] ,c2, at[3,4,RxFixRFlags]; RexRead: Xbus ← 1, XDisp, RET[RxMapFixCaller] ,c3; { Write Map Update Subroutines } {Timing: 4 cycles} {Enter at cycle 3, returns to cycle1} {returns thru L0 if map fixed ok} {returns thru L1 if wants to trap} WLxMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhTT.Q, c3; Map ← [rhTT, Q], DISP2[FixWxFlags], c1; WxMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhMDS.Q, c3; Map ← [rhMDS, Q], DISP2[FixWxFlags], c1; FixWxFlags: MDR ← Rx or 30, L0Disp, GOTO[RexWrite], c2, at[0,4]; MDR ← Rx or 30, L0Disp, GOTO[RexWrite], c2, at[1,4,FixWxFlags]; T ← qWriteProtect, L1Disp, GOTO[WTrap], c2, at[2,4,FixWxFlags]; T ← qPageFault, L1Disp, GOTO[WTrap], c2, at[3,4,FixWxFlags]; RexWrite: Xbus ← 1, XDisp, RET[WxMapFixCaller], c3; { Read Map Update Subroutines } {Timing: 4 cycles} {Enter at cycle 3, returns to cycle1} {returns thru L0 if map fixed ok} {returns thru L1 if wants to trap} {uses L3 to distinguish where virtual address is} RLyMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhTT.Q ,c3; Map ← [rhTT, Q], DISP2[RyFixRFlags] ,c1; RyMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhMDS.Q ,c3; Map ← [rhMDS,Q], DISP2[RyFixRFlags] ,c1; RyFixRFlags: MDR ← Rx or 10, L0Disp, GOTO[ReyRead] ,c2, at[0,4]; MDR ← Rx or 10, L0Disp, GOTO[ReyRead] ,c2, at[1,4,RyFixRFlags]; MDR ← Rx or 10, L0Disp, GOTO[ReyRead], ,c2, at[2,4,RyFixRFlags]; T ← qPageFault, L1Disp, GOTO[RTrap] ,c2, at[3,4,RyFixRFlags]; ReyRead: Xbus ← 1, XDisp, RET[RyMap] ,c3; { Write Map Update Subroutines } {Timing: 4 cycles} {Enter at cycle 3, returns to cycle1} {returns thru L0 if map fixed ok} {returns thru L1 if wants to trap} WyMapFix: Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhMDS.Q, c3; Map ← [rhMDS, Q], DISP2[FixWyFlags], c1; FixWyFlags: MDR ← Rx or 30, L0Disp, GOTO[ReyWrite], c2, at[0,4]; MDR ← Rx or 30, L0Disp, GOTO[ReyWrite], c2, at[1,4,FixWyFlags]; T ← qWriteProtect, L1Disp, GOTO[WTrap], c2, at[2,4,FixWyFlags]; T ← qPageFault, L1Disp, GOTO[WTrap], c2, at[3,4,FixWyFlags]; ReyWrite: Xbus ← 1, XDisp, RET[WyMap], c3; { RFixForTrap } NoFixes: Noop, GOTO[NoMoreFix] ,c1, at[L1r.NoFixes,10,RFixForTrap]; PC ← PC - PC16, GOTO[NoMoreFix] ,c1, at[L1r.DecOnly,10,RFixForTrap]; PopOnlyFix: pop, GOTO[NoMoreFix] ,c1, at[L1r.PopOnly,10,RFixForTrap]; push, GOTO[PushFix] ,c1, at[L1r.Push2Only,10,RFixForTrap]; PC ← PC - PC16, push, GOTO[NoMoreFix] ,c1, at[L1r.PushDec,10,RFixForTrap]; push, GOTO[NoMoreFix] ,c1, at[L1r.PushOnly,10,RFixForTrap]; PC ← PC - 1, push, GOTO[NoMoreFix] ,c1, at[L1r.PushDecDec,10,RFixForTrap]; PC ← PC - 1, pop, GOTO[NoMoreFix] ,c1, at[L1r.PopDecDec,10,RFixForTrap]; PC ← PC - PC16, pop, GOTO[NoMoreFix] ,c1, at[L1r.PopDec,10,RFixForTrap]; PC ← PC - 1, push, GOTO[PushFix] ,c1, at[L1r.Push2DecDec,10,RFixForTrap]; PC ← PC - 1, pop, GOTO[PopFix] ,c1, at[L1r.Pop2DecDec,10,RFixForTrap]; PC ← PC - 1, GOTO[NoMoreFix] ,c1, at[L1r.DecDec,10,RFixForTrap]; { WFixForTrap fixups } Noop, GOTO[NoMoreFix] ,c1, at[L1w.NoFixes,10,WFixForTrap]; PC ← PC - PC16, GOTO[NoMoreFix] ,c1, at[L1w.DecOnly,10,WFixForTrap]; push, GOTO[PushFix] ,c1, at[L1w.Push2Only,10,WFixForTrap]; PC ← PC - PC16, push, GOTO[PushFix] ,c1, at[L1w.Push2Dec,10,WFixForTrap]; PC ← PC - PC16, push, GOTO[NoMoreFix] ,c1, at[L1w.PushDec,10,WFixForTrap]; push, GOTO[NoMoreFix] ,c1, at[L1w.PushOnly,10,WFixForTrap]; push, GOTO[Push3Fix] ,c1, at[L1w.Push3Only,10,WFixForTrap]; PC ← PC - 1, GOTO[NoMoreFix] ,c1, at[L1w.DecDec,10,WFixForTrap]; PC ← PC - 1, push, GOTO[NoMoreFix] ,c1, at[L1w.PushDecDec,10,WFixForTrap]; PC ← PC - PC16, pop, GOTO[NoMoreFix] ,c1, at[L1w.PopDec,10,WFixForTrap]; PC ← PC - 1, push, GOTO[PushFix] ,c1, at[L1w.Push2DecDec,10,WFixForTrap]; pop, GOTO[NoMoreFix] ,c1, at[L1w.PopOnly,10,WFixForTrap]; { Trap Handling } NoMoreFix: L3Disp, GOTO[TrapFixDone] ,c2; PushFix: push, L3Disp, GOTO[TrapFixDone] ,c2; PopFix: pop, L3Disp, GOTO[TrapFixDone] ,c2; Push3Fix: push, L3Disp, GOTO[TrapFixPush3] ,c2; TrapFixDone: DISP3[FormVA] ,c3; TrapFixPush3: push, DISP3[FormVA] ,c3; FormVA: uFaultParm0 ← Q, GOTO[VArhTT] ,c1, at[L3.rhTT.Q,8,FormVA]; uFaultParm0 ← TT, GOTO[VArhTT] ,c1, at[L3.rhTT.TT,8,FormVA]; uFaultParm0 ← Q, GOTO[VAMDS] ,c1, at[L3.rhMDS.Q,8,FormVA]; VAMDS: Q ← rhMDS, GOTO[Faultc3] ,c2; VArhTT: Q ← rhTT, GOTO[Faultc3] ,c2; {At Faultc3, uFaultParm0 stored, Q has uFaultPram1, T has FaultQueuePointer} Faultc3: uFaultParm1 ← Q ,c3; Faultc1: Rx ← pFault, STK ← TOS, pop, GOTO[SaveRegs] ,c1; {At Trapc1, TT holds the trap parmater, T has the sSDIndex} Trapc3: GOTO[Trapc1] ,c3; Trapc1: UTrapParm ← TT, L2 ← L2.TRAPStashr ,c1; Trapc2: TT ← UvPCpage, L1←0, GOTO[StashPC0] {in Xfer.mc} ,c2; { CycleMask } {Timing: 1 click} {Used by: SHIFT, RF, WF, BITBLT instructions} {Entry: T = data to be rotated & masked, TT = pre-rotated version of T a DISP4 pending which determines rotation: 0 => no rotation 1 => left rotate 1 : 0F => left rotate 15; a INIA.11 branch is pending to determine if shift should be abandoned. rhT = value to be dispatched on to determine mask 0 => 1 1 => 3 : 0F => 0FFFF Exit: TT holds the mask, TOS holds the rotated data, T does not contain the original data, rhT is untouched} CycleMask: [] ← rhT, XDisp, BRANCH[ShiftOut0, ShiftOK0], c*, at[0,10,CycleMask]; T ← TT, [] ← rhT, XDisp, BRANCH[ShiftOut0, ShiftOK0], c*, at[1,10,CycleMask]; T ← LRot1 TT, [] ← rhT, XDisp, BRANCH[ShiftOut0, ShiftOK0], c*, at[2,10,CycleMask]; T ← RRot1 T, [] ← rhT, XDisp, BRANCH[ShiftOut4, ShiftOK4], c*, at[3,10,CycleMask]; [] ← rhT, XDisp, BRANCH[ShiftOut4, ShiftOK4], c*, at[4,10,CycleMask]; T ← LRot1 T, [] ← rhT, XDisp, BRANCH[ShiftOut4, ShiftOK4], c*, at[5,10,CycleMask]; T ← LRot1 TT, [] ← rhT, XDisp, BRANCH[ShiftOut4, ShiftOK4], c*, at[6,10,CycleMask]; T ← RRot1 T, [] ← rhT, XDisp, BRANCH[ShiftOut8, ShiftOK8], c*, at[7,10,CycleMask]; [] ← rhT, XDisp, BRANCH[ShiftOut8, ShiftOK8], c*, at[8,10,CycleMask]; T ← LRot1 T, [] ← rhT, XDisp, BRANCH[ShiftOut8, ShiftOK8], c*, at[9,10,CycleMask]; T ← LRot1 TT, [] ← rhT, XDisp, BRANCH[ShiftOut8, ShiftOK8], c*, at[0A,10,CycleMask]; T ← RRot1 T, [] ← rhT, XDisp, BRANCH[ShiftOut12, ShiftOK12], c*, at[0B,10,CycleMask]; [] ← rhT, XDisp, BRANCH[ShiftOut12, ShiftOK12], c*, at[0C,10,CycleMask]; T ← LRot1 T, [] ← rhT, XDisp, BRANCH[ShiftOut12, ShiftOK12], c*, at[0D,10,CycleMask]; T ← LRot1 TT, [] ← rhT, XDisp, BRANCH[ShiftOut12, ShiftOK12], c*, at[0E,10,CycleMask]; T ← RRot1 T, [] ← rhT, XDisp, BRANCH[ShiftOut0, ShiftOK0], c*, at[0F,10,CycleMask]; ShiftOK0: TOS ← T, pRet2, DISP4[MaskTbl], c*; ShiftOK4: TOS ← T LRot4, pRet2, DISP4[MaskTbl], c*; ShiftOK8: TOS ← T LRot8, pRet2, DISP4[MaskTbl], c*; ShiftOK12: TOS ← T LRot12, pRet2, DISP4[MaskTbl], c*; {Here if no pending branch on entry to CycleMask (magnitude of shift count greater than 15). stackP has already been decremented--check for underflow at NegIB.} ShiftOut0: CANCELBR[ShiftOut, 0F], c3; ShiftOut4: CANCELBR[ShiftOut, 0F], c3; ShiftOut8: CANCELBR[ShiftOut, 0F], c3; ShiftOut12: CANCELBR[ShiftOut, 0F], c3; ShiftOut: TOS ← 0, GOTO[NegIB], c1; { MaskTbl SUBROUTINE first cycle = c* , one cycle long This subroutine generates a right justified mask. of n ones given n (n = 1 gives 1, n = 8 gives 00FF and n = 16 gives FFFF). The subroutine may also be used to generate a left justified mask. REGISTERS Rn number of 1 bits desired in mask (0 means 16) mask where the mask is generated CALLING SEQUENCES For a right justified mask [] ← Rn - 1, YDisp ,c1; [] ← retnum, XDisp, DISP4[MaskTbl] ,c2; {rtn here} Noop ,c1, at[retnum,10,MaskRet]; For a left justified mask [] ← 0 - Rn, YDisp ,c2; [] ← retnum, XDisp, DISP4[MaskTbl] ,c3; {rtn here} mask ← RShift1 ~mask, SE ← 1 ,c2, at[retnum,10,MaskRet]; RETURNS THRU MaskRet } MaskTbl: TT ← 1, RET[MaskRet], c*, at[0,10,MaskTbl]; TT ← 3, RET[MaskRet], c*, at[1,10,MaskTbl]; TT ← 7, RET[MaskRet], c*, at[2,10,MaskTbl]; TT ← 0F, RET[MaskRet], c*, at[3,10,MaskTbl]; TT ← 1F, RET[MaskRet], c*, at[4,10,MaskTbl]; TT ← 3F, RET[MaskRet], c*, at[5,10,MaskTbl]; TT ← 7F, RET[MaskRet], c*, at[6,10,MaskTbl]; TT ← 0FF, RET[MaskRet], c*, at[7,10,MaskTbl]; TT ← LShift1 0FF, SE←1, RET[MaskRet] {TT ← 1FF}, c*, at[8,10,MaskTbl]; TT ← RShift1 u7FF, RET[MaskRet] {TT ← 3FF}, c*, at[9,10,MaskTbl]; TT ← u7FF, RET[MaskRet] {TT ← 7FF}, c*, at[0A,10,MaskTbl]; TT ← RShift1 u1FFF, RET[MaskRet] {TT ← FFF}, c*, at[0B,10,MaskTbl]; TT ← u1FFF, RET[MaskRet] {TT ← 1FFF}, c*, at[0C,10,MaskTbl]; TT ← u3FFF, RET[MaskRet] {TT ← 3FFF}, c*, at[0D,10,MaskTbl]; TT ← RShift1 (~TT xor TT), RET[MaskRet] {TT ← 7FFF}, c*, at[0E,10,MaskTbl]; TT ← ~TT xor TT, RET[MaskRet] {TT ← FFFF}, c*, at[0F,10,MaskTbl];