OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.md
index 976bc72..f0bec12 100644 (file)
@@ -1,6 +1,6 @@
 ;; GCC machine description for IA-32 and x86-64.
 ;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
 ;; Free Software Foundation, Inc.
 ;; Mostly by William Schelter.
 ;; x86_64 support added by Jan Hubicka
@@ -58,6 +58,7 @@
    (UNSPEC_GOTNTPOFF           7)
    (UNSPEC_INDNTPOFF           8)
    (UNSPEC_PLTOFF              9)
+   (UNSPEC_MACHOPIC_OFFSET     10)
 
    ; Prologue support
    (UNSPEC_STACK_ALLOC         11)
    (UNSPEC_LFENCE              45)
    (UNSPEC_PSADBW              46)
    (UNSPEC_LDDQU               47)
+   (UNSPEC_MS_TO_SYSV_CALL     48)
 
    ; Generic math support
    (UNSPEC_COPYSIGN            50)
    ; For AVX support
    (UNSPEC_PCMP                        166)
    (UNSPEC_VPERMIL             167)
-   (UNSPEC_VPERMIL2            168)
-   (UNSPEC_VPERMIL2F128                169)
-   (UNSPEC_MASKLOAD            170)
-   (UNSPEC_MASKSTORE           171)
-   (UNSPEC_CAST                        172)
-   (UNSPEC_VTESTP              173)
+   (UNSPEC_VPERMIL2F128                168)
+   (UNSPEC_MASKLOAD            169)
+   (UNSPEC_MASKSTORE           170)
+   (UNSPEC_CAST                        171)
+   (UNSPEC_VTESTP              172)
   ])
 
 (define_constants
    (UNSPECV_ALIGN              7)
    (UNSPECV_MONITOR            8)
    (UNSPECV_MWAIT              9)
-   (UNSPECV_CMPXCHG_1          10)
-   (UNSPECV_CMPXCHG_2          11)
+   (UNSPECV_CMPXCHG            10)
    (UNSPECV_XCHG               12)
    (UNSPECV_LOCK               13)
    (UNSPECV_PROLOGUE_USE       14)
 ;; "reload_completed && TARGET_64BIT".
 
 \f
-;; Processor type.  This attribute must exactly match the processor_type
-;; enumeration in i386.h.
-(define_attr "cpu" "i386,i486,pentium,pentiumpro,geode,k6,athlon,pentium4,k8,
-                    nocona,core2,generic32,generic64,amdfam10"
-  (const (symbol_ref "ix86_tune")))
+;; Processor type.
+(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,
+                   generic64,amdfam10"
+  (const (symbol_ref "ix86_schedule")))
 
 ;; A basic instruction type.  Refinements due to arguments to be
 ;; provided in other attributes.
 ;; All single word integer modes.
 (define_mode_iterator SWI [QI HI SI (DI "TARGET_64BIT")])
 
+;; Single word integer modes without QImode.
+(define_mode_iterator SWI248 [HI SI (DI "TARGET_64BIT")])
+
 ;; Instruction suffix for integer modes.
 (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
 
         to stack may result in unaligned memory access.  */
       if (misaligned_operand (operands[0], TImode)
          || misaligned_operand (operands[1], TImode))
-       { 
+       {
          if (get_attr_mode (insn) == MODE_V4SF)
            return "%vmovups\t{%1, %0|%0, %1}";
         else
           return "%vmovdqu\t{%1, %0|%0, %1}";
        }
       else
-       { 
+       {
          if (get_attr_mode (insn) == MODE_V4SF)
            return "%vmovaps\t{%1, %0|%0, %1}";
         else
         to stack may result in unaligned memory access.  */
       if (misaligned_operand (operands[0], TImode)
          || misaligned_operand (operands[1], TImode))
-       { 
+       {
          if (get_attr_mode (insn) == MODE_V4SF)
            return "%vmovups\t{%1, %0|%0, %1}";
         else
           return "%vmovdqu\t{%1, %0|%0, %1}";
        }
       else
-       { 
+       {
          if (get_attr_mode (insn) == MODE_V4SF)
            return "%vmovaps\t{%1, %0|%0, %1}";
         else
   [(set (match_operand:DF 0 "register_operand" "")
         (float_extend:DF
          (match_operand:SF 1 "nonimmediate_operand" "")))]
-  "(TARGET_USE_VECTOR_CONVERTS || TARGET_GENERIC)
+  "TARGET_USE_VECTOR_FP_CONVERTS
    && optimize_insn_for_speed_p ()
    && reload_completed && SSE_REG_P (operands[0])"
    [(set (match_dup 2)
   [(set (match_operand:SF 0 "register_operand" "")
         (float_truncate:SF
          (match_operand:DF 1 "nonimmediate_operand" "")))]
-  "(TARGET_USE_VECTOR_CONVERTS || TARGET_GENERIC)
+  "TARGET_USE_VECTOR_FP_CONVERTS
    && optimize_insn_for_speed_p ()
    && reload_completed && SSE_REG_P (operands[0])"
    [(set (match_dup 2)
 
   /* Avoid store forwarding (partial memory) stall penalty
      by passing DImode value through XMM registers.  */
-  if (<SSEMODEI24:MODE>mode == DImode && !TARGET_64BIT 
-      && TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES 
+  if (<SSEMODEI24:MODE>mode == DImode && !TARGET_64BIT
+      && TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES
       && optimize_function_for_speed_p (cfun))
     {
       emit_insn (gen_floatdi<X87MODEF:mode>2_i387_with_xmm (operands[0],
     operands[4] = simplify_gen_subreg (V4SImode, operands[1], SImode, 0);
   else
     gcc_unreachable ();
+  emit_insn
+    (gen_sse2_cvtdq2p<ssemodefsuffix> (operands[3], operands[4]));
+  DONE;
 })
 
 (define_split
             (const_int 2)
             (const_int 6)))])
 
-;; ??? Handle alignment requirements for compare and branch fused macro-op;
-;; the branch instruction does not start at a 16-byte boundary or cross
-;; a 16-byte boundary.
-
-(define_insn "*jcc_fused_1"
-  [(set (pc)
-       (if_then_else (match_operator 1 "comparison_operator"
-                       [(match_operand:SWI 2 "register_operand" "<r>")
-                        (match_operand:SWI 3 "const0_operand" "")])
-        (label_ref (match_operand 0 "" ""))
-        (pc)))]
-  "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT"
-{
-  return "test{<imodesuffix>}\t%2, %2\n\t"
-        "%+j%E1\t%l0\t" ASM_COMMENT_START " fused";
-}
-  [(set_attr "type" "multi")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "*jcc_fused_2"
-  [(set (pc)
-       (if_then_else (match_operator 1 "comparison_operator"
-                       [(match_operand:SWI 2 "register_operand" "<r>")
-                        (match_operand:SWI 3 "const0_operand" "")])
-        (pc)
-        (label_ref (match_operand 0 "" ""))))]
-  "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT"
-{
-  return "test{<imodesuffix>}\t%2, %2\n\t"
-        "%+j%e1\t%l0\t" ASM_COMMENT_START " fused";
-}
-  [(set_attr "type" "multi")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "*jcc_fused_3"
-  [(set (pc)
-       (if_then_else
-         (match_operator 1 "ix86_comparison_uns_operator"
-           [(match_operand:SWI 2 "nonimmediate_operand" "<r>,m,<r>")
-            (match_operand:SWI 3 "<general_operand>" "<r><i>,<r>,m")])
-        (label_ref (match_operand 0 "" ""))
-        (pc)))]
-  "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT
-   && !(MEM_P (operands[2])
-       && (MEM_P (operands[3]) || CONST_INT_P (operands[3])))"
-{
-  return "cmp{<imodesuffix>}\t{%3, %2|%2, %3}\n\t"
-        "%+j%E1\t%l0\t" ASM_COMMENT_START " fused";
-}
-  [(set_attr "type" "multi")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "*jcc_fused_4"
-  [(set (pc)
-       (if_then_else
-         (match_operator 1 "ix86_comparison_uns_operator"
-           [(match_operand:SWI 2 "nonimmediate_operand" "<r>,m,<r>")
-            (match_operand:SWI 3 "<general_operand>" "<r><i>,<r>,m")])
-        (pc)
-        (label_ref (match_operand 0 "" ""))))]
-  "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT
-   && !(MEM_P (operands[2])
-       && (MEM_P (operands[3]) || CONST_INT_P (operands[3])))"
-{
-  return "cmp{<imodesuffix>}\t{%3, %2|%2, %3}\n\t"
-        "%+j%e1\t%l0\t" ASM_COMMENT_START " fused";
-}
-  [(set_attr "type" "multi")
-   (set_attr "mode" "<MODE>")])
-
 ;; In general it is not safe to assume too much about CCmode registers,
 ;; so simplify-rtx stops when it sees a second one.  Under certain
 ;; conditions this is safe on x86, so help combine not create
                             (match_operand:QI 2 "register_operand" "r")))
                         (const_int 0)])
                      (label_ref (match_operand 3 "" ""))
-                     (pc)))]
+                     (pc)))
+   (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && (TARGET_USE_BT || optimize_function_for_size_p (cfun))"
   "#"
   "&& 1"
                             (match_operand:SI 2 "register_operand" "r")
                             (match_operand:SI 3 "const_int_operand" "n")))])
                      (label_ref (match_operand 4 "" ""))
-                     (pc)))]
+                     (pc)))
+   (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && (TARGET_USE_BT || optimize_function_for_size_p (cfun))
    && (INTVAL (operands[3]) & 0x3f) == 0x3f"
   "#"
                             (match_operand:QI 2 "register_operand" "r")))
                         (const_int 0)])
                      (label_ref (match_operand 3 "" ""))
-                     (pc)))]
+                     (pc)))
+   (clobber (reg:CC FLAGS_REG))]
   "TARGET_USE_BT || optimize_function_for_size_p (cfun)"
   "#"
   "&& 1"
                             (match_operand:SI 2 "register_operand" "r")
                             (match_operand:SI 3 "const_int_operand" "n")))])
                      (label_ref (match_operand 4 "" ""))
-                     (pc)))]
+                     (pc)))
+   (clobber (reg:CC FLAGS_REG))]
   "(TARGET_USE_BT || optimize_function_for_size_p (cfun))
    && (INTVAL (operands[3]) & 0x1f) == 0x1f"
   "#"
                           (const_int 1))
                         (const_int 0)])
                      (label_ref (match_operand 3 "" ""))
-                     (pc)))]
+                     (pc)))
+   (clobber (reg:CC FLAGS_REG))]
   "TARGET_USE_BT || optimize_function_for_size_p (cfun)"
   "#"
   "&& 1"
               (const_int 1))
             (const_int 0)])
          (label_ref (match_operand 4 "" ""))
-         (pc)))]
+         (pc)))
+   (clobber (reg:CC FLAGS_REG))]
   "(TARGET_USE_BT || optimize_function_for_size_p (cfun))
    && (INTVAL (operands[3]) & 0x1f) == 0x1f"
   "#"
 }
   [(set_attr "type" "call")])
 
+(define_insn "*call_1_rex64_ms_sysv"
+  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
+        (match_operand 1 "" ""))
+   (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
+   (clobber (reg:DI SI_REG))
+   (clobber (reg:DI DI_REG))]
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+{
+  if (constant_call_address_operand (operands[0], Pmode))
+    return "call\t%P0";
+  return "call\t%A0";
+}
+  [(set_attr "type" "call")])
+
 (define_insn "*call_1_rex64_large"
   [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm"))
         (match_operand 1 "" ""))]
 (define_expand "ffs_cmove"
   [(set (match_dup 2) (const_int -1))
    (parallel [(set (reg:CCZ FLAGS_REG)
-                  (compare:CCZ (match_operand:SI 1 "register_operand" "")
+                  (compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "")
                                (const_int 0)))
-             (set (match_operand:SI 0 "nonimmediate_operand" "")
+             (set (match_operand:SI 0 "register_operand" "")
                   (ctz:SI (match_dup 1)))])
    (set (match_dup 0) (if_then_else:SI
                        (eq (reg:CCZ FLAGS_REG) (const_int 0))
   "operands[2] = gen_reg_rtx (SImode);")
 
 (define_insn_and_split "*ffs_no_cmove"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+  [(set (match_operand:SI 0 "register_operand" "=r")
        (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
    (clobber (match_scratch:SI 2 "=&q"))
    (clobber (reg:CC FLAGS_REG))]
 (define_expand "ffsdi2"
   [(set (match_dup 2) (const_int -1))
    (parallel [(set (reg:CCZ FLAGS_REG)
-                  (compare:CCZ (match_operand:DI 1 "register_operand" "")
+                  (compare:CCZ (match_operand:DI 1 "nonimmediate_operand" "")
                                (const_int 0)))
-             (set (match_operand:DI 0 "nonimmediate_operand" "")
+             (set (match_operand:DI 0 "register_operand" "")
                   (ctz:DI (match_dup 1)))])
    (set (match_dup 0) (if_then_else:DI
                        (eq (reg:CCZ FLAGS_REG) (const_int 0))
   [(set_attr "prefix_0f" "1")
    (set_attr "mode" "SI")])
 
-(define_insn "popcountsi2"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (popcount:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
+(define_insn "popcount<mode>2"
+  [(set (match_operand:SWI248 0 "register_operand" "=r")
+       (popcount:SWI248
+         (match_operand:SWI248 1 "nonimmediate_operand" "rm")))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_POPCNT"
-  "popcnt{l}\t{%1, %0|%0, %1}"
+{
+#if TARGET_MACHO
+  return "popcnt\t{%1, %0|%0, %1}";
+#else
+  return "popcnt{<imodesuffix>}\t{%1, %0|%0, %1}";
+#endif
+}
   [(set_attr "prefix_rep" "1")
    (set_attr "type" "bitmanip")
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "<MODE>")])
 
-(define_insn "*popcountsi2_cmp"
+(define_insn "*popcount<mode>2_cmp"
   [(set (reg FLAGS_REG)
        (compare
-         (popcount:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))
+         (popcount:SWI248
+           (match_operand:SWI248 1 "nonimmediate_operand" "rm"))
          (const_int 0)))
-   (set (match_operand:SI 0 "register_operand" "=r")
-       (popcount:SI (match_dup 1)))]
+   (set (match_operand:SWI248 0 "register_operand" "=r")
+       (popcount:SWI248 (match_dup 1)))]
   "TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
-  "popcnt{l}\t{%1, %0|%0, %1}"
+{
+#if TARGET_MACHO
+  return "popcnt\t{%1, %0|%0, %1}";
+#else
+  return "popcnt{<imodesuffix>}\t{%1, %0|%0, %1}";
+#endif
+}
   [(set_attr "prefix_rep" "1")
    (set_attr "type" "bitmanip")
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "<MODE>")])
 
 (define_insn "*popcountsi2_cmp_zext"
   [(set (reg FLAGS_REG)
    (set (match_operand:DI 0 "register_operand" "=r")
         (zero_extend:DI(popcount:SI (match_dup 1))))]
   "TARGET_64BIT && TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
-  "popcnt{l}\t{%1, %0|%0, %1}"
+{
+#if TARGET_MACHO
+  return "popcnt\t{%1, %0|%0, %1}";
+#else
+  return "popcnt{<imodesuffix>}\t{%1, %0|%0, %1}";
+#endif
+}
   [(set_attr "prefix_rep" "1")
    (set_attr "type" "bitmanip")
    (set_attr "mode" "SI")])
   [(set_attr "prefix_0f" "1")
    (set_attr "mode" "DI")])
 
-(define_insn "popcountdi2"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (popcount:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && TARGET_POPCNT"
-  "popcnt{q}\t{%1, %0|%0, %1}"
-  [(set_attr "prefix_rep" "1")
-   (set_attr "type" "bitmanip")
-   (set_attr "mode" "DI")])
-
-(define_insn "*popcountdi2_cmp"
-  [(set (reg FLAGS_REG)
-       (compare
-         (popcount:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))
-         (const_int 0)))
-   (set (match_operand:DI 0 "register_operand" "=r")
-       (popcount:DI (match_dup 1)))]
-  "TARGET_64BIT && TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
-  "popcnt{q}\t{%1, %0|%0, %1}"
-  [(set_attr "prefix_rep" "1")
-   (set_attr "type" "bitmanip")
-   (set_attr "mode" "DI")])
-
 (define_expand "clzhi2"
   [(parallel
      [(set (match_operand:HI 0 "register_operand" "")
   [(set_attr "prefix_0f" "1")
    (set_attr "mode" "HI")])
 
-(define_insn "popcounthi2"
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (popcount:HI (match_operand:HI 1 "nonimmediate_operand" "rm")))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_POPCNT"
-  "popcnt{w}\t{%1, %0|%0, %1}"
-  [(set_attr "prefix_rep" "1")
-   (set_attr "type" "bitmanip")
-   (set_attr "mode" "HI")])
-
-(define_insn "*popcounthi2_cmp"
-  [(set (reg FLAGS_REG)
-        (compare
-          (popcount:HI (match_operand:HI 1 "nonimmediate_operand" "rm"))
-          (const_int 0)))
-   (set (match_operand:HI 0 "register_operand" "=r")
-        (popcount:HI (match_dup 1)))]
-  "TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
-  "popcnt{w}\t{%1, %0|%0, %1}"
-  [(set_attr "prefix_rep" "1")
-   (set_attr "type" "bitmanip")
-   (set_attr "mode" "HI")])
-
 (define_expand "paritydi2"
   [(set (match_operand:DI 0 "register_operand" "")
        (parity:DI (match_operand:DI 1 "register_operand" "")))]
    (set_attr "mode" "DI")])
 
 (define_insn "allocate_stack_worker_32"
-  [(set (match_operand:SI 0 "register_operand" "+a")
-       (unspec_volatile:SI [(match_dup 0)] UNSPECV_STACK_PROBE))
-   (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")]
+                           UNSPECV_STACK_PROBE))
+   (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 1)))
    (clobber (reg:CC FLAGS_REG))]
   "!TARGET_64BIT && TARGET_STACK_PROBE"
   "call\t___chkstk"
    (set_attr "length" "5")])
 
 (define_insn "allocate_stack_worker_64"
-  [(set (match_operand:DI 0 "register_operand" "+a")
-       (unspec_volatile:DI [(match_dup 0)] UNSPECV_STACK_PROBE))
-   (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
+  [(set (match_operand:DI 0 "register_operand" "=a")
+       (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")]
+                           UNSPECV_STACK_PROBE))
+   (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 1)))
    (clobber (reg:DI R10_REG))
    (clobber (reg:DI R11_REG))
    (clobber (reg:CC FLAGS_REG))]
     {
       x = copy_to_mode_reg (Pmode, operands[1]);
       if (TARGET_64BIT)
-       x = gen_allocate_stack_worker_64 (x);
+       x = gen_allocate_stack_worker_64 (x, x);
       else
-       x = gen_allocate_stack_worker_32 (x);
+       x = gen_allocate_stack_worker_32 (x, x);
       emit_insn (x);
     }
 
   [(label_ref (match_operand 0 "" ""))]
   "!TARGET_64BIT && flag_pic"
 {
+#if TARGET_MACHO
   if (TARGET_MACHO)
     {
       rtx xops[3];
       rtx label_rtx = gen_label_rtx ();
       emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx));
       xops[0] = xops[1] = picreg;
-      xops[2] = gen_rtx_CONST (SImode,
-                 gen_rtx_MINUS (SImode,
-                   gen_rtx_LABEL_REF (SImode, label_rtx),
-                   gen_rtx_SYMBOL_REF (SImode, GOT_SYMBOL_NAME)));
+      xops[2] = machopic_gen_offset (gen_rtx_LABEL_REF (SImode, label_rtx));
       ix86_expand_binary_operator (MINUS, SImode, xops);
     }
   else
+#endif
     emit_insn (gen_set_got (pic_offset_table_rtx));
   DONE;
 })
                      [(match_dup 0)
                       (match_operand:SI 1 "memory_operand" "")]))
               (clobber (reg:CC FLAGS_REG))])]
-  "optimize_insn_for_speed_p ()"
+  "optimize_insn_for_speed_p () && ! TARGET_READ_MODIFY"
   [(set (match_dup 2) (match_dup 1))
    (parallel [(set (match_dup 0)
                    (match_op_dup 3 [(match_dup 0) (match_dup 2)]))
   "")
 \f
 ;; Convert compares with 1 to shorter inc/dec operations when CF is not
-;; required and register dies.  Similarly for 128 to plus -128.
+;; required and register dies.  Similarly for 128 to -128.
 (define_peephole2
   [(set (match_operand 0 "flags_reg_operand" "")
        (match_operator 1 "compare_operator"
          [(match_operand 2 "register_operand" "")
           (match_operand 3 "const_int_operand" "")]))]
-  "(INTVAL (operands[3]) == -1
-    || INTVAL (operands[3]) == 1
-    || INTVAL (operands[3]) == 128)
+  "(((!TARGET_FUSE_CMP_AND_BRANCH || optimize_size)
+     && incdec_operand (operands[3], GET_MODE (operands[3])))
+    || (!TARGET_FUSE_CMP_AND_BRANCH
+       && INTVAL (operands[3]) == 128))
    && ix86_match_ccmode (insn, CCGCmode)
    && peep2_reg_dead_p (1, operands[2])"
   [(parallel [(set (match_dup 0)
 }
   [(set_attr "type" "callv")])
 
+(define_insn "*call_value_0_rex64_ms_sysv"
+  [(set (match_operand 0 "" "")
+       (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
+             (match_operand:DI 2 "const_int_operand" "")))
+   (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
+   (clobber (reg:DI SI_REG))
+   (clobber (reg:DI DI_REG))]
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+{
+  if (SIBLING_CALL_P (insn))
+    return "jmp\t%P1";
+  else
+    return "call\t%P1";
+}
+  [(set_attr "type" "callv")])
+
 (define_insn "*call_value_1"
   [(set (match_operand 0 "" "")
        (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
 }
   [(set_attr "type" "callv")])
 
+(define_insn "*call_value_1_rex64_ms_sysv"
+  [(set (match_operand 0 "" "")
+       (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
+             (match_operand:DI 2 "" "")))
+   (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
+   (clobber (reg:DI SI_REG))
+   (clobber (reg:DI DI_REG))]
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+{
+  if (constant_call_address_operand (operands[1], Pmode))
+    return "call\t%P1";
+  return "call\t%A1";
+}
+  [(set_attr "type" "callv")])
+
 (define_insn "*call_value_1_rex64_large"
   [(set (match_operand 0 "" "")
        (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm"))