{

File name : polynomial.mc
Author : Gwan Santosa & Don Charnley
Created : 27-Dec-84 13:16:16

==========================================================================
MICROCODE FOR LISP POLYNOMIAL EVALUATION
==========================================================================

}
{Set[ib.poly, 0];}

{RegDef[uAinitH,	U,	57];	{A(0) H}
RegDef[uAinitL,	U,	58];	{A(0) L}
RegDef[uXHi,	U,	30];	{X H}
RegDef[uXLo,	U,	05];	{X L}
RegDef[uDegree,	U,	42];	{The degree of polynomial}
RegDef[uTTtmp,	U,	43];	{Virtual address, tmp}
RegDef[uAnxtH,	U,	44];	{New A, H word, tmp}
}

{Set[L0.RedoPOLY0,	3];	{Return value for RLMapFixB2}
Set[L0.RedoPOLY1,	4];	{Return value for RLMapFixB2}
}
{Set[PolyBank,	2];
}

{Set[POLYcode, 12A];

Set[L1.NoFixesB2,	2];
RegDef[TT,	R,	2];
RegDef[rhTT,	RH,	2];
RegDef[S,	R,	4];
RegDef[rhS,	RH,	4];
RegDef[Rx,	R,	6];
RegDef[rhRx,	RH,	6];
RegDef[TOS,	R,	0];
RegDef[rhTOS,	RH,	0];
RegDef[TOSH,	R,	1];
RegDef[rhTOSH,	RH,	1];
RegDef[PC,	R,	5];
RegDef[uPPsave,	U,	4C];

Set[smallpl,	16'b];
MacroDef[CROSS, GOTOABS[#1]];
}


{
@POLY:
	Bank ← PolyBank,			c1;
	,					c2;	{assume a two byte opcode}
	Ybus ← Q, ZeroBr, CROSS[POLYcode],	c3;
}

	uTOS ← TOS,	c1, at[POLYcode];
	Ybus ← ibNA, YDisp,	c2;
	uTOSH ← TOSH, DISP4[misc3disp],	c3;
		
PolyB2:	MAR ← [rhS, S - 1],	c1, at[ib.poly, 10, misc3disp];
	Q ← TOSH xor smallpl, ZeroBr,	CANCELBR[$,2],	c2;	{degree of polynomial}
	rhTT ← MD, BRANCH[PolyufnX1, $],		c3;	{H Address of memory block}

	MAR ← [rhS, S + 0],		c1;	{for coefficients of polynomial}
	S ← S - 2,			c2;	
	TT ← MD,			c3;	{L address of coefficient}

	MAR ← [rhS, S - 1],		c1;	{pointer to X}
	Xbus ← ib, CANCELBR[$,2],	c2;
	Q ← MD,				c3;	{Load X H word}
	
	
{	uXHi ← Q,			c1;
	Noop,		 		c2;	{Set up the degree of polynomial}
	uDegree ← TOS,			c3;
	
 
	MAR ← [rhS, S + 0],		c1;	{pointer to X}
	S ← S + 2,			c2;
	Q ← MD,				c3;	{Load X L word}
	
	uXLo ← Q,			c1;
	L1 ← L1.NoFixesB2,		c2;
	L0 ← L0.RedoPOLY0,		c3;}
 
	MAR ← [rhS, S + 0],		c1;	{pointer to X}
	uXHi ← Q,			c2;
	Q ← MD,				c3;	{Load X L word}
	
	uXLo ← Q,				c1;
	S ← S + 2, L1 ← L1.NoFixesB2,		c2;
	uDegree ← TOS, L0 ← L0.RedoPOLY0,	c3;	{Set up the degree of polynomial}
 
	Map ← [rhTT, TT],		c1;	{point to virtual memory}
	uTTtmp ← TT,			c2;	{Save these regs for remap !}
	rhRx ← Rx ← MD, XRefBr,		c3;	{Check ref. bit}
 
	MAR ← Q ← [rhRx, TT + 0], BRANCH[POLYmapcheck, $],	c1, at[L0.RedoPOLY0, 10,RMapFixCallerB2];
	 
	Rx ← Q,							c2;
	Q ← MD,							c3;	{A(0) H word}
 
	MAR ← Rx ← [rhRx, Rx + 1],	c1;
	uAinitH ← Q, CANCELBR[$, 2],	c2;
	Q ← MD,				c3;	{A(0) L word}
 
	TT ← 0FF + 1,		 	c1;	{set PPort to read}
	uAinitL ← Q,			c2;
	Noop,				c3;
	
	Noop, 				c1;
	Q ← uPPsave,			c2;
	PPort ← Q ← Q and ~TT,		c3;
	

{	INNER LOOP OF POLY OPCODE
 	init:	FPChip ← a(0)
		FPChip ← X   mpy

	loop:	FPChip ← a(next)
		FPChip ← FPResult   add

		if no more a, then GOTO end
		FPChip ← X
		FPChip ← FPResult   mpy
		GOTO loop

	end:	Answer ← FPResult}
	
{

This section handles the arithmatic operation,
utilizing the floating point chips.

}

POLYinit:

	FloatNop, 				c1;
	FloatNop, 				c2;
	FloatMode.RN.AI.IEEE, FloatPIPE, 	c3;
	
	Q ← FloatAB ← uAinitH,		c1;	{Load A(0)}
	FloatAB ← uAinitL,		c2;	{Load A(0)}
	TT ← FloatA ← uXHi, FLTimes.A.B,	c3;	{Multiply by X}
	
	Noop,				c1;
	Noop,				c2;	
	FloatA ← uXLo, GOTO[POLYpump],	c3;	

POLYloop:

	uAnxtH ← Q, 			c2;
	Noop,				c3;

	MAR ← Rx ← [rhRx, Rx + 1], 					c1;	{next coeff., L word}	
	FloatAB ← uAnxtH, FloatUnloadP, Float.M, CANCELBR[$,2],		c2;	{Load A(next)hi}
	FloatAB ← MD, FloatUnloadP, Float.L,				c3;	{Load A(next)lo}
	
	Q ← FloatA ← FloatResult, FLPlus,		c1;	{Load multiplication result}
	Xbus ← PPort, XDisp,			c2;	{Get status}
	TT ← FloatA ← FloatResult, DISP4[TEST0,3],	c3;	{Add with new constant}
								{Check result}
TP11:	
	FloatPump,				c1, at[0F,10,TEST0];	
	FloatPump,				c2;	{If correct, continue}
	FloatPump, 				c3;	{count down}
	
	Q ← uDegree,				c1;
	FloatPump,				c2;		
	Q ← Q - 1,	ZeroBr,			c3;
	
	uDegree ← Q, BRANCH[POLYgoon,POLYend],	c1;
			
POLYgoon:

	FloatAB ← uXHi, 			c2;	{Load X, H word}
	FloatAB ← uXLo, 			c3;	{Load X, L word}
	
	Noop,					c1;	
	FloatUnloadS, Float.M,			c2;
	FloatUnloadS, Float.L,			c3;
	
	Q ← FloatA ← FloatResult, FLTimes.A.B,	c1;	{Load new result, multiply by X}
	Xbus ← PPort,  XDisp,			c2;	{Get status}
	TT ← FloatA ← FloatResult,	DISP4[TEST1,3],	c3;	{Check status}
	
POLYpump:

	FloatPump, 				c1, at[0F,10,TEST1];
	FloatPump,				c2;	{If correct, continue}
	FloatPump, 				c3;
	
TP22:	MAR ← Rx ← [rhRx, Rx + 1], 		c1;	{point to next coefficient, H word}
	FloatPump, BRANCH[$, POLYnwpg,1],	c2;	{check for page boundary}
	
POLYpgbn:	
	
	Q ← MD, FloatPump,			c3;	{Load A H word}
	
	FloatPump, GOTO[POLYloop],		c1;

	GOTO[ufnX2],				c1, at[03, 10, TEST0];	{FPT result not OK}
	GOTO[ufnX2],				c1, at[07, 10, TEST0];	{FPT result not OK}
	GOTO[ufnX2],				c1, at[0B, 10, TEST0];	{FPT result not OK}
	
	GOTO[ufnX2],				c1, at[03, 10, TEST1];	{FPT result not OK}
	GOTO[ufnX2],				c1, at[07, 10, TEST1];	{FPT result not OK}
	GOTO[ufnX2],				c1, at[0B, 10, TEST1];	{FPT result not OK}
	
POLYnwpg:

	TT ← uTTtmp,				c3;	{Retrieve TT}	

	Q ← 0FF + 1, 				c1;	{Load Q with 100}
	TT ← TT + Q, CarryBr,			c2;	{Add TT with 100}
	Q ← rhTT, BRANCH[POLYnoadd, POLYadd],	c3;	{Check for carry}
	
POLYadd:

	Q ← Q + 1,				c1;	{If there is, propagate to rhTT}
	rhTT ← Q LRot0,				c2;
	L0 ← L0.RedoPOLY1,			c3;
	
POLYnoadd:

	Map ← [rhTT, TT],			c1;	{No carry}
	L1 ← L1.NoFixesB2, uTTtmp ← TT,		c2;	{Save TT again}
	rhRx ← Rx ← MD, XRefBr,			c3;
	
	MAR ← Q ← [rhRx, 0+0], BRANCH[POLYmapcheck1, $],	c1, at[L0.RedoPOLY1,10,RMapFixCallerB2];

	Rx ← Q, GOTO[POLYpgbn],					c2;	{Go back}

POLYmapcheck:

	CALL[RLMapFixB2],		c2;	
	
POLYmapcheck1:

	CALL[RLMapFixB2],		c2;	
	
		
PolyufnX1:

	GOTO[ufnX2],			c1;

POLYend:

	FloatPump,				c2;
	FloatPump, 				c3;
	
	Noop,					c1;
	FloatUnloadS, Float.M,			c2;
	FloatUnloadS, Float.L,			c3;
	
	TOSH ← FloatResult,			c1;	{Result H word}
	Xbus ← PPort, XDisp,			c2;	{Read the status}
	TOS ← FloatResult, DISP4[TEST2,3],	c3;	{Result L word}

	S ← S - 4,				c1, at[0F,10,TEST2];
	Noop,					c2;
	GOTO[c1.pc2B2],				c3;
	
	GOTO[ufnX2],				c1, at[03, 10, TEST2];	{FPT result not OK}
	GOTO[ufnX2],				c1, at[07, 10, TEST2];	{FPT result not OK}
	GOTO[ufnX2],				c1, at[0B, 10, TEST2];	{FPT result not OK}