GenTraps2.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Edward Fiala March 5, 1986 11:01:20 am PST
This diagnostic tests a few trap conditions which could not conveniently be tested in GenTraps because different handling of the traps would have been required:
1) Verify that IFU stack overflow prevails over ifu page fault.
2) Verify that EU stack overflow trap prevails over reschedule when a SIP enables traps and the EU stack overflow and reschedule-waiting conditions are both true.
3) **Verify that an IFU page fault trap prevails over an EU stack overflow trap.
When simulated correctly it terminates with HALT[177777B] at PC 4016556B, cycle 5506, Inst 1881.
DIRECTORY
DragOpsCross USING [Word, ProcessorRegister, XopBase, TrapBase, TrapWidthBytes, bytesPerWord, TrapIndex, KernalLimit],
--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 [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
GenTraps2: CEDAR PROGRAM
IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport
= BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport;
Word: TYPE = DragOpsCross.Word;
ProcessorRegister: TYPE = DragOpsCross.ProcessorRegister;
ifuSLimit = 7-bit stack limit register. Any opcode which causes the stack pointer to enter the region [SLimit..SLimit+16) will be trapped to the EU stack overflow location.
ifuSLimit: CARDINAL = LOOPHOLE[ProcessorRegister.ifuSLimit, CARDINAL];
IFUStackSize = 15. LIP[ifuEldestPC] removes and SIP[ifuEldestPC] adds to the call stack.
ifuEldestPC: CARDINAL = LOOPHOLE[ProcessorRegister.ifuEldestPC, CARDINAL];
ifuEldestL: CARDINAL = LOOPHOLE[ProcessorRegister.ifuEldestL, CARDINAL];
ifuYoungestPC: CARDINAL = LOOPHOLE[ProcessorRegister.ifuYoungestPC, CARDINAL];
ifuYoungestL: CARDINAL = LOOPHOLE[ProcessorRegister.ifuYoungestL, CARDINAL];
ifuStatus: CARDINAL = LOOPHOLE[ProcessorRegister.ifuStatus, CARDINAL];
euMAR: CARDINAL = LOOPHOLE[ProcessorRegister.euMAR, CARDINAL];
KernelLimit: LONG CARDINAL = DragOpsCross.KernalLimit;
In this diagnostic, the auxiliary registers are called aux0 .. aux15; the locals reg0 .. reg15; and the constants const0 .. const11. Global register usage is as follows:
aux8 contains a code indicating the trap expected (0 if none).
const4 contains the constant 6 for trap routines.
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 = {
area: Area = GetCurrentArea[];
oldPC: LONG CARDINAL;
start: Label = GenLabel[];
dummy: Label = GenLabel[];
initL: Label = GenLabel[];
These labels are for trap procedures.
IFUStackOverflow: Label = GenLabel[];
IFUStkOvfBad: Label = GenLabel[];
EUStackOverflow: Label = GenLabel[];
EUStkOvfBad: Label = GenLabel[];
enterIFUStackOverflowTest: Label = GenLabel[];
enterSLimitTest: Label = GenLabel[];
Must be first instruction on a page that is otherwise unused.
IFUPageFaultAddress: LONG CARDINAL = 27000000000B;
All traps enter kernel mode, disable traps, and push the old ifuStatus onto the EU stack. Disabling affects only Reschedule, EU stack overflow, and IFU stack overflow.
When traps are enabled, the IFU stack allows 11 normal calls but converts the 12th call into an IFU stack overflow trap; when traps are disabled, all 15 levels of the IFU stack are usable. Note, however, that when a trap or KFC is the 12th call, it will complete and disable traps without causing an IFU stack overflow trap. There is no IFU stack underflow trap; the first location in the IFU stack must be made to contain a return link to an appropriate trap procedure (or use the trick of causing a page fault).
When traps are enabled, any opcode causing S to wind up in the range [SLimit..SLimit+16) causes an EU stack overflow trap; this detects both underflows and overflows, though underflow can only happen due to a programming error.
Xops and KFC 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]];
};
Test conditions which should and should not cause IFU stack overflow trap. Begin here in Kernel mode with traps disabled, and 0 IFU call stack entries.
GenIFUStackOverflow: PROC [] ~ {
exitIFUStkOvfTest: Label = GenLabel[];
SetLabel[enterIFUStackOverflowTest];
drASL[377B]; --0 locals, 0 pushes on the EU stack, 0 calls on the IFU stack
drLIB[40B + 4B + 2B];
drSIP[ifuStatus]; --UserModeKeep + TrapsEnabled + RescheduleKeep
Now in Kernel mode with traps enabled.
drLFC[3]; --1 calls
drLFC[3]; --2 calls
drLFC[3]; --3 calls
drLFC[3]; --4 calls
drLFC[3]; --5 calls
drLFC[3]; --6 calls
drLFC[3]; --7 calls
drLFC[3]; --8 calls
drLFC[3]; --9 calls
drLFC[3]; --10 calls
drLIQB[UseLabel32[exitIFUStkOvfTest]]; --Return PC for stack overflow trap
drLIB[1]; drROR[aux8, popSrc, topSrc]; --Indicate IFU stack overflow expected
drDFC[CardToWord[IFUPageFaultAddress]]; --11 calls
The DFC completes, but the following instruction is on a non-existent page and gets an IFU page fault which does a 12th call and gets converted into an IFU stack overflow trap. The IFU stack overflow trap handler will return here, if this happened correctly.
SetLabel[exitIFUStkOvfTest];
drROR[aux8, const0, const0]; --Indicate no traps expected
Remove the 11 calls from the stack and cleanup
FOR I: CARDINAL IN [0..10] DO GetEldestPC[]; ENDLOOP;
drASL[17B]; --L = 1, S = 20B, traps enabled, Kernel mode, 0 calls on the stack
};
GenSLimit: PROC [] ~ {
SetLabel[enterSLimitTest];
Verify that EU stack overflow prevails over Reschedule when it is true at the time traps are enabled and Reschedule turned on by a SIP.
drASL[377B]; --S = 0, L = 1
drLIB[1]; drSIP[ifuStatus]; --Turn off trap enable, turn on Reschedule
drLC0[];
drLIB[1]; drSIP[ifuSLimit];
Indicate EU stack overflow expected.
drLIB[2]; drROR[aux8, topSrc, popSrc]; --S = SLimit = 1 now
drLIB[4B + 1B]; drSIP[ifuStatus]; --Trap enable + Reschedule
Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[];
EU stack overflow should prevail over Reschedule here because it is true at the onset of the trap; trap returns here with reschedule-waiting turned off and traps disabled.
drROR[aux8, const0, const0]; --No trap expected
drLIB[160B]; drSIP[ifuSLimit];
drASL[377B]; --L = 1, S = 0, traps disabled, Kernel mode, 0 calls on the stack
};
SetLabel[dummy];
Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; Halt[123B];
IFU stack overflow trap has code 1
EU stack overflow has code 2
Arrive here when an IFU page fault has given rise to an IFU stack overflow trap; the youngest PC should point at the instruction which page faulted.
SetLabel[IFUStackOverflow];
drALS[377B]; --1 - nargs; nargs = 2 for ifuStatus (return PC and status)
drLIB[1]; drRJNEB[popSrc, aux8, UseLabel8B[IFUStkOvfBad]];
GetYoungestPC[];
drLIQB[CardToWord[IFUPageFaultAddress]];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[IFUStkOvfBad]];
drLRn[reg0]; SetYoungestPC[]; --Change return address
drEXDIS[];
drRETK[377B]; --nResults - 1 where nResults = 0
SetLabel[IFUStkOvfBad]; Pause[];
Arrive here when an EU stack overflow trap has occurred with reschedule-waiting also true. Trap must turn off the reschedule-waiting and pop the stack twice to eliminate the EU stack overflow condition.
SetLabel[EUStackOverflow];
drALS[0]; --1 - nargs; nargs = 1 for ifuStatus
drLIB[2]; drRJNEB[popSrc, aux8, UseLabel8B[EUStkOvfBad]];
GetYoungestPC[]; drRVADD[topDst, topSrc, const4]; SetYoungestPC[];
drLIB[0]; drSIP[ifuStatus]; --Turn off reschedule-waiting and disable traps
drRETK[377B]; --nResults -1; nResults = 0
SetLabel[EUStkOvfBad]; Pause[];
Opcodes 0 and 377B are intercepted by the simulator, but make them trap to dummy here anyway. These calls to FillXop and FillTrap initialize the trap locations with JDB[trap procedure].
oldPC ← GetOutputPC[area];
FillXop[0, dummy]; --opcode 0 = Pause[]
FillXop[377B, dummy]; --opcode 377B = Halt[xxx]
FillTrap[ResetTrap, start];
FillTrap[IFUStackOverflowTrap, IFUStackOverflow];
FillTrap[EUStackOverflowTrap, EUStackOverflow];
FillTrap[EUPageFault, EUPageFlt];
FillTrap[IFUPageFaultTrap, IFUPageFault];
FillTrap[RescheduleTrap, Reschedule];
SetOutputPC[oldPC];
ProcedureEntry[initL, 0];
drLIB[1];
SetYoungestL[]; -- L ← 1 on return
spLimit is set with room for 17 overflow words (just in case).
drLIB[128-16-1];
SetSPLimit[];
ProcedureExit[0];
WordAlign[area];
Simulator execution begins here on a Reset.
SetLabel[start];
drLFC[UseLabel16[initL]]; --Initialize L to 1
drASL[255]; --and S = 0.
drROR[aux8, const0, const0]; --Initialize aux8 to 0, meaning no traps expected.
drLIB[6];
drROR[const4, popSrc, topSrc]; --Initialize const4 to 6 for the trap routines.
GenIFUStackOverflow[];
GenSLimit[];
Halt[177777B]; --Terminate here at the end of the program
};
END.