OSDN Git Service

* config/rs6000/rs6000.c (altivec_in_gprs_p): Rename to ...
authordje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 Sep 2003 02:03:55 +0000 (02:03 +0000)
committerdje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 Sep 2003 02:03:55 +0000 (02:03 +0000)
        (gpr_or_gpr_p): Change to bool.
        (rs6000_split_altivec_in_gprs): Rename to ...
        (rs6000_split_multireg_move): Add support for update addressing.
        * config/rs6000/rs6000-protos.h: Same.
        * config/rs6000/altivec.md: Same.
        * config/rs6000/rs6000.md (movdi_internal32): Use new splitter for
        multiple GPRs.
        (movti): Remove TARGET_STRING || TARGET_POWERPC64 final condition.
        (movti_power): Use new splitter for multiple GPRs.
        (movti_string): Same.
        (movti_ppc64): Same.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71673 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/rs6000/altivec.md
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index a03deee..a7b8b49 100644 (file)
@@ -1,3 +1,19 @@
+2003-09-22  David Edelsohn  <edelsohn@gnu.org>
+           Hartmut Penner  <hpenner@de.ibm.com>
+
+       * config/rs6000/rs6000.c (altivec_in_gprs_p): Rename to ...
+       (gpr_or_gpr_p): Change to bool.
+       (rs6000_split_altivec_in_gprs): Rename to ...
+       (rs6000_split_multireg_move): Add support for update addressing.
+       * config/rs6000/rs6000-protos.h: Same.
+       * config/rs6000/altivec.md: Same.
+       * config/rs6000/rs6000.md (movdi_internal32): Use new splitter for
+       multiple GPRs.
+       (movti): Remove TARGET_STRING || TARGET_POWERPC64 final condition.
+       (movti_power): Use new splitter for multiple GPRs.
+       (movti_string): Same.
+       (movti_ppc64): Same.
+
 2003-09-22  Bob Wilson  <bob.wilson@acm.org>
 
        * config/xtensa/xtensa-protos.h: Convert to ISO C90.
index 5b1dc36..2b58d60 100644 (file)
   [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
         (match_operand:V4SI 1 "input_operand" ""))]
   "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
-   && altivec_in_gprs_p (operands[0], operands[1])"
+   && gpr_or_gpr_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
 "{
-     rs6000_split_altivec_in_gprs (operands);
+     rs6000_split_multireg_move (operands);
 }")
 
 (define_split
   [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
         (match_operand:V4SI 1 "input_operand" ""))]
   "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
-   && altivec_in_gprs_p (operands[0], operands[1])"
+   && gpr_or_gpr_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 6))
    (set (match_dup 3) (match_dup 7))
    (set (match_dup 4) (match_dup 8))
    (set (match_dup 5) (match_dup 9))]
 "{
-     rs6000_split_altivec_in_gprs (operands);
+     rs6000_split_multireg_move (operands);
 }")
 
 (define_split
   [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
         (match_operand:V8HI 1 "input_operand" ""))]
   "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
-   && altivec_in_gprs_p (operands[0], operands[1])"
+   && gpr_or_gpr_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
 "{
-     rs6000_split_altivec_in_gprs (operands);
+     rs6000_split_multireg_move (operands);
 }")
 
 (define_split
   [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
         (match_operand:V8HI 1 "input_operand" ""))]
   "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
-   && altivec_in_gprs_p (operands[0], operands[1])"
+   && gpr_or_gpr_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 6))
    (set (match_dup 3) (match_dup 7))
    (set (match_dup 4) (match_dup 8))
    (set (match_dup 5) (match_dup 9))]
 "{
-     rs6000_split_altivec_in_gprs (operands);
+     rs6000_split_multireg_move (operands);
 }")
 
 (define_split
   [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
         (match_operand:V16QI 1 "input_operand" ""))]
   "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
-   && altivec_in_gprs_p (operands[0], operands[1])"
+   && gpr_or_gpr_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
 "{
-     rs6000_split_altivec_in_gprs (operands);
+     rs6000_split_multireg_move (operands);
 }")
 
 (define_split
   [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
         (match_operand:V16QI 1 "input_operand" ""))]
   "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
-   && altivec_in_gprs_p (operands[0], operands[1])"
+   && gpr_or_gpr_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 6))
    (set (match_dup 3) (match_dup 7))
    (set (match_dup 4) (match_dup 8))
    (set (match_dup 5) (match_dup 9))]
 "{
-     rs6000_split_altivec_in_gprs (operands);
+     rs6000_split_multireg_move (operands);
 }")
 
 (define_split
   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
         (match_operand:V4SF 1 "input_operand" ""))]
   "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
-   && altivec_in_gprs_p (operands[0], operands[1])"
+   && gpr_or_gpr_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
 "{
-     rs6000_split_altivec_in_gprs (operands);
+     rs6000_split_multireg_move (operands);
 }")
 
 (define_split
   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
         (match_operand:V4SF 1 "input_operand" ""))]
   "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
-   && altivec_in_gprs_p (operands[0], operands[1])"
+   && gpr_or_gpr_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 6))
    (set (match_dup 3) (match_dup 7))
    (set (match_dup 4) (match_dup 8))
    (set (match_dup 5) (match_dup 9))]
 "{
-     rs6000_split_altivec_in_gprs (operands);
+     rs6000_split_multireg_move (operands);
 }")
 
 (define_insn "get_vrsave_internal"
index 8340c2b..021c40c 100644 (file)
@@ -100,16 +100,16 @@ extern int includes_rldic_lshift_p (rtx, rtx);
 extern int includes_rldicr_lshift_p (rtx, rtx);
 extern int registers_ok_for_quad_peep (rtx, rtx);
 extern int addrs_ok_for_quad_peep (rtx, rtx);
-extern int altivec_in_gprs_p (rtx, rtx);
+extern bool gpr_or_gpr_p (rtx, rtx);
 extern enum reg_class secondary_reload_class (enum reg_class,
-                                                     enum machine_mode, rtx);
+                                             enum machine_mode, rtx);
 extern int ccr_bit (rtx, int);
 extern int extract_MB (rtx);
 extern int extract_ME (rtx);
 extern void print_operand (FILE *, rtx, int);
 extern void print_operand_address (FILE *, rtx);
 extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
-                                                      enum rtx_code);
+                                              enum rtx_code);
 extern void rs6000_emit_sCOND (enum rtx_code, rtx);
 extern void rs6000_emit_cbranch (enum rtx_code, rtx);
 extern char * output_cbranch (rtx, const char *, int, rtx);
@@ -125,7 +125,7 @@ extern int mfcr_operation (rtx, enum machine_mode);
 extern int mtcrf_operation (rtx, enum machine_mode);
 extern int lmw_operation (rtx, enum machine_mode);
 extern struct rtx_def *create_TOC_reference (rtx);
-extern void rs6000_split_altivec_in_gprs (rtx *);
+extern void rs6000_split_multireg_move (rtx *);
 extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
 extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
 extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
index ae702fc..0b7be5a 100644 (file)
@@ -2200,18 +2200,13 @@ small_data_operand (rtx op ATTRIBUTE_UNUSED,
 #endif
 }
 
-/* Return 1 for all valid move insn operand combination involving altivec      
-   vectors in gprs.  */
+/* Return true if either operand is a general purpose register.  */
 
-int
-altivec_in_gprs_p (rtx op0, rtx op1)
+bool
+gpr_or_gpr_p (rtx op0, rtx op1)
 {
-  if (REG_P (op0) && REGNO_REG_CLASS (REGNO (op0)) == GENERAL_REGS)
-    return 1;
-
-  if (REG_P (op1) && REGNO_REG_CLASS (REGNO (op1)) == GENERAL_REGS) 
-    return 1;
-  return 0;
+  return ((REG_P (op0) && INT_REGNO_P (REGNO (op0)))
+         || (REG_P (op1) && INT_REGNO_P (REGNO (op1))));
 }
 
 \f
@@ -9462,14 +9457,16 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
     emit_move_insn (dest, target);
 }
 
-/* Called by altivec splitter.
+/* Called by splitter for multireg moves.
    Input: 
           operands[0] : Destination of move
           operands[1] : Source of move
-         noperands   : Size of operands vector
+
    Output:
-         operands[2-5] ([2-3] in 64 bit) : Destination slots
-         operands[6-9] ([4-5] in 64 bit) : Source slots
+         operands[2-n] : Destination slots
+         operands[n-m] : Source slots
+   where n = 2 + HARD_REGNO_NREGS (reg, GET_MODE (operands[0]))
+         m = 2 + 2 * HARD_REGNO_NREGS (reg, GET_MODE (operands[0])) - 1
 
    Splits the move of operands[1] to operands[0].
    This is done, if GPRs are one of the operands.  In this case
@@ -9479,10 +9476,13 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
 */
          
 void
-rs6000_split_altivec_in_gprs (rtx *operands)
+rs6000_split_multireg_move (rtx *operands)
 {
-    int nregs, reg, i, j;
+  int nregs, reg, i, j, used_update = 0;
   enum machine_mode mode; 
+  rtx dst = operands[0];
+  rtx src = operands[1];
+  rtx insn = 0;
 
   /* Calculate number to move (2/4 for 32/64 bit mode).  */ 
 
@@ -9500,8 +9500,8 @@ rs6000_split_altivec_in_gprs (rtx *operands)
       for (i = 0; i < nregs; i++)
         {
           j--;
-          operands[i + 2] = operand_subword (operands[0], j, 0, mode);
-          operands[i + 2 + nregs] = 
+          operands[i+2] = operand_subword (operands[0], j, 0, mode);
+          operands[i+2+nregs] = 
             operand_subword (operands[1], j, 0, mode);   
         }
     }     
@@ -9512,29 +9512,87 @@ rs6000_split_altivec_in_gprs (rtx *operands)
       if (GET_CODE (operands[1]) == MEM)
         {
           rtx breg;
-          /* We have offsettable addresses only. If we use one of the
-             registers to address memory, we have change that register last.  */            
-          breg = GET_CODE (XEXP (operands[1], 0)) == PLUS ?
-              XEXP (XEXP (operands[1], 0), 0) :
-              XEXP (operands[1], 0);
-
-          if (REGNO (breg) >= REGNO (operands[0]) 
-              && REGNO (breg) < REGNO (operands[0]) + nregs)
-              j = REGNO (breg) - REGNO (operands[0]);
+
+         if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
+             || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+           {
+             rtx delta_rtx;
+             breg = XEXP (XEXP (operands[1], 0), 0);
+             delta_rtx =  GET_CODE (XEXP (operands[1], 0)) == PRE_INC 
+                 ? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1]))) 
+                 : GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[1]))); 
+             insn = emit_insn (TARGET_32BIT
+                               ? gen_addsi3 (breg, breg, delta_rtx)
+                               : gen_adddi3 (breg, breg, delta_rtx));
+             src = gen_rtx_MEM (mode, breg);
+           }
+
+         /* We have now address involving an base register only.
+            If we use one of the registers to address memory, 
+            we have change that register last.  */
+
+         breg = (GET_CODE (XEXP (src, 0)) == PLUS
+                 ? XEXP (XEXP (src, 0), 0)
+                 : XEXP (src, 0));
+
+         if (!REG_P (breg))
+             abort();
+
+         if (REGNO (breg) >= REGNO (dst) 
+             && REGNO (breg) < REGNO (dst) + nregs)
+           j = REGNO (breg) - REGNO (dst);
         }
 
+      if (GET_CODE (operands[0]) == MEM)
+       {
+         rtx breg;
+
+         if (GET_CODE (XEXP (operands[0], 0)) == PRE_INC
+             || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+           {
+             rtx delta_rtx;
+             breg = XEXP (XEXP (operands[0], 0), 0);
+             delta_rtx = GET_CODE (XEXP (operands[0], 0)) == PRE_INC 
+               ? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0]))) 
+               : GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0]))); 
+
+             /* We have to update the breg before doing the store.
+                Use store with update, if available.  */
+
+             if (TARGET_UPDATE)
+               {
+                 insn = emit_insn (TARGET_32BIT
+                                   ? gen_movsi_update (breg, breg, delta_rtx, 
+                                       operand_subword (src, 0, 0, mode))
+                                   : gen_movdi_update (breg, breg, delta_rtx,
+                                       operand_subword (src, 0, 0, mode)));
+                 used_update = 1;
+               }
+             else
+                 insn = emit_insn (TARGET_32BIT
+                                   ? gen_addsi3 (breg, breg, delta_rtx)
+                                   : gen_adddi3 (breg, breg, delta_rtx));
+             dst = gen_rtx_MEM (mode, breg);
+           }
+       }
+
       for (i = 0; i < nregs; i++)
-        { 
-          /* Calculate index to next subword.  */
-          j++;
-          if (j == nregs) 
-            j = 0;
+       {  
+         /* Calculate index to next subword.  */
+         ++j;
+         if (j == nregs) 
+           j = 0;
 
-          operands[i + 2] = operand_subword (operands[0], j, 0, mode);
-          operands[i + 2 + nregs] = 
-            operand_subword (operands[1], j, 0, mode);
+         operands[i+2] = operand_subword (dst, j, 0, mode);
+         operands[i+2+nregs] = operand_subword (src, j, 0, mode);
 
-        }
+         if (j == 0 && used_update)
+           {
+             /* Already emited move of first word by 
+                store with update -> emit dead insn instead (r := r).  */
+             operands[i+2] = operands[i+2+nregs];
+           }
+       }
     }
 }
 
index 5f91155..d1264c6 100644 (file)
     default:
       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.  */
-      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\";
-      else
-       return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
     case 2:
-      return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
+      return \"#\";
     case 3:
       return \"fmr %0,%1\";
     case 4:
       return \"#\";
     }
 }"
-  [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")
-   (set_attr "length" "8,8,8,4,4,4,8,12,8,12,16")])
+  [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")])
 
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
 }")
 
 (define_split
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (match_operand:DI 1 "input_operand" ""))]
+  "reload_completed && !TARGET_POWERPC64 
+   && gpr_or_gpr_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+"{
+     rs6000_split_multireg_move (operands);
+}")
+
+(define_split
   [(set (match_operand:TI 0 "gpc_reg_operand" "")
        (match_operand:TI 1 "const_double_operand" ""))]
   "TARGET_POWERPC64"
   [(parallel [(set (match_operand:TI 0 "general_operand" "")
                   (match_operand:TI 1 "general_operand" ""))
              (clobber (scratch:SI))])]
-  "TARGET_STRING || TARGET_POWERPC64"
+  ""
   "{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }")
 
 ;; We say that MQ is clobbered in the last alternative because the first
 ;; while the 2nd alternative would not.  We put memory cases first so they
 ;; are preferred.  Otherwise, we'd try to reload the output instead of
 ;; giving the SCRATCH mq.
+
 (define_insn "*movti_power"
   [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
        (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
    (clobber (match_scratch:SI 2 "=q,q#X,X,X,X"))]
-  "TARGET_STRING && TARGET_POWER && ! TARGET_POWERPC64
+  "TARGET_POWER && ! TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
   "*
 {
       abort ();
 
     case 0:
-      return \"{stsi|stswi} %1,%P0,16\";
+      if (TARGET_STRING)
+        return \"{stsi|stswi} %1,%P0,16\";
     case 1:
-      return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\";
+      return \"#\";
     case 2:
-      /* Normally copy registers with lowest numbered register copied first.
-        But copy in the other order if the first register of the output
-        is the second, third, or fourth register in the input.  */
-      if (REGNO (operands[0]) >= REGNO (operands[1]) + 1
-         && REGNO (operands[0]) <= REGNO (operands[1]) + 3)
-       return \"mr %Z0,%Z1\;mr %Y0,%Y1\;mr %L0,%L1\;mr %0,%1\";
-      else
-       return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+      return \"#\";
     case 3:
       /* If the address is not used in the output, we can use lsi.  Otherwise,
         fall through to generating four loads.  */
        return \"{lsi|lswi} %0,%P1,16\";
       /* ... fall through ...  */
     case 4:
-      /* If the address register is the same as the register for the lowest-
-        addressed word, load it last.  Similarly for the next two words.
-        Otherwise load lowest address to highest.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                            operands[1], 0))
-       return \"{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %0,%1\";
-      else if (refers_to_regno_p (REGNO (operands[0]) + 1,
-                                 REGNO (operands[0]) + 2, operands[1], 0))
-       return \"{l|lwz} %0,%1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %L0,%L1\";
-      else if (refers_to_regno_p (REGNO (operands[0]) + 2,
-                                 REGNO (operands[0]) + 3, operands[1], 0))
-       return \"{l|lwz} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Z0,%Z1\;{l|lwz} %Y0,%Y1\";
-      else
-       return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\";
+      return \"#\";
     }
 }"
-  [(set_attr "type" "store,store,*,load,load")
-   (set_attr "length" "4,16,16,4,16")])
+  [(set_attr "type" "store,store,*,load,load")])
 
 (define_insn "*movti_string"
   [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
        (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))]
-  "TARGET_STRING && ! TARGET_POWER && ! TARGET_POWERPC64
+  "! TARGET_POWER && ! TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
   "*
 {
     {
     default:
       abort ();
-
     case 0:
-      return \"{stsi|stswi} %1,%P0,16\";
+      if (TARGET_STRING)
+        return \"{stsi|stswi} %1,%P0,16\";
     case 1:
-      return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\";
+      return \"#\";
     case 2:
-      /* Normally copy registers with lowest numbered register copied first.
-        But copy in the other order if the first register of the output
-        is the second, third, or fourth register in the input.  */
-      if (REGNO (operands[0]) >= REGNO (operands[1]) + 1
-         && REGNO (operands[0]) <= REGNO (operands[1]) + 3)
-       return \"mr %Z0,%Z1\;mr %Y0,%Y1\;mr %L0,%L1\;mr %0,%1\";
-      else
-       return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+      return \"#\";
     case 3:
       /* If the address is not used in the output, we can use lsi.  Otherwise,
         fall through to generating four loads.  */
-      if (! reg_overlap_mentioned_p (operands[0], operands[1]))
+      if (TARGET_STRING  
+          && ! reg_overlap_mentioned_p (operands[0], operands[1]))
        return \"{lsi|lswi} %0,%P1,16\";
       /* ... fall through ...  */
     case 4:
-      /* If the address register is the same as the register for the lowest-
-        addressed word, load it last.  Similarly for the next two words.
-        Otherwise load lowest address to highest.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                            operands[1], 0))
-       return \"{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %0,%1\";
-      else if (refers_to_regno_p (REGNO (operands[0]) + 1,
-                                 REGNO (operands[0]) + 2, operands[1], 0))
-       return \"{l|lwz} %0,%1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %L0,%L1\";
-      else if (refers_to_regno_p (REGNO (operands[0]) + 2,
-                                 REGNO (operands[0]) + 3, operands[1], 0))
-       return \"{l|lwz} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Z0,%Z1\;{l|lwz} %Y0,%Y1\";
-      else
-       return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\";
+      return \"#\";
     }
 }"
-  [(set_attr "type" "store,store,*,load,load")
-   (set_attr "length" "4,16,16,4,16")])
+  [(set_attr "type" "store,store,*,load,load")])
 
 (define_insn "*movti_ppc64"
-  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
-       (match_operand:TI 1 "input_operand" "r,m,r"))]
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,m,r")
+       (match_operand:TI 1 "input_operand" "r,r,o"))]
   "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
    || gpc_reg_operand (operands[1], TImode))"
-  "*
-{
-  switch (which_alternative)
-    {
-    default:
-      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.  */
-      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 \"ld %L0,%L1\;ld %0,%1\";
-      else
-       return \"ld%U1 %0,%1\;ld %L0,%L1\";
-    case 2:
-      return \"std%U0 %1,%0\;std %L1,%L0\";
-    }
-}"
-  [(set_attr "type" "*,load,store")
-   (set_attr "length" "8,8,8")])
+  "@
+   #   
+   #   
+   #"
+  [(set_attr "type" "*,load,store")])
+
+(define_split
+  [(set (match_operand:TI 0 "nonimmediate_operand" "")
+        (match_operand:TI 1 "input_operand" ""))]
+  "reload_completed && TARGET_POWERPC64 
+   && gpr_or_gpr_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+"{
+     rs6000_split_multireg_move (operands);
+}")
+
+(define_split
+  [(set (match_operand:TI 0 "nonimmediate_operand" "")
+        (match_operand:TI 1 "input_operand" ""))]
+  "reload_completed && !TARGET_POWERPC64 
+   && gpr_or_gpr_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 6))
+   (set (match_dup 3) (match_dup 7))
+   (set (match_dup 4) (match_dup 8))
+   (set (match_dup 5) (match_dup 9))]
+"{
+     rs6000_split_multireg_move (operands);
+}")
+
+
 \f
 (define_expand "load_multiple"
   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")