This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] store_bit_field: Handle paradoxical subregs properly
- From: Andreas Krebbel <krebbel1 at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 31 Mar 2006 12:29:55 +0200
- Subject: [PATCH] store_bit_field: Handle paradoxical subregs properly
Hi,
store_bit_field in expmed.c doesn't handle paradoxical subregs properly.
It should use the same logic simplify_subreg is using.
I don't have a testcase because the problem only occurred when using another
patch on top.
Bootstrapped on s390 and s390x with gcc 4.2 and gcc 4.1.
No testsuite regressions.
I will bootstrap and test this on i686 as well.
This patch is needed for another patch (I will post soon) fixing a gcc 4.1
regression. So please consider approving this for mainline and 4.1.
Bye,
-Andreas-
2006-03-31 Andreas Krebbel <krebbel1@de.ibm.com>
* expmed.c (store_bit_field): Add special handling for paradoxical
subregs on big endian machines.
Index: gcc/expmed.c
===================================================================
*** gcc/expmed.c.orig 2006-03-13 09:29:23.000000000 +0100
--- gcc/expmed.c 2006-03-30 17:25:51.000000000 +0200
*************** store_bit_field (rtx str_rtx, unsigned H
*** 363,369 ****
meaningful at a much higher level; when structures are copied
between memory and regs, the higher-numbered regs
always get higher addresses. */
! bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT;
op0 = SUBREG_REG (op0);
}
--- 363,387 ----
meaningful at a much higher level; when structures are copied
between memory and regs, the higher-numbered regs
always get higher addresses. */
! int inner_mode_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)));
! int outer_mode_size = GET_MODE_SIZE (GET_MODE (op0));
!
! byte_offset = 0;
!
! /* Paradoxical subregs need special handling on big endian machines. */
! if (SUBREG_BYTE (op0) == 0 && inner_mode_size < outer_mode_size)
! {
! int difference = inner_mode_size - outer_mode_size;
!
! if (WORDS_BIG_ENDIAN)
! byte_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
! if (BYTES_BIG_ENDIAN)
! byte_offset += difference % UNITS_PER_WORD;
! }
! else
! byte_offset = SUBREG_BYTE (op0);
!
! bitnum += byte_offset * BITS_PER_UNIT;
op0 = SUBREG_REG (op0);
}