aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1992-11-16 06:52:13 -0700
committerJeff Law <law@gcc.gnu.org>1992-11-16 06:52:13 -0700
commite37ce5f6f6d7493a4a9338df33429743ed149527 (patch)
tree4d8257c82481e4abee1354f0b8a372f7c2d7c527
parent143f1945b92e9592f0e3e322a59d5347a6ebe86e (diff)
downloadgcc-e37ce5f6f6d7493a4a9338df33429743ed149527.zip
gcc-e37ce5f6f6d7493a4a9338df33429743ed149527.tar.gz
gcc-e37ce5f6f6d7493a4a9338df33429743ed149527.tar.bz2
pa.c (output_move_double): Handle indirect stores to memory via an auto-incremented/auto-decremented...
* pa.c (output_move_double): Handle indirect stores to memory via an auto-incremented/auto-decremented register in the same manner in which loads are handled. From-SVN: r2751
-rw-r--r--gcc/config/pa/pa.c45
1 files changed, 39 insertions, 6 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index b1a8d8d..8b32e19 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -798,16 +798,49 @@ output_move_double (operands)
if (optype0 == MEMOP)
{
+ /* We have to output the address syntax ourselves, since print_operand
+ doesn't deal with the addresses we want to use. Fix this later. */
+
rtx addr = XEXP (operands[0], 0);
- if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == PRE_INC)
+ if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
{
- operands[0] = gen_rtx (MEM, SImode, addr);
- return "stw%M0 %1,%0\n\tstw%M0 %R1,%0";
+ rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0);
+
+ operands[0] = XEXP (addr, 0);
+ if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
+ abort ();
+
+ if (!reg_overlap_mentioned_p (high_reg, addr))
+ {
+ /* No overlap between high target register and address
+ register. (We do this in a non-obvious way to
+ save a register file writeback) */
+ if (GET_CODE (addr) == POST_INC)
+ return "stws,ma %1,8(0,%0)\n\tstw %R1,-4(0,%0)";
+ return "stws,ma %1,-8(0,%0)\n\tstw %R1,12(0,%0)";
+ }
+ else
+ abort();
}
- else if (GET_CODE (addr) == POST_DEC || GET_CODE (addr) == PRE_DEC)
+ else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
{
- operands[0] = gen_rtx (MEM, SImode, addr);
- return "stw%M0 %R1,%0\n\tstw%M0 %1,%0";
+ rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0);
+
+ operands[0] = XEXP (addr, 0);
+ if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
+ abort ();
+
+ if (!reg_overlap_mentioned_p (high_reg, addr))
+ {
+ /* No overlap between high target register and address
+ register. (We do this in a non-obvious way to
+ save a register file writeback) */
+ if (GET_CODE (addr) == PRE_INC)
+ return "stws,mb %1,8(0,%0)\n\tstw %R1,4(0,%0)";
+ return "stws,mb %1,-8(0,%0)\n\tstw %R1,4(0,%0)";
+ }
+ else
+ abort();
}
}
if (optype1 == MEMOP)