[PATCH] Fix for ereal_from_double and 64bit hosts

Jakub Jelinek jj@sunsite.ms.mff.cuni.cz
Mon Jun 21 10:03:00 GMT 1999


Hi!

Apparently nobody was using REAL_VALUE_FROM_TARGET_DOUBLE on 64bit bigendian
hosts, because it exchanged hi and lo 32bits of the double, plus sparc64 gcc
aborted on code like 

          __real__ retval = (__extension__      
			     ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; })
			      { __l: 0x7ff0000000000000ULL }).__d);
          __imag__ retval = __imag__ x * __copysign (1.0, __real__ x);

1999-06-21  Jakub Jelinek  <jj@ultra.linux.cz>

        * real.c (ereal_from_double): Fix for 64bit
	big endian hosts.
	* emit-rtl.c (gen_lowpart_common): Add case
	for hosts where double fits in HOST_WIDE_INT
	and one uses union to access a long constant
	as double.

--- gcc/real.c.jj3	Thu Jun 17 11:22:48 1999
+++ gcc/real.c	Mon Jun 21 12:04:12 1999
@@ -6405,17 +6405,19 @@ ereal_from_double (d)
   /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces.  */
   if (REAL_WORDS_BIG_ENDIAN)
     {
+#if HOST_BITS_PER_WIDE_INT == 32
       s[0] = (unsigned EMUSHORT) (d[0] >> 16);
       s[1] = (unsigned EMUSHORT) d[0];
-#if HOST_BITS_PER_WIDE_INT == 32
       s[2] = (unsigned EMUSHORT) (d[1] >> 16);
       s[3] = (unsigned EMUSHORT) d[1];
 #else
       /* In this case the entire target double is contained in the
 	 first array element.  The second element of the input is
 	 ignored.  */
-      s[2] = (unsigned EMUSHORT) (d[0] >> 48);
-      s[3] = (unsigned EMUSHORT) (d[0] >> 32);
+      s[0] = (unsigned EMUSHORT) (d[0] >> 48);
+      s[1] = (unsigned EMUSHORT) (d[0] >> 32);
+      s[2] = (unsigned EMUSHORT) (d[0] >> 16);
+      s[3] = (unsigned EMUSHORT) d[0];
 #endif
     }
   else
--- gcc/emit-rtl.c.jj3	Tue Jun 15 17:42:18 1999
+++ gcc/emit-rtl.c	Mon Jun 21 11:31:05 1999
@@ -976,6 +976,22 @@ gen_lowpart_common (mode, x)
       r = REAL_VALUE_FROM_TARGET_SINGLE (i);
       return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
     }
+  else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
+	     && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
+	    || flag_pretend_float)
+	   && GET_MODE_CLASS (mode) == MODE_FLOAT
+	   && GET_MODE_SIZE (mode) == UNITS_PER_WORD
+	   && GET_CODE (x) == CONST_INT
+	   && (sizeof (double) * HOST_BITS_PER_CHAR
+	       == HOST_BITS_PER_WIDE_INT))
+    {
+      REAL_VALUE_TYPE r;
+      HOST_WIDE_INT i;
+
+      i = INTVAL (x);
+      r = REAL_VALUE_FROM_TARGET_DOUBLE (&i);
+      return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
+    }
 #endif
 
   /* Similarly, if this is converting a floating-point value into a

Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
UltraLinux  |  http://ultra.linux.cz/  |  http://ultra.penguin.cz/
Linux version 2.3.6 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________


More information about the Gcc-patches mailing list