{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];