diff options
author | Alan Lawrence <alan.lawrence@arm.com> | 2015-09-08 19:27:30 +0000 |
---|---|---|
committer | Alan Lawrence <alalaw01@gcc.gnu.org> | 2015-09-08 19:27:30 +0000 |
commit | 51aae43f235863454bcce315c748b2836c5d3f98 (patch) | |
tree | 2bda572c4af1c703a5f18f56949e9eb485f4a2f6 | |
parent | 03873eb98330b17e73ada713f31bcbcd50d74026 (diff) | |
download | gcc-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/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/fold-const.c | 22 |
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); |