OSDN Git Service

PR target/34393
[pf3gnuchains/gcc-fork.git] / gcc / config / rs6000 / rs6000.md
index 8ed55f4..d1b43dc 100644 (file)
@@ -1,13 +1,14 @@
 ;; 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, 2007
+;; Free Software Foundation, Inc.
 ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 ;; This file is part of GCC.
 
 ;; GCC is free software; you can redistribute it and/or modify it
 ;; under the terms of the GNU General Public License as published
-;; by the Free Software Foundation; either version 2, or (at your
+;; by the Free Software Foundation; either version 3, or (at your
 ;; option) any later version.
 
 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
 ;; License for more details.
 
 ;; 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, 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301, USA.
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
 
 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
 
 ;;
+;; REGNOS
+;;
+
+(define_constants
+  [(MQ_REGNO                   64)
+   (LR_REGNO                   65)
+   (CTR_REGNO                  66)
+   (CR0_REGNO                  68)
+   (CR1_REGNO                  69)
+   (CR2_REGNO                  70)
+   (CR3_REGNO                  71)
+   (CR4_REGNO                  72)
+   (CR5_REGNO                  73)
+   (CR6_REGNO                  74)
+   (CR7_REGNO                  75)
+   (MAX_CR_REGNO               75)
+   (XER_REGNO                  76)
+   (FIRST_ALTIVEC_REGNO                77)
+   (LAST_ALTIVEC_REGNO         108)
+   (VRSAVE_REGNO               109)
+   (VSCR_REGNO                 110)
+   (SPE_ACC_REGNO              111)
+   (SPEFSCR_REGNO              112)
+   (SFP_REGNO                  113)
+  ])
+
+;;
 ;; UNSPEC usage
 ;;
 
    (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)
@@ -50,7 +81,7 @@
    (UNSPEC_TLSGOTTPREL         28)
    (UNSPEC_TLSTLS              29)
    (UNSPEC_FIX_TRUNC_TF                30)     ; fadd, rounding towards zero
-   (UNSPEC_MV_CR_GT            31)     ; move_from_CR_eq_bit
+   (UNSPEC_MV_CR_GT            31)     ; move_from_CR_gt_bit
    (UNSPEC_STFIWX              32)
    (UNSPEC_POPCNTB             33)
    (UNSPEC_FRES                        34)
    (UNSPEC_CMPXCHG             42)
    (UNSPEC_XCHG                        43)
    (UNSPEC_AND                 44)
+   (UNSPEC_DLMZB               45)
+   (UNSPEC_DLMZB_CR            46)
+   (UNSPEC_DLMZB_STRLEN                47)
+   (UNSPEC_RSQRT               48)
   ])
 
 ;;
 \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,isync,sync,load_l,store_c"
+(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,var_delayed_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,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr"
   (const_string "integer"))
 
 ;; Length (in bytes).
 ;; Processor type -- this attribute must exactly match the processor_type
 ;; enumeration in rs6000.h.
 
-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,power4,power5"
+(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,power4,power5,power6,cell"
   (const (symbol_ref "rs6000_cpu_attr")))
 
+
+;; If this instruction is microcoded on the CELL processor
+; The default for load and stores is conditional
+; The default for load extended and the recorded instructions is always microcoded
+(define_attr "cell_micro" "not,conditional,always"
+  (if_then_else (ior (ior (eq_attr "type" "load")
+                          (eq_attr "type" "store"))
+                     (ior (eq_attr "type" "fpload")
+                          (eq_attr "type" "fpstore")))
+               (const_string "conditional")
+                (if_then_else (ior (eq_attr "type" "load_ext")
+                                  (ior (eq_attr "type" "compare")
+                                       (eq_attr "type" "delayed_compare")))
+                             (const_string "always")
+                              (const_string "not"))))
+
+
 (automata_option "ndfa")
 
 (include "rios1.md")
 (include "8540.md")
 (include "power4.md")
 (include "power5.md")
+(include "power6.md")
+(include "cell.md")
 
 (include "predicates.md")
+(include "constraints.md")
 
 (include "darwin.md")
 
 \f
-;; Mode macros
+;; Mode iterators
 
-; This mode macro allows :GPR to be used to indicate the allowable size
+; This mode iterator allows :GPR to be used to indicate the allowable size
 ; of whole values in GPRs.
-(define_mode_macro GPR [SI (DI "TARGET_POWERPC64")])
+(define_mode_iterator GPR [SI (DI "TARGET_POWERPC64")])
 
 ; Any supported integer mode.
-(define_mode_macro INT [QI HI SI DI TI])
+(define_mode_iterator 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")])
+(define_mode_iterator INT1 [QI HI SI (DI "TARGET_POWERPC64")])
 
 ; extend modes for DImode
-(define_mode_macro QHSI [QI HI SI])
+(define_mode_iterator QHSI [QI HI SI])
 
 ; SImode or DImode, even if DImode doesn't fit in GPRs.
-(define_mode_macro SDI [SI DI])
+(define_mode_iterator 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")])
+(define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
 
 ; Any hardware-supported floating-point mode
-(define_mode_macro FP [(SF "TARGET_HARD_FLOAT")
+(define_mode_iterator FP [(SF "TARGET_HARD_FLOAT")
   (DF "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)")
-  (TF "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128")])
+  (TF "!TARGET_IEEEQUAD
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && TARGET_LONG_DOUBLE_128")
+  (DD "TARGET_DFP")
+  (TD "TARGET_DFP")])
 
 ; Various instructions that come in SI and DI forms.
 ; A generic w/d attribute, for things like cmpw/cmpd.
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (sign_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC64"
-  "extsb %0,%1")
+  "extsb %0,%1"
+  [(set_attr "type" "exts")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    lha%U1%X1 %0,%1
    extsh %0,%1"
-  [(set_attr "type" "load_ext,*")])
+  [(set_attr "type" "load_ext,exts")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    lwa%U1%X1 %0,%1
    extsw %0,%1"
-  [(set_attr "type" "load_ext,*")])
+  [(set_attr "type" "load_ext,exts")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (sign_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC"
-  "extsb %0,%1")
+  "extsb %0,%1"
+  [(set_attr "type" "exts")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   [(set (match_operand:HI 0 "gpc_reg_operand" "=r")
        (sign_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC"
-  "extsb %0,%1")
+  "extsb %0,%1"
+  [(set_attr "type" "exts")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    lha%U1%X1 %0,%1
    {exts|extsh} %0,%1"
-  [(set_attr "type" "load_ext,*")])
+  [(set_attr "type" "load_ext,exts")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   [(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" ""))
        (plus:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
                  (match_operand:SDI 2 "reg_or_add_cint_operand" "")))]
   ""
-  "
 {
   if (<MODE>mode == DImode && ! TARGET_POWERPC64)
     {
   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]))
+      rtx tmp = ((!can_create_pseudo_p ()
+                 || rtx_equal_p (operands[0], operands[1]))
                 ? 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, <MODE>mode);
 
-      if (<MODE>mode == DImode && !CONST_OK_FOR_LETTER_P (rest, 'L'))
+      if (<MODE>mode == DImode && !satisfies_constraint_L (GEN_INT (rest)))
        FAIL;
 
       /* The ordering here is important for the prolog expander.
       emit_insn (gen_add<mode>3 (operands[0], tmp, GEN_INT (low)));
       DONE;
     }
-}")
+})
 
 ;; Discourage ai/addic because of carry but provide it in an alternative
 ;; allowing register zero as source.
   [(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")))]
-  ""
+  "!DECIMAL_FLOAT_MODE_P (GET_MODE (operands[0])) && !DECIMAL_FLOAT_MODE_P (GET_MODE (operands[1]))"
   "@
    {cax|add} %0,%1,%2
    {cal %0,%2(%1)|addi %0,%1,%2}
   ""
   [(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, <MODE>mode);
 
   operands[4] = GEN_INT (low);
-  if (<MODE>mode == SImode || CONST_OK_FOR_LETTER_P (rest, 'L'))
+  if (<MODE>mode == SImode || satisfies_constraint_L (GEN_INT (rest)))
     operands[3] = GEN_INT (rest);
-  else if (! no_new_pseudos)
+  else if (can_create_pseudo_p ())
     {
       operands[3] = gen_reg_rtx (DImode);
       emit_move_insn (operands[3], operands[2]);
     }
   else
     FAIL;
-}")
+})
 
 (define_insn "one_cmpl<mode>2"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
        (clz:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
   ""
-  "{cntlz|cntlz<wd>} %0,%1")
+  "{cntlz|cntlz<wd>} %0,%1"
+  [(set_attr "type" "cntlz")])
 
 (define_expand "ctz<mode>2"
   [(set (match_dup 2)
-       (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))
+       (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))
    (parallel [(set (match_dup 3) (and:GPR (match_dup 1)
                                          (match_dup 2)))
              (clobber (scratch:CC))])
    (set (match_dup 4) (clz:GPR (match_dup 3)))
-   (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+   (set (match_operand:GPR 0 "gpc_reg_operand" "")
        (minus:GPR (match_dup 5) (match_dup 4)))]
   ""
   {
 
 (define_expand "ffs<mode>2"
   [(set (match_dup 2)
-       (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))
+       (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))
    (parallel [(set (match_dup 3) (and:GPR (match_dup 1)
                                          (match_dup 2)))
              (clobber (scratch:CC))])
    (set (match_dup 4) (clz:GPR (match_dup 3)))
-   (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+   (set (match_operand:GPR 0 "gpc_reg_operand" "")
        (minus:GPR (match_dup 5) (match_dup 4)))]
   ""
   {
      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")]
   "TARGET_POPCNTB"
   "popcntb %0,%1")
 
+(define_expand "popcount<mode>2"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+       (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
+  "TARGET_POPCNTB"
+  {
+    rs6000_emit_popcount (operands[0], operands[1]);
+    DONE;
+  })
+
+(define_expand "parity<mode>2"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+       (parity:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
+  "TARGET_POPCNTB"
+  {
+    rs6000_emit_parity (operands[0], operands[1]);
+    DONE;
+  })
+
+(define_insn "bswapsi2"
+  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,Z,&r")
+       (bswap:SI (match_operand:SI 1 "reg_or_mem_operand" "Z,r,r")))]
+  ""
+  "@
+   {lbrx|lwbrx} %0,%y1
+   {stbrx|stwbrx} %1,%y0
+   #"
+  [(set_attr "length" "4,4,12")])
+
+(define_split
+  [(set (match_operand:SI 0 "gpc_reg_operand" "")
+       (bswap:SI (match_operand:SI 1 "gpc_reg_operand" "")))]
+  "reload_completed"
+  [(set (match_dup 0)
+       (rotate:SI (match_dup 1) (const_int 8)))
+   (set (zero_extract:SI (match_dup 0)
+                        (const_int 8)
+                        (const_int 0))
+       (match_dup 1))
+   (set (zero_extract:SI (match_dup 0)
+                        (const_int 8)
+                        (const_int 16))
+       (rotate:SI (match_dup 1)
+                  (const_int 16)))]
+  "")
+
 (define_expand "mulsi3"
   [(use (match_operand:SI 0 "gpc_reg_operand" ""))
    (use (match_operand:SI 1 "gpc_reg_operand" ""))
                  (match_operand:GPR 2 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC && ! TARGET_POWER"
   "div<wd>u %0,%1,%2"
-  [(set_attr "type" "idiv")])
+   [(set (attr "type")
+      (cond [(match_operand:SI 0 "" "")
+               (const_string "idiv")]
+       (const_string "ldiv")))])
+
 
 ;; 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
     ;
   else if (TARGET_POWERPC)
     {
-      operands[2] = force_reg (SImode, operands[2]);
+      operands[2] = force_reg (<MODE>mode, operands[2]);
       if (TARGET_POWER)
        {
          emit_insn (gen_divsi3_mq (operands[0], operands[1], operands[2]));
                 (match_operand:GPR 2 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC && ! TARGET_POWER"
   "div<wd> %0,%1,%2"
-  [(set_attr "type" "idiv")])
+  [(set (attr "type")
+     (cond [(match_operand:SI 0 "" "")
+               (const_string "idiv")]
+       (const_string "ldiv")))])
 
 (define_expand "mod<mode>3"
   [(use (match_operand:GPR 0 "gpc_reg_operand" ""))
         (lshiftrt:DI (mult:DI (sign_extend:DI (reg:SI 3))
                               (sign_extend:DI (reg:SI 4)))
                      (const_int 32))))
-   (clobber (match_scratch:SI 0 "=l"))]
+   (clobber (reg:SI LR_REGNO))]
   "! TARGET_POWER && ! TARGET_POWERPC"
   "bla __mulh"
   [(set_attr "type" "imul")])
   [(set (reg:DI 3)
        (mult:DI (sign_extend:DI (reg:SI 3))
                 (sign_extend:DI (reg:SI 4))))
-   (clobber (match_scratch:SI 0 "=l"))
+   (clobber (reg:SI LR_REGNO))
    (clobber (reg:SI 0))]
   "! TARGET_POWER && ! TARGET_POWERPC"
   "bla __mull"
        (div:SI (reg:SI 3) (reg:SI 4)))
    (set (reg:SI 4)
        (mod:SI (reg:SI 3) (reg:SI 4)))
-   (clobber (match_scratch:SI 0 "=l"))
+   (clobber (reg:SI LR_REGNO))
    (clobber (reg:SI 0))]
   "! TARGET_POWER && ! TARGET_POWERPC"
   "bla __divss"
        (udiv:SI (reg:SI 3) (reg:SI 4)))
    (set (reg:SI 4)
        (umod:SI (reg:SI 3) (reg:SI 4)))
-   (clobber (match_scratch:SI 0 "=l"))
+   (clobber (reg:SI LR_REGNO))
    (clobber (reg:SI 0))
-   (clobber (match_scratch:CC 1 "=x"))
-   (clobber (reg:CC 69))]
+   (clobber (match_scratch:CC 0 "=x"))
+   (clobber (reg:CC CR1_REGNO))]
   "! TARGET_POWER && ! TARGET_POWERPC"
   "bla __divus"
   [(set_attr "type" "idiv")])
 (define_insn "quoss_call"
   [(set (reg:SI 3)
        (div:SI (reg:SI 3) (reg:SI 4)))
-   (clobber (match_scratch:SI 0 "=l"))]
+   (clobber (reg:SI LR_REGNO))]
   "! TARGET_POWER && ! TARGET_POWERPC"
   "bla __quoss"
   [(set_attr "type" "idiv")])
 (define_insn "quous_call"
   [(set (reg:SI 3)
        (udiv:SI (reg:SI 3) (reg:SI 4)))
-   (clobber (match_scratch:SI 0 "=l"))
+   (clobber (reg:SI LR_REGNO))
    (clobber (reg:SI 0))
-   (clobber (match_scratch:CC 1 "=x"))
-   (clobber (reg:CC 69))]
+   (clobber (match_scratch:CC 0 "=x"))
+   (clobber (reg:CC CR1_REGNO))]
   "! TARGET_POWER && ! TARGET_POWERPC"
   "bla __quous"
   [(set_attr "type" "idiv")])
       && ! logical_operand (operands[2], SImode))
     {
       HOST_WIDE_INT value = INTVAL (operands[2]);
-      rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
+      rtx tmp = ((!can_create_pseudo_p ()
+                 || rtx_equal_p (operands[0], operands[1]))
                 ? operands[0] : gen_reg_rtx (SImode));
 
       emit_insn (gen_iorsi3 (tmp, operands[1],
       && ! logical_operand (operands[2], SImode))
     {
       HOST_WIDE_INT value = INTVAL (operands[2]);
-      rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
+      rtx tmp = ((!can_create_pseudo_p ()
+                 || rtx_equal_p (operands[0], operands[1]))
                 ? operands[0] : gen_reg_rtx (SImode));
 
       emit_insn (gen_xorsi3 (tmp, operands[1],
 {
   /* Do not handle 16/8 bit structures that fit in HI/QI modes directly, since
      the (SUBREG:SI (REG:HI xxx)) that is otherwise generated can confuse the
-     compiler if the address of the structure is taken later.  */
+     compiler if the address of the structure is taken later.  Likewise, do
+     not handle invalid E500 subregs.  */
   if (GET_CODE (operands[0]) == SUBREG
-      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD))
+      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD
+         || ((TARGET_E500_DOUBLE || TARGET_SPE)
+             && invalid_e500_subreg (operands[0], GET_MODE (operands[0])))))
     FAIL;
 
   if (TARGET_POWERPC64 && GET_MODE (operands[0]) == DImode)
 
   operands[1] = GEN_INT (64 - start - size);
   return \"rldimi %0,%3,%H1,%H2\";
-}")
+}"
+  [(set_attr "type" "insert_dword")])
 
 (define_insn "*insvdi_internal2"
   [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
     operands[3] = GEN_INT (start + size);
   return \"{rlinm.|rlwinm.} %4,%1,%3,%s2,31\";
 }"
-  [(set_attr "type" "compare")
+  [(set_attr "type" "delayed_compare")
    (set_attr "length" "4,8")])
 
 (define_split
     operands[3] = GEN_INT (start + size);
   return \"{rlinm.|rlwinm.} %0,%1,%3,%s2,31\";
 }"
-  [(set_attr "type" "compare")
+  [(set_attr "type" "delayed_compare")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set_attr "type" "compare")])
 
 (define_insn "rotlsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                  (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+       (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                  (match_operand:SI 2 "reg_or_cint_operand" "r,i")))]
   ""
-  "{rl%I2nm|rlw%I2nm} %0,%1,%h2,0xffffffff")
+  "@
+   {rlnm|rlwnm} %0,%1,%2,0xffffffff
+   {rlinm|rlwinm} %0,%1,%h2,0xffffffff"
+  [(set_attr "type" "var_shift_rotate,integer")])
 
 (define_insn "*rotlsi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                              (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
+   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
   ""
   "@
-   {rl%I2nm.|rlw%I2nm.} %3,%1,%h2,0xffffffff
+   {rlnm.|rlwnm.} %3,%1,%2,0xffffffff
+   {rlinm.|rlwinm.} %3,%1,%h2,0xffffffff
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                              (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
        (rotate:SI (match_dup 1) (match_dup 2)))]
   ""
   "@
-   {rl%I2nm.|rlw%I2nm.} %0,%1,%h2,0xffffffff
+   {rlnm.|rlwnm.} %0,%1,%2,0xffffffff
+   {rlinm.|rlwinm.} %0,%1,%h2,0xffffffff
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal4"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (and:SI (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                          (match_operand:SI 2 "reg_or_cint_operand" "ri"))
-               (match_operand:SI 3 "mask_operand" "n")))]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+       (and:SI (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                          (match_operand:SI 2 "reg_or_cint_operand" "r,i"))
+               (match_operand:SI 3 "mask_operand" "n,n")))]
   ""
-  "{rl%I2nm|rlw%I2nm} %0,%1,%h2,%m3,%M3")
+  "@
+   {rlnm|rlwnm} %0,%1,%2,%m3,%M3
+   {rlinm|rlwinm} %0,%1,%h2,%m3,%M3"
+  [(set_attr "type" "var_shift_rotate,integer")])
 
 (define_insn "*rotlsi3_internal5"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (and:SI
-                    (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                               (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
-                    (match_operand:SI 3 "mask_operand" "n,n"))
+                    (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                               (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
+                    (match_operand:SI 3 "mask_operand" "n,n,n,n"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 4 "=r,r"))]
+   (clobber (match_scratch:SI 4 "=r,r,r,r"))]
   ""
   "@
-   {rl%I2nm.|rlw%I2nm.} %4,%1,%h2,%m3,%M3
+   {rlnm.|rlwnm.} %4,%1,%2,%m3,%M3
+   {rlinm.|rlwinm.} %4,%1,%h2,%m3,%M3
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal6"
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (and:SI
-                    (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                               (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
-                    (match_operand:SI 3 "mask_operand" "n,n"))
+                    (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                               (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
+                    (match_operand:SI 3 "mask_operand" "n,n,n,n"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
        (and:SI (rotate:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
   ""
   "@
-   {rl%I2nm.|rlw%I2nm.} %0,%1,%h2,%m3,%M3
+   {rlnm.|rlwnm.} %0,%1,%2,%m3,%M3
+   {rlinm.|rlwinm.} %0,%1,%h2,%m3,%M3
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
   "{rl%I2nm|rlw%I2nm} %0,%1,%h2,0xff")
 
 (define_insn "*rotlsi3_internal8"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:SI
                     (subreg:QI
-                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
+   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
   ""
   "@
-   {rl%I2nm.|rlw%I2nm.} %3,%1,%h2,0xff
+   {rlnm.|rlwnm.} %3,%1,%2,0xff
+   {rlinm.|rlwinm.} %3,%1,%h2,0xff
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal9"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:SI
                     (subreg:QI
-                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
        (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 0)))]
   ""
   "@
-   {rl%I2nm.|rlw%I2nm.} %0,%1,%h2,0xff
+   {rlnm.|rlwnm.} %0,%1,%2,0xff
+   {rlinm.|rlwinm.} %0,%1,%h2,0xff
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal10"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
        (zero_extend:SI
         (subreg:HI
-         (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                    (match_operand:SI 2 "reg_or_cint_operand" "ri")) 0)))]
+         (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                    (match_operand:SI 2 "reg_or_cint_operand" "r,i")) 0)))]
   ""
-  "{rl%I2nm|rlw%I2nm} %0,%1,%h2,0xffff")
+  "@
+   {rlnm|rlwnm} %0,%1,%2,0xffff
+   {rlinm|rlwinm} %0,%1,%h2,0xffff"
+  [(set_attr "type" "var_shift_rotate,integer")])
+
 
 (define_insn "*rotlsi3_internal11"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:SI
                     (subreg:HI
-                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
+   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
   ""
   "@
-   {rl%I2nm.|rlw%I2nm.} %3,%1,%h2,0xffff
+   {rlnm.|rlwnm.} %3,%1,%2,0xffff
+   {rlinm.|rlwinm.} %3,%1,%h2,0xffff
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal12"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:SI
                     (subreg:HI
-                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
        (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 0)))]
   ""
   "@
-   {rl%I2nm.|rlw%I2nm.} %0,%1,%h2,0xffff
+   {rlnm.|rlwnm.} %0,%1,%2,0xffff
+   {rlinm.|rlwinm.} %0,%1,%h2,0xffff
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
    {sli|slwi} %0,%1,%h2")
 
 (define_insn "ashlsi3_no_power"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                  (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+       (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                  (match_operand:SI 2 "reg_or_cint_operand" "r,i")))]
   "! TARGET_POWER"
-  "{sl|slw}%I2 %0,%1,%h2")
+  "@
+   {sl|slw} %0,%1,%2
+   {sli|slwi} %0,%1,%h2"
+  [(set_attr "type" "var_shift_rotate,shift")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
   "")
 
 (define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                              (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
+   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
   "! TARGET_POWER && TARGET_32BIT"
   "@
-   {sl|slw}%I2. %3,%1,%h2
+   {sl.|slw.} %3,%1,%2
+   {sli.|slwi.} %3,%1,%h2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                              (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
        (ashift:SI (match_dup 1) (match_dup 2)))]
   "! TARGET_POWER && TARGET_32BIT"
   "@
-   {sl|slw}%I2. %0,%1,%h2
+   {sl.|slw.} %0,%1,%2
+   {sli.|slwi.} %0,%1,%h2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
   {s%A2i|s%A2wi} %0,%1,%h2")
 
 (define_insn "lshrsi3_no_power"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                    (match_operand:SI 2 "reg_or_cint_operand" "O,ri")))]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r")
+       (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r")
+                    (match_operand:SI 2 "reg_or_cint_operand" "O,r,i")))]
   "! TARGET_POWER"
   "@
   mr %0,%1
-  {sr|srw}%I2 %0,%1,%h2")
+  {sr|srw} %0,%1,%2
+  {sri|srwi} %0,%1,%h2"
+  [(set_attr "type" "integer,var_shift_rotate,shift")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,?y,?y,?y")
   "")
 
 (define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "O,ri,O,ri"))
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,?y,?y,?y")
+       (compare:CC (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "O,r,i,O,r,i"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=X,r,X,r"))]
+   (clobber (match_scratch:SI 3 "=X,r,r,X,r,r"))]
   "! TARGET_POWER && TARGET_32BIT"
   "@
    mr. %1,%1
-   {sr|srw}%I2. %3,%1,%h2
+   {sr.|srw.} %3,%1,%2
+   {sri.|srwi.} %3,%1,%h2
+   #
    #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "delayed_compare,var_delayed_compare,delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,4,8,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "O,ri,O,ri"))
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,?y,?y,?y")
+       (compare:CC (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "O,r,i,O,r,i"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r,r")
        (lshiftrt:SI (match_dup 1) (match_dup 2)))]
   "! TARGET_POWER && TARGET_32BIT"
   "@
    mr. %0,%1
-   {sr|srw}%I2. %0,%1,%h2
+   {sr.|srw.} %0,%1,%2
+   {sri.|srwi.} %0,%1,%h2
+   #
    #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "delayed_compare,var_delayed_compare,delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,4,8,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
   "TARGET_POWER"
   "@
    srea %0,%1,%2
-   {srai|srawi} %0,%1,%h2")
+   {srai|srawi} %0,%1,%h2"
+  [(set_attr "type" "shift")])
 
 (define_insn "ashrsi3_no_power"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                    (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+       (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                    (match_operand:SI 2 "reg_or_cint_operand" "r,i")))]
   "! TARGET_POWER"
-  "{sra|sraw}%I2 %0,%1,%h2")
+  "@
+   {sra|sraw} %0,%1,%2
+   {srai|srawi} %0,%1,%h2"
+  [(set_attr "type" "var_shift_rotate,shift")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
   "")
 
 (define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
+   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
   "! TARGET_POWER"
   "@
-   {sra|sraw}%I2. %3,%1,%h2
+   {sra.|sraw.} %3,%1,%2
+   {srai.|srawi.} %3,%1,%h2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
        (ashiftrt:SI (match_dup 1) (match_dup 2)))]
   "! TARGET_POWER"
   "@
-   {sra|sraw}%I2. %0,%1,%h2
+   {sra.|sraw.} %0,%1,%2
+   {srai.|srawi.} %0,%1,%h2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 \f
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
   "{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")
   "{fd|fdiv} %0,%1,%2"
   [(set_attr "type" "ddiv")])
 
+(define_expand "recipsf3"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")
+                   (match_operand:SF 2 "gpc_reg_operand" "f")]
+                  UNSPEC_FRES))]
+  "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT && !optimize_size
+   && flag_finite_math_only && !flag_trapping_math"
+{
+   rs6000_emit_swdivsf (operands[0], operands[1], operands[2]);
+   DONE;
+})
+
+(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_insn ""
   [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
        (plus:SF (mult:SF (match_operand:SF 1 "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" "")
   "fsqrt %0,%1"
   [(set_attr "type" "dsqrt")])
 
+(define_expand "rsqrtsf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")]
+                  UNSPEC_RSQRT))]
+  "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT && !optimize_size
+   && flag_finite_math_only && !flag_trapping_math"
+{
+  rs6000_emit_swrsqrtsf (operands[0], operands[1]);
+  DONE;
+})
+
+(define_insn "*rsqrt_internal1"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")]
+                  UNSPEC_RSQRT))]
+  "TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT"
+  "frsqrte %0,%1"
+  [(set_attr "type" "fp")])
+
 (define_expand "copysignsf3"
   [(set (match_dup 3)
         (abs:SF (match_operand:SF 1 "gpc_reg_operand" "")))
   "{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")
   "{fd|fdiv} %0,%1,%2"
   [(set_attr "type" "ddiv")])
 
+(define_expand "recipdf3"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+       (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")
+                   (match_operand:DF 2 "gpc_reg_operand" "f")]
+                  UNSPEC_FRES))]
+  "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_POPCNTB && !optimize_size
+   && flag_finite_math_only && !flag_trapping_math"
+{
+   rs6000_emit_swdivdf (operands[0], operands[1], operands[2]);
+   DONE;
+})
+
+(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_insn ""
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
              (clobber (match_dup 4))
              (clobber (match_dup 5))
              (clobber (match_dup 6))])]
-  "TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
   "
 {
   if (TARGET_E500_DOUBLE)
       emit_insn (gen_spe_floatsidf2 (operands[0], operands[1]));
       DONE;
     }
+  if (TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS)
+    {
+      rtx t1 = gen_reg_rtx (DImode);
+      emit_insn (gen_floatsidf_ppc64_mfpgpr (operands[0], operands[1], t1));
+      DONE;
+    }
   if (TARGET_POWERPC64)
     {
       rtx mem = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
        (float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
    (use (match_operand:SI 2 "gpc_reg_operand" "r"))
    (use (match_operand:DF 3 "gpc_reg_operand" "f"))
-   (clobber (match_operand:DF 4 "memory_operand" "=o"))
+   (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
    (clobber (match_operand:DF 5 "gpc_reg_operand" "=&f"))
    (clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
   "#"
-  "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[4]))"
+  "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[4]))"
   [(pc)]
   "
 {
        (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
    (use (match_operand:SI 2 "gpc_reg_operand" "r"))
    (use (match_operand:DF 3 "gpc_reg_operand" "f"))
-   (clobber (match_operand:DF 4 "memory_operand" "=o"))
+   (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
    (clobber (match_operand:DF 5 "gpc_reg_operand" "=&f"))]
   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
   "#"
-  "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[4]))"
+  "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[4]))"
   [(pc)]
   "
 {
      DONE;
     }
   operands[2] = gen_reg_rtx (DImode);
+  if (TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+      && gpc_reg_operand(operands[0], GET_MODE (operands[0])))
+    {
+      operands[3] = gen_reg_rtx (DImode);
+      emit_insn (gen_fix_truncdfsi2_mfpgpr (operands[0], operands[1],
+                                           operands[2], operands[3]));
+      DONE;
+    }
   if (TARGET_PPC_GFXOPT)
     {
       rtx orig_dest = operands[0];
   [(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"))]
+   (clobber (match_operand:DI 3 "offsettable_mem_operand" "=o"))]
   "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
   "#"
-  "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[3]))"
+  "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[3]))"
   [(pc)]
   "
 {
 }"
   [(set_attr "length" "16")])
 
+(define_insn_and_split "fix_truncdfsi2_mfpgpr"
+  [(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 "gpc_reg_operand" "=r"))]
+  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "#"
+  "&& 1"
+  [(set (match_dup 2) (unspec:DI [(fix:SI (match_dup 1))] UNSPEC_FCTIWZ))
+   (set (match_dup 3) (match_dup 2))
+   (set (match_dup 0) (subreg:SI (match_dup 3) 4))]
+  ""
+  [(set_attr "length" "12")])
+
 ; 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
   "{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")
   "fcfid %0,%1"
   [(set_attr "type" "fp")])
 
+(define_insn_and_split "floatsidf_ppc64_mfpgpr"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+       (float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
+   (clobber (match_operand:DI 2 "gpc_reg_operand" "=r"))]
+  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "#"
+  "&& 1"
+  [(set (match_dup 2) (sign_extend:DI (match_dup 1)))
+   (set (match_dup 0) (float:DF (match_dup 2)))]
+  "")
+
 (define_insn_and_split "floatsidf_ppc64"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
-   (clobber (match_operand:DI 2 "memory_operand" "=o"))
+   (clobber (match_operand:DI 2 "offsettable_mem_operand" "=o"))
    (clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))
    (clobber (match_operand:DI 4 "gpc_reg_operand" "=f"))]
-  "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS"
   "#"
   "&& 1"
   [(set (match_dup 3) (sign_extend:DI (match_dup 1)))
 (define_insn_and_split "floatunssidf_ppc64"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
-   (clobber (match_operand:DI 2 "memory_operand" "=o"))
+   (clobber (match_operand:DI 2 "offsettable_mem_operand" "=o"))
    (clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))
    (clobber (match_operand:DI 4 "gpc_reg_operand" "=f"))]
   "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
    (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)
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
        (truncate:SI
         (lshiftrt:DI (mult:DI (sign_extend:DI
-                               (match_operand:SI 1 "gpc_reg_operand" "%r"))
+                               (match_operand:SI 1 "gpc_reg_operand" ""))
                               (sign_extend:DI
-                               (match_operand:SI 2 "gpc_reg_operand" "r")))
+                               (match_operand:SI 2 "gpc_reg_operand" "")))
                      (const_int 32))))]
   ""
   "
   "@
    {srai|srawi} %0,%1,31\;{srai|srawi} %L0,%1,%h2
    sraiq %0,%1,%h2\;srliq %L0,%L1,%h2"
-  [(set_attr "length" "8")])
+  [(set_attr "type" "shift")
+   (set_attr "length" "8")])
 
 (define_insn "ashrdi3_no_power"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r")
   "")
 
 (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")))]
+  [(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"
-  "mulld %0,%1,%2"
-   [(set_attr "type" "lmul")])
+  "@
+   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 "*muldi3_internal1"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   [(set_attr "type" "lmul")])
 
 (define_insn "rotldi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                  (match_operand:DI 2 "reg_or_cint_operand" "ri")))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                  (match_operand:DI 2 "reg_or_cint_operand" "r,i")))]
   "TARGET_POWERPC64"
-  "rld%I2cl %0,%1,%H2,0")
+  "@
+   rldcl %0,%1,%2,0
+   rldicl %0,%1,%H2,0"
+  [(set_attr "type" "var_shift_rotate,integer")])
 
 (define_insn "*rotldi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                              (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
+   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
   "TARGET_64BIT"
   "@
-   rld%I2cl. %3,%1,%H2,0
+   rldcl. %3,%1,%2,0
+   rldicl. %3,%1,%H2,0
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotldi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                              (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
        (rotate:DI (match_dup 1) (match_dup 2)))]
   "TARGET_64BIT"
   "@
-   rld%I2cl. %0,%1,%H2,0
+   rldcl. %0,%1,%2,0
+   rldicl. %0,%1,%H2,0
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotldi3_internal4"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                          (match_operand:DI 2 "reg_or_cint_operand" "ri"))
-               (match_operand:DI 3 "mask_operand" "n")))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                          (match_operand:DI 2 "reg_or_cint_operand" "r,i"))
+               (match_operand:DI 3 "mask64_operand" "n,n")))]
   "TARGET_POWERPC64"
-  "rld%I2c%B3 %0,%1,%H2,%S3")
+  "@
+   rldc%B3 %0,%1,%2,%S3
+   rldic%B3 %0,%1,%H2,%S3"
+  [(set_attr "type" "var_shift_rotate,integer")])
 
 (define_insn "*rotldi3_internal5"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (and:DI
-                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                               (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
-                    (match_operand:DI 3 "mask_operand" "n,n"))
+                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                               (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i"))
+                    (match_operand:DI 3 "mask64_operand" "n,n,n,n"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 4 "=r,r"))]
+   (clobber (match_scratch:DI 4 "=r,r,r,r"))]
   "TARGET_64BIT"
   "@
-   rld%I2c%B3. %4,%1,%H2,%S3
+   rldc%B3. %4,%1,%2,%S3
+   rldic%B3. %4,%1,%H2,%S3
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
        (compare:CC (and:DI
                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
                                (match_operand:DI 2 "reg_or_cint_operand" ""))
-                    (match_operand:DI 3 "mask_operand" ""))
+                    (match_operand:DI 3 "mask64_operand" ""))
                    (const_int 0)))
    (clobber (match_scratch:DI 4 ""))]
   "TARGET_POWERPC64 && reload_completed"
   "")
 
 (define_insn "*rotldi3_internal6"
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (and:DI
-                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                               (match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
-                    (match_operand:DI 3 "mask_operand" "n,n"))
+                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                               (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i"))
+                    (match_operand:DI 3 "mask64_operand" "n,n,n,n"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
        (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
   "TARGET_64BIT"
   "@
-   rld%I2c%B3. %0,%1,%H2,%S3
+   rldc%B3. %0,%1,%2,%S3
+   rldic%B3. %0,%1,%H2,%S3
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
        (compare:CC (and:DI
                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
                                (match_operand:DI 2 "reg_or_cint_operand" ""))
-                    (match_operand:DI 3 "mask_operand" ""))
+                    (match_operand:DI 3 "mask64_operand" ""))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
        (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
   "")
 
 (define_insn "*rotldi3_internal7"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (zero_extend:DI
         (subreg:QI
-         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                    (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0)))]
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 0)))]
   "TARGET_POWERPC64"
-  "rld%I2cl %0,%1,%H2,56")
+  "@
+   rldcl %0,%1,%2,56
+   rldicl %0,%1,%H2,56"
+  [(set_attr "type" "var_shift_rotate,integer")])
 
 (define_insn "*rotldi3_internal8"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:DI
                     (subreg:QI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
+   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
   "TARGET_64BIT"
   "@
-   rld%I2cl. %3,%1,%H2,56
+   rldcl. %3,%1,%2,56
+   rldicl. %3,%1,%H2,56
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotldi3_internal9"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:DI
                     (subreg:QI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
        (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
   "TARGET_64BIT"
   "@
-   rld%I2cl. %0,%1,%H2,56
+   rldcl. %0,%1,%2,56
+   rldicl. %0,%1,%H2,56
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotldi3_internal10"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (zero_extend:DI
         (subreg:HI
-         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                    (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0)))]
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 0)))]
   "TARGET_POWERPC64"
-  "rld%I2cl %0,%1,%H2,48")
+  "@
+   rldcl %0,%1,%2,48
+   rldicl %0,%1,%H2,48"
+  [(set_attr "type" "var_shift_rotate,integer")])
 
 (define_insn "*rotldi3_internal11"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:DI
                     (subreg:HI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
+   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
   "TARGET_64BIT"
   "@
-   rld%I2cl. %3,%1,%H2,48
+   rldcl. %3,%1,%2,48
+   rldicl. %3,%1,%H2,48
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotldi3_internal12"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:DI
                     (subreg:HI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
        (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
   "TARGET_64BIT"
   "@
-   rld%I2cl. %0,%1,%H2,48
+   rldcl. %0,%1,%2,48
+   rldicl. %0,%1,%H2,48
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotldi3_internal13"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (zero_extend:DI
         (subreg:SI
-         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                    (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0)))]
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 0)))]
   "TARGET_POWERPC64"
-  "rld%I2cl %0,%1,%H2,32")
+  "@
+   rldcl %0,%1,%2,32
+   rldicl %0,%1,%H2,32"
+  [(set_attr "type" "var_shift_rotate,integer")])
 
 (define_insn "*rotldi3_internal14"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:DI
                     (subreg:SI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
+   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
   "TARGET_64BIT"
   "@
-   rld%I2cl. %3,%1,%H2,32
+   rldcl. %3,%1,%2,32
+   rldicl. %3,%1,%H2,32
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*rotldi3_internal15"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (zero_extend:DI
                     (subreg:SI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "ri,ri")) 0))
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 0))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
        (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
   "TARGET_64BIT"
   "@
-   rld%I2cl. %0,%1,%H2,32
+   rldcl. %0,%1,%2,32
+   rldicl. %0,%1,%H2,32
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
 }")
 
 (define_insn "*ashldi3_internal1"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                  (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                  (match_operand:SI 2 "reg_or_cint_operand" "r,i")))]
   "TARGET_POWERPC64"
-  "sld%I2 %0,%1,%H2")
+  "@
+   sld %0,%1,%2
+   sldi %0,%1,%H2"
+  [(set_attr "type" "var_shift_rotate,shift")])
 
 (define_insn "*ashldi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                              (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
+   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
   "TARGET_64BIT"
   "@
-   sld%I2. %3,%1,%H2
+   sld. %3,%1,%2
+   sldi. %3,%1,%H2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*ashldi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                              (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                              (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
        (ashift:DI (match_dup 1) (match_dup 2)))]
   "TARGET_64BIT"
   "@
-   sld%I2. %0,%1,%H2
+   sld. %0,%1,%2
+   sldi. %0,%1,%H2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
   "@
    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
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
                           (match_operand:SI 2 "const_int_operand" "i"))
-               (match_operand:DI 3 "mask_operand" "n")))]
+               (match_operand:DI 3 "mask64_operand" "n")))]
   "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
   "rldicr %0,%1,%H2,%S3")
 
        (compare:CC
         (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
                            (match_operand:SI 2 "const_int_operand" "i,i"))
-                (match_operand:DI 3 "mask_operand" "n,n"))
+                (match_operand:DI 3 "mask64_operand" "n,n"))
         (const_int 0)))
    (clobber (match_scratch:DI 4 "=r,r"))]
   "TARGET_64BIT && includes_rldicr_lshift_p (operands[2], operands[3])"
   "@
    rldicr. %4,%1,%H2,%S3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "compare")
    (set_attr "length" "4,8")])
 
 (define_split
        (compare:CC
         (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
                            (match_operand:SI 2 "const_int_operand" ""))
-                (match_operand:DI 3 "mask_operand" ""))
+                (match_operand:DI 3 "mask64_operand" ""))
         (const_int 0)))
    (clobber (match_scratch:DI 4 ""))]
   "TARGET_POWERPC64 && reload_completed
        (compare:CC
         (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
                            (match_operand:SI 2 "const_int_operand" "i,i"))
-                   (match_operand:DI 3 "mask_operand" "n,n"))
+                   (match_operand:DI 3 "mask64_operand" "n,n"))
         (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
   "@
    rldicr. %0,%1,%H2,%S3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "compare")
    (set_attr "length" "4,8")])
 
 (define_split
        (compare:CC
         (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
                            (match_operand:SI 2 "const_int_operand" ""))
-                (match_operand:DI 3 "mask_operand" ""))
+                (match_operand:DI 3 "mask64_operand" ""))
         (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
        (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
 }")
 
 (define_insn "*lshrdi3_internal1"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                    (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                    (match_operand:SI 2 "reg_or_cint_operand" "r,i")))]
   "TARGET_POWERPC64"
-  "srd%I2 %0,%1,%H2")
+  "@
+   srd %0,%1,%2
+   srdi %0,%1,%H2"
+  [(set_attr "type" "var_shift_rotate,shift")])
 
 (define_insn "*lshrdi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
+   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
   "TARGET_64BIT "
   "@
-   srd%I2. %3,%1,%H2
+   srd. %3,%1,%2
+   srdi. %3,%1,%H2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*lshrdi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
        (lshiftrt:DI (match_dup 1) (match_dup 2)))]
   "TARGET_64BIT"
   "@
-   srd%I2. %0,%1,%H2
+   srd. %0,%1,%2
+   srdi. %0,%1,%H2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
 }")
 
 (define_insn "*ashrdi3_internal1"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                    (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                    (match_operand:SI 2 "reg_or_cint_operand" "r,i")))]
   "TARGET_POWERPC64"
-  "srad%I2 %0,%1,%H2")
+  "@
+   srad %0,%1,%2
+   sradi %0,%1,%H2"
+  [(set_attr "type" "var_shift_rotate,shift")])
 
 (define_insn "*ashrdi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
+   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
   "TARGET_64BIT"
   "@
-   srad%I2. %3,%1,%H2
+   srad. %3,%1,%2
+   sradi. %3,%1,%H2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
   "")
 
 (define_insn "*ashrdi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                                (match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
        (ashiftrt:DI (match_dup 1) (match_dup 2)))]
   "TARGET_64BIT"
   "@
-   srad%I2. %0,%1,%H2
+   srad. %0,%1,%2
+   sradi. %0,%1,%H2
+   #
    #"
-  [(set_attr "type" "delayed_compare")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+   (set_attr "length" "4,4,8,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
    (clobber (match_scratch:CC 3 ""))]
   "TARGET_POWERPC64
     && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
-    && !mask_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)
                           (match_dup 4))
 })
 
 (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")])
+  [(set_attr "type" "compare,compare,delayed_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)"
+    && !mask_operand (operands[2], DImode)
+    && !mask64_operand (operands[2], DImode)"
   [(set (match_dup 3)
        (and:DI (rotate:DI (match_dup 1)
                           (match_dup 5))
 }")
 
 (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,delayed_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 "and_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)"
+    && !mask_operand (operands[2], DImode)
+    && !mask64_operand (operands[2], DImode)"
   [(set (match_dup 0)
        (and:DI (rotate:DI (match_dup 1)
                           (match_dup 5))
   if (non_logical_cint_operand (operands[2], DImode))
     {
       HOST_WIDE_INT value;
-      rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
+      rtx tmp = ((!can_create_pseudo_p ()
+                 || rtx_equal_p (operands[0], operands[1]))
                 ? operands[0] : gen_reg_rtx (DImode));
 
       if (GET_CODE (operands[2]) == CONST_INT)
   if (non_logical_cint_operand (operands[2], DImode))
     {
       HOST_WIDE_INT value;
-      rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
+      rtx tmp = ((!can_create_pseudo_p ()
+                 || rtx_equal_p (operands[0], operands[1]))
                 ? operands[0] : gen_reg_rtx (DImode));
 
       if (GET_CODE (operands[2]) == CONST_INT)
       value = INTVAL (offset);
       if (value != 0)
        {
-         rtx tmp = (no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode));
+         rtx tmp = (!can_create_pseudo_p ()
+                    ? operands[0]
+                    : gen_reg_rtx (Pmode));
          emit_insn (gen_movsi_got (tmp, operands[1]));
          emit_insn (gen_addsi3 (operands[0], tmp, offset));
          DONE;
   "")
 
 (define_insn "*movcc_internal1"
-  [(set (match_operand:CC 0 "nonimmediate_operand" "=y,x,?y,r,r,r,r,q,cl,r,m")
-       (match_operand:CC 1 "nonimmediate_operand" "y,r,r,x,y,r,h,r,r,m,r"))]
+  [(set (match_operand:CC 0 "nonimmediate_operand" "=y,x,?y,y,r,r,r,r,r,q,cl,r,m")
+       (match_operand:CC 1 "general_operand" "y,r,r,O,x,y,r,I,h,r,r,m,r"))]
   "register_operand (operands[0], CCmode)
    || register_operand (operands[1], CCmode)"
   "@
    mcrf %0,%1
    mtcrf 128,%1
    {rlinm|rlwinm} %1,%1,%F0,0xffffffff\;mtcrf %R0,%1\;{rlinm|rlwinm} %1,%1,%f0,0xffffffff
+   crxor %0,%0,%0
    mfcr %0%Q1
    mfcr %0%Q1\;{rlinm|rlwinm} %0,%0,%f1,0xf0000000
    mr %0,%1
+   {lil|li} %0,%1
    mf%1 %0
    mt%0 %1
    mt%0 %1
    {l%U1%X1|lwz%U1%X1} %0,%1
    {st%U0%U1|stw%U0%U1} %1,%0"
   [(set (attr "type")
-     (cond [(eq_attr "alternative" "0")
+     (cond [(eq_attr "alternative" "0,3")
                (const_string "cr_logical")
            (eq_attr "alternative" "1,2")
                (const_string "mtcr")
-           (eq_attr "alternative" "5,7")
+           (eq_attr "alternative" "6,7,9")
                (const_string "integer")
-           (eq_attr "alternative" "6")
-               (const_string "mfjmpr")
            (eq_attr "alternative" "8")
+               (const_string "mfjmpr")
+           (eq_attr "alternative" "10")
                (const_string "mtjmpr")
-           (eq_attr "alternative" "9")
+           (eq_attr "alternative" "11")
                (const_string "load")
-           (eq_attr "alternative" "10")
+           (eq_attr "alternative" "12")
                (const_string "store")
            (ne (symbol_ref "TARGET_MFCRF") (const_int 0))
                (const_string "mfcrf")
           ]
        (const_string "mfcr")))
-   (set_attr "length" "4,4,12,4,8,4,4,4,4,4,4")])
+   (set_attr "length" "4,4,12,4,4,8,4,4,4,4,4,4,4")])
 \f
 ;; For floating-point, we normally deal with the floating-point registers
 ;; unless -msoft-float is used.  The sole exception is that parameter passing
 }")
 
 (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
       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
+                 || GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY)))
        {
          /* If the low-address word is used in the address, we must load
             it last.  Otherwise, load it first.  Note that we cannot have
                                 operands[1], 0))
            return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
          else
-           return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
+           return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
        }
       else
        {
                                 operands[1], 0))
            {
              output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-             output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
+             output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands);
              output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-             return \"{lx|lwzx} %0,%1\";
+             return \"{l%X1|lwz%X1} %0,%1\";
            }
          else
            {
-             output_asm_insn (\"{lx|lwzx} %0,%1\", operands);
+             output_asm_insn (\"{l%X1|lwz%X1} %0,%1\", operands);
              output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-             output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
+             output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands);
              output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
              return \"\";
            }
        }
     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))
-       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
+                 || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
+                 || GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)))
+       return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\";
       else
        {
          rtx addreg;
 
          addreg = find_addr_reg (XEXP (operands[0], 0));
-         output_asm_insn (\"{stx|stwx} %1,%0\", operands);
+         output_asm_insn (\"{st%X0|stw%X0} %1,%0\", operands);
          output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-         output_asm_insn (\"{stx|stwx} %L1,%0\", operands);
+         output_asm_insn (\"{st%X0|stw%X0} %L1,%0\", operands);
          output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
          return \"\";
        }
                             operands[1], 0))
        return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
       else
-       return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
+       return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
     case 2:
-      return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
+      return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\";
     case 3:
     case 4:
     case 5:
 
 ; ld/std require word-aligned displacements -> 'Y' constraint.
 ; List Y->r and r->Y before r->r for reload.
+(define_insn "*movdf_hardfloat64_mfpgpr"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f")
+       (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))]
+  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+   && (gpc_reg_operand (operands[0], DFmode)
+       || gpc_reg_operand (operands[1], DFmode))"
+  "@
+   std%U0%X0 %1,%0
+   ld%U1%X1 %0,%1
+   mr %0,%1
+   fmr %0,%1
+   lfd%U1%X1 %0,%1
+   stfd%U0%X0 %1,%0
+   mt%0 %1
+   mf%1 %0
+   {cror 0,0,0|nop}
+   #
+   #
+   #
+   mftgpr %0,%1
+   mffgpr %0,%1"
+  [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr")
+   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")])
+
+; 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
+  "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
    && (gpc_reg_operand (operands[0], DFmode)
        || gpc_reg_operand (operands[1], 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_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
   "{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }")
 
 ; It's important to list the o->f and f->o moves before f->f because
 (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))"
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
   [(set_attr "length" "8,8,8,20,20,16")])
 
+(define_insn_and_split "*movtf_softfloat"
+  [(set (match_operand:TF 0 "rs6000_nonimmediate_operand" "=r,Y,r")
+       (match_operand:TF 1 "input_operand"         "YGHF,r,r"))]
+  "!TARGET_IEEEQUAD
+   && (TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_LONG_DOUBLE_128
+   && (gpc_reg_operand (operands[0], TFmode)
+       || gpc_reg_operand (operands[1], TFmode))"
+  "#"
+  "&& reload_completed"
+  [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
+  [(set_attr "length" "20,20,16")])
+
 (define_expand "extenddftf2"
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+       (float_extend:TF (match_operand:DF 1 "input_operand" "")))]
+  "!TARGET_IEEEQUAD
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && TARGET_LONG_DOUBLE_128"
+{
+  if (TARGET_E500_DOUBLE)
+    emit_insn (gen_spe_extenddftf2 (operands[0], operands[1]));
+  else
+    emit_insn (gen_extenddftf2_fprs (operands[0], operands[1]));
+  DONE;
+})
+
+(define_expand "extenddftf2_fprs"
   [(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_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "!TARGET_IEEEQUAD
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && TARGET_LONG_DOUBLE_128"
 {
   rtx tmp = gen_reg_rtx (DFmode);
   emit_insn (gen_extendsfdf2 (tmp, operands[1]));
 (define_expand "trunctfdf2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
        (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "!TARGET_IEEEQUAD
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && 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")])
 
-(define_insn_and_split "trunctfsf2"
+(define_expand "trunctfsf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+       (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "")))]
+  "!TARGET_IEEEQUAD
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && TARGET_LONG_DOUBLE_128"
+{
+  if (TARGET_E500_DOUBLE)
+    emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1]));
+  else
+    emit_insn (gen_trunctfsf2_fprs (operands[0], operands[1]));
+  DONE;
+})
+
+(define_insn_and_split "trunctfsf2_fprs"
   [(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_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "")
+        (float:TF (match_operand:SI 1 "gpc_reg_operand" "")))]
+  "!TARGET_IEEEQUAD
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && TARGET_LONG_DOUBLE_128"
 {
   rtx tmp = gen_reg_rtx (DFmode);
   expand_float (tmp, operands[1], false);
    (set_attr "length" "20")])
 
 (define_expand "fix_trunctfsi2"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "")
+       (fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))]
+  "!TARGET_IEEEQUAD
+   && (TARGET_POWER2 || TARGET_POWERPC)
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && TARGET_LONG_DOUBLE_128"
+{
+  if (TARGET_E500_DOUBLE)
+    emit_insn (gen_spe_fix_trunctfsi2 (operands[0], operands[1]));
+  else
+    emit_insn (gen_fix_trunctfsi2_fprs (operands[0], operands[1]));
+  DONE;
+})
+
+(define_expand "fix_trunctfsi2_fprs"
   [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
                   (fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))
              (clobber (match_dup 2))
              (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 2 "gpc_reg_operand" "=f"))
    (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)
+   (clobber (match_operand:DI 5 "offsettable_mem_operand" "=o"))]
+  "!TARGET_IEEEQUAD
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "#"
-  "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[5]))"
+  "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[5]))"
   [(pc)]
 {
   rtx lowword;
   DONE;
 })
 
-(define_insn "negtf2"
+(define_expand "negtf2"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "")
+       (neg:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
+  "!TARGET_IEEEQUAD
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && TARGET_LONG_DOUBLE_128"
+  "")
+
+(define_insn "negtf2_internal"
   [(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"
   "*
 {
    (set_attr "length" "8")])
 
 (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_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "")
+       (abs:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
+  "!TARGET_IEEEQUAD
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && TARGET_LONG_DOUBLE_128"
   "
 {
   rtx label = gen_label_rtx ();
-  emit_insn (gen_abstf2_internal (operands[0], operands[1], label));
+  if (TARGET_E500_DOUBLE)
+    {
+      if (flag_unsafe_math_optimizations)
+       emit_insn (gen_spe_abstf2_tst (operands[0], operands[1], label));
+      else
+       emit_insn (gen_spe_abstf2_cmp (operands[0], operands[1], label));
+    }
+  else
+    emit_insn (gen_abstf2_internal (operands[0], operands[1], label));
   emit_label (label);
   DONE;
 }")
 
 (define_expand "abstf2_internal"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
-       (match_operand:TF 1 "gpc_reg_operand" "f"))
+  [(set (match_operand:TF 0 "gpc_reg_operand" "")
+       (match_operand:TF 1 "gpc_reg_operand" ""))
    (set (match_dup 3) (match_dup 5))
    (set (match_dup 5) (abs:DF (match_dup 5)))
    (set (match_dup 4) (compare:CCFP (match_dup 3) (match_dup 5)))
                           (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"
   "
 {
 ; List r->r after r->"o<>", otherwise reload will try to reload a
 ; non-offsettable address by using r->r which won't make progress.
 (define_insn "*movdi_internal32"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,r,r,*f,*f,m,r")
+  [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=o<>,r,r,*f,*f,m,r")
        (match_operand:DI 1 "input_operand" "r,r,m,f,m,f,IJKnGHF"))]
   "! TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], DImode)
 }")
 
 (define_split
-  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+  [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "")
         (match_operand:DI 1 "input_operand" ""))]
   "reload_completed && !TARGET_POWERPC64
    && gpr_or_gpr_p (operands[0], operands[1])"
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
 
+(define_insn "*movdi_mfpgpr"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h,r,*f")
+       (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0,*f,r"))]
+  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+   && (gpc_reg_operand (operands[0], DImode)
+       || gpc_reg_operand (operands[1], DImode))"
+  "@
+   mr %0,%1
+   ld%U1%X1 %0,%1
+   std%U0%X0 %1,%0
+   li %0,%1
+   lis %0,%v1
+   #
+   {cal|la} %0,%a1
+   fmr %0,%1
+   lfd%U1%X1 %0,%1
+   stfd%U0%X0 %1,%0
+   mf%1 %0
+   mt%0 %1
+   {cror 0,0,0|nop}
+   mftgpr %0,%1
+   mffgpr %0,%1"
+  [(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,mftgpr,mffgpr")
+   (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4")])
+
 (define_insn "*movdi_internal64"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h")
        (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0"))]
-  "TARGET_POWERPC64
+  "TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS)
    && (gpc_reg_operand (operands[0], DImode)
        || gpc_reg_operand (operands[1], DImode))"
   "@
 ;; Use (and:DI (rotate:DI ...)) to avoid anddi3 unnecessary clobber.
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "mask_operand" ""))]
+       (match_operand:DI 1 "mask64_operand" ""))]
   "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
   [(set (match_dup 0) (const_int -1))
    (set (match_dup 0)
       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 2 "gpc_reg_operand" "r"))
-     (clobber (match_scratch:SI 3 "X"))
+     (clobber (match_scratch:SI 3 "=X"))
      (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 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"
     [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
          (match_operand:SI 2 "gpc_reg_operand" "r"))
-     (clobber (match_scratch:SI 3 "X"))
+     (clobber (match_scratch:SI 3 "=X"))
      (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 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"
     [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
          (match_operand:SI 2 "gpc_reg_operand" "r"))
-     (clobber (match_scratch:SI 3 "X"))
+     (clobber (match_scratch:SI 3 "=X"))
      (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 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"
     [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
          (match_operand:SI 2 "gpc_reg_operand" "r"))
-     (clobber (match_scratch:SI 3 "X"))
+     (clobber (match_scratch:SI 3 "=X"))
      (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 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"
     [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
          (match_operand:SI 2 "gpc_reg_operand" "r"))
-     (clobber (match_scratch:SI 3 "X"))
+     (clobber (match_scratch:SI 3 "=X"))
      (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 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"
     [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
          (match_operand:SI 2 "gpc_reg_operand" "r"))
-     (clobber (match_scratch:SI 3 "X"))
+     (clobber (match_scratch:SI 3 "=X"))
      (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")])
+  [(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 "setmemsi"
   [(parallel [(set (match_operand:BLK 0 "" "")
    && (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 ""
    (clobber (reg:SI 10))
    (clobber (reg:SI 11))
    (clobber (reg:SI 12))
-   (clobber (match_scratch:SI 5 "X"))]
+   (clobber (match_scratch:SI 5 "=X"))]
   "TARGET_STRING && ! TARGET_POWER
    && ((INTVAL (operands[2]) > 24 && INTVAL (operands[2]) < 32)
        || INTVAL (operands[2]) == 0)
    && (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 ""
    (clobber (reg:SI  8))
    (clobber (reg:SI  9))
    (clobber (reg:SI 10))
-   (clobber (match_scratch:SI 5 "X"))]
+   (clobber (match_scratch:SI 5 "=X"))]
   "TARGET_STRING && ! TARGET_POWER
    && 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 ""
    (clobber (reg:SI 6))
    (clobber (reg:SI 7))
    (clobber (reg:SI 8))
-   (clobber (match_scratch:SI 5 "X"))]
+   (clobber (match_scratch:SI 5 "=X"))]
   "TARGET_STRING && ! TARGET_POWER
    && 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 ""
    (use (match_operand:SI 2 "immediate_operand" "i"))
    (use (match_operand:SI 3 "immediate_operand" "i"))
    (clobber (match_scratch:DI 4 "=&r"))
-   (clobber (match_scratch:SI 5 "X"))]
+   (clobber (match_scratch:SI 5 "=X"))]
   "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 ""
    (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"))]
+   (clobber (match_scratch:SI 5 "=X"))]
   "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")])
 \f
 ;; Define insns that do load or store with update.  Some of these we can
   "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
 ;; We move the back-chain and decrement the stack pointer.
 
 (define_expand "allocate_stack"
-  [(set (match_operand 0 "gpc_reg_operand" "=r")
+  [(set (match_operand 0 "gpc_reg_operand" "")
        (minus (reg 1) (match_operand 1 "reg_or_short_operand" "")))
    (set (reg 1)
        (minus (reg 1) (match_dup 1)))]
   ""
   "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[1] = force_reg (Pmode, operands[1]);
   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_attr "type" "load")])
 
 (define_insn "load_toc_v4_pic_si"
-  [(set (match_operand:SI 0 "register_operand" "=l")
+  [(set (reg:SI LR_REGNO)
        (unspec:SI [(const_int 0)] UNSPEC_TOC))]
   "DEFAULT_ABI == ABI_V4 && flag_pic == 1 && TARGET_32BIT"
   "bl _GLOBAL_OFFSET_TABLE_@local-4"
    (set_attr "length" "4")])
 
 (define_insn "load_toc_v4_PIC_1"
-  [(set (match_operand:SI 0 "register_operand" "=l")
-       (match_operand:SI 1 "immediate_operand" "s"))
-   (use (unspec [(match_dup 1)] UNSPEC_TOC))]
+  [(set (reg:SI LR_REGNO)
+       (match_operand:SI 0 "immediate_operand" "s"))
+   (use (unspec [(match_dup 0)] UNSPEC_TOC))]
   "TARGET_ELF && DEFAULT_ABI != ABI_AIX
    && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
-  "bcl 20,31,%1\\n%1:"
+  "bcl 20,31,%0\\n%0:"
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
 
 (define_insn "load_toc_v4_PIC_1b"
-  [(set (match_operand:SI 0 "register_operand" "=l")
-       (unspec:SI [(match_operand:SI 1 "immediate_operand" "s")]
+  [(set (reg:SI LR_REGNO)
+       (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")]
                UNSPEC_TOCPTR))]
   "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
-  "bcl 20,31,$+8\\n\\t.long %1-$"
+  "bcl 20,31,$+8\\n\\t.long %0-$"
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
 
                                  CODE_LABEL_NUMBER (operands[0]));
       tmplabrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (tmplab));
 
-      emit_insn (gen_load_macho_picbase (picreg, tmplabrtx));
+      emit_insn (gen_load_macho_picbase (tmplabrtx));
+      emit_move_insn (picreg, gen_rtx_REG (Pmode, LR_REGNO));
       emit_insn (gen_macho_correct_pic (picreg, picreg, picrtx, tmplabrtx));
     }
   else
              (use (reg:SI 11))
              (set (reg:SI 2)
                   (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
-             (clobber (scratch:SI))])]
+             (clobber (reg:SI LR_REGNO))])]
   "TARGET_32BIT"
   "
 { operands[2] = gen_reg_rtx (SImode); }")
              (use (reg:DI 11))
              (set (reg:DI 2)
                   (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
-             (clobber (scratch:SI))])]
+             (clobber (reg:SI LR_REGNO))])]
   "TARGET_64BIT"
   "
 { operands[2] = gen_reg_rtx (DImode); }")
              (use (reg:SI 11))
              (set (reg:SI 2)
                   (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
-             (clobber (scratch:SI))])]
+             (clobber (reg:SI LR_REGNO))])]
   "TARGET_32BIT"
   "
 { operands[3] = gen_reg_rtx (SImode); }")
              (use (reg:DI 11))
              (set (reg:DI 2)
                   (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
-             (clobber (scratch:SI))])]
+             (clobber (reg:SI LR_REGNO))])]
   "TARGET_64BIT"
   "
 { operands[3] = gen_reg_rtx (DImode); }")
   [(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
                    (match_operand 1 "" ""))
              (use (match_operand 2 "" ""))
-             (clobber (scratch:SI))])]
+             (clobber (reg:SI LR_REGNO))])]
   ""
   "
 {
                                     gen_rtx_MEM (SImode, operands[0]),
                                     operands[1]),
                       gen_rtx_USE (VOIDmode, operands[2]),
-                      gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+                      gen_rtx_CLOBBER (VOIDmode,
+                                       gen_rtx_REG (Pmode, LR_REGNO)));
       call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
       use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
       DONE;
                   (call (mem:SI (match_operand 1 "address_operand" ""))
                         (match_operand 2 "" "")))
              (use (match_operand 3 "" ""))
-             (clobber (scratch:SI))])]
+             (clobber (reg:SI LR_REGNO))])]
   ""
   "
 {
                                                               operands[1]),
                                                  operands[2])),
                       gen_rtx_USE (VOIDmode, operands[3]),
-                      gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+                      gen_rtx_CLOBBER (VOIDmode, 
+                                       gen_rtx_REG (Pmode, LR_REGNO)));
       call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
       use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
       DONE;
   [(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
         (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 3 "=l,l"))]
+   (clobber (reg:SI LR_REGNO))]
   "(INTVAL (operands[2]) & CALL_LONG) == 0"
   "*
 {
   [(call (mem:SI (match_operand:DI 0 "current_file_function_operand" "s,s"))
         (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 3 "=l,l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
   "*
 {
        (call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
              (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 4 "=l,l"))]
+   (clobber (reg:SI LR_REGNO))]
   "(INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
 {
        (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
              (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 4 "=l,l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
 {
    (use (reg:SI 11))
    (set (reg:SI 2)
        (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
-   (clobber (match_scratch:SI 2 "=l,l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_32BIT && DEFAULT_ABI == ABI_AIX"
   "b%T0l\;{l|lwz} 2,20(1)"
   [(set_attr "type" "jmpreg")
   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s"))
         (match_operand 1 "" "g"))
    (use (match_operand:SI 2 "immediate_operand" "O"))
-   (clobber (match_scratch:SI 3 "=l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_32BIT
    && DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[2]) & CALL_LONG) == 0"
    (use (reg:DI 11))
    (set (reg:DI 2)
        (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
-   (clobber (match_scratch:SI 2 "=l,l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_64BIT && DEFAULT_ABI == ABI_AIX"
   "b%T0l\;ld 2,40(1)"
   [(set_attr "type" "jmpreg")
   [(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s"))
         (match_operand 1 "" "g"))
    (use (match_operand:SI 2 "immediate_operand" "O"))
-   (clobber (match_scratch:SI 3 "=l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_64BIT
    && DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[2]) & CALL_LONG) == 0"
    (use (reg:SI 11))
    (set (reg:SI 2)
        (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
-   (clobber (match_scratch:SI 3 "=l,l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_32BIT && DEFAULT_ABI == ABI_AIX"
   "b%T1l\;{l|lwz} 2,20(1)"
   [(set_attr "type" "jmpreg")
        (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s"))
              (match_operand 2 "" "g")))
    (use (match_operand:SI 3 "immediate_operand" "O"))
-   (clobber (match_scratch:SI 4 "=l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_32BIT
    && DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[3]) & CALL_LONG) == 0"
    (use (reg:DI 11))
    (set (reg:DI 2)
        (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
-   (clobber (match_scratch:SI 3 "=l,l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_64BIT && DEFAULT_ABI == ABI_AIX"
   "b%T1l\;ld 2,40(1)"
   [(set_attr "type" "jmpreg")
        (call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s"))
              (match_operand 2 "" "g")))
    (use (match_operand:SI 3 "immediate_operand" "O"))
-   (clobber (match_scratch:SI 4 "=l"))]
+   (clobber (reg:SI LR_REGNO))]
   "TARGET_64BIT
    && DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[3]) & CALL_LONG) == 0"
 ;; 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" "c,*l,c,*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"))]
+   (clobber (reg:SI LR_REGNO))]
   "DEFAULT_ABI == ABI_V4
    || DEFAULT_ABI == ABI_DARWIN"
 {
   [(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"))]
+   (clobber (reg:SI LR_REGNO))]
   "(DEFAULT_ABI == ABI_DARWIN
    || (DEFAULT_ABI == ABI_V4
        && (INTVAL (operands[2]) & CALL_LONG) == 0))"
   [(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" "c,*l,c,*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"))]
+   (clobber (reg:SI LR_REGNO))]
   "DEFAULT_ABI == ABI_V4
    || DEFAULT_ABI == ABI_DARWIN"
 {
   [(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"))]
+   (clobber (reg:SI LR_REGNO))]
   "(DEFAULT_ABI == ABI_DARWIN
    || (DEFAULT_ABI == ABI_V4
        && (INTVAL (operands[3]) & CALL_LONG) == 0))"
   [(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
                    (match_operand 1 "" ""))
              (use (match_operand 2 "" ""))
-             (use (match_operand 3 "" ""))
+             (use (reg:SI LR_REGNO))
              (return)])]
   ""
   "
   gcc_assert (GET_CODE (operands[1]) == CONST_INT);
 
   operands[0] = XEXP (operands[0], 0);
-  operands[3] = gen_reg_rtx (SImode);
-
 }")
 
 ;; this and similar patterns must be marked as using LR, otherwise
   [(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
         (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (use (match_operand:SI 3 "register_operand" "l,l"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "(INTVAL (operands[2]) & CALL_LONG) == 0"
   "*
   [(call (mem:SI (match_operand:DI 0 "current_file_function_operand" "s,s"))
         (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (use (match_operand:SI 3 "register_operand" "l,l"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
   "*
        (call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
              (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (use (match_operand:SI 4 "register_operand" "l,l"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "(INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
        (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
              (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (use (match_operand:SI 4 "register_operand" "l,l"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s"))
         (match_operand 1 "" "g"))
    (use (match_operand:SI 2 "immediate_operand" "O"))
-   (use (match_operand:SI 3 "register_operand" "l"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "TARGET_32BIT
    && DEFAULT_ABI == ABI_AIX
   [(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s"))
         (match_operand 1 "" "g"))
    (use (match_operand:SI 2 "immediate_operand" "O"))
-   (use (match_operand:SI 3 "register_operand" "l"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "TARGET_64BIT
    && DEFAULT_ABI == ABI_AIX
        (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s"))
              (match_operand 2 "" "g")))
    (use (match_operand:SI 3 "immediate_operand" "O"))
-   (use (match_operand:SI 4 "register_operand" "l"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "TARGET_32BIT
    && DEFAULT_ABI == ABI_AIX
        (call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s"))
              (match_operand 2 "" "g")))
    (use (match_operand:SI 3 "immediate_operand" "O"))
-   (use (match_operand:SI 4 "register_operand" "l"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "TARGET_64BIT
    && DEFAULT_ABI == ABI_AIX
   [(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"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "(DEFAULT_ABI == ABI_DARWIN
      || DEFAULT_ABI == ABI_V4)
                (call (mem:SI (match_operand 1 "address_operand" ""))
                      (match_operand 2 "" "")))
              (use (match_operand 3 "" ""))
-             (use (match_operand 4 "" ""))
+             (use (reg:SI LR_REGNO))
              (return)])]
   ""
   "
   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"))
+   (use (reg:SI LR_REGNO))
    (return)]
   "(DEFAULT_ABI == ABI_DARWIN
        || DEFAULT_ABI == ABI_V4)
 
 (define_expand "bunordered"
   [(use (match_operand 0 "" ""))]
-  "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_cbranch (UNORDERED, operands[0]); DONE; }")
 
 (define_expand "bordered"
   [(use (match_operand 0 "" ""))]
-  "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_cbranch (ORDERED, operands[0]); DONE; }")
 
 (define_expand "buneq"
   [(use (match_operand 0 "" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_cbranch (UNEQ, operands[0]); DONE; }")
 
 (define_expand "bunge"
   [(use (match_operand 0 "" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_cbranch (UNGE, operands[0]); DONE; }")
 
 (define_expand "bungt"
   [(use (match_operand 0 "" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_cbranch (UNGT, operands[0]); DONE; }")
 
 (define_expand "bunle"
   [(use (match_operand 0 "" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_cbranch (UNLE, operands[0]); DONE; }")
 
 (define_expand "bunlt"
   [(use (match_operand 0 "" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_cbranch (UNLT, operands[0]); DONE; }")
 
 (define_expand "bltgt"
 
 (define_expand "sunordered"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
-  "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }")
 
 (define_expand "sordered"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
-  "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }")
 
 (define_expand "suneq"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_sCOND (UNEQ, operands[0]); DONE; }")
 
 (define_expand "sunge"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_sCOND (UNGE, operands[0]); DONE; }")
 
 (define_expand "sungt"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_sCOND (UNGT, operands[0]); DONE; }")
 
 (define_expand "sunle"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_sCOND (UNLE, operands[0]); DONE; }")
 
 (define_expand "sunlt"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
-  ""
+  "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "{ rs6000_emit_sCOND (UNLT, operands[0]); DONE; }")
 
 (define_expand "sltgt"
   [(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.
+;; 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.
 
-(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.  */
-
-  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"
 (define_insn_and_split "*eq<mode>"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
        (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
-               (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))
-   (clobber (match_scratch:GPR 3 "=r"))
-   (clobber (match_scratch:GPR 4 "=r"))]
-  ""
+               (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))]
+  "!TARGET_POWER"
   "#"
-  "reload_completed"
-  [(set (match_dup 3)
-       (clz:GPR (match_dup 4)))
+  "!TARGET_POWER"
+  [(set (match_dup 0)
+       (clz:GPR (match_dup 3)))
    (set (match_dup 0)
-       (lshiftrt:GPR (match_dup 3) (match_dup 5)))]
+       (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[4],
+         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[4],
+         emit_insn (gen_rtx_SET (VOIDmode, operands[3],
                                  gen_rtx_PLUS (<MODE>mode, operands[1],
                                                negate_rtx (<MODE>mode,
                                                            operands[2]))));
       }
     else
-      operands[4] = operands[1];
+      operands[3] = operands[1];
 
-    operands[5] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
+    operands[4] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
   })
 
 (define_insn_and_split "*eq<mode>_compare"
-  [(set (match_operand:CC 5 "cc_reg_operand" "=y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=y")
        (compare:CC
         (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:P 0 "gpc_reg_operand" "=r")
-       (eq:P (match_dup 1) (match_dup 2)))
-   (clobber (match_scratch:P 3 "=r"))
-   (clobber (match_scratch:P 4 "=r"))]
-  ""
+       (eq:P (match_dup 1) (match_dup 2)))]
+  "!TARGET_POWER && optimize_size"
   "#"
-  "reload_completed"
-  [(set (match_dup 3)
+  "!TARGET_POWER && optimize_size"
+  [(set (match_dup 0)
        (clz:P (match_dup 4)))
-   (parallel [(set (match_dup 5)
-                  (compare:CC (lshiftrt:P (match_dup 3) (match_dup 6))
+   (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 3) (match_dup 6)))])]
+                  (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,
     else
       operands[4] = operands[1];
 
-    operands[6] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
+    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.
 (define_split
    (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 "scc_eq_operand" "r,O,K,L,I"))
   [(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
          (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
          (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
         (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
         (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 "scc_eq_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.
    (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")])
    (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 "*neg_ltu<mode>"
   "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 ""
+(define_insn "*geu<mode>_compare"
   [(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"))
+        (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:SI 0 "gpc_reg_operand" "=r,r,r,r")
-       (geu:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT"
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
+       (geu:P (match_dup 1) (match_dup 2)))]
+  ""
   "@
    {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
 (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" ""))
+        (geu:P (match_operand:P 1 "gpc_reg_operand" "")
+               (match_operand:P 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_operand:P 0 "gpc_reg_operand" "")
+       (geu:P (match_dup 1) (match_dup 2)))]
+  "reload_completed"
   [(set (match_dup 0)
-       (geu:SI (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 "*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"
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
+
 (define_insn ""
-  [(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"))
-        (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"
-  "@
-   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" "compare")
-   (set_attr "length" "12,12,16,16")])
-
-(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" ""))
-        (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_dup 0)
-       (geu:DI (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"
-  "@
-   {sf|subfc} %0,%2,%1\;{aze|addze} %0,%3
-   {ai|addic} %0,%1,%n2\;{aze|addze} %0,%3"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC
         (plus:SI (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)))]
   "")
 
-(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 (match_dup 0) (neg:P (match_dup 0)))]
   "")
 
-(define_insn ""
+(define_insn_and_split "*gtu<mode>_compare"
   [(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" ""))
+        (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: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"
+   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+       (gtu:P (match_dup 1) (match_dup 2)))]
+  ""
   "#"
-  "&& !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)))]
+  ""
+  [(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_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"
+(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: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)))]
+  [(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 ""
+(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" "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)))
-   (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")])
-
-(define_split
-  [(set (match_operand:CC 4 "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" ""))
+        (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 "*neg_gtu<mode>"
 {
   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.
 
 (define_expand "tablejumpdi"
   [(set (match_dup 4)
-        (sign_extend:DI (match_operand:SI 0 "lwa_operand" "rm")))
+        (sign_extend:DI (match_operand:SI 0 "lwa_operand" "")))
    (set (match_dup 3)
        (plus:DI (match_dup 4)
                 (match_dup 2)))
 (define_insn "trap"
   [(trap_if (const_int 1) (const_int 0))]
   ""
-  "{t 31,0,0|trap}")
+  "{t 31,0,0|trap}"
+  [(set_attr "type" "trap")])
 
 (define_expand "conditional_trap"
   [(trap_if (match_operator 0 "trap_comparison_operator"
                              (match_operand:GPR 2 "reg_or_short_operand" "rI")])
            (const_int 0))]
   ""
-  "{t|t<wd>}%V0%I2 %1,%2")
+  "{t|t<wd>}%V0%I2 %1,%2"
+  [(set_attr "type" "trap")])
 \f
 ;; Insns related to generating the function prologue and epilogue.
 
 
 (define_insn "movesi_from_cr"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (unspec:SI [(reg:CC 68) (reg:CC 69) (reg:CC 70) (reg:CC 71)
-                   (reg:CC 72) (reg:CC 73) (reg:CC 74) (reg:CC 75)]
+        (unspec:SI [(reg:CC CR0_REGNO) (reg:CC CR1_REGNO)
+                   (reg:CC CR2_REGNO) (reg:CC CR3_REGNO)
+                   (reg:CC CR4_REGNO) (reg:CC CR5_REGNO)
+                   (reg:CC CR6_REGNO) (reg:CC CR7_REGNO)]
                   UNSPEC_MOVESI_FROM_CR))]
   ""
   "mfcr %0"
                   [(set (match_operand:SI 1 "memory_operand" "=m")
                                 (match_operand:SI 2 "gpc_reg_operand" "r"))])]
   "TARGET_MULTIPLE"
-  "{stm|stmw} %2,%1")
+  "{stm|stmw} %2,%1"
+  [(set_attr "type" "store_ux")])
 
 (define_insn "*save_fpregs_<mode>"
   [(match_parallel 0 "any_parallel_operand"
-                  [(clobber (match_operand:P 1 "register_operand" "=l"))
-                   (use (match_operand:P 2 "call_operand" "s"))
-                   (set (match_operand:DF 3 "memory_operand" "=m")
-                        (match_operand:DF 4 "gpc_reg_operand" "f"))])]
+                  [(clobber (reg:P 65))
+                   (use (match_operand:P 1 "call_operand" "s"))
+                   (set (match_operand:DF 2 "memory_operand" "=m")
+                        (match_operand:DF 3 "gpc_reg_operand" "f"))])]
   ""
-  "bl %z2"
+  "bl %z1"
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
 
 ; faster; for instance, on the 601 and 750.
 
 (define_expand "movsi_to_cr_one"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=y")
-        (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+  [(set (match_operand:CC 0 "cc_reg_operand" "")
+        (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "")
                    (match_dup 2)] UNSPEC_MOVESI_TO_CR))]
   ""
   "operands[2] = GEN_INT (1 << (75 - REGNO (operands[0])));")
 
 ; 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")
+  "{lm|lmw} %1,%2"
+  [(set_attr "type" "load_ux")])
 
 (define_insn "*return_internal_<mode>"
   [(return)
 (define_insn "*return_and_restore_fpregs_<mode>"
  [(match_parallel 0 "any_parallel_operand"
                   [(return)
-                  (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"))])]
+                  (use (reg:P 65))
+                  (use (match_operand:P 1 "call_operand" "s"))
+                  (set (match_operand:DF 2 "gpc_reg_operand" "=f")
+                       (match_operand:DF 3 "memory_operand" "m"))])]
  ""
- "b %z2")
+ "b %z1")
 
 ; This is used in compiling the unwind routines.
 (define_expand "eh_return"
 (include "sync.md")
 (include "altivec.md")
 (include "spe.md")
+(include "dfp.md")
+(include "paired.md")