DIRECTORY DragOpsCross, DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport, Rope; GenQuickTest: CEDAR PROGRAM IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport = BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport; instrSize: AuxRegSpec = [aux[10]]; -- must contain the length of trapping instructns underflowHandler: AuxRegSpec = [aux[12]]; All: PROC = { Global: PROC[name: Rope.ROPE, label: Label] RETURNS[Label] = {MakeLabelGlobal[name, label]; RETURN[label]}; StackedStatusToWord: PROC [ s: DragOpsCross.StackedStatusWord, sense: {normal, complemented} _ normal ] RETURNS [ w: DragOpsCross.Word ] = TRUSTED {w _ LOOPHOLE[s]; IF sense = complemented THEN w _ DragOpsCrossUtils.DragNot[w]}; GenEnableTraps: PROC RETURNS [ enableTraps: Label ] = { enableTraps _ GenLabelHere[]; drLIQB[StackedStatusToWord[[trapsEnabled: TRUE]]]; drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD]; drOR[]; drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD]; drRETN[]}; GenLSUnderflowKernel: PROC RETURNS [ lsUnderflowKernel: Label ] = { underflowTrap: Label; lsUnderflowKernel _ GenLabelHere[]; -- one frame on IFU stack drLIB[sLimitValue]; drSIP[DragOpsCross.ProcessorRegister[ifuSLimit].ORD]; GetEldestPC[]; -- pops IFU stack to EU stack top drSFC[]; -- Call caller's return PC (underflowTrap pushed onto IFU stack) underflowTrap _ GenLabelHere[]; -- no frames on stack drROR[c: pushDst, a: const0, b: underflowHandler]; drSFC[]; drJB[UseLabel8A[underflowTrap]]}; SetSizeForStandardTrapInstr: PROC[instr: DragOpsCross.Inst] = { drLIB[InstToBytes[instr]]; drROR[c: instrSize, a: popSrc, b: const0]}; GenStandardTrap: PROC RETURNS [ standardTrap: Label ] = { standardTrap _ GenLabelHere[]; drRADD[c: pushDst, a: const0, b: const0]; -- save carry on stack GetYoungestPC[]; drRVADD[c: topDst, a: instrSize, b: topSrc]; SetYoungestPC[]; drRUADD[c: topDst, a: popSrc, b: constN1]; -- restore carry, toss result drRETN[]}; GenCallerTrap: PROC RETURNS [ callerTrap: Label ] = { ReturnPatch: Label; callerTrap _ GenLabelHere[]; drLIQB[StackedStatusToWord[[trapsEnabled: TRUE], complemented]]; drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD]; drAND[]; -- clear trapsEnabled drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD]; drLIQB[UseLabel32[ReturnPatch _ GenLabel[]]]; SetYoungestPC[]; -- move caller's PC to within our trap handler drRETN[]; SetLabel[ReturnPatch]; drRETN[]}; GenXOPTrap: PROC RETURNS [ xopTrap: Label ] = { xopTrap _ GenLabelHere[]; drRETN[]}; GenKFCTrap: PROC RETURNS [ kfcTrap: Label ] = { kfcTrap _ GenLabelHere[]; drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD]; drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD]; drRETN[]}; GenReschedTrap: PROC RETURNS [ reschedTrap: Label ] = { reschedTrap _ GenLabelHere[]; drRETN[]}; FillTrap: PROC [ trap: DragOpsCross.TrapIndex, label: Label ] = { oldPC: LONG CARDINAL = GetOutputPC[]; SetOutputPC[DragOpsCrossUtils.TrapIndexToBytePC[trap]]; drJDB[UseLabel16[label]]; -- go to trap handler SetOutputPC[oldPC]}; FillXOP: PROC [ inst: DragOpsCross.Inst, label: Label ] = { oldPC: LONG CARDINAL = GetOutputPC[]; SetOutputPC[DragOpsCrossUtils.XopToBytePC[inst]]; drJDB[UseLabel16[label]]; -- go to trap handler SetOutputPC[oldPC]}; area: Area = GetCurrentArea[]; curPC: CARD; sLimitValue: [0..128) = 16; EnableTraps: Label = Global["EnableTraps", GenEnableTraps[]]; LSUnderflowKernel: Label = Global["LSUnderflowKernel", GenLSUnderflowKernel[]]; StandardTrap: Label = Global["StandardTrap", GenStandardTrap[]]; CallerTrap: Label = Global["CallerTrap", GenCallerTrap[]]; XopTrap: Label = Global["XopTrap", GenXOPTrap[]]; KFCTrap: Label = Global["KFCTrap", GenKFCTrap[]]; ReschedTrap: Label = Global["ReschedTrap", GenReschedTrap[]]; Data: Label = Global["Data", GenLabel[]]; SFCITarget: Label = Global["SFCITarget", GenLabel[]]; SFCITargetLocM4wds: Label = Global["SFCITargetLocM4wds", GenLabel[]]; Start: Label = Global["Start", GenLabel[]]; ALUOverflow: Label = Global["ALUOverflow", GenLabel[]]; ALUOverflowWCry: Label = Global["ALUOverflowWCry", GenLabel[]]; CondJumps: Label = Global["CondJumps", GenLabel[]]; CondJump0: Label = Global["CondJump0", GenLabel[]]; CondJump1: Label = Global["CondJump1", GenLabel[]]; CondJump2: Label = Global["CondJump2", GenLabel[]]; CondJump3: Label = Global["CondJump3", GenLabel[]]; IncompleteLIQB: Label = Global["IncompleteLIQB", GenLabel[]]; EUPageFaultCode: Label = Global["EUPageFaultCode", GenLabel[]]; EUPageFaultContinue: Label = Global["EUPageFaultContinue", GenLabel[]]; SFCITest: Label = Global["SFCITest", GenLabel[]]; SFCIPageFaultContinue: Label = Global["SFCIPageFaultContinue", GenLabel[]]; FaultingLocation: Label = Global["FaultingLocation", GenLabel[]]; CSTProcedure: Label = Global["CSTProcedure", GenLabel[]]; CSTPageFaultReturn: Label = Global["CSTPageFaultReturn", GenLabel[]]; CST0: Label = Global["CST0", GenLabel[]]; CST1: Label = Global["CST1", GenLabel[]]; CST2: Label = Global["CST2", GenLabel[]]; CST3: Label = Global["CST3", GenLabel[]]; SLimitProcedure0: Label = Global["SLimitProcedure0", GenLabel[]]; SLimitProcedure1: Label = Global["SLimitProcedure1", GenLabel[]]; SLimitEnd: Label = Global["SLimitEnd", GenLabel[]]; IFUUnderFlowReturn: Label = Global["IFUUnderFlowReturn", GenLabel[]]; IFUOverExit: Label = Global["IFUOverExit", GenLabel[]]; IFUOverNext: Label; XOPBegin: Label = Global["XOPBegin", GenLabel[]]; XOPExit: Label = Global["XOPExit", GenLabel[]]; KernalToUserJmp: Label = Global["KernalToUserJmp", GenLabel[]]; KernalToUserMode: Label = Global["KernalToUserMode", GenLabel[]]; FillTrap[IFUPageFaultTrap, CallerTrap ]; FillTrap[MapFault, CallerTrap ]; FillTrap[IFUStackOverflowTrap, CallerTrap ]; FillTrap[EUStackOverflowTrap, CallerTrap ]; FillTrap[ALUCondOver, StandardTrap ]; FillTrap[ModeFault, StandardTrap ]; FillTrap[MemAccessFault, StandardTrap ]; FillTrap[IOAccessFault, StandardTrap ]; FillTrap[RescheduleTrap, ReschedTrap ]; FillTrap[ResetTrap, Start ]; FOR inst: DragOpsCross.Inst IN DragOpsCross.Inst DO FillXOP[inst: inst, label: (IF inst=dKFC THEN KFCTrap ELSE XopTrap)]; ENDLOOP; WHILE GetOutputPC[area] MOD 4*DragOpsCross.bytesPerWord # 0 DO OutputByte[area, CardToByte[0]]; ENDLOOP; SetLabel[ Data ]; [] _ ReserveData[words: 16]; SetLabel[ SFCITargetLocM4wds ]; THROUGH [0..3) DO OutputWord[area, IntToWord[0]] ENDLOOP; THROUGH [0..3) DO OutputByte[area, CardToByte[0]] ENDLOOP; drLIQB[UseLabel32[ SFCITarget ]]; SetLabel[ Start ]; -- gets here from reset in kernel mode with traps off drLFC[UseLabel16[ LSUnderflowKernel ]]; drRSUB[ c: constN1, a: const0, b: const1]; drRADD[ c: constN2, a: constN1, b: constN1]; drLC1[]; drLIQB[CardToWord[FieldDescriptorToCard[[insert: FALSE, mask: 32, shift: 31]]]]; drFSDB[0]; -- Load field unit control drRFU[c: constNI, a: popSrc, b: const0]; -- 80000000x drLFC[UseLabel16[ EnableTraps ]]; -- inst 12 SetLabel[ ALUOverflow ]; drRADD[c: pushDst, a: const0, b: const0]; -- clear carry drDIS[]; drRADD[c: pushDst, a: constNI, b: const0]; -- shouldn't overflow drDIS[]; SetSizeForStandardTrapInstr[dRADD]; drRADD[c: pushDst, a: constNI, b: constN1]; -- should overflow drDIS[]; drRADD[c: pushDst, a: const0, b: const0]; -- show carry drDIS[]; SetLabel[ ALUOverflowWCry ]; drRUADD[c: pushDst, a: constN1, b: constN1]; -- set carry drDIS[]; drRADD[c: pushDst, a: constNI, b: constN1]; -- shouldn't overflow drDIS[]; drRUADD[c: pushDst, a: constN1, b: constN1]; -- set carry drDIS[]; SetSizeForStandardTrapInstr[dRADD]; drRADD[c: pushDst, a: constNI, b: constN2]; -- should fail drDIS[]; drRADD[c: pushDst, a: const0, b: const0]; -- show carry drDIS[]; SetLabel[ CondJumps ]; drRJEBJ[ left: const0, right: const0, dist: UseLabel8B[ CondJump1 ]]; drDIS[]; Halt[113]; SetLabel[ CondJump0 ]; drDIS[]; Halt[114]; SetLabel[ CondJump1 ]; drRJNEBJ[ left: const0, right: const0, dist: UseLabel8B[ CondJump0 ]]; drRJEB[ left: const0, right: const0, dist: UseLabel8B[ CondJump3]]; drDIS[]; Halt[115]; SetLabel[ CondJump2 ]; drDIS[]; Halt[116]; SetLabel[ CondJump3 ]; drRJNEB[ left: const0, right: const0, dist: UseLabel8B[ CondJump2]]; drJ1[]; drLFC[UseLabel16[ IncompleteLIQB ]]; drLFC[UseLabel16[ EUPageFaultCode]]; drJDB[UseLabel16[ EUPageFaultContinue]]; SetLabel[ EUPageFaultCode]; drLIB[0]; drSIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- clear euMAR drLIQB[UseLabel32[ IncompleteLIQB ]]; drSHR[FieldDescriptorToCard[[mask: 32-2, shift: 32-2]]]; -- byte to word address WHILE GetOutputPC[area] MOD DragOpsCross.bytesPerWord # 3 DO drJ1[]; -- Align with respect to word boundary ENDLOOP; drRB[20]; -- generates page fault, sets euMAR to faulting address drRADD[c: pushDst, a: constNI, b: constNI]; -- generates arithmetic overflow Halt[131]; -- should never get here SetLabel[ EUPageFaultContinue ]; drLIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- show euMAR drDIS[]; SetLabel[ SFCITest ]; drLIQB[UseLabel32[ SFCITargetLocM4wds ]]; drSHR[FieldDescriptorToCard[[mask: 32-2, shift: 32-2]]]; -- byte to word address drDUP[]; drLIB[4]; drWSB[0]; -- force prior reject drADDB[4]; drSFCI[]; -- force reject within SFCI drJDB[UseLabel16[ SFCIPageFaultContinue ]]; SetLabel[ SFCITarget ]; drLIQB[UseLabel32[ FaultingLocation ]]; -- as if there were a Data word here drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address drSFCI[]; -- generates page fault, sets euMAR to faulting address drRADD[c: pushDst, a: constNI, b: constNI]; -- generates arithmetic overflow Halt[134]; SetLabel[ SFCIPageFaultContinue ]; drLIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- show euMAR drDIS[]; drLFC[UseLabel16[ CSTProcedure ]]; drJDB[UseLabel16[ CSTPageFaultReturn ]]; ProcedureEntry[label: CSTProcedure, args: 0]; drLIQB[UseLabel32[ Data ]]; drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address drLIB[1]; drSRIn[reg0, 0]; drLIB[2]; -- proposed new value drLIB[1]; -- proposed old value drCST[0]; -- should succeed drJEBBJ[lit: 1, dist: UseLabel8B[ CST0 ]]; -- sampled value Halt[141]; SetLabel[ CST0 ]; drLRIn[reg0, 0]; drJEBBJ[lit: 2, dist: UseLabel8B[ CST1 ]]; Halt[143]; SetLabel[ CST1 ]; drDIS[]; drDIS[]; drLIB[3]; -- proposed new value drLIB[1]; -- proposed old value drCST[0]; -- should fail drJEBBJ[lit: 2, dist: UseLabel8B[ CST2 ]]; -- sampled value Halt[144]; SetLabel[ CST2 ]; drLRIn[reg0, 0]; drJEBBJ[lit: 2, dist: UseLabel8B[ CST3 ]]; Halt[146]; SetLabel[ CST3 ]; drDIS[]; drDIS[]; drDIS[]; drLIQB[UseLabel32[ IncompleteLIQB ]]; drSHR[FieldDescriptorToCard[[mask: 30, shift: 32-2]]]; -- byte to word address drLIB[3]; -- proposed new value drLIB[1]; -- proposed old value WHILE GetOutputPC[area] MOD DragOpsCross.bytesPerWord # DragOpsCross.bytesPerWord-1 DO drJ1[]; -- Align to last byte in a word ENDLOOP; drCST[20]; -- generates page fault drRADD[c: pushDst, a: constNI, b: constNI]; -- generates arithmetic overflow Halt[147]; -- should never get here SetLabel[ CSTPageFaultReturn ]; drLIP[DragOpsCross.ProcessorRegister[euMAR].ORD]; -- show euMAR drDIS[]; drDIS[]; drDIS[]; drDIS[]; drLFC[UseLabel16[ SLimitProcedure0 ]]; drJDB[UseLabel16[ SLimitEnd ]]; ProcedureEntry[label: SLimitProcedure0, args: 0]; drLFC[UseLabel16[ SLimitProcedure1 ]]; ProcedureExit[rets: 0]; SetLabel[ SLimitProcedure1 ]; drLIB[0]; FOR i: [0..32) IN [0..32) DO drLIB[2*(i+1)]; ENDLOOP; Halt[151]; -- should have trapped on EU overflow by now SetLabel[ SLimitEnd ]; drLIQB[UseLabel32[ IFUUnderFlowReturn ]]; drROR[c: underflowHandler, a: const0, b: popSrc]; drRETN[]; SetLabel[ IFUUnderFlowReturn ]; drLFC[UseLabel16[ EnableTraps ]]; -- underflow handler sends control w/ traps off drLFC[UseLabel16[ IFUOverNext _ GenLabel[] ]]; drJDB[UseLabel16[ IFUOverExit ]]; FOR level: [2..11) IN [2..11) DO SetLabel[ IFUOverNext ]; drLFC[UseLabel16[ IFUOverNext _ GenLabel[] ]]; drRETN[]; ENDLOOP; SetLabel[ IFUOverNext ]; drLFC[UseLabel16[ IFUOverNext _ GenLabel[] ]]; -- BOOM! - zzzzzzzzzzzzzzzzzz Halt[161]; SetLabel[ IFUOverNext ]; Halt[162]; -- too deep SetLabel[ IFUOverExit ]; SetLabel[ XOPBegin ]; OutputByte[NIL, CardToByte[1B]]; -- one-byte XOP OutputByte[NIL, CardToByte[077B]]; -- five-byte XOP OutputAlphaBetaGammaDelta[NIL, CardToWord[12345678H]]; -- this gets pushed drLIQB[CardToWord[12345678H]]; drRJEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[ XOPExit ]]; Halt[191]; SetLabel[ XOPExit ]; drJDB[UseLabel16[ KernalToUserJmp ]]; SetLabel[ KernalToUserMode ]; -- kernel mode => user mode drLIQB[StackedStatusToWord[[userMode: TRUE, trapsEnabled: TRUE], complemented]]; drLIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD]; drAND[]; drLIQB[StackedStatusToWord[[userMode: TRUE, trapsEnabled: TRUE]]]; drOR[]; drSIP[DragOpsCross.ProcessorRegister[ifuYoungestL].ORD]; drRETN[]; SetLabel[ KernalToUserJmp ]; SetSizeForStandardTrapInstr[ dROR ]; -- 3, LIPs and SIPs need J1 after drLFC[UseLabel16[ KernalToUserMode ]]; drLIB[1]; -- for the store, never used drSIP[07FH]; -- ModeFault drJ1[]; -- skipped on trap return drDIS[]; -- the 1 above drLIP[1]; drDIS[]; drLIP[DragOpsCross.ProcessorRegister[ifuEldestPC].ORD]; -- Mode Fault drJ1[]; -- skipped on trap return drROR[c: const1, a: const0, b: const0]; -- Mode Fault drKFC[]; -- test KFC drROR[c: [aux[0]], a: const0, b: const0]; -- Mode Fault drROR[c: [aux[15]], a: const0, b: const0]; -- Mode Fault Halt[0FFFFH]; -- end of test { bpp: NAT _ DragOpsCross.bytesPerPage; curPC _ GetOutputPC[area]; SetOutputPC[curPC+((2*bpp-4-(curPC MOD bpp)) MOD bpp), area]; SetLabel[ IncompleteLIQB ]; OutputByte[area, CardToByte[DragOpsCross.Inst[dLIQB].ORD]]; -- 4 bytes in this page OutputByte[area, CardToByte[1]]; OutputByte[area, CardToByte[2]]; OutputByte[area, CardToByte[3]]; -- Aprez moi, le faux page! SetLabel[ FaultingLocation ]}; }; END. ‚GenQuickTest.mesa written by McCreight, 28 Sept 85 McCreight, September 11, 1986 6:50:15 pm PDT Don Curry November 15, 1986 7:31:37 pm PST Ed Fiala May 5, 1987 2:23:19 pm PDT Changed EUPageFault to MapFault. UnderflowHandler must have been set. Returns to successor of faulting instr. InstrSize must have been set to the faulting instruction size Enters with faulting instr on ifu stack top and caller of faulting instr underneath. Object is to replace faulting instr pc with that of ReturnPatch, do a return to ReturnPatch, which then returns to the caller. .. something innocuous that's illegal in user mode M A I N L I N E C O D E Data Set up Data area Align to quadword boundary .. it would be nice if there were a way of generating a byte-address and word-address Data word Start Set up EU SLimit and install IFU stack underflow service routine (kernel mode, traps off) Set up some constant registers Enable traps ALU Overflow Conditional Jumps IFU page faulting. EU Page Fault. Test SFCI with rejects Test conditional store Skip over this CST[#0] test until it gets implemented SetLabel[ CSTPageFaultReturn ]; drDIS[]; drDIS[]; drDIS[]; Test S register limiting. Test manual IFU stack entry and underflow. Test IFU stack overflow. XOP Switch to user mode Try several kernel-only instructions from user mode End of test Instruction sequence for IFU page fault test... Κ―˜šœ™Jšœ ™ J™,Icode™*K™D—J˜šΟk ˜ Jšœ ˜ J˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜J˜—šΟn œœ˜JšœD˜KJšœœœE˜QJ˜Jšœ&Οc1˜Wšœ)˜)J˜—Jšžœœ˜ ˜šžœœ œœ ˜J™J˜ Jšœ˜—šœ Οbœ˜J˜—šœ žΠbn ‘œ˜Jšœœ œ˜9Jšœœ!œ˜:Jšœ‘ œ˜!Jšœ_™_J˜——Jš ™™Jšœ ‘œŸ5˜H—J™šœY™Y™Jšœ‘œ˜'——J™šœ™™J˜+J˜,Jšœ˜Jšœ1œ˜PJšœ Ÿ˜&Jšœ)Ÿ ˜6—J˜—™ ˜Jšœ‘ œŸ ˜,—J˜—šœ ™ J™šœ ‘ œ˜Jšœ*Ÿ˜8J˜Jšœ+Ÿ˜@J˜Jšžœ˜#Jšœ,Ÿ˜>J˜Jšœ*Ÿ ˜7J˜—J™šœ ‘œ˜Jšœ-Ÿ ˜9J˜Jšœ,Ÿ˜AJ˜Jšœ-Ÿ ˜9J˜Jšžœ˜#Jšœ,Ÿ˜:J˜Jšœ*Ÿ ˜7J˜——J™™J™šœ ‘ œ˜Jšœ8‘ œ˜FJšœ˜Jšœ ˜ —šœ ‘ œ˜Jšœ˜Jšœ ˜ —šœ ‘ œ˜Jšœ8‘ œ˜FJšœ7‘ œ˜DJšœ˜Jšœ ˜ —šœ ‘ œ˜Jšœ˜Jšœ ˜ —šœ ‘ œ˜Jšœ8‘ œ˜EJ˜J™——™™Jšœ‘œ˜$J™——™™Jšœ‘œ˜$Jšœ‘œ˜(J˜šœ ‘œ˜Jšœ ˜ Jšœ,œŸ˜@Jšœ‘œ˜%Jšœ9Ÿ˜PJ˜—šœœ˜