<> <> DIRECTORY HandCoding, HandCodingPseudos; DragonStackSave: CEDAR PROGRAM IMPORTS HandCoding, HandCodingPseudos = BEGIN OPEN HandCoding, HandCodingPseudos; RegArray: TYPE = ARRAY Reg OF Word; DumpFrame: TYPE = LONG POINTER TO DumpFrameRep; DumpFrameRep: TYPE = RECORD [ link: DumpFrame, -- link to previous frame lastPC: Word, -- continuation PC for this frame nRegs: Word, -- number of regs used for this frame at last save others: DumpFrame, -- if # NIL, then it is a pointer to an aux frame regs: RegArray -- addressable by local regs ]; regOff: CARDINAL = 4; -- offset of DumpBlock.regs LocalAllocationRep: TYPE = RECORD [ lockPtr: GlobalAllocationPtr, -- pointer to global lock for frame allocation ptrs: LocalArray -- start of frame pointers ]; LocalArray: TYPE = ARRAY [0..16] OF DumpFrame; <> <> GlobalAllocationPtr: TYPE = LONG POINTER TO GlobalAllocationRep; GlobalAllocationRep: TYPE = RECORD [ lockPtr: Word, -- pointer to global lock for frame allocation gFree: Word, -- pointer to the next free frame in frames emergency: Word, -- pointer to the emergency limit for frames (not yet used) frames: GlobalArray -- space for the global pool of dump frames ]; GlobalArray: TYPE = ARRAY [0..1024] OF DumpFrame; <> <> StackMargin: NAT _ 8; <> framesToTransfer: NAT _ 4; <> <<>> StackUnderflowTrap: PROC = { <> drLI0[]; SetInterruptEnable[]; <> RestoreStackFrame[]; <> drLI1[]; SetInterruptEnable[]; <> drSJ[]; <> }; StackOverflowTrap: PROC = { <> SaveStackFrame[]; <> drRET[]; <> }; SaveStackFrame: PROC = { <> <> <<<= 16 regs => 38+n*2 cycles.>> <<> 16 regs => 53+n*2 cycles + 1 mispredicted jump.>> <> <> shortLabel: Label = GenLabel[]; jumpLabel: Label = GenLabel[]; AllocDumpFrame[]; <> LReg[hook]; drPSB[0]; PReg[hook]; <> GetEldestPC[]; drPSB[1]; <> GetEldestNregs[]; PReg[nregs]; <> drPSB[2]; <> drLI0[]; drWSB[3]; <> <<>> drLIB[16]; drRJLEBJ[popLeft: TRUE, right: nregs, dist: UseLabel8[shortLabel]]; <> AllocDumpFrame[]; <> PReg[temp]; LReg[hook]; drWB[3]; <<(hook+3)^ _ temp, which sets the "others" field>> drLIB[16]; drRSUB[c: nregs, a: nregs, b: popSrc]; <> GetEldestRL[]; LReg[nregs]; drADD[]; SetRL[]; <> FOR i: NAT DECREASING IN [0..15] DO <> drWAI[reg1: [reg[i]], reg2: temp, disp: regOff+i]; ENDLOOP; <<>> SetLabel[shortLabel]; <> GetEldestRL[]; SetRL[]; <> drRSUB[c: pushDst, a: const0, b: nregs]; <> drRSUB[c: topDst, a: topSrc, b: nregs]; <> drRSUB[c: topDst, a: topSrc, b: nregs]; <> IndexedJump[jumpLabel]; <> FOR i: NAT DECREASING IN [0..15] DO <> drWAI[reg1: [reg[i]], reg2: hook, disp: regOff+i]; ENDLOOP; SetLabel[jumpLabel]; FlushEldest[]; <> }; RestoreStackFrame: PROC = { <> <> <<<= 16 regs => 35+n cycles.>> <<> 16 regs => 47+n cycles + 1 mispredicted jump.>> shortLabel: Label = GenLabel[]; jumpLabel: Label = GenLabel[]; MoveRegI[nregs, hook, const2]; <> MoveRegI[temp, hook, const3]; LReg[temp]; <> drRJEBJ[popLeft: TRUE, right: const0, dist: UseLabel8[shortLabel]]; <> GetRL[]; drADDNB[NegByte[16]]; SetRL[]; <> FOR i: NAT DECREASING IN [0..15] DO <> drRAI[reg1: [reg[i]], reg2: temp, disp: regOff+i]; ENDLOOP; FreeDumpFrame[]; drLIB[16]; drRADD[c: nregs, a: nregs, b: popSrc]; <> SetLabel[shortLabel]; <> MoveReg[temp, hook]; MoveRegI[hook, hook, const0]; <> GetRL[]; drRSUB[c: topDst, a: topSrc, b: nregs]; <> drDUP[]; SetRL[]; <> drADDNB[NegByte[StackMargin]]; GetSPLimit[]; <> drRSUB[c: pushDst, a: const0, b: nregs]; <> drRSUB[c: topDst, a: topSrc, b: nregs]; <> drRSUB[c: topDst, a: topSrc, b: nregs]; <> IndexedJump[jumpLabel]; <> FOR i: NAT DECREASING IN [0..15] DO <> drRAI[reg1: [reg[i]], reg2: temp, disp: regOff+i]; ENDLOOP; SetLabel[jumpLabel]; FreeDumpFrame[]; LRegI[temp, const1]; <> }; AllocDumpFrame: PROC = { <> <> exitLabel: Label = GenLabel[]; retryLabel: Label = GenLabelHere[]; LRegI[free, const0]; AddReg[free, const1]; <> drRJNEBJ[right: const0, dist: UseLabel8[exitLabel]]; <> drRFX[c: topDst, a: base, b: topSrc]; <> SubReg[free, const1]; <> drCST[c: topDst, a: const0, b: process]; <> drJCST[UseLabel8[retryLabel]]; <> LRegI[base, const0]; drRSB[1]; <> FOR i: NAT IN [0..framesToTransfer) DO drRSB[i]; <> drRSD[c: free, b: free, a: popSrc]; <<(free _ free - 1)^ _ [S]; S _ S - 1>> ENDLOOP; drADDB[framesToTransfer]; <> drPSB[1]; <> drLI0[]; drWSB[0]; <> drJB[UseLabel8[retryLabel]]; <> SetLabel[exitLabel]; <> }; FreeDumpFrame: PROC [] = { <> <> exitLabel: Label = GenLabel[]; retryLabel: Label = GenLabelHere[]; drRSUB[c: pushDst, a: free, b: const1]; <> drRJNEBJ[popLeft: TRUE, right: base, dist: UseLabel8[exitLabel]]; <> LRegI[base, const0]; <> drCST[c: topDst, a: const0, b: process]; <> drJCST[UseLabel8[retryLabel]]; <> LRegI[base, const0]; drRSB[1]; <> drADDNB[NegByte[framesToTransfer]]; <> FOR i: NAT IN [0..framesToTransfer) DO LRegI[free, const0]; AddReg[free, const1]; drPSB[i]; <<(gFree+i)^ _ free^; free _ free + 1>> ENDLOOP; drPSB[1]; <> drLI0[]; drWSB[0]; <> SetLabel[exitLabel]; <> drRSD[c: free, b: free, a: temp]; <<(free _ free - 1)^ _ temp>> }; END.