aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJohn David Anglin <dave@hiauly1.hia.nrc.ca>2002-09-29 18:25:20 +0000
committerJohn David Anglin <danglin@gcc.gnu.org>2002-09-29 18:25:20 +0000
commit6ca6193b8250bcef3a3180246e7507a197355f52 (patch)
tree3090aa165727f2794affe010b3a28910ea6e18e2 /gcc
parentd7bb749a3d6d5841b64d0420a3aff3a558f88e1e (diff)
downloadgcc-6ca6193b8250bcef3a3180246e7507a197355f52.zip
gcc-6ca6193b8250bcef3a3180246e7507a197355f52.tar.gz
gcc-6ca6193b8250bcef3a3180246e7507a197355f52.tar.bz2
* expmed.c (extract_bit_field): Fix bit-field extraction from SUBREGs.
From-SVN: r57629
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/expmed.c41
2 files changed, 19 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 89f1d7e..2e488ed 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2002-09-29 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * expmed.c (extract_bit_field): Fix bit-field extraction from SUBREGs.
+
2002-09-29 Kazu Hirata <kazu@cs.umass.edu>
* builtins.def: Fix comment formatting.
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 37622f5..730c4c1 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -1031,25 +1031,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
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, bitnum, unsignedp,
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, bitnum, unsignedp,
&& 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