{ File name Kiku2MCommonSubs.mc Description: Emulator Subroutines Author: don charnley Created: March 28, 1980 Fasnacht, 18-Jul-83 15:42:32 Change WLMapFix for double byte codes Sandman, September 23, 1981 4:41 PM New Instruction Set Last edited: Garner, April 11, 1980 4:52 PM Last edited: Johnsson, January 20, 1981 10:22 AM Last edited: Charnley, October 8, 1980 9:23 AM Last edited: I. Yamaura, 1-Nov-84 10:50:55 Change for 2M word at {+++}} {***************************************************************************** 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} RMapFix: Xbus _ Rx LRot0, XwdDisp, L3 _ L3.rhMDS.Q, c3; Map _ [rhMDS, Q], Xbus _ 0, XDisp, DISP2[RMapa], c1; RCMapFix: Xbus _ Rx LRot0, XwdDisp, L3 _ L3.rhTT.TT, c3; Map _ [rhTT, TT], Xbus _ 0, XDisp, DISP2[RMapa], c1; RMapa: MDR _ Rx or 10, L0Disp, DISP4[RMapb], c2, at[0,10]; MDR _ Rx or 10, L0Disp, DISP4[RMapb], c2, at[1,10,RMapa]; MDR _ Rx or 10, L0Disp, DISP4[RMapb], c2, at[2,10,RMapa]; IBEmptyTrap: T _ qPageFault, L1Disp, DISP4[RTrap], c2, at[3,10,RMapa]; RMapb: Xbus _ 1, XDisp, RET[RMFRtn], c3, at[0,10,RMapb]; RTrap: push, RET[RTrapFix], c3, at[0,10,RTrap]; {***************************************************************************** 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} WMapFix1:{+++ From Kiku2MWrite +++} {+++ Change for 2M +++} Xbus _ Rx LRot0,XwdDisp, L3 _ L3.rhMDS.Q,GOTO[WMapFix0], c3; WMapFix2:{+++ From Kiku2MWrite +++} {+++ Change for 2M +++} Xbus _ Rx LRot0,XwdDisp, L3 _ L3.rhMDS.Q,GOTO[WMapFix0], c3; WMapFix3:{+++ From Kiku2MXfer +++} {+++ Change for 2M +++} Xbus _ Rx LRot0,XwdDisp, L3 _ L3.rhMDS.Q,GOTO[WMapFix0], c3; WMapFix: Xbus _ Rx LRot0,XwdDisp, L3 _ L3.rhMDS.Q, c3; WMapFix0: Map _ [rhMDS,Q], DISP2[WMapa], c1; WMapa: MDR _ Rx or 30, L0Disp, GOTO[WMapb], c2, at[0,4]; {+++ Change for 2M +++} MDR _ Rx or 30, L0Disp, GOTO[WMapb], c2, at[1,4,WMapa]; {+++ Change for 2M +++} T _ qWriteProtect, L1Disp, GOTO[WTrap], c2, at[2,4,WMapa]; T _ qPageFault, L1Disp, GOTO[WTrap], c2, at[3,4,WMapa]; WMapb: Xbus _ 1, XDisp, RET[WMFRtn], c3; {+++ Change for 2M +++} WTrap: push, RET[WTrapFix], c3; {***************************************************************************** Read Long 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; RLMapx: Map _ [rhTT,Q], Xbus _ 1, XDisp, DISP2[RMapa], c1; RLMapb: Xbus _ 1, XDisp, RET[RLMFRtn], c3, at[1,10,RMapb]; RLTrap: push, RET[RLTrapFix], c3, at[1,10,RTrap]; {***************************************************************************** Write Long 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} WLMapFix1:{+++ From Kiku2MWrite +++} {+++ Change for 2M +++} Xbus _ Rx LRot0, XwdDisp, L3 _ L3.rhTT.Q,GOTO[WLMapFix0], c3; WLMapFix2:{+++ From Kiku2MWrite +++} {+++ Change for 2M +++} Xbus _ Rx LRot0, XwdDisp, L3 _ L3.rhTT.Q,GOTO[WLMapFix0], c3; WLMapFix: Xbus _ Rx LRot0, XwdDisp, L3 _ L3.rhTT.Q, c3; WLMapFix0: Map _ [rhTT,Q], L0Disp, DISP2[WLMapa], c1; WLMapa: MDR _ Rx or 30, L0Disp, CANCELBR[WLMapb,0F], LOOPHOLE[wok],c2,at[0,4]; {+++ Change for 2M +++} MDR _ Rx or 30, L0Disp, CANCELBR[WLMapb,0F], LOOPHOLE[wok],c2,at[1,4,WLMapa]; {+++ Change for 2M +++} T _ qWriteProtect, L1Disp, BRANCH[WLTrapD,WLTrap,0E], c2, at[2,4,WLMapa]; T _ qPageFault, L1Disp, BRANCH[WLTrapD,WLTrap,0E], c2, at[3,4,WLMapa]; WLMapb: Xbus _ 1, XDisp, RET[WLMFRtn], c3; {+++ Change for 2M +++} WLTrapD:Noop, RET[WTrapFix], c3; WLTrap: push, RET[WTrapFix], 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"} LGMap: Q _ Q - TT, c1; LGMx: Q _ Q and 0FF, c2; Noop, c3; Map _ Q _ [rhMDS, TT + Q], c1; Noop, c2; Rx _ rhRx _ MD, XRefBr, c3; LGMa: MAR _ [rhRx, Q + 0], BRANCH[LGMUD,$], c1; L2Disp, c2; rhTT _ TT _ MD, RET[LGMRtn], c3; LGMUD: L1_L1.PopDec2, c2; Xbus _ Rx LRot0, XwdDisp, L3 _ L3.rhMDS.Q, c3; Map _ [rhMDS, Q], Xbus _ 2, XDisp, DISP2[RMapa], c1; Xbus _ 1, XDisp, CANCELBR[LGMa,0F], c3, at[2,10,RMapb]; push, RET[RTrapFix], c3, at[2,10,RTrap]; LGMy: Q _ Q - TT, GOTO[LGMx], c1; {***************************************************************************** RTrapFix *****************************************************************************} MacroDef[RTF, at[#1,10,RTrapFix]]; NoFixes: Noop, GOTO[NoMoreFix], c1, RTF[L1.None]; PC _ PC - PC16, GOTO[NoMoreFix], c1, RTF[L1.Dec]; PC _ PC - 1, GOTO[NoMoreFix], c1, RTF[L1.Dec2]; PC _ PC - 1, pop, GOTO[NoMoreFix], c1, RTF[L1.PopDec2]; PC _ PC - PC16, pop, GOTO[NoMoreFix], c1, RTF[L1.PopDec]; PC _ PC - PC16, pop, GOTO[PopFix], c1, RTF[L1.Pop2Dec]; PC _ PC - 1, pop, GOTO[PopFix], c1, RTF[L1.Pop2Dec2]; {***************************************************************************** RLTrapFix *****************************************************************************} MacroDef[RLTF, at[#1,10,RLTrapFix]]; Noop, GOTO[NoMoreFix], c1, RLTF[L1.None]; PC _ PC - PC16, GOTO[NoMoreFix], c1, RLTF[L1.Dec]; PC _ PC - 1, GOTO[NoMoreFix], c1, RLTF[L1.Dec2]; PC _ PC - 1, pop, GOTO[NoMoreFix], c1, RLTF[L1.PopDec2]; PC _ PC - PC16, pop, GOTO[NoMoreFix], c1, RLTF[L1.PopDec]; PC _ PC - PC16, pop, GOTO[PopFix], c1, RLTF[L1.Pop2Dec]; PC _ PC - 1, pop, GOTO[PopFix], c1, RLTF[L1.Pop2Dec2]; push, GOTO[PushFix], c1, RLTF[L1.Push2]; PC _ PC - PC16, push, GOTO[NoMoreFix], c1, RLTF[L1.PushDec]; PC _ PC - 1, push, GOTO[NoMoreFix], c1, RLTF[L1.PushDec2]; push, GOTO[NoMoreFix], c1, RLTF[L1.Push]; PC _ PC - 1 - PC16, GOTO[NoMoreFix], c1, RLTF[L1.Dec3]; {***************************************************************************** WTrapFix fixups *****************************************************************************} MacroDef[WTF, at[#1,10,WTrapFix]]; Noop, GOTO[NoMoreFix], c1, WTF[L1.None]; PC _ PC - PC16, GOTO[NoMoreFix], c1, WTF[L1.Dec]; PC _ PC - 1, GOTO[NoMoreFix], c1, WTF[L1.Dec2]; PC _ PC - 1, pop, GOTO[NoMoreFix], c1, WTF[L1.PopDec2]; PC _ PC - PC16, pop, GOTO[NoMoreFix], c1, WTF[L1.PopDec]; PC _ PC - PC16, pop, GOTO[PopFix], c1, WTF[L1.Pop2Dec]; PC _ PC + PC16, push, GOTO[NoMoreFix], c1, WTF[L1.PushInc]; push, GOTO[PushFix], c1, WTF[L1.Push2]; PC _ PC - PC16, push, GOTO[NoMoreFix], c1, WTF[L1.PushDec]; PC _ PC - 1, push, GOTO[NoMoreFix], c1, WTF[L1.PushDec2]; push, GOTO[NoMoreFix], c1, WTF[L1.Push]; PopOnlyFix: pop, GOTO[NoMoreFix], c1, WTF[L1.Pop]; PC _ PC - 1 - PC16, push, GOTO[NoMoreFix], c1, WTF[L1.PushDec3]; {***************************************************************************** Trap Handling *****************************************************************************} NoMoreFix: L3Disp, GOTO[TrapFixDone], c2; PushFix: push, L3Disp, GOTO[TrapFixDone], c2; PopFix: pop, L3Disp, GOTO[TrapFixDone], c2; TrapFixDone: L3Disp, BRANCH[LowQ, LowTT, 2], c3; LowQ: uFaultParm0 _ Q, BRANCH[HiMDS, HiTT, 1], c1; LowTT: uFaultParm0 _ TT, BRANCH[HiMDS, HiTT, 1], c1; HiMDS: Q _ rhMDS, GOTO[Faultc3], c2; HiTT: 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} Trapc2: GOTO[Trapc3], c2; Trapc3: G _ 0, GOTO[Trapc1], c3; Trapc1: uTrapParm0 _ TT, L2 _ L2.TRAPSpc, c1; 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; 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, GOTO[ShiftOK0], c*, at[0,10,CycleMask]; T _ TT, [] _ rhT, XDisp, GOTO[ShiftOK0], c*, at[1,10,CycleMask]; T _ LRot1 TT, [] _ rhT, XDisp, GOTO[ShiftOK0], c*, at[2,10,CycleMask]; T _ RRot1 T, [] _ rhT, XDisp, GOTO[ShiftOK4], c*, at[3,10,CycleMask]; [] _ rhT, XDisp, GOTO[ShiftOK4], c*, at[4,10,CycleMask]; T _ LRot1 T, [] _ rhT, XDisp, GOTO[ShiftOK4], c*, at[5,10,CycleMask]; T _ LRot1 TT, [] _ rhT, XDisp, GOTO[ShiftOK4], c*, at[6,10,CycleMask]; T _ RRot1 T, [] _ rhT, XDisp, GOTO[ShiftOK8], c*, at[7,10,CycleMask]; [] _ rhT, XDisp, GOTO[ShiftOK8], c*, at[8,10,CycleMask]; T _ LRot1 T, [] _ rhT, XDisp, GOTO[ShiftOK8], c*, at[9,10,CycleMask]; T _ LRot1 TT, [] _ rhT, XDisp, GOTO[ShiftOK8], c*, at[0A,10,CycleMask]; T _ RRot1 T, [] _ rhT, XDisp, GOTO[ShiftOK12], c*, at[0B,10,CycleMask]; [] _ rhT, XDisp, GOTO[ShiftOK12], c*, at[0C,10,CycleMask]; T _ LRot1 T, [] _ rhT, XDisp, GOTO[ShiftOK12], c*, at[0D,10,CycleMask]; T _ LRot1 TT, [] _ rhT, XDisp, GOTO[ShiftOK12], c*, at[0E,10,CycleMask]; T _ RRot1 T, [] _ rhT, XDisp, GOTO[ShiftOK0], c*, at[0F,10,CycleMask]; ShiftOK0: TOS _ T, L2Disp, DISP4[MaskTbl], c*; ShiftOK4: TOS _ T LRot4, L2Disp, DISP4[MaskTbl], c*; ShiftOK8: TOS _ T LRot8, L2Disp, DISP4[MaskTbl], c*; ShiftOK12: TOS _ T LRot12, L2Disp, DISP4[MaskTbl], c*; {***************************************************************************** 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];