// Stack manipulation routines // Allegro change August 2, 1981 11:15 PM by Beau Sheil // Last change July 19, 1981 7:23 PM by Beau Sheil // Last change July 17, 1981 2:02 PM by Beau Sheil // Last change June 2, 1981 3:56 PM by Beau Sheil // Post Tone change April 5, 1981 4:42 PM by Beau Sheil get "LispBcpl.decl" get "Stats.decl" external [ // declared herein NXTUSEDSTKBLOCK; CONTEXTSWITCH // SUBRS StackOverflow // Punt Subr GetFXP // Get current frame extension @BiCall // Caller of Lisp fns GetStkBlkType // declared elsewhere @SGetBase; @SPutBase; IGetBase; IPutBase; @APutBase32 MkSmallPos; SmallUnbox WriteStatsX; RAIDCode; Usc; CallFn; CallSwat // statics @InterruptEnable; @lvNIL; @lvKT ] manifest [ StkBlkType = 0 // Offsets in stack blocks FxNxt = 4 FreeBlkLen = 1 GrdBlkLen = 1 ] // NXTUSEDSTKBLOCK is a SUBR => the low 16 bits of the stack address of // the next block that is not a free block. The intent is to skip // over the currently executing frame. Hence, we also return a free block // if we have left at least 200 (random constant) words of free space. let NXTUSEDSTKBLOCK(lvMyF) = valof [ RAIDCode ("Call to NXTUSEDSTKBLOCK") let px = SmallUnbox(lvMyF) let free = 0 px = SGetBase(px+FxNxt) // next block [ if GetStkBlkType(px) ne FreeStackBlock % Usc(free, 200) gr 0 then break let ps = SGetBase(px+FreeBlkLen) if Usc(ps, WordsPerPage) gr 0 then // split overly large free block [ let s=WordsPerPage-2 // ensure the new guard block will fit SPutBase(px+FreeBlkLen, s) px = px + s SetStkBlkType(px, GuardBlock) SPutBase(px+GrdBlkLen, ps-s) break ] free = free + ps px = px + ps ] repeat resultis MkSmallPos(px) ] and CONTEXTSWITCH(lvI) = valof // switches context I and current FXP [ let I = SmallUnbox(lvI) let newCFXP = IGetBase(IFPCurrentFXP+I) IPutBase(IFPCurrentFXP+I, IGetBase(IFPCurrentFXP)) IPutBase(IFPCurrentFXP, newCFXP) if I eq IFPKbdFXP then APutBase32 (InterruptEnable, lvKT) // turn interrupts back on resultis lvI ] // StackOverflow ensures at least N free words after current FXP, either by // collapsing free blocks and adding new stack pages, or by moving it // to another part of the stack. If the frame is copied, it will have // its quick return bit turned OFF. and StackOverflow(lvN) = RAIDCode("Stack ovflw punt") and GetFXP() = IGetBase(IFPCurrentFXP) and SetFXP(v) = IPutBase(IFPCurrentFXP, v) and BiCall(f) be // sets up stack for Bcpl to call Lisp fn f [ // no longer works let sp = GetFXP() SPutBase(sp, SGetBase(sp)%#002000) // set C bit in FXP let nx=SGetBase(sp+FxNxt) let nxsize=SGetBase(nx+FreeBlkLen) // assumes nx is free; else garbage if GetStkBlkType(nx) ne FreeStackBlock then CallSwat("No CallFn space") lp: switchon Usc(nxsize, 4) into [ case 1: [ SetStkBlkType(nx+4, FreeStackBlock) // split free block SPutBase(nx+4+FreeBlkLen, nxsize-4) endcase ] case 0: endcase // exactly enough space case -1: [ let nxnx = nx+nxsize if GetStkBlkType(nxnx) ne FreeStackBlock then CallSwat("No CallFn space") nxsize = nxsize + SGetBase(nxnx+FreeBlkLen) goto lp ] ] SPutBase(sp+FxNxt, nx+4) SPutBase(nx, ATOMspace) // push fn name atom SPutBase(nx+1, f) SPutBase(nx+2, SMALLPOSspace) // push nargs (always 0) SPutBase(nx+3, 0) let fname = vec 2; if (fname&1) ne 0 then fname=fname+1 // 2 word align fname!0 = ATOMspace; fname!1 = f CallFn(0, fname) ] and GetStkBlkType(s) = SGetBase(s+StkBlkType)&StackMask and SetStkBlkType(s, v) = SPutBase(s+StkBlkType, v)