{File name <tajo>LispGc.mc
Description:  part of DandeLion InterLisp Emulator
Author: Charnley
Last edited by Charnley: 16-Aug-83 14:39:35 
Created by Charnley: April 18, 1983  9:45 AM
}

SetTask[0];

{*******************************************************************
	GCSCAN1, GCSCAN2	1 or 2 clicks per entry
*******************************************************************}

{	GCScan opcodes:
	on entry, TOS contains (index + 1)  into the HashTable
	index is first entry tested.
	on exit, TOS contains (index) found, or NIL if table exhausted.
	GcScan1 finds (collision = 1) or (stk = cnt = 0).
	GcScan2 finds (collision = 1) or (stk = 1).
	L2 = 0 if GcScan1, L2 = 2 if GcScan2
	L1 = 0 if more to scan, L1 = 2 if on last entry
	Interrupts are tested every 256 entries if no entry found by then
}

GcScan1:
	Q ← 0, {L2 = 0 for GcScan1} GOTO[GcSCom],	c1,
opcode[173'b];
GcScan2:
	Q ← 0, L2 ← 2, {L2 ← 2 for GcScan2}	c1,
opcode[174'b];
GcSCom:	TT ← TOS - 1, NegBr, L1 ← 0,	c2;
	rhTT ← crhHashTable, BRANCH[GcScanStart, GcZero],	c3;

GcScanStart:
{	IfEqual[hashmsbit, 1,,CauseError];}
	TT ← LShift1 TT,	c1;
	TT ← RShift1 TT, getHashmsBit,	c2;
	,	c3;

	MAR ← [rhTT, TT  + 0], GOTO[GcSmarP1],	c1;

GcScanLoop:
	TT ← MAR ← [rhTT, TT - 1],	c1;
GcSmarP1:	Rx ← Q, ZeroBr, BRANCH[$, GcSPgC, 1],	c2, at[1,4,GcSDispX];
	Q ← MD, BRANCH[GcStest, GcScanLoop],	c3;

{	Through here if Entry is non-zero	}
GcStest:	Ybus ← Rx and 1, ZeroBr{test coll bit}, L2Disp,	c1;
GcST1:	Rx ← Rx LRot8, DISP2[GcSdisp],	c2;

{GcS1,coll}
	GOTO[GcScanFound],	c3,at[0,4,GcSdisp];
{GcS1,no coll}
	Ybus ← Rx - 2, PgCarryBr, L1Disp, GOTO[GcSchmore],	c3,at[1,4,GcSdisp];
GcSF:
{GcS2,coll}
	GOTO[GcScanFound],	c3,at[2,4,GcSdisp];
{GcS2,no coll}
	Ybus ← Rx and 2, ZeroBr, L1Disp, GOTO[GcSchmore],	c3,at[3,4,GcSdisp];

GcSchmore:	{passing thru here makes TT one too small}
	TT ← MAR ← [rhTT, TT - 1], DISP2[GcSDispX],	c1;
	BRANCH[GcFoundFix,GcFoundPg,1],	c2, at[0,4,GcSDispX];
	CANCELBR[GcSAllThru,2],	c2, at[3,4,GcSDispX];
	BRANCH[GcFoundFix,GcFoundPg,1],	c2, at[2,4,GcSDispX];

GcFoundFix:	TT ← TT + 1, GOTO[GcScanFound],	c3;

GcFoundPg:	TT ← TT - 0FF, GOTO[GcScanFound],	c3;

GcSPgC:	TT ← TT - 0FF - 1, CANCELBR[$],	c3; {fix TT}

	Ybus ← TT, NegBr,	c1;{test for end}
	IfEqual[hashmsbit, 1, , CauseError];
	BRANCH[GcSLastRx, $],	c2;
{	INTERRUPT TESTING DISABLED}
	GOTO[GcScanStart],	c3;


{GcSinttest:
	{gc Interrupt test here,}
	Noop,	c1;
	Q ← Rx, MesaIntBr,	c2;
	Rx ← 0, BRANCH[GcScanStart, $],	c3;

	Ybus ← uWDC, NZeroBr,	c1;
	Ybus ← uWP, ZeroBr, BRANCH[$, GcSIgnoreInt],	c2;
	uWP ← Rx, ClrIntErr, BRANCH[GcSIntHere, GcSS1],	c3;

GcSIntHere:	Rx ← 1,	c1;
	uWDC ← Rx,	c2;
	Rx ← KbdFXP, L2 ← 0, GOTO[GcSpunt],	c3;

GcSpunt:	{*****}Noop, GOTO[ufn2],	c1;

GcSIgnoreInt:	ClrIntErr, CANCELBR[GcSS1],	c3;

GcSS1:	MAR ← [rhTT, TT  + 0], GOTO[GcSmarP1],	c1;
}

GcSLastRx:
	Noop,	c3;

	Noop,	c1;
	Ybus ← Rx, ZeroBr, L1 ← 2,{L1 = 2 during last test}	c2;
	BRANCH[$, GcSExit],	c3;

	Ybus ← Rx and 1, ZeroBr, L2Disp, GOTO[GcST1],	c1;

GcZero:	{hi bit not turned on yet}
	TOS ← TT + 1, GOTO[GcSExit2],	c1;

GcScanFound:
	TOS ← TT + 1, GOTO[GcSExit2],	c1;

GcSAllThru:
	TT ← TT + 1, GOTO[GcSExit],	c3;

GcSExit:	TOS ← TT + 1, GOTO[GcSExit2],	c1;

GcSExit2:
	TOS ← LShift1 TOS,	c2;{remove high bit -- which was used for table address}
	TOS ← RShift1 TOS, SE ← 0, ZeroBr,	c3;

	BRANCH[GcSExit2X, GcSRetNIL],	c1;
GcSExit2X:
	TOSH ← smallpl, L2 ← 0, IBDisp, GOTO[DNI.pc1],	c2;

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

	{END}