diff options
author | Jakub Jelinek <jakub@redhat.com> | 2007-04-03 11:05:38 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2007-04-03 11:05:38 +0200 |
commit | 0a9430a8312d9f5a3795747773796b21d3bfe526 (patch) | |
tree | 602f9d225374a7b7691e8fa6a89f62777839aed1 /gcc/fold-const.c | |
parent | eb9af792f2c0e8934f6b537ec12f8211d1fba505 (diff) | |
download | gcc-0a9430a8312d9f5a3795747773796b21d3bfe526.zip gcc-0a9430a8312d9f5a3795747773796b21d3bfe526.tar.gz gcc-0a9430a8312d9f5a3795747773796b21d3bfe526.tar.bz2 |
re PR middle-end/30704 (Incorrect constant generation for long long)
PR middle-end/30704
* fold-const.c (native_encode_real): Encode real.c provided longs
as a series of 32-bit native integers.
(native_interpret_real): Interpret buffer as a series of 32-bit
native integers.
* gcc.c-torture/execute/ieee/pr30704.c: New test.
From-SVN: r123455
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 5ee9cf1..a8b6f34 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -7162,7 +7162,7 @@ native_encode_real (tree expr, unsigned char *ptr, int len) { tree type = TREE_TYPE (expr); int total_bytes = GET_MODE_SIZE (TYPE_MODE (type)); - int byte, offset, word, words; + int byte, offset, word, words, bitpos; unsigned char value; /* There are always 32 bits in each long, no matter the size of @@ -7172,19 +7172,20 @@ native_encode_real (tree expr, unsigned char *ptr, int len) if (total_bytes > len) return 0; - words = total_bytes / UNITS_PER_WORD; + words = 32 / UNITS_PER_WORD; real_to_target (tmp, TREE_REAL_CST_PTR (expr), TYPE_MODE (type)); - for (byte = 0; byte < total_bytes; byte++) + for (bitpos = 0; bitpos < total_bytes * BITS_PER_UNIT; + bitpos += BITS_PER_UNIT) { - int bitpos = byte * BITS_PER_UNIT; + byte = (bitpos / BITS_PER_UNIT) & 3; value = (unsigned char) (tmp[bitpos / 32] >> (bitpos & 31)); - if (total_bytes > UNITS_PER_WORD) + if (UNITS_PER_WORD < 4) { word = byte / UNITS_PER_WORD; - if (FLOAT_WORDS_BIG_ENDIAN) + if (WORDS_BIG_ENDIAN) word = (words - 1) - word; offset = word * UNITS_PER_WORD; if (BYTES_BIG_ENDIAN) @@ -7193,8 +7194,8 @@ native_encode_real (tree expr, unsigned char *ptr, int len) offset += byte % UNITS_PER_WORD; } else - offset = BYTES_BIG_ENDIAN ? (total_bytes - 1) - byte : byte; - ptr[offset] = value; + offset = BYTES_BIG_ENDIAN ? 3 - byte : byte; + ptr[offset + ((bitpos / BITS_PER_UNIT) & ~3)] = value; } return total_bytes; } @@ -7350,7 +7351,7 @@ native_interpret_real (tree type, unsigned char *ptr, int len) { enum machine_mode mode = TYPE_MODE (type); int total_bytes = GET_MODE_SIZE (mode); - int byte, offset, word, words; + 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 @@ -7361,16 +7362,17 @@ native_interpret_real (tree type, unsigned char *ptr, int len) total_bytes = GET_MODE_SIZE (TYPE_MODE (type)); if (total_bytes > len || total_bytes > 24) return NULL_TREE; - words = total_bytes / UNITS_PER_WORD; + words = 32 / UNITS_PER_WORD; memset (tmp, 0, sizeof (tmp)); - for (byte = 0; byte < total_bytes; byte++) + for (bitpos = 0; bitpos < total_bytes * BITS_PER_UNIT; + bitpos += BITS_PER_UNIT) { - int bitpos = byte * BITS_PER_UNIT; - if (total_bytes > UNITS_PER_WORD) + byte = (bitpos / BITS_PER_UNIT) & 3; + if (UNITS_PER_WORD < 4) { word = byte / UNITS_PER_WORD; - if (FLOAT_WORDS_BIG_ENDIAN) + if (WORDS_BIG_ENDIAN) word = (words - 1) - word; offset = word * UNITS_PER_WORD; if (BYTES_BIG_ENDIAN) @@ -7379,8 +7381,8 @@ native_interpret_real (tree type, unsigned char *ptr, int len) offset += byte % UNITS_PER_WORD; } else - offset = BYTES_BIG_ENDIAN ? (total_bytes - 1) - byte : byte; - value = ptr[offset]; + offset = BYTES_BIG_ENDIAN ? 3 - byte : byte; + value = ptr[offset + ((bitpos / BITS_PER_UNIT) & ~3)]; tmp[bitpos / 32] |= (unsigned long)value << (bitpos & 31); } |