{
File : VECTOROPS.mc
Author : Gwan Santosa
Date :  2-Aug-85 14:11:37

This program does the following vector operations :

1. Get a pointer to a maximum value of a vector.
2. Get a pointer to a minimum value of a vector.
3. Get a pointer to an absolute minimum value of a vector.
4. Get a pointer to an absolute maximum value of a vector.
5. Get sum of vector's elements (not coded yet).

Algorithm (for 1 to 4) :

	Fetch stack parameters. (TOS = count down counter)
	Check counter, if 0, exit.
	If 1, exit.
	Otherwise :
	Initialize current position to 1.
	Initialize index to 0.
	Fetch 2 floating point numbers from array.
	Store the first element into reference register.

Inner loop :
	
	Call comparison subroutine.
	If TOS is 0, done.
	Else :
	Update current position
	Fetch next element.
	Back to Inner loop
	
Comparison subroutine :

	Check if to find absolute extreme.
	If yes, convert sign bit to +.
	Else :
	Compare 2 numbers.
	If new extreme is found, update index and reference register.
	Return	
}

{Set[L1.FS.NR.0C, 0C];}
Set[L0.VO.RO.04, 04];
Set[L0.VO.RO.05, 05];
Set[L0.VO.RO.09, 09];
Set[L0.VO.RO.0A, 0A];
Set[L0.VO.RO.0B, 0B];

RegDef[rCOUNT, R, 04]; {=S}
RegDef[rRESMN, R, 05]; {=PC}
RegDef[uINDEX, U, 42];
RegDef[uNEWH, U, 44];
RegDef[uMAXH, U, 05];
RegDef[uMAXL, U, 56];


	Ybus ← TOSH xor smallpl, ZeroBr, GOTO[VOBK1],	c3, at[0C, 10, ub2op]; {Check if size = NIL}

	Ybus ← TOSH xor smallpl, ZeroBr, GOTO[VOBK1],	c3, at[0D, 10, ub2op]; {Check if size = NIL}

	Ybus ← TOSH xor smallpl, ZeroBr, GOTO[VOBK1],	c3, at[0E, 10, ub2op]; {Check if size = NIL}
	
	Ybus ← TOSH xor smallpl, ZeroBr, GOTO[VOBK1],	c3, at[0F, 10, ub2op]; {Check if size = NIL}
	
VOBK1:	TT ← 0FF + 1, BRANCH[VOER1, $],	 	c1; {set PPort to read}
	Q ← uPPsave, L1 ← L1.FS.NR.0C,		c2;
	PPort ← Q and ~TT, CALL[SaveAllRegsB2],	c3; {Save all registers}
	
	MAR ← [rhS, S - 1],			c1, at[L1.FS.NR.0C, 10, SaveRegsB2Ret];
	Ybus ← TOS, ZeroBr, CANCELBR[$, 2],	c2; {Check if size = 0}
	Q ← MD, BRANCH[$, VOER0],		c3;
	
	MAR ← [rhS, S + 0],			c1;
	TOS ← TOS - 1, ZeroBr,			c2; {check if only 1 entry}
	TT ← MD, BRANCH[$, VOEX0],		c3;
	
	rhTT ← Q LRot0,				c1;
	FloatNop,				c2;
	FloatNop,				c3;
	
TS101:	Map ← [rhTT, TT + 0], L1 ← L1.FS.NR.0C, c1;
	uTT ← TT, L0 ← L0.VO.RO.04, 		c2;
	rhRx ← Rx ← MD, XRefBr,			c3;
	
TS202:	MAR ← Q ← [rhRx, TT + 0], BRANCH[VOCH0, $],	c1, at[L0.VO.RO.04, 10, NRMapFixCallerB2];
	Rx ← Q,						c2;
	TOSH ← MD,					c3;
	
TS303:	MAR ← Rx ← [rhRx, Rx + 1], L2 ← 00,	c1; {Get first element and initialize as MAX}
	uMAXH ← TOSH, BRANCH[$, FXVO0, 1],	c2;
	TOSH ← MD,				c3;
	
		
TS404:	MAR ← Rx ← [rhRx, Rx + 1], L2 ← 01,	c1, at[00, 10, FETCHRET];
	uMAXL ← TOSH, BRANCH[$, FXVO1, 1],	c2;
	TOSH ← MD,				c3;
	
TS505:	MAR ← Rx ← [rhRx, Rx + 1], L2 ← 02,	c1, at[01, 10, FETCHRET];
	uNEWH ← TOSH, BRANCH[$, FXVO2, 1],	c2;
	TOSH ← MD,				c3; {Get second element and initialize as NEW}
	
TS606:	rCOUNT ← 1,					c1, at[02, 10, FETCHRET];
	uINDEX ← 0,					c2; {Index keeps track of the latest extreme}
	FloatMode.RN.AI.IEEE, FloatFLOW, CALL[VOCP],	c3; {Count keeps track of the current position}

{
========================================================================================================
Inner loop
========================================================================================================
}	
	TOS ← TOS - 1, ZeroBr,			c1, at[0, 10, COMPRET]; {TOS is the count down counter}
	rCOUNT ← rCOUNT + 1, BRANCH[$, VOEX1],	c2; {If TOS = 0, done}
	L2 ← 03,				c3; {Current position (rCOUNT) is updated}
	
	MAR ← Rx ← [rhRx, Rx + 1], 		c1; {Fetch next element}
	BRANCH[$, FXVO3, 1],			c2;
	TOSH ← MD, 				c3;

	MAR ← Rx ← [rhRx, Rx + 1], 		c1, at[03, 10, FETCHRET];
	uNEWH ← TOSH, BRANCH[$, FXVO4, 1],	c2;
CHRT5:	TOSH ← MD, CALL[VOCP],			c3; {Call comparison subroutine}
	
{
==========================================================================================
Compare subroutine
==========================================================================================

This subroutine handles 4 comparisons.
The low 2 bits of ib determines which operation.

00 : Find index of max. value.
01 : Find index of min. value.
10 : Find index of absolute max. value.
11 : Find index of absolute min. value.

If a new extreme value is found, it will update the index and the new extreme value is
loaded into a reference register uMAX

}


VOCP:	Xbus ← ibNA, XDisp,		c1;
	Q ← uMAXH, DISP4[MAXMIN, 0D],	c2;
	
	GOTO[VCOM],			c3, at[0D, 10, MAXMIN];
	
	TT ← ~TT xor TT,		c3, at[0F, 10, MAXMIN];
	
	TT ← RShift1 TT, SE ← 0,	c1; {This section convert the sign bit to +}
	Q  ← TT and Q,			c2;
	uMAXH ← Q,			c3;
	
	Q ← uNEWH,			c1;
	Q ← TT and Q,			c2;
	uNEWH ← Q, GOTO[VCOM],		c3;	
	
VCOM:	FloatAB ← uNEWH,		c1;	
	FloatAB ← TOSH LRot0,		c2;
	FloatA ← uMAXH,	FLAMinusB,	c3;
	
	FloatA ← uMAXL,			c1;		
	FloatNop,			c2;
	Noop,				c3;
	
	L3 ← 0,				c1;	
	Noop,				c2;
	FloatUnloadS,	Float.M,	c3;
	
	FloatUnloadS,	Float.L,	c1;	
	rSTATUS ← PPort,		c2;
	rRESMN ← FloatResult,		c3;
	
	Q ← FloatResult,		c1;
	rRESMN ← rRESMN LRot8,		c2;
	
	rRESMN ← rRESMN and 80, 	c3;
	
	Xbus ← ibNA, XDisp,		c1;
	DISP4[VOMAXMIN, 0E],		c2;
		
	Ybus ← rRESMN, ZeroBr,		c3, at[0E, 10, VOMAXMIN]; {Determine max. value}
		
	BRANCH[FNMAX1, SMMAX],		c1;
	
FNMAX1:	Q ← uNEWH, 			c2; {B>A, New max. is found}
	uMAXH ← Q,			c3; {Update uMAXH and uMAXL}
		
	uMAXL ← TOSH,			c1; {They now contain the new extreme value}
	uINDEX ← rCOUNT, L3Disp,	c2;
	RET[COMPRET],			c3;
	
SMMAX:	L3Disp,				c2;
	RET[COMPRET],			c3;

	Ybus ← rRESMN, ZeroBr,		c3, at[0F, 10, VOMAXMIN]; {Determine min. value}

	BRANCH[SMMIN, FNMIN1],		c1;
	
FNMIN1:	Q ← uNEWH, 			c2; {New min. is found}
	uMAXH ← Q,			c3; {Update uMAXH and uMAXL}
		
	uMAXL ← TOSH, 			c1; {They now contain the new extreme value}
	uINDEX ← rCOUNT, L3Disp,	c2;
	RET[COMPRET],			c3;
	
SMMIN:	L3Disp,				c2;
	RET[COMPRET],			c3;

	
{
==========================================================================================
Remap
==========================================================================================
}

VOCH0:	CALL[NRLMapFixB2],		c2;

VOCH1:	CALL[NRLMapFixB2],		c2;

VOCH5:	CALL[NRLMapFixB2],		c2;


FXVO0:	GOTO[VOFX],		c3;

FXVO1:	GOTO[VOFX],		c3;

FXVO2:	GOTO[VOFX],		c3;

FXVO3:	TT ← uTT, GOTO[VOFX],		c3;
		
VOFX:	Q ← 0FF + 1,			c1;

	TT ← TT + Q, CarryBr,		c2;
	Q ← rhTT, BRANCH[VONC0, VOC0],	c3;
	
VONC0:	GOTO[VOMG0],			c1;
	
VOC0:	Q ← Q + 1,			c1;
VOMG0:	rhTT ← Q LRot0,			c2;
	uTT ← TT,			c3;

	Map ← [rhTT, TT + 0], L0 ← L0.VO.RO.05,	c1;
	TOSH ← Rx, L1 ← L1.FS.NR.0C,		c2;
	rhRx ← Rx ← MD, XRefBr,			c3;
	
	MAR ← Q ← [rhRx, TOSH + 0], BRANCH[VOCH1, $],	c1, at[L0.VO.RO.05, 10, NRMapFixCallerB2];
	Rx ← Q, L2Disp,			c2;
	TOSH ← MD, DISP4[FETCHRET],		c3;

FXVO4:	TT ← uTT,			c3;

	Q ← 0FF + 1,			c1;
	TT ← TT + Q, CarryBr,		c2;
	Q ← rhTT, BRANCH[VONC4, VOC4],	c3;
	
VONC4:	GOTO[MGVO1],			c1;	
	
VOC4:	Q ← Q + 1,			c1;
MGVO1:	rhTT ← Q LRot0,			c2;
	TOSH ← Rx,			c3;

	Map ← [rhTT, TT + 0], L1 ← L1.FS.NR.0C,	c1;
	uTT ← TT, L0 ← L0.VO.RO.09,		c2;
	rhRx ← Rx ← MD, XRefBr,			c3;
	
	MAR ← Q ← [rhRx, TOSH + 0], BRANCH[VOCH5, $],	c1, at[L0.VO.RO.09, 10, NRMapFixCallerB2];
	Rx ← Q, GOTO[CHRT5],				c2;
	
{
==========================================================================================
Exit points
==========================================================================================
}

VOEX0:	S ← S - 2, L1 ← L1.RestoreAndExit,	c1;
	Xbus ← ib, L1Disp,			c2;	
	DISP4[RestoreRegsB2Ret],	        c3;
	
VOEX1:	TOS ← uINDEX,				c3;

	TOSH ← uTOSH,				c1;
	S ← uS,					c2;
	PC ← uPC,				c3;
	
	S ← S - 2, L1 ← L1.RestoreAndExit,	c1;
	Xbus ← ib, L1Disp,			c2;	
	PV ← uPVx, DISP4[RestoreRegsB2Ret], 	c3;
		
{
==========================================================================================
Error cases
==========================================================================================
}

VOER0:	Noop,		c1;

VOER1:	GOTO[ufnX3],	c2;

	{END}