op0 = SUBREG_REG (op0);
}
+ /* Make sure we are playing with integral modes. Pun with subregs
+ if we aren't. */
+ {
+ enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
+ if (imode != GET_MODE (op0))
+ {
+ if (GET_CODE (op0) == MEM)
+ op0 = change_address (op0, imode, NULL_RTX);
+ else if (imode != BLKmode)
+ op0 = gen_lowpart (imode, op0);
+ else
+ abort ();
+ }
+ }
+
/* If OP0 is a register, BITPOS must count within a word.
But as we have it, it counts within whatever size OP0 now has.
On a bigendian machine, these are not the same, so convert. */
can be done with just SUBREG. */
if (GET_MODE (op0) != fieldmode)
{
+ if (GET_CODE (op0) == SUBREG)
+ {
+ if (GET_MODE (SUBREG_REG (op0)) == fieldmode
+ || GET_MODE_CLASS (fieldmode) == MODE_INT
+ || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT)
+ op0 = SUBREG_REG (op0);
+ else
+ /* Else we've got some float mode source being extracted into
+ a different float mode destination -- this combination of
+ subregs results in Severe Tire Damage. */
+ abort ();
+ }
if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (fieldmode, op0, offset);
else
op0 = SUBREG_REG (op0);
}
+ /* Make sure we are playing with integral modes. Pun with subregs
+ if we aren't. */
+ {
+ enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
+ if (imode != GET_MODE (op0))
+ {
+ if (GET_CODE (op0) == MEM)
+ op0 = change_address (op0, imode, NULL_RTX);
+ else if (imode != BLKmode)
+ op0 = gen_lowpart (imode, op0);
+ else
+ abort ();
+ }
+ }
+
/* ??? We currently assume TARGET is at least as big as BITSIZE.
If that's wrong, the solution is to test for it and set TARGET to 0
if needed. */
So too extracting a subword value in
the least significant part of the register. */
- if (((GET_CODE (op0) == REG
+ if (((GET_CODE (op0) != MEM
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (GET_MODE (op0))))
|| (GET_CODE (op0) == MEM
if (mode1 != GET_MODE (op0))
{
+ if (GET_CODE (op0) == SUBREG)
+ {
+ if (GET_MODE (SUBREG_REG (op0)) == mode1
+ || GET_MODE_CLASS (mode1) == MODE_INT
+ || GET_MODE_CLASS (mode1) == MODE_PARTIAL_INT)
+ op0 = SUBREG_REG (op0);
+ else
+ /* Else we've got some float mode source being extracted into
+ a different float mode destination -- this combination of
+ subregs results in Severe Tire Damage. */
+ abort ();
+ }
if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (mode1, op0, offset);
else
/* OFFSET is the number of words or bytes (UNIT says which)
from STR_RTX to the first word or byte containing part of the field. */
- if (GET_CODE (op0) == REG)
+ if (GET_CODE (op0) != MEM)
{
if (offset != 0
|| GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
- op0 = gen_rtx_SUBREG (TYPE_MODE (type_for_size (BITS_PER_WORD, 0)),
- op0, offset);
+ op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
+ op0, offset);
offset = 0;
}
else
/* Don't even consider working with paradoxical subregs,
or the moral equivalent seen here. */
- if (size_x < size_sub)
+ if (size_x < size_sub
+ && int_mode_for_mode (GET_MODE (sub)) != BLKmode)
{
/* Do a bitfield insertion to mirror what would happen
in memory. */
rtx val, seq;
- /* We cannot do this if we are trying to pick out
- an integral piece, smaller than a word, of a
- floating point value. */
- if (INTEGRAL_MODE_P (GET_MODE (x))
- && GET_MODE_SIZE (GET_MODE (x)) < UNITS_PER_WORD
- && FLOAT_MODE_P (GET_MODE (sub)))
- {
- put_addressof_into_stack (XEXP (x, 0));
- return;
- }
-
if (store)
{
/* If we can't replace with a register, be afraid. */