aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Lawrence <alan.lawrence@arm.com>2015-09-08 19:27:30 +0000
committerAlan Lawrence <alalaw01@gcc.gnu.org>2015-09-08 19:27:30 +0000
commit51aae43f235863454bcce315c748b2836c5d3f98 (patch)
tree2bda572c4af1c703a5f18f56949e9eb485f4a2f6
parent03873eb98330b17e73ada713f31bcbcd50d74026 (diff)
downloadgcc-51aae43f235863454bcce315c748b2836c5d3f98.zip
gcc-51aae43f235863454bcce315c748b2836c5d3f98.tar.gz
gcc-51aae43f235863454bcce315c748b2836c5d3f98.tar.bz2
[fold-const.c] Fix bigendian HFmode in native_interpret_real
* fold-const.c (native_interpret_real): Fix HFmode for bigendian where UNITS_PER_WORD >= 4. From-SVN: r227552
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/fold-const.c22
2 files changed, 21 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 127829c..bd76b59 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,10 @@
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>,
aarch64_simd_vec_unpacks_hi_<mode>): New insn.
(vec_unpacks_lo_v4sf, vec_unpacks_hi_v4sf): Delete insn.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index a79bfa7..e9366e2 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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);