summaryrefslogtreecommitdiff
path: root/gcc/expmed.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-06 15:39:07 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-06 15:39:07 +0000
commitbc5449fc88f53b28252fdbec7662765405d1f013 (patch)
tree35c1f52210b03c333c66629497b389e5fbd9aefc /gcc/expmed.c
parentfa16ade61e635e539575117c39106b7721c54513 (diff)
downloadgcc-bc5449fc88f53b28252fdbec7662765405d1f013.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94677 138bc75d-0d04-0410-961f-82ee72b054a4
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 87a219d2605..1a1bdf74b04 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.