From 51aae43f235863454bcce315c748b2836c5d3f98 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 8 Sep 2015 19:27:30 +0000 Subject: [PATCH] [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 --- gcc/ChangeLog | 5 +++++ gcc/fold-const.c | 22 ++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 127829c2baa..bd76b596345 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2015-09-08 Alan Lawrence + + * fold-const.c (native_interpret_real): Fix HFmode for bigendian where + UNITS_PER_WORD >= 4. + 2015-09-08 Alan Lawrence * config/aarch64/aarch64-simd.md (aarch64_simd_vec_unpacks_lo_, diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a79bfa7b060..e9366e2de6e 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); -- 2.30.2