Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:49

0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 //  srem_mod.sa 3.1 12/10/90
0005 //
0006 //      The entry point sMOD computes the floating point MOD of the
0007 //      input values X and Y. The entry point sREM computes the floating
0008 //      point (IEEE) REM of the input values X and Y.
0009 //
0010 //      INPUT
0011 //      -----
0012 //      Double-extended value Y is pointed to by address in register
0013 //      A0. Double-extended value X is located in -12(A0). The values
0014 //      of X and Y are both nonzero and finite; although either or both
0015 //      of them can be denormalized. The special cases of zeros, NaNs,
0016 //      and infinities are handled elsewhere.
0017 //
0018 //      OUTPUT
0019 //      ------
0020 //      FREM(X,Y) or FMOD(X,Y), depending on entry point.
0021 //
0022 //       ALGORITHM
0023 //       ---------
0024 //
0025 //       Step 1.  Save and strip signs of X and Y: signX := sign(X),
0026 //                signY := sign(Y), X := |X|, Y := |Y|,
0027 //                signQ := signX EOR signY. Record whether MOD or REM
0028 //                is requested.
0029 //
0030 //       Step 2.  Set L := expo(X)-expo(Y), k := 0, Q := 0.
0031 //                If (L < 0) then
0032 //                   R := X, go to Step 4.
0033 //                else
0034 //                   R := 2^(-L)X, j := L.
0035 //                endif
0036 //
0037 //       Step 3.  Perform MOD(X,Y)
0038 //            3.1 If R = Y, go to Step 9.
0039 //            3.2 If R > Y, then { R := R - Y, Q := Q + 1}
0040 //            3.3 If j = 0, go to Step 4.
0041 //            3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to
0042 //                Step 3.1.
0043 //
0044 //       Step 4.  At this point, R = X - QY = MOD(X,Y). Set
0045 //                Last_Subtract := false (used in Step 7 below). If
0046 //                MOD is requested, go to Step 6.
0047 //
0048 //       Step 5.  R = MOD(X,Y), but REM(X,Y) is requested.
0049 //            5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to
0050 //                Step 6.
0051 //            5.2 If R > Y/2, then { set Last_Subtract := true,
0052 //                Q := Q + 1, Y := signY*Y }. Go to Step 6.
0053 //            5.3 This is the tricky case of R = Y/2. If Q is odd,
0054 //                then { Q := Q + 1, signX := -signX }.
0055 //
0056 //       Step 6.  R := signX*R.
0057 //
0058 //       Step 7.  If Last_Subtract = true, R := R - Y.
0059 //
0060 //       Step 8.  Return signQ, last 7 bits of Q, and R as required.
0061 //
0062 //       Step 9.  At this point, R = 2^(-j)*X - Q Y = Y. Thus,
0063 //                X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1),
0064 //                R := 0. Return signQ, last 7 bits of Q, and R.
0065 //
0066 //
0067 
0068 //      Copyright (C) Motorola, Inc. 1990
0069 //          All Rights Reserved
0070 //
0071 //  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0072 //  The copyright notice above does not evidence any
0073 //  actual or intended publication of such source code.
0074 
0075 SREM_MOD:    //idnt    2,1 | Motorola 040 Floating Point Software Package
0076 
0077     |section    8
0078 
0079 #include "fpsp.defs"
0080 
0081     .set    Mod_Flag,L_SCR3
0082     .set    SignY,FP_SCR3+4
0083     .set    SignX,FP_SCR3+8
0084     .set    SignQ,FP_SCR3+12
0085     .set    Sc_Flag,FP_SCR4
0086 
0087     .set    Y,FP_SCR1
0088     .set    Y_Hi,Y+4
0089     .set    Y_Lo,Y+8
0090 
0091     .set    R,FP_SCR2
0092     .set    R_Hi,R+4
0093     .set    R_Lo,R+8
0094 
0095 
0096 Scale:     .long    0x00010000,0x80000000,0x00000000,0x00000000
0097 
0098     |xref   t_avoid_unsupp
0099 
0100         .global        smod
0101 smod:
0102 
0103    movel               #0,Mod_Flag(%a6)
0104    bras                Mod_Rem
0105 
0106         .global        srem
0107 srem:
0108 
0109    movel               #1,Mod_Flag(%a6)
0110 
0111 Mod_Rem:
0112 //..Save sign of X and Y
0113    moveml              %d2-%d7,-(%a7)     // ...save data registers
0114    movew               (%a0),%d3
0115    movew               %d3,SignY(%a6)
0116    andil               #0x00007FFF,%d3   // ...Y := |Y|
0117 
0118 //
0119    movel               4(%a0),%d4
0120    movel               8(%a0),%d5        // ...(D3,D4,D5) is |Y|
0121 
0122    tstl                %d3
0123    bnes                Y_Normal
0124 
0125    movel               #0x00003FFE,%d3  // ...$3FFD + 1
0126    tstl                %d4
0127    bnes                HiY_not0
0128 
0129 HiY_0:
0130    movel               %d5,%d4
0131    clrl                %d5
0132    subil               #32,%d3
0133    clrl                %d6
0134    bfffo                %d4{#0:#32},%d6
0135    lsll                %d6,%d4
0136    subl                %d6,%d3           // ...(D3,D4,D5) is normalized
0137 //                                       ...with bias $7FFD
0138    bras                Chk_X
0139 
0140 HiY_not0:
0141    clrl                %d6
0142    bfffo                %d4{#0:#32},%d6
0143    subl                %d6,%d3
0144    lsll                %d6,%d4
0145    movel               %d5,%d7           // ...a copy of D5
0146    lsll                %d6,%d5
0147    negl                %d6
0148    addil               #32,%d6
0149    lsrl                %d6,%d7
0150    orl                 %d7,%d4           // ...(D3,D4,D5) normalized
0151 //                                       ...with bias $7FFD
0152    bras                Chk_X
0153 
0154 Y_Normal:
0155    addil               #0x00003FFE,%d3   // ...(D3,D4,D5) normalized
0156 //                                       ...with bias $7FFD
0157 
0158 Chk_X:
0159    movew               -12(%a0),%d0
0160    movew               %d0,SignX(%a6)
0161    movew               SignY(%a6),%d1
0162    eorl                %d0,%d1
0163    andil               #0x00008000,%d1
0164    movew               %d1,SignQ(%a6)   // ...sign(Q) obtained
0165    andil               #0x00007FFF,%d0
0166    movel               -8(%a0),%d1
0167    movel               -4(%a0),%d2       // ...(D0,D1,D2) is |X|
0168    tstl                %d0
0169    bnes                X_Normal
0170    movel               #0x00003FFE,%d0
0171    tstl                %d1
0172    bnes                HiX_not0
0173 
0174 HiX_0:
0175    movel               %d2,%d1
0176    clrl                %d2
0177    subil               #32,%d0
0178    clrl                %d6
0179    bfffo                %d1{#0:#32},%d6
0180    lsll                %d6,%d1
0181    subl                %d6,%d0           // ...(D0,D1,D2) is normalized
0182 //                                       ...with bias $7FFD
0183    bras                Init
0184 
0185 HiX_not0:
0186    clrl                %d6
0187    bfffo                %d1{#0:#32},%d6
0188    subl                %d6,%d0
0189    lsll                %d6,%d1
0190    movel               %d2,%d7           // ...a copy of D2
0191    lsll                %d6,%d2
0192    negl                %d6
0193    addil               #32,%d6
0194    lsrl                %d6,%d7
0195    orl                 %d7,%d1           // ...(D0,D1,D2) normalized
0196 //                                       ...with bias $7FFD
0197    bras                Init
0198 
0199 X_Normal:
0200    addil               #0x00003FFE,%d0   // ...(D0,D1,D2) normalized
0201 //                                       ...with bias $7FFD
0202 
0203 Init:
0204 //
0205    movel               %d3,L_SCR1(%a6)   // ...save biased expo(Y)
0206    movel        %d0,L_SCR2(%a6) //save d0
0207    subl                %d3,%d0           // ...L := expo(X)-expo(Y)
0208 //   Move.L               D0,L            ...D0 is j
0209    clrl                %d6              // ...D6 := carry <- 0
0210    clrl                %d3              // ...D3 is Q
0211    moveal              #0,%a1           // ...A1 is k; j+k=L, Q=0
0212 
0213 //..(Carry,D1,D2) is R
0214    tstl                %d0
0215    bges                Mod_Loop
0216 
0217 //..expo(X) < expo(Y). Thus X = mod(X,Y)
0218 //
0219    movel        L_SCR2(%a6),%d0 //restore d0
0220    bra                Get_Mod
0221 
0222 //..At this point  R = 2^(-L)X; Q = 0; k = 0; and  k+j = L
0223 
0224 
0225 Mod_Loop:
0226    tstl                %d6              // ...test carry bit
0227    bgts                R_GT_Y
0228 
0229 //..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
0230    cmpl                %d4,%d1           // ...compare hi(R) and hi(Y)
0231    bnes                R_NE_Y
0232    cmpl                %d5,%d2           // ...compare lo(R) and lo(Y)
0233    bnes                R_NE_Y
0234 
0235 //..At this point, R = Y
0236    bra                Rem_is_0
0237 
0238 R_NE_Y:
0239 //..use the borrow of the previous compare
0240    bcss                R_LT_Y          // ...borrow is set iff R < Y
0241 
0242 R_GT_Y:
0243 //..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
0244 //..and Y < (D1,D2) < 2Y. Either way, perform R - Y
0245    subl                %d5,%d2           // ...lo(R) - lo(Y)
0246    subxl               %d4,%d1           // ...hi(R) - hi(Y)
0247    clrl                %d6              // ...clear carry
0248    addql               #1,%d3           // ...Q := Q + 1
0249 
0250 R_LT_Y:
0251 //..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
0252    tstl                %d0              // ...see if j = 0.
0253    beqs                PostLoop
0254 
0255    addl                %d3,%d3           // ...Q := 2Q
0256    addl                %d2,%d2           // ...lo(R) = 2lo(R)
0257    roxll               #1,%d1           // ...hi(R) = 2hi(R) + carry
0258    scs                  %d6              // ...set Carry if 2(R) overflows
0259    addql               #1,%a1           // ...k := k+1
0260    subql               #1,%d0           // ...j := j - 1
0261 //..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
0262 
0263    bras                Mod_Loop
0264 
0265 PostLoop:
0266 //..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
0267 
0268 //..normalize R.
0269    movel               L_SCR1(%a6),%d0           // ...new biased expo of R
0270    tstl                %d1
0271    bnes                HiR_not0
0272 
0273 HiR_0:
0274    movel               %d2,%d1
0275    clrl                %d2
0276    subil               #32,%d0
0277    clrl                %d6
0278    bfffo                %d1{#0:#32},%d6
0279    lsll                %d6,%d1
0280    subl                %d6,%d0           // ...(D0,D1,D2) is normalized
0281 //                                       ...with bias $7FFD
0282    bras                Get_Mod
0283 
0284 HiR_not0:
0285    clrl                %d6
0286    bfffo                %d1{#0:#32},%d6
0287    bmis                Get_Mod         // ...already normalized
0288    subl                %d6,%d0
0289    lsll                %d6,%d1
0290    movel               %d2,%d7           // ...a copy of D2
0291    lsll                %d6,%d2
0292    negl                %d6
0293    addil               #32,%d6
0294    lsrl                %d6,%d7
0295    orl                 %d7,%d1           // ...(D0,D1,D2) normalized
0296 
0297 //
0298 Get_Mod:
0299    cmpil        #0x000041FE,%d0
0300    bges     No_Scale
0301 Do_Scale:
0302    movew        %d0,R(%a6)
0303    clrw     R+2(%a6)
0304    movel        %d1,R_Hi(%a6)
0305    movel        %d2,R_Lo(%a6)
0306    movel        L_SCR1(%a6),%d6
0307    movew        %d6,Y(%a6)
0308    clrw     Y+2(%a6)
0309    movel        %d4,Y_Hi(%a6)
0310    movel        %d5,Y_Lo(%a6)
0311    fmovex       R(%a6),%fp0     // ...no exception
0312    movel        #1,Sc_Flag(%a6)
0313    bras     ModOrRem
0314 No_Scale:
0315    movel        %d1,R_Hi(%a6)
0316    movel        %d2,R_Lo(%a6)
0317    subil        #0x3FFE,%d0
0318    movew        %d0,R(%a6)
0319    clrw     R+2(%a6)
0320    movel        L_SCR1(%a6),%d6
0321    subil        #0x3FFE,%d6
0322    movel        %d6,L_SCR1(%a6)
0323    fmovex       R(%a6),%fp0
0324    movew        %d6,Y(%a6)
0325    movel        %d4,Y_Hi(%a6)
0326    movel        %d5,Y_Lo(%a6)
0327    movel        #0,Sc_Flag(%a6)
0328 
0329 //
0330 
0331 
0332 ModOrRem:
0333    movel               Mod_Flag(%a6),%d6
0334    beqs                Fix_Sign
0335 
0336    movel               L_SCR1(%a6),%d6           // ...new biased expo(Y)
0337    subql               #1,%d6           // ...biased expo(Y/2)
0338    cmpl                %d6,%d0
0339    blts                Fix_Sign
0340    bgts                Last_Sub
0341 
0342    cmpl                %d4,%d1
0343    bnes                Not_EQ
0344    cmpl                %d5,%d2
0345    bnes                Not_EQ
0346    bra                Tie_Case
0347 
0348 Not_EQ:
0349    bcss                Fix_Sign
0350 
0351 Last_Sub:
0352 //
0353    fsubx        Y(%a6),%fp0     // ...no exceptions
0354    addql               #1,%d3           // ...Q := Q + 1
0355 
0356 //
0357 
0358 Fix_Sign:
0359 //..Get sign of X
0360    movew               SignX(%a6),%d6
0361    bges     Get_Q
0362    fnegx        %fp0
0363 
0364 //..Get Q
0365 //
0366 Get_Q:
0367    clrl     %d6
0368    movew               SignQ(%a6),%d6        // ...D6 is sign(Q)
0369    movel               #8,%d7
0370    lsrl                %d7,%d6
0371    andil               #0x0000007F,%d3   // ...7 bits of Q
0372    orl                 %d6,%d3           // ...sign and bits of Q
0373    swap                 %d3
0374    fmovel              %fpsr,%d6
0375    andil               #0xFF00FFFF,%d6
0376    orl                 %d3,%d6
0377    fmovel              %d6,%fpsr         // ...put Q in fpsr
0378 
0379 //
0380 Restore:
0381    moveml              (%a7)+,%d2-%d7
0382    fmovel              USER_FPCR(%a6),%fpcr
0383    movel               Sc_Flag(%a6),%d0
0384    beqs                Finish
0385    fmulx        Scale(%pc),%fp0 // ...may cause underflow
0386    bra          t_avoid_unsupp  //check for denorm as a
0387 //                  ;result of the scaling
0388 
0389 Finish:
0390     fmovex      %fp0,%fp0       //capture exceptions & round
0391     rts
0392 
0393 Rem_is_0:
0394 //..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
0395    addql               #1,%d3
0396    cmpil               #8,%d0           // ...D0 is j
0397    bges                Q_Big
0398 
0399    lsll                %d0,%d3
0400    bras                Set_R_0
0401 
0402 Q_Big:
0403    clrl                %d3
0404 
0405 Set_R_0:
0406    fmoves       #0x00000000,%fp0
0407    movel        #0,Sc_Flag(%a6)
0408    bra                Fix_Sign
0409 
0410 Tie_Case:
0411 //..Check parity of Q
0412    movel               %d3,%d6
0413    andil               #0x00000001,%d6
0414    tstl                %d6
0415    beq                Fix_Sign  // ...Q is even
0416 
0417 //..Q is odd, Q := Q + 1, signX := -signX
0418    addql               #1,%d3
0419    movew               SignX(%a6),%d6
0420    eoril               #0x00008000,%d6
0421    movew               %d6,SignX(%a6)
0422    bra                Fix_Sign
0423 
0424    //end