This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: Fix PR c/8023
- From: "John David Anglin" <dave at hiauly1 dot hia dot nrc dot ca>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 28 Sep 2002 12:06:17 -0400 (EDT)
- Subject: PATCH: Fix PR c/8023
The enclosed patch fixes the problem observed in PR c/8023. The old
code incorrectly calculated both the bit position and the byte offset
when the src rtx was a SUBREG. The problem probably wasn't noticed before
because BITPOS was correct if the SUBREG offset was 0 on little-endian
or the SUBREG was at the right-most position on big-endian.
I have tested the patch with no regressions on i686-pc-linux-gnu,
hppa64-hp-hpux11.00, hppa64-hp-hpux11.11, hppa2.0w-hp-hpux11.11,
and hppa-unknown-linux-gnu.
OK?
Dave
--
J. David Anglin dave.anglin@nrc.ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6605)
2002-09-28 John David Anglin <dave@hiauly1.hia.nrc.ca>
* expmed.c (extract_bit_field): Fix bit-field extraction from SUBREGs.
Index: expmed.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.123
diff -u -3 -p -r1.123 expmed.c
--- expmed.c 22 Sep 2002 14:09:31 -0000 1.123
+++ expmed.c 27 Sep 2002 23:01:09 -0000
@@ -1031,25 +1031,15 @@ extract_bit_field (str_rtx, bitsize, bit
if (tmode == VOIDmode)
tmode = mode;
+
while (GET_CODE (op0) == SUBREG)
{
- int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));
- int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));
-
- offset += SUBREG_BYTE (op0) / UNITS_PER_WORD;
-
- inner_size = MIN (inner_size, BITS_PER_WORD);
-
- if (BYTES_BIG_ENDIAN && (outer_size < inner_size))
+ bitpos += SUBREG_BYTE (op0) * BITS_PER_UNIT;
+ if (bitpos > unit)
{
- bitpos += inner_size - outer_size;
- if (bitpos > unit)
- {
- offset += (bitpos / unit);
- bitpos %= unit;
- }
+ offset += (bitpos / unit);
+ bitpos %= unit;
}
-
op0 = SUBREG_REG (op0);
}
@@ -1086,9 +1076,13 @@ extract_bit_field (str_rtx, bitsize, bit
set_mem_expr (op0, 0);
}
- /* ??? 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. */
+ /* Extraction of a full-word or multi-word value from a structure
+ in a register or aligned memory can be done with just a SUBREG.
+ A subword value in the least significant part of a register
+ can also be extracted with a SUBREG. For this, we need the
+ byte offset of the value in op0. */
+
+ byte_offset = bitpos / BITS_PER_UNIT + offset * UNITS_PER_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.
@@ -1098,14 +1092,9 @@ extract_bit_field (str_rtx, bitsize, bit
&& unit > GET_MODE_BITSIZE (GET_MODE (op0)))
bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
- /* Extracting a full-word or multi-word value
- from a structure in a register or aligned memory.
- This can be done with just SUBREG.
- So too extracting a subword value in
- the least significant part of the register. */
-
- byte_offset = (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
- + (offset * UNITS_PER_WORD);
+ /* ??? 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. */
mode1 = (VECTOR_MODE_P (tmode)
? mode