OSDN Git Service

gcc/ada/
[pf3gnuchains/gcc-fork.git] / gcc / real.c
index 48d9e9e..ec7d56b 100644 (file)
@@ -1,6 +1,6 @@
 /* real.c - software floating point emulation.
    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
    Contributed by Stephen L. Moshier (moshier@world.std.com).
    Re-written by Richard Henderson <rth@redhat.com>
 
@@ -8,7 +8,7 @@
 
    GCC is free software; you can redistribute it and/or modify it under
    the terms of the GNU General Public License as published by the Free
-   Software Foundation; either version 2, or (at your option) any later
+   Software Foundation; either version 3, or (at your option) any later
    version.
 
    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -17,9 +17,8 @@
    for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.  */
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
    have guard digits or rounding, the computation of 10**exp can
    accumulate more than a few digits of error.  The previous incarnation
    of real.c successfully used a 144-bit fraction; given the current
-   layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits.
-
-   Target floating point models that use base 16 instead of base 2
-   (i.e. IBM 370), are handled during round_for_format, in which we
-   canonicalize the exponent to be a multiple of 4 (log2(16)), and
-   adjust the significand to match.  */
+   layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits.  */
 
 
 /* Used to classify two numbers simultaneously.  */
@@ -1168,6 +1162,14 @@ real_isnan (const REAL_VALUE_TYPE *r)
   return (r->cl == rvc_nan);
 }
 
+/* Determine whether a floating-point value X is finite.  */
+
+bool
+real_isfinite (const REAL_VALUE_TYPE *r)
+{
+  return (r->cl != rvc_nan) && (r->cl != rvc_inf);
+}
+
 /* Determine whether a floating-point value X is negative.  */
 
 bool
@@ -2282,9 +2284,9 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
     {
       r->cl = rvc_normal;
       r->sign = sign;
-      SET_REAL_EXP (r, fmt->emax * fmt->log2_b);
+      SET_REAL_EXP (r, fmt->emax);
 
-      np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b;
+      np2 = SIGNIFICAND_BITS - fmt->p;
       memset (r->sig, -1, SIGSZ * sizeof (unsigned long));
       clear_significand_below (r, np2);
 
@@ -2302,7 +2304,7 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
 /* Fills R with 2**N.  */
 
 void
-real_2expN (REAL_VALUE_TYPE *r, int n)
+real_2expN (REAL_VALUE_TYPE *r, int n, enum machine_mode fmode)
 {
   memset (r, 0, sizeof (*r));
 
@@ -2317,6 +2319,8 @@ real_2expN (REAL_VALUE_TYPE *r, int n)
       SET_REAL_EXP (r, n);
       r->sig[SIGSZ-1] = SIG_MSB;
     }
+  if (DECIMAL_FLOAT_MODE_P (fmode))
+    decimal_real_convert (r, fmode, r);
 }
 
 \f
@@ -2342,9 +2346,9 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
       decimal_real_convert (r, DFmode, r);
     }
 
-  p2 = fmt->p * fmt->log2_b;
-  emin2m1 = (fmt->emin - 1) * fmt->log2_b;
-  emax2 = fmt->emax * fmt->log2_b;
+  p2 = fmt->p;
+  emin2m1 = fmt->emin - 1;
+  emax2 = fmt->emax;
 
   np2 = SIGNIFICAND_BITS - p2;
   switch (r->cl)
@@ -2372,22 +2376,6 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
       gcc_unreachable ();
     }
 
-  /* If we're not base2, normalize the exponent to a multiple of
-     the true base.  */
-  if (fmt->log2_b != 1)
-    {
-      int shift;
-
-      gcc_assert (fmt->b != 10);
-      shift = REAL_EXP (r) & (fmt->log2_b - 1);
-      if (shift)
-       {
-         shift = fmt->log2_b - shift;
-         r->sig[0] |= sticky_rshift_significand (r, r, shift);
-         SET_REAL_EXP (r, REAL_EXP (r) + shift);
-       }
-    }
-
   /* Check the range of the exponent.  If we're out of range,
      either underflow or overflow.  */
   if (REAL_EXP (r) > emax2)
@@ -2443,19 +2431,6 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
          if (REAL_EXP (r) > emax2)
            goto overflow;
          r->sig[SIGSZ-1] = SIG_MSB;
-
-         if (fmt->log2_b != 1)
-           {
-             int shift = REAL_EXP (r) & (fmt->log2_b - 1);
-             if (shift)
-               {
-                 shift = fmt->log2_b - shift;
-                 rshift_significand (r, r, shift);
-                 SET_REAL_EXP (r, REAL_EXP (r) + shift);
-                 if (REAL_EXP (r) > emax2)
-                   goto overflow;
-               }
-           }
        }
     }
 
@@ -2513,7 +2488,7 @@ exact_real_truncate (enum machine_mode mode, const REAL_VALUE_TYPE *a)
   gcc_assert (fmt);
 
   /* Don't allow conversion to denormals.  */
-  emin2m1 = (fmt->emin - 1) * fmt->log2_b;
+  emin2m1 = fmt->emin - 1;
   if (REAL_EXP (a) <= emin2m1)
     return false;
 
@@ -2604,7 +2579,7 @@ significand_size (enum machine_mode mode)
       double log2_10 = 3.3219281;
       return fmt->p * log2_10;
     }
-  return fmt->p * fmt->log2_b;
+  return fmt->p;
 }
 
 /* Return a hash value for the given real value.  */
@@ -2775,7 +2750,6 @@ const struct real_format ieee_single_format =
     encode_ieee_single,
     decode_ieee_single,
     2,
-    1,
     24,
     24,
     -125,
@@ -2795,7 +2769,6 @@ const struct real_format mips_single_format =
     encode_ieee_single,
     decode_ieee_single,
     2,
-    1,
     24,
     24,
     -125,
@@ -2810,12 +2783,11 @@ const struct real_format mips_single_format =
     true
   };
 
-const struct real_format coldfire_single_format =
+const struct real_format motorola_single_format =
   {
     encode_ieee_single,
     decode_ieee_single,
     2,
-    1,
     24,
     24,
     -125,
@@ -3023,7 +2995,6 @@ const struct real_format ieee_double_format =
     encode_ieee_double,
     decode_ieee_double,
     2,
-    1,
     53,
     53,
     -1021,
@@ -3043,7 +3014,6 @@ const struct real_format mips_double_format =
     encode_ieee_double,
     decode_ieee_double,
     2,
-    1,
     53,
     53,
     -1021,
@@ -3058,12 +3028,11 @@ const struct real_format mips_double_format =
     true
   };
 
-const struct real_format coldfire_double_format =
+const struct real_format motorola_double_format =
   {
     encode_ieee_double,
     decode_ieee_double,
     2,
-    1,
     53,
     53,
     -1021,
@@ -3122,7 +3091,15 @@ encode_ieee_extended (const struct real_format *fmt, long *buf,
       if (fmt->has_nans)
        {
          image_hi |= 32767;
-         if (HOST_BITS_PER_LONG == 32)
+         if (r->canonical)
+           {
+             if (fmt->canonical_nan_lsbs_set)
+               {
+                 sig_hi = (1 << 30) - 1;
+                 sig_lo = 0xffffffff;
+               }
+           }
+         else if (HOST_BITS_PER_LONG == 32)
            {
              sig_hi = r->sig[SIGSZ-1];
              sig_lo = r->sig[SIGSZ-2];
@@ -3393,7 +3370,6 @@ const struct real_format ieee_extended_motorola_format =
     encode_ieee_extended_motorola,
     decode_ieee_extended_motorola,
     2,
-    1,
     64,
     64,
     -16382,
@@ -3405,7 +3381,7 @@ const struct real_format ieee_extended_motorola_format =
     true,
     true,
     true,
-    false
+    true
   };
 
 const struct real_format ieee_extended_intel_96_format =
@@ -3413,7 +3389,6 @@ const struct real_format ieee_extended_intel_96_format =
     encode_ieee_extended_intel_96,
     decode_ieee_extended_intel_96,
     2,
-    1,
     64,
     64,
     -16381,
@@ -3433,7 +3408,6 @@ const struct real_format ieee_extended_intel_128_format =
     encode_ieee_extended_intel_128,
     decode_ieee_extended_intel_128,
     2,
-    1,
     64,
     64,
     -16381,
@@ -3455,7 +3429,6 @@ const struct real_format ieee_extended_intel_96_round_53_format =
     encode_ieee_extended_intel_96,
     decode_ieee_extended_intel_96,
     2,
-    1,
     53,
     53,
     -16381,
@@ -3542,7 +3515,6 @@ const struct real_format ibm_extended_format =
     encode_ibm_extended,
     decode_ibm_extended,
     2,
-    1,
     53 + 53,
     53,
     -1021 + 53,
@@ -3562,7 +3534,6 @@ const struct real_format mips_extended_format =
     encode_ibm_extended,
     decode_ibm_extended,
     2,
-    1,
     53 + 53,
     53,
     -1021 + 53,
@@ -3824,7 +3795,6 @@ const struct real_format ieee_quad_format =
     encode_ieee_quad,
     decode_ieee_quad,
     2,
-    1,
     113,
     113,
     -16381,
@@ -3844,7 +3814,6 @@ const struct real_format mips_quad_format =
     encode_ieee_quad,
     decode_ieee_quad,
     2,
-    1,
     113,
     113,
     -16381,
@@ -4143,7 +4112,6 @@ const struct real_format vax_f_format =
     encode_vax_f,
     decode_vax_f,
     2,
-    1,
     24,
     24,
     -127,
@@ -4163,7 +4131,6 @@ const struct real_format vax_d_format =
     encode_vax_d,
     decode_vax_d,
     2,
-    1,
     56,
     56,
     -127,
@@ -4183,7 +4150,6 @@ const struct real_format vax_g_format =
     encode_vax_g,
     decode_vax_g,
     2,
-    1,
     53,
     53,
     -1023,
@@ -4198,203 +4164,6 @@ const struct real_format vax_g_format =
     false
   };
 \f
-/* A good reference for these can be found in chapter 9 of
-   "ESA/390 Principles of Operation", IBM document number SA22-7201-01.
-   An on-line version can be found here:
-
-   http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/DZ9AR001/9.1?DT=19930923083613
-*/
-
-static void encode_i370_single (const struct real_format *fmt,
-                               long *, const REAL_VALUE_TYPE *);
-static void decode_i370_single (const struct real_format *,
-                               REAL_VALUE_TYPE *, const long *);
-static void encode_i370_double (const struct real_format *fmt,
-                               long *, const REAL_VALUE_TYPE *);
-static void decode_i370_double (const struct real_format *,
-                               REAL_VALUE_TYPE *, const long *);
-
-static void
-encode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
-                   long *buf, const REAL_VALUE_TYPE *r)
-{
-  unsigned long sign, exp, sig, image;
-
-  sign = r->sign << 31;
-
-  switch (r->cl)
-    {
-    case rvc_zero:
-      image = 0;
-      break;
-
-    case rvc_inf:
-    case rvc_nan:
-      image = 0x7fffffff | sign;
-      break;
-
-    case rvc_normal:
-      sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0xffffff;
-      exp = ((REAL_EXP (r) / 4) + 64) << 24;
-      image = sign | exp | sig;
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  buf[0] = image;
-}
-
-static void
-decode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
-                   REAL_VALUE_TYPE *r, const long *buf)
-{
-  unsigned long sign, sig, image = buf[0];
-  int exp;
-
-  sign = (image >> 31) & 1;
-  exp = (image >> 24) & 0x7f;
-  sig = image & 0xffffff;
-
-  memset (r, 0, sizeof (*r));
-
-  if (exp || sig)
-    {
-      r->cl = rvc_normal;
-      r->sign = sign;
-      SET_REAL_EXP (r, (exp - 64) * 4);
-      r->sig[SIGSZ-1] = sig << (HOST_BITS_PER_LONG - 24);
-      normalize (r);
-    }
-}
-
-static void
-encode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
-                   long *buf, const REAL_VALUE_TYPE *r)
-{
-  unsigned long sign, exp, image_hi, image_lo;
-
-  sign = r->sign << 31;
-
-  switch (r->cl)
-    {
-    case rvc_zero:
-      image_hi = image_lo = 0;
-      break;
-
-    case rvc_inf:
-    case rvc_nan:
-      image_hi = 0x7fffffff | sign;
-      image_lo = 0xffffffff;
-      break;
-
-    case rvc_normal:
-      if (HOST_BITS_PER_LONG == 64)
-       {
-         image_hi = r->sig[SIGSZ-1];
-         image_lo = (image_hi >> (64 - 56)) & 0xffffffff;
-         image_hi = (image_hi >> (64 - 56 + 1) >> 31) & 0xffffff;
-       }
-      else
-       {
-         image_hi = r->sig[SIGSZ-1];
-         image_lo = r->sig[SIGSZ-2];
-         image_lo = (image_lo >> 8) | (image_hi << 24);
-         image_hi >>= 8;
-       }
-
-      exp = ((REAL_EXP (r) / 4) + 64) << 24;
-      image_hi |= sign | exp;
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    buf[0] = image_hi, buf[1] = image_lo;
-  else
-    buf[0] = image_lo, buf[1] = image_hi;
-}
-
-static void
-decode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
-                   REAL_VALUE_TYPE *r, const long *buf)
-{
-  unsigned long sign, image_hi, image_lo;
-  int exp;
-
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    image_hi = buf[0], image_lo = buf[1];
-  else
-    image_lo = buf[0], image_hi = buf[1];
-
-  sign = (image_hi >> 31) & 1;
-  exp = (image_hi >> 24) & 0x7f;
-  image_hi &= 0xffffff;
-  image_lo &= 0xffffffff;
-
-  memset (r, 0, sizeof (*r));
-
-  if (exp || image_hi || image_lo)
-    {
-      r->cl = rvc_normal;
-      r->sign = sign;
-      SET_REAL_EXP (r, (exp - 64) * 4 + (SIGNIFICAND_BITS - 56));
-
-      if (HOST_BITS_PER_LONG == 32)
-       {
-         r->sig[0] = image_lo;
-         r->sig[1] = image_hi;
-       }
-      else
-       r->sig[0] = image_lo | (image_hi << 31 << 1);
-
-      normalize (r);
-    }
-}
-
-const struct real_format i370_single_format =
-  {
-    encode_i370_single,
-    decode_i370_single,
-    16,
-    4,
-    6,
-    6,
-    -64,
-    63,
-    31,
-    31,
-    false,
-    false,
-    false, /* ??? The encoding does allow for "unnormals".  */
-    false, /* ??? The encoding does allow for "unnormals".  */
-    false,
-    false
-  };
-
-const struct real_format i370_double_format =
-  {
-    encode_i370_double,
-    decode_i370_double,
-    16,
-    4,
-    14,
-    14,
-    -64,
-    63,
-    63,
-    63,
-    false,
-    false,
-    false, /* ??? The encoding does allow for "unnormals".  */
-    false, /* ??? The encoding does allow for "unnormals".  */
-    false,
-    false
-  };
-\f
 /* Encode real R into a single precision DFP value in BUF.  */
 static void
 encode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
@@ -4455,7 +4224,6 @@ const struct real_format decimal_single_format =
     encode_decimal_single,
     decode_decimal_single,
     10, 
-    1,  /* log10 */
     7,
     7,
     -95,
@@ -4476,7 +4244,6 @@ const struct real_format decimal_double_format =
     encode_decimal_double,
     decode_decimal_double,
     10,
-    1,  /* log10 */
     16,
     16,
     -383,
@@ -4497,7 +4264,6 @@ const struct real_format decimal_quad_format =
     encode_decimal_quad,
     decode_decimal_quad,
     10,
-    1,  /* log10 */
     34,
     34,
     -6143,
@@ -4707,7 +4473,6 @@ const struct real_format c4x_single_format =
     encode_c4x_single,
     decode_c4x_single,
     2,
-    1,
     24,
     24,
     -126,
@@ -4727,7 +4492,6 @@ const struct real_format c4x_extended_format =
     encode_c4x_extended,
     decode_c4x_extended,
     2,
-    1,
     32,
     32,
     -126,
@@ -4772,7 +4536,6 @@ const struct real_format real_internal_format =
     encode_internal,
     decode_internal,
     2,
-    1,
     SIGNIFICAND_BITS - 2,
     SIGNIFICAND_BITS - 2,
     -MAX_EXP,
@@ -4817,7 +4580,7 @@ real_sqrt (REAL_VALUE_TYPE *r, enum machine_mode mode,
     }
 
   /* Infinity and NaN return themselves.  */
-  if (real_isinf (x) || real_isnan (x))
+  if (!real_isfinite (x))
     {
       *r = *x;
       return false;
@@ -5000,7 +4763,7 @@ mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mp_rnd_t rndmode)
   /* Take care of Infinity and NaN.  */
   if (r->cl == rvc_inf)
     {
-      mpfr_set_inf (m, r->sign);
+      mpfr_set_inf (m, r->sign == 1 ? -1 : 1);
       return;
     }
   
@@ -5073,3 +4836,35 @@ real_isinteger (const REAL_VALUE_TYPE *c, enum machine_mode mode)
   real_trunc (&cint, mode, c);
   return real_identical (c, &cint);
 }
+
+/* Write into BUF the maximum representable finite floating-point
+   number, (1 - b**-p) * b**emax for a given FP format FMT as a hex
+   float string.  LEN is the size of BUF, and the buffer must be large
+   enough to contain the resulting string.  */
+
+void
+get_max_float (const struct real_format *fmt, char *buf, size_t len)
+{
+  int i, n;
+  char *p;
+
+  strcpy (buf, "0x0.");
+  n = fmt->p;
+  for (i = 0, p = buf + 4; i + 3 < n; i += 4)
+    *p++ = 'f';
+  if (i < n)
+    *p++ = "08ce"[n - i];
+  sprintf (p, "p%d", fmt->emax);
+  if (fmt->pnan < fmt->p)
+    {
+      /* This is an IBM extended double format made up of two IEEE
+        doubles.  The value of the long double is the sum of the
+        values of the two parts.  The most significant part is
+        required to be the value of the long double rounded to the
+        nearest double.  Rounding means we need a slightly smaller
+        value for LDBL_MAX.  */
+      buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4];
+    }
+
+  gcc_assert (strlen (buf) < len);
+}