aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1993-08-11 05:22:55 +0000
committerRichard Stallman <rms@gnu.org>1993-08-11 05:22:55 +0000
commitc7e33f8937a1fc34594569f9cd19800768110bc0 (patch)
treea99fc9b7a36209d544c9ac4cdceb6ac2a97eaf66
parent2abe5d9099672f3d811f8171fad5593fd546b6b5 (diff)
downloadgcc-c7e33f8937a1fc34594569f9cd19800768110bc0.zip
gcc-c7e33f8937a1fc34594569f9cd19800768110bc0.tar.gz
gcc-c7e33f8937a1fc34594569f9cd19800768110bc0.tar.bz2
(SLOW_UNALIGNED_ACCESS): Define, but allow override.
(store_bit_field): Test that instead of STRICT_ALIGNMENT. Also, allow fetching as non-bitfield if memory is aligned enough. (extract_bit_field): Install code here like that in store_bit_field. From-SVN: r5131
-rw-r--r--gcc/expmed.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 3dcf6c7..1739e70 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -46,6 +46,10 @@ static rtx lshift_value ();
static int sdiv_pow2_cheap, smod_pow2_cheap;
+#ifndef SLOW_UNALIGNED_ACCESS
+#define SLOW_UNALIGNED_ACCESS STRICT_ALIGNMENT
+#endif
+
/* For compilers that support multiple targets with different word sizes,
MAX_BITS_PER_WORD contains the biggest value of BITS_PER_WORD. An example
is the H8/300(H) compiler. */
@@ -230,17 +234,22 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
/* Note that the adjustment of BITPOS above has no effect on whether
BITPOS is 0 in a REG bigger than a word. */
if (GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
- && (! STRICT_ALIGNMENT || GET_CODE (op0) != MEM)
+ && (GET_CODE (op0) != MEM
+ || ! SLOW_UNALIGNED_ACCESS
+ || (offset * BITS_PER_UNIT % bitsize == 0
+ && align % GET_MODE_SIZE (fieldmode) == 0))
&& bitpos == 0 && bitsize == GET_MODE_BITSIZE (fieldmode))
{
/* Storing in a full-word or multi-word field in a register
can be done with just SUBREG. */
if (GET_MODE (op0) != fieldmode)
- if (GET_CODE (op0) == REG)
- op0 = gen_rtx (SUBREG, fieldmode, op0, offset);
- else
- op0 = change_address (op0, fieldmode,
- plus_constant (XEXP (op0, 0), offset));
+ {
+ if (GET_CODE (op0) == REG)
+ op0 = gen_rtx (SUBREG, fieldmode, op0, offset);
+ else
+ op0 = change_address (op0, fieldmode,
+ plus_constant (XEXP (op0, 0), offset));
+ }
emit_move_insn (op0, value);
return value;
}
@@ -804,12 +813,16 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
#endif
/* Extracting a full-word or multi-word value
- from a structure in a register.
+ from a structure in a register or aligned memory.
This can be done with just SUBREG.
So too extracting a subword value in
the least significant part of the register. */
- if (GET_CODE (op0) == REG
+ if ((GET_CODE (op0) == REG
+ || (GET_CODE (op0) == MEM
+ && (! SLOW_UNALIGNED_ACCESS
+ || (offset * BITS_PER_UNIT % bitsize == 0
+ && align * BITS_PER_UNIT % bitsize == 0))))
&& ((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode)
&& bitpos % BITS_PER_WORD == 0)
|| (mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0) != BLKmode
@@ -824,8 +837,13 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
= mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0);
if (mode1 != GET_MODE (op0))
- op0 = gen_rtx (SUBREG, mode1, op0, offset);
-
+ {
+ if (GET_CODE (op0) == REG)
+ op0 = gen_rtx (SUBREG, mode1, op0, offset);
+ else
+ op0 = change_address (op0, mode1,
+ plus_constant (XEXP (op0, 0), offset));
+ }
if (mode1 != mode)
return convert_to_mode (tmode, op0, unsignedp);
return op0;