rs6000.c (find_addr_reg): New function.
authorDavid Edelsohn <edelsohn@gnu.org>
Sat, 19 Jun 1999 00:04:59 +0000 (00:04 +0000)
committerDavid Edelsohn <dje@gcc.gnu.org>
Sat, 19 Jun 1999 00:04:59 +0000 (20:04 -0400)
        * rs6000.c (find_addr_reg): New function.
        * rs6000.h (find_addr_reg): Declare.
        (offsettable_addr_operand): Delete.
        * rs6000.md (movdf_hardfloat32): Handle non-offsettable loads
        from and stores to GPRs.

From-SVN: r27602

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md

index 5efb552b16ba554a1dbf9c9018eb33fdabeffe27..46f9d17617ef8fcb4c6f7823def7c203949349a2 100644 (file)
@@ -1,3 +1,11 @@
+Fri Jun 18 23:47:06 1999  David Edelsohn  <edelsohn@gnu.org>
+
+       * rs6000.c (find_addr_reg): New function.
+       * rs6000.h (find_addr_reg): Declare.
+       (offsettable_addr_operand): Delete.
+       * rs6000.md (movdf_hardfloat32): Handle non-offsettable loads
+       from and stores to GPRs.
+
 Fri Jun 18 15:44:18 1999  Richard Henderson  <rth@cygnus.com>
 
        * alpha.c (alpha_expand_block_move): Use get_insns rather than
index d22e4e76c108f9f62ba14258c51496d1a6bc100d..7d6faf5cb6c5b681796a96f262882d6dfc2b2790 100644 (file)
@@ -5681,7 +5681,33 @@ rs6000_encode_section_info (decl)
 }
 
 #endif /* USING_SVR4_H */
+
 \f
+/* Return a REG that occurs in ADDR with coefficient 1.
+   ADDR can be effectively incremented by incrementing REG.  */
+
+struct rtx_def *
+find_addr_reg (addr)
+     rtx addr;
+{
+  while (GET_CODE (addr) == PLUS)
+    {
+      if (GET_CODE (XEXP (addr, 0)) == REG)
+       addr = XEXP (addr, 0);
+      else if (GET_CODE (XEXP (addr, 1)) == REG)
+       addr = XEXP (addr, 1);
+      else if (CONSTANT_P (XEXP (addr, 0)))
+       addr = XEXP (addr, 1);
+      else if (CONSTANT_P (XEXP (addr, 1)))
+       addr = XEXP (addr, 0);
+      else
+       abort ();
+    }
+  if (GET_CODE (addr) == REG)
+    return addr;
+  abort ();
+}
+
 void
 rs6000_fatal_bad_address (op)
   rtx op;
index 08ac9fd22450969914f649a15df5af6a9eda42f9..4e221314e42ee9f37b29c164d6c46390c38ea681 100644 (file)
@@ -3224,13 +3224,13 @@ extern int flag_expensive_optimizations;
 extern int frame_pointer_needed;
 
 /* Declare functions in rs6000.c */
-extern int offsettable_mem_operand ();
 extern void optimization_options ();
 extern void output_options ();
 extern void rs6000_override_options ();
 extern void rs6000_file_start ();
 extern struct rtx_def *rs6000_float_const ();
 extern struct rtx_def *rs6000_got_register ();
+extern struct rtx_def *find_addr_reg();
 extern int direct_return ();
 extern int get_issue_rate ();
 extern int any_operand ();
@@ -3249,7 +3249,7 @@ extern int got_no_const_operand ();
 extern int num_insns_constant ();
 extern int easy_fp_constant ();
 extern int volatile_mem_operand ();
-extern int offsettable_addr_operand ();
+extern int offsettable_mem_operand ();
 extern int mem_or_easy_const_operand ();
 extern int add_operand ();
 extern int non_add_cint_operand ();
index e8338634d82c4f45b79a5d35eed80c6324f8f959..4286d89ccc06bb46e95edb00c6d1ffdb5631010c 100644 (file)
 ;; The "??" is a kludge until we can figure out a more reasonable way
 ;; of handling these non-offsettable values.
 (define_insn "*movdf_hardfloat32"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,!r,!r,f,f,m")
-       (match_operand:DF 1 "input_operand" "r,o,r,G,H,F,f,m,f"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,!r,!r,!r,f,f,m")
+       (match_operand:DF 1 "input_operand" "r,m,r,G,H,F,f,m,f"))]
   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT
    && (gpc_reg_operand (operands[0], DFmode)
        || gpc_reg_operand (operands[1], DFmode))"
       abort ();
     case 0:
       /* We normally copy the low-numbered register first.  However, if
-        the first register operand 0 is the same as the second register of
-        operand 1, we must copy in the opposite order.  */
+        the first register operand 0 is the same as the second register
+        of operand 1, we must copy in the opposite order.  */
       if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
        return \"mr %L0,%L1\;mr %0,%1\";
       else
        return \"mr %0,%1\;mr %L0,%L1\";
     case 1:
-      /* If the low-address word is used in the address, we must load it
-        last.  Otherwise, load it first.  Note that we cannot have
-        auto-increment in that case since the address register is known to be
-        dead.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                            operands [1], 0))
-       return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
+      if (offsettable_memref_p (operands[1]))
+       {
+         /* If the low-address word is used in the address, we must load
+            it last.  Otherwise, load it first.  Note that we cannot have
+            auto-increment in that case since the address register is
+            known to be dead.  */
+         if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
+                                operands[1], 0))
+           return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
+         else
+           return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
+       }
       else
-       return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
+       {
+         rtx addreg;
+
+         if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
+             || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+           abort ();
+
+         addreg = find_addr_reg (XEXP (operands[1], 0));
+         if (refers_to_regno_p (REGNO (operands[0]),
+                                REGNO (operands[0]) + 1,
+                                operands[1], 0))
+           {
+             output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
+             output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
+             output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
+             return \"{lx|lwzx} %0,%1\";
+           }
+         else
+           {
+             output_asm_insn (\"{lx|lwzx} %0,%1\", operands);
+             output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
+             output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
+             output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
+             return \"\";
+           }
+       }
     case 2:
-      return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
+      if (offsettable_memref_p (operands[0]))
+       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
+      else
+       {
+         rtx addreg;
+
+         if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
+             || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+           abort ();
+
+         addreg = find_addr_reg (XEXP (operands[0], 0));
+         output_asm_insn (\"{stx|stwx} %1,%0\", operands);
+         output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
+         output_asm_insn (\"{stx|stwx} %L1,%0\", operands);
+         output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
+         return \"\";
+       }
     case 3:
     case 4:
     case 5: