GenQuickTest.mesa
written by McCreight, 28 Sept 85
McCreight, September 11, 1986 6:50:15 pm PDT
Don Curry November 15, 1986 7:31:37 pm PST
DIRECTORY
DragOpsCross,
DragOpsCrossUtils,
HandCoding,
HandCodingPseudos,
HandCodingSupport,
Rope;
GenQuickTest: CEDAR PROGRAM
IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport
= BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport;
instrSize:    AuxRegSpec = [aux[10]]; -- must contain the length of trapping instructns
underflowHandler: AuxRegSpec = [aux[12]];
All: PROC = {
Global: PROC[name: Rope.ROPE, label: Label] RETURNS[Label] =
{MakeLabelGlobal[name, label]; RETURN[label]};
StackedStatusToWord: PROC
[ s: DragOpsCross.StackedStatusWord, sense: {normal, complemented} ← normal ]
RETURNS [ w: DragOpsCross.Word ] = TRUSTED
{w ← LOOPHOLE[s]; IF sense = complemented THEN w ← DragOpsCrossUtils.DragNot[w]};
GenEnableTraps: PROC RETURNS [ enableTraps: Label ] = {
enableTraps ← GenLabelHere[];
drLIQB[StackedStatusToWord[[trapsEnabled: TRUE]]];
drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drOR[];
drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drRETN[]};
GenLSUnderflowKernel: PROC RETURNS [ lsUnderflowKernel: Label ] = {
UnderflowHandler must have been set.
underflowTrap: Label;
lsUnderflowKernel ← GenLabelHere[]; -- one frame on IFU stack
drLIB[sLimitValue];
drSIP[DragOpsCross.ProcessorRegister[ifuSLimit].ORD];
GetEldestPC[]; -- pops IFU stack to EU stack top
drSFC[]; -- Call caller's return PC (underflowTrap pushed onto IFU stack)
underflowTrap ← GenLabelHere[]; -- no frames on stack
drROR[c: pushDst, a: const0, b: underflowHandler];
drSFC[];
drJB[UseLabel8A[underflowTrap]]};
SetSizeForStandardTrapInstr: PROC[instr: DragOpsCross.Inst] = {
drLIB[InstToBytes[instr]];
drROR[c: instrSize, a: popSrc, b: const0]};
GenStandardTrap: PROC RETURNS [ standardTrap: Label ] = {
Returns to successor of faulting instr.
InstrSize must have been set to the faulting instruction size
standardTrap ← GenLabelHere[];
drRADD[c: pushDst, a: const0, b: const0]; -- save carry on stack
GetYoungestPC[];
drRVADD[c: topDst, a: instrSize, b: topSrc];
SetYoungestPC[];
drRUADD[c: topDst, a: popSrc, b: constN1]; -- restore carry, toss result
drRETN[]};
GenCallerTrap: PROC RETURNS [ callerTrap: Label ] = {
Enters with faulting instr on ifu stack top and caller of faulting instr underneath.
Object is to replace faulting instr pc with that of ReturnPatch, do a return to ReturnPatch, which then returns to the caller.
ReturnPatch: Label;
callerTrap ← GenLabelHere[];
drLIQB[StackedStatusToWord[[trapsEnabled: TRUE], complemented]];
drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drAND[];   -- clear trapsEnabled
drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drLIQB[UseLabel32[ReturnPatch ← GenLabel[]]];
SetYoungestPC[]; -- move caller's PC to within our trap handler
drRETN[];
SetLabel[ReturnPatch];
drRETN[]};
GenXOPTrap: PROC RETURNS [ xopTrap: Label ] = {
xopTrap ← GenLabelHere[];
drRETN[]};
GenKFCTrap: PROC RETURNS [ kfcTrap: Label ] = {
kfcTrap ← GenLabelHere[];
drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
.. something innocuous that's illegal in user mode
drRETN[]};
GenReschedTrap: PROC RETURNS [ reschedTrap: Label ] = {
reschedTrap ← GenLabelHere[];
drRETN[]};
FillTrap: PROC [ trap: DragOpsCross.TrapIndex, label: Label ] = {
oldPC: LONG CARDINAL = GetOutputPC[];
SetOutputPC[DragOpsCrossUtils.TrapIndexToBytePC[trap]];
drJDB[UseLabel16[label]]; -- go to trap handler
SetOutputPC[oldPC]};
FillXOP: PROC [ inst: DragOpsCross.Inst, label: Label ] = {
oldPC: LONG CARDINAL = GetOutputPC[];
SetOutputPC[DragOpsCrossUtils.XopToBytePC[inst]];
drJDB[UseLabel16[label]]; -- go to trap handler
SetOutputPC[oldPC]};
M A I N L I N E C O D E
area:   Area = GetCurrentArea[];
curPC:  CARD;
sLimitValue: [0..128) = 16;
EnableTraps:     Label = Global["EnableTraps",   GenEnableTraps[]];
LSUnderflowKernel:   Label = Global["LSUnderflowKernel", GenLSUnderflowKernel[]];
StandardTrap:    Label = Global["StandardTrap",  GenStandardTrap[]];
CallerTrap:     Label = Global["CallerTrap",   GenCallerTrap[]];
XopTrap:      Label = Global["XopTrap",    GenXOPTrap[]];
KFCTrap:      Label = Global["KFCTrap",    GenKFCTrap[]];
ReschedTrap:     Label = Global["ReschedTrap",   GenReschedTrap[]];
Data:       Label = Global["Data",       GenLabel[]];
SFCITarget:     Label = Global["SFCITarget",     GenLabel[]];
SFCITargetLocM4wds:  Label = Global["SFCITargetLocM4wds",  GenLabel[]];
Start:       Label = Global["Start",       GenLabel[]];
ALUOverflow:    Label = Global["ALUOverflow",    GenLabel[]];
ALUOverflowWCry:  Label = Global["ALUOverflowWCry",   GenLabel[]];
CondJumps:     Label = Global["CondJumps",     GenLabel[]];
CondJump0:     Label = Global["CondJump0",     GenLabel[]];
CondJump1:     Label = Global["CondJump1",     GenLabel[]];
CondJump2:     Label = Global["CondJump2",     GenLabel[]];
CondJump3:     Label = Global["CondJump3",     GenLabel[]];
IncompleteLIQB:    Label = Global["IncompleteLIQB",    GenLabel[]];
EUPageFaultCode:   Label = Global["EUPageFaultCode",   GenLabel[]];
EUPageFaultContinue:  Label = Global["EUPageFaultContinue",  GenLabel[]];
SFCITest:      Label = Global["SFCITest",      GenLabel[]];
SFCIPageFaultContinue: Label = Global["SFCIPageFaultContinue", GenLabel[]];
FaultingLocation:   Label = Global["FaultingLocation",   GenLabel[]];
CSTProcedure:    Label = Global["CSTProcedure",    GenLabel[]];
CSTPageFaultReturn:  Label = Global["CSTPageFaultReturn",  GenLabel[]];
CST0:       Label = Global["CST0",       GenLabel[]];
CST1:       Label = Global["CST1",       GenLabel[]];
CST2:       Label = Global["CST2",       GenLabel[]];
CST3:       Label = Global["CST3",       GenLabel[]];
SLimitProcedure0:   Label = Global["SLimitProcedure0",   GenLabel[]];
SLimitProcedure1:   Label = Global["SLimitProcedure1",   GenLabel[]];
SLimitEnd:     Label = Global["SLimitEnd",     GenLabel[]];
IFUUnderFlowReturn:  Label = Global["IFUUnderFlowReturn",  GenLabel[]];
IFUOverExit:     Label = Global["IFUOverExit",     GenLabel[]];
IFUOverNext:    Label;
XOPBegin:     Label = Global["XOPBegin",     GenLabel[]];
XOPExit:      Label = Global["XOPExit",      GenLabel[]];
KernalToUserJmp:   Label = Global["KernalToUserJmp",   GenLabel[]];
KernalToUserMode:   Label = Global["KernalToUserMode",   GenLabel[]];
FillTrap[IFUPageFaultTrap,  CallerTrap ];
FillTrap[EUPageFault,    CallerTrap ];
FillTrap[IFUStackOverflowTrap, CallerTrap ];
FillTrap[EUStackOverflowTrap, CallerTrap ];
FillTrap[ALUCondOver,   StandardTrap ];
FillTrap[ModeFault,    StandardTrap ];
FillTrap[MemAccessFault,   StandardTrap ];
FillTrap[IOAccessFault,   StandardTrap ];
FillTrap[RescheduleTrap,   ReschedTrap ];
FillTrap[ResetTrap,     Start   ];
FOR inst: DragOpsCross.Inst IN DragOpsCross.Inst DO
FillXOP[inst: inst, label: (IF inst=dKFC THEN KFCTrap ELSE XopTrap)];
ENDLOOP;
Data
Set up Data area
WHILE GetOutputPC[area] MOD 4*DragOpsCross.bytesPerWord # 0 DO
Align to quadword boundary
OutputByte[area, CardToByte[0]];
ENDLOOP;
SetLabel[ Data ];
[] ← ReserveData[words: 16];
SetLabel[ SFCITargetLocM4wds ];
THROUGH [0..3) DO OutputWord[area, IntToWord[0]] ENDLOOP;
THROUGH [0..3) DO OutputByte[area, CardToByte[0]] ENDLOOP;
drLIQB[UseLabel32[ SFCITarget ]];
.. it would be nice if there were a way of generating a byte-address and word-address Data word
Start
SetLabel[ Start ]; -- gets here from reset in kernel mode with traps off
Set up EU SLimit and install IFU stack underflow service routine (kernel mode, traps off)
drLFC[UseLabel16[ LSUnderflowKernel ]];
Set up some constant registers
drRSUB[ c: constN1, a: const0,  b: const1];
drRADD[ c: constN2, a: constN1, b: constN1];
drLC1[];
drLIQB[CardToWord[FieldDescriptorToCard[[insert: FALSE, mask: 32, shift: 31]]]];
drFSDB[0];  -- Load field unit control
drRFU[c: constNI, a: popSrc, b: const0]; -- 80000000x 
Enable traps
drLFC[UseLabel16[ EnableTraps ]]; -- inst 12
ALU Overflow
SetLabel[ ALUOverflow ];
drRADD[c: pushDst, a: const0, b: const0]; -- clear carry
drDIS[];
drRADD[c: pushDst, a: constNI, b: const0]; -- shouldn't overflow
drDIS[];
SetSizeForStandardTrapInstr[dRADD];
drRADD[c: pushDst, a: constNI, b: constN1]; -- should overflow
drDIS[];
drRADD[c: pushDst, a: const0, b: const0]; -- show carry
drDIS[];
SetLabel[ ALUOverflowWCry ];
drRUADD[c: pushDst, a: constN1, b: constN1]; -- set carry
drDIS[];
drRADD[c: pushDst, a: constNI, b: constN1]; -- shouldn't overflow
drDIS[];
drRUADD[c: pushDst, a: constN1, b: constN1]; -- set carry
drDIS[];
SetSizeForStandardTrapInstr[dRADD];
drRADD[c: pushDst, a: constNI, b: constN2]; -- should fail
drDIS[];
drRADD[c: pushDst, a: const0, b: const0]; -- show carry
drDIS[];
Conditional Jumps
SetLabel[ CondJumps ];
drRJEBJ[  left: const0, right: const0, dist: UseLabel8B[ CondJump1 ]];
drDIS[];
Halt[113];
SetLabel[ CondJump0 ];
drDIS[];
Halt[114];
SetLabel[ CondJump1 ];
drRJNEBJ[ left: const0, right: const0, dist: UseLabel8B[ CondJump0 ]];
drRJEB[  left: const0, right: const0, dist: UseLabel8B[ CondJump3]];
drDIS[];
Halt[115];
SetLabel[ CondJump2 ];
drDIS[];
Halt[116];
SetLabel[ CondJump3 ];
drRJNEB[  left: const0, right: const0, dist: UseLabel8B[ CondJump2]];
drJ1[];
IFU page faulting.
drLFC[UseLabel16[ IncompleteLIQB ]];
EU Page Fault.
drLFC[UseLabel16[ EUPageFaultCode]];
drJDB[UseLabel16[ EUPageFaultContinue]];
SetLabel[ EUPageFaultCode];
drLIB[0];
drSIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- clear euMAR
drLIQB[UseLabel32[ IncompleteLIQB ]];
drSHR[FieldDescriptorToCard[[mask: 32-2, shift: 32-2]]]; -- byte to word address
WHILE GetOutputPC[area] MOD DragOpsCross.bytesPerWord # 3 DO
drJ1[]; -- Align with respect to word boundary
ENDLOOP;
drRB[20]; -- generates page fault, sets euMAR to faulting address
drRADD[c: pushDst, a: constNI, b: constNI]; -- generates arithmetic overflow
Halt[131]; -- should never get here
SetLabel[ EUPageFaultContinue ];
drLIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- show euMAR
drDIS[];
Test SFCI with rejects
SetLabel[ SFCITest ];
drLIQB[UseLabel32[ SFCITargetLocM4wds ]];
drSHR[FieldDescriptorToCard[[mask: 32-2, shift: 32-2]]]; -- byte to word address
drDUP[];
drLIB[4];
drWSB[0]; -- force prior reject
drADDB[4];
drSFCI[]; -- force reject within SFCI
drJDB[UseLabel16[ SFCIPageFaultContinue ]];
SetLabel[ SFCITarget ];
drLIQB[UseLabel32[ FaultingLocation ]]; -- as if there were a Data word here
drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address
drSFCI[]; -- generates page fault, sets euMAR to faulting address
drRADD[c: pushDst, a: constNI, b: constNI]; -- generates arithmetic overflow
Halt[134];
SetLabel[ SFCIPageFaultContinue ];
drLIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- show euMAR
drDIS[];
Test conditional store
drLFC[UseLabel16[ CSTProcedure ]];
drJDB[UseLabel16[ CSTPageFaultReturn ]];
ProcedureEntry[label: CSTProcedure, args: 0];
drLIQB[UseLabel32[ Data ]];
drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address
drLIB[1];
drSRIn[reg0, 0];
drLIB[2]; -- proposed new value
drLIB[1]; -- proposed old value
drCST[0]; -- should succeed
drJEBBJ[lit: 1, dist: UseLabel8B[ CST0 ]]; -- sampled value
Halt[141];
SetLabel[ CST0 ];
drLRIn[reg0, 0];
drJEBBJ[lit: 2, dist: UseLabel8B[ CST1 ]];
Halt[143];
SetLabel[ CST1 ];
drDIS[];
drDIS[];
drLIB[3]; -- proposed new value
drLIB[1]; -- proposed old value
drCST[0]; -- should fail
drJEBBJ[lit: 2, dist: UseLabel8B[ CST2 ]]; -- sampled value
Halt[144];
SetLabel[ CST2 ];
drLRIn[reg0, 0];
drJEBBJ[lit: 2, dist: UseLabel8B[ CST3 ]];
Halt[146];
SetLabel[ CST3 ];
drDIS[];
drDIS[];
drDIS[];
Skip over this CST[#0] test until it gets implemented
drLIQB[UseLabel32[ IncompleteLIQB ]];
drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address
drLIB[3]; -- proposed new value
drLIB[1]; -- proposed old value
WHILE GetOutputPC[area] MOD DragOpsCross.bytesPerWord # DragOpsCross.bytesPerWord-1 DO
drJ1[]; -- Align to last byte in a word
ENDLOOP;
drCST[20]; -- generates page fault
drRADD[c: pushDst, a: constNI, b: constNI]; -- generates arithmetic overflow
Halt[147]; -- should never get here
SetLabel[ CSTPageFaultReturn ];
drLIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- show euMAR
drDIS[];
drDIS[];
drDIS[];
drDIS[];
SetLabel[ CSTPageFaultReturn ];
drDIS[];
drDIS[];
drDIS[];
Test S register limiting.
drLFC[UseLabel16[ SLimitProcedure0 ]];
drJDB[UseLabel16[ SLimitEnd ]];
ProcedureEntry[label: SLimitProcedure0, args: 0];
drLFC[UseLabel16[ SLimitProcedure1 ]];
ProcedureExit[rets: 0];
SetLabel[ SLimitProcedure1 ];
drLIB[0];
FOR i: [0..32) IN [0..32) DO
drLIB[2*(i+1)];
ENDLOOP;
Halt[151]; -- should have trapped on EU overflow by now
SetLabel[ SLimitEnd ];
Test manual IFU stack entry and underflow.
drLIQB[UseLabel32[ IFUUnderFlowReturn ]];
drROR[c: underflowHandler, a: const0, b: popSrc];
drRETN[];
SetLabel[ IFUUnderFlowReturn ];
drLFC[UseLabel16[ EnableTraps ]]; -- underflow handler sends control w/ traps off
Test IFU stack overflow.
drLFC[UseLabel16[ IFUOverNext ← GenLabel[] ]];
drJDB[UseLabel16[ IFUOverExit ]];
FOR level: [2..11) IN [2..11) DO
SetLabel[ IFUOverNext ];
drLFC[UseLabel16[ IFUOverNext ← GenLabel[] ]];
drRETN[];
ENDLOOP;
SetLabel[ IFUOverNext ];
drLFC[UseLabel16[ IFUOverNext ← GenLabel[] ]]; -- BOOM! - zzzzzzzzzzzzzzzzzz
Halt[161];
SetLabel[ IFUOverNext ];
Halt[162]; -- too deep
SetLabel[ IFUOverExit ];
XOP
SetLabel[ XOPBegin ];
OutputByte[NIL, CardToByte[1B]]; -- one-byte XOP
OutputByte[NIL, CardToByte[077B]]; -- five-byte XOP
OutputAlphaBetaGammaDelta[NIL, CardToWord[12345678H]]; -- this gets pushed
drLIQB[CardToWord[12345678H]];
drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[ XOPExit ]];
Halt[191];
SetLabel[ XOPExit ];
Switch to user mode
drJDB[UseLabel16[ KernalToUserJmp ]];
SetLabel[ KernalToUserMode ]; -- kernel mode => user mode
drLIQB[StackedStatusToWord[[userMode: TRUE, trapsEnabled: TRUE], complemented]];
drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drAND[];
drLIQB[StackedStatusToWord[[userMode: TRUE, trapsEnabled: TRUE]]];
drOR[];
drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drRETN[];
SetLabel[ KernalToUserJmp ];
SetSizeForStandardTrapInstr[ dROR ]; -- 3, LIPs and SIPs need J1 after
drLFC[UseLabel16[ KernalToUserMode ]];
Try several kernel-only instructions from user mode
drLIB[1];               -- for the store, never used
drSIP[07FH];              -- ModeFault
drJ1[];               -- skipped on trap return
drDIS[];               -- the 1 above
drLIP[1];
drDIS[];
drLIP[DragOpsCross.ProcessorRegister[ifuEldestPC].ORD]; -- Mode Fault
drJ1[];               -- skipped on trap return
drROR[c: const1, a: const0, b: const0];      -- Mode Fault
drKFC[];               -- test KFC
drROR[c: [aux[0]], a: const0, b: const0];     -- Mode Fault
drROR[c: [aux[15]], a: const0, b: const0];     -- Mode Fault
End of test
Halt[0FFFFH]; -- end of test
Instruction sequence for IFU page fault test...
{
bpp: NAT ← DragOpsCross.bytesPerPage;
curPC  ← GetOutputPC[area];
SetOutputPC[curPC+((2*bpp-4-(curPC MOD bpp)) MOD bpp), area];
SetLabel[ IncompleteLIQB ];
OutputByte[area, CardToByte[DragOpsCross.Inst[dLIQB].ORD]]; -- 4 bytes in this page
OutputByte[area, CardToByte[1]];
OutputByte[area, CardToByte[2]];
OutputByte[area, CardToByte[3]]; -- Aprez moi, le faux page!
SetLabel[ FaultingLocation ]};
};
END.