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 = { 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]; 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]; 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; 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[MapFault, 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; WHILE GetOutputPC[area] MOD 4*DragOpsCross.bytesPerWord # 0 DO 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]]; SetLabel[start]; -- gets here in kernel mode with traps off 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]; drLFC[UseLabel16[lsUnderflowKernel]]; drLFC[UseLabel16[trapsOn]]; 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]; 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]; 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]; 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 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: MapFault]; WHILE GetOutputPC[area] MOD DragOpsCross.bytesPerWord # 3 DO 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]; 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: MapFault]; 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 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: MapFault]; WHILE GetOutputPC[area] MOD DragOpsCross.bytesPerWord # DragOpsCross.bytesPerWord-1 DO 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 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]; 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]; 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 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]; ProcedureExit[rets: 0, dontChangeSP: TRUE]; SetLabel[fwdLabel1]; 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]; 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]]; drLIB[1]; -- for the store, which should never happen Check[willBeTrap: 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]; Halt[0FFFFH]; -- end of 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. œGenTrapTest.mesa written by McCreight, 28 Sept 85 McCreight, September 11, 1986 6:50:15 pm PDT Fiala May 5, 1987 2:25:54 pm PDT Changed EUPageFault to MapFault 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. .. something innocuous that's illegal in user mode .. make caller allowed to trap if and only if we are M A I N L I N E C O D E Set up data area Align to quadword boundary .. it would be nice if there were a way of generating a byte-address and word-address data word Set up some constant registers drLIB[1]; drROR[c: const1, a: const0, b: popSrc]; .. done by ROM cells these days, I'm told. Set up L and SLimit registers in kernel mode with traps off. Turn on traps. Test addition without and with overflow, with carry clear. Test addition without and with overflow, with carry set. Test variants of conditional jumps Test IFU page faulting. Test EU page faulting. Align with respect to word boundary Test SFCI with rejects Test conditional store Align to last byte in a word Test S register limiting. Limits as a drLIB instruction tries to increment from sLimitValue-1 to sLimitValue Test manual IFU stack entry and underflow. Test IFU stack overflow. drJEBBJ[lit: 10, dist: UseLabel8B[fwdLabel0 _ GenLabel[]]]; Halt[182]; -- reg0 holds actual number SetLabel[fwdLabel0]; Test mode-independent XOP's Switch to user mode Try several kernel-only instructions from user mode Address-independent protection violations trap to ModeFault End of test Instruction sequence for IFU page fault test... Κ/˜šœ™Jšœ ™ Icode™,K™@—J˜šΟk ˜ Kšœ ˜ K˜Kšœ ˜ Kšœ˜Kšœ˜K˜—šœ œ˜KšœD˜KKšœœœE˜QK˜Kšœ!˜!Kšœ)˜)Kšœ)˜)Kšœ!˜!K˜Kšœœ˜%K˜K˜šΟnœœOœ˜ŠKšœ˜ Kšœœ˜Kšœœ"˜>Kšœ˜K˜K˜—šžœœ˜ KšœΛ™ΛK™—˜šž œœΟc ˜JšœŸ$˜=Jšœ)˜)J˜J˜—šž œœ œ œ ˜4˜JšœŸ$˜=šœ œ˜Jšœœ œ œ ˜.Jšœ ˜ Jšœ˜Jšœ˜—JšœQ˜QJšœŸ˜$J˜—Jšœ Οi œ˜J˜˜J˜——šžœœ(Ÿœ4Ÿœ˜«Jš˜Jš œœœœŸ ˜jJšœDŸ˜VJšœ*Ÿ ˜4Jšœ˜J˜J˜—š ž œœ!Ÿœ.ŸœŸœ˜ΊJš˜šœœ˜Jšœœ˜#Jšœ!œ˜&JšœœŸ ˜&—Jšœ˜J˜J˜—š žœœ0Ÿœ=Ÿœ'Ÿœœ˜υJš˜J˜˜Jšœ:˜:JšœQ˜QJšœ˜J˜—šœ   œ˜JšœO˜OJ˜—Jšœ˜J˜J˜—šžœœœ˜9JšœŸ:˜@J˜šΟb œŸ˜Jšœ3œ˜8Jšœ%œ˜+J˜—Jšœ˜J˜J˜—šžœœœ˜'JšœŸ˜#J˜šœ‘œŸ˜;Jšœ!˜!JšœH˜HJ˜J˜J˜—Jšœ˜J˜J˜—šžœœœ˜AJš˜Jšœ ˜ J˜Jš‘œ˜#˜Jšœ+œŸ˜JJšœ)˜)J˜J˜Jšœ0œ˜5Jšœ0œ˜5JšœT˜TJšœ Ÿ˜ J˜—šœ   œ˜JšœŸ!˜0Jšœ Ÿ4˜=J˜—šœ Ÿ˜5Jšœ$˜$JšœQ˜QJšœ Ÿ˜&J˜—šœ   œ˜Jšœ˜JšœQ˜QJšœ Ÿ˜—J˜šœ   œ˜Jšœ+œ˜0Jšœ)˜)Jšœ2˜2J˜Jšœ ˜ J˜—Jšœ˜J˜J˜—šž œœœ˜-Jš˜J˜Jš‘œ˜˜Jšœ*œ˜@Jšœ3œ˜8Jšœ˜Jšœ*œ˜2Kšœ˜Kšœ3œ˜8Jšœ%œ˜+J˜—Jšœ˜J˜J˜—šž œœœ‘œ˜-JšœŸ;˜AJ˜J˜š‘œ˜JšœQ˜QJšœ Ÿ˜%J˜—šœ   œ˜Jšœ˜Jšœ+œ˜0Jšœ)˜)Jšœ%œ˜+J˜—Jšœ˜J˜J˜—šž œœœ‘œ˜-Jš˜J˜J˜š‘œ˜JšœQ˜QJšœ Ÿ˜%J˜—šœ   œ˜Jšœ˜Jšœ3œ˜8šœ3œ˜9Jšœ2™2—Jšœ+œ˜0Jšœ)˜)Jšœ%œ˜+J˜—Jšœ˜J˜J˜—šžœœœ‘œ˜7JšœŸi˜oJšœ˜J˜"J˜š‘ œ˜JšœQ˜QJšœ Ÿ˜%J˜—šœ   œ˜Jšœ+œ˜0Jšœ)˜)—J˜šœ+˜+Jšœ*Ÿ˜>Jšœ.œŸ˜PJ˜Jšœ"˜"J˜JšœŸ2˜CJ˜J˜J˜2J˜"J˜6J˜J˜'J˜6Jšœ Ÿœ˜AJšœ Ÿ˜(Jšœ#Ÿ ˜CJ˜Jšœ7Ÿ˜NJšœ Ÿ$˜-Jšœ Ÿ˜JšœŸ˜*Jšœ Ÿ'˜2Jšœ+Ÿ,˜WJšœ˜J˜—J˜šœ ‘ œŸ˜5Jšœ Ÿ˜0Jšœ Ÿ˜1Jšœ Ÿ˜0Jšœ Ÿ˜0Jšœ Ÿ˜1Jšœ Ÿ˜1Jšœ Ÿ˜1Jšœ Ÿ˜1—Jšœ˜J˜J˜—šž œœœ‘œ˜3JšœŸ†˜ŒJšœ%˜%J˜š‘ œ˜JšœQ˜QJšœ Ÿ˜&J˜—šœ   œ˜Jšœ+œ˜0Jšœ)˜)J˜Jšœ Ÿ'˜0Jšœ˜Jšœ˜Jšœ˜J˜—J˜šœ,Ÿ˜?Jšœ*Ÿ˜>J˜Jšœ"˜"J˜Jšœ˜Jšœ Ÿ%˜2Jšœ+˜+JšœŸ.˜?Jšœ3˜3Jšœ3œ˜8Jšœ˜Jšœ˜šœ3œ˜8J™4—Jšœ˜J˜—šœ˜Jšœ3œ˜8Jšœ*œ˜@J˜Jšœ˜Jšœ*œ˜2Jšœ˜Jšœ%œ˜+J˜—šœ   œ˜Jšœ+Ÿ˜HJšœ Ÿ ˜Jšœ Ÿ%˜2JšœŸ-˜EJ˜—šœ˜J˜—J˜J˜—šžœœœ˜5Jš˜Jš‘ œ˜J˜šœ‘ œ ˜,Jšœ˜—Jšœ˜J˜J˜—šžœœ0œ˜EJš˜Jšœœœ˜%Jšœ œœ˜)J˜7JšœŸ˜1JšœŸ˜/J˜Jšœ˜J˜J˜—šžœœ,˜9Jš˜Jšœœœ˜%J˜1JšœŸ˜/JšœŸ˜/J˜Jšœ˜J˜J˜—Jšœ™J˜J˜Jšœœ˜ J˜J˜J˜J˜*J˜J˜J˜2J˜(Jšœ$˜$Jšœ˜J˜J˜&J˜J˜J˜J˜J˜J˜=J˜&J˜3J˜J˜Jšœ'˜'Jšœ˜Jšœ˜Jšœ*˜*J˜J˜Jšœ˜Jšœ˜Jšœ&˜&Jšœ˜J˜šœœ˜3Jšœœ œ œ ˜EJšœ˜—J˜šœ™™šœœ!˜>J™J˜ Jšœ˜J˜——šœ ‘œ˜J˜—šœ ‘œ˜Jšœœ œ˜9Jšœœ!œ˜:šœ˜J™_—J˜—J˜—šœ™J™šœ ‘œŸ*˜;™1J™*—Jšœ*Ÿ˜8J˜J˜)J˜+Jšœ˜Jšœ1œ˜PJšœ Ÿ ˜+J˜(—J˜—šœ<™<™J˜%J˜——šœ™™J˜J˜——šœ:™:™Jšœ*Ÿ˜8J˜Jšœ+Ÿ˜@J˜J˜Jšœ,Ÿ˜>J˜Jšœ*Ÿ˜DJ˜:Jšœ Ÿ˜ J˜—Jšœ   œ˜J˜—šœ8™8™Jšœ-Ÿ ˜9J˜Jšœ,Ÿ˜AJ˜Jšœ-Ÿ ˜9J˜J˜Jšœ+˜+J˜Jšœ*Ÿ˜DJšœ:˜:Jšœ Ÿ˜J˜—šœ   œ˜J˜——™"™Jšœ ˜ JšœO˜OJšœ˜Jšœ ˜ —J˜š  œ˜Jšœ˜Jšœ ˜ J˜—šœ   œ˜JšœC˜CJšœN˜NJšœ˜Jšœ ˜ J˜—š  œ˜Jšœ˜Jšœ ˜ J˜—šœ   œ˜JšœB˜BJ˜J˜J˜J˜——™™J˜%J˜J˜3JšœT˜TJšœ Ÿ˜"J˜—šœ   œ˜Jšœ Ÿ˜#J˜——™™Jšœ*˜*J˜Jšœ*˜*J˜—šœ   œ˜Jšœ ˜ Jšœ,œŸ˜@Jšœ3˜3Jšœ7Ÿ˜NJ˜J˜—šœœ˜Jšœ˜J˜—Jšœ˜šœ œ ˜J˜šœ   œ˜Jšœ*˜*Jšœ˜J˜—šœ˜J˜——šœ   œ˜Jšœ Ÿ ˜J˜J˜—šœ   œ˜JšœŸ(˜GJ˜—š  œ˜Jšœ&Ÿ'˜MJ˜JšœP˜PJšœ˜J˜Jšœ%œ˜+J˜—šœ   œ˜J˜Jšœ˜J˜ Jšœ1˜1Jšœ;™;Jšœ Ÿ™&J˜—šœ   œ™Jšœ%œ˜+J˜—Jšœ   œ˜J˜—šœ™™Jšœœ˜Jšœ œŸ˜0J˜J˜Jšœ ŸA˜JJšœ˜J˜Jšœ œŸ˜2JšœœŸ˜JJ˜JšœT˜TJ˜ J˜—Jšœ   œ˜J˜—šœ™™Jšœ ˜ Jšœ Ÿ,˜9Jšœ*˜*J˜—š  œŸA˜]Jšœ&œœ˜PJšœ3œ˜8Jšœ˜Jšœ&œœ˜BKšœ˜Kšœ3œ˜8Jšœ%œ˜+J˜—šœ   œ˜Jšœ  œ˜J™——™3™Jšœ Ÿ+˜5šœ˜Jšœ;™;—J˜ Jšœ˜Jšœ Ÿ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ2œ˜7Jšœ˜J˜'Jšœ˜Jšœ Ÿ/˜8Jšœ˜Jšœ)˜)J˜Jšœ*˜*J˜J™——šœ ™ ™JšœŸ˜J˜J˜——J™/˜J˜Jšœ:œœ#˜€J˜šœ ‘œ˜Jšœ&Ÿ ˜1—J˜šœ ‘œ˜)Jšœ5œŸ˜SJšœ ˜ Jšœ ˜ Jšœ!Ÿ˜