diff options
author | Jim Wilson <wilson@gcc.gnu.org> | 1994-02-27 16:55:33 -0800 |
---|---|---|
committer | Jim Wilson <wilson@gcc.gnu.org> | 1994-02-27 16:55:33 -0800 |
commit | 5f57dff07ba01651525283483b6ffc1ff59dfa59 (patch) | |
tree | fb59a6276e5779219ed40a789de47de0988a93bf /gcc/expmed.c | |
parent | 81284a6ad220981f2d6a0e13ce3dade55c10cab8 (diff) | |
download | gcc-5f57dff07ba01651525283483b6ffc1ff59dfa59.zip gcc-5f57dff07ba01651525283483b6ffc1ff59dfa59.tar.gz gcc-5f57dff07ba01651525283483b6ffc1ff59dfa59.tar.bz2 |
(store_split_bit_field): If OP0 is a SUBREG, then compute WORD from the base register, instead of from the SUBREG.
(store_split_bit_field): If OP0 is a SUBREG, then
compute WORD from the base register, instead of from the SUBREG.
(extract_split_bit_field): Likewise.
(extract_bit_field): Sign-extend multiword bitfield if necessary.
From-SVN: r6668
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r-- | gcc/expmed.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c index 5a06dbf..1d5d75e 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -757,8 +757,19 @@ store_split_bit_field (op0, bitsize, bitpos, value, align) #endif /* If OP0 is a register, then handle OFFSET here. - In the register case, UNIT must be a whole word. */ - if (GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG) + + When handling multiword bitfields, extract_bit_field may pass + down a word_mode SUBREG of a larger REG for a bitfield that actually + crosses a word boundary. Thus, for a SUBREG, we must find + the current word starting from the base register. */ + if (GET_CODE (op0) == SUBREG) + { + word = operand_subword (SUBREG_REG (op0), + SUBREG_WORD (op0) + offset, 1, + GET_MODE (SUBREG_REG (op0))); + offset = 0; + } + else if (GET_CODE (op0) == REG) { word = operand_subword (op0, offset, 1, GET_MODE (op0)); offset = 0; @@ -917,7 +928,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, emit_move_insn (target_part, result_part); } - return target; + if (unsignedp) + return target; + /* Signed bit field: sign-extend with two arithmetic shifts. */ + target = expand_shift (LSHIFT_EXPR, mode, target, + build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0), + NULL_RTX, 0); + return expand_shift (RSHIFT_EXPR, mode, target, + build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0), + NULL_RTX, 0); } /* From here on we know the desired field is smaller than a word @@ -1505,8 +1524,19 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align) thissize = MIN (thissize, unit - thispos); /* If OP0 is a register, then handle OFFSET here. - In the register case, UNIT must be a whole word. */ - if (GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG) + + When handling multiword bitfields, extract_bit_field may pass + down a word_mode SUBREG of a larger REG for a bitfield that actually + crosses a word boundary. Thus, for a SUBREG, we must find + the current word starting from the base register. */ + if (GET_CODE (op0) == SUBREG) + { + word = operand_subword_force (SUBREG_REG (op0), + SUBREG_WORD (op0) + offset, + GET_MODE (SUBREG_REG (op0))); + offset = 0; + } + else if (GET_CODE (op0) == REG) { word = operand_subword_force (op0, offset, GET_MODE (op0)); offset = 0; |