{File name:  NLispFPTBase.mc
Last edited by cal    21-Oct-83 11:57:59 
Last edited by Sturgis  15-Sep-83 16:40:30 
 Descrition: Floating point code for Lisp {modified from Cedar fpt code}
Created by H. Sturgis 
}

{***********************************************************************************************

De normalization code

enter with  T, ~Q holding the 32 bit quantity,   L0 prepared for return, TT holding shift count

	(note that Q is negated)

contents of TT is destroyed

De normalized result is in T, Q
Q[15] is a sticky bit

***********************************************************************************************}
DeNormC1:						c1;
DeNormC2:						c2;


DeNormC3:
	TT ← -TT - 1,	c3;

DeNormA:
	TT ← TT + 1, NZeroBr,	c1;
	Ybus ← Q and 1, ZeroBr, BRANCH[DeNormA1, $],			c2;
	T ← DRShift1 T, SE ← 0, BRANCH[DeNormA, DeNormB],		c3;

DeNormA1: {stcky bit is 0}
	Q ← ~Q, L0Disp, CANCELBR[$],		c3;

	RET[DeNormRets],	c1;

{sticky bit will be 1}
DeNormB:
	TT ← TT + 1, NZeroBr,	c1;
	BRANCH[DeNormB1, $],	c2;
	T ← DRShift1 T, SE ← 0, GOTO[DeNormB],	c3;

DeNormB1: {stcky bit is 1}
	Q ← ~Q, L0Disp,	c3;

	Q ← Q or 1, RET[DeNormRets],	c1;
	
{****************************************************************************

division code

This procedure calls unpack2 to break the arguments up into components
	Sign1 Exp1  HighHalf1  LowHalf1
	Sign2 Exp2  HighHalf2  LowHalf2

	where the high halves have 16 bits and the lowhalves have 8 bits



****************************************************************************}
	{the arguments are now unpacked}

	T ← uExp1, 						c2, at[L2.Fquot, 10, FptPrepRet];
	TT ← uExp2,						c3;

	T ← T - TT,						c1;
	T ← T + 127'd,  {re bias exponent}				c2;
	uExp1 ← T,						c3;

	TT ← uSign1,						c1;
	Q ← uSign2,						c2;
	uSign1 ← TT xor Q,					c3;

	uDivCount ← divCount, {save a non temporary R reg}			c1;
	uDivResult ← divResult, {save a non temporary R reg}			c2;

{now load the operands, right shifted by 1 bit to allow room to shift left during the divide loop, also test for zero divisor}

	divisorHigh ← uHighHalf2, ZeroBr,				c3;

	Q ← uLowHalf2, ZeroBr, BRANCH[FptDivB, FptDivA],			c1;

FptDivA:	Q ← ~Q, BRANCH[$, FptDivZero],				c2;
	divisorHigh ← DRShift1 divisorHigh, SE ← 0,
			GOTO[FptDivC],			c3;

FptDivB:	Q ← ~Q, CANCELBR[$],					c2;
	divisorHigh ← DRShift1 divisorHigh, SE ← 0,
			GOTO[FptDivC],			c3;

FptDivC:	divisorLow ← ~Q,					c1;
	T ← uHighHalf1,					c2;
	Q ← ~ uLowHalf1,					c3;

	T ← DRShift1 T, SE ← 0,					c1;
	Q ← ~Q, L0 ← L0.div2,					c2;



{as per Ed Tafts Dorado code, we will do a total of 26 iterations, 24 for quotient bits, + 2 guard bits.  They are done by first doing 16 iterations, then 10 iterations}

	divCount ← 16'd, CALL[FptDivLoopC1],				c3;

	uHighHalf1 ← divResult,					c2, at[L0.div2, 10, FptDivLoopRets];
	T ← DLShift1 T, SE ← 1, {puts a 0 into Q.15} L0 ← L0.div3, {remainder did not get its last left shift}
							c3;

	divCount ← 10'd, CALL[FptDivLoopC2],				c1;

	divResult ← divResult  LRot4,				c2, at[L0.div3, 10, FptDivLoopRets];
	[] ← T or Q, NZeroBr,					c3;

	divResult ← LShift1 (divResult), SE ← 0,	BRANCH[FptDivD, FptDivE],	c1;

	{now we install the correct sticky bit}
FptDivD:	divResult ← LShift1 (divResult), SE ← 0,	GOTO[FptDivF],		c2;
FptDivE:	divResult ← LShift1 (divResult), SE ← 1,	GOTO[FptDivF],		c2;
FptDivF:	uLowHalf1 ← divResult , GOTO[FptDivExit],			c3;


{divide by zero}
FptDivZero:	divCount ← uDivCount, {restore a non temporary R reg}		c3;

	divResult ← uDivResult, {restore a non temporary R reg}		c1;
	GOTO[FPTrapsC3],					c2;

	



FptDivExit:	divCount ← uDivCount, {restore a non temporary R reg}		c1;
	divResult ← uDivResult, {restore a non temporary R reg}		c2;
	uStickyBit ← 0, GOTO[RePackC1],				c3;



{***********************************************************************************************

divide loop

	dividend in <T,Q>
	divisor in <divisorHigh, divisorLow>

	bit count in divCount, performs bitCOunt subtractions

	return point in L0

	will accumulate bits in divResult
	<T,Q> will hold the remainder


***********************************************************************************************}

FptDivLoopC1:						c1;
FptDivLoopC2:						c2;
FptDivLoopC3:
	divResult ← 0, GOTO[FptDivSubA],				c3;

{in this part of the loop the contents of <T,Q> are positive}
FptDivSub:	{delay}						c2;
	divResult ← LShift1 (divResult), SE ← 1,				c3;

FptDivSubA:	Q ← Q-divisorLow, CarryBr,				c1;
	divCount ← divCount-1, ZeroBr, 
		BRANCH[FptDivSub1, FptDivSub0],			c2;
FptDivSub0:	T ← T-divisorHigh, CarryBr, BRANCH[$, FptDivSubExit1],		c3;
	T ← DLShift1 T, SE ← 1, {puts a 0 into Q.15}
		BRANCH[FptDivAdd, FptDivSub],			c1;

FptDivSub1:	T ← T-divisorHigh-1, CarryBr,  BRANCH[$ , FptDivSubExit2],		c3;
	T ← DLShift1 T, SE ← 1, {puts a 0 into Q.15}
		BRANCH[FptDivAdd, FptDivSub],			c1;


FptDivSubExit1: BRANCH[FptDivAddExit, FptDivSubExit],			c1;
FptDivSubExit2: BRANCH[FptDivAddExit, FptDivSubExit],			c1;

FptDivSubExit: divResult ← LShift1 (divResult), SE ← 1, GOTO[FptDivLoopExit],		c2;



{in this part of the loop the contents of <T,Q> are negative (in  2's complement)}

FptDivAdd:	{delay}						c2;
	divResult ← LShift1 (divResult), SE ← 0,				c3;
	
	Q ← Q+divisorLow, CarryBr,				c1;
	divCount ← divCount-1, ZeroBr, 
		BRANCH[FptDivAdd0, FptDivAdd1],			c2;
FptDivAdd0:	T ← T+divisorHigh, CarryBr, BRANCH[$,  FptDivAddExit1],		c3;
	T ← DLShift1 T, SE ← 1, {puts a 0 into Q.15}
		BRANCH[FptDivAdd, FptDivSub],			c1;

FptDivAdd1:	T ← T+divisorHigh+1, CarryBr, BRANCH[$, FptDivAddExit2],		c3;
	T ← DLShift1 T, SE ← 1, {puts a 0 into Q.15}
		BRANCH[FptDivAdd, FptDivSub],			c1;


FptDivAddExit1: BRANCH[FptDivAddExit, FptDivSubExit],			c1;
FptDivAddExit2: BRANCH[FptDivAddExit, FptDivSubExit],			c1;

{we have subtracted one too many times, so add back in to get correct remainder}

FptDivAddExit: divResult ← LShift1 (divResult), SE ← 0, 			c2;
	Q ← Q + divisorLow, CarryBr,				c3;

	{delay} BRANCH[FptDivAX0, FptDivAX1],			c1;		
FptDivAX1: T ← T + divisorHigh + 1, GOTO[FptDivLoopExit],			c2;		
FptDivAX0: T ← T + divisorHigh, GOTO[FptDivLoopExit],			c2;	

	

FptDivLoopExit:  L0Disp,						c3;

	RET[FptDivLoopRets],					c1;	 




	{ E N D }