aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1993-06-12 20:23:42 +0000
committerRichard Stallman <rms@gnu.org>1993-06-12 20:23:42 +0000
commit9e69dd9f3a3e70cd53e5cf9717094030a1590e13 (patch)
treef3c6482a671be6ffae28f57686dfc67241a0dec3
parent09d65479966b04ed960e295f7bc17f853dbe57e3 (diff)
downloadgcc-9e69dd9f3a3e70cd53e5cf9717094030a1590e13.zip
gcc-9e69dd9f3a3e70cd53e5cf9717094030a1590e13.tar.gz
gcc-9e69dd9f3a3e70cd53e5cf9717094030a1590e13.tar.bz2
(movqi): Handle copying an address register to or
from memory when the address uses the address register. From-SVN: r4668
-rw-r--r--gcc/config/m68k/m68k.md76
1 files changed, 76 insertions, 0 deletions
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 456b99e..ce6b42f 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -932,6 +932,44 @@
/* Use d0 as an intermediate, but don't clobber its contents. */
if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM)
{
+ /* ??? For 2.5, don't allow this choice and use secondary reloads
+ instead.
+
+ See if the address register is used in the address. If it
+ is, we have to generate a more complex sequence than those below. */
+ if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
+ operands[1], NULL_RTX))
+ {
+ /* See if the stack pointer is used in the address. If it isn't,
+ we can push d0 or d1 (the insn can't use both of them) on
+ the stack, perform our move into d0/d1, copy the byte from d0/1,
+ and pop d0/1. */
+ if (! reg_mentioned_p (stack_pointer_rtx, operands[1]))
+ {
+ if (refers_to_regno_p (0, 1, operands[1], NULL_RTX))
+ return \"move%.l %/d0,%-\;move%.b %1,%/d0\;move%.l %/d0,%0\;move%.l %+,%/d0\";
+ else
+ return \"move%.l %/d1,%-\;move%.b %1,%/d1\;move%.l %/d1,%0\;move%.l %+,%/d1\";
+ }
+ else
+ {
+ /* Otherwise, we know that d0 cannot be used in the address
+ (since sp and one address register is). Assume that sp is
+ being used as a base register and replace the address
+ register that is our operand[0] with d0. */
+ rtx reg_map[FIRST_PSEUDO_REGISTER];
+ int i;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ reg_map[i] = 0;
+
+ reg_map[REGNO (operands[0])] = gen_rtx (REG, Pmode, 0);
+ operands[1] = copy_rtx (operands[1]);
+ replace_regs (operands[1], reg_map, FIRST_PSEUDO_REGISTER, 0);
+ return \"exg %/d0,%0\;move%.b %1,%/d0\;exg %/d0,%0\";
+ }
+ }
+
/* If the address of operand 1 uses d0, choose d1 as intermediate. */
if (refers_to_regno_p (0, 1, operands[1], NULL_RTX))
return \"exg %/d1,%0\;move%.b %1,%/d1\;exg %/d1,%0\";
@@ -944,6 +982,44 @@
/* Likewise for moving from an address reg. */
if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM)
{
+ /* ??? For 2.5, don't allow this choice and use secondary reloads
+ instead.
+
+ See if the address register is used in the address. If it
+ is, we have to generate a more complex sequence than those below. */
+ if (refers_to_regno_p (REGNO (operands[1]), REGNO (operands[1]) + 1,
+ operands[0], NULL_RTX))
+ {
+ /* See if the stack pointer is used in the address. If it isn't,
+ we can push d0 or d1 (the insn can't use both of them) on
+ the stack, copy the byte to d0/1, perform our move from d0/d1,
+ and pop d0/1. */
+ if (! reg_mentioned_p (stack_pointer_rtx, operands[0]))
+ {
+ if (refers_to_regno_p (0, 1, operands[0], NULL_RTX))
+ return \"move%.l %/d0,%-\;move%.l %1,%/d0\;move%.b %/d0,%0\;move%.l %+,%/d0\";
+ else
+ return \"move%.l %/d1,%-\;move%.l %1,%/d1\;move%.b %/d1,%0\;move%.l %+,%/d1\";
+ }
+ else
+ {
+ /* Otherwise, we know that d0 cannot be used in the address
+ (since sp and one address register is). Assume that sp is
+ being used as a base register and replace the address
+ register that is our operand[1] with d0. */
+ rtx reg_map[FIRST_PSEUDO_REGISTER];
+ int i;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ reg_map[i] = 0;
+
+ reg_map[REGNO (operands[1])] = gen_rtx (REG, Pmode, 0);
+ operands[0] = copy_rtx (operands[0]);
+ replace_regs (operands[0], reg_map, FIRST_PSEUDO_REGISTER, 0);
+ return \"exg %/d0,%1\;move%.b %/d0,%0\;exg %/d0,%1\";
+ }
+ }
+
if (refers_to_regno_p (0, 1, operands[0], NULL_RTX))
return \"exg %/d1,%1\;move%.b %/d1,%0\;exg %/d1,%1\";
else