emit-rtl.c (gen_lowpart_common): Handle cross-compiling between 64-bit and 32-bit machines.
* emit-rtl.c (gen_lowpart_common) [REAL_ARITHMETIC]: Handle cross-compiling between 64-bit and 32-bit machines. From-SVN: r35275
This commit is contained in:
parent
75cdbeb8b6
commit
a2061c0d61
@ -1,3 +1,8 @@
|
||||
2000-07-26 Geoffrey Keating <geoffk@cygnus.com>
|
||||
|
||||
* emit-rtl.c (gen_lowpart_common) [REAL_ARITHMETIC]: Handle
|
||||
cross-compiling between 64-bit and 32-bit machines.
|
||||
|
||||
2000-07-27 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* config/ia64/ia64.md (movqicc_astep, movqi_internal_astep): New.
|
||||
|
160
gcc/emit-rtl.c
160
gcc/emit-rtl.c
@ -793,6 +793,7 @@ gen_lowpart_common (mode, x)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef REAL_ARITHMETIC
|
||||
/* If X is an integral constant but we want it in floating-point, it
|
||||
must be the case that we have a union of an integer and a floating-point
|
||||
value. If the machine-parameters allow it, simulate that union here
|
||||
@ -806,23 +807,12 @@ gen_lowpart_common (mode, x)
|
||||
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
|
||||
&& GET_CODE (x) == CONST_INT
|
||||
&& sizeof (float) * HOST_BITS_PER_CHAR == HOST_BITS_PER_WIDE_INT)
|
||||
#ifdef REAL_ARITHMETIC
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
HOST_WIDE_INT i;
|
||||
|
||||
i = INTVAL (x);
|
||||
r = REAL_VALUE_FROM_TARGET_SINGLE (i);
|
||||
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
|
||||
}
|
||||
#else
|
||||
{
|
||||
union {HOST_WIDE_INT i; float d; } u;
|
||||
|
||||
u.i = INTVAL (x);
|
||||
return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);
|
||||
}
|
||||
#endif
|
||||
else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
|
||||
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|
||||
|| flag_pretend_float)
|
||||
@ -832,28 +822,6 @@ gen_lowpart_common (mode, x)
|
||||
&& GET_MODE (x) == VOIDmode
|
||||
&& (sizeof (double) * HOST_BITS_PER_CHAR
|
||||
== 2 * HOST_BITS_PER_WIDE_INT))
|
||||
#ifdef REAL_ARITHMETIC
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
HOST_WIDE_INT i[2];
|
||||
HOST_WIDE_INT low, high;
|
||||
|
||||
if (GET_CODE (x) == CONST_INT)
|
||||
low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);
|
||||
else
|
||||
low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);
|
||||
|
||||
/* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the
|
||||
target machine. */
|
||||
if (WORDS_BIG_ENDIAN)
|
||||
i[0] = high, i[1] = low;
|
||||
else
|
||||
i[0] = low, i[1] = high;
|
||||
|
||||
r = REAL_VALUE_FROM_TARGET_DOUBLE (i);
|
||||
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
|
||||
}
|
||||
#else
|
||||
{
|
||||
union {HOST_WIDE_INT i[2]; double d; } u;
|
||||
HOST_WIDE_INT low, high;
|
||||
@ -871,38 +839,6 @@ gen_lowpart_common (mode, x)
|
||||
|
||||
return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We need an extra case for machines where HOST_BITS_PER_WIDE_INT is the
|
||||
same as sizeof (double) or when sizeof (float) is larger than the
|
||||
size of a word on the target machine. */
|
||||
#ifdef REAL_ARITHMETIC
|
||||
else if (mode == SFmode && GET_CODE (x) == CONST_INT)
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
HOST_WIDE_INT i;
|
||||
|
||||
i = INTVAL (x);
|
||||
r = REAL_VALUE_FROM_TARGET_SINGLE (i);
|
||||
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
|
||||
}
|
||||
else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
|
||||
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|
||||
|| flag_pretend_float)
|
||||
&& GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
|
||||
&& GET_CODE (x) == CONST_INT
|
||||
&& (sizeof (double) * HOST_BITS_PER_CHAR
|
||||
== HOST_BITS_PER_WIDE_INT))
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
HOST_WIDE_INT i;
|
||||
|
||||
i = INTVAL (x);
|
||||
r = REAL_VALUE_FROM_TARGET_DOUBLE (&i);
|
||||
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Similarly, if this is converting a floating-point value into a
|
||||
single-word integer. Only do this is the host and target parameters are
|
||||
@ -941,6 +877,100 @@ gen_lowpart_common (mode, x)
|
||||
&& highpart && GET_CODE (highpart) == CONST_INT)
|
||||
return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);
|
||||
}
|
||||
#else /* ifndef REAL_ARITHMETIC */
|
||||
|
||||
/* When we have a FP emulator, we can handle all conversions between
|
||||
FP and integer operands. This simplifies reload because it
|
||||
doesn't have to deal with constructs like (subreg:DI
|
||||
(const_double:SF ...)) or (subreg:DF (const_int ...)). */
|
||||
|
||||
else if (mode == SFmode
|
||||
&& GET_CODE (x) == CONST_INT)
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
HOST_WIDE_INT i;
|
||||
|
||||
i = INTVAL (x);
|
||||
r = REAL_VALUE_FROM_TARGET_SINGLE (i);
|
||||
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
|
||||
}
|
||||
else if (mode == DFmode
|
||||
&& (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
|
||||
&& GET_MODE (x) == VOIDmode)
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
HOST_WIDE_INT i[2];
|
||||
HOST_WIDE_INT low, high;
|
||||
|
||||
if (GET_CODE (x) == CONST_INT)
|
||||
{
|
||||
low = INTVAL (x);
|
||||
high = low >> (HOST_BITS_PER_WIDE_INT - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
low = CONST_DOUBLE_LOW (x);
|
||||
high = CONST_DOUBLE_HIGH (x);
|
||||
}
|
||||
|
||||
/* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the
|
||||
target machine. */
|
||||
if (WORDS_BIG_ENDIAN)
|
||||
i[0] = high, i[1] = low;
|
||||
else
|
||||
i[0] = low, i[1] = high;
|
||||
|
||||
r = REAL_VALUE_FROM_TARGET_DOUBLE (i);
|
||||
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
|
||||
}
|
||||
else if ((GET_MODE_CLASS (mode) == MODE_INT
|
||||
|| GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
|
||||
&& GET_CODE (x) == CONST_DOUBLE
|
||||
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long i[4]; /* Only the low 32 bits of each 'long' are used. */
|
||||
int endian = WORDS_BIG_ENDIAN ? 1 : 0;
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, x);
|
||||
switch (GET_MODE (x))
|
||||
{
|
||||
case SFmode:
|
||||
REAL_VALUE_TO_TARGET_SINGLE (r, i[endian]);
|
||||
i[1-endian] = 0;
|
||||
break;
|
||||
case DFmode:
|
||||
REAL_VALUE_TO_TARGET_DOUBLE (r, i);
|
||||
break;
|
||||
#if LONG_DOUBLE_TYPE_SIZE == 96
|
||||
case XFmode:
|
||||
#else
|
||||
case TFmode:
|
||||
#endif
|
||||
REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, i);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Now, pack the 32-bit elements of the array into a CONST_DOUBLE
|
||||
and return it. */
|
||||
#if HOST_BITS_PER_WIDE_INT == 32
|
||||
return immed_double_const (i[endian], i[1-endian], mode);
|
||||
#else
|
||||
if (HOST_BITS_PER_WIDE_INT != 64)
|
||||
abort();
|
||||
for (c = 0; c < 4; c++)
|
||||
i[c] &= 0xffffffffL;
|
||||
|
||||
return immed_double_const (i[endian*3] |
|
||||
(((HOST_WIDE_INT) i[1+endian]) << 32),
|
||||
i[2-endian] |
|
||||
(((HOST_WIDE_INT) i[3-endian*3]) << 32),
|
||||
mode);
|
||||
#endif
|
||||
}
|
||||
#endif /* ifndef REAL_ARITHMETIC */
|
||||
|
||||
/* Otherwise, we can't do this. */
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user