{
QLispCons.mc
Created: 10-Aug-83 20:35:27 by don
Last edit: 2-Feb-84 10:41:10 by don {swapped the punt exits}
Last edit: 1-Feb-84 11:56:16 by don {comments only}
Last edit: 24-Oct-83 15:04:59 by don
}
SetTask[0];
{*******************************************************************
CONS
*******************************************************************
# 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
- - - - - - - - - - - - - - - - - - - - - - - - - -
}
{ CONS ( X , Y ) returns cons with X as car
Y is initially on top of stack
}
@CONS: opcode[32'b],
{ test if Y {top of stack} is NIL}
Ybus ← TOS or TOSH, ZeroBr, L2 ← L2.ConsNil, c1;
Q ← ConsNxtPg, BRANCH[ConsList, ConsNil], c2;
ConsNil:
CALL[ConsMapDTD], L3 ← L3.CONS, c3;
{ SUBROUTINE ConsMapDTD}
ConsMapDTD:
rhTT ← DTDspace, c1;
TT ← DTDbasePage, c2;
TT ← TT LRot8, c3;
Map ← [rhTT,TT], L0 ← L0.RedoCons1, c1;
L1 ← L1.NoFixes, c2;
Rx ← rhRx ← MD, XwdDisp{XDirtyDisp}, c3;
{ fetch ListpDTD:NextPage/Counter}
MAR ← [rhRx, Q + 0], DISP2[ConsMap1], c1,at[L0.RedoCons1,10,WMapFixCaller];
L2Disp, c2, at[PgDirty, 4, ConsMap1];
TT{NextPage/Counter} ← MD, RET[ConsMapDTDRet], c3;
Ybus ← TT{NextPage}, ZeroBr, c1,at[L2.ConsNil,10,ConsMapDTDRet];
rhTT ← TT ← TT LRot8, BRANCH[$, ConsNxtPg0], c2;
TT ← TT and ~0FF, CALL[ConsMakeCell], c3;
ConsMakeCell:
{ map it}
Map ← [rhTT,TT], L0 ← L0.RedoCons2, c1;
uAddrNewCellLo ← TT, L1 ← L1.NoFixes, c2;{u ← lo part of Vaddr of cons cell}
Rx ← rhRx ← MD, XwdDisp{XDirtyDisp}, c3;
{ get first word from cons page
this is: [count,,next]
}
ConsMakeCellnoMap:
MAR ← [rhRx, 0 + 0], DISP2[ConsMap2], c1,at[L0.RedoCons2,10,WMapFixCaller];
Rx ← Rx and ~0FF, c2, at[PgDirty, 4, ConsMap2];
TT{cnt,,next} ← MD, c3;
{ MakeConsCell}
Q{next} ← TT and 0FF, c1;
Rx ← Rx or Q, c2;{Raddr of cons cell}
TT ← TT LRot8, c3;
TT{cnt} ← TT and 0FF, c1;{TT now has cnt}
Q ← Q or uAddrNewCellLo, c2;{merge hi and lo Vaddr of cons cell}
TT{cnt-1} ← TT - 1, NegBr, c3;{test if more space}
TT ← TT LRot8, BRANCH[$, ConsNoRoom1], c1;
uNewCount ← TT, c2;
uGcLov ← 0, c3;
{ get first word of cons cell}
MAR ← [rhRx, Rx + 0], c1;
uAddrNewCellLo ← Q, c2;
Q ← MD, c3;
TT{newnext} ← Q and ~0FF, c1;
TT ← TT LRot8, c2;
Q ← uNewCount, c3;
{ rewrite first word of cons page with new [count,,nextcell]}
MAR ← [rhRx, 0 + 0], c1;
MDR ← TT{Lo: newnext} or Q{Hi: cnt-1}, L3Disp, c2;
Q ← rhTT, DISP4[CMCEarly], c3;{saves rh of Vaddr of cons cell}
{ build new cons}
{ get second word of X, put to TOS and conspage}
MAR ← [rhS, S + 0], c1, at[L3.CONS, 10, CMCEarly];
uConsTemp ← Q, c2;
TOS{X.Lo} ← MD, c3;
MAR ← [rhRx, Rx + 1], c1;
MDR ← TOS, CANCELBR[$, 2], LOOPHOLE[wok], c2;
c3;
{ get first word of X}
MAR ← [rhS, S - 1], c1;
TOSH ← 0FF, CANCELBR[$, 0], L2Disp, c2;
TOSH{X.Hi} ← MD and TOSH, RET[ConsCMCRet], c3;
{ change cdrcode to nil (= 200B), put to TOSH and conspage}
TOSH ← LShift1 TOSH, SE ← 0, c1,at[L2.ConsNil,10,ConsCMCRet];
TOSH ← RShift1 TOSH, SE ← 1, c2;
Q ← Q.AddRef, c3;
MAR ← [rhRx, Rx + 0], c1;
MDR ← TOSH, c2;
{goto AddRef X, DelRef newconscell,increment ListpDTD:counter, fix stack and exit}
{ there is one abnormal exit from this section
if entries are added to the overflow table
}
{setup for GcLookup:
Rx ← addrHi & 0FF
TT ← addrLo
uGcLov ← 0 {before first call only}
L2 ← subr #
Q ← 0 if addref, 1 if delref, 2 if stkref
Trashes rhTT and rhRx
}
ConsCom: {Q set to Q.AddRef previously}
TT ← TOS, L2 ← L2.ConsAdd, c3;
Rx ← TOSH and 0FF, CALL[GcLookup], c1;
{GcLookup Subroutine here}
{setup for GcLookup:
Rx ← addrHi & 0FF
TT ← addrLo
uGcLov ← 0 {before first call only}
L2 ← subr #
Q ← 0 if addref, 1 if delref, 2 if stkref
Trashes rhTT and rhRx
}
TT ← uAddrNewCellLo, c2,at[L2.ConsAdd,10,GcLookRet];
TOS ← TT, c3;
TOSH ← uConsTemp, c1;
c2;
Rx ← uConsTemp, L2 ← L2.ConsDel, c3;
Q ← Q.DelRef, CALL[GcLookup], c1;
{GcLookup Subroutine here}
Q ← ConsCnt, c2,at[L2.ConsDel,10,GcLookRet];
CALL[ConsMapDTD], c3;
{ increment ListpDTD:COUNTER}
MAR ← [rhRx, Q + 0], c1,at[L2.ConsDel,10,ConsMapDTDRet];
MDR ← TT + 1, c2;
S ← S - 2, c3;
TT ← TT and ~u0FFF, ZeroBr, c1;
BRANCH[ConsCntBig, ReclX1], c2;
ConsCntBig:
Rx ← AtomGCPUNT {377'b}, L3{ib's} ← 0, c3;
GOTO[ReclOvXit], c1;
{ Cons List}
ConsList:
uGcLov ← 0, L2 ← L2.ConsList, c3;
{ get real address of type table entry}
TT ← 32'b, CALL[NewTyp], c1;
{ pc bumped by one in subroutine}
{ get type table entry}
MAR ← [rhRx, Rx + 0], c1,at[L2.ConsList,10,NewTypRet];
Q ← 0FF, L3 ← L3.CONS, c2;
Rx{entry} ← MD and Q{0FF}, c3;
{ test if Y is of type list}
Ybus ← Rx xor ListType, ZeroBr, c1;
PC ← PC - PC16, BRANCH[ConsOther, $], c2;
rhTT ← TOSH LRot0, c3;
TT ← TOS and ~0FF, c1;
uTOS ← TOS, c2;
uTOSH ← TOSH, CALL[ConsMakeCell], c3;
TT ← uTOS, c1,at[L2.ConsList,10,ConsCMCRet];
TT ← TT and 0FE, c2;
TT ← TT LRot8, c3;
TOSH ← LShift1 TOSH, SE ← 0, c1;
TOSH ← TOSH or TT, c2;
TOSH ← RShift1 TOSH, SE ← 1, c3;
MAR ← [rhRx, Rx + 0], c1;
MDR ← TOSH, c2;
{setup for GcLookup:
Rx ← addrHi & 0FF
TT ← addrLo
uGcLov ← 0 {before first call only}
L2 ← subr #
Q ← 0 if addref, 1 if delref, 2 if stkref
Trashes rhTT and rhRx
}
L2 ← L2.ConsListAdd, c3;
TT ← uTOS , c1;
Rx ← uTOSH, c2;
Rx ← Rx and 0FF, c3;
Q ← Q.AddRef, CALL[GcLookup], c1;
{GcLookup Subroutine here}
Q ← Q.AddRef, GOTO[ConsCom], c2,at[L2.ConsListAdd,10,GcLookRet];
ConsMap1:
CALL[WLMapFix], c2, at[PgClean, 4, ConsMap1];
CALL[WLMapFix], c2, at[PgProt, 4, ConsMap1];
CALL[WLMapFix], c2, at[PgVacant, 4, ConsMap1];
ConsMap2:
CALL[WLMapFix], c2, at[PgClean, 4, ConsMap2];
CALL[WLMapFix], c2, at[PgProt, 4, ConsMap2];
CALL[WLMapFix], c2, at[PgVacant, 4, ConsMap2];
ConsNoRoom1:
GOTO[ufnX3], c2;
ConsNxtPg0:
GOTO[ufnX1], c3;
ConsOther: {ufn for now}
GOTO[ufnX1], c3;
{ E N D }