1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38#include <linux/kernel.h>
39#include <cpu/fpu.h>
40#include <asm/div64.h>
41
42#define LIT64( a ) a##LL
43
44typedef char flag;
45typedef unsigned char uint8;
46typedef signed char int8;
47typedef int uint16;
48typedef int int16;
49typedef unsigned int uint32;
50typedef signed int int32;
51
52typedef unsigned long long int bits64;
53typedef signed long long int sbits64;
54
55typedef unsigned char bits8;
56typedef signed char sbits8;
57typedef unsigned short int bits16;
58typedef signed short int sbits16;
59typedef unsigned int bits32;
60typedef signed int sbits32;
61
62typedef unsigned long long int uint64;
63typedef signed long long int int64;
64
65typedef unsigned long int float32;
66typedef unsigned long long float64;
67
68extern void float_raise(unsigned int flags);
69extern int float_rounding_mode(void);
70
71bits64 extractFloat64Frac(float64 a);
72flag extractFloat64Sign(float64 a);
73int16 extractFloat64Exp(float64 a);
74int16 extractFloat32Exp(float32 a);
75flag extractFloat32Sign(float32 a);
76bits32 extractFloat32Frac(float32 a);
77float64 packFloat64(flag zSign, int16 zExp, bits64 zSig);
78void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr);
79float32 packFloat32(flag zSign, int16 zExp, bits32 zSig);
80void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr);
81float64 float64_sub(float64 a, float64 b);
82float32 float32_sub(float32 a, float32 b);
83float32 float32_add(float32 a, float32 b);
84float64 float64_add(float64 a, float64 b);
85float64 float64_div(float64 a, float64 b);
86float32 float32_div(float32 a, float32 b);
87float32 float32_mul(float32 a, float32 b);
88float64 float64_mul(float64 a, float64 b);
89float32 float64_to_float32(float64 a);
90void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
91 bits64 * z1Ptr);
92void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
93 bits64 * z1Ptr);
94void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr);
95
96static int8 countLeadingZeros32(bits32 a);
97static int8 countLeadingZeros64(bits64 a);
98static float64 normalizeRoundAndPackFloat64(flag zSign, int16 zExp,
99 bits64 zSig);
100static float64 subFloat64Sigs(float64 a, float64 b, flag zSign);
101static float64 addFloat64Sigs(float64 a, float64 b, flag zSign);
102static float32 roundAndPackFloat32(flag zSign, int16 zExp, bits32 zSig);
103static float32 normalizeRoundAndPackFloat32(flag zSign, int16 zExp,
104 bits32 zSig);
105static float64 roundAndPackFloat64(flag zSign, int16 zExp, bits64 zSig);
106static float32 subFloat32Sigs(float32 a, float32 b, flag zSign);
107static float32 addFloat32Sigs(float32 a, float32 b, flag zSign);
108static void normalizeFloat64Subnormal(bits64 aSig, int16 * zExpPtr,
109 bits64 * zSigPtr);
110static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b);
111static void normalizeFloat32Subnormal(bits32 aSig, int16 * zExpPtr,
112 bits32 * zSigPtr);
113
114bits64 extractFloat64Frac(float64 a)
115{
116 return a & LIT64(0x000FFFFFFFFFFFFF);
117}
118
119flag extractFloat64Sign(float64 a)
120{
121 return a >> 63;
122}
123
124int16 extractFloat64Exp(float64 a)
125{
126 return (a >> 52) & 0x7FF;
127}
128
129int16 extractFloat32Exp(float32 a)
130{
131 return (a >> 23) & 0xFF;
132}
133
134flag extractFloat32Sign(float32 a)
135{
136 return a >> 31;
137}
138
139bits32 extractFloat32Frac(float32 a)
140{
141 return a & 0x007FFFFF;
142}
143
144float64 packFloat64(flag zSign, int16 zExp, bits64 zSig)
145{
146 return (((bits64) zSign) << 63) + (((bits64) zExp) << 52) + zSig;
147}
148
149void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr)
150{
151 bits64 z;
152
153 if (count == 0) {
154 z = a;
155 } else if (count < 64) {
156 z = (a >> count) | ((a << ((-count) & 63)) != 0);
157 } else {
158 z = (a != 0);
159 }
160 *zPtr = z;
161}
162
163static int8 countLeadingZeros32(bits32 a)
164{
165 static const int8 countLeadingZerosHigh[] = {
166 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
167 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
168 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
169 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
170 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
171 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
172 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
173 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
182 };
183 int8 shiftCount;
184
185 shiftCount = 0;
186 if (a < 0x10000) {
187 shiftCount += 16;
188 a <<= 16;
189 }
190 if (a < 0x1000000) {
191 shiftCount += 8;
192 a <<= 8;
193 }
194 shiftCount += countLeadingZerosHigh[a >> 24];
195 return shiftCount;
196
197}
198
199static int8 countLeadingZeros64(bits64 a)
200{
201 int8 shiftCount;
202
203 shiftCount = 0;
204 if (a < ((bits64) 1) << 32) {
205 shiftCount += 32;
206 } else {
207 a >>= 32;
208 }
209 shiftCount += countLeadingZeros32(a);
210 return shiftCount;
211
212}
213
214static float64 normalizeRoundAndPackFloat64(flag zSign, int16 zExp, bits64 zSig)
215{
216 int8 shiftCount;
217
218 shiftCount = countLeadingZeros64(zSig) - 1;
219 return roundAndPackFloat64(zSign, zExp - shiftCount,
220 zSig << shiftCount);
221
222}
223
224static float64 subFloat64Sigs(float64 a, float64 b, flag zSign)
225{
226 int16 aExp, bExp, zExp;
227 bits64 aSig, bSig, zSig;
228 int16 expDiff;
229
230 aSig = extractFloat64Frac(a);
231 aExp = extractFloat64Exp(a);
232 bSig = extractFloat64Frac(b);
233 bExp = extractFloat64Exp(b);
234 expDiff = aExp - bExp;
235 aSig <<= 10;
236 bSig <<= 10;
237 if (0 < expDiff)
238 goto aExpBigger;
239 if (expDiff < 0)
240 goto bExpBigger;
241 if (aExp == 0) {
242 aExp = 1;
243 bExp = 1;
244 }
245 if (bSig < aSig)
246 goto aBigger;
247 if (aSig < bSig)
248 goto bBigger;
249 return packFloat64(float_rounding_mode() == FPSCR_RM_ZERO, 0, 0);
250 bExpBigger:
251 if (bExp == 0x7FF) {
252 return packFloat64(zSign ^ 1, 0x7FF, 0);
253 }
254 if (aExp == 0) {
255 ++expDiff;
256 } else {
257 aSig |= LIT64(0x4000000000000000);
258 }
259 shift64RightJamming(aSig, -expDiff, &aSig);
260 bSig |= LIT64(0x4000000000000000);
261 bBigger:
262 zSig = bSig - aSig;
263 zExp = bExp;
264 zSign ^= 1;
265 goto normalizeRoundAndPack;
266 aExpBigger:
267 if (aExp == 0x7FF) {
268 return a;
269 }
270 if (bExp == 0) {
271 --expDiff;
272 } else {
273 bSig |= LIT64(0x4000000000000000);
274 }
275 shift64RightJamming(bSig, expDiff, &bSig);
276 aSig |= LIT64(0x4000000000000000);
277 aBigger:
278 zSig = aSig - bSig;
279 zExp = aExp;
280 normalizeRoundAndPack:
281 --zExp;
282 return normalizeRoundAndPackFloat64(zSign, zExp, zSig);
283
284}
285static float64 addFloat64Sigs(float64 a, float64 b, flag zSign)
286{
287 int16 aExp, bExp, zExp;
288 bits64 aSig, bSig, zSig;
289 int16 expDiff;
290
291 aSig = extractFloat64Frac(a);
292 aExp = extractFloat64Exp(a);
293 bSig = extractFloat64Frac(b);
294 bExp = extractFloat64Exp(b);
295 expDiff = aExp - bExp;
296 aSig <<= 9;
297 bSig <<= 9;
298 if (0 < expDiff) {
299 if (aExp == 0x7FF) {
300 return a;
301 }
302 if (bExp == 0) {
303 --expDiff;
304 } else {
305 bSig |= LIT64(0x2000000000000000);
306 }
307 shift64RightJamming(bSig, expDiff, &bSig);
308 zExp = aExp;
309 } else if (expDiff < 0) {
310 if (bExp == 0x7FF) {
311 return packFloat64(zSign, 0x7FF, 0);
312 }
313 if (aExp == 0) {
314 ++expDiff;
315 } else {
316 aSig |= LIT64(0x2000000000000000);
317 }
318 shift64RightJamming(aSig, -expDiff, &aSig);
319 zExp = bExp;
320 } else {
321 if (aExp == 0x7FF) {
322 return a;
323 }
324 if (aExp == 0)
325 return packFloat64(zSign, 0, (aSig + bSig) >> 9);
326 zSig = LIT64(0x4000000000000000) + aSig + bSig;
327 zExp = aExp;
328 goto roundAndPack;
329 }
330 aSig |= LIT64(0x2000000000000000);
331 zSig = (aSig + bSig) << 1;
332 --zExp;
333 if ((sbits64) zSig < 0) {
334 zSig = aSig + bSig;
335 ++zExp;
336 }
337 roundAndPack:
338 return roundAndPackFloat64(zSign, zExp, zSig);
339
340}
341
342float32 packFloat32(flag zSign, int16 zExp, bits32 zSig)
343{
344 return (((bits32) zSign) << 31) + (((bits32) zExp) << 23) + zSig;
345}
346
347void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr)
348{
349 bits32 z;
350 if (count == 0) {
351 z = a;
352 } else if (count < 32) {
353 z = (a >> count) | ((a << ((-count) & 31)) != 0);
354 } else {
355 z = (a != 0);
356 }
357 *zPtr = z;
358}
359
360static float32 roundAndPackFloat32(flag zSign, int16 zExp, bits32 zSig)
361{
362 flag roundNearestEven;
363 int8 roundIncrement, roundBits;
364 flag isTiny;
365
366
367 roundNearestEven = (float_rounding_mode() == FPSCR_RM_NEAREST);
368 roundIncrement = 0x40;
369 if (!roundNearestEven) {
370 roundIncrement = 0;
371 }
372 roundBits = zSig & 0x7F;
373 if (0xFD <= (bits16) zExp) {
374 if ((0xFD < zExp)
375 || ((zExp == 0xFD)
376 && ((sbits32) (zSig + roundIncrement) < 0))
377 ) {
378 float_raise(FPSCR_CAUSE_OVERFLOW | FPSCR_CAUSE_INEXACT);
379 return packFloat32(zSign, 0xFF,
380 0) - (roundIncrement == 0);
381 }
382 if (zExp < 0) {
383 isTiny = (zExp < -1)
384 || (zSig + roundIncrement < 0x80000000);
385 shift32RightJamming(zSig, -zExp, &zSig);
386 zExp = 0;
387 roundBits = zSig & 0x7F;
388 if (isTiny && roundBits)
389 float_raise(FPSCR_CAUSE_UNDERFLOW);
390 }
391 }
392 if (roundBits)
393 float_raise(FPSCR_CAUSE_INEXACT);
394 zSig = (zSig + roundIncrement) >> 7;
395 zSig &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven);
396 if (zSig == 0)
397 zExp = 0;
398 return packFloat32(zSign, zExp, zSig);
399
400}
401
402static float32 normalizeRoundAndPackFloat32(flag zSign, int16 zExp, bits32 zSig)
403{
404 int8 shiftCount;
405
406 shiftCount = countLeadingZeros32(zSig) - 1;
407 return roundAndPackFloat32(zSign, zExp - shiftCount,
408 zSig << shiftCount);
409}
410
411static float64 roundAndPackFloat64(flag zSign, int16 zExp, bits64 zSig)
412{
413 flag roundNearestEven;
414 int16 roundIncrement, roundBits;
415 flag isTiny;
416
417
418 roundNearestEven = (float_rounding_mode() == FPSCR_RM_NEAREST);
419 roundIncrement = 0x200;
420 if (!roundNearestEven) {
421 roundIncrement = 0;
422 }
423 roundBits = zSig & 0x3FF;
424 if (0x7FD <= (bits16) zExp) {
425 if ((0x7FD < zExp)
426 || ((zExp == 0x7FD)
427 && ((sbits64) (zSig + roundIncrement) < 0))
428 ) {
429 float_raise(FPSCR_CAUSE_OVERFLOW | FPSCR_CAUSE_INEXACT);
430 return packFloat64(zSign, 0x7FF,
431 0) - (roundIncrement == 0);
432 }
433 if (zExp < 0) {
434 isTiny = (zExp < -1)
435 || (zSig + roundIncrement <
436 LIT64(0x8000000000000000));
437 shift64RightJamming(zSig, -zExp, &zSig);
438 zExp = 0;
439 roundBits = zSig & 0x3FF;
440 if (isTiny && roundBits)
441 float_raise(FPSCR_CAUSE_UNDERFLOW);
442 }
443 }
444 if (roundBits)
445 float_raise(FPSCR_CAUSE_INEXACT);
446 zSig = (zSig + roundIncrement) >> 10;
447 zSig &= ~(((roundBits ^ 0x200) == 0) & roundNearestEven);
448 if (zSig == 0)
449 zExp = 0;
450 return packFloat64(zSign, zExp, zSig);
451
452}
453
454static float32 subFloat32Sigs(float32 a, float32 b, flag zSign)
455{
456 int16 aExp, bExp, zExp;
457 bits32 aSig, bSig, zSig;
458 int16 expDiff;
459
460 aSig = extractFloat32Frac(a);
461 aExp = extractFloat32Exp(a);
462 bSig = extractFloat32Frac(b);
463 bExp = extractFloat32Exp(b);
464 expDiff = aExp - bExp;
465 aSig <<= 7;
466 bSig <<= 7;
467 if (0 < expDiff)
468 goto aExpBigger;
469 if (expDiff < 0)
470 goto bExpBigger;
471 if (aExp == 0) {
472 aExp = 1;
473 bExp = 1;
474 }
475 if (bSig < aSig)
476 goto aBigger;
477 if (aSig < bSig)
478 goto bBigger;
479 return packFloat32(float_rounding_mode() == FPSCR_RM_ZERO, 0, 0);
480 bExpBigger:
481 if (bExp == 0xFF) {
482 return packFloat32(zSign ^ 1, 0xFF, 0);
483 }
484 if (aExp == 0) {
485 ++expDiff;
486 } else {
487 aSig |= 0x40000000;
488 }
489 shift32RightJamming(aSig, -expDiff, &aSig);
490 bSig |= 0x40000000;
491 bBigger:
492 zSig = bSig - aSig;
493 zExp = bExp;
494 zSign ^= 1;
495 goto normalizeRoundAndPack;
496 aExpBigger:
497 if (aExp == 0xFF) {
498 return a;
499 }
500 if (bExp == 0) {
501 --expDiff;
502 } else {
503 bSig |= 0x40000000;
504 }
505 shift32RightJamming(bSig, expDiff, &bSig);
506 aSig |= 0x40000000;
507 aBigger:
508 zSig = aSig - bSig;
509 zExp = aExp;
510 normalizeRoundAndPack:
511 --zExp;
512 return normalizeRoundAndPackFloat32(zSign, zExp, zSig);
513
514}
515
516static float32 addFloat32Sigs(float32 a, float32 b, flag zSign)
517{
518 int16 aExp, bExp, zExp;
519 bits32 aSig, bSig, zSig;
520 int16 expDiff;
521
522 aSig = extractFloat32Frac(a);
523 aExp = extractFloat32Exp(a);
524 bSig = extractFloat32Frac(b);
525 bExp = extractFloat32Exp(b);
526 expDiff = aExp - bExp;
527 aSig <<= 6;
528 bSig <<= 6;
529 if (0 < expDiff) {
530 if (aExp == 0xFF) {
531 return a;
532 }
533 if (bExp == 0) {
534 --expDiff;
535 } else {
536 bSig |= 0x20000000;
537 }
538 shift32RightJamming(bSig, expDiff, &bSig);
539 zExp = aExp;
540 } else if (expDiff < 0) {
541 if (bExp == 0xFF) {
542 return packFloat32(zSign, 0xFF, 0);
543 }
544 if (aExp == 0) {
545 ++expDiff;
546 } else {
547 aSig |= 0x20000000;
548 }
549 shift32RightJamming(aSig, -expDiff, &aSig);
550 zExp = bExp;
551 } else {
552 if (aExp == 0xFF) {
553 return a;
554 }
555 if (aExp == 0)
556 return packFloat32(zSign, 0, (aSig + bSig) >> 6);
557 zSig = 0x40000000 + aSig + bSig;
558 zExp = aExp;
559 goto roundAndPack;
560 }
561 aSig |= 0x20000000;
562 zSig = (aSig + bSig) << 1;
563 --zExp;
564 if ((sbits32) zSig < 0) {
565 zSig = aSig + bSig;
566 ++zExp;
567 }
568 roundAndPack:
569 return roundAndPackFloat32(zSign, zExp, zSig);
570
571}
572
573float64 float64_sub(float64 a, float64 b)
574{
575 flag aSign, bSign;
576
577 aSign = extractFloat64Sign(a);
578 bSign = extractFloat64Sign(b);
579 if (aSign == bSign) {
580 return subFloat64Sigs(a, b, aSign);
581 } else {
582 return addFloat64Sigs(a, b, aSign);
583 }
584
585}
586
587float32 float32_sub(float32 a, float32 b)
588{
589 flag aSign, bSign;
590
591 aSign = extractFloat32Sign(a);
592 bSign = extractFloat32Sign(b);
593 if (aSign == bSign) {
594 return subFloat32Sigs(a, b, aSign);
595 } else {
596 return addFloat32Sigs(a, b, aSign);
597 }
598
599}
600
601float32 float32_add(float32 a, float32 b)
602{
603 flag aSign, bSign;
604
605 aSign = extractFloat32Sign(a);
606 bSign = extractFloat32Sign(b);
607 if (aSign == bSign) {
608 return addFloat32Sigs(a, b, aSign);
609 } else {
610 return subFloat32Sigs(a, b, aSign);
611 }
612
613}
614
615float64 float64_add(float64 a, float64 b)
616{
617 flag aSign, bSign;
618
619 aSign = extractFloat64Sign(a);
620 bSign = extractFloat64Sign(b);
621 if (aSign == bSign) {
622 return addFloat64Sigs(a, b, aSign);
623 } else {
624 return subFloat64Sigs(a, b, aSign);
625 }
626}
627
628static void
629normalizeFloat64Subnormal(bits64 aSig, int16 * zExpPtr, bits64 * zSigPtr)
630{
631 int8 shiftCount;
632
633 shiftCount = countLeadingZeros64(aSig) - 11;
634 *zSigPtr = aSig << shiftCount;
635 *zExpPtr = 1 - shiftCount;
636}
637
638void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
639 bits64 * z1Ptr)
640{
641 bits64 z1;
642
643 z1 = a1 + b1;
644 *z1Ptr = z1;
645 *z0Ptr = a0 + b0 + (z1 < a1);
646}
647
648void
649sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
650 bits64 * z1Ptr)
651{
652 *z1Ptr = a1 - b1;
653 *z0Ptr = a0 - b0 - (a1 < b1);
654}
655
656static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b)
657{
658 bits64 b0, b1;
659 bits64 rem0, rem1, term0, term1;
660 bits64 z, tmp;
661 if (b <= a0)
662 return LIT64(0xFFFFFFFFFFFFFFFF);
663 b0 = b >> 32;
664 tmp = a0;
665 do_div(tmp, b0);
666
667 z = (b0 << 32 <= a0) ? LIT64(0xFFFFFFFF00000000) : tmp << 32;
668 mul64To128(b, z, &term0, &term1);
669 sub128(a0, a1, term0, term1, &rem0, &rem1);
670 while (((sbits64) rem0) < 0) {
671 z -= LIT64(0x100000000);
672 b1 = b << 32;
673 add128(rem0, rem1, b0, b1, &rem0, &rem1);
674 }
675 rem0 = (rem0 << 32) | (rem1 >> 32);
676 tmp = rem0;
677 do_div(tmp, b0);
678 z |= (b0 << 32 <= rem0) ? 0xFFFFFFFF : tmp;
679 return z;
680}
681
682void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr)
683{
684 bits32 aHigh, aLow, bHigh, bLow;
685 bits64 z0, zMiddleA, zMiddleB, z1;
686
687 aLow = a;
688 aHigh = a >> 32;
689 bLow = b;
690 bHigh = b >> 32;
691 z1 = ((bits64) aLow) * bLow;
692 zMiddleA = ((bits64) aLow) * bHigh;
693 zMiddleB = ((bits64) aHigh) * bLow;
694 z0 = ((bits64) aHigh) * bHigh;
695 zMiddleA += zMiddleB;
696 z0 += (((bits64) (zMiddleA < zMiddleB)) << 32) + (zMiddleA >> 32);
697 zMiddleA <<= 32;
698 z1 += zMiddleA;
699 z0 += (z1 < zMiddleA);
700 *z1Ptr = z1;
701 *z0Ptr = z0;
702
703}
704
705static void normalizeFloat32Subnormal(bits32 aSig, int16 * zExpPtr,
706 bits32 * zSigPtr)
707{
708 int8 shiftCount;
709
710 shiftCount = countLeadingZeros32(aSig) - 8;
711 *zSigPtr = aSig << shiftCount;
712 *zExpPtr = 1 - shiftCount;
713
714}
715
716float64 float64_div(float64 a, float64 b)
717{
718 flag aSign, bSign, zSign;
719 int16 aExp, bExp, zExp;
720 bits64 aSig, bSig, zSig;
721 bits64 rem0, rem1;
722 bits64 term0, term1;
723
724 aSig = extractFloat64Frac(a);
725 aExp = extractFloat64Exp(a);
726 aSign = extractFloat64Sign(a);
727 bSig = extractFloat64Frac(b);
728 bExp = extractFloat64Exp(b);
729 bSign = extractFloat64Sign(b);
730 zSign = aSign ^ bSign;
731 if (aExp == 0x7FF) {
732 if (bExp == 0x7FF) {
733 }
734 return packFloat64(zSign, 0x7FF, 0);
735 }
736 if (bExp == 0x7FF) {
737 return packFloat64(zSign, 0, 0);
738 }
739 if (bExp == 0) {
740 if (bSig == 0) {
741 if ((aExp | aSig) == 0) {
742 float_raise(FPSCR_CAUSE_INVALID);
743 }
744 return packFloat64(zSign, 0x7FF, 0);
745 }
746 normalizeFloat64Subnormal(bSig, &bExp, &bSig);
747 }
748 if (aExp == 0) {
749 if (aSig == 0)
750 return packFloat64(zSign, 0, 0);
751 normalizeFloat64Subnormal(aSig, &aExp, &aSig);
752 }
753 zExp = aExp - bExp + 0x3FD;
754 aSig = (aSig | LIT64(0x0010000000000000)) << 10;
755 bSig = (bSig | LIT64(0x0010000000000000)) << 11;
756 if (bSig <= (aSig + aSig)) {
757 aSig >>= 1;
758 ++zExp;
759 }
760 zSig = estimateDiv128To64(aSig, 0, bSig);
761 if ((zSig & 0x1FF) <= 2) {
762 mul64To128(bSig, zSig, &term0, &term1);
763 sub128(aSig, 0, term0, term1, &rem0, &rem1);
764 while ((sbits64) rem0 < 0) {
765 --zSig;
766 add128(rem0, rem1, 0, bSig, &rem0, &rem1);
767 }
768 zSig |= (rem1 != 0);
769 }
770 return roundAndPackFloat64(zSign, zExp, zSig);
771
772}
773
774float32 float32_div(float32 a, float32 b)
775{
776 flag aSign, bSign, zSign;
777 int16 aExp, bExp, zExp;
778 bits32 aSig, bSig;
779 uint64_t zSig;
780
781 aSig = extractFloat32Frac(a);
782 aExp = extractFloat32Exp(a);
783 aSign = extractFloat32Sign(a);
784 bSig = extractFloat32Frac(b);
785 bExp = extractFloat32Exp(b);
786 bSign = extractFloat32Sign(b);
787 zSign = aSign ^ bSign;
788 if (aExp == 0xFF) {
789 if (bExp == 0xFF) {
790 }
791 return packFloat32(zSign, 0xFF, 0);
792 }
793 if (bExp == 0xFF) {
794 return packFloat32(zSign, 0, 0);
795 }
796 if (bExp == 0) {
797 if (bSig == 0) {
798 return packFloat32(zSign, 0xFF, 0);
799 }
800 normalizeFloat32Subnormal(bSig, &bExp, &bSig);
801 }
802 if (aExp == 0) {
803 if (aSig == 0)
804 return packFloat32(zSign, 0, 0);
805 normalizeFloat32Subnormal(aSig, &aExp, &aSig);
806 }
807 zExp = aExp - bExp + 0x7D;
808 aSig = (aSig | 0x00800000) << 7;
809 bSig = (bSig | 0x00800000) << 8;
810 if (bSig <= (aSig + aSig)) {
811 aSig >>= 1;
812 ++zExp;
813 }
814 zSig = (((bits64) aSig) << 32);
815 do_div(zSig, bSig);
816
817 if ((zSig & 0x3F) == 0) {
818 zSig |= (((bits64) bSig) * zSig != ((bits64) aSig) << 32);
819 }
820 return roundAndPackFloat32(zSign, zExp, (bits32)zSig);
821
822}
823
824float32 float32_mul(float32 a, float32 b)
825{
826 char aSign, bSign, zSign;
827 int aExp, bExp, zExp;
828 unsigned int aSig, bSig;
829 unsigned long long zSig64;
830 unsigned int zSig;
831
832 aSig = extractFloat32Frac(a);
833 aExp = extractFloat32Exp(a);
834 aSign = extractFloat32Sign(a);
835 bSig = extractFloat32Frac(b);
836 bExp = extractFloat32Exp(b);
837 bSign = extractFloat32Sign(b);
838 zSign = aSign ^ bSign;
839 if (aExp == 0) {
840 if (aSig == 0)
841 return packFloat32(zSign, 0, 0);
842 normalizeFloat32Subnormal(aSig, &aExp, &aSig);
843 }
844 if (bExp == 0) {
845 if (bSig == 0)
846 return packFloat32(zSign, 0, 0);
847 normalizeFloat32Subnormal(bSig, &bExp, &bSig);
848 }
849 if ((bExp == 0xff && bSig == 0) || (aExp == 0xff && aSig == 0))
850 return roundAndPackFloat32(zSign, 0xff, 0);
851
852 zExp = aExp + bExp - 0x7F;
853 aSig = (aSig | 0x00800000) << 7;
854 bSig = (bSig | 0x00800000) << 8;
855 shift64RightJamming(((unsigned long long)aSig) * bSig, 32, &zSig64);
856 zSig = zSig64;
857 if (0 <= (signed int)(zSig << 1)) {
858 zSig <<= 1;
859 --zExp;
860 }
861 return roundAndPackFloat32(zSign, zExp, zSig);
862
863}
864
865float64 float64_mul(float64 a, float64 b)
866{
867 char aSign, bSign, zSign;
868 int aExp, bExp, zExp;
869 unsigned long long int aSig, bSig, zSig0, zSig1;
870
871 aSig = extractFloat64Frac(a);
872 aExp = extractFloat64Exp(a);
873 aSign = extractFloat64Sign(a);
874 bSig = extractFloat64Frac(b);
875 bExp = extractFloat64Exp(b);
876 bSign = extractFloat64Sign(b);
877 zSign = aSign ^ bSign;
878
879 if (aExp == 0) {
880 if (aSig == 0)
881 return packFloat64(zSign, 0, 0);
882 normalizeFloat64Subnormal(aSig, &aExp, &aSig);
883 }
884 if (bExp == 0) {
885 if (bSig == 0)
886 return packFloat64(zSign, 0, 0);
887 normalizeFloat64Subnormal(bSig, &bExp, &bSig);
888 }
889 if ((aExp == 0x7ff && aSig == 0) || (bExp == 0x7ff && bSig == 0))
890 return roundAndPackFloat64(zSign, 0x7ff, 0);
891
892 zExp = aExp + bExp - 0x3FF;
893 aSig = (aSig | 0x0010000000000000LL) << 10;
894 bSig = (bSig | 0x0010000000000000LL) << 11;
895 mul64To128(aSig, bSig, &zSig0, &zSig1);
896 zSig0 |= (zSig1 != 0);
897 if (0 <= (signed long long int)(zSig0 << 1)) {
898 zSig0 <<= 1;
899 --zExp;
900 }
901 return roundAndPackFloat64(zSign, zExp, zSig0);
902}
903
904
905
906
907
908
909
910
911
912float32 float64_to_float32(float64 a)
913{
914 flag aSign;
915 int16 aExp;
916 bits64 aSig;
917 bits32 zSig;
918
919 aSig = extractFloat64Frac( a );
920 aExp = extractFloat64Exp( a );
921 aSign = extractFloat64Sign( a );
922
923 shift64RightJamming( aSig, 22, &aSig );
924 zSig = aSig;
925 if ( aExp || zSig ) {
926 zSig |= 0x40000000;
927 aExp -= 0x381;
928 }
929 return roundAndPackFloat32(aSign, aExp, zSig);
930}
931