: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];