GenXopLS.mesa
Copyright © 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
Edward Fiala February 7, 1986 5:36:17 pm PST
McCreight, January 13, 1986 1:32:24 pm PST
Curry, September 11, 1986 8:43:40 pm PDT
Curry, September 11, 1986 12:25:52 pm PDT
Added definitions for aux13, SetYoungestL, and GetYoungestL.
`Old Code' replaced by `New Code'.
Replaced drLIP[ifuYoungestL] with GetYoungestL[].
Fiala, November 6, 1986 10:35:51 am PST Cosmetic edits; add ← LizardLiverImpl.careful ← FALSE requirement; remove SetYoungestL procedure.
Fiala, March 20, 1987 7:10:48 pm PST Eliminate Halt, Pause, and Reset stuff to run
with GenDebugger.
Load with "quad -cx GenDebugger GenXopLS". This diagnostic tests all Xops, AL, AS, DIS, ASL, and ALS; RETN is also tested a little. When correctly executed it terminates with a HALT[177777B] on instruction 2482 at PC = 4051245B, cycle 5232. Must do ← LizardLiverImpl.careful ← FALSE before running this.
DIRECTORY
Basics USING [BITXOR, BITAND],
DragOpsCross USING [Inst, XopBase, TrapBase, TrapWidthBytes, bytesPerWord, TrapIndex, Word],
--Word, wordsPerPage, bytesPerWord, charsPerWord, bitsPerByte, bitsPerCharacter, bitsPerWord, bytesPerPage, logWordsPerPage, logBitsPerByte, logBitsPerChar, logBytesPerWord, logCharsPerWord, logBitsPerWord, logBytesPerPage, PageCount, PageNumber, maxPagesInVM, SixBitIndex, FiveBitIndex, TwoWords, FourBitIndex, Half, ThreeBitIndex, FourHalves, TwoHalves, Byte, ZerosByte, OnesByte, EightBytes, FourBytes, ByteIndex, BytesPerWord, TwoBytes, Comparison, ByteAddress, WordAddress, FieldDescriptor, RegIndex, PadByte, Lit8, Op4, Op8, JDist8, Inst, OIFormat, OQBformat, LRformat, QRformat, ShortRegQR, OBformat, LRBformat, RRformat, ODBformat, LRRBformat, RJBformat, ShortRegRJB, JBBformat, TrapWidthWords, TrapWidthBytes, XopBase, TrapBase, KernalLimit, TrapIndex, StackUnderflowTrap, IFUPageFaultTrap, ResetTrap, IFUStackOverflowTrap, EUStackOverflowTrap, RescheduleTrap, ALUCondFalse, ALUCondEZ, ALUCondLZ, ALUCondLE, ALUCondSpare, ALUCondNE, ALUCondGE, ALUCondGZ, ALUCondOver, ALUCondBC, ALUCondIL, ALUCondDO, ALUCondNotOver, ALUCondNB, ALUCondNI, ModeFault, MemAccessFault, IOAccessFault, EUPageFault, EUWriteFault, AUFault, euStack, euJunk, euToKBus, euMAR, euField, euConstant, euAux, euBogus, euLast, ifuYoungestL, ifuYoungestPC, ifuEldestL, ifuEldestPC, ifuSLimit, ifuBogus, ifuL, ifuS, ifuPC, ifuLast, EURegs, EULegalRegs, IFURegs, IFULegalRegs, StackedStatusWord, IFUStackIndex, IFUStackSize, IFUOverflow, EUStackIndex, EUStackSize, EULocalIndex, EULocals, EUAuxIndex, EUAuxRegs, EUConstIndex, EUConstants, IOLocation, ioRescheduleRequest, ioResetRequest, IOOperand, PCmdFormat, PCmdByteSelect, PCmdClass, PCmdSpace, PCmdDirection
DragOpsCrossUtils USING [CardToWord, CardToByte, InstToBytes],
--InstToBytes, InstToFormat, BytePCToWordAddress, WordAddressToBytePC, IOOperandToCard, CardToIOOperand, FieldDescriptorToCard, CardToFieldDescriptor, BytesToWord, BytesToHalf, WordToBytes, HalfToBytes, HalvesToWord, WordToHalves, HighHalf, LowHalf, LeftHalf, RightHalf, SwapHalves, WordToInt, IntToWord, WordToCard, HalfToCard, ByteToCard, CardToWord, CardToHalf, CardToByte, DragAnd, DragOr, DragXor, DragNot, VanillaAdd, VanillaSub, AddDelta, HalfNot, HalfAnd, HalfOr, HalfXor, HalfShift, DoubleWordShiftLeft, SingleWordShiftLeft, SingleWordShiftRight, XopToBytePC, TrapIndexToBytePC, FieldUnit
HandCoding, --Has opcode and register defs.
HandCodingPseudos, --Label, SetLabel, GenLabel, GenLabelHere, UseLabel8A, UseLabel8B, UseLabel16, UseLabel32, LReg, PReg, SReg, AddReg, SubReg, SetRegConst, MoveReg, MoveRegI, LRegI, IndexedJump, ProcedureEntry, ProcedureExit, SetupField, ExtractField, ShiftLeft, LoadProcessorReg, StoreProcessorReg, CauseReschedule, CauseReset, GetSPLimit, SetSPLimit, GetYoungestPC, GetYoungestStatus, GetEldestPC, GetEldestStatus, SetYoungestPC, SetYoungestStatus, SetEldestPC, SetEldestStatus, Pause, Halt
HandCodingSupport, --Area, GetProc, PutProc, ProcList, NewArea, GenWithArea, Gen1WithArea, ForceOut, GetCurrentArea, LoadArea, GetOutputPC, SetOutputPC, WordAlign, ReserveData, OutputByte, OutputOneByte, OutputAlphaBeta, OutputAlphaBetaGammaDelta, OutputWord
HandCodingUtil,
Rope;
GenXopLS: CEDAR PROGRAM
IMPORTS Basics, DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport, HandCodingUtil, Rope
= BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport;
XopBase: LONG CARDINAL = DragOpsCross.XopBase;
TrapWidthBytes: NAT = DragOpsCross.TrapWidthBytes;
bytesPerWord: CARDINAL = DragOpsCross.bytesPerWord;
aux13: AuxRegSpec = [aux[13]];
names: HandCodingUtil.NameArray
← HandCodingUtil.GetInstArray[];
All: PROC = {
Xops trap at opcode*TrapWidthBytes + xopBase*bytesPerWord = 4,000,000B + 20B * opcode.
FillXop: PROC [inst: CARDINAL, dest: Label] = {
SetOutputPC[inst * DragOpsCross.TrapWidthBytes + DragOpsCross.XopBase * DragOpsCross.bytesPerWord];
drJDB[UseLabel16[dest]];
};
A trap's location is TrapIndex*TrapWidthBytes + TrapBase*bytesPerWord =
4,002,000B + 20B * TrapIndex. TrapIndex definitions are in DragOpsCross.
FillTrap: PROC [tx: DragOpsCross.TrapIndex, dest: Label] = {
SetOutputPC[LOOPHOLE[tx, CARDINAL] * DragOpsCross.TrapWidthBytes + DragOpsCross.TrapBase * DragOpsCross.bytesPerWord];
drJDB[UseLabel16[dest]];
};
GetYoungestL: PROC = {
GetYoungestStatus[]; drLIB[377B]; drAND[]
};
area: Area = GetCurrentArea[];
savePC: LONG CARDINAL;
enterXopTest: Label = GenLabel[];
enterALTest: Label = GenLabel[];
enterASTest: Label = GenLabel[];
enterDISTest: Label = GenLabel[];
enterASLTest: Label = GenLabel[];
enterALSTest: Label = GenLabel[];
Generate a trap entry and stubs for all Xop's except 0 and 377B which will do Pause[] if the Xop is executed other than in the context of the test for it and which will remove the Alpha, AlphaBeta, or AlphaBetaGammaDelta argument from the stack if the xop is executed in the context of the test.
GenXop: PROC [] ~ {
Xop5Trap: Label = GenLabel[];
abgdPushed: Label = GenLabel[];
GenXop1Trap: PROC [I: CARDINAL] ~ {
notBeingTested: Label = GenLabel[];
SetOutputPC[(I * TrapWidthBytes) + (XopBase * bytesPerWord)];
Push the number of the opcode being tested (or 0 if none); this is kept in aux13.
drLIB[I];
drRJNEB[popSrc, aux13, UseLabel8B[notBeingTested]];
drLIDB[12345B]; --Return value indicating trap routine was executed
drRETN[]; --Return without changing S
SetLabel[notBeingTested];
Pause[]; --Unexpected occurrence of Xop trap for opcode I
};
GenXop1Test: PROC [I: CARDINAL] ~ {
xop1OK: Label = GenLabel[];
drLIB[I];
drRAND[c: aux13, a: topSrc, b: popSrc]; --aux13 ← xop opcode
OutputByte[area, CardToByte[I]];
drLIDB[12345B];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[xop1OK]];
Pause[];
SetLabel[xop1OK];
};
GenXop2Trap: PROC [I: CARDINAL] ~ {
problem: Label = GenLabel[];
SetOutputPC[(I * TrapWidthBytes) + (XopBase * bytesPerWord)];
Compare the opcode number for this trap entry point with the opcode number of the Xop now being tested in aux 13.
drLIB[I];
drRJNEB[popSrc, aux13, UseLabel8B[problem]]; --Being tested?
drLIB[Basics.BITXOR[I, 377B]];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[problem]]; --Alpha pushed?
drLIDB[23456B]; --Return value indicating trap routine was executed
drRETN[]; --Return without changing S
SetLabel[problem];
Pause[]; --Unexpected occurrence of Xop trap for opcode I
};
GenXop2Test: PROC [I: CARDINAL] ~ {
xop2OK: Label = GenLabel[];
drLIB[I];
drRAND[c: aux13, a: topSrc, b: popSrc]; --aux13 ← xop opcode
OutputAlphaBeta[area, (I * 400B) + Basics.BITXOR[I, 377B]];
drLIDB[23456B];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[xop2OK]];
Pause[];
SetLabel[xop2OK];
};
GenXop3Trap: PROC [I: CARDINAL] ~ {
problem: Label = GenLabel[];
SetOutputPC[(I * TrapWidthBytes) + (XopBase * bytesPerWord)];
Compare the opcode number for this trap entry point with the opcode number of the Xop now being tested in aux 13.
drLIB[I];
drRJNEB[popSrc, aux13, UseLabel8B[problem]]; --Trap expected?
drLIDB[177400B + I];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[problem]]; --AlphaBeta pushed?
drLIDB[34567B]; --Return value indicating trap routine was executed
drRETN[]; --Return without changing S
SetLabel[problem];
Pause[]; --Unexpected occurrence of Xop trap for opcode I
};
GenXop3Test: PROC [I: CARDINAL] ~ {
xop3OK: Label = GenLabel[];
drLIB[I];
drRAND[c: aux13, a: topSrc, b: popSrc]; --aux13 ← xop opcode
OutputByte[area, CardToByte[I]]; --Should take Xop trap
OutputAlphaBeta[area, 177400B + I];
drLIDB[34567B];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[xop3OK]];
Pause[];
SetLabel[xop3OK];
};
GenXop5Trap: PROC [I: CARDINAL] ~ {
notBeingTested: Label = GenLabel[];
SetOutputPC[(I * TrapWidthBytes) + (XopBase * bytesPerWord)];
Compare the opcode number for this trap entry point with the opcode number of the Xop now being tested in aux13.
drLIB[I];
drRJNEB[popSrc, aux13, UseLabel8B[notBeingTested]];
drLIQB[CardToWord[37777777400B + LONG[I]]];
drJDB[UseLabel16[Xop5Trap]];
SetLabel[notBeingTested];
Pause[]; --Unexpected occurrence of Xop trap for opcode I
};
GenXop5Test: PROC [I: CARDINAL] ~ {
xop5OK: Label = GenLabel[];
drLIB[I];
drRAND[c: aux13, a: topSrc, b: popSrc]; --aux13 ← xop opcode
OutputByte[area, CardToByte[I]];
OutputWord[area, CardToWord[37777777400B + LONG[I]]]; --Should take Xop trap
drLIDB[45670B];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[xop5OK]];
Pause[];
SetLabel[xop5OK];
};
Generate stubs for Xop trap procedures which don't fit in 16 locations.
SetLabel[Xop5Trap]; --Did Xop push AlphaBetaGammaDelta correctly?
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[abgdPushed]];
Pause[]; --Xop did not push AlphaBetaGammaDelta correctly.
SetLabel[abgdPushed];
drLIDB[45670B];
drRETN[]; --Return without changing S
New Code (to replace Old Code below)
DJC September 11, 1986 1:49:05 pm PDT
Generate a trap entry sequence for every Xop except 0 (Pause) and 377B (Halt).
The following undefined opcodes should not be tested:
 311B, 313B, 337B, 340B, 344B, 350B, and 354B.
savePC ← GetOutputPC[area];
FOR I: CARDINAL IN (0..377B) DO
inst: DragOpsCross.Inst ← LOOPHOLE[I];
name: Rope.ROPE ← names[inst];
length: NAT ← DragOpsCrossUtils.InstToBytes[inst];
IF name.Fetch[]#'x THEN LOOP;
SELECT I FROM
311B, 313B, 337B, 340B, 344B, 350B, 354B => LOOP;
ENDCASE;
SELECT length FROM
1 => GenXop1Trap[I];
2 => GenXop2Trap[I];
3 => GenXop3Trap[I];
5 => GenXop5Trap[I];
ENDCASE => ERROR;
ENDLOOP;
SetOutputPC[savePC];
Generate a test for every Xop except 0 (Pause) and 377B (Halt).
SetLabel[enterXopTest];
FOR I: CARDINAL IN (0..377B) DO
inst: DragOpsCross.Inst ← LOOPHOLE[I];
name: Rope.ROPE ← names[inst];
length: NAT ← DragOpsCrossUtils.InstToBytes[inst];
IF name.Fetch[]#'x THEN LOOP;
SELECT I FROM
311B, 313B, 337B, 340B, 344B, 350B, 354B => LOOP;
ENDCASE;
SELECT length FROM
1 => GenXop1Test[I];
2 => GenXop2Test[I];
3 => GenXop3Test[I];
5 => GenXop5Test[I];
ENDCASE => ERROR;
ENDLOOP };
Old Code
Generate a trap entry sequence for every Xop except 0 (Pause) and 377B (Halt).
savePC ← GetOutputPC[area];
FOR I: CARDINAL IN [1..17B] DO GenXop1Trap[I]; ENDLOOP; --length = 1 Xops
FOR I: CARDINAL IN [30B..37B] DO GenXop1Trap[I]; ENDLOOP; --length = 1 Xops
FOR I: CARDINAL IN [40B..60B] DO GenXop5Trap[I]; ENDLOOP; --length = 5 Xops
FOR I: CARDINAL IN [63B..65B] DO GenXop5Trap[I]; ENDLOOP; --length = 5 Xops
FOR I: CARDINAL IN [70B..77B] DO GenXop5Trap[I]; ENDLOOP; --length = 5 Xops
GenXop1Trap[112B]; --112B length = 1 Xop
FOR I: CARDINAL IN [117B..123B] DO GenXop1Trap[I]; ENDLOOP; --length = 1 Xops
GenXop1Trap[125B]; --125B length = 1 Xop
FOR I: CARDINAL IN [130B..137B] DO GenXop1Trap[I]; ENDLOOP; --length = 1 Xops
GenXop2Trap[215B]; --215B length = 2 Xop
GenXop2Trap[223B]; --223B length = 2 Xop
FOR I: CARDINAL IN [234B..236B] DO GenXop2Trap[I]; ENDLOOP; --length = 2 Xops
GenXop3Trap[311B]; --311B length = 3 Xop (undefined behavior)
GenXop3Trap[313B]; --313B length = 3 Xop (undefined behavior)
GenXop3Trap[323B]; --323B length = 3 Xop
GenXop3Trap[337B]; --337B length = 3 Xop (undefined behavior)
GenXop3Trap[340B]; --340B length = 3 Xop (undefined behavior)
GenXop3Trap[344B]; --344B length = 3 Xop (undefined behavior)
GenXop3Trap[350B]; --350B length = 3 Xop (undefined behavior)
GenXop3Trap[354B]; --354B length = 3 Xop (undefined behavior)
FOR I: CARDINAL IN [364B..367B] DO GenXop3Trap[I]; ENDLOOP; --length = 3 Xops
FOR I: CARDINAL IN [374B..376B] DO GenXop3Trap[I]; ENDLOOP; --length = 3 Xops
SetOutputPC[savePC];
Generate a test for every Xop except 0 (Pause) and 377B (Halt). Note that 311B, 313B, 337B, 340B, 344B, 350B, and 354B are undefined, but not XOP's.
SetLabel[enterXopTest];
FOR I: CARDINAL IN [1..17B] DO GenXop1Test[I]; ENDLOOP; --length = 1 Xops
FOR I: CARDINAL IN [30B..37B] DO GenXop1Test[I]; ENDLOOP; --length = 1 Xops
FOR I: CARDINAL IN [40B..60B] DO GenXop5Test[I]; ENDLOOP; --length = 5 Xops
FOR I: CARDINAL IN [63B..65B] DO GenXop5Test[I]; ENDLOOP; --length = 5 Xops
FOR I: CARDINAL IN [70B..77B] DO GenXop5Test[I]; ENDLOOP; --length = 5 Xops
GenXop1Test[112B]; --112B length = 1 Xop
FOR I: CARDINAL IN [117B..123B] DO GenXop1Test[I]; ENDLOOP; --length = 1 Xops
GenXop1Test[125B]; --125B length = 1 Xop
FOR I: CARDINAL IN [130B..137B] DO GenXop1Test[I]; ENDLOOP; --length = 1 Xops
GenXop2Test[215B]; --215B length = 2 Xop
GenXop2Test[223B]; --223B length = 2 Xop
FOR I: CARDINAL IN [234B..236B] DO GenXop2Test[I]; ENDLOOP; --length = 2 Xops
GenXop3Test[323B]; --323B length = 3 Xop
FOR I: CARDINAL IN [364B..367B] DO GenXop3Test[I]; ENDLOOP; --length = 3 Xops
FOR I: CARDINAL IN [374B..376B] DO GenXop3Test[I]; ENDLOOP; --length = 3 Xops
};
Test AL (L ← L + Alpha mod 128). If the test completes successfully, L is restored to its original value. The current values of L cannot be read; this can only be done indirectly by calling a procedure, which saves L in ifuYoungestL, readable using GetYoungestL.
GenAL: PROC [] ~ {
TestAL: PROC [originalL, alpha: CARDINAL] ~ {
pushL: Label = GenLabel[];
lOK: Label = GenLabel[];
alExit: Label = GenLabel[];
newL: CARDINAL = Basics.BITAND[originalL + alpha, 177B];
drAL[alpha];
drLFC[UseLabel16[pushL]];
drJDB[UseLabel16[alExit]];
SetLabel[pushL];
GetYoungestL[];
drJEBBJ[newL, UseLabel8B[lOK]];
Pause[]; --L was wrong
SetLabel[lOK];
drRETN[];
SetLabel[alExit];
};
Initially, L = 1 and S = 0 here.
SetLabel[enterALTest];
TestAL[1, 127]; --L ← 0
TestAL[0, 1]; --L ← 1
TestAL[1, 2]; --L ← 3
TestAL[3, 4]; --L ← 7
TestAL[7, 8]; --L ← 15
TestAL[15, 16]; --L ← 31
TestAL[31, 32]; --L ← 63
TestAL[63, 64]; --L ← 127
TestAL[127, 128]; --L ← 127
TestAL[127, 0]; --L ← 127
TestAL[127, 64]; --L ← 63
TestAL[63, 32]; --L ← 95
TestAL[95, 16]; --L ← 111
TestAL[111, 8]; --L ← 119
TestAL[119, 4]; --L ← 123
TestAL[123, 2]; --L ← 125
TestAL[125, 1]; --L ← 126
drAL[3];  --L ← 1
};
Test ALS (L ← S+Alpha mod 128). If the test completes successfully, [L, S] is restored to [1, 0]. AS is assumed to work. Current values of L or S cannot be read; this can only be done indirectly by calling a procedure, which saves L in ifuYoungestL, readable using GetYoungestL.
GenALS: PROC [] ~ {
TestALS: PROC [originalS, alpha: CARDINAL] ~ {
pushL: Label = GenLabel[];
lOK: Label = GenLabel[];
alsExit: Label = GenLabel[];
newL: CARDINAL ← Basics.BITAND[originalS + alpha, 177B];
drALS[alpha]; --L ← newL
drLFC[UseLabel16[pushL]]; --push L (= S) on the IFU stack for checking
drJDB[UseLabel16[alsExit]];
SetLabel[pushL];
GetYoungestL[];
drJEBBJ[newL, UseLabel8B[lOK]];
Pause[]; --L was wrong, so S was wrong.
SetLabel[lOK];
drRETN[];
SetLabel[alsExit];
};
Initially, [L, S] = [1, 0] here.
SetLabel[enterALSTest];
Do every bit with no carry generation.
TestALS[0, 1]; --[L, S] ← [1, 0]
TestALS[0, 2]; --[L, S] ← [2, 0]
TestALS[0, 4]; --[L, S] ← [4, 0]
TestALS[0, 8]; --[L, S] ← [8, 0]
TestALS[0, 16]; --[L, S] ← [16, 0]
TestALS[0, 32]; --[L, S] ← [32, 0]
TestALS[0, 64]; --[L, S] ← [64, 0]
TestALS[0, 128]; --[L, S] ← [0, 0]
Now cause carry generation in each bit; (but AS has not yet been tested and might fail).
drAS[127];  --[L, S] ← [0, 127]
TestALS[127, 0]; --[L, S] ← [127, 127]
TestALS[127, 128]; --[L, S] ← [127, 127]
TestALS[127, 64]; --[L, S] ← [63, 127]
TestALS[127, 32]; --[L, S] ← [31, 127]
TestALS[127, 16]; --[L, S] ← [15, 127]
TestALS[127, 8]; --[L, S] ← [7, 127]
TestALS[127, 4]; --[L, S] ← [3, 127]
TestALS[127, 2]; --[L, S] ← [1, 127]
TestALS[127, 1]; --[L, S] ← [0, 127]
drAS[1];  --[L, S] ← [0, 0]
drALS[1];  --[L, S] ← [1, 0] restores original value
};
Test AS (S ← S + Alpha mod 128); ALS 0 is assumed to work. If the test completes successfully, L and S are restored to their original values. Current values of L or S cannot be read; this can only be done indirectly by calling a procedure, which saves L in ifuYoungestL, readable using GetYoungestL.
GenAS: PROC [] ~ {
TestAS: PROC [originalS, alpha: CARDINAL] ~ {
pushL: Label = GenLabel[];
sOK: Label = GenLabel[];
asExit: Label = GenLabel[];
newS: CARDINAL = Basics.BITAND[originalS + alpha, 177B];
drAS[alpha];
drALS[0]; --L ← S
drLFC[UseLabel16[pushL]];
drJDB[UseLabel16[asExit]];
SetLabel[pushL];
GetYoungestL[];
drJEBBJ[newS, UseLabel8B[sOK]];
Pause[]; --L was wrong, so S was wrong.
SetLabel[sOK];
drRETN[];
SetLabel[asExit];
};
Initially, [L, S] = [1, 0] here.
SetLabel[enterASTest];
TestAS[0, 1]; --[L, S] ← [1, 1]
TestAS[1, 2]; --[L, S] ← [3, 3]
TestAS[3, 4]; --[L, S] ← [7, 7]
TestAS[7, 8]; --[L, S] ← [15, 15]
TestAS[15, 16]; --[L, S] ← [31, 31]
TestAS[31, 32]; --[L, S] ← [63, 63]
TestAS[63, 64]; --[L, S] ← [127, 127]
TestAS[127, 128]; --[L, S] ← [127, 127]
TestAS[127, 0]; --[L, S] ← [127, 127]
TestAS[127, 64]; --[L, S] ← [63, 63]
TestAS[63, 32]; --[L, S] ← [95, 95]
TestAS[95, 16]; --[L, S] ← [111, 111]
TestAS[111, 8]; --[L, S] ← [119, 119]
TestAS[119, 4]; --[L, S] ← [123, 123]
TestAS[123, 2]; --[L, S] ← [125, 125]
TestAS[125, 1]; --[L, S] ← [126, 126]
drAS[2];  --[L, S] ← [126, 0]
drALS[1];  --[L, S] ← [1, 0] restores original value
};
Test DIS (S ← S - 1 mod 128). If the test completes successfully, L and S are restored to their original values. Current values of L or S cannot be read; this can only be done indirectly by calling a procedure, which saves L in ifuYoungestL, readable using GetYoungestL.
GenDIS: PROC [] ~ {
TestDIS: PROC [originalS: CARDINAL] RETURNS [newS: CARDINAL] ~ {
pushL: Label = GenLabel[];
sOK: Label = GenLabel[];
disExit: Label = GenLabel[];
newS ← Basics.BITAND[originalS - 1, 177B];
drDIS[];
drALS[0]; --L ← S
drLFC[UseLabel16[pushL]];
drJDB[UseLabel16[disExit]];
SetLabel[pushL];
GetYoungestL[];
drJEBBJ[newS, UseLabel8B[sOK]];
Pause[]; --L was wrong, so S was wrong.
SetLabel[sOK];
drRETN[];
SetLabel[disExit];
};
Initially, [L, S] = [1, 0] here.
SetLabel[enterDISTest];
{
curS: CARDINAL ← 0;
128 iterations restores original value of S.
FOR I: CARDINAL IN [0..128) DO
curS ← TestDIS[curS];
ENDLOOP;
drALS[1]; --[L, S] ← [1, 0].
};
};
Test ASL (S ← L+Alpha mod 128; stack overflow not checked). If the test completes successfully, [L, S] is restored to [1, 0]. Current values of L or S cannot be read; this can only be done indirectly by calling a procedure, which saves L in ifuYoungestL, readable using GetYoungestL.
GenASL: PROC [] ~ {
TestASL: PROC [originalL, alpha: CARDINAL] ~ {
pushL: Label = GenLabel[];
sOK: Label = GenLabel[];
aslExit: Label = GenLabel[];
newS: CARDINAL ← Basics.BITAND[originalL + alpha, 177B];
drASL[alpha]; --S ← newS
drALS[0];  --L ← S + 0
drLFC[UseLabel16[pushL]]; --push L (= S) on the IFU stack for checking
drJDB[UseLabel16[aslExit]];
SetLabel[pushL];
GetYoungestL[];
drJEBBJ[newS, UseLabel8B[sOK]];
Pause[]; --L was wrong, so S was wrong.
SetLabel[sOK];
drRETN[];
SetLabel[aslExit];
};
Initially, [L, S] = [1, 0] here.
SetLabel[enterASLTest];
Do carry in low-order bit and propagate all the way across.
TestASL[1, 127]; --[L, S] ← [0, 0]
Do every bit with no carry generation.
TestASL[0, 1]; --[L, S] ← [1, 1]
TestASL[1, 2]; --[L, S] ← [3, 3]
TestASL[3, 4]; --[L, S] ← [7, 7]
TestASL[7, 8]; --[L, S] ← [15, 15]
TestASL[15, 16]; --[L, S] ← [31, 31]
TestASL[31, 32]; --[L, S] ← [63, 63]
TestASL[63, 64]; --[L, S] ← [127, 127]
TestASL[127, 0]; --[L, S] ← [127, 127]
Now cause carry generation in each bit.
TestASL[127, 64]; --[L, S] ← [63, 63]
TestASL[63, 32]; --[L, S] ← [95, 95]
TestASL[95, 16]; --[L, S] ← [111, 111]
TestASL[111, 8]; --[L, S] ← [119, 119]
TestASL[119, 4]; --[L, S] ← [123, 123]
TestASL[123, 2]; --[L, S] ← [125, 125]
TestASL[125, 1]; --[L, S] ← [126, 126]
drAS[2];  --[L, S] ← [126, 0]
drALS[1];  --[L, S] ← [1, 0] restores original value
};
Begin at PC = userBasePC = 1010000B * 4, L = 1, S = 0 as established in GenDebugger.
drJDB[UseLabel16[enterXopTest]];
GenXop[];
GenAL[];
GenALS[];
GenAS[];
GenDIS[];
GenASL[];
Halt[177777B]; --Terminate here at the end of the program
};
END.