OSDN Git Service

2005-06-14 Pascal Obry <obry@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / real.c
index 2eb2019..81bce44 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 Free Software Foundation, Inc.
+   2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Stephen L. Moshier (moshier@world.std.com).
    Re-written by Richard Henderson <rth@redhat.com>
 
@@ -577,7 +577,7 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Swap the arguments such that A has the larger exponent.  */
@@ -640,6 +640,9 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
   r->cl = rvc_normal;
   r->sign = sign;
   SET_REAL_EXP (r, exp);
+  /* Zero out the remaining fields.  */
+  r->signalling = 0;
+  r->canonical = 0;
 
   /* Re-normalize the result.  */
   normalize (r);
@@ -708,7 +711,7 @@ do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (r == a || r == b)
@@ -850,7 +853,7 @@ do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (r == a || r == b)
@@ -929,7 +932,7 @@ do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (a->sign != b->sign)
@@ -967,14 +970,15 @@ do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
 /* Perform the binary or unary operation described by CODE.
-   For a unary operation, leave OP1 NULL.  */
+   For a unary operation, leave OP1 NULL.  This function returns
+   true if the result may be inexact due to loss of precision.  */
 
-void
+bool
 real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
                 const REAL_VALUE_TYPE *op1)
 {
@@ -983,20 +987,16 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
   switch (code)
     {
     case PLUS_EXPR:
-      do_add (r, op0, op1, 0);
-      break;
+      return do_add (r, op0, op1, 0);
 
     case MINUS_EXPR:
-      do_add (r, op0, op1, 1);
-      break;
+      return do_add (r, op0, op1, 1);
 
     case MULT_EXPR:
-      do_multiply (r, op0, op1);
-      break;
+      return do_multiply (r, op0, op1);
 
     case RDIV_EXPR:
-      do_divide (r, op0, op1);
-      break;
+      return do_divide (r, op0, op1);
 
     case MIN_EXPR:
       if (op1->cl == rvc_nan)
@@ -1031,8 +1031,9 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
+  return false;
 }
 
 /* Legacy.  Similar, but return the result directly.  */
@@ -1084,7 +1085,7 @@ real_compare (int icode, const REAL_VALUE_TYPE *op0,
       return do_compare (op0, op1, 0) != 0;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1103,7 +1104,7 @@ real_exponent (const REAL_VALUE_TYPE *r)
     case rvc_normal:
       return REAL_EXP (r);
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1131,7 +1132,7 @@ real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, int exp)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1199,7 +1200,7 @@ real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   for (i = 0; i < SIGSZ; ++i)
@@ -1279,14 +1280,13 @@ real_to_integer (const REAL_VALUE_TYPE *r)
 
       if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
        i = r->sig[SIGSZ-1];
-      else if (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG)
+      else 
        {
+         gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG);
          i = r->sig[SIGSZ-1];
          i = i << (HOST_BITS_PER_LONG - 1) << 1;
          i |= r->sig[SIGSZ-2];
        }
-      else
-       abort ();
 
       i >>= HOST_BITS_PER_WIDE_INT - REAL_EXP (r);
 
@@ -1295,7 +1295,7 @@ real_to_integer (const REAL_VALUE_TYPE *r)
       return i;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1346,8 +1346,9 @@ real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
          high = t.sig[SIGSZ-1];
          low = t.sig[SIGSZ-2];
        }
-      else if (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG)
+      else 
        {
+         gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG);
          high = t.sig[SIGSZ-1];
          high = high << (HOST_BITS_PER_LONG - 1) << 1;
          high |= t.sig[SIGSZ-2];
@@ -1356,8 +1357,6 @@ real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
          low = low << (HOST_BITS_PER_LONG - 1) << 1;
          low |= t.sig[SIGSZ-4];
        }
-      else
-       abort ();
 
       if (r->sign)
        {
@@ -1369,7 +1368,7 @@ real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   *plow = low;
@@ -1446,7 +1445,7 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
       strcpy (str, (r.sign ? "-NaN" : "+NaN"));
       return;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Bound the number of digits printed by the size of the representation.  */
@@ -1463,8 +1462,7 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
 
   /* Bound the number of digits printed by the size of the output buffer.  */
   max_digits = buf_size - 1 - 1 - 2 - max_digits - 1;
-  if (max_digits > buf_size)
-    abort ();
+  gcc_assert (max_digits <= buf_size);
   if (digits > max_digits)
     digits = max_digits;
 
@@ -1607,8 +1605,7 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
       do_multiply (&r, &r, ten);
       digit = rtd_divmod (&r, &pten);
       dec_exp -= 1;
-      if (digit == 0)
-       abort ();
+      gcc_assert (digit != 0);
     }
 
   /* ... or overflow.  */
@@ -1619,10 +1616,11 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
        *p++ = '0';
       dec_exp += 1;
     }
-  else if (digit > 10)
-    abort ();
   else
-    *p++ = digit + '0';
+    {
+      gcc_assert (digit <= 10);
+      *p++ = digit + '0';
+    }
 
   /* Generate subsequent digits.  */
   while (--digits > 0)
@@ -1713,7 +1711,7 @@ real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size,
       strcpy (str, (r->sign ? "-NaN" : "+NaN"));
       return;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (digits == 0)
@@ -1723,8 +1721,7 @@ real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size,
 
   sprintf (exp_buf, "p%+d", exp);
   max_digits = buf_size - strlen (exp_buf) - r->sign - 4 - 1;
-  if (max_digits > buf_size)
-    abort ();
+  gcc_assert (max_digits <= buf_size);
   if (digits > max_digits)
     digits = max_digits;
 
@@ -1963,6 +1960,7 @@ real_from_integer (REAL_VALUE_TYPE *r, enum machine_mode mode,
     get_zero (r, 0);
   else
     {
+      memset (r, 0, sizeof (*r));
       r->cl = rvc_normal;
       r->sign = high < 0 && !unsigned_p;
       SET_REAL_EXP (r, 2 * HOST_BITS_PER_WIDE_INT);
@@ -1980,19 +1978,15 @@ real_from_integer (REAL_VALUE_TYPE *r, enum machine_mode mode,
        {
          r->sig[SIGSZ-1] = high;
          r->sig[SIGSZ-2] = low;
-         memset (r->sig, 0, sizeof(long)*(SIGSZ-2));
        }
-      else if (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT)
+      else
        {
+         gcc_assert (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT);
          r->sig[SIGSZ-1] = high >> (HOST_BITS_PER_LONG - 1) >> 1;
          r->sig[SIGSZ-2] = high;
          r->sig[SIGSZ-3] = low >> (HOST_BITS_PER_LONG - 1) >> 1;
          r->sig[SIGSZ-4] = low;
-         if (SIGSZ > 4)
-           memset (r->sig, 0, sizeof(long)*(SIGSZ-4));
        }
-      else
-       abort ();
 
       normalize (r);
     }
@@ -2008,8 +2002,8 @@ ten_to_ptwo (int n)
 {
   static REAL_VALUE_TYPE tens[EXP_BITS];
 
-  if (n < 0 || n >= EXP_BITS)
-    abort ();
+  gcc_assert (n >= 0);
+  gcc_assert (n < EXP_BITS);
 
   if (tens[n].cl == rvc_zero)
     {
@@ -2040,8 +2034,8 @@ ten_to_mptwo (int n)
 {
   static REAL_VALUE_TYPE tens[EXP_BITS];
 
-  if (n < 0 || n >= EXP_BITS)
-    abort ();
+  gcc_assert (n >= 0);
+  gcc_assert (n < EXP_BITS);
 
   if (tens[n].cl == rvc_zero)
     do_divide (&tens[n], real_digit (1), ten_to_ptwo (n));
@@ -2056,8 +2050,8 @@ real_digit (int n)
 {
   static REAL_VALUE_TYPE num[10];
 
-  if (n < 0 || n > 9)
-    abort ();
+  gcc_assert (n >= 0);
+  gcc_assert (n <= 9);
 
   if (n > 0 && num[n].cl == rvc_zero)
     real_from_integer (&num[n], VOIDmode, n, 0, 1);
@@ -2111,8 +2105,7 @@ real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
   const struct real_format *fmt;
 
   fmt = REAL_MODE_FORMAT (mode);
-  if (fmt == NULL)
-    abort ();
+  gcc_assert (fmt);
 
   if (*str == 0)
     {
@@ -2124,7 +2117,6 @@ real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
   else
     {
       int base = 10, d;
-      bool neg = false;
 
       memset (r, 0, sizeof (*r));
       r->cl = rvc_nan;
@@ -2134,7 +2126,7 @@ real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
       while (ISSPACE (*str))
        str++;
       if (*str == '-')
-       str++, neg = true;
+       str++;
       else if (*str == '+')
        str++;
       if (*str == '0')
@@ -2163,7 +2155,7 @@ real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
              add_significands (r, r, &u);
              break;
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          get_zero (&u, 0);
@@ -2201,8 +2193,7 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
   int np2;
 
   fmt = REAL_MODE_FORMAT (mode);
-  if (fmt == NULL)
-    abort ();
+  gcc_assert (fmt);
 
   r->cl = rvc_normal;
   r->sign = sign;
@@ -2271,7 +2262,7 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* If we're not base2, normalize the exponent to a multiple of
@@ -2375,8 +2366,7 @@ real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode,
   const struct real_format *fmt;
 
   fmt = REAL_MODE_FORMAT (mode);
-  if (fmt == NULL)
-    abort ();
+  gcc_assert (fmt);
 
   *r = *a;
   round_for_format (fmt, r);
@@ -2437,8 +2427,7 @@ real_to_target (long *buf, const REAL_VALUE_TYPE *r, enum machine_mode mode)
   const struct real_format *fmt;
 
   fmt = REAL_MODE_FORMAT (mode);
-  if (fmt == NULL)
-    abort ();
+  gcc_assert (fmt);
 
   return real_to_target_fmt (buf, r, fmt);
 }
@@ -2462,8 +2451,7 @@ real_from_target (REAL_VALUE_TYPE *r, const long *buf, enum machine_mode mode)
   const struct real_format *fmt;
 
   fmt = REAL_MODE_FORMAT (mode);
-  if (fmt == NULL)
-    abort ();
+  gcc_assert (fmt);
 
   (*fmt->decode) (fmt, r, buf);
 }
@@ -2512,7 +2500,7 @@ real_hash (const REAL_VALUE_TYPE *r)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (sizeof(unsigned long) > sizeof(unsigned int))
@@ -2596,7 +2584,7 @@ encode_ieee_single (const struct real_format *fmt, long *buf,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   buf[0] = image;
@@ -2663,6 +2651,7 @@ const struct real_format ieee_single_format =
     -125,
     128,
     31,
+    31,
     true,
     true,
     true,
@@ -2681,6 +2670,7 @@ const struct real_format mips_single_format =
     -125,
     128,
     31,
+    31,
     true,
     true,
     true,
@@ -2781,7 +2771,7 @@ encode_ieee_double (const struct real_format *fmt, long *buf,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (FLOAT_WORDS_BIG_ENDIAN)
@@ -2886,6 +2876,7 @@ const struct real_format ieee_double_format =
     -1021,
     1024,
     63,
+    63,
     true,
     true,
     true,
@@ -2904,6 +2895,7 @@ const struct real_format mips_double_format =
     -1021,
     1024,
     63,
+    63,
     true,
     true,
     true,
@@ -3004,8 +2996,7 @@ encode_ieee_extended (const struct real_format *fmt, long *buf,
        else
          {
            exp += 16383 - 1;
-           if (exp < 0)
-             abort ();
+           gcc_assert (exp >= 0);
          }
        image_hi |= exp;
 
@@ -3024,7 +3015,7 @@ encode_ieee_extended (const struct real_format *fmt, long *buf,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi;
@@ -3234,6 +3225,7 @@ const struct real_format ieee_extended_motorola_format =
     -16382,
     16384,
     95,
+    95,
     true,
     true,
     true,
@@ -3252,6 +3244,7 @@ const struct real_format ieee_extended_intel_96_format =
     -16381,
     16384,
     79,
+    79,
     true,
     true,
     true,
@@ -3270,6 +3263,7 @@ const struct real_format ieee_extended_intel_128_format =
     -16381,
     16384,
     79,
+    79,
     true,
     true,
     true,
@@ -3290,6 +3284,7 @@ const struct real_format ieee_extended_intel_96_round_53_format =
     -16381,
     16384,
     79,
+    79,
     true,
     true,
     true,
@@ -3303,8 +3298,7 @@ const struct real_format ieee_extended_intel_96_round_53_format =
    range as an IEEE double precision value, but effectively 106 bits of
    significand precision.  Infinity and NaN are represented by their IEEE
    double precision value stored in the first number, the second number is
-   ignored.  Zeroes, Infinities, and NaNs are set in both doubles
-   due to precedent.  */
+   +0.0 or -0.0 for Infinity and don't-care for NaN.  */
 
 static void encode_ibm_extended (const struct real_format *fmt,
                                 long *, const REAL_VALUE_TYPE *);
@@ -3375,6 +3369,7 @@ const struct real_format ibm_extended_format =
     53,
     -1021 + 53,
     1024,
+    127,
     -1,
     true,
     true,
@@ -3393,6 +3388,7 @@ const struct real_format mips_extended_format =
     53,
     -1021 + 53,
     1024,
+    127,
     -1,
     true,
     true,
@@ -3521,7 +3517,7 @@ encode_ieee_quad (const struct real_format *fmt, long *buf,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (FLOAT_WORDS_BIG_ENDIAN)
@@ -3660,6 +3656,7 @@ const struct real_format ieee_quad_format =
     -16381,
     16384,
     127,
+    127,
     true,
     true,
     true,
@@ -3678,6 +3675,7 @@ const struct real_format mips_quad_format =
     -16381,
     16384,
     127,
+    127,
     true,
     true,
     true,
@@ -3738,7 +3736,7 @@ encode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   buf[0] = image;
@@ -3809,7 +3807,7 @@ encode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (FLOAT_WORDS_BIG_ENDIAN)
@@ -3909,7 +3907,7 @@ encode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (FLOAT_WORDS_BIG_ENDIAN)
@@ -3975,6 +3973,7 @@ const struct real_format vax_f_format =
     -127,
     127,
     15,
+    15,
     false,
     false,
     false,
@@ -3993,6 +3992,7 @@ const struct real_format vax_d_format =
     -127,
     127,
     15,
+    15,
     false,
     false,
     false,
@@ -4011,6 +4011,7 @@ const struct real_format vax_g_format =
     -1023,
     1023,
     15,
+    15,
     false,
     false,
     false,
@@ -4060,7 +4061,7 @@ encode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   buf[0] = image;
@@ -4129,7 +4130,7 @@ encode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (FLOAT_WORDS_BIG_ENDIAN)
@@ -4186,6 +4187,7 @@ const struct real_format i370_single_format =
     -64,
     63,
     31,
+    31,
     false,
     false,
     false, /* ??? The encoding does allow for "unnormals".  */
@@ -4204,6 +4206,7 @@ const struct real_format i370_double_format =
     -64,
     63,
     63,
+    63,
     false,
     false,
     false, /* ??? The encoding does allow for "unnormals".  */
@@ -4272,7 +4275,7 @@ encode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   image = ((exp & 0xff) << 24) | (sig & 0xffffff);
@@ -4350,7 +4353,7 @@ encode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   exp = (exp & 0xff) << 24;
@@ -4411,6 +4414,7 @@ const struct real_format c4x_single_format =
     24,
     -126,
     128,
+    23,
     -1,
     false,
     false,
@@ -4429,6 +4433,7 @@ const struct real_format c4x_extended_format =
     32,
     -126,
     128,
+    31,
     -1,
     false,
     false,
@@ -4473,6 +4478,7 @@ const struct real_format real_internal_format =
     -MAX_EXP,
     MAX_EXP,
     -1,
+    -1,
     true,
     true,
     false,
@@ -4637,6 +4643,8 @@ real_floor (REAL_VALUE_TYPE *r, enum machine_mode mode,
     do_add (&t, &t, &dconstm1, 0);
   if (mode != VOIDmode)
     real_convert (r, mode, &t);
+  else
+    *r = t;
 }
 
 /* Round X to the smallest integer not less then argument, i.e. round
@@ -4653,6 +4661,8 @@ real_ceil (REAL_VALUE_TYPE *r, enum machine_mode mode,
     do_add (&t, &t, &dconst1, 0);
   if (mode != VOIDmode)
     real_convert (r, mode, &t);
+  else
+    *r = t;
 }
 
 /* Round X to the nearest integer, but round halfway cases away from