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
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.
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 */
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 */
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) | \
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 */
102 __addsf3 (float a1
, float a2
)
104 register long mant1
, mant2
;
105 register union float_long fl1
, fl2
;
106 register int exp1
, exp2
;
112 /* check for zero args */
123 if (exp1
> exp2
+ 25)
125 if (exp2
> exp1
+ 25) {
130 /* do everything in excess precision so's we can round later */
131 mant1
= MANT (fl1
.l
) << 6;
132 mant2
= MANT (fl2
.l
) << 6;
141 mant2
>>= exp1
- exp2
;
145 mant1
>>= exp2
- exp1
;
161 while (!(mant1
& 0xE0000000))
167 /* normalize down? */
168 if (mant1
& (1 << 30))
175 mant1
+= (mant1
& 0x40) ? 0x20 : 0x1F;
177 /* normalize down? */
178 if (mant1
& (1 << 30))
184 /* lose extra precision */
187 /* turn off hidden bit */
190 /* pack up and go home */
191 fl1
.l
= PACK (sign
, exp1
, mant1
);
196 /* subtract two floats */
198 __subsf3 (float a1
, float a2
)
200 register union float_long fl1
, fl2
;
205 /* check for zero args */
211 /* twiddle sign bit and add */
213 return __addsf3 (a1
, fl2
.f
);
216 /* compare two floats */
218 __cmpsf2 (float a1
, float a2
)
220 register union float_long fl1
, fl2
;
225 if (SIGN (fl1
.l
) && SIGN (fl2
.l
))
237 /* multiply two floats */
239 __mulsf3 (float a1
, float a2
)
241 register union float_long fl1
, fl2
;
242 register unsigned long result
;
249 if (!fl1
.l
|| !fl2
.l
) {
254 /* compute sign and exponent */
255 sign
= SIGN (fl1
.l
) ^ SIGN (fl2
.l
);
256 exp
= EXP (fl1
.l
) - EXCESS
;
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;
268 if (result
& 0x20000000)
281 if (result
& (HIDDEN
<<1)) {
288 /* pack up and go home */
289 fl1
.l
= PACK (sign
, exp
, result
);
294 /* divide two floats */
296 __divsf3 (float a1
, float a2
)
298 register union float_long fl1
, fl2
;
301 register int exp
, sign
;
306 /* subtract exponents */
307 exp
= EXP (fl1
.l
) - EXP (fl2
.l
) + EXCESS
;
310 sign
= SIGN (fl1
.l
) ^ SIGN (fl2
.l
);
312 /* divide by zero??? */
314 /* return NaN or -NaN */
315 return (sign
? 0xFFFFFFFF : 0x7FFFFFFF);
317 /* numerator zero??? */
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 */
332 /* now we perform repeated subtraction of fl2.l from fl1.l */
355 /* pack up and go home */
356 fl1
.l
= PACK (sign
, exp
, result
);
360 /* convert int to double */
362 __floatsidf (register long a1
)
364 register int sign
= 0, exp
= 31 + EXCESSD
;
365 union double_long dl
;
369 dl
.l
.upper
= dl
.l
.lower
= 0;
379 while (a1
< 0x1000000)
385 while (a1
< 0x40000000)
391 /* pack up and go home */
393 dl
.l
.upper
|= exp
<< 20;
394 dl
.l
.upper
|= (a1
>> 10) & ~HIDDEND
;
395 dl
.l
.lower
= a1
<< 22;
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;
411 dl
.l
.upper
= SIGNBIT
;
415 while (a1
< (long long)1<<54) {
419 while (a1
< (long long)1<<62) {
424 /* pack up and go home */
425 dl
.ll
|= (a1
>> 10) & ~HIDDEND_LL
;
426 dl
.l
.upper
|= exp
<< 20;
432 __floatsisf (register long a1
)
434 (float)__floatsidf(a1
);
438 __floatdisf (register long long a1
)
440 (float)__floatdidf(a1
);
447 register union float_long fl1
;
457 /* negate a double */
461 register union double_long dl1
;
465 if (!dl1
.l
.upper
&& !dl1
.l
.lower
)
468 dl1
.l
.upper
^= SIGNBIT
;
472 /* convert float to double */
474 __extendsfdf2 (float a1
)
476 register union float_long fl1
;
477 register union double_long dl
;
484 dl
.l
.upper
= dl
.l
.lower
= 0;
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;
497 /* convert double to float */
499 __truncdfsf2 (double a1
)
503 register union float_long fl
;
504 register union double_long dl1
;
508 if (!dl1
.l
.upper
&& !dl1
.l
.lower
)
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 */
520 /* did the round overflow? */
521 if (mant
& 0xFE000000)
529 /* pack up and go home */
530 fl
.l
= PACK (SIGND (dl1
), exp
, mant
);
534 /* compare two doubles */
536 __cmpdf2 (double a1
, double a2
)
538 register union double_long dl1
, dl2
;
543 if (SIGND (dl1
) && SIGND (dl2
))
545 dl1
.l
.upper
^= SIGNBIT
;
546 dl2
.l
.upper
^= SIGNBIT
;
548 if (dl1
.l
.upper
< dl2
.l
.upper
)
550 if (dl1
.l
.upper
> dl2
.l
.upper
)
552 if (dl1
.l
.lower
< dl2
.l
.lower
)
554 if (dl1
.l
.lower
> dl2
.l
.lower
)
559 /* convert double to int */
561 __fixdfsi (double a1
)
563 register union double_long dl1
;
569 if (!dl1
.l
.upper
&& !dl1
.l
.lower
)
572 exp
= EXPD (dl1
) - EXCESSD
- 31;
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
)
584 return (SIGND (dl1
) ? -l
: l
);
587 /* convert double to int */
589 __fixdfdi (double a1
)
591 register union double_long dl1
;
593 register long long l
;
597 if (!dl1
.l
.upper
&& !dl1
.l
.lower
)
600 exp
= EXPD (dl1
) - EXCESSD
- 64;
604 l
= (long long)1<<63;
610 /* shift down until exp = 0 or l = 0 */
611 if (exp
< 0 && exp
> -64 && l
)
616 return (SIGND (dl1
) ? -l
: l
);
619 /* convert double to unsigned int */
621 __fixunsdfsi (double a1
)
623 register union double_long dl1
;
625 register unsigned long l
;
629 if (!dl1
.l
.upper
&& !dl1
.l
.lower
)
632 exp
= EXPD (dl1
) - EXCESSD
- 32;
633 l
= (((((dl1
.l
.upper
) & 0xFFFFF) | HIDDEND
) << 11) | (dl1
.l
.lower
>> 21));
636 return (0xFFFFFFFFul
); /* largest integer */
638 /* shift down until exp = 0 or l = 0 */
639 if (exp
< 0 && exp
> -32 && l
)
647 /* convert double to unsigned int */
649 __fixunsdfdi (double a1
)
651 register union double_long dl1
;
653 register unsigned long long l
;
660 exp
= EXPD (dl1
) - EXCESSD
- 64;
665 return (unsigned long long)-1;
667 /* shift down until exp = 0 or l = 0 */
668 if (exp
< 0 && exp
> -64 && l
)
678 __adddf3 (double a1
, double a2
)
680 register long long mant1
, mant2
;
681 register union double_long fl1
, fl2
;
682 register int exp1
, exp2
;
688 /* check for zero args */
699 if (exp1
> exp2
+ 54)
701 if (exp2
> exp1
+ 54) {
706 /* do everything in excess precision so's we can round later */
707 mant1
= MANTD_LL(fl1
) << 9;
708 mant2
= MANTD_LL(fl2
) << 9;
716 mant2
>>= exp1
- exp2
;
718 mant1
>>= exp2
- exp1
;
732 while (!(mant1
& ((long long)7<<61))) {
737 /* normalize down? */
738 if (mant1
& ((long long)3<<62)) {
744 mant1
+= (mant1
& (1<<9)) ? (1<<8) : ((1<<8)-1);
746 /* normalize down? */
747 if (mant1
& ((long long)3<<62)) {
752 /* lose extra precision */
755 /* turn off hidden bit */
756 mant1
&= ~HIDDEND_LL
;
758 /* pack up and go home */
759 fl1
.ll
= PACKD_LL(sign
,exp1
,mant1
);
765 /* subtract two doubles */
767 __subdf3 (double a1
, double a2
)
769 register union double_long fl1
, fl2
;
774 /* check for zero args */
777 /* twiddle sign bit and add */
778 fl2
.l
.upper
^= SIGNBIT
;
781 return __adddf3 (a1
, fl2
.d
);
784 /* multiply two doubles */
786 __muldf3 (double a1
, double a2
)
788 register union double_long fl1
, fl2
;
789 register unsigned long long result
;
796 if (!fl1
.ll
|| !fl2
.ll
) {
801 /* compute sign and exponent */
802 sign
= SIGND(fl1
) ^ SIGND(fl2
);
803 exp
= EXPD(fl1
) - EXCESSD
;
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;
815 if (result
& ((long long)1<<61)) {
825 if (result
& (HIDDEND_LL
<<1)) {
830 result
&= ~HIDDEND_LL
;
832 /* pack up and go home */
833 fl1
.ll
= PACKD_LL(sign
,exp
,result
);
838 /* divide two doubles */
840 __divdf3 (double a1
, double a2
)
842 register union double_long fl1
, fl2
;
843 register long long mask
,result
;
844 register int exp
, sign
;
849 /* subtract exponents */
850 exp
= EXPD(fl1
) - EXPD(fl2
) + EXCESSD
;
853 sign
= SIGND(fl1
) ^ SIGND(fl2
);
855 /* numerator zero??? */
857 /* divide by zero??? */
859 fl1
.ll
= ((unsigned long long)1<<63)-1; /* NaN */
865 /* return +Inf or -Inf */
867 fl1
.ll
= PACKD_LL(SIGND(fl1
),2047,0);
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
) {
882 /* now we perform repeated subtraction of fl2.ll from fl1.ll */
883 mask
= (long long)1<<53;
886 if (fl1
.ll
>= fl2
.ll
)
902 result
&= ~HIDDEND_LL
;
904 /* pack up and go home */
905 fl1
.ll
= PACKD_LL(sign
, exp
, result
);
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
;