OSDN Git Service

* real.h: Don't define REAL_INFINITY or REAL_IS_NOT_DOUBLE.
authorzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 23 Mar 2002 01:10:56 +0000 (01:10 +0000)
committerzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 23 Mar 2002 01:10:56 +0000 (01:10 +0000)
Always make REAL_VALUE_TYPE a struct containing an array of
HOST_WIDE_INT, not a double.  Tidy up the code deciding how
big it is.  Don't declare or use union real_extract.

* emit-rtl.c (init_emit_once), varasm.c (immed_real_const_1,
decode_rtx_const, output_constant_pool), config/a29k/a29k.c
(print_operand), config/arm/arm.c (output_move_double),
config/arm/arm.md (consttable_4, consttable_8),
config/romp/romp.c (output_fpops), config/s390/s390.h
(ASM_OUTPUT_SPECIAL_POOL_ENTRY), config/xtensa/xtensa.c
(xtensa_output_literal): Don't use union real_extract.

* config/dsp16xx/dsp16xx.c (print_operand), config/i860/i860.c
(sfmode_constant_to_ulong), config/ns32k/merlin.h
(PRINT_OPERAND), config/ns32k/ns32k.c (print_operand),
config/pdp11/pdp11.h (PRINT_OPERAND), config/we32k/we32k.h
(PRINT_OPERAND): Don't use local version of union
real_extract.

* config/convex/convex.c (check_float_value), config/vax/vax.c
(vax_float_literal), config/m88k/m88k.md (divdf3),
config/dsp16xx/dsp16xx.md (fixuns_trunchfhi2),
config/pdp11/pdp11.c (output_move_quad): Don't do host
arithmetic on target floating point quantities.

* config/a29k/a29k.md, config/dsp16xx/dsp16xx.c
(output_dsp16xx_float_const): Don't test HOST_FLOAT_FORMAT.

* fold-const.c (fold), simplify-rtx.c (simplify_binary_real):
Use MODE_HAS_INFINITIES rather than #ifdef REAL_INFINITY.

* real.c (earith): Test INFINITY rather than REAL_INFINITY;
NANS implies INFINITY, so can drop #ifdef NANS inside #ifndef
INFINITY.
* print-rtl.c (print_rtx): Disable code which needs
floating-point emulator.
* libgcc2.c: Include float.h and use DBL_MANT_DIG,
FLT_MANT_DIG, to define DF_SIZE and SF_SIZE, rather than
depending on HOST_FLOAT_FORMAT to be defined properly.

* ch/grant.c, cp/error.c: Always use REAL_VALUE_TO_DECIMAL;
don't test REAL_IS_NOT_DOUBLE.

* config/1750a/1750a.c (get_double, float_label): Delete.
(print_operand): Delete huge commented-out chunk.  Use
REAL_VALUE_TO_DECIMAL.
* config/1750a/1750a-protos.h: Delete prototypes of deleted
functions.
* config/convex/convex.h: Always set TARGET_FLOAT_FORMAT to
IEEE_FLOAT_FORMAT.
* config/i370/i370.h (PRINT_OPERAND [TARGET_HLASM version]):
Use REAL_VALUE_TO_DECIMAL as ELF version does.
* config/m88k/m88k.c (real_power_of_2_operand,
legitimize_operand): Take the REAL_VALUE_TYPE and/or union
real_extract out of the union; run the input through
REAL_VALUE_TO_TARGET_DOUBLE, then plug the pair of longwords
from that into the union.
* config/pdp11/pdp11.c (output_move_double): Rearrange
parentheses to make automatic indenter happy.

* doc/tm.texi (Cross-compilation): Rename node to "Floating
Point" and rewrite to describe current situation.  Also adjust
documentation of REAL_VALUE_TO_TARGET_SINGLE and friends to
match code.
* doc/rtl.texi: Adjust cross reference.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@51210 138bc75d-0d04-0410-961f-82ee72b054a4

38 files changed:
gcc/ChangeLog
gcc/ch/ChangeLog
gcc/ch/grant.c
gcc/config/1750a/1750a-protos.h
gcc/config/1750a/1750a.c
gcc/config/a29k/a29k.c
gcc/config/a29k/a29k.md
gcc/config/arm/arm.c
gcc/config/arm/arm.md
gcc/config/convex/convex.c
gcc/config/convex/convex.h
gcc/config/dsp16xx/dsp16xx.c
gcc/config/dsp16xx/dsp16xx.md
gcc/config/i370/i370.h
gcc/config/i860/i860.c
gcc/config/m88k/m88k.c
gcc/config/m88k/m88k.md
gcc/config/ns32k/merlin.h
gcc/config/ns32k/ns32k.c
gcc/config/pdp11/pdp11.c
gcc/config/pdp11/pdp11.h
gcc/config/romp/romp.c
gcc/config/s390/s390.h
gcc/config/vax/vax.c
gcc/config/we32k/we32k.h
gcc/config/xtensa/xtensa.c
gcc/cp/ChangeLog
gcc/cp/error.c
gcc/doc/rtl.texi
gcc/doc/tm.texi
gcc/emit-rtl.c
gcc/fold-const.c
gcc/libgcc2.c
gcc/print-rtl.c
gcc/real.c
gcc/real.h
gcc/simplify-rtx.c
gcc/varasm.c

index 1616ef6..287ddeb 100644 (file)
@@ -1,3 +1,69 @@
+2002-03-22  Zack Weinberg  <zack@codesourcery.com>
+
+       * real.h: Don't define REAL_INFINITY or REAL_IS_NOT_DOUBLE.
+       Always make REAL_VALUE_TYPE a struct containing an array of
+       HOST_WIDE_INT, not a double.  Tidy up the code deciding how
+       big it is.  Don't declare or use union real_extract.
+
+       * emit-rtl.c (init_emit_once), varasm.c (immed_real_const_1,
+       decode_rtx_const, output_constant_pool), config/a29k/a29k.c
+       (print_operand), config/arm/arm.c (output_move_double),
+       config/arm/arm.md (consttable_4, consttable_8),
+       config/romp/romp.c (output_fpops), config/s390/s390.h
+       (ASM_OUTPUT_SPECIAL_POOL_ENTRY), config/xtensa/xtensa.c
+       (xtensa_output_literal): Don't use union real_extract.
+
+       * config/dsp16xx/dsp16xx.c (print_operand), config/i860/i860.c
+       (sfmode_constant_to_ulong), config/ns32k/merlin.h
+       (PRINT_OPERAND), config/ns32k/ns32k.c (print_operand),
+       config/pdp11/pdp11.h (PRINT_OPERAND), config/we32k/we32k.h
+       (PRINT_OPERAND): Don't use local version of union
+       real_extract.
+
+       * config/convex/convex.c (check_float_value), config/vax/vax.c
+       (vax_float_literal), config/m88k/m88k.md (divdf3),
+       config/dsp16xx/dsp16xx.md (fixuns_trunchfhi2),
+       config/pdp11/pdp11.c (output_move_quad): Don't do host
+       arithmetic on target floating point quantities.
+
+       * config/a29k/a29k.md, config/dsp16xx/dsp16xx.c
+       (output_dsp16xx_float_const): Don't test HOST_FLOAT_FORMAT.
+
+       * fold-const.c (fold), simplify-rtx.c (simplify_binary_real):
+       Use MODE_HAS_INFINITIES rather than #ifdef REAL_INFINITY.
+
+       * real.c (earith): Test INFINITY rather than REAL_INFINITY;
+       NANS implies INFINITY, so can drop #ifdef NANS inside #ifndef
+       INFINITY.
+       * print-rtl.c (print_rtx): Disable code which needs
+       floating-point emulator.
+       * libgcc2.c: Include float.h and use DBL_MANT_DIG,
+       FLT_MANT_DIG, to define DF_SIZE and SF_SIZE, rather than
+       depending on HOST_FLOAT_FORMAT to be defined properly.
+
+       * config/1750a/1750a.c (get_double, float_label): Delete.
+       (print_operand): Delete huge commented-out chunk.  Use
+       REAL_VALUE_TO_DECIMAL.
+       * config/1750a/1750a-protos.h: Delete prototypes of deleted
+       functions.
+       * config/convex/convex.h: Always set TARGET_FLOAT_FORMAT to
+       IEEE_FLOAT_FORMAT.
+       * config/i370/i370.h (PRINT_OPERAND [TARGET_HLASM version]):
+       Use REAL_VALUE_TO_DECIMAL as ELF version does.
+       * config/m88k/m88k.c (real_power_of_2_operand,
+       legitimize_operand): Take the REAL_VALUE_TYPE and/or union
+       real_extract out of the union; run the input through
+       REAL_VALUE_TO_TARGET_DOUBLE, then plug the pair of longwords
+       from that into the union.
+       * config/pdp11/pdp11.c (output_move_double): Rearrange
+       parentheses to make automatic indenter happy.
+
+       * doc/tm.texi (Cross-compilation): Rename node to "Floating
+       Point" and rewrite to describe current situation.  Also adjust
+       documentation of REAL_VALUE_TO_TARGET_SINGLE and friends to
+       match code.
+       * doc/rtl.texi: Adjust cross reference.
+
 2002-03-22  Bob Wilson  <bob.wilson@acm.org>
 
        * config/xtensa/xtensa-protos.h (non_acc_reg_operand): Remove.
 
 2002-03-22  Neil Booth  <neil@daikokuya.demon.co.uk>
 
-        * cpphash.h (struct cpp_reader): Remove mls_line and mls_col.
-        * cpplex.c (unterminated): Delete.
-        (parse_string): No string literal may extend over multiple
-        lines.  Suppress the error when preprocessing assembly.
+       * cpphash.h (struct cpp_reader): Remove mls_line and mls_col.
+       * cpplex.c (unterminated): Delete.
+       (parse_string): No string literal may extend over multiple
+       lines.  Suppress the error when preprocessing assembly.
        * cppmain.c (scan_translation_unit): Strings are single-line.
 
-        * doc/cpp.texi: Update to match.
+       * doc/cpp.texi: Update to match.
 
 2002-03-22  Jakub Jelinek  <jakub@redhat.com>
 
@@ -495,7 +561,7 @@ Tue Mar 19 14:12:32 2002  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
 2002-03-18  Mark Mitchell  <mark@codesourcery.com>
 
-       * calls.c (precompute_arguments): Do not assume that temporaries 
+       * calls.c (precompute_arguments): Do not assume that temporaries
        can be destroyed after expanding the argument.
        (expand_call): Likewise.
 
index df0d0f5..5dafdbb 100644 (file)
@@ -1,3 +1,8 @@
+2002-03-22  Zack Weinberg  <zack@codesourcery.com>
+
+       * grant.c: Always use REAL_VALUE_TO_DECIMAL; don't test
+       REAL_IS_NOT_DOUBLE.
+
 2002-03-12  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * decl.c (chill_tree_code_type, chill_tree_code_length,
index f143aec..48973e0 100644 (file)
@@ -1851,11 +1851,7 @@ decode_constant (init)
       return result;
 
     case REAL_CST:
-#ifndef REAL_IS_NOT_DOUBLE
-      sprintf (wrk, "%.20g", TREE_REAL_CST (val));
-#else
       REAL_VALUE_TO_DECIMAL (TREE_REAL_CST (val), "%.20g", wrk);
-#endif
       APPEND (result, wrk);
       return result;
 
index aa2b41f..c437f00 100644 (file)
@@ -26,7 +26,6 @@ extern struct rtx_def *function_arg PARAMS ((int, enum machine_mode, tree, int))
 extern const char *movcnt_regno_adjust PARAMS ((rtx *));
 extern const char *mod_regno_adjust PARAMS ((const char *, rtx *));
 extern void notice_update_cc PARAMS ((rtx));
-extern double get_double PARAMS ((rtx));
 extern int memop_valid PARAMS ((rtx));
 extern int mov_memory_operand PARAMS ((rtx, enum machine_mode));
 extern int small_nonneg_const PARAMS ((rtx, enum machine_mode));
@@ -38,7 +37,6 @@ extern void print_operand PARAMS ((FILE *, rtx, int));
 extern void print_operand_address PARAMS ((FILE *, rtx));
 #endif /* RTX_CODE */
 
-extern char *float_label PARAMS ((int, double));
 extern const char *branch_or_jump PARAMS ((const char *, int));
 extern int find_jmplbl PARAMS ((int));
 extern int one_bit_set_p PARAMS ((int));
index 099f7c7..c8b6a79 100644 (file)
@@ -239,44 +239,6 @@ function_arg (cum, mode, type, named)
     return (rtx) 0;
 }
 
-
-double
-get_double (x)
-     rtx x;
-{
-  union
-    {
-      double d;
-      long i[2];
-    }
-  du;
-
-  du.i[0] = CONST_DOUBLE_LOW (x);
-  du.i[1] = CONST_DOUBLE_HIGH (x);
-  return du.d;
-}
-
-char *
-float_label (code, value)
-     int code;
-     double value;
-{
-  static char label[32];
-  char *p;
-
-  label[0] = code;
-  p = label + 1;
-  sprintf (p, "%f", value);
-  while (*p)
-    {
-      *p = (*p == '+') ? 'p' :
-       (*p == '-') ? 'm' : *p;
-      p++;
-    }
-  return xstrdup (label);
-}
-
-
 const char *
 movcnt_regno_adjust (op)
      rtx *op;
@@ -588,59 +550,15 @@ print_operand (file, x, letter)
       break;
 
     case CONST_DOUBLE:
-/*    {
-       double value = get_double (x);
-       char fltstr[32];
-       sprintf (fltstr, "%f", value);
+      {
+       REAL_VALUE_TYPE r;
+       char buf[30];
 
-       if (letter == 'D' || letter == 'E')
-         {
-           int i, found = 0;
-           for (i = 0; i <= datalbl_ndx; i++)
-             if (strcmp (fltstr, datalbl[i].value) == 0)
-               {
-                 found = 1;
-                 break;
-               }
-           if (!found)
-             {
-               strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
-               datalbl[i].name = float_label (letter, value);
-               datalbl[i].size = (letter == 'E') ? 3 : 2;
-               check_section (Konst);
-               fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
-                       (letter == 'E' ? "ef" : "f"), fltstr);
-               check_section (Normal);
-             }
-         }
-       else if (letter == 'F' || letter == 'G')
-         {
-           int i, found = 0;
-           for (i = 0; i <= datalbl_ndx; i++)
-             if (strcmp (fltstr, datalbl[i].value) == 0)
-               {
-                 found = 1;
-                 break;
-               }
-           if (!found)
-             {
-               fprintf (stderr,
-                  "float value %f not found upon label reference\n", value);
-               strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
-               datalbl[i].name = float_label (letter, value);
-               datalbl[i].size = (letter == 'G') ? 3 : 2;
-               check_section (Konst);
-               fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
-                       (letter == 'G' ? "ef" : "f"), fltstr);
-               check_section (Normal);
-             }
-           fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
-         }
-       else
-         fprintf (file, " %s  ;P_O cst_dbl ", fltstr);
+       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+       REAL_VALUE_TO_DECIMAL (r, "%f", buf);
+
+       fputs (buf, file);
       }
- */
-      fprintf (file, "%f", get_double (x));
       break;
 
     case CONST_INT:
index 3291bab..bd08c38 100644 (file)
@@ -1143,10 +1143,13 @@ print_operand (file, x, code)
     case 'L':
       if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
        {
-         union real_extract u;
+         REAL_VALUE_TYPE r;
+         char s[30];
 
-         memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (x), sizeof u);
-         fprintf (file, "$double1(%.20e)", u.d);
+         REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+         REAL_VALUE_TO_DECIMAL (r, "%.20e", s);
+
+         fprintf (file, "$double1(%s)", s);
        }
       else if (GET_CODE (x) == REG)
        fprintf (file, "%s", reg_names[REGNO (x) + 1]);
@@ -1204,26 +1207,30 @@ print_operand (file, x, code)
   else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == SUBREG
           && GET_CODE (SUBREG_REG (XEXP (x, 0))) == CONST_DOUBLE)
     {
-      union real_extract u;
+      REAL_VALUE_TYPE r;
+      char s[30];
 
       if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode)
        fprintf (file, "$float");
       else
        fprintf (file, "$double%d", 
-                (SUBREG_BYTE (XEXP (x, 0)) / GET_MODE_SIZE (GET_MODE (x))));      
-      memcpy ((char *) &u,
-             (char *) &CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), sizeof u);
-      fprintf (file, "(%.20e)", u.d);
+                (SUBREG_BYTE (XEXP (x, 0)) / GET_MODE_SIZE (GET_MODE (x))));
+
+      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+      REAL_VALUE_TO_DECIMAL (r, "%.20e", s);
+      fprintf (file, "(%s)", s);
     }
 
   else if (GET_CODE (x) == CONST_DOUBLE
           && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
     {
-      union real_extract u;
+      REAL_VALUE_TYPE r;
+      char s[30];
 
-      memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (x), sizeof u);
-      fprintf (file, "$%s(%.20e)",
-              GET_MODE (x) == SFmode ? "float" : "double0", u.d);
+      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+      REAL_VALUE_TO_DECIMAL (r, "%.20e", s);
+      fprintf (file, "$%s(%s)",
+              GET_MODE (x) == SFmode ? "float" : "double0", s);
     }
 
   else
index 596aa47..d4e4f34 100644 (file)
 (define_split
   [(set (match_operand:SF 0 "register_operand" "")
        (match_operand:SF 1 "float_const_operand" ""))]
-  "HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT"
+  ""
   [(set (match_dup 0)
        (match_dup 1))]
   "
index f07a281..814c84d 100644 (file)
@@ -6534,11 +6534,11 @@ output_move_double (operands)
        {
          if (GET_MODE (operands[1]) == DFmode)
            {
+             REAL_VALUE_TYPE r;
              long l[2];
-             union real_extract u;
 
-             memcpy (&u, &CONST_DOUBLE_LOW (operands[1]), sizeof (u));
-             REAL_VALUE_TO_TARGET_DOUBLE (u.d, l);
+             REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+             REAL_VALUE_TO_TARGET_DOUBLE (r, l);
              otherops[1] = GEN_INT (l[1]);
              operands[1] = GEN_INT (l[0]);
            }
index cdab5c6..9ea7d0c 100644 (file)
       {
       case MODE_FLOAT:
       {
-        union real_extract u;
-        memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
-        assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
+        REAL_VALUE_TYPE r;
+        REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
+        assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
         break;
       }
       default:
       {
        case MODE_FLOAT:
         {
-          union real_extract u;
-          memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
-          assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
+          REAL_VALUE_TYPE r;
+          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
+          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
           break;
         }
       default:
index bee0f17..74af45e 100644 (file)
@@ -515,12 +515,12 @@ expand_movstr_call (operands)
                     TYPE_MODE (sizetype));
 }
 \f
-#if _IEEE_FLOAT_
-#define MAX_FLOAT 3.4028234663852886e+38
-#define MIN_FLOAT 1.1754943508222875e-38
+#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
+#define MAX_FLOAT "3.4028234663852886e+38"
+#define MIN_FLOAT "1.1754943508222875e-38"
 #else
-#define MAX_FLOAT 1.7014117331926443e+38
-#define MIN_FLOAT 2.9387358770557188e-39
+#define MAX_FLOAT "1.7014117331926443e+38"
+#define MIN_FLOAT "2.9387358770557188e-39"
 #endif
 
 int
@@ -530,28 +530,35 @@ check_float_value (mode, dp, overflow)
      int overflow;
 {
   REAL_VALUE_TYPE d = *dp;
+  REAL_VALUE_TYPE maxfloat = REAL_VALUE_ATOF (MAX_FLOAT, mode);
+  REAL_VALUE_TYPE minfloat = REAL_VALUE_ATOF (MIN_FLOAT, mode);
+  REAL_VALUE_TYPE neg_maxfloat = REAL_VALUE_NEGATE (maxfloat);
+  REAL_VALUE_TYPE neg_minfloat = REAL_VALUE_NEGATE (minfloat);
 
   if (overflow)
     {
-      *dp = MAX_FLOAT;
+      *dp = maxfloat;
       return 1;
     }
 
   if (mode == SFmode)
     {
-      if (d > MAX_FLOAT)
+      if (REAL_VALUES_LESS (maxfloat, d))
        {
-         *dp = MAX_FLOAT;
+         *dp = maxfloat;
          return 1;
        }
-      else if (d < -MAX_FLOAT)
+      else if (REAL_VALUES_LESS (d, neg_maxfloat))
        {
-         *dp = -MAX_FLOAT;
+         *dp = neg_maxfloat;
          return 1;
        }       
-      else if ((d > 0 && d < MIN_FLOAT) || (d < 0 && d > -MIN_FLOAT))
+      else if ((REAL_VALUES_LESS (dconst0, d)
+               && REAL_VALUES_LESS (d, minfloat))
+              || (REAL_VALUES_LESS (d, dconst0)
+                  && REAL_VALUES_LESS (neg_minfloat, d)))
        {
-         *dp = 0.0;
+         *dp = dconst0;
          return 1;
        }
     }
@@ -628,16 +635,7 @@ print_operand (file, x, code)
       REAL_VALUE_FROM_CONST_DOUBLE (d, x);
       switch (GET_MODE (x)) {
       case DFmode:
-#if 0 /* doesn't work, produces dfloats */
        REAL_VALUE_TO_TARGET_DOUBLE (d, u); 
-#else
-       {
-         union { double d; int i[2]; } t;
-         t.d = d;
-         u[0] = t.i[0];
-         u[1] = t.i[1];
-       }
-#endif
        if (code == 'u')
          fprintf (file, "#%#lx", u[0]);
        else if (code == 'v')
index 7ed4e45..d50f60b 100644 (file)
@@ -1073,9 +1073,8 @@ enum reg_class {
 
 #define BRANCH_COST 0
 
-/* Convex uses VAX or IEEE floats.
-   Follow the host format.  */
-#define TARGET_FLOAT_FORMAT HOST_FLOAT_FORMAT
+/* Convex uses VAX or IEEE floats.  Default to IEEE.  */
+#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
 
 /* Check a `double' value for validity for a particular machine mode.  */
 #define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
index 674a3f0..7f5cc0b 100644 (file)
@@ -1870,16 +1870,15 @@ print_operand(file, op, letter)
          fprintf (file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff);
         else
            output_addr_const(file, op);
-    }
+      }
     else if (code == CONST_DOUBLE && GET_MODE(op) != DImode)
-    {
-         union { double d; int i[2]; } u;
-         union { float f; int i; } u1;
-         u.i[0] = CONST_DOUBLE_LOW (op);
-         u.i[1] = CONST_DOUBLE_HIGH (op);
-         u1.f = u.d;
-          fprintf (file, "0x%x", u1.i);
-    }
+      {
+       long l;
+       REAL_VALUE_TYPE r;
+       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+       REAL_VALUE_TO_TARGET_SINGLE (r, l);
+       fprintf (file, "0x%x", l);
+      }
     else if (code == CONST)
       {
        rtx addr = XEXP (op, 0);
@@ -1977,7 +1976,6 @@ output_dsp16xx_float_const (operands)
 {
   rtx src = operands[1];
   
-#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
   REAL_VALUE_TYPE d;
   long value;
   
@@ -1986,9 +1984,6 @@ output_dsp16xx_float_const (operands)
   
   operands[1] = GEN_INT (value);
   output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands);
-#else
-  fatal_error ("inline float constants not supported on this host");
-#endif
 }
 
 static int
index 7cea24a..31247ba 100644 (file)
   rtx reg3 = gen_reg_rtx (HImode);
   rtx label1 = gen_label_rtx ();
   rtx label2 = gen_label_rtx ();
-  REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31);
+  REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (dconst1, 31);
 
   if (reg1)                    /* turn off complaints about unreached code */
     {
index 112758c..adcaca6 100644 (file)
@@ -1374,21 +1374,26 @@ enum reg_class
          }                                                             \
        else                                                            \
          {                                                             \
-            /* hack alert -- this prints wildly incorrect values */    \
-            /* when run in cross-compiler mode. See ELF section  */    \
-            /* for suggested fix */                                    \
-           union { double d; int i[2]; } u;                            \
-           u.i[0] = CONST_DOUBLE_LOW (XV);                             \
-           u.i[1] = CONST_DOUBLE_HIGH (XV);                            \
+            char buf[50];                                              \
+            REAL_VALUE_TYPE rval;                                      \
+            REAL_VALUE_FROM_CONST_DOUBLE(rval, XV);                    \
+            REAL_VALUE_TO_DECIMAL (rval, HOST_WIDE_INT_PRINT_DEC, buf);        \
            if (GET_MODE (XV) == SFmode)                                \
              {                                                         \
                mvs_page_lit += 4;                                      \
-               fprintf (FILE, "=E'%.9G'", u.d);                        \
+               fprintf (FILE, "=E'%s'", buf);                          \
              }                                                         \
            else                                                        \
+           if (GET_MODE (XV) == DFmode)                                \
              {                                                         \
                mvs_page_lit += 8;                                      \
-               fprintf (FILE, "=D'%.18G'", u.d);                       \
+               fprintf (FILE, "=D'%s'", buf);                          \
+             }                                                         \
+           else /* VOIDmode !?!? strange but true ...  */              \
+             {                                                         \
+               mvs_page_lit += 8;                                      \
+               fprintf (FILE, "=XL8'%08X%08X'",                        \
+                       CONST_DOUBLE_HIGH (XV), CONST_DOUBLE_LOW (XV)); \
              }                                                         \
          }                                                             \
        break;                                                          \
index 5538baf..1849397 100644 (file)
@@ -1549,17 +1549,14 @@ sfmode_constant_to_ulong (x)
      rtx x;
 {
   REAL_VALUE_TYPE d;
-  union { float f; unsigned long i; } u2;
+  unsigned long l;
 
   if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != SFmode)
     abort ();
 
-#if TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT
- error IEEE emulation needed
-#endif
   REAL_VALUE_FROM_CONST_DOUBLE (d, x);
-  u2.f = d;
-  return u2.i;
+  REAL_VALUE_TO_TARGET_SINGLE (d, l);
+  return l;
 }
 \f
 /* This function generates the assembly code for function entry.
index d53bffd..80f3ff4 100644 (file)
@@ -1123,9 +1123,9 @@ real_power_of_2_operand (op, mode)
      rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
+  REAL_VALUE_TYPE d;
   union {
-    REAL_VALUE_TYPE d;
-    int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)];
+    long l[2];
     struct {                           /* IEEE double precision format */
       unsigned sign     :  1;
       unsigned exponent  : 11;
@@ -1147,8 +1147,8 @@ real_power_of_2_operand (op, mode)
   if (GET_CODE (op) != CONST_DOUBLE)
     return 0;
 
-  u.i[0] = CONST_DOUBLE_LOW  (op);
-  u.i[1] = CONST_DOUBLE_HIGH (op);
+  REAL_VALUE_FROM_CONST_DOUBLE (d, op);
+  REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
 
   if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
       || u.s.exponent == 0                     /* constant 0.0 */
@@ -1169,8 +1169,9 @@ legitimize_operand (op, mode)
      enum machine_mode mode;
 {
   rtx temp;
+  REAL_VALUE_TYPE r;
   union {
-    union real_extract r;
+    long l[2];
     struct {                           /* IEEE double precision format */
       unsigned sign     :  1;
       unsigned exponent  : 11;
@@ -1191,7 +1192,8 @@ legitimize_operand (op, mode)
 
   if (GET_CODE (op) == CONST_DOUBLE)
     {
-      memcpy (&u.r, &CONST_DOUBLE_LOW (op), sizeof u);
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      REAL_VALUE_TO_TARGET_DOUBLE (r, u.l);
       if (u.d.exponent != 0x7ff /* NaN */
          && u.d.mantissa2 == 0 /* Mantissa fits */
          && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
index 75b9d2c..24a66f8 100644 (file)
   operands[1] = legitimize_operand (operands[1], DFmode);
   if (real_power_of_2_operand (operands[2], DFmode))
     {
-      union real_extract u;
-      memcpy (&u, &CONST_DOUBLE_LOW (operands[2]), sizeof u);
+      REAL_VALUE_TYPE r;
+      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
+      if (!exact_real_inverse (DFmode, &r))
+        abort ();
       emit_insn (gen_muldf3 (operands[0], operands[1],
-                            CONST_DOUBLE_FROM_REAL_VALUE (1.0/u.d, DFmode)));
+                            CONST_DOUBLE_FROM_REAL_VALUE (r, DFmode)));
       DONE;
     }
   else if (! register_operand (operands[2], DFmode))
index a3b41ba..f38870d 100644 (file)
@@ -64,8 +64,8 @@ Boston, MA 02111-1307, USA.  */
 
 #ifdef UTEK_ASM
 #undef PRINT_OPERAND
-#define PRINT_OPERAND(FILE, X, CODE)  \
-{ if (CODE == '$') putc('$', FILE);                                    \
+#define PRINT_OPERAND(FILE, X, CODE) do {                              \
+  if (CODE == '$') putc('$', FILE);                                    \
   else if (CODE == '?');                                               \
   else if (GET_CODE (X) == CONST_INT)                                  \
     fprintf(FILE, "$%d", INTVAL(X));                                   \
@@ -116,14 +116,20 @@ Boston, MA 02111-1307, USA.  */
        }                                                               \
     }                                                                  \
   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode)   \
-    if (GET_MODE (X) == DFmode)                                                \
-      { union { double d; int i[2]; } u;                               \
-       u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X);  \
-       fprintf (FILE, "$0d%.20e", u.d); }                              \
-    else { union { double d; int i[2]; } u;                            \
-          u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
-          fprintf (FILE, "$0f%.20e", u.d); }                           \
-  else output_addr_const (FILE, X); }
+    {                                                                  \
+      char buf[50];                                                    \
+      REAL_VALUE_TYPE rval;                                            \
+      REAL_VALUE_FROM_CONST_DOUBLE(rval, XV);                          \
+      REAL_VALUE_TO_DECIMAL (rval, "%.20e", buf);                      \
+      if (GET_MODE (XV) == SFmode)                                     \
+       fprintf (FILE, "$0e%s", buf);                                   \
+      else if (GET_MODE (XV) == DFmode)                                        \
+       fprintf (FILE, "$0d%s", buf);                                   \
+      else                                                             \
+       abort();                                                        \
+    }                                                                  \
+  else output_addr_const (FILE, X);                                    \
+} while (0)
 
 #endif /* UTEK_ASM */
 
index 9feef5e..8c980c5 100644 (file)
@@ -1119,40 +1119,36 @@ print_operand (file, x, code)
     }
   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
     {
+      REAL_VALUE_TYPE r;
+
+      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+      PUT_IMMEDIATE_PREFIX (file);
       if (GET_MODE (x) == DFmode)
        { 
-         union { double d; int i[2]; } u;
-         u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
-         PUT_IMMEDIATE_PREFIX (file);
 #ifdef SEQUENT_ASM
          /* Sequent likes its floating point constants as integers */
-         fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
+         fprintf (file, "0Dx%08x%08x",
+                  CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
 #else
+         char s[30];
+         REAL_VALUE_TO_DECIMAL (r, "%.20e", s);
 #ifdef ENCORE_ASM
-         fprintf (file, "0f%.20e", u.d); 
+         fprintf (file, "0f%s", s);
 #else
-         fprintf (file, "0d%.20e", u.d); 
+         fprintf (file, "0d%s", s);
 #endif
 #endif
        }
       else
-       { 
-         union { double d; int i[2]; } u;
-         u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
-         PUT_IMMEDIATE_PREFIX (file);
+       {
 #ifdef SEQUENT_ASM
-         /* We have no way of winning if we can't get the bits
-            for a sequent floating point number.  */
-#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
-         abort ();
-#endif
-         {
-           union { float f; long l; } uu;
-           uu.f = u.d;
-           fprintf (file, "0Fx%08lx", uu.l);
-         }
+         long l;
+         REAL_VALUE_TO_TARGET_SINGLE (r, l);
+         fprintf (file, "0Fx%08lx", l);
 #else
-         fprintf (file, "0f%.20e", u.d); 
+         char s[30];
+         REAL_VALUE_TO_DECIMAL (r, "%.20e", s);
+         fprintf (file, "0f%s", s);
 #endif
        }
     }
index cff6fbf..3643db6 100644 (file)
@@ -400,10 +400,11 @@ output_move_double (operands)
 
   if (REG_P (operands[1]))
     optype1 = REGOP;
-  else if (CONSTANT_P (operands[1]))
+  else if (CONSTANT_P (operands[1])
 #if 0
-          || GET_CODE (operands[1]) == CONST_DOUBLE)
+          || GET_CODE (operands[1]) == CONST_DOUBLE
 #endif
+          )
     optype1 = CNSTOP;
   else if (offsettable_memref_p (operands[1]))
     optype1 = OFFSOP;
@@ -620,11 +621,10 @@ output_move_quad (operands)
       {
          if (GET_CODE(operands[1]) == CONST_DOUBLE)
          {
-             union { double d; int i[2]; } u;
-             u.i[0] = CONST_DOUBLE_LOW (operands[1]); 
-             u.i[1] = CONST_DOUBLE_HIGH (operands[1]); 
-             
-             if (u.d == 0.0)
+             REAL_VALUE_TYPE r;
+             REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+
+             if (REAL_VALUES_EQUAL (r, dconst0))
                  return "{clrd|clrf} %0";
          }
              
index 53888ee..99bb7fe 100644 (file)
@@ -1140,9 +1140,11 @@ fprintf (FILE, "$help$: . = .+8 ; space for tmp moves!\n")       \
   else if (GET_CODE (X) == MEM)                                                \
     output_address (XEXP (X, 0));                                      \
   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != SImode)     \
-    { union { double d; int i[2]; } u;                                 \
-      u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X);   \
-      fprintf (FILE, "#%.20e", u.d); }                                 \
+    { REAL_VALUE_TYPE r;                                               \
+      char buf[30];                                                    \
+      REAL_VALUE_FROM_CONST_DOUBLE (r, X);                             \
+      REAL_VALUE_TO_DECIMAL (r, "%.20e", buf);                         \
+      fprintf (FILE, "#%s", buf); }                                    \
   else { putc ('$', FILE); output_addr_const_pdp11 (FILE, X); }}
 \f
 /* Print a memory address as an operand to reference that memory location.  */
index 7f984e8..a4813be 100644 (file)
@@ -1962,10 +1962,9 @@ output_fpops (file)
              size_so_far += 4;
              if (GET_CODE (immed[i]) == CONST_DOUBLE)
                {
-                 union real_extract u;
-
-                 memcpy (&u, &CONST_DOUBLE_LOW (immed[i]), sizeof u);
-                 assemble_real (u.d, GET_MODE (immed[i]),
+                 REAL_VALUE_TYPE r;
+                 REAL_VALUE_FROM_CONST_DOUBLE (r, immed[i]);
+                 assemble_real (r, GET_MODE (immed[i]),
                                 GET_MODE_ALIGNMENT (GET_MODE (immed[i])));
                }
              else
index 96d91fa..1ab431e 100644 (file)
@@ -1386,8 +1386,8 @@ extern int s390_nr_constants;
       if (GET_CODE (EXP) != CONST_DOUBLE)                                  \
        abort ();                                                           \
                                                                            \
-      memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (EXP), sizeof u);            \
-      assemble_real (u.d, MODE, ALIGN);                                            \
+      REAL_VALUE_FROM_CONST_DOUBLE (r, EXP);                               \
+      assemble_real (r, MODE, ALIGN);                                      \
       break;                                                               \
                                                                            \
     case MODE_INT:                                                         \
index 8be850a..9665609 100644 (file)
@@ -374,10 +374,8 @@ vax_float_literal(c)
     register rtx c;
 {
   register enum machine_mode mode;
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
+  REAL_VALUE_TYPE r, s;
   int i;
-  union {double d; int i[2];} val;
-#endif
 
   if (GET_CODE (c) != CONST_DOUBLE)
     return 0;
@@ -389,15 +387,20 @@ vax_float_literal(c)
       || c == const_tiny_rtx[(int) mode][2])
     return 1;
 
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
+  REAL_VALUE_FROM_CONST_DOUBLE (r, c);
 
-  val.i[0] = CONST_DOUBLE_LOW (c);
-  val.i[1] = CONST_DOUBLE_HIGH (c);
+  for (i = 0; i < 7; i++)
+    {
+      int x = 1 << i;
+      REAL_VALUE_FROM_INT (s, x, 0, mode);
 
-  for (i = 0; i < 7; i ++)
-    if (val.d == 1 << i || val.d == 1 / (1 << i))
-      return 1;
-#endif
+      if (REAL_VALUES_EQUAL (r, s))
+       return 1;
+      if (!exact_real_inverse (mode, &s))
+       abort ();
+      if (REAL_VALUES_EQUAL (r, s))
+       return 1;
+    }
   return 0;
 }
 
index eec05ab..1bf6805 100644 (file)
@@ -847,13 +847,12 @@ do {                                                      \
     output_address (XEXP (X, 0));                                      \
   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode)     \
          {                                                             \
-         union { double d; long l[2]; } dtem;                          \
-         union { float f; long l; } ftem;                              \
+          REAL_VALUE_TYPE r;                                           \
+          long l;                                                      \
                                                                        \
-         dtem.l[0] = CONST_DOUBLE_LOW (X);                             \
-         dtem.l[1] = CONST_DOUBLE_HIGH (X);                            \
-         ftem.f = dtem.d;                                              \
-         fprintf(FILE, "&0x%lx", ftem.l);                              \
+          REAL_VALUE_FROM_CONST_DOUBLE (r, X);                         \
+          REAL_VALUE_TO_TARGET_SINGLE (r, l);                          \
+          fprintf (FILE, "&0x%lx", l);                                 \
          }                                                             \
   else { putc ('&', FILE); output_addr_const (FILE, X); }}
 \f
index e24525b..a791da0 100644 (file)
@@ -2078,7 +2078,7 @@ xtensa_output_literal (file, x, mode, labelno)
      int labelno;
 {
   long value_long[2];
-  union real_extract u;
+  REAL_VALUE_TYPE r;
   int size;
 
   fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno);
@@ -2089,18 +2089,18 @@ xtensa_output_literal (file, x, mode, labelno)
       if (GET_CODE (x) != CONST_DOUBLE)
        abort ();
 
-      memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (x), sizeof u);
+      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
       switch (mode)
        {
        case SFmode:
-         REAL_VALUE_TO_TARGET_SINGLE (u.d, value_long[0]);
-         fprintf (file, "0x%08lx\t\t# %.12g (float)\n", value_long[0], u.d);
+         REAL_VALUE_TO_TARGET_SINGLE (r, value_long[0]);
+         fprintf (file, "0x%08lx\n", value_long[0]);
          break;
 
        case DFmode:
-         REAL_VALUE_TO_TARGET_DOUBLE (u.d, value_long);
-         fprintf (file, "0x%08lx, 0x%08lx # %.20g (double)\n",
-                  value_long[0], value_long[1], u.d);
+         REAL_VALUE_TO_TARGET_DOUBLE (r, value_long);
+         fprintf (file, "0x%08lx, 0x%08lx\n",
+                  value_long[0], value_long[1]);
          break;
 
        default:
index 87679b8..01a5f67 100644 (file)
@@ -1,3 +1,8 @@
+2002-03-22  Zack Weinberg  <zack@codesourcery.com>
+
+       * error.c: Always use REAL_VALUE_TO_DECIMAL; don't test
+       REAL_IS_NOT_DOUBLE.
+
 2002-03-22  Jeff Knaggs  <jknaggs@redhat.com>
 
        * typeck.c (expand_ptrmemfunc_cst): Scale idx down to an index
index 20352e0..077181f 100644 (file)
@@ -1507,9 +1507,6 @@ dump_expr (t, flags)
       break;
 
     case REAL_CST:
-#ifndef REAL_IS_NOT_DOUBLE
-      sprintf (digit_buffer, "%g", TREE_REAL_CST (t));
-#else
       {
        const unsigned char *p = (const unsigned char *) &TREE_REAL_CST (t);
        size_t i;
@@ -1517,7 +1514,6 @@ dump_expr (t, flags)
        for (i = 0; i < sizeof TREE_REAL_CST (t); i++)
          sprintf (digit_buffer + 2 + 2*i, "%02x", *p++);
       }
-#endif
       output_add_string (scratch_buffer, digit_buffer);
       break;
 
index 58faea9..10c81e4 100644 (file)
@@ -1204,7 +1204,7 @@ If @var{m} is @code{VOIDmode}, the bits of the value are stored in
 
 If the constant is floating point (regardless of its precision), then
 the number of integers used to store the value depends on the size of
-@code{REAL_VALUE_TYPE} (@pxref{Cross-compilation}).  The integers
+@code{REAL_VALUE_TYPE} (@pxref{Floating Point}).  The integers
 represent a floating point number, but not precisely in the target
 machine's or host machine's floating point format.  To convert them to
 the precise bit pattern used by the target machine, use the macro
index 3f37cdb..ac44ee3 100644 (file)
@@ -46,7 +46,7 @@ through the macros defined in the @file{.h} file.
 * PIC::                        Macros for position independent code.
 * Assembler Format::    Defining how to write insns and pseudo-ops to output.
 * Debugging Info::      Defining the format of debugging output.
-* Cross-compilation::   Handling floating point for cross-compilers.
+* Floating Point::      Handling floating point for cross-compilers.
 * Mode Switching::      Insertion of mode-switching instructions.
 * Target Attributes::   Defining target-specific uses of @code{__attribute__}.
 * Misc::                Everything else.
@@ -6051,12 +6051,14 @@ of @code{ASM_OUTPUT_DOUBLE} and the like:
 @findex REAL_VALUE_TO_TARGET_DOUBLE
 @findex REAL_VALUE_TO_TARGET_LONG_DOUBLE
 These translate @var{x}, of type @code{REAL_VALUE_TYPE}, to the target's
-floating point representation, and store its bit pattern in the array of
-@code{long int} whose address is @var{l}.  The number of elements in the
-output array is determined by the size of the desired target floating
-point data type: 32 bits of it go in each @code{long int} array
-element.  Each array element holds 32 bits of the result, even if
-@code{long int} is wider than 32 bits on the host machine.
+floating point representation, and store its bit pattern in the variable
+@var{l}.  For @code{REAL_VALUE_TO_TARGET_SINGLE}, this variable should
+be a simple @code{long int}.  For the others, it should be an array of
+@code{long int}.  The number of elements in this array is determined by
+the size of the desired target floating point data type: 32 bits of it
+go in each @code{long int} array element.  Each array element holds 32
+bits of the result, even if @code{long int} is wider than 32 bits on the
+host machine.
 
 The array element values are designed so that you can print them out
 using @code{fprintf} in the order they should appear in the target
@@ -7753,167 +7755,126 @@ behavior is controlled by @code{OPTIMIZATION_OPTIONS} and
 @code{OVERRIDE_OPTIONS}.
 @end table
 
-@node Cross-compilation
+@node Floating Point
 @section Cross Compilation and Floating Point
 @cindex cross compilation and floating point
 @cindex floating point and cross compilation
 
-While all modern machines use 2's complement representation for integers,
+While all modern machines use twos-complement representation for integers,
 there are a variety of representations for floating point numbers.  This
 means that in a cross-compiler the representation of floating point numbers
 in the compiled program may be different from that used in the machine
 doing the compilation.
 
-@findex atof
 Because different representation systems may offer different amounts of
-range and precision, the cross compiler cannot safely use the host
-machine's floating point arithmetic.  Therefore, floating point constants
-must be represented in the target machine's format.  This means that the
-cross compiler cannot use @code{atof} to parse a floating point constant;
-it must have its own special routine to use instead.  Also, constant
-folding must emulate the target machine's arithmetic (or must not be done
-at all).
-
-The macros in the following table are provided by @file{real.h} for the
-compiler to use.  All parts of the compiler which generate or optimize
+range and precision, all floating point constants must be represented in
+the target machine's format.  Therefore, the cross compiler cannot
+safely use the host machine's floating point arithmetic; it must emulate
+the target's arithmetic.  To ensure consistency, GCC always uses
+emulation to work with floating point values, even when the host and
+target floating point formats are identical.
+
+The following macros are provided by @file{real.h} for the compiler to
+use.  All parts of the compiler which generate or optimize
 floating-point calculations must use these macros.  They may evaluate
 their operands more than once, so operands must not have side effects.
 
-@table @code
-@findex REAL_VALUE_TYPE
-@item REAL_VALUE_TYPE
-A macro for the C data type to be used to hold a floating point value
-in the target machine's format.  Typically this would be a
-@code{struct} containing an array of @code{int}.
-
-@findex REAL_VALUES_EQUAL
-@item REAL_VALUES_EQUAL (@var{x}, @var{y})
-A macro for a C expression which compares for equality the two values,
-@var{x} and @var{y}, both of type @code{REAL_VALUE_TYPE}.
-
-@findex REAL_VALUES_LESS
-@item REAL_VALUES_LESS (@var{x}, @var{y})
-A macro for a C expression which tests whether @var{x} is less than
-@var{y}, both values being of type @code{REAL_VALUE_TYPE} and
-interpreted as floating point numbers in the target machine's
-representation.
-
-@findex REAL_VALUE_LDEXP
+@defmac REAL_VALUE_TYPE
+The C data type to be used to hold a floating point value in the target
+machine's format.  Typically this is a @code{struct} containing an
+array of @code{HOST_WIDE_INT}, but all code should treat it as an opaque
+quantity.
+@end defmac
+
+@deftypefn Macro int REAL_VALUES_EQUAL (REAL_VALUE_TYPE @var{x}, REAL_VALUE_TYPE @var{y})
+Compares for equality the two values, @var{x} and @var{y}.  If the target
+floating point format supports negative zeroes and/or NaNs,
+@samp{REAL_VALUES_EQUAL (-0.0, 0.0)} is true, and
+@samp{REAL_VALUES_EQUAL (NaN, NaN)} is false.
+@end deftypefn
+
+@deftypefn Macro int REAL_VALUES_LESS (REAL_VALUE_TYPE @var{x}, REAL_VALUE_TYPE @var{y})
+Tests whether @var{x} is less than @var{y}.
+@end deftypefn
+
 @findex ldexp
-@item REAL_VALUE_LDEXP (@var{x}, @var{scale})
-A macro for a C expression which performs the standard library
-function @code{ldexp}, but using the target machine's floating point
-representation.  Both @var{x} and the value of the expression have
-type @code{REAL_VALUE_TYPE}.  The second argument, @var{scale}, is an
-integer.
-
-@findex REAL_VALUE_FIX
-@item REAL_VALUE_FIX (@var{x})
-A macro whose definition is a C expression to convert the target-machine
-floating point value @var{x} to a signed integer.  @var{x} has type
-@code{REAL_VALUE_TYPE}.
-
-@findex REAL_VALUE_UNSIGNED_FIX
-@item REAL_VALUE_UNSIGNED_FIX (@var{x})
-A macro whose definition is a C expression to convert the target-machine
-floating point value @var{x} to an unsigned integer.  @var{x} has type
-@code{REAL_VALUE_TYPE}.
-
-@findex REAL_VALUE_RNDZINT
-@item REAL_VALUE_RNDZINT (@var{x})
-A macro whose definition is a C expression to round the target-machine
-floating point value @var{x} towards zero to an integer value (but still
-as a floating point number).  @var{x} has type @code{REAL_VALUE_TYPE},
-and so does the value.
-
-@findex REAL_VALUE_UNSIGNED_RNDZINT
-@item REAL_VALUE_UNSIGNED_RNDZINT (@var{x})
-A macro whose definition is a C expression to round the target-machine
-floating point value @var{x} towards zero to an unsigned integer value
-(but still represented as a floating point number).  @var{x} has type
-@code{REAL_VALUE_TYPE}, and so does the value.
-
-@findex REAL_VALUE_ATOF
-@item REAL_VALUE_ATOF (@var{string}, @var{mode})
-A macro for a C expression which converts @var{string}, an expression of
-type @code{char *}, into a floating point number in the target machine's
-representation for mode @var{mode}.  The value has type
-@code{REAL_VALUE_TYPE}.
-
-@findex REAL_INFINITY
-@item REAL_INFINITY
-Define this macro if infinity is a possible floating point value, and
-therefore division by 0 is legitimate.
-
-@findex REAL_VALUE_ISINF
-@findex isinf
-@item REAL_VALUE_ISINF (@var{x})
-A macro for a C expression which determines whether @var{x}, a floating
-point value, is infinity.  The value has type @code{int}.
-By default, this is defined to call @code{isinf}.
-
-@findex REAL_VALUE_ISNAN
-@findex isnan
-@item REAL_VALUE_ISNAN (@var{x})
-A macro for a C expression which determines whether @var{x}, a floating
-point value, is a ``nan'' (not-a-number).  The value has type
-@code{int}.  By default, this is defined to call @code{isnan}.
-
-@findex REAL_ARITHMETIC
-@item REAL_ARITHMETIC (@var{output}, @var{code}, @var{x}, @var{y})
-A macro for a C statement which calculates an arithmetic operation of
-the two floating point values @var{x} and @var{y}, both of type
-@code{REAL_VALUE_TYPE} in the target machine's representation, to
-produce a result of the same type and representation which is stored
-in @var{output} (which will be a variable).
-
-The operation to be performed is specified by @var{code}, a tree code
-which will always be one of the following: @code{PLUS_EXPR},
-@code{MINUS_EXPR}, @code{MULT_EXPR}, @code{RDIV_EXPR},
-@code{MAX_EXPR}, @code{MIN_EXPR}.
-
-@cindex overflow while constant folding
-If overflow happens, the macro expansion executes the statement
-@code{return 0;}, which indicates the inability to perform the
-arithmetic operation requested.
-
-@findex REAL_VALUE_NEGATE
-@item REAL_VALUE_NEGATE (@var{x})
-A macro for a C expression which returns the negative of the floating
-point value @var{x}.  Both @var{x} and the value of the expression
-have type @code{REAL_VALUE_TYPE} and are in the target machine's
-floating point representation.
-
-There is no way for this macro to report overflow, since overflow
-can't happen in the negation operation.
-
-@findex REAL_VALUE_TRUNCATE
-@item REAL_VALUE_TRUNCATE (@var{mode}, @var{x})
-A macro for a C expression which converts the floating point value
-@var{x} to mode @var{mode}.
-
-Both @var{x} and the value of the expression are in the target machine's
-floating point representation and have type @code{REAL_VALUE_TYPE}.
-However, the value should have an appropriate bit pattern to be output
-properly as a floating constant whose precision accords with mode
-@var{mode}.
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_LDEXP (REAL_VALUE_TYPE @var{x}, int @var{scale})
+Multiplies @var{x} by 2 raised to the power @var{scale}.
+@end deftypefn
+
+@deftypefn Macro HOST_WIDE_INT REAL_VALUE_FIX (REAL_VALUE_TYPE @var{x})
+Truncates @var{x} to a signed integer, rounding toward zero.
+@end deftypefn
+
+@deftypefn Macro {unsigned HOST_WIDE_INT} REAL_VALUE_UNSIGNED_FIX (REAL_VALUE_TYPE @var{x})
+Truncates @var{x} to an unsigned integer, rounding toward zero.  If
+@var{x} is negative, returns zero.
+@end deftypefn
+
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_RNDZINT (REAL_VALUE_TYPE @var{x})
+Rounds the target-machine floating point value @var{x} towards zero to an
+integer value, but leaves it represented as a floating point number.
+@end deftypefn
 
-There is no way for this macro to report overflow.
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_UNSIGNED_RNDZINT (REAL_VALUE_TYPE @var{x})
+Rounds the target-machine floating point value @var{x} towards zero to an
+unsigned integer value, but leaves it represented as a floating point
+number.  If @var{x} is negative, returns (positive) zero.
+@end deftypefn
 
-@findex REAL_VALUE_TO_INT
-@item REAL_VALUE_TO_INT (@var{low}, @var{high}, @var{x})
-A macro for a C expression which converts a floating point value
-@var{x} into a double-precision integer which is then stored into
-@var{low} and @var{high}, two variables of type @var{int}.
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_ATOF (const char *@var{string}, enum machine_mode @var{mode})
+Converts @var{string} into a floating point number in the target machine's
+representation for mode @var{mode}.  This routine can handle both
+decimal and hexadecimal floating point constants, using the syntax
+defined by the C language for both.
+@end deftypefn
 
-@item REAL_VALUE_FROM_INT (@var{x}, @var{low}, @var{high}, @var{mode})
+@deftypefn Macro int REAL_VALUE_ISINF (REAL_VALUE_TYPE @var{x})
+Determines whether @var{x} represents infinity (positive or negative).
+@end deftypefn
+
+@deftypefn Macro int REAL_VALUE_ISNAN (REAL_VALUE_TYPE @var{x})
+Determines whether @var{x} represents a ``NaN'' (not-a-number).
+@end deftypefn
+
+@deftypefn Macro void REAL_ARITHMETIC (REAL_VALUE_TYPE @var{output}, enum tree_code @var{code}, REAL_VALUE_TYPE @var{x}, REAL_VALUE_TYPE @var{y})
+Calculates an arithmetic operation on the two floating point values
+@var{x} and @var{y}, storing the result in @var{output} (which must be a
+variable).
+
+The operation to be performed is specified by @var{code}.  Only the
+following codes are supported: @code{PLUS_EXPR}, @code{MINUS_EXPR},
+@code{MULT_EXPR}, @code{RDIV_EXPR}, @code{MAX_EXPR}, @code{MIN_EXPR}.
+
+If @code{REAL_ARITHMETIC} is asked to evaluate division by zero and the
+target's floating point format cannot represent infinity, it will call
+@code{abort}.  Callers should check for this situation first, using
+@code{MODE_HAS_INFINITIES}.  @xref{Storage Layout}.
+@end deftypefn
+
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_NEGATE (REAL_VALUE_TYPE @var{x})
+Returns the negative of the floating point value @var{x}.
+@end deftypefn
+
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_TRUNCATE (REAL_VALUE_TYPE @var{mode}, enum machine_mode @var{x})
+Truncates the floating point value @var{x} to fit in @var{mode}.  The
+return value is still a full-size @code{REAL_VALUE_TYPE}, but it has an
+appropriate bit pattern to be output asa floating constant whose
+precision accords with mode @var{mode}.
+@end deftypefn
+
+@deftypefn Macro void REAL_VALUE_TO_INT (HOST_WIDE_INT @var{low}, HOST_WIDE_INT @var{high}, REAL_VALUE_TYPE @var{x})
+Converts a floating point value @var{x} into a double-precision integer
+which is then stored into @var{low} and @var{high}.  If the value is not
+integral, it is truncated.
+@end deftypefn
+
+@deftypefn Macro void REAL_VALUE_FROM_INT (REAL_VALUE_TYPE @var{x}, HOST_WIDE_INT @var{low}, HOST_WIDE_INT @var{high}, enum machine_mode @var{mode})
 @findex REAL_VALUE_FROM_INT
-A macro for a C expression which converts a double-precision integer
-found in @var{low} and @var{high}, two variables of type @var{int},
-into a floating point value which is then stored into @var{x}.
-The value is in the target machine's representation for mode @var{mode}
-and has the type @code{REAL_VALUE_TYPE}.
-@end table
+Converts a double-precision integer found in @var{low} and @var{high},
+into a floating point value which is then stored into @var{x}.  The
+value is truncated to fit in mode @var{mode}.
+@end deftypefn
 
 @node Mode Switching
 @section Mode Switching Instructions
index d54baca..7f1e92b 100644 (file)
@@ -4920,23 +4920,17 @@ init_emit_once (line_numbers)
 
   for (i = 0; i <= 2; i++)
     {
+      REAL_VALUE_TYPE *r =
+       (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
+
       for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
           mode = GET_MODE_WIDER_MODE (mode))
        {
          rtx tem = rtx_alloc (CONST_DOUBLE);
-         union real_extract u;
-
-         /* Zero any holes in a structure.  */
-         memset ((char *) &u, 0, sizeof u);
-         u.d = i == 0 ? dconst0 : i == 1 ? dconst1 : dconst2;
-
-         /* Avoid trailing garbage in the rtx.  */
-         if (sizeof (u) < sizeof (HOST_WIDE_INT))
-           CONST_DOUBLE_LOW (tem) = 0;
-         if (sizeof (u) < 2 * sizeof (HOST_WIDE_INT))
-           CONST_DOUBLE_HIGH (tem) = 0;
-
-         memcpy (&CONST_DOUBLE_LOW (tem), &u, sizeof u);
+         /* Can't use CONST_DOUBLE_FROM_REAL_VALUE here; that uses the
+            tables we're setting up right now.  */
+         memcpy (&CONST_DOUBLE_LOW (tem), r, sizeof (REAL_VALUE_TYPE));
          CONST_DOUBLE_CHAIN (tem) = NULL_RTX;
          PUT_MODE (tem, mode);
 
index 39d18bb..b89b780 100644 (file)
@@ -5379,11 +5379,12 @@ fold (expr)
       goto binary;
 
     case RDIV_EXPR:
-      /* In most cases, do nothing with a divide by zero.  */
-#ifndef REAL_INFINITY
-      if (TREE_CODE (arg1) == REAL_CST && real_zerop (arg1))
+      /* Don't touch a floating-point divide by zero unless the mode
+        of the constant can represent infinity.  */
+      if (TREE_CODE (arg1) == REAL_CST
+         && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg1)))
+         && real_zerop (arg1))
        return t;
-#endif
 
       /* (-A) / (-B) -> A / B  */
       if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
index 08bfc34..cab9256 100644 (file)
@@ -1067,33 +1067,11 @@ __floatdidf (DWtype u)
 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
 #define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
 
-/* Define codes for all the float formats that we know of.  Note
-   that this is copied from real.h.  */
+/* GCC guarantees this header exists at this point.  */
+#include <float.h>
 
-#define UNKNOWN_FLOAT_FORMAT 0
-#define IEEE_FLOAT_FORMAT 1
-#define VAX_FLOAT_FORMAT 2
-#define IBM_FLOAT_FORMAT 3
-
-/* Default to IEEE float if not specified.  Nearly all machines use it.  */
-#ifndef HOST_FLOAT_FORMAT
-#define        HOST_FLOAT_FORMAT       IEEE_FLOAT_FORMAT
-#endif
-
-#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#define DF_SIZE 53
-#define SF_SIZE 24
-#endif
-
-#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-#define DF_SIZE 56
-#define SF_SIZE 24
-#endif
-
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-#define DF_SIZE 56
-#define SF_SIZE 24
-#endif
+#define DF_SIZE DBL_MANT_DIG
+#define SF_SIZE FLT_MANT_DIG
 
 SFtype
 __floatdisf (DWtype u)
index b819d14..496613b 100644 (file)
@@ -502,13 +502,19 @@ print_rtx (in_rtx)
       fputc (']', outfile);
       break;
 
-#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && MAX_LONG_DOUBLE_TYPE_SIZE == 64
+#if 0
+    /* It would be nice to do this, but it would require real.o to
+       be linked into the MD-generator programs.  Maybe we should
+       do that.  -zw 2002-03-03  */
     case CONST_DOUBLE:
       if (FLOAT_MODE_P (GET_MODE (in_rtx)))
        {
-         double val;
+         REAL_VALUE_TYPE val;
+         char s[30];
+
          REAL_VALUE_FROM_CONST_DOUBLE (val, in_rtx);
-         fprintf (outfile, " [%.16g]", val);
+         REAL_VALUE_TO_DECIMAL (val, "%.16g", s);
+         fprintf (outfile, " [%s]", s);
        }
       break;
 #endif
index bac0690..8674ee8 100644 (file)
@@ -607,17 +607,10 @@ earith (value, icode, r1, r2)
       break;
 
     case RDIV_EXPR:
-#ifndef REAL_INFINITY
+#ifndef INFINITY
       if (ecmp (d2, ezero) == 0)
-       {
-#ifdef NANS
-       enan (v, eisneg (d1) ^ eisneg (d2));
-       break;
-#else
        abort ();
 #endif
-       }
-#endif
       ediv (d2, d1, v);        /* d1/d2 */
       break;
 
index e734b26..d3cf780 100644 (file)
@@ -43,10 +43,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define INTEL_EXTENDED_IEEE_FORMAT 0
 #endif
 
-#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#define REAL_INFINITY
-#endif
-
 /* If FLOAT_WORDS_BIG_ENDIAN and HOST_FLOAT_WORDS_BIG_ENDIAN are not defined
    in the header files, then this implies the word-endianness is the same as
    for integers.  */
@@ -79,43 +75,15 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 /* **** Start of software floating point emulator interface macros **** */
 
-/* Support 80-bit extended real XFmode if LONG_DOUBLE_TYPE_SIZE
-   has been defined to be 96 in the tm.h machine file.  */
-#if (MAX_LONG_DOUBLE_TYPE_SIZE == 96)
-#define REAL_IS_NOT_DOUBLE
-typedef struct {
-  HOST_WIDE_INT r[(11 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
-} realvaluetype;
-#define REAL_VALUE_TYPE realvaluetype
-
-#else /* no XFmode support */
-
-#if (MAX_LONG_DOUBLE_TYPE_SIZE == 128)
-
-#define REAL_IS_NOT_DOUBLE
-typedef struct {
-  HOST_WIDE_INT r[(19 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
-} realvaluetype;
-#define REAL_VALUE_TYPE realvaluetype
-
-#else /* not TFmode */
-
-#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
-/* If no XFmode support, then a REAL_VALUE_TYPE is 64 bits wide
-   but it is not necessarily a host machine double.  */
-#define REAL_IS_NOT_DOUBLE
+/* REAL_VALUE_TYPE is an array of the minimum number of HOST_WIDE_INTs
+   required to hold MAX_LONG_DOUBLE_TYPE_SIZE bits.  */
+#define N (MAX_LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT)
+#define S sizeof (HOST_WIDE_INT)
 typedef struct {
-  HOST_WIDE_INT r[(7 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
-} realvaluetype;
-#define REAL_VALUE_TYPE realvaluetype
-#else
-/* If host and target formats are compatible, then a REAL_VALUE_TYPE
-   is actually a host machine double.  */
-#define REAL_VALUE_TYPE double
-#endif
-
-#endif /* no TFmode support */
-#endif /* no XFmode support */
+  HOST_WIDE_INT r[N/S + (N%S ? 1 : 0)]; /* round up */
+} REAL_VALUE_TYPE;
+#undef N
+#undef S
 
 extern unsigned int significand_size   PARAMS ((enum machine_mode));
 
@@ -246,15 +214,6 @@ extern REAL_VALUE_TYPE dconst1;
 extern REAL_VALUE_TYPE dconst2;
 extern REAL_VALUE_TYPE dconstm1;
 
-/* Union type used for extracting real values from CONST_DOUBLEs
-   or putting them in.  */
-
-union real_extract 
-{
-  REAL_VALUE_TYPE d;
-  HOST_WIDE_INT i[sizeof (REAL_VALUE_TYPE) / sizeof (HOST_WIDE_INT)];
-};
-
 /* Given a CONST_DOUBLE in FROM, store into TO the value it represents.  */
 /* Function to return a real value (not a tree node)
    from a given integer constant.  */
@@ -263,9 +222,7 @@ REAL_VALUE_TYPE real_value_from_int_cst     PARAMS ((union tree_node *,
                                                union tree_node *));
 
 #define REAL_VALUE_FROM_CONST_DOUBLE(to, from)         \
-do { union real_extract u;                             \
-     memcpy (&u, &CONST_DOUBLE_LOW ((from)), sizeof u); \
-     to = u.d; } while (0)
+  memcpy (&(to), &CONST_DOUBLE_LOW ((from)), sizeof (REAL_VALUE_TYPE))
 
 /* Return a CONST_DOUBLE with value R and mode M.  */
 
index 21012ce..53f8293 100644 (file)
@@ -763,13 +763,13 @@ simplify_binary_real (p)
   f0 = real_value_truncate (args->mode, f0);
   f1 = real_value_truncate (args->mode, f1);
 
-#ifndef REAL_INFINITY
-  if (args->code == DIV && REAL_VALUES_EQUAL (f1, dconst0))
+  if (args->code == DIV
+      && !MODE_HAS_INFINITIES (args->mode)
+      && REAL_VALUES_EQUAL (f1, dconst0))
     {
       args->result = 0;
       return;
     }
-#endif
   REAL_ARITHMETIC (value, rtx_to_tree_code (args->code), f0, f1);
 
   value = real_value_truncate (args->mode, value);
index 098757e..ef9e872 100644 (file)
@@ -2215,14 +2215,8 @@ immed_real_const_1 (d, mode)
      REAL_VALUE_TYPE d;
      enum machine_mode mode;
 {
-  union real_extract u;
   rtx r;
 
-  /* Get the desired `double' value as a sequence of ints
-     since that is how they are stored in a CONST_DOUBLE.  */
-
-  u.d = d;
-
   /* Detect special cases.  Check for NaN first, because some ports
      (specifically the i386) do not emit correct ieee-fp code by default, and
      thus will generate a core dump here if we pass a NaN to REAL_VALUES_EQUAL
@@ -2234,10 +2228,10 @@ immed_real_const_1 (d, mode)
   else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst2, d))
     return CONST2_RTX (mode);
 
-  if (sizeof u == sizeof (HOST_WIDE_INT))
-    return immed_double_const (u.i[0], 0, mode);
-  if (sizeof u == 2 * sizeof (HOST_WIDE_INT))
-    return immed_double_const (u.i[0], u.i[1], mode);
+  if (sizeof (REAL_VALUE_TYPE) == sizeof (HOST_WIDE_INT))
+    return immed_double_const (d.r[0], 0, mode);
+  if (sizeof (REAL_VALUE_TYPE) == 2 * sizeof (HOST_WIDE_INT))
+    return immed_double_const (d.r[0], d.r[1], mode);
 
   /* The rest of this function handles the case where
      a float value requires more than 2 ints of space.
@@ -2247,7 +2241,7 @@ immed_real_const_1 (d, mode)
      If one is found, return it.  */
   if (cfun != 0)
     for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
-      if (! memcmp ((char *) &CONST_DOUBLE_LOW (r), (char *) &u, sizeof u)
+      if (! memcmp ((char *) &CONST_DOUBLE_LOW (r), (char *) &d, sizeof d)
          && GET_MODE (r) == mode)
        return r;
 
@@ -2259,7 +2253,7 @@ immed_real_const_1 (d, mode)
      freed memory.  */
   r = rtx_alloc (CONST_DOUBLE);
   PUT_MODE (r, mode);
-  memcpy ((char *) &CONST_DOUBLE_LOW (r), (char *) &u, sizeof u);
+  memcpy ((char *) &CONST_DOUBLE_LOW (r), (char *) &d, sizeof d);
 
   /* If we aren't inside a function, don't put r on the
      const_double_chain.  */
@@ -2383,7 +2377,7 @@ struct rtx_const
   ENUM_BITFIELD(kind) kind : 16;
   ENUM_BITFIELD(machine_mode) mode : 16;
   union {
-    union real_extract du;
+    REAL_VALUE_TYPE du;
     struct addr_const addr;
     struct {HOST_WIDE_INT high, low;} di;
 
@@ -3571,8 +3565,7 @@ decode_rtx_const (mode, x, value)
       if (GET_MODE (x) != VOIDmode)
        {
          value->mode = GET_MODE (x);
-         memcpy ((char *) &value->un.du,
-                 (char *) &CONST_DOUBLE_LOW (x), sizeof value->un.du);
+         REAL_VALUE_FROM_CONST_DOUBLE (value->un.du, x);
        }
       else
        {
@@ -3962,7 +3955,7 @@ output_constant_pool (fnname, fndecl)
 {
   struct pool_constant *pool;
   rtx x;
-  union real_extract u;
+  REAL_VALUE_TYPE r;
 
   /* It is possible for gcc to call force_const_mem and then to later
      discard the instructions which refer to the constant.  In such a
@@ -4040,8 +4033,8 @@ output_constant_pool (fnname, fndecl)
          if (GET_CODE (x) != CONST_DOUBLE)
            abort ();
 
-         memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (x), sizeof u);
-         assemble_real (u.d, pool->mode, pool->align);
+         REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+         assemble_real (r, pool->mode, pool->align);
          break;
 
        case MODE_INT:
@@ -4062,10 +4055,8 @@ output_constant_pool (fnname, fndecl)
            for (i = 0; i < units; i++)
              {
                elt = CONST_VECTOR_ELT (x, i);
-               memcpy ((char *) &u,
-                       (char *) &CONST_DOUBLE_LOW (elt),
-                       sizeof u);
-               assemble_real (u.d, GET_MODE_INNER (pool->mode), pool->align);
+               REAL_VALUE_FROM_CONST_DOUBLE (r, elt);
+               assemble_real (r, GET_MODE_INNER (pool->mode), pool->align);
              }
          }
          break;