aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-04-03 11:05:38 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2007-04-03 11:05:38 +0200
commit0a9430a8312d9f5a3795747773796b21d3bfe526 (patch)
tree602f9d225374a7b7691e8fa6a89f62777839aed1 /gcc/fold-const.c
parenteb9af792f2c0e8934f6b537ec12f8211d1fba505 (diff)
downloadgcc-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.c34
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);
}