DIRECTORY Basics USING [DoubleShiftLeft], DragOpsCross USING [Word, ProcessorRegister, XopBase, TrapBase, TrapWidthBytes, bytesPerWord, TrapIndex, Inst, KernalLimit], --XopBase, TrapBase, TrapWidthBytes, Inst, wordsPerPage, bytesPerWord, charsPerWord, bitsPerByte, bitsPerCharacter, bitsPerWord, logWordsPerPage, logBitsPerByte, logBitsPerChar, logBytesPerWord, logCharsPerWord, logBitsPerWord, logBytesPerPage, PageCount, PageNumber, maxPagesInVM, SixBitIndex, FiveBitIndex, Word, TwoWords, FourBitIndex, Half, ThreeBitIndex, FourHalves, TwoHalves, Byte, ZerosByte, OnesByte, EightBytes, FourBytes, ByteIndex, BytesPerWord, TwoBytes, Comparison, ByteAddress, WordAddress, FieldDescriptor, TrapWidthWords, KernalLimit, TrapIndex, StackUnderflowTrap, IFUPageFaultTrap, ResetTrap, IFUStackOverflowTrap, EUStackOverflowTrap, RescheduleTrap, ALUCondOver, ALUCondBC, ALUCondIL, ALUCondDO, EUPageFault, EUWriteFault, AUFault, euStack, euJunk, euMAR, euField, euConstant, euAux, euBogus, euLast, ifuXBus, ifuStatus, ifuSLimit, ifuYoungestL, ifuYoungestPC, ifuEldestL, ifuEldestPC, ifuBogus, ifuL, ifuS, ifuPC, ifuLast, IFUStatusRec, IFUStackIndex, IFUStackSize, IFUOverflow, EUStackIndex, EUStackSize, EULocalIndex, EULocals, EUAuxIndex, EUAuxRegs, EUConstIndex, EUConstants, IOLocation, ioRescheduleRequest, ioResetRequest DragOpsCrossUtils USING [CardToWord, IntToWord, CardToByte], --BytePCToWordAddress, WordAddressToBytePC, IOOperandToCard, CardToIOOperand, FieldDescriptorToCard, CardToFieldDescriptor, StatusToWord, WordToStatus, 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, TrapIndexToBytePC, XopToBytePC HandCoding, --Has opcode and register defs. HandCodingPseudos, --GenLabel, GenLabelHere, SetLabel, Halt, Pause, MakeLabelGlobal, UseLabel8B, UseLabel16, UseLabel32, ProcedureEntry, ProcedureExit, EnableTraps, IndexedJump, SetupField, ExtractField, ShiftLeft, LoadProcessorReg, StoreProcessorReg, DisableTraps, CauseReschedule, CauseReset, GetSPLimit, SetSPLimit, GetL, SetL, GetYoungestPC, GetYoungestL, GetEldestPC, GetEldestL, SetYoungestPC, SetYoungestL, SetEldestPC, SetEldestL HandCodingSupport; --Area, GetCurrentArea, ReserveData, SetOutputPC, GetProc, PutProc, ProcList, NewArea, GenWithArea, Gen1WithArea, ForceOut, GetOutputPC, WordAlign, OutputByte, OutputOneByte, OutputAlphaBeta, OutputAlphaBetaGammaDelta, OutputWord GenTraps: CEDAR PROGRAM IMPORTS Basics, DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport = BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport; Word: TYPE = DragOpsCross.Word; 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]; ifuStatus: CARDINAL = LOOPHOLE[ProcessorRegister.ifuStatus, CARDINAL]; euMAR: CARDINAL = LOOPHOLE[ProcessorRegister.euMAR, CARDINAL]; KernelLimit: LONG CARDINAL = DragOpsCross.KernalLimit; 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]]; 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[]; oldPC: LONG CARDINAL; start: Label = GenLabel[]; dummy: Label = GenLabel[]; initL: Label = GenLabel[]; IFUStackOverflow: Label = GenLabel[]; AddressCheck: 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[]; EUStkOvfBad: 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[]; enterIFUStatusTest: Label = GenLabel[]; enterIFUStackOverflowTest: Label = GenLabel[]; enterSLimitTest: Label = GenLabel[]; enterRescheduleTest: Label = GenLabel[]; enterIFUPageFaultTest: Label = GenLabel[]; enterEUPageFaultTest: Label = GenLabel[]; enterModeFaultPriorityTest: Label = GenLabel[]; enterAddressCheckPriorityTest: Label = GenLabel[]; FillXop: PROC [inst: CARDINAL, dest: Label] = { SetOutputPC[inst * DragOpsCross.TrapWidthBytes + DragOpsCross.XopBase * DragOpsCross.bytesPerWord]; drJDB[UseLabel16[dest]]; }; FillTrap: PROC [tx: DragOpsCross.TrapIndex, dest: Label] = { SetOutputPC[LOOPHOLE[tx, CARDINAL] * DragOpsCross.TrapWidthBytes + DragOpsCross.TrapBase * DragOpsCross.bytesPerWord]; drJDB[UseLabel16[dest]]; }; StandardTrap: PROC [dest: Label, code: CARDINAL] = { TrapUnexpected: Label = GenLabel[]; SetLabel[dest]; drALS[0]; --ALS[1 - nargs], where nargs includes 1 for IFUstatus drLIB[code]; drRJNEB[popSrc, aux8, UseLabel8B[TrapUnexpected]]; GetYoungestPC[]; drRVADD[topDst, const4, topSrc]; SetYoungestPC[]; drRETK[377B]; --RETK[nResults - 1] 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]; Pause[]; Pause[]; Pause[]; Pause[]; }; GenIFUStatus: PROC [] ~ { Bad0: Label = GenLabel[]; userOK0: Label = GenLabel[]; UCall1: Label = GenLabel[]; UCall2: Label = GenLabel[]; UJump1: Label = GenLabel[]; JQBNop0: Label = GenLabel[]; SetLabel[enterIFUStatusTest]; drLIQB[CardToWord[KernelLimit]]; drROR[aux0, topSrc, popSrc]; drLIB[20B + 10B + 2B]; --User mode + trapsEnabledKeep + rescheduleKeep drSIP[ifuStatus]; drLIP[ifuStatus]; drJEBBJ[20B+2B, UseLabel8B[userOK0]]; SetLabel[Bad0]; Pause[]; SetLabel[userOK0]; 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 drLIP[ifuStatus]; --10th push drASL[377B]; --0 pushes on the EU stack, 1 call on the IFU stack WriteAtAddress[ KernelLimit]; WriteAtAddress[ 200000000B]; WriteAtAddress[ 400000000B]; WriteAtAddress[ 1000000000B]; WriteAtAddress[ 2000000000B]; WriteAtAddress[ 4000000000B]; --WriteAtAddress[10000000000B]; --WriteAtAddress[20000000000B]; drLIQB[CardToWord[KernelLimit]]; drIOS[2B]; drLIQB[CardToWord[ 200000000B]]; drIOS[2B]; drLIQB[CardToWord[ 400000000B]]; drIOS[2B]; drLIQB[CardToWord[ 1000000000B]]; drIOS[2B]; drLIQB[CardToWord[ 2000000000B]]; drIOS[2B]; drLIQB[CardToWord[ 4000000000B]]; drIOS[2B]; --drLIQB[CardToWord[10000000000B]]; drIOS[2B]; --drLIQB[CardToWord[20000000000B]]; drIOS[2B]; drAS[372B]; --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]; drRXOR[topDst, topSrc, topSrc]; drFSDB[444]; --1 push drRFU[pushDst, topSrc, topSrc]; --2 pushes drSHD[333]; --1 push drSHL[111]; --1 push drSHR[222]; --1 push drJ1[]; drJ2[]; Pause[]; drJ3[]; Pause[]; Pause[]; drJ5[]; Pause[]; Pause[]; Pause[]; Pause[]; drJDB[3]; drJQB[UseLabel32[JQBNop0]]; SetLabel[JQBNop0]; drEXDIS[]; --0 pushes drLIDB[0]; --1 push drASL[377B]; --0 pushes, 0 locals (S _ 0B, L = 1B) drAL[0]; drLIQB[CardToWord[KernelLimit]]; --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[KernelLimit - 1]]; --2 pushes drRBC[topDst, topSrc, belowSrc]; --won't trap drQBC[topAtop, belowSrc]; --won't trap drDIS[]; drLIQB[CardToWord[KernelLimit + 1]]; drBC[]; --1 push drDUP[]; --2 pushes drLC0[]; drRX[]; drDIS[]; --1 push drQRX[pushAtop, const0]; drDIS[]; drLGF[0]; drDIS[]; --(aux0 was initialized to KernelLimit above) drRAI[reg1, aux0, 0]; drDUP[]; drRB[0]; drDIS[]; drRRI[reg1, reg13, 0]; --(reg0 .. reg15 were set to KernelLimit above) drRRX[reg1, reg13, const0]; drRSB[0]; drDIS[]; drWAI[reg1, aux0, 0]; drWRI[reg1, reg13, 0]; drLC0[]; drWSB[0]; --Still have 1 push drLIB[1]; drLC0[]; drCST[0]; drAS[374B]; --0 pushes drLIB[1]; drJS[]; 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]]; drLIB[12]; drROR[aux8, topSrc, popSrc]; --Indicate KFC trap expected drKFC[]; drROR[aux8, const0, const0]; --Indicate no traps expected drLIB[20B + 4B + 2B]; --User mode + trapsEnabled + rescheduleKeep drSIP[ifuStatus]; drLIQB[CardToWord[KernelLimit]]; --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]; Pause[]; Pause[]; Pause[]; drROR[aux1, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[aux2, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[aux3, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[aux4, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[aux5, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[aux6, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[aux7, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const0, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const1, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const2, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const3, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const4, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const5, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const6, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const7, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const8, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const9, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const10, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drROR[const11, popSrc, topSrc]; Pause[]; Pause[]; Pause[]; drSIP[0]; Pause[]; Pause[]; Pause[]; Pause[]; drSIP[242]; Pause[]; Pause[]; Pause[]; Pause[]; drSIP[246]; Pause[]; Pause[]; Pause[]; Pause[]; drLIP[ifuEldestPC]; Pause[]; Pause[]; Pause[]; Pause[]; drLIB[20B + 10B + 2]; drLFC[4]; Pause[]; --RETK returned in user mode drRETK[377B]; Pause[]; Pause[]; Pause[]; Pause[]; drDIS[]; --16 locals, 1 push, 2 calls on the IFU stack drIOL[4B]; Pause[]; Pause[]; Pause[]; --[S+1] _ PRead[AlphaZ, BetaZ]; S _ S+1. drION[4B]; Pause[]; Pause[]; Pause[]; --[S+1] _ PRead[AlphaZ, BetaZ]. drIOS[4B]; Pause[]; Pause[]; Pause[]; --[S] _ PRead[AlphaZ + [S], BetaZ]. drIOL[177777B]; Pause[]; Pause[]; Pause[]; --PWrite[AlphaZ, BetaZ, [S]]; S _ S-1. drION[177777B]; Pause[]; Pause[]; Pause[]; --PWrite[AlphaZ, BetaZ, [S]]. drIOS[177777B]; Pause[]; Pause[]; Pause[]; --PWrite[AlphaZ + [S], BetaZ, [S-1]]; S _ S-2. drLIB[4]; drROR[aux8, popSrc, topSrc]; --Indicate Address Check trap expected drIOL[2B]; Pause[]; Pause[]; Pause[]; --[S+1] _ PRead[AlphaZ, BetaZ]; S _ S+1. drION[2B]; Pause[]; Pause[]; Pause[]; --[S+1] _ PRead[AlphaZ, BetaZ]. drLC0[]; drIOS[2B]; Pause[]; Pause[]; Pause[]; --[S] _ PRead[AlphaZ + [S], BetaZ]. drLIB[377B]; drIOS[2B]; Pause[]; Pause[]; Pause[]; drLIDB[177400B]; drIOS[2B]; Pause[]; Pause[]; Pause[]; drLIQB[CardToWord[400000B]]; drIOS[2B]; Pause[]; Pause[]; Pause[]; drLIQB[CardToWord[7000000B]]; drIOS[2B]; Pause[]; Pause[]; Pause[]; drLIQB[CardToWord[70000000B]]; drIOS[2B]; Pause[]; Pause[]; Pause[]; drLIQB[CardToWord[37777777B]]; drIOS[2B]; Pause[]; Pause[]; Pause[]; drASL[17B]; --16 locals, 0 pushes, 2 calls on IFU stack WriteTrapAtAddress[ 377B]; WriteTrapAtAddress[ 400B]; WriteTrapAtAddress[ 7000B]; WriteTrapAtAddress[ 70000B]; WriteTrapAtAddress[ 700000B]; WriteTrapAtAddress[ 3000000B]; WriteTrapAtAddress[ 5000000B]; WriteTrapAtAddress[70000000B]; WriteTrapAtAddress[77777777B]; drASL[17B]; --16 locals, 0 pushes on the EU stack, 2 calls on the IFU stack, user mode drLIB[12]; drROR[aux8, popSrc, topSrc]; --Indicate KFC trap expected drKFC[]; drROR[aux8, const0, const0]; --Indicate no traps expected FOR I: CARDINAL IN [0..1] DO GetEldestPC[]; ENDLOOP; }; GenIFUStackOverflow: PROC [] ~ { UCall3: Label = GenLabel[]; JQBNop1: Label = GenLabel[]; exitIFUStackOverflowTest: Label = GenLabel[]; eleventhCall: Label = GenLabel[]; drJB[UseLabel8A[enterIFUStackOverflowTest]]; SetLabel[UCall3]; Pause[]; --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 drLIB[40B + 4B + 2B]; drSIP[ifuStatus]; --UserModeKeep + TrapsEnabled + RescheduleKeep 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[UseLabel16[eleventhCall]]; --11 calls drJDB[UseLabel16[exitIFUStackOverflowTest]]; --10 calls SetLabel[eleventhCall]; drLIB[40B + 4B + 2B]; drSIP[ifuStatus]; --UserModeKeep + TrapsEnabled + RescheduleKeep drJ1[]; drJ2[]; Pause[]; drJ3[]; Pause[]; Pause[]; drJ5[]; Pause[]; Pause[]; Pause[]; Pause[]; drJB[2]; drJDB[3]; drJQB[UseLabel32[JQBNop1]]; SetLabel[JQBNop1]; drLIB[1]; drJS[]; 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]; Pause[]; Pause[]; Pause[]; drDFC[UseLabel32[UCall3]]; Pause[]; drLIQB[UseLabel32[UCall3]]; drSFC[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; OutputByte[area, CardToByte[1B]]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; OutputAlphaBeta[area, (234B * 400B) + 123B]; Pause[]; Pause[]; Pause[]; Pause[]; OutputByte[area, CardToByte[364B]]; OutputAlphaBeta[area, 234B]; Pause[]; Pause[]; Pause[]; OutputByte[area, CardToByte[40B]]; OutputWord[area, CardToWord[345B]]; Pause[]; drKFC[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drLIB[1]; drLIB[2]; drQBC[pushAtop, belowSrc]; Pause[]; Pause[]; Pause[]; Pause[]; drRBC[pushDst, topSrc, belowSrc]; Pause[]; Pause[]; Pause[]; drEXDIS[]; drLIB[1]; drBC[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drLIQB[CardToWord[10000000000B]]; drDUP[]; drLADD[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drADD[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drLIQB[CardToWord[EUPageFaultAddress]]; drRB[0]; Pause[]; Pause[]; Pause[]; Pause[]; drASL[17B]; --L = 1, S = 20B drLIB[21B]; drSIP[ifuSLimit]; drDUP[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drDIS[]; drLIB[160B]; drSIP[ifuSLimit]; drLIB[20B + 4B + 2B]; drSIP[ifuStatus]; --User + TrapEnable + RescheduleKeep drRADD[const1, const0, const0]; Pause[]; Pause[]; Pause[]; drLC0[]; drWB[0]; Pause[]; Pause[]; Pause[]; Pause[]; drROR[aux8, const0, const0]; --Indicate no traps expected drRET[377B]; --returns from 11th call and trims stack SetLabel[exitIFUStackOverflowTest]; drLIB[12]; drROR[aux8, popSrc, topSrc]; --Indicate KFC trap expected drKFC[]; 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, const1, const1]; drASL[SL]; Pause[]; Pause[]; Pause[]; Pause[]; --SLimit drASL[SL + 15]; Pause[]; Pause[]; Pause[]; Pause[]; --SLimit + 15 drROR[aux8, const0, const0]; drASL[SL + 16]; --SLimit + 16 drASL[SL - 1]; --SLimit - 1 drASL[0]; --SLimit }; ReschedRet: Label = GenLabel[]; SetLabel[enterSLimitTest]; drASL[7B]; --L = 1, S = 10B, traps enabled, Kernel mode, 0 calls on the stack drLIB[4B + 2B]; drSIP[ifuStatus]; --TrapsEnabled + RescheduleKeep drLIB[13B]; drSIP[ifuSLimit]; drLIB[9]; drROR[const1, popSrc, topSrc]; --const1 _ EU stk ovf code drROR[aux8, const1, const1]; --Indicate EU stack overflow trap expected drLIQB[CardToWord[KernelLimit]]; drSRn[reg0]; --Memory address for LRIn below drLC0[]; --S = 11B drDUP[]; --S = 12B drLFC[4]; Pause[]; drDUP[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drLRn[reg2]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drQADD[pushA0, const0]; Pause[]; Pause[]; Pause[]; Pause[]; drRADD[pushDst, const0, const0]; Pause[]; Pause[]; Pause[]; drLRIn[reg0, 0]; Pause[]; Pause[]; Pause[]; Pause[]; FOR I: CARDINAL IN [1..16] DO drAS[I]; Pause[]; Pause[]; Pause[]; Pause[]; drASL[11B + I]; Pause[]; Pause[]; Pause[]; Pause[]; drRET[11B + I]; Pause[]; Pause[]; Pause[]; Pause[]; 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]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; --drQAND[topAtop, popSrc]; Pause[]; Pause[]; Pause[]; Pause[]; --drRAND[belowDst, topSrc, popSrc]; Pause[]; Pause[]; Pause[]; --drSRIn[reg0, 0]; Pause[]; Pause[]; Pause[]; Pause[]; --drDIS[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; 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]; Pause[]; Pause[]; Pause[]; Pause[]; drRBC[pushDst, topSrc, belowSrc]; Pause[]; Pause[]; Pause[]; drAS[376B]; drLIB[7]; drROR[aux8, topSrc, popSrc]; --NaN prevails drLIQB[CardToWord[10000000000B]]; drDUP[]; drLADD[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drDIS[]; drLIB[5]; drROR[aux8, topSrc, popSrc]; --Overflow prevails drDUP[]; drADD[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drDIS[]; drLIB[2]; drROR[aux8, topSrc, popSrc]; --EU page fault prevails drLIQB[CardToWord[EUPageFaultAddress]]; drRB[0]; Pause[]; Pause[]; Pause[]; Pause[]; drDIS[]; drLIB[2B]; drSIP[ifuStatus]; --RescheduleKeep (= disable traps) drLIQB[UseLabel32[ReschedRet]]; --Label for reschedule trap return drLIB[11]; drROR[aux8, topSrc, popSrc]; --Reschedule should prevail drLIB[4B + 1B]; --S = SLimit now drSIP[ifuStatus]; --TrapEnable + Reschedule Pause[]; SetLabel[ReschedRet]; drDIS[]; drLIB[20B + 4B + 2B]; drSIP[ifuStatus]; --User + TrapEnable + RescheduleKeep drLIB[8]; drROR[aux8, topSrc, topSrc]; --Mode fault prevails drRADD[const1, const0, const0]; Pause[]; Pause[]; Pause[]; drDIS[]; drLIB[4]; drROR[aux8, topSrc, popSrc]; --Address check prevails drLC0[]; drWB[0]; Pause[]; Pause[]; Pause[]; Pause[]; drDIS[]; drLIB[12]; drROR[aux8, topSrc, topSrc]; --KFC should prevail drKFC[]; drROR[aux8, const0, const0]; --No trap expected drLIB[160B]; drSIP[ifuSLimit]; drASL[17B]; --L = 1, S = 20B, traps enabled, Kernel mode, 0 calls on the stack }; GenReschedule: PROC [] ~ { RescheduleOK: Label = GenLabel[]; SetLabel[enterRescheduleTest]; drASL[17B]; --L = 1, S = 20B, 0 calls on the stack drLIQB[UseLabel32[RescheduleOK]]; --Reschedule trap will send control here drLIB[11]; drROR[aux8, popSrc, topSrc]; --Reschedule trap expected drLIB[40B + 4B + 1B]; --User mode keep + TrapEnable + Reschedule drSIP[ifuStatus]; Pause[]; SetLabel[RescheduleOK]; drROR[aux8, const0, const0]; --No traps expected drLIB[40B + 1B]; --User mode keep + Reschedule (= traps disabled) drSIP[ifuStatus]; --Shouldn't trap drLIB[40B + 4B]; drSIP[ifuStatus]; --CauseReschedule[]; --drJ1[]; drJ1[]; drJ1[]; drJ1[]; drJ1[]; --Pause[]; }; 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 drLIB[4B + 2B]; drSIP[ifuStatus]; --TrapsEnabled + RescheduleKeep 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 drLIB[4B + 2B]; drSIP[ifuStatus]; --TrapsEnabled + RescheduleKeep drLIQB[CardToWord[EUPageFaultAddress]]; drROR[aux9, topSrc, topSrc]; drLIB[2]; drROR[aux8, popSrc, topSrc]; --EU page fault expected drRB[0]; Pause[]; Pause[]; Pause[]; Pause[]; drRJEBJ[topSrc, aux9, UseLabel8B[OKState]]; SetLabel[BadState]; Pause[]; SetLabel[OKState]; drLIB[123B]; drROR[aux10, popSrc, topSrc]; drRRX[aux10, popSrc, const0]; Pause[]; Pause[]; Pause[]; drLIB[123B]; drRJNEB[popSrc, aux10, UseLabel8B[BadState]]; drRJNEB[topSrc, aux9, UseLabel8B[BadState]]; drLIDB[123456B]; drWSB[0]; Pause[]; Pause[]; Pause[]; Pause[]; drLIDB[123456B]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[BadState]]; drRJNEB[topSrc, aux9, UseLabel8B[BadState]]; drLIDB[111111B]; --new value drLIDB[122222B]; --old value drCST[0]; Pause[]; Pause[]; Pause[]; Pause[]; drLIDB[122222B]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[BadState]]; drDIS[]; drSFCI[]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; drRJNEB[topSrc, aux9, UseLabel8B[BadState]]; --drIOS[2B]; -- Pause[]; Pause[]; Pause[]; --drRJNEB[popSrc, aux9, UseLabel8B[BadState]]; --drLIB[123B]; --drROR[pushDst, aux9, const0]; --drIOS[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 drLIB[20B + 4B + 2B]; drSIP[ifuStatus]; --User mode + TrapsEnabled + RescheduleKeep drLIQB[CardToWord[10000000000B]]; drDUP[]; drRLADD[const2, belowSrc, topSrc]; Pause[]; Pause[]; Pause[]; drRADD[const2, belowSrc, topSrc]; Pause[]; Pause[]; Pause[]; drRBC[const2, belowSrc, popSrc]; Pause[]; Pause[]; Pause[]; drDIS[]; drLC0[]; drLIQB[CardToWord[EUPageFaultAddress]]; drRRX[const2, popSrc, belowSrcPop]; Pause[]; Pause[]; Pause[]; drLC0[]; drIOS[7B]; Pause[]; Pause[]; Pause[]; drLIB[12]; drROR[aux8, topSrc, popSrc]; --Indicate KFC trap expected drKFC[]; drROR[aux8, const0, const0]; --No traps expected }; GenAddressCheckPriority: PROC [] ~ { SetLabel[enterAddressCheckPriorityTest]; drASL[377B]; --L = 1, S = 0 drLIB[20B + 4B + 2B]; drSIP[ifuStatus]; --UserMode + TrapsEnabled + RescheduleKeep drLIB[4]; drROR[aux8, topSrc, popSrc]; --Indicate address check expected drLC0[]; drLIQB[CardToWord[EUPageFaultAddress]]; drWB[0]; Pause[]; Pause[]; Pause[]; Pause[]; drLIB[12]; drROR[aux8, topSrc, popSrc]; --Indicate KFC trap expected drKFC[]; drROR[aux8, const0, const0]; --Indicate no traps expected }; SetLabel[dummy]; Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; Halt[123B]; StandardTrap[IFUStackOverflow, 1]; --priority 2 StandardTrap[AddressCheck, 4]; StandardTrap[Overflow, 5]; StandardTrap[BoundsCheck, 6]; StandardTrap[LispNaN, 7]; StandardTrap[UserModeViolation, 8]; SetLabel[EUPageFlt]; drALS[0]; --1 - nargs; nargs = 1 for ifuStatus drLIB[2]; drRJNEB[popSrc, aux8, UseLabel8B[EUPageFaultBad]]; drLIQB[CardToWord[EUPageFaultAddress]]; drLIP[euMAR]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[EUPageFaultBad]]; GetYoungestPC[]; drRVADD[topDst, topSrc, const4]; SetYoungestPC[]; drRETK[377B]; --nResults -1; nResults = 0 SetLabel[EUPageFaultBad]; Pause[]; SetLabel[EUWPFlt]; drALS[0]; --1 - nargs; nargs = 1 for ifuStatus drLIB[3]; drRJNEB[popSrc, aux8, UseLabel8B[EUWPFaultBad]]; drLIQB[CardToWord[EUPageFaultAddress]]; drLIP[euMAR]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[EUWPFaultBad]]; GetYoungestPC[]; drRVADD[topDst, topSrc, const4]; SetYoungestPC[]; drRETK[377B]; --nResults -1; nResults = 0 SetLabel[EUWPFaultBad]; Pause[]; SetLabel[EUStackOverflow]; drALS[0]; --1 - nargs; nargs = 1 for ifuStatus drLIB[9]; drRJNEB[popSrc, aux8, UseLabel8B[EUStkOvfBad]]; GetYoungestPC[]; drRVADD[topDst, topSrc, const4]; SetYoungestPC[]; drRETK[377B]; --nResults -1; nResults = 0 SetLabel[EUStkOvfBad]; Pause[]; SetLabel[IFUPageFault]; drALS[377B]; --1 - nargs; nargs = 2 (return PC and ifuStatus) drLIB[10]; drRJNEB[popSrc, aux8, UseLabel8B[IFUPageFaultBad]]; GetYoungestPC[]; drLIQB[CardToWord[IFUPageFaultPC]]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[IFUPageFaultBad]]; drLRn[reg0]; SetYoungestPC[]; drEXDIS[]; drRETK[377B]; --nResults -1; nResults = 0 SetLabel[IFUPageFaultBad]; Pause[]; SetLabel[Reschedule]; drALS[377B]; --1 - nargs; nargs = 2 (return PC and ifuStatus) drLIB[11]; drRJNEB[popSrc, aux8, UseLabel8B[RescheduleBad]]; drLIB[74B]; drAND[]; --Clear RescheduleKeep and Reschedule in saved ifuStatus drLRn[reg0]; SetYoungestPC[]; drEXDIS[]; drRETK[377B]; --nResults -1; nResults = 0 SetLabel[RescheduleBad]; Pause[]; SetLabel[KFCTrap]; drLIB[12]; drRJNEB[popSrc, aux8, UseLabel8B[KFCBad]]; drDIS[]; --Discard the IFU status drLIP[ifuStatus]; drJNEBB[2B, UseLabel8B[KFCBad]]; 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]; Pause[]; 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]; Pause[]; 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]; Pause[]; 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]; Pause[]; oldPC _ GetOutputPC[area]; FillXop[0, dummy]; --opcode 0 = Pause[] FillXop[377B, dummy]; --opcode 377B = Halt[xxx] FillXop[LOOPHOLE[DragOpsCross.Inst.dKFC, CARDINAL], KFCTrap]; FillXop[1B, Xop1Trap]; FillXop[234B, Xop2Trap]; FillXop[364B, Xop3Trap]; FillXop[40B, Xop5Trap]; FillTrap[ResetTrap, start]; FillTrap[IFUStackOverflowTrap, IFUStackOverflow]; FillTrap[EUPageFault, EUPageFlt]; FillTrap[EUWriteFault, EUWPFlt]; FillTrap[AddressCheckFault, AddressCheck]; FillTrap[ALUCondOver, Overflow]; FillTrap[ALUCondBC, BoundsCheck]; FillTrap[ALUCondIL, LispNaN]; FillTrap[ModeFault, UserModeViolation]; FillTrap[EUStackOverflowTrap, EUStackOverflow]; FillTrap[IFUPageFaultTrap, IFUPageFault]; FillTrap[RescheduleTrap, Reschedule]; SetOutputPC[oldPC]; ProcedureEntry[initL, 0]; drLIB[1]; SetYoungestL[]; -- L _ 1 on return drLIB[128-16-1]; SetSPLimit[]; ProcedureExit[0]; WordAlign[area]; SetLabel[start]; drLFC[UseLabel16[initL]]; --Initialize L to 1 drASL[255]; --and S = 0. 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[const1, topSrc, topSrc]; drROR[const2, topSrc, topSrc]; drROR[const3, topSrc, topSrc]; 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]; FOR I: CARDINAL IN [0..15) DO drLC0[]; ENDLOOP; GenIFUStatus[]; GenIFUStackOverflow[]; GenSLimit[]; GenReschedule[]; GenIFUPageFault[]; GenEUPageFault[]; GenModeFaultPriority[]; GenAddressCheckPriority[]; Halt[177777B]; --Terminate here at the end of the program }; END. CÒGenTraps.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Edward Fiala March 5, 1986 10:49:41 am PST This diagnostic tests the following machine functions (** means not tested; a few more tests are in GenTraps2): 1) LIP[ifuStatus] and SIP[ifuStatus]. 2) KFC instruction. 3) RETK instruction (tested but needs thorough alpha test as per RET). 4) Registers legal and illegal in User mode. 5) Instructions legal and illegal in User mode. 6) Write addresses legal and illegal in User mode. 7) 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 user mode RADD that gets mode fault trap; on user mode WB that gets address check trap; on RB[0] that gets an EU page fault; or on an ifu page fault (ifu page fault tested in GenTraps2). 8) Verify that IFU stack overflow does not occur with 11 call stack entries on Jn, JB, JDB, JQB, JS, or RET; on RBC, QBC, or BC that do not trap. 9) 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). 10) **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 (Lizard won't allow this test). 11) 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. **Lizard gives "out of envelope" for ASL[32], so can't run the tests for 16, 32, 64, or 111. 12) Verify that EU stack overflow is lower priority than KFC, address check, bounds check, NaN, overflow, EU page fault, mode fault, and **ifu page fault traps. 13) Verify that EU stack overflow occurs with greater priority than Reschedule following a SIP which reenables interrupts (tested in GenTraps2). 14) **Verify that EU stack overflow occurs with greater priority than an ALU trap caused on the instruction following a SIP which reenables interrupts. 15) 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. 16) Verify that IFU page fault does not occur when the untaken path of a conditional jump or conditional trap lies in an undeclared page. 17) 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. **EU page fault by IOS read and IOS write isn't tested. 18) Verify that mode fault prevails over bounds check, overflow, NaN, address check, and EU page fault traps. 19) Address check prevails over EU page fault trap. 20) A reschedule trap occurs when SIP[ifuStatus] turns it on if traps are enabled; a reschedule trap does not occur if traps are disabled; if reschedule was on, it does not occur if traps are enabled and reschedule turned off concurrently. 20) **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 has no way to simulate write protect faults.) 21) **Occurrence of Reschedule trap when Reschedule is issued by the CauseReschedule IO instruction isn't tested because it is not simulated. **Note to myself: RETK executed with traps enabled which causes EU stack overflow to become true is outside the envelope, but RET which causes EU stack overflow to become true traps. When simulated correctly it terminates with HALT[177777B] at PC 4016556B, cycle 5506, Inst 1881. 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. All traps enter kernel mode, disable traps, and push the old ifuStatus onto the EU stack. 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. 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 Pause[] opcodes to fill out 6 bytes (i.e., enough for a 5-byte trapping opcode and a 1-byte Pause[] after it); then if no trap occurs, the first Pause[] after the opcode will stop simulation; or if the wrong trap occurs, the mismatch on aux8 will cause Pause[] 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. The status register has 3 two bit fields. When written, the MSB of each field controls whether the LSB of the field is to be preserved (1) or changed(0). When read, the preserve bit will always be false for userModeKeep and trapsEnabledKeep, so that writing the word back restores the state, and always true for rescheduleKeep. pad0 (0: 0..15): [0..65535] _ 0, pad1 (0:16..25): [0..1023] _ 0, userModeKeep (0:26..26): BOOL _ FALSE, userMode (0:27..27): BOOL _ FALSE, trapsEnabledKeep (0:28..28): BOOL _ FALSE, trapsEnabled (0:29..29): BOOL _ FALSE, rescheduleKeep (0:30..30): BOOL _ FALSE, reschedule (0:31..31): BOOL _ FALSE User mode can be enabled either by using SIP[IFUStatus] or RETK to change IFUStatus. In user mode, the following actions are illegal: 1) Any write of a constant or aux0 to aux7 causes a mode fault trap. 2) Any memory write to an address < 100000000B (= KernelLimit) causes an address check trap. 3) All SIPs, RETK, and LIP[IFUEldestPC] (an active operation) cause a mode fault trap. 4) IOS, IOL, 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. Enter user mode with SIP[IFUStatus] and use LIP[IFUStatus] to check result. Test ifuStatus read back against user mode + rescheduleKeep. 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. Now do memory writes at addresses which are legal (>= 100000000B) in user mode. Lizard can't handle the next two. IOS[2B] does [S] _ PRead[0 + [S], BetaZ]. Lizard can't handle the next two. Now execute all instructions legal in user mode (LRn, SRn, LRIn, SRIn, and LCn each treated as a single instruction). Return from KFC trap in Kernel mode with traps disabled. 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. RETK is illegal in user mode IOL, ION, and IOS take an AlphaBeta argument for which the low bits are specially interpreted as well as being part of the device identifier: 1xx => Kernel mode required 01x => address check x0 => read x1 => write Determine whether or not these operations get a ModeFault trap in user mode. These 3 do an Address Check and write as well as checking for kernel mode; the ModeFault trap should prevail over the AddressCheck trap. IOL and ION have an 8-bit Kernel address which always causes address check in user mode, but IOS may have a user address. Now try write references to addresses less than KernelLimit = 100000000B, which should cause an Address Check trap. 4000000B will conflict with program Remove the 2 calls from the stack Return here in Kernel mode with traps disabled. 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. Return here reducing call stack depth by 1 so KFC can get out of user mode. The following opcodes should not cause IFU stack overflow trap 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 Pause[]'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 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; 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], RET[n], and RETK[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. **Russ added a check to Lizard which makes it "outside of defined envelope" to back S into EU overflow, so I had to comment out these checks. 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]. **Lizard won't allow the 20B, 40B, 100B, or 157B tests (out of envelope if alpha >= 40B) Verify that EU stack overflow is lower priority than all other traps. EU stack overflow can happen at the onset of another trap as a result of pushing ifuStatus onto the EU stack. NaN should prevail over EU stack overflow; this is a particularly rough test because the LADD would have decremented S if it hadn't trapped and because Overflow is happening as well as NaN. Reschedule should happen here, and saving ifuStatus at the onset of the trap will make S = SLimit again, but Reschedule should prevail anyway. Reschedule trap returns here with Reschedule-waiting bit in ifuStatus turned off. Return here in Kernel mode with traps disabled. Verify the occurrence of Reschedule trap when Reschedule is requested by this processor. When the condition (TrapsEnabled & Reschedule) = TRUE as a result of SIP or RETK, Reschedule should take immediately. Return here after Reschedule has occurred. User mode keep + Traps enabled (shouldn't trap); turns off Reschedule. CauseReschedule issues the IO command which sends Reschedule to all processors, but this action isn't simulated by Lizard. No-ops while waiting for Reschedule 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, IOS read, and IOS 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. 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 IOS 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 address check, 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. Modefault prevails over address check. These can only happen concurrently when an IO instruction is executed which specifies "kernel mode required" (4B) + "address check" (2B) + "write" (1B). Return here in Kernel mode Verify that address check prevails over EU page fault. EU page fault trap has code 2 EU write protect fault trap has code 3 EU stack overflow has code 9 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. All of the EU page fault tests use the address EUPageFaultAddress. All of the IFU page fault tests try to execute an instruction at IFUPageFaultPC. KFC is used to get back into Kernel mode after testing in User mode Jump if in user mode or traps disabled Opcodes 0 and 377B are intercepted by the simulator, but make them trap to dummy here anyway. These calls to FillXop and FillTrap initialize the trap locations with JDB[trap procedure]. spLimit is set with room for 17 overflow words (just in case). Simulator execution begins here on a Reset. 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 ÊØ–81.25 in leftMargin 1.25 in rightMargin 6.0 in lineLength˜codešœ ™ Kšœ Ïmœ1™K–20 sp tabStops˜K–20 sp tabStopsšœ žœžœ˜6K–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™šÏnœžœ˜ Kšœ˜Kšœžœžœ˜K˜K˜K˜K˜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˜J˜J˜'J˜.J˜$J˜(J˜*J˜)J˜/J˜2K˜K™¨K™K™ƒK™K™ãK˜Kšœ^™^š œžœžœ˜/Kšœc˜cKšœ˜K˜K˜—Kšœ‘™‘š œžœ.˜™>J˜7J˜7J˜7J˜7J˜7J˜7J˜7J˜7J˜9J˜9J˜9J˜9J˜9J˜9J˜9J˜9J˜9J˜9J˜:J˜:J˜Jšœ.™.Jšœ ™ J˜-J˜/J˜/JšœL™LJ˜7Jšœ™J˜Jšœ Ÿ˜&J˜1Jšœ Ÿ-˜7J˜Jšœ¢™¢Jšœ'Ÿ(˜OJšœ'Ÿ˜FJšœ'Ÿ#˜JJšœˆ™ˆJšœ,Ÿ&˜RJšœ,Ÿ˜IJšœ,Ÿ.˜ZJ˜Jšœ ˜ JšœŸ(˜DJ˜Jšœy™yJšœ'Ÿ(˜OJšœ'Ÿ˜FJšœ0Ÿ#˜SJšœ2˜2Jšœ6˜6JšœB˜BJšœC˜CJšœD˜DJšœD˜DJšœ Ÿ+˜8J˜Jšœs™sJ˜J˜J˜J˜J˜J˜Jšœ#™#Jšœ˜J˜J˜Jšœ!™!Jšœ ŸJ˜WJšœ)Ÿ˜EJ˜Jšœ/™/JšœŸ˜:Jš žœžœžœžœžœ˜4K˜—K˜Kšœ˜™˜š œžœ˜ J˜J˜J˜-J˜!J˜J˜,J˜Jšœ Ÿ1˜;J˜Jšœ$˜$JšœŸ>˜LJšœ˜JšœŸ.˜AJšœ&™&Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ Ÿ ˜Jšœ"Ÿ ˜,JšœK™KJšœ.Ÿ ˜8J˜Jšœ˜Jšœ>™>J˜JšœŸ.˜AJšœ™J˜J˜J˜J˜+J˜J˜ J˜.J˜JšœJ™JJšœ7˜7J˜$J˜J˜Jšœ(Ÿ&˜NJšœŽ™ŽJšœ$˜$Jšœ#˜#JšœQ˜QJšœ=™=Jšœ!˜!Jšœ.˜.Jšœ,˜,Jšœ%˜%Jšœ@˜@Jšœ˜JšœF˜FJšœ ˜ J˜5Jšœ?™?Jšœ˜Jšœ>˜>Jšœ<˜J˜>J˜6J˜7J˜Jšœå™åJšœŸ˜9Jšœ Ÿ˜Jšœ›™›J˜J˜JšœX™XJ˜J˜J˜ J˜J˜J˜J˜J˜Kšœ´™´J˜Jšœ Ÿ ˜Kšœ Ÿ ˜J˜Jšœ(Ÿ˜EJšœŸ˜2Jšœ>˜>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šœ$Ÿ˜CK˜'Kšœ˜Kšœ(Ÿ˜@K˜K˜,K˜+K˜K˜K˜K˜*Kšœ&™&K˜8Kšœ<™KšœÀ™ÀK˜.Kšœ)Ÿ˜EK˜Kšœ™KšœŸ˜1K˜—K˜Kšœ6™6š œžœ˜$Kšœ(˜(JšœŸ˜Jšœ*Ÿ*˜TKšœ(Ÿ!˜IK˜0K˜,Kšœ)Ÿ˜EKšœ˜KšœŸ˜:K˜—J˜J˜J˜8K™Kšœ$Ÿ ˜0Kšœ™Kšœ&™&Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ#˜#Kšœ™Kšœ™Kšœ™Kšœ™Kšœ$™$Kšœ2™2Kšœ6™6Kšœ?™?J˜J˜Jšœ Ÿ$˜/J˜J˜>J˜JšœP™PJ˜#J˜:J˜J˜ JšœŸ˜*J˜#J˜J˜JšœŸ0˜>J˜™>Kšœ˜Kšœ ˜ K˜J˜Kšœ˜Kšœ+™+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˜K˜K˜KšœX™XKšœ˜Kšœ˜Kšœ˜Kšœ'™'Kš žœžœžœ žœ žœ˜/K˜J˜J˜J˜ J˜J˜J˜J˜J˜J˜JšœŸ*˜9˜K˜——Kšžœ˜—K˜—…—:Þä