| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | | | 
 | 2 | |	srem_mod.sa 3.1 12/10/90 | 
 | 3 | | | 
 | 4 | |      The entry point sMOD computes the floating point MOD of the | 
 | 5 | |      input values X and Y. The entry point sREM computes the floating | 
 | 6 | |      point (IEEE) REM of the input values X and Y. | 
 | 7 | | | 
 | 8 | |      INPUT | 
 | 9 | |      ----- | 
 | 10 | |      Double-extended value Y is pointed to by address in register | 
 | 11 | |      A0. Double-extended value X is located in -12(A0). The values | 
 | 12 | |      of X and Y are both nonzero and finite; although either or both | 
 | 13 | |      of them can be denormalized. The special cases of zeros, NaNs, | 
 | 14 | |      and infinities are handled elsewhere. | 
 | 15 | | | 
 | 16 | |      OUTPUT | 
 | 17 | |      ------ | 
 | 18 | |      FREM(X,Y) or FMOD(X,Y), depending on entry point. | 
 | 19 | | | 
 | 20 | |       ALGORITHM | 
 | 21 | |       --------- | 
 | 22 | | | 
 | 23 | |       Step 1.  Save and strip signs of X and Y: signX := sign(X), | 
 | 24 | |                signY := sign(Y), X := |X|, Y := |Y|, | 
 | 25 | |                signQ := signX EOR signY. Record whether MOD or REM | 
 | 26 | |                is requested. | 
 | 27 | | | 
 | 28 | |       Step 2.  Set L := expo(X)-expo(Y), k := 0, Q := 0. | 
 | 29 | |                If (L < 0) then | 
 | 30 | |                   R := X, go to Step 4. | 
 | 31 | |                else | 
 | 32 | |                   R := 2^(-L)X, j := L. | 
 | 33 | |                endif | 
 | 34 | | | 
 | 35 | |       Step 3.  Perform MOD(X,Y) | 
 | 36 | |            3.1 If R = Y, go to Step 9. | 
 | 37 | |            3.2 If R > Y, then { R := R - Y, Q := Q + 1} | 
 | 38 | |            3.3 If j = 0, go to Step 4. | 
 | 39 | |            3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to | 
 | 40 | |                Step 3.1. | 
 | 41 | | | 
 | 42 | |       Step 4.  At this point, R = X - QY = MOD(X,Y). Set | 
 | 43 | |                Last_Subtract := false (used in Step 7 below). If | 
 | 44 | |                MOD is requested, go to Step 6. | 
 | 45 | | | 
 | 46 | |       Step 5.  R = MOD(X,Y), but REM(X,Y) is requested. | 
 | 47 | |            5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to | 
 | 48 | |                Step 6. | 
 | 49 | |            5.2 If R > Y/2, then { set Last_Subtract := true, | 
 | 50 | |                Q := Q + 1, Y := signY*Y }. Go to Step 6. | 
 | 51 | |            5.3 This is the tricky case of R = Y/2. If Q is odd, | 
 | 52 | |                then { Q := Q + 1, signX := -signX }. | 
 | 53 | | | 
 | 54 | |       Step 6.  R := signX*R. | 
 | 55 | | | 
 | 56 | |       Step 7.  If Last_Subtract = true, R := R - Y. | 
 | 57 | | | 
 | 58 | |       Step 8.  Return signQ, last 7 bits of Q, and R as required. | 
 | 59 | | | 
 | 60 | |       Step 9.  At this point, R = 2^(-j)*X - Q Y = Y. Thus, | 
 | 61 | |                X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1), | 
 | 62 | |                R := 0. Return signQ, last 7 bits of Q, and R. | 
 | 63 | | | 
 | 64 | | | 
 | 65 |  | 
 | 66 | |		Copyright (C) Motorola, Inc. 1990 | 
 | 67 | |			All Rights Reserved | 
 | 68 | | | 
| Matt Waddel | e00d82d | 2006-02-11 17:55:48 -0800 | [diff] [blame] | 69 | |       For details on the license for this file, please see the | 
 | 70 | |       file, README, in this same directory. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 71 |  | 
 | 72 | SREM_MOD:    |idnt    2,1 | Motorola 040 Floating Point Software Package | 
 | 73 |  | 
 | 74 | 	|section    8 | 
 | 75 |  | 
 | 76 | #include "fpsp.h" | 
 | 77 |  | 
 | 78 | 	.set	Mod_Flag,L_SCR3 | 
 | 79 | 	.set	SignY,FP_SCR3+4 | 
 | 80 | 	.set	SignX,FP_SCR3+8 | 
 | 81 | 	.set	SignQ,FP_SCR3+12 | 
 | 82 | 	.set	Sc_Flag,FP_SCR4 | 
 | 83 |  | 
 | 84 | 	.set	Y,FP_SCR1 | 
 | 85 | 	.set	Y_Hi,Y+4 | 
 | 86 | 	.set	Y_Lo,Y+8 | 
 | 87 |  | 
 | 88 | 	.set	R,FP_SCR2 | 
 | 89 | 	.set	R_Hi,R+4 | 
 | 90 | 	.set	R_Lo,R+8 | 
 | 91 |  | 
 | 92 |  | 
 | 93 | Scale:     .long	0x00010000,0x80000000,0x00000000,0x00000000 | 
 | 94 |  | 
 | 95 | 	|xref	t_avoid_unsupp | 
 | 96 |  | 
 | 97 |         .global        smod | 
 | 98 | smod: | 
 | 99 |  | 
 | 100 |    movel               #0,Mod_Flag(%a6) | 
 | 101 |    bras                Mod_Rem | 
 | 102 |  | 
 | 103 |         .global        srem | 
 | 104 | srem: | 
 | 105 |  | 
 | 106 |    movel               #1,Mod_Flag(%a6) | 
 | 107 |  | 
 | 108 | Mod_Rem: | 
 | 109 | |..Save sign of X and Y | 
 | 110 |    moveml              %d2-%d7,-(%a7)     | ...save data registers | 
 | 111 |    movew               (%a0),%d3 | 
 | 112 |    movew               %d3,SignY(%a6) | 
 | 113 |    andil               #0x00007FFF,%d3   | ...Y := |Y| | 
 | 114 |  | 
 | 115 | | | 
 | 116 |    movel               4(%a0),%d4 | 
 | 117 |    movel               8(%a0),%d5        | ...(D3,D4,D5) is |Y| | 
 | 118 |  | 
 | 119 |    tstl                %d3 | 
 | 120 |    bnes                Y_Normal | 
 | 121 |  | 
 | 122 |    movel               #0x00003FFE,%d3	| ...$3FFD + 1 | 
 | 123 |    tstl                %d4 | 
 | 124 |    bnes                HiY_not0 | 
 | 125 |  | 
 | 126 | HiY_0: | 
 | 127 |    movel               %d5,%d4 | 
 | 128 |    clrl                %d5 | 
 | 129 |    subil               #32,%d3 | 
 | 130 |    clrl                %d6 | 
 | 131 |    bfffo                %d4{#0:#32},%d6 | 
 | 132 |    lsll                %d6,%d4 | 
 | 133 |    subl                %d6,%d3           | ...(D3,D4,D5) is normalized | 
 | 134 | |                                       ...with bias $7FFD | 
 | 135 |    bras                Chk_X | 
 | 136 |  | 
 | 137 | HiY_not0: | 
 | 138 |    clrl                %d6 | 
 | 139 |    bfffo                %d4{#0:#32},%d6 | 
 | 140 |    subl                %d6,%d3 | 
 | 141 |    lsll                %d6,%d4 | 
 | 142 |    movel               %d5,%d7           | ...a copy of D5 | 
 | 143 |    lsll                %d6,%d5 | 
 | 144 |    negl                %d6 | 
 | 145 |    addil               #32,%d6 | 
 | 146 |    lsrl                %d6,%d7 | 
 | 147 |    orl                 %d7,%d4           | ...(D3,D4,D5) normalized | 
 | 148 | |                                       ...with bias $7FFD | 
 | 149 |    bras                Chk_X | 
 | 150 |  | 
 | 151 | Y_Normal: | 
 | 152 |    addil               #0x00003FFE,%d3   | ...(D3,D4,D5) normalized | 
 | 153 | |                                       ...with bias $7FFD | 
 | 154 |  | 
 | 155 | Chk_X: | 
 | 156 |    movew               -12(%a0),%d0 | 
 | 157 |    movew               %d0,SignX(%a6) | 
 | 158 |    movew               SignY(%a6),%d1 | 
 | 159 |    eorl                %d0,%d1 | 
 | 160 |    andil               #0x00008000,%d1 | 
 | 161 |    movew               %d1,SignQ(%a6)	| ...sign(Q) obtained | 
 | 162 |    andil               #0x00007FFF,%d0 | 
 | 163 |    movel               -8(%a0),%d1 | 
 | 164 |    movel               -4(%a0),%d2       | ...(D0,D1,D2) is |X| | 
 | 165 |    tstl                %d0 | 
 | 166 |    bnes                X_Normal | 
 | 167 |    movel               #0x00003FFE,%d0 | 
 | 168 |    tstl                %d1 | 
 | 169 |    bnes                HiX_not0 | 
 | 170 |  | 
 | 171 | HiX_0: | 
 | 172 |    movel               %d2,%d1 | 
 | 173 |    clrl                %d2 | 
 | 174 |    subil               #32,%d0 | 
 | 175 |    clrl                %d6 | 
 | 176 |    bfffo                %d1{#0:#32},%d6 | 
 | 177 |    lsll                %d6,%d1 | 
 | 178 |    subl                %d6,%d0           | ...(D0,D1,D2) is normalized | 
 | 179 | |                                       ...with bias $7FFD | 
 | 180 |    bras                Init | 
 | 181 |  | 
 | 182 | HiX_not0: | 
 | 183 |    clrl                %d6 | 
 | 184 |    bfffo                %d1{#0:#32},%d6 | 
 | 185 |    subl                %d6,%d0 | 
 | 186 |    lsll                %d6,%d1 | 
 | 187 |    movel               %d2,%d7           | ...a copy of D2 | 
 | 188 |    lsll                %d6,%d2 | 
 | 189 |    negl                %d6 | 
 | 190 |    addil               #32,%d6 | 
 | 191 |    lsrl                %d6,%d7 | 
 | 192 |    orl                 %d7,%d1           | ...(D0,D1,D2) normalized | 
 | 193 | |                                       ...with bias $7FFD | 
 | 194 |    bras                Init | 
 | 195 |  | 
 | 196 | X_Normal: | 
 | 197 |    addil               #0x00003FFE,%d0   | ...(D0,D1,D2) normalized | 
 | 198 | |                                       ...with bias $7FFD | 
 | 199 |  | 
 | 200 | Init: | 
 | 201 | | | 
 | 202 |    movel               %d3,L_SCR1(%a6)   | ...save biased expo(Y) | 
 | 203 |    movel		%d0,L_SCR2(%a6)	|save d0 | 
 | 204 |    subl                %d3,%d0           | ...L := expo(X)-expo(Y) | 
 | 205 | |   Move.L               D0,L            ...D0 is j | 
 | 206 |    clrl                %d6              | ...D6 := carry <- 0 | 
 | 207 |    clrl                %d3              | ...D3 is Q | 
 | 208 |    moveal              #0,%a1           | ...A1 is k; j+k=L, Q=0 | 
 | 209 |  | 
 | 210 | |..(Carry,D1,D2) is R | 
 | 211 |    tstl                %d0 | 
 | 212 |    bges                Mod_Loop | 
 | 213 |  | 
 | 214 | |..expo(X) < expo(Y). Thus X = mod(X,Y) | 
 | 215 | | | 
 | 216 |    movel		L_SCR2(%a6),%d0	|restore d0 | 
 | 217 |    bra                Get_Mod | 
 | 218 |  | 
 | 219 | |..At this point  R = 2^(-L)X; Q = 0; k = 0; and  k+j = L | 
 | 220 |  | 
 | 221 |  | 
 | 222 | Mod_Loop: | 
 | 223 |    tstl                %d6              | ...test carry bit | 
 | 224 |    bgts                R_GT_Y | 
 | 225 |  | 
 | 226 | |..At this point carry = 0, R = (D1,D2), Y = (D4,D5) | 
 | 227 |    cmpl                %d4,%d1           | ...compare hi(R) and hi(Y) | 
 | 228 |    bnes                R_NE_Y | 
 | 229 |    cmpl                %d5,%d2           | ...compare lo(R) and lo(Y) | 
 | 230 |    bnes                R_NE_Y | 
 | 231 |  | 
 | 232 | |..At this point, R = Y | 
 | 233 |    bra                Rem_is_0 | 
 | 234 |  | 
 | 235 | R_NE_Y: | 
 | 236 | |..use the borrow of the previous compare | 
 | 237 |    bcss                R_LT_Y          | ...borrow is set iff R < Y | 
 | 238 |  | 
 | 239 | R_GT_Y: | 
 | 240 | |..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0 | 
 | 241 | |..and Y < (D1,D2) < 2Y. Either way, perform R - Y | 
 | 242 |    subl                %d5,%d2           | ...lo(R) - lo(Y) | 
 | 243 |    subxl               %d4,%d1           | ...hi(R) - hi(Y) | 
 | 244 |    clrl                %d6              | ...clear carry | 
 | 245 |    addql               #1,%d3           | ...Q := Q + 1 | 
 | 246 |  | 
 | 247 | R_LT_Y: | 
 | 248 | |..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0. | 
 | 249 |    tstl                %d0              | ...see if j = 0. | 
 | 250 |    beqs                PostLoop | 
 | 251 |  | 
 | 252 |    addl                %d3,%d3           | ...Q := 2Q | 
 | 253 |    addl                %d2,%d2           | ...lo(R) = 2lo(R) | 
 | 254 |    roxll               #1,%d1           | ...hi(R) = 2hi(R) + carry | 
 | 255 |    scs                  %d6              | ...set Carry if 2(R) overflows | 
 | 256 |    addql               #1,%a1           | ...k := k+1 | 
 | 257 |    subql               #1,%d0           | ...j := j - 1 | 
 | 258 | |..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y. | 
 | 259 |  | 
 | 260 |    bras                Mod_Loop | 
 | 261 |  | 
 | 262 | PostLoop: | 
 | 263 | |..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y. | 
 | 264 |  | 
 | 265 | |..normalize R. | 
 | 266 |    movel               L_SCR1(%a6),%d0           | ...new biased expo of R | 
 | 267 |    tstl                %d1 | 
 | 268 |    bnes                HiR_not0 | 
 | 269 |  | 
 | 270 | HiR_0: | 
 | 271 |    movel               %d2,%d1 | 
 | 272 |    clrl                %d2 | 
 | 273 |    subil               #32,%d0 | 
 | 274 |    clrl                %d6 | 
 | 275 |    bfffo                %d1{#0:#32},%d6 | 
 | 276 |    lsll                %d6,%d1 | 
 | 277 |    subl                %d6,%d0           | ...(D0,D1,D2) is normalized | 
 | 278 | |                                       ...with bias $7FFD | 
 | 279 |    bras                Get_Mod | 
 | 280 |  | 
 | 281 | HiR_not0: | 
 | 282 |    clrl                %d6 | 
 | 283 |    bfffo                %d1{#0:#32},%d6 | 
 | 284 |    bmis                Get_Mod         | ...already normalized | 
 | 285 |    subl                %d6,%d0 | 
 | 286 |    lsll                %d6,%d1 | 
 | 287 |    movel               %d2,%d7           | ...a copy of D2 | 
 | 288 |    lsll                %d6,%d2 | 
 | 289 |    negl                %d6 | 
 | 290 |    addil               #32,%d6 | 
 | 291 |    lsrl                %d6,%d7 | 
 | 292 |    orl                 %d7,%d1           | ...(D0,D1,D2) normalized | 
 | 293 |  | 
 | 294 | | | 
 | 295 | Get_Mod: | 
 | 296 |    cmpil		#0x000041FE,%d0 | 
 | 297 |    bges		No_Scale | 
 | 298 | Do_Scale: | 
 | 299 |    movew		%d0,R(%a6) | 
 | 300 |    clrw		R+2(%a6) | 
 | 301 |    movel		%d1,R_Hi(%a6) | 
 | 302 |    movel		%d2,R_Lo(%a6) | 
 | 303 |    movel		L_SCR1(%a6),%d6 | 
 | 304 |    movew		%d6,Y(%a6) | 
 | 305 |    clrw		Y+2(%a6) | 
 | 306 |    movel		%d4,Y_Hi(%a6) | 
 | 307 |    movel		%d5,Y_Lo(%a6) | 
 | 308 |    fmovex		R(%a6),%fp0		| ...no exception | 
 | 309 |    movel		#1,Sc_Flag(%a6) | 
 | 310 |    bras		ModOrRem | 
 | 311 | No_Scale: | 
 | 312 |    movel		%d1,R_Hi(%a6) | 
 | 313 |    movel		%d2,R_Lo(%a6) | 
 | 314 |    subil		#0x3FFE,%d0 | 
 | 315 |    movew		%d0,R(%a6) | 
 | 316 |    clrw		R+2(%a6) | 
 | 317 |    movel		L_SCR1(%a6),%d6 | 
 | 318 |    subil		#0x3FFE,%d6 | 
 | 319 |    movel		%d6,L_SCR1(%a6) | 
 | 320 |    fmovex		R(%a6),%fp0 | 
 | 321 |    movew		%d6,Y(%a6) | 
 | 322 |    movel		%d4,Y_Hi(%a6) | 
 | 323 |    movel		%d5,Y_Lo(%a6) | 
 | 324 |    movel		#0,Sc_Flag(%a6) | 
 | 325 |  | 
 | 326 | | | 
 | 327 |  | 
 | 328 |  | 
 | 329 | ModOrRem: | 
 | 330 |    movel               Mod_Flag(%a6),%d6 | 
 | 331 |    beqs                Fix_Sign | 
 | 332 |  | 
 | 333 |    movel               L_SCR1(%a6),%d6           | ...new biased expo(Y) | 
 | 334 |    subql               #1,%d6           | ...biased expo(Y/2) | 
 | 335 |    cmpl                %d6,%d0 | 
 | 336 |    blts                Fix_Sign | 
 | 337 |    bgts                Last_Sub | 
 | 338 |  | 
 | 339 |    cmpl                %d4,%d1 | 
 | 340 |    bnes                Not_EQ | 
 | 341 |    cmpl                %d5,%d2 | 
 | 342 |    bnes                Not_EQ | 
 | 343 |    bra                Tie_Case | 
 | 344 |  | 
 | 345 | Not_EQ: | 
 | 346 |    bcss                Fix_Sign | 
 | 347 |  | 
 | 348 | Last_Sub: | 
 | 349 | | | 
 | 350 |    fsubx		Y(%a6),%fp0		| ...no exceptions | 
 | 351 |    addql               #1,%d3           | ...Q := Q + 1 | 
 | 352 |  | 
 | 353 | | | 
 | 354 |  | 
 | 355 | Fix_Sign: | 
 | 356 | |..Get sign of X | 
 | 357 |    movew               SignX(%a6),%d6 | 
 | 358 |    bges		Get_Q | 
 | 359 |    fnegx		%fp0 | 
 | 360 |  | 
 | 361 | |..Get Q | 
 | 362 | | | 
 | 363 | Get_Q: | 
 | 364 |    clrl		%d6 | 
 | 365 |    movew               SignQ(%a6),%d6        | ...D6 is sign(Q) | 
 | 366 |    movel               #8,%d7 | 
 | 367 |    lsrl                %d7,%d6 | 
 | 368 |    andil               #0x0000007F,%d3   | ...7 bits of Q | 
 | 369 |    orl                 %d6,%d3           | ...sign and bits of Q | 
 | 370 |    swap                 %d3 | 
 | 371 |    fmovel              %fpsr,%d6 | 
 | 372 |    andil               #0xFF00FFFF,%d6 | 
 | 373 |    orl                 %d3,%d6 | 
 | 374 |    fmovel              %d6,%fpsr         | ...put Q in fpsr | 
 | 375 |  | 
 | 376 | | | 
 | 377 | Restore: | 
 | 378 |    moveml              (%a7)+,%d2-%d7 | 
 | 379 |    fmovel              USER_FPCR(%a6),%fpcr | 
 | 380 |    movel               Sc_Flag(%a6),%d0 | 
 | 381 |    beqs                Finish | 
 | 382 |    fmulx		Scale(%pc),%fp0	| ...may cause underflow | 
 | 383 |    bra			t_avoid_unsupp	|check for denorm as a | 
 | 384 | |					;result of the scaling | 
 | 385 |  | 
 | 386 | Finish: | 
 | 387 | 	fmovex		%fp0,%fp0		|capture exceptions & round | 
 | 388 | 	rts | 
 | 389 |  | 
 | 390 | Rem_is_0: | 
 | 391 | |..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1) | 
 | 392 |    addql               #1,%d3 | 
 | 393 |    cmpil               #8,%d0           | ...D0 is j | 
 | 394 |    bges                Q_Big | 
 | 395 |  | 
 | 396 |    lsll                %d0,%d3 | 
 | 397 |    bras                Set_R_0 | 
 | 398 |  | 
 | 399 | Q_Big: | 
 | 400 |    clrl                %d3 | 
 | 401 |  | 
 | 402 | Set_R_0: | 
 | 403 |    fmoves		#0x00000000,%fp0 | 
 | 404 |    movel		#0,Sc_Flag(%a6) | 
 | 405 |    bra                Fix_Sign | 
 | 406 |  | 
 | 407 | Tie_Case: | 
 | 408 | |..Check parity of Q | 
 | 409 |    movel               %d3,%d6 | 
 | 410 |    andil               #0x00000001,%d6 | 
 | 411 |    tstl                %d6 | 
 | 412 |    beq                Fix_Sign	| ...Q is even | 
 | 413 |  | 
 | 414 | |..Q is odd, Q := Q + 1, signX := -signX | 
 | 415 |    addql               #1,%d3 | 
 | 416 |    movew               SignX(%a6),%d6 | 
 | 417 |    eoril               #0x00008000,%d6 | 
 | 418 |    movew               %d6,SignX(%a6) | 
 | 419 |    bra                Fix_Sign | 
 | 420 |  | 
 | 421 |    |end |