{
File : NEWVECTOROPSB2.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, alpha byte 04.
2. Get a pointer to a minimum value of a vector, alpha byte 05.
3. Get a pointer to an absolute minimum value of a vector, alpha byte 06.
4. Get a pointer to an absolute maximum value of a vector, alpha byte 07.

opcode[372'b],

Stack parameters :

	S - 2 : Pointer to vector base address.
	S - 0 : Pointer of latest index.
	TOS   : Count.
	
Must work backward, start from the tail of the array.	

Algorithm (for 1 to 4) :

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.VO.NR.0E, 0E];
Set[L1.VO.NR.0D, 0D];
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, 03]; {=PV}
RegDef[rRESMN, R, 05]; {=PC}
RegDef[uINDEX, U, 42];
RegDef[uINDEX1, U, 47];
RegDef[uNEWL, U, 44];
RegDef[uNEWH, U, 45];
RegDef[uMAXH, U, 05];
RegDef[uMAXL, U, 59];
RegDef[urbaseL, U, 35];
RegDef[urbaseH, U, 30];
RegDef[urhRx1, U, 37];


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

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

	Ybus ← TOSH xor smallpl, ZeroBr, GOTO[VOBK1],	c3, at[06, 10, FOP1Disp]; {Check if size = NIL}
	
	Ybus ← TOSH xor smallpl, ZeroBr, GOTO[VOBK1],	c3, at[07, 10, FOP1Disp]; {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 + 0],			c1, at[L1.FS.NR.0C, 10, SaveRegsB2Ret];
	S ← S - 2,				c2;
	Rx ← MD,				c3; {Get index of latest extreme}
	
	MAR ← [rhS, S - 1],			c1; {Fetch base address of the array}
	Ybus ← TOS, ZeroBr, CANCELBR[$, 2],	c2; {Check if size = 0}
	Q ← MD, BRANCH[$, VOER0],		c3; {If 0, error}
	
	MAR ← [rhS, S + 0],			c1;
	S ← uS,					c2; {Restore S}
	TT ← MD, 				c3;
	
	urbaseL ← TT,	L0 ← L0.VO.RO.04,	c1;
	rCOUNT ← TOS - 1,			c2; {rCOUNT = current position}
	uINDEX1 ← Rx,				c3; {Save latest index}
	
	uINDEX ← Rx, ZeroBr,				c1; {initialize index}
	Rx ← Rx LShift1, SE ← 0, BRANCH[VONST, VOST],	c2; {If 0, first time}
	
VOST:	Rx ← rCOUNT, ZeroBr,				c3; {If current position is 0, exit}

	uINDEX ← Rx, BRANCH[$, VOEX0],		c1;		
	Rx ← Rx LShift1, SE ← 0,		c2; {Multiply index by 2}
	rCOUNT ← rCOUNT - 1,			c3; {Point to second entry from the tail}
	
	TOS ← TOS - 1,				c1; {Decrement count}
	Noop,					c2;
VONST:	TT ← TT + Rx, CarryBr,			c3; {Get V address of latest extreme}
	
	urbaseH ← Q, BRANCH[VONC00, VOC00],	c1;
	
VONC00:	GOTO[VOM000],				c2;
VOC00:	Q ← Q + 1,				c2;
VOM000:	rhTT ← Q LRot0,				c3;	
	
TS101:	Map ← [rhTT, TT + 0], L1 ← L1.VO.NR.0E, c1;
	Noop, 					c2;
	rhRx ← Rx ← MD, XRefBr,			c3; {# of subtractions = count - 1}
	
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 an element and initialize as MAX}
	uMAXH ← TOSH, BRANCH[$, FXVO0, 1],	c2;
	Q ← MD,					c3;
	
	TT ← urbaseL,				c1, at[00, 10, FETCHRET];
	uMAXL ← Q, L1 ← L1.VO.NR.0E,		c2;
	Rx ← rCOUNT,				c3; {Calculate V address of next element}	
		
	Rx ← Rx LShift1, SE ← 0,		c1;
	FloatNop,				c2;
	TT ← TT + Rx, CarryBr,			c3;
	
	Q ← urbaseH, BRANCH[VONC10, VOC10],	c1;
	
VONC10:	GOTO[VOM111],				c2;

VOC10:	Q ← Q + 1,				c2;
VOM111:	rhTT ← Q LRot0,				c3;

	Map ← [rhTT, TT + 0], L0 ← L0.VO.RO.0A,	c1;
	FloatNop,				c2;
	rhRx ← Rx ← MD, XRefBr,			c3;
	
	MAR ← Q ← [rhRx, TT + 0], BRANCH[VOCH11, $],	c1, at[L0.VO.RO.0A, 10, NRMapFixCallerB2];
	urhRx1 ← Rx,					c2; {Save rhRx}
	TOSH ← MD,					c3;
	
	Rx ← Q,					c1;
	uRx ← Rx,				c2;
	FloatMode.RN.AI.IEEE, FloatFLOW,	c3;		
	
TS505:	MAR ← Rx ← [rhRx, Rx + 1], L2 ← 02,	c1;
	uTT ← TT, BRANCH[$, FXVO2, 1],		c2;
	Q ← MD,					c3; {Get second element and initialize as NEW}
	
TS606:	Rx ← uRx, L2 ← 03,			c1, at[02, 10, FETCHRET];
	rhRx ← urhRx1,				c2;
	uNEWL ← Q, CALL[VOCP],			c3; {Call comparison subroutine}

{
========================================================================================================
Inner loop
========================================================================================================
}	
	uTOS ← TOS, ZeroBr,				c1, at[0, 10, COMPRET]; {TOS is the count down counter}
	TOS ← TOS - 1, ZeroBr, BRANCH[$, VOEX3],	c2; {If TOS = 0, done}
	rCOUNT ← rCOUNT - 1, BRANCH[$, VOEX1],		c3; {Current position (rCOUNT) is updated}
	
	MAR ← Rx ← [rhRx, Rx - 1],  NibCarryBr,	c1; {Fetch next element}
	TOSH ← uTOSH, DISP2[VOIC],		c2; {Restore TOSH for interrupt only}
	Q ← MD,  				c3, at[1, 4, VOIC];

ICRET:	MAR ← Rx ← [rhRx, Rx - 1], L2 ← 04,	c1, at[03, 10, FETCHRET];
	uNEWL ← Q, BRANCH[$, FXVO4, 1],		c2;
	TOSH ← MD, CALL[VOCP],			c3;
	
	,					c1, at[04, 10, FETCHRET];
	TOSH ← Q,				c2; {If page cross, return here}
	CALL[VOCP],				c3;
	
{
==========================================================================================
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;
	
	uNEWH ← TOSH, 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;
	
	Noop,				c1;
	TOSH ← TT and TOSH,		c2;
	uNEWH ← TOSH, GOTO[VCOM],	c3;	
	
VCOM:	FloatAB ← uNEWH,		c1;	
	FloatAB ← uNEWL,		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;	
	Q ← 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:	uMAXH ← TOSH, 			c2; {B>A, New max. is found}
	Q ← uNEWL,			c3; {Update uMAXH and uMAXL}
		
	uMAXL ← Q,			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:	uMAXH ← TOSH, 			c2; {New min. is found}
	Q ← uNEWL,			c3; {Update uMAXH and uMAXL}
		
	uMAXL ← Q, 			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;

VOCH11:	CALL[NRLMapFixB2],		c2;

VOCH5:	CALL[NRLMapFixB2],		c2;


FXVO0:	GOTO[VOFX],		c3;


FXVO2:	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;
	Q ← Rx, L1 ← L1.VO.NR.0E,		c2;
	rhRx ← Rx ← MD, XRefBr,			c3;
	
	MAR ← Q ← [rhRx, Q + 0], BRANCH[VOCH1, $],	c1, at[L0.VO.RO.05, 10, NRMapFixCallerB2];
	Rx ← Q, L2Disp,					c2;
	Q ← MD, DISP4[FETCHRET],			c3;

	TT ← uTT, L2 ← 03, GOTO[VOFX88],		c3, at[2, 4, VOIC];
	
	TT ← uTT, L2 ← 03, GOTO[VOFX88],		c3, at[3, 4, VOIC];

FXVO4:	TT ← uTT, GOTO[VOFX88],		c3;

FXVO5:	TT ← uTT, GOTO[VOFX88],		c3;

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

	Map ← [rhTT, TT + 0], L1 ← L1.VO.NR.0D,	c1;
	uTT ← TT, L0 ← L0.VO.RO.09,		c2;
	rhRx ← Rx ← MD, XRefBr,			c3;
	
	MAR ← Q ← [rhRx, Q + 0], BRANCH[VOCH5, $],	c1, at[L0.VO.RO.09, 10, NRMapFixCallerB2];
	Rx ← Q, L2Disp,					c2;
	Q ← MD, DISP4[FETCHRET],			c3;

	
	MAR ← [rhS, S + 0],		c1, at[L1.VO.NR.0E, 10, NTrapFixesB2];
	MDR ← uINDEX1, GOTO[PF11],	c2;
		
	MAR ← [rhS, S + 0],		c1, at[L1.VO.NR.0D, 10, NTrapFixesB2];
	MDR ← uINDEX,			c2;
PF11:	Noop,				c3;
	
	Q ← 0, GOTO[RestoreAllRegsAndPFB2],	c1;
	
{
==========================================================================================
Interrupts check
==========================================================================================
}

	Q ← MD, MesaIntBr,			c3, at[0, 4, VOIC];
	
BP000:	Ybus ← uWDC, NZeroBr, BRANCH[VONI1, $],	c1;
	Ybus ← uWP, ZeroBr, BRANCH[$, VONI2],	c2;
	uWP ← 0, BRANCH[VOINT, ICRE1],		c3;
	
VONI1:	CANCELBR[$],				c2;

VONI2:	CANCELBR[$],				c3;

ICRE1:	MAR ← Rx ← [rhRx, Rx - 1], L2 ← 04,	c1;
	uNEWL ← Q, BRANCH[$, FXVO5, 1],		c2;
	TOSH ← MD, CALL[VOCP],			c3;

VOINT:	MAR ← [rhS, S + 0],			c1;
	MDR ← uINDEX,				c2;
	TOS ← uTOS, GOTO[FTGIN],		c3;
	
		
{
==========================================================================================
Exit points
==========================================================================================
}

VOEX0:	PV ← uPVx,				c2;
	uINDEX ← 0, GOTO[VOEX2],		c3;

VOEX3:	CANCELBR[$],				c3;

VOEX1:	TOSH ← uTOSH,				c1;
	PV ← uPVx,				c2;
	PC ← uPC,				c3;
	
VOEX2:	S ← S - 4, L1 ← L1.RestoreAndExit,	c1;
	Xbus ← ib, L1Disp,			c2;	
	TOS ← uINDEX, DISP4[RestoreRegsB2Ret], 	c3;
		
{
==========================================================================================
Error cases
==========================================================================================
}

VOER0:	S ← uS,		c1;

VOER1:	GOTO[ufnX32],	c2;

	{END}