OSDN Git Service

* tree-ssa.c (insert_debug_temp_for_var_def): Fix handling of
[pf3gnuchains/gcc-fork.git] / gcc / real.c
index 806e2f8..98e7d78 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, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
+   2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Stephen L. Moshier (moshier@world.std.com).
    Re-written by Richard Henderson <rth@redhat.com>
 
@@ -57,7 +57,7 @@
 
    Both of these requirements are easily satisfied.  The largest target
    significand is 113 bits; we store at least 160.  The smallest
-   denormal number fits in 17 exponent bits; we store 27.
+   denormal number fits in 17 exponent bits; we store 26.
 
    Note that the decimal string conversion routines are sensitive to
    rounding errors.  Since the raw arithmetic routines do not themselves
@@ -110,6 +110,9 @@ static int do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
 static void do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
 
 static unsigned long rtd_divmod (REAL_VALUE_TYPE *, REAL_VALUE_TYPE *);
+static void decimal_from_integer (REAL_VALUE_TYPE *);
+static void decimal_integer_string (char *, const REAL_VALUE_TYPE *,
+                                   size_t);
 
 static const REAL_VALUE_TYPE * ten_to_ptwo (int);
 static const REAL_VALUE_TYPE * ten_to_mptwo (int);
@@ -905,15 +908,23 @@ do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
       /* Sign of zero doesn't matter for compares.  */
       return 0;
 
+    case CLASS2 (rvc_normal, rvc_zero):
+      /* Decimal float zero is special and uses rvc_normal, not rvc_zero.  */
+      if (a->decimal)
+       return decimal_do_compare (a, b, nan_result);
+      /* Fall through.  */
     case CLASS2 (rvc_inf, rvc_zero):
     case CLASS2 (rvc_inf, rvc_normal):
-    case CLASS2 (rvc_normal, rvc_zero):
       return (a->sign ? -1 : 1);
 
     case CLASS2 (rvc_inf, rvc_inf):
       return -a->sign - -b->sign;
 
     case CLASS2 (rvc_zero, rvc_normal):
+      /* Decimal float zero is special and uses rvc_normal, not rvc_zero.  */
+      if (b->decimal)
+       return decimal_do_compare (a, b, nan_result);
+      /* Fall through.  */
     case CLASS2 (rvc_zero, rvc_inf):
     case CLASS2 (rvc_normal, rvc_inf):
       return (b->sign ? 1 : -1);
@@ -989,10 +1000,10 @@ bool
 real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
                 const REAL_VALUE_TYPE *op1)
 {
-  enum tree_code code = icode;
+  enum tree_code code = (enum tree_code) icode;
 
   if (op0->decimal || (op1 && op1->decimal))
-    return decimal_real_arithmetic (r, icode, op0, op1);
+    return decimal_real_arithmetic (r, code, op0, op1);
 
   switch (code)
     {
@@ -1061,7 +1072,7 @@ bool
 real_compare (int icode, const REAL_VALUE_TYPE *op0,
              const REAL_VALUE_TYPE *op1)
 {
-  enum tree_code code = icode;
+  enum tree_code code = (enum tree_code) icode;
 
   switch (code)
     {
@@ -1266,6 +1277,35 @@ exact_real_inverse (enum machine_mode mode, REAL_VALUE_TYPE *r)
   *r = u;
   return true;
 }
+
+/* Return true if arithmetic on values in IMODE that were promoted
+   from values in TMODE is equivalent to direct arithmetic on values
+   in TMODE.  */
+
+bool
+real_can_shorten_arithmetic (enum machine_mode imode, enum machine_mode tmode)
+{
+  const struct real_format *tfmt, *ifmt;
+  tfmt = REAL_MODE_FORMAT (tmode);
+  ifmt = REAL_MODE_FORMAT (imode);
+  /* These conditions are conservative rather than trying to catch the
+     exact boundary conditions; the main case to allow is IEEE float
+     and double.  */
+  return (ifmt->b == tfmt->b
+         && ifmt->p > 2 * tfmt->p
+         && ifmt->emin < 2 * tfmt->emin - tfmt->p - 2
+         && ifmt->emin < tfmt->emin - tfmt->emax - tfmt->p - 2
+         && ifmt->emax > 2 * tfmt->emax + 2
+         && ifmt->emax > tfmt->emax - tfmt->emin + tfmt->p + 2
+         && ifmt->round_towards_zero == tfmt->round_towards_zero
+         && (ifmt->has_sign_dependent_rounding
+             == tfmt->has_sign_dependent_rounding)
+         && ifmt->has_nans >= tfmt->has_nans
+         && ifmt->has_inf >= tfmt->has_inf
+         && ifmt->has_signed_zero >= tfmt->has_signed_zero
+         && !MODE_COMPOSITE_P (tmode)
+         && !MODE_COMPOSITE_P (imode));
+}
 \f
 /* Render R as an integer.  */
 
@@ -2131,10 +2171,70 @@ real_from_integer (REAL_VALUE_TYPE *r, enum machine_mode mode,
       normalize (r);
     }
 
-  if (mode != VOIDmode)
+  if (DECIMAL_FLOAT_MODE_P (mode))
+    decimal_from_integer (r);
+  else if (mode != VOIDmode)
     real_convert (r, mode, r);
 }
 
+/* Render R, an integral value, as a floating point constant with no
+   specified exponent.  */
+
+static void
+decimal_integer_string (char *str, const REAL_VALUE_TYPE *r_orig,
+                       size_t buf_size)
+{
+  int dec_exp, digit, digits;
+  REAL_VALUE_TYPE r, pten;
+  char *p;
+  bool sign;
+
+  r = *r_orig;
+
+  if (r.cl == rvc_zero)
+    {
+      strcpy (str, "0.");
+      return;
+    }
+
+  sign = r.sign;
+  r.sign = 0;
+
+  dec_exp = REAL_EXP (&r) * M_LOG10_2;
+  digits = dec_exp + 1;
+  gcc_assert ((digits + 2) < (int)buf_size);
+
+  pten = *real_digit (1);
+  times_pten (&pten, dec_exp);
+
+  p = str;
+  if (sign)
+    *p++ = '-';
+
+  digit = rtd_divmod (&r, &pten);
+  gcc_assert (digit >= 0 && digit <= 9);
+  *p++ = digit + '0';
+  while (--digits > 0)
+    {
+      times_pten (&r, 1);
+      digit = rtd_divmod (&r, &pten);
+      *p++ = digit + '0';
+    }
+  *p++ = '.';
+  *p++ = '\0';
+}
+
+/* Convert a real with an integral value to decimal float.  */
+
+static void
+decimal_from_integer (REAL_VALUE_TYPE *r)
+{
+  char str[256];
+
+  decimal_integer_string (str, r, sizeof (str) - 1);
+  decimal_real_from_string (r, str);
+}
+
 /* Returns 10**2**N.  */
 
 static const REAL_VALUE_TYPE *
@@ -2225,47 +2325,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;
 
-  gcc_assert (e < rv_max);
+  /* 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;
+}
+
+/* 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).  */
+
+const REAL_VALUE_TYPE *
+dconst_sqrt2_ptr (void)
+{
+  static REAL_VALUE_TYPE value;
 
-  return &value[e];
+  /* 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.  */
@@ -2402,7 +2517,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);
     }
 }
 
@@ -2873,6 +2988,7 @@ const struct real_format ieee_single_format =
     true,
     true,
     true,
+    true,
     false
   };
 
@@ -2892,6 +3008,7 @@ const struct real_format mips_single_format =
     true,
     true,
     true,
+    true,
     false,
     true
   };
@@ -2913,6 +3030,7 @@ const struct real_format motorola_single_format =
     true,
     true,
     true,
+    true,
     true
   };
 
@@ -2941,6 +3059,7 @@ const struct real_format spu_single_format =
     true,
     false,
     false,
+    false,
     true,
     true,
     false,
@@ -3152,6 +3271,7 @@ const struct real_format ieee_double_format =
     true,
     true,
     true,
+    true,
     false
   };
 
@@ -3171,6 +3291,7 @@ const struct real_format mips_double_format =
     true,
     true,
     true,
+    true,
     false,
     true
   };
@@ -3192,6 +3313,7 @@ const struct real_format motorola_double_format =
     true,
     true,
     true,
+    true,
     true
   };
 \f
@@ -3530,6 +3652,7 @@ const struct real_format ieee_extended_motorola_format =
     true,
     true,
     true,
+    true,
     true
   };
 
@@ -3550,6 +3673,7 @@ const struct real_format ieee_extended_intel_96_format =
     true,
     true,
     true,
+    true,
     false
   };
 
@@ -3570,6 +3694,7 @@ const struct real_format ieee_extended_intel_128_format =
     true,
     true,
     true,
+    true,
     false
   };
 
@@ -3592,6 +3717,7 @@ const struct real_format ieee_extended_intel_96_round_53_format =
     true,
     true,
     true,
+    true,
     false
   };
 \f
@@ -3679,6 +3805,7 @@ const struct real_format ibm_extended_format =
     true,
     true,
     true,
+    true,
     false
   };
 
@@ -3698,6 +3825,7 @@ const struct real_format mips_extended_format =
     true,
     true,
     true,
+    true,
     false,
     true
   };
@@ -3961,6 +4089,7 @@ const struct real_format ieee_quad_format =
     true,
     true,
     true,
+    true,
     false
   };
 
@@ -3980,6 +4109,7 @@ const struct real_format mips_quad_format =
     true,
     true,
     true,
+    true,
     false,
     true
   };
@@ -4280,6 +4410,7 @@ const struct real_format vax_f_format =
     false,
     false,
     false,
+    false,
     false
   };
 
@@ -4300,6 +4431,7 @@ const struct real_format vax_d_format =
     false,
     false,
     false,
+    false,
     false
   };
 
@@ -4320,6 +4452,7 @@ const struct real_format vax_g_format =
     false,
     false,
     false,
+    false,
     false
   };
 \f
@@ -4385,14 +4518,15 @@ const struct real_format decimal_single_format =
     10, 
     7,
     7,
-    -95,
-    96,
+    -94,
+    97,
     31,
     31,
     false,
     true,
     true,
     true,
+    true,
     true, 
     true,
     false
@@ -4406,8 +4540,8 @@ const struct real_format decimal_double_format =
     10,
     16,
     16,
-    -383,
-    384,
+    -382,
+    385,
     63,
     63,
     false,
@@ -4416,6 +4550,7 @@ const struct real_format decimal_double_format =
     true,
     true,
     true,
+    true,
     false
   };
 
@@ -4427,19 +4562,181 @@ const struct real_format decimal_quad_format =
     10,
     34,
     34,
-    -6143,
-    6144,
+    -6142,
+    6145,
     127,
     127,
     false,
     true,
     true,
+    true,
     true, 
     true, 
     true,
     false
   };
 \f
+/* Encode half-precision floats.  This routine is used both for the IEEE
+   ARM alternative encodings.  */
+static void
+encode_ieee_half (const struct real_format *fmt, long *buf,
+                 const REAL_VALUE_TYPE *r)
+{
+  unsigned long image, sig, exp;
+  unsigned long sign = r->sign;
+  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
+
+  image = sign << 15;
+  sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 11)) & 0x3ff;
+
+  switch (r->cl)
+    {
+    case rvc_zero:
+      break;
+
+    case rvc_inf:
+      if (fmt->has_inf)
+       image |= 31 << 10;
+      else
+       image |= 0x7fff;
+      break;
+
+    case rvc_nan:
+      if (fmt->has_nans)
+       {
+         if (r->canonical)
+           sig = (fmt->canonical_nan_lsbs_set ? (1 << 9) - 1 : 0);
+         if (r->signalling == fmt->qnan_msb_set)
+           sig &= ~(1 << 9);
+         else
+           sig |= 1 << 9;
+         if (sig == 0)
+           sig = 1 << 8;
+
+         image |= 31 << 10;
+         image |= sig;
+       }
+      else
+       image |= 0x3ff;
+      break;
+
+    case rvc_normal:
+      /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
+        whereas the intermediate representation is 0.F x 2**exp.
+        Which means we're off by one.  */
+      if (denormal)
+       exp = 0;
+      else
+       exp = REAL_EXP (r) + 15 - 1;
+      image |= exp << 10;
+      image |= sig;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  buf[0] = image;
+}
+
+/* Decode half-precision floats.  This routine is used both for the IEEE
+   ARM alternative encodings.  */
+static void
+decode_ieee_half (const struct real_format *fmt, REAL_VALUE_TYPE *r,
+                 const long *buf)
+{
+  unsigned long image = buf[0] & 0xffff;
+  bool sign = (image >> 15) & 1;
+  int exp = (image >> 10) & 0x1f;
+
+  memset (r, 0, sizeof (*r));
+  image <<= HOST_BITS_PER_LONG - 11;
+  image &= ~SIG_MSB;
+
+  if (exp == 0)
+    {
+      if (image && fmt->has_denorm)
+       {
+         r->cl = rvc_normal;
+         r->sign = sign;
+         SET_REAL_EXP (r, -14);
+         r->sig[SIGSZ-1] = image << 1;
+         normalize (r);
+       }
+      else if (fmt->has_signed_zero)
+       r->sign = sign;
+    }
+  else if (exp == 31 && (fmt->has_nans || fmt->has_inf))
+    {
+      if (image)
+       {
+         r->cl = rvc_nan;
+         r->sign = sign;
+         r->signalling = (((image >> (HOST_BITS_PER_LONG - 2)) & 1)
+                          ^ fmt->qnan_msb_set);
+         r->sig[SIGSZ-1] = image;
+       }
+      else
+       {
+         r->cl = rvc_inf;
+         r->sign = sign;
+       }
+    }
+  else
+    {
+      r->cl = rvc_normal;
+      r->sign = sign;
+      SET_REAL_EXP (r, exp - 15 + 1);
+      r->sig[SIGSZ-1] = image | SIG_MSB;
+    }
+}
+
+/* Half-precision format, as specified in IEEE 754R.  */
+const struct real_format ieee_half_format =
+  {
+    encode_ieee_half,
+    decode_ieee_half,
+    2,
+    11,
+    11,
+    -13,
+    16,
+    15,
+    15,
+    false,
+    true,
+    true,
+    true,
+    true,
+    true,
+    true,
+    false
+  };
+
+/* ARM's alternative half-precision format, similar to IEEE but with
+   no reserved exponent value for NaNs and infinities; rather, it just
+   extends the range of exponents by one.  */
+const struct real_format arm_half_format =
+  {
+    encode_ieee_half,
+    decode_ieee_half,
+    2,
+    11,
+    11,
+    -13,
+    17,
+    15,
+    15,
+    false,
+    true,
+    false,
+    false,
+    true,
+    true,
+    false,
+    false
+  };
+\f
 /* A synthetic "format" for internal arithmetic.  It's the size of the
    internal significand minus the two bits needed for proper rounding.
    The encode and decode routines exist only to satisfy our paranoia
@@ -4476,6 +4773,7 @@ const struct real_format real_internal_format =
     -1,
     -1,
     false,
+    false,
     true,
     true,
     false,