{ 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}