<> <> <> <> <<>> DIRECTORY DragonProcessOffsets, DragOpsCross, DragOpsCrossProcess, DragOpsCrossUtils, HandCoding, HandCodingSupport, HandCodingPseudos; GenStack: CEDAR PROGRAM IMPORTS DragOpsCrossUtils, HandCoding, HandCodingSupport, HandCodingPseudos = BEGIN OPEN DragonProcessOffsets, HandCoding, HandCodingSupport, HandCodingPseudos; CARD: TYPE = LONG CARDINAL; Word: TYPE = DragOpsCross.Word; enableTrapsLit: DragOpsCross.Word = LOOPHOLE[ DragOpsCross.IFUStatusRec[trapsEnabled: TRUE]]; <> initialFrames: NAT = 256; <> localFrameArraySize: NAT = 16; <<# of frames in localArray>> <<>> StackLog: NAT = 7; <> emptyFrameLimit: NAT = 1; <> RegArray: TYPE = ARRAY Reg OF Word; Nacho: TYPE = LONG POINTER TO NachoRep; NachoRep: TYPE = RECORD [ link: Nacho, -- link to previous frame lastPC: Word, -- continuation PC for this frame nRegs: Word, -- number of regs used for this frame at last save others: Nacho, -- if # NIL, then it is a pointer to an aux frame regs: RegArray -- addressable by local regs ]; linkOffset: NAT = 0; constLink: ConstSpec = const0; lastPCOffset: NAT = 1; constLastPC: ConstSpec = const1; nRegsOffset: NAT = 2; constNRegs: ConstSpec = const2; othersOffset: NAT = 3; constOthers: ConstSpec = const3; 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..localFrameArraySize] OF Nacho; <> <> GlobalAllocationPtr: TYPE = LONG POINTER TO GlobalAllocationRep; GlobalAllocationRep: TYPE = RECORD [ lock: Word, -- global spin 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 nachos ]; GlobalArray: TYPE = ARRAY [0..initialFrames+1] OF Nacho; <> <> StackMargin: NAT _ 17; <> framesToTransfer: NAT _ 4; <> <<>> <> stackUnderflowTrap: Label _ NIL; <> internalSaveEldest: Label _ NIL; <> globalFreeNacho: Label _ NIL; <> globalAllocNacho: Label _ NIL; <> <<>> StackUnderflowTrap: PROC = { <> stackUnderflowTrap: Label = GenLabel[]; <> setupLabel: Label = GenLabel[]; restoreLabel: Label = GenLabel[]; freeRoutineLabel: Label = GenLabel[]; badLabel: Label = GenLabel[]; notSingleLabel: Label = GenLabel[]; faultLabel: Label = GenLabel[]; flushLabel: Label = GenLabel[]; shortLabel: Label = GenLabel[]; framedLabel: Label = GenLabel[]; area: HandCodingSupport.Area = HandCodingSupport.GetCurrentArea[]; SetLabel[notSingleLabel]; <> SetEldestPC[]; SetEldestL[]; SetLabel[faultLabel]; <> Pause[]; <<>> SetLabel[stackUnderflowTrap]; <> MakeLabelGlobal["DragonStack.StackUnderflowTrap", stackUnderflowTrap]; FillTrap[IFUPageFaultTrap, stackUnderflowTrap]; <> GetYoungestPC[]; drJNEBB[17, UseLabel8B[faultLabel]]; drLIB[19]; SetYoungestPC[]; GetEldestL[]; GetEldestPC[]; drDUP[]; -- so we don't lose it if things are bad drJNEBB[19, UseLabel8B[notSingleLabel]]; <> <<>> drRRX[topDst, hook, constLastPC]; SetEldestPC[]; <> drDUP[]; SetEldestL[]; <> drLIB[16]; LRegI[hook, constNRegs]; <> <<([S] = #regs, [S-1] = 16)>> MoveReg[temp, hook]; <> MoveRegI[hook, hook, constLink]; <> <<>> drRJLEBJ[left: topSrc, right: belowSrc, dist: UseLabel8B[shortLabel]]; <> { < 16, so dump the first 16.>> loopLabel: Label = GenLabelHere[]; <<>> <> FOR i: NAT IN [0..15] DO drRAI[reg1: [reg[i]], reg2: temp, disp: regOff+i]; ENDLOOP; LReg[temp]; MoveRegI[temp, temp, constOthers]; <> <<([S] = nextNacho; [S-1] = #regs; [S-2] = 16)>> FreeNacho[]; <> drAL[16]; drSUBB[16]; <> drRJGB[left: topSrc, right: belowSrc, dist: UseLabel8B[loopLabel]]; <> }; SetLabel[shortLabel]; <> { <> jumpLabel: Label = GenLabel[]; drRVADD[c: belowDst, a: topSrc, b: topSrc]; <<([S] = #regs; [S-1] = 2*#regs)>> drRVADD[c: belowDst, a: belowSrc, b: belowSrc]; <<([S] = #regs; [S-1] = 4*#regs)>> drRVSUB[c: belowDst, a: popSrc, b: belowSrc]; <<([S] = -3*#regs)>> IndexedJump[dest: jumpLabel]; <> FOR i: NAT DECREASING IN [0..15] DO drRAI[reg1: [reg[i]], reg2: temp, disp: regOff+i]; ENDLOOP; SetLabel[jumpLabel]; LReg[temp]; FreeNacho[]; <> }; { <> noFrameLabel: Label = GenLabel[]; <> THROUGH [0..emptyFrameLimit) DO HandCoding.drRJEB[left: const0, right: hook, dist: UseLabel8B[noFrameLabel]]; <> LRegI[hook, constNRegs]; HandCoding.drRJNEBJ[left: const0, right: popSrc, dist: UseLabel8B[noFrameLabel]]; <> drDUP[]; LRegI[hook, constLastPC]; <> SetEldestPC[]; SetEldestL[]; <> LReg[hook]; MoveRegI[hook, hook, constLink]; <> FreeNacho[]; <> ENDLOOP; SetLabel[noFrameLabel]; MakeLabelGlobal["DragonStack.StackUnderflowExit", noFrameLabel]; <<[S] has L for eldest frame on IFU stack, [S-1] has the saved status>> drLIB[17]; SetEldestPC[]; <> { <> noHookLabel: Label = GenLabel[]; drDUP[]; <<[S] = [S-1] = L for eldest frame in IFU stack>> drRJEB[left: const0, right: hook, dist: UseLabel8B[noHookLabel]]; LRegI[hook, constNRegs]; drSUB[]; SetLabel[noHookLabel]; ExtractField[first: 32-StackLog, bits: StackLog]; SetEldestL[]; <> }; <<>> drSUBB[StackMargin]; ExtractField[first: 32-StackLog, bits: StackLog]; SetSPLimit[]; <> drALS[0]; <> MakeLabelGlobal["DragonStack.StackUnderflowReturn", GenLabelHere[]]; drRETK[377B]; <> }; }; StackOverflowTrap: PROC = { <> exitLabel: Label _ GenLabel[]; { <> ifuEntryLabel: Label = GenLabel[]; ProcedureEntry[ifuEntryLabel, 1]; <> MakeLabelGlobal["DragonStack.IFUStackOverflowTrap", ifuEntryLabel]; FillTrap[IFUStackOverflowTrap, ifuEntryLabel]; GetEldestPC[]; drDIS[]; <> <<>> drLFC[UseLabel16[internalSaveEldest]]; <> <<>> drJB[UseLabel8A[exitLabel]]; }; { <> euEntryLabel: Label = GenLabel[]; ProcedureEntry[euEntryLabel, 1]; <> MakeLabelGlobal["DragonStack.EUStackOverflowTrap", euEntryLabel]; FillTrap[EUStackOverflowTrap, euEntryLabel]; GetEldestPC[]; drDIS[]; <> { loopLabel: Label = GenLabelHere[]; drLFC[UseLabel16[internalSaveEldest]]; <> LRegI[hook, constNRegs]; drRJEB[left: popSrc, right: const0, dist: UseLabel8B[loopLabel]]; <> }; }; { <> SetLabel[exitLabel]; MakeLabelGlobal["DragonStack.StackOverflowExit", exitLabel]; <<>> GetEldestL[]; <> <<>> drLIB[17]; SetEldestPC[]; <> LRegI[hook, constNRegs]; drRVSUB[topDst, belowSrc, topSrc]; ExtractField[first: 32-StackLog, bits: StackLog]; SetEldestL[]; <> <<>> drSUBB[StackMargin]; ExtractField[first: 32-StackLog, bits: StackLog]; SetSPLimit[]; <> MakeLabelGlobal["DragonStack.StackOverflowReturn", GenLabelHere[]]; drRETK[377B]; <> }; }; InternalSaveEldest: PROC = { <> setupLabel: Label = GenLabel[]; { <> <> <<[S] = newBlock; [S-1] = PC for dummy frame; hook = frame chain>> <> <<[S] = #regs; [S-1] = 16; L = L of frame to save>> localHook: RegSpec = reg0; localNRegs: RegSpec = reg1; ProcedureEntry[setupLabel, 1]; <> LReg[hook]; drPSB[linkOffset]; <> <<([S] = localHook = newBlock; (localHook+linkOffset)^ = hook)>> PReg[hook]; PReg[temp]; <> <<([S] = localHook = hook = temp = newBlock)>> GetEldestL[]; drDUP[]; SetYoungestL[]; <> <<([S] = localNRegs = L of frame to save; [S-1] = localHook)>> GetEldestPC[]; drSRIn[localHook, lastPCOffset]; <> <<((localHook+lastPCOffset)^ = PC of frame to save)>> GetEldestL[]; drRVSUB[c: localNRegs, a: popSrc, b: localNRegs]; <> <<([S] = localNRegs = eldestL - localNRegs'; [S-1] = localHook)>> ExtractField[first: 32-StackLog, bits: StackLog]; <> <<([S] = localNRegs = #regs = (eldestL - localNRegs') MOD StackSize)>> <<>> drWRI[localNRegs, localHook, nRegsOffset]; <> <<(localHook+nRegsOffset)^ = localNRegs>> <<>> drLIB[16]; SReg[localHook]; <<([S] = #regs; [S-1] = 16)>> drRETN[]; <> }; { <> shortLabel: Label = GenLabel[]; SetLabel[internalSaveEldest]; MakeLabelGlobal["DragonStack.InternalSaveEldest", internalSaveEldest]; AllocNacho[]; <> <<([S] = newBlock)>> drLFC[UseLabel16[setupLabel]]; <> <<([S] = #regs; [S-1] = 16)>> drRJLEBJ[left: topSrc, right: belowSrc, dist: UseLabel8B[shortLabel]]; <> {loopLabel: Label = GenLabelHere[]; <<>> < 16, so dump the first 16. The save block to use has already been allocated, and its address is in temp.>> FOR i: NAT IN [0..15] DO drWAI[reg1: [reg[i]], reg2: temp, disp: regOff+i]; ENDLOOP; LReg[temp]; <> <<([S] = temp = oldBlock; [S-1] = #regs; [S-2] = 16)>> AllocNacho[]; <> <<([S] = newBlock; [S-1] = temp = oldBlock; [S-2] = #regs; [S-3] = 16)>> PReg[temp]; drWSB[othersOffset]; <> <> <<(temp = (temp'+othersOffset)^ = newBlock; [S] = #regs; [S-1] = 16)>> drAL[16]; drSUBB[16]; <> <<([S] = #regs; [S-1] = 16)>> drRJGB[left: topSrc, right: belowSrc, dist: UseLabel8B[loopLabel]]; <> }; <<>> SetLabel[shortLabel]; <<(#regs IN [0..16]; [S] = #regs; [S-1] = 16)>> { <> jumpLabel: Label = GenLabel[]; drRVADD[c: belowDst, a: topSrc, b: topSrc]; <<([S] = #regs; [S-1] = 2*#regs)>> drRVADD[c: belowDst, a: belowSrc, b: belowSrc]; <<([S] = #regs; [S-1] = 4*#regs)>> drRVSUB[c: belowDst, a: popSrc, b: belowSrc]; <<([S] = -3*#regs)>> IndexedJump[jumpLabel]; <> FOR i: NAT DECREASING IN [0..15] DO <> drWAI[reg1: [reg[i]], reg2: temp, disp: regOff+i]; ENDLOOP; SetLabel[jumpLabel]; }; drRETN[]; <> }; }; AllocNacho: PROC = { <> exitLabel: Label = GenLabel[]; enterLabel: Label = GenLabelHere[]; LRegI[free, const0]; <> drRJNEBJ[left: topSrc, right: const0, dist: UseLabel8B[exitLabel]]; <> drLFC[UseLabel16[globalAllocNacho]]; <> drJB[UseLabel8A[enterLabel]]; <> SetLabel[exitLabel]; <> AddReg[free, const1]; <> drLC0[]; drPSB[othersOffset]; <> }; GlobalAllocNacho: PROC = { <> <> exitLabel: Label = GenLabel[]; globalAllocNacho _ GenLabelHere[]; MakeLabelGlobal["DragonStack.GlobalAllocNacho", globalAllocNacho]; drRRX[c: topDst, a: base, b: const0]; <> <<([S] = @lock)>> LReg[process]; <> <<([S] = process; [S-1] = @lock)>> drLC0[]; <> <<([S] = 0; [S-1] = process; [S-2] = @lock)>> {retryLabel: Label = GenLabelHere[]; drCST[0]; <> <<([S] = sample; [S-1] = 0; [S-2] = process; [S-3] = @lock)>> drRJNEB[left: popSrc, right: belowSrc, dist: UseLabel8B[retryLabel]]; <> <<([S] = 0; [S-1] = process; [S-2] = @lock)>> drAS[256-2]; <> <<([S] = @lock)>> }; SubReg[free, const4]; <> drRSB[1]; <> <<(@base.gFree = @base.lock + 1)>> <<([S] = gFree; [S-1] = @lock)>> FOR i: NAT IN [0..framesToTransfer) DO drRSB[i]; LReg[free]; drWB[i]; <<(free+i)^ _ (gFree+i)^>> ENDLOOP; drADDB[framesToTransfer]; <> <<([S] = new gFree; [S-1] = @lock)>> drPSB[1]; <> <<([S] = @lock)>> drLC0[]; drWSB[0]; <> <<(stack is now at original level)>> drRETN[]; }; FreeNacho: PROC [] = { <> exitLabel: Label = GenLabel[]; enterLabel: Label = GenLabelHere[]; drRVSUB[c: pushDst, a: free, b: const1]; <<[S] = free-1; [S-1] = nacho to free>> drRJNEBJ[left: topSrc, right: base, dist: UseLabel8B[exitLabel]]; <> drLFC[UseLabel16[globalFreeNacho]]; <> SetLabel[exitLabel]; <> PReg[free]; drWB[0]; <<(free _ [S])^ _ [S-1]; S_S-2>> }; GlobalFreeNacho: PROC = { <> <<>> <> globalFreeNacho _ GenLabelHere[]; MakeLabelGlobal["DragonStack.GlobalFreeNacho", globalFreeNacho]; drRRX[c: topDst, a: base, b: const0]; <> <<([S] = @lock)>> LReg[process]; <> <<([S] = process; [S-1] = @lock)>> drLC0[]; <> <<([S] = 0; [S-1] = process; [S-2] = @lock)>> <<>> {retryLabel: Label = GenLabelHere[]; drCST[0]; <> <<([S] = sample; [S-1] = 0; [S-2] = process; [S-3] = @lock)>> drRJNEB[left: popSrc, right: belowSrc, dist: UseLabel8B[retryLabel]]; <> <<([S] = 0; [S-1] = process; [S-2] = @lock)>> drAS[256-2]; <> <<([S] = @lock)>> }; drRSB[1]; <> <<([S] = gFree; [S-1] = @lock)>> drSUBB[4]; <> <<([S] = new gFree; [S-1] = @lock)>> FOR i: NAT IN [0..4) DO LReg[free]; drRB[i]; drPSB[i]; <<(gFree+i)^ _ (free+i)^>> ENDLOOP; drPSB[1]; <> <<([S] = @lock)>> drLC0[]; drWSB[0]; <> <<(stack is now at original level)>> drRVADD[c: pushDst, a: free, b: const3]; <<([S] = free + (4-1))>> <> drRETN[]; }; GenFramesInit: PROC = { allocator: Label = HandCodingPseudos.GetGlobalLabel["Basics.AllocVector"]; rZero: RegSpec = reg0; rLB: RegSpec = reg1; -- base of local frame table rSB: RegSpec = reg2; -- base of shared frame table tPtr: RegSpec = reg3; -- pointer to next slot in global table drLC0[]; -- init rZero drLIB[SIZE[LocalAllocationRep]/2]; drLFC[UseLabel16[allocator]]; drROR[base, topSrc, const0]; <> <> drLIDB[4+4+initialFrames]; drLFC[UseLabel16[allocator]]; drWRI[rSB, rLB, 0]; <> <> drWRI[rZero, rSB, 0]; drWRI[rZero, rSB, 2]; <> drRVADD[pushDst, rSB, const3]; drWRI[tPtr, rSB, 1]; <> <> {loopLabel: Label = GenLabelHere[]; drLIB[20]; drLFC[UseLabel16[allocator]]; drSRIn[tPtr, 0]; <> drRVADD[tPtr, tPtr, const1]; drLRn[tPtr]; drSUBDB[initialFrames]; drRJNEBJ[left: popSrc, right: rSB, dist: UseLabel8B[loopLabel]]; <> }; drLIB[17]; drRADD[free, base, popSrc]; drWRI[rZero, rLB, 17]; <> <> drAS[256-4]; <> }; All: PROC = { continueLabel: Label = GenLabel[]; internalSaveEldest _ GenLabel[]; <> GenFramesInit[]; drLFC[UseLabel16[continueLabel]]; <> GlobalAllocNacho[]; GlobalFreeNacho[]; InternalSaveEldest[]; StackUnderflowTrap[]; StackOverflowTrap[]; SetLabel[continueLabel]; <> drLIB[17]; SetYoungestPC[]; EnableTraps[]; MakeLabelGlobal["DragonStack.ExitToUser", GenLabelHere[]]; }; FillTrap: PROC [tx: DragOpsCross.TrapIndex, dest: Label] = { area: HandCodingSupport.Area = HandCodingSupport.GetCurrentArea[]; oldPC: INT = HandCodingSupport.GetOutputPC[area]; SetOutputPC[DragOpsCrossUtils.TrapIndexToBytePC[tx]]; drJDB[UseLabel16[dest]]; HandCodingSupport.SetOutputPC[oldPC]; }; END.