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
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]];
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];
};