OSDN Git Service

PR target/26481
[pf3gnuchains/gcc-fork.git] / gcc / config / rs6000 / rs6000.md
index fc4b6f1..576ffbf 100644 (file)
@@ -1,6 +1,7 @@
 ;; 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, 2005 Free Software Foundation, Inc.
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+;; Free Software Foundation, Inc.
 ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 ;; This file is part of GCC.
@@ -17,8 +18,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_MOVSI_GOT           8)
    (UNSPEC_MV_CR_OV            9)      ; move_from_CR_ov_bit
    (UNSPEC_FCTIWZ              10)
+   (UNSPEC_FRIM                        11)
+   (UNSPEC_FRIN                        12)
+   (UNSPEC_FRIP                        13)
+   (UNSPEC_FRIZ                        14)
    (UNSPEC_LD_MPIC             15)     ; load_macho_picbase
    (UNSPEC_MPIC_CORRECT                16)     ; macho_correct_pic
    (UNSPEC_TLSGD               17)
    (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_POPCNTB             33)
+   (UNSPEC_FRES                        34)
+   (UNSPEC_SP_SET              35)
+   (UNSPEC_SP_TEST             36)
+   (UNSPEC_SYNC                        37)
+   (UNSPEC_LWSYNC              38)
+   (UNSPEC_ISYNC               39)
+   (UNSPEC_SYNC_OP             40)
+   (UNSPEC_ATOMIC              41)
+   (UNSPEC_CMPXCHG             42)
+   (UNSPEC_XCHG                        43)
+   (UNSPEC_AND                 44)
+   (UNSPEC_DLMZB               45)
+   (UNSPEC_DLMZB_CR            46)
+   (UNSPEC_DLMZB_STRLEN                47)
   ])
 
 ;;
 
 (define_constants
   [(UNSPECV_BLOCK              0)
+   (UNSPECV_LL                 1)      ; load-locked
+   (UNSPECV_SC                 2)      ; store-conditional
    (UNSPECV_EH_RR              9)      ; eh_reg_restore
   ])
 \f
 ;; Define an insn type attribute.  This is used in function unit delay
 ;; computations.
-(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"
+(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,isync,sync,load_l,store_c"
   (const_string "integer"))
 
 ;; Length (in bytes).
 (include "power5.md")
 
 (include "predicates.md")
+(include "constraints.md")
 
 (include "darwin.md")
 
 \f
-;; This mode macro allows :P to be used for patterns that operate on
-;; pointer-sized quantities.  Exactly one of the two alternatives will match.
-(define_mode_macro P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
+;; 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")])
+
+; extend modes for DImode
+(define_mode_macro QHSI [QI HI SI])
+
+; 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 "!TARGET_IEEEQUAD
+   && 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 [(QI "b") (HI "h") (SI "w") (DI "d")])
+
+; DImode bits
+(define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
+
+\f
 ;; Start with fixed-point load and store insns.  Here we put only the more
 ;; complex forms.  Basic data transfer is done later.
 
-(define_expand "zero_extendqidi2"
+(define_expand "zero_extend<mode>di2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" "")))]
+       (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" "")))]
   "TARGET_POWERPC64"
   "")
 
-(define_insn ""
+(define_insn "*zero_extend<mode>di2_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
+       (zero_extend:DI (match_operand:QHSI 1 "reg_or_mem_operand" "m,r")))]
   "TARGET_POWERPC64"
   "@
-   lbz%U1%X1 %0,%1
-   rldicl %0,%1,0,56"
+   l<wd>z%U1%X1 %0,%1
+   rldicl %0,%1,0,<dbits>"
   [(set_attr "type" "load,*")])
 
-(define_insn ""
+(define_insn "*zero_extend<mode>di2_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
    (clobber (match_scratch:DI 2 "=r,r"))]
   "TARGET_64BIT"
   "@
-   rldicl. %2,%1,0,56
+   rldicl. %2,%1,0,<dbits>
    #"
   [(set_attr "type" "compare")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" ""))
+       (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" ""))
                    (const_int 0)))
    (clobber (match_scratch:DI 2 ""))]
   "TARGET_POWERPC64 && reload_completed"
                    (const_int 0)))]
   "")
 
-(define_insn ""
+(define_insn "*zero_extend<mode>di2_internal3"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (zero_extend:DI (match_dup 1)))]
   "TARGET_64BIT"
   "@
-   rldicl. %0,%1,0,56
+   rldicl. %0,%1,0,<dbits>
    #"
   [(set_attr "type" "compare")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" ""))
+       (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" ""))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
        (zero_extend:DI (match_dup 1)))]
                    (const_int 0)))]
   "")
 
-(define_expand "zero_extendhidi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" "")))]
-  "TARGET_POWERPC64"
-  "")
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
-  "TARGET_POWERPC64"
-  "@
-   lhz%U1%X1 %0,%1
-   rldicl %0,%1,0,48"
-  [(set_attr "type" "load,*")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 "=r,r"))]
-  "TARGET_64BIT"
-  "@
-   rldicl. %2,%1,0,48
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2)
-       (zero_extend: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 (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI (match_dup 1)))]
-  "TARGET_64BIT"
-  "@
-   rldicl. %0,%1,0,48
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (match_dup 1)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
 (define_expand "extendhidi2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" "")))]
                    (const_int 0)))]
   "")
 
-(define_expand "zero_extendsidi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")))]
-  "TARGET_POWERPC64"
-  "")
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "m,r")))]
-  "TARGET_POWERPC64"
-  "@
-   lwz%U1%X1 %0,%1
-   rldicl %0,%1,0,32"
-  [(set_attr "type" "load,*")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 "=r,r"))]
-  "TARGET_64BIT"
-  "@
-   rldicl. %2,%1,0,32
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2)
-       (zero_extend: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 (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI (match_dup 1)))]
-  "TARGET_64BIT"
-  "@
-   rldicl. %0,%1,0,32
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (match_dup 1)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
 (define_expand "extendsidi2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")))]
   [(set_attr "type" "compare")
    (set_attr "length" "4,8")])
 \f
+;; IBM 405 and 440 half-word multiplication operations.
+
+(define_insn "*macchwc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (plus:SI (mult:SI (ashiftrt:SI
+                                       (match_operand:SI 2 "gpc_reg_operand" "r")
+                                       (const_int 16))
+                                      (sign_extend:SI
+                                       (match_operand:HI 1 "gpc_reg_operand" "r")))
+                             (match_operand:SI 4 "gpc_reg_operand" "0"))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (ashiftrt:SI
+                           (match_dup 2)
+                           (const_int 16))
+                          (sign_extend:SI
+                           (match_dup 1)))
+                 (match_dup 4)))]
+  "TARGET_MULHW"
+  "macchw. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*macchw"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (ashiftrt:SI
+                           (match_operand:SI 2 "gpc_reg_operand" "r")
+                           (const_int 16))
+                          (sign_extend:SI
+                           (match_operand:HI 1 "gpc_reg_operand" "r")))
+                 (match_operand:SI 3 "gpc_reg_operand" "0")))]
+  "TARGET_MULHW"
+  "macchw %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*macchwuc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (plus:SI (mult:SI (lshiftrt:SI
+                                       (match_operand:SI 2 "gpc_reg_operand" "r")
+                                       (const_int 16))
+                                      (zero_extend:SI
+                                       (match_operand:HI 1 "gpc_reg_operand" "r")))
+                             (match_operand:SI 4 "gpc_reg_operand" "0"))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (lshiftrt:SI
+                           (match_dup 2)
+                           (const_int 16))
+                          (zero_extend:SI
+                           (match_dup 1)))
+                 (match_dup 4)))]
+  "TARGET_MULHW"
+  "macchwu. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*macchwu"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (lshiftrt:SI
+                           (match_operand:SI 2 "gpc_reg_operand" "r")
+                           (const_int 16))
+                          (zero_extend:SI
+                           (match_operand:HI 1 "gpc_reg_operand" "r")))
+                 (match_operand:SI 3 "gpc_reg_operand" "0")))]
+  "TARGET_MULHW"
+  "macchwu %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*machhwc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (plus:SI (mult:SI (ashiftrt:SI
+                                       (match_operand:SI 1 "gpc_reg_operand" "%r")
+                                       (const_int 16))
+                                      (ashiftrt:SI
+                                       (match_operand:SI 2 "gpc_reg_operand" "r")
+                                       (const_int 16)))
+                             (match_operand:SI 4 "gpc_reg_operand" "0"))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (ashiftrt:SI
+                           (match_dup 1)
+                           (const_int 16))
+                          (ashiftrt:SI
+                           (match_dup 2)
+                           (const_int 16)))
+                 (match_dup 4)))]
+  "TARGET_MULHW"
+  "machhw. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*machhw"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (ashiftrt:SI
+                           (match_operand:SI 1 "gpc_reg_operand" "%r")
+                           (const_int 16))
+                          (ashiftrt:SI
+                           (match_operand:SI 2 "gpc_reg_operand" "r")
+                           (const_int 16)))
+                 (match_operand:SI 3 "gpc_reg_operand" "0")))]
+  "TARGET_MULHW"
+  "machhw %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*machhwuc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (plus:SI (mult:SI (lshiftrt:SI
+                                       (match_operand:SI 1 "gpc_reg_operand" "%r")
+                                       (const_int 16))
+                                      (lshiftrt:SI
+                                       (match_operand:SI 2 "gpc_reg_operand" "r")
+                                       (const_int 16)))
+                             (match_operand:SI 4 "gpc_reg_operand" "0"))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (lshiftrt:SI
+                           (match_dup 1)
+                           (const_int 16))
+                          (lshiftrt:SI
+                           (match_dup 2)
+                           (const_int 16)))
+                 (match_dup 4)))]
+  "TARGET_MULHW"
+  "machhwu. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*machhwu"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (lshiftrt:SI
+                           (match_operand:SI 1 "gpc_reg_operand" "%r")
+                           (const_int 16))
+                          (lshiftrt:SI
+                           (match_operand:SI 2 "gpc_reg_operand" "r")
+                           (const_int 16)))
+                 (match_operand:SI 3 "gpc_reg_operand" "0")))]
+  "TARGET_MULHW"
+  "machhwu %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*maclhwc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (plus:SI (mult:SI (sign_extend:SI
+                                       (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                                      (sign_extend:SI
+                                       (match_operand:HI 2 "gpc_reg_operand" "r")))
+                             (match_operand:SI 4 "gpc_reg_operand" "0"))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (sign_extend:SI
+                           (match_dup 1))
+                          (sign_extend:SI
+                           (match_dup 2)))
+                 (match_dup 4)))]
+  "TARGET_MULHW"
+  "maclhw. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*maclhw"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (sign_extend:SI
+                           (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                          (sign_extend:SI
+                           (match_operand:HI 2 "gpc_reg_operand" "r")))
+                 (match_operand:SI 3 "gpc_reg_operand" "0")))]
+  "TARGET_MULHW"
+  "maclhw %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*maclhwuc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (plus:SI (mult:SI (zero_extend:SI
+                                       (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                                      (zero_extend:SI
+                                       (match_operand:HI 2 "gpc_reg_operand" "r")))
+                             (match_operand:SI 4 "gpc_reg_operand" "0"))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (zero_extend:SI
+                           (match_dup 1))
+                          (zero_extend:SI
+                           (match_dup 2)))
+                 (match_dup 4)))]
+  "TARGET_MULHW"
+  "maclhwu. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*maclhwu"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (plus:SI (mult:SI (zero_extend:SI
+                           (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                          (zero_extend:SI
+                           (match_operand:HI 2 "gpc_reg_operand" "r")))
+                 (match_operand:SI 3 "gpc_reg_operand" "0")))]
+  "TARGET_MULHW"
+  "maclhwu %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*nmacchwc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+                              (mult:SI (ashiftrt:SI
+                                        (match_operand:SI 2 "gpc_reg_operand" "r")
+                                        (const_int 16))
+                                       (sign_extend:SI
+                                        (match_operand:HI 1 "gpc_reg_operand" "r"))))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (minus:SI (match_dup 4)
+                  (mult:SI (ashiftrt:SI
+                            (match_dup 2)
+                            (const_int 16))
+                           (sign_extend:SI
+                            (match_dup 1)))))]
+  "TARGET_MULHW"
+  "nmacchw. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*nmacchw"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
+                  (mult:SI (ashiftrt:SI
+                            (match_operand:SI 2 "gpc_reg_operand" "r")
+                            (const_int 16))
+                           (sign_extend:SI
+                            (match_operand:HI 1 "gpc_reg_operand" "r")))))]
+  "TARGET_MULHW"
+  "nmacchw %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*nmachhwc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+                              (mult:SI (ashiftrt:SI
+                                        (match_operand:SI 1 "gpc_reg_operand" "%r")
+                                        (const_int 16))
+                                       (ashiftrt:SI
+                                        (match_operand:SI 2 "gpc_reg_operand" "r")
+                                        (const_int 16))))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (minus:SI (match_dup 4)
+                  (mult:SI (ashiftrt:SI
+                            (match_dup 1)
+                            (const_int 16))
+                           (ashiftrt:SI
+                            (match_dup 2)
+                            (const_int 16)))))]
+  "TARGET_MULHW"
+  "nmachhw. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*nmachhw"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
+                  (mult:SI (ashiftrt:SI
+                            (match_operand:SI 1 "gpc_reg_operand" "%r")
+                            (const_int 16))
+                           (ashiftrt:SI
+                            (match_operand:SI 2 "gpc_reg_operand" "r")
+                            (const_int 16)))))]
+  "TARGET_MULHW"
+  "nmachhw %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*nmaclhwc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+                              (mult:SI (sign_extend:SI
+                                        (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                                       (sign_extend:SI
+                                        (match_operand:HI 2 "gpc_reg_operand" "r"))))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (minus:SI (match_dup 4)
+                  (mult:SI (sign_extend:SI
+                            (match_dup 1))
+                           (sign_extend:SI
+                            (match_dup 2)))))]
+  "TARGET_MULHW"
+  "nmaclhw. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*nmaclhw"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
+                  (mult:SI (sign_extend:SI
+                            (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                           (sign_extend:SI
+                            (match_operand:HI 2 "gpc_reg_operand" "r")))))]
+  "TARGET_MULHW"
+  "nmaclhw %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mulchwc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (mult:SI (ashiftrt:SI
+                              (match_operand:SI 2 "gpc_reg_operand" "r")
+                              (const_int 16))
+                             (sign_extend:SI
+                              (match_operand:HI 1 "gpc_reg_operand" "r")))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (ashiftrt:SI
+                  (match_dup 2)
+                  (const_int 16))
+                 (sign_extend:SI
+                  (match_dup 1))))]
+  "TARGET_MULHW"
+  "mulchw. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mulchw"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (ashiftrt:SI
+                  (match_operand:SI 2 "gpc_reg_operand" "r")
+                  (const_int 16))
+                 (sign_extend:SI
+                  (match_operand:HI 1 "gpc_reg_operand" "r"))))]
+  "TARGET_MULHW"
+  "mulchw %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mulchwuc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (mult:SI (lshiftrt:SI
+                              (match_operand:SI 2 "gpc_reg_operand" "r")
+                              (const_int 16))
+                             (zero_extend:SI
+                              (match_operand:HI 1 "gpc_reg_operand" "r")))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (lshiftrt:SI
+                  (match_dup 2)
+                  (const_int 16))
+                 (zero_extend:SI
+                  (match_dup 1))))]
+  "TARGET_MULHW"
+  "mulchwu. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mulchwu"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (lshiftrt:SI
+                  (match_operand:SI 2 "gpc_reg_operand" "r")
+                  (const_int 16))
+                 (zero_extend:SI
+                  (match_operand:HI 1 "gpc_reg_operand" "r"))))]
+  "TARGET_MULHW"
+  "mulchwu %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mulhhwc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (mult:SI (ashiftrt:SI
+                              (match_operand:SI 1 "gpc_reg_operand" "%r")
+                              (const_int 16))
+                             (ashiftrt:SI
+                              (match_operand:SI 2 "gpc_reg_operand" "r")
+                              (const_int 16)))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (ashiftrt:SI
+                  (match_dup 1)
+                  (const_int 16))
+                 (ashiftrt:SI
+                  (match_dup 2)
+                  (const_int 16))))]
+  "TARGET_MULHW"
+  "mulhhw. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mulhhw"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (ashiftrt:SI
+                  (match_operand:SI 1 "gpc_reg_operand" "%r")
+                  (const_int 16))
+                 (ashiftrt:SI
+                  (match_operand:SI 2 "gpc_reg_operand" "r")
+                  (const_int 16))))]
+  "TARGET_MULHW"
+  "mulhhw %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mulhhwuc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (mult:SI (lshiftrt:SI
+                              (match_operand:SI 1 "gpc_reg_operand" "%r")
+                              (const_int 16))
+                             (lshiftrt:SI
+                              (match_operand:SI 2 "gpc_reg_operand" "r")
+                              (const_int 16)))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (lshiftrt:SI
+                  (match_dup 1)
+                  (const_int 16))
+                 (lshiftrt:SI
+                  (match_dup 2)
+                  (const_int 16))))]
+  "TARGET_MULHW"
+  "mulhhwu. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mulhhwu"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (lshiftrt:SI
+                  (match_operand:SI 1 "gpc_reg_operand" "%r")
+                  (const_int 16))
+                 (lshiftrt:SI
+                  (match_operand:SI 2 "gpc_reg_operand" "r")
+                  (const_int 16))))]
+  "TARGET_MULHW"
+  "mulhhwu %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mullhwc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (mult:SI (sign_extend:SI
+                              (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                             (sign_extend:SI
+                              (match_operand:HI 2 "gpc_reg_operand" "r")))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (sign_extend:SI
+                  (match_dup 1))
+                 (sign_extend:SI
+                  (match_dup 2))))]
+  "TARGET_MULHW"
+  "mullhw. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mullhw"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (sign_extend:SI
+                  (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                 (sign_extend:SI
+                  (match_operand:HI 2 "gpc_reg_operand" "r"))))]
+  "TARGET_MULHW"
+  "mullhw %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mullhwuc"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (compare:CC (mult:SI (zero_extend:SI
+                              (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                             (zero_extend:SI
+                              (match_operand:HI 2 "gpc_reg_operand" "r")))
+                    (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (zero_extend:SI
+                  (match_dup 1))
+                 (zero_extend:SI
+                  (match_dup 2))))]
+  "TARGET_MULHW"
+  "mullhwu. %0, %1, %2"
+  [(set_attr "type" "imul3")])
+
+(define_insn "*mullhwu"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mult:SI (zero_extend:SI
+                  (match_operand:HI 1 "gpc_reg_operand" "%r"))
+                 (zero_extend:SI
+                  (match_operand:HI 2 "gpc_reg_operand" "r"))))]
+  "TARGET_MULHW"
+  "mullhwu %0, %1, %2"
+  [(set_attr "type" "imul3")])
+\f
+;; IBM 405 and 440 string-search dlmzb instruction support.
+(define_insn "dlmzb"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+        (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+                    (match_operand:SI 2 "gpc_reg_operand" "r")]
+                   UNSPEC_DLMZB_CR))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (unspec:SI [(match_dup 1)
+                    (match_dup 2)]
+                   UNSPEC_DLMZB))]
+  "TARGET_DLMZB"
+  "dlmzb. %0, %1, %2")
+
+(define_expand "strlensi"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "")
+        (unspec:SI [(match_operand:BLK 1 "general_operand" "")
+                    (match_operand:QI 2 "const_int_operand" "")
+                    (match_operand 3 "const_int_operand" "")]
+                   UNSPEC_DLMZB_STRLEN))
+   (clobber (match_scratch:CC 4 "=x"))]
+  "TARGET_DLMZB && WORDS_BIG_ENDIAN && !optimize_size"
+{
+  rtx result = operands[0];
+  rtx src = operands[1];
+  rtx search_char = operands[2];
+  rtx align = operands[3];
+  rtx addr, scratch_string, word1, word2, scratch_dlmzb;
+  rtx loop_label, end_label, mem, cr0, cond;
+  if (search_char != const0_rtx
+      || GET_CODE (align) != CONST_INT
+      || INTVAL (align) < 8)
+        FAIL;
+  word1 = gen_reg_rtx (SImode);
+  word2 = gen_reg_rtx (SImode);
+  scratch_dlmzb = gen_reg_rtx (SImode);
+  scratch_string = gen_reg_rtx (Pmode);
+  loop_label = gen_label_rtx ();
+  end_label = gen_label_rtx ();
+  addr = force_reg (Pmode, XEXP (src, 0));
+  emit_move_insn (scratch_string, addr);
+  emit_label (loop_label);
+  mem = change_address (src, SImode, scratch_string);
+  emit_move_insn (word1, mem);
+  emit_move_insn (word2, adjust_address (mem, SImode, 4));
+  cr0 = gen_rtx_REG (CCmode, CR0_REGNO);
+  emit_insn (gen_dlmzb (scratch_dlmzb, word1, word2, cr0));
+  cond = gen_rtx_NE (VOIDmode, cr0, const0_rtx);
+  emit_jump_insn (gen_rtx_SET (VOIDmode,
+                               pc_rtx,
+                               gen_rtx_IF_THEN_ELSE (VOIDmode,
+                                                     cond,
+                                                     gen_rtx_LABEL_REF
+                                                       (VOIDmode,
+                                                        end_label),
+                                                     pc_rtx)));
+  emit_insn (gen_addsi3 (scratch_string, scratch_string, GEN_INT (8)));
+  emit_jump_insn (gen_rtx_SET (VOIDmode,
+                               pc_rtx,
+                               gen_rtx_LABEL_REF (VOIDmode, loop_label)));
+  emit_barrier ();
+  emit_label (end_label);
+  emit_insn (gen_addsi3 (scratch_string, scratch_string, scratch_dlmzb));
+  emit_insn (gen_subsi3 (result, scratch_string, addr));
+  emit_insn (gen_subsi3 (result, result, const1_rtx));
+  DONE;
+})
+\f
 (define_split
   [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
        (compare:CC (sign_extend:SI (match_operand:HI 1 "gpc_reg_operand" ""))
 
 ;; 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 && !satisfies_constraint_L (GEN_INT (rest)))
+       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 || satisfies_constraint_L (GEN_INT (rest)))
+    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"
+  "{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)))]
 
 (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 (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])"
   "*
                    (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"))
    #
    fmr %0,%1
    lfs%U1%X1 %0,%1"
-  "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])"
+  "&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])"
   [(const_int 0)]
 {
   emit_note (NOTE_INSN_DELETED);
   "{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")
   "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
    && ! HONOR_SIGNED_ZEROS (SFmode)"
   "{fnms|fnmsub} %0,%1,%2,%3"
-  [(set_attr "type" "fp")])
+  [(set_attr "type" "dmul")])
 
 (define_expand "sqrtsf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
                         (match_dup 3)
                         (match_dup 4)))]
   "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
-   && !HONOR_NANS (SFmode) && !HONOR_SIGNED_ZEROS (SFmode)" 
+   && !HONOR_NANS (SFmode) && !HONOR_SIGNED_ZEROS (SFmode)"
   {
      operands[3] = gen_reg_rtx (SFmode);
      operands[4] = gen_reg_rtx (SFmode);
   "{fm|fmul} %0,%1,%2"
   [(set_attr "type" "dmul")])
 
+(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")
   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" "")
   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))])]
      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")])
 
+(define_insn "btruncdf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+       (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
+  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "friz %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "btruncsf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
+  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "friz %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "ceildf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+       (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIP))]
+  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "frip %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "ceilsf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIP))]
+  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "frip %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "floordf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+       (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIM))]
+  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "frim %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "floorsf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIM))]
+  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "frim %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "rounddf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+       (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
+  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "frin %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "roundsf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
+  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "frin %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" "")))]
    (set (match_dup 0) (plus:DI (match_dup 0)
                               (const_int 2047)))
    (set (match_dup 4) (compare:CCUNS (match_dup 3)
-                                    (const_int 3)))
+                                    (const_int 2)))
    (set (match_dup 0) (ior:DI (match_dup 0)
                              (match_dup 1)))
    (parallel [(set (match_dup 0) (and:DI (match_dup 0)
 \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,r")
+        (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
+                 (match_operand:DI 2 "reg_or_short_operand" "r,I")))]
   "TARGET_POWERPC64"
   "@
-   add %0,%1,%2
-   addi %0,%1,%2
-   addic %0,%1,%2
-   addis %0,%1,%v2")
+   mulld %0,%1,%2
+   mulli %0,%1,%2"
+   [(set (attr "type")
+      (cond [(match_operand:SI 2 "s8bit_cint_operand" "")
+               (const_string "imul3")
+            (match_operand:SI 2 "short_cint_operand" "")
+               (const_string "imul2")]
+       (const_string "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_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_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 "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"
-  [(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);
-
-  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 "one_cmpldi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (not:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
-  "TARGET_POWERPC64"
-  "nor %0,%1,%1")
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 "=r,r"))]
-  "TARGET_64BIT"
-  "@
-   nor. %2,%1,%1
-   #"
-  [(set_attr "type" "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" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2)
-       (not: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 (not:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (not:DI (match_dup 1)))]
-  "TARGET_64BIT"
-  "@
-   nor. %0,%1,%1
-   #"
-  [(set_attr "type" "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 "type" "two")
-   (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")])
+  "mulhdu %0,%1,%2"
+  [(set_attr "type" "lmul")])
 
 (define_insn "rotldi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
   "@
    rldic. %4,%1,%H2,%W3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "compare")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    rldic. %0,%1,%H2,%W3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "compare")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    rldicr. %4,%1,%H2,%S3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "compare")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    rldicr. %0,%1,%H2,%S3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "compare")
    (set_attr "length" "4,8")])
 
 (define_split
    (clobber (match_scratch:CC 3 ""))]
   "TARGET_POWERPC64
     && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
+    && !mask_operand (operands[2], DImode)
     && !mask64_operand (operands[2], DImode)"
   [(set (match_dup 0)
        (and:DI (rotate:DI (match_dup 1)
 })
 
 (define_insn "*anddi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
-       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
-                           (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,x,?y,?y,?y,??y,??y,?y")
+       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r,r,r")
+                           (match_operand:DI 2 "and64_2_operand" "r,S,T,K,J,t,r,S,T,K,J,t"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r,r,r"))
-   (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
+   (clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r,r,r,r,r"))
+   (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,X,X,x,x,X"))]
   "TARGET_64BIT"
   "@
    and. %3,%1,%2
    rldic%B2. %3,%1,0,%S2
+   rlwinm. %3,%1,0,%m2,%M2
    andi. %3,%1,%b2
    andis. %3,%1,%u2
    #
    #
    #
    #
+   #
    #"
-  [(set_attr "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
-   (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)))]
-  "")
+  [(set_attr "type" "compare,compare,compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
+   (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_operand" "")
                     (const_int 0)))
    (clobber (match_scratch:DI 3 ""))
    (clobber (match_scratch:CC 4 ""))]
-  "TARGET_POWERPC64 && reload_completed
+  "TARGET_64BIT && reload_completed
     && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
+    && !mask_operand (operands[2], DImode)
     && !mask64_operand (operands[2], DImode)"
   [(set (match_dup 3)
        (and:DI (rotate:DI (match_dup 1)
 }")
 
 (define_insn "*anddi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
-       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
-                           (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,x,x,?y,?y,?y,??y,??y,?y")
+       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r,r,r")
+                           (match_operand:DI 2 "and64_2_operand" "r,S,T,K,J,t,r,S,T,K,J,t"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r,r,r")
        (and:DI (match_dup 1) (match_dup 2)))
-   (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
+   (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,X,X,x,x,X"))]
   "TARGET_64BIT"
   "@
    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 "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
-   (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
+  [(set_attr "type" "compare,compare,compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
+   (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
 
 (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 "and64_2_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"
+  "TARGET_64BIT && reload_completed"
   [(parallel [(set (match_dup 0)
                    (and:DI (match_dup 1) (match_dup 2)))
               (clobber (match_dup 4))])
    (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
+  "TARGET_64BIT && reload_completed
     && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
+    && !mask_operand (operands[2], DImode)
     && !mask64_operand (operands[2], DImode)"
   [(set (match_dup 0)
        (and:DI (rotate:DI (match_dup 1)
 \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")
-
-
 ;; 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")
     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")
 }")
 
 (define_insn "*movsf_hardfloat"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=!r,!r,m,f,f,m,!cl,!q,!r,!h,!r,!r")
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=!r,!r,m,f,f,m,*c*l,*q,!r,*h,!r,!r")
        (match_operand:SF 1 "input_operand" "r,m,r,f,m,f,r,r,h,0,G,Fn"))]
   "(gpc_reg_operand (operands[0], SFmode)
    || gpc_reg_operand (operands[1], SFmode))
    {cror 0,0,0|nop}
    #
    #"
-  [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,mtjmpr,*,*,*,*")
+  [(set_attr "type" "*,load,store,fp,fpload,fpstore,mtjmpr,*,mfjmpr,*,*,*")
    (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,8")])
 
 (define_insn "*movsf_softfloat"
    #
    #
    {cror 0,0,0|nop}"
-  [(set_attr "type" "*,mtjmpr,*,*,load,store,*,*,*,*,*,*")
+  [(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*,*")
    (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,4")])
 
 \f
 
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (match_operand:DF 1 "easy_fp_constant" ""))]
+       (match_operand:DF 1 "const_double_operand" ""))]
   "TARGET_POWERPC64 && reload_completed
    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
        || (GET_CODE (operands[0]) == SUBREG
   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 (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
+      if (rs6000_offsettable_memref_p (operands[1])
+         || (GET_CODE (operands[1]) == MEM
+             && (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 (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
+      if (rs6000_offsettable_memref_p (operands[0])
+         || (GET_CODE (operands[0]) == MEM
+             && (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
        {
   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
 ; ld/std require word-aligned displacements -> 'Y' constraint.
 ; List Y->r and r->Y before r->r for reload.
 (define_insn "*movdf_hardfloat64"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,!cl,!r,!h,!r,!r,!r")
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r")
        (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
   "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
    && (gpc_reg_operand (operands[0], DFmode)
    #
    #
    #"
-  [(set_attr "type" "*,load,store,fp,fpload,fpstore,mtjmpr,*,*,*,*,*")
+  [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*")
    (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")])
 
 (define_insn "*movdf_softfloat64"
    #
    #
    {cror 0,0,0|nop}"
-  [(set_attr "type" "load,store,*,*,*,*,*,*,*")
+  [(set_attr "type" "load,store,*,mtjmpr,mfjmpr,*,*,*,*")
    (set_attr "length" "4,4,4,4,4,8,12,16,4")])
 \f
 (define_expand "movtf"
   [(set (match_operand:TF 0 "general_operand" "")
        (match_operand:TF 1 "any_operand" ""))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }")
 
 (define_insn_and_split "*movtf_internal"
   [(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_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
    && (gpc_reg_operand (operands[0], TFmode)
        || gpc_reg_operand (operands[1], TFmode))"
   [(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "")
                   (float_extend:TF (match_operand:DF 1 "input_operand" "")))
              (use (match_dup 2))])]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
 {
   operands[2] = CONST0_RTX (DFmode);
+  /* Generate GOT reference early for SVR4 PIC.  */
+  if (DEFAULT_ABI == ABI_V4 && flag_pic)
+    operands[2] = validize_mem (force_const_mem (DFmode, operands[2]));
 })
 
 (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 "zero_reg_mem_operand" "rf,m,f,n"))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "#"
   "&& reload_completed"
 (define_expand "extendsftf2"
   [(set (match_operand:TF 0 "nonimmediate_operand" "")
        (float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "")))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
 {
   rtx tmp = gen_reg_rtx (DFmode);
 (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_IEEEQUAD
    && 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_IEEEQUAD && !TARGET_XL_COMPAT
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "@
    #
 (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) && TARGET_XL_COMPAT
+  "!TARGET_IEEEQUAD && TARGET_XL_COMPAT
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "fadd %0,%1,%L1"
   [(set_attr "type" "fp")])
   [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
        (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "f")))
    (clobber (match_scratch:DF 2 "=f"))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "#"
   "&& reload_completed"
 (define_expand "floatsitf2"
   [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
         (float:TF (match_operand:SI 1 "gpc_reg_operand" "r")))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
 {
   rtx tmp = gen_reg_rtx (DFmode);
              (clobber (match_dup 3))
              (clobber (match_dup 4))
              (clobber (match_dup 5))])]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && (TARGET_POWER2 || TARGET_POWERPC)
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
 {
    (clobber (match_operand:DF 3 "gpc_reg_operand" "=&f"))
    (clobber (match_operand:DI 4 "gpc_reg_operand" "=f"))
    (clobber (match_operand:DI 5 "memory_operand" "=o"))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && 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;
 })
 
 (define_insn "negtf2"
   [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
        (neg:TF (match_operand:TF 1 "gpc_reg_operand" "f")))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "*
 {
 (define_expand "abstf2"
   [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
        (abs:TF (match_operand:TF 1 "gpc_reg_operand" "f")))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "
 {
                           (label_ref (match_operand 2 "" ""))
                           (pc)))
    (set (match_dup 6) (neg:DF (match_dup 6)))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "
 {
 \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.
   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
   switch (which_alternative)
     {
     default:
-      abort ();
+      gcc_unreachable ();
 
     case 0:
       if (TARGET_STRING)
   switch (which_alternative)
     {
     default:
-      abort ();
+      gcc_unreachable ();
     case 0:
       if (TARGET_STRING)
         return \"{stsi|stswi} %1,%P0,16\";
       return \"#\";
     }
 }"
-  [(set_attr "type" "store,store,*,load,load,*")])
+  [(set_attr "type" "store_ux,store_ux,*,load_ux,load_ux,*")])
 
 (define_insn "*movti_ppc64"
   [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o<>,r")
   "TARGET_STRING && XVECLEN (operands[0], 0) == 8"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load")
+  [(set_attr "type" "load_ux")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi7"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 7"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load")
+  [(set_attr "type" "load_ux")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi6"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 6"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load")
+  [(set_attr "type" "load_ux")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi5"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 5"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load")
+  [(set_attr "type" "load_ux")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi4"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 4"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load")
+  [(set_attr "type" "load_ux")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi3"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 3"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load")
+  [(set_attr "type" "load_ux")
    (set_attr "length" "32")])
 
 (define_expand "store_multiple"
                     gen_rtx_REG (SImode, regno + i));
 }")
 
-(define_insn "*store_multiple_power"
-  [(match_parallel 0 "store_multiple_operation"
-                  [(set (match_operand:SI 1 "indirect_operand" "=Q")
-                        (match_operand:SI 2 "gpc_reg_operand" "r"))
-                   (clobber (match_scratch:SI 3 "=q"))])]
-  "TARGET_STRING && TARGET_POWER"
-  "{stsi|stswi} %2,%P1,%O0"
-  [(set_attr "type" "store")])
-
 (define_insn "*stmsi8"
   [(match_parallel 0 "store_multiple_operation"
     [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
          (match_operand:SI 10 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 9"
   "{stsi|stswi} %2,%1,%O0"
-  [(set_attr "type" "store")])
+  [(set_attr "type" "store_ux")])
 
 (define_insn "*stmsi7"
   [(match_parallel 0 "store_multiple_operation"
          (match_operand:SI 9 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 8"
   "{stsi|stswi} %2,%1,%O0"
-  [(set_attr "type" "store")])
+  [(set_attr "type" "store_ux")])
 
 (define_insn "*stmsi6"
   [(match_parallel 0 "store_multiple_operation"
          (match_operand:SI 8 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 7"
   "{stsi|stswi} %2,%1,%O0"
-  [(set_attr "type" "store")])
+  [(set_attr "type" "store_ux")])
 
 (define_insn "*stmsi5"
   [(match_parallel 0 "store_multiple_operation"
          (match_operand:SI 7 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 6"
   "{stsi|stswi} %2,%1,%O0"
-  [(set_attr "type" "store")])
+  [(set_attr "type" "store_ux")])
 
 (define_insn "*stmsi4"
   [(match_parallel 0 "store_multiple_operation"
          (match_operand:SI 6 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 5"
   "{stsi|stswi} %2,%1,%O0"
-  [(set_attr "type" "store")])
+  [(set_attr "type" "store_ux")])
 
 (define_insn "*stmsi3"
   [(match_parallel 0 "store_multiple_operation"
          (match_operand:SI 5 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 4"
   "{stsi|stswi} %2,%1,%O0"
-  [(set_attr "type" "store")])
+  [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi8_power"
+  [(match_parallel 0 "store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+         (match_operand:SI 2 "gpc_reg_operand" "r"))
+     (clobber (match_scratch:SI 3 "=q"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+         (match_operand:SI 4 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+         (match_operand:SI 5 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+         (match_operand:SI 6 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+         (match_operand:SI 7 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+         (match_operand:SI 8 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+         (match_operand:SI 9 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
+         (match_operand:SI 10 "gpc_reg_operand" "r"))])]
+  "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 9"
+  "{stsi|stswi} %2,%1,%O0"
+  [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi7_power"
+  [(match_parallel 0 "store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+         (match_operand:SI 2 "gpc_reg_operand" "r"))
+     (clobber (match_scratch:SI 3 "=q"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+         (match_operand:SI 4 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+         (match_operand:SI 5 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+         (match_operand:SI 6 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+         (match_operand:SI 7 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+         (match_operand:SI 8 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+         (match_operand:SI 9 "gpc_reg_operand" "r"))])]
+  "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 8"
+  "{stsi|stswi} %2,%1,%O0"
+  [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi6_power"
+  [(match_parallel 0 "store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+         (match_operand:SI 2 "gpc_reg_operand" "r"))
+     (clobber (match_scratch:SI 3 "=q"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+         (match_operand:SI 4 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+         (match_operand:SI 5 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+         (match_operand:SI 6 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+         (match_operand:SI 7 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+         (match_operand:SI 8 "gpc_reg_operand" "r"))])]
+  "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 7"
+  "{stsi|stswi} %2,%1,%O0"
+  [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi5_power"
+  [(match_parallel 0 "store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+         (match_operand:SI 2 "gpc_reg_operand" "r"))
+     (clobber (match_scratch:SI 3 "=q"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+         (match_operand:SI 4 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+         (match_operand:SI 5 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+         (match_operand:SI 6 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+         (match_operand:SI 7 "gpc_reg_operand" "r"))])]
+  "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 6"
+  "{stsi|stswi} %2,%1,%O0"
+  [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi4_power"
+  [(match_parallel 0 "store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+         (match_operand:SI 2 "gpc_reg_operand" "r"))
+     (clobber (match_scratch:SI 3 "=q"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+         (match_operand:SI 4 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+         (match_operand:SI 5 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+         (match_operand:SI 6 "gpc_reg_operand" "r"))])]
+  "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 5"
+  "{stsi|stswi} %2,%1,%O0"
+  [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi3_power"
+  [(match_parallel 0 "store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+         (match_operand:SI 2 "gpc_reg_operand" "r"))
+     (clobber (match_scratch:SI 3 "=q"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+         (match_operand:SI 4 "gpc_reg_operand" "r"))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+         (match_operand:SI 5 "gpc_reg_operand" "r"))])]
+  "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 4"
+  "{stsi|stswi} %2,%1,%O0"
+  [(set_attr "type" "store_ux")])
 \f
-(define_expand "clrmemsi"
+(define_expand "setmemsi"
   [(parallel [(set (match_operand:BLK 0 "" "")
-                  (const_int 0))
+                  (match_operand 2 "const_int_operand" ""))
              (use (match_operand:SI 1 "" ""))
-             (use (match_operand:SI 2 "" ""))])]
+             (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
    && (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 "type" "store_ux")
    (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"))
    && (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")])
-
-(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 "type" "store_ux")
    (set_attr "length" "8")])
 
 ;; Move up to 24 bytes at a time.  The fixed registers are needed because the
    && (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 "type" "store_ux")
    (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"))
    && (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")])
-
-(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 "type" "store_ux")
    (set_attr "length" "8")])
 
 ;; Move up to 16 bytes at a time, using 4 fixed registers to avoid spill
    && (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 "type" "store_ux")
    (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"))
    && (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")])
-
-(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 "type" "store_ux")
    (set_attr "length" "8")])
 
 ;; Move up to 8 bytes at a time.
   "TARGET_STRING && TARGET_POWER && ! TARGET_POWERPC64
    && INTVAL (operands[2]) > 4 && INTVAL (operands[2]) <= 8"
   "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
-  [(set_attr "type" "load")
+  [(set_attr "type" "store_ux")
    (set_attr "length" "8")])
 
 (define_insn ""
   "TARGET_STRING && ! TARGET_POWER && ! TARGET_POWERPC64
    && INTVAL (operands[2]) > 4 && INTVAL (operands[2]) <= 8"
   "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
-  [(set_attr "type" "load")
+  [(set_attr "type" "store_ux")
    (set_attr "length" "8")])
 
 ;; Move up to 4 bytes at a time.
   "TARGET_STRING && TARGET_POWER
    && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 4"
   "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
-  [(set_attr "type" "load")
+  [(set_attr "type" "store_ux")
    (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"))
   "TARGET_STRING && ! TARGET_POWER
    && 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")])
-
-(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 "type" "store_ux")
    (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
 ;; Peephole to convert two consecutive FP loads or stores into lfq/stfq.
 
 (define_insn "*lfq_power2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
-       (match_operand:TF 1 "memory_operand" ""))]
+  [(set (match_operand:V2DF 0 "gpc_reg_operand" "=f")
+       (match_operand:V2DF 1 "memory_operand" ""))]
   "TARGET_POWER2
    && TARGET_HARD_FLOAT && TARGET_FPRS"
-   "lfq%U1%X1 %0,%1")
+  "lfq%U1%X1 %0,%1")
 
 (define_peephole2
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
    && registers_ok_for_quad_peep (operands[0], operands[2])
    && 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]));")
+       (match_dup 1))]
+  "operands[1] = widen_memory_access (operands[1], V2DFmode, 0);
+   operands[0] = gen_rtx_REG (V2DFmode, REGNO (operands[0]));")
 
 (define_insn "*stfq_power2"
-  [(set (match_operand:TF 0 "memory_operand" "")
-       (match_operand:TF 1 "gpc_reg_operand" "f"))]
+  [(set (match_operand:V2DF 0 "memory_operand" "")
+       (match_operand:V2DF 1 "gpc_reg_operand" "f"))]
   "TARGET_POWER2
    && TARGET_HARD_FLOAT && TARGET_FPRS"
   "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]));")
+  "operands[0] = widen_memory_access (operands[0], V2DFmode, 0);
+   operands[1] = gen_rtx_REG (V2DFmode, REGNO (operands[1]));")
 
-;; after inserting conditional returns we can sometimes have
+;; 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.
+;; Disallow subregs for E500 so we don't munge frob_di_df_2.
 (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])"
+  "!(TARGET_E500_DOUBLE && GET_CODE (operands[2]) == SUBREG)
+   && peep2_reg_dead_p (2, operands[0])"
   [(set (match_dup 2) (match_dup 1))])
 
 (define_peephole2
   ""
   "DONE;")
 
+;; Adjust stack pointer (op0) to a new value (op1).
+;; First copy old stack backchain to new location, and ensure that the
+;; scheduler won't reorder the sp assignment before the backchain write.
 (define_expand "restore_stack_block"
-  [(use (match_operand 0 "register_operand" ""))
-   (set (match_dup 2) (match_dup 3))
-   (set (match_dup 0) (match_operand 1 "register_operand" ""))
-   (set (match_dup 3) (match_dup 2))]
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 4) (match_dup 2))
+   (set (match_dup 5) (unspec:BLK [(match_dup 5)] UNSPEC_TIE))
+   (set (match_operand 0 "register_operand" "")
+       (match_operand 1 "register_operand" ""))]
   ""
   "
 {
   operands[2] = gen_reg_rtx (Pmode);
-  operands[3] = gen_rtx_MEM (Pmode, operands[0]);
+  operands[3] = gen_frame_mem (Pmode, operands[0]);
+  operands[4] = gen_frame_mem (Pmode, operands[1]);
+  operands[5] = gen_frame_mem (BLKmode, operands[0]);
 }")
 
 (define_expand "save_stack_nonlocal"
-  [(match_operand 0 "memory_operand" "")
-   (match_operand 1 "register_operand" "")]
+  [(set (match_dup 3) (match_dup 4))
+   (set (match_operand 0 "memory_operand" "") (match_dup 3))
+   (set (match_dup 2) (match_operand 1 "register_operand" ""))]
   ""
   "
 {
-  rtx temp = gen_reg_rtx (Pmode);
   int units_per_word = (TARGET_32BIT) ? 4 : 8;
 
   /* Copy the backchain to the first word, sp to the second.  */
-  emit_move_insn (temp, gen_rtx_MEM (Pmode, operands[1]));
-  emit_move_insn (adjust_address_nv (operands[0], Pmode, 0), temp);
-  emit_move_insn (adjust_address_nv (operands[0], Pmode, units_per_word),
-                 operands[1]);
-  DONE;
+  operands[0] = adjust_address_nv (operands[0], Pmode, 0);
+  operands[2] = adjust_address_nv (operands[0], Pmode, units_per_word);
+  operands[3] = gen_reg_rtx (Pmode);
+  operands[4] = gen_frame_mem (Pmode, operands[1]);
 }")
 
 (define_expand "restore_stack_nonlocal"
-  [(match_operand 0 "register_operand" "")
-   (match_operand 1 "memory_operand" "")]
+  [(set (match_dup 2) (match_operand 1 "memory_operand" ""))
+   (set (match_dup 3) (match_dup 4))
+   (set (match_dup 5) (match_dup 2))
+   (set (match_dup 6) (unspec:BLK [(match_dup 6)] UNSPEC_TIE))
+   (set (match_operand 0 "register_operand" "") (match_dup 3))]
   ""
   "
 {
-  rtx temp = gen_reg_rtx (Pmode);
   int units_per_word = (TARGET_32BIT) ? 4 : 8;
 
   /* Restore the backchain from the first word, sp from the second.  */
-  emit_move_insn (temp,
-                 adjust_address_nv (operands[1], Pmode, 0));
-  emit_move_insn (operands[0],
-                 adjust_address_nv (operands[1], Pmode, units_per_word));
-  emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp);
-  DONE;
+  operands[2] = gen_reg_rtx (Pmode);
+  operands[3] = gen_reg_rtx (Pmode);
+  operands[1] = adjust_address_nv (operands[1], Pmode, 0);
+  operands[4] = adjust_address_nv (operands[1], Pmode, units_per_word);
+  operands[5] = gen_frame_mem (Pmode, operands[3]);
+  operands[6] = gen_frame_mem (BLKmode, operands[0]);
 }")
 \f
 ;; TOC register handling.
   [(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_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 "load_toc_v4_PIC_3c"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (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")
 ;; operands[2] is the value FUNCTION_ARG returns for the VOID argument
 ;; 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"))]
+(define_insn "*call_indirect_nonlocal_sysv<mode>"
+  [(call (mem:SI (match_operand:P 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"))
+(define_insn "*call_nonlocal_sysv<mode>"
+  [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s"))
         (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
    (clobber (match_scratch:SI 3 "=l,l"))]
 #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")
    (set_attr "length" "4,8")])
 
-(define_insn "*call_value_indirect_nonlocal_sysv"
+(define_insn "*call_value_indirect_nonlocal_sysv<mode>"
   [(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:P 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"
+(define_insn "*call_value_nonlocal_sysv<mode>"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s,s"))
+       (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s"))
              (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
    (clobber (match_scratch:SI 4 "=l,l"))]
 #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);
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
 
-(define_insn "*sibcall_nonlocal_sysv"
-  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s,s"))
+(define_insn "*sibcall_nonlocal_sysv<mode>"
+  [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s"))
         (match_operand 1 "" ""))
    (use (match_operand 2 "immediate_operand" "O,n"))
    (use (match_operand:SI 3 "register_operand" "l,l"))
   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);
 
 }")
 
-(define_insn "*sibcall_value_nonlocal_sysv"
+(define_insn "*sibcall_value_nonlocal_sysv<mode>"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s,s"))
+       (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s"))
              (match_operand 2 "" "")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
    (use (match_operand:SI 4 "register_operand" "l,l"))
   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 || TARGET_E500_DOUBLE)"
-  "
-{
-  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];
   ""
   "{ rs6000_emit_sCOND (LTGT, operands[0]); DONE; }")
 
+(define_expand "stack_protect_set"
+  [(match_operand 0 "memory_operand" "")
+   (match_operand 1 "memory_operand" "")]
+  ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+  rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2);
+  rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+  operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+  if (TARGET_64BIT)
+    emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
+  else
+    emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
+  DONE;
+})
+
+(define_insn "stack_protect_setsi"
+  [(set (match_operand:SI 0 "memory_operand" "=m")
+       (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+   (set (match_scratch:SI 2 "=&r") (const_int 0))]
+  "TARGET_32BIT"
+  "{l%U1%X1|lwz%U1%X1} %2,%1\;{st%U0%X0|stw%U0%X0} %2,%0\;{lil|li} %2,0"
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
+
+(define_insn "stack_protect_setdi"
+  [(set (match_operand:DI 0 "memory_operand" "=m")
+       (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+   (set (match_scratch:DI 2 "=&r") (const_int 0))]
+  "TARGET_64BIT"
+  "ld%U1%X1 %2,%1\;std%U0%X0 %2,%0\;{lil|li} %2,0"
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
+
+(define_expand "stack_protect_test"
+  [(match_operand 0 "memory_operand" "")
+   (match_operand 1 "memory_operand" "")
+   (match_operand 2 "" "")]
+  ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+  rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2);
+  rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+  operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+  rs6000_compare_op0 = operands[0];
+  rs6000_compare_op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]),
+                                      UNSPEC_SP_TEST);
+  rs6000_compare_fp_p = 0;
+  emit_jump_insn (gen_beq (operands[2]));
+  DONE;
+})
+
+(define_insn "stack_protect_testsi"
+  [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x,?y")
+        (unspec:CCEQ [(match_operand:SI 1 "memory_operand" "m,m")
+                     (match_operand:SI 2 "memory_operand" "m,m")]
+                    UNSPEC_SP_TEST))
+   (set (match_scratch:SI 4 "=r,r") (const_int 0))
+   (clobber (match_scratch:SI 3 "=&r,&r"))]
+  "TARGET_32BIT"
+  "@
+   {l%U1%X1|lwz%U1%X1} %3,%1\;{l%U2%X2|lwz%U2%X2} %4,%2\;xor. %3,%3,%4\;{lil|li} %4,0
+   {l%U1%X1|lwz%U1%X1} %3,%1\;{l%U2%X2|lwz%U2%X2} %4,%2\;{cmpl|cmplw} %0,%3,%4\;{lil|li} %3,0\;{lil|li} %4,0"
+  [(set_attr "length" "16,20")])
+
+(define_insn "stack_protect_testdi"
+  [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x,?y")
+        (unspec:CCEQ [(match_operand:DI 1 "memory_operand" "m,m")
+                     (match_operand:DI 2 "memory_operand" "m,m")]
+                    UNSPEC_SP_TEST))
+   (set (match_scratch:DI 4 "=r,r") (const_int 0))
+   (clobber (match_scratch:DI 3 "=&r,&r"))]
+  "TARGET_64BIT"
+  "@
+   ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;xor. %3,%3,%4\;{lil|li} %4,0
+   ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;cmpld %0,%3,%4\;{lil|li} %3,0\;{lil|li} %4,0"
+  [(set_attr "length" "16,20")])
+
 \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,
-;; we can do this with an XOR followed by a compare.  But we need a scratch
-;; register for the result of the XOR.
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_operand" "")
-       (compare:CC (match_operand:SI 1 "gpc_reg_operand" "")
-                   (match_operand:SI 2 "non_short_cint_operand" "")))
-   (clobber (match_operand:SI 3 "gpc_reg_operand" ""))]
-  "find_single_use (operands[0], insn, 0)
-   && (GET_CODE (*find_single_use (operands[0], insn, 0)) == EQ
-       || GET_CODE (*find_single_use (operands[0], insn, 0)) == NE)"
-  [(set (match_dup 3) (xor:SI (match_dup 1) (match_dup 4)))
-   (set (match_dup 0) (compare:CC (match_dup 3) (match_dup 5)))]
-  "
-{
-  /* Get the constant we are comparing against, C,  and see what it looks like
-     sign-extended to 16 bits.  Then see what constant could be XOR'ed
-     with C to get the sign-extended value.  */
+;; we can do this with an XOR followed by a compare.  But this is profitable
+;; only if the large constant is only used for the comparison (and in this
+;; case we already have a register to reuse as scratch).
+;;
+;; For 64-bit registers, we could only do so if the constant's bit 15 is clear:
+;; otherwise we'd need to XOR with FFFFFFFF????0000 which is not available.
 
-  HOST_WIDE_INT c = INTVAL (operands[2]);
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand")
+        (match_operand:SI 1 "logical_const_operand" ""))
+   (set (match_dup 0) (match_operator:SI 3 "boolean_or_operator"
+                      [(match_dup 0)
+                       (match_operand:SI 2 "logical_const_operand" "")]))
+   (set (match_operand:CC 4 "cc_reg_operand" "")
+        (compare:CC (match_operand:SI 5 "gpc_reg_operand" "")
+                    (match_dup 0)))
+   (set (pc)
+        (if_then_else (match_operator 6 "equality_operator"
+                       [(match_dup 4) (const_int 0)])
+                      (match_operand 7 "" "")
+                      (match_operand 8 "" "")))]
+  "peep2_reg_dead_p (3, operands[0])
+   && peep2_reg_dead_p (4, operands[4])"
+ [(set (match_dup 0) (xor:SI (match_dup 5) (match_dup 9)))
+  (set (match_dup 4) (compare:CC (match_dup 0) (match_dup 10)))
+  (set (pc) (if_then_else (match_dup 6) (match_dup 7) (match_dup 8)))]
+{
+  /* Get the constant we are comparing against, and see what it looks like
+     when sign-extended from 16 to 32 bits.  Then see what constant we could
+     XOR with SEXTC to get the sign-extended value.  */
+  rtx cnst = simplify_const_binary_operation (GET_CODE (operands[3]),
+                                             SImode,
+                                             operands[1], operands[2]);
+  HOST_WIDE_INT c = INTVAL (cnst);
   HOST_WIDE_INT sextc = ((c & 0xffff) ^ 0x8000) - 0x8000;
   HOST_WIDE_INT xorv = c ^ sextc;
 
-  operands[4] = GEN_INT (xorv);
-  operands[5] = GEN_INT (sextc);
-}")
+  operands[9] = GEN_INT (xorv);
+  operands[10] = GEN_INT (sextc);
+})
 
 (define_insn "*cmpsi_internal2"
   [(set (match_operand:CCUNS 0 "cc_reg_operand" "=y")
   [(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) && !TARGET_XL_COMPAT
+  "!TARGET_IEEEQUAD && !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")
     (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_IEEEQUAD && TARGET_XL_COMPAT
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "#"
   "&& reload_completed"
 ;; 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 "type" "three,two,three,three,three")
-   (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 "type" "three,two,three,three,three")
-   (set_attr "length" "12,8,12,12,12")])
-
-(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_mode_attr scc_eq_op2 [(SI "rKLI")
+                             (DI "rKJI")])
 
-(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)))]
-  "")
+(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>")))]
+  "!TARGET_POWER"
+  "#"
+  "!TARGET_POWER"
+  [(set (match_dup 0)
+       (clz:GPR (match_dup 3)))
+   (set (match_dup 0)
+       (lshiftrt:GPR (match_dup 0) (match_dup 4)))]
+  {
+    if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
+      {
+       /* Use output operand as intermediate.  */
+       operands[3] = operands[0];
+
+       if (logical_operand (operands[2], <MODE>mode))
+         emit_insn (gen_rtx_SET (VOIDmode, operands[3],
+                                 gen_rtx_XOR (<MODE>mode,
+                                              operands[1], operands[2])));
+       else
+         emit_insn (gen_rtx_SET (VOIDmode, operands[3],
+                                 gen_rtx_PLUS (<MODE>mode, operands[1],
+                                               negate_rtx (<MODE>mode,
+                                                           operands[2]))));
+      }
+    else
+      operands[3] = operands[1];
 
-(define_insn ""
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?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"))
-        (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")])
+    operands[4] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
+  })
 
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
+(define_insn_and_split "*eq<mode>_compare"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=y")
        (compare:CC
-        (eq:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "reg_or_cint_operand" ""))
+        (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" "")
-       (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)))]
-  "")
+   (set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (eq:P (match_dup 1) (match_dup 2)))]
+  "!TARGET_POWER && optimize_size"
+  "#"
+  "!TARGET_POWER && optimize_size"
+  [(set (match_dup 0)
+       (clz:P (match_dup 4)))
+   (parallel [(set (match_dup 3)
+                  (compare:CC (lshiftrt:P (match_dup 0) (match_dup 5))
+                              (const_int 0)))
+             (set (match_dup 0)
+                  (lshiftrt:P (match_dup 0) (match_dup 5)))])]
+  {
+    if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
+      {
+       /* Use output operand as intermediate.  */
+       operands[4] = operands[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];
+
+    operands[5] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
+  })
+
+(define_insn "*eqsi_power"
+  [(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_POWER"
+  "@
+   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" "three,two,three,three,three")
+   (set_attr "length" "12,8,12,12,12")])
 
 ;; 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.
    (set (match_dup 2) (plus:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
                               (match_dup 4)))])
 
-(define_insn ""
+(define_insn "*plus_eqsi"
   [(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"
   "@
   [(set_attr "type" "three,two,three,three,three")
    (set_attr "length" "12,8,12,12,12")])
 
-(define_insn ""
+(define_insn "*compare_plus_eqsi"
   [(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"))]
-  "TARGET_32BIT"
+  "TARGET_32BIT && optimize_size"
   "@
    xor %4,%1,%2\;{sfi|subfic} %4,%4,0\;{aze.|addze.} %4,%3
    {sfi|subfic} %4,%1,0\;{aze.|addze.} %4,%3
        (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 ""))]
-  "TARGET_32BIT && reload_completed"
+  "TARGET_32BIT && optimize_size && reload_completed"
   [(set (match_dup 4)
        (plus:SI (eq:SI (match_dup 1)
                 (match_dup 2))
                    (const_int 0)))]
   "")
 
-(define_insn ""
+(define_insn "*plus_eqsi_compare"
   [(set (match_operand:CC 4 "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)))
    (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r,&r,&r,&r,&r,&r,&r")
        (plus:SI (eq:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT"
+  "TARGET_32BIT && optimize_size"
   "@
    xor %0,%1,%2\;{sfi|subfic} %0,%0,0\;{aze.|addze.} %0,%3
    {sfi|subfic} %0,%1,0\;{aze.|addze.} %0,%3
        (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" "")
        (plus:SI (eq:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT && reload_completed"
+  "TARGET_32BIT && optimize_size && reload_completed"
   [(set (match_dup 0)
        (plus:SI (eq:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
    (set (match_dup 4)
                    (const_int 0)))]
   "")
 
-(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"))))]
-  "TARGET_32BIT"
-  "@
-   xor %0,%1,%2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0
-   {ai|addic} %0,%1,-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 "type" "three,two,three,three,three")
-    (set_attr "length" "12,8,12,12,12")])
+(define_insn "*neg_eq0<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (neg:P (eq:P (match_operand:P 1 "gpc_reg_operand" "r")
+                    (const_int 0))))]
+  ""
+  "{ai|addic} %0,%1,-1\;{sfe|subfe} %0,%0,%0"
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
+
+(define_insn_and_split "*neg_eq<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (neg:P (eq:P (match_operand:P 1 "gpc_reg_operand" "%r")
+                    (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))]
+  ""
+  "#"
+  ""
+  [(set (match_dup 0) (neg:P (eq:P (match_dup 3) (const_int 0))))]
+  {
+    if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
+      {
+       /* Use output operand as intermediate.  */
+       operands[3] = operands[0];
+
+       if (logical_operand (operands[2], <MODE>mode))
+         emit_insn (gen_rtx_SET (VOIDmode, operands[3],
+                                 gen_rtx_XOR (<MODE>mode,
+                                              operands[1], operands[2])));
+       else
+         emit_insn (gen_rtx_SET (VOIDmode, operands[3],
+                                 gen_rtx_PLUS (<MODE>mode, operands[1],
+                                               negate_rtx (<MODE>mode,
+                                                           operands[2]))));
+      }
+    else
+      operands[3] = operands[1];
+  })
 
 ;; Simplify (ne X (const_int 0)) on the PowerPC.  No need to on the Power,
 ;; since it nabs/sr is just as fast.
-(define_insn "*ne0"
+(define_insn "*ne0si"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
        (lshiftrt:SI (neg:SI (abs:SI (match_operand:SI 1 "gpc_reg_operand" "r")))
                     (const_int 31)))
   [(set_attr "type" "two")
    (set_attr "length" "8")])
 
-(define_insn ""
+(define_insn "*ne0di"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (lshiftrt:DI (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
                     (const_int 63)))
    (set_attr "length" "8")])
 
 ;; This is what (plus (ne X (const_int 0)) Y) looks like.
-(define_insn ""
+(define_insn "*plus_ne0si"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (plus:SI (lshiftrt:SI
                  (neg:SI (abs:SI (match_operand:SI 1 "gpc_reg_operand" "r")))
   [(set_attr "type" "two")
    (set_attr "length" "8")])
 
-(define_insn ""
+(define_insn "*plus_ne0di"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (plus:DI (lshiftrt:DI
                  (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
   [(set_attr "type" "two")
    (set_attr "length" "8")])
 
-(define_insn ""
+(define_insn "*compare_plus_ne0si"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC
         (plus:SI (lshiftrt:SI
                    (const_int 0)))]
   "")
 
-(define_insn ""
+(define_insn "*compare_plus_ne0di"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC
         (plus:DI (lshiftrt:DI
                    (const_int 0)))]
   "")
 
-(define_insn ""
+(define_insn "*plus_ne0si_compare"
   [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
        (compare:CC
         (plus:SI (lshiftrt:SI
                    (const_int 0)))]
   "")
 
-(define_insn ""
+(define_insn "*plus_ne0di_compare"
   [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
        (compare:CC
         (plus:DI (lshiftrt:DI
    {ai|addic} %0,%1,-1\;{aze|addze} %0,%0\;{srai|srawi} %0,%0,31"
   [(set_attr "length" "12")])
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-               (match_operand:SI 2 "reg_or_short_operand" "rI")))]
-  "TARGET_32BIT"
+(define_insn "*leu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
+              (match_operand:P 2 "reg_or_short_operand" "rI")))]
+  ""
   "{sf%I2|subf%I2c} %0,%1,%2\;{cal %0,0(0)|li %0,0}\;{ae|adde} %0,%0,%0"
   [(set_attr "type" "three")
    (set_attr "length" "12")])
 
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (leu: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\;li %0,0\;adde %0,%0,%0"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (leu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                (match_operand:DI 2 "reg_or_short_operand" "rI,rI"))
-        (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (leu:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   subf%I2c %0,%1,%2\;li %0,0\;adde. %0,%0,%0
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (leu:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                (match_operand:DI 2 "reg_or_short_operand" ""))
-        (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (leu:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT && reload_completed"
-  [(set (match_dup 0)
-       (leu:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
+(define_insn "*leu<mode>_compare"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
        (compare:CC
-        (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                (match_operand:SI 2 "reg_or_short_operand" "rI,rI"))
+        (leu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+               (match_operand:P 2 "reg_or_short_operand" "rI,rI"))
         (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (leu:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT"
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (leu:P (match_dup 1) (match_dup 2)))]
+  ""
   "@
    {sf%I2|subf%I2c} %0,%1,%2\;{cal %0,0(0)|li %0,0}\;{ae.|adde.} %0,%0,%0
    #"
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
        (compare:CC
-        (leu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "reg_or_short_operand" ""))
+        (leu: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" "")
-       (leu:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
+   (set (match_operand:P 0 "gpc_reg_operand" "")
+       (leu:P (match_dup 1) (match_dup 2)))]
+  "reload_completed"
   [(set (match_dup 0)
-       (leu:SI (match_dup 1) (match_dup 2)))
+       (leu:P (match_dup 1) (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
-       (plus:SI (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                        (match_operand:SI 2 "reg_or_short_operand" "rI"))
-                (match_operand:SI 3 "gpc_reg_operand" "r")))]
-  "TARGET_32BIT"
+(define_insn "*plus_leu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
+       (plus:P (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
+                      (match_operand:P 2 "reg_or_short_operand" "rI"))
+               (match_operand:P 3 "gpc_reg_operand" "r")))]
+  ""
   "{sf%I2|subf%I2c} %0,%1,%2\;{aze|addze} %0,%3"
   [(set_attr "type" "two")
    (set_attr "length" "8")])
                    (const_int 0)))]
   "")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (neg:SI (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                       (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
-  "TARGET_32BIT"
+(define_insn "*neg_leu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (neg:P (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
+                     (match_operand:P 2 "reg_or_short_operand" "rI"))))]
+  ""
   "{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;nand %0,%0,%0"
    [(set_attr "type" "three")
     (set_attr "length" "12")])
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
-       (and:SI (neg:SI
-                (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                        (match_operand:SI 2 "reg_or_short_operand" "rI")))
-               (match_operand:SI 3 "gpc_reg_operand" "r")))]
-  "TARGET_32BIT"
+(define_insn "*and_neg_leu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
+       (and:P (neg:P
+                (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
+                       (match_operand:P 2 "reg_or_short_operand" "rI")))
+               (match_operand:P 3 "gpc_reg_operand" "r")))]
+  ""
   "{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;andc %0,%3,%0"
   [(set_attr "type" "three")
    (set_attr "length" "12")])
   "doz%I2 %0,%1,%2\;nabs %0,%0\;{srai|srawi} %0,%0,31"
   [(set_attr "length" "12")])
 
-(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"
-  "#"
-  "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"
+(define_insn_and_split "*ltu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+              (match_operand:P 2 "reg_or_neg_short_operand" "r,P")))]
+  ""
   "#"
-  "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)))]
+  ""
+  [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (neg:P (match_dup 0)))]
   "")
 
-(define_insn ""
+(define_insn_and_split "*ltu<mode>_compare"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC
-        (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
-       (ltu:SI (match_dup 1) (match_dup 2)))]
-  "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 "type" "compare")
-   (set_attr "length" "12,12,16,16")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "reg_or_neg_short_operand" ""))
+        (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
+               (match_operand:P 2 "reg_or_neg_short_operand" "r,P,r,P"))
         (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (ltu:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (ltu:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(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"
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
+       (ltu:P (match_dup 1) (match_dup 2)))]
+  ""
   "#"
-  "&& !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)))]
+  ""
+  [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
+   (parallel [(set (match_dup 3)
+                  (compare:CC (neg:P (match_dup 0)) (const_int 0)))
+             (set (match_dup 0) (neg:P (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"
+(define_insn_and_split "*plus_ltu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=&r,r")
+       (plus:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                      (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))
+               (match_operand:P 3 "reg_or_short_operand" "rI,rI")))]
+  ""
   "#"
   "&& !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")
-       (compare:CC
-        (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
-                 (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 "=&r,&r,&r,&r"))]
-  "TARGET_32BIT"
-  "@
-   {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")
-   (set_attr "length" "12,12,16,16")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" ""))
-                 (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 4)
-       (plus:SI (ltu:SI (match_dup 1) (match_dup 2))
-                (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
+  [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))]
   "")
 
-(define_insn ""
+(define_insn_and_split "*plus_ltu<mode>_compare"
   [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC
-        (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
-                 (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r")
-       (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.|subf.} %0,%0,%3
-   {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;{sf.|subf.} %0,%0,%3
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,12,16,16")])
-
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" ""))
-                 (match_operand:SI 3 "gpc_reg_operand" ""))
+        (plus:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
+                       (match_operand:P 2 "reg_or_neg_short_operand" "r,P,r,P"))
+                (match_operand:P 3 "gpc_reg_operand" "r,r,r,r"))
         (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (ltu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (plus:SI (ltu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
+   (set (match_operand:P 0 "gpc_reg_operand" "=&r,&r,&r,&r")
+       (plus:P (ltu:P (match_dup 1) (match_dup 2)) (match_dup 3)))]
+  ""
+  "#"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+  [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
+   (parallel [(set (match_dup 4)
+                  (compare:CC (minus:P (match_dup 3) (match_dup 0))
+                              (const_int 0)))
+             (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))])]
   "")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (neg:SI (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
-   {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0"
-  [(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"
+(define_insn "*neg_ltu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (neg:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                     (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))))]
+  ""
   "@
    {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0
    {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0"
   "doz%I2 %0,%1,%2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0"
   [(set_attr "length" "12")])
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-               (match_operand:SI 2 "reg_or_neg_short_operand" "r,P")))]
-  "TARGET_32BIT"
+(define_insn "*geu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+              (match_operand:P 2 "reg_or_neg_short_operand" "r,P")))]
+  ""
   "@
    {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 "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (geu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-               (match_operand:DI 2 "reg_or_neg_short_operand" "r,P")))]
-  "TARGET_64BIT"
-  "@
-   subfc %0,%2,%1\;li %0,0\;adde %0,%0,%0
-   addic %0,%1,%n2\;li %0,0\;adde %0,%0,%0"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
-       (geu:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT"
-  "@
-   {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 "type" "compare")
-   (set_attr "length" "12,12,16,16")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (geu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "reg_or_neg_short_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (geu:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (geu:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+   (set_attr "length" "12")])
 
-(define_insn ""
+(define_insn "*geu<mode>_compare"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC
-        (geu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
-                (match_operand:DI 2 "reg_or_neg_short_operand" "r,P,r,P"))
+        (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
+               (match_operand:P 2 "reg_or_neg_short_operand" "r,P,r,P"))
         (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
-       (geu:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
+       (geu:P (match_dup 1) (match_dup 2)))]
+  ""
   "@
-   subfc %0,%2,%1\;li %0,0\;adde. %0,%0,%0
-   addic %0,%1,%n2\;li %0,0\;adde. %0,%0,%0
+   {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 "type" "compare")
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
        (compare:CC
-        (geu:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                (match_operand:DI 2 "reg_or_neg_short_operand" ""))
+        (geu:P (match_operand:P 1 "gpc_reg_operand" "")
+               (match_operand:P 2 "reg_or_neg_short_operand" ""))
         (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (geu:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT && reload_completed"
+   (set (match_operand:P 0 "gpc_reg_operand" "")
+       (geu:P (match_dup 1) (match_dup 2)))]
+  "reload_completed"
   [(set (match_dup 0)
-       (geu:DI (match_dup 1) (match_dup 2)))
+       (geu:P (match_dup 1) (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
-       (plus:SI (geu: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 "gpc_reg_operand" "r,r")))]
-  "TARGET_32BIT"
+(define_insn "*plus_geu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=&r,&r")
+       (plus:P (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                      (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))
+               (match_operand:P 3 "gpc_reg_operand" "r,r")))]
+  ""
   "@
    {sf|subfc} %0,%2,%1\;{aze|addze} %0,%3
    {ai|addic} %0,%1,%n2\;{aze|addze} %0,%3"
                    (const_int 0)))]
   "")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (neg:SI (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                       (match_operand:SI 2 "reg_or_short_operand" "r,I"))))]
-  "TARGET_32BIT"
+(define_insn "*neg_geu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (neg:P (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                     (match_operand:P 2 "reg_or_short_operand" "r,I"))))]
+  ""
   "@
    {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 "type" "three")
    (set_attr "length" "12")])
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
-       (and:SI (neg:SI
-                (geu: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 "gpc_reg_operand" "r,r")))]
-  "TARGET_32BIT"
+(define_insn "*and_neg_geu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=&r,&r")
+       (and:P (neg:P
+                (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                       (match_operand:P 2 "reg_or_neg_short_operand" "r,P")))
+               (match_operand:P 3 "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"
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-              (const_int 0)))]
-  "TARGET_32BIT"
-  "{sfi|subfic} %0,%1,0\;{ame|addme} %0,%0\;{sri|srwi} %0,%0,31"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-              (const_int 0)))]
-  "TARGET_64BIT"
-  "subfic %0,%1,0\;addme %0,%0\;srdi %0,%0,63"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-               (const_int 0))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (gt:SI (match_dup 1) (const_int 0)))]
-  "TARGET_32BIT"
-  "@
-   {sfi|subfic} %0,%1,0\;{ame|addme} %0,%0\;{sri.|srwi.} %0,%0,31
-   #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (gt:SI (match_operand:SI 1 "gpc_reg_operand" "")
-               (const_int 0))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (gt:SI (match_dup 1) (const_int 0)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (gt:SI (match_dup 1) (const_int 0)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-               (const_int 0))
-        (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (gt:DI (match_dup 1) (const_int 0)))]
-  "TARGET_64BIT"
-  "@
-   subfic %0,%1,0\;addme %0,%0\;srdi. %0,%0,63
-   #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (gt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (const_int 0))
-        (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (gt:DI (match_dup 1) (const_int 0)))]
-  "TARGET_64BIT && reload_completed"
-  [(set (match_dup 0)
-       (gt:DI (match_dup 1) (const_int 0)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
               (match_operand:SI 2 "reg_or_short_operand" "r")))]
   "TARGET_POWER"
   "doz %0,%2,%1\;nabs %0,%0\;{sri|srwi} %0,%0,31"
                    (const_int 0)))]
   "")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
-       (plus:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                       (const_int 0))
-                (match_operand:SI 2 "gpc_reg_operand" "r")))]
-  "TARGET_32BIT"
+(define_insn "*plus_gt0<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
+       (plus:P (gt:P (match_operand:P 1 "gpc_reg_operand" "r")
+                     (const_int 0))
+                (match_operand:P 2 "gpc_reg_operand" "r")))]
+  ""
   "{a|addc} %0,%1,%1\;{sfe|subfe} %0,%1,%0\;{aze|addze} %0,%2"
   [(set_attr "type" "three")
    (set_attr "length" "12")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
-       (plus:DI (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                       (const_int 0))
-                (match_operand:DI 2 "gpc_reg_operand" "r")))]
-  "TARGET_64BIT"
-  "addc %0,%1,%1\;subfe %0,%1,%0\;addze %0,%2"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC
         (plus:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (neg:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                      (const_int 0))))]
-  "TARGET_32BIT"
-  "{sfi|subfic} %0,%1,0\;{ame|addme} %0,%0\;{srai|srawi} %0,%0,31"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (neg:DI (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                      (const_int 0))))]
-  "TARGET_64BIT"
-  "subfic %0,%1,0\;addme %0,%0\;sradi %0,%0,63"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (neg:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                       (match_operand:SI 2 "reg_or_short_operand" "r"))))]
   "TARGET_POWER"
   "doz %0,%2,%1\;nabs %0,%0\;{srai|srawi} %0,%0,31"
   [(set_attr "length" "12")])
-
-(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")))]
-  "TARGET_32BIT"
-  "#"
-  "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_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")))]
-  "TARGET_64BIT"
-  "#"
-  "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")
-       (compare:CC
-        (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                (match_operand:SI 2 "reg_or_short_operand" "rI,rI"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (gtu:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT"
-  "@
-   {sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;neg. %0,%0
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "reg_or_short_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (gtu:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (gtu:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                (match_operand:DI 2 "reg_or_short_operand" "rI,rI"))
-        (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (gtu:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   subf%I2c %0,%1,%2\;subfe %0,%0,%0\;neg. %0,%0
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                (match_operand:DI 2 "reg_or_short_operand" ""))
-        (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (gtu:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT && reload_completed"
-  [(set (match_dup 0)
-       (gtu:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(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"
-  "#"
-  "&& !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_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"
-  "#"
-  "&& !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")
-       (compare:CC
-        (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:SI 2 "reg_or_short_operand" "I,r,I,r"))
-                 (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 "=&r,&r,&r,&r"))]
-  "TARGET_32BIT"
-  "@
-   {ai|addic} %4,%1,%k2\;{aze.|addze.} %4,%3
-   {sf%I2|subf%I2c} %4,%1,%2\;{sfe|subfe} %4,%4,%4\;{sf.|subf.} %4,%4,%3
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12,12,16")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_short_operand" ""))
-                 (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 4)
-       (plus:SI (gtu:SI (match_dup 1) (match_dup 2))
-                (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:DI 2 "reg_or_short_operand" "I,r,I,r"))
-                 (match_operand:DI 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:DI 4 "=&r,&r,&r,&r"))]
-  "TARGET_64BIT"
-  "@
-   addic %4,%1,%k2\;addze. %4,%3
-   subf%I2c %4,%1,%2\;subfe %4,%4,%4\;subf. %4,%4,%3
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12,12,16")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                         (match_operand:DI 2 "reg_or_short_operand" ""))
-                 (match_operand:DI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:DI 4 ""))]
-  "TARGET_64BIT && reload_completed"
-  [(set (match_dup 4)
-       (plus:DI (gtu:DI (match_dup 1) (match_dup 2))
-                 (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:SI 2 "reg_or_short_operand" "I,r,I,r"))
-                 (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r")
-       (plus:SI (gtu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT"
-  "@
-   {ai|addic} %0,%1,%k2\;{aze.|addze.} %0,%3
-   {sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;{sf.|subf.} %0,%0,%3
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12,12,16")])
-
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_short_operand" ""))
-                 (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (gtu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (plus:SI (gtu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
+
+(define_insn_and_split "*gtu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
+              (match_operand:P 2 "reg_or_short_operand" "rI")))]
+  ""
+  "#"
+  ""
+  [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (neg:P (match_dup 0)))]
   "")
 
-(define_insn ""
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
+(define_insn_and_split "*gtu<mode>_compare"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
        (compare:CC
-        (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:DI 2 "reg_or_short_operand" "I,r,I,r"))
-                 (match_operand:DI 3 "gpc_reg_operand" "r,r,r,r"))
+        (gtu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+                (match_operand:P 2 "reg_or_short_operand" "rI,rI"))
         (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,&r,&r")
-       (plus:DI (gtu:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_64BIT"
-  "@
-   addic %0,%1,%k2\;addze. %0,%3
-   subf%I2c %0,%1,%2\;subfe %0,%0,%0\;subf. %0,%0,%3
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12,12,16")])
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (gtu:P (match_dup 1) (match_dup 2)))]
+  ""
+  "#"
+  ""
+  [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
+   (parallel [(set (match_dup 3)
+                  (compare:CC (neg:P (match_dup 0)) (const_int 0)))
+             (set (match_dup 0) (neg:P (match_dup 0)))])]
+  "")
 
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
+(define_insn_and_split "*plus_gtu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
+        (plus:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
+                      (match_operand:P 2 "reg_or_short_operand" "rI"))
+               (match_operand:P 3 "reg_or_short_operand" "rI")))]
+  ""
+  "#"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+  [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
+   (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))]
+  "")
+
+(define_insn_and_split "*plus_gtu<mode>_compare"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC
-        (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                         (match_operand:DI 2 "reg_or_short_operand" ""))
-                 (match_operand:DI 3 "gpc_reg_operand" ""))
+        (plus:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
+                       (match_operand:P 2 "reg_or_short_operand" "I,r,I,r"))
+                (match_operand:P 3 "gpc_reg_operand" "r,r,r,r"))
         (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (plus:DI (gtu:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_64BIT && reload_completed"
-  [(set (match_dup 0)
-       (plus:DI (gtu:DI (match_dup 1) (match_dup 2)) (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
+   (set (match_operand:P 0 "gpc_reg_operand" "=&r,&r,&r,&r")
+       (plus:P (gtu:P (match_dup 1) (match_dup 2)) (match_dup 3)))]
+  ""
+  "#"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+  [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
+   (parallel [(set (match_dup 4)
+                  (compare:CC (minus:P (match_dup 3) (match_dup 0))
+                              (const_int 0)))
+             (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))])]
   "")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (neg:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                       (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
-  "TARGET_32BIT"
+(define_insn "*neg_gtu<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (neg:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
+                     (match_operand:P 2 "reg_or_short_operand" "rI"))))]
+  ""
   "{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0"
   [(set_attr "type" "two")
    (set_attr "length" "8")])
 
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (neg:DI (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"
-  [(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
 {
   return output_cbranch (operands[0], NULL, 0, insn);
 }"
-  [(set_attr "type" "branch")
+  [(set_attr "type" "jmpreg")
    (set_attr "length" "4")])
 
 (define_insn ""
 {
   return output_cbranch (operands[0], NULL, 1, insn);
 }"
-  [(set_attr "type" "branch")
+  [(set_attr "type" "jmpreg")
    (set_attr "length" "4")])
 
 ;; Logic on condition register values.
   [(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 "" ""))
   operands[4] = gen_reg_rtx (DImode);
 }")
 
-(define_insn ""
+(define_insn "*tablejump<mode>_internal1"
   [(set (pc)
-       (match_operand:SI 0 "register_operand" "c,*l"))
+       (match_operand:P 0 "register_operand" "c,*l"))
    (use (label_ref (match_operand 1 "" "")))]
-  "TARGET_32BIT"
+  ""
   "@
    bctr
    {br|blr}"
   [(set_attr "type" "jmpreg")])
 
-(define_insn ""
-  [(set (pc)
-       (match_operand:DI 0 "register_operand" "c,*l"))
-   (use (label_ref (match_operand 1 "" "")))]
-  "TARGET_64BIT"
-  "@
-   bctr
-   blr"
-  [(set_attr "type" "jmpreg")])
-
 (define_insn "nop"
   [(const_int 0)]
   ""
   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 "nonimmediate_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 "nonimmediate_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 "nonimmediate_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 "nonimmediate_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)
 
 ;; 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 "nonimmediate_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 "nonimmediate_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 "nonimmediate_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 "nonimmediate_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" "")
+                                     [(match_operand:P 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)))
+   (set (match_operand:P 0 "gpc_reg_operand" "")
+       (plus:P (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" "")
-                                      (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)))
-   (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.
 
                   [(set (match_operand:SI 1 "memory_operand" "=m")
                                 (match_operand:SI 2 "gpc_reg_operand" "r"))])]
   "TARGET_MULTIPLE"
-  "{stm|stmw} %2,%1")
-
-(define_insn "*save_fpregs_si"
-  [(match_parallel 0 "any_parallel_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")])
+  "{stm|stmw} %2,%1"
+  [(set_attr "type" "store_ux")])
 
-(define_insn "*save_fpregs_di"
+(define_insn "*save_fpregs_<mode>"
   [(match_parallel 0 "any_parallel_operand"
-                  [(clobber (match_operand:DI 1 "register_operand" "=l"))
-                   (use (match_operand:DI 2 "call_operand" "s"))
+                  [(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")])
 
 ; The load-multiple instructions have similar properties.
 ; Note that "load_multiple" is a name known to the machine-independent
-; code that actually corresponds to the powerpc load-string.
+; code that actually corresponds to the PowerPC load-string.
 
 (define_insn "*lmw"
   [(match_parallel 0 "lmw_operation"
                   [(set (match_operand:SI 1 "gpc_reg_operand" "=r")
                                 (match_operand:SI 2 "memory_operand" "m"))])]
   "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")])
+  "{lm|lmw} %1,%2"
+  [(set_attr "type" "load_ux")])
 
-(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_parallel_operand" is a bit flexible...
 
-(define_insn "*return_and_restore_fpregs_si"
- [(match_parallel 0 "any_parallel_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")
-
-(define_insn "*return_and_restore_fpregs_di"
+(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
 }")
 
 (define_insn "prefetch"
-  [(prefetch (match_operand:V4SI 0 "address_operand" "p")
+  [(prefetch (match_operand 0 "indexed_or_indirect_address" "a")
             (match_operand:SI 1 "const_int_operand" "n")
             (match_operand:SI 2 "const_int_operand" "n"))]
   "TARGET_POWERPC"
   return INTVAL (operands[1]) ? \"dcbtst %a0\" : \"dcbt %a0\";
 }"
   [(set_attr "type" "load")])
+\f
 
+(include "sync.md")
 (include "altivec.md")
 (include "spe.md")