From 77295decc864d07b52e926267f792f303159dcae Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Sat, 14 Jan 1995 06:19:31 +0000 Subject: [PATCH] (extract_bit_field, fields bigger than word case): Count subwords in target. (extract_bit_field, fields bigger than word case): Count subwords in target. Zero remaining upper bits if unsigned. From-SVN: r8756 --- gcc/expmed.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/gcc/expmed.c b/gcc/expmed.c index b2862b6de25..6ff8b2b1049 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -847,6 +847,10 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, offset += SUBREG_WORD (op0); op0 = SUBREG_REG (op0); } + + /* ??? We currently assume TARGET is at least as big as BITSIZE. + If that's wrong, the solution is to test for it and set TARGET to 0 + if needed. */ /* If OP0 is a register, BITPOS must count within a word. But as we have it, it counts within whatever size OP0 now has. @@ -909,7 +913,11 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, { /* If I is 0, use the low-order word in both field and target; if I is 1, use the next to lowest word; and so on. */ - int wordnum = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); + /* Word number in TARGET to use. */ + int wordnum = (WORDS_BIG_ENDIAN + ? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1 + : i); + /* Offset from start of field in OP0. */ int bit_offset = (WORDS_BIG_ENDIAN ? MAX (0, bitsize - (i + 1) * BITS_PER_WORD) : i * BITS_PER_WORD); @@ -929,7 +937,24 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, } if (unsignedp) - return target; + { + /* Unless we've filled TARGET, the upper regs in a multi-reg value + need to be zero'd out. */ + if (GET_MODE_SIZE (GET_MODE (target)) > nwords * UNITS_PER_WORD) + { + int i,total_words; + + total_words = GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD; + for (i = nwords; i < total_words; i++) + { + int wordnum = WORDS_BIG_ENDIAN ? total_words - i - 1 : i; + rtx target_part = operand_subword (target, wordnum, 1, VOIDmode); + emit_move_insn (target_part, const0_rtx); + } + } + 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), @@ -1424,7 +1449,8 @@ extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, /* Return a constant integer (CONST_INT or CONST_DOUBLE) mask value of mode MODE with BITSIZE ones followed by BITPOS zeros, or the complement of that if COMPLEMENT. The mask is truncated if - necessary to the width of mode MODE. */ + necessary to the width of mode MODE. The mask is zero-extended if + BITSIZE+BITPOS is too small for MODE. */ static rtx mask_rtx (mode, bitpos, bitsize, complement) -- 2.30.2