OSDN Git Service

2006-08-06 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.md
index 39d542d..a608b74 100644 (file)
 (include "athlon.md")
 
 \f
-;; Operand and operator predicates
+;; Operand and operator predicates and constraints
 
 (include "predicates.md")
+(include "constraints.md")
 
 \f
 ;; Compare instructions.
 
 (define_insn "*cmpfp_i_mixed"
   [(set (reg:CCFP FLAGS_REG)
-       (compare:CCFP (match_operand 0 "register_operand" "f#x,x#f")
-                     (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
+       (compare:CCFP (match_operand 0 "register_operand" "f,x")
+                     (match_operand 1 "nonimmediate_operand" "f,xm")))]
   "TARGET_MIX_SSE_I387
    && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
    && GET_MODE (operands[0]) == GET_MODE (operands[1])"
 
 (define_insn "*cmpfp_iu_mixed"
   [(set (reg:CCFPU FLAGS_REG)
-       (compare:CCFPU (match_operand 0 "register_operand" "f#x,x#f")
-                      (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
+       (compare:CCFPU (match_operand 0 "register_operand" "f,x")
+                      (match_operand 1 "nonimmediate_operand" "f,xm")))]
   "TARGET_MIX_SSE_I387
    && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
    && GET_MODE (operands[0]) == GET_MODE (operands[1])"
 
 (define_insn "*pushsf"
   [(set (match_operand:SF 0 "push_operand" "=<,<,<")
-       (match_operand:SF 1 "general_no_elim_operand" "f#rx,rFm#fx,x#rf"))]
+       (match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
   "!TARGET_64BIT"
 {
   /* Anything else should be already split before reg-stack.  */
 
 (define_insn "*pushsf_rex64"
   [(set (match_operand:SF 0 "push_operand" "=X,X,X")
-       (match_operand:SF 1 "nonmemory_no_elim_operand" "f#rx,rF#fx,x#rf"))]
+       (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
   "TARGET_64BIT"
 {
   /* Anything else should be already split before reg-stack.  */
 
 (define_insn "*movsf_1"
   [(set (match_operand:SF 0 "nonimmediate_operand"
-         "=f#xr,m   ,f#xr,r#xf  ,m    ,x#rf,x#rf,x#rf ,m   ,!*y,!rm,!*y")
+         "=f,m   ,f,r  ,m    ,x,x,x ,m   ,!*y,!rm,!*y")
        (match_operand:SF 1 "general_operand"
-         "fm#rx,f#rx,G   ,rmF#fx,Fr#fx,C   ,x   ,xm#rf,x#rf,rm ,*y ,*y"))]
+         "fm,f,G   ,rmF,Fr,C   ,x   ,xm,x,rm ,*y ,*y"))]
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))
    && (reload_in_progress || reload_completed
        || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
 
 (define_insn "*pushdf_nointeger"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
-       (match_operand:DF 1 "general_no_elim_operand" "f#Y,Fo#fY,*r#fY,Y#f"))]
+       (match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))]
   "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
 {
   /* This insn should be already split before reg-stack.  */
 
 (define_insn "*pushdf_integer"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<")
-       (match_operand:DF 1 "general_no_elim_operand" "f#rY,rFo#fY,Y#rf"))]
+       (match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))]
   "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
 {
   /* This insn should be already split before reg-stack.  */
 
 (define_insn "*movdf_nointeger"
   [(set (match_operand:DF 0 "nonimmediate_operand"
-                       "=f#Y,m  ,f#Y,*r  ,o  ,Y*x#f,Y*x#f,Y*x#f  ,m    ")
+                       "=f,m,f,*r  ,o  ,Y*x,Y*x,Y*x ,m  ")
        (match_operand:DF 1 "general_operand"
-                       "fm#Y,f#Y,G  ,*roF,F*r,C    ,Y*x#f,HmY*x#f,Y*x#f"))]
+                       "fm,f,G,*roF,F*r,C  ,Y*x,mY*x,Y*x"))]
   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
    && (reload_in_progress || reload_completed
 
 (define_insn "*movdf_integer"
   [(set (match_operand:DF 0 "nonimmediate_operand"
-               "=f#Yr,m   ,f#Yr,r#Yf  ,o    ,Y*x#rf,Y*x#rf,Y*x#rf,m")
+               "=f,m,f,r  ,o ,Y*x,Y*x,Y*x,m  ")
        (match_operand:DF 1 "general_operand"
-               "fm#Yr,f#Yr,G   ,roF#Yf,Fr#Yf,C     ,Y*x#rf,m     ,Y*x#rf"))]
+               "fm,f,G,roF,Fr,C  ,Y*x,m  ,Y*x"))]
   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
    && (reload_in_progress || reload_completed
 
 (define_insn "*pushxf_integer"
   [(set (match_operand:XF 0 "push_operand" "=<,<")
-       (match_operand:XF 1 "general_no_elim_operand" "f#r,ro#f"))]
+       (match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
   "!optimize_size"
 {
   /* This insn should be already split before reg-stack.  */
    (set_attr "mode" "XF,XF,XF,SI,SI")])
 
 (define_insn "*movxf_integer"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
-       (match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
+  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
+       (match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
   "!optimize_size
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && (reload_in_progress || reload_completed
 })
 
 (define_insn "*extendsfdf2_mixed"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,m#fY,Y#f")
-        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm#Y,f#Y,mY#f")))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y")
+        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))]
   "TARGET_SSE2 && TARGET_MIX_SSE_I387
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
 {
 })
 
 (define_insn "*truncxfsf2_mixed"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf")
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x")
        (float_truncate:SF
         (match_operand:XF 1 "register_operand" "f,f,f,f")))
    (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
    (set_attr "mode" "SF")])
 
 (define_insn "*truncxfsf2_i387"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#r,?r#f")
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r")
        (float_truncate:SF
         (match_operand:XF 1 "register_operand" "f,f,f")))
    (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
 })
 
 (define_insn "*truncxfdf2_mixed"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#rY,?r#fY,?Y#rf")
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y")
        (float_truncate:DF
         (match_operand:XF 1 "register_operand" "f,f,f,f")))
    (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
    (set_attr "mode" "DF")])
 
 (define_insn "*truncxfdf2_i387"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#r,?r#f")
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r")
        (float_truncate:DF
         (match_operand:XF 1 "register_operand" "f,f,f")))
    (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
   "")
 
 (define_insn "*floatsisf2_mixed"
-  [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f")
+  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
        (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_MIX_SSE_I387"
   "@
   "")
 
 (define_insn "*floatdisf2_mixed"
-  [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f")
+  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
        (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_64BIT && TARGET_MIX_SSE_I387"
   "@
   "")
 
 (define_insn "*floatsidf2_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
        (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_SSE2 && TARGET_MIX_SSE_I387"
   "@
   "")
 
 (define_insn "*floatdidf2_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
        (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
   "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
   "@
                    (match_dup 2))))]
   "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
    && ix86_binary_operator_ok (MINUS, SImode, operands)"
-  "sub{q}\t{%2, %0|%0, %2}"
+  "sub{l}\t{%2, %1|%1, %2}"
   [(set_attr "type" "alu")
    (set_attr "mode" "DI")])
 
   "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
 
 (define_insn "*absnegsf2_mixed"
-  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x#f,x#f,f#x,rm")
+  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x  ,x,f,rm")
        (match_operator:SF 3 "absneg_operator"
-         [(match_operand:SF 1 "nonimmediate_operand" "0   ,x#f,0  ,0")]))
-   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm  ,0  ,X  ,X"))
+         [(match_operand:SF 1 "nonimmediate_operand" "0   ,x,0,0 ")]))
+   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm  ,0,X,X "))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_SSE_MATH && TARGET_MIX_SSE_I387
    && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
   "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
 
 (define_insn "*absnegdf2_mixed"
-  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y#f,Y#f,f#Y,rm")
+  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,f,rm")
        (match_operator:DF 3 "absneg_operator"
-         [(match_operand:DF 1 "nonimmediate_operand" "0   ,Y#f,0  ,0")]))
-   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym  ,0  ,X  ,X"))
+         [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0,0")]))
+   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X,X"))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
    && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
 (define_insn "*absnegdf2_sse"
   [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,rm")
        (match_operator:DF 3 "absneg_operator"
-         [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0")]))
-   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X"))
+         [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0 ")]))
+   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X "))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_SSE2 && TARGET_SSE_MATH
    && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
 (define_insn "*negsf2_1"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (neg:SF (match_operand:SF 1 "register_operand" "0")))]
-  "TARGET_80387 && reload_completed"
+  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
   "fchs"
   [(set_attr "type" "fsgn")
    (set_attr "mode" "SF")])
 (define_insn "*negdf2_1"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (neg:DF (match_operand:DF 1 "register_operand" "0")))]
-  "TARGET_80387 && reload_completed"
+  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
   "fchs"
   [(set_attr "type" "fsgn")
    (set_attr "mode" "DF")])
 (define_insn "*negxf2_1"
   [(set (match_operand:XF 0 "register_operand" "=f")
        (neg:XF (match_operand:XF 1 "register_operand" "0")))]
-  "TARGET_80387 && reload_completed"
+  "TARGET_80387"
   "fchs"
   [(set_attr "type" "fsgn")
    (set_attr "mode" "XF")])
 (define_insn "*abssf2_1"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (abs:SF (match_operand:SF 1 "register_operand" "0")))]
-  "TARGET_80387 && reload_completed"
+  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
   "fabs"
   [(set_attr "type" "fsgn")
    (set_attr "mode" "SF")])
 (define_insn "*absdf2_1"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (abs:DF (match_operand:DF 1 "register_operand" "0")))]
-  "TARGET_80387 && reload_completed"
+  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
   "fabs"
   [(set_attr "type" "fsgn")
    (set_attr "mode" "DF")])
 (define_insn "*absxf2_1"
   [(set (match_operand:XF 0 "register_operand" "=f")
        (abs:XF (match_operand:XF 1 "register_operand" "0")))]
-  "TARGET_80387 && reload_completed"
+  "TARGET_80387"
   "fabs"
   [(set_attr "type" "fsgn")
    (set_attr "mode" "DF")])
 (define_expand "extv"
   [(set (match_operand:SI 0 "register_operand" "")
        (sign_extract:SI (match_operand:SI 1 "register_operand" "")
-                        (match_operand:SI 2 "immediate_operand" "")
-                        (match_operand:SI 3 "immediate_operand" "")))]
+                        (match_operand:SI 2 "const8_operand" "")
+                        (match_operand:SI 3 "const8_operand" "")))]
   ""
 {
   /* Handle extractions from %ah et al.  */
 (define_expand "extzv"
   [(set (match_operand:SI 0 "register_operand" "")
        (zero_extract:SI (match_operand 1 "ext_register_operand" "")
-                        (match_operand:SI 2 "immediate_operand" "")
-                        (match_operand:SI 3 "immediate_operand" "")))]
+                        (match_operand:SI 2 "const8_operand" "")
+                        (match_operand:SI 3 "const8_operand" "")))]
   ""
 {
   /* Handle extractions from %ah et al.  */
 
 (define_expand "insv"
   [(set (zero_extract (match_operand 0 "ext_register_operand" "")
-                     (match_operand 1 "immediate_operand" "")
-                     (match_operand 2 "immediate_operand" ""))
+                     (match_operand 1 "const8_operand" "")
+                     (match_operand 2 "const8_operand" ""))
         (match_operand 3 "register_operand" ""))]
   ""
 {
-  /* Handle extractions from %ah et al.  */
+  /* Handle insertions to %ah et al.  */
   if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8)
     FAIL;
 
 (define_insn "*fp_jcc_1_mixed"
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
-                       [(match_operand 1 "register_operand" "f#x,x#f")
-                        (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
+                       [(match_operand 1 "register_operand" "f,x")
+                        (match_operand 2 "nonimmediate_operand" "f,xm")])
          (label_ref (match_operand 3 "" ""))
          (pc)))
    (clobber (reg:CCFP FPSR_REG))
 (define_insn "*fp_jcc_2_mixed"
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
-                       [(match_operand 1 "register_operand" "f#x,x#f")
-                        (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
+                       [(match_operand 1 "register_operand" "f,x")
+                        (match_operand 2 "nonimmediate_operand" "f,xm")])
          (pc)
          (label_ref (match_operand 3 "" ""))))
    (clobber (reg:CCFP FPSR_REG))
 #else
   /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that.
      The align insn is used to avoid 3 jump instructions in the row to improve
-     branch prediction and the benefits hardly outweight the cost of extra 8
+     branch prediction and the benefits hardly outweigh the cost of extra 8
      nops on the average inserted by full alignment pseudo operation.  */
 #endif
   return "";
 (define_insn_and_split "*tls_dynamic_gnu2_combine_32"
   [(set (match_operand:SI 0 "register_operand" "=&a")
        (plus:SI
-        (plus:SI (match_operand:SI 3 "tp_or_register_operand" "ir")
-                 (unspec:SI [(match_operand:SI 4 "tls_modbase_operand" "")
-                             (match_operand:SI 5 "" "")
-                             (match_operand:SI 2 "register_operand" "b")
-                             (reg:SI SP_REG)]
-                            UNSPEC_TLSDESC))
+        (unspec:SI [(match_operand:SI 3 "tls_modbase_operand" "")
+                    (match_operand:SI 4 "" "")
+                    (match_operand:SI 2 "register_operand" "b")
+                    (reg:SI SP_REG)]
+                   UNSPEC_TLSDESC)
         (const:SI (unspec:SI
                    [(match_operand:SI 1 "tls_symbolic_operand" "")]
                    UNSPEC_DTPOFF))))
   "!TARGET_64BIT && TARGET_GNU2_TLS"
   "#"
   ""
-  [(parallel
-    [(set (match_dup 0)
-         (plus:SI (match_dup 3)
-                  (match_dup 5)))
-     (clobber (reg:CC FLAGS_REG))])]
+  [(set (match_dup 0) (match_dup 5))]
 {
   operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
   emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2]));
 (define_insn_and_split "*tls_dynamic_gnu2_combine_64"
   [(set (match_operand:DI 0 "register_operand" "=&a")
        (plus:DI
-        (plus:DI (match_operand:DI 2 "tp_or_register_operand" "ir")
-                 (unspec:DI [(match_operand:DI 3 "tls_modbase_operand" "")
-                             (match_operand:DI 4 "" "")
-                             (reg:DI SP_REG)]
-                             UNSPEC_TLSDESC))
+        (unspec:DI [(match_operand:DI 2 "tls_modbase_operand" "")
+                    (match_operand:DI 3 "" "")
+                    (reg:DI SP_REG)]
+                   UNSPEC_TLSDESC)
         (const:DI (unspec:DI
                    [(match_operand:DI 1 "tls_symbolic_operand" "")]
                    UNSPEC_DTPOFF))))
   "TARGET_64BIT && TARGET_GNU2_TLS"
   "#"
   ""
-  [(parallel
-    [(set (match_dup 0)
-         (plus:DI (match_dup 2)
-                  (match_dup 4)))
-     (clobber (reg:CC FLAGS_REG))])]
+  [(set (match_dup 0) (match_dup 4))]
 {
   operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
   emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
 ;; so use special patterns for add and mull.
 
 (define_insn "*fop_sf_comm_mixed"
-  [(set (match_operand:SF 0 "register_operand" "=f#x,x#f")
+  [(set (match_operand:SF 0 "register_operand" "=f,x")
        (match_operator:SF 3 "binary_fp_operator"
                        [(match_operand:SF 1 "nonimmediate_operand" "%0,0")
-                        (match_operand:SF 2 "nonimmediate_operand" "fm#x,xm#f")]))]
+                        (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))]
   "TARGET_MIX_SSE_I387
    && COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
   [(set (match_operand:SF 0 "register_operand" "=f,f,x")
        (match_operator:SF 3 "binary_fp_operator"
                        [(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
-                        (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm#f")]))]
+                        (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))]
   "TARGET_MIX_SSE_I387
    && !COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
    (set_attr "mode" "<MODE>")])
 
 (define_insn "*fop_df_comm_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,Y")
        (match_operator:DF 3 "binary_fp_operator"
                        [(match_operand:DF 1 "nonimmediate_operand" "%0,0")
-                        (match_operand:DF 2 "nonimmediate_operand" "fm#Y,Ym#f")]))]
+                        (match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))]
   "TARGET_SSE2 && TARGET_MIX_SSE_I387
    && COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
    (set_attr "mode" "DF")])
 
 (define_insn "*fop_df_1_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,f#Y,Y#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,f,Y")
        (match_operator:DF 3 "binary_fp_operator"
                        [(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
-                        (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym#f")]))]
+                        (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))]
   "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
    && !COMMUTATIVE_ARITH_P (operands[3])
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
 })
 
 (define_insn "*sqrtsf2_mixed"
-  [(set (match_operand:SF 0 "register_operand" "=f#x,x#f")
-       (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0#x,xm#f")))]
+  [(set (match_operand:SF 0 "register_operand" "=f,x")
+       (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))]
   "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387"
   "@
    fsqrt
 })
 
 (define_insn "*sqrtdf2_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
-       (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0#Y,Ym#f")))]
+  [(set (match_operand:DF 0 "register_operand" "=f,Y")
+       (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))]
   "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387"
   "@
    fsqrt
   "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
 
 (define_insn "*movsfcc_1_387"
-  [(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f")
+  [(set (match_operand:SF 0 "register_operand" "=f,f,r,r")
        (if_then_else:SF (match_operator 1 "fcmov_comparison_operator" 
                                [(reg FLAGS_REG) (const_int 0)])
-                     (match_operand:SF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
-                     (match_operand:SF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
+                     (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0")
+                     (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))]
   "TARGET_80387 && TARGET_CMOVE
    && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
   "@
   "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
 
 (define_insn "*movdfcc_1"
-  [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r")
        (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
                                [(reg FLAGS_REG) (const_int 0)])
-                     (match_operand:DF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
-                     (match_operand:DF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
+                     (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
+                     (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
   "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
    && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
   "@
    (set_attr "mode" "DF")])
 
 (define_insn "*movdfcc_1_rex64"
-  [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,r#f,r#f")
+  [(set (match_operand:DF 0 "register_operand" "=f,f,r,r")
        (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
                                [(reg FLAGS_REG) (const_int 0)])
-                     (match_operand:DF 2 "nonimmediate_operand" "f#r,0#r,rm#f,0#f")
-                     (match_operand:DF 3 "nonimmediate_operand" "0#r,f#r,0#f,rm#f")))]
+                     (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
+                     (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
   "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
    && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
   "@
   [(set_attr "type" "sseadd")
    (set_attr "mode" "DF")])
 
+;; Make two stack loads independent:
+;;   fld aa              fld aa
+;;   fld %st(0)     ->   fld bb
+;;   fmul bb             fmul %st(1), %st
+;;
+;; Actually we only match the last two instructions for simplicity.
+(define_peephole2
+  [(set (match_operand 0 "fp_register_operand" "")
+       (match_operand 1 "fp_register_operand" ""))
+   (set (match_dup 0)
+       (match_operator 2 "binary_fp_operator"
+          [(match_dup 0)
+           (match_operand 3 "memory_operand" "")]))]
+  "REGNO (operands[0]) != REGNO (operands[1])"
+  [(set (match_dup 0) (match_dup 3))
+   (set (match_dup 0) (match_dup 4))]
+
+  ;; The % modifier is not operational anymore in peephole2's, so we have to
+  ;; swap the operands manually in the case of addition and multiplication.
+  "if (COMMUTATIVE_ARITH_P (operands[2]))
+     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
+                                operands[0], operands[1]);
+   else
+     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
+                                operands[1], operands[0]);")
+
 ;; Conditional addition patterns
 (define_expand "addqicc"
   [(match_operand:QI 0 "register_operand" "")
   "! TARGET_PARTIAL_REG_STALL && reload_completed
    && ((GET_MODE (operands[0]) == HImode 
        && ((!optimize_size && !TARGET_FAST_PREFIX)
+            /* ??? next two lines just !satisfies_constraint_K (...) */
            || GET_CODE (operands[2]) != CONST_INT
-           || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')))
+           || satisfies_constraint_K (operands[2])))
        || (GET_MODE (operands[0]) == QImode 
           && (TARGET_PROMOTE_QImode || optimize_size)))"
   [(parallel [(set (match_dup 0)
           (const_int 0)]))]
   "ix86_match_ccmode (insn, CCNOmode)
    && (true_regnum (operands[2]) != 0
-       || (GET_CODE (operands[3]) == CONST_INT
-          && CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'K')))
+       || satisfies_constraint_K (operands[3]))
    && peep2_reg_dead_p (1, operands[2])"
   [(parallel
      [(set (match_dup 0)
                            (match_operand:DI 2 "immediate_operand" "")))
              (clobber (reg:CC FLAGS_REG))])]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && (GET_CODE (operands[2]) != CONST_INT
-       || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+   && !satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 1))
    (parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2)))
              (clobber (reg:CC FLAGS_REG))])]
                            (match_operand:SI 2 "immediate_operand" "")))
              (clobber (reg:CC FLAGS_REG))])]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && (GET_CODE (operands[2]) != CONST_INT
-       || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+   && !satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 1))
    (parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2)))
              (clobber (reg:CC FLAGS_REG))])]
                              (match_operand:SI 2 "immediate_operand" ""))))
              (clobber (reg:CC FLAGS_REG))])]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && (GET_CODE (operands[2]) != CONST_INT
-       || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+   && !satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 1))
    (parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2))))
              (clobber (reg:CC FLAGS_REG))])]
              (clobber (reg:CC FLAGS_REG))])
    (match_scratch:DI 3 "r")]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+   && satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 2))
    (parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3)))
              (clobber (reg:CC FLAGS_REG))])]
              (clobber (reg:CC FLAGS_REG))])
    (match_scratch:SI 3 "r")]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+   && satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 2))
    (parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3)))
              (clobber (reg:CC FLAGS_REG))])]
 (define_insn "trap"
   [(trap_if (const_int 1) (const_int 6))]
   ""
-  ".word\t0x0b0f"
+  { return ASM_SHORT "0x0b0f"; }
   [(set_attr "length" "2")])
 
 (define_expand "sse_prologue_save"
    (set (match_scratch:DI 2 "=&r") (const_int 0))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT"
-  "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
+  {
+     /* The kernel uses a different segment register for performance reasons; a
+        system call would not have to trash the userspace segment register,
+        which would be expensive */
+     if (ix86_cmodel != CM_KERNEL)
+        return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
+     else
+        return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR %%gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
+  }
   [(set_attr "type" "multi")])
 
 (define_expand "stack_protect_test"
                    UNSPEC_SP_TLS_TEST))
    (clobber (match_scratch:DI 3 "=r"))]
   "TARGET_64BIT"
-  "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}"
+  {
+     /* The kernel uses a different segment register for performance reasons; a
+        system call would not have to trash the userspace segment register,
+        which would be expensive */
+     if (ix86_cmodel != CM_KERNEL)
+        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}";
+     else
+        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR %%gs:%P2}";
+  }
   [(set_attr "type" "multi")])
 
 (include "sse.md")