OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / real.c
index 5da2cb3..dc6d748 100644 (file)
@@ -1443,20 +1443,30 @@ rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den)
 /* Render R as a decimal floating point constant.  Emit DIGITS significant
    digits in the result, bounded by BUF_SIZE.  If DIGITS is 0, choose the
    maximum for the representation.  If CROP_TRAILING_ZEROS, strip trailing
-   zeros.  */
+   zeros.  If MODE is VOIDmode, round to nearest value.  Otherwise, round
+   to a string that, when parsed back in mode MODE, yields the same value.  */
 
 #define M_LOG10_2      0.30102999566398119521
 
 void
-real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
-                size_t digits, int crop_trailing_zeros)
+real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig,
+                         size_t buf_size, size_t digits,
+                         int crop_trailing_zeros, enum machine_mode mode)
 {
+  const struct real_format *fmt = NULL;
   const REAL_VALUE_TYPE *one, *ten;
   REAL_VALUE_TYPE r, pten, u, v;
   int dec_exp, cmp_one, digit;
   size_t max_digits;
   char *p, *first, *last;
   bool sign;
+  bool round_up;
+
+  if (mode != VOIDmode)
+   {
+     fmt = REAL_MODE_FORMAT (mode);
+     gcc_assert (fmt);
+   }
 
   r = *r_orig;
   switch (r.cl)
@@ -1672,17 +1682,31 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
   digit = rtd_divmod (&r, &pten);
 
   /* Round the result.  */
-  if (digit == 5)
+  if (fmt && fmt->round_towards_zero)
     {
-      /* Round to nearest.  If R is nonzero there are additional
-        nonzero digits to be extracted.  */
+      /* If the format uses round towards zero when parsing the string
+        back in, we need to always round away from zero here.  */
       if (cmp_significand_0 (&r))
        digit++;
-      /* Round to even.  */
-      else if ((p[-1] - '0') & 1)
-       digit++;
+      round_up = digit > 0;
     }
-  if (digit > 5)
+  else
+    {
+      if (digit == 5)
+       {
+         /* Round to nearest.  If R is nonzero there are additional
+            nonzero digits to be extracted.  */
+         if (cmp_significand_0 (&r))
+           digit++;
+         /* Round to even.  */
+         else if ((p[-1] - '0') & 1)
+           digit++;
+       }
+
+      round_up = digit > 5;
+    }
+
+  if (round_up)
     {
       while (p > first)
        {
@@ -1716,6 +1740,26 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
 
   /* Append the exponent.  */
   sprintf (last, "e%+d", dec_exp);
+
+#ifdef ENABLE_CHECKING
+  /* Verify that we can read the original value back in.  */
+  if (mode != VOIDmode)
+    {
+      real_from_string (&r, str);
+      real_convert (&r, mode, &r);
+      gcc_assert (real_identical (&r, r_orig));
+    }
+#endif
+}
+
+/* Likewise, except always uses round-to-nearest.  */
+
+void
+real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
+                size_t digits, int crop_trailing_zeros)
+{
+  real_to_decimal_for_mode (str, r_orig, buf_size,
+                           digits, crop_trailing_zeros, VOIDmode);
 }
 
 /* Render R as a hexadecimal floating point constant.  Emit DIGITS
@@ -2181,47 +2225,62 @@ times_pten (REAL_VALUE_TYPE *r, int exp)
     do_divide (r, r, &pten);
 }
 
-/* Returns the special REAL_VALUE_TYPE enumerated by E.  */
+/* Returns the special REAL_VALUE_TYPE corresponding to 'e'.  */
 
 const REAL_VALUE_TYPE *
-get_real_const (enum real_value_const e)
+dconst_e_ptr (void)
 {
-  static REAL_VALUE_TYPE value[rv_max];
+  static REAL_VALUE_TYPE value;
+
+  /* Initialize mathematical constants for constant folding builtins.
+     These constants need to be given to at least 160 bits precision.  */
+  if (value.cl == rvc_zero)
+    {
+      mpfr_t m;
+      mpfr_init2 (m, SIGNIFICAND_BITS);
+      mpfr_set_ui (m, 1, GMP_RNDN);
+      mpfr_exp (m, m, GMP_RNDN);
+      real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN);
+      mpfr_clear (m);
+      
+    }
+  return &value;
+}
 
-  gcc_assert (e < rv_max);
+/* Returns the special REAL_VALUE_TYPE corresponding to 1/3.  */
+
+const REAL_VALUE_TYPE *
+dconst_third_ptr (void)
+{
+  static REAL_VALUE_TYPE value;
 
   /* Initialize mathematical constants for constant folding builtins.
      These constants need to be given to at least 160 bits precision.  */
-  if (value[e].cl == rvc_zero)
-    switch (e)
+  if (value.cl == rvc_zero)
     {
-    case rv_e:
-      {
-       mpfr_t m;
-       mpfr_init2 (m, SIGNIFICAND_BITS);
-       mpfr_set_ui (m, 1, GMP_RNDN);
-       mpfr_exp (m, m, GMP_RNDN);
-       real_from_mpfr (&value[e], m, NULL_TREE, GMP_RNDN);
-       mpfr_clear (m);
-      }
-      break;
-    case rv_third:
-      real_arithmetic (&value[e], RDIV_EXPR, &dconst1, real_digit (3));
-      break;
-    case rv_sqrt2:
-      {
-       mpfr_t m;
-       mpfr_init2 (m, SIGNIFICAND_BITS);
-       mpfr_sqrt_ui (m, 2, GMP_RNDN);
-       real_from_mpfr (&value[e], m, NULL_TREE, GMP_RNDN);
-       mpfr_clear (m);
-      }
-      break;
-    default:
-      gcc_unreachable();
+      real_arithmetic (&value, RDIV_EXPR, &dconst1, real_digit (3));
     }
+  return &value;
+}
+
+/* Returns the special REAL_VALUE_TYPE corresponding to sqrt(2).  */
 
-  return &value[e];
+const REAL_VALUE_TYPE *
+dconst_sqrt2_ptr (void)
+{
+  static REAL_VALUE_TYPE value;
+
+  /* Initialize mathematical constants for constant folding builtins.
+     These constants need to be given to at least 160 bits precision.  */
+  if (value.cl == rvc_zero)
+    {
+      mpfr_t m;
+      mpfr_init2 (m, SIGNIFICAND_BITS);
+      mpfr_sqrt_ui (m, 2, GMP_RNDN);
+      real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN);
+      mpfr_clear (m);
+    }
+  return &value;
 }
 
 /* Fills R with +Inf.  */
@@ -2358,7 +2417,7 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
           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.  */
-        clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan);
+       clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan - 1);
     }
 }
 
@@ -2389,9 +2448,8 @@ static void
 round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
 {
   int p2, np2, i, w;
-  unsigned long sticky;
-  bool guard, lsb;
   int emin2m1, emax2;
+  bool round_up = false;
 
   if (r->decimal)
     {
@@ -2463,21 +2521,28 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
        }
     }
 
-  /* There are P2 true significand bits, followed by one guard bit,
-     followed by one sticky bit, followed by stuff.  Fold nonzero
-     stuff into the sticky bit.  */
+  if (!fmt->round_towards_zero)
+    {
+      /* There are P2 true significand bits, followed by one guard bit,
+         followed by one sticky bit, followed by stuff.  Fold nonzero
+         stuff into the sticky bit.  */
+      unsigned long sticky;
+      bool guard, lsb;
+
+      sticky = 0;
+      for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i)
+       sticky |= r->sig[i];
+      sticky |= r->sig[w]
+               & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1);
 
-  sticky = 0;
-  for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i)
-    sticky |= r->sig[i];
-  sticky |=
-    r->sig[w] & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1);
+      guard = test_significand_bit (r, np2 - 1);
+      lsb = test_significand_bit (r, np2);
 
-  guard = test_significand_bit (r, np2 - 1);
-  lsb = test_significand_bit (r, np2);
+      /* Round to even.  */
+      round_up = guard && (sticky || lsb);
+    }
 
-  /* Round to even.  */
-  if (guard && (sticky || lsb))
+  if (round_up)
     {
       REAL_VALUE_TYPE u;
       get_zero (&u, 0);
@@ -2817,6 +2882,8 @@ const struct real_format ieee_single_format =
     128,
     31,
     31,
+    false,
+    true,
     true,
     true,
     true,
@@ -2836,6 +2903,8 @@ const struct real_format mips_single_format =
     128,
     31,
     31,
+    false,
+    true,
     true,
     true,
     true,
@@ -2855,6 +2924,8 @@ const struct real_format motorola_single_format =
     128,
     31,
     31,
+    false,
+    true,
     true,
     true,
     true,
@@ -2862,6 +2933,38 @@ const struct real_format motorola_single_format =
     true,
     true
   };
+
+/*  SPU Single Precision (Extended-Range Mode) format is the same as IEEE
+    single precision with the following differences:
+      - Infinities are not supported.  Instead MAX_FLOAT or MIN_FLOAT
+       are generated.
+      - NaNs are not supported.
+      - The range of non-zero numbers in binary is
+       (001)[1.]000...000 to (255)[1.]111...111.
+      - Denormals can be represented, but are treated as +0.0 when
+       used as an operand and are never generated as a result.
+      - -0.0 can be represented, but a zero result is always +0.0.
+      - the only supported rounding mode is trunction (towards zero).  */
+const struct real_format spu_single_format =
+  {
+    encode_ieee_single,
+    decode_ieee_single,
+    2,
+    24,
+    24,
+    -125,
+    129,
+    31,
+    31,
+    true,
+    false,
+    false,
+    false,
+    true,
+    true,
+    false,
+    false
+  };
 \f
 /* IEEE double-precision format.  */
 
@@ -3062,6 +3165,8 @@ const struct real_format ieee_double_format =
     1024,
     63,
     63,
+    false,
+    true,
     true,
     true,
     true,
@@ -3081,6 +3186,8 @@ const struct real_format mips_double_format =
     1024,
     63,
     63,
+    false,
+    true,
     true,
     true,
     true,
@@ -3100,6 +3207,8 @@ const struct real_format motorola_double_format =
     1024,
     63,
     63,
+    false,
+    true,
     true,
     true,
     true,
@@ -3437,6 +3546,8 @@ const struct real_format ieee_extended_motorola_format =
     16384,
     95,
     95,
+    false,
+    true,
     true,
     true,
     true,
@@ -3456,6 +3567,8 @@ const struct real_format ieee_extended_intel_96_format =
     16384,
     79,
     79,
+    false,
+    true,
     true,
     true,
     true,
@@ -3475,6 +3588,8 @@ const struct real_format ieee_extended_intel_128_format =
     16384,
     79,
     79,
+    false,
+    true,
     true,
     true,
     true,
@@ -3496,6 +3611,8 @@ const struct real_format ieee_extended_intel_96_round_53_format =
     16384,
     79,
     79,
+    false,
+    true,
     true,
     true,
     true,
@@ -3582,6 +3699,8 @@ const struct real_format ibm_extended_format =
     1024,
     127,
     -1,
+    false,
+    true,
     true,
     true,
     true,
@@ -3601,6 +3720,8 @@ const struct real_format mips_extended_format =
     1024,
     127,
     -1,
+    false,
+    true,
     true,
     true,
     true,
@@ -3862,6 +3983,8 @@ const struct real_format ieee_quad_format =
     16384,
     127,
     127,
+    false,
+    true,
     true,
     true,
     true,
@@ -3881,6 +4004,8 @@ const struct real_format mips_quad_format =
     16384,
     127,
     127,
+    false,
+    true,
     true,
     true,
     true,
@@ -4184,6 +4309,8 @@ const struct real_format vax_f_format =
     false,
     false,
     false,
+    false,
+    false,
     false
   };
 
@@ -4203,6 +4330,8 @@ const struct real_format vax_d_format =
     false,
     false,
     false,
+    false,
+    false,
     false
   };
 
@@ -4222,6 +4351,8 @@ const struct real_format vax_g_format =
     false,
     false,
     false,
+    false,
+    false,
     false
   };
 \f
@@ -4279,7 +4410,7 @@ decode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decode_decimal128 (fmt, r, buf);
 }
 
-/* Single precision decimal floating point (IEEE 754R). */
+/* Single precision decimal floating point (IEEE 754). */
 const struct real_format decimal_single_format =
   {
     encode_decimal_single,
@@ -4291,6 +4422,8 @@ const struct real_format decimal_single_format =
     96,
     31,
     31,
+    false,
+    true,
     true,
     true,
     true,
@@ -4299,7 +4432,7 @@ const struct real_format decimal_single_format =
     false
   };
 
-/* Double precision decimal floating point (IEEE 754R). */
+/* Double precision decimal floating point (IEEE 754). */
 const struct real_format decimal_double_format =
   {
     encode_decimal_double,
@@ -4311,6 +4444,8 @@ const struct real_format decimal_double_format =
     384,
     63,
     63,
+    false,
+    true,
     true,
     true,
     true,
@@ -4319,7 +4454,7 @@ const struct real_format decimal_double_format =
     false
   };
 
-/* Quad precision decimal floating point (IEEE 754R). */
+/* Quad precision decimal floating point (IEEE 754). */
 const struct real_format decimal_quad_format =
   {
     encode_decimal_quad,
@@ -4331,6 +4466,8 @@ const struct real_format decimal_quad_format =
     6144,
     127,
     127,
+    false,
+    true,
     true,
     true,
     true, 
@@ -4374,6 +4511,8 @@ const struct real_format real_internal_format =
     MAX_EXP,
     -1,
     -1,
+    false,
+    false,
     true,
     true,
     false,