From 5f57dff07ba01651525283483b6ffc1ff59dfa59 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Sun, 27 Feb 1994 16:55:33 -0800 Subject: [PATCH] (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 --- gcc/expmed.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/gcc/expmed.c b/gcc/expmed.c index 5a06dbf5dc2..1d5d75eddac 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; -- 2.30.2