re PR target/63195 (stage3 build/gengtype miscompiled)
[platform/upstream/gcc.git] / gcc / config / rs6000 / rs6000.md
index 738011c..b5aeaed 100644 (file)
@@ -56,6 +56,8 @@
    (TFHAR_REGNO                        114)
    (TFIAR_REGNO                        115)
    (TEXASR_REGNO               116)
+   (FIRST_SPE_HIGH_REGNO       117)
+   (LAST_SPE_HIGH_REGNO                148)
   ])
 
 ;;
    UNSPEC_P8V_MTVSRD
    UNSPEC_P8V_XXPERMDI
    UNSPEC_P8V_RELOAD_FROM_VSX
+   UNSPEC_ADDG6S
+   UNSPEC_CDTBCD
+   UNSPEC_CBCDTD
+   UNSPEC_DIVE
+   UNSPEC_DIVEO
+   UNSPEC_DIVEU
+   UNSPEC_DIVEUO
+   UNSPEC_UNPACK_128BIT
+   UNSPEC_PACK_128BIT
+   UNSPEC_LSQ
   ])
 
 ;;
 \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,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,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto,htm"
+(define_attr "type"
+  "integer,two,three,
+   add,logical,shift,insert,
+   mul,halfmul,div,
+   exts,cntlz,popcnt,isel,
+   load,store,fpload,fpstore,vecload,vecstore,
+   cmp,
+   branch,jmpreg,mfjmpr,mtjmpr,trap,isync,sync,load_l,store_c,
+   compare,
+   cr_logical,delayed_cr,mfcr,mfcrf,mtcr,
+   fpcompare,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,
+   brinc,
+   vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,
+   vecfloat,vecfdiv,vecdouble,mffgpr,mftgpr,crypto,
+   htm"
   (const_string "integer"))
 
+;; What data size does this instruction work on?
+;; This is used for insert, mul.
+(define_attr "size" "8,16,32,64" (const_string "32"))
+
+;; Is this instruction record form ("dot", signed compare to 0, writing CR0)?
+;; This is used for add, logical, shift, exts, mul.
+(define_attr "dot" "no,yes" (const_string "no"))
+
+;; Does this instruction sign-extend its result?
+;; This is used for load insns.
+(define_attr "sign_extend" "no,yes" (const_string "no"))
+
+;; Does this instruction use indexed (that is, reg+reg) addressing?
+;; This is used for load and store insns.  If operand 0 or 1 is a MEM
+;; it is automatically set based on that.  If a load or store instruction
+;; has fewer than two operands it needs to set this attribute manually
+;; or the compiler will crash.
+(define_attr "indexed" "no,yes"
+  (if_then_else (ior (match_operand 0 "indexed_address_mem")
+                    (match_operand 1 "indexed_address_mem"))
+               (const_string "yes")
+               (const_string "no")))
+
+;; Does this instruction use update addressing?
+;; This is used for load and store insns.  See the comments for "indexed".
+(define_attr "update" "no,yes"
+  (if_then_else (ior (match_operand 0 "update_address_mem")
+                    (match_operand 1 "update_address_mem"))
+               (const_string "yes")
+               (const_string "no")))
+
+;; Is this instruction using operands[2] as shift amount, and can that be a
+;; register?
+;; This is used for shift insns.
+(define_attr "maybe_var_shift" "no,yes" (const_string "no"))
+
+;; Is this instruction using a shift amount from a register?
+;; This is used for shift insns.
+(define_attr "var_shift" "no,yes"
+  (if_then_else (and (eq_attr "type" "shift")
+                    (eq_attr "maybe_var_shift" "yes"))
+               (if_then_else (match_operand 2 "gpc_reg_operand")
+                             (const_string "yes")
+                             (const_string "no"))
+               (const_string "no")))
+
 ;; Define floating point instruction sub-types for use with Xfpu.md
 (define_attr "fp_type" "fp_default,fp_addsub_s,fp_addsub_d,fp_mul_s,fp_mul_d,fp_div_s,fp_div_d,fp_maddsub_s,fp_maddsub_d,fp_sqrt_s,fp_sqrt_d" (const_string "fp_default"))
 
 ;; If this instruction is microcoded on the CELL processor
 ; The default for load extended, the recorded instructions and rotate/shifts by a variable is always microcoded
 (define_attr "cell_micro" "not,conditional,always"
-  (if_then_else (eq_attr "type" "compare,delayed_compare,imul_compare,lmul_compare,load_ext,load_ext_ux,var_shift_rotate,var_delayed_compare")
+  (if_then_else (ior (eq_attr "type" "compare")
+                    (and (eq_attr "type" "shift,exts,mul")
+                         (eq_attr "dot" "yes"))
+                    (and (eq_attr "type" "load")
+                         (eq_attr "sign_extend" "yes"))
+                    (and (eq_attr "type" "shift")
+                         (eq_attr "var_shift" "yes")))
                (const_string "always")
                (const_string "not")))
 
 ; Any supported integer mode that fits in one register.
 (define_mode_iterator INT1 [QI HI SI (DI "TARGET_POWERPC64")])
 
-; extend modes for DImode
-(define_mode_iterator QHSI [QI HI SI])
+; Everything we can extend QImode to.
+(define_mode_iterator EXTQI [HI SI (DI "TARGET_POWERPC64")])
+
+; Everything we can extend HImode to.
+(define_mode_iterator EXTHI [SI (DI "TARGET_POWERPC64")])
+
+; Everything we can extend SImode to.
+(define_mode_iterator EXTSI [(DI "TARGET_POWERPC64")])
 
 ; QImode or HImode for small atomic ops
 (define_mode_iterator QHI [QI HI])
 (define_mode_attr f32_sv [(SF "stxsspx %x1,%y0")  (SD "stxsiwzx %x1,%y0")])
 
 ; Definitions for 32-bit fpr direct move
-(define_mode_attr f32_dm [(SF "wn") (SD "wm")])
+(define_mode_attr f32_dm [(SF "wn") (SD "wh")])
 
 ; These modes do not fit in integer registers in 32-bit mode.
 ; but on e500v2, the gpr are 64 bit registers
                               (simple_return "1")])
 (define_code_attr return_str [(return "") (simple_return "simple_")])
 
+; Signed/unsigned variants of ops.
+(define_code_iterator any_extend [sign_extend zero_extend])
+(define_code_attr u [(sign_extend "") (zero_extend "u")])
+(define_code_attr su [(sign_extend "s") (zero_extend "u")])
+
 ; Various instructions that come in SI and DI forms.
 ; A generic w/d attribute, for things like cmpw/cmpd.
 (define_mode_attr wd [(QI    "b")
                      (V4SI  "w")
                      (V2DI  "d")])
 
+;; How many bits in this mode?
+(define_mode_attr bits [(QI "8") (HI "16") (SI "32") (DI "64")])
+
 ; DImode bits
 (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
 
 ;; ISEL/ISEL64 target selection
 (define_mode_attr sel [(SI "") (DI "64")])
 
+;; Bitmask for shift instructions
+(define_mode_attr hH [(SI "h") (DI "H")])
+
+;; A mode twice the size of the given mode
+(define_mode_attr dmode [(SI "di") (DI "ti")])
+(define_mode_attr DMODE [(SI "DI") (DI "TI")])
+
 ;; Suffix for reload patterns
 (define_mode_attr ptrsize [(SI "32bit")
                           (DI "64bit")])
                                         (V2DI  "wa,v,r,0,0")
                                         (V2DF  "wa,v,r,0,0")
                                         (V1TI  "wa,v,r,0,0")])
-
-;; Mode attribute for the clobber of CC0 for AND expansion.
-;; For the 128-bit types, we never do AND immediate, but we need to
-;; get the correct number of X's for the number of operands.
-(define_mode_attr BOOL_REGS_AND_CR0    [(TI    "X,X,X,X,X")
-                                        (PTI   "X,X,X")
-                                        (V16QI "X,X,X,X,X")
-                                        (V8HI  "X,X,X,X,X")
-                                        (V4SI  "X,X,X,X,X")
-                                        (V4SF  "X,X,X,X,X")
-                                        (V2DI  "X,X,X,X,X")
-                                        (V2DF  "X,X,X,X,X")
-                                        (V1TI  "X,X,X,X,X")])
-
 \f
 ;; Start with fixed-point load and store insns.  Here we put only the more
 ;; complex forms.  Basic data transfer is done later.
 
-(define_expand "zero_extend<mode>di2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" "")))]
-  "TARGET_POWERPC64"
-  "")
+(define_insn "zero_extendqi<mode>2"
+  [(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:EXTQI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
+  ""
+  "@
+   lbz%U1%X1 %0,%1
+   rlwinm %0,%1,0,0xff"
+  [(set_attr "type" "load,shift")])
 
-(define_insn "*zero_extend<mode>di2_internal1"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI (match_operand:QHSI 1 "reg_or_mem_operand" "m,r")))]
-  "TARGET_POWERPC64 && (<MODE>mode != SImode || !TARGET_LFIWZX)"
-  "@
-   l<wd>z%U1%X1 %0,%1
-   rldicl %0,%1,0,<dbits>"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (const_string "*")])])
-
-(define_insn "*zero_extend<mode>di2_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" "r,r"))
+(define_insn_and_split "*zero_extendqi<mode>2_dot"
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+       (compare:CC (zero_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 2 "=r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:EXTQI 0 "=r,r"))]
+  "rs6000_gen_cell_microcode"
   "@
-   rldicl. %2,%1,0,<dbits>
+   andi. %0,%1,0xff
    #"
-  [(set_attr "type" "compare")
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(set (match_dup 0)
+       (zero_extend:EXTQI (match_dup 1)))
+   (set (match_dup 2)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" ""))
+(define_insn_and_split "*zero_extendqi<mode>2_dot2"
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+       (compare:CC (zero_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 2 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2)
-       (zero_extend:DI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
+   (set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:EXTQI (match_dup 1)))]
+  "rs6000_gen_cell_microcode"
+  "@
+   andi. %0,%1,0xff
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(set (match_dup 0)
+       (zero_extend:EXTQI (match_dup 1)))
+   (set (match_dup 2)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
+
+(define_insn "zero_extendhi<mode>2"
+  [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
+  ""
+  "@
+   lhz%U1%X1 %0,%1
+   rlwinm %0,%1,0,0xffff"
+  [(set_attr "type" "load,shift")])
 
-(define_insn "*zero_extend<mode>di2_internal3"
+(define_insn_and_split "*zero_extendhi<mode>2_dot"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (zero_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI (match_dup 1)))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:EXTHI 0 "=r,r"))]
+  "rs6000_gen_cell_microcode"
   "@
-   rldicl. %0,%1,0,<dbits>
+   andi. %0,%1,0xffff
    #"
-  [(set_attr "type" "compare")
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(set (match_dup 0)
+       (zero_extend:EXTHI (match_dup 1)))
+   (set (match_dup 2)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" ""))
+(define_insn_and_split "*zero_extendhi<mode>2_dot2"
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+       (compare:CC (zero_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (match_dup 1)))]
-  "TARGET_POWERPC64 && reload_completed"
+   (set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:EXTHI (match_dup 1)))]
+  "rs6000_gen_cell_microcode"
+  "@
+   andi. %0,%1,0xffff
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
   [(set (match_dup 0)
-       (zero_extend:DI (match_dup 1)))
+       (zero_extend:EXTHI (match_dup 1)))
    (set (match_dup 2)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
 
-(define_insn "*zero_extendsidi2_lfiwzx"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wz,!wu")
-       (zero_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "m,r,r,Z,Z")))]
-  "TARGET_POWERPC64 && TARGET_LFIWZX"
+(define_insn "zero_extendsi<mode>2"
+  [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,??wj,!wz,!wu")
+       (zero_extend:EXTSI (match_operand:SI 1 "reg_or_mem_operand" "m,r,r,Z,Z")))]
+  ""
   "@
    lwz%U1%X1 %0,%1
    rldicl %0,%1,0,32
    mtvsrwz %x0,%1
    lfiwzx %0,%y1
    lxsiwzx %x0,%y1"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (const_string "*")
-       (const_string "mffgpr")
-       (const_string "fpload")
-       (const_string "fpload")])])
-
-(define_insn "extendqidi2"
-  [(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"
-  [(set_attr "type" "exts")])
+  [(set_attr "type" "load,shift,mffgpr,fpload,fpload")])
 
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
+(define_insn_and_split "*zero_extendsi<mode>2_dot"
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+       (compare:CC (zero_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 2 "=r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:EXTSI 0 "=r,r"))]
+  "rs6000_gen_cell_microcode"
   "@
-   extsb. %2,%1
+   rldicl. %0,%1,0,32
    #"
-  [(set_attr "type" "compare")
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(set (match_dup 0)
+       (zero_extend:DI (match_dup 1)))
+   (set (match_dup 2)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:DI (match_operand:QI 1 "gpc_reg_operand" ""))
+(define_insn_and_split "*zero_extendsi<mode>2_dot2"
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+       (compare:CC (zero_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 2 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2)
-       (sign_extend:DI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
+   (set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:EXTSI (match_dup 1)))]
+  "rs6000_gen_cell_microcode"
+  "@
+   rldicl. %0,%1,0,32
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(set (match_dup 0)
+       (zero_extend:EXTSI (match_dup 1)))
+   (set (match_dup 2)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn ""
+
+(define_insn "extendqi<mode>2"
+  [(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r")
+       (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r")))]
+  ""
+  "extsb %0,%1"
+  [(set_attr "type" "exts")])
+
+(define_insn_and_split "*extendqi<mode>2_dot"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:DI (match_dup 1)))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:EXTQI 0 "=r,r"))]
+  "rs6000_gen_cell_microcode"
   "@
    extsb. %0,%1
    #"
-  [(set_attr "type" "compare")
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(set (match_dup 0)
+       (sign_extend:EXTQI (match_dup 1)))
+   (set (match_dup 2)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "exts")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:DI (match_operand:QI 1 "gpc_reg_operand" ""))
+(define_insn_and_split "*extendqi<mode>2_dot2"
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+       (compare:CC (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (sign_extend:DI (match_dup 1)))]
-  "TARGET_POWERPC64 && reload_completed"
+   (set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r")
+       (sign_extend:EXTQI (match_dup 1)))]
+  "rs6000_gen_cell_microcode"
+  "@
+   extsb. %0,%1
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
   [(set (match_dup 0)
-       (sign_extend:DI (match_dup 1)))
+       (sign_extend:EXTQI (match_dup 1)))
    (set (match_dup 2)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "exts")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_expand "extendhidi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" "")))]
-  "TARGET_POWERPC64"
+
+(define_expand "extendhi<mode>2"
+  [(set (match_operand:EXTHI 0 "gpc_reg_operand" "")
+       (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "")))]
+  ""
   "")
 
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:DI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
-  "TARGET_POWERPC64 && rs6000_gen_cell_microcode"
+(define_insn "*extendhi<mode>2"
+  [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
+       (sign_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
+  "rs6000_gen_cell_microcode"
   "@
    lha%U1%X1 %0,%1
    extsh %0,%1"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ext_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_ext_u")
-          (const_string "load_ext")))
-       (const_string "exts")])])
+  [(set_attr "type" "load,exts")
+   (set_attr "sign_extend" "yes")])
 
-(define_insn ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r")))]
-  "TARGET_POWERPC64 && !rs6000_gen_cell_microcode"
+(define_insn "*extendhi<mode>2_noload"
+  [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r")
+        (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r")))]
+  "!rs6000_gen_cell_microcode"
   "extsh %0,%1"
   [(set_attr "type" "exts")])
 
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
+(define_insn_and_split "*extendhi<mode>2_dot"
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+       (compare:CC (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 2 "=r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:EXTHI 0 "=r,r"))]
+  "rs6000_gen_cell_microcode"
   "@
-   extsh. %2,%1
+   extsh. %0,%1
    #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2)
-       (sign_extend:DI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(set (match_dup 0)
+       (sign_extend:EXTHI (match_dup 1)))
+   (set (match_dup 2)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "exts")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn ""
+(define_insn_and_split "*extendhi<mode>2_dot2"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:DI (match_dup 1)))]
-  "TARGET_64BIT"
+   (set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
+       (sign_extend:EXTHI (match_dup 1)))]
+  "rs6000_gen_cell_microcode"
   "@
    extsh. %0,%1
    #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (sign_extend:DI (match_dup 1)))]
-  "TARGET_POWERPC64 && reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
   [(set (match_dup 0)
-       (sign_extend:DI (match_dup 1)))
+       (sign_extend:EXTHI (match_dup 1)))
    (set (match_dup 2)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "exts")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_expand "extendsidi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")))]
-  "TARGET_POWERPC64"
-  "")
 
-(define_insn "*extendsidi2_lfiwax"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wl,!wu")
-       (sign_extend:DI (match_operand:SI 1 "lwa_operand" "m,r,r,Z,Z")))]
-  "TARGET_POWERPC64 && TARGET_LFIWAX"
+(define_insn "extendsi<mode>2"
+  [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,??wj,!wl,!wu")
+       (sign_extend:EXTSI (match_operand:SI 1 "lwa_operand" "Y,r,r,Z,Z")))]
+  ""
   "@
    lwa%U1%X1 %0,%1
    extsw %0,%1
    mtvsrwa %x0,%1
    lfiwax %0,%y1
    lxsiwax %x0,%y1"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ext_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_ext_u")
-          (const_string "load_ext")))
-       (const_string "exts")
-       (const_string "mffgpr")
-       (const_string "fpload")
-       (const_string "fpload")])])
-
-(define_insn "*extendsidi2_nocell"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:DI (match_operand:SI 1 "lwa_operand" "m,r")))]
-  "TARGET_POWERPC64 && rs6000_gen_cell_microcode && !TARGET_LFIWAX"
-  "@
-   lwa%U1%X1 %0,%1
-   extsw %0,%1"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ext_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_ext_u")
-          (const_string "load_ext")))
-       (const_string "exts")])])
-
-(define_insn "*extendsidi2_nocell"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r")))]
-  "TARGET_POWERPC64 && !rs6000_gen_cell_microcode"
-  "extsw %0,%1"
-  [(set_attr "type" "exts")])
+  [(set_attr "type" "load,exts,mffgpr,fpload,fpload")
+   (set_attr "sign_extend" "yes")])
 
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+(define_insn_and_split "*extendsi<mode>2_dot"
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+       (compare:CC (sign_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 2 "=r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:EXTSI 0 "=r,r"))]
+  "rs6000_gen_cell_microcode"
   "@
-   extsw. %2,%1
+   extsw. %0,%1
    #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 2 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2)
-       (sign_extend:DI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(set (match_dup 0)
+       (sign_extend:EXTSI (match_dup 1)))
+   (set (match_dup 2)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "exts")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn ""
+(define_insn_and_split "*extendsi<mode>2_dot2"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+       (compare:CC (sign_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:DI (match_dup 1)))]
-  "TARGET_64BIT"
+   (set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r")
+       (sign_extend:EXTSI (match_dup 1)))]
+  "rs6000_gen_cell_microcode"
   "@
    extsw. %0,%1
    #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (sign_extend:DI (match_dup 1)))]
-  "TARGET_POWERPC64 && reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
   [(set (match_dup 0)
-       (sign_extend:DI (match_dup 1)))
+       (sign_extend:EXTSI (match_dup 1)))
    (set (match_dup 2)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
-
-(define_expand "zero_extendqisi2"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (zero_extend:SI (match_operand:QI 1 "gpc_reg_operand" "")))]
-  ""
-  "")
-
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:SI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
-  ""
-  "@
-   lbz%U1%X1 %0,%1
-   rlwinm %0,%1,0,0xff"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (const_string "*")])])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 2 "=r,r"))]
   ""
-  "@
-   andi. %2,%1,0xff
-   #"
-  [(set_attr "type" "fast_compare,compare")
+  [(set_attr "type" "exts")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
+\f
+;; IBM 405, 440, 464 and 476 half-word multiplication operations.
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:SI (match_operand:QI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 2 ""))]
-  "reload_completed"
-  [(set (match_dup 2)
-       (zero_extend:SI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:SI (match_dup 1)))]
-  ""
-  "@
-   andi. %0,%1,0xff
-   #"
-  [(set_attr "type" "fast_compare,compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:SI (match_operand:QI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (zero_extend:SI (match_dup 1)))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:SI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+(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" "halfmul")])
 
-(define_insn "extendqisi2"
+(define_insn "*macchw"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (sign_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r")))]
-  ""
-  "extsb %0,%1"
-  [(set_attr "type" "exts")])
+        (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" "halfmul")])
 
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 2 "=r,r"))]
-  ""
-  "@
-   extsb. %2,%1
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
+(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" "halfmul")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:SI (match_operand:QI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 2 ""))]
-  "reload_completed"
-  [(set (match_dup 2)
-       (sign_extend:SI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
-                   (const_int 0)))]
-  "")
+(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" "halfmul")])
 
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:SI (match_dup 1)))]
-  ""
-  "@
-   extsb. %0,%1
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
+(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" "halfmul")])
 
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:SI (match_operand:QI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (sign_extend:SI (match_dup 1)))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (sign_extend:SI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+(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" "halfmul")])
 
-(define_insn ""
-  [(set (match_operand:HI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:HI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
-  ""
-  "@
-   lbz%U1%X1 %0,%1
-   rlwinm %0,%1,0,0xff"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (const_string "*")])])
+(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" "halfmul")])
 
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:HI 2 "=r,r"))]
-  ""
-  "@
-   andi. %2,%1,0xff
-   #"
-  [(set_attr "type" "fast_compare,compare")
-   (set_attr "length" "4,8")])
+(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" "halfmul")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:HI (match_operand:QI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:HI 2 ""))]
-  "reload_completed"
-  [(set (match_dup 2)
-       (zero_extend:HI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
-                   (const_int 0)))]
-  "")
+(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" "halfmul")])
 
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:HI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:HI (match_dup 1)))]
-  ""
-  "@
-   andi. %0,%1,0xff
-   #"
-  [(set_attr "type" "fast_compare,compare")
-   (set_attr "length" "4,8")])
+(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" "halfmul")])
 
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:HI (match_operand:QI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:HI 0 "gpc_reg_operand" "")
-       (zero_extend:HI (match_dup 1)))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:HI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+(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" "halfmul")])
 
-(define_insn "extendqihi2"
-  [(set (match_operand:HI 0 "gpc_reg_operand" "=r")
-       (sign_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r")))]
-  ""
-  "extsb %0,%1"
-  [(set_attr "type" "exts")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:HI 2 "=r,r"))]
-  ""
-  "@
-   extsb. %2,%1
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:HI (match_operand:QI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:HI 2 ""))]
-  "reload_completed"
-  [(set (match_dup 2)
-       (sign_extend:HI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:HI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:HI (match_dup 1)))]
-  ""
-  "@
-   extsb. %0,%1
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:HI (match_operand:QI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:HI 0 "gpc_reg_operand" "")
-       (sign_extend:HI (match_dup 1)))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (sign_extend:HI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_expand "zero_extendhisi2"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "")))]
-  ""
-  "")
-
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:SI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
-  ""
-  "@
-   lhz%U1%X1 %0,%1
-   rlwinm %0,%1,0,0xffff"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (const_string "*")])])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 2 "=r,r"))]
-  ""
-  "@
-   andi. %2,%1,0xffff
-   #"
-  [(set_attr "type" "fast_compare,compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 2 ""))]
-  "reload_completed"
-  [(set (match_dup 2)
-       (zero_extend:SI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:SI (match_dup 1)))]
-  ""
-  "@
-   andi. %0,%1,0xffff
-   #"
-  [(set_attr "type" "fast_compare,compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (zero_extend:SI (match_dup 1)))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:SI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_expand "extendhisi2"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (sign_extend:SI (match_operand:HI 1 "gpc_reg_operand" "")))]
-  ""
-  "")
-
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:SI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
-  "rs6000_gen_cell_microcode"
-  "@
-   lha%U1%X1 %0,%1
-   extsh %0,%1"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ext_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_ext_u")
-          (const_string "load_ext")))
-       (const_string "exts")])])
-
-(define_insn ""
+(define_insn "*maclhwu"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (sign_extend:SI (match_operand:HI 1 "gpc_reg_operand" "r")))]
-  "!rs6000_gen_cell_microcode"
-  "extsh %0,%1"
-  [(set_attr "type" "exts")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:SI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 2 "=r,r"))]
-  ""
-  "@
-   extsh. %2,%1
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:SI (match_operand:HI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 2 ""))]
-  "reload_completed"
-  [(set (match_dup 2)
-       (sign_extend:SI (match_dup 1)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 2)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-       (compare:CC (sign_extend:SI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:SI (match_dup 1)))]
-  ""
-  "@
-   extsh. %0,%1
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (sign_extend:SI (match_operand:HI 1 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (sign_extend:SI (match_dup 1)))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (sign_extend:SI (match_dup 1)))
-   (set (match_dup 2)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-\f
-;; IBM 405, 440, 464 and 476 half-word multiplication operations.
+        (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" "halfmul")])
 
-(define_insn "*macchwc"
+(define_insn "*nmacchwc"
   [(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"))
+        (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")
-        (plus:SI (mult:SI (ashiftrt:SI
-                           (match_dup 2)
-                           (const_int 16))
-                          (sign_extend:SI
-                           (match_dup 1)))
-                 (match_dup 4)))]
+        (minus:SI (match_dup 4)
+                  (mult:SI (ashiftrt:SI
+                            (match_dup 2)
+                            (const_int 16))
+                           (sign_extend:SI
+                            (match_dup 1)))))]
   "TARGET_MULHW"
-  "macchw. %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  "nmacchw. %0,%1,%2"
+  [(set_attr "type" "halfmul")])
 
-(define_insn "*macchw"
+(define_insn "*nmacchw"
   [(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")))]
+        (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"
-  "macchw %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  "nmacchw %0,%1,%2"
+  [(set_attr "type" "halfmul")])
 
-(define_insn "*macchwuc"
+(define_insn "*nmachhwc"
   [(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"))
+        (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")
-        (plus:SI (mult:SI (lshiftrt:SI
-                           (match_dup 2)
-                           (const_int 16))
-                          (zero_extend:SI
-                           (match_dup 1)))
-                 (match_dup 4)))]
+        (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"
-  "macchwu. %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  "nmachhw. %0,%1,%2"
+  [(set_attr "type" "halfmul")])
 
-(define_insn "*macchwu"
+(define_insn "*nmachhw"
   [(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")))]
+        (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"
-  "macchwu %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  "nmachhw %0,%1,%2"
+  [(set_attr "type" "halfmul")])
 
-(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"
+(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_dup 2)))))]
   "TARGET_MULHW"
   "nmaclhw. %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*nmaclhw"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                             (match_operand:HI 2 "gpc_reg_operand" "r")))))]
   "TARGET_MULHW"
   "nmaclhw %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mulchwc"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
                   (match_dup 1))))]
   "TARGET_MULHW"
   "mulchw. %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mulchw"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                   (match_operand:HI 1 "gpc_reg_operand" "r"))))]
   "TARGET_MULHW"
   "mulchw %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mulchwuc"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
                   (match_dup 1))))]
   "TARGET_MULHW"
   "mulchwu. %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mulchwu"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                   (match_operand:HI 1 "gpc_reg_operand" "r"))))]
   "TARGET_MULHW"
   "mulchwu %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mulhhwc"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
                   (const_int 16))))]
   "TARGET_MULHW"
   "mulhhw. %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mulhhw"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                   (const_int 16))))]
   "TARGET_MULHW"
   "mulhhw %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mulhhwuc"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
                   (const_int 16))))]
   "TARGET_MULHW"
   "mulhhwu. %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mulhhwu"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                   (const_int 16))))]
   "TARGET_MULHW"
   "mulhhwu %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mullhwc"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
                   (match_dup 2))))]
   "TARGET_MULHW"
   "mullhw. %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mullhw"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                   (match_operand:HI 2 "gpc_reg_operand" "r"))))]
   "TARGET_MULHW"
   "mullhw %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mullhwuc"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
                   (match_dup 2))))]
   "TARGET_MULHW"
   "mullhwu. %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 
 (define_insn "*mullhwu"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                   (match_operand:HI 2 "gpc_reg_operand" "r"))))]
   "TARGET_MULHW"
   "mullhwu %0,%1,%2"
-  [(set_attr "type" "imul3")])
+  [(set_attr "type" "halfmul")])
 \f
 ;; IBM 405, 440, 464 and 476 string-search dlmzb instruction support.
 (define_insn "dlmzb"
    addi %0,%1,%2
    addic %0,%1,%2
    addis %0,%1,%v2"
-  [(set_attr "length" "4,4,4,4")])
+  [(set_attr "type" "add")])
 
 (define_insn "addsi3_high"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
                  (high:SI (match_operand 2 "" ""))))]
   "TARGET_MACHO && !TARGET_64BIT"
   "addis %0,%1,ha16(%2)"
-  [(set_attr "length" "4")])
+  [(set_attr "type" "add")])
 
 (define_insn "*add<mode>3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
    addic. %3,%1,%2
    #
    #"
-  [(set_attr "type" "fast_compare,compare,compare,compare")
+  [(set_attr "type" "add,compare,compare,compare")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,4,8,8")])
 
 (define_split
    addic. %0,%1,%2
    #
    #"
-  [(set_attr "type" "fast_compare,compare,compare,compare")
+  [(set_attr "type" "add,compare,compare,compare")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,4,8,8")])
 
 (define_split
 {
   if (<MODE>mode == DImode && !TARGET_POWERPC64)
     {
-      rs6000_split_logical (operands, NOT, false, false, false, NULL_RTX);
+      rs6000_split_logical (operands, NOT, false, false, false);
       DONE;
     }
 })
   "@
    nor. %2,%1,%1
    #"
-  [(set_attr "type" "fast_compare,compare")
+  [(set_attr "type" "logical,compare")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    nor. %0,%1,%1
    #"
-  [(set_attr "type" "fast_compare,compare")
+  [(set_attr "type" "logical,compare")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   ""
   "@
    subf %0,%2,%1
-   subfic %0,%2,%1")
+   subfic %0,%2,%1"
+  [(set_attr "type" "add")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    subf. %3,%2,%1
    #"
-  [(set_attr "type" "fast_compare")
+  [(set_attr "type" "add")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    subf. %0,%2,%1
    #"
-  [(set_attr "type" "fast_compare")
+  [(set_attr "type" "add")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
        (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
   ""
-  "neg %0,%1")
+  "neg %0,%1"
+  [(set_attr "type" "add")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    neg. %2,%1
    #"
-  [(set_attr "type" "fast_compare")
+  [(set_attr "type" "add")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    neg. %0,%1
    #"
-  [(set_attr "type" "fast_compare")
+  [(set_attr "type" "add")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
 (define_expand "ctz<mode>2"
   [(set (match_dup 2)
        (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_dup 3)
+       (and:GPR (match_dup 1)
+                (match_dup 2)))
+   (set (match_dup 4)
+       (clz:GPR (match_dup 3)))
    (set (match_operand:GPR 0 "gpc_reg_operand" "")
-       (minus:GPR (match_dup 5) (match_dup 4)))]
+       (minus:GPR (match_dup 5)
+                  (match_dup 4)))]
   ""
   {
      operands[2] = gen_reg_rtx (<MODE>mode);
 (define_expand "ffs<mode>2"
   [(set (match_dup 2)
        (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_dup 3)
+       (and:GPR (match_dup 1)
+                (match_dup 2)))
+   (set (match_dup 4)
+       (clz:GPR (match_dup 3)))
    (set (match_operand:GPR 0 "gpc_reg_operand" "")
-       (minus:GPR (match_dup 5) (match_dup 4)))]
+       (minus:GPR (match_dup 5)
+                  (match_dup 4)))]
   ""
   {
      operands[2] = gen_reg_rtx (<MODE>mode);
   emit_insn (gen_bswapsi2 (op4_32, word_high));
   emit_insn (gen_ashldi3 (dest, op3, GEN_INT (32)));
   emit_insn (gen_iordi3 (dest, dest, op4));
+  DONE;
 }")
 
 (define_split
     }
   emit_insn (gen_bswapsi2 (word_high, src_si));
   emit_insn (gen_bswapsi2 (word_low, op3_si));
+  DONE;
 }")
 
 (define_split
   emit_insn (gen_bswapsi2 (op3_si, op2_si));
   emit_insn (gen_ashldi3 (dest, dest, GEN_INT (32)));
   emit_insn (gen_iordi3 (dest, dest, op3));
+  DONE;
 }")
 
 (define_insn "bswapdi2_32bit"
 
   emit_insn (gen_bswapsi2 (dest2, word1));
   emit_insn (gen_bswapsi2 (dest1, word2));
+  DONE;
 }")
 
 (define_split
 
   emit_insn (gen_bswapsi2 (word2, src1));
   emit_insn (gen_bswapsi2 (word1, src2));
+  DONE;
 }")
 
 (define_split
 
   emit_insn (gen_bswapsi2 (dest1, src2));
   emit_insn (gen_bswapsi2 (dest2, src1));
+  DONE;
 }")
 
-(define_insn "mulsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (mult:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
-                (match_operand:SI 2 "reg_or_short_operand" "r,I")))]
+
+(define_insn "mul<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+                 (match_operand:GPR 2 "reg_or_short_operand" "r,I")))]
   ""
   "@
-   mullw %0,%1,%2
+   mull<wd> %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 "imul")))])
-
-(define_insn "*mulsi3_internal1"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (mult:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
-                            (match_operand:SI 2 "gpc_reg_operand" "r,r"))
+   [(set_attr "type" "mul")
+    (set (attr "size")
+      (cond [(match_operand:GPR 2 "s8bit_cint_operand" "")
+               (const_string "8")
+             (match_operand:GPR 2 "short_cint_operand" "")
+               (const_string "16")]
+       (const_string "<bits>")))])
+
+(define_insn_and_split "*mul<mode>3_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                             (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
-  "TARGET_32BIT"
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   mullw. %3,%1,%2
+   mull<wd>. %0,%1,%2
    #"
-  [(set_attr "type" "imul_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (mult:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                            (match_operand:SI 2 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 3)
-       (mult:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (mult:GPR (match_dup 1)
+                 (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "mul")
+   (set_attr "size" "<bits>")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*mulsi3_internal2"
+(define_insn_and_split "*mul<mode>3_dot2"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (mult:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
-                            (match_operand:SI 2 "gpc_reg_operand" "r,r"))
+       (compare:CC (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                             (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (mult:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT"
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (mult:GPR (match_dup 1)
+                 (match_dup 2)))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   mullw. %0,%1,%2
+   mull<wd>. %0,%1,%2
    #"
-  [(set_attr "type" "imul_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (mult:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                            (match_operand:SI 2 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (mult:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
-       (mult:SI (match_dup 1) (match_dup 2)))
+       (mult:GPR (match_dup 1)
+                 (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "mul")
+   (set_attr "size" "<bits>")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
+
+(define_expand "<su>mul<mode>3_highpart"
+  [(set (match_operand:GPR 0 "gpc_reg_operand")
+       (subreg:GPR
+         (mult:<DMODE> (any_extend:<DMODE>
+                         (match_operand:GPR 1 "gpc_reg_operand"))
+                       (any_extend:<DMODE>
+                         (match_operand:GPR 2 "gpc_reg_operand")))
+        0))]
+  ""
+{
+  if (<MODE>mode == SImode && TARGET_POWERPC64)
+    {
+      emit_insn (gen_<su>mulsi3_highpart_64 (operands[0], operands[1],
+                                            operands[2]));
+      DONE;
+    }
+
+  if (!WORDS_BIG_ENDIAN)
+    {
+      emit_insn (gen_<su>mul<mode>3_highpart_le (operands[0], operands[1],
+                                                operands[2]));
+      DONE;
+    }
+})
+
+(define_insn "*<su>mul<mode>3_highpart"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (subreg:GPR
+         (mult:<DMODE> (any_extend:<DMODE>
+                         (match_operand:GPR 1 "gpc_reg_operand" "r"))
+                       (any_extend:<DMODE>
+                         (match_operand:GPR 2 "gpc_reg_operand" "r")))
+        0))]
+  "WORDS_BIG_ENDIAN && !(<MODE>mode == SImode && TARGET_POWERPC64)"
+  "mulh<wd><u> %0,%1,%2"
+  [(set_attr "type" "mul")
+   (set_attr "size" "<bits>")])
+
+(define_insn "<su>mulsi3_highpart_le"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (subreg:SI
+         (mult:DI (any_extend:DI
+                    (match_operand:SI 1 "gpc_reg_operand" "r"))
+                  (any_extend:DI
+                    (match_operand:SI 2 "gpc_reg_operand" "r")))
+        4))]
+  "!WORDS_BIG_ENDIAN && !TARGET_POWERPC64"
+  "mulhw<u> %0,%1,%2"
+  [(set_attr "type" "mul")])
+
+(define_insn "<su>muldi3_highpart_le"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (subreg:DI
+         (mult:TI (any_extend:TI
+                    (match_operand:DI 1 "gpc_reg_operand" "r"))
+                  (any_extend:TI
+                    (match_operand:DI 2 "gpc_reg_operand" "r")))
+        8))]
+  "!WORDS_BIG_ENDIAN && TARGET_POWERPC64"
+  "mulhd<u> %0,%1,%2"
+  [(set_attr "type" "mul")
+   (set_attr "size" "64")])
+
+(define_insn "<su>mulsi3_highpart_64"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (truncate:SI
+         (lshiftrt:DI
+           (mult:DI (any_extend:DI
+                      (match_operand:SI 1 "gpc_reg_operand" "r"))
+                    (any_extend:DI
+                      (match_operand:SI 2 "gpc_reg_operand" "r")))
+           (const_int 32))))]
+  "TARGET_POWERPC64"
+  "mulhw<u> %0,%1,%2"
+  [(set_attr "type" "mul")])
+
+(define_expand "<u>mul<mode><dmode>3"
+  [(set (match_operand:<DMODE> 0 "gpc_reg_operand")
+       (mult:<DMODE> (any_extend:<DMODE>
+                       (match_operand:GPR 1 "gpc_reg_operand"))
+                     (any_extend:<DMODE>
+                       (match_operand:GPR 2 "gpc_reg_operand"))))]
+  "!(<MODE>mode == SImode && TARGET_POWERPC64)"
+{
+  rtx l = gen_reg_rtx (<MODE>mode);
+  rtx h = gen_reg_rtx (<MODE>mode);
+  emit_insn (gen_mul<mode>3 (l, operands[1], operands[2]));
+  emit_insn (gen_<su>mul<mode>3_highpart (h, operands[1], operands[2]));
+  emit_move_insn (gen_lowpart (<MODE>mode, operands[0]), l);
+  emit_move_insn (gen_highpart (<MODE>mode, operands[0]), h);
+  DONE;
+})
 
 
 (define_insn "udiv<mode>3"
                  (match_operand:GPR 2 "gpc_reg_operand" "r")))]
   ""
   "div<wd>u %0,%1,%2"
-   [(set (attr "type")
-      (cond [(match_operand:SI 0 "" "")
-               (const_string "idiv")]
-       (const_string "ldiv")))])
+  [(set_attr "type" "div")
+   (set_attr "size" "<bits>")])
 
 
 ;; For powers of two we can do srai/aze for divide and then adjust for
                 (match_operand:GPR 2 "gpc_reg_operand" "r")))]
   ""
   "div<wd> %0,%1,%2"
-  [(set (attr "type")
-     (cond [(match_operand:SI 0 "" "")
-               (const_string "idiv")]
-       (const_string "ldiv")))])
+  [(set_attr "type" "div")
+   (set_attr "size" "<bits>")])
 
 (define_expand "mod<mode>3"
   [(use (match_operand:GPR 0 "gpc_reg_operand" ""))
 ;; plain 'andi' (only 'andi.'), no plain 'andis', and there are all
 ;; those rotate-and-mask operations.  Thus, the AND insns come first.
 
-(define_expand "andsi3"
-  [(parallel
-    [(set (match_operand:SI 0 "gpc_reg_operand" "")
-         (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                 (match_operand:SI 2 "and_operand" "")))
-     (clobber (match_scratch:CC 3 ""))])]
-  ""
-  "")
-
-(define_insn "andsi3_mc"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
-       (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
-               (match_operand:SI 2 "and_operand" "?r,T,K,L")))
-   (clobber (match_scratch:CC 3 "=X,X,x,x"))]
-  "rs6000_gen_cell_microcode"
-  "@
-   and %0,%1,%2
-   rlwinm %0,%1,0,%m2,%M2
-   andi. %0,%1,%b2
-   andis. %0,%1,%u2"
-  [(set_attr "type" "*,*,fast_compare,fast_compare")])
+(define_expand "and<mode>3"
+  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+       (and:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
+                (match_operand:SDI 2 "reg_or_cint_operand" "")))]
+  ""
+{
+  if (<MODE>mode == DImode && !TARGET_POWERPC64)
+    {
+      rs6000_split_logical (operands, AND, false, false, false);
+      DONE;
+    }
 
-(define_insn "andsi3_nomc"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
-               (match_operand:SI 2 "and_operand" "?r,T")))
-   (clobber (match_scratch:CC 3 "=X,X"))]
-  "!rs6000_gen_cell_microcode"
-  "@
-   and %0,%1,%2
-   rlwinm %0,%1,0,%m2,%M2")
+  if (logical_const_operand (operands[2], <MODE>mode)
+      && !any_mask_operand (operands[2], <MODE>mode))
+    {
+      emit_insn (gen_and<mode>3_imm (operands[0], operands[1], operands[2]));
+      DONE;
+    }
 
-(define_insn "andsi3_internal0_nomc"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-        (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
-                (match_operand:SI 2 "and_operand" "?r,T")))]
-  "!rs6000_gen_cell_microcode"
-  "@
-   and %0,%1,%2
-   rlwinm %0,%1,0,%m2,%M2")
+  if ((<MODE>mode == DImode && !and64_2_operand (operands[2], <MODE>mode))
+      || (<MODE>mode != DImode && !and_operand (operands[2], <MODE>mode)))
+    operands[2] = force_reg (<MODE>mode, operands[2]);
+})
 
 
-;; Note to set cr's other than cr0 we do the and immediate and then
-;; the test again -- this avoids a mfcr which on the higher end
-;; machines causes an execution serialization
+(define_insn "*and<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+                (match_operand:GPR 2 "gpc_reg_operand" "r")))]
+  ""
+  "and %0,%1,%2"
+  [(set_attr "type" "logical")])
 
-(define_insn "*andsi3_internal2_mc"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
-       (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
-                           (match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
+(define_insn_and_split "*and<mode>3_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                            (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r,r,r,r,r"))
-   (clobber (match_scratch:CC 4 "=X,X,X,X,X,x,x,X"))]
-  "TARGET_32BIT && rs6000_gen_cell_microcode"
-  "@
-   and. %3,%1,%2
-   andi. %3,%1,%b2
-   andis. %3,%1,%u2
-   rlwinm. %3,%1,0,%m2,%M2
-   #
-   #
-   #
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
+  "@
+   and. %0,%1,%2
    #"
-  [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
-                    compare,compare,compare,compare")
-   (set_attr "length" "4,4,4,4,8,8,8,8")])
-
-(define_insn "*andsi3_internal3_mc"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
-       (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
-                           (match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (and:GPR (match_dup 1)
+                (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
+(define_insn_and_split "*and<mode>3_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                            (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r,r,r,r,r"))
-   (clobber (match_scratch:CC 4 "=X,X,X,X,X,x,x,X"))]
-  "TARGET_64BIT && rs6000_gen_cell_microcode"
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (and:GPR (match_dup 1)
+                (match_dup 2)))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   #
-   andi. %3,%1,%b2
-   andis. %3,%1,%u2
-   rlwinm. %3,%1,0,%m2,%M2
-   #
-   #
-   #
+   and. %0,%1,%2
    #"
-  [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
-                    compare,compare,compare")
-   (set_attr "length" "8,4,4,4,8,8,8,8")])
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (and:GPR (match_dup 1)
+                (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
-                            (match_operand:GPR 2 "and_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:GPR 3 ""))
-   (clobber (match_scratch:CC 4 ""))]
-  "reload_completed"
-  [(parallel [(set (match_dup 3)
-                  (and:<MODE> (match_dup 1)
-                              (match_dup 2)))
+
+(define_insn "and<mode>3_imm"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r")
+                (match_operand:GPR 2 "logical_const_operand" "n")))
+   (clobber (match_scratch:CC 3 "=x"))]
+  "rs6000_gen_cell_microcode
+   && !any_mask_operand (operands[2], <MODE>mode)"
+  "andi%e2. %0,%1,%u2"
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")])
+
+(define_insn_and_split "*and<mode>3_imm_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
+       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+                            (match_operand:GPR 2 "logical_const_operand" "n,n"))
+                   (const_int 0)))
+   (clobber (match_scratch:GPR 0 "=r,r"))
+   (clobber (match_scratch:CC 4 "=X,x"))]
+  "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
+   && rs6000_gen_cell_microcode
+   && !any_mask_operand (operands[2], <MODE>mode)"
+  "@
+   andi%e2. %0,%1,%u2
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(parallel [(set (match_dup 0)
+                  (and:GPR (match_dup 1)
+                           (match_dup 2)))
              (clobber (match_dup 4))])
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
-
-;; We don't have a 32 bit "and. rt,ra,rb" for ppc64.  cr is set from the
-;; whole 64 bit reg, and we don't know what is in the high 32 bits.
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_operand" "")
-       (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "gpc_reg_operand" ""))
+(define_insn_and_split "*and<mode>3_imm_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
+       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+                            (match_operand:GPR 2 "logical_const_operand" "n,n"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))
-   (clobber (match_scratch:CC 4 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(parallel [(set (match_dup 3)
-                  (and:SI (match_dup 1)
-                          (match_dup 2)))
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (and:GPR (match_dup 1)
+                (match_dup 2)))
+   (clobber (match_scratch:CC 4 "=X,x"))]
+  "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
+   && rs6000_gen_cell_microcode
+   && !any_mask_operand (operands[2], <MODE>mode)"
+  "@
+   andi%e2. %0,%1,%u2
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(parallel [(set (match_dup 0)
+                  (and:GPR (match_dup 1)
+                           (match_dup 2)))
              (clobber (match_dup 4))])
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*andsi3_internal4"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
-       (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
-                           (match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
+(define_insn_and_split "*and<mode>3_imm_mask_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
+       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+                            (match_operand:GPR 2 "logical_const_operand" "n,n"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r")
-       (and:SI (match_dup 1)
-               (match_dup 2)))
-   (clobber (match_scratch:CC 4 "=X,X,X,X,X,x,x,X"))]
-  "TARGET_32BIT && rs6000_gen_cell_microcode"
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
+   && rs6000_gen_cell_microcode
+   && any_mask_operand (operands[2], <MODE>mode)"
   "@
-   and. %0,%1,%2
-   andi. %0,%1,%b2
-   andis. %0,%1,%u2
-   rlwinm. %0,%1,0,%m2,%M2
-   #
-   #
-   #
+   andi%e2. %0,%1,%u2
    #"
-  [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
-                    compare,compare,compare,compare")
-   (set_attr "length" "4,4,4,4,8,8,8,8")])
-
-(define_insn "*andsi3_internal5_mc"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
-       (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
-                           (match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (and:GPR (match_dup 1)
+                (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
+(define_insn_and_split "*and<mode>3_imm_mask_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
+       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+                            (match_operand:GPR 2 "logical_const_operand" "n,n"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r")
-       (and:SI (match_dup 1)
-               (match_dup 2)))
-   (clobber (match_scratch:CC 4 "=X,X,X,X,X,x,x,X"))]
-  "TARGET_64BIT && rs6000_gen_cell_microcode"
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (and:GPR (match_dup 1)
+                (match_dup 2)))]
+  "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
+   && rs6000_gen_cell_microcode
+   && any_mask_operand (operands[2], <MODE>mode)"
   "@
-   #
-   andi. %0,%1,%b2
-   andis. %0,%1,%u2
-   rlwinm. %0,%1,0,%m2,%M2
-   #
-   #
-   #
+   andi%e2. %0,%1,%u2
    #"
-  [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
-                    compare,compare,compare")
-   (set_attr "length" "8,4,4,4,8,8,8,8")])
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (and:GPR (match_dup 1)
+                (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "and_operand" ""))
+
+(define_insn "*and<mode>3_mask"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+                (match_operand:GPR 2 "any_mask_operand" "S,T")))]
+  ""
+  "@
+   rldic%B2 %0,%1,0,%S2
+   rlwinm %0,%1,0,%m2,%M2"
+  [(set_attr "type" "shift")])
+
+(define_insn_and_split "*and<mode>3_mask_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r")
+                            (match_operand:GPR 2 "any_mask_operand" "S,T,S,T"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (and:SI (match_dup 1)
-               (match_dup 2)))
-   (clobber (match_scratch:CC 4 ""))]
-  "reload_completed"
-  [(parallel [(set (match_dup 0)
-                  (and:SI (match_dup 1)
-                          (match_dup 2)))
-             (clobber (match_dup 4))])
+   (clobber (match_scratch:GPR 0 "=r,r,r,r"))]
+  "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
+   && rs6000_gen_cell_microcode
+   && !logical_const_operand (operands[2], <MODE>mode)"
+  "@
+   rldic%B2. %0,%1,0,%S2
+   rlwinm. %0,%1,0,%m2,%M2
+   #
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (and:GPR (match_dup 1)
+                (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,4,8,8")])
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_operand" "")
-       (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "gpc_reg_operand" ""))
+(define_insn_and_split "*and<mode>3_mask_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+       (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r")
+                            (match_operand:GPR 2 "any_mask_operand" "S,T,S,T"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (and:SI (match_dup 1)
-               (match_dup 2)))
-   (clobber (match_scratch:CC 4 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(parallel [(set (match_dup 0)
-                  (and:SI (match_dup 1)
-                          (match_dup 2)))
-             (clobber (match_dup 4))])
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r,r")
+       (and:GPR (match_dup 1)
+                (match_dup 2)))]
+  "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
+   && rs6000_gen_cell_microcode
+   && !logical_const_operand (operands[2], <MODE>mode)"
+  "@
+   rldic%B2. %0,%1,0,%S2
+   rlwinm. %0,%1,0,%m2,%M2
+   #
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (and:GPR (match_dup 1)
+                (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,4,8,8")])
+
+
+
+(define_insn "andsi3_internal0_nomc"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+        (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
+                (match_operand:SI 2 "and_operand" "?r,T")))]
+  "!rs6000_gen_cell_microcode"
+  "@
+   and %0,%1,%2
+   rlwinm %0,%1,0,%m2,%M2"
+  [(set_attr "type" "logical,shift")])
+
 
 ;; Handle the PowerPC64 rlwinm corner case
 
 }"
   [(set_attr "length" "8")])
 
-(define_expand "iorsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (ior:SI (match_operand:SI 1 "gpc_reg_operand" "")
-               (match_operand:SI 2 "reg_or_logical_cint_operand" "")))]
+
+(define_expand "ior<mode>3"
+  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+       (ior:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
+                (match_operand:SDI 2 "reg_or_cint_operand" "")))]
   ""
-  "
 {
-  if (GET_CODE (operands[2]) == CONST_INT
-      && ! logical_operand (operands[2], SImode))
+  if (<MODE>mode == DImode && !TARGET_POWERPC64)
+    {
+      rs6000_split_logical (operands, IOR, false, false, false);
+      DONE;
+    }
+
+  if (non_logical_cint_operand (operands[2], <MODE>mode))
     {
-      HOST_WIDE_INT value = INTVAL (operands[2]);
       rtx tmp = ((!can_create_pseudo_p ()
                  || rtx_equal_p (operands[0], operands[1]))
-                ? operands[0] : gen_reg_rtx (SImode));
+                ? operands[0] : gen_reg_rtx (<MODE>mode));
+      HOST_WIDE_INT value = INTVAL (operands[2]);
 
-      emit_insn (gen_iorsi3 (tmp, operands[1],
+      emit_insn (gen_ior<mode>3 (tmp, operands[1],
                             GEN_INT (value & (~ (HOST_WIDE_INT) 0xffff))));
-      emit_insn (gen_iorsi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
+
+      emit_insn (gen_ior<mode>3 (operands[0], tmp, GEN_INT (value & 0xffff)));
       DONE;
     }
-}")
 
-(define_expand "xorsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (xor:SI (match_operand:SI 1 "gpc_reg_operand" "")
-               (match_operand:SI 2 "reg_or_logical_cint_operand" "")))]
+  if (!reg_or_logical_cint_operand (operands[2], <MODE>mode))
+    operands[2] = force_reg (<MODE>mode, operands[2]);
+})
+
+(define_expand "xor<mode>3"
+  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+       (xor:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
+                (match_operand:SDI 2 "reg_or_cint_operand" "")))]
   ""
-  "
 {
-  if (GET_CODE (operands[2]) == CONST_INT
-      && ! logical_operand (operands[2], SImode))
+  if (<MODE>mode == DImode && !TARGET_POWERPC64)
+    {
+      rs6000_split_logical (operands, XOR, false, false, false);
+      DONE;
+    }
+
+  if (non_logical_cint_operand (operands[2], <MODE>mode))
     {
-      HOST_WIDE_INT value = INTVAL (operands[2]);
       rtx tmp = ((!can_create_pseudo_p ()
                  || rtx_equal_p (operands[0], operands[1]))
-                ? operands[0] : gen_reg_rtx (SImode));
+                ? operands[0] : gen_reg_rtx (<MODE>mode));
+      HOST_WIDE_INT value = INTVAL (operands[2]);
 
-      emit_insn (gen_xorsi3 (tmp, operands[1],
+      emit_insn (gen_xor<mode>3 (tmp, operands[1],
                             GEN_INT (value & (~ (HOST_WIDE_INT) 0xffff))));
-      emit_insn (gen_xorsi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
+
+      emit_insn (gen_xor<mode>3 (operands[0], tmp, GEN_INT (value & 0xffff)));
       DONE;
     }
-}")
 
-(define_insn "*boolsi3_internal1"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r")
-       (match_operator:SI 3 "boolean_or_operator"
-        [(match_operand:SI 1 "gpc_reg_operand" "%r,r,r")
-         (match_operand:SI 2 "logical_operand" "r,K,L")]))]
+  if (!reg_or_logical_cint_operand (operands[2], <MODE>mode))
+    operands[2] = force_reg (<MODE>mode, operands[2]);
+})
+
+(define_insn "*bool<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (match_operator:GPR 3 "boolean_or_operator"
+        [(match_operand:GPR 1 "gpc_reg_operand" "r")
+         (match_operand:GPR 2 "gpc_reg_operand" "r")]))]
+  ""
+  "%q3 %0,%1,%2"
+  [(set_attr "type" "logical")])
+
+(define_insn "*bool<mode>3_imm"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (match_operator:GPR 3 "boolean_or_operator"
+        [(match_operand:GPR 1 "gpc_reg_operand" "%r")
+         (match_operand:GPR 2 "logical_const_operand" "n")]))]
   ""
-  "@
-   %q3 %0,%1,%2
-   %q3i %0,%1,%b2
-   %q3is %0,%1,%u2")
+  "%q3i%e2 %0,%1,%u2"
+  [(set_attr "type" "logical")])
 
-(define_insn "*boolsi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:SI 4 "boolean_or_operator"
-        [(match_operand:SI 1 "gpc_reg_operand" "%r,r")
-         (match_operand:SI 2 "gpc_reg_operand" "r,r")])
+(define_insn_and_split "*bool<mode>3_dot"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+       (compare:CC (match_operator:GPR 3 "boolean_or_operator"
+        [(match_operand:GPR 1 "gpc_reg_operand" "r,r")
+         (match_operand:GPR 2 "gpc_reg_operand" "r,r")])
         (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
-  "TARGET_32BIT"
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   %q4. %3,%1,%2
+   %q3. %0,%1,%2
    #"
-  [(set_attr "type" "fast_compare,compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(match_operand:SI 1 "gpc_reg_operand" "")
-         (match_operand:SI 2 "gpc_reg_operand" "")])
-        (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 3) (match_dup 4))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
+  [(set (match_dup 0)
+       (match_dup 3))
+   (set (match_dup 4)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*boolsi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(match_operand:SI 1 "gpc_reg_operand" "%r,r")
-         (match_operand:SI 2 "gpc_reg_operand" "r,r")])
+(define_insn_and_split "*bool<mode>3_dot2"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+       (compare:CC (match_operator:GPR 3 "boolean_or_operator"
+        [(match_operand:GPR 1 "gpc_reg_operand" "r,r")
+         (match_operand:GPR 2 "gpc_reg_operand" "r,r")])
         (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (match_dup 4))]
-  "TARGET_32BIT"
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (match_dup 3))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   %q4. %0,%1,%2
+   %q3. %0,%1,%2
    #"
-  [(set_attr "type" "fast_compare,compare")
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
+  [(set (match_dup 0)
+       (match_dup 3))
+   (set (match_dup 4)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
+;; Split a logical operation that we can't do in one insn into two insns,
+;; each of which does one 16-bit part.  This is used by combine.
+
 (define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(match_operand:SI 1 "gpc_reg_operand" "")
-         (match_operand:SI 2 "gpc_reg_operand" "")])
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (match_dup 4))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0) (match_dup 4))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-;; Split a logical operation that we can't do in one insn into two insns,
-;; each of which does one 16-bit part.  This is used by combine.
-
-(define_split
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (match_operator:SI 3 "boolean_or_operator"
-        [(match_operand:SI 1 "gpc_reg_operand" "")
-         (match_operand:SI 2 "non_logical_cint_operand" "")]))]
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+       (match_operator:GPR 3 "boolean_or_operator"
+        [(match_operand:GPR 1 "gpc_reg_operand" "")
+         (match_operand:GPR 2 "non_logical_cint_operand" "")]))]
   ""
   [(set (match_dup 0) (match_dup 4))
    (set (match_dup 0) (match_dup 5))]
-"
 {
   rtx i;
   i = GEN_INT (INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff));
-  operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
+  operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[3]), <MODE>mode,
                                operands[1], i);
   i = GEN_INT (INTVAL (operands[2]) & 0xffff);
-  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
+  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), <MODE>mode,
                                operands[0], i);
-}")
+})
 
-(define_insn "*boolcsi3_internal1"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (match_operator:SI 3 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
-         (match_operand:SI 2 "gpc_reg_operand" "r")]))]
+
+(define_insn "*boolc<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (match_operator:GPR 3 "boolean_operator"
+        [(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r"))
+         (match_operand:GPR 1 "gpc_reg_operand" "r")]))]
   ""
-  "%q3 %0,%2,%1")
+  "%q3 %0,%1,%2"
+  [(set_attr "type" "logical")])
 
-(define_insn "*boolcsi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
-         (match_operand:SI 2 "gpc_reg_operand" "r,r")])
+(define_insn_and_split "*boolc<mode>3_dot"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+       (compare:CC (match_operator:GPR 3 "boolean_operator"
+        [(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
+         (match_operand:GPR 1 "gpc_reg_operand" "r,r")])
         (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
-  "TARGET_32BIT"
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   %q4. %3,%2,%1
+   %q3. %0,%1,%2
    #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" ""))
-         (match_operand:SI 2 "gpc_reg_operand" "")])
-        (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 3) (match_dup 4))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
+  [(set (match_dup 0)
+       (match_dup 3))
+   (set (match_dup 4)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*boolcsi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r"))
-         (match_operand:SI 2 "gpc_reg_operand" "r,r")])
+(define_insn_and_split "*boolc<mode>3_dot2"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+       (compare:CC (match_operator:GPR 3 "boolean_operator"
+        [(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
+         (match_operand:GPR 1 "gpc_reg_operand" "r,r")])
         (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (match_dup 4))]
-  "TARGET_32BIT"
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (match_dup 3))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   %q4. %0,%2,%1
+   %q3. %0,%1,%2
    #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" ""))
-         (match_operand:SI 2 "gpc_reg_operand" "")])
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (match_dup 4))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0) (match_dup 4))
-   (set (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
+  [(set (match_dup 0)
+       (match_dup 3))
+   (set (match_dup 4)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*boolccsi3_internal1"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (match_operator:SI 3 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
-         (not:SI (match_operand:SI 2 "gpc_reg_operand" "r"))]))]
+
+(define_insn "*boolcc<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (match_operator:GPR 3 "boolean_operator"
+        [(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
+         (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r"))]))]
   ""
-  "%q3 %0,%1,%2")
+  "%q3 %0,%1,%2"
+  [(set_attr "type" "logical")])
 
-(define_insn "*boolccsi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
-         (not:SI (match_operand:SI 2 "gpc_reg_operand" "r,r"))])
+(define_insn_and_split "*boolcc<mode>3_dot"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+       (compare:CC (match_operator:GPR 3 "boolean_operator"
+        [(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
+         (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))])
         (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
-  "TARGET_32BIT"
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   %q4. %3,%1,%2
+   %q3. %0,%1,%2
    #"
-  [(set_attr "type" "fast_compare,compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" ""))
-         (not:SI (match_operand:SI 2 "gpc_reg_operand" ""))])
-        (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 3) (match_dup 4))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
+  [(set (match_dup 0)
+       (match_dup 3))
+   (set (match_dup 4)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*boolccsi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r"))
-         (not:SI (match_operand:SI 2 "gpc_reg_operand" "r,r"))])
+(define_insn_and_split "*boolcc<mode>3_dot2"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+       (compare:CC (match_operator:GPR 3 "boolean_operator"
+        [(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
+         (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))])
         (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-       (match_dup 4))]
-  "TARGET_32BIT"
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (match_dup 3))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   %q4. %0,%1,%2
+   %q3. %0,%1,%2
    #"
-  [(set_attr "type" "fast_compare,compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:SI 4 "boolean_operator"
-        [(not:SI (match_operand:SI 1 "gpc_reg_operand" ""))
-         (not:SI (match_operand:SI 2 "gpc_reg_operand" ""))])
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (match_dup 4))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0) (match_dup 4))
-   (set (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
+  [(set (match_dup 0)
+       (match_dup 3))
+   (set (match_dup 4)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "logical")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
+
+;; TODO: Should have dots of this as well.
+(define_insn "*eqv<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (not:GPR (xor:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+                         (match_operand:GPR 2 "gpc_reg_operand" "r"))))]
+  ""
+  "eqv %0,%1,%2"
+  [(set_attr "type" "logical")])
 \f
 ;; Rotate and shift insns, in all their variants.  These support shifts,
 ;; field inserts and extracts, and various combinations thereof.
   operands[1] = GEN_INT (start + size - 1);
   return \"rlwimi %0,%3,%h4,%h2,%h1\";
 }"
-  [(set_attr "type" "insert_word")])
+  [(set_attr "type" "insert")])
 
 (define_insn "*insvsi_internal1"
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
   operands[1] = GEN_INT (start + size - 1);
   return \"rlwimi %0,%3,%h4,%h2,%h1\";
 }"
-  [(set_attr "type" "insert_word")])
+  [(set_attr "type" "insert")])
 
 (define_insn "*insvsi_internal2"
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
   operands[1] = GEN_INT (start + size - 1);
   return \"rlwimi %0,%3,%h4,%h2,%h1\";
 }"
-  [(set_attr "type" "insert_word")])
+  [(set_attr "type" "insert")])
 
 (define_insn "*insvsi_internal3"
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
   operands[1] = GEN_INT (start + size - 1);
   return \"rlwimi %0,%3,%h4,%h2,%h1\";
 }"
-  [(set_attr "type" "insert_word")])
+  [(set_attr "type" "insert")])
 
 (define_insn "*insvsi_internal4"
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
   operands[1] = GEN_INT (insert_start + insert_size - 1);
   return \"rlwimi %0,%3,%h5,%h2,%h1\";
 }"
-  [(set_attr "type" "insert_word")])
+  [(set_attr "type" "insert")])
 
 ;; combine patterns for rlwimi
 (define_insn "*insvsi_internal5"
  operands[1] = GEN_INT(me);
  return \"rlwimi %0,%3,%h4,%h2,%h1\";
 }"
-  [(set_attr "type" "insert_word")])
+  [(set_attr "type" "insert")])
 
 (define_insn "*insvsi_internal6"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
  operands[1] = GEN_INT(me);
  return \"rlwimi %0,%3,%h4,%h2,%h1\";
 }"
-  [(set_attr "type" "insert_word")])
+  [(set_attr "type" "insert")])
 
 (define_insn "insvdi_internal"
   [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
   operands[1] = GEN_INT (64 - start - size);
   return \"rldimi %0,%3,%H1,%H2\";
 }"
-  [(set_attr "type" "insert_dword")])
+  [(set_attr "type" "insert")
+   (set_attr "size" "64")])
 
 (define_insn "*insvdi_internal2"
   [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
   else
     operands[3] = GEN_INT (start + size);
   return \"rlwinm %0,%1,%3,%s2,31\";
-}")
+}"
+  [(set_attr "type" "shift")])
 
 (define_insn "*extzvsi_internal1"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
     operands[3] = GEN_INT (start + size);
   return \"rlwinm. %4,%1,%3,%s2,31\";
 }"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
     operands[3] = GEN_INT (start + size);
   return \"rlwinm. %0,%1,%3,%s2,31\";
 }"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
     operands[3] = GEN_INT (start + size);
   operands[2] = GEN_INT (64 - size);
   return \"rldicl %0,%1,%3,%2\";
-}")
+}"
+  [(set_attr "type" "shift")])
 
 (define_insn "*extzvdi_internal1"
   [(set (match_operand:CC 0 "gpc_reg_operand" "=x")
   operands[2] = GEN_INT (64 - size);
   return \"rldicl. %4,%1,%3,%2\";
 }"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")])
 
 (define_insn "*extzvdi_internal2"
   [(set (match_operand:CC 4 "gpc_reg_operand" "=x")
   operands[2] = GEN_INT (64 - size);
   return \"rldicl. %0,%1,%3,%2\";
 }"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")])
 
-(define_insn "rotlsi3"
-  [(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")))]
+
+(define_insn "rotl<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+                   (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
   ""
-  "@
-   rlwnm %0,%1,%2,0xffffffff
-   rlwinm %0,%1,%h2,0xffffffff"
-  [(set_attr "type" "var_shift_rotate,integer")])
+  "rotl<wd>%I2 %0,%1,%<hH>2"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
 (define_insn "*rotlsi3_64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI
-           (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                      (match_operand:SI 2 "reg_or_cint_operand" "r,i"))))]
-  "TARGET_64BIT"
-  "@
-   rlwnm %0,%1,%2,0xffffffff
-   rlwinm %0,%1,%h2,0xffffffff"
-  [(set_attr "type" "var_shift_rotate,integer")])
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+           (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                      (match_operand:SI 2 "reg_or_cint_operand" "rn"))))]
+  "TARGET_POWERPC64"
+  "rotlw%I2 %0,%1,%h2"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
-(define_insn "*rotlsi3_internal2"
-  [(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"))
+(define_insn_and_split "*rotl<mode>3_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                               (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
-  ""
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   rlwnm. %3,%1,%2,0xffffffff
-   rlwinm. %3,%1,%h2,0xffffffff
-   #
+   rotl<wd>%I2. %0,%1,%<hH>2
    #"
-  [(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_micro_cr0_operand" "")
-       (compare:CC (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                              (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "reload_completed"
-  [(set (match_dup 3)
-       (rotate:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (rotate:GPR (match_dup 1)
+                   (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*rotlsi3_internal3"
-  [(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"))
+(define_insn_and_split "*rotl<mode>3_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                               (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
-       (rotate:SI (match_dup 1) (match_dup 2)))]
-  ""
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (rotate:GPR (match_dup 1)
+                   (match_dup 2)))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   rlwnm. %0,%1,%2,0xffffffff
-   rlwinm. %0,%1,%h2,0xffffffff
-   #
+   rotl<wd>%I2. %0,%1,%<hH>2
    #"
-  [(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_micro_cr0_operand" "")
-       (compare:CC (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                              (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (rotate:SI (match_dup 1) (match_dup 2)))]
-  "reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
-       (rotate:SI (match_dup 1) (match_dup 2)))
+       (rotate:GPR (match_dup 1)
+                   (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
 
 (define_insn "*rotlsi3_internal4"
-  [(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")))]
+  [(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" "rn"))
+               (match_operand:SI 3 "mask_operand" "n")))]
   ""
-  "@
-   rlwnm %0,%1,%2,%m3,%M3
-   rlwinm %0,%1,%h2,%m3,%M3"
-  [(set_attr "type" "var_shift_rotate,integer")])
+  "rlw%I2nm %0,%1,%h2,%m3,%M3"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
 (define_insn "*rotlsi3_internal5"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC (and:SI
-                    (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"))
+                    (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                               (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
+                    (match_operand:SI 3 "mask_operand" "n,n"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 4 "=r,r,r,r"))]
+   (clobber (match_scratch:SI 4 "=r,r"))]
   ""
   "@
-   rlwnm. %4,%1,%2,%m3,%M3
-   rlwinm. %4,%1,%h2,%m3,%M3
-   #
+   rlw%I2nm. %4,%1,%h2,%m3,%M3
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal6"
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
        (compare:CC (and:SI
-                    (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"))
+                    (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                               (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
+                    (match_operand:SI 3 "mask_operand" "n,n"))
                    (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")
        (and:SI (rotate:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
   ""
   "@
-   rlwnm. %0,%1,%2,%m3,%M3
-   rlwinm. %0,%1,%h2,%m3,%M3
-   #
+   rlw%I2nm. %0,%1,%h2,%m3,%M3
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "")
   [(set (attr "cell_micro")
      (if_then_else (match_operand:SI 2 "const_int_operand" "")
        (const_string "not")
-       (const_string "always")))])
+       (const_string "always")))
+   (set_attr "type" "shift")])
 
 (define_insn "*rotlsi3_internal7be"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
   [(set (attr "cell_micro")
      (if_then_else (match_operand:SI 2 "const_int_operand" "")
        (const_string "not")
-       (const_string "always")))])
+       (const_string "always")))
+   (set_attr "type" "shift")])
 
 (define_insn "*rotlsi3_internal8le"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC (zero_extend:SI
                     (subreg:QI
-                     (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))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 0))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
+   (clobber (match_scratch:SI 3 "=r,r"))]
   "!BYTES_BIG_ENDIAN"
   "@
-   rlwnm. %3,%1,%2,0xff
-   rlwinm. %3,%1,%h2,0xff
-   #
+   rlw%I2nm. %3,%1,%h2,0xff
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_insn "*rotlsi3_internal8be"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC (zero_extend:SI
                     (subreg:QI
-                     (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")) 3))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 3))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
+   (clobber (match_scratch:SI 3 "=r,r"))]
   "BYTES_BIG_ENDIAN"
   "@
-   rlwnm. %3,%1,%2,0xff
-   rlwinm. %3,%1,%h2,0xff
-   #
+   rlw%I2nm. %3,%1,%h2,0xff
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal9le"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
        (compare:CC (zero_extend:SI
                     (subreg:QI
-                     (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))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 0))
                    (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")
        (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 0)))]
   "!BYTES_BIG_ENDIAN"
   "@
-   rlwnm. %0,%1,%2,0xff
-   rlwinm. %0,%1,%h2,0xff
-   #
+   rlw%I2nm. %0,%1,%h2,0xff
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_insn "*rotlsi3_internal9be"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
        (compare:CC (zero_extend:SI
                     (subreg:QI
-                     (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")) 3))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 3))
                    (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")
        (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 3)))]
   "BYTES_BIG_ENDIAN"
   "@
-   rlwnm. %0,%1,%2,0xff
-   rlwinm. %0,%1,%h2,0xff
-   #
+   rlw%I2nm. %0,%1,%h2,0xff
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal10le"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (zero_extend:SI
         (subreg:HI
-         (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                    (match_operand:SI 2 "reg_or_cint_operand" "r,i")) 0)))]
+         (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                    (match_operand:SI 2 "reg_or_cint_operand" "rn")) 0)))]
   "!BYTES_BIG_ENDIAN"
-  "@
-   rlwnm %0,%1,%2,0xffff
-   rlwinm %0,%1,%h2,0xffff"
-  [(set_attr "type" "var_shift_rotate,integer")])
+  "rlw%I2nm %0,%1,%h2,0xffff"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
 (define_insn "*rotlsi3_internal10be"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (zero_extend:SI
         (subreg:HI
-         (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                    (match_operand:SI 2 "reg_or_cint_operand" "r,i")) 2)))]
+         (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                    (match_operand:SI 2 "reg_or_cint_operand" "rn")) 2)))]
   "BYTES_BIG_ENDIAN"
-  "@
-   rlwnm %0,%1,%2,0xffff
-   rlwinm %0,%1,%h2,0xffff"
-  [(set_attr "type" "var_shift_rotate,integer")])
+  "rlw%I2nm %0,%1,%h2,0xffff"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
 (define_insn "*rotlsi3_internal11le"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC (zero_extend:SI
                     (subreg:HI
-                     (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))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 0))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
+   (clobber (match_scratch:SI 3 "=r,r"))]
   "!BYTES_BIG_ENDIAN"
   "@
-   rlwnm. %3,%1,%2,0xffff
-   rlwinm. %3,%1,%h2,0xffff
-   #
+   rlw%I2nm. %3,%1,%h2,0xffff
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_insn "*rotlsi3_internal11be"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC (zero_extend:SI
                     (subreg:HI
-                     (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")) 2))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 2))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
+   (clobber (match_scratch:SI 3 "=r,r"))]
   "BYTES_BIG_ENDIAN"
   "@
-   rlwnm. %3,%1,%2,0xffff
-   rlwinm. %3,%1,%h2,0xffff
-   #
+   rlw%I2nm. %3,%1,%h2,0xffff
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
   "")
 
 (define_insn "*rotlsi3_internal12le"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
        (compare:CC (zero_extend:SI
                     (subreg:HI
-                     (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))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 0))
                    (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")
        (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 0)))]
   "!BYTES_BIG_ENDIAN"
   "@
-   rlwnm. %0,%1,%2,0xffff
-   rlwinm. %0,%1,%h2,0xffff
-   #
+   rlw%I2nm. %0,%1,%h2,0xffff
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_insn "*rotlsi3_internal12be"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
        (compare:CC (zero_extend:SI
                     (subreg:HI
-                     (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")) 2))
+                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+                                (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 2))
                    (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")
        (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 2)))]
   "BYTES_BIG_ENDIAN"
   "@
-   rlwnm. %0,%1,%2,0xffff
-   rlwinm. %0,%1,%h2,0xffff
-   #
+   rlw%I2nm. %0,%1,%h2,0xffff
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
                    (const_int 0)))]
   "")
 
-(define_insn "ashlsi3"
-  [(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")))]
+
+(define_insn "ashl<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+                   (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
   ""
-  "@
-   slw %0,%1,%2
-   slwi %0,%1,%h2"
-  [(set_attr "type" "var_shift_rotate,shift")])
+  "sl<wd>%I2 %0,%1,%<hH>2"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
 (define_insn "*ashlsi3_64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI
-           (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                      (match_operand:SI 2 "reg_or_cint_operand" "r,i"))))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+           (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                      (match_operand:SI 2 "reg_or_cint_operand" "rn"))))]
   "TARGET_POWERPC64"
-  "@
-   slw %0,%1,%2
-   slwi %0,%1,%h2"
-  [(set_attr "type" "var_shift_rotate,shift")])
+  "slw%I2 %0,%1,%h2"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
-(define_insn ""
-  [(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"))
+(define_insn_and_split "*ashl<mode>3_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                               (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
-  "TARGET_32BIT"
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   slw. %3,%1,%2
-   slwi. %3,%1,%h2
-   #
+   sl<wd>%I2. %0,%1,%<hH>2
    #"
-  [(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 (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                              (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 3)
-       (ashift:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (ashift:GPR (match_dup 1)
+                   (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn ""
-  [(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"))
+(define_insn_and_split "*ashl<mode>3_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                               (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
-       (ashift:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT"
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (ashift:GPR (match_dup 1)
+                   (match_dup 2)))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   slw. %0,%1,%2
-   slwi. %0,%1,%h2
-   #
+   sl<wd>%I2. %0,%1,%<hH>2
    #"
-  [(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" "")
-       (compare:CC (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                              (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (ashift:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
-       (ashift:SI (match_dup 1) (match_dup 2)))
+       (ashift:GPR (match_dup 1)
+                   (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
 
 (define_insn "rlwinm"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                           (match_operand:SI 2 "const_int_operand" "i"))
                (match_operand:SI 3 "mask_operand" "n")))]
   "includes_lshift_p (operands[2], operands[3])"
-  "rlwinm %0,%1,%h2,%m3,%M3")
+  "rlwinm %0,%1,%h2,%m3,%M3"
+  [(set_attr "type" "shift")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    rlwinm. %4,%1,%h2,%m3,%M3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    rlwinm. %0,%1,%h2,%m3,%M3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
                    (const_int 0)))]
   "")
 
-(define_insn "lshrsi3"
-  [(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")))]
+
+(define_insn "lshr<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+                     (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
   ""
-  "@
-  mr %0,%1
-  srw %0,%1,%2
-  srwi %0,%1,%h2"
-  [(set_attr "type" "integer,var_shift_rotate,shift")])
+  "sr<wd>%I2 %0,%1,%<hH>2"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
 (define_insn "*lshrsi3_64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (zero_extend:DI
-           (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                        (match_operand:SI 2 "reg_or_cint_operand" "r,i"))))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+           (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                        (match_operand:SI 2 "reg_or_cint_operand" "rn"))))]
   "TARGET_POWERPC64"
-  "@
-  srw %0,%1,%2
-  srwi %0,%1,%h2"
-  [(set_attr "type" "var_shift_rotate,shift")])
+  "srw%I2 %0,%1,%h2"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
-(define_insn ""
-  [(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"))
+(define_insn_and_split "*lshr<mode>3_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                                 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=X,r,r,X,r,r"))]
-  "TARGET_32BIT"
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   mr. %1,%1
-   srw. %3,%1,%2
-   srwi. %3,%1,%h2
-   #
-   #
+   sr<wd>%I2. %0,%1,%<hH>2
    #"
-  [(set_attr "type" "fast_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" "")
-       (compare:CC (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                                (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 3)
-       (lshiftrt:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (lshiftrt:GPR (match_dup 1)
+                     (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn ""
-  [(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"))
+(define_insn_and_split "*lshr<mode>3_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                                 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r,r")
-       (lshiftrt:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT"
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (lshiftrt:GPR (match_dup 1)
+                     (match_dup 2)))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   mr. %0,%1
-   srw. %0,%1,%2
-   srwi. %0,%1,%h2
-   #
-   #
+   sr<wd>%I2. %0,%1,%<hH>2
    #"
-  [(set_attr "type" "fast_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" "")
-       (compare:CC (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                                (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (lshiftrt:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
-       (lshiftrt:SI (match_dup 1) (match_dup 2)))
+       (lshiftrt:GPR (match_dup 1)
+                     (match_dup 2)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                             (match_operand:SI 2 "const_int_operand" "i"))
                (match_operand:SI 3 "mask_operand" "n")))]
   "includes_rshift_p (operands[2], operands[3])"
-  "rlwinm %0,%1,%s2,%m3,%M3")
+  "rlwinm %0,%1,%s2,%m3,%M3"
+  [(set_attr "type" "shift")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    rlwinm. %4,%1,%s2,%m3,%M3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    rlwinm. %0,%1,%s2,%m3,%M3
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
          (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                       (match_operand:SI 2 "const_int_operand" "i")) 0)))]
   "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))"
-  "rlwinm %0,%1,%s2,0xff")
+  "rlwinm %0,%1,%s2,0xff"
+  [(set_attr "type" "shift")])
 
 (define_insn "*lshiftrt_internal1be"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
          (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                       (match_operand:SI 2 "const_int_operand" "i")) 3)))]
   "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))"
-  "rlwinm %0,%1,%s2,0xff")
+  "rlwinm %0,%1,%s2,0xff"
+  [(set_attr "type" "shift")])
 
 (define_insn "*lshiftrt_internal2le"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    rlwinm. %3,%1,%s2,0xff
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_insn "*lshiftrt_internal2be"
   "@
    rlwinm. %3,%1,%s2,0xff
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    rlwinm. %0,%1,%s2,0xff
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_insn "*lshiftrt_internal3be"
   "@
    rlwinm. %0,%1,%s2,0xff
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
          (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                       (match_operand:SI 2 "const_int_operand" "i")) 0)))]
   "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))"
-  "rlwinm %0,%1,%s2,0xffff")
+  "rlwinm %0,%1,%s2,0xffff"
+  [(set_attr "type" "shift")])
 
 (define_insn "*lshiftrt_internal4be"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
          (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                       (match_operand:SI 2 "const_int_operand" "i")) 2)))]
   "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))"
-  "rlwinm %0,%1,%s2,0xffff")
+  "rlwinm %0,%1,%s2,0xffff"
+  [(set_attr "type" "shift")])
 
 (define_insn "*lshiftrt_internal5le"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    rlwinm. %3,%1,%s2,0xffff
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_insn "*lshiftrt_internal5be"
   "@
    rlwinm. %3,%1,%s2,0xffff
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   "@
    rlwinm. %0,%1,%s2,0xffff
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_insn "*lshiftrt_internal5be"
   "@
    rlwinm. %0,%1,%s2,0xffff
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
                    (const_int 0)))]
   "")
 
-(define_insn "ashrsi3"
-  [(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")))]
+
+(define_expand "ashr<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+       (ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+                     (match_operand:SI 2 "reg_or_cint_operand" "")))]
   ""
-  "@
-   sraw %0,%1,%2
-   srawi %0,%1,%h2"
-  [(set_attr "type" "var_shift_rotate,shift")])
+{
+  /* The generic code does not generate optimal code for the low word
+     (it should be a rlwimi and a rot).  Until we have target code to
+     solve this generically, keep this expander.  */
+
+  if (<MODE>mode == DImode && !TARGET_POWERPC64)
+    {
+      if (CONST_INT_P (operands[2]))
+       {
+         emit_insn (gen_ashrdi3_no_power (operands[0], operands[1], operands[2]));
+         DONE;
+       }
+      else
+       FAIL;
+    }
+})
+
+(define_insn "*ashr<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+                     (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
+  ""
+  "sra<wd>%I2 %0,%1,%<hH>2"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
 (define_insn "*ashrsi3_64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (sign_extend:DI
-           (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                        (match_operand:SI 2 "reg_or_cint_operand" "r,i"))))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (sign_extend:DI
+           (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                        (match_operand:SI 2 "reg_or_cint_operand" "rn"))))]
   "TARGET_POWERPC64"
-  "@
-   sraw %0,%1,%2
-   srawi %0,%1,%h2"
-  [(set_attr "type" "var_shift_rotate,shift")])
+  "sraw%I2 %0,%1,%h2"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
-(define_insn ""
-  [(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"))
+(define_insn_and_split "*ashr<mode>3_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                                 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
                    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r,r,r"))]
-  ""
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   sraw. %3,%1,%2
-   srawi. %3,%1,%h2
-   #
+   sra<wd>%I2. %0,%1,%<hH>2
    #"
-  [(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_micro_cr0_operand" "")
-       (compare:CC (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                                (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "reload_completed"
-  [(set (match_dup 3)
-       (ashiftrt:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (ashiftrt:GPR (match_dup 1)
+                     (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn ""
-  [(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"))
+(define_insn_and_split "*ashr<mode>3_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                                 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
                    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
-       (ashiftrt:SI (match_dup 1) (match_dup 2)))]
-  ""
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (ashiftrt:GPR (match_dup 1)
+                     (match_dup 2)))]
+  "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
-   sraw. %0,%1,%2
-   srawi. %0,%1,%h2
-   #
+   sra<wd>%I2. %0,%1,%<hH>2
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+       (ashiftrt:GPR (match_dup 1)
+                     (match_dup 2)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 \f
 ;; Builtins to replace a division to generate FRE reciprocal estimate
 ;; instructions and the necessary fixup instructions
   DONE;
 })
 \f
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                                (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (ashiftrt:SI (match_dup 1) (match_dup 2)))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (ashiftrt:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-\f
 ;; Floating-point insns, excluding normal data motion.  We combine the SF/DF
 ;; modes here, and also add in conditional vsx/power8-vector support to access
 ;; values in the traditional Altivec registers if the appropriate
        (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
                  (match_operand:SFDF 2 "gpc_reg_operand" "")))]
   "TARGET_<MODE>_INSN && !TARGET_SIMPLE_FPU"
-  "")
-
-(define_insn "*div<mode>3_fpr"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
-                 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
-  "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU"
-  "@
-   fdiv<Ftrad> %0,%1,%2
-   xsdiv<Fvsx> %x0,%x1,%x2"
-  [(set_attr "type" "<Fs>div")
-   (set_attr "fp_type" "fp_div_<Fs>")])
-
-(define_insn "sqrt<mode>2"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
-  "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU
-   && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))"
-  "@
-   fsqrt<Ftrad> %0,%1
-   xssqrt<Fvsx> %x0,%x1"
-  [(set_attr "type" "<Fs>sqrt")
-   (set_attr "fp_type" "fp_sqrt_<Fs>")])
-
-;; Floating point reciprocal approximation
-(define_insn "fre<Fs>"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
-                    UNSPEC_FRES))]
-  "TARGET_<FFRE>"
-  "@
-   fre<Ftrad> %0,%1
-   xsre<Fvsx> %x0,%x1"
-  [(set_attr "type" "fp")])
-
-(define_insn "*rsqrt<mode>2"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
-                    UNSPEC_RSQRT))]
-  "RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)"
-  "@
-   frsqrte<Ftrad> %0,%1
-   xsrsqrte<Fvsx> %x0,%x1"
-  [(set_attr "type" "fp")])
-
-;; Floating point comparisons
-(define_insn "*cmp<mode>_fpr"
-  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y")
-       (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
-                     (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
-  "TARGET_<MODE>_FPR"
-  "@
-   fcmpu %0,%1,%2
-   xscmpudp %0,%x1,%x2"
-  [(set_attr "type" "fpcompare")])
-
-;; Floating point conversions
-(define_expand "extendsfdf2"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))]
-  "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
-  "")
-
-(define_insn_and_split "*extendsfdf2_fpr"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,ws,?ws,wv")
-       (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z")))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
-  "@
-   #
-   fmr %0,%1
-   lfs%U1%X1 %0,%1
-   #
-   xxlor %x0,%x1,%x1
-   lxsspx %x0,%y1"
-  "&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])"
-  [(const_int 0)]
-{
-  emit_note (NOTE_INSN_DELETED);
-  DONE;
-}
-  [(set_attr_alternative "type"
-      [(const_string "fp")
-       (const_string "fp")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "fpload_u")
-          (const_string "fpload")))
-       (const_string "fp")
-       (const_string "vecsimple")
-       (if_then_else
-       (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-       (const_string "fpload_ux")
-       (if_then_else
-        (match_test "update_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_u")
-        (const_string "fpload")))])])
-
-(define_expand "truncdfsf2"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "")
-       (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
-  "")
-
-(define_insn "*truncdfsf2_fpr"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-       (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d")))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
-  "frsp %0,%1"
-  [(set_attr "type" "fp")])
-
-;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
-;; builtins.c and optabs.c that are not correct for IBM long double
-;; when little-endian.
-(define_expand "signbittf2"
-  [(set (match_dup 2)
-       (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))
-   (set (match_dup 3)
-       (subreg:DI (match_dup 2) 0))
-   (set (match_dup 4)
-       (match_dup 5))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (match_dup 6))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
-{
-  operands[2] = gen_reg_rtx (DFmode);
-  operands[3] = gen_reg_rtx (DImode);
-  if (TARGET_POWERPC64)
-    {
-      operands[4] = gen_reg_rtx (DImode);
-      operands[5] = gen_rtx_LSHIFTRT (DImode, operands[3], GEN_INT (63));
-      operands[6] = gen_rtx_SUBREG (SImode, operands[4],
-                                   WORDS_BIG_ENDIAN ? 4 : 0);
-    }
-  else
-    {
-      operands[4] = gen_reg_rtx (SImode);
-      operands[5] = gen_rtx_SUBREG (SImode, operands[3],
-                                   WORDS_BIG_ENDIAN ? 0 : 4);
-      operands[6] = gen_rtx_LSHIFTRT (SImode, operands[4], GEN_INT (31));
-    }
-})
-
-(define_expand "copysign<mode>3"
-  [(set (match_dup 3)
-        (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))
-   (set (match_dup 4)
-       (neg:SFDF (abs:SFDF (match_dup 1))))
-   (set (match_operand:SFDF 0 "gpc_reg_operand" "")
-        (if_then_else:SFDF (ge (match_operand:SFDF 2 "gpc_reg_operand" "")
-                              (match_dup 5))
-                        (match_dup 3)
-                        (match_dup 4)))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
-   && ((TARGET_PPC_GFXOPT
-        && !HONOR_NANS (<MODE>mode)
-        && !HONOR_SIGNED_ZEROS (<MODE>mode))
-       || TARGET_CMPB
-       || VECTOR_UNIT_VSX_P (<MODE>mode))"
-{
-  if (TARGET_CMPB || VECTOR_UNIT_VSX_P (<MODE>mode))
-    {
-      emit_insn (gen_copysign<mode>3_fcpsgn (operands[0], operands[1],
-                                            operands[2]));
-      DONE;
-    }
-
-   operands[3] = gen_reg_rtx (<MODE>mode);
-   operands[4] = gen_reg_rtx (<MODE>mode);
-   operands[5] = CONST0_RTX (<MODE>mode);
-  })
-
-;; Use an unspec rather providing an if-then-else in RTL, to prevent the
-;; compiler from optimizing -0.0
-(define_insn "copysign<mode>3_fcpsgn"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
-                     (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")]
-                    UNSPEC_COPYSIGN))]
-  "TARGET_<MODE>_FPR && TARGET_CMPB"
-  "@
-   fcpsgn %0,%2,%1
-   xscpsgn<Fvsx> %x0,%x2,%x1"
-  [(set_attr "type" "fp")])
-
-;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
-;; fsel instruction and some auxiliary computations.  Then we just have a
-;; single DEFINE_INSN for fsel and the define_splits to make them if made by
-;; combine.
-;; For MIN, MAX on non-VSX machines, and conditional move all of the time, we
-;; use DEFINE_EXPAND's that involve a fsel instruction and some auxiliary
-;; computations.  Then we just have a single DEFINE_INSN for fsel and the
-;; define_splits to make them if made by combine.  On VSX machines we have the
-;; min/max instructions.
-;;
-;; On VSX, we only check for TARGET_VSX instead of checking for a vsx/p8 vector
-;; to allow either DF/SF to use only traditional registers.
-
-(define_expand "smax<mode>3"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
-       (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
-                              (match_operand:SFDF 2 "gpc_reg_operand" ""))
-                          (match_dup 1)
-                          (match_dup 2)))]
-  "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
-{
-  rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
-  DONE;
-})
-
-(define_insn "*smax<mode>3_vsx"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (smax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
-                  (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
-  "TARGET_<MODE>_FPR && TARGET_VSX"
-  "xsmaxdp %x0,%x1,%x2"
-  [(set_attr "type" "fp")])
-
-(define_expand "smin<mode>3"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
-       (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
-                              (match_operand:SFDF 2 "gpc_reg_operand" ""))
-                          (match_dup 2)
-                          (match_dup 1)))]
-  "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
-{
-  rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
-  DONE;
-})
-
-(define_insn "*smin<mode>3_vsx"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (smin:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
-                  (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
-  "TARGET_<MODE>_FPR && TARGET_VSX"
-  "xsmindp %x0,%x1,%x2"
-  [(set_attr "type" "fp")])
-
-(define_split
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
-       (match_operator:SFDF 3 "min_max_operator"
-        [(match_operand:SFDF 1 "gpc_reg_operand" "")
-         (match_operand:SFDF 2 "gpc_reg_operand" "")]))]
-  "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math
-   && !TARGET_VSX"
-  [(const_int 0)]
-{
-  rs6000_emit_minmax (operands[0], GET_CODE (operands[3]), operands[1],
-                     operands[2]);
-  DONE;
-})
-
-(define_split
-  [(set (match_operand:SF 0 "gpc_reg_operand" "")
-       (match_operator:SF 3 "min_max_operator"
-        [(match_operand:SF 1 "gpc_reg_operand" "")
-         (match_operand:SF 2 "gpc_reg_operand" "")]))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS 
-   && TARGET_SINGLE_FLOAT && !flag_trapping_math"
-  [(const_int 0)]
-  "
-{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
-                     operands[1], operands[2]);
-  DONE;
-}")
-
-(define_expand "mov<mode>cc"
-   [(set (match_operand:GPR 0 "gpc_reg_operand" "")
-        (if_then_else:GPR (match_operand 1 "comparison_operator" "")
-                          (match_operand:GPR 2 "gpc_reg_operand" "")
-                          (match_operand:GPR 3 "gpc_reg_operand" "")))]
-  "TARGET_ISEL<sel>"
-  "
-{
-  if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
-    DONE;
-  else
-    FAIL;
-}")
-
-;; We use the BASE_REGS for the isel input operands because, if rA is
-;; 0, the value of 0 is placed in rD upon truth.  Similarly for rB
-;; because we may switch the operands and rB may end up being rA.
-;;
-;; We need 2 patterns: an unsigned and a signed pattern.  We could
-;; leave out the mode in operand 4 and use one pattern, but reload can
-;; change the mode underneath our feet and then gets confused trying
-;; to reload the value.
-(define_insn "isel_signed_<mode>"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
-       (if_then_else:GPR
-        (match_operator 1 "scc_comparison_operator"
-                        [(match_operand:CC 4 "cc_reg_operand" "y,y")
-                         (const_int 0)])
-        (match_operand:GPR 2 "reg_or_cint_operand" "O,b")
-        (match_operand:GPR 3 "gpc_reg_operand" "r,r")))]
-  "TARGET_ISEL<sel>"
-  "*
-{ return output_isel (operands); }"
-  [(set_attr "type" "isel")
-   (set_attr "length" "4")])
-
-(define_insn "isel_unsigned_<mode>"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
-       (if_then_else:GPR
-        (match_operator 1 "scc_comparison_operator"
-                        [(match_operand:CCUNS 4 "cc_reg_operand" "y,y")
-                         (const_int 0)])
-        (match_operand:GPR 2 "reg_or_cint_operand" "O,b")
-        (match_operand:GPR 3 "gpc_reg_operand" "r,r")))]
-  "TARGET_ISEL<sel>"
-  "*
-{ return output_isel (operands); }"
-  [(set_attr "type" "isel")
-   (set_attr "length" "4")])
-
-;; These patterns can be useful for combine; they let combine know that
-;; isel can handle reversed comparisons so long as the operands are
-;; registers.
-
-(define_insn "*isel_reversed_signed_<mode>"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
-       (if_then_else:GPR
-        (match_operator 1 "scc_rev_comparison_operator"
-                        [(match_operand:CC 4 "cc_reg_operand" "y")
-                         (const_int 0)])
-        (match_operand:GPR 2 "gpc_reg_operand" "b")
-        (match_operand:GPR 3 "gpc_reg_operand" "b")))]
-  "TARGET_ISEL<sel>"
-  "*
-{ return output_isel (operands); }"
-  [(set_attr "type" "isel")
-   (set_attr "length" "4")])
-
-(define_insn "*isel_reversed_unsigned_<mode>"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
-       (if_then_else:GPR
-        (match_operator 1 "scc_rev_comparison_operator"
-                        [(match_operand:CCUNS 4 "cc_reg_operand" "y")
-                         (const_int 0)])
-        (match_operand:GPR 2 "gpc_reg_operand" "b")
-        (match_operand:GPR 3 "gpc_reg_operand" "b")))]
-  "TARGET_ISEL<sel>"
-  "*
-{ return output_isel (operands); }"
-  [(set_attr "type" "isel")
-   (set_attr "length" "4")])
-
-(define_expand "movsfcc"
-   [(set (match_operand:SF 0 "gpc_reg_operand" "")
-        (if_then_else:SF (match_operand 1 "comparison_operator" "")
-                         (match_operand:SF 2 "gpc_reg_operand" "")
-                         (match_operand:SF 3 "gpc_reg_operand" "")))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
-  "
-{
-  if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
-    DONE;
-  else
-    FAIL;
-}")
-
-(define_insn "*fselsfsf4"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-       (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
-                            (match_operand:SF 4 "zero_fp_constant" "F"))
-                        (match_operand:SF 2 "gpc_reg_operand" "f")
-                        (match_operand:SF 3 "gpc_reg_operand" "f")))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
-  "fsel %0,%1,%2,%3"
-  [(set_attr "type" "fp")])
-
-(define_insn "*fseldfsf4"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-       (if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "d")
-                            (match_operand:DF 4 "zero_fp_constant" "F"))
-                        (match_operand:SF 2 "gpc_reg_operand" "f")
-                        (match_operand:SF 3 "gpc_reg_operand" "f")))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_SINGLE_FLOAT"
-  "fsel %0,%1,%2,%3"
-  [(set_attr "type" "fp")])
-
-;; The conditional move instructions allow us to perform max and min
-;; operations even when
-
-(define_split
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (match_operator:DF 3 "min_max_operator"
-        [(match_operand:DF 1 "gpc_reg_operand" "")
-         (match_operand:DF 2 "gpc_reg_operand" "")]))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
-   && !flag_trapping_math"
-  [(const_int 0)]
-  "
-{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
-                     operands[1], operands[2]);
-  DONE;
-}")
-
-(define_expand "movdfcc"
-   [(set (match_operand:DF 0 "gpc_reg_operand" "")
-        (if_then_else:DF (match_operand 1 "comparison_operator" "")
-                         (match_operand:DF 2 "gpc_reg_operand" "")
-                         (match_operand:DF 3 "gpc_reg_operand" "")))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
-  "
-{
-  if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
-    DONE;
-  else
-    FAIL;
-}")
-
-(define_insn "*fseldfdf4"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-       (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "d")
-                            (match_operand:DF 4 "zero_fp_constant" "F"))
-                        (match_operand:DF 2 "gpc_reg_operand" "d")
-                        (match_operand:DF 3 "gpc_reg_operand" "d")))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
-  "fsel %0,%1,%2,%3"
-  [(set_attr "type" "fp")])
-
-(define_insn "*fselsfdf4"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-       (if_then_else:DF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
-                            (match_operand:SF 4 "zero_fp_constant" "F"))
-                        (match_operand:DF 2 "gpc_reg_operand" "d")
-                        (match_operand:DF 3 "gpc_reg_operand" "d")))]
-  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_SINGLE_FLOAT"
-  "fsel %0,%1,%2,%3"
-  [(set_attr "type" "fp")])
-\f
-;; Conversions to and from floating-point.
-
-; We don't define lfiwax/lfiwzx with the normal definition, because we
-; don't want to support putting SImode in FPR registers.
-(define_insn "lfiwax"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wm,!wm")
-       (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r")]
-                  UNSPEC_LFIWAX))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX"
-  "@
-   lfiwax %0,%y1
-   lxsiwax %x0,%y1
-   mtvsrwa %x0,%1"
-  [(set_attr "type" "fpload,fpload,mffgpr")])
-
-; This split must be run before register allocation because it allocates the
-; memory slot that is needed to move values to/from the FPR.  We don't allocate
-; it earlier to allow for the combiner to merge insns together where it might
-; not be needed and also in case the insns are deleted as dead code.
-
-(define_insn_and_split "floatsi<mode>2_lfiwax"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
-       (float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
-   (clobber (match_scratch:DI 2 "=d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
-   && <SI_CONVERT_FP> && can_create_pseudo_p ()"
-  "#"
-  ""
-  [(pc)]
-  "
-{
-  rtx dest = operands[0];
-  rtx src = operands[1];
-  rtx tmp;
-
-  if (!MEM_P (src) && TARGET_POWERPC64
-      && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
-    tmp = convert_to_mode (DImode, src, false);
-  else
-    {
-      tmp = operands[2];
-      if (GET_CODE (tmp) == SCRATCH)
-       tmp = gen_reg_rtx (DImode);
-      if (MEM_P (src))
-       {
-         src = rs6000_address_for_fpconvert (src);
-         emit_insn (gen_lfiwax (tmp, src));
-       }
-      else
-       {
-         rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
-         emit_move_insn (stack, src);
-         emit_insn (gen_lfiwax (tmp, stack));
-       }
-    }
-  emit_insn (gen_floatdi<mode>2 (dest, tmp));
-  DONE;
-}"
-  [(set_attr "length" "12")
-   (set_attr "type" "fpload")])
-
-(define_insn_and_split "floatsi<mode>2_lfiwax_mem"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,<rreg2>")
-       (float:SFDF
-        (sign_extend:DI
-         (match_operand:SI 1 "memory_operand" "Z,Z"))))
-   (clobber (match_scratch:DI 2 "=0,d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
-   && <SI_CONVERT_FP>"
-  "#"
-  ""
-  [(pc)]
-  "
-{
-  operands[1] = rs6000_address_for_fpconvert (operands[1]);
-  if (GET_CODE (operands[2]) == SCRATCH)
-    operands[2] = gen_reg_rtx (DImode);
-  emit_insn (gen_lfiwax (operands[2], operands[1]));
-  emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
-  DONE;
-}"
-  [(set_attr "length" "8")
-   (set_attr "type" "fpload")])
-
-(define_insn "lfiwzx"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wm,!wm")
-       (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r")]
-                  UNSPEC_LFIWZX))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX"
-  "@
-   lfiwzx %0,%y1
-   lxsiwzx %x0,%y1
-   mtvsrwz %x0,%1"
-  [(set_attr "type" "fpload,fpload,mftgpr")])
-
-(define_insn_and_split "floatunssi<mode>2_lfiwzx"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
-       (unsigned_float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
-   (clobber (match_scratch:DI 2 "=d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
-   && <SI_CONVERT_FP>"
-  "#"
-  ""
-  [(pc)]
-  "
-{
-  rtx dest = operands[0];
-  rtx src = operands[1];
-  rtx tmp;
-
-  if (!MEM_P (src) && TARGET_POWERPC64
-      && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
-    tmp = convert_to_mode (DImode, src, true);
-  else
-    {
-      tmp = operands[2];
-      if (GET_CODE (tmp) == SCRATCH)
-       tmp = gen_reg_rtx (DImode);
-      if (MEM_P (src))
-       {
-         src = rs6000_address_for_fpconvert (src);
-         emit_insn (gen_lfiwzx (tmp, src));
-       }
-      else
-       {
-         rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
-         emit_move_insn (stack, src);
-         emit_insn (gen_lfiwzx (tmp, stack));
-       }
-    }
-  emit_insn (gen_floatdi<mode>2 (dest, tmp));
-  DONE;
-}"
-  [(set_attr "length" "12")
-   (set_attr "type" "fpload")])
-
-(define_insn_and_split "floatunssi<mode>2_lfiwzx_mem"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,<rreg2>")
-       (unsigned_float:SFDF
-        (zero_extend:DI
-         (match_operand:SI 1 "memory_operand" "Z,Z"))))
-   (clobber (match_scratch:DI 2 "=0,d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
-   && <SI_CONVERT_FP>"
-  "#"
-  ""
-  [(pc)]
-  "
-{
-  operands[1] = rs6000_address_for_fpconvert (operands[1]);
-  if (GET_CODE (operands[2]) == SCRATCH)
-    operands[2] = gen_reg_rtx (DImode);
-  emit_insn (gen_lfiwzx (operands[2], operands[1]));
-  emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
-  DONE;
-}"
-  [(set_attr "length" "8")
-   (set_attr "type" "fpload")])
-
-; For each of these conversions, there is a define_expand, a define_insn
-; with a '#' template, and a define_split (with C code).  The idea is
-; to allow constant folding with the template of the define_insn,
-; then to have the insns split later (between sched1 and final).
-
-(define_expand "floatsidf2"
-  [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
-                  (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
-             (use (match_dup 2))
-             (use (match_dup 3))
-             (clobber (match_dup 4))
-             (clobber (match_dup 5))
-             (clobber (match_dup 6))])]
-  "TARGET_HARD_FLOAT 
-   && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
-  "
-{
-  if (TARGET_E500_DOUBLE)
-    {
-      if (!REG_P (operands[1]))
-       operands[1] = force_reg (SImode, operands[1]);
-      emit_insn (gen_spe_floatsidf2 (operands[0], operands[1]));
-      DONE;
-    }
-  else if (TARGET_LFIWAX && TARGET_FCFID)
-    {
-      emit_insn (gen_floatsidf2_lfiwax (operands[0], operands[1]));
-      DONE;
-    }
-  else if (TARGET_FCFID)
-    {
-      rtx dreg = operands[1];
-      if (!REG_P (dreg))
-       dreg = force_reg (SImode, dreg);
-      dreg = convert_to_mode (DImode, dreg, false);
-      emit_insn (gen_floatdidf2 (operands[0], dreg));
-      DONE;
-    }
-
-  if (!REG_P (operands[1]))
-    operands[1] = force_reg (SImode, operands[1]);
-  operands[2] = force_reg (SImode, GEN_INT (0x43300000));
-  operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503601774854144\", DFmode));
-  operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
-  operands[5] = gen_reg_rtx (DFmode);
-  operands[6] = gen_reg_rtx (SImode);
-}")
-
-(define_insn_and_split "*floatsidf2_internal"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=&d")
-       (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" "d"))
-   (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
-   (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))
-   (clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
-  "! TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
-  "#"
-  ""
-  [(pc)]
-  "
-{
-  rtx lowword, highword;
-  gcc_assert (MEM_P (operands[4]));
-  highword = adjust_address (operands[4], SImode, 0);
-  lowword = adjust_address (operands[4], SImode, 4);
-  if (! WORDS_BIG_ENDIAN)
-    {
-      rtx tmp;
-      tmp = highword; highword = lowword; lowword = tmp;
-    }
-
-  emit_insn (gen_xorsi3 (operands[6], operands[1],
-                        GEN_INT (~ (HOST_WIDE_INT) 0x7fffffff)));
-  emit_move_insn (lowword, operands[6]);
-  emit_move_insn (highword, operands[2]);
-  emit_move_insn (operands[5], operands[4]);
-  emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
-  DONE;
-}"
-  [(set_attr "length" "24")
-   (set_attr "type" "fp")])
-
-;; If we don't have a direct conversion to single precision, don't enable this
-;; conversion for 32-bit without fast math, because we don't have the insn to
-;; generate the fixup swizzle to avoid double rounding problems.
-(define_expand "floatunssisf2"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "")
-        (unsigned_float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
-  "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
-   && (!TARGET_FPRS
-       || (TARGET_FPRS
-          && ((TARGET_FCFIDUS && TARGET_LFIWZX)
-              || (TARGET_DOUBLE_FLOAT && TARGET_FCFID
-                  && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
-  "
-{
-  if (!TARGET_FPRS)
-    {
-      if (!REG_P (operands[1]))
-       operands[1] = force_reg (SImode, operands[1]);
-    }
-  else if (TARGET_LFIWZX && TARGET_FCFIDUS)
-    {
-      emit_insn (gen_floatunssisf2_lfiwzx (operands[0], operands[1]));
-      DONE;
-    }
-  else
-    {
-      rtx dreg = operands[1];
-      if (!REG_P (dreg))
-       dreg = force_reg (SImode, dreg);
-      dreg = convert_to_mode (DImode, dreg, true);
-      emit_insn (gen_floatdisf2 (operands[0], dreg));
-      DONE;
-    }
-}")
-
-(define_expand "floatunssidf2"
-  [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
-                  (unsigned_float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
-             (use (match_dup 2))
-             (use (match_dup 3))
-             (clobber (match_dup 4))
-             (clobber (match_dup 5))])]
-  "TARGET_HARD_FLOAT
-   && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
-  "
-{
-  if (TARGET_E500_DOUBLE)
-    {
-      if (!REG_P (operands[1]))
-       operands[1] = force_reg (SImode, operands[1]);
-      emit_insn (gen_spe_floatunssidf2 (operands[0], operands[1]));
-      DONE;
-    }
-  else if (TARGET_LFIWZX && TARGET_FCFID)
-    {
-      emit_insn (gen_floatunssidf2_lfiwzx (operands[0], operands[1]));
-      DONE;
-    }
-  else if (TARGET_FCFID)
-    {
-      rtx dreg = operands[1];
-      if (!REG_P (dreg))
-       dreg = force_reg (SImode, dreg);
-      dreg = convert_to_mode (DImode, dreg, true);
-      emit_insn (gen_floatdidf2 (operands[0], dreg));
-      DONE;
-    }
-
-  if (!REG_P (operands[1]))
-    operands[1] = force_reg (SImode, operands[1]);
-  operands[2] = force_reg (SImode, GEN_INT (0x43300000));
-  operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503599627370496\", DFmode));
-  operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
-  operands[5] = gen_reg_rtx (DFmode);
-}")
-
-(define_insn_and_split "*floatunssidf2_internal"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=&d")
-       (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" "d"))
-   (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
-   (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))]
-  "! TARGET_FCFIDU && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
-   && !(TARGET_FCFID && TARGET_POWERPC64)"
-  "#"
-  ""
-  [(pc)]
-  "
-{
-  rtx lowword, highword;
-  gcc_assert (MEM_P (operands[4]));
-  highword = adjust_address (operands[4], SImode, 0);
-  lowword = adjust_address (operands[4], SImode, 4);
-  if (! WORDS_BIG_ENDIAN)
-    {
-      rtx tmp;
-      tmp = highword; highword = lowword; lowword = tmp;
-    }
+  "")
 
-  emit_move_insn (lowword, operands[1]);
-  emit_move_insn (highword, operands[2]);
-  emit_move_insn (operands[5], operands[4]);
-  emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
-  DONE;
-}"
-  [(set_attr "length" "20")
-   (set_attr "type" "fp")])
+(define_insn "*div<mode>3_fpr"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+                 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+  "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU"
+  "@
+   fdiv<Ftrad> %0,%1,%2
+   xsdiv<Fvsx> %x0,%x1,%x2"
+  [(set_attr "type" "<Fs>div")
+   (set_attr "fp_type" "fp_div_<Fs>")])
 
-(define_expand "fix_trunc<mode>si2"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && ((TARGET_FPRS && <TARGET_FLOAT>) || <E500_CONVERT>)"
-  "
-{
-  if (!<E500_CONVERT>)
-    {
-      rtx tmp, stack;
+(define_insn "sqrt<mode>2"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+  "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU
+   && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))"
+  "@
+   fsqrt<Ftrad> %0,%1
+   xssqrt<Fvsx> %x0,%x1"
+  [(set_attr "type" "<Fs>sqrt")
+   (set_attr "fp_type" "fp_sqrt_<Fs>")])
 
-      if (TARGET_STFIWX)
-       emit_insn (gen_fix_trunc<mode>si2_stfiwx (operands[0], operands[1]));
-      else
-       {
-         tmp = gen_reg_rtx (DImode);
-         stack = rs6000_allocate_stack_temp (DImode, true, false);
-         emit_insn (gen_fix_trunc<mode>si2_internal (operands[0], operands[1],
-                                                     tmp, stack));
-       }
-      DONE;
-    }
-}")
+;; Floating point reciprocal approximation
+(define_insn "fre<Fs>"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+                    UNSPEC_FRES))]
+  "TARGET_<FFRE>"
+  "@
+   fre<Ftrad> %0,%1
+   xsre<Fvsx> %x0,%x1"
+  [(set_attr "type" "fp")])
 
-; Like the convert to float patterns, this insn must be split before
-; register allocation so that it can allocate the memory slot if it
-; needed
-(define_insn_and_split "fix_trunc<mode>si2_stfiwx"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
-       (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
-   (clobber (match_scratch:DI 2 "=d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
-   && (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
-   && TARGET_STFIWX && can_create_pseudo_p ()"
-  "#"
-  ""
-  [(pc)]
-{
-  rtx dest = operands[0];
-  rtx src = operands[1];
-  rtx tmp = operands[2];
+(define_insn "*rsqrt<mode>2"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+                    UNSPEC_RSQRT))]
+  "RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)"
+  "@
+   frsqrte<Ftrad> %0,%1
+   xsrsqrte<Fvsx> %x0,%x1"
+  [(set_attr "type" "fp")])
 
-  if (GET_CODE (tmp) == SCRATCH)
-    tmp = gen_reg_rtx (DImode);
+;; Floating point comparisons
+(define_insn "*cmp<mode>_fpr"
+  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y")
+       (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+                     (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+  "TARGET_<MODE>_FPR"
+  "@
+   fcmpu %0,%1,%2
+   xscmpudp %0,%x1,%x2"
+  [(set_attr "type" "fpcompare")])
 
-  emit_insn (gen_fctiwz_<mode> (tmp, src));
-  if (MEM_P (dest))
-    {
-      dest = rs6000_address_for_fpconvert (dest);
-      emit_insn (gen_stfiwx (dest, tmp));
-      DONE;
-    }
-  else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
-    {
-      dest = gen_lowpart (DImode, dest);
-      emit_move_insn (dest, tmp);
-      DONE;
-    }
-  else
-    {
-      rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
-      emit_insn (gen_stfiwx (stack, tmp));
-      emit_move_insn (dest, stack);
-      DONE;
-    }
-}
-  [(set_attr "length" "12")
-   (set_attr "type" "fp")])
+;; Floating point conversions
+(define_expand "extendsfdf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))]
+  "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
+  "")
 
-(define_insn_and_split "fix_trunc<mode>si2_internal"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,?r")
-       (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d,<rreg>")))
-   (clobber (match_operand:DI 2 "gpc_reg_operand" "=1,d"))
-   (clobber (match_operand:DI 3 "offsettable_mem_operand" "=o,o"))]
+(define_insn_and_split "*extendsfdf2_fpr"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,ws,?ws,wv")
+       (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z")))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
-  "#"
-  ""
-  [(pc)]
-  "
+  "@
+   #
+   fmr %0,%1
+   lfs%U1%X1 %0,%1
+   #
+   xxlor %x0,%x1,%x1
+   lxsspx %x0,%y1"
+  "&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])"
+  [(const_int 0)]
 {
-  rtx lowword;
-  gcc_assert (MEM_P (operands[3]));
-  lowword = adjust_address (operands[3], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
-
-  emit_insn (gen_fctiwz_<mode> (operands[2], operands[1]));
-  emit_move_insn (operands[3], operands[2]);
-  emit_move_insn (operands[0], lowword);
+  emit_note (NOTE_INSN_DELETED);
   DONE;
-}"
-  [(set_attr "length" "16")
-   (set_attr "type" "fp")])
+}
+  [(set_attr "type" "fp,fp,fpload,fp,vecsimple,fpload")])
 
-(define_expand "fix_trunc<mode>di2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
-   && TARGET_FCFID"
+(define_expand "truncdfsf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+       (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
   "")
 
-(define_insn "*fix_trunc<mode>di2_fctidz"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
-       (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))]
-  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
-    && TARGET_FCFID && !VECTOR_UNIT_VSX_P (<MODE>mode)"
-  "fctidz %0,%1"
+(define_insn "*truncdfsf2_fpr"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d")))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+  "frsp %0,%1"
   [(set_attr "type" "fp")])
 
-(define_expand "fixuns_trunc<mode>si2"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT
-   && ((TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ && TARGET_STFIWX)
-       || <E500_CONVERT>)"
-  "
-{
-  if (!<E500_CONVERT>)
-    {
-      emit_insn (gen_fixuns_trunc<mode>si2_stfiwx (operands[0], operands[1]));
-      DONE;
-    }
-}")
-
-(define_insn_and_split "fixuns_trunc<mode>si2_stfiwx"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
-       (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
-   (clobber (match_scratch:DI 2 "=d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
-   && TARGET_STFIWX && can_create_pseudo_p ()"
-  "#"
-  ""
-  [(pc)]
+;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
+;; builtins.c and optabs.c that are not correct for IBM long double
+;; when little-endian.
+(define_expand "signbittf2"
+  [(set (match_dup 2)
+       (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))
+   (set (match_dup 3)
+       (subreg:DI (match_dup 2) 0))
+   (set (match_dup 4)
+       (match_dup 5))
+   (set (match_operand:SI 0 "gpc_reg_operand" "")
+       (match_dup 6))]
+  "!TARGET_IEEEQUAD
+   && TARGET_HARD_FLOAT
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)
+   && TARGET_LONG_DOUBLE_128"
 {
-  rtx dest = operands[0];
-  rtx src = operands[1];
-  rtx tmp = operands[2];
-
-  if (GET_CODE (tmp) == SCRATCH)
-    tmp = gen_reg_rtx (DImode);
-
-  emit_insn (gen_fctiwuz_<mode> (tmp, src));
-  if (MEM_P (dest))
+  operands[2] = gen_reg_rtx (DFmode);
+  operands[3] = gen_reg_rtx (DImode);
+  if (TARGET_POWERPC64)
     {
-      dest = rs6000_address_for_fpconvert (dest);
-      emit_insn (gen_stfiwx (dest, tmp));
-      DONE;
+      operands[4] = gen_reg_rtx (DImode);
+      operands[5] = gen_rtx_LSHIFTRT (DImode, operands[3], GEN_INT (63));
+      operands[6] = gen_rtx_SUBREG (SImode, operands[4],
+                                   WORDS_BIG_ENDIAN ? 4 : 0);
     }
-  else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
+  else
     {
-      dest = gen_lowpart (DImode, dest);
-      emit_move_insn (dest, tmp);
-      DONE;
+      operands[4] = gen_reg_rtx (SImode);
+      operands[5] = gen_rtx_SUBREG (SImode, operands[3],
+                                   WORDS_BIG_ENDIAN ? 0 : 4);
+      operands[6] = gen_rtx_LSHIFTRT (SImode, operands[4], GEN_INT (31));
     }
-  else
+})
+
+(define_expand "copysign<mode>3"
+  [(set (match_dup 3)
+        (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))
+   (set (match_dup 4)
+       (neg:SFDF (abs:SFDF (match_dup 1))))
+   (set (match_operand:SFDF 0 "gpc_reg_operand" "")
+        (if_then_else:SFDF (ge (match_operand:SFDF 2 "gpc_reg_operand" "")
+                              (match_dup 5))
+                        (match_dup 3)
+                        (match_dup 4)))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
+   && ((TARGET_PPC_GFXOPT
+        && !HONOR_NANS (<MODE>mode)
+        && !HONOR_SIGNED_ZEROS (<MODE>mode))
+       || TARGET_CMPB
+       || VECTOR_UNIT_VSX_P (<MODE>mode))"
+{
+  if (TARGET_CMPB || VECTOR_UNIT_VSX_P (<MODE>mode))
     {
-      rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
-      emit_insn (gen_stfiwx (stack, tmp));
-      emit_move_insn (dest, stack);
+      emit_insn (gen_copysign<mode>3_fcpsgn (operands[0], operands[1],
+                                            operands[2]));
       DONE;
     }
-}
-  [(set_attr "length" "12")
-   (set_attr "type" "fp")])
 
-(define_expand "fixuns_trunc<mode>di2"
-  [(set (match_operand:DI 0 "register_operand" "")
-       (unsigned_fix:DI (match_operand:SFDF 1 "register_operand" "")))]
-  "TARGET_HARD_FLOAT && (TARGET_FCTIDUZ || VECTOR_UNIT_VSX_P (<MODE>mode))"
-  "")
+   operands[3] = gen_reg_rtx (<MODE>mode);
+   operands[4] = gen_reg_rtx (<MODE>mode);
+   operands[5] = CONST0_RTX (<MODE>mode);
+  })
 
-(define_insn "*fixuns_trunc<mode>di2_fctiduz"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
-       (unsigned_fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))]
-  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
-    && TARGET_FCTIDUZ && !VECTOR_UNIT_VSX_P (<MODE>mode)"
-  "fctiduz %0,%1"
+;; Use an unspec rather providing an if-then-else in RTL, to prevent the
+;; compiler from optimizing -0.0
+(define_insn "copysign<mode>3_fcpsgn"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+                     (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")]
+                    UNSPEC_COPYSIGN))]
+  "TARGET_<MODE>_FPR && TARGET_CMPB"
+  "@
+   fcpsgn %0,%2,%1
+   xscpsgn<Fvsx> %x0,%x2,%x1"
   [(set_attr "type" "fp")])
 
-; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
-; rather than (set (subreg:SI (reg)) (fix:SI ...))
-; because the first makes it clear that operand 0 is not live
-; before the instruction.
-(define_insn "fctiwz_<mode>"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
-       (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))]
-                  UNSPEC_FCTIWZ))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
-  "fctiwz %0,%1"
-  [(set_attr "type" "fp")])
+;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
+;; fsel instruction and some auxiliary computations.  Then we just have a
+;; single DEFINE_INSN for fsel and the define_splits to make them if made by
+;; combine.
+;; For MIN, MAX on non-VSX machines, and conditional move all of the time, we
+;; use DEFINE_EXPAND's that involve a fsel instruction and some auxiliary
+;; computations.  Then we just have a single DEFINE_INSN for fsel and the
+;; define_splits to make them if made by combine.  On VSX machines we have the
+;; min/max instructions.
+;;
+;; On VSX, we only check for TARGET_VSX instead of checking for a vsx/p8 vector
+;; to allow either DF/SF to use only traditional registers.
 
-(define_insn "fctiwuz_<mode>"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
-       (unspec:DI [(unsigned_fix:SI
-                    (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>"))]
-                  UNSPEC_FCTIWUZ))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ"
-  "fctiwuz %0,%1"
-  [(set_attr "type" "fp")])
+(define_expand "smax<mode>3"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+       (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
+                              (match_operand:SFDF 2 "gpc_reg_operand" ""))
+                          (match_dup 1)
+                          (match_dup 2)))]
+  "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
+{
+  rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
+  DONE;
+})
 
-;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
-;; since the friz instruction does not truncate the value if the floating
-;; point value is < LONG_MIN or > LONG_MAX.
-(define_insn "*friz"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-       (float:DF (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d"))))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_FPRND
-   && !VECTOR_UNIT_VSX_P (DFmode) && flag_unsafe_math_optimizations
-   && !flag_trapping_math && TARGET_FRIZ"
-  "friz %0,%1"
+(define_insn "*smax<mode>3_vsx"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (smax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+                  (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+  "TARGET_<MODE>_FPR && TARGET_VSX"
+  "xsmaxdp %x0,%x1,%x2"
   [(set_attr "type" "fp")])
 
-;; Since FCTIWZ doesn't sign extend the upper bits, we have to do a store and a
-;; load to properly sign extend the value, but at least doing a store, load
-;; into a GPR to sign extend, a store from the GPR and a load back into the FPR
-;; if we have 32-bit memory ops
-(define_insn_and_split "*round32<mode>2_fprs"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
-       (float:SFDF
-        (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))))
-   (clobber (match_scratch:DI 2 "=d"))
-   (clobber (match_scratch:DI 3 "=d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
-   && <SI_CONVERT_FP> && TARGET_LFIWAX && TARGET_STFIWX && TARGET_FCFID
-   && can_create_pseudo_p ()"
-  "#"
-  ""
-  [(pc)]
+(define_expand "smin<mode>3"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+       (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
+                              (match_operand:SFDF 2 "gpc_reg_operand" ""))
+                          (match_dup 2)
+                          (match_dup 1)))]
+  "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
 {
-  rtx dest = operands[0];
-  rtx src = operands[1];
-  rtx tmp1 = operands[2];
-  rtx tmp2 = operands[3];
-  rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
+  rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
+  DONE;
+})
 
-  if (GET_CODE (tmp1) == SCRATCH)
-    tmp1 = gen_reg_rtx (DImode);
-  if (GET_CODE (tmp2) == SCRATCH)
-    tmp2 = gen_reg_rtx (DImode);
+(define_insn "*smin<mode>3_vsx"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (smin:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+                  (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+  "TARGET_<MODE>_FPR && TARGET_VSX"
+  "xsmindp %x0,%x1,%x2"
+  [(set_attr "type" "fp")])
 
-  emit_insn (gen_fctiwz_<mode> (tmp1, src));
-  emit_insn (gen_stfiwx (stack, tmp1));
-  emit_insn (gen_lfiwax (tmp2, stack));
-  emit_insn (gen_floatdi<mode>2 (dest, tmp2));
+(define_split
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+       (match_operator:SFDF 3 "min_max_operator"
+        [(match_operand:SFDF 1 "gpc_reg_operand" "")
+         (match_operand:SFDF 2 "gpc_reg_operand" "")]))]
+  "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math
+   && !TARGET_VSX"
+  [(const_int 0)]
+{
+  rs6000_emit_minmax (operands[0], GET_CODE (operands[3]), operands[1],
+                     operands[2]);
   DONE;
-}
-  [(set_attr "type" "fpload")
-   (set_attr "length" "16")])
+})
 
-(define_insn_and_split "*roundu32<mode>2_fprs"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
-       (unsigned_float:SFDF
-        (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))))
-   (clobber (match_scratch:DI 2 "=d"))
-   (clobber (match_scratch:DI 3 "=d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
-   && TARGET_LFIWZX && TARGET_STFIWX && TARGET_FCFIDU
-   && can_create_pseudo_p ()"
-  "#"
-  ""
-  [(pc)]
+(define_split
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+       (match_operator:SF 3 "min_max_operator"
+        [(match_operand:SF 1 "gpc_reg_operand" "")
+         (match_operand:SF 2 "gpc_reg_operand" "")]))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS 
+   && TARGET_SINGLE_FLOAT && !flag_trapping_math"
+  [(const_int 0)]
+  "
+{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
+                     operands[1], operands[2]);
+  DONE;
+}")
+
+(define_expand "mov<mode>cc"
+   [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+        (if_then_else:GPR (match_operand 1 "comparison_operator" "")
+                          (match_operand:GPR 2 "gpc_reg_operand" "")
+                          (match_operand:GPR 3 "gpc_reg_operand" "")))]
+  "TARGET_ISEL<sel>"
+  "
 {
-  rtx dest = operands[0];
-  rtx src = operands[1];
-  rtx tmp1 = operands[2];
-  rtx tmp2 = operands[3];
-  rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
+  if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+    DONE;
+  else
+    FAIL;
+}")
+
+;; We use the BASE_REGS for the isel input operands because, if rA is
+;; 0, the value of 0 is placed in rD upon truth.  Similarly for rB
+;; because we may switch the operands and rB may end up being rA.
+;;
+;; We need 2 patterns: an unsigned and a signed pattern.  We could
+;; leave out the mode in operand 4 and use one pattern, but reload can
+;; change the mode underneath our feet and then gets confused trying
+;; to reload the value.
+(define_insn "isel_signed_<mode>"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (if_then_else:GPR
+        (match_operator 1 "scc_comparison_operator"
+                        [(match_operand:CC 4 "cc_reg_operand" "y,y")
+                         (const_int 0)])
+        (match_operand:GPR 2 "reg_or_cint_operand" "O,b")
+        (match_operand:GPR 3 "gpc_reg_operand" "r,r")))]
+  "TARGET_ISEL<sel>"
+  "*
+{ return output_isel (operands); }"
+  [(set_attr "type" "isel")
+   (set_attr "length" "4")])
+
+(define_insn "isel_unsigned_<mode>"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (if_then_else:GPR
+        (match_operator 1 "scc_comparison_operator"
+                        [(match_operand:CCUNS 4 "cc_reg_operand" "y,y")
+                         (const_int 0)])
+        (match_operand:GPR 2 "reg_or_cint_operand" "O,b")
+        (match_operand:GPR 3 "gpc_reg_operand" "r,r")))]
+  "TARGET_ISEL<sel>"
+  "*
+{ return output_isel (operands); }"
+  [(set_attr "type" "isel")
+   (set_attr "length" "4")])
+
+;; These patterns can be useful for combine; they let combine know that
+;; isel can handle reversed comparisons so long as the operands are
+;; registers.
+
+(define_insn "*isel_reversed_signed_<mode>"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (if_then_else:GPR
+        (match_operator 1 "scc_rev_comparison_operator"
+                        [(match_operand:CC 4 "cc_reg_operand" "y")
+                         (const_int 0)])
+        (match_operand:GPR 2 "gpc_reg_operand" "b")
+        (match_operand:GPR 3 "gpc_reg_operand" "b")))]
+  "TARGET_ISEL<sel>"
+  "*
+{ return output_isel (operands); }"
+  [(set_attr "type" "isel")
+   (set_attr "length" "4")])
 
-  if (GET_CODE (tmp1) == SCRATCH)
-    tmp1 = gen_reg_rtx (DImode);
-  if (GET_CODE (tmp2) == SCRATCH)
-    tmp2 = gen_reg_rtx (DImode);
+(define_insn "*isel_reversed_unsigned_<mode>"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (if_then_else:GPR
+        (match_operator 1 "scc_rev_comparison_operator"
+                        [(match_operand:CCUNS 4 "cc_reg_operand" "y")
+                         (const_int 0)])
+        (match_operand:GPR 2 "gpc_reg_operand" "b")
+        (match_operand:GPR 3 "gpc_reg_operand" "b")))]
+  "TARGET_ISEL<sel>"
+  "*
+{ return output_isel (operands); }"
+  [(set_attr "type" "isel")
+   (set_attr "length" "4")])
 
-  emit_insn (gen_fctiwuz_<mode> (tmp1, src));
-  emit_insn (gen_stfiwx (stack, tmp1));
-  emit_insn (gen_lfiwzx (tmp2, stack));
-  emit_insn (gen_floatdi<mode>2 (dest, tmp2));
-  DONE;
-}
-  [(set_attr "type" "fpload")
-   (set_attr "length" "16")])
+(define_expand "movsfcc"
+   [(set (match_operand:SF 0 "gpc_reg_operand" "")
+        (if_then_else:SF (match_operand 1 "comparison_operator" "")
+                         (match_operand:SF 2 "gpc_reg_operand" "")
+                         (match_operand:SF 3 "gpc_reg_operand" "")))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
+  "
+{
+  if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+    DONE;
+  else
+    FAIL;
+}")
 
-;; No VSX equivalent to fctid
-(define_insn "lrint<mode>di2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
-       (unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
-                  UNSPEC_FCTID))]
-  "TARGET_<MODE>_FPR && TARGET_FPRND"
-  "fctid %0,%1"
+(define_insn "*fselsfsf4"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
+                            (match_operand:SF 4 "zero_fp_constant" "F"))
+                        (match_operand:SF 2 "gpc_reg_operand" "f")
+                        (match_operand:SF 3 "gpc_reg_operand" "f")))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
+  "fsel %0,%1,%2,%3"
   [(set_attr "type" "fp")])
 
-(define_insn "btrunc<mode>2"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
-                    UNSPEC_FRIZ))]
-  "TARGET_<MODE>_FPR && TARGET_FPRND"
-  "@
-   friz %0,%1
-   xsrdpiz %x0,%x1"
-  [(set_attr "type" "fp")
-   (set_attr "fp_type" "fp_addsub_<Fs>")])
-
-(define_insn "ceil<mode>2"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
-                    UNSPEC_FRIP))]
-  "TARGET_<MODE>_FPR && TARGET_FPRND"
-  "@
-   frip %0,%1
-   xsrdpip %x0,%x1"
-  [(set_attr "type" "fp")
-   (set_attr "fp_type" "fp_addsub_<Fs>")])
-
-(define_insn "floor<mode>2"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
-       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
-                    UNSPEC_FRIM))]
-  "TARGET_<MODE>_FPR && TARGET_FPRND"
-  "@
-   frim %0,%1
-   xsrdpim %x0,%x1"
-  [(set_attr "type" "fp")
-   (set_attr "fp_type" "fp_addsub_<Fs>")])
+(define_insn "*fseldfsf4"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "d")
+                            (match_operand:DF 4 "zero_fp_constant" "F"))
+                        (match_operand:SF 2 "gpc_reg_operand" "f")
+                        (match_operand:SF 3 "gpc_reg_operand" "f")))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_SINGLE_FLOAT"
+  "fsel %0,%1,%2,%3"
+  [(set_attr "type" "fp")])
 
-;; No VSX equivalent to frin
-(define_insn "round<mode>2"
-  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
-       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
-                    UNSPEC_FRIN))]
-  "TARGET_<MODE>_FPR && TARGET_FPRND"
-  "frin %0,%1"
-  [(set_attr "type" "fp")
-   (set_attr "fp_type" "fp_addsub_<Fs>")])
+;; The conditional move instructions allow us to perform max and min
+;; operations even when
 
-; An UNSPEC is used so we don't have to support SImode in FP registers.
-(define_insn "stfiwx"
-  [(set (match_operand:SI 0 "memory_operand" "=Z")
-       (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "d")]
-                  UNSPEC_STFIWX))]
-  "TARGET_PPC_GFXOPT"
-  "stfiwx %1,%y0"
-  [(set_attr "type" "fpstore")])
+(define_split
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (match_operator:DF 3 "min_max_operator"
+        [(match_operand:DF 1 "gpc_reg_operand" "")
+         (match_operand:DF 2 "gpc_reg_operand" "")]))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
+   && !flag_trapping_math"
+  [(const_int 0)]
+  "
+{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
+                     operands[1], operands[2]);
+  DONE;
+}")
 
-;; If we don't have a direct conversion to single precision, don't enable this
-;; conversion for 32-bit without fast math, because we don't have the insn to
-;; generate the fixup swizzle to avoid double rounding problems.
-(define_expand "floatsisf2"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "")
-        (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
-  "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
-   && (!TARGET_FPRS
-       || (TARGET_FPRS
-          && ((TARGET_FCFIDS && TARGET_LFIWAX)
-              || (TARGET_DOUBLE_FLOAT && TARGET_FCFID
-                  && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
+(define_expand "movdfcc"
+   [(set (match_operand:DF 0 "gpc_reg_operand" "")
+        (if_then_else:DF (match_operand 1 "comparison_operator" "")
+                         (match_operand:DF 2 "gpc_reg_operand" "")
+                         (match_operand:DF 3 "gpc_reg_operand" "")))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
   "
 {
-  if (!TARGET_FPRS)
-    {
-      if (!REG_P (operands[1]))
-       operands[1] = force_reg (SImode, operands[1]);
-    }
-  else if (TARGET_FCFIDS && TARGET_LFIWAX)
-    {
-      emit_insn (gen_floatsisf2_lfiwax (operands[0], operands[1]));
-      DONE;
-    }
-  else if (TARGET_FCFID && TARGET_LFIWAX)
-    {
-      rtx dfreg = gen_reg_rtx (DFmode);
-      emit_insn (gen_floatsidf2_lfiwax (dfreg, operands[1]));
-      emit_insn (gen_truncdfsf2 (operands[0], dfreg));
-      DONE;
-    }
+  if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+    DONE;
   else
-    {
-      rtx dreg = operands[1];
-      if (!REG_P (dreg))
-       dreg = force_reg (SImode, dreg);
-      dreg = convert_to_mode (DImode, dreg, false);
-      emit_insn (gen_floatdisf2 (operands[0], dreg));
-      DONE;
-    }
+    FAIL;
 }")
 
-(define_expand "floatdidf2"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
-  "")
-
-(define_insn "*floatdidf2_fpr"
+(define_insn "*fseldfdf4"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-       (float:DF (match_operand:DI 1 "gpc_reg_operand" "d")))]
-  "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
-   && !VECTOR_UNIT_VSX_P (DFmode)"
-  "fcfid %0,%1"
+       (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "d")
+                            (match_operand:DF 4 "zero_fp_constant" "F"))
+                        (match_operand:DF 2 "gpc_reg_operand" "d")
+                        (match_operand:DF 3 "gpc_reg_operand" "d")))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+  "fsel %0,%1,%2,%3"
   [(set_attr "type" "fp")])
 
-; Allow the combiner to merge source memory operands to the conversion so that
-; the optimizer/register allocator doesn't try to load the value too early in a
-; GPR and then use store/load to move it to a FPR and suffer from a store-load
-; hit.  We will split after reload to avoid the trip through the GPRs
-
-(define_insn_and_split "*floatdidf2_mem"
+(define_insn "*fselsfdf4"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-       (float:DF (match_operand:DI 1 "memory_operand" "m")))
-   (clobber (match_scratch:DI 2 "=d"))]
-  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS && TARGET_FCFID"
-  "#"
-  "&& reload_completed"
-  [(set (match_dup 2) (match_dup 1))
-   (set (match_dup 0) (float:DF (match_dup 2)))]
-  ""
-  [(set_attr "length" "8")
-   (set_attr "type" "fpload")])
+       (if_then_else:DF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
+                            (match_operand:SF 4 "zero_fp_constant" "F"))
+                        (match_operand:DF 2 "gpc_reg_operand" "d")
+                        (match_operand:DF 3 "gpc_reg_operand" "d")))]
+  "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_SINGLE_FLOAT"
+  "fsel %0,%1,%2,%3"
+  [(set_attr "type" "fp")])
+\f
+;; Conversions to and from floating-point.
 
-(define_expand "floatunsdidf2"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (unsigned_float:DF
-        (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && (TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode))"
-  "")
+; We don't define lfiwax/lfiwzx with the normal definition, because we
+; don't want to support putting SImode in FPR registers.
+(define_insn "lfiwax"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wj,!wj")
+       (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r")]
+                  UNSPEC_LFIWAX))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX"
+  "@
+   lfiwax %0,%y1
+   lxsiwax %x0,%y1
+   mtvsrwa %x0,%1"
+  [(set_attr "type" "fpload,fpload,mffgpr")])
 
-(define_insn "*floatunsdidf2_fcfidu"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-       (unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "d")))]
-  "TARGET_HARD_FLOAT && TARGET_FCFIDU && !VECTOR_UNIT_VSX_P (DFmode)"
-  "fcfidu %0,%1"
-  [(set_attr "type" "fp")
-   (set_attr "length" "4")])
+; This split must be run before register allocation because it allocates the
+; memory slot that is needed to move values to/from the FPR.  We don't allocate
+; it earlier to allow for the combiner to merge insns together where it might
+; not be needed and also in case the insns are deleted as dead code.
 
-(define_insn_and_split "*floatunsdidf2_mem"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-       (unsigned_float:DF (match_operand:DI 1 "memory_operand" "m")))
+(define_insn_and_split "floatsi<mode>2_lfiwax"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
+       (float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
    (clobber (match_scratch:DI 2 "=d"))]
-  "TARGET_HARD_FLOAT && (TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode))"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
+   && <SI_CONVERT_FP> && can_create_pseudo_p ()"
   "#"
-  "&& reload_completed"
-  [(set (match_dup 2) (match_dup 1))
-   (set (match_dup 0) (unsigned_float:DF (match_dup 2)))]
   ""
-  [(set_attr "length" "8")
-   (set_attr "type" "fpload")])
-
-(define_expand "floatdisf2"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "")
-        (float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
-   && (TARGET_FCFIDS || TARGET_POWERPC64 || flag_unsafe_math_optimizations)"
+  [(pc)]
   "
 {
-  if (!TARGET_FCFIDS)
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  rtx tmp;
+
+  if (!MEM_P (src) && TARGET_POWERPC64
+      && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
+    tmp = convert_to_mode (DImode, src, false);
+  else
     {
-      rtx val = operands[1];
-      if (!flag_unsafe_math_optimizations)
+      tmp = operands[2];
+      if (GET_CODE (tmp) == SCRATCH)
+       tmp = gen_reg_rtx (DImode);
+      if (MEM_P (src))
        {
-         rtx label = gen_label_rtx ();
-         val = gen_reg_rtx (DImode);
-         emit_insn (gen_floatdisf2_internal2 (val, operands[1], label));
-         emit_label (label);
+         src = rs6000_address_for_fpconvert (src);
+         emit_insn (gen_lfiwax (tmp, src));
+       }
+      else
+       {
+         rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
+         emit_move_insn (stack, src);
+         emit_insn (gen_lfiwax (tmp, stack));
        }
-      emit_insn (gen_floatdisf2_internal1 (operands[0], val));
-      DONE;
     }
-}")
-
-(define_insn "floatdisf2_fcfids"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-       (float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
-   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
-  "fcfids %0,%1"
-  [(set_attr "type" "fp")])
-
-(define_insn_and_split "*floatdisf2_mem"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-       (float:SF (match_operand:DI 1 "memory_operand" "m")))
-   (clobber (match_scratch:DI 2 "=f"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
-   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
-  "#"
-  "&& reload_completed"
-  [(pc)]
-  "
-{
-  emit_move_insn (operands[2], operands[1]);
-  emit_insn (gen_floatdisf2_fcfids (operands[0], operands[2]));
+  emit_insn (gen_floatdi<mode>2 (dest, tmp));
   DONE;
 }"
-  [(set_attr "length" "8")])
+  [(set_attr "length" "12")
+   (set_attr "type" "fpload")])
 
-;; This is not IEEE compliant if rounding mode is "round to nearest".
-;; If the DI->DF conversion is inexact, then it's possible to suffer
-;; from double rounding.
-;; Instead of creating a new cpu type for two FP operations, just use fp
-(define_insn_and_split "floatdisf2_internal1"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-        (float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))
-   (clobber (match_scratch:DF 2 "=d"))]
-  "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
+(define_insn_and_split "floatsi<mode>2_lfiwax_mem"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,<rreg2>")
+       (float:SFDF
+        (sign_extend:DI
+         (match_operand:SI 1 "indexed_or_indirect_operand" "Z,Z"))))
+   (clobber (match_scratch:DI 2 "=0,d"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
+   && <SI_CONVERT_FP>"
   "#"
-  "&& reload_completed"
-  [(set (match_dup 2)
-        (float:DF (match_dup 1)))
-   (set (match_dup 0)
-        (float_truncate:SF (match_dup 2)))]
   ""
-  [(set_attr "length" "8")
-   (set_attr "type" "fp")])
-
-;; Twiddles bits to avoid double rounding.
-;; Bits that might be truncated when converting to DFmode are replaced
-;; by a bit that won't be lost at that stage, but is below the SFmode
-;; rounding position.
-(define_expand "floatdisf2_internal2"
-  [(set (match_dup 3) (ashiftrt:DI (match_operand:DI 1 "" "")
-                                  (const_int 53)))
-   (parallel [(set (match_operand:DI 0 "" "") (and:DI (match_dup 1)
-                                                     (const_int 2047)))
-             (clobber (scratch:CC))])
-   (set (match_dup 3) (plus:DI (match_dup 3)
-                              (const_int 1)))
-   (set (match_dup 0) (plus:DI (match_dup 0)
-                              (const_int 2047)))
-   (set (match_dup 4) (compare:CCUNS (match_dup 3)
-                                    (const_int 2)))
-   (set (match_dup 0) (ior:DI (match_dup 0)
-                             (match_dup 1)))
-   (parallel [(set (match_dup 0) (and:DI (match_dup 0)
-                                        (const_int -2048)))
-             (clobber (scratch:CC))])
-   (set (pc) (if_then_else (geu (match_dup 4) (const_int 0))
-                          (label_ref (match_operand:DI 2 "" ""))
-                          (pc)))
-   (set (match_dup 0) (match_dup 1))]
-  "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
-  "
-{
-  operands[3] = gen_reg_rtx (DImode);
-  operands[4] = gen_reg_rtx (CCUNSmode);
-}")
-
-(define_expand "floatunsdisf2"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "")
-        (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
-   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
-  "")
-
-(define_insn "floatunsdisf2_fcfidus"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-        (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
-   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
-  "fcfidus %0,%1"
-  [(set_attr "type" "fp")])
-
-(define_insn_and_split "*floatunsdisf2_mem"
-  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-       (unsigned_float:SF (match_operand:DI 1 "memory_operand" "m")))
-   (clobber (match_scratch:DI 2 "=f"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
-   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
-  "#"
-  "&& reload_completed"
   [(pc)]
   "
 {
-  emit_move_insn (operands[2], operands[1]);
-  emit_insn (gen_floatunsdisf2_fcfidus (operands[0], operands[2]));
+  operands[1] = rs6000_address_for_fpconvert (operands[1]);
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (DImode);
+  emit_insn (gen_lfiwax (operands[2], operands[1]));
+  emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
   DONE;
 }"
   [(set_attr "length" "8")
    (set_attr "type" "fpload")])
-\f
-;; Define the DImode operations that can be done in a small number
-;; of instructions.  The & constraints are to prevent the register
-;; allocator from allocating registers that overlap with the inputs
-;; (for example, having an input in 7,8 and an output in 6,7).  We
-;; also allow for the output being the same as one of the inputs.
 
-(define_insn "*adddi3_noppc64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r")
-       (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,0,0")
-                (match_operand:DI 2 "reg_or_short_operand" "r,I,r,I")))]
-  "! TARGET_POWERPC64"
-  "*
-{
-  if (WORDS_BIG_ENDIAN)
-    return (GET_CODE (operands[2])) != CONST_INT
-           ? \"addc %L0,%L1,%L2\;adde %0,%1,%2\"
-           : \"addic %L0,%L1,%2\;add%G2e %0,%1\";
-  else
-    return (GET_CODE (operands[2])) != CONST_INT
-           ? \"addc %0,%1,%2\;adde %L0,%L1,%L2\"
-           : \"addic %0,%1,%2\;add%G2e %L0,%L1\";
-}"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
+(define_insn "lfiwzx"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wj,!wj")
+       (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r")]
+                  UNSPEC_LFIWZX))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX"
+  "@
+   lfiwzx %0,%y1
+   lxsiwzx %x0,%y1
+   mtvsrwz %x0,%1"
+  [(set_attr "type" "fpload,fpload,mftgpr")])
 
-(define_insn "*subdi3_noppc64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r,r")
-       (minus:DI (match_operand:DI 1 "reg_or_short_operand" "r,I,0,r,I")
-                 (match_operand:DI 2 "gpc_reg_operand" "r,r,r,0,0")))]
-  "! TARGET_POWERPC64"
-  "*
+(define_insn_and_split "floatunssi<mode>2_lfiwzx"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
+       (unsigned_float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
+   (clobber (match_scratch:DI 2 "=d"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
+   && <SI_CONVERT_FP>"
+  "#"
+  ""
+  [(pc)]
+  "
 {
-  if (WORDS_BIG_ENDIAN)
-    return (GET_CODE (operands[1]) != CONST_INT)
-           ? \"subfc %L0,%L2,%L1\;subfe %0,%2,%1\"
-           : \"subfic %L0,%L2,%1\;subf%G1e %0,%2\";
-  else
-    return (GET_CODE (operands[1]) != CONST_INT)
-           ? \"subfc %0,%2,%1\;subfe %L0,%L2,%L1\"
-           : \"subfic %0,%2,%1\;subf%G1e %L0,%L2\";
-}"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  rtx tmp;
 
-(define_insn "*negdi2_noppc64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
-       (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))]
-  "! TARGET_POWERPC64"
-  "*
-{
-  return (WORDS_BIG_ENDIAN)
-    ? \"subfic %L0,%L1,0\;subfze %0,%1\"
-    : \"subfic %0,%1,0\;subfze %L0,%L1\";
+  if (!MEM_P (src) && TARGET_POWERPC64
+      && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
+    tmp = convert_to_mode (DImode, src, true);
+  else
+    {
+      tmp = operands[2];
+      if (GET_CODE (tmp) == SCRATCH)
+       tmp = gen_reg_rtx (DImode);
+      if (MEM_P (src))
+       {
+         src = rs6000_address_for_fpconvert (src);
+         emit_insn (gen_lfiwzx (tmp, src));
+       }
+      else
+       {
+         rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
+         emit_move_insn (stack, src);
+         emit_insn (gen_lfiwzx (tmp, stack));
+       }
+    }
+  emit_insn (gen_floatdi<mode>2 (dest, tmp));
+  DONE;
 }"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
-
-(define_insn "mulsidi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
-       (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r"))
-                (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
-  "! TARGET_POWERPC64"
-{
-  return (WORDS_BIG_ENDIAN)
-    ? \"mulhw %0,%1,%2\;mullw %L0,%1,%2\"
-    : \"mulhw %L0,%1,%2\;mullw %0,%1,%2\";
-}
-  [(set_attr "type" "imul")
-   (set_attr "length" "8")])
+  [(set_attr "length" "12")
+   (set_attr "type" "fpload")])
 
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
-                (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" ""))))]
-  "! TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (truncate:SI
-        (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
-                              (sign_extend:DI (match_dup 2)))
-                     (const_int 32))))
-   (set (match_dup 4)
-       (mult:SI (match_dup 1)
-                (match_dup 2)))]
+(define_insn_and_split "floatunssi<mode>2_lfiwzx_mem"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,<rreg2>")
+       (unsigned_float:SFDF
+        (zero_extend:DI
+         (match_operand:SI 1 "indexed_or_indirect_operand" "Z,Z"))))
+   (clobber (match_scratch:DI 2 "=0,d"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
+   && <SI_CONVERT_FP>"
+  "#"
+  ""
+  [(pc)]
   "
 {
-  int endian = (WORDS_BIG_ENDIAN == 0);
-  operands[3] = operand_subword (operands[0], endian, 0, DImode);
-  operands[4] = operand_subword (operands[0], 1 - endian, 0, DImode);
-}")
-
-(define_insn "umulsidi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
-       (mult:DI (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r"))
-                (zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
-  "! TARGET_POWERPC64"
-  "*
-{
-  return (WORDS_BIG_ENDIAN)
-    ? \"mulhwu %0,%1,%2\;mullw %L0,%1,%2\"
-    : \"mulhwu %L0,%1,%2\;mullw %0,%1,%2\";
+  operands[1] = rs6000_address_for_fpconvert (operands[1]);
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (DImode);
+  emit_insn (gen_lfiwzx (operands[2], operands[1]));
+  emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
+  DONE;
 }"
-  [(set_attr "type" "imul")
-   (set_attr "length" "8")])
+  [(set_attr "length" "8")
+   (set_attr "type" "fpload")])
 
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (mult:DI (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
-                (zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" ""))))]
-  "! TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (truncate:SI
-        (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
-                              (zero_extend:DI (match_dup 2)))
-                     (const_int 32))))
-   (set (match_dup 4)
-       (mult:SI (match_dup 1)
-                (match_dup 2)))]
+; For each of these conversions, there is a define_expand, a define_insn
+; with a '#' template, and a define_split (with C code).  The idea is
+; to allow constant folding with the template of the define_insn,
+; then to have the insns split later (between sched1 and final).
+
+(define_expand "floatsidf2"
+  [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
+                  (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
+             (use (match_dup 2))
+             (use (match_dup 3))
+             (clobber (match_dup 4))
+             (clobber (match_dup 5))
+             (clobber (match_dup 6))])]
+  "TARGET_HARD_FLOAT 
+   && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
   "
 {
-  int endian = (WORDS_BIG_ENDIAN == 0);
-  operands[3] = operand_subword (operands[0], endian, 0, DImode);
-  operands[4] = operand_subword (operands[0], 1 - endian, 0, DImode);
-}")
+  if (TARGET_E500_DOUBLE)
+    {
+      if (!REG_P (operands[1]))
+       operands[1] = force_reg (SImode, operands[1]);
+      emit_insn (gen_spe_floatsidf2 (operands[0], operands[1]));
+      DONE;
+    }
+  else if (TARGET_LFIWAX && TARGET_FCFID)
+    {
+      emit_insn (gen_floatsidf2_lfiwax (operands[0], operands[1]));
+      DONE;
+    }
+  else if (TARGET_FCFID)
+    {
+      rtx dreg = operands[1];
+      if (!REG_P (dreg))
+       dreg = force_reg (SImode, dreg);
+      dreg = convert_to_mode (DImode, dreg, false);
+      emit_insn (gen_floatdidf2 (operands[0], dreg));
+      DONE;
+    }
 
-(define_insn "smulsi3_highpart"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (truncate:SI
-        (lshiftrt:DI (mult:DI (sign_extend:DI
-                               (match_operand:SI 1 "gpc_reg_operand" "%r"))
-                              (sign_extend:DI
-                               (match_operand:SI 2 "gpc_reg_operand" "r")))
-                     (const_int 32))))]
-  ""
-  "mulhw %0,%1,%2"
-  [(set_attr "type" "imul")])
+  if (!REG_P (operands[1]))
+    operands[1] = force_reg (SImode, operands[1]);
+  operands[2] = force_reg (SImode, GEN_INT (0x43300000));
+  operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503601774854144\", DFmode));
+  operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
+  operands[5] = gen_reg_rtx (DFmode);
+  operands[6] = gen_reg_rtx (SImode);
+}")
 
-(define_insn "umulsi3_highpart"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (truncate:SI
-        (lshiftrt:DI (mult:DI (zero_extend:DI
-                               (match_operand:SI 1 "gpc_reg_operand" "%r"))
-                              (zero_extend:DI
-                               (match_operand:SI 2 "gpc_reg_operand" "r")))
-                     (const_int 32))))]
+(define_insn_and_split "*floatsidf2_internal"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=&d")
+       (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" "d"))
+   (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
+   (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))
+   (clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
+  "! TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+  "#"
   ""
-  "mulhwu %0,%1,%2"
-  [(set_attr "type" "imul")])
-
-;; Shift by a variable amount is too complex to be worth open-coding.  We
-;; just handle shifts by constants.
-(define_insn "ashrdi3_no_power"
-  [(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 "const_int_operand" "M,i")))]
-  "!TARGET_POWERPC64"
-  "*
+  [(pc)]
+  "
 {
-  switch (which_alternative)
+  rtx lowword, highword;
+  gcc_assert (MEM_P (operands[4]));
+  highword = adjust_address (operands[4], SImode, 0);
+  lowword = adjust_address (operands[4], SImode, 4);
+  if (! WORDS_BIG_ENDIAN)
     {
-    default:
-      gcc_unreachable ();
-    case 0:
-      if (WORDS_BIG_ENDIAN)
-        return \"srawi %0,%1,31\;srawi %L0,%1,%h2\";
-      else
-        return \"srawi %L0,%L1,31\;srawi %0,%L1,%h2\";
-    case 1:
-      if (WORDS_BIG_ENDIAN)
-       return \"srwi %L0,%L1,%h2\;insrwi %L0,%1,%h2,0\;srawi %0,%1,%h2\";
-      else
-       return \"srwi %0,%1,%h2\;insrwi %0,%L1,%h2,0\;srawi %L0,%L1,%h2\";
+      rtx tmp;
+      tmp = highword; highword = lowword; lowword = tmp;
     }
+
+  emit_insn (gen_xorsi3 (operands[6], operands[1],
+                        GEN_INT (~ (HOST_WIDE_INT) 0x7fffffff)));
+  emit_move_insn (lowword, operands[6]);
+  emit_move_insn (highword, operands[2]);
+  emit_move_insn (operands[5], operands[4]);
+  emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
+  DONE;
 }"
-  [(set_attr "type" "two,three")
-   (set_attr "length" "8,12")])
+  [(set_attr "length" "24")
+   (set_attr "type" "fp")])
 
-(define_insn "*ashrdisi3_noppc64be"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (subreg:SI (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-                                (const_int 32)) 4))]
-  "TARGET_32BIT && !TARGET_POWERPC64 && WORDS_BIG_ENDIAN"
-  "*
+;; If we don't have a direct conversion to single precision, don't enable this
+;; conversion for 32-bit without fast math, because we don't have the insn to
+;; generate the fixup swizzle to avoid double rounding problems.
+(define_expand "floatunssisf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+        (unsigned_float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
+  "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
+   && (!TARGET_FPRS
+       || (TARGET_FPRS
+          && ((TARGET_FCFIDUS && TARGET_LFIWZX)
+              || (TARGET_DOUBLE_FLOAT && TARGET_FCFID
+                  && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
+  "
 {
-  if (REGNO (operands[0]) == REGNO (operands[1]))
-    return \"\";
+  if (!TARGET_FPRS)
+    {
+      if (!REG_P (operands[1]))
+       operands[1] = force_reg (SImode, operands[1]);
+    }
+  else if (TARGET_LFIWZX && TARGET_FCFIDUS)
+    {
+      emit_insn (gen_floatunssisf2_lfiwzx (operands[0], operands[1]));
+      DONE;
+    }
   else
-    return \"mr %0,%1\";
-}"
-   [(set_attr "length" "4")])
-
-\f
-;; PowerPC64 DImode operations.
-
-(define_insn "muldi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-        (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
-                 (match_operand:DI 2 "reg_or_short_operand" "r,I")))]
-  "TARGET_POWERPC64"
-  "@
-   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")
-       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
-                            (match_operand:DI 2 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
-  "TARGET_POWERPC64"
-  "@
-   mulld. %3,%1,%2
-   #"
-  [(set_attr "type" "lmul_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                            (match_operand:DI 2 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (mult:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*muldi3_internal2"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
-                            (match_operand:DI 2 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (mult:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64"
-  "@
-   mulld. %0,%1,%2
-   #"
-  [(set_attr "type" "lmul_compare")
-   (set_attr "length" "4,8")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (mult:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                            (match_operand:DI 2 "gpc_reg_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (mult:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (mult:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+    {
+      rtx dreg = operands[1];
+      if (!REG_P (dreg))
+       dreg = force_reg (SImode, dreg);
+      dreg = convert_to_mode (DImode, dreg, true);
+      emit_insn (gen_floatdisf2 (operands[0], dreg));
+      DONE;
+    }
+}")
 
-(define_insn "smuldi3_highpart"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (truncate:DI
-        (lshiftrt:TI (mult:TI (sign_extend:TI
-                               (match_operand:DI 1 "gpc_reg_operand" "%r"))
-                              (sign_extend:TI
-                               (match_operand:DI 2 "gpc_reg_operand" "r")))
-                     (const_int 64))))]
-  "TARGET_POWERPC64"
-  "mulhd %0,%1,%2"
-  [(set_attr "type" "lmul")])
+(define_expand "floatunssidf2"
+  [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
+                  (unsigned_float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
+             (use (match_dup 2))
+             (use (match_dup 3))
+             (clobber (match_dup 4))
+             (clobber (match_dup 5))])]
+  "TARGET_HARD_FLOAT
+   && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
+  "
+{
+  if (TARGET_E500_DOUBLE)
+    {
+      if (!REG_P (operands[1]))
+       operands[1] = force_reg (SImode, operands[1]);
+      emit_insn (gen_spe_floatunssidf2 (operands[0], operands[1]));
+      DONE;
+    }
+  else if (TARGET_LFIWZX && TARGET_FCFID)
+    {
+      emit_insn (gen_floatunssidf2_lfiwzx (operands[0], operands[1]));
+      DONE;
+    }
+  else if (TARGET_FCFID)
+    {
+      rtx dreg = operands[1];
+      if (!REG_P (dreg))
+       dreg = force_reg (SImode, dreg);
+      dreg = convert_to_mode (DImode, dreg, true);
+      emit_insn (gen_floatdidf2 (operands[0], dreg));
+      DONE;
+    }
 
-(define_insn "umuldi3_highpart"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (truncate:DI
-        (lshiftrt:TI (mult:TI (zero_extend:TI
-                               (match_operand:DI 1 "gpc_reg_operand" "%r"))
-                              (zero_extend:TI
-                               (match_operand:DI 2 "gpc_reg_operand" "r")))
-                     (const_int 64))))]
-  "TARGET_POWERPC64"
-  "mulhdu %0,%1,%2"
-  [(set_attr "type" "lmul")])
+  if (!REG_P (operands[1]))
+    operands[1] = force_reg (SImode, operands[1]);
+  operands[2] = force_reg (SImode, GEN_INT (0x43300000));
+  operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503599627370496\", DFmode));
+  operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
+  operands[5] = gen_reg_rtx (DFmode);
+}")
 
-(define_expand "mulditi3"
-  [(set (match_operand:TI 0 "gpc_reg_operand")
-       (mult:TI (sign_extend:TI (match_operand:DI 1 "gpc_reg_operand"))
-                (sign_extend:TI (match_operand:DI 2 "gpc_reg_operand"))))]
-  "TARGET_POWERPC64"
+(define_insn_and_split "*floatunssidf2_internal"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=&d")
+       (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" "d"))
+   (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
+   (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))]
+  "! TARGET_FCFIDU && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && !(TARGET_FCFID && TARGET_POWERPC64)"
+  "#"
+  ""
+  [(pc)]
+  "
 {
-  rtx l = gen_reg_rtx (DImode), h = gen_reg_rtx (DImode);
-  emit_insn (gen_muldi3 (l, operands[1], operands[2]));
-  emit_insn (gen_smuldi3_highpart (h, operands[1], operands[2]));
-  emit_move_insn (gen_lowpart (DImode, operands[0]), l);
-  emit_move_insn (gen_highpart (DImode, operands[0]), h);
+  rtx lowword, highword;
+  gcc_assert (MEM_P (operands[4]));
+  highword = adjust_address (operands[4], SImode, 0);
+  lowword = adjust_address (operands[4], SImode, 4);
+  if (! WORDS_BIG_ENDIAN)
+    {
+      rtx tmp;
+      tmp = highword; highword = lowword; lowword = tmp;
+    }
+
+  emit_move_insn (lowword, operands[1]);
+  emit_move_insn (highword, operands[2]);
+  emit_move_insn (operands[5], operands[4]);
+  emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
   DONE;
-})
+}"
+  [(set_attr "length" "20")
+   (set_attr "type" "fp")])
 
-(define_expand "umulditi3"
-  [(set (match_operand:TI 0 "gpc_reg_operand")
-       (mult:TI (zero_extend:TI (match_operand:DI 1 "gpc_reg_operand"))
-                (zero_extend:TI (match_operand:DI 2 "gpc_reg_operand"))))]
-  "TARGET_POWERPC64"
+(define_expand "fix_trunc<mode>si2"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "")
+       (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && ((TARGET_FPRS && <TARGET_FLOAT>) || <E500_CONVERT>)"
+  "
 {
-  rtx l = gen_reg_rtx (DImode), h = gen_reg_rtx (DImode);
-  emit_insn (gen_muldi3 (l, operands[1], operands[2]));
-  emit_insn (gen_umuldi3_highpart (h, operands[1], operands[2]));
-  emit_move_insn (gen_lowpart (DImode, operands[0]), l);
-  emit_move_insn (gen_highpart (DImode, operands[0]), h);
-  DONE;
-})
+  if (!<E500_CONVERT>)
+    {
+      rtx tmp, stack;
 
-(define_insn "rotldi3"
-  [(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"
-  "@
-   rldcl %0,%1,%2,0
-   rldicl %0,%1,%H2,0"
-  [(set_attr "type" "var_shift_rotate,integer")])
+      if (TARGET_STFIWX)
+       emit_insn (gen_fix_trunc<mode>si2_stfiwx (operands[0], operands[1]));
+      else
+       {
+         tmp = gen_reg_rtx (DImode);
+         stack = rs6000_allocate_stack_temp (DImode, true, false);
+         emit_insn (gen_fix_trunc<mode>si2_internal (operands[0], operands[1],
+                                                     tmp, stack));
+       }
+      DONE;
+    }
+}")
 
-(define_insn "*rotldi3_internal2"
-  [(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,r,r"))]
-  "TARGET_64BIT"
-  "@
-   rldcl. %3,%1,%2,0
-   rldicl. %3,%1,%H2,0
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+; Like the convert to float patterns, this insn must be split before
+; register allocation so that it can allocate the memory slot if it
+; needed
+(define_insn_and_split "fix_trunc<mode>si2_stfiwx"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+       (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
+   (clobber (match_scratch:DI 2 "=d"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
+   && TARGET_STFIWX && can_create_pseudo_p ()"
+  "#"
+  ""
+  [(pc)]
+{
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  rtx tmp = operands[2];
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                              (match_operand:DI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (rotate:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
+  if (GET_CODE (tmp) == SCRATCH)
+    tmp = gen_reg_rtx (DImode);
 
-(define_insn "*rotldi3_internal3"
-  [(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,r,r")
-       (rotate:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   rldcl. %0,%1,%2,0
-   rldicl. %0,%1,%H2,0
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  emit_insn (gen_fctiwz_<mode> (tmp, src));
+  if (MEM_P (dest))
+    {
+      dest = rs6000_address_for_fpconvert (dest);
+      emit_insn (gen_stfiwx (dest, tmp));
+      DONE;
+    }
+  else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
+    {
+      dest = gen_lowpart (DImode, dest);
+      emit_move_insn (dest, tmp);
+      DONE;
+    }
+  else
+    {
+      rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
+      emit_insn (gen_stfiwx (stack, tmp));
+      emit_move_insn (dest, stack);
+      DONE;
+    }
+}
+  [(set_attr "length" "12")
+   (set_attr "type" "fp")])
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                              (match_operand:DI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (rotate:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (rotate:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
+(define_insn_and_split "fix_trunc<mode>si2_internal"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,?r")
+       (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d,<rreg>")))
+   (clobber (match_operand:DI 2 "gpc_reg_operand" "=1,d"))
+   (clobber (match_operand:DI 3 "offsettable_mem_operand" "=o,o"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+  "#"
+  ""
+  [(pc)]
+  "
+{
+  rtx lowword;
+  gcc_assert (MEM_P (operands[3]));
+  lowword = adjust_address (operands[3], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
+
+  emit_insn (gen_fctiwz_<mode> (operands[2], operands[1]));
+  emit_move_insn (operands[3], operands[2]);
+  emit_move_insn (operands[0], lowword);
+  DONE;
+}"
+  [(set_attr "length" "16")
+   (set_attr "type" "fp")])
+
+(define_expand "fix_trunc<mode>di2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+   && TARGET_FCFID"
   "")
 
-(define_insn "*rotldi3_internal4"
-  [(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"
-  "@
-   rldc%B3 %0,%1,%2,%S3
-   rldic%B3 %0,%1,%H2,%S3"
-  [(set_attr "type" "var_shift_rotate,integer")])
+(define_insn "*fix_trunc<mode>di2_fctidz"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+       (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))]
+  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+    && TARGET_FCFID && !VECTOR_UNIT_VSX_P (<MODE>mode)"
+  "fctidz %0,%1"
+  [(set_attr "type" "fp")])
 
-(define_insn "*rotldi3_internal5"
-  [(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,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,r,r"))]
-  "TARGET_64BIT"
-  "@
-   rldc%B3. %4,%1,%2,%S3
-   rldic%B3. %4,%1,%H2,%S3
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+(define_expand "fixuns_trunc<mode>si2"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "")
+       (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT
+   && ((TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ && TARGET_STFIWX)
+       || <E500_CONVERT>)"
+  "
+{
+  if (!<E500_CONVERT>)
+    {
+      emit_insn (gen_fixuns_trunc<mode>si2_stfiwx (operands[0], operands[1]));
+      DONE;
+    }
+}")
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_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 "mask64_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 4 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 4)
-       (and:DI (rotate:DI (match_dup 1)
-                               (match_dup 2))
-                    (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
-  "")
+(define_insn_and_split "fixuns_trunc<mode>si2_stfiwx"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+       (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
+   (clobber (match_scratch:DI 2 "=d"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
+   && TARGET_STFIWX && can_create_pseudo_p ()"
+  "#"
+  ""
+  [(pc)]
+{
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  rtx tmp = operands[2];
 
-(define_insn "*rotldi3_internal6"
-  [(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,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,r,r")
-       (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_64BIT"
-  "@
-   rldc%B3. %0,%1,%2,%S3
-   rldic%B3. %0,%1,%H2,%S3
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  if (GET_CODE (tmp) == SCRATCH)
+    tmp = gen_reg_rtx (DImode);
+
+  emit_insn (gen_fctiwuz_<mode> (tmp, src));
+  if (MEM_P (dest))
+    {
+      dest = rs6000_address_for_fpconvert (dest);
+      emit_insn (gen_stfiwx (dest, tmp));
+      DONE;
+    }
+  else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
+    {
+      dest = gen_lowpart (DImode, dest);
+      emit_move_insn (dest, tmp);
+      DONE;
+    }
+  else
+    {
+      rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
+      emit_insn (gen_stfiwx (stack, tmp));
+      emit_move_insn (dest, stack);
+      DONE;
+    }
+}
+  [(set_attr "length" "12")
+   (set_attr "type" "fp")])
 
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_micro_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 "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)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
+(define_expand "fixuns_trunc<mode>di2"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (unsigned_fix:DI (match_operand:SFDF 1 "register_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FCTIDUZ || VECTOR_UNIT_VSX_P (<MODE>mode))"
   "")
 
-(define_insn "*rotldi3_internal7le"
-  [(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,r")
-                    (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 0)))]
-  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN"
-  "@
-   rldcl %0,%1,%2,56
-   rldicl %0,%1,%H2,56"
-  [(set_attr "type" "var_shift_rotate,integer")])
+(define_insn "*fixuns_trunc<mode>di2_fctiduz"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+       (unsigned_fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))]
+  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+    && TARGET_FCTIDUZ && !VECTOR_UNIT_VSX_P (<MODE>mode)"
+  "fctiduz %0,%1"
+  [(set_attr "type" "fp")])
 
-(define_insn "*rotldi3_internal7be"
-  [(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,r")
-                    (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 7)))]
-  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN"
-  "@
-   rldcl %0,%1,%2,56
-   rldicl %0,%1,%H2,56"
-  [(set_attr "type" "var_shift_rotate,integer")])
+; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
+; rather than (set (subreg:SI (reg)) (fix:SI ...))
+; because the first makes it clear that operand 0 is not live
+; before the instruction.
+(define_insn "fctiwz_<mode>"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+       (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))]
+                  UNSPEC_FCTIWZ))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+  "fctiwz %0,%1"
+  [(set_attr "type" "fp")])
 
-(define_insn "*rotldi3_internal8le"
-  [(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,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,r,r"))]
-  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %3,%1,%2,56
-   rldicl. %3,%1,%H2,56
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+(define_insn "fctiwuz_<mode>"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+       (unspec:DI [(unsigned_fix:SI
+                    (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>"))]
+                  UNSPEC_FCTIWUZ))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ"
+  "fctiwuz %0,%1"
+  [(set_attr "type" "fp")])
 
-(define_insn "*rotldi3_internal8be"
-  [(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,r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 7))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
-  "TARGET_64BIT && BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %3,%1,%2,56
-   rldicl. %3,%1,%H2,56
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
+;; since the friz instruction does not truncate the value if the floating
+;; point value is < LONG_MIN or > LONG_MAX.
+(define_insn "*friz"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+       (float:DF (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d"))))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_FPRND
+   && !VECTOR_UNIT_VSX_P (DFmode) && flag_unsafe_math_optimizations
+   && !flag_trapping_math && TARGET_FRIZ"
+  "friz %0,%1"
+  [(set_attr "type" "fp")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:QI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 3)
-       (zero_extend:DI (subreg:QI
-                     (rotate:DI (match_dup 1)
-                                (match_dup 2)) 0)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
+;; Since FCTIWZ doesn't sign extend the upper bits, we have to do a store and a
+;; load to properly sign extend the value, but at least doing a store, load
+;; into a GPR to sign extend, a store from the GPR and a load back into the FPR
+;; if we have 32-bit memory ops
+(define_insn_and_split "*round32<mode>2_fprs"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
+       (float:SFDF
+        (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))))
+   (clobber (match_scratch:DI 2 "=d"))
+   (clobber (match_scratch:DI 3 "=d"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && <SI_CONVERT_FP> && TARGET_LFIWAX && TARGET_STFIWX && TARGET_FCFID
+   && can_create_pseudo_p ()"
+  "#"
+  ""
+  [(pc)]
+{
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  rtx tmp1 = operands[2];
+  rtx tmp2 = operands[3];
+  rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:QI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 7))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 3)
-       (zero_extend:DI (subreg:QI
-                     (rotate:DI (match_dup 1)
-                                (match_dup 2)) 7)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
+  if (GET_CODE (tmp1) == SCRATCH)
+    tmp1 = gen_reg_rtx (DImode);
+  if (GET_CODE (tmp2) == SCRATCH)
+    tmp2 = gen_reg_rtx (DImode);
 
-(define_insn "*rotldi3_internal9le"
-  [(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,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,r,r")
-       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
-  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %0,%1,%2,56
-   rldicl. %0,%1,%H2,56
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  emit_insn (gen_fctiwz_<mode> (tmp1, src));
+  emit_insn (gen_stfiwx (stack, tmp1));
+  emit_insn (gen_lfiwax (tmp2, stack));
+  emit_insn (gen_floatdi<mode>2 (dest, tmp2));
+  DONE;
+}
+  [(set_attr "type" "fpload")
+   (set_attr "length" "16")])
 
-(define_insn "*rotldi3_internal9be"
-  [(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,r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 7))
-                   (const_int 0)))
-   (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)) 7)))]
-  "TARGET_64BIT && BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %0,%1,%2,56
-   rldicl. %0,%1,%H2,56
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+(define_insn_and_split "*roundu32<mode>2_fprs"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
+       (unsigned_float:SFDF
+        (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))))
+   (clobber (match_scratch:DI 2 "=d"))
+   (clobber (match_scratch:DI 3 "=d"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && TARGET_LFIWZX && TARGET_STFIWX && TARGET_FCFIDU
+   && can_create_pseudo_p ()"
+  "#"
+  ""
+  [(pc)]
+{
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  rtx tmp1 = operands[2];
+  rtx tmp2 = operands[3];
+  rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:QI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
-  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+  if (GET_CODE (tmp1) == SCRATCH)
+    tmp1 = gen_reg_rtx (DImode);
+  if (GET_CODE (tmp2) == SCRATCH)
+    tmp2 = gen_reg_rtx (DImode);
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:QI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 7))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 7)))]
-  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 7)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+  emit_insn (gen_fctiwuz_<mode> (tmp1, src));
+  emit_insn (gen_stfiwx (stack, tmp1));
+  emit_insn (gen_lfiwzx (tmp2, stack));
+  emit_insn (gen_floatdi<mode>2 (dest, tmp2));
+  DONE;
+}
+  [(set_attr "type" "fpload")
+   (set_attr "length" "16")])
 
-(define_insn "*rotldi3_internal10le"
-  [(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,r")
-                    (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 0)))]
-  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN"
-  "@
-   rldcl %0,%1,%2,48
-   rldicl %0,%1,%H2,48"
-  [(set_attr "type" "var_shift_rotate,integer")])
+;; No VSX equivalent to fctid
+(define_insn "lrint<mode>di2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+       (unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+                  UNSPEC_FCTID))]
+  "TARGET_<MODE>_FPR && TARGET_FPRND"
+  "fctid %0,%1"
+  [(set_attr "type" "fp")])
 
-(define_insn "*rotldi3_internal10be"
-  [(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,r")
-                    (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 6)))]
-  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN"
+(define_insn "btrunc<mode>2"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+                    UNSPEC_FRIZ))]
+  "TARGET_<MODE>_FPR && TARGET_FPRND"
   "@
-   rldcl %0,%1,%2,48
-   rldicl %0,%1,%H2,48"
-  [(set_attr "type" "var_shift_rotate,integer")])
+   friz %0,%1
+   xsrdpiz %x0,%x1"
+  [(set_attr "type" "fp")
+   (set_attr "fp_type" "fp_addsub_<Fs>")])
 
-(define_insn "*rotldi3_internal11le"
-  [(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,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,r,r"))]
-  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
+(define_insn "ceil<mode>2"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+                    UNSPEC_FRIP))]
+  "TARGET_<MODE>_FPR && TARGET_FPRND"
   "@
-   rldcl. %3,%1,%2,48
-   rldicl. %3,%1,%H2,48
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+   frip %0,%1
+   xsrdpip %x0,%x1"
+  [(set_attr "type" "fp")
+   (set_attr "fp_type" "fp_addsub_<Fs>")])
 
-(define_insn "*rotldi3_internal11be"
-  [(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,r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 6))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
-  "TARGET_64BIT && BYTES_BIG_ENDIAN"
+(define_insn "floor<mode>2"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+                    UNSPEC_FRIM))]
+  "TARGET_<MODE>_FPR && TARGET_FPRND"
   "@
-   rldcl. %3,%1,%2,48
-   rldicl. %3,%1,%H2,48
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+   frim %0,%1
+   xsrdpim %x0,%x1"
+  [(set_attr "type" "fp")
+   (set_attr "fp_type" "fp_addsub_<Fs>")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:HI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 3)
-       (zero_extend:DI (subreg:HI
-                     (rotate:DI (match_dup 1)
-                                (match_dup 2)) 0)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
+;; No VSX equivalent to frin
+(define_insn "round<mode>2"
+  [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+       (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+                    UNSPEC_FRIN))]
+  "TARGET_<MODE>_FPR && TARGET_FPRND"
+  "frin %0,%1"
+  [(set_attr "type" "fp")
+   (set_attr "fp_type" "fp_addsub_<Fs>")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:HI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 6))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 3)
-       (zero_extend:DI (subreg:HI
-                     (rotate:DI (match_dup 1)
-                                (match_dup 2)) 6)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
+; An UNSPEC is used so we don't have to support SImode in FP registers.
+(define_insn "stfiwx"
+  [(set (match_operand:SI 0 "memory_operand" "=Z")
+       (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "d")]
+                  UNSPEC_STFIWX))]
+  "TARGET_PPC_GFXOPT"
+  "stfiwx %1,%y0"
+  [(set_attr "type" "fpstore")])
+
+;; If we don't have a direct conversion to single precision, don't enable this
+;; conversion for 32-bit without fast math, because we don't have the insn to
+;; generate the fixup swizzle to avoid double rounding problems.
+(define_expand "floatsisf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+        (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
+  "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
+   && (!TARGET_FPRS
+       || (TARGET_FPRS
+          && ((TARGET_FCFIDS && TARGET_LFIWAX)
+              || (TARGET_DOUBLE_FLOAT && TARGET_FCFID
+                  && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
+  "
+{
+  if (!TARGET_FPRS)
+    {
+      if (!REG_P (operands[1]))
+       operands[1] = force_reg (SImode, operands[1]);
+    }
+  else if (TARGET_FCFIDS && TARGET_LFIWAX)
+    {
+      emit_insn (gen_floatsisf2_lfiwax (operands[0], operands[1]));
+      DONE;
+    }
+  else if (TARGET_FCFID && TARGET_LFIWAX)
+    {
+      rtx dfreg = gen_reg_rtx (DFmode);
+      emit_insn (gen_floatsidf2_lfiwax (dfreg, operands[1]));
+      emit_insn (gen_truncdfsf2 (operands[0], dfreg));
+      DONE;
+    }
+  else
+    {
+      rtx dreg = operands[1];
+      if (!REG_P (dreg))
+       dreg = force_reg (SImode, dreg);
+      dreg = convert_to_mode (DImode, dreg, false);
+      emit_insn (gen_floatdisf2 (operands[0], dreg));
+      DONE;
+    }
+}")
+
+(define_expand "floatdidf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
+  "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
   "")
 
-(define_insn "*rotldi3_internal12le"
-  [(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,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,r,r")
-       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
-  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %0,%1,%2,48
-   rldicl. %0,%1,%H2,48
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+(define_insn "*floatdidf2_fpr"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+       (float:DF (match_operand:DI 1 "gpc_reg_operand" "d")))]
+  "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+   && !VECTOR_UNIT_VSX_P (DFmode)"
+  "fcfid %0,%1"
+  [(set_attr "type" "fp")])
 
-(define_insn "*rotldi3_internal12be"
-  [(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,r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 6))
-                   (const_int 0)))
-   (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)) 6)))]
-  "TARGET_64BIT && BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %0,%1,%2,48
-   rldicl. %0,%1,%H2,48
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+; Allow the combiner to merge source memory operands to the conversion so that
+; the optimizer/register allocator doesn't try to load the value too early in a
+; GPR and then use store/load to move it to a FPR and suffer from a store-load
+; hit.  We will split after reload to avoid the trip through the GPRs
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:HI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
-  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+(define_insn_and_split "*floatdidf2_mem"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+       (float:DF (match_operand:DI 1 "memory_operand" "m")))
+   (clobber (match_scratch:DI 2 "=d"))]
+  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS && TARGET_FCFID"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2) (match_dup 1))
+   (set (match_dup 0) (float:DF (match_dup 2)))]
+  ""
+  [(set_attr "length" "8")
+   (set_attr "type" "fpload")])
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:HI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 6))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 6)))]
-  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 6)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
+(define_expand "floatunsdidf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (unsigned_float:DF
+        (match_operand:DI 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && (TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode))"
   "")
 
-(define_insn "*rotldi3_internal13le"
-  [(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,r")
-                    (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 0)))]
-  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN"
-  "@
-   rldcl %0,%1,%2,32
-   rldicl %0,%1,%H2,32"
-  [(set_attr "type" "var_shift_rotate,integer")])
+(define_insn "*floatunsdidf2_fcfidu"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+       (unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "d")))]
+  "TARGET_HARD_FLOAT && TARGET_FCFIDU && !VECTOR_UNIT_VSX_P (DFmode)"
+  "fcfidu %0,%1"
+  [(set_attr "type" "fp")
+   (set_attr "length" "4")])
 
-(define_insn "*rotldi3_internal13be"
-  [(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,r")
-                    (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 4)))]
-  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN"
-  "@
-   rldcl %0,%1,%2,32
-   rldicl %0,%1,%H2,32"
-  [(set_attr "type" "var_shift_rotate,integer")])
+(define_insn_and_split "*floatunsdidf2_mem"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+       (unsigned_float:DF (match_operand:DI 1 "memory_operand" "m")))
+   (clobber (match_scratch:DI 2 "=d"))]
+  "TARGET_HARD_FLOAT && (TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode))"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2) (match_dup 1))
+   (set (match_dup 0) (unsigned_float:DF (match_dup 2)))]
+  ""
+  [(set_attr "length" "8")
+   (set_attr "type" "fpload")])
 
-(define_insn "*rotldi3_internal14le"
-  [(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,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,r,r"))]
-  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %3,%1,%2,32
-   rldicl. %3,%1,%H2,32
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+(define_expand "floatdisf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+        (float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
+  "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+   && (TARGET_FCFIDS || TARGET_POWERPC64 || flag_unsafe_math_optimizations)"
+  "
+{
+  if (!TARGET_FCFIDS)
+    {
+      rtx val = operands[1];
+      if (!flag_unsafe_math_optimizations)
+       {
+         rtx label = gen_label_rtx ();
+         val = gen_reg_rtx (DImode);
+         emit_insn (gen_floatdisf2_internal2 (val, operands[1], label));
+         emit_label (label);
+       }
+      emit_insn (gen_floatdisf2_internal1 (operands[0], val));
+      DONE;
+    }
+}")
 
-(define_insn "*rotldi3_internal14be"
-  [(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,r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 4))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
-  "TARGET_64BIT && BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %3,%1,%2,32
-   rldicl. %3,%1,%H2,32
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+(define_insn "floatdisf2_fcfids"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
+  "fcfids %0,%1"
+  [(set_attr "type" "fp")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:SI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 3)
-       (zero_extend:DI (subreg:SI
-                     (rotate:DI (match_dup 1)
-                                (match_dup 2)) 0)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
+(define_insn_and_split "*floatdisf2_mem"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (float:SF (match_operand:DI 1 "memory_operand" "m")))
+   (clobber (match_scratch:DI 2 "=f"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
+  "#"
+  "&& reload_completed"
+  [(pc)]
+  "
+{
+  emit_move_insn (operands[2], operands[1]);
+  emit_insn (gen_floatdisf2_fcfids (operands[0], operands[2]));
+  DONE;
+}"
+  [(set_attr "length" "8")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:SI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 4))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 3)
-       (zero_extend:DI (subreg:SI
-                     (rotate:DI (match_dup 1)
-                                (match_dup 2)) 4)))
+;; This is not IEEE compliant if rounding mode is "round to nearest".
+;; If the DI->DF conversion is inexact, then it's possible to suffer
+;; from double rounding.
+;; Instead of creating a new cpu type for two FP operations, just use fp
+(define_insn_and_split "floatdisf2_internal1"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+        (float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))
+   (clobber (match_scratch:DF 2 "=d"))]
+  "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2)
+        (float:DF (match_dup 1)))
    (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*rotldi3_internal15le"
-  [(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,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,r,r")
-       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
-  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %0,%1,%2,32
-   rldicl. %0,%1,%H2,32
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+        (float_truncate:SF (match_dup 2)))]
+  ""
+  [(set_attr "length" "8")
+   (set_attr "type" "fp")])
 
-(define_insn "*rotldi3_internal15be"
-  [(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,r,r")
-                                (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 4))
-                   (const_int 0)))
-   (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)) 4)))]
-  "TARGET_64BIT && BYTES_BIG_ENDIAN"
-  "@
-   rldcl. %0,%1,%2,32
-   rldicl. %0,%1,%H2,32
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+;; Twiddles bits to avoid double rounding.
+;; Bits that might be truncated when converting to DFmode are replaced
+;; by a bit that won't be lost at that stage, but is below the SFmode
+;; rounding position.
+(define_expand "floatdisf2_internal2"
+  [(set (match_dup 3) (ashiftrt:DI (match_operand:DI 1 "" "")
+                                  (const_int 53)))
+   (set (match_operand:DI 0 "" "") (and:DI (match_dup 1)
+                                          (const_int 2047)))
+   (set (match_dup 3) (plus:DI (match_dup 3)
+                              (const_int 1)))
+   (set (match_dup 0) (plus:DI (match_dup 0)
+                              (const_int 2047)))
+   (set (match_dup 4) (compare:CCUNS (match_dup 3)
+                                    (const_int 2)))
+   (set (match_dup 0) (ior:DI (match_dup 0)
+                             (match_dup 1)))
+   (set (match_dup 0) (and:DI (match_dup 0)
+                             (const_int -2048)))
+   (set (pc) (if_then_else (geu (match_dup 4) (const_int 0))
+                          (label_ref (match_operand:DI 2 "" ""))
+                          (pc)))
+   (set (match_dup 0) (match_dup 1))]
+  "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
+  "
+{
+  operands[3] = gen_reg_rtx (DImode);
+  operands[4] = gen_reg_rtx (CCUNSmode);
+}")
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:SI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
-  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
+(define_expand "floatunsdisf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+        (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
   "")
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (zero_extend:DI
-                    (subreg:SI
-                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:DI 2 "reg_or_cint_operand" "")) 4))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 4)))]
-  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 4)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+(define_insn "floatunsdisf2_fcfidus"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+        (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
+  "fcfidus %0,%1"
+  [(set_attr "type" "fp")])
 
-(define_expand "ashldi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                  (match_operand:SI 2 "reg_or_cint_operand" "")))]
-  "TARGET_POWERPC64"
-  "")
+(define_insn_and_split "*floatunsdisf2_mem"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+       (unsigned_float:SF (match_operand:DI 1 "memory_operand" "m")))
+   (clobber (match_scratch:DI 2 "=f"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
+  "#"
+  "&& reload_completed"
+  [(pc)]
+  "
+{
+  emit_move_insn (operands[2], operands[1]);
+  emit_insn (gen_floatunsdisf2_fcfidus (operands[0], operands[2]));
+  DONE;
+}"
+  [(set_attr "length" "8")
+   (set_attr "type" "fpload")])
+\f
+;; Define the TImode operations that can be done in a small number
+;; of instructions.  The & constraints are to prevent the register
+;; allocator from allocating registers that overlap with the inputs
+;; (for example, having an input in 7,8 and an output in 6,7).  We
+;; also allow for the output being the same as one of the inputs.
 
-(define_insn "*ashldi3_internal1"
-  [(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 %0,%1,%2
-   sldi %0,%1,%H2"
-  [(set_attr "type" "var_shift_rotate,shift")])
+(define_insn "addti3"
+  [(set (match_operand:TI 0 "gpc_reg_operand" "=&r,&r,r,r")
+       (plus:TI (match_operand:TI 1 "gpc_reg_operand" "%r,r,0,0")
+                (match_operand:TI 2 "reg_or_short_operand" "r,I,r,I")))]
+  "TARGET_64BIT"
+{
+  if (WORDS_BIG_ENDIAN)
+    return (GET_CODE (operands[2])) != CONST_INT
+           ? \"addc %L0,%L1,%L2\;adde %0,%1,%2\"
+           : \"addic %L0,%L1,%2\;add%G2e %0,%1\";
+  else
+    return (GET_CODE (operands[2])) != CONST_INT
+           ? \"addc %0,%1,%2\;adde %L0,%L1,%L2\"
+           : \"addic %0,%1,%2\;add%G2e %L0,%L1\";
+}
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
-(define_insn "*ashldi3_internal2"
-  [(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,r,r"))]
+(define_insn "subti3"
+  [(set (match_operand:TI 0 "gpc_reg_operand" "=&r,&r,r,r,r")
+       (minus:TI (match_operand:TI 1 "reg_or_short_operand" "r,I,0,r,I")
+                 (match_operand:TI 2 "gpc_reg_operand" "r,r,r,0,0")))]
   "TARGET_64BIT"
-  "@
-   sld. %3,%1,%2
-   sldi. %3,%1,%H2
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+{
+  if (WORDS_BIG_ENDIAN)
+    return (GET_CODE (operands[1]) != CONST_INT)
+           ? \"subfc %L0,%L2,%L1\;subfe %0,%2,%1\"
+           : \"subfic %L0,%L2,%1\;subf%G1e %0,%2\";
+  else
+    return (GET_CODE (operands[1]) != CONST_INT)
+           ? \"subfc %0,%2,%1\;subfe %L0,%L2,%L1\"
+           : \"subfic %0,%2,%1\;subf%G1e %L0,%L2\";
+}
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                              (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (ashift:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
 
-(define_insn "*ashldi3_internal3"
-  [(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,r,r")
-       (ashift:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   sld. %0,%1,%2
-   sldi. %0,%1,%H2
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+;; Define the DImode operations that can be done in a small number
+;; of instructions.  The & constraints are to prevent the register
+;; allocator from allocating registers that overlap with the inputs
+;; (for example, having an input in 7,8 and an output in 6,7).  We
+;; also allow for the output being the same as one of the inputs.
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                              (match_operand:SI 2 "reg_or_cint_operand" ""))
-                   (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (ashift:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (ashift:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+(define_insn "*adddi3_noppc64"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r")
+       (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,0,0")
+                (match_operand:DI 2 "reg_or_short_operand" "r,I,r,I")))]
+  "! TARGET_POWERPC64"
+  "*
+{
+  if (WORDS_BIG_ENDIAN)
+    return (GET_CODE (operands[2])) != CONST_INT
+           ? \"addc %L0,%L1,%L2\;adde %0,%1,%2\"
+           : \"addic %L0,%L1,%2\;add%G2e %0,%1\";
+  else
+    return (GET_CODE (operands[2])) != CONST_INT
+           ? \"addc %0,%1,%2\;adde %L0,%L1,%L2\"
+           : \"addic %0,%1,%2\;add%G2e %L0,%L1\";
+}"
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
-(define_insn "*ashldi3_internal4"
-  [(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 "const_int_operand" "n")))]
-  "TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])"
-  "rldic %0,%1,%H2,%W3")
+(define_insn "*subdi3_noppc64"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r,r")
+       (minus:DI (match_operand:DI 1 "reg_or_short_operand" "r,I,0,r,I")
+                 (match_operand:DI 2 "gpc_reg_operand" "r,r,r,0,0")))]
+  "! TARGET_POWERPC64"
+  "*
+{
+  if (WORDS_BIG_ENDIAN)
+    return (GET_CODE (operands[1]) != CONST_INT)
+           ? \"subfc %L0,%L2,%L1\;subfe %0,%2,%1\"
+           : \"subfic %L0,%L2,%1\;subf%G1e %0,%2\";
+  else
+    return (GET_CODE (operands[1]) != CONST_INT)
+           ? \"subfc %0,%2,%1\;subfe %L0,%L2,%L1\"
+           : \"subfic %0,%2,%1\;subf%G1e %L0,%L2\";
+}"
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
-(define_insn "ashldi3_internal5"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (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 "const_int_operand" "n,n"))
-        (const_int 0)))
-   (clobber (match_scratch:DI 4 "=r,r"))]
-  "TARGET_64BIT && includes_rldic_lshift_p (operands[2], operands[3])"
-  "@
-   rldic. %4,%1,%H2,%W3
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
+(define_insn "*negdi2_noppc64"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
+       (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))]
+  "! TARGET_POWERPC64"
+  "*
+{
+  return (WORDS_BIG_ENDIAN)
+    ? \"subfic %L0,%L1,0\;subfze %0,%1\"
+    : \"subfic %0,%1,0\;subfze %L0,%L1\";
+}"
+  [(set_attr "type" "two")
+   (set_attr "length" "8")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC
-        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "const_int_operand" ""))
-                (match_operand:DI 3 "const_int_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:DI 4 ""))]
-  "TARGET_POWERPC64 && reload_completed
-   && includes_rldic_lshift_p (operands[2], operands[3])"
-  [(set (match_dup 4)
-       (and:DI (ashift:DI (match_dup 1) (match_dup 2))
-               (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
-  "")
 
-(define_insn "*ashldi3_internal6"
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
-       (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 "const_int_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)))]
-  "TARGET_64BIT && includes_rldic_lshift_p (operands[2], operands[3])"
-  "@
-   rldic. %0,%1,%H2,%W3
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,8")])
+;; Shift by a variable amount is too complex to be worth open-coding.  We
+;; just handle shifts by constants.
+(define_insn "ashrdi3_no_power"
+  [(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 "const_int_operand" "M,i")))]
+  "!TARGET_POWERPC64"
+  "*
+{
+  switch (which_alternative)
+    {
+    default:
+      gcc_unreachable ();
+    case 0:
+      if (WORDS_BIG_ENDIAN)
+        return \"srawi %0,%1,31\;srawi %L0,%1,%h2\";
+      else
+        return \"srawi %L0,%L1,31\;srawi %0,%L1,%h2\";
+    case 1:
+      if (WORDS_BIG_ENDIAN)
+       return \"srwi %L0,%L1,%h2\;insrwi %L0,%1,%h2,0\;srawi %0,%1,%h2\";
+      else
+       return \"srwi %0,%1,%h2\;insrwi %0,%L1,%h2,0\;srawi %L0,%L1,%h2\";
+    }
+}"
+  [(set_attr "type" "two,three")
+   (set_attr "length" "8,12")])
 
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC
-        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "const_int_operand" ""))
-                (match_operand:DI 3 "const_int_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)))]
-  "TARGET_POWERPC64 && reload_completed
-   && includes_rldic_lshift_p (operands[2], operands[3])"
-  [(set (match_dup 0)
-       (and:DI (ashift:DI (match_dup 1) (match_dup 2))
-               (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+(define_insn "*ashrdisi3_noppc64be"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (subreg:SI (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                                (const_int 32)) 4))]
+  "TARGET_32BIT && !TARGET_POWERPC64 && WORDS_BIG_ENDIAN"
+  "*
+{
+  if (REGNO (operands[0]) == REGNO (operands[1]))
+    return \"\";
+  else
+    return \"mr %0,%1\";
+}"
+   [(set_attr "length" "4")])
 
-(define_insn "*ashldi3_internal7"
+\f
+;; PowerPC64 DImode operations.
+
+(define_insn "*rotldi3_internal4"
   [(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"))
+       (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                          (match_operand:DI 2 "reg_or_cint_operand" "rn"))
                (match_operand:DI 3 "mask64_operand" "n")))]
-  "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
-  "rldicr %0,%1,%H2,%S3")
+  "TARGET_POWERPC64"
+  "rld%I2c%B3 %0,%1,%H2,%S3"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
-(define_insn "ashldi3_internal8"
+(define_insn "*rotldi3_internal5"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:SI 2 "const_int_operand" "i,i"))
-                (match_operand:DI 3 "mask64_operand" "n,n"))
-        (const_int 0)))
+       (compare:CC (and:DI
+                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                               (match_operand:DI 2 "reg_or_cint_operand" "rn,rn"))
+                    (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])"
+  "TARGET_64BIT"
   "@
-   rldicr. %4,%1,%H2,%S3
+   rld%I2c%B3. %4,%1,%H2,%S3
    #"
-  [(set_attr "type" "compare")
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC
-        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "const_int_operand" ""))
-                (match_operand:DI 3 "mask64_operand" ""))
-        (const_int 0)))
+       (compare:CC (and:DI
+                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                               (match_operand:DI 2 "reg_or_cint_operand" ""))
+                    (match_operand:DI 3 "mask64_operand" ""))
+                   (const_int 0)))
    (clobber (match_scratch:DI 4 ""))]
-  "TARGET_POWERPC64 && reload_completed
-   && includes_rldicr_lshift_p (operands[2], operands[3])"
+  "TARGET_POWERPC64 && reload_completed"
   [(set (match_dup 4)
-       (and:DI (ashift:DI (match_dup 1) (match_dup 2))
-               (match_dup 3)))
+       (and:DI (rotate:DI (match_dup 1)
+                               (match_dup 2))
+                    (match_dup 3)))
    (set (match_dup 0)
        (compare:CC (match_dup 4)
                    (const_int 0)))]
   "")
 
-(define_insn "*ashldi3_internal9"
+(define_insn "*rotldi3_internal6"
   [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:SI 2 "const_int_operand" "i,i"))
-                   (match_operand:DI 3 "mask64_operand" "n,n"))
-        (const_int 0)))
+       (compare:CC (and:DI
+                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                               (match_operand:DI 2 "reg_or_cint_operand" "rn,rn"))
+                    (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)))]
-  "TARGET_64BIT && includes_rldicr_lshift_p (operands[2], operands[3])"
+       (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+  "TARGET_64BIT"
   "@
-   rldicr. %0,%1,%H2,%S3
+   rld%I2c%B3. %0,%1,%H2,%S3
    #"
-  [(set_attr "type" "compare")
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC
-        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "const_int_operand" ""))
-                (match_operand:DI 3 "mask64_operand" ""))
-        (const_int 0)))
+       (compare:CC (and:DI
+                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                               (match_operand:DI 2 "reg_or_cint_operand" ""))
+                    (match_operand:DI 3 "mask64_operand" ""))
+                   (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_POWERPC64 && reload_completed
-   && includes_rldicr_lshift_p (operands[2], operands[3])"
+       (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+  "TARGET_POWERPC64 && reload_completed"
   [(set (match_dup 0)
-       (and:DI (ashift:DI (match_dup 1) (match_dup 2))
-               (match_dup 3)))
+       (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))
    (set (match_dup 4)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-(define_expand "lshrdi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                    (match_operand:SI 2 "reg_or_cint_operand" "")))]
-  "TARGET_POWERPC64"
-  "")
+(define_insn "*rotldi3_internal7le"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+        (subreg:QI
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "rn")) 0)))]
+  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN"
+  "rld%I2cl %0,%1,%H2,56"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
-(define_insn "*lshrdi3_internal1"
-  [(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"
+(define_insn "*rotldi3_internal7be"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+        (subreg:QI
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "rn")) 7)))]
+  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN"
+  "rld%I2cl %0,%1,%H2,56"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
+
+(define_insn "*rotldi3_internal8le"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?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" "rn,rn")) 0))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 "=r,r"))]
+  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
   "@
-   srd %0,%1,%2
-   srdi %0,%1,%H2"
-  [(set_attr "type" "var_shift_rotate,shift")])
+   rld%I2cl. %3,%1,%H2,56
+   #"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*lshrdi3_internal2"
-  [(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"))
+(define_insn "*rotldi3_internal8be"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?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" "rn,rn")) 7))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
-  "TARGET_64BIT "
+   (clobber (match_scratch:DI 3 "=r,r"))]
+  "TARGET_64BIT && BYTES_BIG_ENDIAN"
   "@
-   srd. %3,%1,%2
-   srdi. %3,%1,%H2
-   #
+   rld%I2cl. %3,%1,%H2,56
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:SI 2 "reg_or_cint_operand" ""))
+       (compare:CC (zero_extend:DI
+                    (subreg:QI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
                    (const_int 0)))
    (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
+  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
   [(set (match_dup 3)
-       (lshiftrt:DI (match_dup 1) (match_dup 2)))
+       (zero_extend:DI (subreg:QI
+                     (rotate:DI (match_dup 1)
+                                (match_dup 2)) 0)))
    (set (match_dup 0)
        (compare:CC (match_dup 3)
                    (const_int 0)))]
   "")
 
-(define_insn "*lshrdi3_internal3"
-  [(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,r,r")
-       (lshiftrt:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   srd. %0,%1,%2
-   srdi. %0,%1,%H2
-   #
-   #"
-  [(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_micro_cr0_operand" "")
-       (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:SI 2 "reg_or_cint_operand" ""))
+  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC (zero_extend:DI
+                    (subreg:QI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 7))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (lshiftrt:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-       (lshiftrt:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
+   (clobber (match_scratch:DI 3 ""))]
+  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
+  [(set (match_dup 3)
+       (zero_extend:DI (subreg:QI
+                     (rotate:DI (match_dup 1)
+                                (match_dup 2)) 7)))
+   (set (match_dup 0)
+       (compare:CC (match_dup 3)
                    (const_int 0)))]
   "")
 
-(define_expand "ashrdi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                    (match_operand:SI 2 "reg_or_cint_operand" "")))]
-  ""
-  "
-{
-  if (TARGET_POWERPC64)
-    ;
-  else if (GET_CODE (operands[2]) == CONST_INT)
-    {
-      emit_insn (gen_ashrdi3_no_power (operands[0], operands[1], operands[2]));
-      DONE;
-    }
-  else
-    FAIL;
-}")
-
-(define_insn "*ashrdi3_internal1"
-  [(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"
+(define_insn "*rotldi3_internal9le"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?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" "rn,rn")) 0))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
+  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
   "@
-   srad %0,%1,%2
-   sradi %0,%1,%H2"
-  [(set_attr "type" "var_shift_rotate,shift")])
+   rld%I2cl. %0,%1,%H2,56
+   #"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*ashrdi3_internal2"
-  [(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"))
+(define_insn "*rotldi3_internal9be"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?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" "rn,rn")) 7))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
-  "TARGET_64BIT"
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 7)))]
+  "TARGET_64BIT && BYTES_BIG_ENDIAN"
   "@
-   srad. %3,%1,%2
-   sradi. %3,%1,%H2
-   #
+   rld%I2cl. %0,%1,%H2,56
    #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:SI 2 "reg_or_cint_operand" ""))
+  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC (zero_extend:DI
+                    (subreg:QI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (ashiftrt:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
+   (set (match_operand:DI 0 "gpc_reg_operand" "")
+       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
+  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
+  [(set (match_dup 0)
+       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-(define_insn "*ashrdi3_internal3"
-  [(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,r,r")
-       (ashiftrt:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   srad. %0,%1,%2
-   sradi. %0,%1,%H2
-   #
-   #"
-  [(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" "")
-       (compare:CC (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                                (match_operand:SI 2 "reg_or_cint_operand" ""))
+  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC (zero_extend:DI
+                    (subreg:QI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 7))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (ashiftrt:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && reload_completed"
+       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 7)))]
+  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
   [(set (match_dup 0)
-       (ashiftrt:DI (match_dup 1) (match_dup 2)))
+       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 7)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-(define_expand "anddi3"
-  [(parallel
-    [(set (match_operand:DI 0 "gpc_reg_operand" "")
-         (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                 (match_operand:DI 2 "reg_or_cint_operand" "")))
-     (clobber (match_scratch:CC 3 ""))])]
-  ""
-{
-  if (!TARGET_POWERPC64)
-    {
-      rtx cc = gen_rtx_SCRATCH (CCmode);
-      rs6000_split_logical (operands, AND, false, false, false, cc);
-      DONE;
-    }
-  else if (!and64_2_operand (operands[2], DImode))
-    operands[2] = force_reg (DImode, operands[2]);
-})
+(define_insn "*rotldi3_internal10le"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+        (subreg:HI
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "rn")) 0)))]
+  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN"
+  "rld%I2cl %0,%1,%H2,48"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
+
+(define_insn "*rotldi3_internal10be"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+        (subreg:HI
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "rn")) 6)))]
+  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN"
+  "rld%I2cl %0,%1,%H2,48"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
-(define_insn "anddi3_mc"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r")
-       (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r")
-               (match_operand:DI 2 "and64_2_operand" "?r,S,T,K,J,t")))
-   (clobber (match_scratch:CC 3 "=X,X,X,x,x,X"))]
-  "TARGET_POWERPC64 && rs6000_gen_cell_microcode"
+(define_insn "*rotldi3_internal11le"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?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" "rn,rn")) 0))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 "=r,r"))]
+  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
   "@
-   and %0,%1,%2
-   rldic%B2 %0,%1,0,%S2
-   rlwinm %0,%1,0,%m2,%M2
-   andi. %0,%1,%b2
-   andis. %0,%1,%u2
+   rld%I2cl. %3,%1,%H2,48
    #"
-  [(set_attr "type" "*,*,*,fast_compare,fast_compare,*")
-   (set_attr "length" "4,4,4,4,4,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "anddi3_nomc"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
-       (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r")
-               (match_operand:DI 2 "and64_2_operand" "?r,S,T,t")))
-   (clobber (match_scratch:CC 3 "=X,X,X,X"))]
-  "TARGET_POWERPC64 && !rs6000_gen_cell_microcode"
+(define_insn "*rotldi3_internal11be"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?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" "rn,rn")) 6))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 "=r,r"))]
+  "TARGET_64BIT && BYTES_BIG_ENDIAN"
   "@
-   and %0,%1,%2
-   rldic%B2 %0,%1,0,%S2
-   rlwinm %0,%1,0,%m2,%M2
+   rld%I2cl. %3,%1,%H2,48
    #"
-  [(set_attr "length" "4,4,4,8")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "mask64_2_operand" "")))
-   (clobber (match_scratch:CC 3 ""))]
-  "TARGET_POWERPC64
-    && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
-    && !mask_operand (operands[2], DImode)
-    && !mask64_operand (operands[2], DImode)"
-  [(set (match_dup 0)
-       (and:DI (rotate:DI (match_dup 1)
-                          (match_dup 4))
-               (match_dup 5)))
+  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC (zero_extend:DI
+                    (subreg:HI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 ""))]
+  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
+  [(set (match_dup 3)
+       (zero_extend:DI (subreg:HI
+                     (rotate:DI (match_dup 1)
+                                (match_dup 2)) 0)))
+   (set (match_dup 0)
+       (compare:CC (match_dup 3)
+                   (const_int 0)))]
+  "")
+
+(define_split
+  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC (zero_extend:DI
+                    (subreg:HI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 6))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 ""))]
+  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
+  [(set (match_dup 3)
+       (zero_extend:DI (subreg:HI
+                     (rotate:DI (match_dup 1)
+                                (match_dup 2)) 6)))
    (set (match_dup 0)
-       (and:DI (rotate:DI (match_dup 0)
-                          (match_dup 6))
-               (match_dup 7)))]
-{
-  build_mask64_2_operands (operands[2], &operands[4]);
-})
+       (compare:CC (match_dup 3)
+                   (const_int 0)))]
+  "")
 
-(define_insn "*anddi3_internal2_mc"
-  [(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"))
+(define_insn "*rotldi3_internal12le"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?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" "rn,rn")) 0))
                    (const_int 0)))
-   (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 && rs6000_gen_cell_microcode"
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
+  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
   "@
-   and. %3,%1,%2
-   rldic%B2. %3,%1,0,%S2
-   rlwinm. %3,%1,0,%m2,%M2
-   andi. %3,%1,%b2
-   andis. %3,%1,%u2
-   #
-   #
-   #
-   #
-   #
-   #
+   rld%I2cl. %0,%1,%H2,48
    #"
-  [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
-                    fast_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" "")
-        (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                            (match_operand:DI 2 "mask64_2_operand" ""))
-                    (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))
-   (clobber (match_scratch:CC 4 ""))]
-  "TARGET_64BIT && reload_completed
-    && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
-    && !mask_operand (operands[2], DImode)
-    && !mask64_operand (operands[2], DImode)"
-  [(set (match_dup 3)
-       (and:DI (rotate:DI (match_dup 1)
-                          (match_dup 5))
-               (match_dup 6)))
-   (parallel [(set (match_dup 0)
-                  (compare:CC (and:DI (rotate:DI (match_dup 3)
-                                                 (match_dup 7))
-                                      (match_dup 8))
-                              (const_int 0)))
-             (clobber (match_dup 3))])]
-  "
-{
-  build_mask64_2_operands (operands[2], &operands[5]);
-}")
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*anddi3_internal3_mc"
-  [(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"))
+(define_insn "*rotldi3_internal12be"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?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" "rn,rn")) 6))
                    (const_int 0)))
-   (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,x,X"))]
-  "TARGET_64BIT && rs6000_gen_cell_microcode"
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 6)))]
+  "TARGET_64BIT && BYTES_BIG_ENDIAN"
   "@
-   and. %0,%1,%2
-   rldic%B2. %0,%1,0,%S2
-   rlwinm. %0,%1,0,%m2,%M2
-   andi. %0,%1,%b2
-   andis. %0,%1,%u2
-   #
-   #
-   #
-   #
-   #
-   #
+   rld%I2cl. %0,%1,%H2,48
    #"
-  [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
-                    fast_compare,compare,compare,compare,compare,compare,\
-                    compare,compare")
-   (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:DI 2 "and64_2_operand" ""))
+       (compare:CC (zero_extend:DI
+                    (subreg:HI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
                    (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_64BIT && reload_completed"
-  [(parallel [(set (match_dup 0)
-                   (and:DI (match_dup 1) (match_dup 2)))
-              (clobber (match_dup 4))])
+       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
+  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
+  [(set (match_dup 0)
+       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
 (define_split
-  [(set (match_operand:CC 3 "cc_reg_operand" "")
-        (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                            (match_operand:DI 2 "mask64_2_operand" ""))
-                    (const_int 0)))
+  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC (zero_extend:DI
+                    (subreg:HI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 6))
+                   (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_64BIT && reload_completed
-    && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
-    && !mask_operand (operands[2], DImode)
-    && !mask64_operand (operands[2], DImode)"
+       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 6)))]
+  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
   [(set (match_dup 0)
-       (and:DI (rotate:DI (match_dup 1)
-                          (match_dup 5))
-               (match_dup 6)))
-   (parallel [(set (match_dup 3)
-                  (compare:CC (and:DI (rotate:DI (match_dup 0)
-                                                 (match_dup 7))
-                                      (match_dup 8))
-                              (const_int 0)))
-             (set (match_dup 0)
-                  (and:DI (rotate:DI (match_dup 0)
-                                     (match_dup 7))
-                          (match_dup 8)))])]
-  "
-{
-  build_mask64_2_operands (operands[2], &operands[5]);
-}")
-
-(define_expand "iordi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (ior:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "reg_or_cint_operand" "")))]
-  ""
-{
-  if (!TARGET_POWERPC64)
-    {
-      rs6000_split_logical (operands, IOR, false, false, false, NULL_RTX);
-      DONE;
-    }
-  else if (!reg_or_logical_cint_operand (operands[2], DImode))
-    operands[2] = force_reg (DImode, operands[2]);
-  else if (non_logical_cint_operand (operands[2], DImode))
-    {
-      HOST_WIDE_INT value;
-      rtx tmp = ((!can_create_pseudo_p ()
-                 || rtx_equal_p (operands[0], operands[1]))
-                ? operands[0] : gen_reg_rtx (DImode));
-
-      value = INTVAL (operands[2]);
-      emit_insn (gen_iordi3 (tmp, operands[1],
-                            GEN_INT (value & (~ (HOST_WIDE_INT) 0xffff))));
-
-      emit_insn (gen_iordi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
-      DONE;
-    }
-})
-
-(define_expand "xordi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (xor:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "reg_or_cint_operand" "")))]
-  ""
-{
-  if (!TARGET_POWERPC64)
-    {
-      rs6000_split_logical (operands, XOR, false, false, false, NULL_RTX);
-      DONE;
-    }
-  else if (!reg_or_logical_cint_operand (operands[2], DImode))
-    operands[2] = force_reg (DImode, operands[2]);
-  if (non_logical_cint_operand (operands[2], DImode))
-    {
-      HOST_WIDE_INT value;
-      rtx tmp = ((!can_create_pseudo_p ()
-                 || rtx_equal_p (operands[0], operands[1]))
-                ? operands[0] : gen_reg_rtx (DImode));
+       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 6)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  "")
 
-      value = INTVAL (operands[2]);
-      emit_insn (gen_xordi3 (tmp, operands[1],
-                            GEN_INT (value & (~ (HOST_WIDE_INT) 0xffff))));
+(define_insn "*rotldi3_internal13le"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+        (subreg:SI
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "rn")) 0)))]
+  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN"
+  "rld%I2cl %0,%1,%H2,32"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
-      emit_insn (gen_xordi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
-      DONE;
-    }
-})
+(define_insn "*rotldi3_internal13be"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+        (subreg:SI
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "rn")) 4)))]
+  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN"
+  "rld%I2cl %0,%1,%H2,32"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")])
 
-(define_insn "*booldi3_internal1"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
-       (match_operator:DI 3 "boolean_or_operator"
-        [(match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
-         (match_operand:DI 2 "logical_operand" "r,K,JF")]))]
-  "TARGET_POWERPC64"
+(define_insn "*rotldi3_internal14le"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?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" "rn,rn")) 0))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 "=r,r"))]
+  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
   "@
-   %q3 %0,%1,%2
-   %q3i %0,%1,%b2
-   %q3is %0,%1,%u2")
+   rld%I2cl. %3,%1,%H2,32
+   #"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*booldi3_internal2"
+(define_insn "*rotldi3_internal14be"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:DI 4 "boolean_or_operator"
-        [(match_operand:DI 1 "gpc_reg_operand" "%r,r")
-         (match_operand:DI 2 "gpc_reg_operand" "r,r")])
-        (const_int 0)))
+       (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" "rn,rn")) 4))
+                   (const_int 0)))
    (clobber (match_scratch:DI 3 "=r,r"))]
-  "TARGET_64BIT"
+  "TARGET_64BIT && BYTES_BIG_ENDIAN"
   "@
-   %q4. %3,%1,%2
+   rld%I2cl. %3,%1,%H2,32
    #"
-  [(set_attr "type" "fast_compare,compare")
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(match_operand:DI 1 "gpc_reg_operand" "")
-         (match_operand:DI 2 "gpc_reg_operand" "")])
-        (const_int 0)))
+       (compare:CC (zero_extend:DI
+                    (subreg:SI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
+                   (const_int 0)))
    (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3) (match_dup 4))
+  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
+  [(set (match_dup 3)
+       (zero_extend:DI (subreg:SI
+                     (rotate:DI (match_dup 1)
+                                (match_dup 2)) 0)))
+   (set (match_dup 0)
+       (compare:CC (match_dup 3)
+                   (const_int 0)))]
+  "")
+
+(define_split
+  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC (zero_extend:DI
+                    (subreg:SI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 4))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 ""))]
+  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
+  [(set (match_dup 3)
+       (zero_extend:DI (subreg:SI
+                     (rotate:DI (match_dup 1)
+                                (match_dup 2)) 4)))
    (set (match_dup 0)
        (compare:CC (match_dup 3)
                    (const_int 0)))]
   "")
 
-(define_insn "*booldi3_internal3"
+(define_insn "*rotldi3_internal15le"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:DI 4 "boolean_or_operator"
-        [(match_operand:DI 1 "gpc_reg_operand" "%r,r")
-         (match_operand:DI 2 "gpc_reg_operand" "r,r")])
-        (const_int 0)))
+       (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" "rn,rn")) 0))
+                   (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (match_dup 4))]
-  "TARGET_64BIT"
+       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
+  "TARGET_64BIT && !BYTES_BIG_ENDIAN"
+  "@
+   rld%I2cl. %0,%1,%H2,32
+   #"
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
+
+(define_insn "*rotldi3_internal15be"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?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" "rn,rn")) 4))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 4)))]
+  "TARGET_64BIT && BYTES_BIG_ENDIAN"
   "@
-   %q4. %0,%1,%2
+   rld%I2cl. %0,%1,%H2,32
    #"
-  [(set_attr "type" "fast_compare,compare")
+  [(set_attr "type" "shift")
+   (set_attr "maybe_var_shift" "yes")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(match_operand:DI 1 "gpc_reg_operand" "")
-         (match_operand:DI 2 "gpc_reg_operand" "")])
-        (const_int 0)))
+       (compare:CC (zero_extend:DI
+                    (subreg:SI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 0))
+                   (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_dup 4))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0) (match_dup 4))
+       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
+  "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed"
+  [(set (match_dup 0)
+       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))
    (set (match_dup 3)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-;; Split a logical operation that we can't do in one insn into two insns,
-;; each of which does one 16-bit part.  This is used by combine.
-
 (define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operator:DI 3 "boolean_or_operator"
-        [(match_operand:DI 1 "gpc_reg_operand" "")
-         (match_operand:DI 2 "non_logical_cint_operand" "")]))]
-  "TARGET_POWERPC64"
-  [(set (match_dup 0) (match_dup 4))
-   (set (match_dup 0) (match_dup 5))]
-"
-{
-  rtx i3,i4;
-
-  i3 = GEN_INT (INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff));
-  i4 = GEN_INT (INTVAL (operands[2]) & 0xffff);
-  operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
-                               operands[1], i3);
-  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
-                               operands[0], i4);
-}")
+  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC (zero_extend:DI
+                    (subreg:SI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                                (match_operand:DI 2 "reg_or_cint_operand" "")) 4))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "")
+       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 4)))]
+  "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed"
+  [(set (match_dup 0)
+       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 4)))
+   (set (match_dup 3)
+       (compare:CC (match_dup 0)
+                   (const_int 0)))]
+  "")
 
-(define_insn "*boolcdi3_internal1"
+(define_insn "*ashldi3_internal4"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (match_operator:DI 3 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
-         (match_operand:DI 2 "gpc_reg_operand" "r")]))]
-  "TARGET_POWERPC64"
-  "%q3 %0,%2,%1")
+       (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                          (match_operand:SI 2 "const_int_operand" "i"))
+               (match_operand:DI 3 "const_int_operand" "n")))]
+  "TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])"
+  "rldic %0,%1,%H2,%W3"
+  [(set_attr "type" "shift")])
 
-(define_insn "*boolcdi3_internal2"
+(define_insn "ashldi3_internal5"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
-         (match_operand:DI 2 "gpc_reg_operand" "r,r")])
+       (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 "const_int_operand" "n,n"))
         (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:DI 4 "=r,r"))]
+  "TARGET_64BIT && includes_rldic_lshift_p (operands[2], operands[3])"
   "@
-   %q4. %3,%2,%1
+   rldic. %4,%1,%H2,%W3
    #"
-  [(set_attr "type" "fast_compare,compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" ""))
-         (match_operand:DI 2 "gpc_reg_operand" "")])
+       (compare:CC
+        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                           (match_operand:SI 2 "const_int_operand" ""))
+                (match_operand:DI 3 "const_int_operand" ""))
         (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3) (match_dup 4))
+   (clobber (match_scratch:DI 4 ""))]
+  "TARGET_POWERPC64 && reload_completed
+   && includes_rldic_lshift_p (operands[2], operands[3])"
+  [(set (match_dup 4)
+       (and:DI (ashift:DI (match_dup 1) (match_dup 2))
+               (match_dup 3)))
    (set (match_dup 0)
-       (compare:CC (match_dup 3)
+       (compare:CC (match_dup 4)
                    (const_int 0)))]
   "")
 
-(define_insn "*boolcdi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r"))
-         (match_operand:DI 2 "gpc_reg_operand" "r,r")])
+(define_insn "*ashldi3_internal6"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+       (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 "const_int_operand" "n,n"))
         (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (match_dup 4))]
-  "TARGET_64BIT"
+       (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+  "TARGET_64BIT && includes_rldic_lshift_p (operands[2], operands[3])"
   "@
-   %q4. %0,%2,%1
+   rldic. %0,%1,%H2,%W3
    #"
-  [(set_attr "type" "fast_compare,compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" ""))
-         (match_operand:DI 2 "gpc_reg_operand" "")])
+  [(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC
+        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                           (match_operand:SI 2 "const_int_operand" ""))
+                (match_operand:DI 3 "const_int_operand" ""))
         (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_dup 4))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0) (match_dup 4))
-   (set (match_dup 3)
+       (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+  "TARGET_POWERPC64 && reload_completed
+   && includes_rldic_lshift_p (operands[2], operands[3])"
+  [(set (match_dup 0)
+       (and:DI (ashift:DI (match_dup 1) (match_dup 2))
+               (match_dup 3)))
+   (set (match_dup 4)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-(define_insn "*boolccdi3_internal1"
+(define_insn "*ashldi3_internal7"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (match_operator:DI 3 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
-         (not:DI (match_operand:DI 2 "gpc_reg_operand" "r"))]))]
-  "TARGET_POWERPC64"
-  "%q3 %0,%1,%2")
+       (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                          (match_operand:SI 2 "const_int_operand" "i"))
+               (match_operand:DI 3 "mask64_operand" "n")))]
+  "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
+  "rldicr %0,%1,%H2,%S3"
+  [(set_attr "type" "shift")])
 
-(define_insn "*boolccdi3_internal2"
+(define_insn "ashldi3_internal8"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
-         (not:DI (match_operand:DI 2 "gpc_reg_operand" "r,r"))])
+       (compare:CC
+        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                           (match_operand:SI 2 "const_int_operand" "i,i"))
+                (match_operand:DI 3 "mask64_operand" "n,n"))
         (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r"))]
-  "TARGET_64BIT"
+   (clobber (match_scratch:DI 4 "=r,r"))]
+  "TARGET_64BIT && includes_rldicr_lshift_p (operands[2], operands[3])"
   "@
-   %q4. %3,%1,%2
+   rldicr. %4,%1,%H2,%S3
    #"
-  [(set_attr "type" "fast_compare,compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" ""))
-         (not:DI (match_operand:DI 2 "gpc_reg_operand" ""))])
+       (compare:CC
+        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                           (match_operand:SI 2 "const_int_operand" ""))
+                (match_operand:DI 3 "mask64_operand" ""))
         (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3) (match_dup 4))
+   (clobber (match_scratch:DI 4 ""))]
+  "TARGET_POWERPC64 && reload_completed
+   && includes_rldicr_lshift_p (operands[2], operands[3])"
+  [(set (match_dup 4)
+       (and:DI (ashift:DI (match_dup 1) (match_dup 2))
+               (match_dup 3)))
    (set (match_dup 0)
-       (compare:CC (match_dup 3)
+       (compare:CC (match_dup 4)
                    (const_int 0)))]
   "")
 
-(define_insn "*boolccdi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r"))
-         (not:DI (match_operand:DI 2 "gpc_reg_operand" "r,r"))])
+(define_insn "*ashldi3_internal9"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+       (compare:CC
+        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+                           (match_operand:SI 2 "const_int_operand" "i,i"))
+                   (match_operand:DI 3 "mask64_operand" "n,n"))
         (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-       (match_dup 4))]
-  "TARGET_64BIT"
+       (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+  "TARGET_64BIT && includes_rldicr_lshift_p (operands[2], operands[3])"
   "@
-   %q4. %0,%1,%2
+   rldicr. %0,%1,%H2,%S3
    #"
-  [(set_attr "type" "fast_compare,compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
 (define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (match_operator:DI 4 "boolean_operator"
-        [(not:DI (match_operand:DI 1 "gpc_reg_operand" ""))
-         (not:DI (match_operand:DI 2 "gpc_reg_operand" ""))])
+  [(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "")
+       (compare:CC
+        (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                           (match_operand:SI 2 "const_int_operand" ""))
+                (match_operand:DI 3 "mask64_operand" ""))
         (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_dup 4))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0) (match_dup 4))
-   (set (match_dup 3)
+       (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+  "TARGET_POWERPC64 && reload_completed
+   && includes_rldicr_lshift_p (operands[2], operands[3])"
+  [(set (match_dup 0)
+       (and:DI (ashift:DI (match_dup 1) (match_dup 2))
+               (match_dup 3)))
+   (set (match_dup 4)
        (compare:CC (match_dup 0)
                    (const_int 0)))]
   "")
 
-;; Eqv operation.
-(define_insn "*eqv<mode>3"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
-       (not:GPR
-        (xor:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
-                 (match_operand:GPR 2 "gpc_reg_operand" "r"))))]
+
+(define_insn_and_split "*anddi3_2rld"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
+               (match_operand:DI 2 "and_2rld_operand" "n")))]
+  "TARGET_POWERPC64"
+  "#"
   ""
-  "eqv %0,%1,%2"
-  [(set_attr "type" "integer")
-   (set_attr "length" "4")])
+  [(set (match_dup 0)
+       (and:DI (rotate:DI (match_dup 1)
+                          (match_dup 4))
+               (match_dup 5)))
+   (set (match_dup 0)
+       (and:DI (rotate:DI (match_dup 0)
+                          (match_dup 6))
+               (match_dup 7)))]
+{
+  build_mask64_2_operands (operands[2], &operands[4]);
+}
+  [(set_attr "length" "8")])
+
+(define_insn_and_split "*anddi3_2rld_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
+                           (match_operand:DI 2 "and_2rld_operand" "n,n"))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 0 "=r,r"))]
+  "TARGET_64BIT && rs6000_gen_cell_microcode"
+  "@
+   #
+   #"
+  "&& reload_completed"
+  [(set (match_dup 0)
+       (and:DI (rotate:DI (match_dup 1)
+                          (match_dup 4))
+               (match_dup 5)))
+   (parallel [(set (match_dup 3)
+                  (compare:CC (and:DI (rotate:DI (match_dup 0)
+                                                 (match_dup 6))
+                                      (match_dup 7))
+                              (const_int 0)))
+             (clobber (match_dup 0))])]
+{
+  build_mask64_2_operands (operands[2], &operands[4]);
+}
+  [(set_attr "type" "compare")
+   (set_attr "dot" "yes")
+   (set_attr "length" "8,12")])
 
+(define_insn_and_split "*anddi3_2rld_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
+                           (match_operand:DI 2 "and_2rld_operand" "n,n"))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (and:DI (match_dup 1)
+               (match_dup 2)))]
+  "TARGET_64BIT && rs6000_gen_cell_microcode"
+  "@
+   #
+   #"
+  "&& reload_completed"
+  [(set (match_dup 0)
+       (and:DI (rotate:DI (match_dup 1)
+                          (match_dup 4))
+               (match_dup 5)))
+   (parallel [(set (match_dup 3)
+                  (compare:CC (and:DI (rotate:DI (match_dup 0)
+                                                 (match_dup 6))
+                                      (match_dup 7))
+                              (const_int 0)))
+             (set (match_dup 0)
+                  (and:DI (rotate:DI (match_dup 0)
+                                     (match_dup 6))
+                          (match_dup 7)))])]
+{
+  build_mask64_2_operands (operands[2], &operands[4]);
+}
+  [(set_attr "type" "compare")
+   (set_attr "dot" "yes")
+   (set_attr "length" "8,12")])
 \f
 ;; 128-bit logical operations expanders
 
 (define_expand "and<mode>3"
-  [(parallel [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
-                  (and:BOOL_128
-                   (match_operand:BOOL_128 1 "vlogical_operand" "")
-                   (match_operand:BOOL_128 2 "vlogical_operand" "")))
-             (clobber (match_scratch:CC 3 ""))])]
+  [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
+       (and:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")
+                     (match_operand:BOOL_128 2 "vlogical_operand" "")))]
   ""
   "")
 
   [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
         (and:BOOL_128
         (match_operand:BOOL_128 1 "vlogical_operand" "%<BOOL_REGS_OP1>")
-        (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>")))
-   (clobber (match_scratch:CC 3 "<BOOL_REGS_AND_CR0>"))]
+        (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>")))]
   ""
 {
   if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
   "reload_completed && int_reg_operand (operands[0], <MODE>mode)"
   [(const_int 0)]
 {
-  rs6000_split_logical (operands, AND, false, false, false, operands[3]);
+  rs6000_split_logical (operands, AND, false, false, false);
   DONE;
 }
   [(set (attr "type")
   "reload_completed && int_reg_operand (operands[0], <MODE>mode)"
   [(const_int 0)]
 {
-  rs6000_split_logical (operands, GET_CODE (operands[3]), false, false, false,
-                       NULL_RTX);
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, false, false);
   DONE;
 }
   [(set (attr "type")
    && reload_completed && int_reg_operand (operands[0], <MODE>mode)"
   [(const_int 0)]
 {
-  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false,
-                       NULL_RTX);
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false);
   DONE;
 }
   [(set (attr "type")
   "reload_completed && !TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
   [(const_int 0)]
 {
-  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false,
-                       NULL_RTX);
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false);
   DONE;
 }
   [(set_attr "type" "integer")
    && reload_completed && int_reg_operand (operands[0], <MODE>mode)"
   [(const_int 0)]
 {
-  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true,
-                       NULL_RTX);
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true);
   DONE;
 }
   [(set (attr "type")
   "reload_completed && !TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
   [(const_int 0)]
 {
-  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true,
-                       NULL_RTX);
+  rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true);
   DONE;
 }
   [(set_attr "type" "integer")
    && int_reg_operand (operands[0], <MODE>mode)"
   [(const_int 0)]
 {
-  rs6000_split_logical (operands, XOR, true, false, false, NULL_RTX);
+  rs6000_split_logical (operands, XOR, true, false, false);
   DONE;
 }
   [(set (attr "type")
   "reload_completed && !TARGET_P8_VECTOR"
   [(const_int 0)]
 {
-  rs6000_split_logical (operands, XOR, true, false, false, NULL_RTX);
+  rs6000_split_logical (operands, XOR, true, false, false);
   DONE;
 }
   [(set_attr "type" "integer")
   "reload_completed && int_reg_operand (operands[0], <MODE>mode)"
   [(const_int 0)]
 {
-  rs6000_split_logical (operands, NOT, false, false, false, NULL_RTX);
+  rs6000_split_logical (operands, NOT, false, false, false);
   DONE;
 }
   [(set (attr "type")
    mt%0 %1
    mt%0 %1
    nop"
-  [(set_attr_alternative "type"
-      [(const_string "*")
-       (const_string "*")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "store_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "store_u")
-          (const_string "store")))
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")
-       (const_string "mfjmpr")
-       (const_string "mtjmpr")
-       (const_string "*")
-       (const_string "*")])
-
+  [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*")
    (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4")])
 
 (define_insn "*movsi_internal1_single"
    nop
    stfs%U0%X0 %1,%0
    lfs%U1%X1 %0,%1"
-  [(set_attr_alternative "type"
-      [(const_string "*")
-       (const_string "*")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "store_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "store_u")
-          (const_string "store")))
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")
-       (const_string "mfjmpr")
-       (const_string "mtjmpr")
-       (const_string "*")
-       (const_string "*")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "fpstore_u")
-          (const_string "fpstore")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "fpload_u")
-          (const_string "fpload")))])
+  [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*,fpstore,fpload")
    (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")])
 
 ;; Split a load of a large constant into the appropriate two-insn
        (ior:SI (match_dup 0)
                (match_dup 3)))]
   "
-{ rtx tem = rs6000_emit_set_const (operands[0], SImode, operands[1], 2);
-
-  if (tem == operands[0])
+{
+  if (rs6000_emit_set_const (operands[0], operands[1]))
     DONE;
   else
     FAIL;
    cmp<wd>i %2,%0,0
    mr. %0,%1
    #"
-  [(set_attr "type" "cmp,fast_compare,cmp")
+  [(set_attr "type" "cmp,logical,cmp")
+   (set_attr "dot" "yes")
    (set_attr "length" "4,4,8")])
 
 (define_split
    mf%1 %0
    mt%0 %1
    nop"
-  [(set_attr_alternative "type"
-      [(const_string "*")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "store_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "store_u")
-          (const_string "store")))
-       (const_string "*")
-       (const_string "mfjmpr")
-       (const_string "mtjmpr")
-       (const_string "*")])])
+  [(set_attr "type" "*,load,store,*,mfjmpr,mtjmpr,*")])
 
 (define_expand "mov<mode>"
   [(set (match_operand:INT 0 "general_operand" "")
    mf%1 %0
    mt%0 %1
    nop"
-  [(set_attr_alternative "type"
-      [(const_string "*")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "store_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "store_u")
-          (const_string "store")))
-       (const_string "*")
-       (const_string "mfjmpr")
-       (const_string "mtjmpr")
-       (const_string "*")])])
+  [(set_attr "type" "*,load,store,*,mfjmpr,mtjmpr,*")])
 \f
 ;; Here is how to move condition codes around.  When we store CC data in
 ;; an integer register or memory, we store just the high-order 4 bits.
            (eq_attr "alternative" "9")
                (const_string "mtjmpr")
            (eq_attr "alternative" "10")
-               (if_then_else
-                 (match_test "update_indexed_address_mem (operands[1],
-                                                          VOIDmode)")
-                 (const_string "load_ux")
-                 (if_then_else
-                   (match_test "update_address_mem (operands[1], VOIDmode)")
-                   (const_string "load_u")
-                   (const_string "load")))
+               (const_string "load")
            (eq_attr "alternative" "11")
-               (if_then_else
-                 (match_test "update_indexed_address_mem (operands[0],
-                                                          VOIDmode)")
-                 (const_string "store_ux")
-                 (if_then_else
-                   (match_test "update_address_mem (operands[0], VOIDmode)")
-                   (const_string "store_u")
-                   (const_string "store")))
+               (const_string "store")
            (match_test "TARGET_MFCRF")
                (const_string "mfcrf")
           ]
    nop
    #
    #"
-  [(set_attr_alternative "type"
-      [(const_string "*")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "store_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "store_u")
-          (const_string "store")))
-       (const_string "fp")
-       (const_string "vecsimple")
-       (const_string "vecsimple")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "fpload_u")
-          (const_string "fpload")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "fpstore_u")
-          (const_string "fpstore")))
-       (const_string "fpload")
-       (const_string "fpstore")
-       (const_string "mftgpr")
-       (const_string "mffgpr")
-       (const_string "mtjmpr")
-       (const_string "mfjmpr")
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")])
+  [(set_attr "type" "*,load,store,fp,vecsimple,vecsimple,fpload,fpstore,fpload,fpstore,mftgpr,mffgpr,mtjmpr,mfjmpr,*,*,*")
    (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8")])
 
 (define_insn "*mov<mode>_softfloat"
    #
    #
    nop"
-  [(set_attr_alternative "type"
-      [(const_string "*")
-       (const_string "mtjmpr")
-       (const_string "mfjmpr")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "store_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "store_u")
-          (const_string "store")))
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")])
+  [(set_attr "type" "*,mtjmpr,mfjmpr,load,store,*,*,*,*,*")
    (set_attr "length" "4,4,4,4,4,4,4,4,8,4")])
 
 \f
    #
    #
    #"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "fpstore_u")
-          (const_string "fpstore")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "fpload_u")
-          (const_string "fpload")))
-       (const_string "fp")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (const_string "fpload"))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (const_string "fpstore"))
-       (const_string "vecsimple")
-       (const_string "vecsimple")
-       (const_string "store")
-       (const_string "load")
-       (const_string "two")
-       (const_string "fp")
-       (const_string "fp")
-       (const_string "*")])
+  [(set_attr "type" "fpstore,fpload,fp,fpload,fpstore,vecsimple,vecsimple,store,load,two,fp,fp,*")
    (set_attr "length" "4,4,4,4,4,4,4,8,8,8,8,12,16")])
 
 (define_insn "*mov<mode>_softfloat32"
   [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,r,r,r")
        (match_operand:FMOVE64 1 "input_operand" "r,Y,r,G,H,F"))]
   "! TARGET_POWERPC64 
-   && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) 
-       || TARGET_SOFT_FLOAT
+   && ((TARGET_FPRS && TARGET_SINGLE_FLOAT) 
+       || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE
        || (<MODE>mode == DDmode && TARGET_E500_DOUBLE))
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
 ; ld/std require word-aligned displacements -> 'Y' constraint.
 ; List Y->r and r->Y before r->r for reload.
 (define_insn "*mov<mode>_hardfloat64"
-  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wm")
-       (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wm,r"))]
+  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wk")
+       (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wk,r"))]
   "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
    mffgpr %0,%1
    mfvsrd %0,%x1
    mtvsrd %x0,%1"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "fpstore_u")
-          (const_string "fpstore")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "fpload_u")
-          (const_string "fpload")))
-       (const_string "fp")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (const_string "fpload"))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (const_string "fpstore"))
-       (const_string "vecsimple")
-       (const_string "vecsimple")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "store_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "store_u")
-          (const_string "store")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (const_string "*")
-       (const_string "mtjmpr")
-       (const_string "mfjmpr")
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")
-       (const_string "mftgpr")
-       (const_string "mffgpr")
-       (const_string "mftgpr")
-       (const_string "mffgpr")])
+  [(set_attr "type" "fpstore,fpload,fp,fpload,fpstore,vecsimple,vecsimple,store,load,*,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr,mftgpr,mffgpr")
    (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4,4,4")])
 
 (define_insn "*mov<mode>_softfloat64"
    #
    #
    nop"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "store_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "store_u")
-          (const_string "store")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (const_string "*")
-       (const_string "mtjmpr")
-       (const_string "mfjmpr")
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")])
+  [(set_attr "type" "store,load,*,mtjmpr,mfjmpr,*,*,*,*")
    (set_attr "length" "4,4,4,4,4,8,12,16,4")])
 \f
 (define_expand "mov<mode>"
    lfd%U1%X1 %0,%1
    fmr %0,%1
    #"
-  [(set_attr_alternative "type"
-      [(const_string "store")
-       (const_string "load")
-       (const_string "*")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "fpstore_u")
-          (const_string "fpstore")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "fpload_u")
-          (const_string "fpload")))
-       (const_string "fp")
-       (const_string "*")])])
+  [(set_attr "type" "store,load,*,fpstore,fpload,fp,*")])
 
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
 
 (define_insn "*movdi_internal64"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,r,*h,*h,r,?*wg,r,?*wm")
-       (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,*h,r,0,*wg,r,*wm,r"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,r,*h,*h,r,?*wg,r,?*wj,?*wi")
+       (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,*h,r,0,*wg,r,*wj,r,O"))]
   "TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], DImode)
        || gpc_reg_operand (operands[1], DImode))"
    mftgpr %0,%1
    mffgpr %0,%1
    mfvsrd %0,%x1
-   mtvsrd %x0,%1"
-  [(set_attr_alternative "type"
-      [(if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "store_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "store_u")
-          (const_string "store")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "load_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "load_u")
-          (const_string "load")))
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")
-       (const_string "*")
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[0], VOIDmode)")
-          (const_string "fpstore_u")
-          (const_string "fpstore")))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (if_then_else
-          (match_test "update_address_mem (operands[1], VOIDmode)")
-          (const_string "fpload_u")
-          (const_string "fpload")))
-       (const_string "fp")
-       (const_string "mfjmpr")
-       (const_string "mtjmpr")
-       (const_string "*")
-       (const_string "mftgpr")
-       (const_string "mffgpr")
-       (const_string "mftgpr")
-       (const_string "mffgpr")])
-   (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4,4")])
+   mtvsrd %x0,%1
+   xxlxor %x0,%x0,%x0"
+  [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,fp,mfjmpr,mtjmpr,*,mftgpr,mffgpr,mftgpr,mffgpr,vecsimple")
+   (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4,4,4")])
 
 ;; Generate all one-bits and clear left or right.
 ;; Use (and:DI (rotate:DI ...)) to avoid anddi3 unnecessary clobber.
   [(set (match_dup 0) (match_dup 2))
    (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
   "
-{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5);
-
-  if (tem == operands[0])
+{
+  if (rs6000_emit_set_const (operands[0], operands[1]))
     DONE;
   else
     FAIL;
 
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_double_operand" ""))]
+       (match_operand:DI 1 "const_scalar_int_operand" ""))]
   "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
   [(set (match_dup 0) (match_dup 2))
    (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
   "
-{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5);
-
-  if (tem == operands[0])
+{
+  if (rs6000_emit_set_const (operands[0], operands[1]))
     DONE;
   else
     FAIL;
       return \"#\";
     }
 }"
-  [(set_attr "type" "store_ux,store_ux,load_ux,load_ux,*,*")
+  [(set_attr "type" "store,store,load,load,*,*")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set (attr "cell_micro") (if_then_else (match_test "TARGET_STRING")
                                          (const_string "always")
                                          (const_string "conditional")))])
 
 (define_split
   [(set (match_operand:TI2 0 "int_reg_operand" "")
-       (match_operand:TI2 1 "const_double_operand" ""))]
+       (match_operand:TI2 1 "const_scalar_int_operand" ""))]
   "TARGET_POWERPC64
    && (VECTOR_MEM_NONE_P (<MODE>mode)
        || (reload_completed && INT_REGNO_P (REGNO (operands[0]))))"
                                       <MODE>mode);
   operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
                                       <MODE>mode);
-  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+  if (CONST_WIDE_INT_P (operands[1]))
     {
-      operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
-      operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+      operands[4] = GEN_INT (CONST_WIDE_INT_ELT (operands[1], 1));
+      operands[5] = GEN_INT (CONST_WIDE_INT_ELT (operands[1], 0));
     }
-  else if (GET_CODE (operands[1]) == CONST_INT)
+  else if (CONST_INT_P (operands[1]))
     {
       operands[4] = GEN_INT (- (INTVAL (operands[1]) < 0));
       operands[5] = operands[1];
   "TARGET_STRING && XVECLEN (operands[0], 0) == 8"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load_ux")
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi7"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 7"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load_ux")
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi6"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 6"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load_ux")
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi5"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 5"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load_ux")
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi4"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 4"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load_ux")
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "length" "32")])
 
 (define_insn "*ldmsi3"
   "TARGET_STRING && XVECLEN (operands[0], 0) == 3"
   "*
 { return rs6000_output_load_multiple (operands); }"
-  [(set_attr "type" "load_ux")
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "length" "32")])
 
 (define_expand "store_multiple"
          (match_operand:SI 10 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && XVECLEN (operands[0], 0) == 9"
   "stswi %2,%1,%O0"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")])
 
 (define_insn "*stmsi7"
          (match_operand:SI 9 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && XVECLEN (operands[0], 0) == 8"
   "stswi %2,%1,%O0"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")])
 
 (define_insn "*stmsi6"
          (match_operand:SI 8 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && XVECLEN (operands[0], 0) == 7"
   "stswi %2,%1,%O0"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")])
 
 (define_insn "*stmsi5"
          (match_operand:SI 7 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && XVECLEN (operands[0], 0) == 6"
   "stswi %2,%1,%O0"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")])
 
 (define_insn "*stmsi4"
          (match_operand:SI 6 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && XVECLEN (operands[0], 0) == 5"
   "stswi %2,%1,%O0"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")])
 
 (define_insn "*stmsi3"
          (match_operand:SI 5 "gpc_reg_operand" "r"))])]
   "TARGET_STRING && XVECLEN (operands[0], 0) == 4"
   "stswi %2,%1,%O0"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")])
 \f
 (define_expand "setmemsi"
    && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 12)
    && REGNO (operands[4]) == 5"
   "lswi %4,%1,%2\;stswi %4,%0,%2"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")
    (set_attr "length" "8")])
 
    && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 10)
    && REGNO (operands[4]) == 5"
   "lswi %4,%1,%2\;stswi %4,%0,%2"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")
    (set_attr "length" "8")])
 
    && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 8)
    && REGNO (operands[4]) == 5"
   "lswi %4,%1,%2\;stswi %4,%0,%2"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")
    (set_attr "length" "8")])
 
   "TARGET_STRING && ! TARGET_POWERPC64
    && INTVAL (operands[2]) > 4 && INTVAL (operands[2]) <= 8"
   "lswi %4,%1,%2\;stswi %4,%0,%2"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")
    (set_attr "length" "8")])
 
    (clobber (match_scratch:SI 5 "=X"))]
   "TARGET_STRING && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 4"
   "lswi %4,%1,%2\;stswi %4,%0,%2"
-  [(set_attr "type" "store_ux")
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")
    (set_attr "length" "8")])
 \f
   "@
    ldux %3,%0,%2
    ldu %3,%2(%0)"
-  [(set_attr "type" "load_ux,load_u")])
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "movdi_<mode>_update"
   [(set (mem:DI (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
   "@
    stdux %3,%0,%2
    stdu %3,%2(%0)"
-  [(set_attr "type" "store_ux,store_u")])
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 ;; This pattern is only conditional on TARGET_POWERPC64, as it is
 ;; needed for stack allocation, even if the user passes -mno-update.
   "@
    stdux %3,%0,%2
    stdu %3,%2(%0)"
-  [(set_attr "type" "store_ux,store_u")])
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movsi_update1"
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
   "@
    lwzux %3,%0,%2
    lwzu %3,%2(%0)"
-  [(set_attr "type" "load_ux,load_u")])
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movsi_update2"
   [(set (match_operand:DI 3 "gpc_reg_operand" "=r")
   "TARGET_POWERPC64 && rs6000_gen_cell_microcode
    && !avoiding_indexed_address_p (DImode)"
   "lwaux %3,%0,%2"
-  [(set_attr "type" "load_ext_ux")])
+  [(set_attr "type" "load")
+   (set_attr "sign_extend" "yes")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")])
 
 (define_insn "movsi_update"
   [(set (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
   "@
    stwux %3,%0,%2
    stwu %3,%2(%0)"
-  [(set_attr "type" "store_ux,store_u")])
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 ;; This is an unconditional pattern; needed for stack allocation, even
 ;; if the user passes -mno-update.
   "@
    stwux %3,%0,%2
    stwu %3,%2(%0)"
-  [(set_attr "type" "store_ux,store_u")])
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movhi_update1"
   [(set (match_operand:HI 3 "gpc_reg_operand" "=r,r")
   "@
    lhzux %3,%0,%2
    lhzu %3,%2(%0)"
-  [(set_attr "type" "load_ux,load_u")])
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movhi_update2"
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
   "@
    lhzux %3,%0,%2
    lhzu %3,%2(%0)"
-  [(set_attr "type" "load_ux,load_u")])
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movhi_update3"
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
   "@
    lhaux %3,%0,%2
    lhau %3,%2(%0)"
-  [(set_attr "type" "load_ext_ux,load_ext_u")])
+  [(set_attr "type" "load")
+   (set_attr "sign_extend" "yes")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movhi_update4"
   [(set (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
   "@
    sthux %3,%0,%2
    sthu %3,%2(%0)"
-  [(set_attr "type" "store_ux,store_u")])
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movqi_update1"
   [(set (match_operand:QI 3 "gpc_reg_operand" "=r,r")
   "@
    lbzux %3,%0,%2
    lbzu %3,%2(%0)"
-  [(set_attr "type" "load_ux,load_u")])
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movqi_update2"
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
   "@
    lbzux %3,%0,%2
    lbzu %3,%2(%0)"
-  [(set_attr "type" "load_ux,load_u")])
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movqi_update3"
   [(set (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
   "@
    stbux %3,%0,%2
    stbu %3,%2(%0)"
-  [(set_attr "type" "store_ux,store_u")])
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movsf_update1"
   [(set (match_operand:SF 3 "gpc_reg_operand" "=f,f")
   "@
    lfsux %3,%0,%2
    lfsu %3,%2(%0)"
-  [(set_attr "type" "fpload_ux,fpload_u")])
+  [(set_attr "type" "fpload")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movsf_update2"
   [(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
   "@
    stfsux %3,%0,%2
    stfsu %3,%2(%0)"
-  [(set_attr "type" "fpstore_ux,fpstore_u")])
+  [(set_attr "type" "fpstore")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movsf_update3"
   [(set (match_operand:SF 3 "gpc_reg_operand" "=r,r")
   "@
    lwzux %3,%0,%2
    lwzu %3,%2(%0)"
-  [(set_attr "type" "load_ux,load_u")])
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movsf_update4"
   [(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
   "@
    stwux %3,%0,%2
    stwu %3,%2(%0)"
-  [(set_attr "type" "store_ux,store_u")])
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movdf_update1"
   [(set (match_operand:DF 3 "gpc_reg_operand" "=d,d")
   "@
    lfdux %3,%0,%2
    lfdu %3,%2(%0)"
-  [(set_attr "type" "fpload_ux,fpload_u")])
+  [(set_attr "type" "fpload")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 (define_insn "*movdf_update2"
   [(set (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
   "@
    stfdux %3,%0,%2
    stfdu %3,%2(%0)"
-  [(set_attr "type" "fpstore_ux,fpstore_u")])
+  [(set_attr "type" "fpstore")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes,no")])
 
 
 ;; After inserting conditional returns we can sometimes have
   operands[2] = gen_rtx_REG (Pmode, 2);
   return \"lwz %0,%1(%2)\";
 }"
-  [(set_attr "type" "load")])
+  [(set_attr "type" "load")
+   (set_attr "update" "no")
+   (set_attr "indexed" "no")])
 
 (define_insn "load_toc_aix_di"
   [(parallel [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
   operands[2] = gen_rtx_REG (Pmode, 2);
   return \"ld %0,%1(%2)\";
 }"
-  [(set_attr "type" "load")])
+  [(set_attr "type" "load")
+   (set_attr "update" "no")
+   (set_attr "indexed" "no")])
 
 (define_insn "load_toc_v4_pic_si"
   [(set (reg:SI LR_REGNO)
   operands[1] = gen_rtx_REG (Pmode, 0);
   return "st<wd>%U0%X0 %1,%0";
 }
-  [(set (attr "type")
-      (if_then_else
-       (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-       (const_string "store_ux")
-       (if_then_else
-         (match_test "update_address_mem (operands[0], VOIDmode)")
-         (const_string "store_u")
-         (const_string "store"))))
+  [(set_attr "type" "store")
+   (set (attr "update")
+       (if_then_else (match_operand 0 "update_address_mem")
+                     (const_string "yes")
+                     (const_string "no")))
+   (set (attr "indexed")
+       (if_then_else (match_operand 0 "indexed_address_mem")
+                     (const_string "yes")
+                     (const_string "no")))
    (set_attr "length" "4")])
 
 (define_insn "probe_stack_range<P:mode>"
   "@
    mfcr %3%Q2\;rlwinm. %3,%3,%J1,1
    #"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "8,16")])
 
 (define_split
 
   return \"mfcr %4%Q2\;rlwinm. %4,%4,%5,%6,%6\";
 }"
-  [(set_attr "type" "delayed_compare")
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
    (set_attr "length" "8,16")])
 
 (define_split
                                 (match_operand:SI 2 "gpc_reg_operand" "r"))])]
   "TARGET_MULTIPLE"
   "stmw %2,%1"
-  [(set_attr "type" "store_ux")])
+  [(set_attr "type" "store")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")])
 
 ; The following comment applies to:
 ;     save_gpregs_*
                                 (match_operand:SI 2 "memory_operand" "m"))])]
   "TARGET_MULTIPLE"
   "lmw %1,%2"
-  [(set_attr "type" "load_ux")
+  [(set_attr "type" "load")
+   (set_attr "update" "yes")
+   (set_attr "indexed" "yes")
    (set_attr "cell_micro" "always")])
 
 (define_insn "*return_internal_<mode>"
 })
 
 \f
+;; Miscellaneous ISA 2.06 (power7) instructions
+(define_insn "addg6s"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+                   (match_operand:SI 2 "register_operand" "r")]
+                  UNSPEC_ADDG6S))]
+  "TARGET_POPCNTD"
+  "addg6s %0,%1,%2"
+  [(set_attr "type" "integer")
+   (set_attr "length" "4")])
+
+(define_insn "cdtbcd"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
+                  UNSPEC_CDTBCD))]
+  "TARGET_POPCNTD"
+  "cdtbcd %0,%1"
+  [(set_attr "type" "integer")
+   (set_attr "length" "4")])
+
+(define_insn "cbcdtd"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
+                  UNSPEC_CBCDTD))]
+  "TARGET_POPCNTD"
+  "cbcdtd %0,%1"
+  [(set_attr "type" "integer")
+   (set_attr "length" "4")])
+
+(define_int_iterator UNSPEC_DIV_EXTEND [UNSPEC_DIVE
+                                       UNSPEC_DIVEO
+                                       UNSPEC_DIVEU
+                                       UNSPEC_DIVEUO])
+
+(define_int_attr div_extend [(UNSPEC_DIVE      "e")
+                            (UNSPEC_DIVEO      "eo")
+                            (UNSPEC_DIVEU      "eu")
+                            (UNSPEC_DIVEUO     "euo")])
+
+(define_insn "div<div_extend>_<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+       (unspec:GPR [(match_operand:GPR 1 "register_operand" "r")
+                    (match_operand:GPR 2 "register_operand" "r")]
+                   UNSPEC_DIV_EXTEND))]
+  "TARGET_POPCNTD"
+  "div<wd><div_extend> %0,%1,%2"
+  [(set_attr "type" "div")
+   (set_attr "size" "<bits>")])
+
+\f
+;; Pack/unpack 128-bit floating point types that take 2 scalar registers
+
+; Type of the 64-bit part when packing/unpacking 128-bit floating point types
+(define_mode_attr FP128_64 [(TF "DF") (TD "DI")])
+
+(define_expand "unpack<mode>"
+  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "")
+       (unspec:<FP128_64>
+        [(match_operand:FMOVE128 1 "register_operand" "")
+         (match_operand:QI 2 "const_0_to_1_operand" "")]
+        UNSPEC_UNPACK_128BIT))]
+  ""
+  "")
+
+(define_insn_and_split "unpack<mode>_dm"
+  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m,d,r,m")
+       (unspec:<FP128_64>
+        [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r")
+         (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")]
+        UNSPEC_UNPACK_128BIT))]
+  "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 0) (match_dup 3))]
+{
+  unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]);
+
+  if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno)
+    {
+      emit_note (NOTE_INSN_DELETED);
+      DONE;
+    }
+
+  operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno);
+}
+  [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store")
+   (set_attr "length" "4")])
+
+(define_insn_and_split "unpack<mode>_nodm"
+  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m")
+       (unspec:<FP128_64>
+        [(match_operand:FMOVE128 1 "register_operand" "d,d")
+         (match_operand:QI 2 "const_0_to_1_operand" "i,i")]
+        UNSPEC_UNPACK_128BIT))]
+  "!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 0) (match_dup 3))]
+{
+  unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]);
+
+  if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno)
+    {
+      emit_note (NOTE_INSN_DELETED);
+      DONE;
+    }
+
+  operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno);
+}
+  [(set_attr "type" "fp,fpstore")
+   (set_attr "length" "4")])
+
+(define_insn_and_split "pack<mode>"
+  [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d")
+       (unspec:FMOVE128
+        [(match_operand:<FP128_64> 1 "register_operand" "0,d")
+         (match_operand:<FP128_64> 2 "register_operand" "d,d")]
+        UNSPEC_PACK_128BIT))]
+  ""
+  "@
+   fmr %L0,%2
+   #"
+  "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 4) (match_dup 2))]
+{
+  unsigned dest_hi = REGNO (operands[0]);
+  unsigned dest_lo = dest_hi + 1;
+
+  gcc_assert (!IN_RANGE (REGNO (operands[1]), dest_hi, dest_lo));
+  gcc_assert (!IN_RANGE (REGNO (operands[2]), dest_hi, dest_lo));
+
+  operands[3] = gen_rtx_REG (<FP128_64>mode, dest_hi);
+  operands[4] = gen_rtx_REG (<FP128_64>mode, dest_lo);
+}
+  [(set_attr "type" "fp,fp")
+   (set_attr "length" "4,8")])
+
+(define_insn "unpackv1ti"
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+       (unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa")
+                   (match_operand:QI 2 "const_0_to_1_operand" "O,i")]
+        UNSPEC_UNPACK_128BIT))]
+  "TARGET_VSX"
+{
+  if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0)
+    return ASM_COMMENT_START " xxpermdi to same register";
+
+  operands[3] = GEN_INT (INTVAL (operands[2]) == 0 ? 0 : 3);
+  return "xxpermdi %x0,%x1,%x1,%3";
+}
+  [(set_attr "type" "vecperm")
+   (set_attr "length" "4")])
+
+(define_insn "packv1ti"
+  [(set (match_operand:V1TI 0 "register_operand" "=wa")
+       (unspec:V1TI
+        [(match_operand:DI 1 "register_operand" "d")
+         (match_operand:DI 2 "register_operand" "d")]
+        UNSPEC_PACK_128BIT))]
+  "TARGET_VSX"
+  "xxpermdi %x0,%x1,%x2,0"
+  [(set_attr "type" "vecperm")
+   (set_attr "length" "4")])
+
+\f
 
 (include "sync.md")
 (include "vector.md")