DIRECTORY Basics USING [DoubleShiftLeft], DebuggerDefs, DragOpsCross USING [ProcessorRegister, XopBase, TrapBase, TrapWidthBytes, TrapIndex, Inst], --Word, wordsPerPage, bytesPerWord, charsPerWord, bitsPerByte, bitsPerCharacter, bitsPerWord, bytesPerPage, logWordsPerPage, logBitsPerByte, logBitsPerChar, logBytesPerWord, logCharsPerWord, logBitsPerWord, logBytesPerPage, PageCount, PageNumber, maxPagesInVM, SixBitIndex, FiveBitIndex, TwoWords, FourBitIndex, Half, ThreeBitIndex, FourHalves, TwoHalves, Byte, ZerosByte, OnesByte, EightBytes, FourBytes, ByteIndex, BytesPerWord, TwoBytes, Comparison, ByteAddress, WordAddress, FieldDescriptor, RegIndex, PadByte, Lit8, Op4, Op8, JDist8, Inst, OIFormat, OQBformat, LRformat, QRformat, ShortRegQR, OBformat, LRBformat, RRformat, ODBformat, LRRBformat, RJBformat, ShortRegRJB, JBBformat, TrapWidthWords, TrapWidthBytes, XopBase, TrapBase, KernalLimit, TrapIndex, StackUnderflowTrap, IFUPageFaultTrap, ResetTrap, IFUStackOverflowTrap, EUStackOverflowTrap, RescheduleTrap, ALUCondFalse, ALUCondEZ, ALUCondLZ, ALUCondLE, ALUCondSpare, ALUCondNE, ALUCondGE, ALUCondGZ, ALUCondOver, ALUCondBC, ALUCondIL, ALUCondDO, ALUCondNotOver, ALUCondNB, ALUCondNI, ModeFault, MemAccessFault, IOAccessFault, EUPageFault, EUWriteFault, AUFault, euStack, euJunk, euToKBus, euMAR, euField, euConstant, euAux, euBogus, euLast, ifuYoungestL, ifuYoungestPC, ifuEldestL, ifuEldestPC, ifuSLimit, ifuBogus, ifuL, ifuS, ifuPC, ifuLast, EURegs, EULegalRegs, IFURegs, IFULegalRegs, StackedStatusWord, IFUStackIndex, IFUStackSize, IFUOverflow, EUStackIndex, EUStackSize, EULocalIndex, EULocals, EUAuxIndex, EUAuxRegs, EUConstIndex, EUConstants, IOLocation, ioRescheduleRequest, ioResetRequest, IOOperand, PCmdFormat, PCmdByteSelect, PCmdClass, PCmdSpace, PCmdDirection DragOpsCrossUtils USING [CardToWord, FieldDescriptorToCard, IntToWord, CardToByte], --InstToBytes, InstToFormat, BytePCToWordAddress, WordAddressToBytePC, IOOperandToCard, CardToIOOperand, FieldDescriptorToCard, CardToFieldDescriptor, BytesToWord, BytesToHalf, WordToBytes, HalfToBytes, HalvesToWord, WordToHalves, HighHalf, LowHalf, LeftHalf, RightHalf, SwapHalves, WordToInt, IntToWord, WordToCard, HalfToCard, ByteToCard, CardToWord, CardToHalf, CardToByte, DragAnd, DragOr, DragXor, DragNot, VanillaAdd, VanillaSub, AddDelta, HalfNot, HalfAnd, HalfOr, HalfXor, HalfShift, DoubleWordShiftLeft, SingleWordShiftLeft, SingleWordShiftRight, XopToBytePC, TrapIndexToBytePC, FieldUnit HandCoding, --Has opcode and register defs. HandCodingPseudos, --Label, SetLabel, GenLabel, GenLabelHere, UseLabel8A, UseLabel8B, UseLabel16, UseLabel32, LReg, PReg, SReg, AddReg, SubReg, SetRegConst, MoveReg, MoveRegI, LRegI, IndexedJump, ProcedureEntry, ProcedureExit, SetupField, ExtractField, ShiftLeft, LoadProcessorReg, StoreProcessorReg, CauseReschedule, CauseReset, GetSPLimit, SetSPLimit, GetYoungestPC, GetYoungestStatus, GetEldestPC, GetEldestStatus, SetYoungestPC, SetYoungestStatus, SetEldestPC, SetEldestStatus, Pause, Halt HandCodingSupport; --Area, GetProc, PutProc, ProcList, NewArea, GenWithArea, Gen1WithArea, ForceOut, GetCurrentArea, LoadArea, GetOutputPC, SetOutputPC, WordAlign, ReserveData, OutputByte, OutputOneByte, OutputAlphaBeta, OutputAlphaBetaGammaDelta, OutputWord GenTraps: CEDAR PROGRAM IMPORTS Basics, DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport = BEGIN OPEN DebuggerDefs, DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport; ProcessorRegister: TYPE = DragOpsCross.ProcessorRegister; ifuSLimit: CARDINAL = LOOPHOLE[ProcessorRegister.ifuSLimit, CARDINAL]; ifuEldestPC: CARDINAL = LOOPHOLE[ProcessorRegister.ifuEldestPC, CARDINAL]; ifuEldestL: CARDINAL = LOOPHOLE[ProcessorRegister.ifuEldestL, CARDINAL]; ifuYoungestPC: CARDINAL = LOOPHOLE[ProcessorRegister.ifuYoungestPC, CARDINAL]; ifuYoungestL: CARDINAL = LOOPHOLE[ProcessorRegister.ifuYoungestL, CARDINAL]; euMAR: CARDINAL = LOOPHOLE[ProcessorRegister.euMAR, CARDINAL]; aux0: AuxRegSpec = [aux[0]]; aux1: AuxRegSpec = [aux[1]]; aux2: AuxRegSpec = [aux[2]]; aux3: AuxRegSpec = [aux[3]]; aux4: AuxRegSpec = [aux[4]]; aux5: AuxRegSpec = [aux[5]]; aux6: AuxRegSpec = [aux[6]]; aux13: AuxRegSpec = [aux[13]]; aux14: AuxRegSpec = [aux[14]]; aux15: AuxRegSpec = [aux[15]]; const5: ConstSpec = [const[5]]; const6: ConstSpec = [const[6]]; const7: ConstSpec = [const[7]]; const8: ConstSpec = [const[8]]; const9: ConstSpec = [const[9]]; const10: ConstSpec = [const[10]]; const11: ConstSpec = [const[11]]; All: PROC = { area: Area = GetCurrentArea[]; IFUStackOverflow: Label = GenLabel[]; Overflow: Label = GenLabel[]; BoundsCheck: Label = GenLabel[]; LispNaN: Label = GenLabel[]; UserModeViolation: Label = GenLabel[]; EUPageFlt: Label = GenLabel[]; EUPageFaultBad: Label = GenLabel[]; EUWPFlt: Label = GenLabel[]; EUWPFaultBad: Label = GenLabel[]; IFUPageFault: Label = GenLabel[]; IFUPageFaultBad: Label = GenLabel[]; IFUPageFaultPC: LONG CARDINAL = 300000000B; EUPageFaultAddress: LONG CARDINAL = IFUPageFaultPC/4; EUStackOverflow: Label = GenLabel[]; Reschedule: Label = GenLabel[]; RescheduleBad: Label = GenLabel[]; KFCTrap: Label = GenLabel[]; KFCBad: Label = GenLabel[]; Xop1Trap: Label = GenLabel[]; Xop1Bad: Label = GenLabel[]; Xop2Trap: Label = GenLabel[]; Xop2Bug: Label = GenLabel[]; Xop3Trap: Label = GenLabel[]; Xop3Bug: Label = GenLabel[]; Xop5Trap: Label = GenLabel[]; Xop5Bug: Label = GenLabel[]; ErrorXop1Trap: Label = GenLabel[]; AlreadyInKernel: Label = GenLabel[]; TurnOnTraps: Label = GenLabel[]; TurnOffTraps: Label = GenLabel[]; TurnOnUserMode: Label = GenLabel[]; enterIFUStatusTest: Label = GenLabel[]; enterIFUStackOverflowTest: Label = GenLabel[]; enterSLimitTest: Label = GenLabel[]; enterIFUPageFaultTest: Label = GenLabel[]; enterEUPageFaultTest: Label = GenLabel[]; enterModeFaultPriorityTest: Label = GenLabel[]; userMemAddr: LONG CARDINAL = IF withSoftCard THEN 1770000B ELSE 100000000B; kernelMemAddr: LONG CARDINAL = IF withSoftCard THEN 17760000B ELSE 77777777B; FillXop: PROC [inst: CARDINAL, dest: Label] = { SetOutputPC[inst * DragOpsCross.TrapWidthBytes + DragOpsCross.XopBase * bytesPerWord]; drJDB[UseLabel16[dest]]; }; FillTrap: PROC [tx: DragOpsCross.TrapIndex, dest: Label] = { SetOutputPC[LOOPHOLE[tx, CARDINAL] * DragOpsCross.TrapWidthBytes + DragOpsCross.TrapBase * bytesPerWord]; drJDB[UseLabel16[dest]]; }; EnableTraps: PROC [] = { drDFC[UseLabel32[TurnOnTraps]]; }; DisableTraps: PROC [] = { drDFC[UseLabel32[TurnOffTraps]]; }; EnterUser: PROC [] = { drDFC[UseLabel32[TurnOnUserMode]]; }; EnterKernel: PROC [] = { drLIB[12]; drROR[aux8, popSrc, topSrc]; drKFC[]; drROR[aux8, const0, const0]; }; StandardTrap: PROC [dest: Label, code: CARDINAL] = { TrapUnexpected: Label = GenLabel[]; SetLabel[dest]; drLIB[code]; drRJNEB[popSrc, aux8, UseLabel8B[TrapUnexpected]]; GetYoungestPC[]; drRVADD[topDst, const4, topSrc]; SetYoungestPC[]; drRETN[]; SetLabel[TrapUnexpected]; Pause[]; }; WriteAtAddress: PROC [addr: LONG CARDINAL] ~ { oldPC: LONG CARDINAL = GetOutputPC[area]; bytePC: LONG CARDINAL _ Basics.DoubleShiftLeft[[lc[addr]], 2].lc; SetOutputPC[bytePC]; --pc is a byte address OutputWord[area, IntToWord[-1], FALSE]; SetOutputPC[oldPC]; drLC0[]; drLIQB[CardToWord[addr]]; drWB[0]; }; WriteTrapAtAddress: PROC [addr: LONG CARDINAL] ~ { WriteAtAddress[addr]; XPause[]; XPause[]; XPause[]; XPause[]; }; GenIFUStatus: PROC [] ~ { UCall1: Label = GenLabel[]; UCall2: Label = GenLabel[]; UJump1: Label = GenLabel[]; JQBNop0: Label = GenLabel[]; JSDNop0: Label = GenLabel[]; BeginUserTest: Label = GenLabel[]; CheckTrapEnable: Label = GenLabel[]; CheckTrapDisable: Label = GenLabel[]; CheckUserMode: Label = GenLabel[]; BadEnable: Label = GenLabel[]; SetLabel[enterIFUStatusTest]; drLIQB[CardToWord[userMemAddr]]; drROR[aux0, topSrc, popSrc]; drJDB[UseLabel16[BeginUserTest]]; --inst 50 SetLabel[CheckTrapEnable]; GetYoungestStatus[]; drLIQB[CardToWord[200000B]]; drOR[]; drDUP[]; SetYoungestStatus[]; --Set trapsEnabled drLIP[ifuYoungestL]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[BadEnable]]; drRETN[]; SetLabel[BadEnable]; XPause[]; SetLabel[CheckTrapDisable]; GetYoungestStatus[]; drLIQB[CardToWord[37777577777B]]; drAND[]; drDUP[]; SetYoungestStatus[]; --Set trapsEnabled drLIP[ifuYoungestL]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[BadEnable]]; drRETN[]; SetLabel[CheckUserMode]; GetYoungestStatus[]; drLIQB[CardToWord[400000B]]; drOR[]; drDUP[]; SetYoungestStatus[]; --Set trapsEnabled drLIP[ifuYoungestL]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[BadEnable]]; drRETN[]; SetLabel[BeginUserTest]; drLFC[UseLabel16[CheckTrapEnable]]; drLFC[UseLabel16[CheckTrapDisable]]; drLFC[UseLabel16[CheckUserMode]]; drROR[aux9, aux0, aux1]; drROR[aux9, aux2, aux3]; drROR[aux10, aux4, aux5]; drROR[aux11, aux6, aux7]; drROR[aux12, aux8, aux9]; drROR[aux13, aux10, aux11]; drROR[aux14, aux12, aux13]; drROR[aux15, aux14, aux14]; drROR[aux15, aux15, aux15]; drROR[pushDst, const0, const1]; --1st push drROR[topDst, const2, const3]; drROR[pushDst, const4, const5]; --2nd push drROR[belowDst, const6, const7]; drROR[topDst, const8, const9]; drROR[topDst, const10, const11]; drLIP[0]; --3rd push drLIP[127]; --4th push drLIP[159]; --5th push drLFC[3]; drLIP[ifuYoungestL]; --6th push drLIP[ifuYoungestPC]; --7th push drLIP[ifuEldestL]; --8th push drLIP[ifuSLimit]; --9th push drASL[377B]; --0 pushes on the EU stack, 1 call on the IFU stack WriteAtAddress[userMemAddr]; --drLIQB[CardToWord[userMemAddr]]; drIODA[2B]; drASL[377B]; --0 pushes again drLC0[]; drDUP[]; drADD[]; --1st push = reg0 drLC1[]; --2 pushes drLIDB[0]; drLIQB[CardToWord[0]]; --4 pushes drLRn[reg11]; --5 pushes drQADD[topAtop, const0]; drRADD[belowDst, topSrc, belowSrcPop]; --4 pushes drSUB[]; --3 pushes drQSUB[topAtop, const0]; drRSUB[belowDst, popSrc, belowSrc]; --2 pushes drQLADD[topAtop, const0]; drRLADD[belowDst, popSrc, const0]; --1 push drQLSUB[topAtop, const0]; --1 push drRLSUB[pushDst, popSrc, const0]; drRUADD[belowDst, const0, popSrc]; --0 pushes drRUSUB[pushDst, const0, const0]; --1 push drRVADD[pushDst, const0, topSrc]; --2 pushes drRVSUB[topDst, topSrc, const0]; drAND[]; --1 push drQAND[pushAtop, const0]; --2 pushes drRAND[topDst, topSrc, topSrc]; drOR[]; --1 push drQOR[pushAtop, const0]; --2 pushes drADDB[0]; drSUBB[0]; drADDDB[0]; drSUBDB[0]; drADDQB[CardToWord[0]]; drSUBQB[CardToWord[0]]; drRXOR[topDst, topSrc, topSrc]; drRAND[topDst, topSrc, const0]; --Zero [S] drFSDB[FieldDescriptorToCard[[mask: 6, shift: 20]]]; --1 push drRFU[pushDst, topSrc, topSrc]; --2 pushes drSHDL[FieldDescriptorToCard[[mask: 32, shift: 0]]]; --1 push drSHL[FieldDescriptorToCard[[mask: 0, shift: 32]]]; --1 push drSHR[FieldDescriptorToCard[[mask: 16, shift: 16]]]; --1 push drJ1[]; drJ2[]; XPause[]; drJ3[]; XPause[]; XPause[]; drJ5[]; XPause[]; XPause[]; XPause[]; XPause[]; drJDB[3]; drJQB[UseLabel32[JQBNop0]]; SetLabel[JQBNop0]; drLIQB[UseLabel32[JSDNop0]]; drJSD[]; SetLabel[JSDNop0]; drEXDIS[]; --0 pushes drLIDB[0]; --1 push drASL[377B]; --0 pushes, 0 locals (S _ 0B, L = 1B) drAL[0]; drLIQB[CardToWord[userMemAddr]]; --legal address already used, 1 push FOR I: CARDINAL IN [0..17) DO drDUP[]; ENDLOOP; drSRn[reg0]; --Now have L = 1B, S = 21B (= 16 locals, 1 push) drLRIn[reg0, 0]; drSRIn[reg0, 0]; drDUP[]; drJEBB[0, 3]; drDUP[]; drJNEBB[0, 3]; drDUP[]; drJNEBBJ[0, 3]; drRJEB[topSrc, topSrc, 3]; drRJEBJ[topSrc, topSrc, 3]; drRJGB[topSrc, topSrc, 3]; drRJGBJ[topSrc, topSrc, 3]; drRJLB[topSrc, topSrc, 3]; drRJLBJ[topSrc, topSrc, 3]; drRJGEB[topSrc, topSrc, 3]; drRJGEBJ[topSrc, topSrc, 3]; drRJLEB[topSrc, topSrc, 3]; drRJLEBJ[topSrc, topSrc, 3]; drRJNEB[topSrc, topSrc, 3]; drRJNEBJ[topSrc, topSrc, 3]; --Still have 1 push (L = 1B, S = 21B) drLIQB[CardToWord[userMemAddr - 1]]; --2 pushes drRBC[topDst, topSrc, belowSrc]; --won't trap drQBC[topAtop, belowSrc]; --won't trap drDIS[]; drLIQB[CardToWord[userMemAddr + 1]]; drBC[]; --1 push drDUP[]; --2 pushes drLC0[]; drRX[]; drDIS[]; --1 push drQRX[pushAtop, const0]; drDIS[]; drLGF[0]; drDIS[]; --(aux0 was initialized to userMemAddr above) drRAI[reg1, aux0, 0]; drDUP[]; drRB[0]; drDIS[]; drRRI[reg1, reg13, 0]; --(reg0 .. reg15 were set to userMemAddr above) drRRX[reg1, reg13, const0]; drRSB[0]; drDIS[]; drWAI[reg1, aux0, 0]; drWRI[reg1, reg13, 0]; drLC0[]; drWSB[0]; --Still have 1 push IF NOT withSoftCard THEN { drLIB[1]; drLC0[]; drCST[0]; }; drASL[377B]; --0 pushes drLIB[1]; drJSR[]; drDFC[UseLabel32[UCall1]]; drLFC[UseLabel16[UCall2]]; drLIB[13]; drROR[aux8, topSrc, popSrc]; --Indicate XOP1 trap expected OutputByte[area, CardToByte[1B]]; drLIB[14]; drROR[aux8, topSrc, popSrc]; --Indicate XOP2 trap expected OutputAlphaBeta[area, (234B * 400B) + 123B]; drLIB[15]; drROR[aux8, topSrc, popSrc]; --Indicate XOP3 trap expected OutputByte[area, CardToByte[364B]]; OutputAlphaBeta[area, 234B]; drLIB[16]; drROR[aux8, topSrc, popSrc]; --Indicate XOP5 trap expected OutputByte[area, CardToByte[40B]]; OutputWord[area, CardToWord[345B]]; EnterKernel[]; --KFC trap returns in Kernel mode with traps disabled. EnterUser[]; --Enter user mode and enable traps drLIQB[CardToWord[userMemAddr]]; --1 push drLIQB[UseLabel32[UCall1]]; --2 pushes drPSB[0]; --1 push drAS[1]; --2 pushes drSFC[]; --1 push drSFCI[]; drJB[UseLabel8A[UJump1]]; SetLabel[UCall1]; drRETN[]; SetLabel[UCall2]; drALS[377B]; --L _ S-1 drRET[1B]; --S _ L+1 SetLabel[UJump1]; drASL[17B]; --16 local registers, 0 EU pushes, 1 call on the IFU stack drLIB[8]; --1 push drROR[aux8, topSrc, topSrc]; --Indicate mode fault trap expected (aux8 = 8) drROR[aux0, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[aux1, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[aux2, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[aux3, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[aux4, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[aux5, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[aux6, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[aux7, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const0, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const1, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const2, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const3, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const4, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const5, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const6, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const7, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const8, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const9, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const10, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drROR[const11, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; drSIP[0]; XPause[]; XPause[]; XPause[]; XPause[]; drSIP[242]; XPause[]; XPause[]; XPause[]; XPause[]; drSIP[246]; XPause[]; XPause[]; XPause[]; XPause[]; drLIP[ifuEldestPC]; XPause[]; XPause[]; XPause[]; XPause[]; drDIS[]; --16 locals, 1 push, 2 calls on the IFU stack --drIOD[4B]; XPause[]; XPause[]; XPause[]; --drION[4B]; XPause[]; XPause[]; XPause[]; --drIODA[4B]; XPause[]; XPause[]; XPause[]; --WriteTrapAtAddress[kernelMemAddr]; drASL[17B]; --16 locals, 0 pushes on the EU stack, 2 calls on the IFU stack, user mode EnterKernel[]; --Use KFC to enter kernel mode and return with traps disabled. FOR I: CARDINAL IN [0..0] DO GetEldestPC[]; ENDLOOP; }; GenIFUStackOverflow: PROC [] ~ { UCall3: Label = GenLabel[]; JQBNop1: Label = GenLabel[]; JSDNop1: Label = GenLabel[]; exitIFUStackOverflowTest: Label = GenLabel[]; eleventhCall: Label = GenLabel[]; drJB[UseLabel8A[enterIFUStackOverflowTest]]; SetLabel[UCall3]; XPause[]; --DFC, SFC, or SFCI trap was expected but didn't. SetLabel[enterIFUStackOverflowTest]; drASL[377B]; --0 locals, 0 pushes on the EU stack, 0 calls on the IFU stack EnableTraps[]; drLFC[3]; --1 calls drLFC[3]; --2 calls drLFC[3]; --3 calls drLFC[3]; --4 calls drLFC[3]; --5 calls drLFC[3]; --6 calls drLFC[3]; --7 calls drLFC[3]; --8 calls drLFC[3]; --9 calls drLFC[3]; --10 calls drLFC[4]; --11 calls XPause[]; drJ1[]; drJ2[]; XPause[]; drJ3[]; XPause[]; XPause[]; drJ5[]; XPause[]; XPause[]; XPause[]; XPause[]; drJB[2]; drJDB[3]; drJQB[UseLabel32[JQBNop1]]; XPause[]; SetLabel[JQBNop1]; drLIQB[UseLabel32[JSDNop1]]; drJSD[]; XPause[]; SetLabel[JSDNop1]; drLIB[1]; drJSR[]; drLIB[2]; drLIB[1]; drQBC[pushAtop, belowSrc]; drDIS[]; drRBC[pushDst, reg1, reg0]; drDIS[]; drEXDIS[]; drLIB[2]; drBC[]; drLIB[1]; drROR[aux8, popSrc, topSrc]; --Indicate IFU stack overflow expected drLFC[3]; XPause[]; XPause[]; XPause[]; drDFC[UseLabel32[UCall3]]; XPause[]; drLIQB[UseLabel32[UCall3]]; drSFC[]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; OutputByte[area, CardToByte[1B]]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; OutputAlphaBeta[area, (234B * 400B) + 123B]; XPause[]; XPause[]; XPause[]; XPause[]; OutputByte[area, CardToByte[364B]]; OutputAlphaBeta[area, 234B]; XPause[]; XPause[]; XPause[]; OutputByte[area, CardToByte[40B]]; OutputWord[area, CardToWord[345B]]; XPause[]; drKFC[]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drLIB[1]; drLIB[2]; drQBC[pushAtop, belowSrc]; XPause[]; XPause[]; XPause[]; XPause[]; drRBC[pushDst, topSrc, belowSrc]; XPause[]; XPause[]; XPause[]; drEXDIS[]; drLIB[1]; drBC[]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drLIQB[CardToWord[10000000000B]]; drDUP[]; drLADD[]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drADD[]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drLIQB[CardToWord[EUPageFaultAddress]]; drROR[aux9, topSrc, topSrc]; drRB[0]; XPause[]; XPause[]; XPause[]; XPause[]; drASL[17B]; --L = 1, S = 20B drLIB[21B]; drSIP[ifuSLimit]; drDUP[]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drDIS[]; drLIB[160B]; drSIP[ifuSLimit]; drROR[aux8, const0, const0]; --Indicate no traps expected GetEldestPC[]; --Clear 1 call to enter user mode EnterUser[]; drLFC[UseLabel16[eleventhCall]]; --11 calls again drJDB[UseLabel16[exitIFUStackOverflowTest]]; --10 calls SetLabel[eleventhCall]; drLIB[1]; drROR[aux8, topSrc, popSrc]; --Indicate IFU stack overflow expected drRADD[const1, const0, const0]; XPause[]; XPause[]; XPause[]; --****drLC0[]; drWB[0]; XPause[]; XPause[]; XPause[]; XPause[]; drROR[aux8, const0, const0]; --Indicate no traps expected drRET[377B]; --returns from 11th call and trims stack SetLabel[exitIFUStackOverflowTest]; EnterKernel[]; FOR I: CARDINAL IN [0..9] DO GetEldestPC[]; ENDLOOP; drASL[17B]; --L = 1, S = 20B, traps enabled, Kernel mode, 0 calls on the stack }; GenSLimit: PROC [] ~ { SLimitTest: PROC [SL: CARDINAL] ~ { drLIB[SL]; drSIP[ifuSLimit]; drROR[aux8, aux15, aux15]; drASL[SL]; XPause[]; XPause[]; XPause[]; XPause[]; --SLimit drASL[SL + 15]; XPause[]; XPause[]; XPause[]; XPause[]; --SLimit + 15 drROR[aux8, const0, const0]; drASL[SL + 16]; --SLimit + 16 drASL[SL - 1]; --SLimit - 1 drASL[0]; --SLimit }; SetLabel[enterSLimitTest]; drASL[7B]; --L = 1, S = 10B, traps enabled, Kernel mode, 0 calls on the stack EnableTraps[]; drLIB[13B]; drSIP[ifuSLimit]; drLIQB[CardToWord[userMemAddr]]; drSRn[reg0]; --Memory address for LRIn below drLC0[]; --S = 11B drLIB[9]; drROR[aux8, topSrc, topSrc]; --aux8 _ EU stk ovf trap expected drROR[aux15, topSrc, popSrc]; --aux15 _ EU stk ovf trap expected for SLimitTests below drDUP[]; --S = 12B drLFC[4]; XPause[]; drDUP[]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drLRn[reg2]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drQADD[pushA0, const0]; XPause[]; XPause[]; XPause[]; XPause[]; drRADD[pushDst, const0, const0]; XPause[]; XPause[]; XPause[]; drLRIn[reg0, 0]; XPause[]; XPause[]; XPause[]; XPause[]; FOR I: CARDINAL IN [1..16] DO drAS[I]; XPause[]; XPause[]; XPause[]; XPause[]; drASL[11B + I]; XPause[]; XPause[]; XPause[]; XPause[]; drRET[11B + I]; XPause[]; XPause[]; XPause[]; XPause[]; ENDLOOP; drASL[377B]; --S = 0, L = 1 (won't trap) drLIB[160B]; drSIP[ifuSLimit]; --S in [160B..177B] will trap drLIP[ifuEldestPC]; drDIS[]; --clear the call stack drSRn[reg15]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drQAND[topAtop, popSrc]; XPause[]; XPause[]; XPause[]; XPause[]; drRAND[belowDst, topSrc, popSrc]; XPause[]; XPause[]; XPause[]; drSRIn[reg0, 0]; XPause[]; XPause[]; XPause[]; XPause[]; drDIS[]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drROR[aux8, const0, const0]; --Indicate no trap expected drAL[377B]; --L _ 0 SLimitTest[4B]; SLimitTest[10B]; SLimitTest[20B]; SLimitTest[1B]; drASL[377B]; SLimitTest[40B]; SLimitTest[100B]; SLimitTest[2B]; SLimitTest[157B]; drLIB[21B]; drSIP[ifuSLimit]; drAL[1B]; --L = 1 again drASL[15B]; --S = 16B drLIB[6]; drROR[aux8, topSrc, popSrc]; --Bounds check should prevail drLIB[1]; drLIB[2]; --S = 20B (1 less than SLimit) drQBC[pushAtop, belowSrc]; XPause[]; XPause[]; XPause[]; XPause[]; drRBC[pushDst, topSrc, belowSrc]; XPause[]; XPause[]; XPause[]; drAS[376B]; drLIB[7]; drROR[aux8, topSrc, popSrc]; --NaN prevails drLIQB[CardToWord[10000000000B]]; drDUP[]; --S = 20B (1 less than SLimit) drRLADD[pushDst, topSrc, belowSrc]; XPause[]; XPause[]; XPause[]; drDIS[]; drLIB[5]; drROR[aux8, topSrc, popSrc]; --Overflow prevails drDUP[]; --S = 20B (1 less than SLimit) drRADD[pushDst, topSrc, belowSrc]; XPause[]; XPause[]; XPause[]; --drAS[376B]; EnterUser[]; drDUP[]; --drLIB[4]; drROR[aux8, topSrc, popSrc]; --drLC0[]; drWB[0]; XPause[]; XPause[]; XPause[]; XPause[]; drASL[377B]; --S = 0, L = 1 (won't trap) drLIB[160B]; drSIP[ifuSLimit]; --S in [160B..177B] will trap drLIB[8]; drROR[aux8, topSrc, topSrc]; --Indicate ModeFault expected EnterUser[]; drRADD[const1, popSrc, topSrc]; XPause[]; XPause[]; XPause[]; EnterKernel[]; --Enter Kernel mode and disable traps drASL[17B]; --L = 1, S = 20B, traps disabled, Kernel mode, 0 calls on the stack }; GenIFUPageFault: PROC [] ~ { oldPC: LONG CARDINAL; LFCFaultOK: Label = GenLabel[]; RETNFaultOK: Label = GenLabel[]; CJumpFOK0: Label = GenLabel[]; CJumpFOK1: Label = GenLabel[]; FallThruOK: Label = GenLabel[]; endIFUPFTest: Label = GenLabel[]; nearFaultPagePC0: LONG CARDINAL = 277777600B; nearFaultPagePC1: LONG CARDINAL = 310007600B; IFUPageFaultPC1: LONG CARDINAL = 310010000B; nearFaultPagePC2: LONG CARDINAL = 320007775B; --Must be page boundary - 3 SetLabel[enterIFUPageFaultTest]; drASL[377B]; --L = 1, S = 0 EnableTraps[]; drLIQB[CardToWord[nearFaultPagePC0]]; --location to which page fault trap returns drLIB[10]; drROR[aux8, popSrc, topSrc]; --IFU page fault expected drJQB[CardToWord[IFUPageFaultPC]]; --Will cause IFU page fault oldPC _ GetOutputPC[area]; SetOutputPC[nearFaultPagePC0]; drLIQB[UseLabel32[LFCFaultOK]]; drLFC[IFUPageFaultPC - GetOutputPC[area]]; --IFU page fault next SetLabel[LFCFaultOK]; drLIQB[CardToWord[IFUPageFaultPC]]; SetYoungestPC[]; drLIQB[UseLabel32[RETNFaultOK]]; drRETN[]; --Will cause IFU page fault SetLabel[RETNFaultOK]; drLIQB[UseLabel32[CJumpFOK0]]; drRJEB[const0, const0, IFUPageFaultPC - GetOutputPC[area]]; --IFU page fault next SetLabel[CJumpFOK0]; drLIQB[UseLabel32[CJumpFOK1]]; drRJEBJ[const0, const0, IFUPageFaultPC - GetOutputPC[area]]; --IFU page fault next SetLabel[CJumpFOK1]; drLIQB[UseLabel32[FallThruOK]]; drJB[IFUPageFaultPC - GetOutputPC[area] - 1]; SetOutputPC[IFUPageFaultPC - 1]; drJ1[]; --Next instruction causes IFU page fault SetOutputPC[nearFaultPagePC1]; SetLabel[FallThruOK]; drROR[aux8, const0, const0]; --Indicate no traps expected drRJNEB[const0, const0, IFUPageFaultPC1 - GetOutputPC[area]]; drRJNEBJ[const0, const0, IFUPageFaultPC1 - GetOutputPC[area]]; drJB[IFUPageFaultPC1 - GetOutputPC[area] - 3]; SetOutputPC[IFUPageFaultPC1 - 3]; drRJEB[const0, const0, 370B]; SetOutputPC[IFUPageFaultPC1 - 3 - 10B]; drJQB[CardToWord[nearFaultPagePC2]]; SetOutputPC[nearFaultPagePC2]; drRJEBJ[const0, const0, 370B]; SetOutputPC[nearFaultPagePC2 - 10B]; drJQB[CardToWord[oldPC]]; SetOutputPC[oldPC]; }; GenEUPageFault: PROC [] ~ { OKState: Label = GenLabel[]; BadState: Label = GenLabel[]; SetLabel[enterEUPageFaultTest]; drASL[377B]; --L = 1, S = 0 EnableTraps[]; drLIB[2]; drROR[aux8, popSrc, topSrc]; --EU page fault expected drLIB[21B]; drSIP[ifuSLimit]; drASL[16B]; --S = 17B drLIQB[CardToWord[EUPageFaultAddress]]; drROR[aux9, topSrc, topSrc]; drRB[0]; XPause[]; XPause[]; XPause[]; XPause[]; drASL[377B]; --L = 1, S = 0 drLIQB[CardToWord[EUPageFaultAddress]]; drRB[0]; XPause[]; XPause[]; XPause[]; XPause[]; drRJEBJ[topSrc, aux9, UseLabel8B[OKState]]; --Make sure RB[0] didn't smash [S] SetLabel[BadState]; XPause[]; SetLabel[OKState]; drLIB[123B]; drROR[aux10, popSrc, topSrc]; drRRX[aux10, popSrc, const0]; XPause[]; XPause[]; XPause[]; drLIB[123B]; drRJNEB[popSrc, aux10, UseLabel8B[BadState]]; drRJNEB[topSrc, aux9, UseLabel8B[BadState]]; drLIDB[123456B]; drWSB[0]; XPause[]; XPause[]; XPause[]; XPause[]; drLIDB[123456B]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[BadState]]; drRJNEB[topSrc, aux9, UseLabel8B[BadState]]; IF NOT withSoftCard THEN { drLIDB[111111B]; --new value drLIDB[122222B]; --old value drCST[0]; XPause[]; XPause[]; XPause[]; XPause[]; }; drLIDB[122222B]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[BadState]]; drDIS[]; drSFCI[]; XPause[]; XPause[]; XPause[]; XPause[]; XPause[]; drRJNEB[topSrc, aux9, UseLabel8B[BadState]]; --drIODA[2B]; XPause[]; XPause[]; XPause[]; --drRJNEB[popSrc, aux9, UseLabel8B[BadState]]; --drLIB[123B]; drROR[pushDst, aux9, const0]; --drIODA[3B]; --drRJNEB[popSrc, aux9, UseLabel8B[BadState]]; --drJNEBB[123B, UseLabel8B[BadState]]; }; GenModeFaultPriority: PROC [] ~ { SetLabel[enterModeFaultPriorityTest]; drASL[377B]; --L = 1, S = 0 drLIB[8]; drROR[aux8, topSrc, popSrc]; --code for ModeFault trap EnterUser[]; drLIQB[CardToWord[10000000000B]]; drDUP[]; drRLADD[const2, belowSrc, topSrc]; XPause[]; XPause[]; XPause[]; drRADD[const2, belowSrc, topSrc]; XPause[]; XPause[]; XPause[]; drRBC[const2, belowSrc, popSrc]; XPause[]; XPause[]; XPause[]; drDIS[]; drLC0[]; drLIQB[CardToWord[EUPageFaultAddress]]; drRRX[const2, popSrc, belowSrcPop]; XPause[]; XPause[]; XPause[]; EnterKernel[]; --Indicate KFC trap expected }; XPause: PROC = { HandCodingSupport.OutputByte[HandCodingSupport.GetCurrentArea[], LOOPHOLE[2]]; }; drLIB[128-16-1]; SetSPLimit[]; drROR[aux8, const0, const0]; --Initialize aux8 to 0, meaning no traps expected. drLIB[6]; drROR[const4, popSrc, topSrc]; --Initialize const4 to 6 for the trap routines. drLIB[1]; drROR[const5, topSrc, topSrc]; drROR[const6, topSrc, topSrc]; drROR[const7, topSrc, topSrc]; drROR[const8, topSrc, topSrc]; drROR[const9, topSrc, topSrc]; drROR[const10, topSrc, topSrc]; drROR[const11, topSrc, topSrc]; drROR[aux1, topSrc, topSrc]; drROR[aux2, topSrc, topSrc]; drROR[aux3, topSrc, topSrc]; drROR[aux4, topSrc, topSrc]; drROR[aux5, topSrc, topSrc]; drROR[aux6, topSrc, topSrc]; drROR[aux7, topSrc, topSrc]; drLC0[]; drSIP[0]; drLC0[]; drSIP[127]; drLC0[]; drSIP[159]; --aux 15, inst. 33 FOR I: CARDINAL IN [0..15) DO drLC0[]; ENDLOOP; GenIFUStatus[]; GenIFUStackOverflow[]; GenSLimit[]; GenIFUPageFault[]; GenEUPageFault[]; GenModeFaultPriority[]; Halt[177777B]; --Terminate here at the end of the program StandardTrap[IFUStackOverflow, 1]; --priority 2 StandardTrap[Overflow, 5]; StandardTrap[BoundsCheck, 6]; StandardTrap[LispNaN, 7]; StandardTrap[UserModeViolation, 8]; StandardTrap[EUStackOverflow, 9]; SetLabel[EUPageFlt]; drLIB[2]; drRJNEB[popSrc, aux8, UseLabel8B[EUPageFaultBad]]; drLIP[euMAR]; drRJNEB[popSrc, aux9, UseLabel8B[EUPageFaultBad]]; GetYoungestPC[]; drRVADD[topDst, topSrc, const4]; SetYoungestPC[]; drRETN[]; SetLabel[EUPageFaultBad]; Pause[]; SetLabel[EUWPFlt]; drLIB[3]; drRJNEB[popSrc, aux8, UseLabel8B[EUWPFaultBad]]; drLIQB[CardToWord[EUPageFaultAddress]]; drLIP[euMAR]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[EUWPFaultBad]]; GetYoungestPC[]; drRVADD[topDst, topSrc, const4]; SetYoungestPC[]; drRETN[]; SetLabel[EUWPFaultBad]; Pause[]; SetLabel[IFUPageFault]; drLIB[10]; drRJNEB[popSrc, aux8, UseLabel8B[IFUPageFaultBad]]; GetYoungestPC[]; drLIQB[CardToWord[IFUPageFaultPC]]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[IFUPageFaultBad]]; SetYoungestPC[]; drRETN[]; SetLabel[IFUPageFaultBad]; Pause[]; SetLabel[Reschedule]; --Arg is the return PC drLIB[11]; drRJNEB[popSrc, aux8, UseLabel8B[RescheduleBad]]; SetYoungestPC[]; drRETN[]; SetLabel[RescheduleBad]; Pause[]; SetLabel[KFCTrap]; drLIB[12]; drRJNEB[popSrc, aux8, UseLabel8B[KFCBad]]; drLIP[ifuYoungestL]; drLIB[377B]; drAND[]; drSIP[ifuYoungestL]; drRETN[]; --Return to caller remaining in Kernel mode with traps disabled. SetLabel[KFCBad]; Pause[]; SetLabel[Xop1Trap]; drLIB[13]; drRJNEB[popSrc, aux8, UseLabel8B[Xop1Bad]]; drRETN[]; --Return to caller remaining in Kernel mode. SetLabel[Xop1Bad]; XPause[]; SetLabel[Xop2Trap]; drLIB[14]; drRJNEB[popSrc, aux8, UseLabel8B[Xop2Bug]]; drJNEBB[123B, UseLabel8B[Xop2Bug]]; --Discard the pushed Alpha drRETN[]; --Return to caller remaining in Kernel mode. SetLabel[Xop2Bug]; XPause[]; SetLabel[Xop3Trap]; drLIB[15]; drRJNEB[popSrc, aux8, UseLabel8B[Xop3Bug]]; drJNEBB[234B, UseLabel8B[Xop3Bug]]; --Discard the pushed AlphaBeta drRETN[]; --Return to caller remaining in Kernel mode. SetLabel[Xop3Bug]; XPause[]; SetLabel[Xop5Trap]; drLIB[16]; drRJNEB[popSrc, aux8, UseLabel8B[Xop5Bug]]; drJNEBB[345B, UseLabel8B[Xop5Bug]]; --Discard the pushed AlphaBetaGammaDelta drRETN[]; --Return to caller remaining in Kernel mode. SetLabel[Xop5Bug]; XPause[]; SetLabel[ErrorXop1Trap]; drLIQB[CardToWord[600000B]]; GetYoungestStatus[]; drAND[]; drJEBB[0, UseLabel8B[AlreadyInKernel]]; EnterKernel[]; SetLabel[AlreadyInKernel]; drLIQB[CardToWord[debugBase]]; drLIP[130]; drWSB[euRegBase + 130]; --euMAR drLIB[2]; --Opcode number of XPause[]; drJQB[CardToWord[debuggerBasePC]]; SetLabel[TurnOnTraps]; --Call here with EnableTraps[] drLIB[377B]; GetYoungestStatus[]; drAND[]; --Preserve L drLIQB[CardToWord[200000B]]; drOR[]; SetYoungestStatus[]; --Set trapsEnabled drRETN[]; SetLabel[TurnOffTraps]; --Call here with DisableTraps[] drLIB[377B]; GetYoungestStatus[]; drAND[]; --Preserve L, clear trapsEnabled and User SetYoungestStatus[]; --Set trapsEnabled drRETN[]; SetLabel[TurnOnUserMode]; --Call here with EnterUser[] drLIB[377B]; GetYoungestStatus[]; drAND[]; --Preserve L drLIQB[CardToWord[600000B]]; drOR[]; SetYoungestStatus[]; drRETN[]; FillXop[LOOPHOLE[DragOpsCross.Inst.dKFC, CARDINAL], KFCTrap]; FillXop[1B, Xop1Trap]; FillXop[234B, Xop2Trap]; FillXop[364B, Xop3Trap]; FillXop[40B, Xop5Trap]; FillXop[2B, ErrorXop1Trap]; FillTrap[IFUStackOverflowTrap, IFUStackOverflow]; FillTrap[EUPageFault, EUPageFlt]; FillTrap[EUWriteFault, EUWPFlt]; FillTrap[ALUCondOver, Overflow]; FillTrap[ALUCondBC, BoundsCheck]; FillTrap[ALUCondIL, LispNaN]; FillTrap[ModeFault, UserModeViolation]; FillTrap[EUStackOverflowTrap, EUStackOverflow]; FillTrap[IFUPageFaultTrap, IFUPageFault]; FillTrap[RescheduleTrap, Reschedule]; }; END. @–GenTraps.mesa Copyright c 1986, 1987 by Xerox Corporation. All rights reserved. Edward Fiala March 5, 1986 10:49:41 am PST McCreight February 16, 1987 10:56:29 am PST Curry, September 11, 1986 2:40:33 pm PDT Fiala November 7, 1986 6:44:21 pm PST Massive edits to fix program for the fact that Reschedule and address check are no longer implemented, for the fact that ifuStatus is no longer pushed on the EU stack on a trap, for the different way of enabling and disabling traps and entering user mode, for features which can now be tested with _ LizardLiverImpl.careful _ FALSE, and for the deimplementation of partial simulation for IOD, IODA, and ION. Fiala April 3, 1987 4:21:46 pm PST Eliminate Reset, Halt, and Pause stuff to run with GenDebugger. Add XPause[] error halt to enter user mode and disable traps before entering the debugger. Add drRAND[...const0] to make FSDB have a harmless argument. Fiala April 10, 1987 1:26:22 pm PST Moved the test that EU page fault is higher priority than EU stack overflow from GenSLimit to GenEUPageFault for Softcard debugging, so that the GenSLimit test will not run into page fault incompatibilities with the Softcard. Load with "quad -cx GenDebugger GenTraps" and do "_ LizardLiverImpl.careful _ FALSE" before execution. When simulated correctly with withSoftCard = TRUE, it terminates with HALT[177777B] at PC 4043607B, cycle 4758, Inst 1588. This diagnostic will NOT run under Lizard if DebuggerDefs.withSoftCard = TRUE because Lizard traps user mode writes to addresses < KernalLimit. It tests the following machine functions (** means not tested because of some problem with the Lizard simulation): 1) User mode enabling and trap enabling and disabling via ifuYoungestL and RET to caller (L and the IFU stack were tested in GenReg.mesa). 2) KFC instruction. 3) Registers legal and illegal in User mode. 4) Instructions legal and illegal in User mode. 5) Verify that IFU stack overflow occurs when traps are enabled on DFC, SFC, SFCI, LFC, Xop1, Xop2, Xop3, Xop5, or KFC; on RBC, QBC, or BC that get bounds-check trap; on ADD that overflows; on LADD that gets NaN trap; on DUP that gets EU stack overflow; on RB[0] that gets an EU page fault; or on an ifu page fault (ifu page fault tested in GenTraps2); on user mode RADD that gets mode fault trap. 6) Verify that IFU stack overflow does not occur with 11 call stack entries on Jn, JB, JDB, JQB, JSR, JSD, or RET; on RBC, QBC, or BC that do not trap. 7) Verify that EU stack overflow trap occurs when traps are enabled and an instruction would put S in [SLimit .. SLimit + 16) for several opcodes that push the stack and for AS[n], ASL[n], and RET[n] (tested for only one value of SLimit). 8) Verify that EU stack overflow trap occurs when traps are enabled and an instruction would put S in [SLimit .. SLimit + 16) for several opcodes that pop the stack. 9) Verify that an EU stack overflow trap does not occur when ASL[n] makes S equal to SLimit - 1 or SLimit + 16 and does occur when ASL[n] makes S equal to SLimit or SLimit + 15 for SLimit = 1, 2, 4, 8, 16, 32, 64, and 111. 10) Verify that EU stack overflow is lower priority than bounds check, NaN, overflow, EU page fault, and mode fault. 11) Verify that IFU page fault occurs in sequence when jumping, calling, returning, conditionally jumping (correctly or incorrectly predicted), or falling through into an undeclared page. 12) Verify that IFU page fault does not occur when the untaken path of a conditional jump or conditional trap lies in an undeclared page. 13) Verify that EU page fault occurs in sequence for a storage read, a storage write, CST, and SFCI; that machine state which would have been affected by the faulting instruction is not modified, and that euMAR contains the fault address. 14) Verify that mode fault prevails over bounds check, overflow, NaN, and EU page fault traps. 15) **User mode and trap enabling and disabling via ifuEldestL aren't tested (don't need testing?). 16) **Memory access faults aren't tested, such as user mode WB into the Kernel (former Address Check tests were commented out because of architecture change); references to addresses >= 2^30 aren't tested (Lizard limitation). 17) **IFU page fault priority over EU stack overflow is not tested (see GenTraps2). 18) **IO Access faults on IOD, IODA, and ION aren't tested. 19) **Verify that EU stack overflow occurs with greater priority than an ALU trap caused on the instruction following a SIP which reenables interrupts. 20) **Verify that EU stack overflow occurs with greater priority than Reschedule following a SIP which reenables interrupts (tested in GenTraps2). 21) **EU write protect fault occurs in sequence for a storage write and the CST instruction, that machine state which would have been affected by the faulting instruction is not modified, and that euMAR contains the fault address. (Lizard doesn't simulate write protect faults.) 22) **Reschedule trap isn't tested because it is not simulated. ifuSLimit = 7-bit stack limit register. Any opcode which causes the stack pointer to enter the region [SLimit..SLimit+16) will be trapped to the EU stack overflow location. IFUStackSize = 15. LIP[ifuEldestPC] removes and SIP[ifuEldestPC] adds to the call stack. In this diagnostic, the auxiliary registers are called aux0 .. aux15; the locals reg0 .. reg15; and the constants const0 .. const11. Global register usage is as follows: aux8 contains a code indicating the trap expected (0 if none). const4 contains the constant 6 for trap routines. These labels are for trap procedures. Lizard only permits addresses >= DragOpsCross.KernelLimit = 100000000B to be written in user mode; the Softcard only permits addresses in [1,000,000B..2,000,000B) to be referenced. All traps enter kernel mode and disable traps; disabling affects only Reschedule, EU stack overflow, and IFU stack overflow. When traps are enabled, the IFU stack allows 11 normal calls but converts the 12th call into an IFU stack overflow trap; when traps are disabled, all 15 levels of the IFU stack are usable. Note, however, that when a trap or KFC is the 12th call, it will complete and disable traps without causing an IFU stack overflow trap. There is no IFU stack underflow trap; the first location in the IFU stack must be made to contain a return link to an appropriate trap procedure (or use the trick of causing a page fault). When traps are enabled, any opcode causing S to wind up in the range [SLimit..SLimit+16) causes an EU stack overflow trap; this detects both underflows and overflows, though underflow can only happen due to a programming error. Xops and KFC trap at opcode*TrapWidthBytes + xopBase*bytesPerWord = 4,000,000B + 20B * opcode. A trap's location is TrapIndex*TrapWidthBytes + TrapBase*bytesPerWord = 4,002,000B + 20B * TrapIndex. TrapIndex definitions are in DragOpsCross. Procedures to enable and disable traps in the caller's context; must be in Kernel mode. Indicate KFC trap expected by loading 12 into aux8 16 bytes between consecutive trap instructions is insufficient for StandardTrap, so the trap instruction must be filled separately with FillTrap[TrapName, dest]. aux8 has previously been loaded with a code for the trap presently expected (or 0 if none), and an opcode which is supposed to trap is followed by enough XPause[] opcodes to fill out 6 bytes (i.e., enough for a 5-byte trapping opcode and a 1-byte XPause[] after it); then if no trap occurs, the first XPause[] after the opcode will stop simulation; or if the wrong trap occurs, the mismatch on aux8 will cause XPause[] to occur. Otherwise, the trap procedure will return to the 6th byte after the location that trapped. Advance return PC by 6 Write 0 into storage at the address addr. Make the location addr known to Lizard. Write 0 into storage at the address addr which should cause an Address Check trap. StackedStatusWord: TYPE = MACHINE DEPENDENT RECORD [ version (0:00..07): [0..255] _ 0, pad (0:08..13) [0..63] _ 0, userMode (0:14..14) BOOL _ FALSE (True = kernel mode), trapsEnabled (0:15..15): BOOL _ FALSE, pad (1:00..07) [0..255] _ 0, lBase (1:08..15) [0..255] _ 0 ]; User mode can be enabled by changing the user mode bit in the stacked status word and then doing a RET. In user mode, the following actions are illegal: 1) Any write of a constant or aux0 to aux7 causes a mode fault trap. 2) All SIPs, and LIP[IFUEldestPC] (an active operation) cause a mode fault trap. 3) IODA, IOD, and ION pass a device number in Beta for which the low-order bit is 0 (PRead) or 1 (PWrite) and for which the next two low-order bits serve both as a device number and for user mode checking purposes as follows: Beta[4B] = 1 means "kernel mode required"; the IO operation will get a ModeFault trap if it is executed in user mode. Beta[2B] = 1 means "address check"; the instruction will cause an AddressCheck trap on a Kernel address. Once in user mode, kernel mode can be reentered only by executing a KFC or trapping. Initialize aux0 here before entering user mode because it cannot be written in user mode and must point at a valid memory address when the LGF opcode is tested in user mode. Check trap enabling and disabling and user mode enabling (must call a subroutine). Reference all registers that can legally be read and written in user mode. The call stack must be at least 1 deep for the ifu LIP operations to yield defined values. ***FIXES NEEDED HERE. IODA[2B] does [S] _ PRead[0 + [S], BetaZ]. Now execute all instructions legal in user mode (LRn, SRn, LRIn, SRIn, and LCn each treated as a single instruction). Reference all registers illegal in user mode. aux0 to aux7 and const0 to const11 are read-only in user mode. Execute all instructions illegal in user mode. Representative SIP instructions. LIP[IFUEldestPC] is illegal in user mode because it modifies the call stack. IOD, ION, and IODA are legal or illegal in user mode according to the device which is selected. Now try a write reference to a Kernel page, which should trap. Remove the 2 calls from the stack Test conditions which should and should not cause IFU stack overflow trap. Begin here in Kernel mode with traps disabled, and 0 IFU call stack entries. Now in Kernel mode with traps enabled. Now in Kernel mode with traps enabled and 11 calls on the stack; the following opcodes shouldn't cause IFU stack overflow trap. RBC, QBC, and BC should not cause IFU stack overflow when they don't trap. Each of the following instructions does a 12th call which should go through the IFU stack overflow trap and skip the XPause[]'s after the call. 1, 2, 3, and 5-byte Xops should cause IFU stack overflow trap RBC, QBC, or BC should cause IFU stack overflow when they trap. NaN trap causing stack overflow should get IFU stack overflow trap. ADD that Overflows should get IFU stack overflow trap. EU page fault. Push that gets EU stack overflow Return here reducing call stack depth by 1 so KFC can get out of user mode. User mode RADD that gets mode fault. User mode store that gets address check Remove the 10 calls from the stack and cleanup S = L = 0 here and aux15 must contain 9 (the code for EU stack overflow trap expected); SL is the value of SLimit to be tested for ASL[SL-1], ASL[SL + 16], ASL[SL], and ASL[SL + 15]. Note that S is left equal to 0. SLimitTest executes about 15 instructions. For one value of SLimit, verify that EU stack overflow trap occurs when traps are enabled and an instruction would put S in [SLimit .. SLimit + 16) for several opcodes that push and pop the stack and for AS[n], ASL[n], and RET[n]. Also verify that the trap occurs when S is already in the restricted range when traps are reenabled. Create one call stack entry so that RET below has a defined return; perhaps this is not strictly necessary because these instructions trap, but Lizard is picky. Should get EU stack overflow trap on these typical instructions Lizard gave a "VERY suspicious S adjustment" crash for alpha >= 40B in this test, so I changed the code to have fewer locals. Now check for popping that puts S in the restricted range. For SLimit = 4B, 10B, 20B, 1B, 40B, 100B, 2B, and 157B verify that an EU stack overflow trap does not occur when ASL[n] makes S equal to SLimit - 1 or SLimit + 16 and does occur when ASL[n] makes S equal to SLimit or SLimit + 15. L = 0, S = 0, 0 call stack entries, SLimit = 160B, no trap expected. Since S is left 0 by SLimitTest, none of the args to SLimitTest may be in [161B..0B]. Verify that EU stack overflow is lower priority than all other traps. NaN should prevail; this is a particularly rough test because RLADD would have decremented S if it hadn't trapped and because Overflow is happening as well as NaN. ****Address check isn't implemented any more. ****Used to test that Reschedule won out over EUStackOverflow here. Test that ModeFault prevails over EUStackOVerflow when writing an illegal register occurs at the same time as popping into the restricted range. Verify that IFU page fault occurs in sequence when jumping, calling, returning, conditionally jumping (correctly or incorrectly predicted), or falling through into an undeclared page. Verify that IFU page fault does not occur when the untaken path of a conditional jump or conditional trap lies in an undeclared page. predicted non-jump; jump would fault; doesn't jump; test that no fault occurs. predicted jump; jump would fault; doesn't jump; test that no fault occurs. predicted non-jump; fall-through would fault; jumps; test that no fault occurs. predicted jump; fall-through would fault; jumps; test that no fault occurs. **Should test EU stack overflow coincident with IFU page fault. Verify that EU page fault occurs in sequence and that machine state which would have been affected by the faulting instruction is not modified on storage read, storage write, CST read-write, SFCI read, IODA read, and IODA write; verify that euMAR contains the fault address. No current instructions which are storage writes modify any EU registers; only S is modified, so verify that on a storage write S is not changed; reads modify both S and some destination register. Verify that EU stack overflow is lower priority than EU page fault. S _ S - 1 if the popSrc isn't a no-op. Make sure value in aux10 isn't overwritten during the fault. Make sure S didn't change during the fault. It is a "don't care" whether or not CST smashes the value in [S+1] on a page fault because that value will be overwritten by the page fault trap procedure. Lizard doesn't trap the IODA opcode for page faults. [S] _ PRead[AlphaZ + [S], BetaZ] with address check. PWrite[AlphaZ + [S], BetaZ with address check, [S-1]]; S _ S-2. Verify that ModeFault prevails over bounds check, overflow, NaN, and EU page fault. Modefault prevails over NaN. Modefault prevails over overflow. Modefault prevails over bounds check. Modefault prevails over EU page fault. Return here in Kernel mode XPause[] = Pause[] but uses opcode 2 instead of 0. spLimit is set with room for 17 overflow words (just in case). Now initialize the other constants and auxiliary registers to 1 so that they can be read during the user mode test without confusing the simulators. To avoid undefined values, write the 3 registers which will be read by LIP in user mode. Initialize all the locals for one frame Next instruction is the 49th. All of these work except that in GenIFUStackOverflow ModeFault trap takes priority over IFUStackOverflow, a Lizard bug. EU page fault trap has code 2 EU write protect fault trap has code 3 IFU page fault trap has code 10 Reschedule trap has code 11 KFC trap has code 12 1-byte Xop (opcode = 1B) has code 13 2-byte Xop (opcode 234B, alpha = 123B) has code 14 3-byte Xop (opcode 364B, alphabeta = 234B) has code 15 5-byte Xop (opcode 40B, alphabetagammadelta = 345B) has code 16 All of the EU page fault tests use the address EUPageFaultAddress in aux9. All of the EU page fault tests use the address EUPageFaultAddress. 1 arg = return PC All of the IFU page fault tests try to execute an instruction at IFUPageFaultPC. ****Does Reschedule-waiting have to be cleared here? KFC is used to get back into Kernel mode with traps disabled after testing in User mode XPause[] (opcode 2) is used instead of Pause[] (opcode 0) to enter the debugger from user mode. This is done by first executing KFC to enter monitor mode and then doing Pause[]. Set trapsEnabled and user mode These calls to FillXop and FillTrap initialize the trap locations with JDB[trap procedure]. ΚΪ˜codešœ ™ Kšœ Οmœ7™BK™*K™+K™(K™½K™όK™…K™Kšœσ™σK™Kšœτ™τK™—šΟk ˜ Kšœžœ˜Kšœ ˜ Kšœ žœJΟcε ˜Α Kšœžœ=ŸΥ˜©Kšœ Ÿ˜,KšœŸΪ˜ξKšœŸο˜ƒK˜—šœ žœž˜KšžœL˜SKšœžœžœS˜_K–20 sp tabStops˜K–20 sp tabStopsšœžœ"˜9Kšœ­™­K–20 sp tabStopsšœ žœžœžœ˜FKšœY™YK–20 sp tabStopsšœ žœžœ žœ˜JK–20 sp tabStopsšœ žœžœžœ˜HK–20 sp tabStopsšœžœžœ"žœ˜NK–20 sp tabStopsšœžœžœ!žœ˜LK–20 sp tabStopsšœžœžœžœ˜>K–20 sp tabStops˜K–40 sp tabStopsšœŸ™ŸK–40 sp tabStopsšœ˜K–40 sp tabStopsšœ˜K–40 sp tabStopsšœ˜K–40 sp tabStopsšœ˜K–40 sp tabStopsšœ˜K–40 sp tabStopsšœ˜K–40 sp tabStopsšœ˜K–40 sp tabStopsšœ˜K–40 sp tabStopsšœ˜K–40 sp tabStopsšœ˜K–40 sp tabStops˜K–40 sp tabStops˜K–40 sp tabStops˜K–40 sp tabStops˜K–40 sp tabStops˜K–40 sp tabStops˜!K–40 sp tabStops˜!K™šΟnœžœ˜ Kšœ˜K˜Kšœ%™%K˜%K˜K˜ K˜K˜&K˜K˜#K˜K˜!K˜!K˜$Jšœžœžœ˜+Jšœžœžœ˜5K˜$K˜K˜"K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜"K˜$K˜K˜ K˜!K˜#J˜J˜'J˜.J˜$J˜*J˜)J˜/J˜Jšœ΄™΄Jš œ žœžœžœžœ žœ ˜KJš œžœžœžœžœ žœ ˜MK˜K™|K™K™ƒK™K™γK˜Kšœ^™^š œžœžœ˜/KšœV˜VKšœ˜K˜K˜—Kšœ‘™‘š œžœ.˜Jšœ!Ÿ ˜+Jšœ6Ÿ˜>Jšœ5Ÿ˜=Jšœ6Ÿ˜>J˜Jšœ˜Jšœ˜Jšœ/˜/J˜ J˜.J˜8Jšœ Ÿ ˜Jšœ Ÿ˜JšœŸ%˜3J˜Jšœ"Ÿ$˜FJš žœžœžœ žœ žœ˜/Jšœ Ÿ0˜=Jšœ"˜"J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜JšœŸ%˜CJšœ&Ÿ ˜0Jšœ"Ÿ ˜.JšœŸ ˜'Jšœ-˜-Jšœ Ÿ˜Jšœ Ÿ ˜JšœŸ˜"Jšœ!˜!JšœŸ-˜AJ˜J˜JšœŸ/˜GJ˜J˜J˜J˜JšœŸ˜'Jšžœžœžœ"˜:JšœŸ ˜J˜J˜J˜Jšœ)Ÿ˜FJšœ!˜!Jšœ)Ÿ˜FJšœ,˜,Jšœ)Ÿ˜FJšœ@˜@Jšœ)Ÿ˜FJšœF˜FJšœŸ6˜FJšœŸ"˜0Jšœ"Ÿ˜*JšœŸ ˜'Jšœ Ÿ˜Jšœ Ÿ ˜Jšœ Ÿ˜J˜ J˜J˜J˜J˜ J˜J˜JšœŸ ˜Jšœ Ÿ ˜J˜J˜Jšœ Ÿ:˜GJ˜Jšœ-™-Jšœ Ÿ˜JšœŸ#œ ˜LJšœ>™>J˜:J˜:J˜:J˜:J˜:J˜:J˜:J˜:J˜™>J˜$J˜Jšœ!™!Jšœ ŸJ˜WJšœŸ>˜NJš žœžœžœžœžœ˜4K˜—K˜Kšœ˜™˜š œžœ˜ J˜J˜J˜J˜-J˜!J˜J˜,J˜Jšœ Ÿ1˜˜LJ˜Jšœ&™&Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜J˜ J˜Jšœ™J˜J˜J˜J˜/J˜J˜ J˜8J˜BJ˜JšœJ™JJšœ7˜7J˜$J˜J˜Jšœ(Ÿ&˜NJšœ™Jšœ'˜'Jšœ$˜$JšœV˜VJšœ=™=Jšœ!˜!Jšœ3˜3Jšœ,˜,Jšœ)˜)Jšœ@˜@Jšœ˜JšœF˜FJšœ ˜ J˜:Jšœ?™?Jšœ˜JšœB˜BJšœ?˜?J˜J˜9JšœC™CJ˜*J˜;Jšœ6™6J˜:Jšœ™J˜'Jšœ˜J˜0Jšœ ™ Jšœ Ÿ˜J˜J˜:J˜'JšœŸ˜9JšœŸ!˜1J˜ Jšœ"Ÿ˜2JšœK™KJšœ.Ÿ ˜8J˜Jšœ˜Jšœ(Ÿ&˜NJšœ$™$J˜=Jšœ'™'Jšœ?˜?J˜JšœŸ˜:JšœŸ(˜6J˜J˜#Jšœ˜Jšœ.™.Jš žœžœžœžœžœ˜4Jšœ ŸB˜OK˜—K˜š  œžœ˜Kšœƒ™ƒš  œžœžœžœ˜#Kšœžœ˜Jšœ˜Jšœžœ,Ÿ˜J˜?J˜>J˜8J˜Jšœ}™}šžœžœžœ ž˜J˜0J˜7J˜7Jšžœ˜—J˜Jšœ:™:JšœŸ˜)Jšœ Ÿ˜=JšœŸ˜4J˜?J˜@J˜?J˜8J˜:J˜Jšœε™εJšœŸ˜9Jšœ Ÿ˜Jšœ›™›J˜J˜J˜J˜J˜ J˜J˜J˜J˜J˜KšœE™EJ˜Jšœ Ÿ ˜Kšœ Ÿ ˜J˜Jšœ(Ÿ˜EJšœŸ˜3JšœB˜BJšœ?˜?J˜Jšœ£™£Jšœ4Ÿ˜BJšœ,Ÿ˜JJšœA˜AJ˜Jšœ1Ÿ˜DJšœ Ÿ˜(Jšœ@˜@J˜Jšœ-™-J˜#Jšœ(˜(Jšœ;˜;J™JšœC™CJ˜Jšœ™JšœŸ˜)Jšœ Ÿ˜=Jšœ(Ÿ˜EJšœ ˜ J˜=JšœŸ%˜5J˜Jšœ ŸC˜PK˜—K˜Jšœ·™·š œžœ˜Jšœžœžœ˜J˜J˜ J˜J˜J˜J˜!Jšœžœžœ˜-Jšœžœžœ˜-Jšœžœžœ˜,JšœžœžœŸ˜JJ˜Jšœ ˜ J˜JšœŸ˜Jšœ˜Jšœ'Ÿ+˜RJšœ)Ÿ˜BJšœ$Ÿ˜?Jšœ˜J˜J˜Jšœ˜Jšœ,Ÿ˜AJ˜J˜J˜#J˜J˜ Jšœ Ÿ˜&J˜J˜J˜Jšœ=Ÿ˜RJ˜J˜J˜Jšœ>Ÿ˜SJ˜J˜J˜Jšœ-˜-Jšœ ˜ Jšœ Ÿ(˜1J˜J˜K˜Jšœ…™…K˜KšœŸ˜:KšœN™NKšœ=˜=J˜KšœJ™JKšœ>˜>J˜J˜PJšœO™OJšœ˜J˜'J˜CJ˜JšœK™KJšœ˜J˜$J˜J˜J˜Jšœ?™?J˜—J˜J˜JšœΨ™Ψš œžœ˜K˜K˜K˜JšœŸ˜Jšœ˜Kšœ(Ÿ˜@J˜KšœC™CJ˜Kšœ Ÿ ˜K˜'Kšœ˜J˜0JšœŸ˜K˜K˜'K˜0Kšœ-Ÿ"˜OK˜K˜K˜K˜*Kšœ&™&K˜;Kšœ<™K˜K˜0Kšœ&™&K˜AKšœŸ˜,Kšœ™K˜—K˜Kšœ2™2š œžœ˜KšœAžœ˜NJ˜—J˜K˜Kšœ>™>Kšœ˜Kšœ ˜ KšœŸ2˜PK˜ Kšœ Ÿ/˜OKšœ”™”K˜ K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜KšœX™XKšœ˜Kšœ˜KšœŸ˜(Kšœ'™'Kš žœžœžœ žœ žœ˜/K˜Jšœ–™–J˜J˜J˜ J˜J˜J˜J˜JšœŸ*˜9J˜J˜J˜Kšœ$Ÿ ˜0Kšœ™Kšœ&™&K˜Kšœ˜Kšœ˜Kšœ˜Kšœ#˜#K˜!Kšœ™Kšœ™Kšœ™Kšœ$™$Kšœ2™2Kšœ6™6Kšœ?™?J˜J˜J˜J˜JšœP™PJ˜#J˜:J˜Jšœ ˜ J˜#J˜Jšœ4™4JšœŸ˜-J˜