%
*** *** *** *** Revision 1 *** *** *** ***

************************************************************************************************
*** EDTask.mc : The Task Switching and Register Addressing Test Program
*** Purpose : To test task mechanism and register addressing modes.
*** Hardware Configuration : Standard 4 CPU boards
*** Written by : Tom Horsley, Dec. 12, 1977
*** Modified by : Bill Kennedy, Feb. 23, 1978
Added control store parity.
Took code off page 0.
*** Modified by : Bill Kennedy, Apr. 6, 1978
Stayed from a KERNEL register and added meaningful tags to Breakpoints.
*** Modified by : Chuck Thacker, Jan. 25, 1979
Changed for 8G configuration.
*** Modified by : Chuck Thacker, June 16, 1979
Changed to avoid stack overflow.
*** Modified by : Camellia Chan, Mar. 4, 1980
Standardize title page, code format, labels and looping.
*** Modified by : Chuck Thacker, May 3, 1980
standardized assembly with task.cm, fixed for new d0lang.
************************************************************************************************



************************************************************************************************
*SubTest Description:
* SubTest 1: In the READ test, confirm that the contents (Result) of the register read
(TargetRegister) match those expected (TargetValue).
In this test, the absolute address of the register to be tested is calculated using
RMOD, RSEL, TASK, STKSHFT, and REGSHIFT from XA. Then control store instruction 760
is stuffed with an appropriate read instruction. Finally a random value from XB is
written into the absolute register location via the stack, a switch is made to the
relevant task and the instruction at location 760 is executed.
* SubTest 2: In the StackCompare test, confirm that the expected stack pointer (ExpectedStkp)
matches the value of the STKP found immediately after the read or write instruction
(SaveStkp).
* SubTest 3: In the WRITE test, confirm that the contents (t) of the register written
(TargetRegister) match those expected (TargetValue).

The write test is similar to the read test except that location 762 is stuffed and
the test is not performed on some of the special hardware registers.

*
Note: Registers outside the range R46 to R360 are not read or written in any test.


************************************************************************************************
*BreakPoints:
* ReadFail: the contents (Result) of the register read (TargetRegister) do not match those
expected (TargetValue).
* StackFail: the content (ExpectedStkp) does not match the value of the STKP found immediatley
after the read or write instruction (SaveStkp).
* WriteFail: the contents (t) of the register written (TargetRegister) do not match those
expected (TargetValue).
* Passed-EDTask-Test: Passed all tests, and all passes.


****************************************************************************************
* ShortLoop Logic Analyzer Sync Points at Control Store address:
* ReadFail: Control Store address 770 at SubTest1.
* StackFail: Control Store address 1546 at StackCompare.
* WriteFail: Control Store address 772 at SubTest3.

************************************************************************************************
*Subroutine Description:
* FirstSixBits:
deciphers the first six bits of the absolute R-register from Target Task.
* LastTwoBits:
inserts the last two bits of the absolute R-register from t.
* NewInstx:
NewInst is now done when control is at 2001b+4*n, n=0-377b.
* PrimeTarget:
prime the target register with a value.
* ReadTest:
executes the read test.
* SetUpRead:
create environment for read test.
* StackCompare:
make sure the stack pointer is correct.
* WriteTest:
sets up and executes the write test.


************************************************************************************************
*Special Reg. Definition:
* XA: The arguments of the test are built up from the random 16-bit word (XA) as follows:

RMOD=XA[0]
RSEL=XA[1-6]
TASK=XA[7-12]
PCF=XA[13-15]
DB=XA[12-17]
SB=XA[12-17]
STKSHFT=XA[7]
REGSHIFT=XA[10]
STKP=XA[10-17]
Rd/Wr=XA[13]

XA is used to choose a task and a register addressing mode (RMOD and RSEL).
It is also used to decide whether to test reading or writing the register and to
provide starting values for such registers as DB, SB,PCF and STKP.

* InnerLoopCounter: 16 bits inner loop counter.

*
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.
* PassCount:Outer loop pass counter,
incremented each time when InnerLoopCounter reached the limit.

* MaxPass:
number of times outer loop is to repeat before breakpointing.
* NewRand:1 = change the pseudorandom number.
0 = keep the current pseudorandom number.

* ShortLoop:
At any breakpoint the user has the option of changing the value of ShortLoop
to 1, which will cause the current subtest to loop endlessly. If ShortLoop is a zero
then the program will proceed to the next subtest.
************************************************************************************************
%

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

TITLE[EDTask];
*Task and register test program, ED revision
SET[MainPage, 2];
*definition of Main Program page
SET[SubPage1, 1];
*definition of Subroutine page 1
SET[sp1b,lshift[SubPage1,10]];
SET[SubPage2, 4];
*definition of Subroutine page 2
SET[sp2b,lshift[SubPage2,10]];
SET[SubPage3, 3];
*definition of Subroutine page 3

**************************** Switch Base: *****************************

SET[SpecialBigSwitch, 1120];
*switch base for special register selection
SET[SpecialSmallSwitch, 1140];
*switch base for special register
SET[outerSwitch, 1240];
*base of switch on RSEL[4:5]
SET[StkSwitch0, 1460];
*stack switch base
SET[StkSwitch1, 1500];
*stack switch base
SET[RegBase, 40];

**************************** Offsets: *****************************

SET[InitialStkpOffset, 0];
SET[TargetValueOffset, 1];
SET[TmpOffset, 2];
SET[SaveStkpOffset, 3];
SET[ResultOffset, 4];
SET[ReentryOffset, 5];

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

RV[Revision,0 ,1]
*REVISION 1
RV[Run-Time,1,5]
*Run-Time is 5 seconds


RV[InnerLoopCounter,2,0];
*16 bits inner loop counter
RV[PassCount,3];
*outer loop pass counter incremented each time when
* InnerLoopCounter reached the limit
RV[MaxPass,4, 2];
*number of times outer loop is to repeat before breakpointing
RV[NewRand,5,1];
*1 = change the pseudorandom number
*0 = keep the current pseudorandom number
RV[ShortLoop,6,0];
*1 = loop endlessly on current subtest
*0 = proceed to the next subtest
RV[SubTest,7];
*current location of test

RV[DBTest,11];
*number of times the DB register test has executed
RV[MiscTest,12];
*number of times the Misc registers test has executed
RV[PCFTest,13];
*number of times the PCF register test has executed
RV[RRTest,14];
*number of times the straight register test has executed
RV[SBTest,15];
*number of times the SB register test has executed
RV[StkTest,16];
*number of times the stack register test has executed

RV[CS0,17];
*temporary storage for first word of a control store location
RV[CS1,20];
*temporary storage for second word of a control store location
RV[CS2,21];
*temporary storage for third word of a control store location
RV[DeltaStack,22];
*amount by which stack is to be incremented or decremented
RV[DummyRegister,23];
*used as a place holder in instruction to be stuffed
RV[ExpectedStkp,24];
*value of STKP after stack operation
RV[FieldMask,25];
*indicates part of result to be tested (usually all 1’s)
RV[InitialCycCtl,26];
*value to be stuffed into cyclecontrol immmedialtly preceding
* read test
RV[InstructionAddress,27];
*location of CS instruction to be stuffed
RV[NewTask,30];
*task switching contents for APC&APCTASK
RV[RegShiftFlag,31];
*indicates that the REGSHIFT function is to be used
RV[StackShiftFlag,32];
*indicates that the STACKSHIFT function is to be used
RV[StkpTest,33];
*indicates that the STKP is to be checked after the test
RV[StuffTmp,34];
*used in the stuff operations
RV[TargetRegister,35];
*the absolute address of the register to be tested
RV[TargetTask,36];
*the task that will be briefly entered for test purposes


RV[InitialStkp,40,ADD[RegBase, InitialStkpOffset]];
*value of STKP before stack operation
RV[TargetValue,41,ADD[RegBase, TargetValueOffset]];
*value to be stuffed in register
RV[Tmp,42,ADD[RegBase, TmpOffset]];
*used to load APC in remote task
* (different for each task)
RV[SaveStkp,43,ADD[RegBase, SaveStkpOffset]];
*contents of STKP placed here by upper task
RV[Result,44,ADD[RegBase, ResultOffset]];
*contents of target register placed here
* by upper task
RV[WriteTestReentryLoc,45,ADD[RegBase, ReentryOffset]];
*location in task 0 to return to

RV[CA,52];
*used in random number generation, A*XA + CA
RV[CB,53];
*used in random number generation, A*XB + CB
RV[XA,54];
*random number generated via A*XA + CA
RV[XB,55];
*used in random number generation, A*XB + CB

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

ONPAGE[MainPage];

go:
start:
*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 ← 456, CB ← 33035)
XB ← AND[0377, 456]C;*Load16Bits (XB ← 456)
XB ← (XB) OR (AND[177400, 456]C);

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

CLEARMPANEL;
PassCount ← 0C;
RRTest ← 0C;
PCFTest ← 0C;
SBTest ← 0C;
DBTest ← 0C;
StkTest ← 0C;
MiscTest ← 0C;

WriteTestReentryLoc ← AND[0377, 772]C;*Load16Bits (WriteTestReentryLoc ← 772)
WriteTestReentryLoc ← (WriteTestReentryLoc) OR (AND[177400, 772]C);

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

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

***** SUBTEST0 *****
mainLoop:
SubTest ← 0C;
RegShiftFlag ← 0C;
StackShiftFlag ← 0C;
StkpTest ← 0C;
InitialStkp ← 20c;
FieldMask ← (ZERO) - 1;

LU ← (NewRand);
GOTO[SetTTask, ALU = 0];

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;

SetTTask:
t ← LDF[XA, 7, 4];
TargetTask ← t;
lu ← (TargetTask) - (16C);
GOTO[ChooseTest, ALU < 0];
GOTO[mainLoop]; *don’t touch tasks 16 or 17 (kernel)

*choose test
ChooseTest:
LU ← (XA) AND (100000C);
GOTO[OutSwitch, ALU # 0];

*xxxxxxRR
LOADPAGE[SubPage3];
CALLP[FirstSixBits];
RRTest ← (RRTest) + 1;
GOTO[RunSubTest];


* Switch4 (Use DISPATCH[XA, 5, 2] to select cases. Locate switch table at outerSwitch.)
OutSwitch:
SET[Switch10, outerSwitch];
DISPATCH[XA, 5, 2];
DISP[SwitchTab10];

SwitchTab10:
GOTO[Case10], AT[Switch10, 0];
GOTO[Case11], AT[Switch10, 1];
GOTO[Case12], AT[Switch10, 2];
GOTO[Case13], AT[Switch10, 3];

*xxxxxxPP - PCF
Case10:
LOADPAGE[SubPage3];
CALLP[FirstSixBits];
t ← LDF[XA, 13, 2];
LOADPAGE[SubPage3];
CALLP[LastTwoBits];
t ← LDF[XA, 13, 3];
Tmp ← t;
PCF ← Tmp;
PCFTest ← (PCFTest) + 1;
GOTO[RunSubTest];

*xxxxxxSS - SB
Case11:
LOADPAGE[SubPage3];
CALLP[FirstSixBits];
t ← LDF[XA, 12, 2];
LOADPAGE[SubPage3];
CALLP[LastTwoBits];
t ← LDF[XA, 12, 6];
Tmp ← t;
SB ← Tmp;
BBFB; *to advance SB to SBX
SBTest ← (SBTest) + 1;
GOTO[RunSubTest];

*xxxxxxDD - DB
Case12:
LOADPAGE[SubPage3];
CALLP[FirstSixBits];
t ← LDF[XA, 12, 2];
LOADPAGE[SubPage3];
CALLP[LastTwoBits];
t ← LDF[XA, 12, 6];
Tmp ← t;
DB ← Tmp;
BBFB; *to advance DB to DBX
DBTest ← (DBTest) + 1;
GOTO[RunSubTest];

Case13:
t ← 3C;
LU ← (LDF[XA, 1, 2]) - (t);
GOTO[SpecialReg, ALU # 0];

* SSSSSSSS - STKP
LOADPAGE[SubPage3];
GOTOP[.+1];
ONPAGE[SubPage3];

t ← LDF[XA, 10, 10];
TargetRegister ← t;
t ← LDF[XA, 7, 1];
StackShiftFlag ← t;
t ← LDF[XA, 10, 10];
ExpectedStkp ← t;
t ← (ExpectedStkp);
InitialStkp ← t;
lu ← (InitialStkp) and not (37c);
goto[.+3,alu#0];

AbandonTest:
loadpage[mainPage];
gotop[mainLoop];*don’t load stkp with <40b

LU ← (StackShiftFlag);
GOTO[StkSwitchB, ALU # 0];

* Switch4 (Use DISPATCH[XA, 3, 2] to select cases. Locate switch table at StkSwitch0.)
StkSwitchA:
SET[Switch20, StkSwitch0];
DISPATCH[XA, 3, 2];
DISP[SwitchTab20];

SwitchTab20:
GOTO[Case20], AT[Switch20, 0];
GOTO[Case21], AT[Switch20, 1];
GOTO[Case22], AT[Switch20, 2];
GOTO[Case23], AT[Switch20, 3];

Case20:
DeltaStack ← 0C;
GOTO[DltStack];

Case21:
DeltaStack ← 1C;
GOTO[DltStack];

Case22:
DeltaStack ← (ZERO) - 1;
GOTO[DltStack];

Case23:
t ← 2C;
DeltaStack ← (ZERO) - (t);
GOTO[DltStack];

* Switch4 (Use DISPATCH[XA, 3, 2] to select cases. Locate switch table at StkSwitch1.)
StkSwitchB:
SET[Switch30, StkSwitch1];
DISPATCH[XA, 3, 2];
DISP[SwitchTab30];

SwitchTab30:
GOTO[Case30], AT[Switch30, 0];
GOTO[Case31], AT[Switch30, 1];
GOTO[Case32], AT[Switch30, 2];
GOTO[Case33], AT[Switch30, 3];

Case30:
DeltaStack ← 2C;
GOTO[DltStack];

Case31:
DeltaStack ← 3C;
GOTO[DltStack];

Case32:
LOADPAGE[MainPage];
GOTOP[mainLoop];

Case33:
t ← 3C;
DeltaStack ← (ZERO) - (t);

DltStack:
LU ← (XA) AND (000020C);
GOTO[SubtractStk, ALU # 0];

*add DeltaStack to lower 4 bits of ExpectedStkp with no carry into upper bits
t ← (ExpectedStkp) AND (17C);
ExpectedStkp ← (ExpectedStkp) AND NOT (17C);
t ← (DeltaStack) + (t);
Tmp ← t;
t ← (Tmp) AND (17C);
ExpectedStkp ← (ExpectedStkp) OR (t);
GOTO[SetStkp];

*subtract DeltaStack from lower 4 bits of InitialStkp with no carry into upper bits
SubtractStk:
t ← (InitialStkp) AND (17C);
InitialStkp ← (InitialStkp) AND NOT (17C);
Tmp ← t;
Tmp ← (Tmp) + (20C);
t ← DeltaStack;
Tmp ← (Tmp) - (t);
t ← (Tmp) AND (17C);
InitialStkp ← (InitialStkp) OR (t);

SetStkp:
StkpTest ← 1C;
StkTest ← (StkTest) + 1;
LOADPAGE[2];
GOTOP[.+1];
ONPAGE[2];

GOTO[RunSubTest];

*Special Registers
SpecialReg:
t ← LDF[XA, 10, 1];
RegShiftFlag ← t;

LU ← (NewRand);
GOTO[SetTarValue, ALU = 0];

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

SetTarValue:
t ← (XB);
TargetValue ← t;

LU ← (XA) AND (040000C);
GOTO[SmallSwitch, ALU # 0];

* Switch8 (Use DISPATCH[XA, 2, 3] to select cases. Locate switch table at SpecialBigSwitch.)
BigSwitch:
SET[Switch40, SpecialBigSwitch];
DISPATCH[XA, 2, 3];
DISP[SwitchTab40];

SwitchTab40:
GOTO[Case40], AT[Switch40, 0];
GOTO[Case41], AT[Switch40, 1];
GOTO[Case42], AT[Switch40, 2];
GOTO[Case43], AT[Switch40, 3];
GOTO[Case44], AT[Switch40, 4];
GOTO[Case45], AT[Switch40, 5];
GOTO[Case46], AT[Switch40, 6];
GOTO[Case47], AT[Switch40, 7];

* RSEL = 3, SSTKP, STKP
*Load SSTKP
Case40:
t ← LDF[XB, 0, 10];
Tmp ← t;
lu ← (Tmp) and not (37c);
goto[.+3,alu#0];

AbandonTest1:
loadpage[mainPage];
gotop[mainLoop];*don’t load stkp with <40

STKP ← Tmp;
loadpage[4];
callp[NewInstx];*NewInst is now done when control is at 2001b+4*n, n=0-377b

*Load STKP
t ← LDF[XB, 10, 10];
InitialStkp ← t;
InitialStkp ← (InitialStkp) xor (377c);
lu ← (InitialStkp) and not (37c);
goto[IncMiscTest,ALU#0];
goto[AbandonTest1];

* RSEL = 7, (ALURESULT), SALUF
Case41:
FieldMask ← 377C;
t ← TargetValue;
t ← (ZERO) OR NOT (t);
SALUF ← t;
GOTO[IncMiscTest];

* RSEL = 13, MEMSYNDROME
Case42:
GOTO[mainLoop];

* RSEL = 17, MEMERROR
Case43:
GOTO[mainLoop];

* RSEL = 23, UNUSED
Case44:
GOTO[mainLoop];

* RSEL = 27
Case45:
LU ← (RegShiftFlag);
GOTO[GoBack, ALU # 0];

* CYCLECONTROL, PCXREG, PCFREG
FieldMask ← AND[0377, 177567]C;*Load16Bits (FieldMask ← 177567)
FieldMask ← (FieldMask) OR (AND[177400, 177567]C);

* Load PCXREG
t ← LDF[XB, 10, 4];
Tmp ← t;
PCF ← Tmp;
loadpage[4];
callp[NewInstx];*NewInst is now done when control is at 2001b+4*n, n=0-377b

* NEWINST;
* Load PCXREG
t ← LDF[XB, 14, 4];
Tmp ← t;
PCF ← Tmp;

* Load CycleControl (DBX and MWX)
t ← LDF[XB, 0, 10];
InitialCycCtl ← t;
GOTO[IncMiscTest];

* PRINTER
GoBack:
GOTO[mainLoop];

* RSEL = 33
Case46:
LU ← (RegShiftFlag);
GOTO[SetDB&SB, ALU # 0];

* TIMER
GOTO[mainLoop];

* DBREG, SBREG
SetDB&SB:
FieldMask ← AND[0377, 7777]C;*Load16Bits (FieldMask ← 7777)
FieldMask ← (FieldMask) OR (AND[177400, 7777]C);
t ← LDF[TargetValue, 4, 6];
Tmp ← t;
DB ← Tmp;
t ← LDF[TargetValue, 12, 6];
Tmp ← t;
SB ← Tmp;
BBFB;*to advance DB to DBX and SB to SBX
GOTO[IncMiscTest];

* RSEL = 37
Case47:
LU ← (RegShiftFlag);
GOTO[SetMNBR, ALU # 0];

* RS232
GOTO[mainLoop];

* MNBR
SetMNBR:
MNBR ← TargetValue;
GOTO[IncMiscTest];

* Switch4 (Use DISPATCH[XA, 3, 2] to select cases. Locate switch table at SpecialSmallSwitch.)
SmallSwitch:
SET[Switch50, SpecialSmallSwitch];
DISPATCH[XA, 3, 2];
DISP[SwitchTab50];

SwitchTab50:
GOTO[Case50], AT[Switch50, 0];
GOTO[Case51], AT[Switch50, 1];
GOTO[Case52], AT[Switch50, 2];
GOTO[Case53], AT[Switch50, 3];

* RSEL = 43, APCTASK, APC
Case50:
GOTO[mainLoop];

* RSEL = 47, CTASK, NCIA
Case51:
GOTO[mainLoop];

* RSEL = 53, CSDATA
* CSDATA will be loaded just prior to switching to higher task
Case52:
GOTO[IncMiscTest];

* RSEL = 57, PAGE, PARITY, BOOTREASON
Case53:
GOTO[mainLoop];


IncMiscTest:
MiscTest ← (MiscTest) + 1;
LOADPAGE[SubPage1];
CALLP[SetUpRead];
LOADPAGE[SubPage1];
CALLP[ReadTest];
GOTO[mainLoop];

RunSubTest:
LOADPAGE[SubPage3];
GOTOP[.+1];
ONPAGE[SubPage3];

*actual test
LU ← (XA) AND (000020C);
GOTO[Write, ALU # 0];

*Read Test
LOADPAGE[SubPage1];
CALLP[SetUpRead];
LOADPAGE[SubPage2];
CALLP[PrimeTarget];
LOADPAGE[SubPage1];
CALLP[ReadTest];
GOTO[CheckStkp];

*Write Test
Write:
LOADPAGE[SubPage2];
CALLP[WriteTest];

CheckStkp:
LU ← (StkpTest);
GOTO[RepeatQ, ALU = 0];
LOADPAGE[SubPage3];
CALLP[StackCompare];
nop;

RepeatQ:
LOADPAGE[MainPage];
GOTOP[mainLoop];

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

********** SUBROUTINE: FirstSixBits **********
*
*
deciphers the first six bits of the absolute R-register from Target Task

ONPAGE[SubPage3];
FirstSixBits:
LU ← (XA) AND (060000C);
GOTO[ShiftTarget, ALU # 0];

*TTTTRRxx
t ← LSH[TargetTask, 4];
t ← (LDF[XA, 3, 4]) OR t;
GOTO[SetTarget];

*TTRRRRxx
ShiftTarget:
t ← RSH[TargetTask, 2];
TargetRegister ← t;
t ← LSH[TargetRegister, 6];
t ← (LDF[XA, 1, 6]) OR t;

SetTarget:
TargetRegister ← t;
RETURN;





********** SUBROUTINE: LastTwoBits **********
*
*
inserts the last two bits of the absolute R-reg from t

ONPAGE[SubPage3];
LastTwoBits:
TargetRegister ← RSH[TargetRegister, 2];
TargetRegister ← (LSH[TargetRegister, 2]) OR t;
RETURN;





********** SUBROUTINE: NewInstx **********
*
*
NewInst is now done when control is at 2001b+4*n, n=0-377b

OnPage[SubPage2];
NewInstx:
Return, at[2001];



********** SUBROUTINE: PrimeTarget **********
*
*
prime the target register with a value

ONPAGE[SubPage2];

PrimeTarget:
LU ← (TargetRegister) - (46C);
GOTO[SkipRead, ALU < 0];
t ← 360C;*done this way (with t) due to assembler bug
LU ← (TargetRegister) - (t);
GOTO[SetStkp2, ALU < 0];
NOP;

SkipRead:
LoadPage[mainPage];*don’t do read test
gotop[mainLoop];

SetStkp2:
stkp ← TargetRegister;
LU ← (NewRand);
GOTO[SetTarValue2, ALU = 0];

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

SetTarValue2:
t ← XB;
TargetValue ← t;
STACK ← t;
RETURN;

********** SUBROUTINE: ReadTest **********
*
*
executes the read test.

ONPAGE[SubPage1];

*switch to higher task
*set up CSDATA
ReadTest:
LU ← TargetValue;
APC&APCTASK ← InstructionAddress;
WRITECS1;
t ← 1C,at[sp1b,14];
APC&APCTASK ← InstructionAddress;
READCS;
CYCLECONTROL ← InitialCycCtl,at[sp1b,16];
STKP ← InitialStkp;

APC&APCTASK ← NewTask;
RETURN;

HighTask760:
*IN HIGHER TASK
t ← DummyRegister, REGSHIFT, AT[760];

*Save test results
Result ← t;*Result will be different for each task
t ← (GETRSPEC[103]) OR (177400C);*get the STKP in a form ready to be inverted

*Put test results in low register memory
Tmp ← ADD[RegBase, SaveStkpOffset]C;
STKP ← Tmp;
STACK ← (ZERO) OR NOT (t);*write SaveStkp( inverting STKP first)
t ← Result;
STACK&+1 ← t;*write Result

*Load16Bits (Tmp ← 770)
Tmp ← AND[0377, 770]C;
Tmp ← (Tmp) OR (AND[177400, 770]C);

*Tmp will be different for each task
APC&APCTASK ← Tmp;
RETURN;


***** SUBTEST1 *****
SubTest1:
SubTest ← 1C, AT[770];
t ← FieldMask;
TargetValue ← (TargetValue) AND (t);
t ← Result ← (Result) AND (t);
LU ← (TargetValue) - (t);
GOTO[ReadSuccess, ALU = 0];

ShortLoop ← ShortLoop, GOTO[.+2, R EVEN]; *Test for shortLoop option
GOTO[SubTest1];*ShortLoop selected

ReadFail:
BREAKPOINT;

ShortLoop ← ShortLoop, GOTO[.+2, R EVEN]; *Test for shortLoop option
GOTO[SubTest1];*ShortLoop selected
NOP;*resolves a branching conflict

ReadSuccess:
RETURN;

********** SUBROUTINE: SetUpRead **********
*
*
create environment for read test


ONPAGE[SubPage1];
NOP, AT[777];

SetUpRead:
*modify the register reference instruction
InstructionAddress ← AND[0377, 760]C;*Load16Bits (InstructionAddress ← 760)
InstructionAddress ← (InstructionAddress) OR (AND[177400, 760]C);

*readCS (read control store location ’InstructionAddress’)
*use CS2 for a temporary register until end
t ← (InstructionAddress);
CS2 ← t;
t ← 0C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData, AT[sp1b,2];
CS0 ← t;
t ← 1C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData, AT[sp1b,4];
CS1 ← t;
t ← 3C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData, AT[sp1b,6];
CS2 ← t;
CS2 ← RSH[CS2, 14];

*stuffRsel (set the RMOD and RSEL fields in CS0, CS1, CS2 to contents of XA)
*CopyField (CS0[01, 5] ← XA[0, 5], temp is stuffTmp)
t ← LDF[XA, 0, 5];
stuffTmp ← 5C;
stuffTmp ← (stuffTmp) - 1;
stuffTmp ← (stuffTmp) OR (LSHIFT[01, 4]C);
CYCLECONTROL ← stuffTmp;
stuffTmp ← t;
t ← WFA[stuffTmp];
CS0 ← WFB[(CS0) OR t];
CS0 ← (CS0) XOR (030000C);*invert bits in microinstruction

*CopyField (CS2[14, 2] ← XA[5, 2], temp is stuffTmp)
t ← LDF[XA, 5, 2];
stuffTmp ← 2C;
stuffTmp ← (stuffTmp) - 1;
stuffTmp ← (stuffTmp) OR (LSHIFT[14, 4]C);
CYCLECONTROL ← stuffTmp;
stuffTmp ← t;
t ← WFA[stuffTmp];
CS2 ← WFB[(CS2) OR t];

*stuffF2 (set the F2 field in CS0, CS1, CS2 to 12)
StuffTmp ← OR[LSHIFT[2, 4], SUB[4, 1]]C;
CYCLECONTROL ← StuffTmp;
StuffTmp ← 12C;
t ← WFA[StuffTmp];
CS1 ← WFB[(CS1) OR t];
LU ← (StackShiftFlag);
GOTO[CheckFlag, ALU = 0];

*stuffF2 (set the F2 field in CS0, CS1, CS2 to 03)
StuffTmp ← OR[LSHIFT[2, 4], SUB[4, 1]]C;
CYCLECONTROL ← StuffTmp;
StuffTmp ← 03C;
t ← WFA[StuffTmp];
CS1 ← WFB[(CS1) OR t];

CheckFlag:
LU ← (RegShiftFlag);
GOTO[WriteCS, ALU = 0];

*stuffF2 (set the F2 field in CS0, CS1, CS2 to 00)
StuffTmp ← OR[LSHIFT[2, 4], SUB[4, 1]]C;
CYCLECONTROL ← StuffTmp;
StuffTmp ← 00C;
t ← WFA[StuffTmp];
CS1 ← WFB[(CS1) OR t];

*writeCS (write control store location ’InstructionAddress’)
WriteCS:
t ← (CS0);
Tmp ← t;* put CS0 in the temp. reg.
t ← (CS1);* get CS1
Tmp ← t ← (Tmp) 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
Tmp ← t ← (LDF[Tmp,0,10]) XOR (t);*now start the halfing process to get parity
Tmp ← t ← (LDF[Tmp,10,4]) XOR (t);
Tmp ← t ← (LDF[Tmp,14,2]) XOR (t);
Tmp ← t ← (LDF[Tmp,16,1]) XNOR (t);*do last part and complement it
t ← (LDF[Tmp,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,10];
APCTASK&APC ← (InstructionAddress);
WriteCS1;

*set up higher task
t ← LSH[TargetTask, 14], at[sp1b,12];
NewTask ← t;

Tmp ← AND[0377, 760]C;*Load16Bits (Tmp ← 760)
Tmp ← (Tmp) OR (AND[177400, 760]C);
t ← Tmp;
NewTask ←(NewTask) OR (t);

*set up for writing into control store the value that will be read into CSDATA
InstructionAddress ← AND[0377, 777]C;*Load16Bits (InstructionAddress ← 777)
InstructionAddress ← (InstructionAddress) OR (AND[177400, 777]C);

RETURN;





********** SUBROUTINE: StackCompare **********
*
*
make sure the stack pointer is correct

ONPAGE[SubPage3];

***** SUBTEST2 *****
StackCompare:
SubTest ← 2C;
t ← (SaveStkp) AND (0377C);
LU ← (ExpectedStkp) - (t);
GOTO[StackSuccess, ALU = 0];

ShortLoop ← ShortLoop, GOTO[.+2, R EVEN];*Test for shortLoop option
GOTO[StackCompare];*ShortLoop selected

StackFail:
BREAKPOINT;

ShortLoop ← ShortLoop, GOTO[.+2, R EVEN];*Test for shortLoop option
GOTO[StackCompare];*ShortLoop selected
NOP;*resolves a branching conflict

StackSuccess:
RETURN;


********** SUBROUTINE: WriteTest **********
*
*
sets up and executes the write test

ONPAGE[SubPage2];

WriteTest:

*modify the register reference instruction
InstructionAddress ← AND[0377, 762]C;*Load16Bits (InstructionAddress ← 762)
InstructionAddress ← (InstructionAddress) OR (AND[177400, 762]C);

*readCS (read control store location ’InstructionAddress’)
*use CS2 for a temporary register until end
t ← (InstructionAddress);
CS2 ← t;
t ← 0C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData,at[sp2b,20];
CS0 ← t;
t ← 1C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData,at[sp2b,22];
CS1 ← t;
t ← 3C;
APCTASK&APC ← (CS2);
READCS;
t ← CSData,at[sp2b,24];
CS2 ← t;
CS2 ← RSH[CS2, 14];

*stuffRsel (set the RMOD and RSEL fields in CS0, CS1, CS2 to contents of XA)
*CopyField (CS0[01, 5] ← XA[0, 5], temp is stuffTmp)
t ← LDF[XA, 0, 5];
stuffTmp ← 5C;
stuffTmp ← (stuffTmp) - 1;
stuffTmp ← (stuffTmp) OR (LSHIFT[01, 4]C);
CYCLECONTROL ← stuffTmp;
stuffTmp ← t;
t ← WFA[stuffTmp];
CS0 ← WFB[(CS0) OR t];
CS0 ← (CS0) XOR (030000C); *invert bits in microinstruction

*CopyField (CS2[14, 2] ← XA[5, 2], temp is stuffTmp)
t ← LDF[XA, 5, 2];
stuffTmp ← 2C;
stuffTmp ← (stuffTmp) - 1;
stuffTmp ← (stuffTmp) OR (LSHIFT[14, 4]C);
CYCLECONTROL ← stuffTmp;
stuffTmp ← t;
t ← WFA[stuffTmp];
CS2 ← WFB[(CS2) OR t];

*stuffF2 (set the F2 field in CS0, CS1, CS2 to 12)
StuffTmp ← OR[LSHIFT[2, 4], SUB[4, 1]]C;
CYCLECONTROL ← StuffTmp;
StuffTmp ← 12C;
t ← WFA[StuffTmp];
CS1 ← WFB[(CS1) OR t];
LU ← (StackShiftFlag);
GOTO[CheckFlag2, ALU = 0];

*stuffF2 (set the F2 field in CS0, CS1, CS2 to 03)
StuffTmp ← OR[LSHIFT[2, 4], SUB[4, 1]]C;
CYCLECONTROL ← StuffTmp;
StuffTmp ← 03C;
t ← WFA[StuffTmp];
CS1 ← WFB[(CS1) OR t];

CheckFlag2:
LU ← (RegShiftFlag);
GOTO[WriteCS2, ALU = 0];

*stuffF2 (set the F2 field in CS0, CS1, CS2 to 00)
StuffTmp ← OR[LSHIFT[2, 4], SUB[4, 1]]C;
CYCLECONTROL ← StuffTmp;
StuffTmp ← 00C;
t ← WFA[StuffTmp];
CS1 ← WFB[(CS1) OR t];

WriteCS2:
*writeCS (write control store location ’InstructionAddress’)
t ← (CS0);
Tmp ← t;*put CS0 in the temp. reg.
t ← (CS1);*get CS1
Tmp ← t ← (Tmp) 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
Tmp ← t ← (LDF[Tmp,0,10]) XOR (t);*now start the halfing process to get parity
Tmp ← t ← (LDF[Tmp,10,4]) XOR (t);
Tmp ← t ← (LDF[Tmp,14,2]) XOR (t);
Tmp ← t ← (LDF[Tmp,16,1]) XNOR (t);*do last part and complement it
t ← (LDF[Tmp,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[sp2b,26];
APCTASK&APC ← (InstructionAddress);
WriteCS1;

*set up higher task
t ← LSH[TargetTask, 14],at[sp2b,30];
NewTask ← t;

Tmp ← AND[0377, 761]C;*Load16Bits (Tmp ← 761)
Tmp ← (Tmp) OR (AND[177400, 761]C);
t ← Tmp;
NewTask ←(NewTask) OR (t);

*check range of target register and establish target value
LU ← (TargetRegister) - (46C);
GOTO[BackToMain, ALU < 0];

t ← 360C;*done this way (with t) due to assembler bug
LU ← (TargetRegister) - (t);
GOTO[ChangeXB, ALU < 0];
NOP;

BackToMain:
LOADPAGE[MainPage];
GOTOP[mainLoop];

ChangeXB:
LU ← (NewRand);
GOTO[SetTargetVal, ALU = 0];

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

SetTargetVal:
t ← XB;
TargetValue ← t;

*switch to higher task
APC&APCTASK ← NewTask;
RETURN;

*IN HIGHER TASK
HighTask761:
Tmp ← ADD[RegBase, TargetValueOffset]C, AT[761];
STKP ← Tmp;
t ← STACK&-1;*access TargetValue
STKP ← STACK;*access InitialStkp
DummyRegister ← t, REGSHIFT, AT[762];

*save STKP
t ← ADD[RegBase, SaveStkpOffset]C;
t ← (ZERO) OR NOT (t);*invert value stored into SALUF
SALUF ← t;
t ← (GETRSPEC[103]) OR (177400C); *get the STKP in a form ready to be inverted
STKP ← GETRSPEC[107];*use SALUF as general purpose register
STACK ← (ZERO) OR NOT (t);*write SaveStkp (invert STKP)
LU ←STACK&+2;*increment STKP
APC&APCTASK ← STACK;*get return register off of stack
RETURN;


***** SUBTEST3 *****
SubTest3:
SubTest ← 3C, AT[772];
STKP ← TargetRegister;
t ← STACK;
LU ← (TargetValue) - (t);
GOTO[WriteSuccess, ALU = 0];

ShortLoop ← ShortLoop, GOTO[.+2, R EVEN]; *Test for shortLoop option
GOTO[SubTest3];*ShortLoop selected

WriteFail:
BREAKPOINT;

ShortLoop ← ShortLoop, GOTO[.+2, R EVEN]; *Test for shortLoop option
GOTO[SubTest3];*ShortLoop selected
NOP;*resolves a branching conflict

WriteSuccess:
RETURN;


END;* to end the main routine