OSDN Git Service

Revert:
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / mmx.md
index 3371161..af19732 100644 (file)
@@ -1,5 +1,5 @@
 ;; GCC machine description for MMX and 3dNOW! instructions
-;; Copyright (C) 2005, 2007
+;; Copyright (C) 2005, 2007, 2008, 2009
 ;; Free Software Foundation, Inc.
 ;;
 ;; This file is part of GCC.
 
 ;; 8 byte integral modes handled by MMX (and by extension, SSE)
 (define_mode_iterator MMXMODEI [V8QI V4HI V2SI])
+(define_mode_iterator MMXMODEI8 [V8QI V4HI V2SI V1DI])
 
 ;; All 8-byte vector modes handled by MMX
-(define_mode_iterator MMXMODE [V8QI V4HI V2SI V2SF])
+(define_mode_iterator MMXMODE [V8QI V4HI V2SI V1DI V2SF])
 
 ;; Mix-n-match
 (define_mode_iterator MMXMODE12 [V8QI V4HI])
 (define_mode_iterator MMXMODE24 [V4HI V2SI])
+(define_mode_iterator MMXMODE248 [V4HI V2SI V1DI])
 
 ;; Mapping from integer vector mode to mnemonic suffix
-(define_mode_attr mmxvecsize [(V8QI "b") (V4HI "w") (V2SI "d") (DI "q")])
+(define_mode_attr mmxvecsize [(V8QI "b") (V4HI "w") (V2SI "d") (V1DI "q")])
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
@@ -53,8 +55,8 @@
 ;; This is essential for maintaining stable calling conventions.
 
 (define_expand "mov<mode>"
-  [(set (match_operand:MMXMODEI 0 "nonimmediate_operand" "")
-       (match_operand:MMXMODEI 1 "nonimmediate_operand" ""))]
+  [(set (match_operand:MMXMODEI8 0 "nonimmediate_operand" "")
+       (match_operand:MMXMODEI8 1 "nonimmediate_operand" ""))]
   "TARGET_MMX"
 {
   ix86_expand_vector_move (<MODE>mode, operands);
 })
 
 (define_insn "*mov<mode>_internal_rex64"
-  [(set (match_operand:MMXMODEI 0 "nonimmediate_operand"
-                               "=rm,r,!y,!y ,m ,!y,Y2,x,x ,m,r,x")
-       (match_operand:MMXMODEI 1 "vector_move_operand"
-                               "Cr ,m,C ,!ym,!y,Y2,!y,C,xm,x,x,r"))]
+  [(set (match_operand:MMXMODEI8 0 "nonimmediate_operand"
+                               "=rm,r,!?y,!?y ,m  ,!y,*Y2,x,x ,m,r,Yi")
+       (match_operand:MMXMODEI8 1 "vector_move_operand"
+                               "Cr ,m,C  ,!?ym,!?y,*Y2,!y,C,xm,x,Yi,r"))]
   "TARGET_64BIT && TARGET_MMX
    && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "@
     movq\t{%1, %0|%0, %1}
     movdq2q\t{%1, %0|%0, %1}
     movq2dq\t{%1, %0|%0, %1}
-    pxor\t%0, %0
-    movq\t{%1, %0|%0, %1}
-    movq\t{%1, %0|%0, %1}
-    movd\t{%1, %0|%0, %1}
-    movd\t{%1, %0|%0, %1}"
+    %vpxor\t%0, %d0
+    %vmovq\t{%1, %0|%0, %1}
+    %vmovq\t{%1, %0|%0, %1}
+    %vmovq\t{%1, %0|%0, %1}
+    %vmovq\t{%1, %0|%0, %1}"
   [(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,ssemov")
    (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*")
+   (set_attr "prefix_rep" "*,*,*,*,*,1,1,*,1,*,*,*")
+   (set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,1,1,1")
+   (set (attr "prefix_rex")
+     (if_then_else (eq_attr "alternative" "8,9")
+       (symbol_ref "x86_extended_reg_mentioned_p (insn)")
+       (const_string "*")))
+   (set (attr "prefix")
+     (if_then_else (eq_attr "alternative" "7,8,9,10,11")
+       (const_string "maybe_vex")
+       (const_string "orig")))
    (set_attr "mode" "DI")])
 
+(define_insn "*mov<mode>_internal_avx"
+  [(set (match_operand:MMXMODEI8 0 "nonimmediate_operand"
+                       "=!?y,!?y,m  ,!y ,*Y2,*Y2,*Y2 ,m  ,r  ,m")
+       (match_operand:MMXMODEI8 1 "vector_move_operand"
+                       "C   ,!ym,!?y,*Y2,!y ,C  ,*Y2m,*Y2,irm,r"))]
+  "TARGET_AVX
+   && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  "@
+    pxor\t%0, %0
+    movq\t{%1, %0|%0, %1}
+    movq\t{%1, %0|%0, %1}
+    movdq2q\t{%1, %0|%0, %1}
+    movq2dq\t{%1, %0|%0, %1}
+    vpxor\t%0, %0, %0
+    vmovq\t{%1, %0|%0, %1}
+    vmovq\t{%1, %0|%0, %1}
+    #
+    #"
+  [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,*,*")
+   (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*")
+   (set_attr "prefix_rep" "*,*,*,1,1,*,*,*,*,*")
+   (set (attr "prefix")
+     (if_then_else (eq_attr "alternative" "5,6,7")
+       (const_string "vex")
+       (const_string "orig")))
+   (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,DI,DI,DI")])
+
 (define_insn "*mov<mode>_internal"
-  [(set (match_operand:MMXMODEI 0 "nonimmediate_operand"
-                       "=!y,!y ,m ,!y ,*Y2,*Y2,*Y2 ,m  ,*x,*x,*x,m ,?r ,?m")
-       (match_operand:MMXMODEI 1 "vector_move_operand"
-                       "C  ,!ym,!y,*Y2,!y ,C  ,*Y2m,*Y2,C ,*x,m ,*x,irm,r"))]
+  [(set (match_operand:MMXMODEI8 0 "nonimmediate_operand"
+                       "=!?y,!?y,m  ,!y ,*Y2,*Y2,*Y2 ,m  ,*x,*x,*x,m ,r  ,m")
+       (match_operand:MMXMODEI8 1 "vector_move_operand"
+                       "C   ,!ym,!?y,*Y2,!y ,C  ,*Y2m,*Y2,C ,*x,m ,*x,irm,r"))]
   "TARGET_MMX
    && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "@
     #"
   [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov,*,*")
    (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*,*,*,*")
+   (set_attr "prefix_rep" "*,*,*,1,1,*,1,*,*,*,*,*,*,*")
+   (set_attr "prefix_data16" "*,*,*,*,*,*,*,1,*,*,*,*,*,*")
    (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
 
 (define_expand "movv2sf"
   DONE;
 })
 
+(define_insn "*movv2sf_internal_rex64_avx"
+  [(set (match_operand:V2SF 0 "nonimmediate_operand"
+                               "=rm,r ,!?y,!?y ,m ,!y,Y2,x,x,x,m,r,x")
+        (match_operand:V2SF 1 "vector_move_operand"
+                               "Cr ,m ,C  ,!?ym,!y,Y2,!y,C,x,m,x,x,r"))]
+  "TARGET_64BIT && TARGET_AVX
+   && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  "@
+    mov{q}\t{%1, %0|%0, %1}
+    mov{q}\t{%1, %0|%0, %1}
+    pxor\t%0, %0
+    movq\t{%1, %0|%0, %1}
+    movq\t{%1, %0|%0, %1}
+    movdq2q\t{%1, %0|%0, %1}
+    movq2dq\t{%1, %0|%0, %1}
+    vxorps\t%0, %0, %0
+    vmovaps\t{%1, %0|%0, %1}
+    vmovlps\t{%1, %0, %0|%0, %0, %1}
+    vmovlps\t{%1, %0|%0, %1}
+    vmovq\t{%1, %0|%0, %1}
+    vmovq\t{%1, %0|%0, %1}"
+  [(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,sselog1,ssemov,ssemov,ssemov,ssemov")
+   (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*,*")
+   (set_attr "prefix_rep" "*,*,*,*,*,1,1,*,*,*,*,*,*")
+   (set_attr "length_vex" "*,*,*,*,*,*,*,*,*,*,*,4,4")
+   (set (attr "prefix")
+     (if_then_else (eq_attr "alternative" "7,8,9,10,11,12")
+       (const_string "vex")
+       (const_string "orig")))
+   (set_attr "mode" "DI,DI,DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
+
 (define_insn "*movv2sf_internal_rex64"
   [(set (match_operand:V2SF 0 "nonimmediate_operand"
-                               "=rm,r,!y ,!y ,m ,!y,Y2,x,x,x,m,r,x")
+                               "=rm,r ,!?y,!?y ,m ,!y,*Y2,x,x,x,m,r,Yi")
         (match_operand:V2SF 1 "vector_move_operand"
-                               "Cr ,m ,C ,!ym,!y,Y2,!y,C,x,m,x,x,r"))]
+                               "Cr ,m ,C  ,!?ym,!y,*Y2,!y,C,x,m,x,Yi,r"))]
   "TARGET_64BIT && TARGET_MMX
    && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "@
     movd\t{%1, %0|%0, %1}"
   [(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,sselog1,ssemov,ssemov,ssemov,ssemov")
    (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*,*")
+   (set_attr "prefix_rep" "*,*,*,*,*,1,1,*,*,*,*,*,*")
    (set_attr "mode" "DI,DI,DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
 
+(define_insn "*movv2sf_internal_avx"
+  [(set (match_operand:V2SF 0 "nonimmediate_operand"
+                       "=!?y,!?y ,m  ,!y ,*Y2,*x,*x,*x,m ,r  ,m")
+        (match_operand:V2SF 1 "vector_move_operand"
+                       "C   ,!?ym,!?y,*Y2,!y ,C ,*x,m ,*x,irm,r"))]
+  "TARGET_AVX
+   && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  "@
+    pxor\t%0, %0
+    movq\t{%1, %0|%0, %1}
+    movq\t{%1, %0|%0, %1}
+    movdq2q\t{%1, %0|%0, %1}
+    movq2dq\t{%1, %0|%0, %1}
+    vxorps\t%0, %0, %0
+    vmovaps\t{%1, %0|%0, %1}
+    vmovlps\t{%1, %0, %0|%0, %0, %1}
+    vmovlps\t{%1, %0|%0, %1}
+    #
+    #"
+  [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,*,*")
+   (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*")
+   (set_attr "prefix_rep" "*,*,*,1,1,*,*,*,*,*,*")
+   (set (attr "prefix")
+     (if_then_else (eq_attr "alternative" "5,6,7,8")
+       (const_string "vex")
+       (const_string "orig")))
+   (set_attr "mode" "DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
+
 (define_insn "*movv2sf_internal"
   [(set (match_operand:V2SF 0 "nonimmediate_operand"
-                       "=!y,!y ,m,!y ,*Y2,*x,*x,*x,m ,?r ,?m")
+                       "=!?y,!?y ,m  ,!y ,*Y2,*x,*x,*x,m ,r  ,m")
         (match_operand:V2SF 1 "vector_move_operand"
-                       "C ,!ym,!y,*Y2,!y ,C ,*x,m ,*x,irm,r"))]
+                       "C   ,!?ym,!?y,*Y2,!y ,C ,*x,m ,*x,irm,r"))]
   "TARGET_MMX
    && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "@
     #"
   [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,*,*")
    (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*")
+   (set_attr "prefix_rep" "*,*,*,1,1,*,*,*,*,*,*")
    (set_attr "mode" "DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
 
 ;; %%% This multiword shite has got to go.
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(define_insn "mmx_addv2sf3"
+(define_expand "mmx_addv2sf3"
+  [(set (match_operand:V2SF 0 "register_operand" "")
+       (plus:V2SF
+         (match_operand:V2SF 1 "nonimmediate_operand" "")
+         (match_operand:V2SF 2 "nonimmediate_operand" "")))]
+  "TARGET_3DNOW"
+  "ix86_fixup_binary_operands_no_copy (PLUS, V2SFmode, operands);")
+
+(define_insn "*mmx_addv2sf3"
   [(set (match_operand:V2SF 0 "register_operand" "=y")
        (plus:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
                   (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
   "TARGET_3DNOW && ix86_binary_operator_ok (PLUS, V2SFmode, operands)"
-  "pfadd\\t{%2, %0|%0, %2}"
+  "pfadd\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
-(define_insn "mmx_subv2sf3"
+(define_expand "mmx_subv2sf3"
+  [(set (match_operand:V2SF 0 "register_operand" "")
+        (minus:V2SF (match_operand:V2SF 1 "register_operand" "")
+                   (match_operand:V2SF 2 "nonimmediate_operand" "")))]
+  "TARGET_3DNOW"
+  "")
+
+(define_expand "mmx_subrv2sf3"
+  [(set (match_operand:V2SF 0 "register_operand" "")
+        (minus:V2SF (match_operand:V2SF 2 "register_operand" "")
+                   (match_operand:V2SF 1 "nonimmediate_operand" "")))]
+  "TARGET_3DNOW"
+  "")
+
+(define_insn "*mmx_subv2sf3"
   [(set (match_operand:V2SF 0 "register_operand" "=y,y")
         (minus:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "0,ym")
                    (match_operand:V2SF 2 "nonimmediate_operand" "ym,0")))]
   "TARGET_3DNOW && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "@
-   pfsub\\t{%2, %0|%0, %2}
-   pfsubr\\t{%2, %0|%0, %2}"
+   pfsub\t{%2, %0|%0, %2}
+   pfsubr\t{%1, %0|%0, %1}"
   [(set_attr "type" "mmxadd")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
-(define_expand "mmx_subrv2sf3"
+(define_expand "mmx_mulv2sf3"
   [(set (match_operand:V2SF 0 "register_operand" "")
-        (minus:V2SF (match_operand:V2SF 2 "nonimmediate_operand" "")
-                   (match_operand:V2SF 1 "nonimmediate_operand" "")))]
-  "TARGET_3DNOW && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
-  "")
+       (mult:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "")
+                  (match_operand:V2SF 2 "nonimmediate_operand" "")))]
+  "TARGET_3DNOW"
+  "ix86_fixup_binary_operands_no_copy (MULT, V2SFmode, operands);")
 
-(define_insn "mmx_mulv2sf3"
+(define_insn "*mmx_mulv2sf3"
   [(set (match_operand:V2SF 0 "register_operand" "=y")
        (mult:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
                   (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
   "TARGET_3DNOW && ix86_binary_operator_ok (MULT, V2SFmode, operands)"
-  "pfmul\\t{%2, %0|%0, %2}"
+  "pfmul\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxmul")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
-(define_insn "mmx_smaxv2sf3"
+;; ??? For !flag_finite_math_only, the representation with SMIN/SMAX
+;; isn't really correct, as those rtl operators aren't defined when
+;; applied to NaNs.  Hopefully the optimizers won't get too smart on us.
+
+(define_expand "mmx_<code>v2sf3"
+  [(set (match_operand:V2SF 0 "register_operand" "")
+        (smaxmin:V2SF
+         (match_operand:V2SF 1 "nonimmediate_operand" "")
+         (match_operand:V2SF 2 "nonimmediate_operand" "")))]
+  "TARGET_3DNOW"
+{
+  if (!flag_finite_math_only)
+    operands[1] = force_reg (V2SFmode, operands[1]);
+  ix86_fixup_binary_operands_no_copy (<CODE>, V2SFmode, operands);
+})
+
+(define_insn "*mmx_<code>v2sf3_finite"
   [(set (match_operand:V2SF 0 "register_operand" "=y")
-        (smax:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
-                   (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
-  "TARGET_3DNOW && ix86_binary_operator_ok (SMAX, V2SFmode, operands)"
-  "pfmax\\t{%2, %0|%0, %2}"
+        (smaxmin:V2SF
+         (match_operand:V2SF 1 "nonimmediate_operand" "%0")
+         (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+  "TARGET_3DNOW && flag_finite_math_only
+   && ix86_binary_operator_ok (<CODE>, V2SFmode, operands)"
+  "pf<maxmin_float>\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
-(define_insn "mmx_sminv2sf3"
+(define_insn "*mmx_<code>v2sf3"
   [(set (match_operand:V2SF 0 "register_operand" "=y")
-        (smin:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
-                   (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
-  "TARGET_3DNOW && ix86_binary_operator_ok (SMIN, V2SFmode, operands)"
-  "pfmin\\t{%2, %0|%0, %2}"
+        (smaxmin:V2SF
+         (match_operand:V2SF 1 "register_operand" "0")
+         (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+  "TARGET_3DNOW"
+  "pf<maxmin_float>\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_rcpv2sf2"
         (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
                     UNSPEC_PFRCP))]
   "TARGET_3DNOW"
-  "pfrcp\\t{%1, %0|%0, %1}"
+  "pfrcp\t{%1, %0|%0, %1}"
   [(set_attr "type" "mmx")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_rcpit1v2sf3"
                      (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
                     UNSPEC_PFRCPIT1))]
   "TARGET_3DNOW"
-  "pfrcpit1\\t{%2, %0|%0, %2}"
+  "pfrcpit1\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmx")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_rcpit2v2sf3"
                      (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
                     UNSPEC_PFRCPIT2))]
   "TARGET_3DNOW"
-  "pfrcpit2\\t{%2, %0|%0, %2}"
+  "pfrcpit2\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmx")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_rsqrtv2sf2"
        (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
                     UNSPEC_PFRSQRT))]
   "TARGET_3DNOW"
-  "pfrsqrt\\t{%1, %0|%0, %1}"
+  "pfrsqrt\t{%1, %0|%0, %1}"
   [(set_attr "type" "mmx")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_rsqit1v2sf3"
                      (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
                     UNSPEC_PFRSQIT1))]
   "TARGET_3DNOW"
-  "pfrsqit1\\t{%2, %0|%0, %2}"
+  "pfrsqit1\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmx")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_haddv2sf3"
              (parallel [(const_int  0)]))
            (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))))]
   "TARGET_3DNOW"
-  "pfacc\\t{%2, %0|%0, %2}"
+  "pfacc\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_hsubv2sf3"
              (parallel [(const_int  0)]))
            (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))))]
   "TARGET_3DNOW_A"
-  "pfnacc\\t{%2, %0|%0, %2}"
+  "pfnacc\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_addsubv2sf3"
           (minus:V2SF (match_dup 1) (match_dup 2))
           (const_int 1)))]
   "TARGET_3DNOW_A"
-  "pfpnacc\\t{%2, %0|%0, %2}"
+  "pfpnacc\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(define_insn "mmx_gtv2sf3"
+(define_expand "mmx_eqv2sf3"
+  [(set (match_operand:V2SI 0 "register_operand" "")
+       (eq:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "")
+                (match_operand:V2SF 2 "nonimmediate_operand" "")))]
+  "TARGET_3DNOW"
+  "ix86_fixup_binary_operands_no_copy (EQ, V2SFmode, operands);")
+
+(define_insn "*mmx_eqv2sf3"
   [(set (match_operand:V2SI 0 "register_operand" "=y")
-       (gt:V2SI (match_operand:V2SF 1 "register_operand" "0")
+       (eq:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "%0")
                 (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
-  "TARGET_3DNOW"
-  "pfcmpgt\\t{%2, %0|%0, %2}"
+  "TARGET_3DNOW && ix86_binary_operator_ok (EQ, V2SFmode, operands)"
+  "pfcmpeq\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxcmp")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
-(define_insn "mmx_gev2sf3"
+(define_insn "mmx_gtv2sf3"
   [(set (match_operand:V2SI 0 "register_operand" "=y")
-       (ge:V2SI (match_operand:V2SF 1 "register_operand" "0")
+       (gt:V2SI (match_operand:V2SF 1 "register_operand" "0")
                 (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
   "TARGET_3DNOW"
-  "pfcmpge\\t{%2, %0|%0, %2}"
+  "pfcmpgt\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxcmp")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
-(define_insn "mmx_eqv2sf3"
+(define_insn "mmx_gev2sf3"
   [(set (match_operand:V2SI 0 "register_operand" "=y")
-       (eq:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "%0")
+       (ge:V2SI (match_operand:V2SF 1 "register_operand" "0")
                 (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
-  "TARGET_3DNOW && ix86_binary_operator_ok (EQ, V2SFmode, operands)"
-  "pfcmpeq\\t{%2, %0|%0, %2}"
+  "TARGET_3DNOW"
+  "pfcmpge\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxcmp")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   [(set (match_operand:V2SI 0 "register_operand" "=y")
        (fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))]
   "TARGET_3DNOW"
-  "pf2id\\t{%1, %0|%0, %1}"
+  "pf2id\t{%1, %0|%0, %1}"
   [(set_attr "type" "mmxcvt")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_pf2iw"
            (fix:V2SI
              (match_operand:V2SF 1 "nonimmediate_operand" "ym")))))]
   "TARGET_3DNOW_A"
-  "pf2iw\\t{%1, %0|%0, %1}"
+  "pf2iw\t{%1, %0|%0, %1}"
   [(set_attr "type" "mmxcvt")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_pi2fw"
            (truncate:V2HI
              (match_operand:V2SI 1 "nonimmediate_operand" "ym")))))]
   "TARGET_3DNOW_A"
-  "pi2fw\\t{%1, %0|%0, %1}"
+  "pi2fw\t{%1, %0|%0, %1}"
   [(set_attr "type" "mmxcvt")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "mmx_floatv2si2"
   [(set (match_operand:V2SF 0 "register_operand" "=y")
        (float:V2SF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))]
   "TARGET_3DNOW"
-  "pi2fd\\t{%1, %0|%0, %1}"
+  "pi2fd\t{%1, %0|%0, %1}"
   [(set_attr "type" "mmxcvt")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        (vec_select:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "ym")
                         (parallel [(const_int 1) (const_int 0)])))]
   "TARGET_3DNOW_A"
-  "pswapd\\t{%1, %0|%0, %1}"
+  "pswapd\t{%1, %0|%0, %1}"
   [(set_attr "type" "mmxcvt")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "V2SF")])
 
 (define_insn "*vec_dupv2sf"
   DONE;
 })
 
+;; Avoid combining registers from different units in a single alternative,
+;; see comment above inline_secondary_memory_needed function in i386.c
 (define_insn_and_split "*vec_extractv2sf_0"
-  [(set (match_operand:SF 0 "nonimmediate_operand"     "=x,y,m,m,frxy")
+  [(set (match_operand:SF 0 "nonimmediate_operand"     "=x, m,y ,m,f,r")
        (vec_select:SF
-         (match_operand:V2SF 1 "nonimmediate_operand" " x,y,x,y,m")
+         (match_operand:V2SF 1 "nonimmediate_operand" " xm,x,ym,y,m,m")
          (parallel [(const_int 0)])))]
   "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "#"
   DONE;
 })
 
+;; Avoid combining registers from different units in a single alternative,
+;; see comment above inline_secondary_memory_needed function in i386.c
 (define_insn "*vec_extractv2sf_1"
-  [(set (match_operand:SF 0 "nonimmediate_operand"     "=y,x,frxy")
+  [(set (match_operand:SF 0 "nonimmediate_operand"     "=y,x,y,x,f,r")
        (vec_select:SF
-         (match_operand:V2SF 1 "nonimmediate_operand" " 0,0,o")
+         (match_operand:V2SF 1 "nonimmediate_operand" " 0,0,o,o,o,o")
          (parallel [(const_int 1)])))]
   "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "@
    punpckhdq\t%0, %0
    unpckhps\t%0, %0
+   #
+   #
+   #
    #"
-  [(set_attr "type" "mmxcvt,sselog1,*")
-   (set_attr "mode" "DI,V4SF,SI")])
+  [(set_attr "type" "mmxcvt,sselog1,mmxmov,ssemov,fmov,imov")
+   (set_attr "mode" "DI,V4SF,SF,SF,SF,SF")])
 
 (define_split
   [(set (match_operand:SF 0 "register_operand" "")
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(define_insn "mmx_add<mode>3"
-  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
-        (plus:MMXMODEI
-         (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
-         (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
-  "TARGET_MMX && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
-  "padd<mmxvecsize>\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
-
-(define_insn "mmx_adddi3"
-  [(set (match_operand:DI 0 "register_operand" "=y")
-        (unspec:DI
-        [(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
-                  (match_operand:DI 2 "nonimmediate_operand" "ym"))]
-        UNSPEC_NOP))]
-  "TARGET_SSE2 && ix86_binary_operator_ok (PLUS, DImode, operands)"
-  "paddq\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
-
-(define_insn "mmx_ssadd<mode>3"
-  [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
-        (ss_plus:MMXMODE12
-         (match_operand:MMXMODE12 1 "nonimmediate_operand" "%0")
-         (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
-  "TARGET_MMX"
-  "padds<mmxvecsize>\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
-
-(define_insn "mmx_usadd<mode>3"
-  [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
-        (us_plus:MMXMODE12
-         (match_operand:MMXMODE12 1 "nonimmediate_operand" "%0")
-         (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
-  "TARGET_MMX"
-  "paddus<mmxvecsize>\t{%2, %0|%0, %2}"
+(define_expand "mmx_<plusminus_insn><mode>3"
+  [(set (match_operand:MMXMODEI8 0 "register_operand" "")
+       (plusminus:MMXMODEI8
+         (match_operand:MMXMODEI8 1 "nonimmediate_operand" "")
+         (match_operand:MMXMODEI8 2 "nonimmediate_operand" "")))]
+  "TARGET_MMX || (TARGET_SSE2 && <MODE>mode == V1DImode)"
+  "ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
+
+(define_insn "*mmx_<plusminus_insn><mode>3"
+  [(set (match_operand:MMXMODEI8 0 "register_operand" "=y")
+        (plusminus:MMXMODEI8
+         (match_operand:MMXMODEI8 1 "nonimmediate_operand" "<comm>0")
+         (match_operand:MMXMODEI8 2 "nonimmediate_operand" "ym")))]
+  "(TARGET_MMX || (TARGET_SSE2 && <MODE>mode == V1DImode))
+   && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+  "p<plusminus_mnemonic><mmxvecsize>\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_sub<mode>3"
-  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
-        (minus:MMXMODEI
-         (match_operand:MMXMODEI 1 "register_operand" "0")
-         (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
+(define_expand "mmx_<plusminus_insn><mode>3"
+  [(set (match_operand:MMXMODE12 0 "register_operand" "")
+       (sat_plusminus:MMXMODE12
+         (match_operand:MMXMODE12 1 "nonimmediate_operand" "")
+         (match_operand:MMXMODE12 2 "nonimmediate_operand" "")))]
   "TARGET_MMX"
-  "psub<mmxvecsize>\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
-
-(define_insn "mmx_subdi3"
-  [(set (match_operand:DI 0 "register_operand" "=y")
-        (unspec:DI
-        [(minus:DI (match_operand:DI 1 "register_operand" "0")
-                   (match_operand:DI 2 "nonimmediate_operand" "ym"))]
-        UNSPEC_NOP))]
-  "TARGET_SSE2"
-  "psubq\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
+  "ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
 
-(define_insn "mmx_sssub<mode>3"
+(define_insn "*mmx_<plusminus_insn><mode>3"
   [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
-        (ss_minus:MMXMODE12
-         (match_operand:MMXMODE12 1 "register_operand" "0")
+        (sat_plusminus:MMXMODE12
+         (match_operand:MMXMODE12 1 "nonimmediate_operand" "<comm>0")
          (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
-  "TARGET_MMX"
-  "psubs<mmxvecsize>\t{%2, %0|%0, %2}"
+  "TARGET_MMX && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+  "p<plusminus_mnemonic><mmxvecsize>\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_ussub<mode>3"
-  [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
-        (us_minus:MMXMODE12
-         (match_operand:MMXMODE12 1 "register_operand" "0")
-         (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
+(define_expand "mmx_mulv4hi3"
+  [(set (match_operand:V4HI 0 "register_operand" "")
+        (mult:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "")
+                  (match_operand:V4HI 2 "nonimmediate_operand" "")))]
   "TARGET_MMX"
-  "psubus<mmxvecsize>\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
+  "ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
 
-(define_insn "mmx_mulv4hi3"
+(define_insn "*mmx_mulv4hi3"
   [(set (match_operand:V4HI 0 "register_operand" "=y")
         (mult:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
                   (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
   [(set_attr "type" "mmxmul")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_smulv4hi3_highpart"
+(define_expand "mmx_smulv4hi3_highpart"
+  [(set (match_operand:V4HI 0 "register_operand" "")
+       (truncate:V4HI
+         (lshiftrt:V4SI
+           (mult:V4SI
+             (sign_extend:V4SI
+               (match_operand:V4HI 1 "nonimmediate_operand" ""))
+             (sign_extend:V4SI
+               (match_operand:V4HI 2 "nonimmediate_operand" "")))
+           (const_int 16))))]
+  "TARGET_MMX"
+  "ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
+
+(define_insn "*mmx_smulv4hi3_highpart"
   [(set (match_operand:V4HI 0 "register_operand" "=y")
        (truncate:V4HI
-        (lshiftrt:V4SI
-         (mult:V4SI (sign_extend:V4SI
-                     (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
-                    (sign_extend:V4SI
-                     (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
-         (const_int 16))))]
+         (lshiftrt:V4SI
+           (mult:V4SI
+             (sign_extend:V4SI
+               (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+             (sign_extend:V4SI
+               (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+           (const_int 16))))]
   "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
   "pmulhw\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxmul")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_umulv4hi3_highpart"
+(define_expand "mmx_umulv4hi3_highpart"
+  [(set (match_operand:V4HI 0 "register_operand" "")
+       (truncate:V4HI
+         (lshiftrt:V4SI
+           (mult:V4SI
+             (zero_extend:V4SI
+               (match_operand:V4HI 1 "nonimmediate_operand" ""))
+             (zero_extend:V4SI
+               (match_operand:V4HI 2 "nonimmediate_operand" "")))
+           (const_int 16))))]
+  "TARGET_SSE || TARGET_3DNOW_A"
+  "ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
+
+(define_insn "*mmx_umulv4hi3_highpart"
   [(set (match_operand:V4HI 0 "register_operand" "=y")
        (truncate:V4HI
-        (lshiftrt:V4SI
-         (mult:V4SI (zero_extend:V4SI
-                     (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
-                    (zero_extend:V4SI
-                     (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+         (lshiftrt:V4SI
+           (mult:V4SI
+             (zero_extend:V4SI
+               (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+             (zero_extend:V4SI
+               (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
          (const_int 16))))]
   "(TARGET_SSE || TARGET_3DNOW_A)
    && ix86_binary_operator_ok (MULT, V4HImode, operands)"
   [(set_attr "type" "mmxmul")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_pmaddwd"
+(define_expand "mmx_pmaddwd"
+  [(set (match_operand:V2SI 0 "register_operand" "")
+        (plus:V2SI
+         (mult:V2SI
+           (sign_extend:V2SI
+             (vec_select:V2HI
+               (match_operand:V4HI 1 "nonimmediate_operand" "")
+               (parallel [(const_int 0) (const_int 2)])))
+           (sign_extend:V2SI
+             (vec_select:V2HI
+               (match_operand:V4HI 2 "nonimmediate_operand" "")
+               (parallel [(const_int 0) (const_int 2)]))))
+         (mult:V2SI
+           (sign_extend:V2SI
+             (vec_select:V2HI (match_dup 1)
+               (parallel [(const_int 1) (const_int 3)])))
+           (sign_extend:V2SI
+             (vec_select:V2HI (match_dup 2)
+               (parallel [(const_int 1) (const_int 3)]))))))]
+  "TARGET_MMX"
+  "ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
+
+(define_insn "*mmx_pmaddwd"
   [(set (match_operand:V2SI 0 "register_operand" "=y")
         (plus:V2SI
          (mult:V2SI
   [(set_attr "type" "mmxmul")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_pmulhrwv4hi3"
+(define_expand "mmx_pmulhrwv4hi3"
+  [(set (match_operand:V4HI 0 "register_operand" "")
+       (truncate:V4HI
+         (lshiftrt:V4SI
+           (plus:V4SI
+             (mult:V4SI
+               (sign_extend:V4SI
+                 (match_operand:V4HI 1 "nonimmediate_operand" ""))
+               (sign_extend:V4SI
+                 (match_operand:V4HI 2 "nonimmediate_operand" "")))
+             (const_vector:V4SI [(const_int 32768) (const_int 32768)
+                                 (const_int 32768) (const_int 32768)]))
+           (const_int 16))))]
+  "TARGET_3DNOW"
+  "ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
+
+(define_insn "*mmx_pmulhrwv4hi3"
   [(set (match_operand:V4HI 0 "register_operand" "=y")
        (truncate:V4HI
          (lshiftrt:V4SI
                                  (const_int 32768) (const_int 32768)]))
            (const_int 16))))]
   "TARGET_3DNOW && ix86_binary_operator_ok (MULT, V4HImode, operands)"
-  "pmulhrw\\t{%2, %0|%0, %2}"
+  "pmulhrw\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxmul")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "DI")])
 
-(define_insn "sse2_umulsidi3"
-  [(set (match_operand:DI 0 "register_operand" "=y")
-        (mult:DI
-         (zero_extend:DI
-           (vec_select:SI
+(define_expand "sse2_umulv1siv1di3"
+  [(set (match_operand:V1DI 0 "register_operand" "")
+        (mult:V1DI
+         (zero_extend:V1DI
+           (vec_select:V1SI
+             (match_operand:V2SI 1 "nonimmediate_operand" "")
+             (parallel [(const_int 0)])))
+         (zero_extend:V1DI
+           (vec_select:V1SI
+             (match_operand:V2SI 2 "nonimmediate_operand" "")
+             (parallel [(const_int 0)])))))]
+  "TARGET_SSE2"
+  "ix86_fixup_binary_operands_no_copy (MULT, V2SImode, operands);")
+
+(define_insn "*sse2_umulv1siv1di3"
+  [(set (match_operand:V1DI 0 "register_operand" "=y")
+        (mult:V1DI
+         (zero_extend:V1DI
+           (vec_select:V1SI
              (match_operand:V2SI 1 "nonimmediate_operand" "%0")
              (parallel [(const_int 0)])))
-         (zero_extend:DI
-           (vec_select:SI
+         (zero_extend:V1DI
+           (vec_select:V1SI
              (match_operand:V2SI 2 "nonimmediate_operand" "ym")
              (parallel [(const_int 0)])))))]
   "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V2SImode, operands)"
   [(set_attr "type" "mmxmul")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_umaxv8qi3"
-  [(set (match_operand:V8QI 0 "register_operand" "=y")
-        (umax:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "%0")
-                  (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
-  "(TARGET_SSE || TARGET_3DNOW_A)
-   && ix86_binary_operator_ok (UMAX, V8QImode, operands)"
-  "pmaxub\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
+(define_expand "mmx_<code>v4hi3"
+  [(set (match_operand:V4HI 0 "register_operand" "")
+        (smaxmin:V4HI
+         (match_operand:V4HI 1 "nonimmediate_operand" "")
+         (match_operand:V4HI 2 "nonimmediate_operand" "")))]
+  "TARGET_SSE || TARGET_3DNOW_A"
+  "ix86_fixup_binary_operands_no_copy (<CODE>, V4HImode, operands);")
 
-(define_insn "mmx_smaxv4hi3"
+(define_insn "*mmx_<code>v4hi3"
   [(set (match_operand:V4HI 0 "register_operand" "=y")
-        (smax:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
-                  (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
+        (smaxmin:V4HI
+         (match_operand:V4HI 1 "nonimmediate_operand" "%0")
+         (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
   "(TARGET_SSE || TARGET_3DNOW_A)
-   && ix86_binary_operator_ok (SMAX, V4HImode, operands)"
-  "pmaxsw\t{%2, %0|%0, %2}"
+   && ix86_binary_operator_ok (<CODE>, V4HImode, operands)"
+  "p<maxmin_int>w\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_uminv8qi3"
-  [(set (match_operand:V8QI 0 "register_operand" "=y")
-        (umin:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "%0")
-                  (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
-  "(TARGET_SSE || TARGET_3DNOW_A)
-   && ix86_binary_operator_ok (UMIN, V8QImode, operands)"
-  "pminub\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
+(define_expand "mmx_<code>v8qi3"
+  [(set (match_operand:V8QI 0 "register_operand" "")
+        (umaxmin:V8QI
+         (match_operand:V8QI 1 "nonimmediate_operand" "")
+         (match_operand:V8QI 2 "nonimmediate_operand" "")))]
+  "TARGET_SSE || TARGET_3DNOW_A"
+  "ix86_fixup_binary_operands_no_copy (<CODE>, V8QImode, operands);")
 
-(define_insn "mmx_sminv4hi3"
-  [(set (match_operand:V4HI 0 "register_operand" "=y")
-        (smin:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
-                  (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
+(define_insn "*mmx_<code>v8qi3"
+  [(set (match_operand:V8QI 0 "register_operand" "=y")
+        (umaxmin:V8QI
+         (match_operand:V8QI 1 "nonimmediate_operand" "%0")
+         (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
   "(TARGET_SSE || TARGET_3DNOW_A)
-   && ix86_binary_operator_ok (SMIN, V4HImode, operands)"
-  "pminsw\t{%2, %0|%0, %2}"
+   && ix86_binary_operator_ok (<CODE>, V8QImode, operands)"
+  "p<maxmin_int>b\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
    (set_attr "mode" "DI")])
 
   [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
         (ashiftrt:MMXMODE24
          (match_operand:MMXMODE24 1 "register_operand" "0")
-         (match_operand:DI 2 "nonmemory_operand" "yi")))]
+         (match_operand:SI 2 "nonmemory_operand" "yN")))]
   "TARGET_MMX"
   "psra<mmxvecsize>\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxshft")
+   (set (attr "length_immediate")
+     (if_then_else (match_operand 2 "const_int_operand" "")
+       (const_string "1")
+       (const_string "0")))
    (set_attr "mode" "DI")])
 
 (define_insn "mmx_lshr<mode>3"
-  [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
-        (lshiftrt:MMXMODE24
-         (match_operand:MMXMODE24 1 "register_operand" "0")
-         (match_operand:DI 2 "nonmemory_operand" "yi")))]
+  [(set (match_operand:MMXMODE248 0 "register_operand" "=y")
+        (lshiftrt:MMXMODE248
+         (match_operand:MMXMODE248 1 "register_operand" "0")
+         (match_operand:SI 2 "nonmemory_operand" "yN")))]
   "TARGET_MMX"
   "psrl<mmxvecsize>\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxshft")
-   (set_attr "mode" "DI")])
-
-(define_insn "mmx_lshrdi3"
-  [(set (match_operand:DI 0 "register_operand" "=y")
-        (unspec:DI
-         [(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
-                      (match_operand:DI 2 "nonmemory_operand" "yi"))]
-         UNSPEC_NOP))]
-  "TARGET_MMX"
-  "psrlq\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxshft")
+   (set (attr "length_immediate")
+     (if_then_else (match_operand 2 "const_int_operand" "")
+       (const_string "1")
+       (const_string "0")))
    (set_attr "mode" "DI")])
 
 (define_insn "mmx_ashl<mode>3"
-  [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
-        (ashift:MMXMODE24
-         (match_operand:MMXMODE24 1 "register_operand" "0")
-         (match_operand:DI 2 "nonmemory_operand" "yi")))]
+  [(set (match_operand:MMXMODE248 0 "register_operand" "=y")
+        (ashift:MMXMODE248
+         (match_operand:MMXMODE248 1 "register_operand" "0")
+         (match_operand:SI 2 "nonmemory_operand" "yN")))]
   "TARGET_MMX"
   "psll<mmxvecsize>\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxshft")
-   (set_attr "mode" "DI")])
-
-(define_insn "mmx_ashldi3"
-  [(set (match_operand:DI 0 "register_operand" "=y")
-        (unspec:DI
-        [(ashift:DI (match_operand:DI 1 "register_operand" "0")
-                    (match_operand:DI 2 "nonmemory_operand" "yi"))]
-        UNSPEC_NOP))]
-  "TARGET_MMX"
-  "psllq\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxshft")
+   (set (attr "length_immediate")
+     (if_then_else (match_operand 2 "const_int_operand" "")
+       (const_string "1")
+       (const_string "0")))
    (set_attr "mode" "DI")])
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(define_insn "mmx_eq<mode>3"
+(define_expand "mmx_eq<mode>3"
+  [(set (match_operand:MMXMODEI 0 "register_operand" "")
+        (eq:MMXMODEI
+         (match_operand:MMXMODEI 1 "nonimmediate_operand" "")
+         (match_operand:MMXMODEI 2 "nonimmediate_operand" "")))]
+  "TARGET_MMX"
+  "ix86_fixup_binary_operands_no_copy (EQ, <MODE>mode, operands);")
+
+(define_insn "*mmx_eq<mode>3"
   [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
         (eq:MMXMODEI
          (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(define_insn "mmx_and<mode>3"
-  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
-       (and:MMXMODEI
-         (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
-         (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
-  "TARGET_MMX && ix86_binary_operator_ok (AND, <MODE>mode, operands)"
-  "pand\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
-
-(define_insn "mmx_nand<mode>3"
+(define_insn "mmx_andnot<mode>3"
   [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
        (and:MMXMODEI
          (not:MMXMODEI (match_operand:MMXMODEI 1 "register_operand" "0"))
   [(set_attr "type" "mmxadd")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_ior<mode>3"
-  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
-        (ior:MMXMODEI
-         (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
-         (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
-  "TARGET_MMX && ix86_binary_operator_ok (IOR, <MODE>mode, operands)"
-  "por\t{%2, %0|%0, %2}"
-  [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")])
+(define_expand "mmx_<code><mode>3"
+  [(set (match_operand:MMXMODEI 0 "register_operand" "")
+       (any_logic:MMXMODEI
+         (match_operand:MMXMODEI 1 "nonimmediate_operand" "")
+         (match_operand:MMXMODEI 2 "nonimmediate_operand" "")))]
+  "TARGET_MMX"
+  "ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
 
-(define_insn "mmx_xor<mode>3"
+(define_insn "*mmx_<code><mode>3"
   [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
-       (xor:MMXMODEI
+        (any_logic:MMXMODEI
          (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
          (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
-  "TARGET_MMX && ix86_binary_operator_ok (XOR, <MODE>mode, operands)"
-  "pxor\t{%2, %0|%0, %2}"
+  "TARGET_MMX && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+  "p<logic>\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxadd")
-   (set_attr "mode" "DI")
-   (set_attr "memory" "none")])
+   (set_attr "mode" "DI")])
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
   "TARGET_SSE || TARGET_3DNOW_A"
 {
   operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])));
-  return "pinsrw\t{%3, %k2, %0|%0, %k2, %3}";
+  if (MEM_P (operands[2]))
+    return "pinsrw\t{%3, %2, %0|%0, %2, %3}";
+  else
+    return "pinsrw\t{%3, %k2, %0|%0, %k2, %3}";
 }
   [(set_attr "type" "mmxcvt")
+   (set_attr "length_immediate" "1")
    (set_attr "mode" "DI")])
 
 (define_insn "mmx_pextrw"
   "TARGET_SSE || TARGET_3DNOW_A"
   "pextrw\t{%2, %1, %0|%0, %1, %2}"
   [(set_attr "type" "mmxcvt")
+   (set_attr "length_immediate" "1")
    (set_attr "mode" "DI")])
 
 (define_expand "mmx_pshufw"
   return "pshufw\t{%2, %1, %0|%0, %1, %2}";
 }
   [(set_attr "type" "mmxcvt")
+   (set_attr "length_immediate" "1")
    (set_attr "mode" "DI")])
 
 (define_insn "mmx_pswapdv2si2"
          (match_operand:V2SI 1 "nonimmediate_operand" "ym")
          (parallel [(const_int 1) (const_int 0)])))]
   "TARGET_3DNOW_A"
-  "pswapd\\t{%1, %0|%0, %1}"
+  "pswapd\t{%1, %0|%0, %1}"
   [(set_attr "type" "mmxcvt")
+   (set_attr "prefix_extra" "1")
    (set_attr "mode" "DI")])
 
 (define_insn "*vec_dupv4hi"
   "TARGET_SSE || TARGET_3DNOW_A"
   "pshufw\t{$0, %0, %0|%0, %0, 0}"
   [(set_attr "type" "mmxcvt")
+   (set_attr "length_immediate" "1")
    (set_attr "mode" "DI")])
 
 (define_insn "*vec_dupv2si"
   DONE;
 })
 
+;; Avoid combining registers from different units in a single alternative,
+;; see comment above inline_secondary_memory_needed function in i386.c
 (define_insn_and_split "*vec_extractv2si_0"
-  [(set (match_operand:SI 0 "nonimmediate_operand"     "=x,y,m,m,frxy")
+  [(set (match_operand:SI 0 "nonimmediate_operand"     "=x,m,y, m,r")
        (vec_select:SI
-         (match_operand:V2SI 1 "nonimmediate_operand" " x,y,x,y,m")
+         (match_operand:V2SI 1 "nonimmediate_operand" "xm,x,ym,y,m")
          (parallel [(const_int 0)])))]
   "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "#"
   DONE;
 })
 
+;; Avoid combining registers from different units in a single alternative,
+;; see comment above inline_secondary_memory_needed function in i386.c
 (define_insn "*vec_extractv2si_1"
-  [(set (match_operand:SI 0 "nonimmediate_operand"     "=y,Y2,Y2,x,frxy")
+  [(set (match_operand:SI 0 "nonimmediate_operand"     "=y,Y2,Y2,x,y,x,r")
        (vec_select:SI
-         (match_operand:V2SI 1 "nonimmediate_operand" " 0,0 ,Y2,0,o")
+         (match_operand:V2SI 1 "nonimmediate_operand" " 0,0 ,Y2,0,o,o,o")
          (parallel [(const_int 1)])))]
   "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "@
    punpckhdq\t%0, %0
    pshufd\t{$85, %1, %0|%0, %1, 85}
    unpckhps\t%0, %0
+   #
+   #
    #"
-  [(set_attr "type" "mmxcvt,sselog1,sselog1,sselog1,*")
-   (set_attr "mode" "DI,TI,TI,V4SF,SI")])
+  [(set_attr "type" "mmxcvt,sselog1,sselog1,sselog1,mmxmov,ssemov,imov")
+   (set_attr "length_immediate" "*,*,1,*,*,*,*")
+   (set_attr "mode" "DI,TI,TI,V4SF,SI,SI,SI")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(define_insn "mmx_uavgv8qi3"
+(define_expand "mmx_uavgv8qi3"
+  [(set (match_operand:V8QI 0 "register_operand" "")
+       (truncate:V8QI
+         (lshiftrt:V8HI
+           (plus:V8HI
+             (plus:V8HI
+               (zero_extend:V8HI
+                 (match_operand:V8QI 1 "nonimmediate_operand" ""))
+               (zero_extend:V8HI
+                 (match_operand:V8QI 2 "nonimmediate_operand" "")))
+             (const_vector:V8HI [(const_int 1) (const_int 1)
+                                 (const_int 1) (const_int 1)
+                                 (const_int 1) (const_int 1)
+                                 (const_int 1) (const_int 1)]))
+           (const_int 1))))]
+  "TARGET_SSE || TARGET_3DNOW"
+  "ix86_fixup_binary_operands_no_copy (PLUS, V8QImode, operands);")
+
+(define_insn "*mmx_uavgv8qi3"
   [(set (match_operand:V8QI 0 "register_operand" "=y")
        (truncate:V8QI
          (lshiftrt:V8HI
   if (TARGET_SSE || TARGET_3DNOW_A)
     return "pavgb\t{%2, %0|%0, %2}";
   else
-    return "pavgusb\\t{%2, %0|%0, %2}";
+    return "pavgusb\t{%2, %0|%0, %2}";
 }
   [(set_attr "type" "mmxshft")
+   (set (attr "prefix_extra")
+     (if_then_else
+       (eq (symbol_ref "(TARGET_SSE || TARGET_3DNOW_A)") (const_int 0))
+       (const_string "1")
+       (const_string "*")))
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_uavgv4hi3"
+(define_expand "mmx_uavgv4hi3"
+  [(set (match_operand:V4HI 0 "register_operand" "")
+       (truncate:V4HI
+         (lshiftrt:V4SI
+           (plus:V4SI
+             (plus:V4SI
+               (zero_extend:V4SI
+                 (match_operand:V4HI 1 "nonimmediate_operand" ""))
+               (zero_extend:V4SI
+                 (match_operand:V4HI 2 "nonimmediate_operand" "")))
+             (const_vector:V4SI [(const_int 1) (const_int 1)
+                                 (const_int 1) (const_int 1)]))
+           (const_int 1))))]
+  "TARGET_SSE || TARGET_3DNOW_A"
+  "ix86_fixup_binary_operands_no_copy (PLUS, V4HImode, operands);")
+
+(define_insn "*mmx_uavgv4hi3"
   [(set (match_operand:V4HI 0 "register_operand" "=y")
        (truncate:V4HI
          (lshiftrt:V4SI
    (set_attr "mode" "DI")])
 
 (define_insn "mmx_psadbw"
-  [(set (match_operand:DI 0 "register_operand" "=y")
-        (unspec:DI [(match_operand:V8QI 1 "register_operand" "0")
-                   (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
-                  UNSPEC_PSADBW))]
+  [(set (match_operand:V1DI 0 "register_operand" "=y")
+        (unspec:V1DI [(match_operand:V8QI 1 "register_operand" "0")
+                     (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
+                    UNSPEC_PSADBW))]
   "TARGET_SSE || TARGET_3DNOW_A"
   "psadbw\t{%2, %0|%0, %2}"
   [(set_attr "type" "mmxshft")
   [(set_attr "type" "mmxcvt")
    (set_attr "mode" "DI")])
 
-(define_insn "mmx_emms"
-  [(unspec_volatile [(const_int 0)] UNSPECV_EMMS)
-   (clobber (reg:XF 8))
-   (clobber (reg:XF 9))
-   (clobber (reg:XF 10))
-   (clobber (reg:XF 11))
-   (clobber (reg:XF 12))
-   (clobber (reg:XF 13))
-   (clobber (reg:XF 14))
-   (clobber (reg:XF 15))
-   (clobber (reg:DI 29))
-   (clobber (reg:DI 30))
-   (clobber (reg:DI 31))
-   (clobber (reg:DI 32))
-   (clobber (reg:DI 33))
-   (clobber (reg:DI 34))
-   (clobber (reg:DI 35))
-   (clobber (reg:DI 36))]
+(define_expand "mmx_emms"
+  [(match_par_dup 0 [(const_int 0)])]
+  "TARGET_MMX"
+{
+  int regno;
+
+  operands[0] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (17));
+
+  XVECEXP (operands[0], 0, 0)
+    = gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec (1, const0_rtx),
+                              UNSPECV_EMMS);
+
+  for (regno = 0; regno < 8; regno++)
+    {
+      XVECEXP (operands[0], 0, regno + 1)
+       = gen_rtx_CLOBBER (VOIDmode,
+                          gen_rtx_REG (XFmode, FIRST_STACK_REG + regno));
+
+      XVECEXP (operands[0], 0, regno + 9)
+       = gen_rtx_CLOBBER (VOIDmode,
+                          gen_rtx_REG (DImode, FIRST_MMX_REG + regno));
+    }
+})
+
+(define_insn "*mmx_emms"
+  [(match_parallel 0 "emms_operation"
+    [(unspec_volatile [(const_int 0)] UNSPECV_EMMS)])]
   "TARGET_MMX"
   "emms"
   [(set_attr "type" "mmx")
-   (set_attr "memory" "unknown")])
-
-(define_insn "mmx_femms"
-  [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS)
-   (clobber (reg:XF 8))
-   (clobber (reg:XF 9))
-   (clobber (reg:XF 10))
-   (clobber (reg:XF 11))
-   (clobber (reg:XF 12))
-   (clobber (reg:XF 13))
-   (clobber (reg:XF 14))
-   (clobber (reg:XF 15))
-   (clobber (reg:DI 29))
-   (clobber (reg:DI 30))
-   (clobber (reg:DI 31))
-   (clobber (reg:DI 32))
-   (clobber (reg:DI 33))
-   (clobber (reg:DI 34))
-   (clobber (reg:DI 35))
-   (clobber (reg:DI 36))]
+   (set_attr "modrm" "0")
+   (set_attr "memory" "none")])
+
+(define_expand "mmx_femms"
+  [(match_par_dup 0 [(const_int 0)])]
+  "TARGET_3DNOW"
+{
+  int regno;
+
+  operands[0] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (17));
+
+  XVECEXP (operands[0], 0, 0)
+    = gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec (1, const0_rtx),
+                              UNSPECV_FEMMS);
+
+  for (regno = 0; regno < 8; regno++)
+    {
+      XVECEXP (operands[0], 0, regno + 1)
+       = gen_rtx_CLOBBER (VOIDmode,
+                          gen_rtx_REG (XFmode, FIRST_STACK_REG + regno));
+
+      XVECEXP (operands[0], 0, regno + 9)
+       = gen_rtx_CLOBBER (VOIDmode,
+                          gen_rtx_REG (DImode, FIRST_MMX_REG + regno));
+    }
+})
+
+(define_insn "*mmx_femms"
+  [(match_parallel 0 "emms_operation"
+    [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS)])]
   "TARGET_3DNOW"
   "femms"
   [(set_attr "type" "mmx")
+   (set_attr "modrm" "0")
    (set_attr "memory" "none")])