{File name: GrayBltSubs.mc Description: Common subroutines for Bank1 opcodes. Author: JPM Created: May 29, 1986 Last Revised: October 14, 1986 -- JPM -- add comments August 7, 1986 -- JPM -- generalize subroutine & register names (e.g. MapSrc instead of MapGrSrc) August 5, 1986 -- JPM -- set stackP in LoadGTable July 17, 1986 -- JPM -- rename Incr/DecrVA to BumpByteVA/BumpByteVANeg July 14, 1986 -- JPM -- change meaning of rTemp parameter to LoadGTable, add label LoadGTableSideDoor July 11, 1986 -- JPM -- remove GMFFault (now in Bank1Misc.mc and renamed Bank1Fault) July 10, 1986 -- JPM -- fix bug in MapGrDest (must mask extraneous XWtOKDisp bits); invert rTemp return from Incr/DecrVA; add forced branch to returns from map fix June 26, 1986 -- JPM -- add IncrVA and DecrVA; redo MapGrSrc and MapGrDest June 13, 1986 -- JPM -- use new register names June 12, 1986 -- JPM -- fix LRotateN to do L0Disp before dispatching on RMaskNNNN; change MapGrSrc and MapGrDest to use rh/r regs instead of u regs} { Copyright (C) 1986 by Xerox Corporation. All rights reserved.} {LoadTable: for loading any 16-word-aligned table into stack regs} {Parameters: [rhVirtualH, rVirtualL] contains virtual address of last word of table rTemp contains table size minus 1 (incremented by 2 for last U-reg index) Scratch regs: [rhSrcReal, rSrcReal] used for real address of table words rCount and Q used for interim storage of data L1 used for map fix call Initial condition: Map started in cycle 1 on virtual page Return: L0 used for return from subroutine} LoadTable: rTemp ← rTemp + 2, L1 ← 0, push, c2; LoadTableSideDoor: rhSrcReal ← rSrcReal ← MD, XRefBr, c3; LTa: MAR ← Q ← [rhSrcReal, rVirtualL + 0], BRANCH[TableFix,$,2], c1, at[0,10,MFRtn]; rSrcReal ← Q, stackP ← rTemp, c2; rCount ← MD, c3; LTLoop: MAR ← rSrcReal ← [rhSrcReal, rSrcReal - 1], NibCarryBr, c1; Ybus ← rTemp, AltUaddr, rTemp ← rTemp - 1, L0Disp, BRANCH[LTEnd,$,2], c2; uyStack ← rCount, rCount ← MD, CANCELBR[LTLoop,0F], c3; LTEnd: uyStack ← rCount, DISP4[LoadTableRtn], c3; TableFix: CALL[MapReadFix], c2; {fault return from MapReadFix comes here} uFaultParm1 ← Q, CANCELBR[Bank1Fault,0F], c2, at[0,10,MFFaultRtn]; {MapSrc: map source virtual page to real, check flags} {Parameters: [rhVirtualH, rVirtualL] contains virtual address of source Scratch regs: Q used for interim storage of data Return: [rhSrcReal, rSrcReal] loaded with real address of source L0 used for return from subroutine} MapSrc: Map ← [rhVirtualH, rVirtualL], c1; L1 ← 1, c2; rhSrcReal ← rSrcReal ← MD, XRefBr, c3; MAR ← Q ← [rhSrcReal, rVirtualL + 0], L0Disp, BRANCH[MSFix,$,2], c1, at[1,10,MFRtn]; rSrcReal ← Q, RET[MapSrcRtn], c2; MSFix: CANCELBR[MapReadFix,0F], c2; {fault return from MapReadFix comes here} uFaultParm1 ← Q, RET[MapSrcFault], c2, at[1,10,MFFaultRtn]; {MapDst: map destination virtual page to real, check flags} {Parameters: [rhVirtualH, rVirtualL] contains virtual address of destination Scratch regs: Q used for interim storage of data Return: [rhDstReal, rDstReal] loaded with real address of destination L0 used for return from subroutine} MapDst: Map ← [rhVirtualH, rVirtualL], c1; L1 ← 2, c2; rhDstReal ← rDstReal ← MD, XWtOKDisp, c3; MAR ← Q ← [rhDstReal, rVirtualL + 0], L0Disp, BRANCH[MDFix,$,0D], c1, at[2,10,MFRtn]; rDstReal ← Q, RET[MapDstRtn], c2; MDFix: CANCELBR[MapWriteFix,0F], c2; {fault return from MapWriteFix comes here} uFaultParm1 ← Q, RET[MapDstFault], c2, at[2,10,MFFaultRtn]; MapReadFix: Xbus ← rSrcReal LRot0, XwdDisp, c3; Map ← [rhVirtualH, rVirtualL], DISP2[MFRa], c1; MFRa: MDR ← rSrcReal or map.referenced, L1Disp, GOTO[MFb], c2, at[0,4]; MDR ← rSrcReal or map.referenced, L1Disp, GOTO[MFb], c2, at[1,4,MFRa]; MDR ← rSrcReal or map.referenced, L1Disp, GOTO[MFb], c2, at[2,4,MFRa]; T ← qPageFault, GOTO[MFc], c2, at[3,4,MFRa]; MFb: Xbus ← 3, XDisp, RET[MFRtn], c3; MFc: uFaultParm0 ← rVirtualL, L1Disp, c3; Q ← rhVirtualH, L0Disp, RET[MFFaultRtn], c1; MapWriteFix: Xbus ← rDstReal LRot0, XwdDisp, c3; Map ← [rhVirtualH, rVirtualL], DISP2[MFWa], c1; MFWa: MDR ← rDstReal or map.rd, L1Disp, GOTO[MFb], c2, at[0,4]; T ← qWriteProtect, GOTO[MFc], c2, at[1,4,MFWa]; MDR ← rDstReal or map.rd, L1Disp, GOTO[MFb], c2, at[2,4,MFWa]; T ← qPageFault, GOTO[MFc], c2, at[3,4,MFWa]; {BumpByteVA: Increment virtual byte address} {BumpByteVANeg: Decrement virtual byte address} {Parameters: [rhVirtualH, rVirtualL] contains virtual word address rTemp contains byte increment or decrement (branch to BumpByteVA if positive, BumpByteVANeg if negative) Execution: 5 cycles starting from anywhere Return: [rhVirtualH, rVirtualL] updated to new word address Q also has contents of rhVirtualH rTemp contains inverted byte offset L1 used for return from subroutine} BumpByteVA: rTemp ← DRShift1 rTemp, SE ← 0, GOTO[IncrDecrVA], c*; BumpByteVANeg: rTemp ← DRShift1 rTemp, SE ← 1, NegBr, c*; IncrDecrVA: rVirtualL ← rVirtualL + rTemp, CarryBr, BRANCH[IncrVAChkCarry,DecrVAChkCarry], c*; IncrVAChkCarry: rTemp ← DLShift1 ~rTemp xor rTemp, BRANCH[IncrVANoCarry,IncrVACarry], c*; DecrVAChkCarry: rTemp ← DLShift1 ~rTemp xor rTemp, BRANCH[DecrVANoCarry,DecrVACarry], c*; IncrVANoCarry: Q ← rhVirtualH, L1Disp, GOTO[BumpByteVAEnd], c*; IncrVACarry: Q ← rhVirtualH + 1, LOOPHOLE[byteTiming], L1Disp, GOTO[BumpByteVAEnd], c*; DecrVANoCarry: Q ← rhVirtualH - 1, LOOPHOLE[byteTiming], L1Disp, GOTO[BumpByteVAEnd], c*; DecrVACarry: Q ← rhVirtualH, L1Disp, GOTO[BumpByteVAEnd], c*; BumpByteVAEnd: rhVirtualH ← Q LRot0, RET[BumpByteVARtn], c*; {LRotateN: does LRotN, and also creates an N-bit right-justified mask} {Parameters: Q contains data rhTemp contains N (1 - 10H) Execution: 5 cycles starting from anywhere Return: rTemp contains rotated data rMaskN contains N-bit right-justified mask L0 used for return from subroutine} LRotateN: rTemp ← LRot1 Q, Xbus ← rhTemp, XDisp, c*; rTemp ← LRot1 rTemp, Xbus ← rhTemp, XDisp, DISP4[LRotXXNN,0C], c*; rTemp ← Q, Xbus ← rhTemp, XDisp, DISP4[LRotNNXX,3], c*, at[0C,10,LRotXXNN]; rTemp ← LRot1 Q, Xbus ← rhTemp, XDisp, DISP4[LRotNNXX,3], c*, at[0D,10,LRotXXNN]; rTemp ← rTemp, Xbus ← rhTemp, XDisp, DISP4[LRotNNXX,3], c*, at[0E,10,LRotXXNN]; rTemp ← LRot1 rTemp, Xbus ← rhTemp, XDisp, DISP4[LRotNNXX,3], c*, at[0F,10,LRotXXNN]; rTemp ← rTemp LRot0, L0Disp, DISP4[RMaskNNNN], c*, at[3,10,LRotNNXX]; rTemp ← rTemp LRot4, L0Disp, DISP4[RMaskNNNN], c*, at[7,10,LRotNNXX]; rTemp ← rTemp LRot8, L0Disp, DISP4[RMaskNNNN], c*, at[0B,10,LRotNNXX]; rTemp ← rTemp LRot12, L0Disp, DISP4[RMaskNNNN], c*, at[0F,10,LRotNNXX]; {RMaskN: creates an N-bit right-justified mask} {Parameters: rhTemp contains N (1 - 10H) Execution: 3 cycles starting from anywhere Return: rMaskN contains mask L0 used for return from subroutine} RMaskN: Xbus ← rhTemp, XDisp, c*; L0Disp, DISP4[RMaskNNNN],{note that 10H causes a 0 disp} c*; rMaskN ← 1, RET[RMaskNRtn], c*, at[1,10,RMaskNNNN]; rMaskN ← 3, RET[RMaskNRtn], c*, at[2,10,RMaskNNNN]; rMaskN ← 7, RET[RMaskNRtn], c*, at[3,10,RMaskNNNN]; rMaskN ← 0F, RET[RMaskNRtn], c*, at[4,10,RMaskNNNN]; rMaskN ← 1F, RET[RMaskNRtn], c*, at[5,10,RMaskNNNN]; rMaskN ← 3F, RET[RMaskNRtn], c*, at[6,10,RMaskNNNN]; rMaskN ← 7F, RET[RMaskNRtn], c*, at[7,10,RMaskNNNN]; rMaskN ← 0FF, RET[RMaskNRtn], c*, at[8,10,RMaskNNNN]; rMaskN ← LShift1 0FF, SE←1, RET[RMaskNRtn] {rMaskN ← 1FF}, c*, at[9,10,RMaskNNNN]; rMaskN ← RShift1 u7FF, RET[RMaskNRtn] {rMaskN ← 3FF}, c*, at[0A,10,RMaskNNNN]; rMaskN ← u7FF, RET[RMaskNRtn] {rMaskN ← 7FF}, c*, at[0B,10,RMaskNNNN]; rMaskN ← RShift1 u1FFF, RET[RMaskNRtn] {rMaskN ← FFF}, c*, at[0C,10,RMaskNNNN]; rMaskN ← u1FFF, RET[RMaskNRtn] {rMaskN ← 1FFF}, c*, at[0D,10,RMaskNNNN]; rMaskN ← u3FFF, RET[RMaskNRtn] {rMaskN ← 3FFF}, c*, at[0E,10,RMaskNNNN]; rMaskN ← RShift1 (~rMaskN xor rMaskN), RET[RMaskNRtn] {rMaskN ← 7FFF}, c*, at[0F,10,RMaskNNNN]; rMaskN ← ~rMaskN xor rMaskN, RET[RMaskNRtn] {rMaskN ← FFFF}, c*, at[0,10,RMaskNNNN]; {LinkSet: landing spot for link-register setting, via a sequence such as the following: Xbus ← linkval, XDisp, c*; Xbus ← retnum, XDisp, pCalln, DISP4[LinkSet], c*;} RET[LinkSetRtn], c*, at[0,10,LinkSet]; RET[LinkSetRtn], c*, at[1,10,LinkSet]; RET[LinkSetRtn], c*, at[2,10,LinkSet]; RET[LinkSetRtn], c*, at[3,10,LinkSet]; RET[LinkSetRtn], c*, at[4,10,LinkSet]; RET[LinkSetRtn], c*, at[5,10,LinkSet]; RET[LinkSetRtn], c*, at[6,10,LinkSet]; RET[LinkSetRtn], c*, at[7,10,LinkSet]; RET[LinkSetRtn], c*, at[8,10,LinkSet]; RET[LinkSetRtn], c*, at[9,10,LinkSet]; RET[LinkSetRtn], c*, at[0A,10,LinkSet]; RET[LinkSetRtn], c*, at[0B,10,LinkSet]; RET[LinkSetRtn], c*, at[0C,10,LinkSet]; RET[LinkSetRtn], c*, at[0D,10,LinkSet]; RET[LinkSetRtn], c*, at[0E,10,LinkSet]; RET[LinkSetRtn], c*, at[0F,10,LinkSet];