diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1996-05-11 07:42:11 -0400 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1996-05-11 07:42:11 -0400 |
commit | a281e72d06a335cb2e69a254b6844609b861865b (patch) | |
tree | d631d973de309a4d67349630dea33308c4b690d1 /gcc | |
parent | 574baa641db6d80b3656164a97efec735d588d4d (diff) | |
download | gcc-a281e72d06a335cb2e69a254b6844609b861865b.zip gcc-a281e72d06a335cb2e69a254b6844609b861865b.tar.gz gcc-a281e72d06a335cb2e69a254b6844609b861865b.tar.bz2 |
(store_field): Support BLKmode bitfield if aligned on byte boundary using emit_block_move.
(store_field): Support BLKmode bitfield if aligned on byte boundary using
emit_block_move.
(expand_expr, case COMPONENT_REF): Likewise.
From-SVN: r11971
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/expr.c | 43 |
1 files changed, 42 insertions, 1 deletions
@@ -3915,6 +3915,27 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, && mode != TYPE_MODE (TREE_TYPE (exp))) temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1); + /* If the modes of TARGET and TEMP are both BLKmode, both + must be in memory and BITPOS must be aligned on a byte + boundary. If so, we simply do a block copy. */ + if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode) + { + if (GET_CODE (target) != MEM || GET_CODE (temp) != MEM + || bitpos % BITS_PER_UNIT != 0) + abort (); + + temp = change_address (temp, VOIDmode, + plus_constant (XEXP (temp, 0), + bitpos / BITS_PER_UNIT)); + + emit_block_move (target, temp, + GEN_INT ((bitsize + BITS_PER_UNIT - 1) + / BITS_PER_UNIT), + 1); + + return value_mode == VOIDmode ? const0_rtx : target; + } + /* Store the value in the bitfield. */ store_bit_field (target, bitsize, bitpos, mode, temp, align, total_size); if (value_mode != VOIDmode) @@ -5350,7 +5371,27 @@ expand_expr (exp, target, tmode, modifier) ext_mode = mode_for_size (bitsize, MODE_INT, 1); if (ext_mode == BLKmode) - abort (); + { + /* In this case, BITPOS must start at a byte boundary and + TARGET, if specified, must be a MEM. */ + if (GET_CODE (op0) != MEM + || (target != 0 && GET_CODE (target) != MEM) + || bitpos % BITS_PER_UNIT != 0) + abort (); + + op0 = change_address (op0, VOIDmode, + plus_constant (XEXP (op0, 0), + bitpos / BITS_PER_UNIT)); + if (target == 0) + target = assign_temp (type, 0, 1, 1); + + emit_block_move (target, op0, + GEN_INT ((bitsize + BITS_PER_UNIT - 1) + / BITS_PER_UNIT), + 1); + + return target; + } op0 = validize_mem (op0); |