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