{
File name bbInit1.mc
Description: Modified for Lisp, Mesa BitBlt op-code
Purcell July 14, 1982 10:38 PM Bit offset correction + PC correct (see ***)
Description: Mesa BitBlt op-code
Sandman November 2, 1981 2:28 PM New Instruction Set
Last edited by Jim August 20, 1981 2:20 PM: Fix for new assembler.
Last edited by Jim Frandeen: March 31, 1981 8:39 AM: Change SrcMapRet from Mod 8 to Mod 10.
Last edited by Don Charnley: March 6, 1981 1:48 PM: Fixed PageFault/64K cross interaction problem.
Last edited by Don Charnley: March 3, 1981 4:08 PM: Moved UWidth into stack, no memory reads after int and pf, stack now has 12’d things.
Last edited by Olmstead: February 27, 1981 2:51 PM
Last edited by Don Charnley: February 26, 1981 2:35 PM: Add changes for new stack size to save 10 instructions.
Author: don charnley
Created: January, 1980
}
@BITBLT:{Save R and RH registers}
ULsave ← L, L2 ← 0, CALL[SavebbRegs],,c1;
{SaveRegs subroutine here {2 2/3 Clicks},c2-c3;}
rhType ← Type.normal, push,c1, at[0,10,SavebbRegsRet];
Xbus ← ErrnIBnStkp, XDisp,c2;
Noop, DISP4[HowBigStack,06],c3;
{move BitBltArg to stack and rh}
bbNormEntry: {non-interrupts come here}
{get real address of BitBltArg}
{and insure that it is 0 mod 16}
VS ← UBitBltArg,,c1, at[hbs.2,10,HowBigStack];
{rhVS = rhMDS, so no need to load it}
VS ← VS and ~0{F***}, L2 ← sd.spec,c2;
rhRet ← argMap, CALL[SrcMapSpec],c3;
{SrcMapSpec subroutine here {2 Clicks},c1-c3;}
bbGetArg:{move BitBltArg to U registers}
{rtn here}MAR ← [rhSrcA,SrcA + 8], L0 ← 0,c1, at[argMap,10,SrcMapRet];
CANCELBR[$,0], L0Disp,c2;
MDtoRbb0:Rbb0 ← MD{UWidth}, DISP4[MDtoRbb0Ret],c3;
MAR ← [rhSrcA,SrcA + 0A], L0 ← 1,c1, at[0,10,MDtoRbb0Ret];
UWidth ← Rbb0, CANCELBR[MDtoRbb0,0], L0Disp,c2;
{MDtoRbb0:Rbb0 ← MD{UFlags}, DISP4[MDtoRbb0Ret],c3;}
MAR ← [rhSrcA,SrcA + 3], L0 ← 2,c1, at[1,10,MDtoRbb0Ret];
UFlags ← Rbb0, CANCELBR[MDtoRbb0,0], L0Disp,c2;
{MDtoRbb0:Rbb0 ← MD{UDstBpl}, DISP4[MDtoRbb0Ret],c3;}
MAR ← [rhSrcA,SrcA + 7], L0 ← 3,c1, at[2,10,MDtoRbb0Ret];
UDstBpl ← Rbb0, CANCELBR[MDtoRbb0,0], L0Disp,c2;
{MDtoRbb0:Rbb0 ← MD{SrcBpl}, DISP4[MDtoRbb0Ret],c3;}
MAR ← [rhSrcA,SrcA + 9], L0 ← 4,c1, at[3,10,MDtoRbb0Ret];
USrcBpl ← Rbb0, CANCELBR[MDtoRbb0,0], L0Disp,c2;
{MDtoRbb0:Rbb0 ← MD{Height}, DISP4[MDtoRbb0Ret],c3;}
MAR ← [rhSrcA,SrcA + 0], L0 ← 5,c1, at[4,10,MDtoRbb0Ret];
UHeight ← Rbb0, CANCELBR[MDtoRbb0,0], L0Disp,c2;
{MDtoRbb0:Rbb0 ← MD{DLo}, DISP4[MDtoRbb0Ret],c3;}
MAR ← [rhSrcA,SrcA + 6], L0 ← 8,c1, at[5,10,MDtoRbb0Ret];
UDstVALo ← Rbb0, CANCELBR[MDtoRbb0,0], L0Disp,c2;
{MDtoRbb0:Rbb0 ← MD{SBit}, DISP4[MDtoRbb0Ret],c3;}
MAR ← [rhSrcA,SrcA + 5],c1, at[8,10,MDtoRbb0Ret];
Q ← Rbb0 and 0F, CANCELBR[$,0],c2;
Rbb1 ← MD{SHi},c3;
USrcBit ← Q,c1;
Rbb0 ← Rbb0 and ~0F,c2;
Rbb0 ← Rbb0 LRot12,c3;
MAR ← [rhSrcA,SrcA + 4],c1;
CANCELBR[$,0],c2;
Q ← MD{SLo},c3;
Rbb0 ← Rbb0 + Q, CarryBr,c1;
USrcVALo ← Rbb0, BRANCH[bbbitsrcok, bbbitsrcnok],c2;
bbbitsrcnok:
Rbb1 ← Rbb1 + 1, GOTO[bbbitsrcend],c3;
bbbitsrcok:
GOTO[bbbitsrcend],c3;
bbbitsrcend:
MAR ← [rhSrcA,SrcA + 2], L0 ← 0A,c1;
UrhVS ← Rbb1, CANCELBR[MDtoRbb0,0], L0Disp,c2;
{MDtoRbb0:Rbb0 ← MD{DBit}, DISP4[MDtoRbb0Ret],c3;}
MAR ← [rhSrcA,SrcA + 1],c1, at[0A,10,MDtoRbb0Ret];
Q ← Rbb0 and 0F, CANCELBR[$,0],c2;
Rbb1 ← MD{DHi},c3;
UDstBit ← Q,,c1;
Rbb0 ← Rbb0 and ~0F,c2;
Rbb0 ← Rbb0 LRot12,c3;
Q ← UDstVALo,c1;
Rbb0 ← Rbb0 + Q, CarryBr,c2;
UDstVALo ← Rbb0, BRANCH[bbbitdstok, bbbitdstnok],c3;
bbbitdstnok:
Rbb1 ← Rbb1 + 1, GOTO[bbbitend],c1;
bbbitdstok:
GOTO[bbbitend],c1;
bbbitend:
rhVS ← UrhVS,c2;
UrhVD ← Rbb1,c3;
Ybus ← UFlags, NegBr,c1;
rhVD ← UrhVD, BRANCH[FsetUp,$],c2;
{if direction backward, mod SrcVA and DstVA}
{Note: gray is always forward}
{Backwards SetUp}
TempBpl ← UWidth,c3;
TempBpl ← TempBpl - 1, rhWho ← sdWidth, CALL[DstVAMod],c1;
{DstVAMod subroutine here {4 clicks},c2-c1;}
TempBpl ← UWidth,c2, at[sdWidth,4,DstVAModRet];
TempBpl ← TempBpl - 1, CALL[SrcVAMod],c3;
{SrcVAMod subroutine here {4 clicks},c1-c3;}
{interrupt entry goes thru this code}
{restore rh from u regs}
BandBLTNormEntry:
rhVS ← UrhVS, GOTO[rhfromu],c1, at[hbs.C,10,HowBigStack];
rhVS ← UrhVS, GOTO[rhfromu],c1, at[hbs.D,10,HowBigStack];
rhfromu:rhVD ← UrhVD,c2;
FsetUp:Noop,c3;
TextBltToBitBltEntry:
Rbb3{W} ← UWidth,c1, at[sdWidth,4,SrcVAModRet];
Rbb0{W-1} ← Rbb3{W} - 1, NegBr {test if width = 0},c2;
Rbb2 ← 0F, BRANCH[$,Widtheq0],c3;
Rbb2 ← Rbb2 LRot12,c1;
[] ← Rbb2 and Rbb3, ZeroBr,c2;
Rbb1 ← 8, BRANCH[wnotsmall,wsmall],c3;
wnotsmall:Q ← 2,c1;
Q ← Q or rhType,c2;
rhType ← Q LRot0,c3;
wsmall:Rbb4 ← UFlags, NegBr,c1;
Rbb3 ← Rbb4 LRot4, BRANCH[DirFor,DirBack],c2;
DirFor:Rbb1 ← 0,c3;
Rbb2{W-1} ← Rbb0{W-1}, GOTO[uwwpos],c1;
DirBack:Rbb0 ← 0 - Rbb0, NegBr,c3;
Rbb2{0-(W-1)} ← 0 - Rbb0{W-1}, BRANCH[uwwpos,uwwneg],c1;
uwwpos:Rbb2 ← Rbb2 and ~0F, GOTO[conL13],c2;
uwwneg:Rbb2 ← Rbb2 or 0F, GOTO[conL13],c2;
conL13:Rbb2 ← Rbb2 LRot12{this only used for PgCarry and sign check},c3;
UWidthM1 ← Rbb0,c1;
UWidthW ← Rbb2,c2;
[] ← UHeight, ZeroBr {test if height = 0},c3;
{L3 ← 0,,gr,,0,,sF}
{gr and srcFunc}
Rbb0 ← LRot1 Rbb3, BRANCH[$,Heighteq0],c1;
Rbb0 ← Rbb0 and 3,c2;
Rbb0 ← Rbb0 + 6,c3;
[] ← Rbb0 and 5, YDisp,c1;
Xbus ← dtRet.L3, L3 ← 0, XDisp, DISP4[dT],c2;
{dT subroutine here {1 cycle},c3;}
{dstFunc and dir}
Rbb0 ← Rbb4 LRot8,c1, at[dtRet.L3,10,dTRets];
Rbb0 ← Rbb0 and 6,c2;
[] ← Rbb0 or Rbb1, YDisp,c3;
Xbus ← dtRet.L1, L1 ← 0, XDisp, DISP4[dT],c1;
{dT subroutine here {1 cycle},c2;}
Rbb0 ← UDstBpl,c3, at[dtRet.L1,10,dTRets];
[] ← Rbb0 and 0F, ZeroBr,c1;
Rbb1 ← dbneq0, grDisp, BRANCH[dstwn0,$],c2;
Rbb0 ← USrcBpl, grDISP[srcgrchk],c3;
Xbus ← 1, XDisp, GOTO[srcchk],c1, at[gr.gray,grM,srcgrchk];
[] ← Rbb0 and 0F, ZeroBr, GOTO[srcchk],c1, at[gr.notgray,grM,srcgrchk];
srcchk:Rbb1 ← sbneq0, BRANCH[sbnot0,sbis0],c2;
sbis0:UrefillType ← dbsb0, GOTO[SetUpAllC1],c3;
sbnot0:UrefillType ← Rbb1{sbneq0}, GOTO[SetUpAllC1],c3;
dstwn0:UrefillType ← Rbb1{dbneq0}, CANCELBR[SetUpAllC1,0F],c3;
{ITEM REFILL}
{updateHeight, test if thru}
ItemRefill3:
Rbb0 ← UHeight, L2 ← sd.src,c3;
Rbb0 ← Rbb0 - 1, ZeroBr,c1;
UHeight ← Rbb0, grDisp, BRANCH[$,bbNormExit],c2;
rhWho ← sdBpl, grDISP[srcgrayornot],c3;
{notGray}TempBpl ← USrcBpl, CALL[SrcVAMod],c1, at[gr.notgray,grM,srcgrayornot];
{SrcVAMod subroutine {4 clicks},c2-c1;}
{will return to dstUphere}
{update Src address}
{gray}Rbb0{max} ← UGray,c1, at[gr.gray,grM,srcgrayornot];
Rbb1{cur} ← Rbb0 LRot8,c2;
Rbb0{max} ← Rbb0 and 0F, ZeroBr,c3;
Rbb1{cur} ← Rbb1 and 0F, BRANCH[$,dstUphere],c1;
Rbb1{cur+1} ← Rbb1{cur} + 1,c2;
[] ← Rbb0{max} - Rbb1{cur+1}, NegBr,c3;
Rbb1 ← Rbb1 LRot8, BRANCH[$,GrayWrap],c1;
{not gray wrap}
UGray ← Rbb1 xor Rbb0,c2;
Rbb2{usva} ← USrcVALo,c3;
Rbb2{usva+1} ← Rbb2{usva} + 1, PgCarryBr,c1;
Noop, BRANCH[$,GrayNewPage],c2;
USrcVALo ← Rbb2{usva+1},c3;
GOTO[dstUphere],c1;
GrayNewPage:
Noop ,c3;
TempBpl ← 10, CALL[SrcVAMod],c1;
GrayWrap:UGray ← Rbb0,c2;
Rbb1{maxX10} ← Rbb0{max} LRot4,c3;
Rbb2{usva} ← USrcVALo,c1;
Rbb2{usva-max} ← Rbb2{usva} - Rbb0{max}, PgCarryBr,c2;
Noop, BRANCH[GrayWrapNewPage,$],c3;
USrcVALo ← Rbb2{usva-max}, GOTO[dstUphere],c1;
GrayWrapNewPage:
TempBpl ← 0 - Rbb1{maxX10}, CALL[SrcVAMod],c1;
{update Dst address}
dstUphere:TempBpl ← UDstBpl, CALL[DstVAMod],c2, at[sdBpl,4,SrcVAModRet];
{DstVAMod subroutine {4 clicks},c3-c2;}
{will return to IntTest}
IntTest:Q ← UWidthM1{, MesaIntBr}{***},c3, at[sdBpl,4,DstVAModRet];
wdcTest:[] ← uWDC, ZeroBr, BRANCH[bbNoInt, MaybeInt],c1;
MaybeInt:[] ← uWP, ZeroBr, BRANCH[bbNoWDC, bbWDC],c2;
bbWDC:ClrIntErr, BRANCH[bbDoInt, $],c3;
Noop, GOTO[bbNoInt],c1;
{no mesa interrupt}
bbNoWDC:ClrIntErr, CANCELBR[$],c3;
Noop,c1;
bbNoInt:
Xbus ← UrefillType, XDisp, CANCELBR[SetUpTest],c2;
SetUpTest:
[] ← USrcBit + Q, NibCarryBr, LOOPHOLE[niblTiming], DISP2[SetUpAllC1],c3;
SetUpAllC1:
{Lcount ← number of dest words to be written minus 1 }
Rbb1 ← UDstBit, dirDisp, CANCELBR[$],c1, at[dbneq0,4,SetUpAllC1];
Lcount ← Rbb1 and 0F, dirDISP[lcx],c2;
Lcount ← 10 - Lcount,c3, at[dir.backwards,dirM,lcx];
Rbb0 ← ~UWidthM1, GOTO[lccont],c1;
Rbb0 ← UWidthM1,c3, at[dir.forward,dirM,lcx];
Noop, GOTO[lccont],c1;
lccont:Lcount ← Lcount + Rbb0,c2;
Lcount ← Lcount and ~0F,c3;
{Umask1 ← Rmask[0 - DstBit]}
[] ← 0F - Rbb1{db}, YDisp,c1;
Xbus ← maskRet.f1, XDisp, DISP4[MaskTbl],c2;
{MaskTbl subroutine here {1 cycle},c3;}
Lcount ← Lcount LRot12, dirDisp,c1, at[maskRet.f1,10,MaskRet];
ULcntsav ← Lcount, dirDISP[m2set],c2;
{FORWARD MASKS HERE}
Umask1 ← Rbb2,c3, at[dir.forward,dirM,m2set];
Rbb0{-w+1} ← 0 - Rbb0{w-1},c1;
[] ← Rbb0{-w+1} - Rbb1{db} - 1, YDisp,c2;
Xbus ← maskRet.f2, XDisp, DISP4[MaskTbl],c3;
{MaskTbl subroutine here {1 cycle},c1;}
Rbb2 ← RShift1 ~Rbb2, SE ← 1, GOTO[stum2],c2, at[maskRet.f2,10,MaskRet];
{BACKWARDS MASKS HERE}
Rbb2 ← RShift1 ~Rbb2, SE ← 1,c3, at[dir.backwards,dirM,m2set];
Noop,c1;
Umask1 ← Rbb2,c2;
{Umask2 ← Rmask[width - DstBit - 1]}
[] ← Rbb0{w-2} - Rbb1{db}, YDisp,c3;
Xbus ← maskRet.b2, XDisp, DISP4[MaskTbl],c1;
{MaskTbl subroutine here,c2;}
stum2:Umask2 ← Rbb2,c3, at[maskRet.b2,10,MaskRet];
{L0 ← skew + 2}
Rbb0{sb} ← USrcBit, dirDisp, CANCELBR[$],c1, at[sbneq0,4,SetUpAllC1];
Rbb1{db} ← UDstBit, dirDISP[WhichMasks],c2;
{Q ← Rmask[SrcBit - DstBit]}
[] ← Rbb0{sb} - Rbb1{db} - 1, YDisp,c3, at[dir.forward,dirM,WhichMasks];
Xbus ← maskRet.fQ, XDisp, DISP4[MaskTbl],c1;
{MaskTbl subroutine here {1 cycle},c2;}
GOTO[setL0] {leave pre-Qmask in Rbb2},c3, at[maskRet.fQ,10,MaskRet];
{Q ← Lmask[DstBit - SrcBit]}
[] ← Rbb0{sb} - Rbb1{db}, YDisp,c3, at[dir.backwards,dirM,WhichMasks];
Xbus ← maskRet.bQ, XDisp, DISP4[MaskTbl],c1;
{MaskTbl subroutine here {1 cycle},c2;}
Rbb2 ← RShift1 ~Rbb2, SE ← 1, GOTO[setL0] {leave pre-Qmask in Rbb2},c3, at[maskRet.bQ,10,MaskRet];
setL0:Rbb0{skew} ← Rbb0{sb} - Rbb1{db},c1;
[]{skew+2} ← Rbb0{skew} + 2, YDisp,c2;
[] ← dtRet.L0, L0 ← 0, XDisp, DISP4[dT],c3;
{dT subroutine here {1 cycle},c1;}
scDisp,c2, at[dtRet.L0,10,dTRets];
Q ← UWidthM1, sc3DISP[FixQ],c3;
Rbb2 ← LRot1 Rbb2, GOTO[SavQval],c1, at[0D,10,FixQ];
Rbb2 ← RRot1 Rbb2, GOTO[SavQval],c1, at[0F,10,FixQ];
SavQval:UmaskL ← Rbb2, L2 ← sd.src,c2;
[] ← USrcBit + Q, NibCarryBr, {L2 ← sd.src}, LOOPHOLE[niblTiming],c3;
TouchSourcePages:
Q ← UWidthW, NegBr, BRANCH[oldWords,newWords],c1, at[dbsb0,4,SetUpAllC1];
oldWords:BRANCH[oldposchks,oldnegchks],c2;
newWords:Q ← Q + 1, PgCarryBr, BRANCH[newposchks1,newnegchks1],c2;
oldposchks:[] ← rhType, XDisp, GOTO[oldposs1],c3;
oldnegchks:[] ← rhType, XDisp, GOTO[oldnegs1],c3;
newposchks1:[] ← rhType, XDisp, BRANCH[oldposs1,newposs1],c3;
newnegchks1:[] ← rhType, XDisp, BRANCH[newnegs1,oldnegs1],c3;
oldposs1:[] ← USrcVALo + Q, PgCarryBr, DISP3[SrcsmallP,5], LOOPHOLE[byteTiming],c1;
newposs1:CANCELBR[$,7],c1;
Noop, CANCELBR[pospgs,1],c2, at[type.notsmall,typeM,SrcsmallP];
rhRet ← MapOne, BRANCH[posnopgs,pospgs],c2, at[type.small,typeM,SrcsmallP];
newnegs1:[] ← USrcVALo + Q , PgCarryBr, DISP3[SrcsmallN,5], LOOPHOLE[byteTiming],c1;
oldnegs1:Xbus ← 1, XDisp, DISP3[SrcsmallN,5],c1;
rhRet ← MapOne, BRANCH[negpgs,negnopgs],c2, at[type.small,typeM,SrcsmallN];
Noop, CANCELBR[pospgs,1],c2, at[type.notsmall,typeM,SrcsmallN];
pospgs:Q ← USrcVALo, grDisp, GOTO[smapmore],c3;
negpgs:Q ← USrcVALo, grDisp, GOTO[smapmore],c3;
smapmore:TempB ← USrcBit, grDISP[schkgray],c1;
rhRet ← srcTP,c2, at[gr.notgray,grM,schkgray];
callva:TempBpl ← UWidthM1, CALL[VAMod],c3;
{VAMod subroutine here {2 or 3 clicks},c1-c3;}
VS ← rhVS + TempBpl, GOTO[fixrhVS], LOOPHOLE[byteTiming],c1, at[Or[srcTP,1],8,VAModRet];
TempB{old} ← USrcVALo, GOTO[comA],c1, at[srcTP,8,VAModRet];
comA:Q{new hi} ← Q and ~0FF, dirDisp,c2;
TempBpl{old hi} ← TempB and ~0FF, dirDISP[comA.1],c3;
TempBpl{num hi} ← Q{new hi} - TempBpl{old hi}, GOTO[comX],c1, at[dir.forward,dirM,comA.1];
TempBpl{num hi} ← TempBpl{old hi} - Q{new hi}, GOTO[comX],c1, at[dir.backwards,dirM,comA.1];
comX:TempB{old low} ← TempB{old} and 0FF,c2;
TempB ← TempB{old low} or Q{new hi}, sdDisp,c3;
TempBpl{num low} ← TempBpl LRot8, sdDISP[comB],c1;
VS ← TempB,c2, at[sd.src,sdM,comB];
csrc:rhRet ← sdMap, CALL[SrcMapSpec],c3;
sSnonewrhF:VS ← USrcVALoSav, CALL[SrcMapSpec],c3;
sSnonewrhB:VS ← USrcVALoSav, CALL[SrcMapSpec],c3;
{SrcMapSpec subroutine here 2 clicks,c1-c3;}
TempBpl ← TempBpl - 1, NegBr,c1, at[sdMap,10,SrcMapRet];
VS ← 0FF + 1, dirDisp, BRANCH[srcmore,srcthru],c2;
srcmore:TempB ← USrcVALoSav, dirDISP[y.f],c3;
TempB ← TempB - VS, CarryBr,c1, at[dir.forward,dirM,y.f];
USrcVALoSav ← TempB, BRANCH[sSnewrhF,sSnonewrhF],c2;
sSnewrhF:VS ← rhVS - 1, LOOPHOLE[byteTiming],c3;
y.c:rhVS ← VS LRot0,c1;
CALL[SrcMap],c2;
TempB ← TempB + VS, CarryBr,c1, at[dir.backwards,dirM,y.f];
USrcVALoSav ← TempB, BRANCH[sSnonewrhB,sSnewrhB],c2;
sSnewrhB:VS ← rhVS + 1, GOTO[y.c], LOOPHOLE[byteTiming],c3;
srcthru:CANCELBR[$,Sub[dirM,2]],c3;
Mask2 ← Umask2 {Mask2 = VS}, GOTO[sss],c1;
rhRet ← MapOne, GOTO[posnopgs],c2, at[gr.gray,grM,schkgray];
posnopgs:VS ← USrcVALo, CALL[SrcMapSpec],c3;
negnopgs:VS ← USrcVALo, CALL[SrcMapSpec],c3;
{SrcMapSpec subroutine here 2 clicks,c1-c3;}
srcFin:Mask2 ← Umask2 {Mask2 = VS}, GOTO[sss],c1, at[MapOne,10,SrcMapRet];
sss:Q ← UWidthM1,c2;
[] ← UDstBit + Q, NibCarryBr, L2 ← sd.dst, LOOPHOLE[niblTiming],c3;
TouchDestPages:
Q ← UWidthW, NegBr, BRANCH[oldWordd,newWordd],c1;
oldWordd:BRANCH[oldposchkd,oldnegchkd],c2;
newWordd:Q ← Q + 1, PgCarryBr, BRANCH[newposchkd1,newnegchkd1],c2;
oldposchkd:[] ← rhType, XDisp, GOTO[oldposd1],c3;
oldnegchkd:[] ← rhType, XDisp, GOTO[oldnegd1],c3;
newposchkd1:[] ← rhType, XDisp, BRANCH[oldposd1,newposd1],c3;
newnegchkd1:[] ← rhType, XDisp, BRANCH[newnegd1,oldnegd1],c3;
oldposd1:[] ← UDstVALo + Q, PgCarryBr, DISP3[DstsmallP,5], LOOPHOLE[byteTiming],c1;
newposd1:CANCELBR[$,7],c1;
Noop, CANCELBR[pospgd,1],c2, at[type.notsmall,typeM,DstsmallP];
rhRet ← MapOne, BRANCH[posnopgd,pospgd],c2, at[type.small,typeM,DstsmallP];
newnegd1:[] ← UDstVALo + Q, PgCarryBr, DISP3[DstsmallN,5], LOOPHOLE[byteTiming],c1;
oldnegd1:Xbus ← 1, XDisp, DISP3[DstsmallN,5],c1;
rhRet ← MapOne, BRANCH[negpgd,negnopgd],c2, at[type.small,typeM,DstsmallN];
Noop, CANCELBR[pospgd,1],c2, at[type.notsmall,typeM,DstsmallN];
pospgd:Q ← UDstVALo, GOTO[dmapmore],c3;
negpgd:Q ← UDstVALo, GOTO[dmapmore],c3;
dmapmore:TempB ← UDstBit,c1;
rhRet ← dstTP, GOTO[callva],c2;
{callva:TempBpl ← UWidthM1, CALL[VAMod],c3;}
{VAMod subroutine here {2 or 3 clicks},c1-c3;}
VD ← rhVD + TempBpl, GOTO[fixrhVD], LOOPHOLE[byteTiming],c1, at[Or[dstTP,1],8,VAModRet];
TempB{old} ← UDstVALo, GOTO[comA],c1, at[dstTP,8,VAModRet];
{comA:Q{new hi} ← Q and ~0FF, dirDisp,c2;}
{TempBpl{old hi} ← TempB and ~0FF, sdDisp, dirDISP[comA.1],c3;}
{TempBpl{num hi} ← Q{new hi} - TempBpl{old hi}, GOTO[comX],c1, at[dir.forward,dirM,comA.1];}
{TempBpl{num hi} ← TempBpl{old hi} - Q{new hi}, GOTO[comX],c1, at[dir.backwards,dirM,comA.1];}
{comX:TempB{old low} ← TempB{old} and 0FF,c2;}
{TempB ← TempB{old low} or Q{new hi}, sdDisp,c3;}
{TempBpl{num low} ← TempBpl LRot8, sdDISP[comB],c1;}
VD ← TempB{first touch address},c2, at[sd.dst,sdM,comB];
cdst:rhRet ← sdMap, CALL[DstMapSpec],c3;
dSnonewrhF:VD ← UDstVALoSav, CALL[DstMapSpec],c3;
dSnonewrhB:VD ← UDstVALoSav, CALL[DstMapSpec],c3;
{DstMapSpec subroutine here 2 clicks,c1-c3;}
TempBpl ← TempBpl - 1, NegBr,c1, at[sdMap,4,DstMapRet];
VD ← 0FF + 1, dirDisp, BRANCH[dstmore,dstthru],c2;
dstmore:TempB ← UDstVALoSav, dirDISP[y.fx],c3;
TempB ← TempB - VD, CarryBr,c1, at[dir.forward,dirM,y.fx];
UDstVALoSav ← TempB, BRANCH[dSnewrhF,dSnonewrhF],c2;
dSnewrhF:VD ← rhVD - 1, LOOPHOLE[byteTiming],c3;
y.cx:rhVD ← VD LRot0,c1;
CALL[DstMap],c2;
TempB ← TempB + VD, CarryBr,c1, at[dir.backwards,dirM,y.fx];
UDstVALoSav ← TempB, BRANCH[dSnonewrhB,dSnewrhB],c2;
dSnewrhB:VD ← rhVD + 1, GOTO[y.cx], LOOPHOLE[byteTiming],c3;
dstthru:CANCELBR[$,Sub[dirM,2]],c3;
Lcount ← ULcntsav, GOTO[detLoop],c1;
posnopgd:VD ← UDstVALo, CALL[DstMapSpec],c3;
negnopgd:VD ← UDstVALo, CALL[DstMapSpec],c3;
{DstMapSpec subroutine here 2 clicks,c1-c3;}
dstFin:Lcount ← ULcntsav, GOTO[detLoop],c1, at[MapOne,4,DstMapRet];
{determine loop and entry point}
detLoop:Mask1 ← Umask1, grDisp,c2;
Q ← UmaskL, grDISP[chooseLoop],c3;
{if gray then Entry to L1 and L2D at L1I1lsar}
{Entry to L4}
L4SetUp:dirDisp, Dst ← UDstBit{Dbit},c1, at[gr.notgray,grM,chooseLoop];
Src ← USrcBit{Sbit}, dirDISP[CheckL4Init],c2;
{forward: fetch 1 if Dbit >= Sbit, else fetch 2}
[] ← Dst{Dbit} - Src{Sbit}, NibCarryBr, GOTO[L4I1lsar],c3, at[dir.forward,dirM,CheckL4Init];
{backwards: fetch 1 if Sbit >= Dbit, else fetch 2}
[] ← Src{Sbit} - Dst{Dbit}, NibCarryBr, GOTO[L4I1lsar],c3, at[dir.backwards,dirM,CheckL4Init];
{Exits}
Heighteq0:Noop,c2;
bbNormExit:CANCELBR[$,Sub[grM,1]],c3;
Widtheq0:[] ← rhType, XDisp, L0 ← restore.term,c1;
stackP ← 0, DISP3[LSEPReturn,2],c2;
{will go to RestoreRandRHRegs if not LSEP}
{RestoreRandRHRegs subroutine {2 1/3 clicks},c3-c3;}
BBExit:Xbus ← uPCCross, XRefBr,c1, at[restore.term,10,RestoreCallers];
Noop, BRANCH[$,BBSetInt],c2;
Noop, GOTO[BBThru],c3;
BBSetInt:MesaIntRq, GOTO[BBThru],c3;
{Mesa Interrupt}
bbDoInt:stackP ← 0C,c1;
L0 ← restore.int,c2;
Xbus ← rhType, XDisp,c3;
DISP3[MoverhVToStkandRestore,3],c1;
{RestoreRandRHRegs subroutine {2 1/3 clicks},c2-c2;}
Rx ← pInt, push,c3, at[restore.int,10,RestoreCallers];
TOS ← STK, pop, GOTO[SaveRegs],c1;
{PAGE FAULTS}
DFault:UVSsave ← Q,c3;
uFaultParm0 ← VD,c1;
Q ← rhVD, GOTO[pfCom],c2;
SFault:UVSsave ← Q,c3;
uFaultParm0 ← VS, sdDisp,c1;
Q ← rhVS, sdDISP[pfCom],c2;
pfCom:stackP ← 0C, GOTO[bbDoFault],c3, at[sd.src,sdM,pfCom];
stackP ← 1, GOTO[bbDoFault],c3, at[sd.spec,sdM,pfCom];
bbDoFault:
uFaultParm1 ← Q,c1;
L0 ← restore.pf,c2;
Xbus ← rhType, XDisp,c3;
DISP3[MoverhVToStkandRestore,3],c1;
{RestoreRandRHRegs subroutine {2 1/3 clicks},c2-c2;}
T ← UVSsave {Trap index},c3, at[restore.pf,10,RestoreCallers];
Rx ← pFault, GOTO[SaveRegs],c1;
{END}