GenField.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Edward Fiala February 7, 1986 11:46:08 am PST
This diagnostic tests the Field Unit opcodes SHL, SHR, SHD, RFU, and FSDB. When correctly executed it terminates with a HALT[177777b] at PC = 4135027B on instruction 12031 cycle 26629.
DIRECTORY
Basics USING [DoubleShiftLeft, DoubleShiftRight, DoubleAnd, DoubleOr, DoubleNot, LongNumber],
DragOpsCross USING [XopBase, TrapBase, TrapWidthBytes, bytesPerWord, TrapIndex, Word],
--XopBase, TrapBase, TrapWidthBytes, Inst, wordsPerPage, bytesPerWord, charsPerWord, bitsPerByte, bitsPerCharacter, bitsPerWord, logWordsPerPage, logBitsPerByte, logBitsPerChar, logBytesPerWord, logCharsPerWord, logBitsPerWord, logBytesPerPage, PageCount, PageNumber, maxPagesInVM, SixBitIndex, FiveBitIndex, Word, TwoWords, FourBitIndex, Half, ThreeBitIndex, FourHalves, TwoHalves, Byte, ZerosByte, OnesByte, EightBytes, FourBytes, ByteIndex, BytesPerWord, TwoBytes, Comparison, ByteAddress, WordAddress, FieldDescriptor, TrapWidthWords, KernalLimit, TrapIndex, StackUnderflowTrap, IFUPageFaultTrap, ResetTrap, IFUStackOverflowTrap, EUStackOverflowTrap, RescheduleTrap, ALUCondOver, ALUCondBC, ALUCondIL, ALUCondDO, EUPageFault, EUWriteFault, AUFault, euStack, euJunk, euMAR, euField, euConstant, euAux, euBogus, euLast, ifuXBus, ifuStatus, ifuSLimit, ifuYoungestL, ifuYoungestPC, ifuEldestL, ifuEldestPC, ifuBogus, ifuL, ifuS, ifuPC, ifuLast, IFUStatusRec, IFUStackIndex, IFUStackSize, IFUOverflow, EUStackIndex, EUStackSize, EULocalIndex, EULocals, EUAuxIndex, EUAuxRegs, EUConstIndex, EUConstants, IOLocation, ioRescheduleRequest, ioResetRequest
DragOpsCrossUtils USING [IntToWord, CardToWord],
--BytePCToWordAddress, WordAddressToBytePC, IOOperandToCard, CardToIOOperand, FieldDescriptorToCard, CardToFieldDescriptor, StatusToWord, WordToStatus, 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, TrapIndexToBytePC, XopToBytePC
HandCoding, --Has opcode and register defs.
HandCodingPseudos, --GenLabel, GenLabelHere, SetLabel, Halt, Pause, MakeLabelGlobal, UseLabel8B, UseLabel16, UseLabel32, ProcedureEntry, ProcedureExit, EnableTraps, IndexedJump, SetupField, ExtractField, ShiftLeft, LoadProcessorReg, StoreProcessorReg, DisableTraps, CauseReschedule, CauseReset, GetSPLimit, SetSPLimit, GetL, SetL, GetYoungestPC, GetYoungestL, GetEldestPC, GetEldestL, SetYoungestPC, SetYoungestL, SetEldestPC, SetEldestL
HandCodingSupport; --Area, GetCurrentArea, ReserveData, SetOutputPC, GetProc, PutProc, ProcList, NewArea, GenWithArea, Gen1WithArea, ForceOut, GetOutputPC, WordAlign, OutputByte, OutputOneByte, OutputAlphaBeta, OutputAlphaBetaGammaDelta, OutputWord
GenField: CEDAR PROGRAM
IMPORTS Basics, DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport
= BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport;
Word: TYPE = DragOpsCross.Word;
In this diagnostic, the auxiliary registers are called aux0, aux1, ..., aux15; the locals are called reg0, reg1, ..., reg15; and the constants are called const0, const1, ..., const15.
const2 contains -1.
const3 is used as an enabling flag for the bounds-check subroutine.
const6 contains 4 for bounds-check trap subroutine.
aux0: AuxRegSpec = [aux[0]];
aux1: AuxRegSpec = [aux[1]];
aux2: AuxRegSpec = [aux[2]];
aux3: AuxRegSpec = [aux[3]];
aux4: AuxRegSpec = [aux[4]];
aux5: AuxRegSpec = [aux[5]];
aux6: AuxRegSpec = [aux[6]];
aux14: AuxRegSpec = [aux[14]];
aux15: AuxRegSpec = [aux[15]];
const5: ConstSpec = [const[5]];
const6: ConstSpec = [const[6]];
const7: ConstSpec = [const[7]];
const8: ConstSpec = [const[8]];
const9: ConstSpec = [const[9]];
const10: ConstSpec = [const[10]];
const11: ConstSpec = [const[11]];
All: PROC = {
The Xop trap locations assigned to each opcode are at at opcode*TrapWidthBytes + xopBase*bytesPerWord = 4,000,000B + 20B * opcode, and the trap location assigned to each trap are at TrapIndex*TrapWidthBytes + TrapBase*bytesPerWord = 4,002,000B + 20B * TrapIndex. The TrapIndex definitions are in DragOpsCross.
FillXop: PROC [inst: CARDINAL, dest: Label] = {
SetOutputPC[inst * DragOpsCross.TrapWidthBytes + DragOpsCross.XopBase * DragOpsCross.bytesPerWord];
drJDB[UseLabel16[dest]];
};
FillTrap: PROC [tx: DragOpsCross.TrapIndex, dest: Label] = {
SetOutputPC[LOOPHOLE[tx, CARDINAL] * DragOpsCross.TrapWidthBytes + DragOpsCross.TrapBase * DragOpsCross.bytesPerWord];
drJDB[UseLabel16[dest]];
};
area: Area = GetCurrentArea[];
savePC: LONG CARDINAL;
start: Label = GenLabel[];
dummy: Label = GenLabel[];
enterFSDBTest: Label = GenLabel[];
enterSHTest: Label = GenLabel[];
A field descriptor is a special interpretation of a 16-bit quantity used to control the Field Unit.
FieldDescriptor: TYPE = MACHINE DEPENDENT RECORD [
reserved: [0..7] ← 0,
reserved bits, not currently used, but must be 0s
insert: BOOL ← FALSE,
governs choice of background and low bits of mask
mask: [0..32] ← 32,
32-mask gives start pos of 1s in the mask (mask = 0 => no 1s)
shift: [0..32] ← 0
gives # of bits to left-shift the double word
];
Test FSDB (FieldDescriptor ← [S] + AlphaBeta; S ← S - 1); this doesn't really test the loading of the shift control hardware because LIP reads the value from a shadow register.
GenFSDB: PROC [] ~ {
FSDBTest: PROC [s: LONG CARDINAL, ab: CARDINAL] ~ {
sw: Word ← CardToWord[s];
resw: Word ← CardToWord[s + ab];
fsdbOK: Label = GenLabel[];
drLIQB[sw]; drFSDB[ab]; drLIQB[resw];
drLIP[131]; --read the field register
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[fsdbOK]]; Pause[]; SetLabel[fsdbOK];
};
SetLabel[enterFSDBTest];
FSDBTest[0, 0];
FSDBTest[0, 1];
FSDBTest[0, 2];
FSDBTest[0, 4];
FSDBTest[0, 10B];
FSDBTest[0, 20B];
FSDBTest[0, 40B];
FSDBTest[0, 100B];
FSDBTest[0, 200B];
FSDBTest[0, 400B];
FSDBTest[0, 1000B];
FSDBTest[0, 2000B];
FSDBTest[0, 4000B];
FSDBTest[17777B, 0];
FSDBTest[17777B, 1];
FSDBTest[17777B, 2];
FSDBTest[17777B, 4];
FSDBTest[17777B, 10B];
FSDBTest[17777B, 20B];
FSDBTest[17777B, 40B];
FSDBTest[17777B, 100B];
FSDBTest[17777B, 200B];
FSDBTest[17777B, 400B];
FSDBTest[17777B, 1000B];
FSDBTest[17777B, 2000B];
FSDBTest[17777B, 4000B];
FSDBTest[13456B, 0];
FSDBTest[11111B, 1];
FSDBTest[12222B, 2];
FSDBTest[13333B, 4];
FSDBTest[14444B, 10B];
FSDBTest[16666B, 20B];
FSDBTest[15555B, 40B];
FSDBTest[10000B, 100B];
FSDBTest[01234B, 200B];
FSDBTest[02345B, 400B];
FSDBTest[03456B, 1000B];
FSDBTest[04567B, 2000B];
FSDBTest[05670B, 4000B];
};
For a pair of inputs and shifter control values, determine the FieldDescriptor and output result for the shifter. Shifter input is the left word in [0..32) and right word in [32..64); this quantity is left-shifted by the specified count, and the left-most 32 bits of the result are the output (so a shift of 0 delivers the left input word, while a shift of 32 delivers the right input word at the output). The mask is used as a multiplexor to select bits from either the shifter output or the background word.
FUSim: PROC [left, right: LONG CARDINAL, insert: BOOLEAN, mask, shift: CARDINAL] RETURNS[out: Word, ab: CARDINAL] ~ {
output: LONG CARDINAL;
shifted: LONG CARDINAL ← Basics.DoubleShiftLeft[[lc[left]], shift].lc + Basics.DoubleShiftRight[[lc[right]], 32 - shift].lc;
mMask: LONG CARDINAL ← Basics.DoubleShiftRight[[lc[37777777777B]], 32 - mask].lc;
IF insert THEN {
mMask ← Basics.DoubleAnd[[lc[mMask]], Basics.DoubleShiftLeft[[lc[37777777777B]], shift]].lc;
output ← Basics.DoubleOr[Basics.DoubleAnd[[lc[shifted]], [lc[mMask]]], Basics.DoubleAnd[[lc[right]], Basics.DoubleNot[[lc[mMask]]]]].lc;
}
ELSE output ← Basics.DoubleAnd[[lc[shifted]], [lc[mMask]]].lc;
RETURN[CardToWord[output], (IF insert THEN 10000B ELSE 0) + (mask * 64) + shift];
};
Test SHL, SHR, and SHD on each value of the shift count.
SHL = [S] ← FieldUnit[[S], 0, AlphaBeta].
SHR = [S] ← FieldUnit[[S], [S], AlphaBeta].
SHD = [S-1] ← FieldUnit[[S-1], [S], AlphaBeta]; S ← S - 1.
RFU = [Rc] ← FieldUnit[[Ra], [Rb], FieldDescriptor].
GenSH: PROC [] ~ {
TestSHOp executes 17 instructions to test FSDB, SHR, SHL, SHD, and RFU on a particular input, shift, and mask.
TestSHOp: PROC [left, right: LONG CARDINAL, insert: BOOLEAN, mask, shift: CARDINAL] ~ {
leftw: Word ← CardToWord[left];
rightw: Word ← CardToWord[right];
result0, result1: Word;
control0, control1: CARDINAL;
SHDok: Label = GenLabel[];
SHBad: Label = GenLabel[];
[result0, control0] ← FUSim[left, right, insert, mask, shift];
drLIQB[CardToWord[LONG[control0 - mask]]];
drFSDB[mask];
[result1, control1] ← FUSim[left, left, insert, mask, shift];
drLIQB[leftw]; --Duplicate the left word for the SHR, RHL, and SHD tests
drDUP[];
drDUP[];
drSHR[control1];
drLIQB[result1];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[SHBad]];
[result1, control1] ← FUSim[left, 0, insert, mask, shift];
drSHL[control1];
drLIQB[result1];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[SHBad]];
drLIQB[rightw];
drRFU[const5, reg0, reg1];
drSHD[control0];
drLIQB[result0];
drRJEBJ[topSrc, const5, UseLabel8B[SHDok]]; SetLabel[SHBad]; Pause[];
SetLabel[SHDok];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[SHBad]];
};
TestSH: PROC [left, right: LONG CARDINAL] ~ {
FOR I: CARDINAL IN [0..32] DO
TestSHOp[left, right, FALSE, 32, I]; --All values of shift for a mask of 32
TestSHOp[left, right, FALSE, I, 0]; --All values of mask for a shift of 0
ENDLOOP;
For these tests with mask = 0, the output should always be 0; this seemed uninteresting, so I commented out these tests.
--TestSHOp[left, right, FALSE, 0, 1];
--TestSHOp[left, right, FALSE, 0, 2];
--TestSHOp[left, right, FALSE, 0, 4];
--TestSHOp[left, right, FALSE, 0, 8];
--TestSHOp[left, right, FALSE, 0, 16];
--TestSHOp[left, right, FALSE, 0, 32];
TestSHOp[left, right, FALSE, 1, 1];
TestSHOp[left, right, FALSE, 1, 2];
TestSHOp[left, right, FALSE, 1, 4];
TestSHOp[left, right, FALSE, 1, 8];
TestSHOp[left, right, FALSE, 1, 16];
TestSHOp[left, right, FALSE, 1, 32];
TestSHOp[left, right, FALSE, 2, 1];
TestSHOp[left, right, FALSE, 2, 2];
TestSHOp[left, right, FALSE, 2, 4];
TestSHOp[left, right, FALSE, 2, 8];
TestSHOp[left, right, FALSE, 2, 16];
TestSHOp[left, right, FALSE, 2, 32];
TestSHOp[left, right, FALSE, 4, 0];
TestSHOp[left, right, FALSE, 4, 1];
TestSHOp[left, right, FALSE, 4, 2];
TestSHOp[left, right, FALSE, 4, 4];
TestSHOp[left, right, FALSE, 4, 8];
TestSHOp[left, right, FALSE, 4, 16];
TestSHOp[left, right, FALSE, 4, 32];
TestSHOp[left, right, FALSE, 8, 1];
TestSHOp[left, right, FALSE, 8, 2];
TestSHOp[left, right, FALSE, 8, 4];
TestSHOp[left, right, FALSE, 8, 8];
TestSHOp[left, right, FALSE, 8, 16];
TestSHOp[left, right, FALSE, 8, 32];
TestSHOp[left, right, FALSE, 16, 1];
TestSHOp[left, right, FALSE, 16, 2];
TestSHOp[left, right, FALSE, 16, 4];
TestSHOp[left, right, FALSE, 16, 8];
TestSHOp[left, right, FALSE, 16, 16];
TestSHOp[left, right, FALSE, 16, 32];
These are the inserts.
FOR I: CARDINAL IN [0..32] DO
TestSHOp[left, right, TRUE, 32, I]; --All values of shift for a mask of 32
TestSHOp[left, right, TRUE, I, 0]; --All values of mask for a shift of 0
ENDLOOP;
For these tests with mask = 0, the output should always be the right input and when shift is >= mask, then no insert takes place; these seemed uninteresting, so I commented them out
--TestSHOp[left, right, TRUE, 0, 1];
--TestSHOp[left, right, TRUE, 0, 2];
--TestSHOp[left, right, TRUE, 0, 4];
--TestSHOp[left, right, TRUE, 0, 8];
--TestSHOp[left, right, TRUE, 0, 16];
--TestSHOp[left, right, TRUE, 0, 32];
--TestSHOp[left, right, TRUE, 1, 1];
--TestSHOp[left, right, TRUE, 1, 2];
--TestSHOp[left, right, TRUE, 1, 4];
--TestSHOp[left, right, TRUE, 1, 8];
--TestSHOp[left, right, TRUE, 1, 16];
--TestSHOp[left, right, TRUE, 1, 32];
TestSHOp[left, right, TRUE, 2, 1];
--TestSHOp[left, right, TRUE, 2, 2];
--TestSHOp[left, right, TRUE, 2, 4];
--TestSHOp[left, right, TRUE, 2, 8];
--TestSHOp[left, right, TRUE, 2, 16];
--TestSHOp[left, right, TRUE, 2, 32];
TestSHOp[left, right, TRUE, 4, 1];
TestSHOp[left, right, TRUE, 4, 2];
--TestSHOp[left, right, TRUE, 4, 4];
--TestSHOp[left, right, TRUE, 4, 8];
--TestSHOp[left, right, TRUE, 4, 16];
--TestSHOp[left, right, TRUE, 4, 32];
TestSHOp[left, right, TRUE, 8, 1];
TestSHOp[left, right, TRUE, 8, 2];
TestSHOp[left, right, TRUE, 8, 4];
--TestSHOp[left, right, TRUE, 8, 8];
--TestSHOp[left, right, TRUE, 8, 16];
--TestSHOp[left, right, TRUE, 8, 32];
TestSHOp[left, right, TRUE, 16, 1];
TestSHOp[left, right, TRUE, 16, 2];
TestSHOp[left, right, TRUE, 16, 4];
TestSHOp[left, right, TRUE, 16, 8];
TestSHOp[left, right, TRUE, 16, 16];
--TestSHOp[left, right, TRUE, 16, 32];
};
SetLabel[enterSHTest];
TestSH[37777777777B, 0];
TestSH[0, 37777777777B];
TestSH[11111111111B, 12345670123B];
TestSH[33333333333B, 23423423423B];
};
WordAlign[area];
SetLabel[dummy];
Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; Halt[123B];
Opcodes 0 and 377B are intercepted by the simulator, but make them trap to dummy here anyway.
savePC ← GetOutputPC[area];
FillTrap[ResetTrap, start];
FillXop[0, dummy];
FillXop[377B, dummy];
SetOutputPC[savePC];
Simulator execution begins here on a Reset.
WordAlign[area];
SetLabel[start];
const0 is in a ROM, so it requires no initialization; const2 is initialized to -1 here; the other constants require no initialization for this diagnostic.
drASL[255];
When there is nothing on the stack, S should be at L-1
drLIQB[IntToWord[-1]];
drROR[const2, topSrc, popSrc]; --Put -1 in const2.
GenFSDB[];
GenSH[];
Halt[177777B]; --Terminate here at the end of the program
};
END.