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