OSDN Git Service

2005-06-28 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / config / rs6000 / rs6000.md
index b88aef9..6d0e581 100644 (file)
@@ -1,6 +1,6 @@
 ;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler
 ;; Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 ;; This file is part of GCC.
@@ -17,8 +17,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GCC; see the file COPYING.  If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
 
 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
 
    (UNSPEC_TLSGOTTPREL         28)
    (UNSPEC_TLSTLS              29)
    (UNSPEC_FIX_TRUNC_TF                30)     ; fadd, rounding towards zero
+   (UNSPEC_MV_CR_GT            31)     ; move_from_CR_eq_bit
+   (UNSPEC_STFIWX              32)
+   (UNSPEC_SYNC                        33)
+   (UNSPEC_SYNC_OP             34)
+   (UNSPEC_SYNC_SWAP           35)
+   (UNSPEC_LWSYNC              36)
+   (UNSPEC_ISYNC               37)
+   (UNSPEC_POPCNTB             38)
+   (UNSPEC_FRES                        39)
   ])
 
 ;;
@@ -63,7 +72,7 @@
 \f
 ;; Define an insn type attribute.  This is used in function unit delay
 ;; computations.
-(define_attr "type" "integer,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv"
+(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv"
   (const_string "integer"))
 
 ;; Length (in bytes).
 (include "power4.md")
 (include "power5.md")
 
+(include "predicates.md")
+
+(include "darwin.md")
+
+\f
+;; Mode macros
+
+; This mode macro allows :GPR to be used to indicate the allowable size
+; of whole values in GPRs.
+(define_mode_macro GPR [SI (DI "TARGET_POWERPC64")])
+
+; Any supported integer mode.
+(define_mode_macro INT [QI HI SI DI TI])
+
+; Any supported integer mode that fits in one register.
+(define_mode_macro INT1 [QI HI SI (DI "TARGET_POWERPC64")])
+
+; SImode or DImode, even if DImode doesn't fit in GPRs.
+(define_mode_macro SDI [SI DI])
+
+; The size of a pointer.  Also, the size of the value that a record-condition
+; (one with a '.') will compare.
+(define_mode_macro P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
+
+; Any hardware-supported floating-point mode
+(define_mode_macro FP [(SF "TARGET_HARD_FLOAT")
+  (DF "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)")
+  (TF "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128")])
+
+; Various instructions that come in SI and DI forms.
+; A generic w/d attribute, for things like cmpw/cmpd.
+(define_mode_attr wd [(SI "w") (DI "d")])
+
 \f
 ;; Start with fixed-point load and store insns.  Here we put only the more
 ;; complex forms.  Basic data transfer is done later.
 
 ;; Fixed-point arithmetic insns.
 
-;; Discourage ai/addic because of carry but provide it in an alternative
-;; allowing register zero as source.
-(define_expand "addsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "reg_or_arith_cint_operand" "")))]
+(define_expand "add<mode>3"
+  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+       (plus:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
+                 (match_operand:SDI 2 "reg_or_add_cint_operand" "")))]
   ""
   "
 {
-  if (GET_CODE (operands[2]) == CONST_INT
-               && ! add_operand (operands[2], SImode))
+  if (<MODE>mode == DImode && ! TARGET_POWERPC64)
+    {
+      if (non_short_cint_operand (operands[2], DImode))
+       FAIL;
+    }
+  else if (GET_CODE (operands[2]) == CONST_INT
+          && ! add_operand (operands[2], <MODE>mode))
     {
       rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
-                ? operands[0] : gen_reg_rtx (SImode));
+                ? operands[0] : gen_reg_rtx (<MODE>mode));
 
       HOST_WIDE_INT val = INTVAL (operands[2]);
       HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
-      HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
+      HOST_WIDE_INT rest = trunc_int_for_mode (val - low, <MODE>mode);
+
+      if (<MODE>mode == DImode && !CONST_OK_FOR_LETTER_P (rest, 'L'))
+       FAIL;
 
       /* The ordering here is important for the prolog expander.
         When space is allocated from the stack, adding 'low' first may
         produce a temporary deallocation (which would be bad).  */
-      emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (rest)));
-      emit_insn (gen_addsi3 (operands[0], tmp, GEN_INT (low)));
+      emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (rest)));
+      emit_insn (gen_add<mode>3 (operands[0], tmp, GEN_INT (low)));
       DONE;
     }
 }")
 
-(define_insn "*addsi3_internal1"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,?r,r")
-       (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,b,r,b")
-                (match_operand:SI 2 "add_operand" "r,I,I,L")))]
+;; Discourage ai/addic because of carry but provide it in an alternative
+;; allowing register zero as source.
+(define_insn "*add<mode>3_internal1"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,?r,r")
+       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,r,b")
+                 (match_operand:GPR 2 "add_operand" "r,I,I,L")))]
   ""
   "@
    {cax|add} %0,%1,%2
   "{cau|addis} %0,%1,ha16(%2)"
   [(set_attr "length" "4")])
 
-(define_insn "*addsi3_internal2"
+(define_insn "*add<mode>3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
-                            (match_operand:SI 2 "reg_or_short_operand" "r,I,r,I"))
+       (compare:CC (plus:P (match_operand:P 1 "gpc_reg_operand" "%r,r,r,r")
+                           (match_operand:P 2 "reg_or_short_operand" "r,I,r,I"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
-  "TARGET_32BIT"
+   (clobber (match_scratch:P 3 "=r,r,r,r"))]
+  ""
   "@
    {cax.|add.} %3,%1,%2
    {ai.|addic.} %3,%1,%2
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                            (match_operand:SI 2 "reg_or_short_operand" ""))
+       (compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+                             (match_operand:GPR 2 "reg_or_short_operand" ""))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
+   (clobber (match_scratch:GPR 3 ""))]
+  "reload_completed"
   [(set (match_dup 3)
-       (plus:SI (match_dup 1)
+       (plus:GPR (match_dup 1)
                 (match_dup 2)))
    (set (match_dup 0)
        (compare:CC (match_dup 3)
                    (const_int 0)))]
   "")
 
-(define_insn "*addsi3_internal3"
+(define_insn "*add<mode>3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
-                            (match_operand:SI 2 "reg_or_short_operand" "r,I,r,I"))
+       (compare:CC (plus:P (match_operand:P 1 "gpc_reg_operand" "%r,r,r,r")
+                           (match_operand:P 2 "reg_or_short_operand" "r,I,r,I"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
-       (plus:SI (match_dup 1)
-                (match_dup 2)))]
-  "TARGET_32BIT"
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
+       (plus:P (match_dup 1)
+               (match_dup 2)))]
+  ""
   "@
    {cax.|add.} %0,%1,%2
    {ai.|addic.} %0,%1,%2
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                            (match_operand:SI 2 "reg_or_short_operand" ""))
+       (compare:CC (plus:P (match_operand:P 1 "gpc_reg_operand" "")
+                           (match_operand:P 2 "reg_or_short_operand" ""))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
+   (set (match_operand:P 0 "gpc_reg_operand" "")
+       (plus:P (match_dup 1) (match_dup 2)))]
+  "reload_completed"
   [(set (match_dup 0)
-       (plus:SI (match_dup 1)
-                (match_dup 2)))
+       (plus:P (match_dup 1)
+               (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
 ;; add should be last in case the result gets used in an address.
 
 (define_split
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "non_add_cint_operand" "")))]
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+                 (match_operand:GPR 2 "non_add_cint_operand" "")))]
   ""
-  [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))
-   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))]
+  [(set (match_dup 0) (plus:GPR (match_dup 1) (match_dup 3)))
+   (set (match_dup 0) (plus:GPR (match_dup 0) (match_dup 4)))]
 "
 {
   HOST_WIDE_INT val = INTVAL (operands[2]);
   HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
-  HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
+  HOST_WIDE_INT rest = trunc_int_for_mode (val - low, <MODE>mode);
 
-  operands[3] = GEN_INT (rest);
   operands[4] = GEN_INT (low);
+  if (<MODE>mode == SImode || CONST_OK_FOR_LETTER_P (rest, 'L'))
+    operands[3] = GEN_INT (rest);
+  else if (! no_new_pseudos)
+    {
+      operands[3] = gen_reg_rtx (DImode);
+      emit_move_insn (operands[3], operands[2]);
+      emit_insn (gen_adddi3 (operands[0], operands[1], operands[3]));
+      DONE;
+    }
+  else
+    FAIL;
 }")
 
-(define_insn "one_cmplsi2"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
   ""
   "nor %0,%1,%1")
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (not:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (not:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 2 "=r,r"))]
-  "TARGET_32BIT"
+   (clobber (match_scratch:P 2 "=r,r"))]
+  ""
   "@
    nor. %2,%1,%1
    #"
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (not:SI (match_operand:SI 1 "gpc_reg_operand" ""))
+       (compare:CC (not:P (match_operand:P 1 "gpc_reg_operand" ""))
                    (const_int 0)))
-   (clobber (match_scratch:SI 2 ""))]
-  "TARGET_32BIT && reload_completed"
+   (clobber (match_scratch:P 2 ""))]
+  "reload_completed"
   [(set (match_dup 2)
-       (not:SI (match_dup 1)))
+       (not:P (match_dup 1)))
    (set (match_dup 0)
        (compare:CC (match_dup 2)
                    (const_int 0)))]
 
 (define_insn ""
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (not:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (not:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (not:SI (match_dup 1)))]
-  "TARGET_32BIT"
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (not:P (match_dup 1)))]
+  ""
   "@
    nor. %0,%1,%1
    #"
 
 (define_split
   [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC (not:SI (match_operand:SI 1 "gpc_reg_operand" ""))
+       (compare:CC (not:P (match_operand:P 1 "gpc_reg_operand" ""))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (not:SI (match_dup 1)))]
-  "TARGET_32BIT && reload_completed"
+   (set (match_operand:P 0 "gpc_reg_operand" "")
+       (not:P (match_dup 1)))]
+  "reload_completed"
   [(set (match_dup 0)
-       (not:SI (match_dup 1)))
+       (not:P (match_dup 1)))
    (set (match_dup 2)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "{sf%I1|subf%I1c} %0,%2,%1")
 
 (define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (minus:SI (match_operand:SI 1 "reg_or_short_operand" "r,I")
-                 (match_operand:SI 2 "gpc_reg_operand" "r,r")))]
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (minus:GPR (match_operand:GPR 1 "reg_or_short_operand" "r,I")
+                  (match_operand:GPR 2 "gpc_reg_operand" "r,r")))]
   "TARGET_POWERPC"
   "@
    subf %0,%2,%1
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (minus:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                             (match_operand:SI 2 "gpc_reg_operand" "r,r"))
+       (compare:CC (minus:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                            (match_operand:P 2 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
-  "TARGET_POWERPC && TARGET_32BIT"
+   (clobber (match_scratch:P 3 "=r,r"))]
+  "TARGET_POWERPC"
   "@
    subf. %3,%2,%1
    #"
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (minus:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                             (match_operand:SI 2 "gpc_reg_operand" ""))
+       (compare:CC (minus:P (match_operand:P 1 "gpc_reg_operand" "")
+                            (match_operand:P 2 "gpc_reg_operand" ""))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
+   (clobber (match_scratch:P 3 ""))]
+  "reload_completed"
   [(set (match_dup 3)
-       (minus:SI (match_dup 1)
+       (minus:P (match_dup 1)
                  (match_dup 2)))
    (set (match_dup 0)
        (compare:CC (match_dup 3)
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (minus:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                             (match_operand:SI 2 "gpc_reg_operand" "r,r"))
+       (compare:CC (minus:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                            (match_operand:P 2 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (minus:SI (match_dup 1)
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (minus:P (match_dup 1)
                  (match_dup 2)))]
-  "TARGET_POWERPC && TARGET_32BIT"
+  "TARGET_POWERPC"
   "@
    subf. %0,%2,%1
    #"
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC (minus:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                             (match_operand:SI 2 "gpc_reg_operand" ""))
+       (compare:CC (minus:P (match_operand:P 1 "gpc_reg_operand" "")
+                            (match_operand:P 2 "gpc_reg_operand" ""))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (minus:SI (match_dup 1)
+   (set (match_operand:P 0 "gpc_reg_operand" "")
+       (minus:P (match_dup 1)
                  (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
+  "reload_completed"
   [(set (match_dup 0)
-       (minus:SI (match_dup 1)
+       (minus:P (match_dup 1)
                  (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-(define_expand "subsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (minus:SI (match_operand:SI 1 "reg_or_short_operand" "")
-                 (match_operand:SI 2 "reg_or_arith_cint_operand" "")))]
+(define_expand "sub<mode>3"
+  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+       (minus:SDI (match_operand:SDI 1 "reg_or_short_operand" "")
+                  (match_operand:SDI 2 "reg_or_sub_cint_operand" "")))]
   ""
   "
 {
   if (GET_CODE (operands[2]) == CONST_INT)
     {
-      emit_insn (gen_addsi3 (operands[0], operands[1],
-                            negate_rtx (SImode, operands[2])));
+      emit_insn (gen_add<mode>3 (operands[0], operands[1],
+                                negate_rtx (<MODE>mode, operands[2])));
       DONE;
     }
 }")
    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 0)))]
   "")
 
-(define_insn "negsi2"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
+(define_expand "neg<mode>2"
+  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+       (neg:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
+  ""
+  "")
+
+(define_insn "*neg<mode>2_internal"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
   ""
   "neg %0,%1")
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 2 "=r,r"))]
-  "TARGET_32BIT"
+   (clobber (match_scratch:P 2 "=r,r"))]
+  ""
   "@
    neg. %2,%1
    #"
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (neg:SI (match_operand:SI 1 "gpc_reg_operand" ""))
+       (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" ""))
                    (const_int 0)))
-   (clobber (match_scratch:SI 2 ""))]
-  "TARGET_32BIT && reload_completed"
+   (clobber (match_scratch:P 2 ""))]
+  "reload_completed"
   [(set (match_dup 2)
-       (neg:SI (match_dup 1)))
+       (neg:P (match_dup 1)))
    (set (match_dup 0)
        (compare:CC (match_dup 2)
                    (const_int 0)))]
 
 (define_insn ""
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (neg:SI (match_dup 1)))]
-  "TARGET_32BIT"
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (neg:P (match_dup 1)))]
+  ""
   "@
    neg. %0,%1
    #"
 
 (define_split
   [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC (neg:SI (match_operand:SI 1 "gpc_reg_operand" ""))
+       (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" ""))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (neg:SI (match_dup 1)))]
-  "TARGET_32BIT && reload_completed"
+   (set (match_operand:P 0 "gpc_reg_operand" "")
+       (neg:P (match_dup 1)))]
+  "reload_completed"
   [(set (match_dup 0)
-       (neg:SI (match_dup 1)))
+       (neg:P (match_dup 1)))
    (set (match_dup 2)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-(define_insn "clzsi2"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (clz:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
+(define_insn "clz<mode>2"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (clz:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
   ""
-  "{cntlz|cntlzw} %0,%1")
+  "{cntlz|cntlz<wd>} %0,%1")
 
-(define_expand "ctzsi2"
+(define_expand "ctz<mode>2"
   [(set (match_dup 2)
-       (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r")))
-   (parallel [(set (match_dup 3) (and:SI (match_dup 1)
-                                        (match_dup 2)))
+       (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))
+   (parallel [(set (match_dup 3) (and:GPR (match_dup 1)
+                                         (match_dup 2)))
              (clobber (scratch:CC))])
-   (set (match_dup 4) (clz:SI (match_dup 3)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (minus:SI (const_int 31) (match_dup 4)))]
+   (set (match_dup 4) (clz:GPR (match_dup 3)))
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (minus:GPR (match_dup 5) (match_dup 4)))]
   ""
   {
-     operands[2] = gen_reg_rtx (SImode);
-     operands[3] = gen_reg_rtx (SImode);
-     operands[4] = gen_reg_rtx (SImode);
+     operands[2] = gen_reg_rtx (<MODE>mode);
+     operands[3] = gen_reg_rtx (<MODE>mode);
+     operands[4] = gen_reg_rtx (<MODE>mode);
+     operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1);
   })
 
-(define_expand "ffssi2"
+(define_expand "ffs<mode>2"
   [(set (match_dup 2)
-       (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r")))
-   (parallel [(set (match_dup 3) (and:SI (match_dup 1)
-                                        (match_dup 2)))
+       (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))
+   (parallel [(set (match_dup 3) (and:GPR (match_dup 1)
+                                         (match_dup 2)))
              (clobber (scratch:CC))])
-   (set (match_dup 4) (clz:SI (match_dup 3)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (minus:SI (const_int 32) (match_dup 4)))]
+   (set (match_dup 4) (clz:GPR (match_dup 3)))
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (minus:GPR (match_dup 5) (match_dup 4)))]
   ""
   {
-     operands[2] = gen_reg_rtx (SImode);
-     operands[3] = gen_reg_rtx (SImode);
-     operands[4] = gen_reg_rtx (SImode);
+     operands[2] = gen_reg_rtx (<MODE>mode);
+     operands[3] = gen_reg_rtx (<MODE>mode);
+     operands[4] = gen_reg_rtx (<MODE>mode);
+     operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));
+  })
+
+(define_expand "popcount<mode>2"
+  [(set (match_dup 2)
+       (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
+                    UNSPEC_POPCNTB))
+   (set (match_dup 3)
+       (mult:GPR (match_dup 2) (match_dup 4)))
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (lshiftrt:GPR (match_dup 3) (match_dup 5)))]
+  "TARGET_POPCNTB"
+  {
+    operands[2] = gen_reg_rtx (<MODE>mode);
+    operands[3] = gen_reg_rtx (<MODE>mode);
+    operands[4] = force_reg (<MODE>mode,
+                            <MODE>mode == SImode
+                            ? GEN_INT (0x01010101)
+                            : GEN_INT ((HOST_WIDE_INT)
+                                       0x01010101 << 32 | 0x01010101));
+    operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 8);
   })
 
+(define_insn "popcntb<mode>2"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
+                     UNSPEC_POPCNTB))]
+  "TARGET_POPCNTB"
+  "popcntb %0,%1")
+
 (define_expand "mulsi3"
   [(use (match_operand:SI 0 "gpc_reg_operand" ""))
    (use (match_operand:SI 1 "gpc_reg_operand" ""))
   "divs %0,%1,%2"
   [(set_attr "type" "idiv")])
 
-(define_expand "udivsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-        (udiv:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                 (match_operand:SI 2 "gpc_reg_operand" "")))]
+(define_expand "udiv<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+        (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+                 (match_operand:GPR 2 "gpc_reg_operand" "")))]
   "TARGET_POWERPC || (! TARGET_POWER && ! TARGET_POWERPC)"
   "
 {
   [(set_attr "type" "idiv")])
 
 (define_insn "*udivsi3_no_mq"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (udiv:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                 (match_operand:SI 2 "gpc_reg_operand" "r")))]
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+                 (match_operand:GPR 2 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC && ! TARGET_POWER"
-  "divwu %0,%1,%2"
+  "div<wd>u %0,%1,%2"
   [(set_attr "type" "idiv")])
 
 ;; For powers of two we can do srai/aze for divide and then adjust for
 ;; modulus.  If it isn't a power of two, FAIL on POWER so divmodsi4 will be
 ;; used; for PowerPC, force operands into register and do a normal divide;
 ;; for AIX common-mode, use quoss call on register operands.
-(define_expand "divsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
-               (match_operand:SI 2 "reg_or_cint_operand" "")))]
+(define_expand "div<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+       (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+                (match_operand:GPR 2 "reg_or_cint_operand" "")))]
   ""
   "
 {
   "divw %0,%1,%2"
   [(set_attr "type" "idiv")])
 
-(define_insn "*divsi3_no_mq"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                (match_operand:SI 2 "gpc_reg_operand" "r")))]
+(define_insn "*div<mode>3_no_mq"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+                (match_operand:GPR 2 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC && ! TARGET_POWER"
-  "divw %0,%1,%2"
+  "div<wd> %0,%1,%2"
   [(set_attr "type" "idiv")])
 
-(define_expand "modsi3"
-  [(use (match_operand:SI 0 "gpc_reg_operand" ""))
-   (use (match_operand:SI 1 "gpc_reg_operand" ""))
-   (use (match_operand:SI 2 "reg_or_cint_operand" ""))]
+(define_expand "mod<mode>3"
+  [(use (match_operand:GPR 0 "gpc_reg_operand" ""))
+   (use (match_operand:GPR 1 "gpc_reg_operand" ""))
+   (use (match_operand:GPR 2 "reg_or_cint_operand" ""))]
   ""
   "
 {
       || (i = exact_log2 (INTVAL (operands[2]))) < 0)
     FAIL;
 
-  temp1 = gen_reg_rtx (SImode);
-  temp2 = gen_reg_rtx (SImode);
+  temp1 = gen_reg_rtx (<MODE>mode);
+  temp2 = gen_reg_rtx (<MODE>mode);
 
-  emit_insn (gen_divsi3 (temp1, operands[1], operands[2]));
-  emit_insn (gen_ashlsi3 (temp2, temp1, GEN_INT (i)));
-  emit_insn (gen_subsi3 (operands[0], operands[1], temp2));
+  emit_insn (gen_div<mode>3 (temp1, operands[1], operands[2]));
+  emit_insn (gen_ashl<mode>3 (temp2, temp1, GEN_INT (i)));
+  emit_insn (gen_sub<mode>3 (operands[0], operands[1], temp2));
   DONE;
 }")
 
 (define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-               (match_operand:SI 2 "exact_log2_cint_operand" "N")))]
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+                (match_operand:GPR 2 "exact_log2_cint_operand" "N")))]
   ""
-  "{srai|srawi} %0,%1,%p2\;{aze|addze} %0,%0"
-  [(set_attr "length" "8")])
+  "{srai|sra<wd>i} %0,%1,%p2\;{aze|addze} %0,%0"
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:SI 2 "exact_log2_cint_operand" "N,N"))
+       (compare:CC (div:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                          (match_operand:P 2 "exact_log2_cint_operand" "N,N"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
+   (clobber (match_scratch:P 3 "=r,r"))]
   ""
   "@
-   {srai|srawi} %3,%1,%p2\;{aze.|addze.} %3,%3
+   {srai|sra<wd>i} %3,%1,%p2\;{aze.|addze.} %3,%3
    #"
   [(set_attr "type" "compare")
    (set_attr "length" "8,12")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "exact_log2_cint_operand" ""))
+       (compare:CC (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+                            (match_operand:GPR 2 "exact_log2_cint_operand"
+                             ""))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
+   (clobber (match_scratch:GPR 3 ""))]
   "reload_completed"
   [(set (match_dup 3)
-       (div:SI (match_dup 1) (match_dup 2)))
+       (div:<MODE> (match_dup 1) (match_dup 2)))
    (set (match_dup 0)
        (compare:CC (match_dup 3)
                    (const_int 0)))]
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:SI 2 "exact_log2_cint_operand" "N,N"))
+       (compare:CC (div:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                          (match_operand:P 2 "exact_log2_cint_operand" "N,N"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (div:SI (match_dup 1) (match_dup 2)))]
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (div:P (match_dup 1) (match_dup 2)))]
   ""
   "@
-   {srai|srawi} %0,%1,%p2\;{aze.|addze.} %0,%0
+   {srai|sra<wd>i} %0,%1,%p2\;{aze.|addze.} %0,%0
    #"
   [(set_attr "type" "compare")
    (set_attr "length" "8,12")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "exact_log2_cint_operand" ""))
+       (compare:CC (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+                            (match_operand:GPR 2 "exact_log2_cint_operand"
+                             ""))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (div:SI (match_dup 1) (match_dup 2)))]
+   (set (match_operand:GPR 0 "gpc_reg_operand" "")
+       (div:GPR (match_dup 1) (match_dup 2)))]
   "reload_completed"
   [(set (match_dup 0)
-       (div:SI (match_dup 1) (match_dup 2)))
+       (div:<MODE> (match_dup 1) (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
    and %0,%1,%2
    {rlinm|rlwinm} %0,%1,0,%m2,%M2
    {andil.|andi.} %0,%1,%b2
-   {andiu.|andis.} %0,%1,%u2")
+   {andiu.|andis.} %0,%1,%u2"
+  [(set_attr "type" "*,*,compare,compare")])
 
 ;; Note to set cr's other than cr0 we do the and immediate and then
 ;; the test again -- this avoids a mfcr which on the higher end
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "and_operand" ""))
+       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+                            (match_operand:GPR 2 "and_operand" ""))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))
+   (clobber (match_scratch:GPR 3 ""))
    (clobber (match_scratch:CC 4 ""))]
   "reload_completed"
   [(parallel [(set (match_dup 3)
-                  (and:SI (match_dup 1)
-                          (match_dup 2)))
+                  (and:<MODE> (match_dup 1)
+                              (match_dup 2)))
              (clobber (match_dup 4))])
    (set (match_dup 0)
        (compare:CC (match_dup 3)
 }"
   [(set_attr "length" "8")])
 
-(define_insn_and_split "*andsi3_internal7"
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (and:SI (match_operand:SI 0 "gpc_reg_operand" "r,r")
-                           (match_operand:SI 1 "mask_operand_wrap" "i,i"))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
-  "TARGET_POWERPC64"
-  "#"
-  "TARGET_POWERPC64"
-  [(parallel [(set (match_dup 2)
-                  (compare:CC (and:SI (rotate:SI (match_dup 0) (match_dup 4))
-                                      (match_dup 5))
-                              (const_int 0)))
-             (clobber (match_dup 3))])]
-  "
-{
-  int mb = extract_MB (operands[1]);
-  int me = extract_ME (operands[1]);
-  operands[4] = GEN_INT (me + 1);
-  operands[5] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
-}"
-  [(set_attr "type" "delayed_compare,compare")
-   (set_attr "length" "4,8")])
-
-(define_insn_and_split "*andsi3_internal8"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
-       (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:SI 2 "mask_operand_wrap" "i,i"))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (and:SI (match_dup 1)
-               (match_dup 2)))]
-  "TARGET_POWERPC64"
-  "#"
-  "TARGET_POWERPC64"
-  [(parallel [(set (match_dup 3)
-                  (compare:CC (and:SI (rotate:SI (match_dup 1) (match_dup 4))
-                                      (match_dup 5))
-                              (const_int 0)))
-             (set (match_dup 0)
-                  (and:SI (rotate:SI (match_dup 1) (match_dup 4))
-                          (match_dup 5)))])
-   (set (match_dup 0)
-       (rotate:SI (match_dup 0) (match_dup 6)))]
-  "
-{
-  int mb = extract_MB (operands[2]);
-  int me = extract_ME (operands[2]);
-  operands[4] = GEN_INT (me + 1);
-  operands[6] = GEN_INT (32 - (me + 1));
-  operands[5] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
-}"
-  [(set_attr "type" "delayed_compare,compare")
-   (set_attr "length" "8,12")])
-
 (define_expand "iorsi3"
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
        (ior:SI (match_operand:SI 1 "gpc_reg_operand" "")
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
                         (match_operand:SI 1 "const_int_operand" "i")
                         (match_operand:SI 2 "const_int_operand" "i"))
-       (ashift:SI (match_operand:SI 3 "gpc_reg_operand" "r")
+       (rotate:SI (match_operand:SI 3 "gpc_reg_operand" "r")
                   (match_operand:SI 4 "const_int_operand" "i")))]
   "(32 - (INTVAL (operands[4]) & 31)) >= INTVAL (operands[1])"
   "*
 }"
   [(set_attr "type" "insert_word")])
 
+;; combine patterns for rlwimi
+(define_insn "*insvsi_internal5"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (ior:SI (and:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+                        (match_operand:SI 1 "mask_operand" "i"))
+                (and:SI (lshiftrt:SI (match_operand:SI 3 "gpc_reg_operand" "r")
+                                     (match_operand:SI 2 "const_int_operand" "i"))
+                        (match_operand:SI 5 "mask_operand" "i"))))]
+  "TARGET_POWERPC && INTVAL(operands[1]) == ~INTVAL(operands[5])"
+  "*
+{
+ int me = extract_ME(operands[5]);
+ int mb = extract_MB(operands[5]);
+ operands[4] = GEN_INT(32 - INTVAL(operands[2]));
+ operands[2] = GEN_INT(mb);
+ operands[1] = GEN_INT(me);
+ return \"{rlimi|rlwimi} %0,%3,%h4,%h2,%h1\";
+}"
+  [(set_attr "type" "insert_word")])
+
+(define_insn "*insvsi_internal6"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 3 "gpc_reg_operand" "r")
+                                     (match_operand:SI 2 "const_int_operand" "i"))
+                        (match_operand:SI 5 "mask_operand" "i"))
+                (and:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+                        (match_operand:SI 1 "mask_operand" "i"))))]
+  "TARGET_POWERPC && INTVAL(operands[1]) == ~INTVAL(operands[5])"
+  "*
+{
+ int me = extract_ME(operands[5]);
+ int mb = extract_MB(operands[5]);
+ operands[4] = GEN_INT(32 - INTVAL(operands[2]));
+ operands[2] = GEN_INT(mb);
+ operands[1] = GEN_INT(me);
+ return \"{rlimi|rlwimi} %0,%3,%h4,%h2,%h1\";
+}"
+  [(set_attr "type" "insert_word")])
+
 (define_insn "insvdi"
   [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
                         (match_operand:SI 1 "const_int_operand" "i")
   return \"rldimi %0,%3,%H1,%H2\";
 }")
 
+(define_insn "*insvdi_internal2"
+  [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
+                        (match_operand:SI 1 "const_int_operand" "i")
+                        (match_operand:SI 2 "const_int_operand" "i"))
+       (ashiftrt:DI (match_operand:DI 3 "gpc_reg_operand" "r")
+                    (match_operand:SI 4 "const_int_operand" "i")))]
+  "TARGET_POWERPC64
+   && insvdi_rshift_rlwimi_p (operands[1], operands[2], operands[4])"
+  "*
+{
+  int shift = INTVAL (operands[4]) & 63;
+  int start = (INTVAL (operands[2]) & 63) - 32;
+  int size = INTVAL (operands[1]) & 63;
+
+  operands[4] = GEN_INT (64 - shift - start - size);
+  operands[2] = GEN_INT (start);
+  operands[1] = GEN_INT (start + size - 1);
+  return \"rlwimi %0,%3,%h4,%h2,%h1\";
+}")
+
+(define_insn "*insvdi_internal3"
+  [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
+                        (match_operand:SI 1 "const_int_operand" "i")
+                        (match_operand:SI 2 "const_int_operand" "i"))
+       (lshiftrt:DI (match_operand:DI 3 "gpc_reg_operand" "r")
+                    (match_operand:SI 4 "const_int_operand" "i")))]
+  "TARGET_POWERPC64
+   && insvdi_rshift_rlwimi_p (operands[1], operands[2], operands[4])"
+  "*
+{
+  int shift = INTVAL (operands[4]) & 63;
+  int start = (INTVAL (operands[2]) & 63) - 32;
+  int size = INTVAL (operands[1]) & 63;
+
+  operands[4] = GEN_INT (64 - shift - start - size);
+  operands[2] = GEN_INT (start);
+  operands[1] = GEN_INT (start + size - 1);
+  return \"rlwimi %0,%3,%h4,%h2,%h1\";
+}")
+
 (define_expand "extzv"
   [(set (match_operand 0 "gpc_reg_operand" "")
        (zero_extract (match_operand 1 "gpc_reg_operand" "")
     operands[3] = GEN_INT (start + size);
   operands[2] = GEN_INT (64 - size);
   return \"rldicl. %4,%1,%3,%2\";
-}")
+}"
+  [(set_attr "type" "compare")])
 
 (define_insn "*extzvdi_internal2"
   [(set (match_operand:CC 4 "gpc_reg_operand" "=x")
     operands[3] = GEN_INT (start + size);
   operands[2] = GEN_INT (64 - size);
   return \"rldicl. %0,%1,%3,%2\";
-}")
+}"
+  [(set_attr "type" "compare")])
 
 (define_insn "rotlsi3"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                    (const_int 0)))]
   "")
 
-(define_insn ""
+(define_insn "rlwinm"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (and:SI (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                           (match_operand:SI 2 "const_int_operand" "i"))
 ;; this case, we just lose precision that we would have otherwise gotten but
 ;; is not guaranteed.  Perhaps this should be tightened up at some point.
 
-(define_insn "extendsfdf2"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
-       (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "f")))]
+(define_expand "extendsfdf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "")
+
+(define_insn_and_split "*extendsfdf2_fpr"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f,?f,f")
+       (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m")))]
   "TARGET_HARD_FLOAT && TARGET_FPRS"
-  "*
+  "@
+   #
+   fmr %0,%1
+   lfs%U1%X1 %0,%1"
+  "&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])"
+  [(const_int 0)]
 {
-  if (REGNO (operands[0]) == REGNO (operands[1]))
-    return \"\";
-  else
-    return \"fmr %0,%1\";
-}"
-  [(set_attr "type" "fp")])
+  emit_note (NOTE_INSN_DELETED);
+  DONE;
+}
+  [(set_attr "type" "fp,fp,fpload")])
+
+(define_expand "truncdfsf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+       (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "")
 
-(define_insn "truncdfsf2"
+(define_insn "*truncdfsf2_fpr"
   [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
        (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "f")))]
   "TARGET_HARD_FLOAT && TARGET_FPRS"
   "{fm|fmul} %0,%1,%2"
   [(set_attr "type" "dmul")])
 
+(define_insn "fres"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
+  "TARGET_PPC_GFXOPT && flag_finite_math_only"
+  "fres %0,%1"
+  [(set_attr "type" "fp")])
+
 (define_expand "divsf3"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
        (div:SF (match_operand:SF 1 "gpc_reg_operand" "")
                (match_operand:SF 2 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT"
-  "")
+{
+  if (swdiv && !optimize_size && TARGET_PPC_GFXOPT
+  && flag_finite_math_only && !flag_trapping_math)
+    {
+      rs6000_emit_swdivsf (operands[0], operands[1], operands[2]);
+      DONE;
+    }
+})
 
 (define_insn ""
   [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
   "fsqrt %0,%1"
   [(set_attr "type" "dsqrt")])
 
+(define_expand "copysignsf3"
+  [(set (match_dup 3)
+        (abs:SF (match_operand:SF 1 "gpc_reg_operand" "")))
+   (set (match_dup 4)
+       (neg:SF (abs:SF (match_dup 1))))
+   (set (match_operand:SF 0 "gpc_reg_operand" "")
+        (if_then_else:SF (ge (match_operand:SF 2 "gpc_reg_operand" "")
+                            (match_dup 5))
+                        (match_dup 3)
+                        (match_dup 4)))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
+   && !HONOR_NANS (SFmode) && !HONOR_SIGNED_ZEROS (SFmode)" 
+  {
+     operands[3] = gen_reg_rtx (SFmode);
+     operands[4] = gen_reg_rtx (SFmode);
+     operands[5] = CONST0_RTX (SFmode);
+  })
+
+(define_expand "copysigndf3"
+  [(set (match_dup 3)
+        (abs:DF (match_operand:DF 1 "gpc_reg_operand" "")))
+   (set (match_dup 4)
+       (neg:DF (abs:DF (match_dup 1))))
+   (set (match_operand:DF 0 "gpc_reg_operand" "")
+        (if_then_else:DF (ge (match_operand:DF 2 "gpc_reg_operand" "")
+                            (match_dup 5))
+                        (match_dup 3)
+                        (match_dup 4)))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
+   && !HONOR_NANS (DFmode) && !HONOR_SIGNED_ZEROS (DFmode)"
+  {
+     operands[3] = gen_reg_rtx (DFmode);
+     operands[4] = gen_reg_rtx (DFmode);
+     operands[5] = CONST0_RTX (DFmode);
+  })
+
 ;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
 ;; fsel instruction and some auxiliary computations.  Then we just have a
 ;; single DEFINE_INSN for fsel and the define_splits to make them if made by
 ;; combine.
-(define_expand "maxsf3"
+(define_expand "smaxsf3"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
        (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
                             (match_operand:SF 2 "gpc_reg_operand" ""))
                         (match_dup 1)
                         (match_dup 2)))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
   "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
 
-(define_expand "minsf3"
+(define_expand "sminsf3"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
        (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
                             (match_operand:SF 2 "gpc_reg_operand" ""))
                         (match_dup 2)
                         (match_dup 1)))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
   "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
 
 (define_split
        (match_operator:SF 3 "min_max_operator"
         [(match_operand:SF 1 "gpc_reg_operand" "")
          (match_operand:SF 2 "gpc_reg_operand" "")]))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
   [(const_int 0)]
   "
 { rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
   "fsel %0,%1,%2,%3"
   [(set_attr "type" "fp")])
 
-(define_insn "negdf2"
+(define_expand "negdf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (neg:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "")
+
+(define_insn "*negdf2_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
   "TARGET_HARD_FLOAT && TARGET_FPRS"
   "fneg %0,%1"
   [(set_attr "type" "fp")])
 
-(define_insn "absdf2"
+(define_expand "absdf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (abs:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "")
+
+(define_insn "*absdf2_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
   "TARGET_HARD_FLOAT && TARGET_FPRS"
   "fabs %0,%1"
   [(set_attr "type" "fp")])
 
-(define_insn ""
+(define_insn "*nabsdf2_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f"))))]
   "TARGET_HARD_FLOAT && TARGET_FPRS"
   "fnabs %0,%1"
   [(set_attr "type" "fp")])
 
-(define_insn "adddf3"
+(define_expand "adddf3"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (plus:DF (match_operand:DF 1 "gpc_reg_operand" "")
+                (match_operand:DF 2 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "")
+
+(define_insn "*adddf3_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
                 (match_operand:DF 2 "gpc_reg_operand" "f")))]
   "{fa|fadd} %0,%1,%2"
   [(set_attr "type" "fp")])
 
-(define_insn "subdf3"
+(define_expand "subdf3"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (minus:DF (match_operand:DF 1 "gpc_reg_operand" "")
+                 (match_operand:DF 2 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "")
+
+(define_insn "*subdf3_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (minus:DF (match_operand:DF 1 "gpc_reg_operand" "f")
                  (match_operand:DF 2 "gpc_reg_operand" "f")))]
   "{fs|fsub} %0,%1,%2"
   [(set_attr "type" "fp")])
 
-(define_insn "muldf3"
+(define_expand "muldf3"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (mult:DF (match_operand:DF 1 "gpc_reg_operand" "")
+                (match_operand:DF 2 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "")
+
+(define_insn "*muldf3_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
                 (match_operand:DF 2 "gpc_reg_operand" "f")))]
   "{fm|fmul} %0,%1,%2"
   [(set_attr "type" "dmul")])
 
-(define_insn "divdf3"
+(define_insn "fred"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+       (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
+  "TARGET_POPCNTB && flag_finite_math_only"
+  "fre %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_expand "divdf3"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (div:DF (match_operand:DF 1 "gpc_reg_operand" "")
+               (match_operand:DF 2 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+{
+  if (swdiv && !optimize_size && TARGET_POPCNTB
+  && flag_finite_math_only && !flag_trapping_math)
+    {
+      rs6000_emit_swdivdf (operands[0], operands[1], operands[2]);
+      DONE;
+    }
+})
+
+(define_insn "*divdf3_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (div:DF (match_operand:DF 1 "gpc_reg_operand" "f")
                (match_operand:DF 2 "gpc_reg_operand" "f")))]
 ;; The conditional move instructions allow us to perform max and min
 ;; operations even when
 
-(define_expand "maxdf3"
+(define_expand "smaxdf3"
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
        (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
                             (match_operand:DF 2 "gpc_reg_operand" ""))
                         (match_dup 1)
                         (match_dup 2)))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
   "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
 
-(define_expand "mindf3"
+(define_expand "smindf3"
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
        (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
                             (match_operand:DF 2 "gpc_reg_operand" ""))
                         (match_dup 2)
                         (match_dup 1)))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
   "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
 
 (define_split
        (match_operator:DF 3 "min_max_operator"
         [(match_operand:DF 1 "gpc_reg_operand" "")
          (match_operand:DF 2 "gpc_reg_operand" "")]))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
   [(const_int 0)]
   "
 { rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
   "TARGET_HARD_FLOAT && TARGET_FPRS"
   "
 {
+  if (TARGET_E500_DOUBLE)
+    {
+      emit_insn (gen_spe_floatsidf2 (operands[0], operands[1]));
+      DONE;
+    }
   if (TARGET_POWERPC64)
     {
       rtx mem = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
   operands[6] = gen_reg_rtx (SImode);
 }")
 
-(define_insn "*floatsidf2_internal"
+(define_insn_and_split "*floatsidf2_internal"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=&f")
        (float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
    (use (match_operand:SI 2 "gpc_reg_operand" "r"))
    (clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
   "#"
-  [(set_attr "length" "24")])
-
-(define_split
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
-   (use (match_operand:SI 2 "gpc_reg_operand" ""))
-   (use (match_operand:DF 3 "gpc_reg_operand" ""))
-   (clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
-   (clobber (match_operand:DF 5 "gpc_reg_operand" ""))
-   (clobber (match_operand:SI 6 "gpc_reg_operand" ""))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
-   (use (match_operand:SI 2 "gpc_reg_operand" ""))
-   (use (match_operand:DF 3 "gpc_reg_operand" ""))
-   (clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
-   (clobber (match_operand:DF 5 "gpc_reg_operand" ""))
-   (clobber (match_operand:SI 6 "gpc_reg_operand" ""))]
+  "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[4]))"
+  [(pc)]
   "
 {
   rtx lowword, highword;
-  if (GET_CODE (operands[4]) != MEM)
-    abort();
-  highword = XEXP (operands[4], 0);
-  lowword = plus_constant (highword, 4);
+  gcc_assert (MEM_P (operands[4]));
+  highword = adjust_address (operands[4], SImode, 0);
+  lowword = adjust_address (operands[4], SImode, 4);
   if (! WORDS_BIG_ENDIAN)
     {
       rtx tmp;
 
   emit_insn (gen_xorsi3 (operands[6], operands[1],
                         GEN_INT (~ (HOST_WIDE_INT) 0x7fffffff)));
-  emit_move_insn (gen_rtx_MEM (SImode, lowword), operands[6]);
-  emit_move_insn (gen_rtx_MEM (SImode, highword), operands[2]);
+  emit_move_insn (lowword, operands[6]);
+  emit_move_insn (highword, operands[2]);
   emit_move_insn (operands[5], operands[4]);
   emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
   DONE;
-}")
+}"
+  [(set_attr "length" "24")])
 
 (define_expand "floatunssisf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
              (use (match_dup 3))
              (clobber (match_dup 4))
              (clobber (match_dup 5))])]
-  "TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
   "
 {
+  if (TARGET_E500_DOUBLE)
+    {
+      emit_insn (gen_spe_floatunssidf2 (operands[0], operands[1]));
+      DONE;
+    }
   if (TARGET_POWERPC64)
     {
       rtx mem = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
   operands[5] = gen_reg_rtx (DFmode);
 }")
 
-(define_insn "*floatunssidf2_internal"
+(define_insn_and_split "*floatunssidf2_internal"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=&f")
        (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
    (use (match_operand:SI 2 "gpc_reg_operand" "r"))
    (clobber (match_operand:DF 5 "gpc_reg_operand" "=&f"))]
   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
   "#"
-  [(set_attr "length" "20")])
-
-(define_split
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
-   (use (match_operand:SI 2 "gpc_reg_operand" ""))
-   (use (match_operand:DF 3 "gpc_reg_operand" ""))
-   (clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
-   (clobber (match_operand:DF 5 "gpc_reg_operand" ""))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
-   (use (match_operand:SI 2 "gpc_reg_operand" ""))
-   (use (match_operand:DF 3 "gpc_reg_operand" ""))
-   (clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
-   (clobber (match_operand:DF 5 "gpc_reg_operand" ""))]
+  "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[4]))"
+  [(pc)]
   "
 {
   rtx lowword, highword;
-  if (GET_CODE (operands[4]) != MEM)
-    abort();
-  highword = XEXP (operands[4], 0);
-  lowword = plus_constant (highword, 4);
+  gcc_assert (MEM_P (operands[4]));
+  highword = adjust_address (operands[4], SImode, 0);
+  lowword = adjust_address (operands[4], SImode, 4);
   if (! WORDS_BIG_ENDIAN)
     {
       rtx tmp;
       tmp = highword; highword = lowword; lowword = tmp;
     }
 
-  emit_move_insn (gen_rtx_MEM (SImode, lowword), operands[1]);
-  emit_move_insn (gen_rtx_MEM (SImode, highword), operands[2]);
+  emit_move_insn (lowword, operands[1]);
+  emit_move_insn (highword, operands[2]);
   emit_move_insn (operands[5], operands[4]);
   emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
   DONE;
-}")
+}"
+  [(set_attr "length" "20")])
 
 (define_expand "fix_truncdfsi2"
-  [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
+  [(parallel [(set (match_operand:SI 0 "fix_trunc_dest_operand" "")
                   (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
              (clobber (match_dup 2))
              (clobber (match_dup 3))])]
-  "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "(TARGET_POWER2 || TARGET_POWERPC)
+   && TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
   "
 {
+  if (TARGET_E500_DOUBLE)
+    {
+     emit_insn (gen_spe_fix_truncdfsi2 (operands[0], operands[1]));
+     DONE;
+    }
   operands[2] = gen_reg_rtx (DImode);
+  if (TARGET_PPC_GFXOPT)
+    {
+      rtx orig_dest = operands[0];
+      if (! memory_operand (orig_dest, GET_MODE (orig_dest)))
+       operands[0] = assign_stack_temp (SImode, GET_MODE_SIZE (SImode), 0);
+      emit_insn (gen_fix_truncdfsi2_internal_gfxopt (operands[0], operands[1],
+                                                    operands[2]));
+      if (operands[0] != orig_dest)
+       emit_move_insn (orig_dest, operands[0]);
+      DONE;
+    }
   operands[3] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
 }")
 
-(define_insn "*fix_truncdfsi2_internal"
+(define_insn_and_split "*fix_truncdfsi2_internal"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
    (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))
    (clobber (match_operand:DI 3 "memory_operand" "=o"))]
   "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
   "#"
-  [(set_attr "length" "16")])
-
-(define_split
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
-   (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
-   (clobber (match_operand:DI 3 "offsettable_mem_operand" ""))]
-  "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
-   (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
-   (clobber (match_operand:DI 3 "offsettable_mem_operand" ""))]
+  "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[3]))"
+  [(pc)]
   "
 {
   rtx lowword;
-  if (GET_CODE (operands[3]) != MEM)
-    abort();
-  lowword = XEXP (operands[3], 0);
-  if (WORDS_BIG_ENDIAN)
-    lowword = plus_constant (lowword, 4);
+  gcc_assert (MEM_P (operands[3]));
+  lowword = adjust_address (operands[3], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
 
   emit_insn (gen_fctiwz (operands[2], operands[1]));
   emit_move_insn (operands[3], operands[2]);
-  emit_move_insn (operands[0], gen_rtx_MEM (SImode, lowword));
+  emit_move_insn (operands[0], lowword);
   DONE;
-}")
+}"
+  [(set_attr "length" "16")])
+
+(define_insn_and_split "fix_truncdfsi2_internal_gfxopt"
+  [(set (match_operand:SI 0 "memory_operand" "=Z")
+       (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
+   (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))]
+  "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
+   && TARGET_PPC_GFXOPT"
+  "#"
+  "&& 1"
+  [(pc)]
+  "
+{
+  emit_insn (gen_fctiwz (operands[2], operands[1]));
+  emit_insn (gen_stfiwx (operands[0], operands[2]));
+  DONE;
+}"
+  [(set_attr "length" "16")])
 
 ; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
 ; rather than (set (subreg:SI (reg)) (fix:SI ...))
 ; because the first makes it clear that operand 0 is not live
 ; before the instruction.
 (define_insn "fctiwz"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=*f")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
        (unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))]
                   UNSPEC_FCTIWZ))]
   "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
   "{fcirz|fctiwz} %0,%1"
   [(set_attr "type" "fp")])
 
+; An UNSPEC is used so we don't have to support SImode in FP registers.
+(define_insn "stfiwx"
+  [(set (match_operand:SI 0 "memory_operand" "=Z")
+       (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "f")]
+                  UNSPEC_STFIWX))]
+  "TARGET_PPC_GFXOPT"
+  "stfiwx %1,%y0"
+  [(set_attr "type" "fpstore")])
+
 (define_expand "floatsisf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
         (float:SF (match_operand:SI 1 "gpc_reg_operand" "")))]
 (define_expand "floatdisf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
         (float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
   "
 {
+  rtx val = operands[1];
   if (!flag_unsafe_math_optimizations)
     {
       rtx label = gen_label_rtx ();
-      emit_insn (gen_floatdisf2_internal2 (operands[1], label));
+      val = gen_reg_rtx (DImode);
+      emit_insn (gen_floatdisf2_internal2 (val, operands[1], label));
       emit_label (label);
     }
-  emit_insn (gen_floatdisf2_internal1 (operands[0], operands[1]));
+  emit_insn (gen_floatdisf2_internal1 (operands[0], val));
   DONE;
 }")
 
 ;; by a bit that won't be lost at that stage, but is below the SFmode
 ;; rounding position.
 (define_expand "floatdisf2_internal2"
-  [(parallel [(set (match_dup 4)
-                  (compare:CC (and:DI (match_operand:DI 0 "" "")
-                                      (const_int 2047))
-                              (const_int 0)))
-             (set (match_dup 2) (and:DI (match_dup 0) (const_int 2047)))
-             (clobber (match_scratch:CC 7 ""))])
-   (set (match_dup 3) (ashiftrt:DI (match_dup 0) (const_int 53)))
-   (set (match_dup 3) (plus:DI (match_dup 3) (const_int 1)))
-   (set (pc) (if_then_else (eq (match_dup 4) (const_int 0))
-                          (label_ref (match_operand:DI 1 "" ""))
-                          (pc)))
-   (set (match_dup 5) (compare:CCUNS (match_dup 3) (const_int 2)))
-   (set (pc) (if_then_else (ltu (match_dup 5) (const_int 0))
-                          (label_ref (match_dup 1))
+  [(set (match_dup 3) (ashiftrt:DI (match_operand:DI 1 "" "")
+                                  (const_int 53)))
+   (parallel [(set (match_operand:DI 0 "" "") (and:DI (match_dup 1)
+                                                     (const_int 2047)))
+             (clobber (scratch:CC))])
+   (set (match_dup 3) (plus:DI (match_dup 3)
+                              (const_int 1)))
+   (set (match_dup 0) (plus:DI (match_dup 0)
+                              (const_int 2047)))
+   (set (match_dup 4) (compare:CCUNS (match_dup 3)
+                                    (const_int 3)))
+   (set (match_dup 0) (ior:DI (match_dup 0)
+                             (match_dup 1)))
+   (parallel [(set (match_dup 0) (and:DI (match_dup 0)
+                                        (const_int -2048)))
+             (clobber (scratch:CC))])
+   (set (pc) (if_then_else (geu (match_dup 4) (const_int 0))
+                          (label_ref (match_operand:DI 2 "" ""))
                           (pc)))
-   (set (match_dup 0) (xor:DI (match_dup 0) (match_dup 2)))
-   (set (match_dup 0) (ior:DI (match_dup 0) (const_int 2048)))]
-  "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_FPRS"
+   (set (match_dup 0) (match_dup 1))]
+  "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
   "
 {
-  operands[2] = gen_reg_rtx (DImode);
   operands[3] = gen_reg_rtx (DImode);
-  operands[4] = gen_reg_rtx (CCmode);
-  operands[5] = gen_reg_rtx (CCUNSmode);
+  operands[4] = gen_reg_rtx (CCUNSmode);
 }")
 \f
 ;; Define the DImode operations that can be done in a small number
            ? \"{a|addc} %0,%1,%2\;{ae|adde} %L0,%L1,%L2\"
            : \"{ai|addic} %0,%1,%2\;{a%G2e|add%G2e} %L0,%L1\";
 }"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn "*subdi3_noppc64"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r,r")
            ? \"{sf|subfc} %0,%2,%1\;{sfe|subfe} %L0,%L2,%L1\"
            : \"{sfi|subfic} %0,%2,%1\;{sf%G1e|subf%G1e} %L0,%L2\";
 }"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn "*negdi2_noppc64"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
     ? \"{sfi|subfic} %L0,%L1,0\;{sfze|subfze} %0,%1\"
     : \"{sfi|subfic} %0,%1,0\;{sfze|subfze} %L0,%L1\";
 }"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_expand "mulsidi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
   "@
    {srai|srawi} %0,%1,31\;{srai|srawi} %L0,%1,%h2
    {sri|srwi} %L0,%L1,%h2\;insrwi %L0,%1,%h2,0\;{srai|srawi} %0,%1,%h2"
-  [(set_attr "length" "8,12")])
+  [(set_attr "type" "two,three")
+   (set_attr "length" "8,12")])
 
 (define_insn "*ashrdisi3_noppc64"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
 \f
 ;; PowerPC64 DImode operations.
 
-(define_expand "adddi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                (match_operand:DI 2 "reg_or_add_cint64_operand" "")))]
-  ""
-  "
-{
-  if (! TARGET_POWERPC64)
-    {
-      if (non_short_cint_operand (operands[2], DImode))
-       FAIL;
-    }
-  else
-    if (GET_CODE (operands[2]) == CONST_INT
-       && ! add_operand (operands[2], DImode))
-      {
-       rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
-                  ? operands[0] : gen_reg_rtx (DImode));
-
-       HOST_WIDE_INT val = INTVAL (operands[2]);
-       HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
-       HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
-
-       if (!CONST_OK_FOR_LETTER_P (rest, 'L'))
-         FAIL;
-
-       /* The ordering here is important for the prolog expander.
-          When space is allocated from the stack, adding 'low' first may
-          produce a temporary deallocation (which would be bad).  */
-       emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (rest)));
-       emit_insn (gen_adddi3 (operands[0], tmp, GEN_INT (low)));
-       DONE;
-      }
-}")
+(define_insn_and_split "absdi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
+        (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
+   (clobber (match_scratch:DI 2 "=&r,&r"))]
+  "TARGET_POWERPC64"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
+   (set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
+   (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 2)))]
+  "")
 
-;; Discourage ai/addic because of carry but provide it in an alternative
-;; allowing register zero as source.
+(define_insn_and_split "*nabsdi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
+        (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
+   (clobber (match_scratch:DI 2 "=&r,&r"))]
+  "TARGET_POWERPC64"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
+   (set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
+   (set (match_dup 0) (minus:DI (match_dup 2) (match_dup 0)))]
+  "")
 
-(define_insn "*adddi3_internal1"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,?r,r")
-       (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,b,r,b")
-                (match_operand:DI 2 "add_operand" "r,I,I,L")))]
+(define_insn "muldi3"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
+                (match_operand:DI 2 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC64"
-  "@
-   add %0,%1,%2
-   addi %0,%1,%2
-   addic %0,%1,%2
-   addis %0,%1,%v2")
+  "mulld %0,%1,%2"
+   [(set_attr "type" "lmul")])
 
-(define_insn "*adddi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r")
-                            (match_operand:DI 2 "reg_or_short_operand" "r,I,r,I"))
+(define_insn "*muldi3_internal1"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
+                            (match_operand:DI 2 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:DI 3 "=r,r"))]
+  "TARGET_POWERPC64"
   "@
-   add. %3,%1,%2
-   addic. %3,%1,%2
-   #
+   mulld. %3,%1,%2
    #"
-  [(set_attr "type" "fast_compare,compare,compare,compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "lmul_compare")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                            (match_operand:DI 2 "reg_or_short_operand" ""))
+       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                            (match_operand:DI 2 "gpc_reg_operand" ""))
                    (const_int 0)))
    (clobber (match_scratch:DI 3 ""))]
   "TARGET_POWERPC64 && reload_completed"
   [(set (match_dup 3)
-       (plus:DI (match_dup 1) (match_dup 2)))
+       (mult:DI (match_dup 1) (match_dup 2)))
    (set (match_dup 0)
        (compare:CC (match_dup 3)
                    (const_int 0)))]
   "")
 
-(define_insn "*adddi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r")
-                            (match_operand:DI 2 "reg_or_short_operand" "r,I,r,I"))
+(define_insn "*muldi3_internal2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
+                            (match_operand:DI 2 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
-       (plus:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (mult:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_POWERPC64"
   "@
-   add. %0,%1,%2
-   addic. %0,%1,%2
-   #
+   mulld. %0,%1,%2
    #"
-  [(set_attr "type" "fast_compare,compare,compare,compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "lmul_compare")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                            (match_operand:DI 2 "reg_or_short_operand" ""))
+       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                            (match_operand:DI 2 "gpc_reg_operand" ""))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (plus:DI (match_dup 1) (match_dup 2)))]
+       (mult:DI (match_dup 1) (match_dup 2)))]
   "TARGET_POWERPC64 && reload_completed"
   [(set (match_dup 0)
-       (plus:DI (match_dup 1) (match_dup 2)))
+       (mult:DI (match_dup 1) (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-;; Split an add that we can't do in one insn into two insns, each of which
-;; does one 16-bit part.  This is used by combine.  Note that the low-order
-;; add should be last in case the result gets used in an address.
-
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                (match_operand:DI 2 "non_add_cint_operand" "")))]
+(define_insn "smuldi3_highpart"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (truncate:DI
+        (lshiftrt:TI (mult:TI (sign_extend:TI
+                               (match_operand:DI 1 "gpc_reg_operand" "%r"))
+                              (sign_extend:TI
+                               (match_operand:DI 2 "gpc_reg_operand" "r")))
+                     (const_int 64))))]
   "TARGET_POWERPC64"
-  [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 3)))
-   (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
-"
-{
-  HOST_WIDE_INT val = INTVAL (operands[2]);
-  HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
-  HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
+  "mulhd %0,%1,%2"
+  [(set_attr "type" "lmul")])
 
-  operands[4] = GEN_INT (low);
-  if (CONST_OK_FOR_LETTER_P (rest, 'L'))
-    operands[3] = GEN_INT (rest);
-  else if (! no_new_pseudos)
-    {
-      operands[3] = gen_reg_rtx (DImode);
-      emit_move_insn (operands[3], operands[2]);
-      emit_insn (gen_adddi3 (operands[0], operands[1], operands[3]));
-      DONE;
-    }
-  else
-    FAIL;
-}")
+(define_insn "umuldi3_highpart"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (truncate:DI
+        (lshiftrt:TI (mult:TI (zero_extend:TI
+                               (match_operand:DI 1 "gpc_reg_operand" "%r"))
+                              (zero_extend:TI
+                               (match_operand:DI 2 "gpc_reg_operand" "r")))
+                     (const_int 64))))]
+  "TARGET_POWERPC64"
+  "mulhdu %0,%1,%2"
+  [(set_attr "type" "lmul")])
 
-(define_insn "one_cmpldi2"
+(define_insn "rotldi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (not:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
+       (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                  (match_operand:DI 2 "reg_or_cint_operand" "ri")))]
   "TARGET_POWERPC64"
-  "nor %0,%1,%1")
+  "rld%I2cl %0,%1,%H2,0")
 
-(define_insn ""
+(define_insn "*rotldi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                              (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 2 "=r,r"))]
+   (clobber (match_scratch:DI 3 "=r,r"))]
   "TARGET_64BIT"
   "@
-   nor. %2,%1,%1
+   rld%I2cl. %3,%1,%H2,0
    #"
-  [(set_attr "type" "compare")
+  [(set_attr "type" "delayed_compare")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" ""))
+       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                              (match_operand:DI 2 "reg_or_cint_operand" ""))
                    (const_int 0)))
-   (clobber (match_scratch:DI 2 ""))]
+   (clobber (match_scratch:DI 3 ""))]
   "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2)
-       (not:DI (match_dup 1)))
+  [(set (match_dup 3)
+       (rotate:DI (match_dup 1) (match_dup 2)))
    (set (match_dup 0)
-       (compare:CC (match_dup 2)
+       (compare:CC (match_dup 3)
                    (const_int 0)))]
   "")
 
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
+(define_insn "*rotldi3_internal3"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                              (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (not:DI (match_dup 1)))]
+       (rotate:DI (match_dup 1) (match_dup 2)))]
   "TARGET_64BIT"
   "@
-   nor. %0,%1,%1
+   rld%I2cl. %0,%1,%H2,0
    #"
-  [(set_attr "type" "compare")
+  [(set_attr "type" "delayed_compare")
    (set_attr "length" "4,8")])
 
 (define_split
-  [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (not:DI (match_dup 1)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (not:DI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (minus:DI (match_operand:DI 1 "reg_or_short_operand" "r,I")
-                 (match_operand:DI 2 "gpc_reg_operand" "r,r")))]
-  "TARGET_POWERPC64"
-  "@
-   subf %0,%2,%1
-   subfic %0,%2,%1")
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                             (match_operand:DI 2 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
-  "TARGET_64BIT"
-  "@
-   subf. %3,%2,%1
-   #"
-  [(set_attr "type" "fast_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                             (match_operand:DI 2 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (minus:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                             (match_operand:DI 2 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (minus:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   subf. %0,%2,%1
-   #"
-  [(set_attr "type" "fast_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                             (match_operand:DI 2 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (minus:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (minus:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_expand "subdi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (minus:DI (match_operand:DI 1 "reg_or_short_operand" "")
-                 (match_operand:DI 2 "reg_or_sub_cint64_operand" "")))]
-  ""
-  "
-{
-  if (GET_CODE (operands[2]) == CONST_INT)
-    {
-      emit_insn (gen_adddi3 (operands[0], operands[1],
-                            negate_rtx (DImode, operands[2])));
-      DONE;
-    }
-}")
-
-(define_insn_and_split "absdi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
-        (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
-   (clobber (match_scratch:DI 2 "=&r,&r"))]
-  "TARGET_POWERPC64"
-  "#"
-  "&& reload_completed"
-  [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
-   (set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
-   (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 2)))]
-  "")
-
-(define_insn_and_split "*nabsdi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
-        (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
-   (clobber (match_scratch:DI 2 "=&r,&r"))]
-  "TARGET_POWERPC64"
-  "#"
-  "&& reload_completed"
-  [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
-   (set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
-   (set (match_dup 0) (minus:DI (match_dup 2) (match_dup 0)))]
-  "")
-
-(define_expand "negdi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (neg:DI (match_operand:DI 1 "gpc_reg_operand" "")))]
-  ""
-  "")
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
-  "TARGET_POWERPC64"
-  "neg %0,%1")
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 "=r,r"))]
-  "TARGET_64BIT"
-  "@
-   neg. %2,%1
-   #"
-  [(set_attr "type" "fast_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2)
-       (neg:DI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (neg:DI (match_dup 1)))]
-  "TARGET_64BIT"
-  "@
-   neg. %0,%1
-   #"
-  [(set_attr "type" "fast_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (neg:DI (match_dup 1)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (neg:DI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn "clzdi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (clz:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
-  "TARGET_POWERPC64"
-  "cntlzd %0,%1")
-
-(define_expand "ctzdi2"
-  [(set (match_dup 2)
-       (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
-   (parallel [(set (match_dup 3) (and:DI (match_dup 1)
-                                        (match_dup 2)))
-             (clobber (scratch:CC))])
-   (set (match_dup 4) (clz:DI (match_dup 3)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (minus:DI (const_int 63) (match_dup 4)))]
-  "TARGET_POWERPC64"
-  {
-     operands[2] = gen_reg_rtx (DImode);
-     operands[3] = gen_reg_rtx (DImode);
-     operands[4] = gen_reg_rtx (DImode);
-  })
-
-(define_expand "ffsdi2"
-  [(set (match_dup 2)
-       (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
-   (parallel [(set (match_dup 3) (and:DI (match_dup 1)
-                                        (match_dup 2)))
-             (clobber (scratch:CC))])
-   (set (match_dup 4) (clz:DI (match_dup 3)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (minus:DI (const_int 64) (match_dup 4)))]
-  "TARGET_POWERPC64"
-  {
-     operands[2] = gen_reg_rtx (DImode);
-     operands[3] = gen_reg_rtx (DImode);
-     operands[4] = gen_reg_rtx (DImode);
-  })
-
-(define_insn "muldi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
-                (match_operand:DI 2 "gpc_reg_operand" "r")))]
-  "TARGET_POWERPC64"
-  "mulld %0,%1,%2"
-   [(set_attr "type" "lmul")])
-
-(define_insn "*muldi3_internal1"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
-                            (match_operand:DI 2 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
-  "TARGET_POWERPC64"
-  "@
-   mulld. %3,%1,%2
-   #"
-  [(set_attr "type" "lmul_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                            (match_operand:DI 2 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (mult:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*muldi3_internal2"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
-                            (match_operand:DI 2 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (mult:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64"
-  "@
-   mulld. %0,%1,%2
-   #"
-  [(set_attr "type" "lmul_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                            (match_operand:DI 2 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (mult:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (mult:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn "smuldi3_highpart"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (truncate:DI
-        (lshiftrt:TI (mult:TI (sign_extend:TI
-                               (match_operand:DI 1 "gpc_reg_operand" "%r"))
-                              (sign_extend:TI
-                               (match_operand:DI 2 "gpc_reg_operand" "r")))
-                     (const_int 64))))]
-  "TARGET_POWERPC64"
-  "mulhd %0,%1,%2"
-  [(set_attr "type" "lmul")])
-
-(define_insn "umuldi3_highpart"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (truncate:DI
-        (lshiftrt:TI (mult:TI (zero_extend:TI
-                               (match_operand:DI 1 "gpc_reg_operand" "%r"))
-                              (zero_extend:TI
-                               (match_operand:DI 2 "gpc_reg_operand" "r")))
-                     (const_int 64))))]
-  "TARGET_POWERPC64"
-  "mulhdu %0,%1,%2"
-  [(set_attr "type" "lmul")])
-
-(define_expand "divdi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "reg_or_cint_operand" "")))]
-  "TARGET_POWERPC64"
-  "
-{
-  if (GET_CODE (operands[2]) == CONST_INT
-      && INTVAL (operands[2]) > 0
-      && exact_log2 (INTVAL (operands[2])) >= 0)
-    ;
-  else
-    operands[2] = force_reg (DImode, operands[2]);
-}")
-
-(define_expand "moddi3"
-  [(use (match_operand:DI 0 "gpc_reg_operand" ""))
-   (use (match_operand:DI 1 "gpc_reg_operand" ""))
-   (use (match_operand:DI 2 "reg_or_cint_operand" ""))]
-  "TARGET_POWERPC64"
-  "
-{
-  int i;
-  rtx temp1;
-  rtx temp2;
-
-  if (GET_CODE (operands[2]) != CONST_INT
-      || INTVAL (operands[2]) <= 0
-      || (i = exact_log2 (INTVAL (operands[2]))) < 0)
-    FAIL;
-
-  temp1 = gen_reg_rtx (DImode);
-  temp2 = gen_reg_rtx (DImode);
-
-  emit_insn (gen_divdi3 (temp1, operands[1], operands[2]));
-  emit_insn (gen_ashldi3 (temp2, temp1, GEN_INT (i)));
-  emit_insn (gen_subdi3 (operands[0], operands[1], temp2));
-  DONE;
-}")
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-               (match_operand:DI 2 "exact_log2_cint_operand" "N")))]
-  "TARGET_POWERPC64"
-  "sradi %0,%1,%p2\;addze %0,%0"
-  [(set_attr "length" "8")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:DI 2 "exact_log2_cint_operand" "N,N"))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
-  "TARGET_64BIT"
-  "@
-   sradi %3,%1,%p2\;addze. %3,%3
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:DI 2 "exact_log2_cint_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (div:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:DI 2 "exact_log2_cint_operand" "N,N"))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (div:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   sradi %0,%1,%p2\;addze. %0,%0
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:DI 2 "exact_log2_cint_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (div:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (div:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-        (div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                (match_operand:DI 2 "gpc_reg_operand" "r")))]
-  "TARGET_POWERPC64"
-  "divd %0,%1,%2"
-  [(set_attr "type" "ldiv")])
-
-(define_insn "udivdi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-        (udiv:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                 (match_operand:DI 2 "gpc_reg_operand" "r")))]
-  "TARGET_POWERPC64"
-  "divdu %0,%1,%2"
-  [(set_attr "type" "ldiv")])
-
-(define_insn "rotldi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                  (match_operand:DI 2 "reg_or_cint_operand" "ri")))]
-  "TARGET_POWERPC64"
-  "rld%I2cl %0,%1,%H2,0")
-
-(define_insn "*rotldi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
-  "TARGET_64BIT"
-  "@
-   rld%I2cl. %3,%1,%H2,0
-   #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                              (match_operand:DI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (rotate:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*rotldi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (rotate:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   rld%I2cl. %0,%1,%H2,0
-   #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                              (match_operand:DI 2 "reg_or_cint_operand" ""))
+  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
+       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                              (match_operand:DI 2 "reg_or_cint_operand" ""))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
        (rotate:DI (match_dup 1) (match_dup 2)))]
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
                           (match_operand:DI 2 "reg_or_cint_operand" "ri"))
-               (match_operand:DI 3 "mask64_operand" "n")))]
+               (match_operand:DI 3 "mask_operand" "n")))]
   "TARGET_POWERPC64"
   "rld%I2c%B3 %0,%1,%H2,%S3")
 
        (compare:CC (and:DI
                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
                                (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
-                    (match_operand:DI 3 "mask64_operand" "n,n"))
+                    (match_operand:DI 3 "mask_operand" "n,n"))
                    (const_int 0)))
    (clobber (match_scratch:DI 4 "=r,r"))]
   "TARGET_64BIT"
        (compare:CC (and:DI
                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
                                (match_operand:DI 2 "reg_or_cint_operand" ""))
-                    (match_operand:DI 3 "mask64_operand" ""))
+                    (match_operand:DI 3 "mask_operand" ""))
                    (const_int 0)))
    (clobber (match_scratch:DI 4 ""))]
   "TARGET_POWERPC64 && reload_completed"
        (compare:CC (and:DI
                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
                                (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
-                    (match_operand:DI 3 "mask64_operand" "n,n"))
+                    (match_operand:DI 3 "mask_operand" "n,n"))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
        (compare:CC (and:DI
                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
                                (match_operand:DI 2 "reg_or_cint_operand" ""))
-                    (match_operand:DI 3 "mask64_operand" ""))
+                    (match_operand:DI 3 "mask_operand" ""))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
        (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
        (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
                   (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
   "TARGET_POWERPC64"
-  "sld%I2 %0,%1,%H2"
-  [(set_attr "length" "8")])
+  "sld%I2 %0,%1,%H2")
 
 (define_insn "*ashldi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
                           (match_operand:SI 2 "const_int_operand" "i"))
-               (match_operand:DI 3 "mask64_operand" "n")))]
+               (match_operand:DI 3 "mask_operand" "n")))]
   "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
   "rldicr %0,%1,%H2,%S3")
 
        (compare:CC
         (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
                            (match_operand:SI 2 "const_int_operand" "i,i"))
-                (match_operand:DI 3 "mask64_operand" "n,n"))
+                (match_operand:DI 3 "mask_operand" "n,n"))
         (const_int 0)))
    (clobber (match_scratch:DI 4 "=r,r"))]
   "TARGET_64BIT && includes_rldicr_lshift_p (operands[2], operands[3])"
        (compare:CC
         (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
                            (match_operand:SI 2 "const_int_operand" ""))
-                (match_operand:DI 3 "mask64_operand" ""))
+                (match_operand:DI 3 "mask_operand" ""))
         (const_int 0)))
    (clobber (match_scratch:DI 4 ""))]
   "TARGET_POWERPC64 && reload_completed
        (compare:CC
         (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
                            (match_operand:SI 2 "const_int_operand" "i,i"))
-                   (match_operand:DI 3 "mask64_operand" "n,n"))
+                   (match_operand:DI 3 "mask_operand" "n,n"))
         (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
        (compare:CC
         (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
                            (match_operand:SI 2 "const_int_operand" ""))
-                (match_operand:DI 3 "mask64_operand" ""))
+                (match_operand:DI 3 "mask_operand" ""))
         (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
        (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
   "")
 
 (define_insn "anddi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
-       (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
-               (match_operand:DI 2 "and64_2_operand" "?r,S,K,J,t")))
-   (clobber (match_scratch:CC 3 "=X,X,x,x,X"))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r")
+       (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r")
+               (match_operand:DI 2 "and64_2_operand" "?r,S,T,K,J,t")))
+   (clobber (match_scratch:CC 3 "=X,X,X,x,x,X"))]
   "TARGET_POWERPC64"
   "@
    and %0,%1,%2
    rldic%B2 %0,%1,0,%S2
+   rlwinm %0,%1,0,%m2,%M2
    andi. %0,%1,%b2
    andis. %0,%1,%u2
    #"
-  [(set_attr "length" "4,4,4,4,8")])
+  [(set_attr "type" "*,*,*,compare,compare,*")
+   (set_attr "length" "4,4,4,4,4,8")])
 
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
    (clobber (match_scratch:CC 3 ""))]
   "TARGET_POWERPC64
     && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
-    && !mask64_operand (operands[2], DImode)"
+    && !mask_operand (operands[2], DImode)"
   [(set (match_dup 0)
        (and:DI (rotate:DI (match_dup 1)
                           (match_dup 4))
        (and:DI (rotate:DI (match_dup 0)
                           (match_dup 6))
                (match_dup 7)))]
-  "
 {
   build_mask64_2_operands (operands[2], &operands[4]);
-}")
+})
 
 (define_insn "*anddi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
    (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
 
 (define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-        (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                            (match_operand:DI 2 "and64_operand" ""))
-                    (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))
-   (clobber (match_scratch:CC 4 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(parallel [(set (match_dup 3)
-                   (and:DI (match_dup 1)
-                           (match_dup 2)))
-              (clobber (match_dup 4))])
-   (set (match_dup 0)
-        (compare:CC (match_dup 3)
-                    (const_int 0)))]
-  "")
-
-(define_split
   [(set (match_operand:CC 0 "cc_reg_operand" "")
         (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
                             (match_operand:DI 2 "mask64_2_operand" ""))
    (clobber (match_scratch:CC 4 ""))]
   "TARGET_POWERPC64 && reload_completed
     && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
-    && !mask64_operand (operands[2], DImode)"
+    && !mask_operand (operands[2], DImode)"
   [(set (match_dup 3)
        (and:DI (rotate:DI (match_dup 1)
                           (match_dup 5))
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
        (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:DI 2 "and64_operand" ""))
+                           (match_operand:DI 2 "and_operand" ""))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
        (and:DI (match_dup 1) (match_dup 2)))
    (clobber (match_scratch:CC 4 ""))]
   "TARGET_POWERPC64 && reload_completed
     && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
-    && !mask64_operand (operands[2], DImode)"
+    && !mask_operand (operands[2], DImode)"
   [(set (match_dup 0)
        (and:DI (rotate:DI (match_dup 1)
                           (match_dup 5))
 \f
 ;; Now define ways of moving data around.
 
-;; Elf specific ways of loading addresses for non-PIC code.
-;; The output of this could be r0, but we make a very strong
-;; preference for a base register because it will usually
-;; be needed there.
-(define_insn "elf_high"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
-       (high:SI (match_operand 1 "" "")))]
-  "TARGET_ELF && ! TARGET_64BIT"
-  "{liu|lis} %0,%1@ha")
-
-(define_insn "elf_low"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
-                  (match_operand 2 "" "")))]
-   "TARGET_ELF && ! TARGET_64BIT"
-   "@
-    {cal|la} %0,%2@l(%1)
-    {ai|addic} %0,%1,%K2")
-
-;; Mach-O PIC trickery.
-(define_insn "macho_high"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
-       (high:SI (match_operand 1 "" "")))]
-  "TARGET_MACHO && ! TARGET_64BIT"
-  "{liu|lis} %0,ha16(%1)")
-
-(define_insn "macho_low"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
-                  (match_operand 2 "" "")))]
-   "TARGET_MACHO && ! TARGET_64BIT"
-   "@
-    {cal %0,%a2@l(%1)|la %0,lo16(%2)(%1)}
-    {cal %0,%a2@l(%1)|addic %0,%1,lo16(%2)}")
-
 ;; Set up a register with a value from the GOT table
 
 (define_expand "movsi_got"
 ;; do the load 16-bits at a time.  We could do this by loading from memory,
 ;; and this is even supposed to be faster, but it is simpler not to get
 ;; integers in the TOC.
-(define_expand "movsi"
-  [(set (match_operand:SI 0 "general_operand" "")
-       (match_operand:SI 1 "any_operand" ""))]
-  ""
-  "{ rs6000_emit_move (operands[0], operands[1], SImode); DONE; }")
-
 (define_insn "movsi_low"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
         (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
-(define_insn "movsi_low_st"
-  [(set (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
-                           (match_operand 2 "" "")))
-       (match_operand:SI 0 "gpc_reg_operand" "r"))]
-  "TARGET_MACHO && ! TARGET_64BIT"
-  "{st|stw} %0,lo16(%2)(%1)"
-  [(set_attr "type" "store")
-   (set_attr "length" "4")])
-
-(define_insn "movdf_low"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=f,!r")
-        (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
-                           (match_operand 2 "" ""))))]
-  "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
-  "*
-{
-  switch (which_alternative)
-    {
-      case 0:
-       return \"lfd %0,lo16(%2)(%1)\";
-      case 1:
-       {
-         rtx operands2[4];
-         operands2[0] = operands[0];
-         operands2[1] = operands[1];
-         operands2[2] = operands[2];
-         if (TARGET_POWERPC64 && TARGET_32BIT)
-           /* Note, old assemblers didn't support relocation here.  */
-           return \"ld %0,lo16(%2)(%1)\";
-         else
-         {
-           operands2[3] = gen_rtx_REG (SImode, RS6000_PIC_OFFSET_TABLE_REGNUM);
-           output_asm_insn (\"{l|lwz} %0,lo16(%2)(%1)\", operands);
-#if TARGET_MACHO
-           if (MACHO_DYNAMIC_NO_PIC_P)
-             output_asm_insn (\"{liu|lis} %L0,ha16(%2+4)\", operands);
-           else
-           /* We cannot rely on ha16(low half)==ha16(high half), alas,
-              although in practice it almost always is.  */
-           output_asm_insn (\"{cau|addis} %L0,%3,ha16(%2+4)\", operands2);
-#endif
-           return (\"{l|lwz} %L0,lo16(%2+4)(%L0)\");
-         }
-       }
-      default:
-       abort();
-    }
-}"
-  [(set_attr "type" "load")
-   (set_attr "length" "4,12")])
-
-(define_insn "movdf_low_st"
-  [(set (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
-                           (match_operand 2 "" "")))
-       (match_operand:DF 0 "gpc_reg_operand" "f"))]
-  "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
-  "stfd %0,lo16(%2)(%1)"
-  [(set_attr "type" "store")
-   (set_attr "length" "4")])
-
-(define_insn "movsf_low"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "=f,!r")
-        (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
-                           (match_operand 2 "" ""))))]
-  "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
-  "@
-   lfs %0,lo16(%2)(%1)
-   {l|lwz} %0,lo16(%2)(%1)"
-  [(set_attr "type" "load")
-   (set_attr "length" "4")])
-
-(define_insn "movsf_low_st"
-  [(set (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
-                           (match_operand 2 "" "")))
-       (match_operand:SF 0 "gpc_reg_operand" "f,!r"))]
-  "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
-  "@
-   stfs %0,lo16(%2)(%1)
-   {st|stw} %0,lo16(%2)(%1)"
-  [(set_attr "type" "store")
-   (set_attr "length" "4")])
-
 (define_insn "*movsi_internal1"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
+  [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
        (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0"))]
   "gpc_reg_operand (operands[0], SImode)
    || gpc_reg_operand (operands[1], SImode)"
     FAIL;
 }")
 
-(define_insn "*movsi_internal2"
+(define_insn "*mov<mode>_internal2"
   [(set (match_operand:CC 2 "cc_reg_operand" "=y,x,?y")
-       (compare:CC (match_operand:SI 1 "gpc_reg_operand" "0,r,r")
+       (compare:CC (match_operand:P 1 "gpc_reg_operand" "0,r,r")
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r") (match_dup 1))]
-  "TARGET_32BIT"
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r") (match_dup 1))]
+  ""
   "@
-   {cmpi|cmpwi} %2,%0,0
+   {cmpi|cmp<wd>i} %2,%0,0
    mr. %0,%1
    #"
   [(set_attr "type" "cmp,compare,cmp")
 
 (define_split
   [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC (match_operand:SI 1 "gpc_reg_operand" "")
+       (compare:CC (match_operand:P 1 "gpc_reg_operand" "")
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "") (match_dup 1))]
-  "TARGET_32BIT && reload_completed"
+   (set (match_operand:P 0 "gpc_reg_operand" "") (match_dup 1))]
+  "reload_completed"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 \f
-(define_expand "movhi"
-  [(set (match_operand:HI 0 "general_operand" "")
-       (match_operand:HI 1 "any_operand" ""))]
-  ""
-  "{ rs6000_emit_move (operands[0], operands[1], HImode); DONE; }")
-
 (define_insn "*movhi_internal"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
        (match_operand:HI 1 "input_operand" "r,m,r,i,*h,r,r,0"))]
    {cror 0,0,0|nop}"
   [(set_attr "type" "*,load,store,*,mfjmpr,*,mtjmpr,*")])
 
-(define_expand "movqi"
-  [(set (match_operand:QI 0 "general_operand" "")
-       (match_operand:QI 1 "any_operand" ""))]
+(define_expand "mov<mode>"
+  [(set (match_operand:INT 0 "general_operand" "")
+       (match_operand:INT 1 "any_operand" ""))]
   ""
-  "{ rs6000_emit_move (operands[0], operands[1], QImode); DONE; }")
+  "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }")
 
 (define_insn "*movqi_internal"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
   switch (which_alternative)
     {
     default:
-      abort ();
+      gcc_unreachable ();
     case 0:
       /* We normally copy the low-numbered register first.  However, if
         the first register operand 0 is the same as the second register
       else
        return \"mr %0,%1\;mr %L0,%L1\";
     case 1:
-      if (offsettable_memref_p (operands[1])
-         || (GET_CODE (operands[1]) == MEM
-             && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
+      if (GET_CODE (operands[1]) == MEM
+         && (rs6000_legitimate_offset_address_p (DFmode, XEXP (operands[1], 0),
+                       reload_completed || reload_in_progress)
+             || GET_CODE (XEXP (operands[1], 0)) == REG
+             || GET_CODE (XEXP (operands[1], 0)) == LO_SUM
                  || GET_CODE (XEXP (operands[1], 0)) == PRE_INC
-                 || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)))
+             || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC))
        {
          /* If the low-address word is used in the address, we must load
             it last.  Otherwise, load it first.  Note that we cannot have
            }
        }
     case 2:
-      if (offsettable_memref_p (operands[0])
-         || (GET_CODE (operands[0]) == MEM
-             && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
+      if (GET_CODE (operands[0]) == MEM
+          && (rs6000_legitimate_offset_address_p (DFmode, XEXP (operands[0], 0),
+                   reload_completed || reload_in_progress)
+             || GET_CODE (XEXP (operands[0], 0)) == REG
+             || GET_CODE (XEXP (operands[0], 0)) == LO_SUM
                  || GET_CODE (XEXP (operands[0], 0)) == PRE_INC
-                 || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)))
+             || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))
        return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
       else
        {
       return \"#\";
     }
 }"
-  [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*")
+  [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*")
    (set_attr "length" "8,16,16,4,4,4,8,12,16")])
 
 (define_insn "*movdf_softfloat32"
   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,r,r,r")
        (match_operand:DF 1 "input_operand" "r,m,r,G,H,F"))]
-  "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
+  "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
    && (gpc_reg_operand (operands[0], DFmode)
        || gpc_reg_operand (operands[1], DFmode))"
   "*
   switch (which_alternative)
     {
     default:
-      abort ();
+      gcc_unreachable ();
     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
       return \"#\";
     }
 }"
-  [(set_attr "type" "*,load,store,*,*,*")
+  [(set_attr "type" "two,load,store,*,*,*")
    (set_attr "length" "8,8,8,8,12,16")])
 
 ; ld/std require word-aligned displacements -> 'Y' constraint.
 
 ; It's important to list the o->f and f->o moves before f->f because
 ; otherwise reload, given m->f, will try to pick f->f and reload it,
-; which doesn't make progress.
+; which doesn't make progress.  Likewise r->Y must be before r->r.
 (define_insn_and_split "*movtf_internal"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,f,rm,r")
-       (match_operand:TF 1 "input_operand"         "f,o,f,r,mGHF"))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,f,r,Y,r")
+       (match_operand:TF 1 "input_operand"         "f,o,f,YGHF,r,r"))]
   "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
    && (gpc_reg_operand (operands[0], TFmode)
   "&& reload_completed"
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
-  [(set_attr "length" "8,8,8,20,20")])
+  [(set_attr "length" "8,8,8,20,20,16")])
 
 (define_expand "extenddftf2"
   [(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "")
 (define_insn_and_split "*extenddftf2_internal"
   [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,&f,r")
        (float_extend:TF (match_operand:DF 1 "input_operand" "fr,mf,mf,rmGHF")))
-   (use (match_operand:DF 2 "input_operand" "rf,m,f,n"))]
+   (use (match_operand:DF 2 "zero_reg_mem_operand" "rf,m,f,n"))]
   "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "#"
   DONE;
 })
 
-(define_insn "trunctfdf2"
+(define_expand "trunctfdf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))]
+  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "")
+
+(define_insn_and_split "trunctfdf2_internal1"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f,?f")
+       (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,f")))]
+  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) && !TARGET_XL_COMPAT
+   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "@
+   #
+   fmr %0,%1"
+  "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])"
+  [(const_int 0)]
+{
+  emit_note (NOTE_INSN_DELETED);
+  DONE;
+}
+  [(set_attr "type" "fp")])
+
+(define_insn "trunctfdf2_internal2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "f")))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) && TARGET_XL_COMPAT
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "fadd %0,%1,%L1"
-  [(set_attr "type" "fp")
-   (set_attr "length" "4")])
+  [(set_attr "type" "fp")])
 
 (define_insn_and_split "trunctfsf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
   "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "#"
-  "&& reload_completed"
+  "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[5]))"
   [(pc)]
 {
   rtx lowword;
   emit_insn (gen_fix_trunc_helper (operands[2], operands[1], operands[3]));
 
-  if (GET_CODE (operands[5]) != MEM)
-    abort();
-  lowword = XEXP (operands[5], 0);
-  if (WORDS_BIG_ENDIAN)
-    lowword = plus_constant (lowword, 4);
+  gcc_assert (MEM_P (operands[5]));
+  lowword = adjust_address (operands[5], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
 
   emit_insn (gen_fctiwz (operands[4], operands[2]));
   emit_move_insn (operands[5], operands[4]);
-  emit_move_insn (operands[0], gen_rtx_MEM (SImode, lowword));
+  emit_move_insn (operands[0], lowword);
   DONE;
 })
 
 \f
 ;; Next come the multi-word integer load and store and the load and store
 ;; multiple insns.
-(define_expand "movdi"
-  [(set (match_operand:DI 0 "general_operand" "")
-       (match_operand:DI 1 "any_operand" ""))]
-  ""
-  "{ rs6000_emit_move (operands[0], operands[1], DImode); DONE; }")
 
+; List r->r after r->"o<>", otherwise reload will try to reload a
+; non-offsettable address by using r->r which won't make progress.
 (define_insn "*movdi_internal32"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m,r,r,r,r,r")
-       (match_operand:DI 1 "input_operand" "r,m,r,f,m,f,IJK,n,G,H,F"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,r,r,*f,*f,m,r")
+       (match_operand:DI 1 "input_operand" "r,r,m,f,m,f,IJKnGHF"))]
   "! TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], DImode)
        || gpc_reg_operand (operands[1], DImode))"
-  "*
-{
-  switch (which_alternative)
-    {
-    default:
-      abort ();
-    case 0:
-    case 1:
-    case 2:
-      return \"#\";
-    case 3:
-      return \"fmr %0,%1\";
-    case 4:
-      return \"lfd%U1%X1 %0,%1\";
-    case 5:
-      return \"stfd%U0%X0 %1,%0\";
-    case 6:
-    case 7:
-    case 8:
-    case 9:
-    case 10:
-      return \"#\";
-    }
-}"
-  [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")])
+  "@
+   #
+   #
+   #
+   fmr %0,%1
+   lfd%U1%X1 %0,%1
+   stfd%U0%X0 %1,%0
+   #"
+  [(set_attr "type" "load,*,store,fp,fpload,fpstore,*")])
 
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
 
-(define_split
-  [(set (match_operand:TI 0 "gpc_reg_operand" "")
-       (match_operand:TI 1 "const_double_operand" ""))]
-  "TARGET_POWERPC64"
-  [(set (match_dup 2) (match_dup 4))
-   (set (match_dup 3) (match_dup 5))]
-  "
-{
-  operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0,
-                                      TImode);
-  operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
-                                      TImode);
-  if (GET_CODE (operands[1]) == CONST_DOUBLE)
-    {
-      operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
-      operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-    }
-  else if (GET_CODE (operands[1]) == CONST_INT)
-    {
-      operands[4] = GEN_INT (- (INTVAL (operands[1]) < 0));
-      operands[5] = operands[1];
-    }
-  else
-    FAIL;
-}")
-
 (define_insn "*movdi_internal64"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,?f,f,m,r,*h,*h")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h")
        (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0"))]
   "TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], DImode)
 ;; Use (and:DI (rotate:DI ...)) to avoid anddi3 unnecessary clobber.
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "mask64_operand" ""))]
+       (match_operand:DI 1 "mask_operand" ""))]
   "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
   [(set (match_dup 0) (const_int -1))
    (set (match_dup 0)
   else
     FAIL;
 }")
-
-(define_insn "*movdi_internal2"
-  [(set (match_operand:CC 2 "cc_reg_operand" "=y,x,?y")
-       (compare:CC (match_operand:DI 1 "gpc_reg_operand" "0,r,r")
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r") (match_dup 1))]
-  "TARGET_64BIT"
-  "@
-   cmpdi %2,%0,0
-   mr. %0,%1
-   #"
-  [(set_attr "type" "cmp,compare,cmp")
-   (set_attr "length" "4,4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC (match_operand:DI 1 "gpc_reg_operand" "")
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "") (match_dup 1))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0) (match_dup 1))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
 \f
 ;; TImode is similar, except that we usually want to compute the address into
 ;; a register and use lsi/stsi (the exception is during reload).  MQ is also
 ;; clobbered in stsi for POWER, so we need a SCRATCH for it.
-(define_expand "movti"
-  [(parallel [(set (match_operand:TI 0 "general_operand" "")
-                  (match_operand:TI 1 "general_operand" ""))
-             (clobber (scratch:SI))])]
-  ""
-  "{ 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
 ;; 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"))]
+  [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r,r")
+       (match_operand:TI 1 "input_operand" "r,r,r,Q,m,n"))
+   (clobber (match_scratch:SI 2 "=q,q#X,X,X,X,X"))]
   "TARGET_POWER && ! TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
   "*
   switch (which_alternative)
     {
     default:
-      abort ();
+      gcc_unreachable ();
 
     case 0:
       if (TARGET_STRING)
        return \"{lsi|lswi} %0,%P1,16\";
       /* ... fall through ...  */
     case 4:
+    case 5:
       return \"#\";
     }
 }"
-  [(set_attr "type" "store,store,*,load,load")])
+  [(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"))]
+  [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,o<>,????r,????r,????r,r")
+       (match_operand:TI 1 "input_operand" "r,r,r,Q,m,n"))]
   "! TARGET_POWER && ! TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
   "*
   switch (which_alternative)
     {
     default:
-      abort ();
+      gcc_unreachable ();
     case 0:
       if (TARGET_STRING)
         return \"{stsi|stswi} %1,%P0,16\";
        return \"{lsi|lswi} %0,%P1,16\";
       /* ... fall through ...  */
     case 4:
+    case 5:
       return \"#\";
     }
 }"
-  [(set_attr "type" "store,store,*,load,load")])
+  [(set_attr "type" "store,store,*,load,load,*")])
 
 (define_insn "*movti_ppc64"
-  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,m,r")
-       (match_operand:TI 1 "input_operand" "r,r,o"))]
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o<>,r")
+       (match_operand:TI 1 "input_operand" "r,r,m"))]
   "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
    || gpc_reg_operand (operands[1], TImode))"
-  "@
-   #
-   #
-   #"
+  "#"
   [(set_attr "type" "*,load,store")])
 
 (define_split
+  [(set (match_operand:TI 0 "gpc_reg_operand" "")
+       (match_operand:TI 1 "const_double_operand" ""))]
+  "TARGET_POWERPC64"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+  "
+{
+  operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0,
+                                      TImode);
+  operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
+                                      TImode);
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    {
+      operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
+      operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+    }
+  else if (GET_CODE (operands[1]) == CONST_INT)
+    {
+      operands[4] = GEN_INT (- (INTVAL (operands[1]) < 0));
+      operands[5] = operands[1];
+    }
+  else
+    FAIL;
+}")
+
+(define_split
   [(set (match_operand:TI 0 "nonimmediate_operand" "")
         (match_operand:TI 1 "input_operand" ""))]
   "reload_completed
   "{stsi|stswi} %2,%1,%O0"
   [(set_attr "type" "store")])
 \f
+(define_expand "setmemsi"
+  [(parallel [(set (match_operand:BLK 0 "" "")
+                  (match_operand 2 "const_int_operand" ""))
+             (use (match_operand:SI 1 "" ""))
+             (use (match_operand:SI 3 "" ""))])]
+  ""
+  "
+{
+  /* If value to set is not zero, use the library routine.  */
+  if (operands[2] != const0_rtx)
+    FAIL;
+
+  if (expand_block_clear (operands))
+    DONE;
+  else
+    FAIL;
+}")
+
 ;; String/block move insn.
 ;; Argument 0 is the destination
 ;; Argument 1 is the source
 ;; Argument 2 is the length
 ;; Argument 3 is the alignment
 
-(define_expand "movstrsi"
+(define_expand "movmemsi"
   [(parallel [(set (match_operand:BLK 0 "" "")
                   (match_operand:BLK 1 "" ""))
              (use (match_operand:SI 2 "" ""))
 ;; Move up to 32 bytes at a time.  The fixed registers are needed because the
 ;; register allocator doesn't have a clue about allocating 8 word registers.
 ;; rD/rS = r5 is preferred, efficient form.
-(define_expand "movstrsi_8reg"
+(define_expand "movmemsi_8reg"
   [(parallel [(set (match_operand 0 "" "")
                   (match_operand 1 "" ""))
              (use (match_operand 2 "" ""))
    (set_attr "length" "8")])
 
 (define_insn ""
-  [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b"))
-       (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b")))
+  [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
+       (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
    (use (match_operand:SI 2 "immediate_operand" "i"))
    (use (match_operand:SI 3 "immediate_operand" "i"))
    (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
   [(set_attr "type" "load")
    (set_attr "length" "8")])
 
-(define_insn ""
-  [(set (mem:BLK (match_operand:DI 0 "gpc_reg_operand" "b"))
-       (mem:BLK (match_operand:DI 1 "gpc_reg_operand" "b")))
-   (use (match_operand:SI 2 "immediate_operand" "i"))
-   (use (match_operand:SI 3 "immediate_operand" "i"))
-   (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
-   (clobber (reg:SI  6))
-   (clobber (reg:SI  7))
-   (clobber (reg:SI  8))
-   (clobber (reg:SI  9))
-   (clobber (reg:SI 10))
-   (clobber (reg:SI 11))
-   (clobber (reg:SI 12))
-   (clobber (match_scratch:SI 5 "X"))]
-  "TARGET_STRING && TARGET_POWERPC64
-   && ((INTVAL (operands[2]) > 24 && INTVAL (operands[2]) < 32)
-       || INTVAL (operands[2]) == 0)
-   && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 12)
-   && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 12)
-   && REGNO (operands[4]) == 5"
-  "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
-  [(set_attr "type" "load")
-   (set_attr "length" "8")])
-
 ;; Move up to 24 bytes at a time.  The fixed registers are needed because the
 ;; register allocator doesn't have a clue about allocating 6 word registers.
 ;; rD/rS = r5 is preferred, efficient form.
-(define_expand "movstrsi_6reg"
+(define_expand "movmemsi_6reg"
   [(parallel [(set (match_operand 0 "" "")
                   (match_operand 1 "" ""))
              (use (match_operand 2 "" ""))
    (set_attr "length" "8")])
 
 (define_insn ""
-  [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b"))
-       (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b")))
+  [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
+       (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
    (use (match_operand:SI 2 "immediate_operand" "i"))
    (use (match_operand:SI 3 "immediate_operand" "i"))
    (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
   [(set_attr "type" "load")
    (set_attr "length" "8")])
 
-(define_insn ""
-  [(set (mem:BLK (match_operand:DI 0 "gpc_reg_operand" "b"))
-       (mem:BLK (match_operand:DI 1 "gpc_reg_operand" "b")))
-   (use (match_operand:SI 2 "immediate_operand" "i"))
-   (use (match_operand:SI 3 "immediate_operand" "i"))
-   (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
-   (clobber (reg:SI  6))
-   (clobber (reg:SI  7))
-   (clobber (reg:SI  8))
-   (clobber (reg:SI  9))
-   (clobber (reg:SI 10))
-   (clobber (match_scratch:SI 5 "X"))]
-  "TARGET_STRING && TARGET_POWERPC64
-   && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 32
-   && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 10)
-   && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 10)
-   && REGNO (operands[4]) == 5"
-  "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
-  [(set_attr "type" "load")
-   (set_attr "length" "8")])
-
 ;; Move up to 16 bytes at a time, using 4 fixed registers to avoid spill
 ;; problems with TImode.
 ;; rD/rS = r5 is preferred, efficient form.
-(define_expand "movstrsi_4reg"
+(define_expand "movmemsi_4reg"
   [(parallel [(set (match_operand 0 "" "")
                   (match_operand 1 "" ""))
              (use (match_operand 2 "" ""))
    (set_attr "length" "8")])
 
 (define_insn ""
-  [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b"))
-       (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b")))
+  [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
+       (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
    (use (match_operand:SI 2 "immediate_operand" "i"))
    (use (match_operand:SI 3 "immediate_operand" "i"))
    (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
   [(set_attr "type" "load")
    (set_attr "length" "8")])
 
-(define_insn ""
-  [(set (mem:BLK (match_operand:DI 0 "gpc_reg_operand" "b"))
-       (mem:BLK (match_operand:DI 1 "gpc_reg_operand" "b")))
-   (use (match_operand:SI 2 "immediate_operand" "i"))
-   (use (match_operand:SI 3 "immediate_operand" "i"))
-   (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
-   (clobber (reg:SI 6))
-   (clobber (reg:SI 7))
-   (clobber (reg:SI 8))
-   (clobber (match_scratch:SI 5 "X"))]
-  "TARGET_STRING && TARGET_POWERPC64
-   && INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16
-   && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 8)
-   && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 8)
-   && REGNO (operands[4]) == 5"
-  "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
-  [(set_attr "type" "load")
-   (set_attr "length" "8")])
-
 ;; Move up to 8 bytes at a time.
-(define_expand "movstrsi_2reg"
+(define_expand "movmemsi_2reg"
   [(parallel [(set (match_operand 0 "" "")
                   (match_operand 1 "" ""))
              (use (match_operand 2 "" ""))
    (set_attr "length" "8")])
 
 ;; Move up to 4 bytes at a time.
-(define_expand "movstrsi_1reg"
+(define_expand "movmemsi_1reg"
   [(parallel [(set (match_operand 0 "" "")
                   (match_operand 1 "" ""))
              (use (match_operand 2 "" ""))
    (set_attr "length" "8")])
 
 (define_insn ""
-  [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b"))
-       (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b")))
+  [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
+       (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
    (use (match_operand:SI 2 "immediate_operand" "i"))
    (use (match_operand:SI 3 "immediate_operand" "i"))
    (clobber (match_scratch:SI 4 "=&r"))
   "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
   [(set_attr "type" "load")
    (set_attr "length" "8")])
-
-(define_insn ""
-  [(set (mem:BLK (match_operand:DI 0 "gpc_reg_operand" "b"))
-       (mem:BLK (match_operand:DI 1 "gpc_reg_operand" "b")))
-   (use (match_operand:SI 2 "immediate_operand" "i"))
-   (use (match_operand:SI 3 "immediate_operand" "i"))
-   (clobber (match_scratch:SI 4 "=&r"))
-   (clobber (match_scratch:SI 5 "X"))]
-  "TARGET_STRING && TARGET_POWERPC64
-   && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 4"
-  "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
-  [(set_attr "type" "load")
-   (set_attr "length" "8")])
-
 \f
 ;; Define insns that do load or store with update.  Some of these we can
 ;; get by using pre-decrement or pre-increment, but the hardware can also
    ldu %3,%2(%0)"
   [(set_attr "type" "load_ux,load_u")])
 
-(define_insn "movdi_update"
-  [(set (mem:DI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
-                        (match_operand:DI 2 "reg_or_aligned_short_operand" "r,I")))
+(define_insn "movdi_<mode>_update"
+  [(set (mem:DI (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
+                        (match_operand:P 2 "reg_or_aligned_short_operand" "r,I")))
        (match_operand:DI 3 "gpc_reg_operand" "r,r"))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
-       (plus:DI (match_dup 1) (match_dup 2)))]
+   (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
+       (plus:P (match_dup 1) (match_dup 2)))]
   "TARGET_POWERPC64 && TARGET_UPDATE"
   "@
    stdux %3,%0,%2
 
 ;; Peephole to convert two consecutive FP loads or stores into lfq/stfq.
 
-(define_peephole
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+(define_insn "*lfq_power2"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
+       (match_operand:TF 1 "memory_operand" ""))]
+  "TARGET_POWER2
+   && TARGET_HARD_FLOAT && TARGET_FPRS"
+   "lfq%U1%X1 %0,%1")
+
+(define_peephole2
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
        (match_operand:DF 1 "memory_operand" ""))
-   (set (match_operand:DF 2 "gpc_reg_operand" "=f")
+   (set (match_operand:DF 2 "gpc_reg_operand" "")
        (match_operand:DF 3 "memory_operand" ""))]
   "TARGET_POWER2
    && TARGET_HARD_FLOAT && TARGET_FPRS
    && registers_ok_for_quad_peep (operands[0], operands[2])
-   && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
-   && addrs_ok_for_quad_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
-  "lfq%U1%X1 %0,%1")
+   && mems_ok_for_quad_peep (operands[1], operands[3])"
+  [(set (match_dup 0)
+        (match_dup 1))]
+  "operands[1] = widen_memory_access (operands[1], TFmode, 0);
+   operands[0] = gen_rtx_REG (TFmode, REGNO (operands[0]));")
 
-(define_peephole
+(define_insn "*stfq_power2"
+  [(set (match_operand:TF 0 "memory_operand" "")
+       (match_operand:TF 1 "gpc_reg_operand" "f"))]
+  "TARGET_POWER2
+   && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "stfq%U0%X0 %1,%0")
+
+
+(define_peephole2
   [(set (match_operand:DF 0 "memory_operand" "")
-       (match_operand:DF 1 "gpc_reg_operand" "f"))
+       (match_operand:DF 1 "gpc_reg_operand" ""))
    (set (match_operand:DF 2 "memory_operand" "")
-       (match_operand:DF 3 "gpc_reg_operand" "f"))]
+       (match_operand:DF 3 "gpc_reg_operand" ""))]
   "TARGET_POWER2
    && TARGET_HARD_FLOAT && TARGET_FPRS
    && registers_ok_for_quad_peep (operands[1], operands[3])
-   && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
-   && addrs_ok_for_quad_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
-  "stfq%U0%X0 %1,%0")
+   && mems_ok_for_quad_peep (operands[0], operands[2])"
+  [(set (match_dup 0)
+       (match_dup 1))]
+  "operands[0] = widen_memory_access (operands[0], TFmode, 0);
+   operands[1] = gen_rtx_REG (TFmode, REGNO (operands[1]));")
+
+;; after inserting conditional returns we can sometimes have
+;; unnecessary register moves.  Unfortunately we cannot have a
+;; modeless peephole here, because some single SImode sets have early
+;; clobber outputs.  Although those sets expand to multi-ppc-insn
+;; sequences, using get_attr_length here will smash the operands
+;; array.  Neither is there an early_cobbler_p predicate.
+(define_peephole2
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (match_operand:DF 1 "any_operand" ""))
+   (set (match_operand:DF 2 "gpc_reg_operand" "")
+       (match_dup 0))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 2) (match_dup 1))])
+
+(define_peephole2
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+       (match_operand:SF 1 "any_operand" ""))
+   (set (match_operand:SF 2 "gpc_reg_operand" "")
+       (match_dup 0))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 2) (match_dup 1))])
+
 \f
 ;; TLS support.
 
 ;; "b" output constraint here and on tls_ld to support tls linker optimization.
 (define_insn "tls_gd_32"
-  [(set (match_operand:SI 0 "register_operand" "=b")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSGD))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "addi %0,%1,%2@got@tlsgd")
 
 (define_insn "tls_gd_64"
-  [(set (match_operand:DI 0 "register_operand" "=b")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSGD))]
   "HAVE_AS_TLS && TARGET_64BIT"
   "addi %0,%1,%2@got@tlsgd")
 
 (define_insn "tls_ld_32"
-  [(set (match_operand:SI 0 "register_operand" "=b")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")]
                   UNSPEC_TLSLD))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "addi %0,%1,%&@got@tlsld")
 
 (define_insn "tls_ld_64"
-  [(set (match_operand:DI 0 "register_operand" "=b")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")]
                   UNSPEC_TLSLD))]
   "HAVE_AS_TLS && TARGET_64BIT"
   "addi %0,%1,%&@got@tlsld")
 
 (define_insn "tls_dtprel_32"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSDTPREL))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "addi %0,%1,%2@dtprel")
 
 (define_insn "tls_dtprel_64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSDTPREL))]
   "HAVE_AS_TLS && TARGET_64BIT"
   "addi %0,%1,%2@dtprel")
 
 (define_insn "tls_dtprel_ha_32"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSDTPRELHA))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "addis %0,%1,%2@dtprel@ha")
 
 (define_insn "tls_dtprel_ha_64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSDTPRELHA))]
   "HAVE_AS_TLS && TARGET_64BIT"
   "addis %0,%1,%2@dtprel@ha")
 
 (define_insn "tls_dtprel_lo_32"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSDTPRELLO))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "addi %0,%1,%2@dtprel@l")
 
 (define_insn "tls_dtprel_lo_64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSDTPRELLO))]
   "HAVE_AS_TLS && TARGET_64BIT"
   "addi %0,%1,%2@dtprel@l")
 
 (define_insn "tls_got_dtprel_32"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSGOTDTPREL))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "lwz %0,%2@got@dtprel(%1)")
 
 (define_insn "tls_got_dtprel_64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSGOTDTPREL))]
   "HAVE_AS_TLS && TARGET_64BIT"
   "ld %0,%2@got@dtprel(%1)")
 
 (define_insn "tls_tprel_32"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSTPREL))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "addi %0,%1,%2@tprel")
 
 (define_insn "tls_tprel_64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSTPREL))]
   "HAVE_AS_TLS && TARGET_64BIT"
   "addi %0,%1,%2@tprel")
 
 (define_insn "tls_tprel_ha_32"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSTPRELHA))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "addis %0,%1,%2@tprel@ha")
 
 (define_insn "tls_tprel_ha_64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSTPRELHA))]
   "HAVE_AS_TLS && TARGET_64BIT"
   "addis %0,%1,%2@tprel@ha")
 
 (define_insn "tls_tprel_lo_32"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSTPRELLO))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "addi %0,%1,%2@tprel@l")
 
 (define_insn "tls_tprel_lo_64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSTPRELLO))]
   "HAVE_AS_TLS && TARGET_64BIT"
 ;; optimization.  The linker may edit the instructions emitted by a
 ;; tls_got_tprel/tls_tls pair to addis,addi.
 (define_insn "tls_got_tprel_32"
-  [(set (match_operand:SI 0 "register_operand" "=b")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSGOTTPREL))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "lwz %0,%2@got@tprel(%1)")
 
 (define_insn "tls_got_tprel_64"
-  [(set (match_operand:DI 0 "register_operand" "=b")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSGOTTPREL))]
   "HAVE_AS_TLS && TARGET_64BIT"
   "ld %0,%2@got@tprel(%1)")
 
 (define_insn "tls_tls_32"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
                    (match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSTLS))]
   "HAVE_AS_TLS && !TARGET_64BIT"
   "add %0,%1,%2@tls")
 
 (define_insn "tls_tls_64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
                    (match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
                   UNSPEC_TLSTLS))]
   "HAVE_AS_TLS && TARGET_64BIT"
     neg_op0 = GEN_INT (- INTVAL (operands[1]));
 
   if (TARGET_UPDATE)
-    emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update : gen_movdi_update))
+    emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update : gen_movdi_di_update))
                (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
 
   else
   [(set (match_operand:SI 0 "register_operand" "=l")
        (match_operand:SI 1 "immediate_operand" "s"))
    (use (unspec [(match_dup 1)] UNSPEC_TOC))]
-  "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+  "TARGET_ELF && DEFAULT_ABI != ABI_AIX
+   && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
   "bcl 20,31,%1\\n%1:"
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
 
 (define_insn "load_toc_v4_PIC_1b"
   [(set (match_operand:SI 0 "register_operand" "=l")
-       (match_operand:SI 1 "immediate_operand" "s"))
-   (use (unspec [(match_dup 1) (match_operand 2 "immediate_operand" "s")]
+       (unspec:SI [(match_operand:SI 1 "immediate_operand" "s")]
                UNSPEC_TOCPTR))]
   "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
-  "bcl 20,31,%1+4\\n%1:\\n\\t.long %2-%1"
+  "bcl 20,31,$+8\\n\\t.long %1-$"
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
 
   "{l|lwz} %0,%2-%3(%1)"
   [(set_attr "type" "load")])
 
-(define_insn "load_macho_picbase"
-  [(set (match_operand:SI 0 "register_operand" "=l")
-       (unspec:SI [(match_operand:SI 1 "immediate_operand" "s")]
-                  UNSPEC_LD_MPIC))]
-  "(DEFAULT_ABI == ABI_DARWIN) && flag_pic"
-  "bcl 20,31,%1\\n%1:"
-  [(set_attr "type" "branch")
-   (set_attr "length" "4")])
+(define_insn "load_toc_v4_PIC_3b"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+       (plus:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                (high:SI
+                  (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+                            (match_operand:SI 3 "symbol_ref_operand" "s")))))]
+  "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+  "{cau|addis} %0,%1,%2-%3@ha")
 
-(define_insn "macho_correct_pic"
+(define_insn "load_toc_v4_PIC_3c"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (plus:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                (unspec:SI [(match_operand:SI 2 "immediate_operand" "s")
-                            (match_operand:SI 3 "immediate_operand" "s")]
-                           UNSPEC_MPIC_CORRECT)))]
-  "DEFAULT_ABI == ABI_DARWIN"
-  "addis %0,%1,ha16(%2-%3)\n\taddi %0,%0,lo16(%2-%3)"
-  [(set_attr "length" "8")])
+       (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+                  (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+                            (match_operand:SI 3 "symbol_ref_operand" "s"))))]
+  "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+  "{cal|addi} %0,%1,%2-%3@l")
 
 ;; If the TOC is shared over a translation unit, as happens with all
 ;; the kinds of PIC that we support, we need to restore the TOC
     rs6000_emit_load_toc_table (FALSE);
   DONE;
 }")
+
+;; Elf specific ways of loading addresses for non-PIC code.
+;; The output of this could be r0, but we make a very strong
+;; preference for a base register because it will usually
+;; be needed there.
+(define_insn "elf_high"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
+       (high:SI (match_operand 1 "" "")))]
+  "TARGET_ELF && ! TARGET_64BIT"
+  "{liu|lis} %0,%1@ha")
+
+(define_insn "elf_low"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+       (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
+                  (match_operand 2 "" "")))]
+   "TARGET_ELF && ! TARGET_64BIT"
+   "@
+    {cal|la} %0,%2@l(%1)
+    {ai|addic} %0,%1,%K2")
 \f
 ;; A function pointer under AIX is a pointer to a data area whose first word
 ;; contains the actual address of the function, whose second word contains a
     operands[0] = machopic_indirect_call_target (operands[0]);
 #endif
 
-  if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
-    abort ();
+  gcc_assert (GET_CODE (operands[0]) == MEM);
+  gcc_assert (GET_CODE (operands[1]) == CONST_INT);
 
   operands[0] = XEXP (operands[0], 0);
 
+  if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
+      && flag_pic
+      && GET_CODE (operands[0]) == SYMBOL_REF
+      && !SYMBOL_REF_LOCAL_P (operands[0]))
+    {
+      rtx call;
+      rtvec tmp;
+
+      tmp = gen_rtvec (3,
+                      gen_rtx_CALL (VOIDmode,
+                                    gen_rtx_MEM (SImode, operands[0]),
+                                    operands[1]),
+                      gen_rtx_USE (VOIDmode, operands[2]),
+                      gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+      call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+      use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+      DONE;
+    }
+
   if (GET_CODE (operands[0]) != SYMBOL_REF
       || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0]))
       || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
       if (INTVAL (operands[2]) & CALL_LONG)
        operands[0] = rs6000_longcall_ref (operands[0]);
 
-      if (DEFAULT_ABI == ABI_V4
-         || DEFAULT_ABI == ABI_DARWIN)
-       operands[0] = force_reg (Pmode, operands[0]);
+      switch (DEFAULT_ABI)
+        {
+       case ABI_V4:
+       case ABI_DARWIN:
+         operands[0] = force_reg (Pmode, operands[0]);
+         break;
 
-      else if (DEFAULT_ABI == ABI_AIX)
-       {
+       case ABI_AIX:
          /* AIX function pointers are really pointers to a three word
             area.  */
          emit_call_insn (TARGET_32BIT
                                                                operands[0]),
                                                     operands[1]));
          DONE;
+
+       default:
+         gcc_unreachable ();
        }
-      else
-       abort ();
     }
 }")
 
     operands[1] = machopic_indirect_call_target (operands[1]);
 #endif
 
-  if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
-    abort ();
+  gcc_assert (GET_CODE (operands[1]) == MEM);
+  gcc_assert (GET_CODE (operands[2]) == CONST_INT);
 
   operands[1] = XEXP (operands[1], 0);
 
+  if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
+      && flag_pic
+      && GET_CODE (operands[1]) == SYMBOL_REF
+      && !SYMBOL_REF_LOCAL_P (operands[1]))
+    {
+      rtx call;
+      rtvec tmp;
+
+      tmp = gen_rtvec (3,
+                      gen_rtx_SET (VOIDmode,
+                                   operands[0],
+                                   gen_rtx_CALL (VOIDmode,
+                                                 gen_rtx_MEM (SImode,
+                                                              operands[1]),
+                                                 operands[2])),
+                      gen_rtx_USE (VOIDmode, operands[3]),
+                      gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+      call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+      use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+      DONE;
+    }
+
   if (GET_CODE (operands[1]) != SYMBOL_REF
       || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1]))
       || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
       if (INTVAL (operands[3]) & CALL_LONG)
        operands[1] = rs6000_longcall_ref (operands[1]);
 
-      if (DEFAULT_ABI == ABI_V4
-         || DEFAULT_ABI == ABI_DARWIN)
-       operands[1] = force_reg (Pmode, operands[1]);
+      switch (DEFAULT_ABI)
+        {
+       case ABI_V4:
+       case ABI_DARWIN:
+         operands[1] = force_reg (Pmode, operands[1]);
+         break;
 
-      else if (DEFAULT_ABI == ABI_AIX)
-       {
+       case ABI_AIX:
          /* AIX function pointers are really pointers to a three word
             area.  */
          emit_call_insn (TARGET_32BIT
                                                                      operands[1]),
                                                           operands[2]));
          DONE;
+
+       default:
+         gcc_unreachable ();
        }
-      else
-       abort ();
     }
 }")
 
 ;; and < 0 if they were not.
 
 (define_insn "*call_indirect_nonlocal_aix32"
-  [(call (mem:SI (match_operand:SI 0 "register_operand" "cl"))
-        (match_operand 1 "" "g"))
+  [(call (mem:SI (match_operand:SI 0 "register_operand" "c,*l"))
+        (match_operand 1 "" "g,g"))
    (use (reg:SI 2))
    (use (reg:SI 11))
    (set (reg:SI 2)
        (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
-   (clobber (match_scratch:SI 2 "=l"))]
+   (clobber (match_scratch:SI 2 "=l,l"))]
   "TARGET_32BIT && DEFAULT_ABI == ABI_AIX"
   "b%T0l\;{l|lwz} 2,20(1)"
   [(set_attr "type" "jmpreg")
    (set_attr "length" "8")])
 
 (define_insn "*call_indirect_nonlocal_aix64"
-  [(call (mem:SI (match_operand:DI 0 "register_operand" "cl"))
-        (match_operand 1 "" "g"))
+  [(call (mem:SI (match_operand:DI 0 "register_operand" "c,*l"))
+        (match_operand 1 "" "g,g"))
    (use (reg:DI 2))
    (use (reg:DI 11))
    (set (reg:DI 2)
        (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
-   (clobber (match_scratch:SI 2 "=l"))]
+   (clobber (match_scratch:SI 2 "=l,l"))]
   "TARGET_64BIT && DEFAULT_ABI == ABI_AIX"
   "b%T0l\;ld 2,40(1)"
   [(set_attr "type" "jmpreg")
 
 (define_insn "*call_value_indirect_nonlocal_aix32"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:SI 1 "register_operand" "cl"))
-             (match_operand 2 "" "g")))
+       (call (mem:SI (match_operand:SI 1 "register_operand" "c,*l"))
+             (match_operand 2 "" "g,g")))
    (use (reg:SI 2))
    (use (reg:SI 11))
    (set (reg:SI 2)
        (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
-   (clobber (match_scratch:SI 3 "=l"))]
+   (clobber (match_scratch:SI 3 "=l,l"))]
   "TARGET_32BIT && DEFAULT_ABI == ABI_AIX"
   "b%T1l\;{l|lwz} 2,20(1)"
   [(set_attr "type" "jmpreg")
 
 (define_insn "*call_value_indirect_nonlocal_aix64"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:DI 1 "register_operand" "cl"))
-             (match_operand 2 "" "g")))
+       (call (mem:SI (match_operand:DI 1 "register_operand" "c,*l"))
+             (match_operand 2 "" "g,g")))
    (use (reg:DI 2))
    (use (reg:DI 11))
    (set (reg:DI 2)
        (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
-   (clobber (match_scratch:SI 3 "=l"))]
+   (clobber (match_scratch:SI 3 "=l,l"))]
   "TARGET_64BIT && DEFAULT_ABI == ABI_AIX"
   "b%T1l\;ld 2,40(1)"
   [(set_attr "type" "jmpreg")
 ;; which indicates how to set cr1
 
 (define_insn "*call_indirect_nonlocal_sysv"
-  [(call (mem:SI (match_operand:SI 0 "register_operand" "cl,cl"))
-        (match_operand 1 "" "g,g"))
-   (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 3 "=l,l"))]
+  [(call (mem:SI (match_operand:SI 0 "register_operand" "c,*l,c,*l"))
+        (match_operand 1 "" "g,g,g,g"))
+   (use (match_operand:SI 2 "immediate_operand" "O,O,n,n"))
+   (clobber (match_scratch:SI 3 "=l,l,l,l"))]
   "DEFAULT_ABI == ABI_V4
    || DEFAULT_ABI == ABI_DARWIN"
 {
 
   return "b%T0l";
 }
-  [(set_attr "type" "jmpreg,jmpreg")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
+   (set_attr "length" "4,4,8,8")])
 
 (define_insn "*call_nonlocal_sysv"
   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s,s"))
 #if TARGET_MACHO
   return output_call(insn, operands, 0, 2);
 #else
-  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0";
+  if (DEFAULT_ABI == ABI_V4 && flag_pic)
+    {
+      if (TARGET_SECURE_PLT && flag_pic == 2)
+       /* The magic 32768 offset here and in the other sysv call insns
+          corresponds to the offset of r30 in .got2, as given by LCTOC1.
+          See sysv4.h:toc_section.  */
+       return "bl %z0+32768@plt";
+      else
+       return "bl %z0@plt";
+    }
+  else
+    return "bl %z0";
 #endif
 }
   [(set_attr "type" "branch,branch")
 
 (define_insn "*call_value_indirect_nonlocal_sysv"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:SI 1 "register_operand" "cl,cl"))
-             (match_operand 2 "" "g,g")))
-   (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 4 "=l,l"))]
+       (call (mem:SI (match_operand:SI 1 "register_operand" "c,*l,c,*l"))
+             (match_operand 2 "" "g,g,g,g")))
+   (use (match_operand:SI 3 "immediate_operand" "O,O,n,n"))
+   (clobber (match_scratch:SI 4 "=l,l,l,l"))]
   "DEFAULT_ABI == ABI_V4
    || DEFAULT_ABI == ABI_DARWIN"
 {
 
   return "b%T1l";
 }
-  [(set_attr "type" "jmpreg,jmpreg")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
+   (set_attr "length" "4,4,8,8")])
 
 (define_insn "*call_value_nonlocal_sysv"
   [(set (match_operand 0 "" "")
 #if TARGET_MACHO
   return output_call(insn, operands, 1, 3);
 #else
-  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1";
+  if (DEFAULT_ABI == ABI_V4 && flag_pic)
+    {
+      if (TARGET_SECURE_PLT && flag_pic == 2)
+       return "bl %z1+32768@plt";
+      else
+       return "bl %z1@plt";
+    }
+  else
+    return "bl %z1";
 #endif
 }
   [(set_attr "type" "branch,branch")
     operands[0] = machopic_indirect_call_target (operands[0]);
 #endif
 
-  if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
-    abort ();
+  gcc_assert (GET_CODE (operands[0]) == MEM);
+  gcc_assert (GET_CODE (operands[1]) == CONST_INT);
 
   operands[0] = XEXP (operands[0], 0);
   operands[3] = gen_reg_rtx (SImode);
   else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn (\"creqv 6,6,6\", operands);
 
-  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@plt\" : \"b %z0\";
+  if (DEFAULT_ABI == ABI_V4 && flag_pic)
+    {
+      if (TARGET_SECURE_PLT && flag_pic == 2)
+       return \"b %z0+32768@plt\";
+      else
+       return \"b %z0@plt\";
+    }
+  else
+    return \"b %z0\";
 }"
   [(set_attr "type" "branch,branch")
    (set_attr "length" "4,8")])
     operands[1] = machopic_indirect_call_target (operands[1]);
 #endif
 
-  if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
-    abort ();
+  gcc_assert (GET_CODE (operands[1]) == MEM);
+  gcc_assert (GET_CODE (operands[2]) == CONST_INT);
 
   operands[1] = XEXP (operands[1], 0);
   operands[4] = gen_reg_rtx (SImode);
   else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn (\"creqv 6,6,6\", operands);
 
-  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@plt\" : \"b %z1\";
+  if (DEFAULT_ABI == ABI_V4 && flag_pic)
+    {
+      if (TARGET_SECURE_PLT && flag_pic == 2)
+       return \"b %z1+32768@plt\";
+      else
+       return \"b %z1@plt\";
+    }
+  else
+    return \"b %z1\";
 }"
   [(set_attr "type" "branch,branch")
    (set_attr "length" "4,8")])
 ;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc
 ;; insns, and branches.  We store the operands of compares until we see
 ;; how it is used.
-(define_expand "cmpsi"
+(define_expand "cmp<mode>"
   [(set (cc0)
-        (compare (match_operand:SI 0 "gpc_reg_operand" "")
-                (match_operand:SI 1 "reg_or_short_operand" "")))]
+        (compare (match_operand:GPR 0 "gpc_reg_operand" "")
+                (match_operand:GPR 1 "reg_or_short_operand" "")))]
   ""
   "
 {
      this might be a logical operation.  That insn doesn't exist.  */
   if (GET_CODE (operands[1]) == CONST_INT
       && INTVAL (operands[1]) < 0)
-    operands[1] = force_reg (SImode, operands[1]);
-
-  rs6000_compare_op0 = operands[0];
-  rs6000_compare_op1 = operands[1];
-  rs6000_compare_fp_p = 0;
-  DONE;
-}")
-
-(define_expand "cmpdi"
-  [(set (cc0)
-        (compare (match_operand:DI 0 "gpc_reg_operand" "")
-                (match_operand:DI 1 "reg_or_short_operand" "")))]
-  "TARGET_POWERPC64"
-  "
-{
-  /* Take care of the possibility that operands[1] might be negative but
-     this might be a logical operation.  That insn doesn't exist.  */
-  if (GET_CODE (operands[1]) == CONST_INT
-      && INTVAL (operands[1]) < 0)
-    operands[1] = force_reg (DImode, operands[1]);
+    operands[1] = force_reg (<MODE>mode, operands[1]);
 
   rs6000_compare_op0 = operands[0];
   rs6000_compare_op1 = operands[1];
   DONE;
 }")
 
-(define_expand "cmpsf"
-  [(set (cc0) (compare (match_operand:SF 0 "gpc_reg_operand" "")
-                      (match_operand:SF 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT"
-  "
-{
-  rs6000_compare_op0 = operands[0];
-  rs6000_compare_op1 = operands[1];
-  rs6000_compare_fp_p = 1;
-  DONE;
-}")
-
-(define_expand "cmpdf"
-  [(set (cc0) (compare (match_operand:DF 0 "gpc_reg_operand" "")
-                      (match_operand:DF 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS"
-  "
-{
-  rs6000_compare_op0 = operands[0];
-  rs6000_compare_op1 = operands[1];
-  rs6000_compare_fp_p = 1;
-  DONE;
-}")
-
-(define_expand "cmptf"
-  [(set (cc0) (compare (match_operand:TF 0 "gpc_reg_operand" "")
-                      (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+(define_expand "cmp<mode>"
+  [(set (cc0) (compare (match_operand:FP 0 "gpc_reg_operand" "")
+                      (match_operand:FP 1 "gpc_reg_operand" "")))]
+  ""
   "
 {
   rs6000_compare_op0 = operands[0];
 
 (define_expand "bunordered"
   [(use (match_operand 0 "" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
   "{ rs6000_emit_cbranch (UNORDERED, operands[0]); DONE; }")
 
 (define_expand "bordered"
   [(use (match_operand 0 "" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
   "{ rs6000_emit_cbranch (ORDERED, operands[0]); DONE; }")
 
 (define_expand "buneq"
   ""
   "
 {
-  if (! rs6000_compare_fp_p
-      && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
+  if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
     FAIL;
 
   rs6000_emit_sCOND (GE, operands[0]);
   ""
   "
 {
-  if (! rs6000_compare_fp_p
-      && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
+  if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
     FAIL;
 
   rs6000_emit_sCOND (GT, operands[0]);
   ""
   "
 {
-  if (! rs6000_compare_fp_p
-      && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
+  if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
     FAIL;
 
   rs6000_emit_sCOND (LE, operands[0]);
   ""
   "
 {
-  if (! rs6000_compare_fp_p
-      && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
+  if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
     FAIL;
 
   rs6000_emit_sCOND (LT, operands[0]);
 
 (define_expand "sunordered"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
   "{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }")
 
 (define_expand "sordered"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
   "{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }")
 
 (define_expand "suneq"
 
 \f
 ;; Here are the actual compare insns.
-(define_insn "*cmpsi_internal1"
+(define_insn "*cmp<mode>_internal1"
   [(set (match_operand:CC 0 "cc_reg_operand" "=y")
-       (compare:CC (match_operand:SI 1 "gpc_reg_operand" "r")
-                   (match_operand:SI 2 "reg_or_short_operand" "rI")))]
+       (compare:CC (match_operand:GPR 1 "gpc_reg_operand" "r")
+                   (match_operand:GPR 2 "reg_or_short_operand" "rI")))]
   ""
-  "{cmp%I2|cmpw%I2} %0,%1,%2"
-  [(set_attr "type" "cmp")])
-
-(define_insn "*cmpdi_internal1"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=y")
-       (compare:CC (match_operand:DI 1 "gpc_reg_operand" "r")
-                   (match_operand:DI 2 "reg_or_short_operand" "rI")))]
-  "TARGET_POWERPC64"
-  "cmpd%I2 %0,%1,%2"
+  "{cmp%I2|cmp<wd>%I2} %0,%1,%2"
   [(set_attr "type" "cmp")])
 
 ;; If we are comparing a register for equality with a large constant,
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
        (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "f")
                      (match_operand:TF 2 "gpc_reg_operand" "f")))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) && !TARGET_XL_COMPAT
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "fcmpu %0,%1,%2\;bne %0,$+8\;fcmpu %0,%L1,%L2"
   [(set_attr "type" "fpcompare")
    (set_attr "length" "12")])
+
+(define_insn_and_split "*cmptf_internal2"
+  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+       (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "f")
+                     (match_operand:TF 2 "gpc_reg_operand" "f")))
+    (clobber (match_scratch:DF 3 "=f"))
+    (clobber (match_scratch:DF 4 "=f"))
+    (clobber (match_scratch:DF 5 "=f"))
+    (clobber (match_scratch:DF 6 "=f"))
+    (clobber (match_scratch:DF 7 "=f"))
+    (clobber (match_scratch:DF 8 "=f"))
+    (clobber (match_scratch:DF 9 "=f"))
+    (clobber (match_scratch:DF 10 "=f"))]
+  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) && TARGET_XL_COMPAT
+   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 3) (match_dup 13))
+   (set (match_dup 4) (match_dup 14))
+   (set (match_dup 9) (abs:DF (match_dup 5)))
+   (set (match_dup 0) (compare:CCFP (match_dup 9) (match_dup 3)))
+   (set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
+                          (label_ref (match_dup 11))
+                          (pc)))
+   (set (match_dup 0) (compare:CCFP (match_dup 5) (match_dup 7)))
+   (set (pc) (label_ref (match_dup 12)))
+   (match_dup 11)
+   (set (match_dup 10) (minus:DF (match_dup 5) (match_dup 7)))
+   (set (match_dup 9) (minus:DF (match_dup 6) (match_dup 8)))
+   (set (match_dup 9) (plus:DF (match_dup 10) (match_dup 9)))
+   (set (match_dup 0) (compare:CCFP (match_dup 7) (match_dup 4)))
+   (match_dup 12)]
+{
+  REAL_VALUE_TYPE rv;
+  const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
+  const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
+
+  operands[5] = simplify_gen_subreg (DFmode, operands[1], TFmode, hi_word);
+  operands[6] = simplify_gen_subreg (DFmode, operands[1], TFmode, lo_word);
+  operands[7] = simplify_gen_subreg (DFmode, operands[2], TFmode, hi_word);
+  operands[8] = simplify_gen_subreg (DFmode, operands[2], TFmode, lo_word);
+  operands[11] = gen_label_rtx ();
+  operands[12] = gen_label_rtx ();
+  real_inf (&rv);
+  operands[13] = force_const_mem (DFmode,
+                                 CONST_DOUBLE_FROM_REAL_VALUE (rv, DFmode));
+  operands[14] = force_const_mem (DFmode,
+                                 CONST_DOUBLE_FROM_REAL_VALUE (dconst0,
+                                                               DFmode));
+  if (TARGET_TOC)
+    {
+      operands[13] = gen_const_mem (DFmode,
+                                   create_TOC_reference (XEXP (operands[13], 0)));
+      operands[14] = gen_const_mem (DFmode,
+                                   create_TOC_reference (XEXP (operands[14], 0)));
+      set_mem_alias_set (operands[13], get_TOC_alias_set ());
+      set_mem_alias_set (operands[14], get_TOC_alias_set ());
+    }
+})
 \f
 ;; Now we have the scc insns.  We can do some combinations because of the
 ;; way the machine works.
                (const_string "mfcrf")
           ]
        (const_string "mfcr")))
-   (set_attr "length" "12")])
+   (set_attr "length" "8")])
+
+;; Same as above, but get the GT bit.
+(define_insn "move_from_CR_gt_bit"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_GT))]
+  "TARGET_E500"
+  "mfcr %0\;{rlinm|rlwinm} %0,%0,%D1,31,31"
+  [(set_attr "type" "mfcr")
+   (set_attr "length" "8")])
 
 ;; Same as above, but get the OV/ORDERED bit.
 (define_insn "move_from_CR_ov_bit"
   "TARGET_ISEL"
   "mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1"
   [(set_attr "type" "mfcr")
-   (set_attr "length" "12")])
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
                (const_string "mfcrf")
           ]
        (const_string "mfcr")))
-   (set_attr "length" "12")])
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
    mfcr %3%Q2\;{rlinm.|rlwinm.} %3,%3,%J1,1
    #"
   [(set_attr "type" "delayed_compare")
-   (set_attr "length" "12,16")])
+   (set_attr "length" "8,16")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
                (const_string "mfcrf")
           ]
        (const_string "mfcr")))
-   (set_attr "length" "12")])
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   return \"mfcr %4%Q2\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
 }"
   [(set_attr "type" "delayed_compare")
-   (set_attr "length" "12,16")])
+   (set_attr "length" "8,16")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "REGNO (operands[2]) != REGNO (operands[5])"
   "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
   [(set_attr "type" "mfcr")
-   (set_attr "length" "20")])
+   (set_attr "length" "12")])
 
 (define_peephole
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
   "TARGET_POWERPC64 && REGNO (operands[2]) != REGNO (operands[5])"
   "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
   [(set_attr "type" "mfcr")
-   (set_attr "length" "20")])
+   (set_attr "length" "12")])
 
 ;; There are some scc insns that can be done directly, without a compare.
 ;; These are faster because they don't involve the communications between
 ;; otherwise won't accept constants.  We do this because it is faster than
 ;; the cmp/mfcr sequence we would otherwise generate.
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r")
-       (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
-              (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I")))
-   (clobber (match_scratch:SI 3 "=r,&r,r,r,r"))]
-  "TARGET_32BIT"
-  "@
-   xor %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0
-   {sfi|subfic} %3,%1,0\;{ae|adde} %0,%3,%1
-   {xoril|xori} %0,%1,%b2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0
-   {xoriu|xoris} %0,%1,%u2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0
-   {sfi|subfic} %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0"
-  [(set_attr "length" "12,8,12,12,12")])
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
-       (eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
-              (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I")))
-   (clobber (match_scratch:DI 3 "=r,&r,r,r,r"))]
-  "TARGET_64BIT"
-  "@
-   xor %0,%1,%2\;subfic %3,%0,0\;adde %0,%3,%0
-   subfic %3,%1,0\;adde %0,%3,%1
-   xori %0,%1,%b2\;subfic %3,%0,0\;adde %0,%3,%0
-   xoris %0,%1,%u2\;subfic %3,%0,0\;adde %0,%3,%0
-   subfic %0,%1,%2\;subfic %3,%0,0\;adde %0,%3,%0"
-  [(set_attr "length" "12,8,12,12,12")])
+(define_mode_attr scc_eq_op2 [(SI "rKLI")
+                             (DI "rKJI")])
 
-(define_insn ""
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
-       (compare:CC
-        (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
-               (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I,r,O,K,L,I"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
-       (eq:SI (match_dup 1) (match_dup 2)))
-   (clobber (match_scratch:SI 3 "=r,&r,r,r,r,r,&r,r,r,r"))]
-  "TARGET_32BIT"
-  "@
-   xor %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae.|adde.} %0,%3,%0
-   {sfi|subfic} %3,%1,0\;{ae.|adde.} %0,%3,%1
-   {xoril|xori} %0,%1,%b2\;{sfi|subfic} %3,%0,0\;{ae.|adde.} %0,%3,%0
-   {xoriu|xoris} %0,%1,%u2\;{sfi|subfic} %3,%0,0\;{ae.|adde.} %0,%3,%0
-   {sfi|subfic} %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae.|adde.} %0,%3,%0
-   #
-   #
-   #
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,8,12,12,12,16,12,16,16,16")])
+(define_insn_and_split "*eq<mode>"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+               (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))
+   (clobber (match_scratch:GPR 3 "=r"))
+   (clobber (match_scratch:GPR 4 "=r"))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (match_dup 3)
+       (clz:GPR (match_dup 4)))
+   (set (match_dup 0)
+       (lshiftrt:GPR (match_dup 3) (match_dup 5)))]
+  {
+    if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
+      {
+       if (logical_operand (operands[2], <MODE>mode))
+         emit_insn (gen_rtx_SET (VOIDmode, operands[4],
+                                 gen_rtx_XOR (<MODE>mode,
+                                              operands[1], operands[2])));
+       else
+         emit_insn (gen_rtx_SET (VOIDmode, operands[4],
+                                 gen_rtx_PLUS (<MODE>mode, operands[1],
+                                               negate_rtx (<MODE>mode,
+                                                           operands[2]))));
+      }
+    else
+      operands[4] = operands[1];
 
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (eq:SI (match_operand:SI 1 "gpc_reg_operand" "")
-               (match_operand:SI 2 "reg_or_cint_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (eq:SI (match_dup 1) (match_dup 2)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(parallel [(set (match_dup 0)
-       (eq:SI (match_dup 1) (match_dup 2)))
-   (clobber (match_dup 3))])
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+    operands[5] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
+  })
 
-(define_insn ""
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
+(define_insn_and_split "*eq<mode>_compare"
+  [(set (match_operand:CC 5 "cc_reg_operand" "=y")
        (compare:CC
-        (eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
-               (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I,r,O,K,J,I"))
+        (eq:P (match_operand:P 1 "gpc_reg_operand" "=r")
+              (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))
         (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
-       (eq:DI (match_dup 1) (match_dup 2)))
-   (clobber (match_scratch:DI 3 "=r,&r,r,r,r,r,&r,r,r,r"))]
-  "TARGET_64BIT"
-  "@
-   xor %0,%1,%2\;subfic %3,%0,0\;adde. %0,%3,%0
-   subfic %3,%1,0\;adde. %0,%3,%1
-   xori %0,%1,%b2\;subfic %3,%0,0\;adde. %0,%3,%0
-   xoris %0,%1,%u2\;subfic %3,%0,0\;adde. %0,%3,%0
-   subfic %0,%1,%2\;subfic %3,%0,0\;adde. %0,%3,%0
-   #
-   #
-   #
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,8,12,12,12,16,12,16,16,16")])
+   (set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (eq:P (match_dup 1) (match_dup 2)))
+   (clobber (match_scratch:P 3 "=r"))
+   (clobber (match_scratch:P 4 "=r"))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (match_dup 3)
+       (clz:P (match_dup 4)))
+   (parallel [(set (match_dup 5)
+                  (compare:CC (lshiftrt:P (match_dup 3) (match_dup 6))
+                              (const_int 0)))
+             (set (match_dup 0)
+                  (lshiftrt:P (match_dup 3) (match_dup 6)))])]
+  {
+    if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
+      {
+       if (logical_operand (operands[2], <MODE>mode))
+         emit_insn (gen_rtx_SET (VOIDmode, operands[4],
+                                 gen_rtx_XOR (<MODE>mode,
+                                              operands[1], operands[2])));
+       else
+         emit_insn (gen_rtx_SET (VOIDmode, operands[4],
+                                 gen_rtx_PLUS (<MODE>mode, operands[1],
+                                               negate_rtx (<MODE>mode,
+                                                           operands[2]))));
+      }
+    else
+      operands[4] = operands[1];
 
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (eq:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "reg_or_cint_operand" ""))
-        (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (eq:DI (match_dup 1) (match_dup 2)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_64BIT && reload_completed"
-  [(parallel [(set (match_dup 0)
-       (eq:DI (match_dup 1) (match_dup 2)))
-   (clobber (match_dup 3))])
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+    operands[6] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
+  })
 
 ;; We have insns of the form shown by the first define_insn below.  If
 ;; there is something inside the comparison operation, we must split it.
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r,&r")
        (plus:SI (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
-                       (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I"))
+                       (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I"))
                 (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r")))]
   "TARGET_32BIT"
   "@
    {xoril|xori} %0,%1,%b2\;{sfi|subfic} %0,%0,0\;{aze|addze} %0,%3
    {xoriu|xoris} %0,%1,%u2\;{sfi|subfic} %0,%0,0\;{aze|addze} %0,%3
    {sfi|subfic} %0,%1,%2\;{sfi|subfic} %0,%0,0\;{aze|addze} %0,%3"
-  [(set_attr "length" "12,8,12,12,12")])
+  [(set_attr "type" "three,two,three,three,three")
+   (set_attr "length" "12,8,12,12,12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
        (compare:CC
         (plus:SI
          (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
-                (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I,r,O,K,L,I"))
+                (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I,r,O,K,L,I"))
          (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r,r,r,r,r,r"))
         (const_int 0)))
    (clobber (match_scratch:SI 4 "=&r,&r,&r,&r,&r,&r,&r,&r,&r,&r"))]
        (compare:CC
         (plus:SI
          (eq:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "reg_or_cint_operand" ""))
+                (match_operand:SI 2 "scc_eq_operand" ""))
          (match_operand:SI 3 "gpc_reg_operand" ""))
         (const_int 0)))
    (clobber (match_scratch:SI 4 ""))]
        (compare:CC
         (plus:SI
          (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
-                (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I,r,O,K,L,I"))
+                (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I,r,O,K,L,I"))
          (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r,r,r,r,r,r"))
         (const_int 0)))
    (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r,&r,&r,&r,&r,&r,&r")
        (compare:CC
         (plus:SI
          (eq:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "reg_or_cint_operand" ""))
+                (match_operand:SI 2 "scc_eq_operand" ""))
          (match_operand:SI 3 "gpc_reg_operand" ""))
         (const_int 0)))
    (set (match_operand:SI 0 "gpc_reg_operand" "")
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r")
        (neg:SI (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
-                      (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I"))))]
+                      (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I"))))]
   "TARGET_32BIT"
   "@
    xor %0,%1,%2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0
    {xoril|xori} %0,%1,%b2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0
    {xoriu|xoris} %0,%1,%u2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0
    {sfi|subfic} %0,%1,%2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0"
-   [(set_attr "length" "12,8,12,12,12")])
+   [(set_attr "type" "three,two,three,three,three")
+    (set_attr "length" "12,8,12,12,12")])
 
 ;; Simplify (ne X (const_int 0)) on the PowerPC.  No need to on the Power,
 ;; since it nabs/sr is just as fast.
    (clobber (match_scratch:SI 2 "=&r"))]
   "! TARGET_POWER && TARGET_32BIT && !TARGET_ISEL"
   "{ai|addic} %2,%1,-1\;{sfe|subfe} %0,%2,%1"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
    (clobber (match_scratch:DI 2 "=&r"))]
   "TARGET_64BIT"
   "addic %2,%1,-1\;subfe %0,%2,%1"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 ;; This is what (plus (ne X (const_int 0)) Y) looks like.
 (define_insn ""
    (clobber (match_scratch:SI 3 "=&r"))]
   "TARGET_32BIT"
   "{ai|addic} %3,%1,-1\;{aze|addze} %0,%2"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
    (clobber (match_scratch:DI 3 "=&r"))]
   "TARGET_64BIT"
   "addic %3,%1,-1\;addze %0,%2"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
                (match_operand:SI 2 "reg_or_short_operand" "rI")))]
   "TARGET_32BIT"
   "{sf%I2|subf%I2c} %0,%1,%2\;{cal %0,0(0)|li %0,0}\;{ae|adde} %0,%0,%0"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
                (match_operand:DI 2 "reg_or_short_operand" "rI")))]
   "TARGET_64BIT"
   "subf%I2c %0,%1,%2\;li %0,0\;adde %0,%0,%0"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
                 (match_operand:SI 3 "gpc_reg_operand" "r")))]
   "TARGET_32BIT"
   "{sf%I2|subf%I2c} %0,%1,%2\;{aze|addze} %0,%3"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
                        (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
   "TARGET_32BIT"
   "{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;nand %0,%0,%0"
-   [(set_attr "length" "12")])
+   [(set_attr "type" "three")
+    (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
                (match_operand:SI 3 "gpc_reg_operand" "r")))]
   "TARGET_32BIT"
   "{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;andc %0,%3,%0"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "doz%I2 %0,%1,%2\;nabs %0,%0\;{srai|srawi} %0,%0,31"
   [(set_attr "length" "12")])
 
-(define_insn ""
+(define_insn_and_split ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
        (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
                (match_operand:SI 2 "reg_or_neg_short_operand" "r,P")))]
   "TARGET_32BIT"
-  "@
-   {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;neg %0,%0
-   {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;neg %0,%0"
-  [(set_attr "length" "12")])
+  "#"
+  "TARGET_32BIT"
+  [(set (match_dup 0) (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (neg:SI (match_dup 0)))]
+  "")
+
+(define_insn_and_split ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (ltu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+               (match_operand:DI 2 "reg_or_neg_short_operand" "r,P")))]
+  "TARGET_64BIT"
+  "#"
+  "TARGET_64BIT"
+  [(set (match_dup 0) (neg:DI (ltu:DI (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (neg:DI (match_dup 0)))]
+  "")
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
                    (const_int 0)))]
   "")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
+(define_insn_and_split ""
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,r")
        (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
                         (match_operand:SI 2 "reg_or_neg_short_operand" "r,P"))
                 (match_operand:SI 3 "reg_or_short_operand" "rI,rI")))]
   "TARGET_32BIT"
-  "@
-  {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;{sf%I3|subf%I3c} %0,%0,%3
-  {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;{sf%I3|subf%I3c} %0,%0,%3"
- [(set_attr "length" "12")])
+  "#"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+  [(set (match_dup 0) (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 0)))]
+  "")
+
+(define_insn_and_split ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
+       (plus:DI (ltu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                        (match_operand:DI 2 "reg_or_neg_short_operand" "r,P"))
+                (match_operand:DI 3 "reg_or_short_operand" "rI,rI")))]
+  "TARGET_64BIT"
+  "#"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+  [(set (match_dup 0) (neg:DI (ltu:DI (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (minus:DI (match_dup 3) (match_dup 0)))]
+  "")
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
    (clobber (match_scratch:SI 4 "=&r,&r,&r,&r"))]
   "TARGET_32BIT"
   "@
-   {sf|subfc} %4,%2,%1\;{sfe|subfe} %4,%4,%4\;{sf.|subfc.} %4,%4,%3
-   {ai|addic} %4,%1,%n2\;{sfe|subfe} %4,%4,%4\;{sf.|subfc.} %4,%4,%3
+   {sf|subfc} %4,%2,%1\;{sfe|subfe} %4,%4,%4\;{sf.|subf.} %4,%4,%3
+   {ai|addic} %4,%1,%n2\;{sfe|subfe} %4,%4,%4\;{sf.|subf.} %4,%4,%3
    #
    #"
   [(set_attr "type" "compare")
        (plus:SI (ltu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
   "TARGET_32BIT"
   "@
-   {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;{sf.|subfc.} %0,%0,%3
-   {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;{sf.|subfc.} %0,%0,%3
+   {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;{sf.|subf.} %0,%0,%3
+   {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;{sf.|subf.} %0,%0,%3
    #
    #"
   [(set_attr "type" "compare")
   "@
    {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0
    {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
+
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (neg:DI (ltu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                       (match_operand:DI 2 "reg_or_neg_short_operand" "r,P"))))]
+  "TARGET_64BIT"
+  "@
+   {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0
+   {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0"
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
   "@
    {sf|subfc} %0,%2,%1\;{cal %0,0(0)|li %0,0}\;{ae|adde} %0,%0,%0
    {ai|addic} %0,%1,%n2\;{cal %0,0(0)|li %0,0}\;{ae|adde} %0,%0,%0"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
   "@
    subfc %0,%2,%1\;li %0,0\;adde %0,%0,%0
    addic %0,%1,%n2\;li %0,0\;adde %0,%0,%0"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
   "@
    {sf|subfc} %0,%2,%1\;{aze|addze} %0,%3
    {ai|addic} %0,%1,%n2\;{aze|addze} %0,%3"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
   "@
    {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;nand %0,%0,%0
    {sfi|subfic} %0,%1,-1\;{a%I2|add%I2c} %0,%0,%2\;{sfe|subfe} %0,%0,%0"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
   "@
    {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;andc %0,%3,%0
    {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;andc %0,%3,%0"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
               (const_int 0)))]
   "TARGET_32BIT"
   "{sfi|subfic} %0,%1,0\;{ame|addme} %0,%0\;{sri|srwi} %0,%0,31"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
               (const_int 0)))]
   "TARGET_64BIT"
   "subfic %0,%1,0\;addme %0,%0\;srdi %0,%0,63"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
                 (match_operand:SI 2 "gpc_reg_operand" "r")))]
   "TARGET_32BIT"
   "{a|addc} %0,%1,%1\;{sfe|subfe} %0,%1,%0\;{aze|addze} %0,%2"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
                 (match_operand:DI 2 "gpc_reg_operand" "r")))]
   "TARGET_64BIT"
   "addc %0,%1,%1\;subfe %0,%1,%0\;addze %0,%2"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
                       (const_int 0))))]
   "TARGET_32BIT"
   "{sfi|subfic} %0,%1,0\;{ame|addme} %0,%0\;{srai|srawi} %0,%0,31"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
                       (const_int 0))))]
   "TARGET_64BIT"
   "subfic %0,%1,0\;addme %0,%0\;sradi %0,%0,63"
-  [(set_attr "length" "12")])
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
   "doz %0,%2,%1\;nabs %0,%0\;{srai|srawi} %0,%0,31"
   [(set_attr "length" "12")])
 
-(define_insn ""
+(define_insn_and_split ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-               (match_operand:SI 2 "reg_or_short_operand" "rI")))]
+        (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                (match_operand:SI 2 "reg_or_short_operand" "rI")))]
   "TARGET_32BIT"
-  "{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;neg %0,%0"
-  [(set_attr "length" "12")])
+  "#"
+  "TARGET_32BIT"
+  [(set (match_dup 0) (neg:SI (gtu:SI (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (neg:SI (match_dup 0)))]
+  "")
 
-(define_insn ""
+(define_insn_and_split ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-               (match_operand:DI 2 "reg_or_short_operand" "rI")))]
+        (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                (match_operand:DI 2 "reg_or_short_operand" "rI")))]
   "TARGET_64BIT"
-  "subf%I2c %0,%1,%2\;subfe %0,%0,%0\;neg %0,%0"
-  [(set_attr "length" "12")])
+  "#"
+  "TARGET_64BIT"
+  [(set (match_dup 0) (neg:DI (gtu:DI (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (neg:DI (match_dup 0)))]
+  "")
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
                    (const_int 0)))]
   "")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
-       (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                        (match_operand:SI 2 "reg_or_short_operand" "I,rI"))
-                (match_operand:SI 3 "reg_or_short_operand" "r,rI")))]
+(define_insn_and_split ""
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
+        (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                         (match_operand:SI 2 "reg_or_short_operand" "rI"))
+                 (match_operand:SI 3 "reg_or_short_operand" "rI")))]
   "TARGET_32BIT"
-  "@
-   {ai|addic} %0,%1,%k2\;{aze|addze} %0,%3
-   {sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;{sf%I3|subf%I3c} %0,%0,%3"
-  [(set_attr "length" "8,12")])
+  "#"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+  [(set (match_dup 0) (neg:SI (gtu:SI (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 0)))]
+  "")
 
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r")
-       (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                        (match_operand:DI 2 "reg_or_short_operand" "I,rI"))
-                (match_operand:DI 3 "reg_or_short_operand" "r,rI")))]
+(define_insn_and_split ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
+        (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                         (match_operand:DI 2 "reg_or_short_operand" "rI"))
+                 (match_operand:DI 3 "reg_or_short_operand" "rI")))]
   "TARGET_64BIT"
-  "@
-   addic %0,%1,%k2\;addze %0,%3
-   subf%I2c %0,%1,%2\;subfe %0,%0,%0\;subf%I3c %0,%0,%3"
-  [(set_attr "length" "8,12")])
+  "#"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+  [(set (match_dup 0) (neg:DI (gtu:DI (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (minus:DI (match_dup 3) (match_dup 0)))]
+  "")
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
   "TARGET_32BIT"
   "@
    {ai|addic} %4,%1,%k2\;{aze.|addze.} %4,%3
-   {sf%I2|subf%I2c} %4,%1,%2\;{sfe|subfe} %4,%4,%4\;{sf.|subfc.} %4,%4,%3
+   {sf%I2|subf%I2c} %4,%1,%2\;{sfe|subfe} %4,%4,%4\;{sf.|subf.} %4,%4,%3
    #
    #"
   [(set_attr "type" "compare")
   "TARGET_64BIT"
   "@
    addic %4,%1,%k2\;addze. %4,%3
-   subf%I2c %4,%1,%2\;subfe %4,%4,%4\;subfc. %4,%4,%3
+   subf%I2c %4,%1,%2\;subfe %4,%4,%4\;subf. %4,%4,%3
    #
    #"
   [(set_attr "type" "compare")
   "TARGET_32BIT"
   "@
    {ai|addic} %0,%1,%k2\;{aze.|addze.} %0,%3
-   {sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;{sf.|subfc.} %0,%0,%3
+   {sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;{sf.|subf.} %0,%0,%3
    #
    #"
   [(set_attr "type" "compare")
   "TARGET_64BIT"
   "@
    addic %0,%1,%k2\;addze. %0,%3
-   subf%I2c %0,%1,%2\;subfe %0,%0,%0\;subfc. %0,%0,%3
+   subf%I2c %0,%1,%2\;subfe %0,%0,%0\;subf. %0,%0,%3
    #
    #"
   [(set_attr "type" "compare")
                        (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
   "TARGET_32BIT"
   "{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
                        (match_operand:DI 2 "reg_or_short_operand" "rI"))))]
   "TARGET_64BIT"
   "subf%I2c %0,%1,%2\;subfe %0,%0,%0"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 \f
 ;; Define both directions of branch and return.  If we need a reload
 ;; register, we'd rather use CR0 since it is much easier to copy a
 ; which are generated by the branch logic.
 ; Prefer destructive operations where BT = BB (for crXX BT,BA,BB)
 
-(define_insn ""
+(define_insn "*cceq_ior_compare"
   [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
         (compare:CCEQ (match_operator:SI 1 "boolean_operator"
                        [(match_operator:SI 2
   "cr%q1 %E0,%j2,%j4"
   [(set_attr "type" "cr_logical,delayed_cr")])
 
-(define_insn ""
+(define_insn "*cceq_rev_compare"
   [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
        (compare:CCEQ (match_operator:SI 1
                                      "branch_positive_comparison_operator"
                                                      "cc_reg_operand" "0,y")
                                       (const_int 0)])
                      (const_int 0)))]
-  "!TARGET_SPE"
+  ""
   "{crnor %E0,%j1,%j1|crnot %E0,%j1}"
   [(set_attr "type" "cr_logical,delayed_cr")])
 
 {
   int positive_1, positive_2;
 
-  positive_1 = branch_positive_comparison_operator (operands[1], CCEQmode);
-  positive_2 = branch_positive_comparison_operator (operands[3], CCEQmode);
+  positive_1 = branch_positive_comparison_operator (operands[1],
+                                                   GET_MODE (operands[1]));
+  positive_2 = branch_positive_comparison_operator (operands[3],
+                                                   GET_MODE (operands[3]));
 
   if (! positive_1)
     operands[1] = gen_rtx_fmt_ee (rs6000_reverse_condition (GET_MODE (operands[2]),
   [(set_attr "type" "jmpreg")])
 
 (define_expand "indirect_jump"
-  [(set (pc) (match_operand 0 "register_operand" ""))]
-  ""
-  "
-{
-  if (TARGET_32BIT)
-    emit_jump_insn (gen_indirect_jumpsi (operands[0]));
-  else
-    emit_jump_insn (gen_indirect_jumpdi (operands[0]));
-  DONE;
-}")
+  [(set (pc) (match_operand 0 "register_operand" ""))])
 
-(define_insn "indirect_jumpsi"
-  [(set (pc) (match_operand:SI 0 "register_operand" "c,*l"))]
-  "TARGET_32BIT"
+(define_insn "*indirect_jump<mode>"
+  [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))]
+  ""
   "@
    bctr
    {br|blr}"
   [(set_attr "type" "jmpreg")])
 
-(define_insn "indirect_jumpdi"
-  [(set (pc) (match_operand:DI 0 "register_operand" "c,*l"))]
-  "TARGET_64BIT"
-  "@
-   bctr
-   blr"
-  [(set_attr "type" "jmpreg")])
-
 ;; Table jump for switch statements:
 (define_expand "tablejump"
   [(use (match_operand 0 "" ""))
              (use (label_ref (match_operand 1 "" "")))])]
   "TARGET_64BIT"
   "
-{ operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
-  operands[3] = gen_reg_rtx (DImode);
-  operands[4] = gen_reg_rtx (DImode);
-}")
-
-(define_insn ""
-  [(set (pc)
-       (match_operand:SI 0 "register_operand" "c,*l"))
-   (use (label_ref (match_operand 1 "" "")))]
-  "TARGET_32BIT"
-  "@
-   bctr
-   {br|blr}"
-  [(set_attr "type" "jmpreg")])
+{ operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
+  operands[3] = gen_reg_rtx (DImode);
+  operands[4] = gen_reg_rtx (DImode);
+}")
 
 (define_insn ""
   [(set (pc)
-       (match_operand:DI 0 "register_operand" "c,*l"))
+       (match_operand:P 0 "register_operand" "c,*l"))
    (use (label_ref (match_operand 1 "" "")))]
-  "TARGET_64BIT"
+  ""
   "@
    bctr
-   blr"
+   {br|blr}"
   [(set_attr "type" "jmpreg")])
 
 (define_insn "nop"
   DONE;
 }")
 
-(define_expand "ctrsi"
-  [(parallel [(set (pc)
-                  (if_then_else (ne (match_operand:SI 0 "register_operand" "")
-                                    (const_int 1))
-                                (label_ref (match_operand 1 "" ""))
-                                (pc)))
-             (set (match_dup 0)
-                  (plus:SI (match_dup 0)
-                           (const_int -1)))
-             (clobber (match_scratch:CC 2 ""))
-             (clobber (match_scratch:SI 3 ""))])]
-  "TARGET_32BIT"
-  "")
-
-(define_expand "ctrdi"
+(define_expand "ctr<mode>"
   [(parallel [(set (pc)
-                  (if_then_else (ne (match_operand:DI 0 "register_operand" "")
+                  (if_then_else (ne (match_operand:P 0 "register_operand" "")
                                     (const_int 1))
                                 (label_ref (match_operand 1 "" ""))
                                 (pc)))
              (set (match_dup 0)
-                  (plus:DI (match_dup 0)
+                  (plus:P (match_dup 0)
                            (const_int -1)))
              (clobber (match_scratch:CC 2 ""))
-             (clobber (match_scratch:DI 3 ""))])]
-  "TARGET_64BIT"
+             (clobber (match_scratch:P 3 ""))])]
+  ""
   "")
 
 ;; We need to be able to do this for any operand, including MEM, or we
 ;; For the length attribute to be calculated correctly, the
 ;; label MUST be operand 0.
 
-(define_insn "*ctrsi_internal1"
-  [(set (pc)
-       (if_then_else (ne (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
-                         (const_int 1))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))
-   (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
-       (plus:SI (match_dup 1)
-                (const_int -1)))
-   (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
-  "TARGET_32BIT"
-  "*
-{
-  if (which_alternative != 0)
-    return \"#\";
-  else if (get_attr_length (insn) == 4)
-    return \"{bdn|bdnz} %l0\";
-  else
-    return \"bdz $+8\;b %l0\";
-}"
-  [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrsi_internal2"
-  [(set (pc)
-       (if_then_else (ne (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
-                         (const_int 1))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))
-   (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
-       (plus:SI (match_dup 1)
-                (const_int -1)))
-   (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
-  "TARGET_32BIT"
-  "*
-{
-  if (which_alternative != 0)
-    return \"#\";
-  else if (get_attr_length (insn) == 4)
-    return \"bdz %l0\";
-  else
-    return \"{bdn|bdnz} $+8\;b %l0\";
-}"
-  [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrdi_internal1"
+(define_insn "*ctr<mode>_internal1"
   [(set (pc)
-       (if_then_else (ne (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
+       (if_then_else (ne (match_operand:P 1 "register_operand" "c,*r,*r,*r")
                          (const_int 1))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))
-   (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
-       (plus:DI (match_dup 1)
+   (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*q*c*l")
+       (plus:P (match_dup 1)
                 (const_int -1)))
    (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:P 4 "=X,X,&r,r"))]
+  ""
   "*
 {
   if (which_alternative != 0)
   [(set_attr "type" "branch")
    (set_attr "length" "*,12,16,16")])
 
-(define_insn "*ctrdi_internal2"
+(define_insn "*ctr<mode>_internal2"
   [(set (pc)
-       (if_then_else (ne (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
+       (if_then_else (ne (match_operand:P 1 "register_operand" "c,*r,*r,*r")
                          (const_int 1))
                      (pc)
                      (label_ref (match_operand 0 "" ""))))
-   (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
-       (plus:DI (match_dup 1)
-                (const_int -1)))
-   (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
-  "TARGET_64BIT"
-  "*
-{
-  if (which_alternative != 0)
-    return \"#\";
-  else if (get_attr_length (insn) == 4)
-    return \"bdz %l0\";
-  else
-    return \"{bdn|bdnz} $+8\;b %l0\";
-}"
-  [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
-
-;; Similar, but we can use GE since we have a REG_NONNEG.
-
-(define_insn "*ctrsi_internal3"
-  [(set (pc)
-       (if_then_else (ge (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
-                         (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))
-   (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
-       (plus:SI (match_dup 1)
-                (const_int -1)))
-   (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
-  "TARGET_32BIT && find_reg_note (insn, REG_NONNEG, 0)"
-  "*
-{
-  if (which_alternative != 0)
-    return \"#\";
-  else if (get_attr_length (insn) == 4)
-    return \"{bdn|bdnz} %l0\";
-  else
-    return \"bdz $+8\;b %l0\";
-}"
-  [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrsi_internal4"
-  [(set (pc)
-       (if_then_else (ge (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
-                         (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))
-   (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
-       (plus:SI (match_dup 1)
-                (const_int -1)))
-   (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
-  "TARGET_32BIT && find_reg_note (insn, REG_NONNEG, 0)"
-  "*
-{
-  if (which_alternative != 0)
-    return \"#\";
-  else if (get_attr_length (insn) == 4)
-    return \"bdz %l0\";
-  else
-    return \"{bdn|bdnz} $+8\;b %l0\";
-}"
-  [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrdi_internal3"
-  [(set (pc)
-       (if_then_else (ge (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
-                         (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))
-   (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
-       (plus:DI (match_dup 1)
-                (const_int -1)))
-   (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
-  "TARGET_64BIT && find_reg_note (insn, REG_NONNEG, 0)"
-  "*
-{
-  if (which_alternative != 0)
-    return \"#\";
-  else if (get_attr_length (insn) == 4)
-    return \"{bdn|bdnz} %l0\";
-  else
-    return \"bdz $+8\;b %l0\";
-}"
-  [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrdi_internal4"
-  [(set (pc)
-       (if_then_else (ge (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
-                         (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))
-   (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
-       (plus:DI (match_dup 1)
+   (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*q*c*l")
+       (plus:P (match_dup 1)
                 (const_int -1)))
    (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
-  "TARGET_64BIT && find_reg_note (insn, REG_NONNEG, 0)"
+   (clobber (match_scratch:P 4 "=X,X,&r,r"))]
+  ""
   "*
 {
   if (which_alternative != 0)
 
 ;; Similar but use EQ
 
-(define_insn "*ctrsi_internal5"
-  [(set (pc)
-       (if_then_else (eq (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
-                         (const_int 1))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))
-   (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
-       (plus:SI (match_dup 1)
-                (const_int -1)))
-   (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
-  "TARGET_32BIT"
-  "*
-{
-  if (which_alternative != 0)
-    return \"#\";
-  else if (get_attr_length (insn) == 4)
-    return \"bdz %l0\";
-  else
-    return \"{bdn|bdnz} $+8\;b %l0\";
-}"
-  [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrsi_internal6"
-  [(set (pc)
-       (if_then_else (eq (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
-                         (const_int 1))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))
-   (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
-       (plus:SI (match_dup 1)
-                (const_int -1)))
-   (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
-  "TARGET_32BIT"
-  "*
-{
-  if (which_alternative != 0)
-    return \"#\";
-  else if (get_attr_length (insn) == 4)
-    return \"{bdn|bdnz} %l0\";
-  else
-    return \"bdz $+8\;b %l0\";
-}"
-  [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrdi_internal5"
+(define_insn "*ctr<mode>_internal5"
   [(set (pc)
-       (if_then_else (eq (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
+       (if_then_else (eq (match_operand:P 1 "register_operand" "c,*r,*r,*r")
                          (const_int 1))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))
-   (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
-       (plus:DI (match_dup 1)
+   (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*q*c*l")
+       (plus:P (match_dup 1)
                 (const_int -1)))
    (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:P 4 "=X,X,&r,r"))]
+  ""
   "*
 {
   if (which_alternative != 0)
   [(set_attr "type" "branch")
    (set_attr "length" "*,12,16,16")])
 
-(define_insn "*ctrdi_internal6"
+(define_insn "*ctr<mode>_internal6"
   [(set (pc)
-       (if_then_else (eq (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
+       (if_then_else (eq (match_operand:P 1 "register_operand" "c,*r,*r,*r")
                          (const_int 1))
                      (pc)
                      (label_ref (match_operand 0 "" ""))))
-   (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
-       (plus:DI (match_dup 1)
+   (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*q*c*l")
+       (plus:P (match_dup 1)
                 (const_int -1)))
    (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:P 4 "=X,X,&r,r"))]
+  ""
   "*
 {
   if (which_alternative != 0)
 (define_split
   [(set (pc)
        (if_then_else (match_operator 2 "comparison_operator"
-                                     [(match_operand:SI 1 "gpc_reg_operand" "")
-                                      (const_int 1)])
-                     (match_operand 5 "" "")
-                     (match_operand 6 "" "")))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (match_dup 1)
-                (const_int -1)))
-   (clobber (match_scratch:CC 3 ""))
-   (clobber (match_scratch:SI 4 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(parallel [(set (match_dup 3)
-                  (compare:CC (plus:SI (match_dup 1)
-                                       (const_int -1))
-                              (const_int 0)))
-             (set (match_dup 0)
-                  (plus:SI (match_dup 1)
-                           (const_int -1)))])
-   (set (pc) (if_then_else (match_dup 7)
-                          (match_dup 5)
-                          (match_dup 6)))]
-  "
-{ operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode,
-                               operands[3], const0_rtx); }")
-
-(define_split
-  [(set (pc)
-       (if_then_else (match_operator 2 "comparison_operator"
-                                     [(match_operand:SI 1 "gpc_reg_operand" "")
-                                      (const_int 1)])
-                     (match_operand 5 "" "")
-                     (match_operand 6 "" "")))
-   (set (match_operand:SI 0 "nonimmediate_operand" "")
-       (plus:SI (match_dup 1) (const_int -1)))
-   (clobber (match_scratch:CC 3 ""))
-   (clobber (match_scratch:SI 4 ""))]
-  "TARGET_32BIT && reload_completed
-   && ! gpc_reg_operand (operands[0], SImode)"
-  [(parallel [(set (match_dup 3)
-                  (compare:CC (plus:SI (match_dup 1)
-                                       (const_int -1))
-                              (const_int 0)))
-             (set (match_dup 4)
-                  (plus:SI (match_dup 1)
-                           (const_int -1)))])
-   (set (match_dup 0)
-       (match_dup 4))
-   (set (pc) (if_then_else (match_dup 7)
-                          (match_dup 5)
-                          (match_dup 6)))]
-  "
-{ operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode,
-                               operands[3], const0_rtx); }")
-(define_split
-  [(set (pc)
-       (if_then_else (match_operator 2 "comparison_operator"
-                                     [(match_operand:DI 1 "gpc_reg_operand" "")
+                                     [(match_operand:P 1 "gpc_reg_operand" "")
                                       (const_int 1)])
                      (match_operand 5 "" "")
                      (match_operand 6 "" "")))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (plus:DI (match_dup 1)
-                (const_int -1)))
+   (set (match_operand:P 0 "gpc_reg_operand" "")
+       (plus:P (match_dup 1) (const_int -1)))
    (clobber (match_scratch:CC 3 ""))
-   (clobber (match_scratch:DI 4 ""))]
-  "TARGET_64BIT && reload_completed"
+   (clobber (match_scratch:P 4 ""))]
+  "reload_completed"
   [(parallel [(set (match_dup 3)
-                  (compare:CC (plus:DI (match_dup 1)
+                  (compare:CC (plus:P (match_dup 1)
                                        (const_int -1))
                               (const_int 0)))
              (set (match_dup 0)
-                  (plus:DI (match_dup 1)
+                  (plus:P (match_dup 1)
                            (const_int -1)))])
    (set (pc) (if_then_else (match_dup 7)
                           (match_dup 5)
 (define_split
   [(set (pc)
        (if_then_else (match_operator 2 "comparison_operator"
-                                     [(match_operand:DI 1 "gpc_reg_operand" "")
+                                     [(match_operand:P 1 "gpc_reg_operand" "")
                                       (const_int 1)])
                      (match_operand 5 "" "")
                      (match_operand 6 "" "")))
-   (set (match_operand:DI 0 "nonimmediate_operand" "")
-       (plus:DI (match_dup 1) (const_int -1)))
+   (set (match_operand:P 0 "nonimmediate_operand" "")
+       (plus:P (match_dup 1) (const_int -1)))
    (clobber (match_scratch:CC 3 ""))
-   (clobber (match_scratch:DI 4 ""))]
-  "TARGET_64BIT && reload_completed
-   && ! gpc_reg_operand (operands[0], DImode)"
+   (clobber (match_scratch:P 4 ""))]
+  "reload_completed && ! gpc_reg_operand (operands[0], SImode)"
   [(parallel [(set (match_dup 3)
-                  (compare:CC (plus:DI (match_dup 1)
+                  (compare:CC (plus:P (match_dup 1)
                                        (const_int -1))
                               (const_int 0)))
              (set (match_dup 4)
-                  (plus:DI (match_dup 1)
+                  (plus:P (match_dup 1)
                            (const_int -1)))])
    (set (match_dup 0)
        (match_dup 4))
 
 (define_insn ""
   [(trap_if (match_operator 0 "trap_comparison_operator"
-                            [(match_operand:SI 1 "register_operand" "r")
-                             (match_operand:SI 2 "reg_or_short_operand" "rI")])
+                            [(match_operand:GPR 1 "register_operand" "r")
+                             (match_operand:GPR 2 "reg_or_short_operand" "rI")])
            (const_int 0))]
   ""
-  "{t|tw}%V0%I2 %1,%2")
-
-(define_insn ""
-  [(trap_if (match_operator 0 "trap_comparison_operator"
-                            [(match_operand:DI 1 "register_operand" "r")
-                             (match_operand:DI 2 "reg_or_short_operand" "rI")])
-           (const_int 0))]
-  "TARGET_POWERPC64"
-  "td%V0%I2 %1,%2")
+  "{t|t<wd>}%V0%I2 %1,%2")
 \f
 ;; Insns related to generating the function prologue and epilogue.
 
   "TARGET_MULTIPLE"
   "{stm|stmw} %2,%1")
 
-(define_insn "*save_fpregs_si"
-  [(match_parallel 0 "any_operand"
-                  [(clobber (match_operand:SI 1 "register_operand" "=l"))
-                   (use (match_operand:SI 2 "call_operand" "s"))
-                   (set (match_operand:DF 3 "memory_operand" "=m")
-                        (match_operand:DF 4 "gpc_reg_operand" "f"))])]
-  "TARGET_32BIT"
-  "bl %z2"
-  [(set_attr "type" "branch")
-   (set_attr "length" "4")])
-
-(define_insn "*save_fpregs_di"
-  [(match_parallel 0 "any_operand"
-                  [(clobber (match_operand:DI 1 "register_operand" "=l"))
-                   (use (match_operand:DI 2 "call_operand" "s"))
+(define_insn "*save_fpregs_<mode>"
+  [(match_parallel 0 "any_parallel_operand"
+                  [(clobber (match_operand:P 1 "register_operand" "=l"))
+                   (use (match_operand:P 2 "call_operand" "s"))
                    (set (match_operand:DF 3 "memory_operand" "=m")
                         (match_operand:DF 4 "gpc_reg_operand" "f"))])]
-  "TARGET_64BIT"
+  ""
   "bl %z2"
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
   "TARGET_MULTIPLE"
   "{lm|lmw} %1,%2")
 
-(define_insn "*return_internal_si"
-  [(return)
-   (use (match_operand:SI 0 "register_operand" "lc"))]
-  "TARGET_32BIT"
-  "b%T0"
-  [(set_attr "type" "jmpreg")])
-
-(define_insn "*return_internal_di"
+(define_insn "*return_internal_<mode>"
   [(return)
-   (use (match_operand:DI 0 "register_operand" "lc"))]
-  "TARGET_64BIT"
+   (use (match_operand:P 0 "register_operand" "lc"))]
+  ""
   "b%T0"
   [(set_attr "type" "jmpreg")])
 
 ; FIXME: This would probably be somewhat simpler if the Cygnus sibcall
-; stuff was in GCC.  Oh, and "any_operand" is a bit flexible...
-
-(define_insn "*return_and_restore_fpregs_si"
- [(match_parallel 0 "any_operand"
-                  [(return)
-                  (use (match_operand:SI 1 "register_operand" "l"))
-                  (use (match_operand:SI 2 "call_operand" "s"))
-                  (set (match_operand:DF 3 "gpc_reg_operand" "=f")
-                       (match_operand:DF 4 "memory_operand" "m"))])]
- "TARGET_32BIT"
- "b %z2")
+; stuff was in GCC.  Oh, and "any_parallel_operand" is a bit flexible...
 
-(define_insn "*return_and_restore_fpregs_di"
- [(match_parallel 0 "any_operand"
+(define_insn "*return_and_restore_fpregs_<mode>"
+ [(match_parallel 0 "any_parallel_operand"
                   [(return)
-                  (use (match_operand:DI 1 "register_operand" "l"))
-                  (use (match_operand:DI 2 "call_operand" "s"))
+                  (use (match_operand:P 1 "register_operand" "l"))
+                  (use (match_operand:P 2 "call_operand" "s"))
                   (set (match_operand:DF 3 "gpc_reg_operand" "=f")
                        (match_operand:DF 4 "memory_operand" "m"))])]
- "TARGET_64BIT"
+ ""
  "b %z2")
 
 ; This is used in compiling the unwind routines.
 }")
 
 ; We can't expand this before we know where the link register is stored.
-(define_insn "eh_set_lr_si"
-  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
-                   UNSPECV_EH_RR)
-   (clobber (match_scratch:SI 1 "=&b"))]
-  "TARGET_32BIT"
-  "#")
-
-(define_insn "eh_set_lr_di"
-  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
+(define_insn "eh_set_lr_<mode>"
+  [(unspec_volatile [(match_operand:P 0 "register_operand" "r")]
                    UNSPECV_EH_RR)
-   (clobber (match_scratch:DI 1 "=&b"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:P 1 "=&b"))]
+  ""
   "#")
 
 (define_split
   return INTVAL (operands[1]) ? \"dcbtst %a0\" : \"dcbt %a0\";
 }"
   [(set_attr "type" "load")])
+\f
 
+(include "sync.md")
 (include "altivec.md")
 (include "spe.md")