OSDN Git Service

* tree-loop-linear.c (try_interchange_loops): Compare memory access
[pf3gnuchains/gcc-fork.git] / gcc / dfp.c
index 804f203..88ffded 100644 (file)
--- a/gcc/dfp.c
+++ b/gcc/dfp.c
@@ -1,11 +1,11 @@
 /* Decimal floating point support.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 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
@@ -14,9 +14,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 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"
@@ -32,29 +31,11 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    decNumber structure is large enough to hold decimal128 digits.  */
 
 #include "decimal128.h"
+#include "decimal128Local.h"
 #include "decimal64.h"
 #include "decimal32.h"
 #include "decNumber.h"
 
-static uint32_t
-dfp_byte_swap (uint32_t in)
-{
-  uint32_t out = 0;
-  unsigned char *p = (unsigned char *) &out;
-  union {
-    uint32_t i;
-    unsigned char b[4];
-  } u;
-
-  u.i = in;
-  p[0] = u.b[3];
-  p[1] = u.b[2];
-  p[2] = u.b[1];
-  p[3] = u.b[0];
-
-  return out;
-}
-
 /* Initialize R (a real with the decimal flag set) from DN.  Can
    utilize status passed in via CONTEXT, if a previous operation had
    interesting status.  */
@@ -96,7 +77,7 @@ decimal_real_from_string (REAL_VALUE_TYPE *r, const char *s)
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
 
-  decNumberFromString (&dn, (char *) s, &set);
+  decNumberFromString (&dn, s, &set);
 
   /* It would be more efficient to store directly in decNumber format,
      but that is impractical from current data structure size.
@@ -119,17 +100,17 @@ decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn)
       decNumberZero (dn);
       break;
     case rvc_inf:
-      decNumberFromString (dn, (char *)"Infinity", &set);
+      decNumberFromString (dn, "Infinity", &set);
       break;
     case rvc_nan:
       if (r->signalling)
-        decNumberFromString (dn, (char *)"snan", &set);
+        decNumberFromString (dn, "snan", &set);
       else
-        decNumberFromString (dn, (char *)"nan", &set);
+        decNumberFromString (dn, "nan", &set);
       break;
     case rvc_normal:
       gcc_assert (r->decimal);
-      decimal128ToNumber ((decimal128 *) r->sig, dn);
+      decimal128ToNumber ((const decimal128 *) r->sig, dn);
       break;
     default:
       gcc_unreachable ();
@@ -137,12 +118,12 @@ decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn)
 
   /* Fix up sign bit.  */
   if (r->sign != decNumberIsNegative (dn))
-    decNumberNegate (dn);
+    dn->bits ^= DECNEG;
 }
 
 /* Encode a real into an IEEE 754R decimal32 type.  */
 
-void 
+void
 encode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
                  long *buf, const REAL_VALUE_TYPE *r)
 {
@@ -156,16 +137,14 @@ encode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decimal_to_decnumber (r, &dn); 
   decimal32FromNumber (&d32, &dn, &set);
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    buf[0] = *(uint32_t *) d32.bytes;
-  else
-    buf[0] = dfp_byte_swap (*(uint32_t *) d32.bytes);
+  buf[0] = *(uint32_t *) d32.bytes;
 }
 
 /* Decode an IEEE 754R decimal32 type into a real.  */
 
-void decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
-                      REAL_VALUE_TYPE *r, const long *buf)
+void
+decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
+                 REAL_VALUE_TYPE *r, const long *buf)
 {
   decNumber dn;
   decimal32 d32;
@@ -174,10 +153,7 @@ void decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    *((uint32_t *) d32.bytes) = (uint32_t) buf[0];
-  else
-    *((uint32_t *) d32.bytes) = dfp_byte_swap ((uint32_t) buf[0]);
+  *((uint32_t *) d32.bytes) = (uint32_t) buf[0];
 
   decimal32ToNumber (&d32, &dn);
   decimal_from_decnumber (r, &dn, &set); 
@@ -185,7 +161,7 @@ void decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
 
 /* Encode a real into an IEEE 754R decimal64 type.  */
 
-void 
+void
 encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
                  long *buf, const REAL_VALUE_TYPE *r)
 {
@@ -199,21 +175,13 @@ encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decimal_to_decnumber (r, &dn);
   decimal64FromNumber (&d64, &dn, &set);
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    {
-      buf[0] = *(uint32_t *) &d64.bytes[0];
-      buf[1] = *(uint32_t *) &d64.bytes[4];
-    }
-  else
-    {
-      buf[1] = dfp_byte_swap (*(uint32_t *) &d64.bytes[0]);
-      buf[0] = dfp_byte_swap (*(uint32_t *) &d64.bytes[4]);
-    }
+  buf[0] = *(uint32_t *) &d64.bytes[0];
+  buf[1] = *(uint32_t *) &d64.bytes[4];
 }
 
 /* Decode an IEEE 754R decimal64 type into a real.  */
 
-void 
+void
 decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
                  REAL_VALUE_TYPE *r, const long *buf)
 { 
@@ -224,16 +192,8 @@ decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    {
-      *((uint32_t *) &d64.bytes[0]) = (uint32_t) buf[0];
-      *((uint32_t *) &d64.bytes[4]) = (uint32_t) buf[1];
-    }
-  else
-    {
-      *((uint32_t *) &d64.bytes[0]) = dfp_byte_swap ((uint32_t) buf[1]);
-      *((uint32_t *) &d64.bytes[4]) = dfp_byte_swap ((uint32_t) buf[0]); 
-    }
+  *((uint32_t *) &d64.bytes[0]) = (uint32_t) buf[0];
+  *((uint32_t *) &d64.bytes[4]) = (uint32_t) buf[1];
 
   decimal64ToNumber (&d64, &dn);
   decimal_from_decnumber (r, &dn, &set); 
@@ -241,7 +201,7 @@ decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
 
 /* Encode a real into an IEEE 754R decimal128 type.  */
 
-void 
+void
 encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
                   long *buf, const REAL_VALUE_TYPE *r)
 {
@@ -255,25 +215,15 @@ encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decimal_to_decnumber (r, &dn);
   decimal128FromNumber (&d128, &dn, &set);
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    {
-      buf[0] = *(uint32_t *) &d128.bytes[0];
-      buf[1] = *(uint32_t *) &d128.bytes[4];
-      buf[2] = *(uint32_t *) &d128.bytes[8];
-      buf[3] = *(uint32_t *) &d128.bytes[12];
-    }
-  else
-    {
-      buf[0] = dfp_byte_swap (*(uint32_t *) &d128.bytes[12]);
-      buf[1] = dfp_byte_swap (*(uint32_t *) &d128.bytes[8]);
-      buf[2] = dfp_byte_swap (*(uint32_t *) &d128.bytes[4]);
-      buf[3] = dfp_byte_swap (*(uint32_t *) &d128.bytes[0]);
-    }
+  buf[0] = *(uint32_t *) &d128.bytes[0];
+  buf[1] = *(uint32_t *) &d128.bytes[4];
+  buf[2] = *(uint32_t *) &d128.bytes[8];
+  buf[3] = *(uint32_t *) &d128.bytes[12];
 }
 
 /* Decode an IEEE 754R decimal128 type into a real.  */
 
-void 
+void
 decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
                   REAL_VALUE_TYPE *r, const long *buf)
 {
@@ -284,20 +234,10 @@ decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    {
-      *((uint32_t *) &d128.bytes[0])  = (uint32_t) buf[0];
-      *((uint32_t *) &d128.bytes[4])  = (uint32_t) buf[1];
-      *((uint32_t *) &d128.bytes[8])  = (uint32_t) buf[2];
-      *((uint32_t *) &d128.bytes[12]) = (uint32_t) buf[3];
-    }
-  else
-    {
-      *((uint32_t *) &d128.bytes[0])  = dfp_byte_swap ((uint32_t) buf[3]);
-      *((uint32_t *) &d128.bytes[4])  = dfp_byte_swap ((uint32_t) buf[2]);
-      *((uint32_t *) &d128.bytes[8])  = dfp_byte_swap ((uint32_t) buf[1]);
-      *((uint32_t *) &d128.bytes[12]) = dfp_byte_swap ((uint32_t) buf[0]);
-    }
+  *((uint32_t *) &d128.bytes[0])  = (uint32_t) buf[0];
+  *((uint32_t *) &d128.bytes[4])  = (uint32_t) buf[1];
+  *((uint32_t *) &d128.bytes[8])  = (uint32_t) buf[2];
+  *((uint32_t *) &d128.bytes[12]) = (uint32_t) buf[3];
 
   decimal128ToNumber (&d128, &dn);
   decimal_from_decnumber (r, &dn, &set); 
@@ -311,8 +251,7 @@ decimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from,
                   enum machine_mode mode)
 {
   char string[256];
-  decimal128 *d128;
-  d128 = (decimal128 *) from->sig;
+  const decimal128 *const d128 = (const decimal128 *) from->sig;
 
   decimal128ToString (d128, string);
   real_from_string3 (to, string, mode);
@@ -359,8 +298,8 @@ decimal_do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
   /* Convert into decNumber form for comparison operation.  */
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;  
-  decimal128ToNumber ((decimal128 *) a->sig, &dn2);
-  decimal128ToNumber ((decimal128 *) b->sig, &dn3);
+  decimal128ToNumber ((const decimal128 *) a->sig, &dn2);
+  decimal128ToNumber ((const decimal128 *) b->sig, &dn3);
 
   /* Finally, do the comparison.  */
   decNumberCompare (&dn, &dn2, &dn3, &set);
@@ -444,12 +383,13 @@ decimal_real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode,
    CROP_TRAILING_ZEROS, strip trailing zeros.  Currently, not honoring
    DIGITS or CROP_TRAILING_ZEROS.  */
 
-void decimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig,
-                             size_t buf_size,
-                             size_t digits ATTRIBUTE_UNUSED,
-                             int crop_trailing_zeros ATTRIBUTE_UNUSED)
+void
+decimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig,
+                        size_t buf_size,
+                        size_t digits ATTRIBUTE_UNUSED,
+                        int crop_trailing_zeros ATTRIBUTE_UNUSED)
 {
-  decimal128 *d128 = (decimal128*) r_orig->sig;
+  const decimal128 *const d128 = (const decimal128*) r_orig->sig;
 
   /* decimal128ToString requires space for at least 24 characters;
      Require two more for suffix.  */
@@ -538,7 +478,7 @@ decimal_do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
   set.round = DEC_ROUND_DOWN;
-  decimal128ToNumber ((decimal128 *) a->sig, &dn2);
+  decimal128ToNumber ((const decimal128 *) a->sig, &dn2);
 
   decNumberToIntegralValue (&dn, &dn2, &set);
   decimal_from_decnumber (r, &dn, &set);
@@ -557,7 +497,7 @@ decimal_real_to_integer (const REAL_VALUE_TYPE *r)
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
   set.round = DEC_ROUND_DOWN;
-  decimal128ToNumber ((decimal128 *) r->sig, &dn);
+  decimal128ToNumber ((const decimal128 *) r->sig, &dn);
 
   decNumberToIntegralValue (&dn2, &dn, &set);
   decNumberZero (&dn3);
@@ -584,7 +524,7 @@ decimal_real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
   set.round = DEC_ROUND_DOWN;
-  decimal128ToNumber ((decimal128 *) r->sig, &dn);
+  decimal128ToNumber ((const decimal128 *) r->sig, &dn);
 
   decNumberToIntegralValue (&dn2, &dn, &set);
   decNumberZero (&dn3);
@@ -597,49 +537,42 @@ decimal_real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
   real_to_integer2 (plow, phigh, &to);
 }
 
-/* Perform the decimal floating point operation described by COODE.
-   For a unary operation, leave OP1 NULL.  This function returns true
-   if the result may be inexact due to loss of precision.  */
+/* Perform the decimal floating point operation described by CODE.
+   For a unary operation, OP1 will be NULL.  This function returns
+   true if the result may be inexact due to loss of precision.  */
 
 bool
-decimal_real_arithmetic (REAL_VALUE_TYPE *r, int icode,
+decimal_real_arithmetic (REAL_VALUE_TYPE *r, enum tree_code code,
                         const REAL_VALUE_TYPE *op0,
                         const REAL_VALUE_TYPE *op1)
 {
-  enum tree_code code = icode;
-  REAL_VALUE_TYPE a1;
-  REAL_VALUE_TYPE b1;
+  REAL_VALUE_TYPE a, b;
 
-  /* If either op is not a decimal, create a temporary decimal
-     versions.  */
+  /* If either operand is non-decimal, create temporaries.  */
   if (!op0->decimal)
     {
-      decimal_from_binary (&a1, op0);
-      op0 = &a1;
+      decimal_from_binary (&a, op0);
+      op0 = &a;
     }
   if (op1 && !op1->decimal)
     {
-      decimal_from_binary (&b1, op1);
-      op1 = &b1;
+      decimal_from_binary (&b, op1);
+      op1 = &b;
     }
 
   switch (code)
     {
     case PLUS_EXPR:
-      (void) decimal_do_add (r, op0, op1, 0);
-      break;
+      return decimal_do_add (r, op0, op1, 0);
 
     case MINUS_EXPR:
-      (void) decimal_do_add (r, op0, op1, 1);
-      break;
+      return decimal_do_add (r, op0, op1, 1);
 
     case MULT_EXPR:
-      (void) decimal_do_multiply (r, op0, op1);
-      break;
+      return decimal_do_multiply (r, op0, op1);
 
     case RDIV_EXPR:
-      (void) decimal_do_divide (r, op0, op1);
-      break;
+      return decimal_do_divide (r, op0, op1);
 
     case MIN_EXPR:
       if (op1->cl == rvc_nan)
@@ -648,7 +581,7 @@ decimal_real_arithmetic (REAL_VALUE_TYPE *r, int icode,
         *r = *op0;
       else
         *r = *op1;
-      break;
+      return false;
 
     case MAX_EXPR:
       if (op1->cl == rvc_nan)
@@ -657,43 +590,35 @@ decimal_real_arithmetic (REAL_VALUE_TYPE *r, int icode,
         *r = *op1;
       else
         *r = *op0;
-      break;
+      return false;
 
     case NEGATE_EXPR:
       {
-       decimal128 *d128;
        *r = *op0;
-       d128 = (decimal128 *) r->sig;
-       /* Flip high bit.  */
-       d128->bytes[0] ^= 1 << 7;
+       /* Flip sign bit.  */
+       decimal128FlipSign ((decimal128 *) r->sig);
        /* Keep sign field in sync.  */
        r->sign ^= 1;
       }
-      break;
+      return false;
 
     case ABS_EXPR:
       {
-        decimal128 *d128;
         *r = *op0;
-        d128 = (decimal128 *) r->sig;
-       /* Clear high bit.  */
-        d128->bytes[0] &= 0x7f;
+       /* Clear sign bit.  */
+       decimal128ClearSign ((decimal128 *) r->sig);
        /* Keep sign field in sync.  */
        r->sign = 0;
       }
-      break;
+      return false;
 
     case FIX_TRUNC_EXPR:
       decimal_do_fix_trunc (r, op0);
-      break;
+      return false;
 
     default:
       gcc_unreachable ();
     }
-
-  /* FIXME: Indicate all operations as inexact for now due to unknown
-     working precision.  */
-  return true;
 }
 
 /* Fills R with the largest finite value representable in mode MODE.
@@ -702,18 +627,18 @@ decimal_real_arithmetic (REAL_VALUE_TYPE *r, int icode,
 void
 decimal_real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
 { 
-  char *max;
+  const char *max;
 
   switch (mode)
     {
     case SDmode:
-      max = (char *) "9.999999E96";
+      max = "9.999999E96";
       break;
     case DDmode:
-      max = (char *) "9.999999999999999E384";
+      max = "9.999999999999999E384";
       break;
     case TDmode:
-      max = (char *) "9.999999999999999999999999999999999E6144";
+      max = "9.999999999999999999999999999999999E6144";
       break;
     default:
       gcc_unreachable ();
@@ -721,5 +646,5 @@ decimal_real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
 
   decimal_real_from_string (r, max);
   if (sign)
-    r->sig[0] |= 0x80000000;
+    decimal128SetSign ((decimal128 *) r->sig, 1);
 }