diff options
author | uweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-10-28 12:47:21 +0000 |
---|---|---|
committer | uweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-10-28 12:47:21 +0000 |
commit | d7041732999cc4ab850ff823358b34eba59af6bf (patch) | |
tree | a9bda2464d7b200ebd679487ccda3fef16f416b1 /gcc/final.c | |
parent | 99005f0295bbd3d43057a21061be9e36015a7258 (diff) | |
download | gcc-d7041732999cc4ab850ff823358b34eba59af6bf.tar.gz |
PR target/15286
* final.c (alter_subreg): Compute correct offset to use with
paradoxical SUBREGs of memory operands.
* recog.c (general_operand): Allow paradoxical SUBREGs of
memory operands after reload.
* simplify-rtx.c (simplify_gen_subreg): Fail if simplify_subreg
has failed when passed a hard register.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@89752 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/final.c')
-rw-r--r-- | gcc/final.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/gcc/final.c b/gcc/final.c index bf4f521bcf5..3952b9ff82c 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2608,7 +2608,24 @@ alter_subreg (rtx *xp) /* simplify_subreg does not remove subreg from volatile references. We are required to. */ if (MEM_P (y)) - *xp = adjust_address (y, GET_MODE (x), SUBREG_BYTE (x)); + { + int offset = SUBREG_BYTE (x); + + /* For paradoxical subregs on big-endian machines, SUBREG_BYTE + contains 0 instead of the proper offset. See simplify_subreg. */ + if (offset == 0 + && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x))) + { + int difference = GET_MODE_SIZE (GET_MODE (y)) + - GET_MODE_SIZE (GET_MODE (x)); + if (WORDS_BIG_ENDIAN) + offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; + if (BYTES_BIG_ENDIAN) + offset += difference % UNITS_PER_WORD; + } + + *xp = adjust_address (y, GET_MODE (x), offset); + } else { rtx new = simplify_subreg (GET_MODE (x), y, GET_MODE (y), |