{
File : NEWVECTOROPS.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[ufnX3], c2;
{END}