(make_extraction): Use is_mode, not inner_mode,

for BYTES_BIG_ENDIAN adjustment to offset for non-bitfield case.
Update is_mode when stripping subreg from around a mem.

From-SVN: r2556
This commit is contained in:
Richard Stallman 1992-10-22 13:28:02 +00:00
parent 1880be65a8
commit 94b4b17a33
1 changed files with 20 additions and 8 deletions

View File

@ -4536,6 +4536,9 @@ make_extraction (mode, inner, pos, pos_rtx, len,
int unsignedp;
int in_dest, in_compare;
{
/* This mode describes the size of the storage area
to fetch the overall value from. Within that, we
ignore the POS lowest bits, etc. */
enum machine_mode is_mode = GET_MODE (inner);
enum machine_mode inner_mode;
enum machine_mode wanted_mem_mode = byte_mode;
@ -4547,11 +4550,21 @@ make_extraction (mode, inner, pos, pos_rtx, len,
/* Get some information about INNER and get the innermost object. */
if (GET_CODE (inner) == USE)
/* (use:SI (mem:QI foo)) stands for (mem:SI foo). */
/* We don't need to adjust the position because we set up the USE
to pretend that it was a full-word object. */
spans_byte = 1, inner = XEXP (inner, 0);
else if (GET_CODE (inner) == SUBREG && subreg_lowpart_p (inner))
inner = SUBREG_REG (inner);
{
/* If going from (subreg:SI (mem:QI ...)) to (mem:QI ...),
consider just the QI as the memory to extract from.
The subreg adds or removes high bits; its mode is
irrelevant to the meaning of this extraction,
since POS and LEN count from the lsb. */
if (GET_CODE (SUBREG_REG (inner)) == MEM)
is_mode = GET_MODE (SUBREG_REG (inner));
inner = SUBREG_REG (inner);
}
inner_mode = GET_MODE (inner);
@ -4589,8 +4602,6 @@ make_extraction (mode, inner, pos, pos_rtx, len,
|| (! mode_dependent_address_p (XEXP (inner, 0))
&& ! MEM_VOLATILE_P (inner))))))
{
int offset = pos / BITS_PER_UNIT;
/* If INNER is a MEM, make a new MEM that encompasses just the desired
field. If the original and current mode are the same, we need not
adjust the offset. Otherwise, we do if bytes big endian.
@ -4600,11 +4611,12 @@ make_extraction (mode, inner, pos, pos_rtx, len,
if (GET_CODE (inner) == MEM)
{
#if BYTES_BIG_ENDIAN
if (inner_mode != tmode)
offset = (GET_MODE_SIZE (inner_mode)
- GET_MODE_SIZE (tmode) - offset);
#endif
int offset;
/* POS counts from lsb, but make OFFSET count in memory order. */
if (BYTES_BIG_ENDIAN)
offset = (GET_MODE_BITSIZE (is_mode) - len - pos) / BITS_PER_UNIT;
else
offset = pos / BITS_PER_UNIT;
new = gen_rtx (MEM, tmode, plus_constant (XEXP (inner, 0), offset));
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (inner);