{ File : NewXFTS.mc Author : Gwan Santosa Date : 16-Sep-85 15:49:45 This program converts an array of floating points into an array of integers The integers are 8 bits numbers, the floating points are 32 bits numbers. The format : (FTS Src Dest Count) S - 2 Src S - 0 Dst TOS Count opcode[372'b], alpha byte 08. Start: Fetch Stack parameters Set up SRCEMREG (set up the address of the last entry, because we work backward) Set up DSTMEMREG Call Conversion subroutine Decrement Count Set up SRCMEMREG GOTO[FSILE] Inner Loop: Set up SRCMEMREG Set up DSTMEMREG, and check interrupt FSILE: Call Conversion subroutine Store Result in memory Decrement Count, if 0, exit at FSEX0 Count is not 0, Set up SRCMEMREG. Call Conversion subroutine Decrement Count, back to inner loop. FSEX0: Done We have to work backward, i.e. : start from the tail of the array. After page fault we only continue to convert the rest of the array The size of the Dst is 1/2 of Src. In the conversion subroutine, if the number is >FF, will return FF, if <0, will return 0. Restriction : The calling function must make sure : 1. The count is an even number, non zero. 2. The count is not greater than the number of Src elements. 3. Src and Dst is a pointer to base address of the arrays. 4. Src is a floating point array ('FLOATP). 5. Dst is an integer array ('WORD). } Set[L0.FS.RO.00, 00]; Set[L0.FS.RO.01, 01]; Set[L0.FS.NR.0F, 0F]; Set[L1.FS.NR.0B, 0B]; Set[L0.FS.RO.02, 02]; Set[L0.FS.RO.03, 03]; Set[L0.FS.NR.0C, 0C]; Set[L1.FS.NR.0C, 0C]; Set[L2.FS.FtoS.00, 00]; Set[L2.FS.FtoS.01, 01]; Set[L2.FS.FtoS.02, 02]; Set[L2.FS.FtoS.03, 03]; Set[L3.SRCMEMREG.00, 00]; Set[L3.SRCMEMREG.01, 01]; Set[L3.SRCMEMREG.02, 02]; RegDef[rSTATUS, R, 03]; {=PV} RegDef[rRESM, R, 06]; {=Rx} RegDef[rRESL, R, 05]; {=PC} RegDef[rRESLtemp,R, 04]; {=S} RegDef[uNSrcoffset, U, 51]; RegDef[urhNSrc, U, 53]; RegDef[uNDstoffset, U, 35]; RegDef[urhNDst, U, 45]; RegDef[uNSrcoffsetReal, U, 44]; RegDef[urhNSrcReal, U, 30]; RegDef[uNDstoffsetReal, U, 59]; RegDef[urhNDstReal, U, 7]; FSBK0: Ybus ← TOSH xor smallpl, ZeroBr, c3, at[08, 10, FOP1Disp]; {Check if size = NIL} FSBK1: TT ← 0FF + 1, BRANCH[FSER1, $], c1; {set PPort to read} Q ← uPPsave, L1 ← L1.FS.NR.0B, c2; PPort ← Q and ~TT, CALL[SaveAllRegsB2], c3; {Save all registers} MAR ← [rhS, S - 1], c1, at[L1.FS.NR.0B, 10, SaveRegsB2Ret]; {Point to Dst Bitmap} Ybus ← TOS, ZeroBr, CANCELBR[$, 2], c2; {Check if size = 0} PV ← MD, BRANCH[$, FSER0], c3; {PV = high word V address of Dst} MAR ← [rhS, S + 0], c1; S ← S - 2, c2; PC ← MD, c3; {PC = low word V address of Dst} MAR ← [rhS, S - 1], c1; {Point to Src array} FloatNop, CANCELBR[$, 2], c2; Q ← MD, c3; {Q = high word V address of Src} MAR ← [rhS, S + 0], c1; FloatNop, c2; TT ← MD, c3; {TT = low word V address of Src} Rx ← TOS - 1, c1; {Set up ORGSRCMEMREG, TOS contains COUNTS} Rx ← Rx LShift1, SE ← 0, c2; {Rx = (COUNTS - 1) X 2} FSBK2: TT ← TT + Rx, CarryBr, c3; uNSrcoffset ← TT, BRANCH[PRNC11, PRCR11], c1; PRCR11: Q ← Q + 1, GOTO[FSMG55], c2; PRNC11: Noop, c2; FSMG55: rhTT ← Q LRot0, c3; FSBK3: Map ← [rhTT, TT + 0], L1 ← L1.FS.NR.0C, c1; {Map Src address} urhNSrc ← Q, L0 ← L0.FS.RO.00, c2; {Must fetch 2 words for each floating point} rhRx ← Rx ← MD, XRefBr, c3; MAR ← Q ← [rhRx, TT + 0], BRANCH[FSCH0, $], c1, at[L0.FS.RO.00, 10, NRMapFixCallerB2]; {Calculate (last -1) position} uNSrcoffsetReal ← Q, c2; S ← MD, c3; Rx ← Q, FloatMode.RZ.AI.FAST, c1; Q ← rhRx, c2; urhNSrcReal ← Q, c3; MAR ← Q ← [rhRx, Rx + 1], c1; uFix ← S, BRANCH[$, FXFS1, 1], c2; FSC2: TOSH ← MD, c3; TT ← TOS - 1, L2 ← L2.FS.FtoS.00, c1; TT ← TT RShift1, SE ← 0, c2; {TT = (COUNTS - 1)/2} TT ← TT + PC, CarryBr, c3; uNDstoffset ← TT, BRANCH[DNC1, DC1], c1; DNC1: Noop, GOTO[DSTM1], c2; DC1: PV ← PV + 1, c2; DSTM1: rhTT ← PV LRot0, c3; MDST: Map ← [rhTT, TT + 0], L1 ← L1.FS.NR.0C, c1; {Map address of Last Dst} urhNDst ← PV, L0 ← L0.FS.NR.0F, c2; {mode must be RZ for FLFixA} rhRx ← Rx ← MD, XwdDisp, c3; MAR ← Q ← [rhRx, TT + 0], DISP2[FSCH1], c1, at[L0.FS.NR.0F, 10, NRWMapFixCallerB2]; uNDstoffsetReal ← Q, c2, at[1, 4, FSCH1]; Rx ← rhRx, CALL[FtoS], c3; rRESLtemp ← rRESL, c2, at[L2.FS.FtoS.00, 10, FtoSRet]; urhNDstReal ← Rx, L2 ← L2.FS.FtoS.02, c3; {Save result in rRESLtemp} TOS ← TOS - 1, L3 ← L3.SRCMEMREG.00, c1; Rx ← uNSrcoffsetReal, CALL[SRCMEMREG], c2; {Set up floating point number} rhRx ← urhNDstReal, CALL[FtoS], c3, at[L3.SRCMEMREG.00, 10, SRCMEMREGRet]; FSIL: L2 ← L2.FS.FtoS.02, CALL[DSTMEMREG], c1; {Inner loop} Rx ← uNSrcoffsetReal, CALL[SRCMEMREG], c2, at[L3.SRCMEMREG.01, 10, DSTMEMREGRet]; rhRx ← urhNDstReal, CALL[FtoS], c3, at[L3.SRCMEMREG.01, 10, SRCMEMREGRet]; FSILE: rRESL ← rRESL LRot8, c2, at[L2.FS.FtoS.02, 10, FtoSRet]; Rx ← uNDstoffsetReal, L2 ← L2.FS.FtoS.03, c3; MAR ← [rhRx, Rx + 0], L3 ← L3.SRCMEMREG.02, c1; {Store in Dst} MDR ← rRESLtemp or rRESL, c2; {Compact the result} TOS ← TOS - 1, ZeroBr, c3; {Decrement counter} uTOS ← TOS, BRANCH[$, FSEX0], c1; {uTOS is updated every 2 counts} Rx ← uNSrcoffsetReal, CALL[SRCMEMREG], c2; CALL[FtoS], c3, at[L3.SRCMEMREG.02, 10, SRCMEMREGRet]; TOS ← TOS - 1, L3 ← L3.SRCMEMREG.01, c2, at[L2.FS.FtoS.03, 10, FtoSRet]; rRESLtemp ← rRESL, GOTO[FSIL], c3; { ======================================================================== Conversion ======================================================================== } FtoS: FloatAB ← uFix, FLFixA, c1; FloatAB ← TOSH LRot0, c2; FloatStartFlow, c3; uRx ← Rx, c1; Noop, c2; Noop, c3; Noop, c1; FloatUnloadS, Float.M, c2; {unload MS word} FloatUnloadS, Float.L, c3; {unload LS word} rSTATUS ← PPort, c1; {store MS word of result} rRESM ← FloatResult, c2; {read status} rRESL ← FloatResult, c3; {LS word} Xbus ← rRESM LRot8, XDisp, c1; {Check sign bit} Ybus ← rRESM, ZeroBr, DISP4[FSRSF, 0E], c2; {If 0, check further} {If 1, force low word to 0} rRESL ← 0, CANCELBR[$], L2Disp, c3, at[0F, 10, FSRSF]; FSOK2: Rx ← uRx, RET[FtoSRet], c1; Rx ← uRx, BRANCH[FSLF0, FSMG0], c3, at[0E, 10, FSRSF]; FSLF0: rRESL ← 0FF, c1; {Force low word to 0FF} Noop, c2; L2Disp, GOTO[FSOK2], c3; FSMG0: TT ← rRESL and ~0FF, c1; Ybus ← TT, ZeroBr, c2; BRANCH[FC255, FSOK1], L2Disp, c3; FC255: rRESL ← 0FF, RET[FtoSRet], c1; {Force low word to 0FF} FSOK1: RET[FtoSRet], c1; { ======================================================================== DSTMEMREG ======================================================================== } DSTMEMREG: rhRx ← urhNDstReal, c2; Rx ← uNDstoffsetReal, c3; MAR ← Rx ← [rhRx, Rx - 1], NibCarryBr, c1; {Set up Dst address} TOSH ← Rx, DISP2[FSFX0], c2; DSMG3: Q ← rhRx, c3, at[1, 4, FSFX0]; FTSNI3: urhNDstReal ← Q, c1; {The real address of Dst is decremented by 2 each time} uNDstoffsetReal ← Rx, c2; L3Disp, c3; RET[DSTMEMREGRet], c1; { ======================================================================== SRCMEMREG ======================================================================== This subroutine fetch 32 bits floating point number } SRCMEMREG: rhRx ← urhNSrcReal, c3; MAR ← Rx ← [rhRx, Rx - 1], c1; TOSH ← Rx, BRANCH[$, FSFX1, 1], c2; SRCT1: TOSH ← MD, c3; MAR ← Rx ← [rhRx, Rx - 1], c1; Q ← Rx, BRANCH[$, FSFX2, 1], c2; SRCT2: Q ← MD, c3; uFix ← Q, c1; Q ← rhRx, c2; urhNSrcReal ← Q, c3; {Update the real address} uNSrcoffsetReal ← Rx, L3Disp, c1; {The real address of Src is decremented by 2 each time} RET[SRCMEMREGRet], c2; { ================================================================================================ Error cases ================================================================================================ } FSER0: PV ← uPVx, c1; FSER1: GOTO[ufnX32], c2; { ================================================================================================ Exit points ================================================================================================ } FSEX0: TOSH ← smallpl, c2; Q ← 4'd, c3; Xbus ← ib, GOTO[RestoreAllRegsAndExitB2], c1; { ======================================================================== Remap ======================================================================== } FSCH0: CALL[NRLMapFixB2], c2; FXFS1: TT ← uNSrcoffset, c3; Rx ← 0FF + 1, c1; TT ← TT + Rx, CarryBr, c2; Rx ← urhNSrc, BRANCH[SNC1, SC1], c3; SNC1: Noop, GOTO[SRMG1], c1; SC1: Rx ← Rx + 1, c1; SRMG1: rhTT ← Rx LRot0, c2; L0 ← L0.FS.RO.01, c3; Map ← [rhTT, TT + 0], c1; L1 ← L1.FS.NR.0C, c2; rhRx ← Rx ← MD, XRefBr, c3; MAR ← [rhRx, Q + 0], BRANCH[FSCH3, $], c1, at[L0.FS.RO.01, 10, NRMapFixCallerB2]; GOTO[FSC2], c2; FSCH3: CALL[NRLMapFixB2], c2; TT ← uNDstoffset, GOTO[FXC0N], c3, at[2, 4, FSFX0]; TT ← uNDstoffset, GOTO[FXC0N], c3, at[3, 4, FSFX0]; FXC0N: Q ← 0FF + 1, c1; TT ← TT - Q, CarryBr, c2; Q ← urhNDst, BRANCH[SBR2, SNBR2], c3; SNBR2: Noop, GOTO[SMG03], c1; SBR2: Q ← Q - 1, c1; SMG03: rhTT ← Q LRot0, c2; urhNDst ← Q, L1 ← L1.FS.NR.0C, c3; Map ← [rhTT, TT + 0], c1; uNDstoffset ← TT, L0 ← L0.FS.NR.0C, c2; rhRx ← Rx ← MD, XwdDisp, c3; MAR ← Q ← [rhRx, TOSH + 0], DISP2[FSCH6], c1, at[L0.FS.NR.0C, 10, NRWMapFixCallerB2]; Rx ← Q, GOTO[DSMG3], c2, at[1, 4, FSCH6]; FSFX1: TT ← uNSrcoffset, c3; Q ← 0FF + 1, c1; TT ← TT - Q, CarryBr, c2; Q ← urhNSrc, BRANCH[SBR1, SNBR1], c3; SNBR1: Noop, GOTO[SMG02], c1; SBR1: Q ← Q - 1, c1; SMG02: rhTT ← Q LRot0, c2; urhNSrc ← Q, L0 ← L0.FS.RO.02, c3; Map ← [rhTT, TT + 0], c1; uNSrcoffset ← TT, L1 ← L1.FS.NR.0C, c2; rhRx ← Rx ← MD, XRefBr, c3; MAR ← Q ← [rhRx, TOSH + 0], BRANCH[FSCH66, $], c1, at[L0.FS.RO.02, 10, NRMapFixCallerB2]; Rx ← Q, GOTO[SRCT1], c2; FSCH66: CALL[NRLMapFixB2], c2; FSFX2: TT ← uNSrcoffset, c3; Rx ← 0FF + 1, c1; TT ← TT - Rx, CarryBr, c2; Rx ← urhNSrc, BRANCH[SBR3, SNBR3], c3; SNBR3: Noop, GOTO[SMG02], c1; SBR3: Rx ← Rx - 1, c1; SMG04: rhTT ← Rx LRot0, c2; urhNSrc ← Rx, L0 ← L0.FS.RO.03, c3; Map ← [rhTT, TT + 0], c1; uNSrcoffset ← TT, L1 ← L1.FS.NR.0C, c2; rhRx ← Rx ← MD, XRefBr, c3; MAR ← Q ← [rhRx, Q + 0], BRANCH[FSCH7, $], c1, at[L0.FS.RO.03, 10, NRMapFixCallerB2]; Rx ← Q, GOTO[SRCT2], c2; FSCH7: CALL[NRLMapFixB2], c2; GOTO[NRWLMapFixB2], c2, at[0, 4, FSCH6]; GOTO[NRWLMapFixB2], c2, at[2, 4, FSCH6]; GOTO[NRWLMapFixB2], c2, at[3, 4, FSCH6]; GOTO[NRWLMapFixB2], c2, at[0, 4, FSCH1]; GOTO[NRWLMapFixB2], c2, at[2, 4, FSCH1]; GOTO[NRWLMapFixB2], c2, at[3, 4, FSCH1]; Q ← 0, GOTO[RestoreAllRegsAndPFB2], c1, at[L1.FS.NR.0C, 10, NTrapFixesB2]; { ============================================================================================== Handle Interrupts ============================================================================================== } Q ← rhRx, MesaIntBr, c3, at[0, 4, FSFX0]; {Check interrupts} Ybus ← uWDC, NZeroBr, BRANCH[FTSNI1, $], c1; Ybus ← uWP, ZeroBr, BRANCH[FTSI1, FTSNI2], c2; FTSNI1: CANCELBR[$], c2; FTSNI2: CANCELBR[FTSNI3], c3; FTSI1: uWP ← 0, BRANCH[FTSIN, $], c3; urhNDstReal ← Q, c1; {The real address of Dst is decremented by 2 each time} uNDstoffsetReal ← Rx, c2; L3Disp, c3; RET[DSTMEMREGRet], c1; FTSIN: TOS ← uTOS, c1; TOSH ← uTOSH, c2; S ← uS, c3; FTGIN: Bank ← EmuBank, c1; PV ← uPVx, c2; PC ← uPC, CROSS[EmuInt], c3; {END}