%
*** *** *** ***
<D0Diag>Rev-1>EDBitBlt.mc Revision 1.1 May 3, 1980 *** *** *** ***

****************************************************************************************
*** EDBitBlt.mc : Bit Boundary Block Transfer microcode
*** Purpose : This test moves information from one region of main storage to another,
modifying the information at the destination as the transfer is done.
*** Hardware Configuration : Standard 4 CPU boards.
*** Written by : Tom Horsley, Nov. 15, 1977
*** Modified by : Bill Kennedy, Mar. 10, 1978
Took code off of Page 0.
*** Modified by : Bill Kennedy, Apr. 7, 1978
Added MPanel use.
*** Modified by : Chuck Thacker, Aug. 22, 1978
Looped on errors.
*** Modified by : Camellia Chan, Oct. 30, 1979
Standardize title page, code format and labels, modified looping.
*** Modified by : C. Thacker, May 3, 1980
Standardized assembly with bitblt.cm, modified for new d0lang.
****************************************************************************************



****************************************************************************************
*SubTest Description:
* SubTest 1: the number of times the hardware goes around the loop to complete an item
(LoopCount) is compared with the simulators loop count (simLoopCount).
* SubTest 2: confirms that the reason the hardware exited the loop (Result) is the same
as the simulators (simResult). The reasons are encoded as follows:
1 = item done
2 = fill source and destination
3 = fill source
4 = fill destination
* SubTest 3: confirm that the first word of the hardware destination quadword (Dest0)
matches the simulated equivalent (simDest0).
* SubTest 4: confirm that the second word of the hardware destination quadword (Dest1)
matches the simulated equivalent (simDest1).
* SubTest 5: confirm that the third word of the hardware destination quadword (Dest2)
matches the simulated equivalent (simDest2).
* SubTest 6: confirm that the fourth word of the hardware destination quadword (Dest3)
matches the simulated equivalent (simDest3).
* SubTest 7: confirm that the hardware register MNBR contains the expected value (simNBR).
* SubTest 10: confirm that the hardware register SB contains the expected value (simSB).
* SubTest 11: confirm that the hardware register DB contains the expected value (simDB).


****************************************************************************************
*BreakPoints:
* Error1: hardware loop count does not equal to simulator’s loop count.
* Error2: reason for hardware existed the loop is not the same as the simulator.
* Error3: the first word of the hardware destination quadword (Dest0) does not match
the simulated equivalent (simDest0).
* Error4: the second word of the hardware destination quadword (Dest1) does not match
the simulated equivalent (simDest1).
* Error5: the third word of the hardware destination quadword (Dest2) does not match
the simulated equivalent (simDest2).
* Error6: the fourth word of the hardware destination quadword (Dest3) does not match
the simulated equivalent (simDest3).
* Error7: the hardware register MNBR does not contain the expected value (simNBR).
* Error10: the hardware register SB does not contain the expected value (simSB).
* Error11: the hardware register DB does not contain the expected value (simDB).
* Passed-EDBitBlt-Test: Passed all tests, and all passes.


****************************************************************************************
* ShortLoop Logic Analyzer Sync Points at Control Store address:
* Error1: Control Store address 600 at Repeat.
* Error2: Control Store address 600 at Repeat.
* Error3: Control Store address 600 at Repeat.
* Error4: Control Store address 600 at Repeat.
* Error5: Control Store address 600 at Repeat.
* Error6: Control Store address 600 at Repeat.
* Error7: Control Store address 600 at Repeat.
* Error10: Control Store address 600 at Repeat.
* Error11: Control Store address 600 at Repeat.

****************************************************************************************
*Subroutine Description:
* BitBlt:
invoke hardware bitblt.
* SimBitBlt:
simulate a bitblt given simDB, simSB, simNBR, simOP, simMaskFillSrc,
simBBF1.


****************************************************************************************
*Special Reg. Definition:
* LoopOn:
At any breakpoint, the user has the choice of setting LoopOn to 1, 2, 3, 4, 5, 6,
7, 10, or 11 to loop from Subtest0 to that subtest repeatedly for trouble shooting.

0, no looping on any subtest.
N, loop on subtest N, for N=1,2,3,4,5,6,7,10,11.
* XA and XB: The two random numbers held in these registers XA and XB are used to choose
the bitblt starting values as follows:

SB← XA[0, 6]
DB← XA[6, 6]
MaskDestination← XB[0, 1]
Mask and Fill Source← XB[1, 1]
SALUF function← XB[2, 6]
MNBR← -(XB[10, 7] + 1)
Src0← XA
Src1← XB
Src2← NOT XA
Src3← NOT XB
Dest0← XB
Dest1← XA
Dest2← 0
Dest3← 177777

*
Note that the random number generator has been constructed so that it produces each
number in the range [0, 64K) once and only once before repeating any number. Thus it
is guaranteed to exhaust all possible combinations of the fields derived from it each
time the inner loop is exhausted.
* InnerLoopCounter: 16 bits inner loop counter.
* PassCount: Outer loop pass counter,
incremented each time when InnerLoopCounter reached the limit.

* MaxPass: number of times outer loop is to repeat before breakpointing.
****************************************************************************************
%

****************************************************************************************
*INITIALIZATION:

TITLE[EDBitBlt]; * Bitblt test program, ED revision
SET[BB0, 1200]; * base for BBFB dispatch
SET[BB1, 1300]; * base for BBFBX dispatch
SET[MainPage, 1]; * tag for Main Program page number
SET[SubPage1, 2]; * tag for Subroutine page number

********* Macro constants: *********

MC[fillSource, 3]; * bitblt dispatch type indicating source ran out
MC[fillDest, 4]; * bitblt dispatch type indicating destination ran out
MC[fillBoth, 2]; * bitblt dispatch type indicating both source and destination ran out
MC[itemDone, 1]; * bitblt dispatch type indicating item done

********* R-registers: *********

RV[CA,1]; * used in random number generation, A*XA + CA
RV[XA,2]; * random number generated via A*XA + CA
RV[CB,3]; * used in the random number calculation (a*XB + CB)
RV[XB,4]; * second random number
RV[InnerLoopCounter,5,0]; * 16 bits inner loop counter
RV[PassCount,6]; * Outer loop pass counter incremented each time when InnerLoopCounter
* reached the limit
RV[MaxPass,7,2]; * number of times outer loop is to repeat before breakpointing
RV[LoopOn,13,0]; * loop on subtest
RV[SubTest,14]; * current location of test

RV[allOnes,15]; * holds 177777 during mask creations
RV[Dest0,20]; * hardware bitblt destination quadword
RV[Dest1,21];
RV[Dest2,22];
RV[Dest3,23];
RV[destBitsToGo,24]; * number of bits between current DB and next word boundary
RV[destFieldDescriptor,25]; * describes the destination bit field
RV[destMask,26]; * mask used to set background in source field and/or clear destination field
RV[destStart,27]; * lower 4 bits of DB (word offset)
RV[destWord,30]; * working register for current destination word
RV[LoopCount,31]; * number of times through loop of hardware bitblt
RV[MaskDest,32]; * flag indicating whether to clear the destination field or leave it
RV[nbits,33]; * distance to next word boundary or the end of the item
RV[Result,34]; * indicates which dispatch was taken out of hardware bitblt
* (see fillSource etc. below)
RV[simDB,35]; * simulated bitblt’s DB
RV[simDest0,40]; * simulated bitblt destination quadword
RV[simDest1,41];
RV[simDest2,42];
RV[simDest3,43];
RV[simLoopCount,44]; * simulated bitblt loop count
RV[simMaskFillSrc,45]; * flag indicating whether background of source field should be 0 or 1
RV[simNBR,46]; * simulated bitblt MNBR
RV[simOp,47]; * simulated bitblt SALUF operator
RV[simResult,52]; * indicates which dispatch was indicated by simulated bitblt
* (see fillSource etc. below)
RV[simSB,53]; * simulated bitblt SB
RV[Src0,54]; * source quadword for both bitblt’s
RV[Src1,55];
RV[Src2,56];
RV[Src3,57];
RV[srcBitsToGo,60]; * number of bits between current SB and next word boundary
RV[srcFieldDescriptor,61]; * describes the source bit field
RV[srcStart,62]; * lower 4 bits of SB (word offset)
RV[srcWord,63]; * working register for current source word
RV[Tmp,64]; * temporary register
RV[tmpWord,65]; * temporary register
RV[Revision,66,1]; * REVISION 1
RV[Run-Time,67,14]; * Run-Time is 14b or 12 seconds

****************************************************************************************
*** MAIN routine:

ONPAGE[MainPage];

go:
start:
PassCount ← 0C;
CLEARMPANEL;

*RandomInit (Initialize random generator registers: XA ← 123, CA ← 33031)
XA ← AND[0377, 123]C;*Load16Bits (XA ← 123)
XA ← (XA) OR (AND[177400, 123]C);

CA ← AND[0377, 33031]C;*Load16Bits (CA ← 33031)
CA ← (CA) OR (AND[177400, 33031]C);

*RandomInit (Initialize random generator registers: XB ← 012300, CB ← 33037)
XB ← AND[0377, 012300]C;*Load16Bits (XB ← 012300)
XB ← (XB) OR (AND[177400, 012300]C);

CB ← AND[0377, 33037]C;*Load16Bits (CB ← 33037)
CB ← (CB) OR (AND[177400, 33037]C);

bigLoop:
INCMPANEL;
t ← PassCount ← (PassCount) + 1;
LU ← (MaxPass) - (t) ;* check for maximum pass counter reached
GOTO[Then1A, ALU >= 0];

Passed-EDBitBlt-Test: BREAKPOINT, goto[go];

Then1A:
XB ← (XB) + 1;

mainloop:
InnerLoopCounter ← (InnerLoopCounter) + 1;
GOTO[bigLoop, CARRY];

* Random (4005*XA + CA mod 2**16)
t ← XA;
t ← (LSH[XA, 2]) + t;
t ← (LSH[XA, 13]) + t;
t ← (CA) + t;
XA ← t;

* Random (4005*XB + CB mod 2**16)
t ← XB;
t ← (LSH[XB, 2]) + t;
t ← (LSH[XB, 13]) + t;
t ← (CB) + t;
XB ← t;

* SUBTEST 0:
RepeatQ:
Subtest ← 0C;
TASK;* allow mouse halt

* load source and destination registers
t ← XA;
src0 ← t;
src2 ← (ZERO) OR NOT (t);
dest1 ← t;
simDest1 ← t;
t ← XB;
src1 ← t;
src3 ← (ZERO) OR NOT (t);
dest0 ← t;
simDest0 ← t;
dest2 ← 0C;
simDest2 ← 0C;
dest3 ← (ZERO) - 1;
simDest3 ← (ZERO) - 1;

* load DB and SB
t ← LDF[XA, 6, 6];
simDB ← t;
DB ← (simDB);
t ← LDF[XA, 0, 6];
simSB ← t;
SB ← (simSB);

* load MNBR
t ← (LDF[XB, 10, 7]) + 1;
simNBR ← (ZERO) - t;
MNBR ← (simNBR);

* load SALUF and related bits
t ← LDF[XB, 0, 10];
SALUF ← t;
t ← LDF[XB, 2, 6];
simOP ← t;
t ← LDF[XB, 0, 1];
simMaskFillSrc ← t;
t ← LDF[XB, 1, 1];
MaskDest ← t;

* do it
LOADPAGE[SubPage1];
CALLP[SimBitblt];
LOADPAGE[SubPage1];
CALLP[Bitblt];

CompareResult:
SUBTEST1:
subTest ← 1C;
t ← subTest;
lu ← (LoopOn)-(t);
goto[.+2,ALU # 0];* check for looping on this subtest
goto[RepeatQ];
t ← simLoopCount;* hardware loop count is the same as simulator’s loop count?
LU ← (LoopCount) - (t);
GOTO[SUBTEST2, ALU = 0];
Error1:
BREAKPOINT,goto[RepeatQ];

SUBTEST2:
subTest ← 2C;
t ← subTest;
lu ← (LoopOn)-(t);
goto[.+2,ALU # 0];* check for looping on this subtest
goto[RepeatQ];
t ← simResult; * reason for hardware existed the loop is the same as simulator?
LU ← (Result) - (t);
GOTO[SUBTEST3, ALU = 0];
Error2:
BREAKPOINT,goto[RepeatQ];

SUBTEST3:
subTest ← 3C;
t ← subTest;
lu ← (LoopOn)-(t);
goto[.+2,ALU # 0];* check for looping on this subtest
goto[RepeatQ];
t ← simDest0;* 1st word of the hardware dest. quadword matches the
* simulated equivilent?
LU ← (Dest0) - (t);
GOTO[SUBTEST4, ALU = 0];
Error3:
BREAKPOINT,goto[RepeatQ];

SUBTEST4:
subTest ← 4C;
t ← subTest;
lu ← (LoopOn)-(t);
goto[.+2,ALU # 0];* check for looping on this subtest
goto[RepeatQ];
t ← simDest1;* 2nd word of the hardware dest. quadword matches the
* simulated equivilent?
LU ← (Dest1) - (t);
GOTO[SUBTEST5, ALU = 0];
Error4:
BREAKPOINT,goto[RepeatQ];

SUBTEST5:
subTest ← 5C;
t ← subTest;
lu ← (LoopOn)-(t);
goto[.+2,ALU # 0];* check for looping on this subtest
goto[RepeatQ];
t ← simDest2;* 3rd word of the hardware dest. quadword matches the
* simulated equivilent?
LU ← (Dest2) - (t);
GOTO[SUBTEST6, ALU = 0];
Error5:
BREAKPOINT,goto[RepeatQ];

SUBTEST6:
subTest ← 6C;
t ← subTest;
lu ← (LoopOn)-(t);
goto[.+2,ALU # 0];* check for looping on this subtest
goto[RepeatQ];
t ← simDest3;* 4th word of the hardware dest. quadword matches the
* simulated equivilent?
LU ← (Dest3) - (t);
GOTO[SUBTEST7, ALU = 0];
Error6:
BREAKPOINT,goto[RepeatQ];

SUBTEST7:
subTest ← 7C;
t ← subTest;
lu ← (LoopOn)-(t);
goto[.+2,ALU # 0];* check for looping on this subtest
goto[RepeatQ];
t ← MNBR;* the hardware register MNBR contains the
* expected value (simNBR)?
LU ← (simNBR) - (t);
GOTO[SUBTEST10, ALU = 0];
Error7:
BREAKPOINT,goto[RepeatQ];

SUBTEST10:
subTest ← 10C;
t ← subTest;
lu ← (LoopOn)-(t);
goto[.+2,ALU # 0];* check for looping on this subtest
goto[RepeatQ];
t ← DBSB;* the hardware register SB contains the
* expected value (simSB)?
Tmp ← t;
t ← LDF[Tmp, 12, 6];
LU ← (simSB) - (t);
GOTO[SUBTEST11, ALU = 0];
Error10:
BREAKPOINT,goto[RepeatQ];

SUBTEST11:
subTest ← 11C;
t ← subTest;
lu ← (LoopOn)-(t);
goto[.+2,ALU # 0];* check for looping on this subtest
goto[RepeatQ];
t ← DBSB;* the hardware register DB contains the
* expected value (simDB)?
Tmp ← t;
t ← LDF[Tmp, 4, 6];
LU ← (simDB) - (t);
GOTO[TheEnd, ALU = 0];
Error11:
BREAKPOINT,goto[RepeatQ];

TheEnd:
LOADPAGE[MainPage];
GOTOP[mainloop];

****************************************************************************************
*SUBROUTINE

ONPAGE[SubPage1];

********** SUBROUTINE: Bitblt **********
*
* invoke harware bitblt

Bitblt:
LoopCount ← 0C;
GOTO[maskTheDestination, MB];

dontMaskDestination:
BBFB;* initialize internal bitblt registers
BBLoop0:
LoopCount ← (LoopCount) + 1, AT[BB0, 07];
t ← BBFA[SB[src0]] OR (t);
DB[dest0] ← (BBFBX[DB[dest0]]) SALUFOP (t), DISP[BBLoop0];

BBFillSource0:
Result ← fillSource, RETURN, AT[BB0, 05];

BBFillDest0:
Result ← fillDest, RETURN, AT[BB0, 06];

BBFillBoth0:
Result ← fillBoth, RETURN, AT[BB0, 04];

BBItemDone0:
Result ← itemDone, RETURN, AT[BB0, 03];

maskTheDestination:
BBFB;* initialize internal bitblt registers
BBLoop1:
LoopCount ← (LoopCount) + 1, AT[BB1, 07];
t ← BBFA[SB[src0]] OR (t);
DB[dest0] ← (BBFB[DB[dest0]]) SALUFOP (t), DISP[BBLoop1];

BBFillSource1:
Result ← fillSource, RETURN, AT[BB1, 05];

BBFillDest1:
Result ← fillDest, RETURN, AT[BB1, 06];

BBFillBoth1:
Result ← fillBoth, RETURN, AT[BB1, 04];

BBItemDone1:
Result ← itemDone, RETURN, AT[BB1, 03];

RETURN;


********** SUBROUTINE: SimBitblt **********
*
* simulate a bitblit given simDB, simSB, simNBR, simOp, simMaskFillSrc, simBBF1

SimBitblt:
simLoopCount ← 0C;
SimBltStart:
simLoopCount ← (simLoopCount) + 1;

* get correct source word, based on simSB
t ← LDF[simSB, 12, 2];
tmpWord ← t;
LU ← (tmpWord);
GOTO[TrySrc1, ALU # 0];* go to TrySrc1 if the correct source word is not Src0
t ← (Src0);* Copy (srcWord ← Src0)
srcWord ← t;
GOTO[CalSrcBit];

TrySrc1:
LU ← (tmpWord) - (1C);
GOTO[TrySrc2, ALU # 0];* go to TrySrc2 if the correct source word is not Src1
t ← (Src1);* Copy (srcWord ← Src1)
srcWord ← t;
GOTO[CalSrcBit];

TrySrc2:
LU ← (tmpWord) - (2C);
GOTO[IsSrc3, ALU # 0];* go to IsSrc3 if the correct source word is not Src2
t ← (Src2);* Copy (srcWord ← Src2)
srcWord ← t;
GOTO[CalSrcBit];

IsSrc3:
t ← (Src3);* Copy (srcWord ← Src3)
srcWord ← t;

* calculate actual source bit related values
CalSrcBit:
t ← LDF[simSB, 14, 4];
srcStart ← t;
srcBitsToGo ← (ZERO) - t;
srcBitsToGo ← (srcBitsToGo) + (20C);

* get correct destination word, based on simDB
t ← LDF[simDB, 12, 2];
tmpWord ← t;
LU ← (tmpWord);
GOTO[TryDest1, ALU # 0];* go to TryDest1 if the correct destination word is
* not simDest0
t ← (simDest0);* Copy (destWord ← simDest0)
destWord ← t;
GOTO[CalDstBit];

TryDest1:
LU ← (tmpWord) - (1C);
GOTO[TryDest2, ALU # 0];* go to TryDest2 if the correct destination word is
* not simDest1
t ← (simDest1);* Copy (destWord ← simDest1)
destWord ← t;
GOTO[CalDstBit];

TryDest2:
LU ← (tmpWord) - (2C);
GOTO[IsDest3, ALU # 0];* go to IsDest3 if the correct destination word is
* not simDest2
t ← (simDest2);* Copy (destWord ← simDest2)
destWord ← t;
GOTO[CalDstBit];

IsDest3:
t ← (simDest3);* Copy (destWord ← simDest3)
destWord ← t;

* calculate actual destination bit related values
CalDstBit:
t ← LDF[simDB, 14, 4];
destStart ← t;
destBitsToGo ← (ZERO) - t;
destBitsToGo ← (destBitsToGo) + (20C);

* calculate number of bits to next word boundary (or end)
t ← destBitsToGo;
LU ← (srcBitsToGo) - (t);
GOTO[GetSrcBit, ALU < 0];* go to GetSrcBit if srcBitsToGo is less than
* destBitsToGo
t ← (destBitsToGo);* Copy (nbits ← destBitsToGo)
nbits ← t;
GOTO[ThenNBR];

GetSrcBit:
t ← (srcBitsToGo);* Copy (nbits ← srcBitsToGo)
nbits ← t;

ThenNBR:
t ← nbits;
LU ← (simNBR) + (t);
GOTO[SrcField, ALU < 0];
t ← (simNBR);* Copy (nbits ← -simNBR)
nbits ← (ZERO) - t;

* create source field descriptor
SrcField:
t ← LSH[srcStart, 4];
srcFieldDescriptor ← t;
t ← (nbits) - 1;
srcFieldDescriptor ← (srcFieldDescriptor) OR t;

* load the source field
CYCLECONTROL ←srcFieldDescriptor;
t ← RF[srcWord];
srcWord ← t;

* create destination field descriptor
t ← LSH[destStart, 4];
destFieldDescriptor ← t;
t ← (nbits) - 1;
destFieldDescriptor ← (destFieldDescriptor) OR t;

* set up mask
allOnes ←(ZERO) - 1;
destMask ← 0C;
CYCLECONTROL ←destFieldDescriptor;
t ← WFA[allOnes];
destMask ← WFB[(destMask) OR (t)];

* align source with destination
tmpWord ← 0C;
CYCLECONTROL ←destFieldDescriptor;
t ← WFA[srcWord];
tmpWord ← WFB[(tmpWord) OR (t)];
t ← (tmpWord);* Copy (srcWord ← tmpWord)
srcWord ← t;

* set source background bits if required
LU ← (simMaskFillSrc);
GOTO[ClearDBit, ALU # 0];* go to ClearDBit if source background bits do not
* need to be set
t ← (destMask);* set source background bits
srcWord ← (srcWord) OR NOT t;

* clear destination bits if required
ClearDBit:
LU ← (MaskDest);
GOTO[Perform, ALU = 0];* go to Perform if destination bits do not need
* to be cleared
t ← (destMask);* clear destination bits
destWord ← (destWord) AND NOT t;

Perform:
t ← (srcWord);* perform the operation
destWord ← (destWord) SALUFOP t;

* stuff result into correct destination register
t ← LDF[simDB, 12, 2];
tmpWord ← t;
LU ← (tmpWord);
GOTO[TrySimD1, ALU # 0];* go to TrySimD1 if the correct dest. reg. is not
* simDest0
t ← (destWord);* Copy (simDest0 ← destWord)
simDest0 ← t;
GOTO[IncBitCnt];

TrySimD1:
LU ← (tmpWord) - (1C);
GOTO[TrySimD2, ALU # 0];* go to TrySimD2 if the correct dest. reg. is not
* simDest1
t ← (destWord);* Copy (simDest1 ← destWord)
simDest1 ← t;
GOTO[IncBitCnt];

TrySimD2:
LU ← (tmpWord) - (2C);
GOTO[IsSimD3, ALU # 0]; * go to IsSimD3 if the correct dest. reg. is not simDest2
t ← (destWord);* Copy (simDest2 ← destWord)
simDest2 ← t;
GOTO[IncBitCnt];

IsSimD3:
t ← (destWord);* Copy (simDest3 ← destWord)
simDest3 ← t;

* increment various bit counters
IncBitCnt:
t ← (nbits);
simSB ← (simSB) + t;
simSB ← LDF[simSB, 12, 6];
simDB ← (simDB) + t;
simDB ← LDF[simDB, 12, 6];
simNBR ← (simNBR) + t;

* decide if finished or not
LU ← (simNBR);
GOTO[CheckSB, ALU # 0];* go to CheckSB if simulated bitblt MNBR did not finish
simResult ← 1C, RETURN;* item done, return to main program

CheckSB:
LU ← (simSB);
GOTO[CheckDB, ALU # 0];* go to CheckDB if simulated bitblt SB did not finish
LU ← (simDB);
GOTO[SrcOut, ALU #0];* go to SrcOut if simulated bitblt DB did not finish
simResult ← 2C, RETURN;* source and destination ran out, return to main program

SrcOut:
simResult ← 3C, RETURN;* source ran out, return to main program

CheckDB:
LU ← (simDB);
GOTO[NotFinish, ALU # 0]; * go to NotFinish if simulated bitblt DB did not finish
simResult ← 4C, RETURN;* destination ran out, return to main program

NotFinish:
GOTO[SimBltStart];* not finished
RETURN;

end;* to end the MAIN routine