1 /* This is a stripped down version of floatlib.c. It supplies only those
2 functions which exist in libgcc, but for which there is not assembly
3 language versions in m68k/lb1sf68.S.
5 It also includes simplistic support for extended floats (by working in
6 double precision). You must compile this file again with -DEXTFLOAT
7 to get this support. */
10 ** gnulib support for software floating point.
11 ** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved.
12 ** Permission is granted to do *anything* you want with this file,
13 ** commercial or otherwise, provided this message remains intact. So there!
14 ** I would appreciate receiving any updates/patches/changes that anyone
15 ** makes, and am willing to be the repository for said changes (am I
16 ** making a big mistake?).
19 ** Pipeline Associates, Inc.
20 ** pipeline!phw@motown.com or
21 ** sun!pipeline!phw or
22 ** uunet!motown!pipeline!phw
24 ** 05/01/91 -- V1.0 -- first release to gcc mailing lists
25 ** 05/04/91 -- V1.1 -- added float and double prototypes and return values
26 ** -- fixed problems with adding and subtracting zero
27 ** -- fixed rounding in truncdfsf2
28 ** -- fixed SWAP define and tested on 386
32 ** The following are routines that replace the gnulib soft floating point
33 ** routines that are called automatically when -msoft-float is selected.
34 ** The support single and double precision IEEE format, with provisions
35 ** for byte-swapped machines (tested on 386). Some of the double-precision
36 ** routines work at full precision, but most of the hard ones simply punt
37 ** and call the single precision routines, producing a loss of accuracy.
38 ** long long support is not assumed or included.
39 ** Overall accuracy is close to IEEE (actually 68882) for single-precision
40 ** arithmetic. I think there may still be a 1 in 1000 chance of a bit
41 ** being rounded the wrong way during a multiply. I'm not fussy enough to
42 ** bother with it, but if anyone is, knock yourself out.
44 ** Efficiency has only been addressed where it was obvious that something
45 ** would make a big difference. Anyone who wants to do this right for
46 ** best speed should go in and rewrite in assembler.
48 ** I have tested this only on a 68030 workstation and 386/ix integrated
49 ** in with -msoft-float.
52 /* the following deal with IEEE single-precision numbers */
54 #define SIGNBIT 0x80000000L
55 #define HIDDEN (1L << 23L)
56 #define SIGN(fp) ((fp) & SIGNBIT)
58 #define EXP(fp) (((fp) >> 23L) & 0xFF)
59 #define MANT(fp) (((fp) & 0x7FFFFFL) | HIDDEN)
60 #define PACK(s,e,m) ((s) | ((e) << 23L) | (m))
62 /* the following deal with IEEE double-precision numbers */
64 #define HIDDEND (1L << 20L)
66 #define EXPDMASK 0x7FFL
67 #define EXPD(fp) (((fp.l.upper) >> 20L) & 0x7FFL)
68 #define SIGND(fp) ((fp.l.upper) & SIGNBIT)
69 #define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
71 #define MANTDMASK 0xFFFFFL /* mask of upper part */
73 /* the following deal with IEEE extended-precision numbers */
74 #define EXCESSX 16382L
75 #define HIDDENX (1L << 31L)
77 #define EXPXMASK 0x7FFF
78 #define EXPX(fp) (((fp.l.upper) >> 16) & EXPXMASK)
79 #define SIGNX(fp) ((fp.l.upper) & SIGNBIT)
80 #define MANTXMASK 0x7FFFFFFFL /* mask of upper part */
96 union long_double_long
102 unsigned long middle
;
110 __unordsf2(float a
, float b
)
115 if (EXP(fl
.l
) == EXP(~0u) && (MANT(fl
.l
) & ~HIDDEN
) != 0)
118 if (EXP(fl
.l
) == EXP(~0u) && (MANT(fl
.l
) & ~HIDDEN
) != 0)
124 __unorddf2(double a
, double b
)
126 union double_long dl
;
129 if (EXPD(dl
) == EXPDMASK
130 && ((dl
.l
.upper
& MANTDMASK
) != 0 || dl
.l
.lower
!= 0))
133 if (EXPD(dl
) == EXPDMASK
134 && ((dl
.l
.upper
& MANTDMASK
) != 0 || dl
.l
.lower
!= 0))
139 /* convert unsigned int to double */
141 __floatunsidf (unsigned long a1
)
143 long exp
= 32 + EXCESSD
;
144 union double_long dl
;
148 dl
.l
.upper
= dl
.l
.lower
= 0;
152 while (a1
< 0x2000000L
)
158 while (a1
< 0x80000000L
)
164 /* pack up and go home */
165 dl
.l
.upper
= exp
<< 20L;
166 dl
.l
.upper
|= (a1
>> 11L) & ~HIDDEND
;
167 dl
.l
.lower
= a1
<< 21L;
172 /* convert int to double */
174 __floatsidf (long a1
)
176 long sign
= 0, exp
= 31 + EXCESSD
;
177 union double_long dl
;
181 dl
.l
.upper
= dl
.l
.lower
= 0;
188 a1
= (long)-(unsigned long)a1
;
191 dl
.l
.upper
= SIGNBIT
| ((32 + EXCESSD
) << 20L);
197 while (a1
< 0x1000000L
)
203 while (a1
< 0x40000000L
)
209 /* pack up and go home */
211 dl
.l
.upper
|= exp
<< 20L;
212 dl
.l
.upper
|= (a1
>> 10L) & ~HIDDEND
;
213 dl
.l
.lower
= a1
<< 22L;
218 /* convert unsigned int to float */
220 __floatunsisf (unsigned long l
)
222 double foo
= __floatunsidf (l
);
226 /* convert int to float */
230 double foo
= __floatsidf (l
);
234 /* convert float to double */
236 __extendsfdf2 (float a1
)
238 register union float_long fl1
;
239 register union double_long dl
;
245 dl
.l
.upper
= SIGN (fl1
.l
);
246 if ((fl1
.l
& ~SIGNBIT
) == 0)
253 mant
= MANT (fl1
.l
) & ~HIDDEN
;
258 while (!(mant
& HIDDEN
))
265 exp
= exp
- EXCESS
+ EXCESSD
;
266 /* Handle inf and NaN */
267 if (exp
== EXPMASK
- EXCESS
+ EXCESSD
)
269 dl
.l
.upper
|= exp
<< 20;
270 dl
.l
.upper
|= mant
>> 3;
271 dl
.l
.lower
= mant
<< 29;
276 /* convert double to float */
278 __truncdfsf2 (double a1
)
282 register union float_long fl
;
283 register union double_long dl1
;
289 if ((dl1
.l
.upper
& ~SIGNBIT
) == 0 && !dl1
.l
.lower
)
295 exp
= EXPD (dl1
) - EXCESSD
+ EXCESS
;
297 sticky
= dl1
.l
.lower
& ((1 << 22) - 1);
299 /* shift double mantissa 6 bits so we can round */
300 sticky
|= mant
& ((1 << 6) - 1);
302 if (exp
== EXPDMASK
- EXCESSD
+ EXCESS
)
305 mant
= (mant
>> 1) | (mant
& 1) | (!!sticky
);
309 /* Check for underflow and denormals. */
319 sticky
|= mant
& ((1 << (1 - exp
)) - 1);
327 if ((mant
& 1) && (sticky
|| (mant
& 2)))
329 int rounding
= exp
? 2 : 1;
333 /* did the round overflow? */
334 if (mant
>= (HIDDEN
<< rounding
))
351 /* pack up and go home */
352 fl
.l
= PACK (SIGND (dl1
), exp
, mant
);
356 /* convert double to int */
358 __fixdfsi (double a1
)
360 register union double_long dl1
;
366 if (!dl1
.l
.upper
&& !dl1
.l
.lower
)
369 exp
= EXPD (dl1
) - EXCESSD
- 31;
374 /* Return largest integer. */
375 return SIGND (dl1
) ? 0x80000000L
: 0x7fffffffL
;
381 /* shift down until exp = 0 */
385 return (SIGND (dl1
) ? -l
: l
);
388 /* convert float to int */
393 return __fixdfsi (foo
);
398 /* We do not need these routines for coldfire, as it has no extended
400 #if !defined (__mcoldfire__)
402 /* Primitive extended precision floating point support.
404 We assume all numbers are normalized, don't do any rounding, etc. */
406 /* Prototypes for the above in case we use them. */
407 double __floatunsidf (unsigned long);
408 double __floatsidf (long);
409 float __floatsisf (long);
410 double __extendsfdf2 (float);
411 float __truncdfsf2 (double);
412 long __fixdfsi (double);
413 long __fixsfsi (float);
414 int __cmpdf2 (double, double);
417 __unordxf2(long double a
, long double b
)
419 union long_double_long ldl
;
422 if (EXPX(ldl
) == EXPXMASK
423 && ((ldl
.l
.middle
& MANTXMASK
) != 0 || ldl
.l
.lower
!= 0))
426 if (EXPX(ldl
) == EXPXMASK
427 && ((ldl
.l
.middle
& MANTXMASK
) != 0 || ldl
.l
.lower
!= 0))
432 /* convert double to long double */
434 __extenddfxf2 (double d
)
436 register union double_long dl
;
437 register union long_double_long ldl
;
441 /*printf ("dfxf in: %g\n", d);*/
443 ldl
.l
.upper
= SIGND (dl
);
444 if ((dl
.l
.upper
& ~SIGNBIT
) == 0 && !dl
.l
.lower
)
451 exp
= EXPD (dl
) - EXCESSD
+ EXCESSX
;
452 /* Check for underflow and denormals. */
462 ldl
.l
.lower
= (ldl
.l
.middle
& MANTXMASK
) >> ((1 - exp
) - 32);
463 ldl
.l
.middle
&= ~MANTXMASK
;
467 ldl
.l
.lower
>>= 1 - exp
;
468 ldl
.l
.lower
|= (ldl
.l
.middle
& MANTXMASK
) << (32 - (1 - exp
));
469 ldl
.l
.middle
= (ldl
.l
.middle
& ~MANTXMASK
) | (ldl
.l
.middle
& MANTXMASK
>> (1 - exp
));
473 /* Handle inf and NaN */
474 if (exp
== EXPDMASK
- EXCESSD
+ EXCESSX
)
476 ldl
.l
.upper
|= exp
<< 16;
477 ldl
.l
.middle
= HIDDENX
;
478 /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
479 ldl
.l
.middle
|= (dl
.l
.upper
& MANTDMASK
) << (31 - 20);
480 /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
481 ldl
.l
.middle
|= dl
.l
.lower
>> (1 + 20);
482 /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */
483 ldl
.l
.lower
= dl
.l
.lower
<< (32 - 21);
485 /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/
489 /* convert long double to double */
491 __truncxfdf2 (long double ld
)
494 register union double_long dl
;
495 register union long_double_long ldl
;
498 /*printf ("xfdf in: %s\n", dumpxf (ld));*/
500 dl
.l
.upper
= SIGNX (ldl
);
501 if ((ldl
.l
.upper
& ~SIGNBIT
) == 0 && !ldl
.l
.middle
&& !ldl
.l
.lower
)
507 exp
= EXPX (ldl
) - EXCESSX
+ EXCESSD
;
508 /* Check for underflow and denormals. */
518 ldl
.l
.lower
= (ldl
.l
.middle
& MANTXMASK
) >> ((1 - exp
) - 32);
519 ldl
.l
.middle
&= ~MANTXMASK
;
523 ldl
.l
.lower
>>= 1 - exp
;
524 ldl
.l
.lower
|= (ldl
.l
.middle
& MANTXMASK
) << (32 - (1 - exp
));
525 ldl
.l
.middle
= (ldl
.l
.middle
& ~MANTXMASK
) | (ldl
.l
.middle
& MANTXMASK
>> (1 - exp
));
529 else if (exp
== EXPXMASK
- EXCESSX
+ EXCESSD
)
532 ldl
.l
.middle
|= ldl
.l
.lower
;
534 else if (exp
>= EXPDMASK
)
540 dl
.l
.upper
|= exp
<< (32 - (EXPDBITS
+ 1));
541 /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
542 dl
.l
.upper
|= (ldl
.l
.middle
& MANTXMASK
) >> (EXPDBITS
+ 1 - 1);
543 dl
.l
.lower
= (ldl
.l
.middle
& MANTXMASK
) << (32 - (EXPDBITS
+ 1 - 1));
544 dl
.l
.lower
|= ldl
.l
.lower
>> (EXPDBITS
+ 1 - 1);
546 /*printf ("xfdf out: %g\n", dl.d);*/
550 /* convert a float to a long double */
552 __extendsfxf2 (float f
)
554 long double foo
= __extenddfxf2 (__extendsfdf2 (f
));
558 /* convert a long double to a float */
560 __truncxfsf2 (long double ld
)
562 float foo
= __truncdfsf2 (__truncxfdf2 (ld
));
566 /* convert an int to a long double */
570 double foo
= __floatsidf (l
);
574 /* convert an unsigned int to a long double */
576 __floatunsixf (unsigned long l
)
578 double foo
= __floatunsidf (l
);
582 /* convert a long double to an int */
584 __fixxfsi (long double a
)
586 union long_double_long ldl
;
593 if (exp
== 0 && ldl
.l
.middle
== 0 && ldl
.l
.lower
== 0)
596 exp
= exp
- EXCESSX
- 63;
600 /* Return largest integer. */
601 return SIGNX (ldl
) ? 0x80000000L
: 0x7fffffffL
;
609 ldl
.l
.lower
= ldl
.l
.middle
>> (-exp
- 32);
613 ldl
.l
.lower
= ldl
.l
.lower
>> -exp
;
614 ldl
.l
.lower
|= ldl
.l
.middle
<< (32 + exp
);
617 return SIGNX (ldl
) ? -ldl
.l
.lower
: ldl
.l
.lower
;
620 /* The remaining provide crude math support by working in double precision. */
623 __addxf3 (long double x1
, long double x2
)
625 return (double) x1
+ (double) x2
;
629 __subxf3 (long double x1
, long double x2
)
631 return (double) x1
- (double) x2
;
635 __mulxf3 (long double x1
, long double x2
)
637 return (double) x1
* (double) x2
;
641 __divxf3 (long double x1
, long double x2
)
643 return (double) x1
/ (double) x2
;
647 __negxf2 (long double x1
)
649 return - (double) x1
;
653 __cmpxf2 (long double x1
, long double x2
)
655 return __cmpdf2 ((double) x1
, (double) x2
);
659 __eqxf2 (long double x1
, long double x2
)
661 return __cmpdf2 ((double) x1
, (double) x2
);
665 __nexf2 (long double x1
, long double x2
)
667 return __cmpdf2 ((double) x1
, (double) x2
);
671 __ltxf2 (long double x1
, long double x2
)
673 return __cmpdf2 ((double) x1
, (double) x2
);
677 __lexf2 (long double x1
, long double x2
)
679 return __cmpdf2 ((double) x1
, (double) x2
);
683 __gtxf2 (long double x1
, long double x2
)
685 return __cmpdf2 ((double) x1
, (double) x2
);
689 __gexf2 (long double x1
, long double x2
)
691 return __cmpdf2 ((double) x1
, (double) x2
);
694 #endif /* !__mcoldfire__ */
695 #endif /* EXTFLOAT */