summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authoralalaw01 <alalaw01@138bc75d-0d04-0410-961f-82ee72b054a4>2015-09-08 19:27:30 +0000
committeralalaw01 <alalaw01@138bc75d-0d04-0410-961f-82ee72b054a4>2015-09-08 19:27:30 +0000
commit3ea4b099db3dc24efdb57f615a36dba4e11f92d7 (patch)
tree2bda572c4af1c703a5f18f56949e9eb485f4a2f6 /gcc/fold-const.c
parent90d05d2d9759b2cb0028ab1338c1253b88cab27e (diff)
downloadgcc-3ea4b099db3dc24efdb57f615a36dba4e11f92d7.tar.gz
[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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@227552 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c22
1 files changed, 16 insertions, 6 deletions
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);