aboutsummaryrefslogtreecommitdiff
path: root/gcc/expmed.c
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@redhat.com>2005-02-06 15:39:07 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2005-02-06 15:39:07 +0000
commit2c58f7dde2bdb003105479ffe316cb7935b711c3 (patch)
tree35c1f52210b03c333c66629497b389e5fbd9aefc /gcc/expmed.c
parent55c4ae3f3a80eda3855ccc64fa3064347a1dda01 (diff)
downloadgcc-2c58f7dde2bdb003105479ffe316cb7935b711c3.zip
gcc-2c58f7dde2bdb003105479ffe316cb7935b711c3.tar.gz
gcc-2c58f7dde2bdb003105479ffe316cb7935b711c3.tar.bz2
expmed.c (store_bit_field): Make the SUBREG code adjust bitnum.
* expmed.c (store_bit_field): Make the SUBREG code adjust bitnum. Set bitpos and offset later in the function. Do nothing if the target is a register and if the bitfield lies completely outside that register. (extract_bit_field): Make the same SUBREG, bitpos and offset changes here. Return an uninitialised register if the source value is stored in a register and the bitfield lies completely outside that register. From-SVN: r94677
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r--gcc/expmed.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 87a219d..1a1bdf7 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -337,8 +337,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{
unsigned int unit
= (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD;
- unsigned HOST_WIDE_INT offset = bitnum / unit;
- unsigned HOST_WIDE_INT bitpos = bitnum % unit;
+ unsigned HOST_WIDE_INT offset, bitpos;
rtx op0 = str_rtx;
int byte_offset;
rtx orig_value;
@@ -352,12 +351,16 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
meaningful at a much higher level; when structures are copied
between memory and regs, the higher-numbered regs
always get higher addresses. */
- offset += (SUBREG_BYTE (op0) / UNITS_PER_WORD);
- /* We used to adjust BITPOS here, but now we do the whole adjustment
- right after the loop. */
+ bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT;
op0 = SUBREG_REG (op0);
}
+ /* No action is needed if the target is a register and if the field
+ lies completely outside that register. This can occur if the source
+ code contains an out-of-bounds access to a small array. */
+ if (REG_P (op0) && bitnum >= GET_MODE_BITSIZE (GET_MODE (op0)))
+ return value;
+
/* Use vec_set patterns for inserting parts of vectors whenever
available. */
if (VECTOR_MODE_P (GET_MODE (op0))
@@ -419,6 +422,8 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
done with a simple store. For targets that support fast unaligned
memory, any naturally sized, unit aligned field can be done directly. */
+ offset = bitnum / unit;
+ bitpos = bitnum % unit;
byte_offset = (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+ (offset * UNITS_PER_WORD);
@@ -1064,8 +1069,7 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{
unsigned int unit
= (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD;
- unsigned HOST_WIDE_INT offset = bitnum / unit;
- unsigned HOST_WIDE_INT bitpos = bitnum % unit;
+ unsigned HOST_WIDE_INT offset, bitpos;
rtx op0 = str_rtx;
rtx spec_target = target;
rtx spec_target_subreg = 0;
@@ -1080,15 +1084,16 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
while (GET_CODE (op0) == SUBREG)
{
- bitpos += SUBREG_BYTE (op0) * BITS_PER_UNIT;
- if (bitpos > unit)
- {
- offset += (bitpos / unit);
- bitpos %= unit;
- }
+ bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT;
op0 = SUBREG_REG (op0);
}
+ /* If we have an out-of-bounds access to a register, just return an
+ uninitialised register of the required mode. This can occur if the
+ source code contains an out-of-bounds access to a small array. */
+ if (REG_P (op0) && bitnum >= GET_MODE_BITSIZE (GET_MODE (op0)))
+ return gen_reg_rtx (tmode);
+
if (REG_P (op0)
&& mode == GET_MODE (op0)
&& bitnum == 0
@@ -1188,6 +1193,8 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
can also be extracted with a SUBREG. For this, we need the
byte offset of the value in op0. */
+ bitpos = bitnum % unit;
+ offset = bitnum / unit;
byte_offset = bitpos / BITS_PER_UNIT + offset * UNITS_PER_WORD;
/* If OP0 is a register, BITPOS must count within a word.