<> <> <> <> <<>> DIRECTORY DragonProcessOffsets, DragOpsCross, DragOpsCrossProcess, DragOpsCrossUtils, HandCoding, HandCodingSupport, HandCodingPseudos; GenStack: CEDAR PROGRAM IMPORTS DragOpsCrossUtils, HandCoding, HandCodingSupport, HandCodingPseudos = BEGIN OPEN DragonProcessOffsets, HandCoding, HandCodingSupport, HandCodingPseudos; StackedStatusWord: TYPE = DragOpsCross.StackedStatusWord; Word: TYPE = DragOpsCross.Word; <> initialFrames: NAT = 256; <> localFrameArraySize: NAT = 16; <<# of frames in localArray>> framesToTransfer: NAT = localFrameArraySize/2; <> <<(this # should be explored)>> <<>> StackLog: NAT = 7; StackSize: NAT = 128; <> statusMask: StackedStatusWord = [userMode: TRUE, trapsEnabled: TRUE, lBase: 377B]; <> regsPerNacho: NAT = 16; RegArray: TYPE = ARRAY [0..regsPerNacho) 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 frames: GlobalArray -- space for the global pool of nachos ]; GlobalArray: TYPE = ARRAY [0..initialFrames+1] OF Nacho; <> <> StackMargin: NAT _ 17; <> <<>> <> stackUnderflowTrap: Label _ NIL; <> internalSaveEldest: Label _ NIL; <> globalFreeNacho: Label _ NIL; <> globalAllocNacho: Label _ NIL; <> <<>> StackUnderflowTrap: PROC [stackUnderflowTrap: Label] = { <> { <> <<>> underflowEntry1: Label = GenLabel[]; underflowEntry2: Label = GenLabel[]; underflowEntry3: Label = GenLabel[]; WordAlign[]; drJ1[]; <> SetLabel[stackUnderflowTrap]; MakeLabelGlobal["DragonStack.StackUnderflowTrap", stackUnderflowTrap]; <<>> <> drLFC[UseLabel16[underflowEntry1]]; <> <<[S] = new L>> drSUBB[StackMargin]; ExtractField[first: 32-StackLog, bits: StackLog]; SetSPLimit[]; <> drLFC[UseLabel16[underflowEntry2]]; <> drJB[UseLabel8A[stackUnderflowTrap]]; <> WordAlign[]; SetLabel[underflowEntry1]; <> <<>> LRegI[hook, constNRegs]; GetYoungestStatus[]; drRVSUB[belowDst, popSrc, belowSrc]; <<[S] holds the new value for L, but it needs masking.>> ExtractField[first: 32-StackLog, bits: StackLog]; PReg[temp]; <> drDUP[]; SetYoungestStatus[]; <> drRETN[]; WordAlign[]; SetLabel[underflowEntry2]; <<>> <> LRegI[hook, constLink]; <> <<[S] = next hook>> drLFC[UseLabel16[underflowEntry3]]; <> <<[S] = next hook>> WordAlign[]; SetLabel[underflowEntry3]; <> }; { <> <<[S] = next hook>> noHookLabel: Label = GenLabel[]; underflowNoSplice: Label = GenLabel[]; singleLabel: Label = GenLabel[]; multiLabel: Label = GenLabel[]; fatalLabel: Label = GenLabel[]; dispatchPC: CARD = HandCodingSupport.ReserveData[StackSize]; dispatchWord: Word = DragOpsCrossUtils.CardToWord[dispatchPC / DragOpsCross.bytesPerWord]; drRJEB[topSrc, const0, UseLabel8B[noHookLabel]]; <> drRSB[nRegsOffset]; drDUP[]; ExtractField[first: 32-StackLog, bits: StackLog]; drRJNEBJ[popSrc, const0, UseLabel8B[underflowNoSplice]]; <> <<[S] = #regs (+ status bits), but #regs = 0!>> <<[S-1] = frame to splice>> <> drRRX[topDst, belowSrc, constNRegs]; <<[S] = #regs (+ status bits) for the frame to splice>> <<[S-1] = frame to splice>> LReg[temp]; <> drSHDR[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: StackLog]]]; <> SetYoungestStatus[]; <<[S] = frame to splice, youngest status is now correct>> drDUP[]; drRRX[belowDst, topSrc, constLink]; <> <<[S] = frame to splice, [S-1] = next elder frame>> drRSB[lastPCOffset]; SetYoungestPC[]; <> <<[S] = frame to splice, [S-1] = next elder frame>> FreeNacho[]; <> <<[S] = next elder frame (next hook)>> LRegI[hook, constNRegs]; <<[S] = #regs (+ status bits) for the hook>> <<[S-1] = next hook>> drLFC[UseLabel16[underflowNoSplice]]; <> SetLabel[noHookLabel]; drLC0[]; <> WordAlign[]; SetLabel[underflowNoSplice]; <> <<[S] = #regs (+ status bits) for the hook>> <<[S-1] = next hook (may be 0)>> <> LReg[temp]; <> drSHDR[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: StackLog]]]; <> SetYoungestStatus[]; <> <<[S] = next value for hook, youngest status is now correct>> LRegI[hook, constLastPC]; SetYoungestPC[]; <<[S] = next value for hook, youngest status & PC is now correct>> LRegI[hook, constNRegs]; ExtractField[first: 32-StackLog, bits: StackLog]; <> <<[S] = #regs, [S-1] = next hook>> drLIQB[dispatchWord]; drQRX[topAtop, belowSrc]; drJSD[]; <> <<[S] = # of regs to save>> <<[S-1] = next hook>> SetLabel[singleLabel]; <> <<[S] = # of regs to restore>> <<[S-1] = next hook>> FOR i: NAT DECREASING IN [0..regsPerNacho) DO drRAI[reg1: [reg[i]], reg2: hook, disp: regOff+i]; ENDLOOP; MoveReg[topDst, hook]; FreeNacho[]; <> <<[S] = next hook>> MakeLabelGlobal["DragonStack.StackUnderflowReturn", GenLabelHere[]]; SReg[hook]; <> drRETN[]; <> SetLabel[fatalLabel]; <> Pause[]; SetLabel[multiLabel]; <> FOR i: NAT IN [0..regsPerNacho) DO drRAI[reg1: [reg[i]], reg2: hook, disp: regOff+i]; ENDLOOP; LReg[hook]; MoveRegI[hook, hook, constOthers]; <> <<[S] = nextNacho, [S-1] = #regs>> FreeNacho[]; <> <<[S] = # regs>> drAL[regsPerNacho]; drSUBB[regsPerNacho]; <> <<[S] = #regs left>> drLIQB[dispatchWord]; drQRX[topAtop, belowSrc]; drJSD[]; <> <<[S] = # of regs to save>> <<[S-1] = next hook>> { <> area: HandCodingSupport.Area _ HandCodingSupport.GetCurrentArea[]; oldPC: CARD _ HandCodingSupport.GetOutputPC[]; HandCodingSupport.SetOutputPC[dispatchPC]; FOR nr: NAT DECREASING IN [0..regsPerNacho] DO HandCodingSupport.OutputWord[area, DragOpsCrossUtils.IntToWord[singleLabel.offset+3*nr]]; ENDLOOP; FOR nr: NAT IN (regsPerNacho..regsPerNacho*4] DO HandCodingSupport.OutputWord[area, DragOpsCrossUtils.IntToWord[multiLabel.offset]]; ENDLOOP; FOR nr: NAT IN (4*regsPerNacho..StackSize) DO HandCodingSupport.OutputWord[area, DragOpsCrossUtils.IntToWord[fatalLabel.offset]]; ENDLOOP; HandCodingSupport.SetOutputPC[oldPC]; }; }; }; StackOverflowTrap: PROC [underflowLabel: Label] = { <> internalSaveSetup: Label _ GenLabel[]; exitLabel: Label _ GenLabel[]; dispatchLabel: Label = GenLabel[]; dispatchPC: CARD = HandCodingSupport.ReserveData[StackSize]; dispatchWord: Word = DragOpsCrossUtils.CardToWord[dispatchPC / DragOpsCross.bytesPerWord]; { <> ifuEntryLabel: Label = GenLabel[]; ProcedureEntry[ifuEntryLabel, 0, TRUE]; <> MakeLabelGlobal["DragonStack.IFUStackOverflowTrap", ifuEntryLabel]; FillTrap[IFUStackOverflowTrap, ifuEntryLabel]; GetEldestPC[]; drDIS[]; GetEldestStatus[]; <> <<[S] holds the eldest status>> <<>> AllocNacho[]; <> <<([S] = newBlock, [S-1] = eldest status)>> drLFC[UseLabel16[internalSaveSetup]]; <> <> <<[S] = #regs, [S-1] = eldest status>> SetLabel[dispatchLabel]; <> drLIQB[dispatchWord]; drQRX[topAtop, belowSrc]; drSFC[]; <> <> <<>> <> SetLabel[exitLabel]; MakeLabelGlobal["DragonStack.StackOverflowExit", exitLabel]; <> <<>> drLIQB[UseLabel32[underflowLabel]]; SetEldestPC[]; <> ExtractField[first: 32-StackLog, bits: StackLog]; drDUP[]; SetEldestStatus[]; <> <<>> drSUBB[StackMargin]; ExtractField[first: 32-StackLog, bits: StackLog]; SetSPLimit[]; <> MakeLabelGlobal["DragonStack.StackOverflowReturn", GenLabelHere[]]; drRETN[]; <> }; { <> euEntryLabel: Label = GenLabel[]; ProcedureEntry[euEntryLabel, 0, TRUE]; <> MakeLabelGlobal["DragonStack.EUStackOverflowTrap", euEntryLabel]; FillTrap[EUStackOverflowTrap, euEntryLabel]; GetEldestPC[]; drDIS[]; GetEldestStatus[]; <> <<[S] holds the eldest status>> { loopLabel: Label = GenLabelHere[]; <<[S] = eldest status>> AllocNacho[]; <> <<([S] = newBlock, [S-1] = eldest status)>> drLFC[UseLabel16[internalSaveSetup]]; <> <> <<[S] = #regs, [S-1] = eldest status>> drRJNEBJ[left: topSrc, right: const0, dist: UseLabel8B[dispatchLabel]]; <> drRJEBJ[popSrc, const0, UseLabel8B[loopLabel]]; <> <<[S] = eldest status>> }; }; { <> exitEntryLabel: Label = GenLabel[]; ProcedureEntry[exitEntryLabel, 0, TRUE]; <<>> GetEldestStatus[]; <> MakeLabelGlobal["DragonStack.InstallBogusFrame", exitEntryLabel]; drJB[UseLabel8A[exitLabel]]; }; { <> exitEntryLabel: Label = GenLabel[]; ProcedureEntry[exitEntryLabel, 0]; MakeLabelGlobal["DragonStack.RemoveBogusFrame", exitEntryLabel]; GetEldestPC[]; drDIS[]; GetEldestStatus[]; <> <> ProcedureExit[1]; <> }; { <> <> <> <<[S] = newBlock, [S-1] = eldest status>> <> <> <<[S] = #regs, [S-1] = eldest status>> eldestStatus: RegSpec = reg0; localHook: RegSpec = reg1; localStatus: RegSpec = reg2; ProcedureEntry[internalSaveSetup, 2]; <> LReg[hook]; drPSB[linkOffset]; <> <<[S] = localHook = newBlock; (localHook+linkOffset)^ = hook>> PReg[hook]; PReg[temp]; <> <<[S] = localHook = hook = temp = newBlock>> LReg[eldestStatus]; ExtractField[first: 32-StackLog, bits: StackLog]; SetYoungestStatus[]; <> <<[S] = localStatus = L of frame to save; [S-1] = localHook, [S-2] = eldest status>> <<(note that the status bits must be clear in [S])>> GetEldestPC[]; drSRIn[localHook, lastPCOffset]; <> <<((localHook+lastPCOffset)^ = PC of frame to save)>> GetEldestStatus[]; <> <<[S] (aka localStatus) = eldest status (the new version)>> <<[S-1] = localHook>> <<[S-2] = eldest status (the old version)>> drRVSUB[c: pushDst, a: localStatus, b: eldestStatus]; <> <<[S] = # of regs to save (with garbage in top bits)>> <<[S-1] (aka localStatus) = status>> <<[S-2] = localHook>> <<[S-3] = eldest status>> MoveReg[eldestStatus, localStatus]; <<[S] = # of regs to save (with garbage in top bits)>> <<[S-1] (aka localStatus) = eldest status (the new version)>> <<[S-2] = localHook>> <<[S-3] = eldest status (the new version)>> drSHDR[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: StackLog]]]; <> <<[S] (aka localStatus) = #regs (+ status bits)>> <<[S-1] (aka localHook)>> <<[S-2] = eldest status>> drWRI[localStatus, localHook, nRegsOffset]; <> <<(localHook+nRegsOffset)^ _ localStatus>> <<[S] = #regs, [S-1] = localHook, [S-2] = eldest status>> <<>> drSHDR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: StackLog]]]; <<[S] = #regs, [S-1] = eldest status>> ProcedureExit[2]; <> <<[S] = #regs, [S-1] = eldest status>> }; { <> singleLabel: Label = GenLabel[]; multiLabel: Label = GenLabel[]; fatalLabel: Label = GenLabel[]; shortLabel: Label = GenLabel[]; SetLabel[internalSaveEldest]; MakeLabelGlobal["DragonStack.InternalSaveEldest", internalSaveEldest]; AllocNacho[]; <> <<([S] = newBlock, [S-1] = eldest status)>> drLFC[UseLabel16[internalSaveSetup]]; <> <<[S] = #regs, [S-1] = eldest status>> drLIQB[dispatchWord]; drQRX[topAtop, belowSrc]; drJSD[]; <> <> SetLabel[singleLabel]; FOR i: NAT DECREASING IN [0..regsPerNacho) DO drWAI[reg1: [reg[i]], reg2: temp, disp: regOff+i]; ENDLOOP; drDIS[]; <> <<[S] = eldest status>> drRETN[]; <> <<[S] = eldest status>> <<>> SetLabel[fatalLabel]; <> Pause[]; <<>> SetLabel[multiLabel]; FOR i: NAT IN [0..regsPerNacho) DO drWAI[reg1: [reg[i]], reg2: temp, disp: regOff+i]; ENDLOOP; LReg[temp]; <> <<([S] = temp = oldBlock; [S-1] = #regs; [S-2] = eldest status)>> AllocNacho[]; <> <<([S] = newBlock; [S-1] = temp = oldBlock; [S-2] = #regs)>> PReg[temp]; drWSB[othersOffset]; <> <> <<(temp = (temp'+othersOffset)^ = newBlock; [S] = #regs)>> drAL[regsPerNacho]; drSUBB[regsPerNacho]; <> <<[S] = #regs, [S-1] = eldest status>> drLIQB[dispatchWord]; drQRX[topAtop, belowSrc]; drJSD[]; <> <<[S] = #regs, [S-1] = eldest status>> <<>> { <> area: HandCodingSupport.Area _ HandCodingSupport.GetCurrentArea[]; oldPC: CARD _ HandCodingSupport.GetOutputPC[]; HandCodingSupport.SetOutputPC[dispatchPC]; FOR nr: NAT DECREASING IN [0..regsPerNacho] DO HandCodingSupport.OutputWord[area, DragOpsCrossUtils.IntToWord[singleLabel.offset+3*nr]]; ENDLOOP; FOR nr: NAT IN (regsPerNacho..regsPerNacho*4] DO HandCodingSupport.OutputWord[area, DragOpsCrossUtils.IntToWord[multiLabel.offset]]; ENDLOOP; FOR nr: NAT IN (4*regsPerNacho..StackSize) DO HandCodingSupport.OutputWord[area, DragOpsCrossUtils.IntToWord[fatalLabel.offset]]; ENDLOOP; HandCodingSupport.SetOutputPC[oldPC]; }; }; }; AllocNacho: PROC = { <> exitLabel: Label = GenLabel[]; enterLabel: Label = GenLabelHere[]; LRegI[free, const0]; <> drLC0[]; <> drRJNEBJ[left: topSrc, right: belowSrc, dist: UseLabel8B[exitLabel]]; <> drLFC[UseLabel16[globalAllocNacho]]; <> drJB[UseLabel8A[enterLabel]]; <> SetLabel[exitLabel]; <> AddReg[free, const1]; <> <<[S] = 0, [S-1] = new nacho>> drPSB[othersOffset]; <> <<[S] = new nacho>> }; GlobalAllocNacho: PROC = { <> <> exitLabel: Label = GenLabel[]; globalAllocNacho _ GenLabelHere[]; MakeLabelGlobal["DragonStack.GlobalAllocNacho", globalAllocNacho]; drRRX[c: belowDst, a: base, b: popSrc]; <> <<([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]; <> <<(@base.gFree = @base.lock + 1)>> <<([S] = gFree; [S-1] = @lock)>> drLIB[framesToTransfer]; drRVSUB[free, free, popSrc]; <> 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[framesToTransfer]; <> <<([S] = new gFree; [S-1] = @lock)>> FOR i: NAT IN [0..framesToTransfer) 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)>> drLIB[framesToTransfer-1]; drRVADD[c: topDst, a: topSrc, b: free]; <<([S] = free + (framesToTransfer-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[framesToTransfer*2+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[]; underflowLabel: Label = GenLabel[]; internalSaveEldest _ GenLabel[]; <> GenFramesInit[]; drLFC[UseLabel16[continueLabel]]; <> GlobalAllocNacho[]; GlobalFreeNacho[]; StackUnderflowTrap[underflowLabel]; StackOverflowTrap[underflowLabel]; SetLabel[continueLabel]; <> drLIQB[UseLabel32[underflowLabel]]; SetYoungestPC[]; GetYoungestStatus[]; drLIQB[LOOPHOLE[DragOpsCross.StackedStatusWord[trapsEnabled: TRUE]]]; drOR[]; drDFC[UseLabel32[HandCodingPseudos.GetGlobalLabel["Basics.SetStatus"]]]; MakeLabelGlobal["DragonStack.ExitToUser", GenLabelHere[]]; }; FillTrap: PROC [tx: DragOpsCross.TrapIndex, dest: Label] = { area: HandCodingSupport.Area = HandCodingSupport.GetCurrentArea[]; oldPC: CARD = HandCodingSupport.GetOutputPC[area]; SetOutputPC[DragOpsCrossUtils.TrapIndexToBytePC[tx]]; drJDB[UseLabel16[dest]]; HandCodingSupport.SetOutputPC[oldPC]; }; END.