{File name dbNewBLT.mc
Description: new BLT code
Author: Charnley
Created:  9-Jun-83 11:01:00
Last edit by Charnley:    20-Jul-83 10:44:09
}

SetTask[0];

{*******************************************************************
	BLT {daddr, saddr, nwords}
********************************************************************}
{	this code uses a two click inner loop to transfer words.
	the loop is exited when either the source or the dest
	cross a page boundary {and require remapping}
	or the required number of words has been moved.
	a test for pending interrupts is performed whenever
	the source is remapped {care must be taken to 
	ignore uPCCrossL}
	AT ENTRY
	tos  :  number of words
	tos-1:  virtual address of first source word
	tos-2:  virtual address of first dest word
	AT INTERRUPT EXIT
	tos  :  number of words remaining
	tos-1:  virtual address of first source word
	tos-2:  virtual address of first dest word
	AT COMPLETION EXIT
	stkcnt ← stkcnt - 2
}
{	REGISTER USAGE
	Within Inner Loop:
	  Q		cnt of words to go
	  TOSH	Src Real Address
	  TOS	Dst Real Address
	  TT		Move Data
	  rhTOSH	High Src Real Address
	  rhTOS	High Dst Real Address
}

{	BLTInnerLoop }
BLTS1:	MAR ← {SrcRA}TOSH ← [rhTOSH,TOSH - 1], BRANCH[BLTdone, $],	c1;
BLTS2:	BRANCH[$, BLTSrcRemap, 1],	c2;
BLTS3:	{Data}TT ← MD,	c3;

BLTD1:	MAR ← {DstRA}TOS ← [rhTOS, TOS - 1],	c1;
BLTD2:	uSaveTT ← MDR ← {Data}TT, BRANCH[$, BLTDstRemap, 1],	c2;
BLTD3:	Q{BLTcnt} ← Q - 1, CarryBr, GOTO[BLTS1],	c3;

{	Loop Exits}

BLTSrcRemap:
	{restore state first}
	uSaveTOS ← TOS, L2 ← 1,	c3;{save DstRA, set L2 for Src Remap}

{	test for interrupt}
	TOS ← Q + 1, L1 ← L1.NoFixes,	c1;{restore TOS}
	Ybus ← Q and ~0F, ZeroBr,	c2;{small counts don't interrupt}
	TOSH ← smallpl, MesaIntBr, BRANCH[$, BLTnoint0],	c3;{restore TOSH}

	Ybus ← uWDC, NZeroBr, BRANCH[BLTnoint1, $],	c1;
	Ybus ← uWP, ZeroBr, BRANCH[$, BLTnoint2],	c2;
	uWP ← 0, BRANCH[{BLTIntNow}anotherBLTnoint3, BLTnoint3],	c3;  {%M BLT ints disabled here}

anotherBLTnoint3: GOTO[BLTnoint1], c1;
	
BLTIntNow:
	ClrIntErr, Rx ← 1,	c1, at[EmuInt];
	uWDC ← Rx,	c2;
	Rx ←  KbdFXP, L2 ← 0, GOTO[PUNT],	c3;

BLTnoint1:	CANCELBR[$],	c2;
BLTnoint2:	CANCELBR[BLTRemap],	c3;

BLTSrc:	{BLTRemap returns here}
	Rx ← rhRx ← MD, ReadXRefBr,	c3;

	Q ← rhRx, ReadBRANCH[BLTSMap, $],	c1,at[L0.RedoBLT,10,RxMapFixCaller];{move rhRx,,Rx to rhTOSH,,TOSH}
	rhTOSH ← Q LRot0,	c2;
	TOSH ← Rx,	c3;

	Q ← TOS - 1,	c1;{restore loop count}
	TOS ← uSaveTOS,	c2;{restore DstRA}
	c3;

	MAR ← {SrcRA}TOSH ← [rhTOSH, TT + 0], GOTO[BLTS2],	c1;

BLTSMap:	CALL[RLxMapFix],	c2;

BLTDstRemap:
{	restore state, prepare for Remap}
	uSaveTOSH ← TOSH, L2 ← 3,	c3;{save SrcRA, set L2 for Dst Remap}

	TOS ← Q + 1, L1 ← L1.PushOnly,	c1;{restore TOS}
	TOSH ← smallpl,	c2;{restore TOSH}
	S ← S - 2, GOTO[BLTRemap],	c3;{point stack at Dest}
	
BLTDst:	{BLTRemap returns here}
	Rx ← rhRx ← MD, XwdDisp{XDirtyDisp},	c3;

	Q ← rhRx, DISP2[BLTDMap],	c1,at[L0.RedoBLT,10,WMapFixCaller];
	rhTOS ← Q LRot0,	c2, at[PgDirty, 4, BLTDMap];{move rhRx,,Rx to rhTOS,,TOS}
	Q ← TOS - 1,	c3;{restore loop count}

	TOS ← Rx,	c1;
	TOSH ← uSaveTOSH,	c2;{restore SrcRA}
	S ← S + 2,	c3;{restore stack}

	MAR ← {DstRA}TOS ← [rhTOS, TT + 0],	c1;
	MDR ← uSaveTT, GOTO[BLTD3],	c2;{store saved data}

BLTDMap:	CALL[WLMapFix],	c2, at[PgClean, 4, BLTDMap];
	CALL[WLMapFix],	c2, at[PgProt, 4, BLTDMap];
	CALL[WLMapFix],	c2, at[PgVacant, 4, BLTDMap];

{****************************************************}
BLTnoint0:
	MAR ← [rhS, S + 0], L0 ← L0.RedoBLT, CANCELBR[BLTReX],	c1;
BLTnoint3:
	MAR ← [rhS, S + 0], L0 ← L0.RedoBLT, CANCELBR[BLTReX],	c1;

{	Remap Subroutine }
BLTRemap:
	MAR ← [rhS, S + 0], L0 ← L0.RedoBLT,	c1;
BLTReX:	TOS ← TOS - 1, CarryBr,	c2;
	TT ← MD{addr}, L2Disp, BRANCH[BLTdone1, $],	c3;

	MAR ← [rhS, S - 1], BRANCH[$, BLTsavedest, 1],	c1;
	TT ← TT + TOS, CarryBr, CANCELBR[$, 2],	c2;
	rhTT ← MD{addrH}, BRANCH[BLT64NoCross, BLT64Cross],	c3;

BLTsavedest:
	uTOS ← TT, CANCELBR[$, 2],	c2;
	Q ← rhTT ← MD,	c3;

	uTOSH ← Q,	c1;
	TT ← TT + TOS, CarryBr,	c2;
	BRANCH[BLT64NoCross, BLT64Cross],	c3;


BLT64Cross:
	Q ← rhTT + 1, LOOPHOLE[byteTiming],	c1;
	rhTT ← Q LRot0,	c2;
	GOTO[BLT64NoCross],	c3;

BLT64NoCross:
	Map ← [rhTT,TT], L2Disp,	c1;
	TOS ← TOS + 1, BRANCH[BLTSrc, BLTDst, 1],	c2;{restore count}


{****************************************************}

BLTdone1:
	CANCELBR[$, 3],	c1;
	TOSH ← uTOSH, GOTO[BLTdone2],	c2;
BLTdone:
	TOSH ← uTOSH, CANCELBR[$, 2],	c2;
BLTdone2:
	TOS ← uTOS,	c3;

	PC ← PC + PC16,  MesaIntRq,	c1;
	S ← S - 4, IBDisp, L2 ← L2.0, GOTO[DISPNIonly],	c2;

BLTufn:	 Rx ← 304'b, GOTO[ufn2],	c1;

@BLT:	uSaveTOS ← 0, L2 ← 1,	c1, opcode[304'b];
	Ybus ← TOSH xor smallpl, ZeroBr, L1 ← L1.NoFixes,	c2;
	rhTOS ← 0, BRANCH[BLTufn, BLTRemap],	c3;

	{ E N D }