; Mu Float.mu     
; Copywrite Xerox Corporation 1980
; Horizontal bit blit.
; Updated by Bob Lyon on November 2, 1979  10:48 AM
; Updated by LStewart on May 14, 1980  7:33 PM
; Entry point is 540B.
; The only way this routine distinguishes HBlt from XHBlt
; is by inspection of stkp.  If its is NOT 1 then XHBlt is used
; instead of HBlt.
; If this is used with the floating point package,
; put this file after the floating point entry predefs.
; That is, put "#HBlt.mu;" after the ram entry vector in file
; Float.mu.
;
$ROMMUL	$L004120,0,0;	MUL routine address (120B) in ROM0
; shiftable register declarations
$MRMC	$600;	
; shiftable register declarations
$Temp	$R1;	
$OpCode	$R2;	
; non-shiftable register declarations	
$flags	$R35;
$dbca	$R36;	
$gray	$R55;	
$Smask	$R57;	
$x1	$R56;	
$x2	$R41;	
$Mflag	$R45;	
$HoldPC	$R44;	
$addr	$R47;	
$endAddr $R51;
$AllOnes $R46;
$savBnk	$R43;
$BnkAddr $R42;
; 3 and 50 should be available
; Move seven parameters from memory to S registers
; and claculate deltax, deltay, and init point P to point A
; %1,1777,550,HBlt;		HBlt is the entry point.
%7,17,0, Got0,, Got2,, Got4,, Got6;  Return locs for mem reads.
!1,2, Punt, Read;
!1,2, Step4, Step3;
HBlt:
	T ← ALLONES;
	MAR ← L ← 37 XOR T;
	BnkAddr ← L, L ← T;
	AllOnes ← L;
	L ← MD, TASK;
	savBnk ← L;

	T ← 2, :Read;		-- read dbmr and y
Got2:	T ← MD;
	AC2 ← L, L ← T;
	AC1 ← L, L ← T ← 0;	-- get ready for (y*dbmr)
;
	AC0 ← L, :Read;		-- read flags and dbca
Got0:	T ← MD;
	flags ← L, L ← T, TASK;
	dbca ← L;
;
	T ← 4, :Read;		-- read x1 and x2
Got4:	T ← MD;
	x1 ← L, L ← T;
	x2 ← L;
	L ← x1 - T - 1;
	T ← 6, SH<0;
;
	:Punt;			-- IF (x1 <= x2) goto read
Got6:	gray ← L, :GetAddr;
;
; -- Read memory subroutine
Read:
	MAR ← stk0 + T;
	L ← T;
	SINK ← M, BUS;
	L ← MD, :Got0;		-- return to Got[0-6]
;
;
; Compute the effective word begin & end address
; addr ← dbca + (y*dbmr) + x1/16;
; endAddr ← dbca + (y*dbmr) + x2/16;
; %1,1777,177,MULret;
GetAddr:
	L ← PC, TASK;
	HoldPC ← L;
	T ← ALLONES;
	L ← MRMC XOR T, SWMODE;
	PC ← L, :ROMMUL;
MULret:	L ← HoldPC, TASK;		-- restore the return addr
	PC ← L;
	T ← dbca;	-- result is in AC1
	L ← AC1 + T;
	T ← M;
;
	L ← x1;
	Temp ← L RSH 1;
	L ← Temp; 
	Temp ← L RSH 1;
	L ← Temp; 
	Temp ← L RSH 1;
	L ← Temp; 
	Temp ← L RSH 1;
	L ← Temp + T;
	addr ← L;
;
	L ← x2;
	Temp ← L RSH 1;
	L ← Temp; 
	Temp ← L RSH 1;
	L ← Temp; 
	Temp ← L RSH 1;
	L ← Temp; 
	Temp ← L RSH 1;
	L ← Temp + T, TASK;
	endAddr ← L;
;
	T ← 0 + 1;
	L ← flags AND T;
	Mflag ← L;
	T ← 7;
	L ← flags AND T;
	OpCode ← L RSH 1;

!1,2,UseXHB,Step1;
; -- If not HBlt then alter memory bank
	L ← stkp - 1;
	T ← 3, SH=0, :UseXHB;
;
UseXHB:	L ← savBnk AND NOT T;
	T ← stk1 . T;
	MAR ← BnkAddr;
	L ← M OR T;
	MD ← M, :Step1;
;
; -- mainloop has for steps:
; --	Step1: The left hand side of the blt.
; --	Step2: The right hand side of the blt.
; -- 	Step3: The middle of the blt.
; --	Step4: Finished.
; -- Narrow blts causes steps 1 and 3 to be performed together.
%17,37,0, LftEnd0, LftEnd1, LftEnd2, LftEnd3, LftEnd4, LftEnd5,
LftEnd6, LftEnd7, LftEnd8, LftEnd9, LftEnd10, LftEnd11,
LftEnd12, LftEnd13,LftEnd14, LftEnd15;
;
; -- Step 1 - Draw the furthest left hand side of the scanline.
; -- Bits [15-offset1 .. 0] are set to 1's.
Step1:
	T ← 17;			-- SINK ← x1 AND 17
	L ← x1 AND T;
	SINK ← M, BUS;
	T ← endAddr, :LftEnd0;
LftEnd0:	L ← ALLONES, :ContLE;
LftEnd1:	L ← 77777,	:ContLE;
LftEnd2:	L ← 37777,	:ContLE;
LftEnd3:	L ← 17777,	:ContLE;
LftEnd4:	L ← 7777,	:ContLE;
LftEnd5:	L ← 3777,	:ContLE;
LftEnd6:	L ← 1777,	:ContLE;
LftEnd7:	L ← 777,	:ContLE;
LftEnd8:	L ← 377,	:ContLE;
LftEnd9:	L ← 177,	:ContLE;
LftEnd10:	L ← 77,	:ContLE;
LftEnd11:	L ← 37,	:ContLE;
LftEnd12:	L ← 17,	:ContLE;
LftEnd13:	L ← 7,	:ContLE;
LftEnd14:	L ← 3,	:ContLE;
LftEnd15:	L ← 0 + 1,	:ContLE;
;
!1,2, ContSt1, Stp1to3;
%3,7,0, mRead, XmRead;
%3,7,0, mWrite, XmWrite;
;
ContLE:	Smask ← L;
	L ← addr - T;		-- T ← endAddr from above
	TASK, SH=0;
	:ContSt1;
ContSt1: SINK ← Mflag, BUS;
	L ← ALLONES, :mRead;
Stp1to3: T ← 17, :Step3;
;
!1,2, ContSt2, ContSt3;
%17,37,0, RhtEnd0, RhtEnd1, RhtEnd2, RhtEnd3, RhtEnd4, RhtEnd5,
RhtEnd6, RhtEnd7, RhtEnd8, RhtEnd9, RhtEnd10, RhtEnd11,
RhtEnd12, RhtEnd13,RhtEnd14, RhtEnd15;
; -- Step 3 - Draw the furthest right hand side word of the
; -- scanline. Bits [0 .. offset2] are left alone.
Step3:
	L ← x2 AND T;	 	-- SINK ← x2 AND 17
	SINK ← M, BUS;
	:RhtEnd0;
RhtEnd0:	T ← 77777,	:ContRE;
RhtEnd1:	T ← 37777,	:ContRE;
RhtEnd2:	T ← 17777,	:ContRE;
RhtEnd3:	T ← 7777,	:ContRE;
RhtEnd4:	T ← 3777,	:ContRE;
RhtEnd5:	T ← 1777,	:ContRE;
RhtEnd6:	T ← 777,	:ContRE;
RhtEnd7:	T ← 377,	:ContRE;
RhtEnd8:	T ← 177,	:ContRE;
RhtEnd9:	T ← 77,		:ContRE;
RhtEnd10:	T ← 37,		:ContRE;
RhtEnd11:	T ← 17,		:ContRE;
RhtEnd12:	T ← 7,		:ContRE;
RhtEnd13:	T ← 3,		:ContRE;
RhtEnd14:	T ← 0+1,	:ContRE;
RhtEnd15: 	T ← 0,		:ContRE;
ContRE:	L ← Smask AND NOT T, TASK;
	Smask ← L;
ContSt3: SINK ← Mflag, BUS;
	L ← ALLONES, :mRead;
;
; -- The 1's in Smask describes which bit locations in the word
; -- That will be affected by HBlt.
%7,17,0, op0, op1, op2, op3;
mRead:	MAR  ← addr, :ContMB;
XmRead:	XMAR ← addr, :ContMB;
ContMB:	T ← Smask;
	SINK ← OpCode, BUS;
	Smask ← L, :op0;
;
op0:	L ← MD AND NOT T; 	-- dest ← gray
	T ← gray . T;
	L ← M OR T, :ContBd2;
;
op1:	T ← gray . T;		-- dest ← dest OR gray
	L ← MD OR T, :ContBd2;
;
op2:	T ← gray . T;		-- dest ← dest XOR gray
	L ← MD XOR T, :ContBd2;
;
op3:	T ← gray . T;		-- dest ← (NOT gray) AND dest
	L ← AllOnes XOR T;
	T ← MD;
	L ← M AND T, :ContBd2;
;
ContBd2: SINK ← Mflag, TASK, BUS;
	Temp ← L, :mWrite;
mWrite:	MAR  ← addr, :Step2;
XmWrite: XMAR ← addr, :Step2;
;
Step2:
	T ← endAddr-1;
	L ← addr - T;
	MD ← Temp;
	L ← addr + 1, SH<0;
	addr ← L, :ContSt2;	-- IF(addr<endAddr) goto ContSt3
ContSt2: L ← addr - T - 1;
	SH=0;
	T ← 17, :Step4;		-- IF(addr=endAddr) goto Step3
;
; -- Step 4 is where we return to mesa.
Punt:	T ← 0;			-- NOP, premature exit
Step4:
	MAR ← BnkAddr;
	L ← 0;
	MD ← savBnk, TASK;
	stkp ← L;
	SWMODE;
	:romnextA;