home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / gcc / config / m68k / fpgnulib.c < prev    next >
C/C++ Source or Header  |  1995-03-10  |  10KB  |  443 lines

  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.asm.
  4.  
  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.  */
  8.  
  9. /*
  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?).
  17. **
  18. ** Pat Wood
  19. ** Pipeline Associates, Inc.
  20. ** pipeline!phw@motown.com or
  21. ** sun!pipeline!phw or
  22. ** uunet!motown!pipeline!phw
  23. **
  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
  29. */
  30.  
  31. /*
  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.
  43. **
  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.
  47. **
  48. ** I have tested this only on a 68030 workstation and 386/ix integrated
  49. ** in with -msoft-float.
  50. */
  51.  
  52. /* the following deal with IEEE single-precision numbers */
  53. #define EXCESS        126L
  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))
  60.  
  61. /* the following deal with IEEE double-precision numbers */
  62. #define EXCESSD        1022
  63. #define HIDDEND        (1L << 20L)
  64. #define EXPDBITS    11
  65. #define EXPDMASK    0x7FF
  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) | \
  69.                 (fp.l.lower >> 22))
  70. #define MANTDMASK    0xFFFFF /* mask of upper part */
  71.  
  72. /* the following deal with IEEE extended-precision numbers */
  73. #define EXCESSX        16382
  74. #define HIDDENX        (1L << 31L)
  75. #define EXPXBITS    15
  76. #define EXPXMASK    0x7FFF
  77. #define EXPX(fp)    (((fp.l.upper) >> 16) & EXPXMASK)
  78. #define SIGNX(fp)    ((fp.l.upper) & SIGNBIT)
  79. #define MANTXMASK    0x7FFFFFFF /* mask of upper part */
  80.  
  81. union double_long 
  82. {
  83.   double d;
  84.   struct {
  85.       long upper;
  86.       unsigned long lower;
  87.     } l;
  88. };
  89.  
  90. union float_long {
  91.   float f;
  92.   long l;
  93. };
  94.  
  95. union long_double_long
  96. {
  97.   long double ld;
  98.   struct
  99.     {
  100.       long upper;
  101.       unsigned long middle;
  102.       unsigned long lower;
  103.     } l;
  104. };
  105.  
  106. #ifndef EXTFLOAT
  107.  
  108. /* convert int to double */
  109. double
  110. __floatsidf (int a1)
  111. {
  112.   long sign = 0, exp = 31 + EXCESSD;
  113.   union double_long dl;
  114.  
  115.   if (!a1)
  116.     {
  117.       dl.l.upper = dl.l.lower = 0;
  118.       return dl.d;
  119.     }
  120.  
  121.   if (a1 < 0)
  122.     {
  123.       sign = SIGNBIT;
  124.       a1 = -a1;
  125.       if (a1 < 0)
  126.     {
  127.       dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L);
  128.       dl.l.lower = 0;
  129.       return dl.d;
  130.         }
  131.     }
  132.  
  133.   while (a1 < 0x1000000)
  134.     {
  135.       a1 <<= 4;
  136.       exp -= 4;
  137.     }
  138.  
  139.   while (a1 < 0x40000000)
  140.     {
  141.       a1 <<= 1;
  142.       exp--;
  143.     }
  144.  
  145.   /* pack up and go home */
  146.   dl.l.upper = sign;
  147.   dl.l.upper |= exp << 20L;
  148.   dl.l.upper |= (a1 >> 10L) & ~HIDDEND;
  149.   dl.l.lower = a1 << 22L;
  150.  
  151.   return dl.d;
  152. }
  153.  
  154. /* convert int to float */
  155. float
  156. __floatsisf (int l)
  157. {
  158.   double foo = __floatsidf (l);
  159.   return foo;
  160. }
  161.  
  162. /* convert float to double */
  163. double
  164. __extendsfdf2 (float a1)
  165. {
  166.   register union float_long fl1;
  167.   register union double_long dl;
  168.   register long exp;
  169.  
  170.   fl1.f = a1;
  171.  
  172.   if (!fl1.l)
  173.     {
  174.       dl.l.upper = dl.l.lower = 0;
  175.       return dl.d;
  176.     }
  177.  
  178.   dl.l.upper = SIGN (fl1.l);
  179.   exp = EXP (fl1.l) - EXCESS + EXCESSD;
  180.   dl.l.upper |= exp << 20;
  181.   dl.l.upper |= (MANT (fl1.l) & ~HIDDEN) >> 3;
  182.   dl.l.lower = MANT (fl1.l) << 29;
  183.     
  184.   return dl.d;
  185. }
  186.  
  187. /* convert double to float */
  188. float
  189. __truncdfsf2 (double a1)
  190. {
  191.   register long exp;
  192.   register long mant;
  193.   register union float_long fl;
  194.   register union double_long dl1;
  195.  
  196.   dl1.d = a1;
  197.  
  198.   if (!dl1.l.upper && !dl1.l.lower)
  199.     return 0;
  200.  
  201.   exp = EXPD (dl1) - EXCESSD + EXCESS;
  202.  
  203.   /* shift double mantissa 6 bits so we can round */
  204.   mant = MANTD (dl1) >> 6;
  205.  
  206.   /* now round and shift down */
  207.   mant += 1;
  208.   mant >>= 1;
  209.  
  210.   /* did the round overflow? */
  211.   if (mant & 0xFF000000)
  212.     {
  213.       mant >>= 1;
  214.       exp++;
  215.     }
  216.  
  217.   mant &= ~HIDDEN;
  218.  
  219.   /* pack up and go home */
  220.   fl.l = PACK (SIGND (dl1), exp, mant);
  221.   return (fl.f);
  222. }
  223.  
  224. /* convert double to int */
  225. int
  226. __fixdfsi (double a1)
  227. {
  228.   register union double_long dl1;
  229.   register long exp;
  230.   register long l;
  231.  
  232.   dl1.d = a1;
  233.  
  234.   if (!dl1.l.upper && !dl1.l.lower) 
  235.     return 0;
  236.  
  237.   exp = EXPD (dl1) - EXCESSD - 31;
  238.   l = MANTD (dl1);
  239.  
  240.   if (exp > 0) 
  241.     {
  242.       /* Return largest integer.  */
  243.       return SIGND (dl1) ? 0x80000000 : 0x7fffffff;
  244.     }
  245.  
  246.   if (exp <= -32)
  247.     return 0;
  248.  
  249.   /* shift down until exp = 0 */
  250.   if (exp < 0)
  251.     l >>= -exp;
  252.  
  253.   return (SIGND (dl1) ? -l : l);
  254. }
  255.  
  256. /* convert float to int */
  257. int
  258. __fixsfsi (float a1)
  259. {
  260.   double foo = a1;
  261.   return __fixdfsi (foo);
  262. }
  263.  
  264. #else /* EXTFLOAT */
  265.  
  266. /* Primitive extended precision floating point support.
  267.  
  268.    We assume all numbers are normalized, don't do any rounding, etc.  */
  269.  
  270. /* Prototypes for the above in case we use them.  */
  271. double __floatsidf (int);
  272. float __floatsisf (int);
  273. double __extendsfdf2 (float);
  274. float __truncdfsf2 (double);
  275. int __fixdfsi (double);
  276. int __fixsfsi (float);
  277.  
  278. /* convert double to long double */
  279. long double
  280. __extenddfxf2 (double d)
  281. {
  282.   register union double_long dl;
  283.   register union long_double_long ldl;
  284.   register long exp;
  285.  
  286.   dl.d = d;
  287.   /*printf ("dfxf in: %g\n", d);*/
  288.  
  289.   if (!dl.l.upper && !dl.l.lower)
  290.     return 0;
  291.  
  292.   ldl.l.upper = SIGND (dl);
  293.   exp = EXPD (dl) - EXCESSD + EXCESSX;
  294.   ldl.l.upper |= exp << 16;
  295.   ldl.l.middle = HIDDENX;
  296.   /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
  297.   ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
  298.   /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
  299.   ldl.l.middle |= dl.l.lower >> (1 + 20);
  300.   /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */
  301.   ldl.l.lower = dl.l.lower << (32 - 21);
  302.  
  303.   /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/
  304.   return ldl.ld;
  305. }
  306.  
  307. /* convert long double to double */
  308. double
  309. __truncxfdf2 (long double ld)
  310. {
  311.   register long exp;
  312.   register union double_long dl;
  313.   register union long_double_long ldl;
  314.  
  315.   ldl.ld = ld;
  316.   /*printf ("xfdf in: %s\n", dumpxf (ld));*/
  317.  
  318.   if (!ldl.l.upper && !ldl.l.middle && !ldl.l.lower)
  319.     return 0;
  320.  
  321.   exp = EXPX (ldl) - EXCESSX + EXCESSD;
  322.   /* ??? quick and dirty: keep `exp' sane */
  323.   if (exp >= EXPDMASK)
  324.     exp = EXPDMASK - 1;
  325.   dl.l.upper = SIGNX (ldl);
  326.   dl.l.upper |= exp << (32 - (EXPDBITS + 1));
  327.   /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
  328.   dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
  329.   dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));
  330.   dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);
  331.  
  332.   /*printf ("xfdf out: %g\n", dl.d);*/
  333.   return dl.d;
  334. }
  335.  
  336. /* convert a float to a long double */
  337. long double
  338. __extendsfxf2 (float f)
  339. {
  340.   long double foo = __extenddfxf2 (__extendsfdf2 (f));
  341.   return foo;
  342. }
  343.  
  344. /* convert a long double to a float */
  345. float
  346. __truncxfsf2 (long double ld)
  347. {
  348.   float foo = __truncdfsf2 (__truncxfdf2 (ld));
  349.   return foo;
  350. }
  351.  
  352. /* convert an int to a long double */
  353. long double
  354. __floatsixf (int l)
  355. {
  356.   double foo = __floatsidf (l);
  357.   return foo;
  358. }
  359.  
  360. /* convert a long double to an int */
  361. int
  362. __fixxfsi (long double ld)
  363. {
  364.   int foo = __fixdfsi ((double) ld);
  365.   return foo;
  366. }
  367.  
  368. /* The remaining provide crude math support by working in double precision.  */
  369.  
  370. long double
  371. __addxf3 (long double x1, long double x2)
  372. {
  373.   return (double) x1 + (double) x2;
  374. }
  375.  
  376. long double
  377. __subxf3 (long double x1, long double x2)
  378. {
  379.   return (double) x1 - (double) x2;
  380. }
  381.  
  382. long double
  383. __mulxf3 (long double x1, long double x2)
  384. {
  385.   return (double) x1 * (double) x2;
  386. }
  387.  
  388. long double
  389. __divxf3 (long double x1, long double x2)
  390. {
  391.   return (double) x1 / (double) x2;
  392. }
  393.  
  394. long double
  395. __negxf2 (long double x1)
  396. {
  397.   return - (double) x1;
  398. }
  399.  
  400. long
  401. __cmpxf2 (long double x1, long double x2)
  402. {
  403.   return __cmpdf2 ((double) x1, (double) x2);
  404. }
  405.  
  406. long
  407. __eqxf2 (long double x1, long double x2)
  408. {
  409.   return __cmpdf2 ((double) x1, (double) x2);
  410. }
  411.  
  412. long
  413. __nexf2 (long double x1, long double x2)
  414. {
  415.   return __cmpdf2 ((double) x1, (double) x2);
  416. }
  417.  
  418. long
  419. __ltxf2 (long double x1, long double x2)
  420. {
  421.   return __cmpdf2 ((double) x1, (double) x2);
  422. }
  423.  
  424. long
  425. __lexf2 (long double x1, long double x2)
  426. {
  427.   return __cmpdf2 ((double) x1, (double) x2);
  428. }
  429.  
  430. long
  431. __gtxf2 (long double x1, long double x2)
  432. {
  433.   return __cmpdf2 ((double) x1, (double) x2);
  434. }
  435.  
  436. long
  437. __gexf2 (long double x1, long double x2)
  438. {
  439.   return __cmpdf2 ((double) x1, (double) x2);
  440. }
  441.  
  442. #endif /* EXTFLOAT */
  443.