* optimize.c (initialize_inlined_parameters): Take FN to which the
[official-gcc.git] / gcc / floatlib.c
blobdc7913937245130b89b0120669916012ee23d573
1 /*
2 ** libgcc support for software floating point.
3 ** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved.
4 ** Permission is granted to do *anything* you want with this file,
5 ** commercial or otherwise, provided this message remains intact. So there!
6 ** I would appreciate receiving any updates/patches/changes that anyone
7 ** makes, and am willing to be the repository for said changes (am I
8 ** making a big mistake?).
10 Warning! Only single-precision is actually implemented. This file
11 won't really be much use until double-precision is supported.
13 However, once that is done, this file might eventually become a
14 replacement for libgcc1.c. It might also make possible
15 cross-compilation for an IEEE target machine from a non-IEEE
16 host such as a VAX.
18 If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
20 --> Double precision floating support added by James Carlson on 20 April 1998.
23 ** Pat Wood
24 ** Pipeline Associates, Inc.
25 ** pipeline!phw@motown.com or
26 ** sun!pipeline!phw or
27 ** uunet!motown!pipeline!phw
29 ** 05/01/91 -- V1.0 -- first release to gcc mailing lists
30 ** 05/04/91 -- V1.1 -- added float and double prototypes and return values
31 ** -- fixed problems with adding and subtracting zero
32 ** -- fixed rounding in truncdfsf2
33 ** -- fixed SWAP define and tested on 386
37 ** The following are routines that replace the libgcc soft floating point
38 ** routines that are called automatically when -msoft-float is selected.
39 ** The support single and double precision IEEE format, with provisions
40 ** for byte-swapped machines (tested on 386). Some of the double-precision
41 ** routines work at full precision, but most of the hard ones simply punt
42 ** and call the single precision routines, producing a loss of accuracy.
43 ** long long support is not assumed or included.
44 ** Overall accuracy is close to IEEE (actually 68882) for single-precision
45 ** arithmetic. I think there may still be a 1 in 1000 chance of a bit
46 ** being rounded the wrong way during a multiply. I'm not fussy enough to
47 ** bother with it, but if anyone is, knock yourself out.
49 ** Efficiency has only been addressed where it was obvious that something
50 ** would make a big difference. Anyone who wants to do this right for
51 ** best speed should go in and rewrite in assembler.
53 ** I have tested this only on a 68030 workstation and 386/ix integrated
54 ** in with -msoft-float.
57 /* the following deal with IEEE single-precision numbers */
58 #define EXCESS 126
59 #define SIGNBIT 0x80000000
60 #define HIDDEN (1 << 23)
61 #define SIGN(fp) ((fp) & SIGNBIT)
62 #define EXP(fp) (((fp) >> 23) & 0xFF)
63 #define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN)
64 #define PACK(s,e,m) ((s) | ((e) << 23) | (m))
66 /* the following deal with IEEE double-precision numbers */
67 #define EXCESSD 1022
68 #define HIDDEND (1 << 20)
69 #define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
70 #define SIGND(fp) ((fp.l.upper) & SIGNBIT)
71 #define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
72 (fp.l.lower >> 22))
73 #define HIDDEND_LL ((long long)1 << 52)
74 #define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
75 #define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m))
77 /* define SWAP for 386/960 reverse-byte-order brain-damaged CPUs */
78 union double_long {
79 double d;
80 #ifdef SWAP
81 struct {
82 unsigned long lower;
83 long upper;
84 } l;
85 #else
86 struct {
87 long upper;
88 unsigned long lower;
89 } l;
90 #endif
91 long long ll;
94 union float_long
96 float f;
97 long l;
100 /* add two floats */
101 float
102 __addsf3 (float a1, float a2)
104 register long mant1, mant2;
105 register union float_long fl1, fl2;
106 register int exp1, exp2;
107 int sign = 0;
109 fl1.f = a1;
110 fl2.f = a2;
112 /* check for zero args */
113 if (!fl1.l) {
114 fl1.f = fl2.f;
115 goto test_done;
117 if (!fl2.l)
118 goto test_done;
120 exp1 = EXP (fl1.l);
121 exp2 = EXP (fl2.l);
123 if (exp1 > exp2 + 25)
124 goto test_done;
125 if (exp2 > exp1 + 25) {
126 fl1.f = fl2.f;
127 goto test_done;
130 /* do everything in excess precision so's we can round later */
131 mant1 = MANT (fl1.l) << 6;
132 mant2 = MANT (fl2.l) << 6;
134 if (SIGN (fl1.l))
135 mant1 = -mant1;
136 if (SIGN (fl2.l))
137 mant2 = -mant2;
139 if (exp1 > exp2)
141 mant2 >>= exp1 - exp2;
143 else
145 mant1 >>= exp2 - exp1;
146 exp1 = exp2;
148 mant1 += mant2;
150 if (mant1 < 0)
152 mant1 = -mant1;
153 sign = SIGNBIT;
155 else if (!mant1) {
156 fl1.f = 0;
157 goto test_done;
160 /* normalize up */
161 while (!(mant1 & 0xE0000000))
163 mant1 <<= 1;
164 exp1--;
167 /* normalize down? */
168 if (mant1 & (1 << 30))
170 mant1 >>= 1;
171 exp1++;
174 /* round to even */
175 mant1 += (mant1 & 0x40) ? 0x20 : 0x1F;
177 /* normalize down? */
178 if (mant1 & (1 << 30))
180 mant1 >>= 1;
181 exp1++;
184 /* lose extra precision */
185 mant1 >>= 6;
187 /* turn off hidden bit */
188 mant1 &= ~HIDDEN;
190 /* pack up and go home */
191 fl1.l = PACK (sign, exp1, mant1);
192 test_done:
193 return (fl1.f);
196 /* subtract two floats */
197 float
198 __subsf3 (float a1, float a2)
200 register union float_long fl1, fl2;
202 fl1.f = a1;
203 fl2.f = a2;
205 /* check for zero args */
206 if (!fl2.l)
207 return (fl1.f);
208 if (!fl1.l)
209 return (-fl2.f);
211 /* twiddle sign bit and add */
212 fl2.l ^= SIGNBIT;
213 return __addsf3 (a1, fl2.f);
216 /* compare two floats */
217 long
218 __cmpsf2 (float a1, float a2)
220 register union float_long fl1, fl2;
222 fl1.f = a1;
223 fl2.f = a2;
225 if (SIGN (fl1.l) && SIGN (fl2.l))
227 fl1.l ^= SIGNBIT;
228 fl2.l ^= SIGNBIT;
230 if (fl1.l < fl2.l)
231 return (-1);
232 if (fl1.l > fl2.l)
233 return (1);
234 return (0);
237 /* multiply two floats */
238 float
239 __mulsf3 (float a1, float a2)
241 register union float_long fl1, fl2;
242 register unsigned long result;
243 register int exp;
244 int sign;
246 fl1.f = a1;
247 fl2.f = a2;
249 if (!fl1.l || !fl2.l) {
250 fl1.f = 0;
251 goto test_done;
254 /* compute sign and exponent */
255 sign = SIGN (fl1.l) ^ SIGN (fl2.l);
256 exp = EXP (fl1.l) - EXCESS;
257 exp += EXP (fl2.l);
259 fl1.l = MANT (fl1.l);
260 fl2.l = MANT (fl2.l);
262 /* the multiply is done as one 16x16 multiply and two 16x8 multiples */
263 result = (fl1.l >> 8) * (fl2.l >> 8);
264 result += ((fl1.l & 0xFF) * (fl2.l >> 8)) >> 8;
265 result += ((fl2.l & 0xFF) * (fl1.l >> 8)) >> 8;
267 result >>= 2;
268 if (result & 0x20000000)
270 /* round */
271 result += 0x20;
272 result >>= 6;
274 else
276 /* round */
277 result += 0x10;
278 result >>= 5;
279 exp--;
281 if (result & (HIDDEN<<1)) {
282 result >>= 1;
283 exp++;
286 result &= ~HIDDEN;
288 /* pack up and go home */
289 fl1.l = PACK (sign, exp, result);
290 test_done:
291 return (fl1.f);
294 /* divide two floats */
295 float
296 __divsf3 (float a1, float a2)
298 register union float_long fl1, fl2;
299 register int result;
300 register int mask;
301 register int exp, sign;
303 fl1.f = a1;
304 fl2.f = a2;
306 /* subtract exponents */
307 exp = EXP (fl1.l) - EXP (fl2.l) + EXCESS;
309 /* compute sign */
310 sign = SIGN (fl1.l) ^ SIGN (fl2.l);
312 /* divide by zero??? */
313 if (!fl2.l)
314 /* return NaN or -NaN */
315 return (sign ? 0xFFFFFFFF : 0x7FFFFFFF);
317 /* numerator zero??? */
318 if (!fl1.l)
319 return (0);
321 /* now get mantissas */
322 fl1.l = MANT (fl1.l);
323 fl2.l = MANT (fl2.l);
325 /* this assures we have 25 bits of precision in the end */
326 if (fl1.l < fl2.l)
328 fl1.l <<= 1;
329 exp--;
332 /* now we perform repeated subtraction of fl2.l from fl1.l */
333 mask = 0x1000000;
334 result = 0;
335 while (mask)
337 if (fl1.l >= fl2.l)
339 result |= mask;
340 fl1.l -= fl2.l;
342 fl1.l <<= 1;
343 mask >>= 1;
346 /* round */
347 result += 1;
349 /* normalize down */
350 exp++;
351 result >>= 1;
353 result &= ~HIDDEN;
355 /* pack up and go home */
356 fl1.l = PACK (sign, exp, result);
357 return (fl1.f);
360 /* convert int to double */
361 double
362 __floatsidf (register long a1)
364 register int sign = 0, exp = 31 + EXCESSD;
365 union double_long dl;
367 if (!a1)
369 dl.l.upper = dl.l.lower = 0;
370 return (dl.d);
373 if (a1 < 0)
375 sign = SIGNBIT;
376 a1 = -a1;
379 while (a1 < 0x1000000)
381 a1 <<= 4;
382 exp -= 4;
385 while (a1 < 0x40000000)
387 a1 <<= 1;
388 exp--;
391 /* pack up and go home */
392 dl.l.upper = sign;
393 dl.l.upper |= exp << 20;
394 dl.l.upper |= (a1 >> 10) & ~HIDDEND;
395 dl.l.lower = a1 << 22;
397 return (dl.d);
400 double
401 __floatdidf (register long long a1)
403 register int exp = 63 + EXCESSD;
404 union double_long dl;
406 dl.l.upper = dl.l.lower = 0;
407 if (a1 == 0)
408 return (dl.d);
410 if (a1 < 0) {
411 dl.l.upper = SIGNBIT;
412 a1 = -a1;
415 while (a1 < (long long)1<<54) {
416 a1 <<= 8;
417 exp -= 8;
419 while (a1 < (long long)1<<62) {
420 a1 <<= 1;
421 exp -= 1;
424 /* pack up and go home */
425 dl.ll |= (a1 >> 10) & ~HIDDEND_LL;
426 dl.l.upper |= exp << 20;
428 return (dl.d);
431 float
432 __floatsisf (register long a1)
434 (float)__floatsidf(a1);
437 float
438 __floatdisf (register long long a1)
440 (float)__floatdidf(a1);
443 /* negate a float */
444 float
445 __negsf2 (float a1)
447 register union float_long fl1;
449 fl1.f = a1;
450 if (!fl1.l)
451 return (0);
453 fl1.l ^= SIGNBIT;
454 return (fl1.f);
457 /* negate a double */
458 double
459 __negdf2 (double a1)
461 register union double_long dl1;
463 dl1.d = a1;
465 if (!dl1.l.upper && !dl1.l.lower)
466 return (dl1.d);
468 dl1.l.upper ^= SIGNBIT;
469 return (dl1.d);
472 /* convert float to double */
473 double
474 __extendsfdf2 (float a1)
476 register union float_long fl1;
477 register union double_long dl;
478 register int exp;
480 fl1.f = a1;
482 if (!fl1.l)
484 dl.l.upper = dl.l.lower = 0;
485 return (dl.d);
488 dl.l.upper = SIGN (fl1.l);
489 exp = EXP (fl1.l) - EXCESS + EXCESSD;
490 dl.l.upper |= exp << 20;
491 dl.l.upper |= (MANT (fl1.l) & ~HIDDEN) >> 3;
492 dl.l.lower = MANT (fl1.l) << 29;
494 return (dl.d);
497 /* convert double to float */
498 float
499 __truncdfsf2 (double a1)
501 register int exp;
502 register long mant;
503 register union float_long fl;
504 register union double_long dl1;
506 dl1.d = a1;
508 if (!dl1.l.upper && !dl1.l.lower)
509 return (float)(0);
511 exp = EXPD (dl1) - EXCESSD + EXCESS;
513 /* shift double mantissa 6 bits so we can round */
514 mant = MANTD (dl1) >> 6;
516 /* now round and shift down */
517 mant += 1;
518 mant >>= 1;
520 /* did the round overflow? */
521 if (mant & 0xFE000000)
523 mant >>= 1;
524 exp++;
527 mant &= ~HIDDEN;
529 /* pack up and go home */
530 fl.l = PACK (SIGND (dl1), exp, mant);
531 return (fl.f);
534 /* compare two doubles */
535 long
536 __cmpdf2 (double a1, double a2)
538 register union double_long dl1, dl2;
540 dl1.d = a1;
541 dl2.d = a2;
543 if (SIGND (dl1) && SIGND (dl2))
545 dl1.l.upper ^= SIGNBIT;
546 dl2.l.upper ^= SIGNBIT;
548 if (dl1.l.upper < dl2.l.upper)
549 return (-1);
550 if (dl1.l.upper > dl2.l.upper)
551 return (1);
552 if (dl1.l.lower < dl2.l.lower)
553 return (-1);
554 if (dl1.l.lower > dl2.l.lower)
555 return (1);
556 return (0);
559 /* convert double to int */
560 long
561 __fixdfsi (double a1)
563 register union double_long dl1;
564 register int exp;
565 register long l;
567 dl1.d = a1;
569 if (!dl1.l.upper && !dl1.l.lower)
570 return (0);
572 exp = EXPD (dl1) - EXCESSD - 31;
573 l = MANTD (dl1);
575 if (exp > 0)
576 return SIGND(dl1) ? (1<<31) : ((1ul<<31)-1);
578 /* shift down until exp = 0 or l = 0 */
579 if (exp < 0 && exp > -32 && l)
580 l >>= -exp;
581 else
582 return (0);
584 return (SIGND (dl1) ? -l : l);
587 /* convert double to int */
588 long long
589 __fixdfdi (double a1)
591 register union double_long dl1;
592 register int exp;
593 register long long l;
595 dl1.d = a1;
597 if (!dl1.l.upper && !dl1.l.lower)
598 return (0);
600 exp = EXPD (dl1) - EXCESSD - 64;
601 l = MANTD_LL(dl1);
603 if (exp > 0) {
604 l = (long long)1<<63;
605 if (!SIGND(dl1))
606 l--;
607 return l;
610 /* shift down until exp = 0 or l = 0 */
611 if (exp < 0 && exp > -64 && l)
612 l >>= -exp;
613 else
614 return (0);
616 return (SIGND (dl1) ? -l : l);
619 /* convert double to unsigned int */
620 unsigned long
621 __fixunsdfsi (double a1)
623 register union double_long dl1;
624 register int exp;
625 register unsigned long l;
627 dl1.d = a1;
629 if (!dl1.l.upper && !dl1.l.lower)
630 return (0);
632 exp = EXPD (dl1) - EXCESSD - 32;
633 l = (((((dl1.l.upper) & 0xFFFFF) | HIDDEND) << 11) | (dl1.l.lower >> 21));
635 if (exp > 0)
636 return (0xFFFFFFFFul); /* largest integer */
638 /* shift down until exp = 0 or l = 0 */
639 if (exp < 0 && exp > -32 && l)
640 l >>= -exp;
641 else
642 return (0);
644 return (l);
647 /* convert double to unsigned int */
648 unsigned long long
649 __fixunsdfdi (double a1)
651 register union double_long dl1;
652 register int exp;
653 register unsigned long long l;
655 dl1.d = a1;
657 if (dl1.ll == 0)
658 return (0);
660 exp = EXPD (dl1) - EXCESSD - 64;
662 l = dl1.ll;
664 if (exp > 0)
665 return (unsigned long long)-1;
667 /* shift down until exp = 0 or l = 0 */
668 if (exp < 0 && exp > -64 && l)
669 l >>= -exp;
670 else
671 return (0);
673 return (l);
676 /* addtwo doubles */
677 double
678 __adddf3 (double a1, double a2)
680 register long long mant1, mant2;
681 register union double_long fl1, fl2;
682 register int exp1, exp2;
683 int sign = 0;
685 fl1.d = a1;
686 fl2.d = a2;
688 /* check for zero args */
689 if (!fl2.ll)
690 goto test_done;
691 if (!fl1.ll) {
692 fl1.d = fl2.d;
693 goto test_done;
696 exp1 = EXPD(fl1);
697 exp2 = EXPD(fl2);
699 if (exp1 > exp2 + 54)
700 goto test_done;
701 if (exp2 > exp1 + 54) {
702 fl1.d = fl2.d;
703 goto test_done;
706 /* do everything in excess precision so's we can round later */
707 mant1 = MANTD_LL(fl1) << 9;
708 mant2 = MANTD_LL(fl2) << 9;
710 if (SIGND(fl1))
711 mant1 = -mant1;
712 if (SIGND(fl2))
713 mant2 = -mant2;
715 if (exp1 > exp2)
716 mant2 >>= exp1 - exp2;
717 else {
718 mant1 >>= exp2 - exp1;
719 exp1 = exp2;
721 mant1 += mant2;
723 if (mant1 < 0) {
724 mant1 = -mant1;
725 sign = SIGNBIT;
726 } else if (!mant1) {
727 fl1.d = 0;
728 goto test_done;
731 /* normalize up */
732 while (!(mant1 & ((long long)7<<61))) {
733 mant1 <<= 1;
734 exp1--;
737 /* normalize down? */
738 if (mant1 & ((long long)3<<62)) {
739 mant1 >>= 1;
740 exp1++;
743 /* round to even */
744 mant1 += (mant1 & (1<<9)) ? (1<<8) : ((1<<8)-1);
746 /* normalize down? */
747 if (mant1 & ((long long)3<<62)) {
748 mant1 >>= 1;
749 exp1++;
752 /* lose extra precision */
753 mant1 >>= 9;
755 /* turn off hidden bit */
756 mant1 &= ~HIDDEND_LL;
758 /* pack up and go home */
759 fl1.ll = PACKD_LL(sign,exp1,mant1);
761 test_done:
762 return (fl1.d);
765 /* subtract two doubles */
766 double
767 __subdf3 (double a1, double a2)
769 register union double_long fl1, fl2;
771 fl1.d = a1;
772 fl2.d = a2;
774 /* check for zero args */
775 if (!fl2.ll)
776 return (fl1.d);
777 /* twiddle sign bit and add */
778 fl2.l.upper ^= SIGNBIT;
779 if (!fl1.ll)
780 return (fl2.d);
781 return __adddf3 (a1, fl2.d);
784 /* multiply two doubles */
785 double
786 __muldf3 (double a1, double a2)
788 register union double_long fl1, fl2;
789 register unsigned long long result;
790 register int exp;
791 int sign;
793 fl1.d = a1;
794 fl2.d = a2;
796 if (!fl1.ll || !fl2.ll) {
797 fl1.d = 0;
798 goto test_done;
801 /* compute sign and exponent */
802 sign = SIGND(fl1) ^ SIGND(fl2);
803 exp = EXPD(fl1) - EXCESSD;
804 exp += EXPD(fl2);
806 fl1.ll = MANTD_LL(fl1);
807 fl2.ll = MANTD_LL(fl2);
809 /* the multiply is done as one 31x31 multiply and two 31x21 multiples */
810 result = (fl1.ll >> 21) * (fl2.ll >> 21);
811 result += ((fl1.ll & 0x1FFFFF) * (fl2.ll >> 21)) >> 21;
812 result += ((fl2.ll & 0x1FFFFF) * (fl1.ll >> 21)) >> 21;
814 result >>= 2;
815 if (result & ((long long)1<<61)) {
816 /* round */
817 result += 1<<8;
818 result >>= 9;
819 } else {
820 /* round */
821 result += 1<<7;
822 result >>= 8;
823 exp--;
825 if (result & (HIDDEND_LL<<1)) {
826 result >>= 1;
827 exp++;
830 result &= ~HIDDEND_LL;
832 /* pack up and go home */
833 fl1.ll = PACKD_LL(sign,exp,result);
834 test_done:
835 return (fl1.d);
838 /* divide two doubles */
839 double
840 __divdf3 (double a1, double a2)
842 register union double_long fl1, fl2;
843 register long long mask,result;
844 register int exp, sign;
846 fl1.d = a1;
847 fl2.d = a2;
849 /* subtract exponents */
850 exp = EXPD(fl1) - EXPD(fl2) + EXCESSD;
852 /* compute sign */
853 sign = SIGND(fl1) ^ SIGND(fl2);
855 /* numerator zero??? */
856 if (fl1.ll == 0) {
857 /* divide by zero??? */
858 if (fl2.ll == 0)
859 fl1.ll = ((unsigned long long)1<<63)-1; /* NaN */
860 else
861 fl1.ll = 0;
862 goto test_done;
865 /* return +Inf or -Inf */
866 if (fl2.ll == 0) {
867 fl1.ll = PACKD_LL(SIGND(fl1),2047,0);
868 goto test_done;
872 /* now get mantissas */
873 fl1.ll = MANTD_LL(fl1);
874 fl2.ll = MANTD_LL(fl2);
876 /* this assures we have 54 bits of precision in the end */
877 if (fl1.ll < fl2.ll) {
878 fl1.ll <<= 1;
879 exp--;
882 /* now we perform repeated subtraction of fl2.ll from fl1.ll */
883 mask = (long long)1<<53;
884 result = 0;
885 while (mask) {
886 if (fl1.ll >= fl2.ll)
888 result |= mask;
889 fl1.ll -= fl2.ll;
891 fl1.ll <<= 1;
892 mask >>= 1;
895 /* round */
896 result += 1;
898 /* normalize down */
899 exp++;
900 result >>= 1;
902 result &= ~HIDDEND_LL;
904 /* pack up and go home */
905 fl1.ll = PACKD_LL(sign, exp, result);
907 test_done:
908 return (fl1.d);
912 __gtdf2 (double a1, double a2)
914 return __cmpdf2 ((float) a1, (float) a2) > 0;
918 __gedf2 (double a1, double a2)
920 return (__cmpdf2 ((float) a1, (float) a2) >= 0) - 1;
924 __ltdf2 (double a1, double a2)
926 return - (__cmpdf2 ((float) a1, (float) a2) < 0);
930 __ledf2 (double a1, double a2)
932 return __cmpdf2 ((float) a1, (float) a2) > 0;
936 __eqdf2 (double a1, double a2)
938 return *(long long *) &a1 == *(long long *) &a2;
942 __nedf2 (double a1, double a2)
944 return *(long long *) &a1 != *(long long *) &a2;