<> <> <> <> 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]; <<.. something innocuous that's illegal in user mode>> 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[EUPageFault, 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 ]]; <<.. it would be nice if there were a way of generating a byte-address and word-address Data word>> <> <<>> 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.