GenReg.mesa
Copyright © 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
Edward Fiala February 7, 1986 2:59:57 pm PST
McCreight, January 7, 1986 3:52:02 pm PST
Curry, September 11, 1986 9:13:11 pm PDT
Curry, September 11, 1986 12:07:36 pm PDT
Removed references to ifuStatus (all unused).
Changed comment for ifuSLimit's value from 242 to 241.
Added definitions for SetYoungestL and GetYoungestL
Remove incorrect comments on ifu register values
Used GetYoungestL and SetYoungestL when doing LIP's and SIP's of ifuYoungestL in GenRegWrite, GenRegRead, and elsewhere.
Fiala November 6, 1986 9:53:36 am PST Fix problem with not masking ifuEldestL before comparing it to desired L value (version number screws this up); removed careful write of ifuYoungestL because not needed for this diagnostic (saves many instructions).
Fiala March 20, 1987 7:01:08 pm PST Eliminate Reset, Halt, and Pause stuff
to run with GenDebugger.
Fiala April 1, 1987 6:19:30 pm PST Make const1 to 3 read-only. ****Need to test that const1 to 3 have the values 1, 2, and 3****.
This diagnostic should be loaded with "quad -cx GenDebugger GenReg". It tests EU and IFU registers using LIP and SIP and (in a limited way) using LFC and RETN. It presumes that LIQB and RJEBJ have been thoroughly tested by GenLICJ. When successfully executed it halts at instruction 2283, cycle 5383, PC 4057012B.
DIRECTORY
--Basics USING [],
DragOpsCross USING [XopBase, TrapBase, TrapWidthBytes, bytesPerWord, TrapIndex, Word, ProcessorRegister, IFUStackIndex],
--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],
--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
GenReg: CEDAR PROGRAM
IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport
= BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport;
Word: TYPE = DragOpsCross.Word;
ProcessorRegister: TYPE = DragOpsCross.ProcessorRegister;
IFUStackIndex: TYPE = DragOpsCross.IFUStackIndex;
ifuSLimit: CARDINAL = LOOPHOLE[ProcessorRegister.ifuSLimit, CARDINAL];
ifuEldestPC: CARDINAL = LOOPHOLE[ProcessorRegister.ifuEldestPC, CARDINAL];
ifuEldestL: CARDINAL = LOOPHOLE[ProcessorRegister.ifuEldestL, CARDINAL];
ifuYoungestPC: CARDINAL = LOOPHOLE[ProcessorRegister.ifuYoungestPC, CARDINAL];
ifuYoungestL: CARDINAL = LOOPHOLE[ProcessorRegister.ifuYoungestL, CARDINAL];
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]];
};
Note that the write of the StackedStatusWord does not mask the upper fields in the word; not needed because userMode=FALSE and trapsEnabled=FALSE.
GenRegWrite: PROC [reg: CARDINAL, val: LONG CARDINAL] ~ {
IF reg = ifuYoungestL THEN { drLIB[val]; SetYoungestStatus[]; }
ELSE { drLIQB[CardToWord[val]]; drSIP[reg]};
};
GenRegRead: PROC [reg: CARDINAL, val: LONG CARDINAL] ~ {
rdOK: Label = GenLabel[];
IF reg = ifuYoungestL THEN { GetYoungestStatus[]; drLIB[377B]; drAND[]; }
ELSE IF reg = ifuEldestL THEN { GetEldestStatus[]; drLIB[377B]; drAND[]; }
ELSE drLIP[reg];
drLIQB[CardToWord[val]];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[rdOK]];
Pause[];
SetLabel[rdOK];
};
SetYoungestL: PROC = {
GetYoungestStatus[];
drLIQB[CardToWord[37777777400B]]; drAND[]; drOR[];
SetYoungestStatus[];
};
--area: Area = GetCurrentArea[];
enterEUSLTest: Label = GenLabel[];
enterIFUSLTest: Label = GenLabel[];
GenEUSL tests all EU registers except const0 using LIQB and SIP to consecutively write different values in all registers, then LIP, LIQB, and RJEB to read back and check all values. This test will catch addressing errors which cause the write of one register to wind up in another as well as storage failures. Register descriptions are in DragOpsCross.mesa. Skip over euJunk = 128 and 129; test euMar = 130 and euField = 131. euMar is a dumping place for memory addresses on address faults; it is (??) a regular register. euField is both a normal register and a collection of other logic to control the field unit; this test covers the register part of it; the other control logic can only be tested indirectly by noting whether or not the field unit performs correctly for values in euField.
GenEUSL: PROC = {
testVal: LONG CARDINAL;
SetLabel[enterEUSLTest];
testVal ← 8;
GenRegWrite[0, 1];
FOR I: CARDINAL IN [3..127] DO
GenRegWrite[I, testVal];
testVal ← IF testVal = 20000000000B THEN 1 ELSE testVal + testVal;
ENDLOOP;
FOR I: CARDINAL IN [130..131] DO
GenRegWrite[I, testVal];
testVal ← IF testVal = 20000000000B THEN 1 ELSE testVal + testVal;
ENDLOOP;
Const0, 1, 2, and 3 are read-only.
FOR I: CARDINAL IN [136..159] DO
GenRegWrite[I, testVal];
testVal ← IF testVal = 20000000000B THEN 1 ELSE testVal + testVal;
ENDLOOP;
Read and compare; must skip registers 1 and 2 which have been smashed by the various pushes during writing and reading.
testVal ← 8;
GenRegRead[0, 1];
FOR I: CARDINAL IN [3..127] DO
GenRegRead[I, testVal];
testVal ← IF testVal = 20000000000B THEN 1 ELSE testVal + testVal;
ENDLOOP;
FOR I: CARDINAL IN [130..131] DO
GenRegRead[I, testVal];
testVal ← IF testVal = 20000000000B THEN 1 ELSE testVal + testVal;
ENDLOOP;
Const0 = 132. const0, 1, 2, and 3 are read-only.
FOR I: CARDINAL IN [136..159] DO
GenRegRead[I, testVal];
testVal ← IF testVal = 20000000000B THEN 1 ELSE testVal + testVal;
ENDLOOP;
Finally, go back and test registers 1 and 2.
drASL[4]; --S ← 5
GenRegWrite[1, 2];
GenRegWrite[2, 4];
GenRegRead[1, 2];
GenRegRead[2, 4];
drASL[255]; --S ← 0 again
Write with inverse values.
testVal ← 37777777767B;
GenRegWrite[0, 37777777776B];
FOR I: CARDINAL IN [3..127] DO
GenRegWrite[I, testVal];
testVal ← IF testVal = 17777777777B THEN 37777777776B ELSE testVal + testVal + 1;
ENDLOOP;
FOR I: CARDINAL IN [130..131] DO
GenRegWrite[I, testVal];
testVal ← IF testVal = 17777777777B THEN 37777777776B ELSE testVal + testVal + 1;
ENDLOOP;
Const0 = 132. const0, 1, 2, and 3 are read-only.
FOR I: CARDINAL IN [136..159] DO
GenRegWrite[I, testVal];
testVal ← IF testVal = 17777777777B THEN 37777777776B ELSE testVal + testVal + 1;
ENDLOOP;
Read and compare, skipping registers 1 and 2 smashed by stack operations.
testVal ← 37777777767B;
GenRegRead[0, 37777777776B];
FOR I: CARDINAL IN [3..127] DO
GenRegRead[I, testVal];
testVal ← IF testVal = 17777777777B THEN 37777777776B ELSE testVal + testVal + 1;
ENDLOOP;
FOR I: CARDINAL IN [130..131] DO
GenRegRead[I, testVal];
testVal ← IF testVal = 17777777777B THEN 37777777776B ELSE testVal + testVal + 1;
ENDLOOP;
Const0 = 132. const0, 1, 2, and 3 are read-only.
FOR I: CARDINAL IN [136..159] DO
GenRegRead[I, testVal];
testVal ← IF testVal = 17777777777B THEN 37777777776B ELSE testVal + testVal + 1;
ENDLOOP;
Finally, go back and test registers 1 and 2.
drASL[4]; --S ← 5
GenRegWrite[1, 37777777775B];
GenRegWrite[2, 37777777773B];
GenRegRead[1, 37777777775B];
GenRegRead[2, 37777777773B];
drASL[255]; --S ← 0 again
};
GenIFUSL tests all IFU registers except ifuXBus (untestable) using LIQB and SIP to consecutively write different values in all registers, then LIP, LIQB, and RJEB to read back and check all values.
The IFU stack is tested both when writing it with ifuEldestL/PC and when writing it with ifuYoungestL/PC and changing the stack depth with LFC/RETN. Current values of L, S, and PC cannot be read; the stack covers only previous frames. In normal operation, ifuEldestL/PC are written on IFU stack underflow when previous frames are restored to the registers, and read on IFU or EU stack overflow to remove frames from the registers. This test will catch addressing errors which cause the write of one register to wind up in another, and it checks the manipulation of the IFU stack and L register by LFC and RETN. The description of the funny IFU registers is in DragOpsCross.mesa.
ifuXBus = base for IFU regs, can't be tested.
ifuSLimit = stack limit register, 7-bit register. This register is written and read by GenIFUSL, but its function as a stack limit register is not tested.
IFUStackSize = 15.
ifuYoungestL = youngest L in IFU stack (user mode and traps enabled not tested).
ifuYoungestPC = youngest PC in IFU stack.
ifuEldestL = eldest L in IFU stack (user mode and traps enabled not tested).
ifuEldestPC = eldest PC in IFU stack (read removes, write adds).
GenIFUSL: PROC = {
GenCallTest: PROC [dest: Label, lVal, rVal: CARDINAL] ~ {
drLFC[UseLabel16[dest]];
GenRegRead[ifuYoungestL, rVal];
drRETN[];
Pause[];
SetLabel[dest];
GenRegWrite[ifuYoungestL, lVal];
};
testPCVal, testLVal: LONG CARDINAL;
SetLabel[enterIFUSLTest];
Test with single 1-bit cycled left 1 position each time.
testPCVal ← 1;
testLVal ← 4;
GenRegWrite[ifuSLimit, 0];
FOR I: CARDINAL IN IFUStackIndex DO
GenRegWrite[ifuEldestPC, testPCVal];
testPCVal ← IF testPCVal = 20000000000B THEN 1 ELSE testPCVal + testPCVal;
GenRegWrite[ifuEldestL, testLVal];
testLVal ← IF testLVal = 100B THEN 1 ELSE testLVal + testLVal;
ENDLOOP;
GenRegRead[ifuSLimit, 0];
FOR I: CARDINAL IN IFUStackIndex DO
testLVal ← IF testLVal = 1 THEN 100B ELSE testLVal / 2;
GenRegRead[ifuEldestL, testLVal];
testPCVal ← IF testPCVal = 1 THEN 20000000000B ELSE testPCVal / 2;
GenRegRead[ifuEldestPC, testPCVal];
ENDLOOP;
Test with single 0-bit cycled left 1 position each time (i.e., inverse of first test).
testPCVal ← 37777777776B;
testLVal ← 173B;
GenRegWrite[ifuSLimit, 177B];
FOR I: CARDINAL IN IFUStackIndex DO
GenRegWrite[ifuEldestPC, testPCVal];
testPCVal ← IF testPCVal = 17777777777B THEN 37777777776B ELSE testPCVal + testPCVal + 1;
GenRegWrite[ifuEldestL, testLVal];
testLVal ← IF testLVal = 77B THEN 176B ELSE testLVal + testLVal + 1 - 200B;
ENDLOOP;
GenRegRead[ifuSLimit, 177B];
FOR I: CARDINAL IN IFUStackIndex DO
testLVal ← IF testLVal = 176B THEN 77B ELSE testLVal / 2 + 100B;
GenRegRead[ifuEldestL, testLVal];
testPCVal ← IF testPCVal = 37777777776B THEN 17777777777B ELSE testPCVal / 2 + 20000000000B;
GenRegRead[ifuEldestPC, testPCVal];
ENDLOOP;
Test the ifu stack with LFC and ifuYoungestL/PC used to push and to write, and ifuEldestL/PC used to read and pop.
testPCVal ← 200000B;
testLVal ← 1;
FOR I: CARDINAL IN IFUStackIndex DO
youngCall: Label = GenLabel[];
drLFC[UseLabel16[youngCall]];
SetLabel[youngCall];
GenRegWrite[ifuYoungestPC, testPCVal];
testPCVal ← IF testPCVal = 20000000000B THEN 1 ELSE testPCVal + testPCVal;
GenRegWrite[ifuYoungestL, testLVal];
testLVal ← IF testLVal = 100B THEN 1 ELSE testLVal + testLVal;
ENDLOOP;
testPCVal ← 200000B;
testLVal ← 1;
FOR I: CARDINAL IN IFUStackIndex DO
GenRegRead[ifuEldestL, testLVal];
testLVal ← IF testLVal = 100B THEN 1 ELSE testLVal + testLVal;
GenRegRead[ifuEldestPC, testPCVal];
testPCVal ← IF testPCVal = 20000000000B THEN 1 ELSE testPCVal + testPCVal;
ENDLOOP;
Test the ifu stack with LFC used to push and to write PC, ifuYoungestL to write, and RETN used to read and pop. This test will malfunction unless L and PC are correctly manipulated by LFC and RETN. Note that only 15 calls can be made here because, even though there are 16 levels in the ifu stack, only 15 are usable by call and return; if a 16th LFC is given, then its RETN results in a stack underflow trap.
{
Call1: Label = GenLabel[];
Call2: Label = GenLabel[];
Call3: Label = GenLabel[];
Call4: Label = GenLabel[];
Call5: Label = GenLabel[];
Call6: Label = GenLabel[];
Call7: Label = GenLabel[];
Call8: Label = GenLabel[];
Call9: Label = GenLabel[];
Call10: Label = GenLabel[];
Call11: Label = GenLabel[];
Call12: Label = GenLabel[];
Call13: Label = GenLabel[];
Call14: Label = GenLabel[];
Call15: Label = GenLabel[];
EndCallTest: Label = GenLabel[];
drLFC[UseLabel16[Call1]];
drJDB[UseLabel16[EndCallTest]];
SetLabel[Call1];
GenRegWrite[ifuYoungestL, 1];
GenCallTest[Call2, 2, 1];
GenCallTest[Call3, 3, 2];
GenCallTest[Call4, 4, 3];
GenCallTest[Call5, 5, 4];
GenCallTest[Call6, 6, 5];
GenCallTest[Call7, 7, 6];
GenCallTest[Call8, 8, 7];
GenCallTest[Call9, 9, 8];
GenCallTest[Call10, 10, 9];
GenCallTest[Call11, 11, 10];
GenCallTest[Call12, 12, 11];
GenCallTest[Call13, 13, 12];
GenCallTest[Call14, 14, 13];
GenCallTest[Call15, 15, 14];
GenRegRead[ifuYoungestL, 15];
drRETN[];
SetLabel[EndCallTest];
};
};
Begin at PC = userBasePC = 1010000B * 4, L = 1, S = 0 as established in GenDebugger.
GenEUSL[];
GenIFUSL[];
Halt[177777B]; --Terminate here at the end of the program
};
END.