diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-06 15:39:07 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-06 15:39:07 +0000 |
commit | bc5449fc88f53b28252fdbec7662765405d1f013 (patch) | |
tree | 35c1f52210b03c333c66629497b389e5fbd9aefc /gcc/expmed.c | |
parent | fa16ade61e635e539575117c39106b7721c54513 (diff) | |
download | gcc-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.c | 33 |
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. |