:TITLE[Lisp0.0mc, October 25, 1982  12:30 PM, van Melle];

* Alto mode instructions

insert[DisplayDefs];		* Get WordsPerLine definition
SetTask[0];

IMRESERVE[pgLisp0, IntfaceBase, IntfaceCnt];

LispInst:
	dispatch[PCF[IBUF], 14, 4], at[LispInstLoc];
	disp[@@Mbix], CSkipData;

*	breakpoint, mbx[12];
*	breakpoint, mbx[13];
*	breakpoint, mbx[14];
*	breakpoint, mbx[17];

@@Mbix:			* Return to Lisp with value in Ac0,1
	lspGenBrHi ← (INTERFACEspace), mbx[00];
	lspGenBr ← (INTERFACEbase);
	PFetch1[lspGenBr, lspEp, 0];	* retrieve FX from Intfacepg

	T ← AC0;	* move value to L0,1 for return
	lspL0 ← T;

* need to get WW to see if a Lisp interrupt struck while we were in AltoLand (which would be masked out of ACTIVE)

:IF[WindFlg];
	T ← (R400) or (52c);		* mds 452 = WW
	PFetch2[MDS, WW];		* fetch WW, ACTIVE
:ENDIF;

	T ← AC1, task;
	lspL1 ← T;

:IF[StatsMode];
	T ← (StatsPointerLocation);
	PFetch1[MDS, lspStatsPtr];		* Get this fetch going, too
:ENDIF;

	lspInstFlag ← (NormalState);
	MDSTypeBaseBrHi ← MDSTypeSpace;		* for type tests
	MDSTypeBaseBr ← MDSTypeBase;

:IF[WindFlg];
	WW ← (WW) and not (100000c);		* maybe don't need this
	T ← (ACTIVE) or (LispKeyMask);
	T ← (WW) and T;				* Ignore masked-out interrupts
	NWW ← (NWW) or T, goto[mbi2, R<0];	* OR waiting interrupts into NWW, skip if ints off
	   FreezeResult, call[CheckInterrupts];	* may need to set IntPending
:ENDIF;


mbi2:	lspEpHi ← (StackSpace);			* Setup constant registers
	T ← lspEpHi ← (lspEpHi) or (300c);	* StackHi in left, error value
	lspStkBrHi ← T;				* in right (for overflow case)
	lspTspHi ← T, loadpage[pgReturn];
	lspStkBr ← 0c;
onpage[pgReturn];

:IF[StatsMode];
	lu ← lspStatsPtr;		* Are stats on (this loc nonzero)?
	T ← lspEp, skip[alu#0];
	  lspStatsPtr ← (Zero) - 1;
					* set sign bit so we can test quickly
:ELSE;
	T ← lspEp;
:ENDIF;
	lspLN ← T, goto[lspRtn2];	* return to frame Ep

@@InitLispRegs:
	AC1 ← 2000c, mbx[11];
	LoadPageExternal[PNIPPage];
	T ← (AC1) or (114c), callExternal[PNIPLoc];	* MP ← 1100d
	AC1 ← IP[FFault]c;
	Stkp ← AC1;			* Address of Ffault
	T ← lspInstFlag ← 0c;
	Stack ← (Stack) or (1c);	* let emulator handle pagefault
	Stack ← (Stack) and not (20000c);	* Ignore H4 parity errors

	AC1 ← (RamRelease);
	AC1 ← (AC1) or (DolphinMcVersion), call[InitStore];
	AC1 ← (MinBcplVersion), call[InitStore];
	AC1 ← (MinLispVersion), call[InitStore];
	AC1 ← (WordsPerLine), call[InitStore];
	AC1 ← IP[StoragePages]c;
	Stkp ← AC1;
	PStore1[AC0, Stack], call[IncTRet];
	AC1 ← 400c;
	AC1 ← (AC1) or (200c), call[InitStore];	* pages per module = 600

* for most Dolphins, the 48-bit NS host number is hiding in the high 32 bits
* of ram location 7777.  High word is constant zero.

	AC1 ← Zero, call[InitStore];		* Store zero
	T ← lspL0 ← 7400c;			* low bits of T ← 0
	lspL0 ← (lspL0) or (377c), call[ReadRamInit];	* L0 ← 7777
						* Read 7777[0:15]
	PStore1[AC0, AC1, 7];
	T ← 1c, call[ReadRamInit];		* Read 7777[16:31]
	PStore1[AC0, AC1, 10], goto[NoSkipStart];


InitStore:
	PStore1[AC0, AC1];	* Store AC1 at offset T from init vector
IncTRet:
	T ← (Zero) + T + 1, return;	* T ← T+1

ReadRamInit:	* Return in AC0 the contents of location in LspL0, part by T
	APCTask&APC ← lspL0;
	ReadCS;
	T ← CSData, disptable[1,1,0];		* Even placement
	AC1 ← T, return;


lspuPCTrace:			* uPC trace, not on Dolphin
	return, mbx[15];

SkipStart:
	LoadPageExternal[nePage], gotoExternal[lneTaskSkpLoc];

NoSkipStart:
	LoadPageExternal[nePage], gotoExternal[lneTask1stLoc], at[FaultDisp, InBcplState!];

:IF[WithPilotBitBlt];
@@XBitBlt:				* No alto bitblt
	loadpageExternal[xoPage], gotoExternal[lTrapLoc], mbx[16];
:ELSE;
@@XBitBlt:				* AC0 points at a bitblt table
					* AC3 holds 2*scanlines done
	PFetch1[AC0, AC2hi, 0], mbx[16];

	T ← (PCF.WORD);
	PCB ← (PCB) + T;
	PCF ← RZero;			* update PCB, PCF

	PFetch1[AC0, AC2, 1];		* get low pointer out of bbt

		* BitBlt needs Stkp pointing at 2*scanlines done, viz. AC3
	lspL0 ← IP[AC3]c;
	Stkp ← lspL0;
	lspInstFlag ← (InAltoBitBltState);
	T ← rhmask[AC2hi];		* adjust the high pointer
	AC2hi ← (lsh[AC2hi, 10]) + T + 1;
	T ← (Cycle&PCXF) or (100000c), gotoExternal[lbbBitBltLoc];

bbPageFault:
	lspL1 ← 1c, goto[bbMExit], at[FaultDisp, InAltoBitBltState!];
lbbMesaInt:
	lspL1 ← 0c, goto[bbMExit], at[BBMesaIntLoc];
lbbMDone:
	lspL1 ← 2c, goto[bbMExit], at[BBMDoneLoc];

bbMExit:
	AC2hi ← 0c;			* restore normal AC2hi
	lspInstFlag ← (NormalState);
*****	T ← (ldf[Cycle&PCXF, 15, 2]) + T;
	T ← lspL1, gotoExternal[lBitBltDoneLoc];	* T ← skip distance
:ENDIF;

* XNOvaOps for accessing the virtual memory.  These return skipping
* on success, or not skipping if pagefault


@@BGetBase:		* AC0 ← GetBase(AC0,,AC1)
	nop, mbx[04];				* alloc constraint
	call[lspSetGBr];
	PFetch1[lspGenBr, AC0, 0];
	AC0 ← AC0, goto[SkipStart];		* wait for fault

@@BGetBase32:		* AC0,,AC1 ← GetBase32Bits(AC0,,AC1)
	nop, mbx[06];				* alloc constraint
	call[lspSetGBr];
	PFetch1[lspGenBr, AC0, 0];
	PFetch1[lspGenBr, AC1, 1];
	AC1 ← AC1, goto[SkipStart];

@@BGetBasePtr:		* AC0,,AC1 ← GetBasePtr(AC0,,AC1)
	nop, mbx[07];				* alloc constraint
	call[lspSetGBr];
	PFetch1[lspGenBr, AC1, 1];
	PFetch1[lspGenBr, AC0, 0];
	AC0 ← (AC0) and (377c), goto[SkipStart];

@@BPutBase:		* PutBase(AC0,,AC1, @AC2)
	PFetch1[AC2, lspL3, 3], mbx[05];
	call[lspSetGBr];
	PStore1[lspGenBr, lspL3, 0];
	lspL3 ← lspL3, goto[SkipStart];

@@BPutBase32:		* PutBase32Bits(AC0,,AC1, @@AC2)
	PFetch1[AC2, lspL3, 3], mbx[10];
	T ← lspL3;
	PFetch1[MDS, lspL2], call[retLBL];
	T ← (lspL3) + 1;
	PFetch1[MDS, lspL3];
	call[lspSetGBr];
	PStore2[lspGenBr, lspL2, 0];
	lspL3 ← lspL3, goto[SkipStart];

lspSetGBr:			* Load base reg LispGenBr from AC0,1
	T ← rhmask[AC0];
	lspGenBrHi ← T;
	lspGenBrHi ← (lsh[lspGenBrHi, 10]) + T + 1;
	T ← AC1;
	lspGenBr ← T, goto[retLBL];	* Wait for lspGenBr ← to finish

* VMTransferPage(toVp, FromVp)
** moves 400b words from virtual address in ac1 to that in ac0

@@VMTransferPage:
	T ← lhmask[AC0], mbx[03];
	lspL3 ← T;
	T ← lsh[AC0, 10];
	lspL2 ← T;			* L2,3 is base for page AC0 (dest)
	T ← lsh[AC1, 10];
	lspGenBr ← T;
	T ← lhmask[AC1];
	lspGenBrHi ← T;			* lspGenBr is base for page AC1 (src)
	T ← lspLN ← 374c;		* Counter/offset

xmm:	nop;				* alloc constraint
	PFetch4[lspGenBr, XBuf], call[retLBL];
	PStore4[lspL2, XBuf], call[retLBL];
	T ← lspLN ← (lspLN) - (4c);
	goto[xmm, alu>=0];
	goto[SkipStart];

* ReadFlags(Vp) -> Real Page, Flags (ref, -- , wp, dirty, ...)

@@ReadFlags:
	Loadpage[pgMapOps], mbx[01];		* alloc constraint
	UseCTask, callp[xReadFlags];		* get Rp in AC0, Flags in T
	AC1 ← T, goto[NoSkipStart];

* Lisp instructions for the same thing

@ReadFlags:
	lspUFN ← 161c, call[lspReadFlags], opcode[161];
PushTP5:					* Flags were left in T
	Stack&+1 ← T, goto[nxiLBL];

@ReadRP:
	lspUFN ← 162c, call[lspReadFlags], opcode[162];
	T ← AC0, goto[PushTP5];			* get RP, stuff it

lspReadFlags:		* Come here with lspUFN set appropriately
			* Return with Flags in T, RP in AC0, or else ufn out
	T ← Stack&-1;
	lu ← (Stack) - (smallpl);
	AC0 ← T, UseCtask, goto[xReadFlags, alu=0];
	  goto[ufnLBL];				* VP not smallpos?

* Come here with VP in AC0, returns flags in T, RP in AC0
*  UseCTask in calling instruction

xReadFlags:
	T ← APC&APCTask;
	lspL5 ← T, call[XMapAC0];	* Get info in XBuf1,2,3 complemented
	T ← lsh[XBufFC, 10];		* flags
	T ← (rhmask[XBufRow]) or T;	* Row address in RH
	XBuf ← (Zero) - 1;
	XBuf ← (XBuf) xor T;		* XBuf ← ~T = flags,,old real page#
	nop;				* is this needed?
	xmap[lspGenBr, XBuf, 0];	* Restore entry (XMap had changed it)
	XBuf ← XBuf;			* is this needed?

	T ← (XBuf) and not (170000c);	* Mask out flags to get
	Ac0 ← T;				* AC0 ← real page#
	lu ← (XBuf) and (10000c);
	XBuf ← rsh[XBuf, 1], skip[alu=0];	* Rearrange flag bits:
	 XBuf ← (XBuf) or (100000c);	* Dolphin gives LOGSE,WP,DIRTY,REF
					* Lisp wants REF,--,WP,DIRTY
	APC&APCTask ← lspL5;
	T ← (XBuf) and (130000c), return;	* T ← flags


* SetFlags(Vp, RP, flags)

@@SetFlags:
	PFetch1[AC2, XBuf1, 3], mbx[02];	* flags in XBuf1
	T ← AC1, loadpage[pgMapOps];		* RP in XBuf
	XBuf ← T, callp[WriteMap2];
	goto[NoSkipStart];

@WriteMap:
	loadpage[pgHStack], call[CheckElt3P5], opcode[163];
	T ← Stack&-1, call[WriteMap1];		* Flags
Pop2P5:	StkState ← rsh[StkState, 2], goto[nxiLBL];	* Two pops



WriteMap1:
	lu ← (Stack&-1) - (smallpl);
	XBuf1 ← T, skip[alu=0];			* XBuf1 ← flags
	  lspUFN ← 163c, goto[ufnLBL];			* not smallpos
	T ← Stack&-1;
	lu ← (Stack&-1) - (smallpl);
	XBuf ← T, skip[alu=0];			* XBuf ← RP
	  lspUFN ← 163c, goto[ufnLBL];			* not smallpos
	T ← Stack&-1;
	lu ← (Stack&+1) - (smallpl);
	AC0 ← T, skip[alu=0];			* AC0 ← VP
	  lspUFN ← 163c, goto[ufnLBL];			* not smallpos

WriteMap2:

* Now have XBuf = RP, XBuf1 = Flags, AC0 = VP

	XBuf1 ← lsh[XBuf1, 1], skip[R>=0];
	  XBuf1 ← (XBuf1) or (10000c);		* rearrange flags as needed
	T ← (XBuf1) and (70000c);
	XBuf ← (ldf[XBuf, 4, 14]) or T, goto[XMapAc0];


XmapAc0:			* Call XMap for page in AC0 using XBuf
	T ← lhmask[AC0];
	lspGenBrHi ← T;
	T ← lsh[AC0, 10];
	lspGenBr ← T;
	nop;			* is this needed?
	xmap[lspGenBr, XBuf, 0];
	XBuf ← XBuf, UseCTask, goto[retLBL];
				* Don't task while map is screwy



	:END[Lisp0];