OSDN Git Service

* config/i386/i386.md (lround<X87MODEF:mode><SWI248x:mode>2): Do not
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.md
index 98d60ec..1b37118 100644 (file)
   [(SF "ss") (DF "sd")
    (V8SF "ps") (V4DF "pd")
    (V4SF "ps") (V2DF "pd")
-   (V16QI "b") (V8HI "w") (V4SI "d") (V2DI "q")
-   (V8SI "si")])
+   (V16QI "b") (V8HI "w") (V4SI "d") (V2DI "q")])
 
 ;; SSE vector suffix for floating point modes
 (define_mode_attr ssevecmodesuffix [(SF "ps") (DF "pd")])
 ;; This mode iterator allows :P to be used for patterns that operate on
 ;; pointer-sized quantities.  Exactly one of the two alternatives will match.
 (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
+
+;; This mode iterator allows :PTR to be used for patterns that operate on
+;; ptr_mode sized quantities.
+(define_mode_iterator PTR
+  [(SI "ptr_mode == SImode") (DI "ptr_mode == DImode")])
 \f
 ;; Scheduling descriptions
 
 
 (define_insn "*push<mode>2"
   [(set (match_operand:DWI 0 "push_operand" "=<")
-       (match_operand:DWI 1 "general_no_elim_operand" "riF*m"))]
+       (match_operand:DWI 1 "general_no_elim_operand" "riF*o"))]
   ""
-  "#")
+  "#"
+  [(set_attr "type" "multi")
+   (set_attr "mode" "<MODE>")])
 
 (define_split
   [(set (match_operand:TI 0 "push_operand" "")
 
 (define_insn "*movdi_internal_rex64"
   [(set (match_operand:DI 0 "nonimmediate_operand"
-         "=r,r  ,r,m ,!m,*y,m*y,?*y,?r ,?*Ym,*x,m ,*x,*x,?r ,?*Yi,?*x,?*Ym")
+         "=r,r  ,r,m ,!o,*y,m*y,?*y,?r ,?*Ym,*x,m ,*x,*x,?r ,?*Yi,?*x,?*Ym")
        (match_operand:DI 1 "general_operand"
          "Z ,rem,i,re,n ,C ,*y ,m  ,*Ym,r   ,C ,*x,*x,m ,*Yi,r   ,*Ym,*x"))]
   "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
        (const_string "orig")))
    (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,DI,TI,DI,TI,DI,DI,DI,DI,DI")])
 
+;; Reload patterns to support multi-word load/store
+;; with non-offsetable address.
+(define_expand "reload_noff_store"
+  [(parallel [(match_operand 0 "memory_operand" "=m")
+              (match_operand 1 "register_operand" "r")
+              (match_operand:DI 2 "register_operand" "=&r")])]
+  "TARGET_64BIT"
+{
+  rtx mem = operands[0];
+  rtx addr = XEXP (mem, 0);
+
+  emit_move_insn (operands[2], addr);
+  mem = replace_equiv_address_nv (mem, operands[2]);
+
+  emit_insn (gen_rtx_SET (VOIDmode, mem, operands[1]));
+  DONE;
+})
+
+(define_expand "reload_noff_load"
+  [(parallel [(match_operand 0 "register_operand" "=r")
+              (match_operand 1 "memory_operand" "m")
+              (match_operand:DI 2 "register_operand" "=r")])]
+  "TARGET_64BIT"
+{
+  rtx mem = operands[1];
+  rtx addr = XEXP (mem, 0);
+
+  emit_move_insn (operands[2], addr);
+  mem = replace_equiv_address_nv (mem, operands[2]);
+
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], mem));
+  DONE;
+})
+
 ;; Convert impossible stores of immediate to existing instructions.
 ;; First try to get scratch register and go through it.  In case this
 ;; fails, move by 32bit parts.
 ;; only once, but this ought to be handled elsewhere).
 
 (define_insn "*pushxf_nointeger"
-  [(set (match_operand:XF 0 "push_operand" "=X,X")
+  [(set (match_operand:XF 0 "push_operand" "=<,<")
        (match_operand:XF 1 "general_no_elim_operand" "f,*rFo"))]
   "optimize_function_for_size_p (cfun)"
 {
    (set (mem:XF (reg:P SP_REG)) (match_dup 1))]
   "operands[2] = GEN_INT (-GET_MODE_SIZE (XFmode));")
 
+(define_insn "*pushdf_rex64"
+  [(set (match_operand:DF 0 "push_operand" "=<,<,<")
+       (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFm,Y2"))]
+  "TARGET_64BIT"
+{
+  /* This insn should be already split before reg-stack.  */
+  gcc_unreachable ();
+}
+  [(set_attr "type" "multi")
+   (set_attr "unit" "i387,*,*")
+   (set_attr "mode" "DF,DI,DF")])
+
 ;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
 ;; Size of pushdf using integer instructions is 2+2*memory operand size
 ;; On the average, pushdf using integers can be still shorter.
 (define_insn "*pushdf"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<")
        (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFo,Y2"))]
-  ""
+  "!TARGET_64BIT"
 {
   /* This insn should be already split before reg-stack.  */
   gcc_unreachable ();
 }
   [(set_attr "type" "multi")
    (set_attr "unit" "i387,*,*")
-   (set_attr "mode" "DF,SI,DF")])
+   (set_attr "mode" "DF,DI,DF")])
 
 ;; %%% Kill this when call knows how to work this out.
 (define_split
 
 (define_insn "*movdf_internal_rex64"
   [(set (match_operand:DF 0 "nonimmediate_operand"
-               "=f,m,f,?r,?m,?r,!m,Y2*x,Y2*x,Y2*x,m   ,Yi,r ")
+               "=f,m,f,?r,?m,?r,!o,Y2*x,Y2*x,Y2*x,m   ,Yi,r ")
        (match_operand:DF 1 "general_operand"
                "fm,f,G,rm,r ,F ,F ,C   ,Y2*x,m   ,Y2*x,r ,Yi"))]
   "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))
 
 (define_insn "*lea_1"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
-       (match_operand:SWI48 1 "no_seg_address_operand" "p"))]
+       (match_operand:SWI48 1 "lea_address_operand" "p"))]
   ""
   "lea{<imodesuffix>}\t{%a1, %0|%0, %a1}"
   [(set_attr "type" "lea")
 (define_insn "*lea_1_zext"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
-         (match_operand:SI 1 "no_seg_address_operand" "p")))]
+         (match_operand:SI 1 "lea_address_operand" "p")))]
   "TARGET_64BIT"
   "lea{l}\t{%a1, %k0|%k0, %a1}"
   [(set_attr "type" "lea")
 
 (define_insn "*lea_2"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))]
+       (subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0))]
   "TARGET_64BIT"
   "lea{l}\t{%a1, %0|%0, %a1}"
   [(set_attr "type" "lea")
 (define_insn "*lea_2_zext"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
-         (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))]
+         (subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0)))]
   "TARGET_64BIT"
   "lea{l}\t{%a1, %k0|%k0, %a1}"
   [(set_attr "type" "lea")
 
 ;; Convert add to the lea pattern to avoid flags dependency.
 (define_split
-  [(set (match_operand 0 "register_operand" "")
-       (plus (match_operand 1 "register_operand" "")
-              (match_operand 2 "nonmemory_operand" "")))
+  [(set (match_operand:SWI 0 "register_operand" "")
+       (plus:SWI (match_operand:SWI 1 "register_operand" "")
+                 (match_operand:SWI 2 "<nonmemory_operand>" "")))
    (clobber (reg:CC FLAGS_REG))]
-  "GET_MODE (operands[0]) == GET_MODE (operands[1])
-   && (GET_MODE (operands[0]) == GET_MODE (operands[2])
-       || GET_MODE (operands[2]) == VOIDmode)
-   && reload_completed && ix86_lea_for_add_ok (insn, operands)" 
+  "reload_completed && ix86_lea_for_add_ok (insn, operands)" 
   [(const_int 0)]
 {
-  enum machine_mode mode = GET_MODE (operands[0]);
+  enum machine_mode mode = <MODE>mode;
   rtx pat;
 
   if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))
 })
 
 ;; Convert add to the lea pattern to avoid flags dependency.
-;; ??? This pattern handles immediate operands that do not satisfy immediate
-;; operand predicate (TARGET_LEGITIMATE_CONSTANT_P) in the previous pattern.
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (plus:DI (match_operand:DI 1 "register_operand" "")
-                (match_operand:DI 2 "x86_64_immediate_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && reload_completed 
-   && true_regnum (operands[0]) != true_regnum (operands[1])"
-  [(set (match_dup 0)
-       (plus:DI (match_dup 1) (match_dup 2)))])
-
-;; Convert add to the lea pattern to avoid flags dependency.
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
        (zero_extend:DI
          (plus:SI (match_operand:SI 1 "register_operand" "")
-                  (match_operand:SI 2 "nonmemory_operand" ""))))
+                  (match_operand:SI 2 "x86_64_nonmemory_operand" ""))))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && reload_completed
-   && ix86_lea_for_add_ok (insn, operands)"
+  "TARGET_64BIT && reload_completed && ix86_lea_for_add_ok (insn, operands)"
   [(set (match_dup 0)
        (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))])
 
   [(set_attr "type" "call")])
 
 (define_insn_and_split "*call_rex64_ms_sysv_vzeroupper"
-  [(parallel
-    [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzw"))
-          (match_operand 1 "" ""))
-     (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
-     (clobber (reg:TI XMM6_REG))
-     (clobber (reg:TI XMM7_REG))
-     (clobber (reg:TI XMM8_REG))
-     (clobber (reg:TI XMM9_REG))
-     (clobber (reg:TI XMM10_REG))
-     (clobber (reg:TI XMM11_REG))
-     (clobber (reg:TI XMM12_REG))
-     (clobber (reg:TI XMM13_REG))
-     (clobber (reg:TI XMM14_REG))
-     (clobber (reg:TI XMM15_REG))
-     (clobber (reg:DI SI_REG))
-     (clobber (reg:DI DI_REG))])
+  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzw"))
+        (match_operand 1 "" ""))
+   (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
+   (clobber (reg:TI XMM6_REG))
+   (clobber (reg:TI XMM7_REG))
+   (clobber (reg:TI XMM8_REG))
+   (clobber (reg:TI XMM9_REG))
+   (clobber (reg:TI XMM10_REG))
+   (clobber (reg:TI XMM11_REG))
+   (clobber (reg:TI XMM12_REG))
+   (clobber (reg:TI XMM13_REG))
+   (clobber (reg:TI XMM14_REG))
+   (clobber (reg:TI XMM15_REG))
+   (clobber (reg:DI SI_REG))
+   (clobber (reg:DI DI_REG))
    (unspec [(match_operand 2 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
   "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)"
 })
 
 (define_insn_and_split "*call_pop_vzeroupper"
-  [(parallel
-    [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lzm"))
-          (match_operand:SI 1 "" ""))
-     (set (reg:SI SP_REG)
-         (plus:SI (reg:SI SP_REG)
-                  (match_operand:SI 2 "immediate_operand" "i")))])
+  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lzm"))
+        (match_operand:SI 1 "" ""))
+   (set (reg:SI SP_REG)
+       (plus:SI (reg:SI SP_REG)
+                (match_operand:SI 2 "immediate_operand" "i")))
    (unspec [(match_operand 3 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
   "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)"
   [(set_attr "type" "call")])
 
 (define_insn_and_split "*sibcall_pop_vzeroupper"
- [(parallel
-   [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz"))
-         (match_operand 1 "" ""))
-     (set (reg:SI SP_REG)
-         (plus:SI (reg:SI SP_REG)
-                  (match_operand:SI 2 "immediate_operand" "i")))])
+  [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz"))
+        (match_operand 1 "" ""))
+   (set (reg:SI SP_REG)
+       (plus:SI (reg:SI SP_REG)
+                (match_operand:SI 2 "immediate_operand" "i")))
    (unspec [(match_operand 3 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
   "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)"
   [(set_attr "type" "callv")])
 
 (define_insn_and_split "*call_value_rex64_ms_sysv_vzeroupper"
-  [(parallel
-    [(set (match_operand 0 "" "")
-         (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzw"))
-               (match_operand 2 "" "")))
-     (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
-     (clobber (reg:TI XMM6_REG))
-     (clobber (reg:TI XMM7_REG))
-     (clobber (reg:TI XMM8_REG))
-     (clobber (reg:TI XMM9_REG))
-     (clobber (reg:TI XMM10_REG))
-     (clobber (reg:TI XMM11_REG))
-     (clobber (reg:TI XMM12_REG))
-     (clobber (reg:TI XMM13_REG))
-     (clobber (reg:TI XMM14_REG))
-     (clobber (reg:TI XMM15_REG))
-     (clobber (reg:DI SI_REG))
-     (clobber (reg:DI DI_REG))])
+  [(set (match_operand 0 "" "")
+       (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzw"))
+             (match_operand 2 "" "")))
+   (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
+   (clobber (reg:TI XMM6_REG))
+   (clobber (reg:TI XMM7_REG))
+   (clobber (reg:TI XMM8_REG))
+   (clobber (reg:TI XMM9_REG))
+   (clobber (reg:TI XMM10_REG))
+   (clobber (reg:TI XMM11_REG))
+   (clobber (reg:TI XMM12_REG))
+   (clobber (reg:TI XMM13_REG))
+   (clobber (reg:TI XMM14_REG))
+   (clobber (reg:TI XMM15_REG))
+   (clobber (reg:DI SI_REG))
+   (clobber (reg:DI DI_REG))
    (unspec [(match_operand 3 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
   "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)"
 })
 
 (define_insn_and_split "*call_value_pop_vzeroupper"
-  [(parallel
-    [(set (match_operand 0 "" "")
-         (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm"))
-               (match_operand 2 "" "")))
-     (set (reg:SI SP_REG)
-         (plus:SI (reg:SI SP_REG)
-                  (match_operand:SI 3 "immediate_operand" "i")))])
+  [(set (match_operand 0 "" "")
+       (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm"))
+             (match_operand 2 "" "")))
+   (set (reg:SI SP_REG)
+       (plus:SI (reg:SI SP_REG)
+                (match_operand:SI 3 "immediate_operand" "i")))
    (unspec [(match_operand 4 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
   "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)"
   [(set_attr "type" "callv")])
 
 (define_insn_and_split "*sibcall_value_pop_vzeroupper"
- [(parallel
-   [(set (match_operand 0 "" "")
-         (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz"))
-               (match_operand 2 "" "")))
-     (set (reg:SI SP_REG)
-         (plus:SI (reg:SI SP_REG)
-                  (match_operand:SI 3 "immediate_operand" "i")))])
+  [(set (match_operand 0 "" "")
+       (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz"))
+             (match_operand 2 "" "")))
+   (set (reg:SI SP_REG)
+       (plus:SI (reg:SI SP_REG)
+                (match_operand:SI 3 "immediate_operand" "i")))
    (unspec [(match_operand 4 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
   "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)"
       (clobber (reg:CC FLAGS_REG))])]
   ""
 {
-  if (TARGET_ABM)
+  if (TARGET_LZCNT)
     {
-      emit_insn (gen_clz<mode>2_abm (operands[0], operands[1]));
+      emit_insn (gen_clz<mode>2_lzcnt (operands[0], operands[1]));
       DONE;
     }
   operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)-1);
 })
 
-(define_insn "clz<mode>2_abm"
+(define_insn "clz<mode>2_lzcnt"
   [(set (match_operand:SWI248 0 "register_operand" "=r")
        (clz:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "rm")))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_ABM || TARGET_BMI"
+  "TARGET_LZCNT"
   "lzcnt{<imodesuffix>}\t{%1, %0|%0, %1}"
   [(set_attr "prefix_rep" "1")
    (set_attr "type" "bitmanip")
        (call:DI
         (mem:QI (match_operand:DI 2 "constant_call_address_operand" "z"))
         (match_operand:DI 3 "" "")))
-   (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+   (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
              UNSPEC_TLS_GD)]
   "TARGET_64BIT"
 {
-  fputs (ASM_BYTE "0x66\n", asm_out_file);
+  if (!TARGET_X32)
+    fputs (ASM_BYTE "0x66\n", asm_out_file);
   output_asm_insn
     ("lea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}", operands);
   fputs (ASM_SHORT "0x6666\n", asm_out_file);
   return "call\t%P2";
 }
   [(set_attr "type" "multi")
-   (set_attr "length" "16")])
+   (set (attr "length")
+       (symbol_ref "TARGET_X32 ? 15 : 16"))])
 
 (define_expand "tls_global_dynamic_64"
   [(parallel
          (call:DI
           (mem:QI (match_operand:DI 2 "constant_call_address_operand" ""))
           (const_int 0)))
-     (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+     (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
                UNSPEC_TLS_GD)])])
 
 (define_insn "*tls_local_dynamic_base_32_gnu"
 (define_mode_attr tp_seg [(SI "gs") (DI "fs")])
 
 ;; Load and add the thread base pointer from %<tp_seg>:0.
+(define_insn "*load_tp_x32"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unspec:SI [(const_int 0)] UNSPEC_TP))]
+  "TARGET_X32"
+  "mov{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}"
+  [(set_attr "type" "imov")
+   (set_attr "modrm" "0")
+   (set_attr "length" "7")
+   (set_attr "memory" "load")
+   (set_attr "imm_disp" "false")])
+
+(define_insn "*load_tp_x32_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (unspec:SI [(const_int 0)] UNSPEC_TP)))]
+  "TARGET_X32"
+  "mov{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}"
+  [(set_attr "type" "imov")
+   (set_attr "modrm" "0")
+   (set_attr "length" "7")
+   (set_attr "memory" "load")
+   (set_attr "imm_disp" "false")])
+
 (define_insn "*load_tp_<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
        (unspec:P [(const_int 0)] UNSPEC_TP))]
-  ""
+  "!TARGET_X32"
   "mov{<imodesuffix>}\t{%%<tp_seg>:0, %0|%0, <iptrsize> PTR <tp_seg>:0}"
   [(set_attr "type" "imov")
    (set_attr "modrm" "0")
    (set_attr "memory" "load")
    (set_attr "imm_disp" "false")])
 
+(define_insn "*add_tp_x32"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
+                (match_operand:SI 1 "register_operand" "0")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_X32"
+  "add{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}"
+  [(set_attr "type" "alu")
+   (set_attr "modrm" "0")
+   (set_attr "length" "7")
+   (set_attr "memory" "load")
+   (set_attr "imm_disp" "false")])
+
+(define_insn "*add_tp_x32_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
+                  (match_operand:SI 1 "register_operand" "0"))))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_X32"
+  "add{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}"
+  [(set_attr "type" "alu")
+   (set_attr "modrm" "0")
+   (set_attr "length" "7")
+   (set_attr "memory" "load")
+   (set_attr "imm_disp" "false")])
+
 (define_insn "*add_tp_<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
        (plus:P (unspec:P [(const_int 0)] UNSPEC_TP)
                (match_operand:P 1 "register_operand" "0")))
    (clobber (reg:CC FLAGS_REG))]
-  ""
+  "!TARGET_X32"
   "add{<imodesuffix>}\t{%%<tp_seg>:0, %0|%0, <iptrsize> PTR <tp_seg>:0}"
   [(set_attr "type" "alu")
    (set_attr "modrm" "0")
   ix86_tls_descriptor_calls_expanded_in_cfun = true;
 })
 
-(define_insn "*tls_dynamic_lea_32"
+(define_insn "*tls_dynamic_gnu2_lea_32"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (plus:SI (match_operand:SI 1 "register_operand" "b")
                 (const:SI
    (set_attr "length" "6")
    (set_attr "length_address" "4")])
 
-(define_insn "*tls_dynamic_call_32"
+(define_insn "*tls_dynamic_gnu2_call_32"
   [(set (match_operand:SI 0 "register_operand" "=a")
        (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")
                    (match_operand:SI 2 "register_operand" "0")
 
 (define_expand "tls_dynamic_gnu2_64"
   [(set (match_dup 2)
-       (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+       (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
                   UNSPEC_TLSDESC))
    (parallel
     [(set (match_operand:DI 0 "register_operand" "")
   ix86_tls_descriptor_calls_expanded_in_cfun = true;
 })
 
-(define_insn "*tls_dynamic_lea_64"
+(define_insn "*tls_dynamic_gnu2_lea_64"
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+       (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
                   UNSPEC_TLSDESC))]
   "TARGET_64BIT && TARGET_GNU2_TLS"
   "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[rip]}"
    (set_attr "length" "7")
    (set_attr "length_address" "4")])
 
-(define_insn "*tls_dynamic_call_64"
+(define_insn "*tls_dynamic_gnu2_call_64"
   [(set (match_operand:DI 0 "register_operand" "=a")
-       (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
+       (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")
                    (match_operand:DI 2 "register_operand" "0")
                    (reg:DI SP_REG)]
                   UNSPEC_TLSDESC))
                     (reg:DI SP_REG)]
                    UNSPEC_TLSDESC)
         (const:DI (unspec:DI
-                   [(match_operand:DI 1 "tls_symbolic_operand" "")]
+                   [(match_operand 1 "tls_symbolic_operand" "")]
                    UNSPEC_DTPOFF))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && TARGET_GNU2_TLS"
 })
 
 (define_expand "round<mode>2"
-  [(match_operand:MODEF 0 "register_operand" "")
-   (match_operand:MODEF 1 "nonimmediate_operand" "")]
-  "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
-   && !flag_trapping_math && !flag_rounding_math"
+  [(match_operand:X87MODEF 0 "register_operand" "")
+   (match_operand:X87MODEF 1 "nonimmediate_operand" "")]
+  "(TARGET_USE_FANCY_MATH_387
+    && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+       || TARGET_MIX_SSE_I387)
+    && flag_unsafe_math_optimizations)
+   || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
+       && !flag_trapping_math && !flag_rounding_math)"
 {
   if (optimize_insn_for_size_p ())
     FAIL;
-  if (TARGET_64BIT || (<MODE>mode != DFmode))
-    ix86_expand_round (operand0, operand1);
+
+  if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
+      && !flag_trapping_math && !flag_rounding_math)
+    {
+      if (TARGET_64BIT || (<MODE>mode != DFmode))
+       ix86_expand_round (operands[0], operands[1]);
+      else
+       ix86_expand_rounddf_32 (operands[0], operands[1]);
+    }
   else
-    ix86_expand_rounddf_32 (operand0, operand1);
+    {
+      operands[1] = force_reg (<MODE>mode, operands[1]);
+      ix86_emit_i387_round (operands[0], operands[1]);
+    }
   DONE;
 })
 
   "SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH
    && ((<SWI48x:MODE>mode != DImode) || TARGET_64BIT)")
 
-(define_expand "lround<MODEF:mode><SWI48x:mode>2"
-  [(match_operand:SWI48x 0 "nonimmediate_operand" "")
-   (match_operand:MODEF 1 "register_operand" "")]
-  "SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH
-   && ((<SWI48x:MODE>mode != DImode) || TARGET_64BIT)
-   && !flag_trapping_math && !flag_rounding_math"
+(define_expand "lround<X87MODEF:mode><SWI248x:mode>2"
+  [(match_operand:SWI248x 0 "nonimmediate_operand" "")
+   (match_operand:X87MODEF 1 "register_operand" "")]
+  "(TARGET_USE_FANCY_MATH_387
+    && (!(SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH)
+       || TARGET_MIX_SSE_I387)
+    && flag_unsafe_math_optimizations)
+   || (SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH
+       && <SWI248x:MODE>mode != HImode 
+       && ((<SWI248x:MODE>mode != DImode) || TARGET_64BIT)
+       && !flag_trapping_math && !flag_rounding_math)"
 {
   if (optimize_insn_for_size_p ())
     FAIL;
-  ix86_expand_lround (operand0, operand1);
+
+  if (SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH
+      && <SWI248x:MODE>mode != HImode
+      && ((<SWI248x:MODE>mode != DImode) || TARGET_64BIT)
+      && !flag_trapping_math && !flag_rounding_math)
+    ix86_expand_lround (operand0, operand1);
+  else
+    ix86_emit_i387_round (operands[0], operands[1]);
   DONE;
 })
 
    (set (match_operand:DI 1 "register_operand" "=S")
        (plus:DI (match_dup 3)
                 (const_int 8)))]
-  "TARGET_64BIT"
+  "TARGET_64BIT
+   && !(fixed_regs[SI_REG] || fixed_regs[DI_REG])"
   "movsq"
   [(set_attr "type" "str")
    (set_attr "memory" "both")
    (set (match_operand:P 1 "register_operand" "=S")
        (plus:P (match_dup 3)
                (const_int 4)))]
-  ""
+  "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])"
   "movs{l|d}"
   [(set_attr "type" "str")
    (set_attr "memory" "both")
    (set (match_operand:P 1 "register_operand" "=S")
        (plus:P (match_dup 3)
                (const_int 2)))]
-  ""
+  "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])"
   "movsw"
   [(set_attr "type" "str")
    (set_attr "memory" "both")
    (set (match_operand:P 1 "register_operand" "=S")
        (plus:P (match_dup 3)
                (const_int 1)))]
-  ""
+  "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])"
   "movsb"
   [(set_attr "type" "str")
    (set_attr "memory" "both")
    (set (mem:BLK (match_dup 3))
        (mem:BLK (match_dup 4)))
    (use (match_dup 5))]
-  "TARGET_64BIT"
+  "TARGET_64BIT
+   && !(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
   "rep{%;} movsq"
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
    (set (mem:BLK (match_dup 3))
        (mem:BLK (match_dup 4)))
    (use (match_dup 5))]
-  ""
+  "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
   "rep{%;} movs{l|d}"
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
    (set (mem:BLK (match_dup 3))
        (mem:BLK (match_dup 4)))
    (use (match_dup 5))]
-  ""
+  "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
   "rep{%;} movsb"
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
   operands[3] = gen_rtx_PLUS (Pmode, operands[0],
                              GEN_INT (GET_MODE_SIZE (GET_MODE
                                                      (operands[2]))));
-  if (TARGET_SINGLE_STRINGOP || optimize_insn_for_size_p ())
+  /* Can't use this if the user has appropriated eax or edi.  */
+  if ((TARGET_SINGLE_STRINGOP || optimize_insn_for_size_p ())
+      && !(fixed_regs[AX_REG] || fixed_regs[DI_REG]))
     {
       emit_insn (gen_strset_singleop (operands[0], operands[1], operands[2],
                                      operands[3]));
    (set (match_operand:DI 0 "register_operand" "=D")
        (plus:DI (match_dup 1)
                 (const_int 8)))]
-  "TARGET_64BIT"
+  "TARGET_64BIT
+   && !(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
   "stosq"
   [(set_attr "type" "str")
    (set_attr "memory" "store")
    (set (match_operand:P 0 "register_operand" "=D")
        (plus:P (match_dup 1)
                (const_int 4)))]
-  ""
+  "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
   "stos{l|d}"
   [(set_attr "type" "str")
    (set_attr "memory" "store")
    (set (match_operand:P 0 "register_operand" "=D")
        (plus:P (match_dup 1)
                (const_int 2)))]
-  ""
+  "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
   "stosw"
   [(set_attr "type" "str")
    (set_attr "memory" "store")
    (set (match_operand:P 0 "register_operand" "=D")
        (plus:P (match_dup 1)
                (const_int 1)))]
-  ""
+  "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
   "stosb"
   [(set_attr "type" "str")
    (set_attr "memory" "store")
        (const_int 0))
    (use (match_operand:DI 2 "register_operand" "a"))
    (use (match_dup 4))]
-  "TARGET_64BIT"
+  "TARGET_64BIT
+   && !(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])"
   "rep{%;} stosq"
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
        (const_int 0))
    (use (match_operand:SI 2 "register_operand" "a"))
    (use (match_dup 4))]
-  ""
+  "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])"
   "rep{%;} stos{l|d}"
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
        (const_int 0))
    (use (match_operand:QI 2 "register_operand" "a"))
    (use (match_dup 4))]
-  ""
+  "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])"
   "rep{%;} stosb"
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
   if (optimize_insn_for_size_p () && !TARGET_INLINE_ALL_STRINGOPS)
     FAIL;
 
-  /* Can't use this if the user has appropriated esi or edi.  */
-  if (fixed_regs[SI_REG] || fixed_regs[DI_REG])
+  /* Can't use this if the user has appropriated ecx, esi or edi.  */
+  if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
     FAIL;
 
   out = operands[0];
    (clobber (match_operand:P 0 "register_operand" "=S"))
    (clobber (match_operand:P 1 "register_operand" "=D"))
    (clobber (match_operand:P 2 "register_operand" "=c"))]
-  ""
+  "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
   "repz{%;} cmpsb"
   [(set_attr "type" "str")
    (set_attr "mode" "QI")
    (clobber (match_operand:P 0 "register_operand" "=S"))
    (clobber (match_operand:P 1 "register_operand" "=D"))
    (clobber (match_operand:P 2 "register_operand" "=c"))]
-  ""
+  "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
   "repz{%;} cmpsb"
   [(set_attr "type" "str")
    (set_attr "mode" "QI")
    (set_attr "prefix_rep" "1")])
 
 (define_expand "strlen<mode>"
-  [(set (match_operand:SWI48x 0 "register_operand" "")
-       (unspec:SWI48x [(match_operand:BLK 1 "general_operand" "")
-                       (match_operand:QI 2 "immediate_operand" "")
-                       (match_operand 3 "immediate_operand" "")]
-                      UNSPEC_SCAS))]
+  [(set (match_operand:P 0 "register_operand" "")
+       (unspec:P [(match_operand:BLK 1 "general_operand" "")
+                  (match_operand:QI 2 "immediate_operand" "")
+                  (match_operand 3 "immediate_operand" "")]
+                 UNSPEC_SCAS))]
   ""
 {
  if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
                   (match_operand:P 4 "register_operand" "0")] UNSPEC_SCAS))
    (clobber (match_operand:P 1 "register_operand" "=D"))
    (clobber (reg:CC FLAGS_REG))]
-  ""
+  "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])"
   "repnz{%;} scasb"
   [(set_attr "type" "str")
    (set_attr "mode" "QI")
 
 #ifdef TARGET_THREAD_SSP_OFFSET
   operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET);
-  insn = (TARGET_64BIT
+  insn = (TARGET_LP64
          ? gen_stack_tls_protect_set_di
          : gen_stack_tls_protect_set_si);
 #else
-  insn = (TARGET_64BIT
+  insn = (TARGET_LP64
          ? gen_stack_protect_set_di
          : gen_stack_protect_set_si);
 #endif
 })
 
 (define_insn "stack_protect_set_<mode>"
-  [(set (match_operand:P 0 "memory_operand" "=m")
-       (unspec:P [(match_operand:P 1 "memory_operand" "m")] UNSPEC_SP_SET))
-   (set (match_scratch:P 2 "=&r") (const_int 0))
+  [(set (match_operand:PTR 0 "memory_operand" "=m")
+       (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
+                   UNSPEC_SP_SET))
+   (set (match_scratch:PTR 2 "=&r") (const_int 0))
    (clobber (reg:CC FLAGS_REG))]
   ""
   "mov{<imodesuffix>}\t{%1, %2|%2, %1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
   [(set_attr "type" "multi")])
 
 (define_insn "stack_tls_protect_set_<mode>"
-  [(set (match_operand:P 0 "memory_operand" "=m")
-       (unspec:P [(match_operand:P 1 "const_int_operand" "i")]
-                 UNSPEC_SP_TLS_SET))
-   (set (match_scratch:P 2 "=&r") (const_int 0))
+  [(set (match_operand:PTR 0 "memory_operand" "=m")
+       (unspec:PTR [(match_operand:PTR 1 "const_int_operand" "i")]
+                   UNSPEC_SP_TLS_SET))
+   (set (match_scratch:PTR 2 "=&r") (const_int 0))
    (clobber (reg:CC FLAGS_REG))]
   ""
   "mov{<imodesuffix>}\t{%@:%P1, %2|%2, <iptrsize> PTR %@:%P1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
 
 #ifdef TARGET_THREAD_SSP_OFFSET
   operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET);
-  insn = (TARGET_64BIT
+  insn = (TARGET_LP64
          ? gen_stack_tls_protect_test_di
          : gen_stack_tls_protect_test_si);
 #else
-  insn = (TARGET_64BIT
+  insn = (TARGET_LP64
          ? gen_stack_protect_test_di
          : gen_stack_protect_test_si);
 #endif
 
 (define_insn "stack_protect_test_<mode>"
   [(set (match_operand:CCZ 0 "flags_reg_operand" "")
-       (unspec:CCZ [(match_operand:P 1 "memory_operand" "m")
-                    (match_operand:P 2 "memory_operand" "m")]
+       (unspec:CCZ [(match_operand:PTR 1 "memory_operand" "m")
+                    (match_operand:PTR 2 "memory_operand" "m")]
                    UNSPEC_SP_TEST))
-   (clobber (match_scratch:P 3 "=&r"))]
+   (clobber (match_scratch:PTR 3 "=&r"))]
   ""
   "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%2, %3|%3, %2}"
   [(set_attr "type" "multi")])
 
 (define_insn "stack_tls_protect_test_<mode>"
   [(set (match_operand:CCZ 0 "flags_reg_operand" "")
-       (unspec:CCZ [(match_operand:P 1 "memory_operand" "m")
-                    (match_operand:P 2 "const_int_operand" "i")]
+       (unspec:CCZ [(match_operand:PTR 1 "memory_operand" "m")
+                    (match_operand:PTR 2 "const_int_operand" "i")]
                    UNSPEC_SP_TLS_TEST))
-   (clobber (match_scratch:P 3 "=r"))]
+   (clobber (match_scratch:PTR 3 "=r"))]
   ""
   "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%@:%P2, %3|%3, <iptrsize> PTR %@:%P2}"
   [(set_attr "type" "multi")])