Commit d006aa54 by Richard Henderson Committed by Richard Henderson

expmed.c (store_bit_field): Pun non-integral str_rtx modes.

        * expmed.c (store_bit_field): Pun non-integral str_rtx modes.
        Take extra care for op0 now possibly being a subreg.
        (extract_bit_field): Likewise.
        * function.c (purge_addressof_1): Revert Oct 4 change.  Drop
        the reg to memory if there is no equal sized integral mode.
        * stor-layout.c (int_mode_for_mode): New function.
        * machmode.h: Prototype it.

From-SVN: r22962
parent 3663a304
Fri Oct 9 15:49:29 1998 Richard Henderson <rth@cygnus.com>
* expmed.c (store_bit_field): Pun non-integral str_rtx modes.
Take extra care for op0 now possibly being a subreg.
(extract_bit_field): Likewise.
* function.c (purge_addressof_1): Revert Oct 4 change. Drop
the reg to memory if there is no equal sized integral mode.
* stor-layout.c (int_mode_for_mode): New function.
* machmode.h: Prototype it.
Fri Oct 9 14:26:44 1998 Jeffrey A Law (law@cygnus.com) Fri Oct 9 14:26:44 1998 Jeffrey A Law (law@cygnus.com)
* global.c (build_insn_chain): Verify no real insns exist past the * global.c (build_insn_chain): Verify no real insns exist past the
......
...@@ -261,6 +261,21 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size) ...@@ -261,6 +261,21 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
op0 = SUBREG_REG (op0); 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. /* If OP0 is a register, BITPOS must count within a word.
But as we have it, it counts within whatever size OP0 now has. But as we have it, it counts within whatever size OP0 now has.
On a bigendian machine, these are not the same, so convert. */ On a bigendian machine, these are not the same, so convert. */
...@@ -287,6 +302,18 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size) ...@@ -287,6 +302,18 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
can be done with just SUBREG. */ can be done with just SUBREG. */
if (GET_MODE (op0) != fieldmode) 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) if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (fieldmode, op0, offset); op0 = gen_rtx_SUBREG (fieldmode, op0, offset);
else else
...@@ -955,6 +982,21 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, ...@@ -955,6 +982,21 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
op0 = SUBREG_REG (op0); 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. /* ??? 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 that's wrong, the solution is to test for it and set TARGET to 0
if needed. */ if needed. */
...@@ -973,7 +1015,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, ...@@ -973,7 +1015,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
So too extracting a subword value in So too extracting a subword value in
the least significant part of the register. */ the least significant part of the register. */
if (((GET_CODE (op0) == REG if (((GET_CODE (op0) != MEM
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode), && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (GET_MODE (op0)))) GET_MODE_BITSIZE (GET_MODE (op0))))
|| (GET_CODE (op0) == MEM || (GET_CODE (op0) == MEM
...@@ -996,6 +1038,18 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, ...@@ -996,6 +1038,18 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
if (mode1 != GET_MODE (op0)) 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) if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (mode1, op0, offset); op0 = gen_rtx_SUBREG (mode1, op0, offset);
else else
...@@ -1088,12 +1142,12 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, ...@@ -1088,12 +1142,12 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
/* OFFSET is the number of words or bytes (UNIT says which) /* 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. */ 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 if (offset != 0
|| GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD) || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
op0 = gen_rtx_SUBREG (TYPE_MODE (type_for_size (BITS_PER_WORD, 0)), op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
op0, offset); op0, offset);
offset = 0; offset = 0;
} }
else else
......
...@@ -2874,24 +2874,14 @@ purge_addressof_1 (loc, insn, force, store) ...@@ -2874,24 +2874,14 @@ purge_addressof_1 (loc, insn, force, store)
/* Don't even consider working with paradoxical subregs, /* Don't even consider working with paradoxical subregs,
or the moral equivalent seen here. */ 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 /* Do a bitfield insertion to mirror what would happen
in memory. */ in memory. */
rtx val, seq; 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 (store)
{ {
/* If we can't replace with a register, be afraid. */ /* If we can't replace with a register, be afraid. */
......
...@@ -211,6 +211,11 @@ extern unsigned char mode_wider_mode[]; ...@@ -211,6 +211,11 @@ extern unsigned char mode_wider_mode[];
extern enum machine_mode mode_for_size PROTO((unsigned int, enum mode_class, int)); extern enum machine_mode mode_for_size PROTO((unsigned int, enum mode_class, int));
/* Return an integer mode of the exact same size as the input mode,
or BLKmode on failure. */
extern enum machine_mode int_mode_for_mode PROTO((enum machine_mode));
/* Find the best mode to use to access a bit field. */ /* Find the best mode to use to access a bit field. */
extern enum machine_mode get_best_mode PROTO((int, int, int, enum machine_mode, int)); extern enum machine_mode get_best_mode PROTO((int, int, int, enum machine_mode, int));
......
...@@ -176,6 +176,37 @@ smallest_mode_for_size (size, class) ...@@ -176,6 +176,37 @@ smallest_mode_for_size (size, class)
abort (); abort ();
} }
/* Find an integer mode of the exact same size, or BLKmode on failure. */
enum machine_mode
int_mode_for_mode (mode)
enum machine_mode mode;
{
switch (GET_MODE_CLASS (mode))
{
case MODE_INT:
case MODE_PARTIAL_INT:
break;
case MODE_COMPLEX_INT:
case MODE_COMPLEX_FLOAT:
case MODE_FLOAT:
mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
break;
case MODE_RANDOM:
if (mode == BLKmode)
break;
/* FALLTHRU */
case MODE_CC:
default:
abort();
}
return mode;
}
/* Return the value of VALUE, rounded up to a multiple of DIVISOR. */ /* Return the value of VALUE, rounded up to a multiple of DIVISOR. */
tree tree
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment