{
File name LispBB.mc
Description: BitBlt op-code
Author: don charnley
Last edited: October 8, 1980  6:35 PM
Created: October 1983
}

{*****************************************************************************
	BITBLT
*****************************************************************************}

{OLD: {CAUTION: there is a delicate sharing of .u+D by uTOS and UWidth; during faults UWidth is stored in TOS; at restart {BBpart} it is tested for nonZero and restorted}}
{.u+2 thru .u+C must be preserved accross faults; in particular no bitBlt by fault handler}

{TOS=0 if virgin BB call;  else suspended with saved state on stack under TOS}
{2 args one usually 0 in TOS; S points to ptr to BBtable}

	MAR ← [rhS, S+0],	c1, at[BBEntry];
	{UWidth}Ybus ← TOS, NZeroBr,	c2;
	TOS ← MD, BRANCH[$, BBpart],	c3;

	MAR ← S ← [rhS, S - 1],	c1;
	S←S-1, CANCELBR[$, 2],	c2;
	TOSH ← MD,	c3;

{S points to some stack entry that has nothing to do with BB}
{BBInit vs BBInit1 differ on advacing PC}
	PC ← PC + 1{PC16}{1}{%?}{saveRegs does PC←PC-1},	c1;
	stackP ← 2,	c2;
	Noop,	c3;

	uPCCross ← TOSH xor ~TOSH,{uPCCross#uPCCrossL}	c1;
	STK{UBitBltArg} ← TOS, pop,	c2;
	rhMDS ← TOSH LRot0, GOTO[@BITBLT],	c3;

{@BITBLT returns directly to IBDispOnly; saves and restores L, G, PC}

BBpart:	{Q ← 166'b, GOTO[sink2],	c1;}
	uPCCross ← TOSH xor ~TOSH,{uPCCross#uPCCrossL}	c1;
	PC ← PC + 1{PC16}{1}{%?}{undone by saveRegs},	c2;
	stackP ← 0C{vestigial}, {GOTO[@BITBLT],}	c3;

{restore 12 uRegs from memory stack: u2 thru u0D } 
	stackP ← 0D,	c1;
	Rx ← 0C,	c2;
BBLp:	Noop,	c3;

{Stack pointer points to full odd word } 
	MAR ← S ← [rhS, S +0], 	c1;
	S ← S - 2,	c2;
	TT ← MD,	c3;

	Rx ← Rx - 1, ZeroBr,	c1;
	STK ← TT, pop, BRANCH[BBLp, BBLpD],	c2;

BBLpD:	stackP ← 0C{not vestigial}, GOTO[@BITBLT],	c3;

{@BITBLT returns  to IBDispOnly normally or to SaveRegs if fault {or interrupt}}
{interupts are temporarily disabled in BB}
{S points to some stack entry that has nothing to do with BB}

{if faulting save 12 uRegs to memory stack: u2 thru u0D } 
{then set TOSH,TOS to nonzero to indicate BB suspended (PFault saves TOS)} 
{at PFault TOS is nonzero and under that is saved regs } 
SaveRegs: {come here on pageFault}{{state held in stack (faults can't bitblt)}}
	rhTT ← uFaultParm1, 	c2;
	TT ← uFaultParm0,	c3;

{Stack pointer points to full odd word } 
{save 12 uRegs from memory stack: u2 thru u0D } 
	stackP ← 02,	c1;
	Rx ← 0C,	c2;
BBsLp:	S{even empty} ← S{odd full} + 1,	c3;

	MAR ← S ← [rhS, S +0], 	c1;
	MDR ← smallpl,	c2;
	S ← S + 1,	c3;

	MAR ← S ← [rhS, S +0], 	c1;
	MDR ← STK, push,	c2;
	Noop,	c3;

	Rx ← Rx - 1, ZeroBr,	c1;
	BRANCH[BBsLp, BBsLpD],	c2;

BBsLpD:	stackP ← 0C{not vestigial},	c3;

	TOSH ← smallpl,	c1;
	TOS ← 1{UWidth}{uTOS}, L1 ← L1.NoFixes{DecOnly?},	c2;
	stackP ← 0,	c3;

	Bank ← 1,	c1;
	,	c2;
	CROSS[BBFault],	c3;

{S points to some stack entry that has nothing to do with BB}
{Normal BB returns undefined : set TOSH, TOS to any valid object (use smallpl)}
{@BITBLT returns directly to IBDispOnly; saves and restores L{PV}, G{S}, PC}
{stackP was set to zero by BB as we return here; any thing below .u+D is ok}
BBThru:
	Bank ← 1,	c1;
	,	c2;
	CROSS[BBExit],	c3;

{*********************************************
	MaskTbl  SUBROUTINE	1 cycle
*********************************************}
{	first cycle = c* , one cycle long
This subroutine generates a right justified mask. of n ones
RETURNS THRU MaskRet
}

MaskTbl:	TT ← 1, RET[MaskRet],	c*, at[0,10,MaskTbl];
	TT ← 3, RET[MaskRet],	c*, at[1,10,MaskTbl];
	TT ← 7, RET[MaskRet],	c*, at[2,10,MaskTbl];
	TT ← 0F, RET[MaskRet],	c*, at[3,10,MaskTbl];
	TT ← 1F, RET[MaskRet],	c*, at[4,10,MaskTbl];
	TT ← 3F, RET[MaskRet],	c*, at[5,10,MaskTbl];
	TT ← 7F, RET[MaskRet],	c*, at[6,10,MaskTbl];
	TT ← 0FF, RET[MaskRet],	c*, at[7,10,MaskTbl];
	TT ← LShift1 0FF, SE←1, RET[MaskRet] {TT ← 1FF},	c*, at[8,10,MaskTbl];
	TT ← RShift1 u7FF, RET[MaskRet] {TT ← 3FF},	c*, at[9,10,MaskTbl];
	TT ← u7FF, RET[MaskRet] {TT ← 7FF},	c*, at[0A,10,MaskTbl];
	TT ← RShift1 u1FFF, RET[MaskRet] {TT ← FFF},	c*, at[0B,10,MaskTbl];
	TT ← u1FFF, RET[MaskRet] {TT ← 1FFF},	c*, at[0C,10,MaskTbl];
	TT ← uTT3FFF, RET[MaskRet] {TT ← 3FFF},	c*, at[0D,10,MaskTbl];
	TT ← RShift1 (~TT xor TT), RET[MaskRet] {TT ← 7FFF},	c*, at[0E,10,MaskTbl];
	TT ← ~TT xor TT, RET[MaskRet] {TT ← FFFF},	c*, at[0F,10,MaskTbl];

	{ E N D }