{	PrologBase.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.
}

{	Refill }
{
PHILOSOPHY:
PC is kept pointing to the last word fetched into IB, which is essentially PC + 1 {in words}.  This is not always true during refill, and must be kept track of carefully.

	2 byte refill:
		IB ← [PC ← PC + 1], AlwaysIBDisp

	4 byte refill:
		IB ← [PC ← PC + 1],
		IB ← [PC ← PC + 1], AlwaysIBDisp

	6 byte refill:
		IB ← [PC ← PC + 2],
		IB ← [PC ← PC + 1], AlwaysIBDisp
}
{	Page Fault handling
	There are many places in the Prolog microcode where, after handling a page fault, the code cannot be restarted from the beginning of the opcode.  A U register, upPFcont, contains a unique value for each Prolog restart point in case of page fault.  This register must be initialized to zero before Prolog code is begun.  Thereafter, the microcode will maintain it.  The microcode is responsible for setting it to zero at the end of any opcode which sets it non-zero.
}

{	there are specific entry points to refill for 2, 4, 6 byte ops }

{	last c3 contained:  "L3Disp, MesaIntBr, " }
{--------------------------------------------------------------------}
Pr2Refill:
	MAR ← PC ← [rhPC, PC + 1], IBPtr ← 0, BRANCH[Pr2RefillC2, PrologExit2{PC-0}],	c1;
Pr2RefillC2:
	AlwaysIBDisp, L2Disp, BRANCH[$, PrbumpPC2, 1],	c2;
PrRemap2C3:
	upPFcont ← 0, IB ← MD, DISPNI[PrologOpTable],	c3;

PrbumpPC2:
	TT ← upVPClo, CANCELBR[$],	c3;

	Q ← 0FF + 1, L0 ← L0.PC2,	c1;
	TT ← TT + Q, CarryBr, GOTO[PrBumpCom],	c2;
PrBumpCom:
	Q ← rhTT ← upVPChi, BRANCH[PrPCMap, PrincrhTT],	c3;

PrincrhTT:
	Q ← Q + 1,	c1;
	upVPChi ← Q,	c2;
	rhTT ← Q LRot0, GOTO[PrPCMap],	c3;

PrPCMap:
	Map ← MAR ← TT ← [rhTT, PC + 0],	c1;{move low 8 bits of PC to TT}
	upVPClo ← TT, L0Disp,	c2;
	PC ← rhPC ← MD, ReadXRefBr, DISP4[PrRMapFixret],	c3;

	MAR ← Q ← [rhPC, TT + 0], ReadBRANCH[remapPC2, $],	c1, at[L0.PC2, 10, PrRMapFixret];{move all 16 bits of PC from PC and TT to Q}
	PC ← Q, AlwaysIBDisp, L2Disp, GOTO[PrRemap2C3],	c2;{restore PC}

remapPC2:
	Rx ← PC, GOTO[PrRMapFix],	c2;

{--------------------------------------------------------------------}
Pr4Refill:
	MAR ← PC ← [rhPC, PC + 1], BRANCH[Pr4RefillC2, PrologExit4],	c1;
Pr4RefillC2:
	BRANCH[$, PrbumpPC4a, 1],	c2;
Pr4RefillC3a:
	IB ← MD, GOTO[Pr2Refill],	c3;

PrbumpPC4a:
	TT ← upVPClo, L0 ← L0.PC4a, CANCELBR[$],	c3;

	Q ← 0FF + 1,	c1;
	TT ← TT + Q, CarryBr, GOTO[PrBumpCom],	c2;

	MAR ← Q ← [rhPC, TT + 0], ReadBRANCH[remapPC4a, $]	c1, at[L0.PC4a, 10, PrRMapFixret];
	PC ← Q, GOTO[Pr4RefillC3a],	c2;

remapPC4a:
	Rx ← PC, GOTO[PrRMapFix],	c2;

{--------------------------------------------------------------------}
Pr6Refill:
	MAR ← PC ← [rhPC, PC + 2], BRANCH[Pr4RefillC2, PrologExit4],	c1;
{--------------------------------------------------------------------}

{	Refill Exits }
{	come here if Interrupt or DebugMode}
{	there is a pending page cross branch to handle }
PrologExit2:
	{PC is + 1, and VPC is correct }
	TT ← upVPClo, CANCELBR[$, 2],	c2;{ignore PageCross}

Prvpcok:
	PC ← PC - 1, GOTO[PrSaveVPC],	c3;

PrologExit4:
	{there is a pending page cross branch to handle }
	{PC is + 0, and VPC is - 1 }
	TT ← upVPClo, BRANCH[PrExPCok, PrExPgCr, 1],	c2;
PrExPCok:
	GOTO[PrSaveVPC],	c3;

PrExPgCr:
	{add 1 to VPC}
	Q ← 0FF + 1,	c3;

	TT ← TT + Q, CarryBr,	c1;
	upVPClo ← TT, BRANCH[$, PrfixPChi],	c2;
	GOTO[PrSaveVPC],	c3;

PrfixPChi:
	Q ← upVPChi,	c3;

	Q ← Q + 1,	c1;
	upVPChi ← Q,	c2;
	GOTO[PrSaveVPC],	c3;

PrSaveVPC:
	Q ← 0FF + 1, L2Disp,	c1;
	upPFcont ← 0, BRANCH[PrsetR, PrsetW, 0E],	c2;
PrsetR:
	upWriteMode ← 0, GOTO[Prsetcont],	c3;

PrsetW:
	upWriteMode ← Q, GOTO[Prsetcont],	c3;

Prsetcont:
	MAR ← TT ← [TT, PC + 0], L0 ← L0.PrB.1,	c1;{byte merge}
	upVPClo ← TT, MesaIntBr, L1 ← L1.PrInt,	c2;
	Ybus ← uWDC, NZeroBr, BRANCH[PrNoInt, PrInt],	c3;

PrInt:
	Ybus ← uWP, ZeroBr, BRANCH[$, PrNointc2],	c1;
	BRANCH[PrIntNow, PrNointc3],	c2;

PrIntNow:
	ClrIntErr, Rx ← 1,	c3;

PrInttoLisp:
	uWP ← 0,	c1;
	uWDC ← Rx,{off interrupts}	c2;
	Rx ←  KbdFXP, GOTO[SavePrologC1],	c3;

PrNointc1:	CANCELBR[$],	c1;
PrNointc2:	CANCELBR[$],	c2;
PrNointc3:	ClrIntErr,	c3;

PrNoInt:
	Ybus ← upDebug, ZeroBr, CANCELBR[$],	c1;
	TT ← upVPClo, BRANCH[PrDebugC, PrNoDebug],	c2;

PrDebugC:
	rhTT ← upVPChi,	c3;

	Map ← [rhTT, TT], L0 ← L0.PFPCdc,	c1;
	,	c2;
	PC ← rhPC ← MD, ReadXRefBr,	c3;

	MAR ← Q ← [rhPC, TT +0], ReadBRANCH[PrPCMneedsfix, $],	c1, at[L0.PFPCdc, 10, PrRMapFixret];
	Q ← upWriteMode,	c2;
	TT ← MD or Q,	c3;

	upSave ← TT,	c1;
	TT ← TT LRot8,	c2;
	rhRx ← Rx ← uLMBbase,	c3;

	MAR ← [rhRx, TT + 0],	c1;{fetch of Lisp/Mcode word}
	,	c2;
	Q ← MD,	c3;{zero to lisp/nonzero to ucode}

	Ybus ← Q, ZeroBr,	c1;
	Q ← Q + 1, CarryBr, BRANCH[Pb.ucode, Pb.lisp],	c2;
Pb.ucode:
	BRANCH[Pb.1.nocarry, Pb.1.carry],	c3;
Pb.1.nocarry:
	MAR ← [rhRx, TT + 0],	c1;
	MDR ← Q,	c2;
	,	c3;
Pb.1.carry:	{don't let ucode turn itself off}
	,	c1;
	TT ← upVPClo, GOTO[ReEnterProlog],	c2;
Pb.lisp:
	CANCELBR[SavePrologC1],	c3;

PrPCMneedsfix:
	Rx ← PC, GOTO[PrRMapFix],	c2;

ReEnterProlog:
	rhTT ← upVPChi, GOTO[PrNewRefill],	c3;

PrNoDebug:
	{redo PrRefill - no reason to stop - PC is ok}
	,	c3;

	,	c1;
	TT ← upVPClo,	c2;
	rhTT ← upVPChi,	c3;

PrNewRefill:
	Map ← [rhTT, TT], L0 ← L0.PCcont,	c1;
	,	c2;
	PC ← rhPC ← MD, ReadXRefBr,	c3;

PrNewRefillMAR:
	MAR ← Q ← [rhPC, TT + 0], ReadBRANCH[remapPCcont, $],	c1, at[L0.PCcont, 10, PrRMapFixret];
	PC ← Q,	c2;
	IB ← MD, GOTO[Pr2Refill],	c3;

remapPCcont:
	Rx ← PC, GOTO[PrRMapFix],	c2;

PrHErr.C3:
	,	c3;
PrHErr.C1:
	,	c1;
PrHErr.C2:
	PC ← PC - 1, PgCarryBr, L1 ← L1.PrHeapErr,	c2;
	TT ← upVPClo, BRANCH[PrFixIt, PrSaveVPCforUI],	c3;

UI3:
	,	c3;
UI1:
	,	c1;
UI2:	{standard entry point for UI's}
	{PC is + 1 and VPC is + 1 }
	PC ← PC - 1, PgCarryBr, L1 ← L1.PrUI,	c2;
	TT ← upVPClo, BRANCH[PrFixIt, PrSaveVPCforUI],	c3;

PrFixIt:
	TT ← TT and ~0FF,	c1;
	,	c2;
	,	c3;

PrPCdecCont:
	TT ← TT - 1, CarryBr,	c1;
	upVPClo ← TT, BRANCH[PrfixdecPChi, $],	c2;
	GOTO[PrSaveVPCforUI],	c3;

PrfixdecPChi:
	Q ← upVPChi,	c3;

	Q ← Q - 1,	c1;
	upVPChi ← Q,	c2;
	GOTO[PrSaveVPCforUI],	c3;

PrSaveVPCforUI:
	MAR ← TT ← [TT, PC + 0],	c1;{byte merge}
	upVPClo ← TT, GOTO[SavePrologC3],	c2;

{	SAVE PROLOG REGISTERS }
{	PC has been saved to upVPChi and upVPClo
	L1 has been set with the type of exit
	BB to uprhB and upB
	TR to uprhTR and upTR
	H to uprhHH and upHH
	S to uprhSS and upSS
	A1 to upA1hi and upA1lo
	A2 to upA2hi and upA2lo
	A3 to upA3hi and upA3lo
	A4 to upA4hi and upA4lo
	{L2 {Write-Mode} to upWriteMode -- done whenever Write-Mode changes}
}
SavePrologC3:
	,	c3;
SavePrologC1:
	,	c1;
SavePrologC2:
	Q ← upVPChi,	c2;
	upLVPChi ← Q,	c3;

	Q ← upB0,	c1;
	upLB0 ← Q,	c2;
	upB ← BB,	c3;

	Q ← rhBB,	c1;
	uprhB ← Q,	c2;
	upCC ←CC,	c3;

	Q ← 0FF + 1, L2Disp,	c1;
	BRANCH[PrsetR1, PrsetW1, 0E],	c2;
PrsetR1:
	upWriteMode ← 0, GOTO[Prsetcont1],	c3;

PrsetW1:
	upWriteMode ← Q, GOTO[Prsetcont1],	c3;

Prsetcont1:
	Q ← rhCC,	c1;
	uprhCC ← Q,	c2;
	upHH ← HH,	c3;

	Q ← rhHH,	c1;
	uprhHH ← Q,	c2;
	upSS ← SS,	c3;

	Q ← rhSS,	c1;
	uprhSS ← Q,	c2;
	Q ← upPRA1hi,	c3;

	upA1hi ← Q,	c1;
	Q ← upPRA1lo,	c2;
	upA1lo ← Q,	c3;

	Q ← upPRA2hi,	c1;
	upA2hi ← Q,	c2;
	Q ← upPRA2lo,	c3;

	upA2lo ← Q,	c1;
	Q ← upPRA3hi,	c2;
	upA3hi ← Q,	c3;

	Q ← upPRA3lo,	c1;
	upA3lo ← Q,	c2;
	Q ← upPRA4hi,	c3;

	upA4hi ← Q,	c1;
	Q ← upPRA4lo,	c2;
	upA4lo ← Q,	c3;

SavePrologEnd:
	Bank ← EmuBank,	c1;
	,	c2;
	CROSS[PrologToLisp],	c3;

{--------------------------------------------------------------}
{	entry from Lisp
	restore regs and L2, and L3 do PC fetch and PrologIBDisp
}
	at[LispToProlog],
	BB ← upB,	c1;
	rhBB ← uprhB,	c2;
	CC ← upCC,	c3;

	rhCC ←uprhCC,	c1;
	HH ← upHH,	c2;
	rhHH ← uprhHH,	c3;

	SS ← upSS,	c1;
	rhSS ←uprhSS,	c2;
	Q ← upA1hi,	c3;

	upPRA1hi ← Q,	c1;
	Q ← upA1lo,	c2;
	upPRA1lo ← Q,	c3;

	Q ← upA2hi,	c1;
	upPRA2hi ← Q,	c2;
	Q ← upA2lo,	c3;

	upPRA2lo ← Q,	c1;
	Q ← upA3hi,	c2;
	upPRA3hi ← Q,	c3;

	Q ← upA3lo,	c1;
	upPRA3lo ← Q,	c2;
	Q ← upA4hi,	c3;

	upPRA4hi ← Q,	c1;
	Q ← upA4lo,	c2;
	upPRA4lo ← Q,	c3;

	Q ← upLVPChi,	c1;
	upVPChi ← Q,	c2;
	Q ← upLB0,	c3;

	Ybus ← upDebug, NZeroBr,	c1;
	upB0 ← Q, BRANCH[LPrDB0, LPrDB1], L3 ← 0,	c2;{set L3 to 1 if Debug not zero}
LPrDB0:
	GOTO[RestorePrologEnd],	c3;
LPrDB1:
	GOTO[RestorePrologEnd],	c3;

RestorePrologEnd:
	Ybus ← upWriteMode, NZeroBr,	c1;
	TT ← upVPClo, BRANCH[LPrWM0, LPrWM1], L2 ← 0,	c2;
LPrWM0:
	rhTT ← upVPChi, GOTO[startprologpcfetch],	c3;
LPrWM1:
	rhTT ← upVPChi, GOTO[startprologpcfetch],	c3;

startprologpcfetch:
	,	c1;
	Rx ← upPFcont, ZeroBr,	c2;
	BRANCH[PrPFStart, PrNewRefill],	c3;

PrPFStart:
	{load last three bytes of op into IB, don't IBDisp}
	Map ← [rhTT, TT], L0 ← L0.PCPFcont,	c1;
	,	c2;
	PC ← rhPC ← MD, ReadXRefBr,	c3;

	MAR ← Q ← [rhPC, TT + 0], ReadBRANCH[remapPCPFcont, $],	c1, at[L0.PCPFcont, 10, PrRMapFixret];
	PC ← Q,	c2;
	IB ← MD,	c3;

	MAR ← PC ← [rhPC, PC + 1], IBPtr ← 1{byte},	c1;
	BRANCH[$, PrbumpPFPC4b, 1],	c2;
PrPFgt:
	IB ← MD,	c3;

PrPFDispHere:
	Xbus ← Rx LRot12, XDisp,	c1;
	Ybus ← Rx, YDisp, DISP4[PrPFDispA],	c2;
	at[0, 10, PrPFDispA],
	DISP4[PrPFDisp0X],	c3;
	at[1, 10, PrPFDispA],
	DISP4[PrPFDisp1X],	c3;
	at[2, 10, PrPFDispA],
	DISP4[PrPFDisp2X],	c3;
	at[3, 10, PrPFDispA],
	DISP4[PrPFDisp3X],	c3;
	at[4, 10, PrPFDispA],
	DISP4[PrPFDisp4X],	c3;
	at[5, 10, PrPFDispA],
	DISP4[PrPFDisp5X],	c3;
{	at[6, 10, PrPFDispA],
	DISP4[PrPFDisp6X],	c3;
}

PrPF01:
	at[01, 10, PrPFDisp0X],
	GOTO[C2Dead],	c1;
C2Dead:
	,	c2;
	,	c3;
PrPFCantFind:
	GOTO[C2Dead],	c1;

remapPCPFcont:
	Rx ← PC, GOTO[PrRMapFix],	c2;
	{will return thru PrRMapFixret using L0.PCPFcont}

PrbumpPFPC4b:
	TT ← upVPClo,	c3;

	Q ← 0FF + 1, L0 ← L0.PFPC4b,	c1;
	TT ← TT + Q, CarryBr, GOTO[PrBumpCom],	c2;
	{will return thru PrRMapFixret using L0.PFPC4b}

	MAR ← Q ← [rhPC, TT + 0], CANCELBR[$, ReadOK],	c1, at[L0.PFPC4b, 10, PrRMapFixret];
	PC ← Q, GOTO[PrPFgt],	c2;{restore PC}

{	to put screen back up -- maybe}
{PrScreen:
	DISP4[PrScreenDisp],	c1;

	,	c2, at[0, 10, PrScreenDisp];
	Xbus ← 0, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[1, 10, PrScreenDisp];
	Xbus ← 1, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[2, 10, PrScreenDisp];
	Xbus ← 2, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[3, 10, PrScreenDisp];
	Xbus ← 3, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[4, 10, PrScreenDisp];
	Xbus ← 4, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[5, 10, PrScreenDisp];
	Xbus ← 5, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[6, 10, PrScreenDisp];
	Xbus ← 6, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[7, 10, PrScreenDisp];
	Xbus ← 7, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[8, 10, PrScreenDisp];
	Xbus ← 8, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[9, 10, PrScreenDisp];
	Xbus ← 9, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[0A, 10, PrScreenDisp];
	Xbus ← 0A, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[0B, 10, PrScreenDisp];
	Xbus ← 0B, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[0C, 10, PrScreenDisp];
	Xbus ← 0C, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[0D, 10, PrScreenDisp];
	Xbus ← 0D, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[0E, 10, PrScreenDisp];
	Xbus ← 0E, XDisp, GOTO[PrScreen],	c3;

	,	c2, at[0F, 10, PrScreenDisp];
	Xbus ← 0F, XDisp, GOTO[PrScreen],	c3;
}
{--------------------------------------------------------------}
{	Read Map Update Routine}
{	returns thru L0 }
PrRMapFix:
	PC ← Q,	c3;

	,	c1;
	,	c2;
PrRMapFixNorm:
	Xbus ← Rx LRot0, XwdDisp,	c3;

	Map ← [rhTT,TT], DISP2[PrRFixFlags],	c1;

	MDR ← Rx or refFlag, L0Disp, GOTO[PrReRead],	c2, at[0, 4, PrRFixFlags];
	MDR ← Rx or refFlag, L0Disp, GOTO[PrReRead],	c2, at[1, 4, PrRFixFlags];
	MDR ← Rx or refFlag, L0Disp, GOTO[PrReRead],	c2, at[2, 4, PrRFixFlags];
	GOTO[PrRWTrap], L1 ← L1.PrPF,	c2, at[3, 4, PrRFixFlags];

PrReRead:
	Xbus ← ReadOK, XDisp, RET[PrRMapFixret],	c3;

PrRWTrap:
	{L0 indicates current state of PC
	if L0 is odd, then PC is + 0, VPC is + 0
	if L0 is even, then PC is + 1, VPC is + 1}
	{rebuild correct PC and goto SaveProlog}
	L0Disp,	c3;
	BRANCH[PrPFdecPC, PrPCstate0, 0E],	c1;
PrPCstate0:
	GOTO[SavePrologC3],	c2;

PrPFdecPC:
	L1 ← L1.PrPF,	c2;
	Rx ← upVPClo,	c3;

PrRetToLisp:
	MAR ← Rx ← [Rx, PC + 0],	c1;{byte merge}
	PC ← Rx - 1, CarryBr,	c2;
	upVPClo ← PC, BRANCH[PrfixPChigh, $],	c3;

	GOTO[SavePrologC2],	c1;

PrfixPChigh:
	Q ← upVPChi,	c1;
	Q ← Q - 1,	c2;
	upVPChi ← Q, GOTO[SavePrologC1],	c3;


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


	{ E N D }