{
dbLispRplCons.mc
Created:   26-Nov-84 16:03:47 by don
Last edit:    4-Dec-84 11:08:53 by don
Last edit:    4-Dec-84 11:08:53 by Mitch - daybreakified %M

}

SetTask[0];

#LispRplCons:

{
- - - - - - - - - - - - - - - - - - - - - - - - - -
  #      name        len-1    stk level effect   UFN table entry
 46      RPLCONS     0        -1                 \RPLCONS

takes two args (LST ITEM):

check	(LISTP LST)
	LST's pages CNT field # 0 (see CONS below), 
	LST's cdrcode = 200q.
call UFN if any of these are not true

MAKECONSCELL on LST's page
store ITEM as in cell, with cdr code = 200q (\CDR.NIL)

store as LST's new cdrcode (((LOLOC newcell) and 377) rsh 1) + 200q.

ADDREF item
increment LISTPDTD:COUNTER
return new cell

[not required; in D0, Dorado?]

- - - - - - - - - - - - - - - - - - - - - - - - - -
  #      name        len-1    stk level effect   UFN table entry
 32      CONS        0        -1                 CONS

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)

DTDs (data type descriptors) have (ucode relevant fields in caps)
	word 0:	NAME
	word 1:	SIZE
	words 2,3:	FREE
	words 4,5:	descrs
	words 6,7:	tyspecs
	words 10,11:	POINTERS
	words 12,13:	oldcnt
	word 14:	COUNTER
	word 15:	NEXTPAGE

\CDR.NIL= 200q

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


Subroutine MAKECONSCELL[page] (given page, return new cell from it):
	new cell is at page + page:nxtcell
	new CNT is old CNT - 1; punt if CNT was zero
	new NXTCELL is new cell's cdr code


Subroutine NEXTCONSPAGE:
	if LISTPDTD:NEXTPAGE # 0 then return it, else punt
	(lisp code scans for page with cnt>1)

CONS(X Y) // note: this may not be right. Check sources for truth
If Y is NIL:
	get NEXTCONSPAGE
	MAKECONSCELL on it
	store new cell with \CDR.NIL in cdrcode (hi byte)
	X in rest of cell

Elseif Y is a listp and the CNT in Y's page > 0, then
	MAKECONSCELL[Y's page]
	store X as CAR, CDR code = ([(LOLOC Y) and 377q] rsh 1) + 200q

Else:
	get NEXTCONSPAGE
	MAKECONSCELL on it
	store Y in new cell (hi byte 0)
	(remember this as Z)

	MAKECONSCELL on same page
	store X in new cell, with hi byte= [(LOLOC Z) and 377q] rsh 1

ADDREF X
ADDREF Y
increment LISTPDTD:COUNTER
DELREF result

- - - - - - - - - - - - - - - - - - - - - - - - - -
}

{	start by verifying that tos-1 is a LISTP 
}


@RPLCONS:	opcode[46'b],
	MAR ← [rhS, S - 1], L3 ← L3.RPLCONS,	c1;
	rhRx ← crhTypeTable, CANCELBR[rplTypC3, 2],	c2;



	uTT ← TT,	c1, at[L3.RPLCONS, 10, rpls];{uTT ← high data of old cell}
	TT ← TT LRot8,	c2;
	TT ← TT xor 200'b,	c3;

	Ybus ← TT - 1, PgCarryBr, L1 ← L1.NoFixes,	c1;{test if old cell cdrcode = 200'b}
	BRANCH[$, rplcNot200ufn],	c2;
	TT ← uTOSm1,	c3;{Lo 16 bits of old cell VA}

	TT ← TT and ~0FF,	c1;{mid 8 bits of cell VA}
	uAddrNewCellLo ← TT,	c2;{uAddrNewCellLo ← mid 8 bits of cell VA}
	Xbus ← PgDirty {%M}, XDisp, CALL[ConsMakeCellnoMap],	c3;


		at[L3.RPLCONS, 10, CMCEarly],
{	store new value into new cell }
	TT ← LShift1 TOSH and 0FF,	c1;
	TT ← RShift1 TT, SE ← 1,	c2;{tos hi with cdrcode = 200'b}
	,	c3;

	MAR ← [rhRx, Rx + 0],	c1;
	MDR ← TT,	c2;{tos hi with cdrcode = 200'b}
	TT ← uTT,	c3;{hi data of old cell}

	MAR ← [rhRx, Rx + 1],	c1;
	MDR ← TOS, CANCELBR[$, 2], LOOPHOLE[wok],	c2;{tos lo}
{	change cdr code of old cell to RSH1(loloc new cell) + 200'b }
	TT ← TT and 0FF,	c3;{lo half of hi 16 bits of old cell} 

	Rx ← RShift1 Rx and 0FF,	c1;{lo 8 bits of new cell addr RSH 1}
	Rx ← Rx or 080,	c2;{add 200'b}
	Rx ← Rx LRot8,	c3;{move to hi 8 bits}

	TT ← TT or Rx,	c1;{new hi 16 bits for old cell}
	Rx ← uSavAddr,	c2;{lo 16 bits old cell RA}
	,	c3;

	MAR ← [rhRx, Rx + 0],	c1;
	MDR ← TT,	c2;{new high contents for old cell}

{	set tos to be new cell }
	uTOS ← TOS,	c3;{uTOS ← old tos lo}

	Q ← TOSH and 0FF,	c1;
	uTOSH ← Q,	c2;{uTOSH ← old tos hi and 0FF}
	TOS ← uAddrNewCellLo,	c3;{lo 16 bits of new cell VA}

	TOSH ← uTOSHm1,	c1;{high 8 bits cell VA}
	{setup for GcLookup:
	  Rx ← addrHi & 0FF
	  TT ← addrLo
	  uGcLov ← 0 {before first call only}
	  L2 used for return via GcLookRet {to c2}
	  Q ← Q.AddRef or Q.DelRef
	  Trashes rhTT and rhRx
	  }
{	AddRef to item = tos}
	Rx ← uTOSH, L2 ← L2.ConsDel{share exit},	c2;{old tos hi and 0FF}
	TT ← uTOS,	c3;{old tos lo}

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


rplcNot200ufn:
	GOTO[ufnX1],	c3;

	{ E N D }