:Title[LGC.mc, December 6, 1982  1:44 PM, Masinter];

   KnowRBase[LTEMP0];
   TOP LEVEL;
   InsSet[LispInsSet, 1];

:if[Reduced];
	UfnOps[25];
	UfnOps[24];
:else;
*--------------------------------------------------------------------
opGCREF:	* modify reference count of DATUM according to CASE
*--------------------------------------------------------------------
   T← (fetch← TSP) + 1;
   CASE← (Id) + (100000c), call[GCLOOKUP];
   pd← T, memBase← StackM2BR;
   branch[.+2, alu#0], pd← T and (htstkcnt);
	branch[.htnil];
   branch[.+2, alu#0];
	NextOpCode;

* new entry created, return NIL

.htnil:
   TSP← (store← TSP) + 1, dbuf← 0c;
   TSP← (store← TSP) - 1, dbuf← AT.NIL, NextOpCode;
   

regOP2[25, StackM2BR, opGCREF, noNData];
*--------------------------------------------------------------------
opRPLPTR:	* takes (PTR VAL) on stack, alpha byte is offset
		* replace pointer at PTR+offset with VAL, doing
		* two reference counts
*--------------------------------------------------------------------
   T← (TSP) - (4c);
   T← (fetch← T) + 1;
   T← Md, fetch← T;
   LTEMP1← (Id) + (Md);
   branch[.rplptr1, carry'], memBase← LScratchBR, LEFT← (LEFT) + 1;
	T← T + 1, branch[.rplptr1];

.rplptr1:
   BrLo← LTEMP1;
   BrHi← T;

	PAGEFAULTOK;

   T← (fetch← 0s) + 1;

* RPLPTR1: 
* call with LScratchBR pointing to cell containing old value
* T← (fetch← 0s) + 1 just done
* TSP contains new value

RPLPTR1:
   Case← 1c, call[GCLOOKUP];	* deleteref old pointer

   TSP ← (TSP) - (2c);
   memBase← StackBR;

RPLPTRTAIL:
   T← (fetch← TSP) + 1;
   Case← 0c, call[GCLOOKUP];	* addref new value

   memBase← LScratchBR;
   fetch← 0s;
   T← Md;
   T← T and (lhmask);
   T← T + (LTEMP0);		* put high bits back
   store← 0s, dbuf← T;		* store new value
   store← 1s, dbuf← LTEMP1;

GCOPTAIL:
   pd← (PSTATE) and (or[PS.HTCNTFULL!, PS.HTOVERFLOW!]c);
   branch[.+2, alu#0], PSTATE← (PSTATE) and not (PS.HTOVERFLOW);
	 NextOpCode;
   branch[.+2, alu#0], A← Id, NARGS← 1c;
      DEFLO← AT.GCSCAN, branch[DOCALLPUNT];
   PSTATE← (PSTATE) and not (PS.HTCNTFULL);
   DEFLO← AT.GCOVERFLOW, branch[DOCALLPUNT];

regOP2[24, StackBR, opRPLPTR, noNData];

*--------------------------------------------------------------------
   SUBROUTINE;
*--------------------------------------------------------------------
* called with CASE 
* T← (fetch← hi word) + 1 done
* return pointer counted in LTEMP0,,LTEMP1, with T = entry in htable

GCLOOKUP:
   T← MD, fetch← T;				* could fault

	PAGEFAULTNOTOK;

   T← T and (rhmask), LTEMP1← Md;
   memBase← tyBaseBR, LTEMP0← T, branch[.+2];

GCLOOKT1:
	* called with CASE
 	* pointer to reference in in T, LTEMP1
	* return pointer counted in LTEMP0,,LTEMP1, with T = entry in htable
   memBase← tyBaseBR, LTEMP0← T;
   T← rcy[T, LTEMP1, 11];
   fetch← T;
   PROBE← Md, memBase← htMainBR;
   branch[.+2, R>=0], pd← (PROBE) and (TT.LISPREF);
	T← A0, return;				* no reference
   branch[.+2, alu=0], T← (LTEMP1) rsh 1;
	LTEMP2← Link, branch[.htpunt];		* always do in lisp

   PROBE ← fetch ← T;				* fetch main table entry
   ENTRY ← Md, T← (LTEMP0) + (LTEMP0);
   branch[.+2, R even], pd← ENTRY;
	LTEMP2← Link, branch[.htpunt];		* collision
   branch[.htnotempty, alu#0], LTEMP2← Link;

TOP LEVEL;

   bdispatch← CASE;
   T← T or (ht1cnt), branch[.htprobe];

.htnotempty:
   T← ldf[ENTRY, 10, 1];			* get hi bits of entry
   pd← T xor (LTEMP0);				* compare hi bits of pointer
   branch[.+2, alu=0], pd← (ENTRY) + (ht1cnt);
	branch[.htpunt];			* collision

   goto[.htoverflow, carry], Link← LTEMP2;

   bdispatch← CASE;
   T← ENTRY, branch[.htprobe];

.htprobe:   DISPTABLE[5],
   T← T + (ht1cnt), branch[.htstore];		* case 0: addref
   T← T - (ht1cnt), branch[.htstore];		* case 1: delref
   T← T or (htstkbit), branch[.htstore];	* case 2: stkref

.htstore:
   LTEMP3← T and (htStkCnt);
   pd← (LTEMP3) xor (ht1cnt);

SUBROUTINE;

   branch[.+2, alu=0], Link← LTEMP2;
   store← PROBE, dbuf← T, return;
   store← PROBE, T← (dbuf← 0c), return;

.htoverflow:
   T← ENTRY, return;

TOP LEVEL;

.htpunt:
   MemBase← htOfloBR, T← A0, branch[.+2, R>=0], CASE;
	CallUFN;	* if CASE negative, do UFN if not fit

.htpuntloop:
   T← (fetch← T) + 1;
   pd← Md;
   branch[.+2, alu=0], PSTATE← (PSTATE) or (PS.HTOVERFLOW);
	T← T + 1, branch[.htpuntloop];

   LTEMP3← (store← T) - 1, dbuf← LTEMP1;
   T← LSH[CASE, 10];
   T← T + (LTEMP0);
   store← LTEMP3, dbuf← T;
 
SUBROUTINE;
   Link← LTEMP2;
   return;

:endif;	* Reduced