summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1998-10-09 15:50:25 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1998-10-09 15:50:25 +0000
commit86cde393d905d784e6808e01d199675dfa3d6fcd (patch)
treedcc7d4ffbedc5308ac113fce833c31a0318fd188 /gcc
parent3cf7d3b94b2170181803828fe49030a91087a9bc (diff)
downloadgcc-86cde393d905d784e6808e01d199675dfa3d6fcd.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22962 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/expmed.c62
-rw-r--r--gcc/function.c14
-rw-r--r--gcc/machmode.h5
-rw-r--r--gcc/stor-layout.c31
5 files changed, 106 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 436cd1d33a2..2a0bd663641 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+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)
* global.c (build_insn_chain): Verify no real insns exist past the
diff --git a/gcc/expmed.c b/gcc/expmed.c
index f9bd9ad20be..9b285d0e23f 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -261,6 +261,21 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
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. */
@@ -287,6 +302,18 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
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
@@ -955,6 +982,21 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
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. */
@@ -973,7 +1015,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
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
@@ -996,6 +1038,18 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
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
@@ -1088,12 +1142,12 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
/* 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
diff --git a/gcc/function.c b/gcc/function.c
index 5e607597f4f..5ad113cfc93 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2874,24 +2874,14 @@ purge_addressof_1 (loc, insn, force, store)
/* 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. */
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 119950c4348..e8c17e01642 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -211,6 +211,11 @@ extern unsigned char mode_wider_mode[];
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. */
extern enum machine_mode get_best_mode PROTO((int, int, int, enum machine_mode, int));
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 3c7cf23d7d3..a6bf053ba76 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -176,6 +176,37 @@ smallest_mode_for_size (size, class)
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. */
tree