{ File name bbSubs.mc Last edited by I. Yamaura: 27-Nov-84 18:06:45: Change for 2M Words At {+++} Last edited by Jim Frandeen: January 12, 1982 4:18 PM: Reverse labels at SLRBack+1 and DLRBack+1. Last edited by Jim Frandeen: January 11, 1982 1:35 PM: Fix at 3,4,mapSFixes. Sandman: January 8, 1982 11:03 AM: init rhVS(VD) from uReg in Src(Dst)VAMod. Last edited by Jim Frandeen: August 20, 1981 2:18 PM: Change for new Assembler. Last edited by Jim Frandeen: March 16, 1981 3:52 PM: Change MoverhVtoStkandRestore to fix bug for crossing 64K boundaries. Last edited by Jim Frandeen: March 15, 1981 11:05 PM: Add entry points to RestoreRandRHRegs and rearrange for new Block.mc that includes Checksum. Last edited by Don Charnley: February 26, 1981 2:39 PM: Make MoverhVToStkandRestore smaller for new stack size. Last edited by Jim Frandeen: February 24, 1981 8:46 PM: Add entry points to RestoreRandRHRegs and rearrange for new Block.mc. Created by: Don Charnley January, 1980 Description: BitBlt op-code }(1764)\f1 { dT SUBROUTINE first cycle = c* , one cycle long This subroutine is used to aid in loading a link register. REGISTERS rL value to place in link register Lx link register to be loaded CALLING SEQUENCE To load a link register [] _ rL, YDisp ,c2; [] _ retnum, Lx _ 0, XDisp, DISP4[dT] ,c3; {rtn here} Noop ,c2, at[retnum,10,dTrets]; RETURNS THRU dTRets } dT: {0} RET[dTRets] ,c*, at[0,10,dT]; {1} RET[dTRets] ,c*, at[1,10,dT]; {2} RET[dTRets] ,c*, at[2,10,dT]; {3} RET[dTRets] ,c*, at[3,10,dT]; {4} RET[dTRets] ,c*, at[4,10,dT]; {5} RET[dTRets] ,c*, at[5,10,dT]; {6} RET[dTRets] ,c*, at[6,10,dT]; {7} RET[dTRets] ,c*, at[7,10,dT]; {8} RET[dTRets] ,c*, at[8,10,dT]; {9} RET[dTRets] ,c*, at[9,10,dT]; {0A} RET[dTRets] ,c*, at[0A,10,dT]; {0B} RET[dTRets] ,c*, at[0B,10,dT]; {0C} RET[dTRets] ,c*, at[0C,10,dT]; {0D} RET[dTRets] ,c*, at[0D,10,dT]; {0E} RET[dTRets] ,c*, at[0E,10,dT]; {0F} RET[dTRets] ,c*, at[0F,10,dT]; { MoverhVToStkandRestore SUBROUTINE length = 3 clicks This subroutine is used to move the rhV registers into the stack. USES L0 caller MOVES Rbb1 to UDstBit Q to USrcBit EXITS TO RestoreRandRHRegs SUBROUTINE } MoverhVToStkandRestore: rhL _ UrhLsave, GOTO[RestoreBlockRegsC3], ,c*{c1}, at[3,8,MoverhVToStkandRestore]; { RestoreRandRHRegs SUBROUTINE length = 2 1/3 clicks This subroutine is used to restore the R registers and rh registers which were saved at the entry into BitBlt. USES L0 caller RESTORES L from ULsave G from UGsave PC from UPCsave rhMDS from UrhMDSsave rhPC from UrhPCsave rhG from UrhGsave rhL from UrhLsave RETURNS THRU RestoreCallers RestoreBlockRegs entries are used by Block.mc in order to end up on the right cycle. Block.mc saves all registers but does not use them all. } RestoreRandRHRegs: rhL _ UrhLsave ,c*{c1}, at[2,8, LSEPReturn]; RestoreBlockRegsC3: rhPC _ UrhPCsave ,c*{c2}; RestoreBlockRegsC2: rhMDS _ UrhMDSsave ,c*{c3}; RestoreBlockRegsC1: rhG _ UrhGsave ,c*{c1}; RestoreBlockRegsC3Initial: {This entry can be used from Block only if rhG has not yet been modified.} PC _ UPCsave ,c*{c2}; G _ UGsave, L0Disp ,c*{c3}; L _ ULsave, RET[RestoreCallers] ,c*{c1}; { DstVAMod SUBROUTINE first cycle = c3 , last cycle = c2 Timing: 4 clicks, + 1 if neg, + 1 if rh fix This subroutine is used to modify the destination virtual address. CALLING ARGUMENTS rhWho caller TempBpl increment for the destination address UDstVALo virtual destination page and word UDstBit virtual destination bit rhDstVA virtual destination rh always UPDATES UDstVALo virtual destination page and word UDstBit virtual destination bit rhDstVA virtual destination rh USES Q virtual page and word TempB bit rhRet to call VAModSub CALLS VAModSub RETURNS THRU DstVAModRtn } DstVAMod: Noop ,c*{c1}; Noop ,c*{c2}; rhVD _ UrhVD ,c*{c3}; Q _ UDstVALo ,c*{c1}; TempB _ UDstBit ,c*{c2}; rhRet _ VAaRet, CALL[VAMod] ,c*{c3}; {VAMod subroutine here {2 or 3 clicks} ,c*{c1}-c*{c3};} {return here if rh needs fix} VD _ UrhVD ,c*{c1}, at[Or[VAaRet,1],8,VAModRet]; VD _ VD + TempBpl ,c*{c2}; UrhVD _ VD ,c*{c3}; Noop ,c*{c1}; fixrhVD: [] _ rhRet, XDisp ,c*{c2}; rhVD _ VD LRot0, DISP3{RET}[VAModRet] ,c*{c3}; {return here if no rh fix or after rh fix} UDstVALo _ Q ,c*{c1}, at[VAaRet,8,VAModRet]; DstVAExit: [] _ rhWho, XDisp ,c*{c2}; UDstBit _ TempB, DISP2{RET}[DstVAModRet] ,c*{c3}; { SrcVAMod SUBROUTINE first cycle = c3 , last cycle = c2 Timing: 4 clicks, + 1 if neg, + 1 if rh fix This subroutine is used to modify the source virtual address. CALLING ARGUMENTS rhWho caller TempBpl increment for the source address USrcVALo virtual source page and word USrcBit virtual source bit rhSrcVA virtual source rh always UPDATES USrcVALo virtual source page and word USrcBit virtual source bit rhSrcVA virtual source rh USES Q virtual page and word TempB bit rhRet to call VAModSub and SrcRemap CALLS VAModSub RETURNS THRU SrcVAModRtn } SrcVAMod: Noop ,c*{c1}; Noop ,c*{c2}; rhVS _ UrhVS ,c*{c3}; Q _ USrcVALo ,c*{c1}; TempB _ USrcBit ,c*{c2}; rhRet _ VAbRet, CALL[VAMod] ,c*{c3}; {VAMod subroutine here {2 or 3 clicks} ,c*{c1}-c*{c3};} {return here if rh needs fix} VS _ UrhVS ,c*{c1}, at[Or[VAbRet,1],8,VAModRet]; VS _ VS + TempBpl ,c*{c2}; UrhVS _ VS ,c*{c3}; Noop ,c*{c1}; fixrhVS: [] _ rhRet, XDisp ,c*{c2}; rhVS _ VS LRot0, DISP3{RET}[VAModRet] ,c*{c3}; {return here if no rh fix or after fix} USrcVALo _ Q ,c*{c1}, at[VAbRet,8,VAModRet]; SrcVAExit: [] _ rhWho, XDisp ,c*{c2}; USrcBit _ TempB, DISP2{RET}[SrcVAModRet] ,c*{c3}; { VAMod SUBROUTINE first cycle = c3 , last cycle = c2 Timing: 2 clicks, + 1 if neg This subroutine is used to modify a virtual address. CALLING ARGUMENTS rhRet caller Q virtual page and word TempBpl increment for the address TempB bit always UPDATES Q virtual page and word TempB bit RETURNS TempBpl modifier for rh } VAMod: TempB _ TempB + TempBpl, NibCarryBr, GOTO[VAmod1] ,c*{c1}; VAmod1: TempBpl _ TempBpl and ~0F, NegBr, BRANCH[oldWord, nextWord] ,c*{c2}; oldWord: TempBpl _ TempBpl LRot12, BRANCH[oldWPos, oldWNeg] ,c*{c3}; nextWord: TempBpl _ TempBpl LRot12, BRANCH[nextWPos, nextWNeg] ,c*{c3}; oldWPos: Q _ Q + TempBpl, CarryBr, GOTO[bPP] ,c*{c1}; bPP: [] _ rhRet, XDisp, BRANCH[oldPSeg, newPSeg] ,c*{c2}; nextWPos: Q _ Q + TempBpl + 1, CarryBr, GOTO[bPP] ,c*{c1}; oldWNeg: TempBpl _ TempBpl LRot4 ,c*{c1}; TempBpl _ TempBpl or 0F ,c*{c2}; TempBpl _ TempBpl LRot12 ,c*{c3}; Q _ Q + TempBpl, CarryBr ,c*{c1}; bPN: [] _ rhRet, XDisp, BRANCH[newNSeg, oldNSeg] ,c*{c2}; nextWNeg: TempBpl _ TempBpl LRot4 ,c*{c1}; TempBpl _ TempBpl or 0F ,c*{c2}; TempBpl _ TempBpl LRot12 ,c*{c3}; Q _ Q + TempBpl + 1, CarryBr, GOTO[bPN] ,c*{c1}; oldPSeg: TempBpl _ 0, DISP3{RET}[VAModRet] ,c*{c3}; newPSeg: TempBpl _ 1, DISP3{RET}[VAModRet,1] {signal rh update} ,c*{c3}; oldNSeg: TempBpl _ 0, DISP3{RET}[VAModRet] ,c*{c3}; newNSeg: TempBpl _ {-1}TempBpl xor ~TempBpl, DISP3{RET}[VAModRet,1] {signal rh update} ,c*{c3}; { SrcLRemap SUBROUTINE first cycle = c1 , last cycle = c3 This subroutine is used to remap the source virtual address. CALLING ARGUMENTS rhRet caller USrcVALo virtual source page rhVS virtual source rh always UPDATES SrcA real source page and word rhSrcA real source rh USES UQSave saved value of Q UVSsave saved contents of VS uT saved contents or rhVS RETURNS THRU SrcRemapReturn } SrcLRemap: UQSave _ Q ,c1; UXsave _ VS ,c2; VS _ USrcVALoSav, dirDisp ,c3; Q _ 0FF + 1, dirDISP[SrcInc] ,c1; SLRFor: VS _ VS + Q, CarryBr ,c2, at[dir.forward,dirM,SrcInc]; Q _ rhVS + 1, LOOPHOLE[byteTiming], BRANCH[nofixSRhP,fixSRhP] ,c3; fixSRhP: rhVS _ Q LRot0 ,c1; fixRSh: Noop ,c2; Noop ,c3; nofixSRhP: Map _ USrcVALoSav _ [rhVS, VS], GOTO[mpS1] ,c1; SLRBack: VS _ VS - Q, CarryBr ,c2, at[dir.backwards,dirM,SrcInc]; Q _ rhVS - 1, LOOPHOLE[byteTiming], BRANCH[fixSRhN,nofixSRhN] ,c3; fixSRhN: rhVS _ Q LRot0, GOTO[fixRSh] ,c1; nofixSRhN: Map _ USrcVALoSav _ [rhVS, VS], GOTO[mpS1] ,c1; mpS1: Q _ SrcA and 0FF ,c2; SrcA _ MD, rhSrcA _ MD, XRefBr ,c3; Noop, BRANCH[fixSMap, nofixSMap] ,c1; nofixSMap: SrcA _ SrcA and ~0FF ,c2; SrcA _ SrcA or Q ,c3; mfsR: Q _ UQSave ,c1; [] _ rhRet, XDisp ,c2; VS _ UXsave, RET[SrcRemapReturn] ,c3; fixSMap: Noop ,c2; [] _ SrcA LRot0, XwdDisp ,c3; Map _ [rhVS, VS], DISP2[mapSFixes] ,c1; mapSFixes: MDR _ SrcA or 10, GOTO[mfS1] ,c2, at[0,4,mapSFixes]; MDR _ SrcA or 10, GOTO[mfS1] ,c2, at[1,4,mapSFixes]; MDR _ SrcA or 10, GOTO[mfS1] ,c2, at[2,4,mapSFixes]; GOTO[mfS1] ,c2, at[3,4,mapSFixes]; mfS1: SrcA _ SrcA and ~0FF ,c3; SrcA _ SrcA or Q ,c1; Noop ,c2; GOTO[mfsR] ,c3; { DstLRemap SUBROUTINE first cycle = c1 , last cycle = c3 This subroutine is used to remap the source virtual address. CALLING ARGUMENTS rhRet caller UDstVALo virtual source page rhVD virtual source rh always UPDATES DstA real source page and word rhDstA real source rh USES UQSave saved value of Q UVDsave saved contents of VD uT saved contents or rhVD RETURNS THRU DstRemapReturn } DstLRemap: UQSave _ Q, c1; UXsave _ VD, c2; VD _ UDstVALoSav, dirDisp, c3; Q _ 0FF + 1, dirDISP[DstInc], c1; DLRFor: VD _ VD + Q, CarryBr, c2,at[dir.forward,dirM,DstInc]; Q _ rhVD + 1, LOOPHOLE[byteTiming], BRANCH[nofixDRhP,fixDRhP], c3; fixDRhP: rhVD _ Q LRot0, c1; fixRDh: Noop, c2; Noop, c3; nofixDRhP: Map _ UDstVALoSav _ [rhVD, VD], GOTO[mpD1], c1; DLRBack: VD _ VD - Q, CarryBr, c2,at[dir.backwards,dirM,DstInc]; Q _ rhVD - 1, LOOPHOLE[byteTiming], BRANCH[fixDRhN,nofixDRhN], c3; fixDRhN: rhVD _ Q LRot0, GOTO[fixRDh], c1; nofixDRhN: Map _ UDstVALoSav _ [rhVD, VD], GOTO[mpD1], c1; mpD1: Q _ DstA and 0FF, c2; DstA _ MD, rhDstA _ MD, XRefBr, c3; Noop, BRANCH[fixDMap, nofixDMap], c1; nofixDMap: DstA _ DstA and ~0FF, c2; DstA _ DstA or Q, c3; mfdR: Q _ UQSave, c1; [] _ rhRet, XDisp, c2; VD _ UXsave, RET[DstRemapReturn], c3; fixDMap: Noop ,c2; [] _ DstA LRot0, XwdDisp, c3; Map _ [rhVD, VD], DISP2[mapDFixes], c1; mapDFixes: MDR _ DstA or 30, GOTO[mfD1], c2, at[0,4,mapDFixes]; {+++ Change for 2M +++} MDR _ DstA or 30, GOTO[mfD1], c2, at[1,4,mapDFixes]; {+++ Change for 2M +++} {page fault cant happen. Checked before entering loop} {page fault cant happen. Checked before entering loop} mfD1: DstA _ DstA and ~0FF, c3; DstA _ DstA or Q, c1; Noop ,c2; GOTO[mfdR], c3; { DstMap SUBROUTINE first cycle = c3 , last cycle = c3 Timing: 2 1/3 clicks, + 1 if fix map flags This subroutine is used to map the destination virtual address. CALLING ARGUMENTS rhRet caller UDstVALo virtual destination rhVD virtual destination rh always UPDATES DstA real destination page and word rhDstA real destination rh UDstVALoSav virtual destination uses as a temp Q real destination page and word RETURNS THRU DstMapRet } DstMap: VD _ UDstVALoSav ,c3; DstMapSpec: Map _ [rhVD, VD], c1; UDstVALoSav _ VD, c2; DstA _ MD, rhDstA _ MD, XwdDisp, c3; {+++ Change for 2M +++} DMapRef: MAR _ Q _ [rhDstA, VD + 0], DISP2[upDMap], c1; {+++ Change for 2M +++} DMapOK: [] _ rhRet, XDisp, c2,at[1,4,upDMap]; {+++ Change for 2M +++} DstA _ Q, DISP2{RET}[DstMapRet], c3; upDMap: GOTO[upDMap1], c2,at[0,4,upDMap]; {+++ Change for 2M +++} GOTO[upDMap1], c2,at[2,4,upDMap]; {+++ Change for 2M +++} GOTO[upDMap1], c2,at[3,4,upDMap]; {+++ Change for 2M +++} upDMap1: [] _ DstA LRot0, XwdDisp, c3; Map _ [rhVD, VD], DISP2[upDMapHere], c1; upDMapHere: MDR _ DstA or 30, GOTO[mapD], c2,at[0,4,upDMapHere]; {+++ Change for 2M +++} MDR _ DstA or 30, GOTO[mapD], c2,at[1,4,upDMapHere]; {+++ Change for 2M +++} Q _ qWriteProtect, GOTO[DFault], c2,at[2,4,upDMapHere]; Q _ qPageFault, GOTO[DFault], c2,at[3,4,upDMapHere]; mapD: Xbus _ 1, XDisp, GOTO[DMapRef], c3; {+++ Change for 2M +++} { SrcMap SUBROUTINE first cycle = c3 , last cycle = c3 Timing: 2 1/3 clicks, + 1 if fix map flags This subroutine is used to map the source virtual address. CALLING ARGUMENTS rhRet caller USrcVALo virtual source rhVS virtual source rh always UPDATES SrcA real source page and word rhSrcA real source rh USrcVALoSav virtual destination uses as a temp Q real destination page and word RETURNS THRU SrcMapRet } SrcMap: VS _ USrcVALoSav ,c3; SrcMapSpec: Map _ [rhVS, VS] ,c1; USrcVALoSav _ VS ,c2; SrcA _ MD, rhSrcA _ MD, XRefBr ,c3; SMapRef: MAR _ Q _ [rhSrcA, VS + 0], BRANCH[upSMap, SMapOK] ,c1; SMapOK: [] _ rhRet, XDisp ,c2; SrcA _ Q, DISP3{RET}[SrcMapRet] ,c3; upSMap: Noop ,c2; [] _ SrcA LRot0, XwdDisp ,c3; Map _ [rhVS, VS], DISP2[upSMapHere] ,c1; upSMapHere: MDR _ SrcA or 10, GOTO[mapS] ,c2, at[0,4,upSMapHere]; MDR _ SrcA or 10, GOTO[mapS] ,c2, at[1,4,upSMapHere]; MDR _ SrcA or 10, GOTO[mapS] ,c2, at[2,4,upSMapHere]; Q _ qPageFault, GOTO[SFault] ,c2, at[3,4,upSMapHere]; mapS: [] _ 0, ZeroBr, GOTO[SMapRef] ,c3; { SavebbRegs SUBROUTINE length = 2 2/3 clicks This subroutine is used to move the rh registers in U. Note that the caller MUST save L before calling. MOVES TOS STK G to UGsave rhG UrhGsave PC to UPCsave rhPC UrhPCsave L UrhLsave rhL UrhLsave rhMDS UrhMDSsave EXITS TO SavebbRegsRet } SavebbRegs: L _ rhL ,c*{c2}, at[0,10,SavebbRegs]; SaveBlockRegs:: PC _ PC - 1 ,c*{c3}; SaveBlockRegsx: {Radr same as Ublock containing following Uregs} UPCsave _ PC ,c*{c1}; {the following Uregs are at "xB" to allow "_ rh"} UGsave _ G ,c*{c2}; UrhLsave _ L, G _ rhG ,c*{c3}; UrhGsave _ G, PC _ rhPC ,c*{c1}; UrhPCsave _ PC, TOS _ rhMDS, pRet2, ,c*{c2}; UrhMDSsave _ TOS, RET[SavebbRegsRet], ,c*{c3}; {END}(0,5080)(1,5842)(2,15240)(3,16510)(4,17780)\f1 2g54G360g54G566g54G214g54G77b32B4g54G485g54G52b1B358g54G582g54G627g54G555g54G623g54G322g54G1112g54G388g54G194i20I234i20I780g54G2f0 3f1 149f0 3f1 27f0 2f1 35f0 3f1 30f0 3f1 48f0 2f1 23f0 2f1 24f0 2f1 15f0 3f1 12g54G3f0 3f1 34f0 2f1 7f0 2f1 4f0 3f1 45f0 3f1 18f0 2f1 3f0 2f1 39f0 3f1 13f0 2f1 6i20I45f0 2f1 64f0 3f1 13f0 2f1 2f0 2f1 29f0 2f1 3f0 2f1 41f0 3f1 13f0 2f1 6i20I45f0 2f1 48f0 3f1 13f0 2f1 2f0 2f1 31f0 3f1 16f0 3f1 10f0 3f1 71f0 3f1 4f0 3f1 17f0 3f1 4f0 3f1 60f0 2f1 15f0 3f1 44f0 3f1 33f0 2f1 2f0 2f1 43f0 3f1 52f0 3f1 165f0 3f1 4f0 3f1 18f0 3f1 4f0 3f1 45g54G438g54G646g54G413g54G240b1B391g54G286g54G