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)
57 #define EXP(fp) (((fp) >> 23L) & 0xFF)
58 #define MANT(fp) (((fp) & 0x7FFFFFL) | HIDDEN)
59 #define PACK(s,e,m) ((s) | ((e) << 23L) | (m))
61 /* the following deal with IEEE double-precision numbers */
63 #define HIDDEND (1L << 20L)
65 #define EXPDMASK 0x7FFL
66 #define EXPD(fp) (((fp.l.upper) >> 20L) & 0x7FFL)
67 #define SIGND(fp) ((fp.l.upper) & SIGNBIT)
68 #define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
70 #define MANTDMASK 0xFFFFFL /* mask of upper part */
72 /* the following deal with IEEE extended-precision numbers */
73 #define EXCESSX 16382L
74 #define HIDDENX (1L << 31L)
76 #define EXPXMASK 0x7FFF
77 #define EXPX(fp) (((fp.l.upper) >> 16) & EXPXMASK)
78 #define SIGNX(fp) ((fp.l.upper) & SIGNBIT)
79 #define MANTXMASK 0x7FFFFFFFL /* mask of upper part */
95 union long_double_long
101 unsigned long middle;
109 __unordsf2(float a, float b)
114 if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0)
117 if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0)
123 __unorddf2(double a, double b)
125 union double_long dl;
128 if (EXPD(dl) == EXPDMASK
129 && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0))
132 if (EXPD(dl) == EXPDMASK
133 && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0))
138 /* convert unsigned int to double */
140 __floatunsidf (unsigned long a1)
142 long exp = 32 + EXCESSD;
143 union double_long dl;
147 dl.l.upper = dl.l.lower = 0;
151 while (a1 < 0x2000000L)
157 while (a1 < 0x80000000L)
163 /* pack up and go home */
164 dl.l.upper = exp << 20L;
165 dl.l.upper |= (a1 >> 11L) & ~HIDDEND;
166 dl.l.lower = a1 << 21L;
171 /* convert int to double */
173 __floatsidf (long a1)
175 long sign = 0, exp = 31 + EXCESSD;
176 union double_long dl;
180 dl.l.upper = dl.l.lower = 0;
187 a1 = (long)-(unsigned long)a1;
190 dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L);
196 while (a1 < 0x1000000L)
202 while (a1 < 0x40000000L)
208 /* pack up and go home */
210 dl.l.upper |= exp << 20L;
211 dl.l.upper |= (a1 >> 10L) & ~HIDDEND;
212 dl.l.lower = a1 << 22L;
217 /* convert unsigned int to float */
219 __floatunsisf (unsigned long l)
221 double foo = __floatunsidf (l);
225 /* convert int to float */
229 double foo = __floatsidf (l);
233 /* convert float to double */
235 __extendsfdf2 (float a1)
237 register union float_long fl1;
238 register union double_long dl;
244 dl.l.upper = SIGN (fl1.l);
245 if ((fl1.l & ~SIGNBIT) == 0)
252 mant = MANT (fl1.l) & ~HIDDEN;
257 while (!(mant & HIDDEN))
264 exp = exp - EXCESS + EXCESSD;
265 dl.l.upper |= exp << 20;
266 dl.l.upper |= mant >> 3;
267 dl.l.lower = mant << 29;
272 /* convert double to float */
274 __truncdfsf2 (double a1)
278 register union float_long fl;
279 register union double_long dl1;
285 if ((dl1.l.upper & ~SIGNBIT) == 0 && !dl1.l.lower)
291 exp = EXPD (dl1) - EXCESSD + EXCESS;
293 sticky = dl1.l.lower & ((1 << 22) - 1);
295 /* shift double mantissa 6 bits so we can round */
296 sticky |= mant & ((1 << 6) - 1);
299 /* Check for underflow and denormals. */
309 sticky |= mant & ((1 << (1 - exp)) - 1);
317 if ((mant & 1) && (sticky || (mant & 2)))
319 int rounding = exp ? 2 : 1;
323 /* did the round overflow? */
324 if (mant >= (HIDDEN << rounding))
335 /* pack up and go home */
336 fl.l = PACK (SIGND (dl1), exp, mant);
340 /* convert double to int */
342 __fixdfsi (double a1)
344 register union double_long dl1;
350 if (!dl1.l.upper && !dl1.l.lower)
353 exp = EXPD (dl1) - EXCESSD - 31;
358 /* Return largest integer. */
359 return SIGND (dl1) ? 0x80000000L : 0x7fffffffL;
365 /* shift down until exp = 0 */
369 return (SIGND (dl1) ? -l : l);
372 /* convert float to int */
377 return __fixdfsi (foo);
382 /* We do not need these routines for coldfire, as it has no extended
384 #if !defined (__mcoldfire__)
386 /* Primitive extended precision floating point support.
388 We assume all numbers are normalized, don't do any rounding, etc. */
390 /* Prototypes for the above in case we use them. */
391 double __floatunsidf (unsigned long);
392 double __floatsidf (long);
393 float __floatsisf (long);
394 double __extendsfdf2 (float);
395 float __truncdfsf2 (double);
396 long __fixdfsi (double);
397 long __fixsfsi (float);
400 __unordxf2(long double a, long double b)
402 union long_double_long ldl;
405 if (EXPX(ldl) == EXPXMASK
406 && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0))
409 if (EXPX(ldl) == EXPXMASK
410 && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0))
415 /* convert double to long double */
417 __extenddfxf2 (double d)
419 register union double_long dl;
420 register union long_double_long ldl;
424 /*printf ("dfxf in: %g\n", d);*/
426 ldl.l.upper = SIGND (dl);
427 if ((dl.l.upper & ~SIGNBIT) == 0 && !dl.l.lower)
434 exp = EXPD (dl) - EXCESSD + EXCESSX;
435 ldl.l.upper |= exp << 16;
436 ldl.l.middle = HIDDENX;
437 /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
438 ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
439 /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
440 ldl.l.middle |= dl.l.lower >> (1 + 20);
441 /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */
442 ldl.l.lower = dl.l.lower << (32 - 21);
444 /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/
448 /* convert long double to double */
450 __truncxfdf2 (long double ld)
453 register union double_long dl;
454 register union long_double_long ldl;
457 /*printf ("xfdf in: %s\n", dumpxf (ld));*/
459 dl.l.upper = SIGNX (ldl);
460 if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower)
466 exp = EXPX (ldl) - EXCESSX + EXCESSD;
467 /* ??? quick and dirty: keep `exp' sane */
470 dl.l.upper |= exp << (32 - (EXPDBITS + 1));
471 /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
472 dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
473 dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));
474 dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);
476 /*printf ("xfdf out: %g\n", dl.d);*/
480 /* convert a float to a long double */
482 __extendsfxf2 (float f)
484 long double foo = __extenddfxf2 (__extendsfdf2 (f));
488 /* convert a long double to a float */
490 __truncxfsf2 (long double ld)
492 float foo = __truncdfsf2 (__truncxfdf2 (ld));
496 /* convert an int to a long double */
500 double foo = __floatsidf (l);
504 /* convert an unsigned int to a long double */
506 __floatunsixf (unsigned long l)
508 double foo = __floatunsidf (l);
512 /* convert a long double to an int */
514 __fixxfsi (long double ld)
516 long foo = __fixdfsi ((double) ld);
520 /* The remaining provide crude math support by working in double precision. */
523 __addxf3 (long double x1, long double x2)
525 return (double) x1 + (double) x2;
529 __subxf3 (long double x1, long double x2)
531 return (double) x1 - (double) x2;
535 __mulxf3 (long double x1, long double x2)
537 return (double) x1 * (double) x2;
541 __divxf3 (long double x1, long double x2)
543 return (double) x1 / (double) x2;
547 __negxf2 (long double x1)
549 return - (double) x1;
553 __cmpxf2 (long double x1, long double x2)
555 return __cmpdf2 ((double) x1, (double) x2);
559 __eqxf2 (long double x1, long double x2)
561 return __cmpdf2 ((double) x1, (double) x2);
565 __nexf2 (long double x1, long double x2)
567 return __cmpdf2 ((double) x1, (double) x2);
571 __ltxf2 (long double x1, long double x2)
573 return __cmpdf2 ((double) x1, (double) x2);
577 __lexf2 (long double x1, long double x2)
579 return __cmpdf2 ((double) x1, (double) x2);
583 __gtxf2 (long double x1, long double x2)
585 return __cmpdf2 ((double) x1, (double) x2);
589 __gexf2 (long double x1, long double x2)
591 return __cmpdf2 ((double) x1, (double) x2);
594 #endif /* !__mcoldfire__ */
595 #endif /* EXTFLOAT */