emit-rtl.c (operand_subword): Religiously mask and sign-extend from 32-bits to HOST_W...
authorRichard Henderson <rth@cygnus.com>
Thu, 29 Apr 1999 17:24:37 +0000 (10:24 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 29 Apr 1999 17:24:37 +0000 (10:24 -0700)
        * emit-rtl.c (operand_subword): Religiously mask and sign-extend
        from 32-bits to HOST_WIDE_INT.

From-SVN: r26699

gcc/ChangeLog
gcc/emit-rtl.c

index 8262582777667ca94b88dfbcaa52090b95a15d96..5f6fdc662ac48444074e752e633dd35398828aba 100644 (file)
@@ -1,3 +1,7 @@
+Thu Apr 29 17:23:59 1999  Richard Henderson  <rth@cygnus.com>
+
+       * emit-rtl.c (operand_subword): Religiously mask and sign-extend
+       from 32-bits to HOST_WIDE_INT.
 
 Thu Apr 29 15:58:52 1999  Robert Lipe  <robertlipe@usa.net>
 
index 88edee3bb0b527e22fc567acda8c1d40aef16701..b1e2d3dca01c6adfe120836c5545835cda16d7e1 100644 (file)
@@ -1273,24 +1273,35 @@ operand_subword (op, i, validate_address, mode)
 
       /* We handle 32-bit and >= 64-bit words here.  Note that the order in
         which the words are written depends on the word endianness.
-
         ??? This is a potential portability problem and should
-        be fixed at some point.  */
+        be fixed at some point.
+
+        We must excercise caution with the sign bit.  By definition there
+        are 32 significant bits in K; there may be more in a HOST_WIDE_INT.
+        Consider a host with a 32-bit long and a 64-bit HOST_WIDE_INT.
+        So we explicitly mask and sign-extend as necessary.  */
       if (BITS_PER_WORD == 32)
-       return GEN_INT ((HOST_WIDE_INT) k[i]);
-#if HOST_BITS_PER_WIDE_INT > 32
+       {
+         val = k[i];
+         val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
+         return GEN_INT (val);
+       }
+#if HOST_BITS_PER_WIDE_INT >= 64
       else if (BITS_PER_WORD >= 64 && i == 0)
-       return GEN_INT ((((HOST_WIDE_INT) k[! WORDS_BIG_ENDIAN]) << 32)
-                       | (HOST_WIDE_INT) k[WORDS_BIG_ENDIAN]);
+       {
+         val = k[! WORDS_BIG_ENDIAN];
+         val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
+         val |= (HOST_WIDE_INT) k[WORDS_BIG_ENDIAN] & 0xffffffff;
+         return GEN_INT (val);
+       }
 #endif
       else if (BITS_PER_WORD == 16)
        {
-         long value;
-         value = k[i >> 1];
-         if ((i & 0x1) == !WORDS_BIG_ENDIAN)
-           value >>= 16;
-         value &= 0xffff;
-         return GEN_INT ((HOST_WIDE_INT) value);
+         val = k[i >> 1];
+         if ((i & 1) == !WORDS_BIG_ENDIAN)
+           val >>= 16;
+         val &= 0xffff;
+         return GEN_INT (val);
        }
       else
        abort ();
@@ -1307,7 +1318,13 @@ operand_subword (op, i, validate_address, mode)
     REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
 
     if (BITS_PER_WORD == 32)
-      return GEN_INT ((HOST_WIDE_INT) k[i]);
+      {
+       val = k[i];
+       val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
+       return GEN_INT (val);
+      }
+    else
+      abort ();
   }
 #else /* no REAL_ARITHMETIC */
   if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
@@ -1345,25 +1362,18 @@ operand_subword (op, i, validate_address, mode)
       REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
       REAL_VALUE_TO_TARGET_SINGLE (rv, l);
 
-      /* If 32 bits is an entire word for the target, but not for the host,
-        then sign-extend on the host so that the number will look the same
-        way on the host that it would on the target.  See for instance
-        simplify_unary_operation.  The #if is needed to avoid compiler
-        warnings.  */
-
-#if HOST_BITS_PER_LONG > 32
-      if (BITS_PER_WORD < HOST_BITS_PER_LONG && BITS_PER_WORD == 32
-         && (l & ((long) 1 << 31)))
-       l |= ((long) (-1) << 32);
-#endif
+      /* Sign extend from known 32-bit value to HOST_WIDE_INT.  */
+      val = l;
+      val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
 
       if (BITS_PER_WORD == 16)
        {
-         if ((i & 0x1) == !WORDS_BIG_ENDIAN)
-           l >>= 16;
-         l &= 0xffff;
+         if ((i & 1) == !WORDS_BIG_ENDIAN)
+           val >>= 16;
+         val &= 0xffff;
        }
-      return GEN_INT ((HOST_WIDE_INT) l);
+
+      return GEN_INT (val);
     }
 #else
   if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT