;; 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, 2009, 2010
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; Free Software Foundation, Inc.
;; Mostly by William Schelter.
;; x86_64 support added by Jan Hubicka
UNSPEC_INDNTPOFF
UNSPEC_PLTOFF
UNSPEC_MACHOPIC_OFFSET
+ UNSPEC_PCREL
;; Prologue support
UNSPEC_STACK_ALLOC
UNSPEC_TLS_GD
UNSPEC_TLS_LD_BASE
UNSPEC_TLSDESC
+ UNSPEC_TLS_IE_SUN
;; Other random patterns
UNSPEC_SCAS
UNSPEC_LD_MPIC ; load_macho_picbase
UNSPEC_TRUNC_NOOP
UNSPEC_DIV_ALREADY_SPLIT
+ UNSPEC_CALL_NEEDS_VZEROUPPER
;; For SSE/MMX support:
UNSPEC_FIX_NOTRUNC
UNSPEC_VTESTP
UNSPEC_VCVTPH2PS
UNSPEC_VCVTPS2PH
+
+ ;; For BMI support
+ UNSPEC_BEXTR
+
+ ;; For RDRAND support
+ UNSPEC_RDRAND
])
(define_c_enum "unspecv" [
UNSPECV_RDGSBASE
UNSPECV_WRFSBASE
UNSPECV_WRGSBASE
- UNSPECV_RDRAND
+ UNSPECV_SPLIT_STACK_RETURN
])
+;; Constants to represent rounding modes in the ROUND instruction
+(define_constants
+ [(ROUND_FLOOR 0x1)
+ (ROUND_CEIL 0x2)
+ (ROUND_TRUNC 0x3)
+ (ROUND_MXCSR 0x4)
+ (ROUND_NO_EXC 0x8)
+ ])
+
;; Constants to represent pcomtrue/pcomfalse variants
(define_constants
[(PCOM_FALSE 0)
\f
;; Processor type.
-(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,atom,
- generic64,amdfam10,bdver1"
+(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,corei7,
+ atom,generic64,amdfam10,bdver1,btver1"
(const (symbol_ref "ix86_schedule")))
;; A basic instruction type. Refinements due to arguments to be
(include "bdver1.md")
(include "geode.md")
(include "atom.md")
+(include "core2.md")
\f
;; Operand and operator predicates and constraints
(define_insn "*ashl<mode>3_cconly"
[(set (reg FLAGS_REG)
(compare
- (ashift:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")
+ (ashift:SWI (match_operand:SWI 1 "register_operand" "0")
(match_operand:QI 2 "<shift_immediate_operand>" "<S>"))
(const_int 0)))
(clobber (match_scratch:SWI 0 "=<r>"))]
|| (operands[2] == const1_rtx
&& (TARGET_SHIFT1
|| TARGET_DOUBLE_WITH_ADD)))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands)"
+ && ix86_match_ccmode (insn, CCGOCmode)"
{
switch (get_attr_type (insn))
{
[(set (reg FLAGS_REG)
(compare
(any_shiftrt:SWI
- (match_operand:SWI 1 "nonimmediate_operand" "0")
+ (match_operand:SWI 1 "register_operand" "0")
(match_operand:QI 2 "<shift_immediate_operand>" "<S>"))
(const_int 0)))
(clobber (match_scratch:SWI 0 "=<r>"))]
|| !TARGET_PARTIAL_FLAG_REG_STALL
|| (operands[2] == const1_rtx
&& TARGET_SHIFT1))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+ && ix86_match_ccmode (insn, CCGOCmode)"
{
if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
DONE;
})
+(define_insn_and_split "*call_pop_0_vzeroupper"
+ [(parallel
+ [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" ""))
+ (match_operand:SI 1 "" ""))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 2 "immediate_operand" "")))])
+ (unspec [(match_operand 3 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && !TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
+ [(set_attr "type" "call")])
+
(define_insn "*call_pop_0"
[(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" ""))
(match_operand:SI 1 "" ""))
}
[(set_attr "type" "call")])
+(define_insn_and_split "*call_pop_1_vzeroupper"
+ [(parallel
+ [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
+ (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)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
+ [(set_attr "type" "call")])
+
(define_insn "*call_pop_1"
[(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
(match_operand:SI 1 "" ""))
}
[(set_attr "type" "call")])
+(define_insn_and_split "*sibcall_pop_1_vzeroupper"
+ [(parallel
+ [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U"))
+ (match_operand:SI 1 "" ""))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 2 "immediate_operand" "i,i")))])
+ (unspec [(match_operand 3 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
+ [(set_attr "type" "call")])
+
(define_insn "*sibcall_pop_1"
[(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U"))
(match_operand:SI 1 "" ""))
DONE;
})
+(define_insn_and_split "*call_0_vzeroupper"
+ [(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
+ (match_operand 1 "" ""))
+ (unspec [(match_operand 2 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;"
+ [(set_attr "type" "call")])
+
(define_insn "*call_0"
[(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
(match_operand 1 "" ""))]
""
-{
- if (SIBLING_CALL_P (insn))
- return "jmp\t%P0";
- else
- return "call\t%P0";
-}
+ { return ix86_output_call_insn (insn, operands[0], 0); }
+ [(set_attr "type" "call")])
+
+(define_insn_and_split "*call_1_vzeroupper"
+ [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
+ (match_operand 1 "" ""))
+ (unspec [(match_operand 2 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;"
[(set_attr "type" "call")])
(define_insn "*call_1"
[(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
(match_operand 1 "" ""))]
"!TARGET_64BIT && !SIBLING_CALL_P (insn)"
-{
- if (constant_call_address_operand (operands[0], Pmode))
- return "call\t%P0";
- return "call\t%A0";
-}
+ { return ix86_output_call_insn (insn, operands[0], 0); }
+ [(set_attr "type" "call")])
+
+(define_insn_and_split "*sibcall_1_vzeroupper"
+ [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U"))
+ (match_operand 1 "" ""))
+ (unspec [(match_operand 2 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;"
[(set_attr "type" "call")])
(define_insn "*sibcall_1"
[(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U"))
(match_operand 1 "" ""))]
"!TARGET_64BIT && SIBLING_CALL_P (insn)"
- "@
- jmp\t%P0
- jmp\t%A0"
+ { return ix86_output_call_insn (insn, operands[0], 0); }
+ [(set_attr "type" "call")])
+
+(define_insn_and_split "*call_1_rex64_vzeroupper"
+ [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
+ (match_operand 1 "" ""))
+ (unspec [(match_operand 2 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)
+ && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;"
[(set_attr "type" "call")])
(define_insn "*call_1_rex64"
(match_operand 1 "" ""))]
"TARGET_64BIT && !SIBLING_CALL_P (insn)
&& ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
-{
- if (constant_call_address_operand (operands[0], Pmode))
- return "call\t%P0";
- return "call\t%A0";
-}
+ { return ix86_output_call_insn (insn, operands[0], 0); }
+ [(set_attr "type" "call")])
+
+(define_insn_and_split "*call_1_rex64_ms_sysv_vzeroupper"
+ [(parallel
+ [(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: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)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;"
[(set_attr "type" "call")])
(define_insn "*call_1_rex64_ms_sysv"
(clobber (reg:DI SI_REG))
(clobber (reg:DI DI_REG))]
"TARGET_64BIT && !SIBLING_CALL_P (insn)"
-{
- if (constant_call_address_operand (operands[0], Pmode))
- return "call\t%P0";
- return "call\t%A0";
-}
+ { return ix86_output_call_insn (insn, operands[0], 0); }
+ [(set_attr "type" "call")])
+
+(define_insn_and_split "*call_1_rex64_large_vzeroupper"
+ [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm"))
+ (match_operand 1 "" ""))
+ (unspec [(match_operand 2 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;"
[(set_attr "type" "call")])
(define_insn "*call_1_rex64_large"
[(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm"))
(match_operand 1 "" ""))]
"TARGET_64BIT && !SIBLING_CALL_P (insn)"
- "call\t%A0"
+ { return ix86_output_call_insn (insn, operands[0], 0); }
+ [(set_attr "type" "call")])
+
+(define_insn_and_split "*sibcall_1_rex64_vzeroupper"
+ [(call (mem:QI (match_operand:DI 0 "sibcall_insn_operand" "s,U"))
+ (match_operand 1 "" ""))
+ (unspec [(match_operand 2 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[2]); DONE;"
[(set_attr "type" "call")])
(define_insn "*sibcall_1_rex64"
[(call (mem:QI (match_operand:DI 0 "sibcall_insn_operand" "s,U"))
(match_operand 1 "" ""))]
"TARGET_64BIT && SIBLING_CALL_P (insn)"
- "@
- jmp\t%P0
- jmp\t%A0"
+ { return ix86_output_call_insn (insn, operands[0], 0); }
[(set_attr "type" "call")])
;; Call subroutine, returning value in operand 0
;; instruction which the middle-end doesn't see.
(define_insn "split_stack_return"
[(unspec_volatile [(match_operand:SI 0 "const_int_operand" "")]
- UNSPEC_STACK_CHECK)]
+ UNSPECV_SPLIT_STACK_RETURN)]
""
{
if (operands[0] == const0_rtx)
(set_attr "mode" "<MODE>")])
(define_insn "ctz<mode>2"
- [(set (match_operand:SWI48 0 "register_operand" "=r")
- (ctz:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+ [(set (match_operand:SWI248 0 "register_operand" "=r")
+ (ctz:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "rm")))
(clobber (reg:CC FLAGS_REG))]
""
- "bsf{<imodesuffix>}\t{%1, %0|%0, %1}"
+{
+ if (TARGET_BMI)
+ return "tzcnt{<imodesuffix>}\t{%1, %0|%0, %1}";
+ else
+ return "bsf{<imodesuffix>}\t{%1, %0|%0, %1}";
+}
[(set_attr "type" "alu1")
(set_attr "prefix_0f" "1")
+ (set (attr "prefix_rep") (symbol_ref "TARGET_BMI"))
(set_attr "mode" "<MODE>")])
(define_expand "clz<mode>2"
[(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_ABM || TARGET_BMI"
"lzcnt{<imodesuffix>}\t{%1, %0|%0, %1}"
[(set_attr "prefix_rep" "1")
(set_attr "type" "bitmanip")
(set_attr "mode" "<MODE>")])
+;; BMI instructions.
+(define_insn "*bmi_andn_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (and:SWI48
+ (not:SWI48
+ (match_operand:SWI48 1 "register_operand" "r"))
+ (match_operand:SWI48 2 "nonimmediate_operand" "rm")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "andn\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "bmi_bextr_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (unspec:SWI48 [(match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (match_operand:SWI48 2 "register_operand" "r")]
+ UNSPEC_BEXTR))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "bextr\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*bmi_blsi_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (and:SWI48
+ (neg:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm"))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "blsi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*bmi_blsmsk_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (xor:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int -1))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "blsmsk\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*bmi_blsr_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (and:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int -1))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "blsr\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+;; TBM instructions.
+(define_insn "tbm_bextri_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (zero_extract:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (match_operand:SWI48 2 "const_0_to_255_operand" "n")
+ (match_operand:SWI48 3 "const_0_to_255_operand" "n")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) << 8 | INTVAL (operands[3]));
+ return "bextr\t{%2, %1, %0|%0, %1, %2}";
+}
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blcfill_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (and:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int 1))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+ "blcfill\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blci_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (ior:SWI48
+ (not:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int 1)))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+ "blci\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blcic_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (and:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int 1))
+ (not:SWI48
+ (match_dup 1))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+ "blcic\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blcmsk_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (xor:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int 1))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+ "blcmsk\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blcs_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (ior:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int 1))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+ "blcs\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blsfill_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (ior:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int -1))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+ "blsfill\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blsic_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (ior:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int -1))
+ (not:SWI48
+ (match_dup 1))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+ "blsic\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_t1mskc_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (ior:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int 1))
+ (not:SWI48
+ (match_dup 1))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+ "t1mskc\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_tzmsk_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (and:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int -1))
+ (not:SWI48
+ (match_dup 1))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_TBM"
+ "tzmsk\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "bsr_rex64"
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (const_int 63)
(set_attr "memory" "load")
(set_attr "imm_disp" "false")])
+;; The Sun linker took the AMD64 TLS spec literally and can only handle
+;; %rax as destination of the initial executable code sequence.
+(define_insn "tls_initial_exec_64_sun"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI
+ [(match_operand:DI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLS_IE_SUN))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && TARGET_SUN_TLS"
+ "mov{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}\n\tadd{q}\t{%a1@gottpoff(%%rip), %0|%0, %a1@gottpoff[rip]}"
+ [(set_attr "type" "multi")])
+
;; GNU2 TLS patterns can be split.
(define_expand "tls_dynamic_gnu2_32"
FAIL;
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
- (operands[0], operands[1], GEN_INT (0x04)));
+ (operands[0], operands[1], GEN_INT (ROUND_MXCSR)));
else
ix86_expand_rint (operand0, operand1);
}
FAIL;
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
- (operands[0], operands[1], GEN_INT (0x01)));
+ (operands[0], operands[1], GEN_INT (ROUND_FLOOR)));
else if (TARGET_64BIT || (<MODE>mode != DFmode))
ix86_expand_floorceil (operand0, operand1, true);
else
{
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
- (operands[0], operands[1], GEN_INT (0x02)));
+ (operands[0], operands[1], GEN_INT (ROUND_CEIL)));
else if (optimize_insn_for_size_p ())
FAIL;
else if (TARGET_64BIT || (<MODE>mode != DFmode))
{
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
- (operands[0], operands[1], GEN_INT (0x03)));
+ (operands[0], operands[1], GEN_INT (ROUND_TRUNC)));
else if (optimize_insn_for_size_p ())
FAIL;
else if (TARGET_64BIT || (<MODE>mode != DFmode))
(plus (match_dup 0)
(match_operand 4 "x86_64_general_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
- "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
+ "IN_RANGE (INTVAL (operands[2]), 1, 3)
/* Validate MODE for lea. */
&& ((!TARGET_PARTIAL_REG_STALL
&& (GET_MODE (operands[0]) == QImode
[(set (match_dup 5) (match_dup 4))
(set (match_dup 0) (match_dup 1))]
{
- enum machine_mode mode = GET_MODE (operands[1]) == DImode ? DImode : SImode;
+ enum machine_mode op1mode = GET_MODE (operands[1]);
+ enum machine_mode mode = op1mode == DImode ? DImode : SImode;
int scale = 1 << INTVAL (operands[2]);
rtx index = gen_lowpart (Pmode, operands[1]);
rtx base = gen_lowpart (Pmode, operands[5]);
gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
operands[5] = base;
if (mode != Pmode)
- {
- operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
- operands[5] = gen_rtx_SUBREG (mode, operands[5], 0);
- }
+ operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
+ if (op1mode != Pmode)
+ operands[5] = gen_rtx_SUBREG (op1mode, operands[5], 0);
operands[0] = dest;
})
\f
;; Call-value patterns last so that the wildcard operand does not
;; disrupt insn-recog's switch tables.
+(define_insn_and_split "*call_value_pop_0_vzeroupper"
+ [(parallel
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
+ (match_operand:SI 2 "" "")))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 3 "immediate_operand" "")))])
+ (unspec [(match_operand 4 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && !TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;"
+ [(set_attr "type" "callv")])
+
(define_insn "*call_value_pop_0"
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
(plus:SI (reg:SI SP_REG)
(match_operand:SI 3 "immediate_operand" "")))]
"!TARGET_64BIT"
-{
- if (SIBLING_CALL_P (insn))
- return "jmp\t%P1";
- else
- return "call\t%P1";
-}
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*call_value_pop_1_vzeroupper"
+ [(parallel
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm"))
+ (match_operand:SI 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)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*call_value_pop_1"
(plus:SI (reg:SI SP_REG)
(match_operand:SI 3 "immediate_operand" "i")))]
"!TARGET_64BIT && !SIBLING_CALL_P (insn)"
-{
- if (constant_call_address_operand (operands[1], Pmode))
- return "call\t%P1";
- return "call\t%A1";
-}
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*sibcall_value_pop_1_vzeroupper"
+ [(parallel
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U"))
+ (match_operand:SI 2 "" "")))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 3 "immediate_operand" "i,i")))])
+ (unspec [(match_operand 4 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[4]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*sibcall_value_pop_1"
(plus:SI (reg:SI SP_REG)
(match_operand:SI 3 "immediate_operand" "i,i")))]
"!TARGET_64BIT && SIBLING_CALL_P (insn)"
- "@
- jmp\t%P1
- jmp\t%A1"
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*call_value_0_vzeroupper"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
+ (match_operand:SI 2 "" "")))
+ (unspec [(match_operand 3 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && !TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*call_value_0"
(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
(match_operand:SI 2 "" "")))]
"!TARGET_64BIT"
-{
- if (SIBLING_CALL_P (insn))
- return "jmp\t%P1";
- else
- return "call\t%P1";
-}
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*call_value_0_rex64_vzeroupper"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
+ (match_operand:DI 2 "const_int_operand" "")))
+ (unspec [(match_operand 3 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*call_value_0_rex64"
(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
(match_operand:DI 2 "const_int_operand" "")))]
"TARGET_64BIT"
-{
- if (SIBLING_CALL_P (insn))
- return "jmp\t%P1";
- else
- return "call\t%P1";
-}
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*call_value_0_rex64_ms_sysv_vzeroupper"
+ [(parallel
+ [(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: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)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*call_value_0_rex64_ms_sysv"
(clobber (reg:DI SI_REG))
(clobber (reg:DI DI_REG))]
"TARGET_64BIT && !SIBLING_CALL_P (insn)"
-{
- if (SIBLING_CALL_P (insn))
- return "jmp\t%P1";
- else
- return "call\t%P1";
-}
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*call_value_1_vzeroupper"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm"))
+ (match_operand:SI 2 "" "")))
+ (unspec [(match_operand 3 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*call_value_1"
(call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm"))
(match_operand:SI 2 "" "")))]
"!TARGET_64BIT && !SIBLING_CALL_P (insn)"
-{
- if (constant_call_address_operand (operands[1], Pmode))
- return "call\t%P1";
- return "call\t%A1";
-}
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*sibcall_value_1_vzeroupper"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U"))
+ (match_operand:SI 2 "" "")))
+ (unspec [(match_operand 3 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*sibcall_value_1"
(call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U"))
(match_operand:SI 2 "" "")))]
"!TARGET_64BIT && SIBLING_CALL_P (insn)"
- "@
- jmp\t%P1
- jmp\t%A1"
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*call_value_1_rex64_vzeroupper"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
+ (match_operand:DI 2 "" "")))
+ (unspec [(match_operand 3 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)
+ && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*call_value_1_rex64"
(match_operand:DI 2 "" "")))]
"TARGET_64BIT && !SIBLING_CALL_P (insn)
&& ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
-{
- if (constant_call_address_operand (operands[1], Pmode))
- return "call\t%P1";
- return "call\t%A1";
-}
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*call_value_1_rex64_ms_sysv_vzeroupper"
+ [(parallel
+ [(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: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)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*call_value_1_rex64_ms_sysv"
(clobber (reg:DI SI_REG))
(clobber (reg:DI DI_REG))]
"TARGET_64BIT && !SIBLING_CALL_P (insn)"
-{
- if (constant_call_address_operand (operands[1], Pmode))
- return "call\t%P1";
- return "call\t%A1";
-}
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*call_value_1_rex64_large_vzeroupper"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm"))
+ (match_operand:DI 2 "" "")))
+ (unspec [(match_operand 3 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*call_value_1_rex64_large"
(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm"))
(match_operand:DI 2 "" "")))]
"TARGET_64BIT && !SIBLING_CALL_P (insn)"
- "call\t%A1"
+ { return ix86_output_call_insn (insn, operands[1], 1); }
+ [(set_attr "type" "callv")])
+
+(define_insn_and_split "*sibcall_value_1_rex64_vzeroupper"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand:DI 1 "sibcall_insn_operand" "s,U"))
+ (match_operand:DI 2 "" "")))
+ (unspec [(match_operand 3 "const_int_operand" "")]
+ UNSPEC_CALL_NEEDS_VZEROUPPER)]
+ "TARGET_VZEROUPPER && TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "ix86_split_call_vzeroupper (curr_insn, operands[3]); DONE;"
[(set_attr "type" "callv")])
(define_insn "*sibcall_value_1_rex64"
(call (mem:QI (match_operand:DI 1 "sibcall_insn_operand" "s,U"))
(match_operand:DI 2 "" "")))]
"TARGET_64BIT && SIBLING_CALL_P (insn)"
- "@
- jmp\t%P1
- jmp\t%A1"
+ { return ix86_output_call_insn (insn, operands[1], 1); }
[(set_attr "type" "callv")])
\f
;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5.
[(set_attr "type" "other")
(set_attr "prefix_extra" "2")])
-(define_expand "rdrand<mode>"
- [(set (match_operand:SWI248 0 "register_operand" "=r")
- (unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRAND))]
- "TARGET_RDRND"
-{
- rtx retry_label, insn, ccc;
-
- retry_label = gen_label_rtx ();
-
- emit_label (retry_label);
-
- /* Generate rdrand. */
- emit_insn (gen_rdrand<mode>_1 (operands[0]));
-
- /* Retry if the carry flag isn't valid. */
- ccc = gen_rtx_REG (CCCmode, FLAGS_REG);
- ccc = gen_rtx_EQ (VOIDmode, ccc, const0_rtx);
- ccc = gen_rtx_IF_THEN_ELSE (VOIDmode, ccc, pc_rtx,
- gen_rtx_LABEL_REF (VOIDmode, retry_label));
- insn = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, ccc));
- JUMP_LABEL (insn) = retry_label;
-
- DONE;
-})
-
(define_insn "rdrand<mode>_1"
[(set (match_operand:SWI248 0 "register_operand" "=r")
- (unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRAND))]
+ (unspec:SWI248 [(const_int 0)] UNSPEC_RDRAND))
+ (set (reg:CCC FLAGS_REG)
+ (unspec:CCC [(const_int 0)] UNSPEC_RDRAND))]
"TARGET_RDRND"
- "rdrand %0"
+ "rdrand\t%0"
[(set_attr "type" "other")
(set_attr "prefix_extra" "1")])