rs6000.c (rs6000_emit_move): New function.
authorGeoff Keating <geoffk@cygnus.com>
Mon, 3 Jul 2000 20:00:44 +0000 (20:00 +0000)
committerGeoffrey Keating <geoffk@gcc.gnu.org>
Mon, 3 Jul 2000 20:00:44 +0000 (20:00 +0000)
* config/rs6000/rs6000.c (rs6000_emit_move): New function.
* config/rs6000/rs6000-proto.h: Prototype rs6000_emit_move.
* config/rs6000/rs6000.md (movsi): Use rs6000_emit_move.
(movhi): Likewise.
(movqi): Likewise.
(movdf): Likewise.
(movsf): Likewise.
(movdi): Likewise.
(movti): Likewise.

From-SVN: r34852

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

index a14e763..85c2e08 100644 (file)
@@ -1,5 +1,15 @@
 2000-07-03  Geoff Keating  <geoffk@cygnus.com>
 
+       * config/rs6000/rs6000.c (rs6000_emit_move): New function.
+       * config/rs6000/rs6000-proto.h: Prototype rs6000_emit_move.
+       * config/rs6000/rs6000.md (movsi): Use rs6000_emit_move.
+       (movhi): Likewise.
+       (movqi): Likewise.
+       (movdf): Likewise.
+       (movsf): Likewise.
+       (movdi): Likewise.
+       (movti): Likewise.
+
        * expmed.c (expand_mult_highpart): Use op1 instead of wide_op1 when
        mode instead of wider_mode is being used.
 
index 691dfa9..2237b7e 100644 (file)
@@ -97,6 +97,7 @@ extern int mtcrf_operation PARAMS ((rtx, enum machine_mode));
 extern int lmw_operation PARAMS ((rtx, enum machine_mode));
 extern struct rtx_def *create_TOC_reference PARAMS ((rtx));
 extern void rs6000_emit_eh_toc_restore PARAMS ((rtx));
+extern void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode));
 extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
 extern void rs6000_select_rtx_section PARAMS ((enum machine_mode, rtx));
 #endif /* RTX_CODE */
index 66cb911..73b46df 100644 (file)
@@ -1458,8 +1458,277 @@ rs6000_legitimize_address (x, oldx, mode)
   else
     return NULL_RTX;
 }
+\f
+/* Emit a move from SOURCE to DEST in mode MODE.  */
+void
+rs6000_emit_move (dest, source, mode)
+     rtx dest;
+     rtx source;
+     enum machine_mode mode;
+{
+  rtx operands[2];
+  operands[0] = dest;
+  operands[1] = source;
+  
+  /* Sanity checks.  Check that we get CONST_DOUBLE only when we should.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE
+      && ! FLOAT_MODE_P (mode)
+      && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+    {
+      /* FIXME.  This should never happen.  */
+      /* Since it seems that it does, do the safe thing and convert
+        to a CONST_INT.  */
+      operands[1] = 
+       GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (operands[1]), mode));
+    }
+  if (GET_CODE (operands[1]) == CONST_DOUBLE
+      && ! FLOAT_MODE_P (mode)
+      && ((CONST_DOUBLE_HIGH (operands[1]) == 0
+          && CONST_DOUBLE_LOW (operands[1]) >= 0)
+         || (CONST_DOUBLE_HIGH (operands[1]) == -1
+             && CONST_DOUBLE_LOW (operands[1]) < 0)))
+    abort ();
+  
+  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
+    operands[1] = force_reg (mode, operands[1]);
+  
+  if (mode == SFmode && ! TARGET_POWERPC && TARGET_HARD_FLOAT)
+    {
+      int regnum = true_regnum (operands[1]);
+      /* regnum may be -1 in which case the test below will fail.  */  
+      
+      /* If operands[1] is a register, on POWER it may have
+        double-precision data in it, so truncate it to single
+        precision.  */
+      if (FP_REGNO_P (regnum) || regnum >= FIRST_PSEUDO_REGISTER)
+       {
+         rtx newreg;
+         newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (mode));
+         emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));
+         operands[1] = newreg;
+       }
+    }
+
+  /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary.  */
+  if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
+    {
+      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+      return;
+    }
+
+  /* FIXME:  In the long term, this switch statement should go away
+     and be replaced by a sequence of tests based on things like
+     mode == Pmode.  */
+  switch (mode)
+    {
+    case HImode:
+    case QImode:
+      if (CONSTANT_P (operands[1])
+         && GET_CODE (operands[1]) != CONST_INT)
+       {
+         operands[1] = force_const_mem (mode, operands[1]);
+         if (! memory_address_p (mode, XEXP (operands[1], 0))
+             && ! reload_in_progress)
+           operands[1] = change_address (operands[1], mode,
+                                         XEXP (operands[1], 0));
+       }
+      break;
 
+    case DFmode:
+    case SFmode:
+      if (CONSTANT_P (operands[1]) 
+         && ! easy_fp_constant (operands[1], mode))
+       {
+         operands[1] = force_const_mem (mode, operands[1]);
+         if (! memory_address_p (mode, XEXP (operands[1], 0))
+             && ! reload_in_progress)
+           operands[1] = change_address (operands[1], mode,
+                                         XEXP (operands[1], 0));
+       }
+      break;
+      
+    case SImode:
+      /* Use default pattern for address of ELF small data */
+      if (TARGET_ELF
+         && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
+         && (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST)
+         && small_data_operand (operands[1], SImode))
+       {
+         emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+         return;
+       }
+
+      if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
+         && flag_pic == 1 && got_operand (operands[1], SImode))
+       {
+         emit_insn (gen_movsi_got (operands[0], operands[1]));
+         return;
+       }
 
+      if (TARGET_ELF && TARGET_NO_TOC && ! TARGET_64BIT
+         && ! flag_pic
+         && CONSTANT_P (operands[1])
+         && GET_CODE (operands[1]) != HIGH
+         && GET_CODE (operands[1]) != CONST_INT)
+       {
+         rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (SImode));
+
+         /* If this is a function address on -mcall-aixdesc,
+            convert it to the address of the descriptor.  */
+         if (DEFAULT_ABI == ABI_AIX
+             && GET_CODE (operands[1]) == SYMBOL_REF
+             && XSTR (operands[1], 0)[0] == '.')
+           {
+             const char *name = XSTR (operands[1], 0);
+             rtx new_ref;
+             while (*name == '.')
+               name++;
+             new_ref = gen_rtx_SYMBOL_REF (Pmode, name);
+             CONSTANT_POOL_ADDRESS_P (new_ref)
+               = CONSTANT_POOL_ADDRESS_P (operands[1]);
+             SYMBOL_REF_FLAG (new_ref) = SYMBOL_REF_FLAG (operands[1]);
+             SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
+             operands[1] = new_ref;
+           }
+
+         emit_insn (gen_elf_high (target, operands[1]));
+         emit_insn (gen_elf_low (operands[0], target, operands[1]));
+         return;
+       }
+
+      if (CONSTANT_P (operands[1])
+         && GET_CODE (operands[1]) != CONST_INT
+         && GET_CODE (operands[1]) != HIGH
+         && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
+         && ! TOC_RELATIVE_EXPR_P (operands[1]))
+       {
+         /* Emit a USE operation so that the constant isn't deleted if
+            expensive optimizations are turned on because nobody
+            references it.  This should only be done for operands that
+            contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
+            This should not be done for operands that contain LABEL_REFs.
+            For now, we just handle the obvious case.  */
+         if (GET_CODE (operands[1]) != LABEL_REF)
+           emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
+
+      /* If we are to limit the number of things we put in the TOC and
+        this is a symbol plus a constant we can add in one insn,
+        just put the symbol in the TOC and add the constant.  Don't do
+        this if reload is in progress.  */
+         if (GET_CODE (operands[1]) == CONST
+             && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
+             && GET_CODE (XEXP (operands[1], 0)) == PLUS
+             && add_operand (XEXP (XEXP (operands[1], 0), 1), SImode)
+             && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
+                 || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
+             && ! side_effects_p (operands[0]))
+           {
+             rtx sym = force_const_mem (SImode, XEXP (XEXP (operands[1], 0), 0));
+             rtx other = XEXP (XEXP (operands[1], 0), 1);
+
+             emit_insn (gen_addsi3 (operands[0], force_reg (SImode, sym), other));
+             return;
+           }
+
+         operands[1] = force_const_mem (SImode, operands[1]);
+
+         if (TARGET_TOC 
+             && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
+             && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
+                                                                    XEXP (operands[1], 0))))
+           {
+             operands[1] = gen_rtx_MEM (SImode,
+                                        create_TOC_reference (XEXP (operands[1], 0)));
+             MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();       
+             RTX_UNCHANGING_P (operands[1]) = 1;
+           }
+
+         if (! memory_address_p (SImode, XEXP (operands[1], 0))
+             && ! reload_in_progress)
+           operands[1] = change_address (operands[1], SImode,
+                                         XEXP (operands[1], 0));
+       }
+      break;
+
+    case DImode:
+      if (TARGET_64BIT
+         && CONSTANT_P (operands[1])
+#if HOST_BITS_PER_WIDE_INT == 32
+         && GET_CODE (operands[1]) != CONST_INT
+#endif
+         && ! easy_fp_constant (operands[1], DImode)
+         && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
+         && ! TOC_RELATIVE_EXPR_P (operands[1]))
+       {
+         /* Emit a USE operation so that the constant isn't deleted if
+            expensive optimizations are turned on because nobody
+            references it.  This should only be done for operands that
+            contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
+            This should not be done for operands that contain LABEL_REFs.
+            For now, we just handle the obvious case.  */
+         if (GET_CODE (operands[1]) != LABEL_REF)
+           emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
+
+         /* If we are to limit the number of things we put in the TOC and
+            this is a symbol plus a constant we can add in one insn,
+            just put the symbol in the TOC and add the constant.  Don't do
+            this if reload is in progress.  */
+         if (GET_CODE (operands[1]) == CONST
+             && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
+             && GET_CODE (XEXP (operands[1], 0)) == PLUS
+             && add_operand (XEXP (XEXP (operands[1], 0), 1), DImode)
+             && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
+                 || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
+             && ! side_effects_p (operands[0]))
+           {
+             rtx sym = force_const_mem (DImode, XEXP (XEXP (operands[1], 0), 0));
+             rtx other = XEXP (XEXP (operands[1], 0), 1);
+
+             emit_insn (gen_adddi3 (operands[0], force_reg (DImode, sym), other));
+             return;
+           }
+
+         operands[1] = force_const_mem (DImode, operands[1]);
+
+         if (TARGET_TOC 
+             && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
+             && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
+                                                                    XEXP (operands[1], 0))))
+           {
+             operands[1] = gen_rtx_MEM (DImode,
+                                        create_TOC_reference (XEXP (operands[1], 0)));
+
+             MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();       
+             RTX_UNCHANGING_P (operands[1]) = 1;
+           }   
+
+         if (! memory_address_p (DImode, XEXP (operands[1], 0))
+             && ! reload_in_progress)
+           operands[1] = change_address (operands[1], DImode,
+                                         XEXP (operands[1], 0));
+       }
+      break;
+  
+    case TImode:
+      if (GET_CODE (operands[0]) == MEM
+         && GET_CODE (XEXP (operands[0], 0)) != REG
+         && ! reload_in_progress)
+       operands[0] = change_address (operands[0], TImode,
+                                     copy_addr_to_reg (XEXP (operands[0], 0)));
+
+      if (GET_CODE (operands[1]) == MEM
+         && GET_CODE (XEXP (operands[1], 0)) != REG
+         && ! reload_in_progress)
+       operands[1] = change_address (operands[1], TImode,
+                                     copy_addr_to_reg (XEXP (operands[1], 0)));
+      break;
+
+    default:
+      abort ();
+    }
+
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+}
 \f
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
index a839971..4dfe6ba 100644 (file)
   [(set (match_operand:SI 0 "general_operand" "")
        (match_operand:SI 1 "any_operand" ""))]
   ""
-  "
-{
-  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (SImode, operands[1]);
-
-  /* Convert a move of a CONST_DOUBLE into a CONST_INT */
-  if (GET_CODE (operands[1]) == CONST_DOUBLE)
-    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-
-  /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary.  */
-  if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
-    {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
-      DONE;
-    }
-
-  /* Use default pattern for address of ELF small data */
-  if (TARGET_ELF
-      && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
-      && (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST)
-      && small_data_operand (operands[1], SImode))
-    {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
-      DONE;
-    }
-
-  if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
-      && flag_pic == 1 && got_operand (operands[1], SImode))
-    {
-      emit_insn (gen_movsi_got (operands[0], operands[1]));
-      DONE;
-    }
-
-  if (TARGET_ELF && TARGET_NO_TOC && ! TARGET_64BIT
-      && ! flag_pic
-      && CONSTANT_P (operands[1])
-      && GET_CODE (operands[1]) != HIGH
-      && GET_CODE (operands[1]) != CONST_INT)
-    {
-      rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (SImode));
-
-      /* If this is a function address on -mcall-aixdesc,
-        convert it to the address of the descriptor.  */
-      if (DEFAULT_ABI == ABI_AIX
-         && GET_CODE (operands[1]) == SYMBOL_REF
-         && XSTR (operands[1], 0)[0] == '.')
-       {
-         const char *name = XSTR (operands[1], 0);
-         rtx new_ref;
-         while (*name == '.')
-           name++;
-         new_ref = gen_rtx_SYMBOL_REF (Pmode, name);
-         CONSTANT_POOL_ADDRESS_P (new_ref)
-           = CONSTANT_POOL_ADDRESS_P (operands[1]);
-         SYMBOL_REF_FLAG (new_ref) = SYMBOL_REF_FLAG (operands[1]);
-         SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
-         operands[1] = new_ref;
-       }
-
-      emit_insn (gen_elf_high (target, operands[1]));
-      emit_insn (gen_elf_low (operands[0], target, operands[1]));
-      DONE;
-    }
-
-  if (CONSTANT_P (operands[1])
-      && GET_CODE (operands[1]) != CONST_INT
-      && GET_CODE (operands[1]) != HIGH
-      && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
-      && ! TOC_RELATIVE_EXPR_P (operands[1]))
-    {
-      /* Emit a USE operation so that the constant isn't deleted if
-        expensive optimizations are turned on because nobody
-        references it.  This should only be done for operands that
-        contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
-        This should not be done for operands that contain LABEL_REFs.
-        For now, we just handle the obvious case.  */
-      if (GET_CODE (operands[1]) != LABEL_REF)
-       emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
-
-      /* If we are to limit the number of things we put in the TOC and
-        this is a symbol plus a constant we can add in one insn,
-        just put the symbol in the TOC and add the constant.  Don't do
-        this if reload is in progress.  */
-      if (GET_CODE (operands[1]) == CONST
-         && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
-         && GET_CODE (XEXP (operands[1], 0)) == PLUS
-         && add_operand (XEXP (XEXP (operands[1], 0), 1), SImode)
-         && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
-             || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
-         && ! side_effects_p (operands[0]))
-       {
-         rtx sym = force_const_mem (SImode, XEXP (XEXP (operands[1], 0), 0));
-         rtx other = XEXP (XEXP (operands[1], 0), 1);
-
-         emit_insn (gen_addsi3 (operands[0], force_reg (SImode, sym), other));
-         DONE;
-       }
-
-      operands[1] = force_const_mem (SImode, operands[1]);
-
-      if (TARGET_TOC 
-         && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
-         && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
-               XEXP (operands[1], 0))))
-       {
-         operands[1] = gen_rtx_MEM (SImode,
-                            create_TOC_reference (XEXP (operands[1], 0)));
-         MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();   
-         RTX_UNCHANGING_P (operands[1]) = 1;
-       }
-
-      if (! memory_address_p (SImode, XEXP (operands[1], 0))
-         && ! reload_in_progress)
-       operands[1] = change_address (operands[1], SImode,
-                                     XEXP (operands[1], 0));
-    }
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], SImode); DONE; }")
 
 (define_insn "*movsi_internal1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h")
   [(set (match_operand:HI 0 "general_operand" "")
        (match_operand:HI 1 "any_operand" ""))]
   ""
-  "
-{
-  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (HImode, operands[1]);
-
-  if (CONSTANT_P (operands[1])
-      && GET_CODE (operands[1]) != CONST_INT)
-    {
-      operands[1] = force_const_mem (HImode, operands[1]);
-      if (! memory_address_p (HImode, XEXP (operands[1], 0))
-         && ! reload_in_progress)
-       operands[1] = change_address (operands[1], HImode,
-                                     XEXP (operands[1], 0));
-    }
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], HImode); DONE; }")
 
 (define_insn ""
   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
   [(set (match_operand:QI 0 "general_operand" "")
        (match_operand:QI 1 "any_operand" ""))]
   ""
-  "
-{
-  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (QImode, operands[1]);
-
-  if (CONSTANT_P (operands[1])
-      && GET_CODE (operands[1]) != CONST_INT)
-    {
-      operands[1] = force_const_mem (QImode, operands[1]);
-      if (! memory_address_p (QImode, XEXP (operands[1], 0))
-         && ! reload_in_progress)
-       operands[1] = change_address (operands[1], QImode,
-                                     XEXP (operands[1], 0));
-    }
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], QImode); DONE; }")
 
 (define_insn ""
   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
   [(set (match_operand:SF 0 "nonimmediate_operand" "")
        (match_operand:SF 1 "any_operand" ""))]
   ""
-  "
-{
-  /* If we are called from reload, we might be getting a SUBREG of a hard
-     reg.  So expand it.  */
-  if (GET_CODE (operands[0]) == SUBREG
-      && GET_CODE (SUBREG_REG (operands[0])) == REG
-      && REGNO (SUBREG_REG (operands[0])) < FIRST_PSEUDO_REGISTER
-      && (! REG_FUNCTION_VALUE_P (SUBREG_REG (operands[0]))
-         || ! rtx_equal_function_value_matters))
-    operands[0] = alter_subreg (operands[0]);
-  if (GET_CODE (operands[1]) == SUBREG
-      && GET_CODE (SUBREG_REG (operands[1])) == REG
-      && REGNO (SUBREG_REG (operands[1])) < FIRST_PSEUDO_REGISTER)
-    operands[1] = alter_subreg (operands[1]);
-
-  if (GET_CODE (operands[0]) == MEM)
-    {
-      /* If operands[1] is a register, it may have double-precision data
-        in it, so truncate it to single precision.  We need not do
-        this for POWERPC.  */
-      if (! TARGET_POWERPC && TARGET_HARD_FLOAT
-         && GET_CODE (operands[1]) == REG
-         && (FP_REGNO_P (REGNO (operands[1]))
-             || REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER))
-       {
-         rtx newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (SFmode));
-         emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));
-         operands[1] = newreg;
-       }
-
-      operands[1] = force_reg (SFmode, operands[1]);
-    }
-
-  if (CONSTANT_P (operands[1]) && TARGET_HARD_FLOAT
-      && ! easy_fp_constant (operands[1], SFmode))
-    {
-      operands[1] = force_const_mem (SFmode, operands[1]);
-      if (! memory_address_p (SFmode, XEXP (operands[1], 0))
-         && ! reload_in_progress)
-       operands[1] = change_address (operands[1], SFmode,
-                                     XEXP (operands[1], 0));
-    }
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], SFmode); DONE; }")
 
 (define_split
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
        (match_operand:DF 1 "any_operand" ""))]
   ""
-  "
-{
-  if (GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (DFmode, operands[1]);
-
-  if (CONSTANT_P (operands[1]) && ! easy_fp_constant (operands[1], DFmode))
-    {
-      operands[1] = force_const_mem (DFmode, operands[1]);
-      if (! memory_address_p (DFmode, XEXP (operands[1], 0))
-         && ! reload_in_progress)
-       operands[1] = change_address (operands[1], DFmode,
-                                     XEXP (operands[1], 0));
-    }
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], DFmode); DONE; }")
 
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
   [(set (match_operand:DI 0 "general_operand" "")
        (match_operand:DI 1 "any_operand" ""))]
   ""
-  "
-{
-  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (DImode, operands[1]);
-
-  /* Convert a move of a CONST_DOUBLE into a CONST_INT
-     only if sign-extended lower-half for 32-bit host.  */
-  if (GET_CODE (operands[1]) == CONST_DOUBLE
-#if HOST_BITS_PER_WIDE_INT == 32
-      && ((CONST_DOUBLE_HIGH (operands[1]) == 0
-          && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
-         || (CONST_DOUBLE_HIGH (operands[1]) == (HOST_WIDE_INT) 0xffffffff
-             && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
-#endif
-        )
-    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-
-  /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary.  */
-  if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
-    {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
-      DONE;
-    }
-
-  if (TARGET_64BIT
-      && CONSTANT_P (operands[1])
-#if HOST_BITS_PER_WIDE_INT == 32
-      && GET_CODE (operands[1]) != CONST_INT
-#endif
-      && ! easy_fp_constant (operands[1], DImode)
-      && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
-      && ! TOC_RELATIVE_EXPR_P (operands[1]))
-    {
-      /* Emit a USE operation so that the constant isn't deleted if
-        expensive optimizations are turned on because nobody
-        references it.  This should only be done for operands that
-        contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
-        This should not be done for operands that contain LABEL_REFs.
-        For now, we just handle the obvious case.  */
-      if (GET_CODE (operands[1]) != LABEL_REF)
-       emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
-
-      /* If we are to limit the number of things we put in the TOC and
-        this is a symbol plus a constant we can add in one insn,
-        just put the symbol in the TOC and add the constant.  Don't do
-        this if reload is in progress.  */
-      if (GET_CODE (operands[1]) == CONST
-         && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
-         && GET_CODE (XEXP (operands[1], 0)) == PLUS
-         && add_operand (XEXP (XEXP (operands[1], 0), 1), DImode)
-         && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
-             || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
-         && ! side_effects_p (operands[0]))
-       {
-         rtx sym = force_const_mem (DImode, XEXP (XEXP (operands[1], 0), 0));
-         rtx other = XEXP (XEXP (operands[1], 0), 1);
-
-         emit_insn (gen_adddi3 (operands[0], force_reg (DImode, sym), other));
-         DONE;
-       }
-
-      operands[1] = force_const_mem (DImode, operands[1]);
-
-      if (TARGET_TOC 
-         && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
-         && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
-               XEXP (operands[1], 0))))
-       {
-         operands[1] = gen_rtx_MEM (DImode,
-                            create_TOC_reference (XEXP (operands[1], 0)));
-
-         MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();   
-         RTX_UNCHANGING_P (operands[1]) = 1;
-       }       
-
-      if (! memory_address_p (DImode, XEXP (operands[1], 0))
-         && ! reload_in_progress)
-       operands[1] = change_address (operands[1], DImode,
-                                     XEXP (operands[1], 0));
-    }
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], DImode); DONE; }")
 
 (define_insn "*movdi_internal32"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m,r,r,r,r,r")
@@ -8526,23 +8247,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
                   (match_operand:TI 1 "general_operand" ""))
              (clobber (scratch:SI))])]
   "TARGET_STRING || TARGET_POWERPC64"
-  "
-{
-  if (GET_CODE (operands[0]) == MEM)
-    operands[1] = force_reg (TImode, operands[1]);
-
-  if (GET_CODE (operands[0]) == MEM
-      && GET_CODE (XEXP (operands[0], 0)) != REG
-      && ! reload_in_progress)
-    operands[0] = change_address (operands[0], TImode,
-                                 copy_addr_to_reg (XEXP (operands[0], 0)));
-
-  if (GET_CODE (operands[1]) == MEM
-      && GET_CODE (XEXP (operands[1], 0)) != REG
-      && ! reload_in_progress)
-    operands[1] = change_address (operands[1], TImode,
-                                 copy_addr_to_reg (XEXP (operands[1], 0)));
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }")
 
 ;; We say that MQ is clobbered in the last alternative because the first
 ;; alternative would never get used otherwise since it would need a reload