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

{	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
}
{	moved to Prolog.dfn

Set[L0.PC2, 1],{if PF then PC is + 0, VPC is + 0}
Set[L0.PC4a, 3],{if PF then PC is + 0, VPC is + 0}
Set[L0.PC4b, 4],{if PF then PC is + 1, VPC is + 1}
Set[L0.PCcont, 7],{if PF then PC is + 0, VPC is + 0}

{the following values are used when returning to Lisp}
Set[L1.PrDebugSS, 1],
Set[L1.PrInt, 2],
Set[L1.PrDebugC, 3],
Set[L1.PrPF, 4],
Set[L1.PrUI, 5],
}

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

{	last c3 contained:  "L3Disp, MesaIntBr, " }
{--------------------------------------------------------------------}
Pr2Refill:
	MAR ← PC ← [rhPC, PC + 1], BRANCH[Pr2RefillC2, PrologExit2{PC-0}],	c1;
Pr2RefillC2:
	AlwaysIBDisp, L2Disp, BRANCH[$, PrbumpPC2, 1],	c2;
PrRemap2C3:
	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, XRefBr, DISP4[PrRMapFixret],	c3;

	MAR ← Q ← [rhPC, TT + 0], BRANCH[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,	c3;

PrSecondIBFetch:
	MAR ← PC ← [rhPC, PC + 1], IBPtr ← 0,	c1;
	AlwaysIBDisp, L2Disp, BRANCH[$, PrbumpPC4b, 1],	c2;
Pr4RefillC3b:
	IB ← MD, DISPNI[PrologOpTable],	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], BRANCH[remapPC4a, $]	c1, at[L0.PC4a, 10, PrRMapFixret];
	PC ← Q, GOTO[Pr4RefillC3a],	c2;

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

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

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

	MAR ← [rhPC, TT + 0], BRANCH[remapPC4b, $]	c1, at[L0.PC4b, 10, PrRMapFixret];
	PC ← Q, AlwaysIBDisp, L2Disp, GOTO[Pr4RefillC3b],	c2;

remapPC4b:
	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:
	MAR ← TT ← [TT, PC + 0],	c1;{byte merge}
	upVPClo ← TT,	c2;
	GOTO[VerifyPrologExit],	c3;

VerifyPrologExit:
	Q ← upDebug, L1 ← L1.PrDebugSS,	c1;
	Ybus ← Q - 2, CarryBr,	c2;
	BRANCH[PrDebugSS, PrNotDebugSS],	c3;

PrDebugSS:
	{save Prolog state and perform Lisp IBDisp}
	GOTO[SavePrologC2],	c1;

PrNotDebugSS:
	MesaIntBr, L1 ← L1.PrInt,	c1;
	BRANCH[PrNoInt, PrInt],	c2;

PrInt:
	Ybus ← uWDC, NZeroBr, BRANCH[PrNointc1, $],	c3;

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

PrIntNow:
	ClrIntErr, Rx ← 1, CANCELBR[SavePrologC1],	c3;

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

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

	Ybus ← Q, ZeroBr, L1 ← L1.PrDebugC,	c1;
	BRANCH[PrDebugC, PrNoDebug],	c2;

PrDebugC:
	{save Prolog state and GOTO[PrologOpDisp]}
	GOTO[SavePrologC1],	c3;

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

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

	Map ← MAR ← TT ← [rhTT, PC + 0], L0 ← L0.PCcont,	c1;
PrPCcont:
	L0Disp,	c2;
	PC ← rhPC ← MD, XRefBr, DISP4[PrRMapFixret],	c3;

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

	MAR ← PC ← [rhPC, PC + 1], IBPtr ← 0,	c1;
	AlwaysIBDisp, L2Disp, BRANCH[Pr4RefillC3b, PrbumpPC4b, 1],	c2;

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

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[$, PrSaveVPCforUI],	c3;

	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}
}
SavePrologC1:
	,	c1;
SavePrologC2:
	,	c2;
SavePrologC3:
	upB ← BB,	c3;

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

	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 ← upPRA4hi,	c3;

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

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

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

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

	upA3hi ← Q,	c1;
	Q ← upPRA3lo,	c2;
	upA3lo ← 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 ← upA4hi,	c3;

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

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

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

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

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

	Ybus ← upDebug, NZeroBr,	c1;
	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:
	Map ← [rhTT, TT], L0 ← L0.PCcont, GOTO[PrPCcont],	c1;

{--------------------------------------------------------------}
{	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 10, L0Disp, GOTO[PrReRead],	c2, at[0, 4, PrRFixFlags];
	MDR ← Rx or 10, L0Disp, GOTO[PrReRead],	c2, at[1, 4, PrRFixFlags];
	MDR ← Rx or 10, L0Disp, GOTO[PrReRead],	c2, at[2, 4, PrRFixFlags];
	GOTO[PrRWTrap], L1 ← L1.PrPF,	c2, at[3, 4, PrRFixFlags];

PrReRead:
	Xbus ← 1, 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:
	Rx ← upVPClo, L1 ← L1.PrPF,	c2;
	,	c3;

	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 }