This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]