diff options
author | Doug Evans <dje@gnu.org> | 1993-07-28 16:39:07 +0000 |
---|---|---|
committer | Doug Evans <dje@gnu.org> | 1993-07-28 16:39:07 +0000 |
commit | 0eb61c19ed94cea01e7e8e0540a932f15acf7ac7 (patch) | |
tree | cfb77f12f945f5f3a3527c454e8ce0f681ddbf6c /gcc/expmed.c | |
parent | 3ffeb92223535793cc6c7cca9ec9e5ba6534f79e (diff) | |
download | gcc-0eb61c19ed94cea01e7e8e0540a932f15acf7ac7.zip gcc-0eb61c19ed94cea01e7e8e0540a932f15acf7ac7.tar.gz gcc-0eb61c19ed94cea01e7e8e0540a932f15acf7ac7.tar.bz2 |
expmed.c (store_split_bitfield): Fix handling of bitfields that cross word boundaries...
* expmed.c (store_split_bitfield): Fix handling of bitfields that
cross word boundaries, can only handle a word at a time.
(extract_split_bitfield): Likewise.
From-SVN: r5012
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r-- | gcc/expmed.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c index ed07d5a..ebbce4c 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -678,7 +678,9 @@ store_split_bit_field (op0, bitsize, bitpos, value, align) rtx value; int align; { - int unit = align * BITS_PER_UNIT; + /* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that + much at a time. */ + int unit = MIN (align * BITS_PER_UNIT, BITS_PER_WORD); rtx word; int bitsdone = 0; @@ -699,7 +701,11 @@ store_split_bit_field (op0, bitsize, bitpos, value, align) offset = (bitpos + bitsdone) / unit; thispos = (bitpos + bitsdone) % unit; - thissize = unit - offset * BITS_PER_UNIT % unit; + /* THISSIZE must not overrun a word boundary. Otherwise, + store_fixed_bit_field will call us again, and we will mutually + recurse forever. */ + thissize = MIN (bitsize - bitsdone, BITS_PER_WORD); + thissize = MIN (thissize, unit - thispos); #if BYTES_BIG_ENDIAN /* Fetch successively less significant portions. */ @@ -736,7 +742,10 @@ store_split_bit_field (op0, bitsize, bitpos, value, align) if (word == 0) abort (); - store_fixed_bit_field (word, offset, thissize, thispos, part, align); + /* OFFSET is in UNITs, and UNIT is in bits. + store_fixed_bit_field wants offset in bytes. */ + store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT, + thissize, thispos, part, align); bitsdone += thissize; } } @@ -1434,7 +1443,9 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align) rtx op0; int bitsize, bitpos, unsignedp, align; { - int unit = align * BITS_PER_UNIT; + /* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that + much at a time. */ + int unit = MIN (align * BITS_PER_UNIT, BITS_PER_WORD); int bitsdone = 0; rtx result; int first = 1; @@ -1449,7 +1460,11 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align) offset = (bitpos + bitsdone) / unit; thispos = (bitpos + bitsdone) % unit; - thissize = unit - offset * BITS_PER_UNIT % unit; + /* THISSIZE must not overrun a word boundary. Otherwise, + extract_fixed_bit_field will call us again, and we will mutually + recurse forever. */ + thissize = MIN (bitsize - bitsdone, BITS_PER_WORD); + thissize = MIN (thissize, unit - thispos); /* If OP0 is a register, then handle OFFSET here. In the register case, UNIT must be a whole word. */ @@ -1465,8 +1480,11 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align) abort (); /* Extract the parts in bit-counting order, - whose meaning is determined by BYTES_PER_UNIT. */ - part = extract_fixed_bit_field (word_mode, word, offset, + whose meaning is determined by BYTES_PER_UNIT. + OFFSET is in UNITs, and UNIT is in bits. + extract_fixed_bit_field wants offset in bytes. */ + part = extract_fixed_bit_field (word_mode, word, + offset * unit / BITS_PER_UNIT, thissize, thispos, 0, 1, align); bitsdone += thissize; |