- else if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG
- || GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR)
- return simplify_gen_subreg (mode, x, GET_MODE (x), offset);
- else if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
- || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
- && GET_MODE (x) == VOIDmode)
- return simplify_gen_subreg (mode, x, int_mode_for_mode (mode), offset);
- /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
- from the low-order part of the constant. */
- else if ((GET_MODE_CLASS (mode) == MODE_INT
- || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
- && GET_MODE (x) == VOIDmode
- && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
- {
- /* If MODE is twice the host word size, X is already the desired
- representation. Otherwise, if MODE is wider than a word, we can't
- do this. If MODE is exactly a word, return just one CONST_INT. */
-
- if (GET_MODE_BITSIZE (mode) >= 2 * HOST_BITS_PER_WIDE_INT)
- return x;
- else if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
- return 0;
- else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT)
- return (GET_CODE (x) == CONST_INT ? x
- : GEN_INT (CONST_DOUBLE_LOW (x)));
- else
- {
- /* MODE must be narrower than HOST_BITS_PER_WIDE_INT. */
- HOST_WIDE_INT val = (GET_CODE (x) == CONST_INT ? INTVAL (x)
- : CONST_DOUBLE_LOW (x));
-
- /* Sign extend to HOST_WIDE_INT. */
- val = trunc_int_for_mode (val, mode);
-
- return (GET_CODE (x) == CONST_INT && INTVAL (x) == val ? x
- : GEN_INT (val));
- }
- }
-
- /* The floating-point emulator 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 ...)). */
- /* Single-precision floats are always 32-bits and double-precision
- floats are always 64-bits. */
-
- else if (GET_MODE_CLASS (mode) == MODE_FLOAT
- && GET_MODE_BITSIZE (mode) == 32
- && GET_CODE (x) == CONST_INT)
- {
- REAL_VALUE_TYPE r;
- long i = INTVAL (x);
-
- real_from_target (&r, &i, mode);
- return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
- }
- else if (GET_MODE_CLASS (mode) == MODE_FLOAT
- && GET_MODE_BITSIZE (mode) == 64
- && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
- && GET_MODE (x) == VOIDmode)
- {
- REAL_VALUE_TYPE r;
- HOST_WIDE_INT low, high;
- long i[2];
-
- 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);
- }
-
- if (HOST_BITS_PER_WIDE_INT > 32)
- high = low >> 31 >> 1;
-
- /* 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;
-
- real_from_target (&r, i, mode);
- 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;
-
- /* Convert 'r' into an array of four 32-bit words in target word
- order. */
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- switch (GET_MODE_BITSIZE (GET_MODE (x)))
- {
- case 32:
- REAL_VALUE_TO_TARGET_SINGLE (r, i[3 * endian]);
- i[1] = 0;
- i[2] = 0;
- i[3 - 3 * endian] = 0;
- break;
- case 64:
- REAL_VALUE_TO_TARGET_DOUBLE (r, i + 2 * endian);
- i[2 - 2 * endian] = 0;
- i[3 - 2 * endian] = 0;
- break;
- case 96:
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, i + endian);
- i[3 - 3 * endian] = 0;
- break;
- case 128:
- 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[3 * endian], i[1 + endian], mode);
-#else
- if (HOST_BITS_PER_WIDE_INT != 64)
- abort ();
-
- return immed_double_const ((((unsigned long) i[3 * endian])
- | ((HOST_WIDE_INT) i[1 + endian] << 32)),
- (((unsigned long) i[2 - endian])
- | ((HOST_WIDE_INT) i[3 - 3 * endian] << 32)),
- mode);
-#endif
- }
- /* If MODE is a condition code and X is a CONST_INT, the value of X
- must already have been "recognized" by the back-end, and we can
- assume that it is valid for this mode. */
- else if (GET_MODE_CLASS (mode) == MODE_CC
- && GET_CODE (x) == CONST_INT)
- return x;