;; GCC machine description for IA-32 and x86-64.
;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2005
+;; 2001, 2002, 2003, 2004, 2005, 2006
;; Free Software Foundation, Inc.
;; Mostly by William Schelter.
;; x86_64 support added by Jan Hubicka
(UNSPEC_TP 16)
(UNSPEC_TLS_GD 17)
(UNSPEC_TLS_LD_BASE 18)
+ (UNSPEC_TLSDESC 19)
; Other random patterns
(UNSPEC_SCAS 20)
(UNSPEC_FLDCW 25)
(UNSPEC_REP 26)
(UNSPEC_EH_RETURN 27)
+ (UNSPEC_LD_MPIC 28) ; load_macho_picbase
; For SSE/MMX support:
(UNSPEC_FIX_NOTRUNC 30)
\f
;; Processor type. This attribute must exactly match the processor_type
;; enumeration in i386.h.
-(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8,nocona"
+(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8,nocona,generic32,generic64"
(const (symbol_ref "ix86_tune")))
;; A basic instruction type. Refinements due to arguments to be
(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])"
(const_string "SI")
(and (eq_attr "type" "imov")
(and (eq_attr "alternative" "0,1")
- (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
- (const_int 0))))
+ (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
+ (const_int 0))
+ (and (eq (symbol_ref "optimize_size")
+ (const_int 0))
+ (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
+ (const_int 0))))))
(const_string "SI")
;; Avoid partial register stalls when not using QImode arithmetic
(and (eq_attr "type" "imov")
(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
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
+ {
+ if ((!TARGET_SSE2 || TARGET_MIX_SSE_I387)
+ && standard_80387_constant_p (operands[1]) > 0)
+ {
+ operands[1] = simplify_const_unary_operation
+ (FLOAT_EXTEND, DFmode, operands[1], SFmode);
+ emit_move_insn_1 (operands[0], operands[1]);
+ DONE;
+ }
+ operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
+ }
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
(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)"
{
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
+ {
+ if (standard_80387_constant_p (operands[1]) > 0)
+ {
+ operands[1] = simplify_const_unary_operation
+ (FLOAT_EXTEND, XFmode, operands[1], SFmode);
+ emit_move_insn_1 (operands[0], operands[1]);
+ DONE;
+ }
+ operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
+ }
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
+ {
+ if (standard_80387_constant_p (operands[1]) > 0)
+ {
+ operands[1] = simplify_const_unary_operation
+ (FLOAT_EXTEND, XFmode, operands[1], DFmode);
+ emit_move_insn_1 (operands[0], operands[1]);
+ DONE;
+ }
+ operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
+ }
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (DFmode, operands[1]);
})
})
(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"))]
[(match_scratch:DF 2 "Y")
(set (match_operand:SSEMODEI24 0 "register_operand" "")
(fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))]
- "TARGET_K8 && !optimize_size"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
"")
[(match_scratch:SF 2 "x")
(set (match_operand:SSEMODEI24 0 "register_operand" "")
(fix:SSEMODEI24 (match_operand:SF 1 "memory_operand" "")))]
- "TARGET_K8 && !optimize_size"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
"")
"")
(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")])
(match_operand:SI 2 "const_int_operand" ""))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)
+ && INTVAL (operands[1]) > 0
+ && INTVAL (operands[2]) >= 0
+ && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
&& (GET_MODE (operands[0]) == SImode
|| (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
|| GET_MODE (operands[0]) == HImode
(const_int 0)))]
"TARGET_64BIT
&& ix86_match_ccmode (insn, CCNOmode)
- /* The code below cannot deal with constants outside HOST_WIDE_INT. */
- && INTVAL (operands[1]) + INTVAL (operands[2]) < HOST_BITS_PER_WIDE_INT
+ && INTVAL (operands[1]) > 0
+ && INTVAL (operands[2]) >= 0
/* Ensure that resulting mask is zero or sign extended operand. */
&& (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
|| (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
val = gen_lowpart (QImode, val);
}
- mask = ((HOST_WIDE_INT)1 << (pos + len)) - 1;
- mask &= ~(((HOST_WIDE_INT)1 << pos) - 1);
+ if (len == HOST_BITS_PER_WIDE_INT)
+ mask = -1;
+ else
+ mask = ((HOST_WIDE_INT)1 << len) - 1;
+ mask <<= pos;
operands[2] = gen_rtx_AND (mode, val, gen_int_mode (mask, mode));
})
"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")])
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(ashift:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, DImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{q}\t{%0, %0|%0, %0}";
+
+ default:
+ if (REG_P (operands[2]))
+ return "sal{q}\t{%b2, %0|%0, %b2}";
+ else if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_size))
+ return "sal{q}\t%0";
+ else
+ return "sal{q}\t{%2, %0|%0, %2}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
+ (match_operand 0 "register_operand" ""))
+ (match_operand 2 "const1_operand" ""))
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
+ (set_attr "mode" "DI")])
+
+(define_insn "*ashldi3_cconly_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "immediate_operand" "e"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFT, DImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
{
switch (get_attr_type (insn))
{
[(const_int 0)]
{
rtx pat, clob;
- emit_move_insn (operands[1], operands[0]);
+ emit_move_insn (operands[0], operands[1]);
pat = gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_ASHIFT (GET_MODE (operands[0]),
operands[0], operands[2]));
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(ashift:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{l}\t{%0, %0|%0, %0}";
+
+ default:
+ if (REG_P (operands[2]))
+ return "sal{l}\t{%b2, %0|%0, %b2}";
+ else if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_size))
+ return "sal{l}\t%0";
+ else
+ return "sal{l}\t{%2, %0|%0, %2}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
+ (match_operand 0 "register_operand" ""))
+ (match_operand 2 "const1_operand" ""))
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashlsi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
{
switch (get_attr_type (insn))
{
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
{
switch (get_attr_type (insn))
{
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashift:HI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{w}\t{%0, %0|%0, %0}";
+
+ default:
+ if (REG_P (operands[2]))
+ return "sal{w}\t{%b2, %0|%0, %b2}";
+ else if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_size))
+ return "sal{w}\t%0";
+ else
+ return "sal{w}\t{%2, %0|%0, %2}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
+ (match_operand 0 "register_operand" ""))
+ (match_operand 2 "const1_operand" ""))
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
+ (set_attr "mode" "HI")])
+
+(define_insn "*ashlhi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
{
switch (get_attr_type (insn))
{
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(ashift:QI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{b}\t{%0, %0|%0, %0}";
+
+ default:
+ if (REG_P (operands[2]))
+ return "sal{b}\t{%b2, %0|%0, %b2}";
+ else if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_size))
+ return "sal{b}\t%0";
+ else
+ return "sal{b}\t{%2, %0|%0, %2}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
+ (match_operand 0 "register_operand" ""))
+ (match_operand 2 "const1_operand" ""))
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
+ (set_attr "mode" "QI")])
+
+(define_insn "*ashlqi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
{
switch (get_attr_type (insn))
{
(const_string "2")
(const_string "*")))])
+(define_insn "*ashrdi3_one_bit_cconly_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+ "sar{q}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(ashiftrt:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "sar{q}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "DI")])
+
+(define_insn "*ashrdi3_cconly_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_int_operand" "n"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "DI")])
(const_string "2")
(const_string "*")))])
+(define_insn "*ashrsi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ "sar{l}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
(define_insn "*ashrsi3_one_bit_cmp_zext"
[(set (reg FLAGS_REG)
(compare
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(ashiftrt:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "sar{l}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashrsi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "SI")])
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "SI")])
(const_string "2")
(const_string "*")))])
+(define_insn "*ashrhi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
+ "sar{w}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashiftrt:HI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "sar{w}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "HI")])
+
+(define_insn "*ashrhi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "HI")])
(const_string "2")
(const_string "*")))])
+(define_insn "*ashrqi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
+ "sar{b}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(ashiftrt:QI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "sar{b}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "QI")])
+
+(define_insn "*ashrqi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "QI")])
+
\f
;; Logical shift instructions
(const_string "2")
(const_string "*")))])
+(define_insn "*lshrdi3_cconly_one_bit_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{q}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(lshiftrt:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "shr{q}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "DI")])
+
+(define_insn "*lshrdi3_cconly_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_int_operand" "e"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "DI")])
(const_string "2")
(const_string "*")))])
+(define_insn "*lshrsi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{l}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
(define_insn "*lshrsi3_cmp_one_bit_zext"
[(set (reg FLAGS_REG)
(compare
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(lshiftrt:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "shr{l}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "SI")])
+
+(define_insn "*lshrsi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "SI")])
(set (match_operand:DI 0 "register_operand" "=r")
(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "SI")])
(const_string "2")
(const_string "*")))])
+(define_insn "*lshrhi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{w}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(lshiftrt:HI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "shr{w}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "HI")])
+
+(define_insn "*lshrhi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "HI")])
(const_string "2")
(const_string "*")))])
+(define_insn "*lshrqi2_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
+ "shr{b}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(lshiftrt:QI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "shr{b}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "QI")])
+
+(define_insn "*lshrqi2_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "QI")])
(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 "";
(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
- { return output_set_got (operands[0]); }
+ { return output_set_got (operands[0], NULL_RTX); }
+ [(set_attr "type" "multi")
+ (set_attr "length" "12")])
+
+(define_insn "set_got_labelled"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(label_ref (match_operand 1 "" ""))]
+ UNSPEC_SET_GOT))
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT"
+ { return output_set_got (operands[0], operands[1]); }
[(set_attr "type" "multi")
(set_attr "length" "12")])
operands[2] = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (operands[2]));
}
+ if (TARGET_GNU2_TLS)
+ {
+ emit_insn (gen_tls_dynamic_gnu2_32
+ (operands[0], operands[1], operands[2]));
+ DONE;
+ }
operands[3] = ix86_tls_get_addr ();
})
UNSPEC_TLS_GD)])]
""
{
+ if (TARGET_GNU2_TLS)
+ {
+ emit_insn (gen_tls_dynamic_gnu2_64
+ (operands[0], operands[1]));
+ DONE;
+ }
operands[2] = ix86_tls_get_addr ();
})
operands[1] = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (operands[1]));
}
+ if (TARGET_GNU2_TLS)
+ {
+ emit_insn (gen_tls_dynamic_gnu2_32
+ (operands[0], ix86_tls_module_base (), operands[1]));
+ DONE;
+ }
operands[2] = ix86_tls_get_addr ();
})
(unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
""
{
+ if (TARGET_GNU2_TLS)
+ {
+ emit_insn (gen_tls_dynamic_gnu2_64
+ (operands[0], ix86_tls_module_base ()));
+ DONE;
+ }
operands[1] = ix86_tls_get_addr ();
})
(set_attr "length" "7")
(set_attr "memory" "load")
(set_attr "imm_disp" "false")])
+
+;; GNU2 TLS patterns can be split.
+
+(define_expand "tls_dynamic_gnu2_32"
+ [(set (match_dup 3)
+ (plus:SI (match_operand:SI 2 "register_operand" "")
+ (const:SI
+ (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLSDESC))))
+ (parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(match_dup 1) (match_dup 3)
+ (match_dup 2) (reg:SI SP_REG)]
+ UNSPEC_TLSDESC))
+ (clobber (reg:CC FLAGS_REG))])]
+ "!TARGET_64BIT && TARGET_GNU2_TLS"
+{
+ operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+ ix86_tls_descriptor_calls_expanded_in_cfun = true;
+})
+
+(define_insn "*tls_dynamic_lea_32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "b")
+ (const:SI
+ (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")]
+ UNSPEC_TLSDESC))))]
+ "!TARGET_64BIT && TARGET_GNU2_TLS"
+ "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}"
+ [(set_attr "type" "lea")
+ (set_attr "mode" "SI")
+ (set_attr "length" "6")
+ (set_attr "length_address" "4")])
+
+(define_insn "*tls_dynamic_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")
+ ;; we have to make sure %ebx still points to the GOT
+ (match_operand:SI 3 "register_operand" "b")
+ (reg:SI SP_REG)]
+ UNSPEC_TLSDESC))
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT && TARGET_GNU2_TLS"
+ "call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}"
+ [(set_attr "type" "call")
+ (set_attr "length" "2")
+ (set_attr "length_address" "0")])
+
+(define_insn_and_split "*tls_dynamic_gnu2_combine_32"
+ [(set (match_operand:SI 0 "register_operand" "=&a")
+ (plus:SI
+ (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))))
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT && TARGET_GNU2_TLS"
+ "#"
+ ""
+ [(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_expand "tls_dynamic_gnu2_64"
+ [(set (match_dup 2)
+ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLSDESC))
+ (parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)]
+ UNSPEC_TLSDESC))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT && TARGET_GNU2_TLS"
+{
+ operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+ ix86_tls_descriptor_calls_expanded_in_cfun = true;
+})
+
+(define_insn "*tls_dynamic_lea_64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLSDESC))]
+ "TARGET_64BIT && TARGET_GNU2_TLS"
+ "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}"
+ [(set_attr "type" "lea")
+ (set_attr "mode" "DI")
+ (set_attr "length" "7")
+ (set_attr "length_address" "4")])
+
+(define_insn "*tls_dynamic_call_64"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
+ (match_operand:DI 2 "register_operand" "0")
+ (reg:DI SP_REG)]
+ UNSPEC_TLSDESC))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && TARGET_GNU2_TLS"
+ "call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}"
+ [(set_attr "type" "call")
+ (set_attr "length" "2")
+ (set_attr "length_address" "0")])
+
+(define_insn_and_split "*tls_dynamic_gnu2_combine_64"
+ [(set (match_operand:DI 0 "register_operand" "=&a")
+ (plus:DI
+ (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))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && TARGET_GNU2_TLS"
+ "#"
+ ""
+ [(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]));
+})
+
+;;
\f
;; These patterns match the binary 387 instructions for addM3, subM3,
;; mulM3 and divM3. There are three patterns for each of DFmode and
;; 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)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(if_then_else (eq_attr "alternative" "1")
- (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (if_then_else (match_operand:DF 3 "mult_operator" "")
(const_string "ssemul")
(const_string "sseadd"))
- (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (if_then_else (match_operand:DF 3 "mult_operator" "")
(const_string "fmul")
(const_string "fop"))))
(set_attr "mode" "DF")])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
- (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (if_then_else (match_operand:DF 3 "mult_operator" "")
(const_string "ssemul")
(const_string "sseadd")))
(set_attr "mode" "DF")])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
- (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (if_then_else (match_operand:DF 3 "mult_operator" "")
(const_string "fmul")
(const_string "fop")))
(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)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(and (eq_attr "alternative" "2")
- (match_operand:SF 3 "mult_operator" ""))
+ (match_operand:DF 3 "mult_operator" ""))
(const_string "ssemul")
(and (eq_attr "alternative" "2")
- (match_operand:SF 3 "div_operator" ""))
+ (match_operand:DF 3 "div_operator" ""))
(const_string "ssediv")
(eq_attr "alternative" "2")
(const_string "sseadd")
"* return output_387_binary_op (insn, operands);"
[(set_attr "mode" "DF")
(set (attr "type")
- (cond [(match_operand:SF 3 "mult_operator" "")
+ (cond [(match_operand:DF 3 "mult_operator" "")
(const_string "ssemul")
- (match_operand:SF 3 "div_operator" "")
+ (match_operand:DF 3 "div_operator" "")
(const_string "ssediv")
]
(const_string "sseadd")))])
})
(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" "")
[(label_ref (match_operand 0 "" ""))]
"!TARGET_64BIT && flag_pic"
{
- emit_insn (gen_set_got (pic_offset_table_rtx));
+ if (TARGET_MACHO)
+ {
+ rtx xops[3];
+ rtx picreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
+ 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)));
+ ix86_expand_binary_operator (MINUS, SImode, xops);
+ }
+ else
+ emit_insn (gen_set_got (pic_offset_table_rtx));
DONE;
})
\f
"! 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)
(mult:DI (match_operand:DI 1 "memory_operand" "")
(match_operand:DI 2 "immediate_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
- "TARGET_K8 && !optimize_size
- && (GET_CODE (operands[2]) != CONST_INT
- || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && !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))])]
(mult:SI (match_operand:SI 1 "memory_operand" "")
(match_operand:SI 2 "immediate_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
- "TARGET_K8 && !optimize_size
- && (GET_CODE (operands[2]) != CONST_INT
- || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && !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))])]
(mult:SI (match_operand:SI 1 "memory_operand" "")
(match_operand:SI 2 "immediate_operand" ""))))
(clobber (reg:CC FLAGS_REG))])]
- "TARGET_K8 && !optimize_size
- && (GET_CODE (operands[2]) != CONST_INT
- || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && !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))])]
(match_operand:DI 2 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))])
(match_scratch:DI 3 "r")]
- "TARGET_K8 && !optimize_size
- && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && 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))])]
(match_operand:SI 2 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))])
(match_scratch:SI 3 "r")]
- "TARGET_K8 && !optimize_size
- && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && 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))])]
(match_operand:HI 2 "immediate_operand" "")))
(clobber (reg:CC FLAGS_REG))])
(match_scratch:HI 3 "r")]
- "TARGET_K8 && !optimize_size"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
[(set (match_dup 3) (match_dup 2))
(parallel [(set (match_dup 0) (mult:HI (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")