{
LispRecl.mc
Last edit:      9-Mar-84 12:30:37 by don
}

{- - - - - - - - - - - - - - - - - - - - - - - - - -
  #      name        len-1    stk level effect   UFN table entry
172      RECLAIMCELL 0        0                  \GCRECLAIMCELL

\CDR.NIL= 200q

LISTPDTD is the DTD for type LISTP, i.e., at DTDbase + (LLSH ListType 4)


Cons pages start with two word header:
	word 0: [cnt, nxtcell]	(two 8-bit fields: count of available cells
				on this page, and word# of next free cell
				on this page)
	word 1: nextpage	(page# of next cons page) {negative if not on free chain}

If not LISTP then punt
Reclaim list:
	code←PTR:cdrcode
	if (code and 200q) = 0 then punt	[or optional: if code = 0 then punt]
	FreeListCell(PTR)
	val← deleteref(PTR:carfield)		* deleteref CAR
	if code # \CDR.NIL
	  then PTR←PTR:pagebase + (code lsh 1) * point to cdr or lvcdr
		{ if (code and 200q) = 0		* optional
		    then FreeListCell(PTR)		* cdr indirect--free cell
		    PTR← GetBasePtr(PTR)] }
	if deleteref(PTR)			* deleteref CDR
	  then val←PTR
	return val

FreeListCell(PTR):

	PAGE ← address of PTR's page
	if PAGE:Nextpage < 0 then punt	* only when page was full
	PTR:cdrcode ← PAGE:nextcell
	PAGE:nextcell ← word# of PTR
	PAGE:count ← PAGE:count + 1


How to reclaim other types, roughly (needs type table change):
	if Type bit "ok to reclaim" is off, call UFN
	store DTD:FREELST in first two words of DATUM
	store DATUM in DTD:FREELST

[not required; implemented for Listp on D0, Dorado?]

- - - - - - - - - - - - - - - - - - - - - - - - - -}

	SetTask[0];

@RECLAIMCELL:	opcode[172'b],
	TT ← 172'b, L2 ← L2.Recl,	c1;
	Xbus ← TOSH LRot12, XDisp, GOTO[NewTypC3],	c2;
{	
	NewTyp will call ufn[TT] if tos is not a valid LISP pointer (i.e. if it is larger than a 22 bit number).
	ELSE: typ increments PC by a byte, returns Q:0FF; Rx: real address of type table entry. 
}

	{fetch Type}
	MAR ← [rhRx, Rx], Rx ← ListType + 0,	c1, at[L2.Recl,10, NewTypRet];
	rhTT ← TOSH LRot0,	c2;
	Q ← MD{Type} xor Rx,	c3;

	{map PTR -- last place for fault}
	Map ← TT ← [rhTT, TOS], L0 ← L0.RedoRecl	c1;
	PC ← PC - PC16, L1 ← L1.NoFixes,	c2;
	rhRx ← Rx ← MD, XwdDisp,	c3;

	MAR ← [rhRx, TOS + 0], DISP2[ReclMap],	c1, at[L0.RedoRecl, 10, WMapFixCaller];
	Ybus ← Q - 1, PgCarryBr,	c2, at[1, 4, ReclMap];{test Type=ListP?}
	TT ← MD{CDR,,CARhi}, BRANCH[$, ReplNotListufn],	c3;{get hi cell contents}

	MAR ← [rhRx, TOS + 1],	c1;
	uCARhi ← TT, NegBr, CANCELBR[$, 2],	c2;{test if cdrcode and 200 = 0}
	Q ← MD{CARlo}, BRANCH[ReclIndufn, $],	c3;{get lo cell contents}


{SUBROUTINE?: FLC  --  FreeListCell(PTR):

	PAGE ← address of PTR's page
	if PAGE:Nextpage < 0 then punt	* only when page was full
	PTR:cdrcode ← PAGE:nextcell
	PAGE:nextcell ← word# of PTR
	PAGE:count ← PAGE:count + 1
}

{	assume real addr of PTR in rhRx  Rx TOS }
	MAR ← [rhRx, 1 + 0],	c1;
	uCARlo ← Q,	c2;
	TT ← MD{nextpage},	c3;{get wd 1 of page = nextpage}

	MAR ← [rhRx, 0 + 0],	c1;
	Ybus ← TT, NegBr,	c2;{test if nextpage < 0 : if so ufn}
	Q ← MD{cnt,,nxtcell}, BRANCH[$, ReclPgFullufn],	c3;{get wd 0 of page}

	uNxtCell ← Q,	c1;{save old nxtcell}
	TT ← TOS and 0FF,	c2;{TT ← new nxtcell}
	Q ← Q and ~0FF,	c3;{Q ← old cnt in Hi}

	Q ← TT{new nxtcell  Lo} or Q{old cnt  Hi},	c1;{merge cnt and new nxtcell}
	Q ← Q + 0FF + 1,	c2;{add 1 to old cnt}
	TT ← uNxtCell,	c3;{TT ← old nxtcell}

	MAR ← [rhRx, 0 + 0],	c1;{rewrite  cnt,,nxtcell}
	MDR ← Q,	c2;{ = cnt + 1,,new nxtcell}
	TT ← TT LRot8,	c3;{TT ← old nxtcell,,garbage}

	MAR ← [rhRx, TOS + 0],	c1;{PTR:cdrcode ← PAGE:nextcell}
	MDR ← TT, L2 ← L2.Recl1,	c2;
	uTOS ← TOS,	c3;{set tos to NIL}

	uTOSH ← TOSH,	c1;
	TOS ← uGcLov ← 0,	c2;
	TOSH ← uGcZero ← 0,	c3;

	{delref to CAR}
	{use PTR for all 24 bits}
	Rx ← uCARhi,	c1;
	TT ← uCARlo,	c2;
	Rx ← Rx and 0FF,	c3;

	Q ← Q.DelRef, CALL[GcLookup],	c1;

	Ybus ← uGcZero, ZeroBr,	c2, at[L2.Recl1, 10, GcLookRet];
	BRANCH[$, ReclLvtos1],	c3;

	TOS ← uGcLlo,	c1;
	TOSH ← uGcLhi,	c2;
	uGcZero ← 0,	c3;

ReclLvtos1:
	{delref to CDR}
	{use @PTR: for high 16 bits, cdrcode for low 8}
	{verify that not cdrnil}
	TT ← uTOS, L2 ← L2.Recl2,	c1;
	TT ← TT and ~0FF,	c2;
	Rx ← uCARhi,	c3;

	Rx ← Rx LRot8,	c1;
	Rx ← LShift1 (Rx and 07F), SE ← 0,	c2;
	Ybus ← Rx, ZeroBr,	c3;{test if cdrNIL}

	TT ← TT or Rx, BRANCH[$, ReclCdrNil]	c1;
	Rx ← uTOSH,	c2;
	Rx ← Rx and 0FF,	c3;

	Q ← Q.DelRef, CALL[GcLookup],	c1;

	Ybus ← uGcZero, ZeroBr, L3{ib's} ← 0,	c2, at[L2.Recl2, 10, GcLookRet];
	Ybus ← uGcLov{set by GcLookup}, NZeroBr,  BRANCH[ReclFixtos, $],	c3;

	Rx ← AtomGCSCAN {371'b}, BRANCH[ReclNoOvXit, ReclOvXit],	c1;

ReclFixtos:
	TOS ← uGcLlo, CANCELBR[$],	c1;
	TOSH ← uGcLhi,	c2;
ReclX1:
	Ybus ← uGcLov{set by GcLookup}, NZeroBr, L3{ib's} ← 0,	c3;

ReclX2:
	Rx ← AtomGCSCAN {371'b}, BRANCH[ReclNoOvXit, ReclOvXit],	c1;

ReclNoOvXit:
	L2 ← L2.0, IBDisp, GOTO[DNI.pc1],	c2;

ReclOvXit:
	GOTO[RplFNXIT],	c2;

{	IB ← Rx LRot0,	c3;

	MAR ← Q ← [rhS, S + 1], IBPtr ← 0, GOTO[FN1Ext],	c1;}

	GOTO[WLMapFix],	c2, at[0, 4, ReclMap];
	GOTO[WLMapFix],	c2, at[2, 4, ReclMap];
	GOTO[WLMapFix],	c2, at[3, 4, ReclMap];

ReclCdrNil:
	GOTO[ReclX1],	c2;

ReplNotListufn:
	GOTO[ufnX2],	c1;

ReclIndufn:
	GOTO[ufnX2],	c1;

ReclPgFullufn:
	GOTO[ufnX2],	c1;

	{ E N D }