summaryrefslogtreecommitdiff
path: root/gcc/emit-rtl.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1993-05-29 18:13:55 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1993-05-29 18:13:55 +0000
commit48509d9036308c649a0e04bc55002f4c6ea0524d (patch)
tree7bd29990524d37fb97cc4b584910fa0f2e92fb5e /gcc/emit-rtl.c
parent2ebe8a66011013f2182060c1d672bc458e4f40d2 (diff)
downloadgcc-48509d9036308c649a0e04bc55002f4c6ea0524d.tar.gz
(operand_subword): Correctly handle case when
REAL_VALUE_TO_TARGET_DOUBLE is used on a 64-bit machine. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@4593 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/emit-rtl.c')
-rw-r--r--gcc/emit-rtl.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index cec8f0ff8bf..afa0601b8bf 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -921,11 +921,13 @@ operand_subword (op, i, validate_address, mode)
/* The only remaining cases are when OP is a constant. If the host and
target floating formats are the same, handling two-word floating
- constants are easy. */
+ constants are easy. Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}
+ are defined as returning 32 bit and 64-bit values, respectively,
+ and not values of BITS_PER_WORD and 2 * BITS_PER_WORD bits. */
#ifdef REAL_ARITHMETIC
if ((HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
&& GET_MODE_CLASS (mode) == MODE_FLOAT
- && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
+ && GET_MODE_BITSIZE (mode) == 64
&& GET_CODE (op) == CONST_DOUBLE)
{
HOST_WIDE_INT k[2];
@@ -933,7 +935,19 @@ operand_subword (op, i, validate_address, mode)
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
- return GEN_INT (k[i]);
+
+ /* We handle 32-bit and 64-bit host words here. Note that the order in
+ which the words are written depends on the word endianness.
+
+ ??? This is a potential portability problem and should
+ be fixed at some point. */
+ if (HOST_BITS_PER_WIDE_INT == 32)
+ return GEN_INT (k[i]);
+ else if (HOST_BITS_PER_WIDE_INT == 64 && i == 0)
+ return GEN_INT ((k[! WORDS_BIG_ENDIAN] << 32)
+ | k[WORDS_BIG_ENDIAN]);
+ else
+ abort ();
}
#else /* no REAL_ARITHMETIC */
if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
@@ -963,7 +977,7 @@ operand_subword (op, i, validate_address, mode)
#ifdef REAL_ARITHMETIC
if ((HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
&& GET_MODE_CLASS (mode) == MODE_FLOAT
- && GET_MODE_SIZE (mode) == UNITS_PER_WORD
+ && GET_MODE_BITSIZE (mode) == 32
&& GET_CODE (op) == CONST_DOUBLE)
{
HOST_WIDE_INT l;