{ File Name: ChainBlt.mc
  
  Description: ChainBlt writes out a pattern of alternating runs of zeros and runs of ones. This operation is very similar to BLTLineGray except for the parameters that are passed to the instruction and the amount of data that can be processed. A run of data can be up to 64K bits long. The processing steps are as follows : get parameters from stack, check length, fetch the count of the run from base address; check page fault, if no page fault, bring in pages to write the run, set up BltLineGray parameters, call BltlineGray to write the run, decrement length; check if done, if not, update destination bit address,increment base address, toggle the writeBit, and check for any interrupts;if no, then go back to loop for the next run. If interrupt happened, it will branch to interrupt handler and back to the entrance of CHAINBLT after that. Page fault will  be handlered the same except it will branch to page fault handler.
      
  Author: MYT
  
  Created:   July 19, 1986
  	     July 30, 1986 mass assembler
	     Aug. 03, 1986 length <= 0
	     Aug. 04, 1986 goto writerun
	     Aug 05, stackP correct
	     Aug 06, interrupt checking ok
	     Aug 08, move to bank 1
	     Aug 12, fix bug in calling parameters to BumpBitAddress
	     Aug 13, bug in page fault from ComMap
  Edited:    Sep 18, optimization xxx 
  Last Edited:
  	     Oct 08, complete testing optimization codes xxx
  
}

{ Copyright (C) 1986 by XEROX corporation. All rights reserved.}

@CHAINBLT:

{****************************************************************************************
 				POP Parameters from stack			
 ****************************************************************************************}

 	{length = TOS}
	rhchainbaseh ← STK, pop,			c1, at [09,10,ESCAn];
	rchainbasel ← STK, pop,			        c2;
	writebit ← STK, pop,				c3;
	DBit ← STK, pop,			        c1;
	rhdsthigh ← STK, pop,			 	c2;
	rdstlow ← STK, pop, L0 ← L0.ChainBlt,      	c3;

{****************************************************************************************
 				Check length			
 ****************************************************************************************}

ChkLength:
	[] ← length, ZeroBr, pop,						c1;{ length is a cardinal*opt* }
	rchaintemp ← rdstlow,BRANCH[$,ChainExit3],		c2;{ xxx*opt* }
{	save r1 = rdstlow before call MapSrc 					 }
	
{*****************************************************************************************
  				Fetch word at base address  
*****************************************************************************************}
	
Fetch:	CALL [MapSrc],					c3; { xxx*opt*}
{ 	MapSrc routine called here 							 } 
	bitWidth ← MD,L2 ← 0,  				c3, MapSrcRet[L0.ChainBlt]; {L2 is caller to save register}
	
{****************************************************************************************
	Call ComMap to determine pages needed to write the run,
	L1 - Src/Dst mapping flag (0/1),
	L3 - caller, 
*****************************************************************************************}
chkdata:
	L3 ← L3.ChainBlt, CALL[SaveChainReg],		c1;
	L1 ← 1, CALL[ComMap], 				c3, at [0,10,SaveChainRegRet];
	writebit ← USavewritebit, BRANCH[WriteRun,ToPageFault],	c2, at [L3.ChainBlt,10,ComMapRet];	{restore write bit value }

{****************************************************************************************
  	If page ok, set up parameters to call BLTLineGray to write the run
*****************************************************************************************}
WriteRun:
	GCount ← USavecount,				c3;
	
{	set function  = 0								}
	temp ← 0,					c1;
{	set up starting bit to write out the run					 }
	DstBit ← USavedstbit,	 			c2;
{	set up destination address to write the run					 }
	rhVirtualH ← USavedsthigh,			c3;
	rVirtualL ← USavedstlow, 			c1;
{	set up grey word								}
	[] ← writebit, ZeroBr, L3 ← L3.ChainBltBLG,	c2;
	Grayword ← 0, BRANCH[WriteOne,$],		c3;
WriteZero:
	GOTO[CallBLTLineGray],				c1;
WriteOne:
	Grayword ← ~ Grayword,				c1;
CallBLTLineGray:
	CALL[BLGSubEntry],				c2;	
ChkStkP:
	L5 ← 2, CALL[RestoreChainReg], 			c3, at [L3.ChainBltBLG,10,BLTLineGrayRet]; {8/4/86}

{****************************************************************************************
	decrement length variable, check if more run to perform;
*****************************************************************************************}

ChkExit:
	length ← length - 1, ZeroBr,			c2, at [2,10,RestoreChainRegRet];
	USavelength ← length, BRANCH[$,ChainExit1],	c3;

{****************************************************************************************
  	set up parameters to call BumpBitAddress 
*****************************************************************************************}

ToBump:	offset ← bitWidth, L4 ← L4.ChainBlt,		c1;
	{bitnum = DBit}
	rwrdaddl ← USavedstlow,				c2; 
	rwrdaddh ← USavedsthigh, CALL[BBASubEntry],	c3;
	
{	BumpBitAddress is here  c1 - c2 					     }
	
ResBump:
	Q ← rwrdaddh,					c3, at[9,10,BumpBitAddressRet];
	rhdsthigh ← Q LRot0,				c1;
	writebit ← USavewritebit,			c2; {restore write bit value }
	rdstlow ← rwrdaddl,				c3;
	rchainbasel ← USavechainbasel,			c1; 
	Q ← USavechainbaseh, 				c2;
	rhchainbaseh ← Q LRot0,				c3;
	
{****************************************************************************************
  				Get next run 
*****************************************************************************************}	  
	rchainbasel ← rchainbasel + 1, CarryBr,		c1; {increment word base to point to next location}
	MesaIntBr, BRANCH[ChkInt,$],			c2;
	Q ← rhchainbaseh, CANCELBR[$],			c3;
	Q ← Q + 1,					c1;
	rhchainbaseh ← Q LRot0, MesaIntBr,		c2;
	
{****************************************************************************************
  				toggle the writebit 
*****************************************************************************************}
ChkInt:	writebit ← writebit xor 1,BRANCH[$,YesInt],	c3;{toggle the bit             } 
	L0 ← L0.ChainBlt,				c1;{xxx}
	rchaintemp ← rdstlow, GOTO[Fetch],		c2;{save R1 to rchaintemp in case page fault happens xxx}
		
{****************************************************************************************
  				interrupt checking 
*****************************************************************************************}
YesInt: stackP ← 2, 					c1;
 	Q ← rhdsthigh,					c2;
	STK ← rdstlow, push, 				c3; 
	STK ← Q, push, 					c1;
	STK ← DBit, push, 				c2;
	STK ← writebit, push, 				c3;
Yes5:	Q ← rhchainbaseh,				c1;
Yes6:	STK ← rchainbasel, push, 			c2;
	STK ← Q, GOTO[Bank1Interrupt],			c3;
	{TOS = length}
	
{****************************************************************************************
  				page fault case 
*****************************************************************************************}	
ToPageFault:
	rchaintemp ← USavedstlow,			c3; 	{restore base address to rchaintemp = rdstlow 8/12 corrected  }
	length ← USavelength, 				c1;
	uFaultParm0 ← VD,	 			c2;{set up fault 8/13}
	T ← Q,				c3;{set up fault virtual address 8/13}
	Q ← rhVD,					c1;
	uFaultParm1 ← Q,				c2;
	rchainbasel ← USavechainbasel,			c3;{8/12}
	Noop,						c1;
	GOTO[PageFaultChain],				c2;
	
 {****************************************************************************************
  				save parameters on the stack, if page fault happened 
*****************************************************************************************}	
PageFaultChain:
	stackP ← 2,					c3, MapSrcF[L0.ChainBlt];
	Q ← rhdsthigh,					c1;
	STK ← rchaintemp, push, 			c2; {push rdstlow}
	STK ← Q, push, 					c3;
	STK ← DBit, push, 				c1;
	STK ← writebit, push, 				c2;
	Q ← rhchainbaseh, 				c3;
	STK ← rchainbasel, push, 			c1;
	STK ← Q, GOTO [Bank1Fault],			c2;
	{TOS = length}
				
{****************************************************************************************
  				Exit from mesa 
*****************************************************************************************}
ChainExit1:
	Noop,						c1;
	Noop,						c2;
ChainExit3:
	CANCELBR[Bank1NxtInstc1],	 		c3;