:Title[LRETURN.mc, December 7, 1982 12:44 PM, Masinter]; *-------------------------------------------------------------------- * RETURN *-------------------------------------------------------------------- KnowRBase[LTEMP0]; top level; InsSet[LispInsSet, 1]; opRETURN: T← (fetch← TSP) - 1, FlipMemBase; LTEMP0← Md, fetch← T, T← (FXBACK[ALINK]); LTEMP1← Md, T← (PVAR) - T; fetch← T, LTEMP3← (rhmask); * get alink field LTEMP2← Md; branch[.nquick, R odd], LTEMP2, T← (LTEMP2) - (FXBACK[IVAR]); T← (fetch← T) + (FXDIF[DEFLO, IVAR]); Q← IVAR, IVAR← Md, T← (fetch← T) + 1; * new IVAR DEFLO← Md, T← (fetch← T) + (FXDIF[PC, DEFHI]); T← Md, PVAR← (fetch← T) + (FXDIF[PVAR, PC]); T← T and (LTEMP3), memBase← ifuBR; * new PVAR :if[FNStats]; BrHi← T, branch[.+2, R<0], FnStatsPtr; branch[.retstat], BrLo← DEFLO; :else; BrHi← T; BrLo← DEFLO; :endif; BrLo← DEFLO; T← ESP, PCF← Md; .finishret: LEFT← T - Q, memBase← StackBR; T← (store← Q) + 1, dbuf← LTEMP0; TSP← (store← T) + 1, dbuf← LTEMP1; LEFT← (LEFT) rsh 1; LEFT← (LEFT) - (add[LeftOffset!, 1]c), NextOpCode; :if[FNStats]; .retstat: DEFHI← T; PCF← Md, call[.storeretstat]; * finish this operation T← ESP, branch[.finishret]; :endif; IFUpause[20,1,StackM2BR,0,opReturn,noNData, 0, 0]; *-------------------------------------------------------------------- * NQUICK cases of return *-------------------------------------------------------------------- m[HardReturn, CallUFN]; .nquick: T← (PVAR) - (FXBACK[ALINK]); T← (fetch← T) + (FXDIF[CLINK, ALINK]); LTEMP2← Md, T← (fetch← T) + (FXDIF[BLINK, CLINK]); pd← (LTEMP2) - (Md) - 1, branch[.+2, R odd]; UCodeCheck[BadFrame]; branch[.+2, alu=0], LTEMP2← (LTEMP2) - 1; HardReturn; * alink#clink * LTEMP2 is returnee T← (LTEMP2) - (FXBACK[FLAGS]); fetch← T; * flagword T← Md; :if[Debugging]; LTEMP3← T and (StackMask); pd← (LTEMP3) xor (FxtnBlock); branch[.+2, alu=0]; uCodeCheck[BadFrame]; :endif; pd← T and (rhmask); branch[.+2, alu=0], T← (LTEMP2) - (FXBACK[NEXT]); HardReturn; * usecnt of returnee # 0 fetch← T, T← FreeStackBlock; LTEMP3← fetch← Md; * LTEMP3 points to returnee's next pd← T xor (Md); * T ← flags branch[.+2, alu#0], T← IVAR; branch[DORETURN]; * check for contiguous BF pd← T xor (LTEMP3); * is IVAR=returnee's next? branch[.+2, alu=0], T← (PVAR) - (FXBACK[BLINK]); HardReturn; fetch← T; T← Md; fetch← T; T← Md; pd← T and (rhmask); branch[DORETURN, alu=0]; HardReturn; DORETURN: * do return to LTEMP2 T← (PVAR) - (FXBACK[BFLAGS]); fetch← T, T← add[BfResidual!, rhmask!]c; pd← T and Md; branch[.freefx, alu=0], T← IVAR; :if[Debugging]; .checkfreebf: T← (PVAR) - (FXBACK[ALINK]); fetch← T; LTEMP3← Md; branch[.+2, R odd], LTEMP3; UCodeCheck[ShouldBeSlowFrame]; T← (PVAR) - (FXBACK[BLINK]); :else; .checkfreebf: T← (PVAR) - (FXBACK[BLINK]); :endif; fetch← T, T← (rhmask); LTEMP3← fetch← Md; * get bf flags LTEMP4← Md, pd← T and Md; branch[.nqnz, alu#0], T← (LTEMP3) + (2c); :if[Debugging]; T← (LTEMP3) + 1; T← (fetch← T) + 1; pd← (IVAR) - (Md); branch[.+2, alu=0]; uCodeCheck[IVARWRONG]; :endif; T← T - (IVAR); IVAR← (store← IVAR) + 1, dbuf← FreeStackBlock; store← IVAR, dbuf← T, branch[.clresid]; .nqnz: * leave BF alone, just decrement use count T← (LTEMP4) - 1; store← LTEMP3, dbuf← T, branch[.clresid]; .clresid: T← (PVAR) - (FXBACK[BFLAGS]); :if[Debugging]; fetch← T; LTEMP3← Md; pd←(LTEMP3) and (BFResidual); branch[.+2, alu#0]; uCodeCheck[StackBad]; nop; :endif; .freefx: * make from T to ESP into a free block ESP← (ESP) - T; T← (store← T) + 1, dbuf← FreeStackBlock; store← T, dbuf← ESP; PVAR← LTEMP2; *-------------------------------------------------------------------- RTN2: * return to frame at PVAR with LTEMP0,,LTEMP1 *-------------------------------------------------------------------- memBase← StackBR; :if[Debugging]; T← (PVAR) - (FXBACK[FLAGS]); fetch← T; T← Md; T← T and (StackMask); pd← T xor (FxtnBlock); branch[.+2, alu=0]; uCodeCheck[BadFrame]; :endif; T← (PVAR) - (FXBACK[IVAR]); T← (fetch← T) + (FXDIF[NEXT,IVAR]); IVAR← Md, fetch← T; ESP← Md; TSP← Md, fetch← Md; .extend: ESP← (fetch← ESP) + 1; T← Md; pd← T xor (FreeStackBlock); branch[.+2, alu#0], T← ESP← (fetch← ESP) - 1; ESP← (ESP) + (Md), branch[.extend]; T← (T - (TSP)) rsh 1; branch[.+2, carry], LEFT← T - (LeftOffset); uCodeCheck[noStackAtPunt]; T← (PVAR) - (FXBACK[FLAGS]); fetch← T; LTEMP2← Md; pd← (LTEMP2) and (FXInCall); branch[.retcall, alu#0], pd← (LTEMP2) and (FXNoPushReturn); branch[.nopush, alu#0], Q← TSP; T← (store← Q) + 1, dbuf← LTEMP0; TSP← (store← T) + 1, dbuf← LTEMP1; branch[.retfe2, R>=0], Left← (Left) - 1; uCodeCheck[NoStackAtPunt]; .nopush: LTEMP2← (LTEMP2) and not (FXNoPushReturn); store← T, dbuf← LTEMP2; * turn off no pushbit .retfe2: T← (PVAR) - (FXBACK[IVAR]); T← (fetch← T) + (FXDIF[DEFLO, IVAR]); IVAR← Md, T← (fetch← T) + 1; DEFLO← Md, T← (fetch← T) + (FXDIF[PC, DEFHI]); DEFHI← Md, fetch← T, T← (rhmask); DEFHI← (DEFHI) and T, memBase← ifuBR; BrHi← DEFHI; BrLo← DEFLO; PCF← Md; :if[FNStats]; branch[.+2, R<0], FnStatsPtr; call[.storeretstat]; NextOpCode; :else; nop; NextOpCode; :endif; .retcall: LTEMP2← (LTEMP2) and not (FXInCall); store← T, dbuf← LTEMP2; T← (TSP) - 1; T← (fetch← T) - 1; DEFLO← Md, T← (fetch← T) - 1; DEFHI← Md, T← (fetch← T) - 1; NARGS← Md; fetch← T; :if[Debugging]; pd← DEFHI; branch[.+2, alu=0], LTEMP0← Md; uCodeCheck[BadRetCall]; pd← (LTEMP0) xor (SmallHi); branch[.+2, alu=0]; uCodeCheck[BadRetCall]; :endif; TSP← T, branch[RESTARTCALL0];