GenTrapTest.mesa
written by McCreight, 28 Sept 85
McCreight, February 26, 1986 4:03:00 pm PST
DIRECTORY
DragOpsCross,
DragOpsCrossUtils,
HandCoding,
HandCodingPseudos,
HandCodingSupport;
GenTrapTest: CEDAR PROGRAM
IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport
= BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport;
expected: AuxRegSpec = aux10;
ifuOvflCallDepth: AuxRegSpec = aux11;
underflowHandler: AuxRegSpec = aux12;
stackPos: AuxRegSpec = aux13;
Other: TYPE = {none, stackUnderflow};
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;
GenGetS: PROC RETURNS [ getS: Label ] =
BEGIN -- Effect: [S+1] ← S; S ← S+1
getS ← GenLabel[];
ProcedureEntry[label: getS, args: 1]; -- L ← S
GetL[];
ProcedureExit[rets: 2];
END;
GenLSEnaKernel: PROC RETURNS [ lsEnaKernel: Label ] =
BEGIN
underflowTrap, fwdLabel0: Label;
lsEnaKernel ← GenLabelHere[];
drLIB[DragOpsCross.TrapIndex[ALUCondFalse].ORD]; -- one frame on IFU stack
drROR[c: expected, a: const0, b: popSrc];
drLIB[LOOPHOLE[DragOpsCross.IFUStatusRec[userMode: FALSE, trapsEnabled: FALSE, reschedule: FALSE], LONG CARDINAL]];
drSIP[DragOpsCross.ProcessorRegister[ifuStatus].ORD];
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
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;
GenXOPTrap: PROC RETURNS [ xopTrap: Label ] =
BEGIN -- Checks fault type and S, and returns to successor of faulting instr.
fwdLabel0: Label;
xopTrap ← GenLabelHere[];
drRJEBJ[left: popSrc, right: expected, dist: UseLabel8B[fwdLabel0 ← GenLabel[]]];
Halt[22]; -- this trap 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
kfcTrap ← GenLabel[];
ProcedureEntry[label: kfcTrap, args: 2]; -- saved IFU status, Reg0; trap#, Reg1
drLFC[UseLabel16[xopTrap]];
ProcedureExit[rets: 0, enableTraps: 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.
resumeStatus: DragOpsCross.IFUStatusRec = [ trapsEnabled: TRUE, rescheduleKeep: TRUE ];
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: 1]; -- saved IFU status, Reg0
drRADD[c: pushDst, a: const0, b: const0]; -- saved carry, Reg1
drLIP[DragOpsCross.ProcessorRegister[euField].ORD]; -- saved field control, Reg2
CheckStack[haltCode: 3, delta: 3];
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, enableTraps: TRUE];
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: 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];
ProcedureEntry[label: GenLabel[], args: 2]; -- stack top, Reg0; saved IFU status, Reg1
drLRn[reg1]; -- saved IFU status, Reg2
drRADD[c: pushDst, a: const0, b: const0]; -- saved carry, Reg3
drLRn[reg0]; -- stack top, Reg4
CheckStack[haltCode: 5, delta: 4];
GetYoungestPC[]; -- PC of offending instruction, Reg5
drLIQB[UseLabel32[fwdLabel0 ← GenLabel[]]];
SetYoungestPC[];
ProcedureExit[rets: 6];
SetLabel[fwdLabel0];
drSRn[reg1];
drSRn[reg0];
drRUADD[c: topDst, a: popSrc, b: constN1]; -- restore carry, toss result
ProcedureExit[rets: 2, enableTraps: TRUE];
END;
GenReschedTrap: PROC RETURNS [ reschedTrap: Label ] =
BEGIN
resumeStatusAnd: DragOpsCross.IFUStatusRec =
[ userMode: TRUE, trapsEnabled: TRUE ]; -- clears reschedule
reschedTrap ← GenLabel[];
ProcedureEntry[label: reschedTrap, args: 1];
drLIQB[LOOPHOLE[resumeStatusAnd]];
drAND[];
ProcedureExit[rets: 0, enableTraps: TRUE];
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;
getS: Label = GenGetS[];
lsEnaKernel: Label = GenLSEnaKernel[];
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[AddressCheckFault];
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];
drLIB[1]; drROR[c: const1, a: const0, b: popSrc];
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 and turn on traps in kernel mode.
drLFC[UseLabel16[lsEnaKernel]];
EnableTraps[];
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[]; -- discard second result from trap handler
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]; -- form 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[]; -- faulting address
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[]; -- discard second result from trap handler
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];
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: x065B];
drDIS[];
OutputByte[NIL, CardToByte[65B]]; -- 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];
drLIQB[LOOPHOLE[DragOpsCross.IFUStatusRec[userMode: TRUE, trapsEnabled: TRUE]]];
drLFC[UseLabel16[fwdLabel0 ← GenLabel[]]];
HandCodingSupport.OIcommon[dJ5]; -- jump around two-instruction routine
SetLabel[fwdLabel0];
drALS[0]; -- one argument
drRETK[0FFH];
Try several kernel-mode instructions
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[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 fault de page!
SetLabel[faultingPC];
};
END.