[fold-const.c] Fix bigendian HFmode in native_interpret_real
authorAlan Lawrence <alan.lawrence@arm.com>
Tue, 8 Sep 2015 19:27:30 +0000 (19:27 +0000)
committerAlan Lawrence <alalaw01@gcc.gnu.org>
Tue, 8 Sep 2015 19:27:30 +0000 (19:27 +0000)
* fold-const.c (native_interpret_real): Fix HFmode for bigendian where
UNITS_PER_WORD >= 4.

From-SVN: r227552

gcc/ChangeLog
gcc/fold-const.c

index 127829c2baa7f2467a3f5534f2157a3b15c2e5d5..bd76b596345bb843365b9d12d9e86f9682b68b6f 100644 (file)
@@ -1,3 +1,8 @@
+2015-09-08  Alan Lawrence  <alan.lawrence@arm.com>
+
+       * fold-const.c (native_interpret_real): Fix HFmode for bigendian where
+       UNITS_PER_WORD >= 4.
+
 2015-09-08  Alan Lawrence  <alan.lawrence@arm.com>
 
        * config/aarch64/aarch64-simd.md (aarch64_simd_vec_unpacks_lo_<mode>,
index a79bfa7b0600eb3f9f3239939d5e8aa982256698..e9366e2de6e8a7684bf0a0f51fc63ebd2c2154e8 100644 (file)
@@ -7182,7 +7182,6 @@ native_interpret_real (tree type, const unsigned char *ptr, int len)
 {
   machine_mode mode = TYPE_MODE (type);
   int total_bytes = GET_MODE_SIZE (mode);
-  int byte, offset, word, words, bitpos;
   unsigned char value;
   /* There are always 32 bits in each long, no matter the size of
      the hosts long.  We handle floating point representations with
@@ -7193,16 +7192,18 @@ native_interpret_real (tree type, const unsigned char *ptr, int len)
   total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
   if (total_bytes > len || total_bytes > 24)
     return NULL_TREE;
-  words = (32 / BITS_PER_UNIT) / UNITS_PER_WORD;
+  int words = (32 / BITS_PER_UNIT) / UNITS_PER_WORD;
 
   memset (tmp, 0, sizeof (tmp));
-  for (bitpos = 0; bitpos < total_bytes * BITS_PER_UNIT;
+  for (int bitpos = 0; bitpos < total_bytes * BITS_PER_UNIT;
        bitpos += BITS_PER_UNIT)
     {
-      byte = (bitpos / BITS_PER_UNIT) & 3;
+      /* Both OFFSET and BYTE index within a long;
+        bitpos indexes the whole float.  */
+      int offset, byte = (bitpos / BITS_PER_UNIT) & 3;
       if (UNITS_PER_WORD < 4)
        {
-         word = byte / UNITS_PER_WORD;
+         int word = byte / UNITS_PER_WORD;
          if (WORDS_BIG_ENDIAN)
            word = (words - 1) - word;
          offset = word * UNITS_PER_WORD;
@@ -7212,7 +7213,16 @@ native_interpret_real (tree type, const unsigned char *ptr, int len)
            offset += byte % UNITS_PER_WORD;
        }
       else
-       offset = BYTES_BIG_ENDIAN ? 3 - byte : byte;
+       {
+         offset = byte;
+         if (BYTES_BIG_ENDIAN)
+           {
+             /* Reverse bytes within each long, or within the entire float
+                if it's smaller than a long (for HFmode).  */
+             offset = MIN (3, total_bytes - 1) - offset;
+             gcc_assert (offset >= 0);
+           }
+       }
       value = ptr[offset + ((bitpos / BITS_PER_UNIT) & ~3)];
 
       tmp[bitpos / 32] |= (unsigned long)value << (bitpos & 31);