{	LispNoProlog.mc
by don:  16-Apr-85 14:49:02
}

{
Copyright 1985 Xerox Corporation.  All rights reserved.
    This is unpublished proprietary software and or documentation.
    Information contained here is proprietary to Xerox and is for Xerox internal use and is furnished to others only under a confidential disclosure agreement.
}

{
Read a Prolog Pointer - 52d  64q
Read a Prolog Tag      - 53d  65q
Write Pointer and Tag- 54d  66q
Write Pointer and Zero Tag - 55d  67q
Prolog Opcode Dispatch - 34d  42q
}

Set[L0.PrologOpFetch, 07];

{	Lisp microcode of functions required by Prolog }

{	Read a Prolog Pointer   4 clicks}
{	tos contains UaddrLo,,UaddrHi as a smallp
	returns low 24 bits of contents
}

@PROLOGREADPTR:	opcode[64'b],
	Xbus ← TOS LRot12, XDisp, L2 ← L2.ReadUHi,	c1;
	Ybus ← TOS, AltUaddr, L2Disp, DISP4[ReadSomeU],	c2;
	TT ← UPblock0, RET[ReadSomeUret],	c*, at[00, 10, ReadSomeU];
	TT ← UPblock1, RET[ReadSomeUret],	c*, at[01, 10, ReadSomeU];
	TT ← UPblock2, RET[ReadSomeUret],	c*, at[02, 10, ReadSomeU];
	TT ← UPblock3, RET[ReadSomeUret],	c*, at[03, 10, ReadSomeU];
	TT ← UPblock4, RET[ReadSomeUret],	c*, at[04, 10, ReadSomeU];
	TT ← UPblock5, RET[ReadSomeUret],	c*, at[05, 10, ReadSomeU];
	TT ← UPblock6, RET[ReadSomeUret],	c*, at[06, 10, ReadSomeU];
	TT ← UPblock7, RET[ReadSomeUret],	c*, at[07, 10, ReadSomeU];
	TT ← UPblock8, RET[ReadSomeUret],	c*, at[08, 10, ReadSomeU];
	TT ← UPblock9, RET[ReadSomeUret],	c*, at[09, 10, ReadSomeU];
	TT ← UPblockA, RET[ReadSomeUret],	c*, at[0A, 10, ReadSomeU];
	TT ← UPblockB, RET[ReadSomeUret],	c*, at[0B, 10, ReadSomeU];
	TT ← UPblockC, RET[ReadSomeUret],	c*, at[0C, 10, ReadSomeU];
	TT ← UPblockD, RET[ReadSomeUret],	c*, at[0D, 10, ReadSomeU];
	TT ← UPblockE, RET[ReadSomeUret],	c*, at[0E, 10, ReadSomeU];
	TT ← UPblockF, RET[ReadSomeUret],	c*, at[0F, 10, ReadSomeU];

	TOSH ← TT and 0FF,	c1, at[L2.ReadUHi, 10, ReadSomeUret];
	TOS ← TOS LRot8,	c2;
	Xbus ← TOS LRot12, XDisp, L2 ← L2.ReadULo,	c3;

	Ybus ← TOS, AltUaddr, L2Disp, DISP4[ReadSomeU],	c1;
{	TT ← UPblockN, RET[ReadSomeUret],	c*;}
	TOS ← TT,	c3, at[L2.ReadULo, 10, ReadSomeUret];

	PC ← PC + PC16, GOTO[IB.nop],	c1;

{	Read a Prolog Tag   2 clicks }
{	tos contains UaddrLo,,UaddrHi as a smallp
	returns high 8 bits of contents as a smallp
}
@PROLOGREADTAG:	opcode[65'b],
	Xbus ← TOS LRot12, XDisp, L2 ← L2.ReadUTag,	c1;
	Ybus ← TOS, AltUaddr, L2Disp, DISP4[ReadSomeU],	c2;
{	TT ← UPblockN, RET[ReadSomeUret],	c*;}

	TOS ← TT and ~0FF,	c1, at[L2.ReadUTag, 10, ReadSomeUret];
	TOS ← TOS LRot8, L2 ← L2.0, IBDisp, GOTO[DNI.pc1],	c2;

{	Write a Prolog Pointer and Tag   7 clicks }
{	tos contains 24 bit ptr to be stored
	tos-1 contains 8 bit tag to be stored as a smallp
	tos-2 contains UaddrLo,,UaddrHi as a smallp
	returns UaddrLo,,UaddrHi as a smallp
}
@PROLOGWRITETAGPTR:	opcode[66'b],
	MAR ← [rhS, S + 0],	c1;
	S ← S - 2,	c2;
	TT ← MD{tag},	c3;

	TT ← TT and 0FF,	c1;
	TT ← TT LRot8,	c2;
	TOSH ← TT or TOSH, GOTO[@PROLOGWRITE0PTR],	c3;

{	OPTIONAL for Lisp-Prolog-Emulator speed   5 clicks }
{	Write a Prolog Pointer and set Tag to zero }
{	tos contains low 24 bits to be stored
	tos-1 contains UaddrLo,,UaddrHi as a smallp
	returns UaddrLo,,UaddrHi as a smallp
}
@PROLOGWRITE0PTR:	opcode[67'b],
	MAR ← [rhS, S + 0],	c1;
	,	c2;
	Rx ← MD{uaddrs},	c3;

PWriteTail:
	Xbus ← Rx LRot12, XDisp, L2 ← L2.WriteUhi,	c1;
	Ybus ← Rx, AltUaddr, L2Disp, DISP4[WriteSomeU],	c2;
	UPblock0 ← TOSH, RET[WriteSomeUret],	c*, at[00, 10, WriteSomeU];
	UPblock1 ← TOSH, RET[WriteSomeUret],	c*, at[01, 10, WriteSomeU];
	UPblock2 ← TOSH, RET[WriteSomeUret],	c*, at[02, 10, WriteSomeU];
	UPblock3 ← TOSH, RET[WriteSomeUret],	c*, at[03, 10, WriteSomeU];
	UPblock4 ← TOSH, RET[WriteSomeUret],	c*, at[04, 10, WriteSomeU];
	UPblock5 ← TOSH, RET[WriteSomeUret],	c*, at[05, 10, WriteSomeU];
	UPblock6 ← TOSH, RET[WriteSomeUret],	c*, at[06, 10, WriteSomeU];
	UPblock7 ← TOSH, RET[WriteSomeUret],	c*, at[07, 10, WriteSomeU];
	UPblock8 ← TOSH, RET[WriteSomeUret],	c*, at[08, 10, WriteSomeU];
	UPblock9 ← TOSH, RET[WriteSomeUret],	c*, at[09, 10, WriteSomeU];
	UPblockA ← TOSH, RET[WriteSomeUret],	c*, at[0A, 10, WriteSomeU];
	UPblockB ← TOSH, RET[WriteSomeUret],	c*, at[0B, 10, WriteSomeU];
	UPblockC ← TOSH, RET[WriteSomeUret],	c*, at[0C, 10, WriteSomeU];
	UPblockD ← TOSH, RET[WriteSomeUret],	c*, at[0D, 10, WriteSomeU];
	UPblockE ← TOSH, RET[WriteSomeUret],	c*, at[0E, 10, WriteSomeU];
	UPblockF ← TOSH, RET[WriteSomeUret],	c*, at[0F, 10, WriteSomeU];

	TOSH ← TOS,	c1, at[L2.WriteUhi, 10, WriteSomeUret];
	Rx ← Rx LRot8,	c2;
	Xbus ← Rx LRot12, XDisp, L2 ← L2.WriteUlo,	c3;

	Ybus ← Rx, AltUaddr, L2Disp, DISP4[WriteSomeU],	c1;
{	UPblockN ← TOSH, RET[ReadSomeUret],	c*;}
	TOSH ← smallpl,	c3, at[L2.WriteUlo, 10, WriteSomeUret];

	PC ← PC + PC16,	c1;
	TOS ← Rx LRot8, IBDisp, L2 ← L2.0,	c2;
	S ← S - 2, L2 ← L2.0, DISPNI[OpTable],	c3;

{	PrologOpDisp   14 clicks to Lisp execution / 10 clicks to Prolog area }
{	tos contains delta PrologPC as a smallp OR new PrologPC value
	uLMBbase contains real addr of Lisp{ #0 }/Microcode { =0 } table as (Bits 8 to 15,,Bits 0 to 7) of the 24 bit base address
	uSQtablebase contains real addr of base of SELECTQ arms table as (Bits 8 to 15,,Bits 0 to 7) of the 24 bit base address
	uSQbasehi, uSQbaselo contains virtual address of code base used by SQ offsets
	either jumps to Lisp code at appropriate arm
	or goes to EnterProlog
	never returns from Lisp
	returns from Prolog
}

@PROLOGOPFETCHPLUSOPDISP:	opcode[42'b],
	Ybus ← TOSH xor smallpl, ZeroBr,	c1;
	TT ← TOS, BRANCH[PrNewPC, PrDeltaPC],	c2;
PrNewPC:
	upVPClo ← TOS, L3 ← 0,	c3;

	upLVPChi ← TOSH, GOTO[PrOPPcx],	c1;

PrDeltaPC:
	{TT ← (PrologPC + TOS)↑}
	TT ← upVPClo, L3 ← 0,	c3;

	TOS ← TT + TOS, CarryBr,	c1;
	TOSH ← upLVPChi, BRANCH[$, PrOPPcCar],	c2;
PrOpFen:
	TT ← TOS,	c3;

	GOTO[PrOPPcx],	c1;

PrOPPcCar:
	TOSH ← TOSH + 1,	c3;

	TT ← TOS,	c1;

PrOPPcx:
	upVPClo ← TOS, L0 ← L0.PrologOpFetch,	c2;{update Prolog VPC low}
	rhTT ← TOSH LRot0,	c3;

	Map ← [rhTT, TT], CANCELBR[$],	c1;
	upLVPChi ← TOSH, L1 ← L1.NoFixes,	c2;{update Prolog VPC high}
	rhRx ← Rx ← MD, ReadXRefBr,	c3;

	MAR ← [rhRx, TOS + 0], ReadBRANCH[remapPrologPC, $],	c1, at[L0.PrologOpFetch, 10, RxMapFixCaller];
	Q ← upWriteMode,	c2;
	TT ← MD or Q,	c3;

	,	c1;
	Q ← TT and 0FF,{ L3Disp,}	c2;
	upN ← Q, GOTO[prepExuLisp],	c3;

prepExuLisp:	{got here from a UI call or Careful, don't look at LMTable}
	TT ← TT LRot8,	c1;
	rhRx ← Rx ← uSQtablebase,	c2;
	GOTO[ExecuteLispVersion],	c3;

remapPrologPC:
	GOTO[RLxMapFix],	c2;


{PROLOGOPDISP:
	Ybus ← upPFcont, ZeroBr,	c1;
	TT ← TT LRot8, BRANCH[Pr.PFentry.1, $],	c2;
	rhRx ← Rx ← uLMBbase,	c3;

	MAR ← [rhRx, TT + 0],	c1;{fetch of lisp/ucode word}
	Ybus ← upDebug, ZeroBr,	c2;
	Q ← MD, BRANCH[Prcareful, Prfast],	c3;

Prcareful:
	Ybus ← Q, ZeroBr,	c1;
	Q ← Q + 1, CarryBr, BRANCH[LP.ucode, LP.lisp],	c2;
LP.ucode:
	BRANCH[LP.1.nocarry, LP.1.carry],	c3;
LP.1.nocarry:
	MAR ← [rhRx, TT + 0],	c1;
	MDR ← Q, GOTO[EnterPrologC3],	c2;
LP.1.carry:	{don't let ucode turn itself off}
	GOTO[EnterPrologC2],	c1;
Prfast:
	Ybus ← Q, ZeroBr,	c1;
	Xbus ← 1, XDisp, BRANCH[LP.ucode, LP.lisp],	c2;
LP.lisp:
	rhRx ← Rx ← uSQtablebase, CANCELBR[ExecuteLispVersion],	c3;

Pr.PFentry.1:
	GOTO[EnterPrologC1],	c3;

}

ExecuteLispVersion:
	{add 1 to Prolog PC for Lisp code}
	{S ← PV + 3 -- moved},	c1;{fix stack before going to Lisp code}
	Q ← TOS + 1, CarryBr,	c2;
	upVPClo ← Q, BRANCH[PrLispEntryPCok, PrLispEntryPccar],	c3;

PrLispEntryPccar:
	,	c1;
	Q ← TOSH + 1,	c2;
	upLVPChi ← Q,	c3;

PrLispEntryPCok:
	MAR ← [rhRx, TT + 0],	c1;{fetch byte offset of new PC}
	Q ← rhTT ← uSQbasehi,	c2;
	Rx ← MD, L0 ← L0.ERefill,	c3;{setup L0 for Refill}

	TT ← uSQbaselo, L1 ← L1.Refill,	c1;{setup L1 for Refill}
	Rx ← RShift1 Rx, SE ← 0, YDisp,	c2;{byte offset to word offset}
	TT ← TT + Rx, CarryBr, BRANCH[evenByte, oddByte, 0E],	c3;

evenByte:	{new byte {pc16} 0}
	uPCCrossL ← 0, XC2npcDisp, BRANCH[Enofix, EfixrhTT],	c1;
Enofix:
	PC ← TT, BRANCH[EnopcwasO, EnopcwasE, 0E],	c2;
EnopcwasO:
	Cin ← pc16, GOTO[prrhTTok],	c3;{toggle pc16}
EnopcwasE:
	GOTO[prrhTTok],	c3;

oddByte:	{new byte {pc16} 1}
	uPCCrossL ← 0, XC2npcDisp, BRANCH[Onofix, OfixrhTT],	c1;
Onofix:
	PC ← TT, BRANCH[OnopcwasO, OnopcwasE, 0E],	c2;
OnopcwasO:
	GOTO[prrhTTok],	c3;
OnopcwasE:
	Cin ← pc16, GOTO[prrhTTok],	c3;{toggle pc16}

EfixrhTT:
	PC ← TT, BRANCH[EfixpcwasO, EfixpcwasE, 0E],	c2;
EfixpcwasO:
	Cin ← pc16, GOTO[rhTTneedsfix],	c3;{toggle pc16}
EfixpcwasE:
	GOTO[rhTTneedsfix],	c3;

OfixrhTT:
	PC ← TT, BRANCH[OfixpcwasO, OfixpcwasE, 0E],	c2;
OfixpcwasO:
	GOTO[rhTTneedsfix],	c3;
OfixpcwasE:
	Cin ← pc16, GOTO[rhTTneedsfix],	c3;{toggle pc16}

rhTTneedsfix:
	Q ← rhTT,	c1;
	Q ← Q + 1,	c2;
	rhTT ← Q LRot0, GOTO[prrhTTok],	c3;

prrhTTok:
	UvChighL ← Q,	c1;
	UvPCpageL ← TT, L0 ← L0.JRemap,	c2;
	PC ← TT,	c3;

	S ← S - 2,	c1;
	uPCCrossL ← Q ← 0,	c2;
	GOTO[UpdatePC],	c3;

{	EnterProlog NOT AN OP-CODE }
{	first part of this runs in Lisp uCode, last part in Prolog uCode
}
{
EnterPrologC2:
	,	c2;
EnterPrologC3:
	,	c3;
EnterPrologC1:
	{start by saving Lisp state }
{
	upPC16 ← PC16
	PC16 ← 0
	upTOS ← TOS
	upTOSH ← TOSH
	upPV ← PV
	upPC ← PC
	upS ← S
	don't save rhPC  --  need to remap PC at return to Lisp (page could be gone)
}
	XC2npcDisp,	c1;
	TT ← 1, BRANCH[prPC16is1, prPC16is0, 0E],	c2;
prPC16is1:
	upPC16 ← TT, Cin ← pc16, GOTO[PrPrep],	c3;
prPC16is0:
	upPC16 ← 0, GOTO[PrPrep],	c3;

PrPrep:
	upTOS ← TOS,	c1;
	upTOSH ← TOSH,	c2;
	upPV ← PV,	c3;

	Bank ← PrologBank,	c1;
	upPC ← PC,	c2;
	upS ← S, CROSS[LispToProlog],	c3;

{-------------------------------------------------------------------------------}
{	Lisp part of ExitProlog }
{	arrive here from Prolog after saving prolog state }
{	restore lisp regs and continue }
	at[PrologToLisp],
PrToLisp:
	TOS ← upVPClo,	c1;
	TOSH ← upLVPChi,	c2;
	PV ← upPV,	c3;

	Ybus ← upPC16, ZeroBr,	c1;
	PC ← upPC, BRANCH[PrSetPC16to1, PrSetPC16to0],	c2;
PrSetPC16to0:
	rhS ← nRhS, GOTO[PrPC16done],	c3;
PrSetPC16to1:
	rhS ← nRhS, Cin ← pc16, GOTO[PrPC16done],	c3;

PrPC16done:
	S ← upS, L1Disp,	c1;
	rhPV ← nRhS, DISP4[PrologExitType],	c2;

{	dispatch on exit type:
		Debug  Careful   GOTO[prepExuLisp]
		PageFault   GOTO[PFault]
		Interrupt   GOTO[LispInterrupt]
		PrUI unimplemented   GOTO[ExecuteLispVersion]
		PrUI exception   GOTO[ExecuteLispVersion]
		Heap Error    Execute PrologOp 376'b
}

{-------------------------------------------------------------------------------}
	at[L1.PrInt, 10, PrologExitType],
	Rx ←  KbdFXP, L2 ← 0, GOTO[PUNT],	c3;

{-------------------------------------------------------------------------------}
	at[L1.PrDebugC, 10, PrologExitType],
	,	c3;

PrCareful.Exit:
	TT ← upSave,	c1;
	Q ← TT and 0FF,	c2;
	upN ← Q, GOTO[prepExuLisp],	c3;

{-------------------------------------------------------------------------------}
	at[L1.PrPF, 10, PrologExitType],
	,	c3;

PrPF.Exit:
	,	c1;
	L1 ← L1.NoFixes,	c2;
	GOTO[PFault],	c3;

{-------------------------------------------------------------------------------}
	at[L1.PrUI, 10, PrologExitType],
	L3 ← 1,	c3;

PrUI.Exit:
	,	c1;
	GOTO[PrOpFen],	c2;

{-------------------------------------------------------------------------------}
	at[L1.PrHeapErr, 10, PrologExitType],
	rhRx ← Rx ← uSQtablebase,	c3;

PrHeap.Exit:
	upPFcont ← 0,	c1;
	TT ← 0FE,	c2;
	GOTO[PrLispEntryPCok],	c3;{execute op 376'b}

{-------------------------------------------------------------------------------}
	at[L1.PrSink, 10, PrologExitType],
	Q ← upTemp, GOTO[sink1],	c3;{9000 + Q to MP}

{-------------------------------------------------------------------------------}
}

	{ E N D }