GenTrapTest.mesa
written by McCreight, 28 Sept 85
McCreight, September 11, 1986 6:50:15 pm PDT
DIRECTORY
DragOpsCross,
DragOpsCrossUtils,
HandCoding,
HandCodingPseudos,
HandCodingSupport;
GenTrapTest: CEDAR PROGRAM
IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport
= BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport;
expected: AuxRegSpec = [aux[10]];
ifuOvflCallDepth: AuxRegSpec = [aux[11]];
underflowHandler: AuxRegSpec = [aux[12]];
stackPos: AuxRegSpec = [aux[13]];
Other: TYPE = {none, stackUnderflow};
StackedStatusToWord: PROC [ s: DragOpsCross.StackedStatusWord, sense: {normal, complemented} ← normal ] RETURNS [ w: DragOpsCross.Word ] =
TRUSTED BEGIN
w ← LOOPHOLE[s];
IF sense = complemented THEN w ← DragOpsCrossUtils.DragNot[w];
END;
All: PROC = {
The register expected is used to indicate which trap is expected, and stackPos indicates where the stack should be when the trap strikes. Main line code sets them, and trap routines check and reset them.
MarkStack: PROC = { -- 6 bytes
drLFC[UseLabel16[getS]]; -- get the current EU stack position
drROR[c: stackPos, a: const0, b: popSrc];
};
CheckStack: PROC [haltCode: NAT, delta: INT ← 0] = {
drLFC[UseLabel16[getS]]; -- get the current EU stack position
IF delta # 0 THEN {
drADDB[IF delta>0 THEN 128-delta ELSE -delta];
drLIB[07FH];
drAND[];
};
drRJEBJ[left: popSrc, right: stackPos, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[haltCode]; -- stack misadjusted
SetLabel[fwdLabel0];
};
Expect: PROC [ willBeXOP: DragOpsCross.Inst ← dLIQB -- never an XOP --, willBeTrap: DragOpsCross.TrapIndex ← ALUCondFalse -- never a trap --, willBeOther: Other ← none ] =
BEGIN
IF (willBeXOP # dLIQB) OR (willBeOther # none) OR (willBeTrap # ALUCondFalse) THEN MarkStack[]; -- 6 bytes
PushExpected[xop: willBeXOP, trap: willBeTrap, other: willBeOther]; -- 2 bytes if trap
drROR[c: expected, a: const0, b: popSrc]; -- 3 bytes
END;
PushExpected: PROC [xop: DragOpsCross.Inst ← dLIQB -- not a real xop --, trap: DragOpsCross.TrapIndex ← ALUCondFalse -- not a real trap --, other: Other ← none -- not a real other -- ] =
BEGIN
SELECT TRUE FROM
xop # dLIQB => drLIDB[256+xop.ORD];
other # none => drLIDB[512+other.ORD];
ENDCASE => drLIB[trap.ORD]; -- 2 bytes
END;
Check: PROC [ wasXOP, willBeXOP: DragOpsCross.Inst ← dLIQB -- never an XOP --, wasTrap, willBeTrap: DragOpsCross.TrapIndex ← ALUCondFalse -- never a trap -- , wasOther, willBeOther: Other ← none -- never a trap -- , wasFailCode: CARDINAL ← 1 ] =
BEGIN
fwdLabel0: Label;
PushExpected[xop: wasXOP, trap: wasTrap, other: wasOther];
drRJEBJ[left: popSrc, right: expected, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[wasFailCode];
SetLabel[fwdLabel0];
Expect[willBeXOP: willBeXOP, willBeTrap: willBeTrap, willBeOther: willBeOther];
END;
GenGetLAndStatus: PROC RETURNS [ getLAndStatus: Label ] =
BEGIN -- Effect: [S+1] ← DragOpsCross.StackedStatusWord; S ← S+1
getLAndStatus ← GenLabelHere[];
drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
ProcedureExit[rets: 1, dontChangeSP: TRUE];
END;
GenGetS: PROC RETURNS [ getS: Label ] =
BEGIN -- Effect: [S+1] ← S; S ← S+1
ProcedureEntry[label: getS ← GenLabel[], args: 1]; -- L ← S
drLFC[UseLabel16[getLAndStatus]];
drLIB[DragOpsCrossUtils.WordToCard[StackedStatusToWord[[lBase: 0FFH]]]];
drAND[];
ProcedureExit[rets: 2];
END;
GenLSUnderflowKernel: PROC RETURNS [ lsUnderflowKernel: Label ] =
BEGIN
underflowTrap, fwdLabel0: Label;
lsUnderflowKernel ← GenLabelHere[];
drLIB[DragOpsCross.TrapIndex[ALUCondFalse].ORD]; -- one frame on IFU stack
drROR[c: expected, a: const0, b: popSrc];
drLIB[sLimitValue];
drDUP[];
drSIP[DragOpsCross.ProcessorRegister[ifuSLimit].ORD];
drLIP[DragOpsCross.ProcessorRegister[ifuSLimit].ORD];
drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[5]; -- couldn't set SPLimit
SetLabel[fwdLabel0];
GetEldestPC[]; -- pops IFU stack to EU stack top
drSFC[]; -- returns to caller with underflow handler on stack
underflowTrap ← GenLabelHere[]; -- no frames on stack
PushExpected[other: stackUnderflow];
drRJEBJ[left: popSrc, right: expected, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[6]; -- this fault wasn't expected
SetLabel[fwdLabel0];
drLFC[UseLabel16[getS]];
drRJEBJ[left: popSrc, right: stackPos, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[7]; -- stack misadjusted
SetLabel[fwdLabel0];
drLIB[DragOpsCross.TrapIndex[ALUCondFalse].ORD];
drROR[c: expected, a: const0, b: popSrc];
drROR[c: pushDst, a: const0, b: underflowHandler];
drSFC[];
drJB[UseLabel8A[underflowTrap]];
END;
GenTrapsOn: PROC RETURNS [ trapsOn: Label ] =
BEGIN
trapsOn ← GenLabelHere[];
drLIQB[StackedStatusToWord[[trapsEnabled: TRUE], complemented]];
drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drAND[];
drLIQB[StackedStatusToWord[[trapsEnabled: TRUE]]];
drOR[];
drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
ProcedureExit[rets: 0, dontChangeSP: TRUE];
END;
GenXOPTrap: PROC RETURNS [ xopTrap: Label ] =
BEGIN -- Checks fault type and S, and returns to successor of xop
fwdLabel0: Label;
xopTrap ← GenLabelHere[];
drRJEBJ[left: popSrc, right: expected, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[22]; -- this xop wasn't expected
SetLabel[fwdLabel0];
CheckStack[haltCode: 23];
drLIB[DragOpsCross.TrapIndex[ALUCondFalse].ORD];
drROR[c: expected, a: const0, b: popSrc];
ProcedureExit[rets: 0, dontChangeSP: TRUE];
END;
GenKFCTrap: PROC RETURNS [ kfcTrap: Label ] =
BEGIN
fwdLabel0: Label;
kfcTrap ← GenLabelHere[];
drRJEBJ[left: popSrc, right: expected, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[24]; -- this kfc wasn't expected
SetLabel[fwdLabel0];
CheckStack[haltCode: 25];
drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
.. something innocuous that's illegal in user mode
drLIB[DragOpsCross.TrapIndex[ALUCondFalse].ORD];
drROR[c: expected, a: const0, b: popSrc];
ProcedureExit[rets: 0, dontChangeSP: TRUE];
END;
GenStandardTrap: PROC RETURNS [ standardTrap: Label ] =
BEGIN -- Checks fault type and S, pushes PC of faulting instr on S, and returns to successor of faulting instr.
fwdLabel0: Label;
opLengthTable: Label = GenLabel[];
standardTrap ← GenLabelHere[];
drRJEBJ[left: popSrc, right: expected, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[2]; -- this trap wasn't expected
SetLabel[fwdLabel0];
drLIB[DragOpsCross.TrapIndex[ALUCondFalse].ORD];
drROR[c: expected, a: const0, b: popSrc];
ProcedureEntry[label: GenLabel[], args: 0];
drRADD[c: pushDst, a: const0, b: const0]; -- saved carry, Reg0
drLIP[DragOpsCross.ProcessorRegister[euField].ORD]; -- saved field control, Reg1
CheckStack[haltCode: 3, delta: 2];
GetYoungestPC[]; -- read PC of offending instruction from IFU stack
drDUP[];
drDUP[];
drSHL[FieldDescriptorToCard[[mask: 5, shift: 3]]];
drFSDB[FieldDescriptorToCard[[]]];
drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]];
drRB[0];
drRFU[c: topDst, a: topSrc, b: const0];
drSHR[FieldDescriptorToCard[[mask: 5, shift: 32-27]]];
drLIB[(7 -- three bits of opcode -- )*DragOpsCross.bytesPerWord];
drAND[]; -- byte offset in opLengthTable
drLIQB[UseLabel32[opLengthTable]]; -- byte address of opLengthTable
drADD[];
drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address
drRB[0]; -- read length table for trapping op
drADD[]; -- add to trap PC
SetYoungestPC[]; -- adjust PC on IFU stack
drFSDB[0]; -- restore field control from stack top
drRUADD[c: topDst, a: popSrc, b: constN1]; -- restore carry from stack top, toss result
ProcedureExit[rets: 0];
WordAlign[area];
SetLabel[opLengthTable]; -- gleaned from DragOpsCross
OutputWord[area, IntToWord[1]]; -- 000 => 1 byte
OutputWord[area, IntToWord[5]]; -- 001 => 5 bytes
OutputWord[area, IntToWord[1]]; -- 01- => 1 byte
OutputWord[area, IntToWord[1]]; -- 01- => 1 byte
OutputWord[area, IntToWord[2]]; -- 10- => 2 bytes
OutputWord[area, IntToWord[2]]; -- 10- => 2 bytes
OutputWord[area, IntToWord[3]]; -- 11- => 3 bytes
OutputWord[area, IntToWord[3]]; -- 11- => 3 bytes
END;
GenCallerTrap: PROC RETURNS [ callerTrap: Label ] =
BEGIN -- Checks fault type and S, and returns to caller of faulting instr with two results: PC of faulting instr on top, and stack top next.
fwdLabel0, getTrapStatusMasks: Label;
callerTrap ← GenLabelHere[];
drRJEBJ[left: popSrc, right: expected, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[4]; -- this fault wasn't expected
SetLabel[fwdLabel0];
drLIB[DragOpsCross.TrapIndex[ALUCondFalse].ORD];
drROR[c: expected, a: const0, b: popSrc];
drDUP[]; -- make space for results, fill with ST
drDUP[];
drDUP[];
drDUP[];
ProcedureEntry[label: GenLabel[], args: 2]; -- ST in Reg0, Reg1
drRADD[c: pushDst, a: const0, b: const0]; -- saved carry, Reg2
CheckStack[haltCode: 5, delta: 5];
GetYoungestPC[];
drSRn[reg0]; -- Reg0 ← PC of offending instruction
drLIQB[UseLabel32[fwdLabel0 ← GenLabel[]]];
SetYoungestPC[]; -- move caller's PC to within our trap handler
drLFC[UseLabel16[getTrapStatusMasks ← GenLabel[]]];
drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drOR[];
drAND[];
drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
.. make caller allowed to trap if and only if we are
ProcedureExit[rets: 3];
SetLabel[getTrapStatusMasks];
drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD];
drLIQB[StackedStatusToWord[[trapsEnabled: TRUE], complemented]];
drOR[];
drDUP[];
drLIQB[StackedStatusToWord[[trapsEnabled: TRUE]]];
drAND[];
ProcedureExit[rets: 2, dontChangeSP: TRUE];
SetLabel[fwdLabel0];
drRUADD[c: topDst, a: popSrc, b: constN1]; -- restore carry, toss result
drSRn[reg0]; -- Reg0 ← ST
drSRn[reg1]; -- Reg1 ← PC of offending instruction
ProcedureExit[rets: 2]; -- returns PC of offending instruction on top
END;
GenReschedTrap: PROC RETURNS [ reschedTrap: Label ] =
BEGIN
reschedTrap ← GenLabel[];
ProcedureEntry[label: reschedTrap, args: 1];
ProcedureExit[rets: 0];
END;
FillTrap: PROC [ trap: DragOpsCross.TrapIndex, label: Label ← NIL ] =
BEGIN
oldPC: LONG CARDINAL = GetOutputPC[];
IF label = NIL THEN label ← standardTrap;
SetOutputPC[DragOpsCrossUtils.TrapIndexToBytePC[trap]];
PushExpected[trap: trap]; -- push the trap number
drJDB[UseLabel16[label]]; -- go to trap handler
SetOutputPC[oldPC];
END;
FillXOP: PROC [ inst: DragOpsCross.Inst, label: Label ] =
BEGIN
oldPC: LONG CARDINAL = GetOutputPC[];
SetOutputPC[DragOpsCrossUtils.XopToBytePC[inst]];
PushExpected[xop: inst]; -- push the xop number
drJDB[UseLabel16[label]]; -- go to trap handler
SetOutputPC[oldPC];
END;
M A I N L I N E C O D E
area: Area = GetCurrentArea[];
curPC: CARD;
sLimitValue: [0..128) = 16;
getLAndStatus: Label = GenGetLAndStatus[];
getS: Label = GenGetS[];
trapsOn: Label = GenTrapsOn[];
lsUnderflowKernel: Label = GenLSUnderflowKernel[];
standardTrap: Label = GenStandardTrap[];
callerTrap: Label = GenCallerTrap[];
xopTrap: Label = GenXOPTrap[];
kfcTrap: Label = GenKFCTrap[];
reschedTrap: Label = GenReschedTrap[];
data: Label = GenLabel[];
dataA: Label = GenLabel[];
SFCITarget: Label = GenLabel[];
start: Label = GenLabel[];
fwdLabel0, fwdLabel1, fwdLabel2, bwdLabel0, bwdLabel1: Label;
ifuPageFaultTest1: Label = GenLabel[];
ifuFirstIncompleteInstruction1: Label = GenLabel[];
faultingPC: Label = GenLabel[];
FillTrap[IFUPageFaultTrap, callerTrap];
FillTrap[EUPageFault, callerTrap];
FillTrap[IFUStackOverflowTrap];
FillTrap[EUStackOverflowTrap, callerTrap];
FillTrap[ALUCondOver];
FillTrap[ModeFault];
FillTrap[MemAccessFault];
FillTrap[IOAccessFault];
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;
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[dataA];
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
Set up some constant registers
SetLabel[start]; -- gets here in kernel mode with traps off
drLIB[1]; drROR[c: const1, a: const0, b: popSrc];
.. done by ROM cells these days, I'm told.
drRADD[c: pushDst, a: const0, b: const0]; -- clear carry
drDIS[];
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]; -- initialize field unit control
drRFU[c: constNI, a: popSrc, b: const0];
Set up L and SLimit registers in kernel mode with traps off.
drLFC[UseLabel16[lsUnderflowKernel]];
Turn on traps.
drLFC[UseLabel16[trapsOn]];
Test addition without and with overflow, with carry clear.
drRADD[c: pushDst, a: const0, b: const0]; -- clear carry
drDIS[];
drRADD[c: pushDst, a: constNI, b: const0]; -- shouldn't overflow
drDIS[];
Check[willBeTrap: ALUCondOver];
drRADD[c: pushDst, a: constNI, b: constN1]; -- should overflow
Check[wasFailCode: 101];
drRADD[c: pushDst, a: const0, b: const0]; -- find out what carry was
drJEBBJ[lit: 0, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[102]; -- carry wasn't clear
SetLabel[fwdLabel0];
Test addition without and with overflow, with carry set.
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[];
Check[willBeTrap: ALUCondOver];
drRADD[c: pushDst, a: constNI, b: constN2];
Check[wasFailCode: 111];
drRADD[c: pushDst, a: const0, b: const0]; -- find out what carry was
drJEBBJ[lit: 1, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[112]; -- carry wasn't set
SetLabel[fwdLabel0];
Test variants of conditional jumps
MarkStack[];
drRJEBJ[left: const0, right: const0, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
drDIS[];
Halt[113];
bwdLabel0 ← GenLabelHere[];
drDIS[];
Halt[114];
SetLabel[fwdLabel0];
drRJNEBJ[left: const0, right: const0, dist: UseLabel8B[bwdLabel0]];
drRJEB[left: const0, right: const0, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
drDIS[];
Halt[115];
bwdLabel0 ← GenLabelHere[];
drDIS[];
Halt[116];
SetLabel[fwdLabel0];
drRJNEB[left: const0, right: const0, dist: UseLabel8B[bwdLabel0]];
drJ1[];
CheckStack[haltCode: 117];
Test IFU page faulting.
drLFC[UseLabel16[ifuPageFaultTest1]];
Check[wasFailCode: 105];
drLIQB[UseLabel32[ifuFirstIncompleteInstruction1]];
drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[121]; -- trap PC wasn't right
SetLabel[fwdLabel0];
drDIS[]; -- ignore copied stack top
Test EU page faulting.
drLFC[UseLabel16[fwdLabel0 ← GenLabel[]]];
Check[];
drJDB[UseLabel16[fwdLabel1 ← GenLabel[]]];
SetLabel[fwdLabel0];
drLIB[0];
drSIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- clear euMAR
drLIQB[UseLabel32[ifuFirstIncompleteInstruction1]];
drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address
Check[willBeTrap: EUPageFault];
WHILE GetOutputPC[area] MOD DragOpsCross.bytesPerWord # 3 DO
Align with respect to word boundary
drJ1[];
ENDLOOP;
bwdLabel0 ← GenLabelHere[];
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[fwdLabel1];
drLIQB[UseLabel32[bwdLabel0]];
drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[132]; -- trap PC wasn't right
SetLabel[fwdLabel0];
drLIB[20]; -- stack top + 20 = address that faulted
drADD[];
drLIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- compare against euMAR
drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[133]; -- euMAR wasn't right
SetLabel[fwdLabel0];
Test SFCI with rejects
drLIQB[UseLabel32[dataA]];
drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address
drDUP[];
drLIB[4];
drWSB[0]; -- force prior reject
drADDB[4];
drSFCI[]; -- force reject within SFCI
Check[];
drJDB[UseLabel16[fwdLabel0 ← GenLabel[]]];
SetLabel[SFCITarget];
drLIQB[UseLabel32[faultingPC]]; -- as if there were a data word here
drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address
Check[willBeTrap: EUPageFault];
bwdLabel0 ← GenLabelHere[];
drSFCI[]; -- generates page fault, sets euMAR to faulting address
drRADD[c: pushDst, a: constNI, b: constNI]; -- generates arithmetic overflow
Halt[134];
SetLabel[fwdLabel0];
drLIQB[UseLabel32[bwdLabel0]];
drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[132]; -- trap PC wasn't right
SetLabel[fwdLabel0];
drDIS[]; -- ignore copied stack top
Test conditional store
drLFC[UseLabel16[fwdLabel0 ← GenLabel[]]];
drJDB[UseLabel16[fwdLabel1 ← GenLabel[]]];
ProcedureEntry[label: fwdLabel0, 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
MarkStack[];
drCST[0]; -- should succeed
drJEBBJ[lit: 1, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]]; -- sampled value
Halt[141];
SetLabel[fwdLabel0];
CheckStack[haltCode: 142];
drLRIn[reg0, 0];
drJEBBJ[lit: 2, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[143];
SetLabel[fwdLabel0];
drDIS[];
drDIS[];
drLIB[3]; -- proposed new value
drLIB[1]; -- proposed old value
drCST[0]; -- should fail
drJEBBJ[lit: 2, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]]; -- sampled value
Halt[144];
SetLabel[fwdLabel0];
CheckStack[haltCode: 145];
drLRIn[reg0, 0];
drJEBBJ[lit: 2, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[146];
SetLabel[fwdLabel0];
drDIS[];
drDIS[];
drDIS[];
drLIQB[UseLabel32[ifuFirstIncompleteInstruction1]];
drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address
drLIB[3]; -- proposed new value
drLIB[1]; -- proposed old value
Check[willBeTrap: EUPageFault];
WHILE GetOutputPC[area] MOD DragOpsCross.bytesPerWord # DragOpsCross.bytesPerWord-1 DO
Align to last byte in a word
drJ1[];
ENDLOOP;
bwdLabel0 ← GenLabelHere[];
drCST[20]; -- generates page fault
drRADD[c: pushDst, a: constNI, b: constNI]; -- generates arithmetic overflow
Halt[147]; -- should never get here
SetLabel[fwdLabel1];
Check[wasFailCode: 148];
drLIQB[UseLabel32[bwdLabel0]];
drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[149]; -- trap PC wasn't right
SetLabel[fwdLabel0];
drDIS[]; -- ignore copied stack top
Test S register limiting.
drLFC[UseLabel16[fwdLabel0 ← GenLabel[]]];
drJDB[UseLabel16[fwdLabel1 ← GenLabel[]]];
ProcedureEntry[label: fwdLabel0, args: 0];
drLFC[UseLabel16[fwdLabel0 ← GenLabel[]]];
drSRn[reg1]; -- PC of offender
drSRn[reg0]; -- last successfully pushed value
ProcedureExit[rets: 2];
SetLabel[fwdLabel0];
Check[willBeTrap: EUStackOverflowTrap];
drLIB[sLimitValue-1];
Limits as a drLIB instruction tries to increment from sLimitValue-1 to sLimitValue
drROR[c: stackPos, a: const0, b: popSrc];
drLIB[0];
bwdLabel0 ← GenLabelHere[];
FOR i: [0..32) IN [0..32) DO
drLIB[2*(i+1)];
ENDLOOP;
Halt[151]; -- should have trapped on EU overflow by now
SetLabel[fwdLabel1];
Check[];
drLIQB[UseLabel32[bwdLabel0]];
drRVSUB[c: belowDst, a: belowSrc, b: popSrc];
drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[152]; -- trap PC didn't agree with topmost value
SetLabel[fwdLabel0];
Test manual IFU stack entry and underflow.
drLIQB[UseLabel32[fwdLabel0 ← GenLabel[]]];
drROR[c: underflowHandler, a: const0, b: popSrc];
Check[willBeOther: stackUnderflow];
ProcedureExit[rets: 0, dontChangeSP: TRUE];
SetLabel[fwdLabel0];
Check[wasFailCode: 161];
drLFC[UseLabel16[trapsOn]]; -- underflow handler sends control w/ traps off
Test IFU stack overflow.
drLFC[UseLabel16[fwdLabel0 ← GenLabel[]]];
drJDB[UseLabel16[fwdLabel1 ← GenLabel[]]];
ProcedureEntry[label: fwdLabel0, args: 0];
drLIB[0];
Check[willBeTrap: IFUStackOverflowTrap];
drLFC[UseLabel16[fwdLabel0 ← GenLabel[]]];
bwdLabel0 ← GenLabelHere[]; -- IFU PC address at which to stop
ProcedureExit[rets: 0];
fwdLabel2 ← GenLabel[];
FOR i: [0..16) IN [0..16) DO
SetLabel[fwdLabel0];
drLFC[UseLabel16[fwdLabel0 ← GenLabel[]]];
drJDB[UseLabel16[fwdLabel2]];
ENDLOOP;
SetLabel[fwdLabel0];
Halt[171]; -- too deep
SetLabel[fwdLabel2];
drLIQB[UseLabel32[bwdLabel0]]; -- IFU stack PC address at which to stop
bwdLabel1 ← GenLabelHere[];
drRVADD[c: reg0, a: reg0, b: const1]; -- pull most of the calls off the stack
GetYoungestPC[];
drRJEB[left: popSrc, right: belowSrc, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
drLIQB[UseLabel32[bwdLabel1]];
SetYoungestPC[];
ProcedureExit[rets: 0, dontChangeSP: TRUE];
SetLabel[fwdLabel0];
drDIS[];
Check[wasFailCode: 181];
drLRn[reg0];
drROR[c: ifuOvflCallDepth, a: popSrc, b: const0];
drJEBBJ[lit: 10, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[182]; -- reg0 holds actual number
SetLabel[fwdLabel0];
ProcedureExit[rets: 0, dontChangeSP: TRUE];
SetLabel[fwdLabel1];
Test mode-independent XOP's
Check[willBeXOP: VAL[1B]];
OutputByte[NIL, CardToByte[1B]]; -- one-byte XOP
Check[];
drLIQB[CardToWord[12345678H]];
drDUP[]; -- get stack to depth it will have after XOP pushes argument word
Check[willBeXOP: x077b];
drDIS[];
OutputByte[NIL, CardToByte[77B]]; -- five-byte XOP
OutputAlphaBetaGammaDelta[NIL, CardToWord[12345678H]]; -- this gets pushed
Check[];
drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[191];
SetLabel[fwdLabel0];
Switch to user mode
drLIB[0FEH];
drSIP[07FH]; -- succeeds because I'm still in kernel mode
drJDB[UseLabel16[fwdLabel0 ← GenLabel[]]];
bwdLabel0 ← GenLabelHere[]; -- subroutine executed from kernel mode that returns to 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];
ProcedureExit[rets: 0, dontChangeSP: TRUE];
SetLabel[fwdLabel0];
drLFC[UseLabel16[bwdLabel0]];
Try several kernel-only instructions from user mode
drLIB[1]; -- for the store, which should never happen
Check[willBeTrap: ModeFault];
Address-independent protection violations trap to ModeFault
drSIP[07FH];
Check[];
drDIS[]; -- the 1 above
drLIP[07FH];
drDIS[];
Check[willBeTrap: ModeFault];
drLIP[DragOpsCross.ProcessorRegister[ifuEldestPC].ORD];
Check[willBeTrap: ModeFault];
drROR[c: const1, a: const0, b: const0];
Check[willBeXOP: dKFC];
drKFC[]; -- make sure we can get to kernel mode and back
Check[willBeTrap: ModeFault];
drROR[c: [aux[0]], a: const0, b: const0];
Check[];
drROR[c: [aux[15]], a: const0, b: const0];
End of test
Halt[0FFFFH]; -- end of test
Instruction sequence for IFU page fault test...
curPC ← GetOutputPC[area];
SetOutputPC[curPC+((2*DragOpsCross.bytesPerPage-15-(curPC MOD DragOpsCross.bytesPerPage)) MOD DragOpsCross.bytesPerPage), area];
SetLabel[ifuPageFaultTest1];
Expect[willBeTrap: IFUPageFaultTrap]; -- 11 bytes
SetLabel[ifuFirstIncompleteInstruction1];
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[faultingPC];
};
END.