%
*** *** *** *** <D0Diag>Rev-1>EDMemAbort.mc Revision 1.1 May 2, 1980 *** *** *** ***

**********************************************************************************************
*** EDMemAbort.mc : Memory Abort Test microcode
*** Purpose : Test the memory reference abort conditions.
*** Minimum Hardware : Standard 4 CPU boards & 96K memory board.
*** Approximate Run Time : 88 seconds.
*** Written by : Bill Kennedy,
March 15, 1978
*** Modified by : Chuck Thacker,
June 16, 1979
*** Modified by : P.Hardjadinata,
December 12, 1979
Standardize title page and code format.
Implement looping and standard labels.
*** Modified by : C. Thacker,
May 2, 1980
Changed assembly procedure: added command file MemAbort.cm
**********************************************************************************************


**********************************************************************************************
*SubTest Description:
* SUBTEST 0: Generate random number and set the instruction type accordingly.
* SUBTEST 1: Check double-word and quad-word overflow using REG for SRCDEST.
* SUBTEST 2: Check double-word and quad-word overflow using the stack for SRCDEST.
* SUBTEST 3: Check that stack is as expected when done with SubTest 2. Expected value for
stack is in ExpStack.
* SUBTEST 4:
* Attempt to decrement stack during PFETCH2 using the stack.
Check expected stack against actual.
* Check value read from memory against what was expected.
* SUBTEST 5:
* Check that attempting to increment the stack during a PSTORE1 yields
the expected results in the stack.
* Check that attempting to increment the stack during a PSTORE2 yields
the expected results in the stack.
* Check that attempting to increment the stack during a PSTORE4 yields
the expected results in the stack.

**********************************************************************************************
*BreakPoints:
* ErrorOvflSet: Overflow bit is set when it shouldn’t be.
* ErrorDidTrans: Transferred data when not supposed to.
* ErrorNoOvfl: Overflow bit is not set when it should be.
* ErrorDataCompare: Data transferred did not compare.
* Error3: Stack Pointer is not as expected in SubTest2.
* Error41: Stack Pointer is not as expected in doing PFETCH2.
* Error42: Data is not as expected in doing PFETCH2.
* Error51: Stack Pointer is not as expected in doing PSTORE1.
* Error52: Stack Pointer is not as expected in doing PSTORE2.
* Error53: Stack Pointer is not as expected in doing PSTORE4.
* PageCountError1: No page.
* PageCountError2: Page Count larger than allowed.
* Passed-EDMemAbort-Test: Passed all tests, and all passes.

**********************************************************************************************
* ShortLoop Logic Analyzer Sync Points at Control Store address:
* ErrorOvlSet: Control Store address 471 at SUBTEST1 or 410 at SUBTEST2.
* ErrorDidTrans: Control Store address 471 at SUBTEST1 or 410 at SUBTEST2.
* ErrorNoOvfl: Control Store address 471 at SUBTEST1 or 410 at SUBTEST2.
* ErrorDataCompare: Control Store address 471 at SUBTEST1 or 410 at SUBTEST2.
* Error3: Control Store address 410 at SUBTEST2.
* Error41: Control Store address 456 at SUBTEST4.
* Error42: Control Store address 456 at SUBTEST4.
* Error51: Control Store address 613 at CASET51.
* Error52: Control Store address 547 at CASET52.
* Error53: Control Store address 570 at CASET54.

**********************************************************************************************
*Special Reg. Definition:

* ShortLoop: At any breakpoint, the user has the choice of setting ShortLoop to a 1 to
loop on the current test. During the short loop, the user can modify the type of
memory transfer and the memory address by changing XA.

1, the current test will loop repeatedly for trouble shooting
0, no looping in current test

* XA: This test is driven by a sequence of random 16 bit words. The arguments of the test
are built up from the random word (XA) as follows:

XA[0-1]: selects the register to be used for SRCDEST in PFetch or PStore
0 = register block 0 (RegBlock0)
1 = register block 1 (RegBlock1)
2 = register block 2 (RegBlock2)
3 = register block 3 (RegBlock3)
XA[2-3]: type of action to be done
0 = double fetch
1 = quad fetch
2 = double store
3 = quad store
XA[8-15]: selects the memory location on a page
XA[0-11]: selects the page number

* TestCounter: A Counter that keep track of how many loops have been executed in the
main loop. The maximum possible loop here is 64K times.

* PageCount: Register containing the actual number of pages of memory.

**********************************************************************************************
*Subroutine Description:
* Check: Sets up TRANSFER flag for later use. It is set up based on the type of transfer to be
done. If at the end, TRANSFER = 0, then no actual transfer of data should take place and
QUADOVF should be set.
* CheckValues: This routine checks the register block or memory for transfers:
At exit from this routine, TempReg will be 0 or -1. If it is 0, then registers on fetch or
memory on store were equal to what was tried to be read or written. If it is -1, then they
were’nt as expected or tested.
* IncPanel: Increment the Maintenance Panel. On entry to subroutine, t contains the count of the
number of times to increment from 0.
* InitMem: to initialize all of available memory to known values (page number XOR’ed with
displacement on page).
* SetUpBaseRegs: Set up the base registers for page access to main memory based on Current Page
contents. Base Page Even is the even base register for references and Base Page Odd is the
odd base register.
* SetUpInstructions: set up the memory reference instructions - build them in Control Store in
700 and 720.
* SetUpRegs: Set up the register block with zeroes before executing any transfers. Additionally,
determine what the stack pointer should be after the stack transfer and put it in TempReg
for later use by caller.
* TestResults: Test the results of tests 1 or 2 and see if they worked as expected. On entry,
TRANSFER and QUADOVF determine which way to go. If TRANSFER is equal to zero, then no
transfer should occur.
* WritePage: actually do the writing in all locations in a page.

**********************************************************************************************
%

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

*BUILTIN[INSERT,24];
*INSERT[d0lang];
TITLE[MemAbort];

********** R-Registers: **********

RV[Revision,0,1];
* REVISION 1
RV[Run-Time,1,130];
* Run-Time is 130B or 88D seconds
RV[Transfer,2];
*register used to determine whether data should actually transfer
RV[PassCount,3, 0];
*outer loop counter
RV[MaxPass,4, 2];
*number of times PassCount is to repeat before breakpointing
RV[TestCounter, 5];
* inner loop counter
RV[SubTest,6, 0];
*contains SubTest number at time of failure
RV[ShortLoop,7, 0];
* 1 => loop on current test, 0 => continue to the next test

RV[CA, 10];
*used in random number generation, A*XA + CA
RV[XA, 11];
*random number generated via A*XA + CA
RV[CS0,12];
*used in writing and reading control store word 0
RV[CS1,13];
*used in writing and reading control store word 1
RV[CS2,14];
*used in writing and reading control store word 2
RV[CurrentReg,15];
*contains the current register to be used in memory instruction
RV[OldReg,16];
*contains the old (last) register used in the memory instruction
RV[InstructionAddress,17]; *contains address of control store being used to build instructions
RV[BasePageEven,20];
*base page number to be used in memory instruction
RV[BasePageOdd,21];
*odd base page number to be used in memory instruction
RV[TypeReg,22];
*contains the type of memory reference to be done
RV[CurrentPage,23];
*current page number to be used in memory instruction
RV[OldPage,24];
*old page number last used in memory instruction
RV[CurrentLoc,25];
*location within a page being addressed by memory reference
RV[OldLoc,26];
*contains old (last) location within a page addressed by memory reference
RV[ExpStack,27];
*contains expected stack when checking stack updating

RV[TempReg,30];
*temporary register used throughout program
RV[TempReg2,31];
*temporary register used throughout program
RV[TempReg3,32];
*temporary register used throughout program
RV[TempReg4,33];
*temporary register used throughout program
RV[TempReg5, 34];
*temporary register
RV[TempReg6, 62];
*temporary register
RV[APCSave,36];
*register used to save APC in Subroutine Call
RV[C177776,37, 177776]; *constant used in check routine
* put the register block used for memory transfers well away from all other
* registers to prevent contamination.
* Note that registers at 40 thru 47 are also used although no called out here.
RV[RegBlockAdd,35,50];
*contains address of register block used in memory references
RV[RegBlock, 50];
*register block used for SRC/DEST in memory transfers
RV[RegBlock0, 50];
*first register in register block
RV[RegBlock1, 51];
*second register in register block
RV[RegBlock2, 52];
*third register in register block
RV[RegBlock3, 53];
*fourth register in register block
RV[RegBlock4, 54];
*fifth register in register block
RV[RegBlock5, 55];
*sixth register in register block
RV[RegBlock6, 56];
*seventh register in register block
RV[RegBlock7, 57];
*eighth register in register block
RV[C177774,60, 177774]; *constant used in check routine
RV[PageCount,61];
*register containing the actual number of pages of memory
Set[SpecialLoc1,500];
*location in control store for dispatch table 1
Set[SpecialLoc2,600];
*location in control store for dispatch table 2
Set[MainPage,1];
*tag for Main Program page number
Set[SubPage1,2];
*tag for Sub-Program page number 1
Set[sp1b,lshift[SubPage1,10]]; *base address of SubPage1
Set[SubPage2,3];
*tag for Sub-Program page number 2

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

ONPAGE[MainPage];
go:
Start:
CLEARMPANEL;
* initialize counters, registers, and random number
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);
PassCount ← 0C;
TestCounter ← 0C;

LOADPAGE[SubPage1]; * go initialize memory to known values (addresses)
CallP[InitMem];
CurrentPage ← 0C;
BigLoop:t ← (PassCount) + 1;
* to check if MaxPass has already been reached
LU ← (MaxPass) - (t);
GOTO[MainLoop, ALU >= 0];

t ← PassCount; * go increment the maintenance panel equal to PassCount
LOADPAGE[SubPage2];
CallP[IncPanel];

Passed-EDMemAbort-Test:
BREAKPOINT; *go to Midas
GOTO[START];

MainLoop:t ← TestCounter ← (TestCounter) + 1;
GOTO[NextPass,CARRY];*if test counter has overflowed, increment Big Loop
GOTO[SubTest0];

NextPass:PassCount ← (PassCount) + 1;
*increment big loop counter
GOTO[BigLoop];

*** SUBTEST 0 ***
SubTest0:SubTest ← 0C;
*initialize test number
INCMPANEL;

t ← (CurrentPage);*Copy (OldPage ← CurrentPage)
OldPage ← t;

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

t ← LDF[XA,0,14];*Assign (CurrentPage ← LDF[XA,0,14])
CurrentPage ← t;

LU ← (PageCount) - (t) - 1;*IF CurrentPage > PageCount THEN Assign OldPage
GOTO[UseCurrentPage, ALU >= 0];
t ← (OldPage);*Copy (CurrentPage ← OldPage)
CurrentPage ← t;

UseCurrentPage:
t ← LDF[XA,10,10];*Assign (CurrentLoc ← LDF[XA,10,10])
CurrentLoc ← t;

t ← LDF[XA,0,2]; *Assign (CurrentReg ← (RegBlockAdd OR XA[0:1]))
t ← ((RegBlockAdd) OR (t));
CurrentReg ← t;

SET[TypeSel, SpecialLoc1];*Select type of reference based on XA[2:3]
DISPATCH[XA, 2, 2];
DISP[SwitchTypeSel];
SwitchTypeSel:
GOTO[Case0], AT[TypeSel, 0];
GOTO[Case1], AT[TypeSel, 1];
GOTO[Case2], AT[TypeSel, 2];
GOTO[Case3], AT[TypeSel, 3];
Case0:
TypeReg ← 5C;*Type = PFETCH2
t ← 1C;
t ← ((CurrentReg) + t);*Copy (ExpStack ← (CurrentReg) + t)
ExpStack ← t;
GOTO[EndTypeSel];
Case1:
TypeReg ← 6C;*Type = PFETCH4
t ← ((CurrentReg));*Copy (ExpStack ← (CurrentReg))
ExpStack ← t;
GOTO[EndTypeSel];
Case2:
TypeReg ← 11C;*Type = PSTORE2
t ← 1C;
t ← ((CurrentReg) - t);*Copy (ExpStack ← (CurrentReg) - t)
ExpStack ← t;
GOTO[EndTypeSel];
Case3:
TypeReg ← 12C;*Type = PSTORE4
t ← ((CurrentReg));*Copy (ExpStack ← (CurrentReg))
ExpStack ← t;

EndTypeSel:

LOADPAGE[SubPage1];*check that conditions are right with register and location
CallP[Check];

LOADPAGE[SubPage1]; *build memory reference instructions in CS
CallP[SetUpInstructions];

LOADPAGE[SubPage1]; *set up the Base registers used in memory transfers
CallP[SetUpBaseRegs];

*** SUBTEST 1 ***
SubTest1:SubTest ← 1C, AT [471];
TempReg ← (ZERO) - 1;
LOADPAGE[SubPage1];*set up the registers used in memory transfers
CallP[SetUpRegs];
t ← CurrentLoc;

PFETCH4[BasePageEven,RegBlock], AT [700];*this instruction gets rebuilt at run time

LOADPAGE[SubPage2]; *see if everything worked the way we think it should
CallP[TestResults];

ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[SubTest1];

*** SUBTEST 2 ***
SubTest2:SubTest ← 2C, AT [410];
*initialize registers
TempReg ← (ZERO) - 1;

LOADPAGE[SubPage1]; *set up the registers used in memory transfers
CallP[SetUpRegs];

STKP ← TempReg ; *put register in the stack as determined in SetUpRegs
t ← CurrentLoc;

PFETCH4[BasePageEven,Stack], AT [720];*this instruction gets rebuilt at run time

LOADPAGE[SubPage2]; *see if everything worked the way we think it should
CallP[TestResults];

ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[SubTest2];

*** SUBTEST 3 ***
SubTest3:SubTest ← 3C;

t ← STKP; *save the stack pointer
TempReg4 ← t;
TempReg4 ← (TempReg4) XNOR (0C); * put stack in proper order
t ← LDF[TempReg4,10,10]; * get the stack that was saved and test it for expected value

LU ← (ExpStack) - (t);*IF ExpStack=STKP THEN GOTO SubTest4
GOTO[SubTest4, ALU = 0];
Error3:
BREAKPOINT; *Test 3 failed - stack not as expected

ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[SubTest2];
nop;

*** SUBTEST 4 ***
SubTest4:SubTest ← 4C;
*assign SubTestNumber into SubTest
LOADPAGE[SubPage1], AT [456]; *set up the registers used in memory transfers
CallP[SetUpRegs];

t ← (RegBlockAdd);*Copy (ExpStack ← (RegBlockAdd))
ExpStack ← t;
t ← (RegBlockAdd) - 1;*and TempReg and STKP with RegBlockAdd - 1
TempReg ← t;
STKP ← TempReg;
t ← 0C;
PFETCH2[BasePageEven,Stack]; *go do a fetch using stack
t ← STACK&-1; *and try to update the stack during fetch
TempReg ← t; *stuff data read into temporary register
t ← STKP; * save the stack pointer
CS1 ← t; * in CS1 temporarily
CS1 ← (CS1) XNOR (0C); * invert it
t ← LDF[CS1,10,10]; * now get just the bits wanted for test

ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[SubTest4];

LU ← (ExpStack) - (t);*IF ExpStack=STKP THEN GOTO PassSubTest41
GOTO[PassSubTest41, ALU = 0];
Error41:BREAKPOINT;
*Test 4 subtest 1 failed - stack not as expected

ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[SubTest4];
nop;

PassSubTest41:
t ← (CurrentPage) XOR (1C); *calculate what data should have been
LU ← (TempReg) - (t);*Is TempReg=ExpectedData ?
GOTO[SubTest5, ALU = 0];
Error42:BREAKPOINT;
*Test 4 subtest 2 failed - data not as expected
ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[SubTest4];
nop;

*** SUBTEST 5 ***
SubTest5:SubTest ← 5C;
LOADPAGE[SubPage1];*set up the SRC/DEST registers used in memory transfers again
CallP[SetUpRegs];

SET[TypeSelLoc2, SpecialLoc2];*Use XA[2:3] to select cases
DISPATCH[XA, 2, 2];
DISP[SwitchTypeSelLoc2];
SwitchTypeSelLoc2:
GOTO[CaseT51], AT[TypeSelLoc2, 0];* PStore1
GOTO[CaseT52], AT[TypeSelLoc2, 1];* PStore2
GOTO[CaseT53], AT[TypeSelLoc2, 2];
GOTO[CaseT54], AT[TypeSelLoc2, 3];* PStore4
CaseT51:t ← ((RegBlockAdd)), AT [613];*Copy (ExpStack and STKP ← (RegBlockAdd))
ExpStack ← t;
STKP ← RegBlockAdd;
t ← 0C; * load displacement
PSTORE1[BasePageEven,Stack]; *store into main memory
t ← STACK&+1; * and try to increment stack during memory store
TempReg ← t; *stuff the data away for later use
t ← STKP; * get the present value of the stack pointer
CS1 ← t; * in CS1 temporarily
CS1 ← (CS1) XNOR (0C); * invert it
t ← LDF[CS1,10,10]; * now get just the bits wanted for test
LU ← (ExpStack) - (t);*IF ExpStack=STKP THEN GOTO PassSubTest51
GOTO[PassSubTest51, ALU = 0];
Error51:ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[CaseT51];
nop;
BREAKPOINT; *Test 5 subtest 1 failed - stack not as expected
ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[CaseT51];
nop;

PassSubTest51:
GOTO[EndswitchT5];

CaseT52:t ← ((RegBlockAdd) + (2C)), AT [547];*Copy (ExpStack ← (RegBlockAdd) + (2C))
ExpStack ← t;
t ← (RegBlockAdd) + (3C);
TempReg ← t; *put the stack in temporary register
STKP ← TempReg; * set up stack
t ← 0C; * load displacement
PSTORE2[BasePageEven,Stack]; *store into main memory
t ← STACK&+1; * and try to increment stack during memory store
TempReg ← t; *stuff the data away for later use
t ← STKP; * get the present value of the stack pointer
CS1 ← t; * in CS1 temporarily
CS1 ← (CS1) XNOR (0C); * invert it
t ← LDF[CS1,10,10]; * now get just the bits wanted for test
LU ← (ExpStack) - (t);*IF ExpStack=STKP THEN GOTO PassSubTest52
GOTO[PassSubTest52, ALU = 0];
Error52:ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[CaseT52];
nop;
BREAKPOINT; *Test 5 subtest 2 failed - stack not as expected
ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[CaseT52];
nop;

PassSubTest52:
GOTO[EndswitchT5];

CaseT53:GOTO[MainLoop];
*PSTORE3 - no such thing so ignore

CaseT54:t ← (RegBlockAdd) + (4C), AT [570];
*Copy (ExpStack ← (RegBlockAdd) + (4C))
ExpStack ← t;
t ← (RegBlockAdd) + (3C);
TempReg ← t; *put calculated stack in temporary register
STKP ← TempReg; * set up stack
t ← 0C; * load displacement
PSTORE4[BasePageEven,Stack]; *store into main memory
t ← STACK&+1; * and try to increment stack during memory store
TempReg ← t; *stuff the data away for later use
t ← STKP; * get the present value of the stack pointer
CS1 ← t; * in CS1 temporarily
CS1 ← (CS1) XNOR (0C); * invert it
t ← LDF[CS1,10,10]; * now get just the bits wanted for test
LU ← (ExpStack) - (t);*IF ExpStack=STKP THEN GOTO PassSubTest53
GOTO[EndswitchT5, ALU = 0];
Error53:ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[CaseT54];
nop;
BREAKPOINT; *Test 5 subtest 3 failed - stack not as expected
ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[CaseT54];
nop;

EndswitchT5:
LOADPAGE[SubPage1];
CALLP[WritePage]; *go rewrite contaminated page
GOTO[MainLoop]; *go back through loop


********** SUBROUTINE: Check **********
*
*
Sets up TRANSFER flag for later use. It is set up based on the type
*
of transfer to be done. If at the end, TRANSFER = 0, then no actual
*
transfer of data should take place and QUADOVF should be set.

ONPAGE[SubPage1];

Check:
Transfer ← 1C; * initialize the flag
LU ← LDF[TypeReg,17,1]; *IF QuadWordTransfer THEN GOTO QuadWordTransfer
GOTO[QuadWordTransfer, ALU = 0];

t ← LDF[CurrentLoc,16,2]; * double transfer, now see if its modulo 3
CS0 ← t; *use CS0 as temporary register
t ← 3C;
LU ← (CS0) - t;*Is CurrentLoc = 3 Modulo 4 ?
GOTO[Yes3Modulo4, ALU = 0];
GOTO[QuadWordTransfer];

Yes3Modulo4:
Transfer ← 0C; * yes, CurrentLoc = 3 Modulo 4 so set flag for no transfer
GOTO[EndOfCheck];

QuadWordTransfer:
LU ← LDF[TypeReg,17,1];
GOTO[Skip001,ALU=0]; * skip if quad transfer
t ← C177776;
GOTO[ANDIT];

Skip001:t ← C177774;

ANDIT:
CurrentLoc ← (CurrentLoc) AND (t);

EndOfCheck:
RETURN;

********** SUBROUTINE: CheckValues **********
*
*
This routine checks the register block or memory for transfers.
*
At exit from this routine, TempReg will be 0 or -1.
*
If it is 0, then registers on fetch or memory on store were equal to what was
*
tried to be read or written.
*
If it is -1, then they were’nt as expected or tested.

ONPAGE[SubPage2];

CheckValues:
TempReg ← 0C; *init. to ’Pass"
t ← STKP; * Save the stack before using it
TempReg4 ← t; * save it in one of the temproary registers
LU ← (TypeReg) - (10C);*Is this a fetch action ?
GOTO[StoreAction, ALU >= 0];
FetchAction:

LU ← (TypeReg) - (6C);*What kind of fetch type?
GOTO[NotDblFetch, ALU >= 0];
DblFetch:

t ← CS0 ← 1C; * using CS0 as counter, set it to 1 for double
t ← (CurrentLoc) ANDNOT (t); * put location in proper base
TempReg2 ← t;
GOTO[EndOfFetchTypeCheck];
NotDblFetch:

t ← CS0 ← 3C; * using CS0 as counter, set it to 3 for quad
t ← (CurrentLoc) ANDNOT (t); * put location in proper base
TempReg2 ← t;
EndOfFetchTypeCheck:
STKP ← CurrentReg; * initialize the stack

t ← (0C);* FOR CS1 IN[0C..CS0] DO
CS1 ← t;
CheckFetch:
t ← (CS0);
LU ← (CS1) - (t) - 1;
GOTO[EndOfFetchCheck, ALU >= 0];

t ← CS1;
t ← (TempReg2) + (t);
t ← ((CurrentPage) XOR (t));*Copy (CS2 ← (CurrentPage) XOR (t))
CS2 ← t;
t ← STACK&+1;
LU ← (CS2) - (t);*Is CS2=T ?
GOTO[FetchDataMatch, ALU = 0];
TempReg ← (ZERO) - 1; * set flag to error
FetchDataMatch:
CS1 ← (CS1) + 1;*Increment FOR loop counter
GOTO[CheckFetch];
EndOfFetchCheck:
GOTO[EndOfStoreCheck];

StoreAction:

LU ← (TypeReg) - (12C);*What type of Store ?
GOTO[NotDblStore, ALU >= 0];
DblStore:

t ← CS0 ← 1C; * using CS0, set it to 1 for double store
t ← (CurrentLoc) ANDNOT (t); * put location in proper base
TempReg2 ← t;
GOTO[EndOfStoreTypeCheck];
NotDblStore:

t ← CS0 ← 3C; * using CS0, set it to 3 for quad store
t ← (CurrentLoc) ANDNOT (t); * put location in proper base
TempReg2 ← t;

EndOfStoreTypeCheck:
t ← (0C);* FOR CS1 IN[0C..CS0] DO
CS1 ← t;
CheckStore: t ← (CS0);
LU ← (CS1) - (t) - 1;
GOTO[EndOfStoreCheck, ALU >= 0];

t ← CS1;
t ← (TempReg2) + t;
PFETCH1[BasePageEven,CS2];
nop;
nop;
nop;
nop;
nop;
nop;
TempReg5 ← t; * put address in t away for a bit
t ← ((CurrentPage) XOR (t));*Copy (TempReg3 ← (CurrentPage) XOR (t))
TempReg3 ← t;

t ← TempReg5; * now get the address put away above
PSTORE1[BasePageEven,TempReg3];

LU ← (CS2);*Is CS2=t ?
GOTO[StoreDataMatch, ALU = 0];
TempReg ← (ZERO) - 1;
StoreDataMatch:
CS1 ← (CS1) + 1;*Increment FOR loop counter
GOTO[CheckStore];

EndOfStoreCheck:
TempReg4 ← (TempReg4) XNOR (0C); * complement saved stack
STKP ← TempReg4; * and restore the stack
RETURN;

********** SUBROUTINE: IncPanel **********
*
*
Increment the Maintenance Panel.
*
On entry to subroutine, t contains the count of the
*
number of times to increment from 0.

ONPAGE[SubPage2];

IncPanel:TempReg ← t, CLEARMPANEL;
* first put panel at zero
TempReg6 ← 6C;
GOTO[., R>=0], TempReg6 ← (TempReg6) - 1;
GOTO[.+1];
IncLoop:INCMPANEL;
GOTO[.+1];
TempReg ← (TempReg) - 1;*decrement the counter
GOTO[IncLoop, ALU # 0]; * keep it up until it is zero
RETURN;

********** SUBROUTINE: InitMem **********
*
*
Check that we actually got a value for Page Count with limits of
*
0<PageCount<40001.
*
To initialize all of available memory to known values (page number XOR’ed with
*
displacement on page)

ONPAGE[SubPage1];

InitMem:LU ← (PageCount) - 1;
*IF PageCount>0 THEN GOTO NoPageCountError1
GOTO[NoPageCountError1, ALU >= 0];
t ← 2C;

PageCountError1:
BREAKPOINT; *Page Count says no pages
goto[NoPageCountError2];

NoPageCountError1:
t ← 40000C; *maximum allowed pages in 2 to power 22
LU ← (PageCount) - (t) - 1;*IF PageCount<=40000 THEN GOTO NoPageCountError2
GOTO[NoPageCountError2, ALU < 0];
t ← 3C;

PageCountError2:
BREAKPOINT; *Page count larger than allowed

NoPageCountError2:
CurrentPage ← 0C;
t ← 0C;
USECTASK;
t ← APC&APCTASK;
TempReg ← t;
InitLoop:LOADPAGE[SubPage1];
CallP[SetUpBaseRegs];
LOADPAGE[SubPage1];
CallP[WritePage];
t ← (CurrentPage) ← (CurrentPage) + 1; * increment page counter
LU ← (PageCount) - (t) - 1;*IF CurrentPage<=PageCount THEN GOTO InitLoop
GOTO[InitLoop, ALU >= 0];

APC&APCTASK ← TempReg;
RETURN;

********** SUBROUTINE: SetUpBaseRegs **********
*
*
Set up the base registers for page access to main memory based on Current
*
Page contents. Base Page Even is the even base register for references and
*
Base Page Odd is the odd base register.

ONPAGE[SubPage1];

SetUpBaseRegs:
t ← (LDF[CurrentPage,10,10]); * get the lower 8 bits of page number
BasePageEven ← t;
BasePageEven ← LSH[BasePageEven,10]; * shift into upper 8 bits

t ← (LDF[CurrentPage,0,10]); * get the upper eight bits of page number
BasePageOdd ← t;
BasePageOdd ← LSH[BasePageOdd,10]; * shift into upper 8 bits
BasePageOdd ← (BasePageOdd) OR (t); *put in both halfs
BasePageOdd ← (BasePageOdd) + 1; * add 1 to lower half

RETURN;

********** SUBROUTINE: SetUpInstructions **********
*
*
set up the memory reference instructions - build them in Control Store in
*
700 and 720.

ONPAGE[SubPage1];

SetUpInstructions:
InstructionAddress ← AND[0377, 700]C;*Load16Bits (InstructionAddress ← 700)
InstructionAddress ← (InstructionAddress) OR (AND[177400, 700]C);

t ← (InstructionAddress);*Copy (CS2 ← InstructionAddress)
CS2 ← t;

t ← 0C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData, AT[sp1b,10];
CS0 ← t;

t ← 1C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData, AT[sp1b,20];
CS1 ← t;

t ← 3C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData, AT[sp1b,30];
CS2 ← t;
CS2 ← RSH[CS2, 14];

t ← LDF[TypeReg, 14, 4];*CopyField (CS0[06, 4] ← TypeReg[14, 4], temp is TempReg)
TempReg ← 4C;
TempReg ← (TempReg) - 1;
TempReg ← (TempReg) OR (LSHIFT[06, 4]C);
CYCLECONTROL ← TempReg;
TempReg ← t;
t ← WFA[TempReg];
CS0 ← WFB[(CS0) OR t];

t ← LDF[CurrentReg, 10, 6];*CopyField (CS0[12, 6] ← CurrentReg[10, 6], temp is TempReg)
TempReg ← 6C;
TempReg ← (TempReg) - 1;
TempReg ← (TempReg) OR (LSHIFT[12, 4]C);
CYCLECONTROL ← TempReg;
TempReg ← t;
t ← WFA[TempReg];
CS0 ← WFB[(CS0) OR t];

t ← LDF[CurrentReg, 16, 2];*CopyField (CS1[0, 2] ← CurrentReg[16, 2], temp is TempReg)
TempReg ← 2C;
TempReg ← (TempReg) - 1;
TempReg ← (TempReg) OR (LSHIFT[0, 4]C);
CYCLECONTROL ← TempReg;
TempReg ← t;
t ← WFA[TempReg];
CS1 ← WFB[(CS1) OR t];

t ← CS0;*WriteCS (write control store location ’InstructionAddress’)
TempReg ← t; *put CS0 in the temp. reg.
t ← CS1; *get CS1
TempReg ← t ← (TempReg) XOR (t);*exclusive or the first two CS words
t ← (LDF[CS2,14,4]) XOR (t); *now exclusive or the third CS word with the result
TempReg ← t ← (LDF[TempReg,0,10]) XOR (t);*now start halfing process to get parity
TempReg ← t ← (LDF[TempReg,10,4]) XOR (t);
TempReg ← t ← (LDF[TempReg,14,2]) XOR (t);
TempReg ← t ← (LDF[TempReg,16,1]) XNOR (t); *Do last part and complement it
t ← (LDF[TempReg,17,1]); *put parity bit in the t-register
CS1 ← (CS1) XOR (t); * exclusive or the parity bit into bit 31 of CS (15 of CS1)
t ← (CS2);
LU ← (CS0);
APCTASK&APC ← (InstructionAddress);
WriteCS0&2;
LU ← (CS1), AT[sp1b,40];
APCTASK&APC ← (InstructionAddress);
WriteCS1;

InstructionAddress ← AND[0377, 720]C, AT[sp1b,50];*Load16Bits (InstructionAddress ← 720)
InstructionAddress ← (InstructionAddress) OR (AND[177400, 720]C);

t ← (InstructionAddress);*Copy (CS2 ← InstructionAddress)
CS2 ← t;

t ← 0C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData, AT[sp1b,60];
CS0 ← t;

t ← 1C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData, AT[sp1b,70];
CS1 ← t;

t ← 3C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData, AT[sp1b,100];
CS2 ← t;
CS2 ← RSH[CS2, 14];

t ← LDF[TypeReg, 14, 4];*CopyField (CS0[06, 4] ← TypeReg[14, 4], temp is TempReg)
TempReg ← 4C;
TempReg ← (TempReg) - 1;
TempReg ← (TempReg) OR (LSHIFT[06, 4]C);
CYCLECONTROL ← TempReg;
TempReg ← t;
t ← WFA[TempReg];
CS0 ← WFB[(CS0) OR t];

t ← CS0;*WriteCS (write control store location ’InstructionAddress’)
TempReg ← t; *put CS0 in the temp. reg.
t ← CS1; *get CS1
TempReg ← t ← (TempReg) XOR (t);*exclusive or the first two CS words
t ← (LDF[CS2,14,4]) XOR (t); *now exclusive or the third CS word with the result
TempReg ← t ← (LDF[TempReg,0,10]) XOR (t);*now start halfing process to get parity
TempReg ← t ← (LDF[TempReg,10,4]) XOR (t);
TempReg ← t ← (LDF[TempReg,14,2]) XOR (t);
TempReg ← t ← (LDF[TempReg,16,1]) XNOR (t); *Do last part and complement it
t ← (LDF[TempReg,17,1]); *put parity bit in the t-register
CS1 ← (CS1) XOR (t); * exclusive or the parity bit into bit 31 of CS (15 of CS1)
t ← (CS2);
LU ← (CS0);
APCTASK&APC ← (InstructionAddress);
WriteCS0&2;
LU ← (CS1), AT[sp1b,110];
APCTASK&APC ← (InstructionAddress);
WriteCS1;

RETURN, AT[sp1b,120];

********** SUBROUTINE: SetUpRegs **********
*
*
Set up the register block with zeroes before executing any transfers.
*
Additionally, determine what the stack pointer should be after the
*
stack transfer and put it in TempReg for later use by caller.

ONPAGE[SubPage1];

SetUpRegs:
STKP ← RegBlockAdd; * set up stack to point to register block
t ← (0C);* FOR TempReg IN[0C..17C] DO
TempReg ← t;

TempRegClear:
t ← (17C);
LU ← (TempReg) - (t) - 1;
GOTO[EndTempRegClear, ALU >= 0];
STACK&+1 ← 0C; * zero out the registers
TempReg ← (TempReg) + 1;*Increment FOR loop counter
GOTO[TempRegClear];

EndTempRegClear:
LU ← (LDF[TypeReg,17,1]);*Is this DoubleWordTransfer ?
GOTO[NotDoubleWordTrans, ALU = 0];

LU ← (TypeReg) - (11C);*Is it a fetch type transfer ?
GOTO[StoreTypeTrans, ALU >= 0];

FetchTypeTrans:

t ← ((CurrentReg) - 1);*Yes, it’s a fetch type transfer
TempReg ← t;*Copy (TempReg ← (CurrentReg) - 1)
GOTO[EndOfSetUpRegs];

StoreTypeTrans:

t ← ((CurrentReg) + 1);*Copy (TempReg ← (CurrentReg) + 1)
TempReg ← t;
GOTO[EndOfSetUpRegs];

NotDoubleWordTrans:

t ← (CurrentReg);*Copy (TempReg ← CurrentReg)
TempReg ← t;

EndOfSetUpRegs:
RETURN;

********** SUBROUTINE: TestResults **********
*
*
Test the results of tests 1 or 2 and see if they worked as expected.
*
On entry, TRANSFER and QUADOVF determine which way to go. If TRANSFER
*
is equal to zero, then no transfer should occur.

ONPAGE[SubPage2];

TestResults:t ← 0C;
USECTASK;
t ← APC&APCTASK;
APCSave ← t;
GOTO[QuadIsSet, QUADOVF]; *see if overflow bit is set

QuadIsNotSet:LU ← (Transfer);
*Do the transfer ?
GOTO[YesTransfer, ALU # 0];
NoTransfer:LU ← (SubTest) - (2C);
* see if it is test 2
GOTO[ErrorNoOvfl, ALU = 0]; * if it is, then BREAKPOINT
GOTO[YesTransfer]; * if not, it is not an error
ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[GetOutOfHere];
nop;
ErrorNoOvfl:BREAKPOINT;
* overflow bit is not set when it should be
goto[GetOutOfHere];
YesTransfer:LOADPAGE[SubPage2];
CallP[CheckValues]; *go check memory/registers to check on transfers
LU ← (TempReg);*Is TempReg<0 ?
GOTO[EndOfQuadIsNotSet, ALU >= 0];
ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[GetOutOfHere];
ErrorDataCompare:
BREAKPOINT; * data transferred did not compare
goto[GetOutOfHere];
EndOfQuadIsNotSet:
GOTO[GetOutOfHere];

QuadIsSet:LU ← (Transfer);
*Do the transfer ?
GOTO[NoTransferQS, ALU = 0];
ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[GetOutOfHere];
ErrorOvflSet:BREAKPOINT;
* overflow bit is set when it shouldn’t be
goto[GetOutOfHere];
NoTransferQS:LOADPAGE[SubPage2];
CallP[CheckValues];
LU ← (TempReg);*Is TempReg=0 ?
GOTO[GetOutOfHere, ALU # 0];
ShortLoop ← ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected
goto[GetOutOfHere];
ErrorDidTrans:
BREAKPOINT; * transferred data when not supposed to

GetOutOfHere:
APC&APCTASK ← APCSave;
RETURN;

********** SUBROUTINE: WritePage **********
*
*
actually do the writing in all locations in a page

ONPAGE[SubPage1];

WritePage:CurrentLoc ← 0C;
* FOR CurrentLoc IN[0C..377C] DO
WriteLoop:t ← (377C);
LU ← (CurrentLoc) - (t) - 1;
GOTO[EndWriteLoop, ALU >= 0];

t ← CurrentLoc; *get the displacement
t ← ((CurrentPage) XOR (t));*Copy (RegBlock0 ← (CurrentPage) XOR (t))
RegBlock0 ← t;

t ← CurrentLoc; *get the displacement, again
PSTORE1[BasePageEven,RegBlock0]; *write the location

CurrentLoc ← (CurrentLoc) + 1;*Increment FOR loop counter
GOTO[WriteLoop];
EndWriteLoop:
RETURN;

END;* to end the MAIN routine