190286Sobrien;; GCC machine description for IA-32 and x86-64.
2117404Skan;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3169699Skan;; 2001, 2002, 2003, 2004, 2005, 2006
490286Sobrien;; Free Software Foundation, Inc.
518334Speter;; Mostly by William Schelter.
690286Sobrien;; x86_64 support added by Jan Hubicka
790286Sobrien;;
8132727Skan;; This file is part of GCC.
990286Sobrien;;
10132727Skan;; GCC is free software; you can redistribute it and/or modify
1118334Speter;; it under the terms of the GNU General Public License as published by
1218334Speter;; the Free Software Foundation; either version 2, or (at your option)
1318334Speter;; any later version.
1490286Sobrien;;
15132727Skan;; GCC is distributed in the hope that it will be useful,
1618334Speter;; but WITHOUT ANY WARRANTY; without even the implied warranty of
1718334Speter;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1818334Speter;; GNU General Public License for more details.
1990286Sobrien;;
2018334Speter;; You should have received a copy of the GNU General Public License
21132727Skan;; along with GCC; see the file COPYING.  If not, write to
22169699Skan;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23169699Skan;; Boston, MA 02110-1301, USA.  */
2490286Sobrien;;
2518334Speter;; The original PO technology requires these to be ordered by speed,
2618334Speter;; so that assigner will pick the fastest.
2790286Sobrien;;
2818334Speter;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
2990286Sobrien;;
3018334Speter;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register
3118334Speter;; constraint letters.
3290286Sobrien;;
3390286Sobrien;; The special asm out single letter directives following a '%' are:
3418334Speter;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of
3518334Speter;;     operands[1].
3618334Speter;; 'L' Print the opcode suffix for a 32-bit integer opcode.
3718334Speter;; 'W' Print the opcode suffix for a 16-bit integer opcode.
3818334Speter;; 'B' Print the opcode suffix for an 8-bit integer opcode.
3950650Sobrien;; 'Q' Print the opcode suffix for a 64-bit float opcode.
4018334Speter;; 'S' Print the opcode suffix for a 32-bit float opcode.
4118334Speter;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode.
4218334Speter;; 'J' Print the appropriate jump operand.
4390286Sobrien;;
4418334Speter;; 'b' Print the QImode name of the register for the indicated operand.
4518334Speter;;     %b0 would print %al if operands[0] is reg 0.
4618334Speter;; 'w' Likewise, print the HImode name of the register.
4718334Speter;; 'k' Likewise, print the SImode name of the register.
4818334Speter;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh.
4918334Speter;; 'y' Print "st(0)" instead of "st" as a register.
50117404Skan
5118334Speter;; UNSPEC usage:
5290286Sobrien
53117404Skan(define_constants
54117404Skan  [; Relocation specifiers
55117404Skan   (UNSPEC_GOT			0)
56117404Skan   (UNSPEC_GOTOFF		1)
57117404Skan   (UNSPEC_GOTPCREL		2)
58117404Skan   (UNSPEC_GOTTPOFF		3)
59117404Skan   (UNSPEC_TPOFF		4)
60117404Skan   (UNSPEC_NTPOFF		5)
61117404Skan   (UNSPEC_DTPOFF		6)
62117404Skan   (UNSPEC_GOTNTPOFF		7)
63117404Skan   (UNSPEC_INDNTPOFF		8)
6490286Sobrien
65117404Skan   ; Prologue support
66117404Skan   (UNSPEC_STACK_ALLOC		11)
67117404Skan   (UNSPEC_SET_GOT		12)
68117404Skan   (UNSPEC_SSE_PROLOGUE_SAVE	13)
69169699Skan   (UNSPEC_REG_SAVE		14)
70169699Skan   (UNSPEC_DEF_CFA		15)
71117404Skan
72117404Skan   ; TLS support
73169699Skan   (UNSPEC_TP			16)
74169699Skan   (UNSPEC_TLS_GD		17)
75169699Skan   (UNSPEC_TLS_LD_BASE		18)
76169699Skan   (UNSPEC_TLSDESC		19)
77117404Skan
78117404Skan   ; Other random patterns
79117404Skan   (UNSPEC_SCAS			20)
80169699Skan   (UNSPEC_FNSTSW		21)
81169699Skan   (UNSPEC_SAHF			22)
82169699Skan   (UNSPEC_FSTCW		23)
83169699Skan   (UNSPEC_ADD_CARRY		24)
84169699Skan   (UNSPEC_FLDCW		25)
85169699Skan   (UNSPEC_REP			26)
86169699Skan   (UNSPEC_EH_RETURN		27)
87169699Skan   (UNSPEC_LD_MPIC		28)	; load_macho_picbase
88117404Skan
89117404Skan   ; For SSE/MMX support:
90169699Skan   (UNSPEC_FIX_NOTRUNC		30)
91169699Skan   (UNSPEC_MASKMOV		31)
92169699Skan   (UNSPEC_MOVMSK		32)
93169699Skan   (UNSPEC_MOVNT		33)
94169699Skan   (UNSPEC_MOVU			34)
95169699Skan   (UNSPEC_RCP			35)
96169699Skan   (UNSPEC_RSQRT		36)
97169699Skan   (UNSPEC_SFENCE		37)
98169699Skan   (UNSPEC_NOP			38)	; prevents combiner cleverness
99169699Skan   (UNSPEC_PFRCP		39)
100169699Skan   (UNSPEC_PFRCPIT1		40)
101169699Skan   (UNSPEC_PFRCPIT2		41)
102169699Skan   (UNSPEC_PFRSQRT		42)
103169699Skan   (UNSPEC_PFRSQIT1		43)
104169699Skan   (UNSPEC_MFENCE		44)
105169699Skan   (UNSPEC_LFENCE		45)
106169699Skan   (UNSPEC_PSADBW		46)
107237021Spfg   (UNSPEC_LDQQU		47)
108132727Skan
109169699Skan   ; Generic math support
110169699Skan   (UNSPEC_COPYSIGN		50)
111169699Skan   (UNSPEC_IEEE_MIN		51)	; not commutative
112169699Skan   (UNSPEC_IEEE_MAX		52)	; not commutative
113169699Skan
114132727Skan   ; x87 Floating point
115169699Skan   (UNSPEC_SIN			60)
116169699Skan   (UNSPEC_COS			61)
117169699Skan   (UNSPEC_FPATAN		62)
118169699Skan   (UNSPEC_FYL2X		63)
119169699Skan   (UNSPEC_FYL2XP1		64)
120169699Skan   (UNSPEC_FRNDINT		65)
121169699Skan   (UNSPEC_FIST			66)
122169699Skan   (UNSPEC_F2XM1		67)
123132727Skan
124169699Skan   ; x87 Rounding
125169699Skan   (UNSPEC_FRNDINT_FLOOR	70)
126169699Skan   (UNSPEC_FRNDINT_CEIL 	71)
127169699Skan   (UNSPEC_FRNDINT_TRUNC	72)
128169699Skan   (UNSPEC_FRNDINT_MASK_PM	73)
129169699Skan   (UNSPEC_FIST_FLOOR		74)
130169699Skan   (UNSPEC_FIST_CEIL 		75)
131169699Skan
132169699Skan   ; x87 Double output FP
133169699Skan   (UNSPEC_SINCOS_COS		80)
134169699Skan   (UNSPEC_SINCOS_SIN		81)
135169699Skan   (UNSPEC_TAN_ONE		82)
136169699Skan   (UNSPEC_TAN_TAN		83)
137169699Skan   (UNSPEC_XTRACT_FRACT		84)
138169699Skan   (UNSPEC_XTRACT_EXP		85)
139169699Skan   (UNSPEC_FSCALE_FRACT		86)
140169699Skan   (UNSPEC_FSCALE_EXP		87)
141169699Skan   (UNSPEC_FPREM_F		88)
142169699Skan   (UNSPEC_FPREM_U		89)
143169699Skan   (UNSPEC_FPREM1_F		90)
144169699Skan   (UNSPEC_FPREM1_U		91)
145169699Skan
146169699Skan   ; SSP patterns
147169699Skan   (UNSPEC_SP_SET		100)
148169699Skan   (UNSPEC_SP_TEST		101)
149169699Skan   (UNSPEC_SP_TLS_SET		102)
150169699Skan   (UNSPEC_SP_TLS_TEST		103)
151219639Smm
152219639Smm   ; SSSE3
153219639Smm   (UNSPEC_PSHUFB		120)
154219639Smm   (UNSPEC_PSIGN		121)
155219639Smm   (UNSPEC_PALIGNR		122)
156251212Spfg
157251212Spfg   ; For SSE4A support
158251212Spfg   (UNSPEC_EXTRQI               130)
159251212Spfg   (UNSPEC_EXTRQ                131)   
160251212Spfg   (UNSPEC_INSERTQI             132)
161251212Spfg   (UNSPEC_INSERTQ              133)
162117404Skan  ])
163117404Skan
164117404Skan(define_constants
165117404Skan  [(UNSPECV_BLOCKAGE		0)
166169699Skan   (UNSPECV_STACK_PROBE		1)
167169699Skan   (UNSPECV_EMMS		2)
168169699Skan   (UNSPECV_LDMXCSR		3)
169169699Skan   (UNSPECV_STMXCSR		4)
170169699Skan   (UNSPECV_FEMMS		5)
171169699Skan   (UNSPECV_CLFLUSH		6)
172169699Skan   (UNSPECV_ALIGN		7)
173169699Skan   (UNSPECV_MONITOR		8)
174169699Skan   (UNSPECV_MWAIT		9)
175169699Skan   (UNSPECV_CMPXCHG_1		10)
176169699Skan   (UNSPECV_CMPXCHG_2		11)
177169699Skan   (UNSPECV_XCHG		12)
178169699Skan   (UNSPECV_LOCK		13)
179117404Skan  ])
180117404Skan
181169699Skan;; Registers by name.
182169699Skan(define_constants
183169699Skan  [(BP_REG			 6)
184169699Skan   (SP_REG			 7)
185169699Skan   (FLAGS_REG			17)
186169699Skan   (FPSR_REG			18)
187237021Spfg   (DIRFLAG_REG			19)
188169699Skan  ])
189169699Skan
19090286Sobrien;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
19190286Sobrien;; from i386.c.
19290286Sobrien
19390286Sobrien;; In C guard expressions, put expressions which may be compile-time
19490286Sobrien;; constants first.  This allows for better optimization.  For
19590286Sobrien;; example, write "TARGET_64BIT && reload_completed", not
19690286Sobrien;; "reload_completed && TARGET_64BIT".
19790286Sobrien
19818334Speter
19990286Sobrien;; Processor type.  This attribute must exactly match the processor_type
20090286Sobrien;; enumeration in i386.h.
201251212Spfg(define_attr "cpu" "i386,i486,pentium,pentiumpro,geode,k6,athlon,pentium4,k8,
202251212Spfg                    nocona,core2,generic32,generic64,amdfam10"
203132727Skan  (const (symbol_ref "ix86_tune")))
20450650Sobrien
20590286Sobrien;; A basic instruction type.  Refinements due to arguments to be
20690286Sobrien;; provided in other attributes.
20752296Sobrien(define_attr "type"
208117404Skan  "other,multi,
209117404Skan   alu,alu1,negnot,imov,imovx,lea,
210117404Skan   incdec,ishift,ishift1,rotate,rotate1,imul,idiv,
211117404Skan   icmp,test,ibr,setcc,icmov,
212132727Skan   push,pop,call,callv,leave,
213251212Spfg   str,bitmanip,cld,
214169699Skan   fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
215169699Skan   sselog,sselog1,sseiadd,sseishft,sseimul,
216251212Spfg   sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,sseins,
217117404Skan   mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
21890286Sobrien  (const_string "other"))
21950650Sobrien
22090286Sobrien;; Main data type used by the insn
221117404Skan(define_attr "mode"
222169699Skan  "unknown,none,QI,HI,SI,DI,SF,DF,XF,TI,V4SF,V2DF,V2SF,V1DF"
22390286Sobrien  (const_string "unknown"))
22452296Sobrien
225117404Skan;; The CPU unit operations uses.
226117404Skan(define_attr "unit" "integer,i387,sse,mmx,unknown"
227169699Skan  (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint")
228117404Skan	   (const_string "i387")
229169699Skan	 (eq_attr "type" "sselog,sselog1,sseiadd,sseishft,sseimul,
230251212Spfg			  sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,sseins")
231117404Skan	   (const_string "sse")
232117404Skan	 (eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft")
233117404Skan	   (const_string "mmx")
234117404Skan	 (eq_attr "type" "other")
235117404Skan	   (const_string "unknown")]
236117404Skan	 (const_string "integer")))
23752296Sobrien
23890286Sobrien;; The (bounding maximum) length of an instruction immediate.
23990286Sobrien(define_attr "length_immediate" ""
240251212Spfg  (cond [(eq_attr "type" "incdec,setcc,icmov,str,cld,lea,other,multi,idiv,leave,
241251212Spfg                          bitmanip")
24290286Sobrien	   (const_int 0)
243117404Skan	 (eq_attr "unit" "i387,sse,mmx")
24490286Sobrien	   (const_int 0)
245117404Skan	 (eq_attr "type" "alu,alu1,negnot,imovx,ishift,rotate,ishift1,rotate1,
246117404Skan			  imul,icmp,push,pop")
24790286Sobrien	   (symbol_ref "ix86_attr_length_immediate_default(insn,1)")
24890286Sobrien	 (eq_attr "type" "imov,test")
24990286Sobrien	   (symbol_ref "ix86_attr_length_immediate_default(insn,0)")
25090286Sobrien	 (eq_attr "type" "call")
25190286Sobrien	   (if_then_else (match_operand 0 "constant_call_address_operand" "")
25290286Sobrien	     (const_int 4)
25390286Sobrien	     (const_int 0))
25490286Sobrien	 (eq_attr "type" "callv")
25590286Sobrien	   (if_then_else (match_operand 1 "constant_call_address_operand" "")
25690286Sobrien	     (const_int 4)
25790286Sobrien	     (const_int 0))
258117404Skan	 ;; We don't know the size before shorten_branches.  Expect
259117404Skan	 ;; the instruction to fit for better scheduling.
26090286Sobrien	 (eq_attr "type" "ibr")
261117404Skan	   (const_int 1)
26290286Sobrien	 ]
263117404Skan	 (symbol_ref "/* Update immediate_length and other attributes! */
264169699Skan		      gcc_unreachable (),1")))
26552296Sobrien
26690286Sobrien;; The (bounding maximum) length of an instruction address.
26790286Sobrien(define_attr "length_address" ""
26890286Sobrien  (cond [(eq_attr "type" "str,cld,other,multi,fxch")
26990286Sobrien	   (const_int 0)
27090286Sobrien	 (and (eq_attr "type" "call")
271117404Skan	      (match_operand 0 "constant_call_address_operand" ""))
27290286Sobrien	     (const_int 0)
27390286Sobrien	 (and (eq_attr "type" "callv")
27490286Sobrien	      (match_operand 1 "constant_call_address_operand" ""))
27590286Sobrien	     (const_int 0)
27690286Sobrien	 ]
27790286Sobrien	 (symbol_ref "ix86_attr_length_address_default (insn)")))
27852296Sobrien
27990286Sobrien;; Set when length prefix is used.
28090286Sobrien(define_attr "prefix_data16" ""
281117404Skan  (if_then_else (ior (eq_attr "mode" "HI")
282117404Skan		     (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF")))
28390286Sobrien    (const_int 1)
28490286Sobrien    (const_int 0)))
28552296Sobrien
28690286Sobrien;; Set when string REP prefix is used.
287259563Spfg(define_attr "prefix_rep" ""
288117404Skan  (if_then_else (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
289117404Skan    (const_int 1)
290117404Skan    (const_int 0)))
29152296Sobrien
29290286Sobrien;; Set when 0f opcode prefix is used.
29390286Sobrien(define_attr "prefix_0f" ""
294259563Spfg  (if_then_else
295251212Spfg    (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip")
296132727Skan	 (eq_attr "unit" "sse,mmx"))
29790286Sobrien    (const_int 1)
29890286Sobrien    (const_int 0)))
29952296Sobrien
300169699Skan;; Set when REX opcode prefix is used.
301132727Skan(define_attr "prefix_rex" ""
302132727Skan  (cond [(and (eq_attr "mode" "DI")
303132727Skan  	      (eq_attr "type" "!push,pop,call,callv,leave,ibr"))
304132727Skan	   (const_int 1)
305132727Skan	 (and (eq_attr "mode" "QI")
306132727Skan	      (ne (symbol_ref "x86_extended_QIreg_mentioned_p (insn)")
307132727Skan		  (const_int 0)))
308132727Skan	   (const_int 1)
309132727Skan	 (ne (symbol_ref "x86_extended_reg_mentioned_p (insn)")
310132727Skan	     (const_int 0))
311132727Skan	   (const_int 1)
312132727Skan	]
313132727Skan	(const_int 0)))
314132727Skan
31590286Sobrien;; Set when modrm byte is used.
31690286Sobrien(define_attr "modrm" ""
317132727Skan  (cond [(eq_attr "type" "str,cld,leave")
31890286Sobrien	   (const_int 0)
319117404Skan	 (eq_attr "unit" "i387")
32090286Sobrien	   (const_int 0)
32190286Sobrien         (and (eq_attr "type" "incdec")
32290286Sobrien	      (ior (match_operand:SI 1 "register_operand" "")
32390286Sobrien		   (match_operand:HI 1 "register_operand" "")))
32490286Sobrien	   (const_int 0)
32590286Sobrien	 (and (eq_attr "type" "push")
32690286Sobrien	      (not (match_operand 1 "memory_operand" "")))
32790286Sobrien	   (const_int 0)
32890286Sobrien	 (and (eq_attr "type" "pop")
32990286Sobrien	      (not (match_operand 0 "memory_operand" "")))
33090286Sobrien	   (const_int 0)
33190286Sobrien	 (and (eq_attr "type" "imov")
332169699Skan	      (ior (and (match_operand 0 "register_operand" "")
333169699Skan			(match_operand 1 "immediate_operand" ""))
334169699Skan		   (ior (and (match_operand 0 "ax_reg_operand" "")
335169699Skan			     (match_operand 1 "memory_displacement_only_operand" ""))
336169699Skan			(and (match_operand 0 "memory_displacement_only_operand" "")
337169699Skan			     (match_operand 1 "ax_reg_operand" "")))))
33890286Sobrien	   (const_int 0)
339117404Skan	 (and (eq_attr "type" "call")
340117404Skan	      (match_operand 0 "constant_call_address_operand" ""))
341117404Skan	     (const_int 0)
342117404Skan	 (and (eq_attr "type" "callv")
343117404Skan	      (match_operand 1 "constant_call_address_operand" ""))
344117404Skan	     (const_int 0)
34590286Sobrien	 ]
34690286Sobrien	 (const_int 1)))
34790286Sobrien
34890286Sobrien;; The (bounding maximum) length of an instruction in bytes.
349169699Skan;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences.
350169699Skan;; Later we may want to split them and compute proper length as for
351169699Skan;; other insns.
35290286Sobrien(define_attr "length" ""
353169699Skan  (cond [(eq_attr "type" "other,multi,fistp,frndint")
35490286Sobrien	   (const_int 16)
355117404Skan	 (eq_attr "type" "fcmp")
356117404Skan	   (const_int 4)
357117404Skan	 (eq_attr "unit" "i387")
358117404Skan	   (plus (const_int 2)
359117404Skan		 (plus (attr "prefix_data16")
360117404Skan		       (attr "length_address")))]
36190286Sobrien	 (plus (plus (attr "modrm")
36290286Sobrien		     (plus (attr "prefix_0f")
363132727Skan			   (plus (attr "prefix_rex")
364132727Skan				 (const_int 1))))
36590286Sobrien	       (plus (attr "prefix_rep")
36690286Sobrien		     (plus (attr "prefix_data16")
36790286Sobrien			   (plus (attr "length_immediate")
36890286Sobrien				 (attr "length_address")))))))
36990286Sobrien
37090286Sobrien;; The `memory' attribute is `none' if no memory is referenced, `load' or
37190286Sobrien;; `store' if there is a simple memory reference therein, or `unknown'
37290286Sobrien;; if the instruction is complex.
37390286Sobrien
37490286Sobrien(define_attr "memory" "none,load,store,both,unknown"
37590286Sobrien  (cond [(eq_attr "type" "other,multi,str")
37690286Sobrien	   (const_string "unknown")
37790286Sobrien	 (eq_attr "type" "lea,fcmov,fpspc,cld")
37890286Sobrien	   (const_string "none")
379132727Skan	 (eq_attr "type" "fistp,leave")
38090286Sobrien	   (const_string "both")
381169699Skan	 (eq_attr "type" "frndint")
382169699Skan	   (const_string "load")
38390286Sobrien	 (eq_attr "type" "push")
38490286Sobrien	   (if_then_else (match_operand 1 "memory_operand" "")
38590286Sobrien	     (const_string "both")
38690286Sobrien	     (const_string "store"))
387132727Skan	 (eq_attr "type" "pop")
38890286Sobrien	   (if_then_else (match_operand 0 "memory_operand" "")
38990286Sobrien	     (const_string "both")
39090286Sobrien	     (const_string "load"))
391132727Skan	 (eq_attr "type" "setcc")
392132727Skan	   (if_then_else (match_operand 0 "memory_operand" "")
393132727Skan	     (const_string "store")
394132727Skan	     (const_string "none"))
395132727Skan	 (eq_attr "type" "icmp,test,ssecmp,ssecomi,mmxcmp,fcmp")
39690286Sobrien	   (if_then_else (ior (match_operand 0 "memory_operand" "")
39790286Sobrien			      (match_operand 1 "memory_operand" ""))
39890286Sobrien	     (const_string "load")
39990286Sobrien	     (const_string "none"))
40090286Sobrien	 (eq_attr "type" "ibr")
40190286Sobrien	   (if_then_else (match_operand 0 "memory_operand" "")
40290286Sobrien	     (const_string "load")
40390286Sobrien	     (const_string "none"))
40490286Sobrien	 (eq_attr "type" "call")
40590286Sobrien	   (if_then_else (match_operand 0 "constant_call_address_operand" "")
40690286Sobrien	     (const_string "none")
40790286Sobrien	     (const_string "load"))
40890286Sobrien	 (eq_attr "type" "callv")
40990286Sobrien	   (if_then_else (match_operand 1 "constant_call_address_operand" "")
41090286Sobrien	     (const_string "none")
41190286Sobrien	     (const_string "load"))
412169699Skan	 (and (eq_attr "type" "alu1,negnot,ishift1,sselog1")
41390286Sobrien	      (match_operand 1 "memory_operand" ""))
41490286Sobrien	   (const_string "both")
41590286Sobrien	 (and (match_operand 0 "memory_operand" "")
41690286Sobrien	      (match_operand 1 "memory_operand" ""))
41790286Sobrien	   (const_string "both")
41890286Sobrien	 (match_operand 0 "memory_operand" "")
41990286Sobrien	   (const_string "store")
42090286Sobrien	 (match_operand 1 "memory_operand" "")
42190286Sobrien	   (const_string "load")
422117404Skan	 (and (eq_attr "type"
423132727Skan		 "!alu1,negnot,ishift1,
424251212Spfg		   imov,imovx,icmp,test,bitmanip,
425117404Skan		   fmov,fcmp,fsgn,
426169699Skan		   sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt,sselog1,
427117404Skan		   mmx,mmxmov,mmxcmp,mmxcvt")
42890286Sobrien	      (match_operand 2 "memory_operand" ""))
42990286Sobrien	   (const_string "load")
43090286Sobrien	 (and (eq_attr "type" "icmov")
43190286Sobrien	      (match_operand 3 "memory_operand" ""))
43290286Sobrien	   (const_string "load")
43390286Sobrien	]
43452296Sobrien	(const_string "none")))
43552296Sobrien
43690286Sobrien;; Indicates if an instruction has both an immediate and a displacement.
43750650Sobrien
43890286Sobrien(define_attr "imm_disp" "false,true,unknown"
43990286Sobrien  (cond [(eq_attr "type" "other,multi")
44090286Sobrien	   (const_string "unknown")
441117404Skan	 (and (eq_attr "type" "icmp,test,imov,alu1,ishift1,rotate1")
44290286Sobrien	      (and (match_operand 0 "memory_displacement_operand" "")
44390286Sobrien		   (match_operand 1 "immediate_operand" "")))
44490286Sobrien	   (const_string "true")
445117404Skan	 (and (eq_attr "type" "alu,ishift,rotate,imul,idiv")
44690286Sobrien	      (and (match_operand 0 "memory_displacement_operand" "")
44790286Sobrien		   (match_operand 2 "immediate_operand" "")))
44890286Sobrien	   (const_string "true")
44990286Sobrien	]
45090286Sobrien	(const_string "false")))
45150650Sobrien
45290286Sobrien;; Indicates if an FP operation has an integer source.
45350650Sobrien
45490286Sobrien(define_attr "fp_int_src" "false,true"
45590286Sobrien  (const_string "false"))
45650650Sobrien
457169699Skan;; Defines rounding mode of an FP operation.
458169699Skan
459169699Skan(define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any"
460169699Skan  (const_string "any"))
461169699Skan
46290286Sobrien;; Describe a user's asm statement.
46390286Sobrien(define_asm_attributes
46490286Sobrien  [(set_attr "length" "128")
46590286Sobrien   (set_attr "type" "multi")])
466169699Skan
467169699Skan;; All x87 floating point modes
468169699Skan(define_mode_macro X87MODEF [SF DF XF])
469259563Spfg
470169699Skan;; All integer modes handled by x87 fisttp operator.
471169699Skan(define_mode_macro X87MODEI [HI SI DI])
472169699Skan
473169699Skan;; All integer modes handled by integer x87 operators.
474169699Skan(define_mode_macro X87MODEI12 [HI SI])
475169699Skan
476169699Skan;; All SSE floating point modes
477169699Skan(define_mode_macro SSEMODEF [SF DF])
478259563Spfg
479169699Skan;; All integer modes handled by SSE cvtts?2si* operators.
480169699Skan(define_mode_macro SSEMODEI24 [SI DI])
481169699Skan
48290286Sobrien
483169699Skan;; Scheduling descriptions
484169699Skan
485117404Skan(include "pentium.md")
486117404Skan(include "ppro.md")
487117404Skan(include "k6.md")
488117404Skan(include "athlon.md")
489219374Smm(include "geode.md")
490169699Skan
49190286Sobrien
492169699Skan;; Operand and operator predicates and constraints
493169699Skan
494169699Skan(include "predicates.md")
495169699Skan(include "constraints.md")
496169699Skan
497169699Skan
49890286Sobrien;; Compare instructions.
49990286Sobrien
50090286Sobrien;; All compare insns have expanders that save the operands away without
50190286Sobrien;; actually generating RTL.  The bCOND or sCOND (emitted immediately
50290286Sobrien;; after the cmp) will actually emit the cmpM.
50390286Sobrien
504169699Skan(define_expand "cmpti"
505169699Skan  [(set (reg:CC FLAGS_REG)
506169699Skan	(compare:CC (match_operand:TI 0 "nonimmediate_operand" "")
507169699Skan		    (match_operand:TI 1 "x86_64_general_operand" "")))]
508169699Skan  "TARGET_64BIT"
509169699Skan{
510169699Skan  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
511169699Skan    operands[0] = force_reg (TImode, operands[0]);
512169699Skan  ix86_compare_op0 = operands[0];
513169699Skan  ix86_compare_op1 = operands[1];
514169699Skan  DONE;
515169699Skan})
516169699Skan
51790286Sobrien(define_expand "cmpdi"
518169699Skan  [(set (reg:CC FLAGS_REG)
51990286Sobrien	(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
52090286Sobrien		    (match_operand:DI 1 "x86_64_general_operand" "")))]
52190286Sobrien  ""
52218334Speter{
52390286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
52490286Sobrien    operands[0] = force_reg (DImode, operands[0]);
52590286Sobrien  ix86_compare_op0 = operands[0];
52690286Sobrien  ix86_compare_op1 = operands[1];
52718334Speter  DONE;
52890286Sobrien})
52918334Speter
53018334Speter(define_expand "cmpsi"
531169699Skan  [(set (reg:CC FLAGS_REG)
53290286Sobrien	(compare:CC (match_operand:SI 0 "cmpsi_operand" "")
53390286Sobrien		    (match_operand:SI 1 "general_operand" "")))]
53418334Speter  ""
53518334Speter{
53618334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
53718334Speter    operands[0] = force_reg (SImode, operands[0]);
53890286Sobrien  ix86_compare_op0 = operands[0];
53990286Sobrien  ix86_compare_op1 = operands[1];
54018334Speter  DONE;
54190286Sobrien})
54218334Speter
54318334Speter(define_expand "cmphi"
544169699Skan  [(set (reg:CC FLAGS_REG)
54590286Sobrien	(compare:CC (match_operand:HI 0 "nonimmediate_operand" "")
54690286Sobrien		    (match_operand:HI 1 "general_operand" "")))]
54718334Speter  ""
54818334Speter{
54918334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
55018334Speter    operands[0] = force_reg (HImode, operands[0]);
55190286Sobrien  ix86_compare_op0 = operands[0];
55290286Sobrien  ix86_compare_op1 = operands[1];
55318334Speter  DONE;
55490286Sobrien})
55518334Speter
55618334Speter(define_expand "cmpqi"
557169699Skan  [(set (reg:CC FLAGS_REG)
55890286Sobrien	(compare:CC (match_operand:QI 0 "nonimmediate_operand" "")
55990286Sobrien		    (match_operand:QI 1 "general_operand" "")))]
56090286Sobrien  "TARGET_QIMODE_MATH"
56118334Speter{
56218334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
56318334Speter    operands[0] = force_reg (QImode, operands[0]);
56490286Sobrien  ix86_compare_op0 = operands[0];
56590286Sobrien  ix86_compare_op1 = operands[1];
56618334Speter  DONE;
56790286Sobrien})
56818334Speter
56990286Sobrien(define_insn "cmpdi_ccno_1_rex64"
570169699Skan  [(set (reg FLAGS_REG)
57190286Sobrien	(compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")
57290286Sobrien		 (match_operand:DI 1 "const0_operand" "n,n")))]
57390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
57490286Sobrien  "@
57590286Sobrien   test{q}\t{%0, %0|%0, %0}
57690286Sobrien   cmp{q}\t{%1, %0|%0, %1}"
57790286Sobrien  [(set_attr "type" "test,icmp")
57890286Sobrien   (set_attr "length_immediate" "0,1")
57990286Sobrien   (set_attr "mode" "DI")])
58018334Speter
58190286Sobrien(define_insn "*cmpdi_minus_1_rex64"
582169699Skan  [(set (reg FLAGS_REG)
58390286Sobrien	(compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r")
58490286Sobrien			   (match_operand:DI 1 "x86_64_general_operand" "re,mr"))
58590286Sobrien		 (const_int 0)))]
58690286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)"
58790286Sobrien  "cmp{q}\t{%1, %0|%0, %1}"
58890286Sobrien  [(set_attr "type" "icmp")
58990286Sobrien   (set_attr "mode" "DI")])
59018334Speter
59190286Sobrien(define_expand "cmpdi_1_rex64"
592169699Skan  [(set (reg:CC FLAGS_REG)
59390286Sobrien	(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
59490286Sobrien		    (match_operand:DI 1 "general_operand" "")))]
59590286Sobrien  "TARGET_64BIT"
59690286Sobrien  "")
59718334Speter
59890286Sobrien(define_insn "cmpdi_1_insn_rex64"
599169699Skan  [(set (reg FLAGS_REG)
60090286Sobrien	(compare (match_operand:DI 0 "nonimmediate_operand" "mr,r")
60190286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "re,mr")))]
60290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
60390286Sobrien  "cmp{q}\t{%1, %0|%0, %1}"
60490286Sobrien  [(set_attr "type" "icmp")
60590286Sobrien   (set_attr "mode" "DI")])
60650650Sobrien
60718334Speter
60890286Sobrien(define_insn "*cmpsi_ccno_1"
609169699Skan  [(set (reg FLAGS_REG)
61090286Sobrien	(compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
61190286Sobrien		 (match_operand:SI 1 "const0_operand" "n,n")))]
61290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
61390286Sobrien  "@
61490286Sobrien   test{l}\t{%0, %0|%0, %0}
61590286Sobrien   cmp{l}\t{%1, %0|%0, %1}"
61690286Sobrien  [(set_attr "type" "test,icmp")
61790286Sobrien   (set_attr "length_immediate" "0,1")
61890286Sobrien   (set_attr "mode" "SI")])
61950650Sobrien
62090286Sobrien(define_insn "*cmpsi_minus_1"
621169699Skan  [(set (reg FLAGS_REG)
62290286Sobrien	(compare (minus:SI (match_operand:SI 0 "nonimmediate_operand" "rm,r")
62390286Sobrien			   (match_operand:SI 1 "general_operand" "ri,mr"))
62490286Sobrien		 (const_int 0)))]
62590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
62690286Sobrien  "cmp{l}\t{%1, %0|%0, %1}"
62790286Sobrien  [(set_attr "type" "icmp")
62890286Sobrien   (set_attr "mode" "SI")])
62918334Speter
63090286Sobrien(define_expand "cmpsi_1"
631169699Skan  [(set (reg:CC FLAGS_REG)
63290286Sobrien	(compare:CC (match_operand:SI 0 "nonimmediate_operand" "rm,r")
63390286Sobrien		    (match_operand:SI 1 "general_operand" "ri,mr")))]
63490286Sobrien  ""
63590286Sobrien  "")
63618334Speter
63790286Sobrien(define_insn "*cmpsi_1_insn"
638169699Skan  [(set (reg FLAGS_REG)
63990286Sobrien	(compare (match_operand:SI 0 "nonimmediate_operand" "rm,r")
64090286Sobrien		 (match_operand:SI 1 "general_operand" "ri,mr")))]
64190286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
64290286Sobrien    && ix86_match_ccmode (insn, CCmode)"
64390286Sobrien  "cmp{l}\t{%1, %0|%0, %1}"
64490286Sobrien  [(set_attr "type" "icmp")
64590286Sobrien   (set_attr "mode" "SI")])
64618334Speter
64790286Sobrien(define_insn "*cmphi_ccno_1"
648169699Skan  [(set (reg FLAGS_REG)
64990286Sobrien	(compare (match_operand:HI 0 "nonimmediate_operand" "r,?mr")
65090286Sobrien		 (match_operand:HI 1 "const0_operand" "n,n")))]
65190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
65290286Sobrien  "@
65390286Sobrien   test{w}\t{%0, %0|%0, %0}
65490286Sobrien   cmp{w}\t{%1, %0|%0, %1}"
65590286Sobrien  [(set_attr "type" "test,icmp")
65690286Sobrien   (set_attr "length_immediate" "0,1")
65790286Sobrien   (set_attr "mode" "HI")])
65818334Speter
65990286Sobrien(define_insn "*cmphi_minus_1"
660169699Skan  [(set (reg FLAGS_REG)
66190286Sobrien	(compare (minus:HI (match_operand:HI 0 "nonimmediate_operand" "rm,r")
66290286Sobrien			   (match_operand:HI 1 "general_operand" "ri,mr"))
66390286Sobrien		 (const_int 0)))]
66490286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
66590286Sobrien  "cmp{w}\t{%1, %0|%0, %1}"
66690286Sobrien  [(set_attr "type" "icmp")
66790286Sobrien   (set_attr "mode" "HI")])
66850650Sobrien
66990286Sobrien(define_insn "*cmphi_1"
670169699Skan  [(set (reg FLAGS_REG)
67190286Sobrien	(compare (match_operand:HI 0 "nonimmediate_operand" "rm,r")
67290286Sobrien		 (match_operand:HI 1 "general_operand" "ri,mr")))]
67390286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
67490286Sobrien   && ix86_match_ccmode (insn, CCmode)"
67590286Sobrien  "cmp{w}\t{%1, %0|%0, %1}"
67690286Sobrien  [(set_attr "type" "icmp")
67790286Sobrien   (set_attr "mode" "HI")])
67818334Speter
67990286Sobrien(define_insn "*cmpqi_ccno_1"
680169699Skan  [(set (reg FLAGS_REG)
68190286Sobrien	(compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq")
68290286Sobrien		 (match_operand:QI 1 "const0_operand" "n,n")))]
68390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
68490286Sobrien  "@
68590286Sobrien   test{b}\t{%0, %0|%0, %0}
68690286Sobrien   cmp{b}\t{$0, %0|%0, 0}"
68790286Sobrien  [(set_attr "type" "test,icmp")
68890286Sobrien   (set_attr "length_immediate" "0,1")
68990286Sobrien   (set_attr "mode" "QI")])
69018334Speter
69190286Sobrien(define_insn "*cmpqi_1"
692169699Skan  [(set (reg FLAGS_REG)
69390286Sobrien	(compare (match_operand:QI 0 "nonimmediate_operand" "qm,q")
69490286Sobrien		 (match_operand:QI 1 "general_operand" "qi,mq")))]
69590286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
69690286Sobrien    && ix86_match_ccmode (insn, CCmode)"
69790286Sobrien  "cmp{b}\t{%1, %0|%0, %1}"
69890286Sobrien  [(set_attr "type" "icmp")
69990286Sobrien   (set_attr "mode" "QI")])
70018334Speter
70190286Sobrien(define_insn "*cmpqi_minus_1"
702169699Skan  [(set (reg FLAGS_REG)
70390286Sobrien	(compare (minus:QI (match_operand:QI 0 "nonimmediate_operand" "qm,q")
70490286Sobrien			   (match_operand:QI 1 "general_operand" "qi,mq"))
70590286Sobrien		 (const_int 0)))]
70690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
70790286Sobrien  "cmp{b}\t{%1, %0|%0, %1}"
70890286Sobrien  [(set_attr "type" "icmp")
70990286Sobrien   (set_attr "mode" "QI")])
71018334Speter
71190286Sobrien(define_insn "*cmpqi_ext_1"
712169699Skan  [(set (reg FLAGS_REG)
71390286Sobrien	(compare
71490286Sobrien	  (match_operand:QI 0 "general_operand" "Qm")
71590286Sobrien	  (subreg:QI
71690286Sobrien	    (zero_extract:SI
71790286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
71890286Sobrien	      (const_int 8)
71990286Sobrien	      (const_int 8)) 0)))]
72090286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
72190286Sobrien  "cmp{b}\t{%h1, %0|%0, %h1}"
72290286Sobrien  [(set_attr "type" "icmp")
72390286Sobrien   (set_attr "mode" "QI")])
72490286Sobrien
72590286Sobrien(define_insn "*cmpqi_ext_1_rex64"
726169699Skan  [(set (reg FLAGS_REG)
72790286Sobrien	(compare
72890286Sobrien	  (match_operand:QI 0 "register_operand" "Q")
72990286Sobrien	  (subreg:QI
73090286Sobrien	    (zero_extract:SI
73190286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
73290286Sobrien	      (const_int 8)
73390286Sobrien	      (const_int 8)) 0)))]
73490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
73590286Sobrien  "cmp{b}\t{%h1, %0|%0, %h1}"
73690286Sobrien  [(set_attr "type" "icmp")
73790286Sobrien   (set_attr "mode" "QI")])
73890286Sobrien
73990286Sobrien(define_insn "*cmpqi_ext_2"
740169699Skan  [(set (reg FLAGS_REG)
74190286Sobrien	(compare
74290286Sobrien	  (subreg:QI
74390286Sobrien	    (zero_extract:SI
74490286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
74590286Sobrien	      (const_int 8)
74690286Sobrien	      (const_int 8)) 0)
74790286Sobrien	  (match_operand:QI 1 "const0_operand" "n")))]
74890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
74990286Sobrien  "test{b}\t%h0, %h0"
75090286Sobrien  [(set_attr "type" "test")
75190286Sobrien   (set_attr "length_immediate" "0")
75290286Sobrien   (set_attr "mode" "QI")])
75390286Sobrien
75490286Sobrien(define_expand "cmpqi_ext_3"
755169699Skan  [(set (reg:CC FLAGS_REG)
75690286Sobrien	(compare:CC
75790286Sobrien	  (subreg:QI
75890286Sobrien	    (zero_extract:SI
75990286Sobrien	      (match_operand 0 "ext_register_operand" "")
76090286Sobrien	      (const_int 8)
76190286Sobrien	      (const_int 8)) 0)
76290286Sobrien	  (match_operand:QI 1 "general_operand" "")))]
76390286Sobrien  ""
76490286Sobrien  "")
76590286Sobrien
76690286Sobrien(define_insn "cmpqi_ext_3_insn"
767169699Skan  [(set (reg FLAGS_REG)
76890286Sobrien	(compare
76990286Sobrien	  (subreg:QI
77090286Sobrien	    (zero_extract:SI
77190286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
77290286Sobrien	      (const_int 8)
77390286Sobrien	      (const_int 8)) 0)
77490286Sobrien	  (match_operand:QI 1 "general_operand" "Qmn")))]
77590286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
77690286Sobrien  "cmp{b}\t{%1, %h0|%h0, %1}"
77790286Sobrien  [(set_attr "type" "icmp")
77890286Sobrien   (set_attr "mode" "QI")])
77990286Sobrien
78090286Sobrien(define_insn "cmpqi_ext_3_insn_rex64"
781169699Skan  [(set (reg FLAGS_REG)
78290286Sobrien	(compare
78390286Sobrien	  (subreg:QI
78490286Sobrien	    (zero_extract:SI
78590286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
78690286Sobrien	      (const_int 8)
78790286Sobrien	      (const_int 8)) 0)
78890286Sobrien	  (match_operand:QI 1 "nonmemory_operand" "Qn")))]
78990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
79090286Sobrien  "cmp{b}\t{%1, %h0|%h0, %1}"
79190286Sobrien  [(set_attr "type" "icmp")
79290286Sobrien   (set_attr "mode" "QI")])
79390286Sobrien
79490286Sobrien(define_insn "*cmpqi_ext_4"
795169699Skan  [(set (reg FLAGS_REG)
79690286Sobrien	(compare
79790286Sobrien	  (subreg:QI
79890286Sobrien	    (zero_extract:SI
79990286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
80090286Sobrien	      (const_int 8)
80190286Sobrien	      (const_int 8)) 0)
80290286Sobrien	  (subreg:QI
80390286Sobrien	    (zero_extract:SI
80490286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
80590286Sobrien	      (const_int 8)
80690286Sobrien	      (const_int 8)) 0)))]
80790286Sobrien  "ix86_match_ccmode (insn, CCmode)"
80890286Sobrien  "cmp{b}\t{%h1, %h0|%h0, %h1}"
80990286Sobrien  [(set_attr "type" "icmp")
81090286Sobrien   (set_attr "mode" "QI")])
81190286Sobrien
81290286Sobrien;; These implement float point compares.
81390286Sobrien;; %%% See if we can get away with VOIDmode operands on the actual insns,
81490286Sobrien;; which would allow mix and match FP modes on the compares.  Which is what
81590286Sobrien;; the old patterns did, but with many more of them.
81690286Sobrien
81718334Speter(define_expand "cmpxf"
818169699Skan  [(set (reg:CC FLAGS_REG)
819169699Skan	(compare:CC (match_operand:XF 0 "nonmemory_operand" "")
820169699Skan		    (match_operand:XF 1 "nonmemory_operand" "")))]
82118334Speter  "TARGET_80387"
82218334Speter{
82390286Sobrien  ix86_compare_op0 = operands[0];
82490286Sobrien  ix86_compare_op1 = operands[1];
82518334Speter  DONE;
82690286Sobrien})
82718334Speter
82818334Speter(define_expand "cmpdf"
829169699Skan  [(set (reg:CC FLAGS_REG)
83090286Sobrien	(compare:CC (match_operand:DF 0 "cmp_fp_expander_operand" "")
83190286Sobrien		    (match_operand:DF 1 "cmp_fp_expander_operand" "")))]
832169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
83318334Speter{
83490286Sobrien  ix86_compare_op0 = operands[0];
83590286Sobrien  ix86_compare_op1 = operands[1];
83618334Speter  DONE;
83790286Sobrien})
83818334Speter
83918334Speter(define_expand "cmpsf"
840169699Skan  [(set (reg:CC FLAGS_REG)
84190286Sobrien	(compare:CC (match_operand:SF 0 "cmp_fp_expander_operand" "")
84290286Sobrien		    (match_operand:SF 1 "cmp_fp_expander_operand" "")))]
843169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
84418334Speter{
84590286Sobrien  ix86_compare_op0 = operands[0];
84690286Sobrien  ix86_compare_op1 = operands[1];
84718334Speter  DONE;
84890286Sobrien})
84918334Speter
85090286Sobrien;; FP compares, step 1:
85190286Sobrien;; Set the FP condition codes.
85290286Sobrien;;
85390286Sobrien;; CCFPmode	compare with exceptions
85490286Sobrien;; CCFPUmode	compare with no exceptions
85518334Speter
856169699Skan;; We may not use "#" to split and emit these, since the REG_DEAD notes
857169699Skan;; used to manage the reg stack popping would not be preserved.
85818334Speter
85990286Sobrien(define_insn "*cmpfp_0"
86090286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
86190286Sobrien	(unspec:HI
862169699Skan	  [(compare:CCFP
863169699Skan	     (match_operand 1 "register_operand" "f")
864169699Skan	     (match_operand 2 "const0_operand" "X"))]
865169699Skan	UNSPEC_FNSTSW))]
86690286Sobrien  "TARGET_80387
86790286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
86890286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
869169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
87090286Sobrien  [(set_attr "type" "multi")
871169699Skan   (set_attr "unit" "i387")
872132727Skan   (set (attr "mode")
873132727Skan     (cond [(match_operand:SF 1 "" "")
874132727Skan	      (const_string "SF")
875132727Skan	    (match_operand:DF 1 "" "")
876132727Skan	      (const_string "DF")
877132727Skan	   ]
878132727Skan	   (const_string "XF")))])
87990286Sobrien
880169699Skan(define_insn "*cmpfp_sf"
88190286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
88290286Sobrien	(unspec:HI
88390286Sobrien	  [(compare:CCFP
88490286Sobrien	     (match_operand:SF 1 "register_operand" "f")
885117404Skan	     (match_operand:SF 2 "nonimmediate_operand" "fm"))]
886117404Skan	  UNSPEC_FNSTSW))]
88718334Speter  "TARGET_80387"
888169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
889169699Skan  [(set_attr "type" "multi")
890169699Skan   (set_attr "unit" "i387")
89190286Sobrien   (set_attr "mode" "SF")])
89218334Speter
893169699Skan(define_insn "*cmpfp_df"
89490286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
89590286Sobrien	(unspec:HI
89690286Sobrien	  [(compare:CCFP
89790286Sobrien	     (match_operand:DF 1 "register_operand" "f")
898117404Skan	     (match_operand:DF 2 "nonimmediate_operand" "fm"))]
899117404Skan	  UNSPEC_FNSTSW))]
90018334Speter  "TARGET_80387"
901169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
90290286Sobrien  [(set_attr "type" "multi")
903169699Skan   (set_attr "unit" "i387")
90490286Sobrien   (set_attr "mode" "DF")])
90518334Speter
906169699Skan(define_insn "*cmpfp_xf"
90790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
90890286Sobrien	(unspec:HI
90990286Sobrien	  [(compare:CCFP
91090286Sobrien	     (match_operand:XF 1 "register_operand" "f")
911117404Skan	     (match_operand:XF 2 "register_operand" "f"))]
912117404Skan	  UNSPEC_FNSTSW))]
91390286Sobrien  "TARGET_80387"
914169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
91590286Sobrien  [(set_attr "type" "multi")
916169699Skan   (set_attr "unit" "i387")
91790286Sobrien   (set_attr "mode" "XF")])
91818334Speter
919169699Skan(define_insn "*cmpfp_u"
92090286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
92190286Sobrien	(unspec:HI
92290286Sobrien	  [(compare:CCFPU
92390286Sobrien	     (match_operand 1 "register_operand" "f")
924117404Skan	     (match_operand 2 "register_operand" "f"))]
925117404Skan	  UNSPEC_FNSTSW))]
92690286Sobrien  "TARGET_80387
92790286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
92890286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
929169699Skan  "* return output_fp_compare (insn, operands, 0, 1);"
93090286Sobrien  [(set_attr "type" "multi")
931169699Skan   (set_attr "unit" "i387")
932132727Skan   (set (attr "mode")
933132727Skan     (cond [(match_operand:SF 1 "" "")
934132727Skan	      (const_string "SF")
935132727Skan	    (match_operand:DF 1 "" "")
936132727Skan	      (const_string "DF")
937132727Skan	   ]
938132727Skan	   (const_string "XF")))])
93918334Speter
940169699Skan(define_insn "*cmpfp_<mode>"
941169699Skan  [(set (match_operand:HI 0 "register_operand" "=a")
942169699Skan	(unspec:HI
943169699Skan	  [(compare:CCFP
944169699Skan	     (match_operand 1 "register_operand" "f")
945169699Skan	     (match_operator 3 "float_operator"
946169699Skan	       [(match_operand:X87MODEI12 2 "memory_operand" "m")]))]
947169699Skan	  UNSPEC_FNSTSW))]
948169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
949169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
950169699Skan   && (GET_MODE (operands [3]) == GET_MODE (operands[1]))"
951169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
952169699Skan  [(set_attr "type" "multi")
953169699Skan   (set_attr "unit" "i387")
954169699Skan   (set_attr "fp_int_src" "true")
955169699Skan   (set_attr "mode" "<MODE>")])
95618334Speter
95790286Sobrien;; FP compares, step 2
95890286Sobrien;; Move the fpsw to ax.
95918334Speter
960169699Skan(define_insn "x86_fnstsw_1"
96190286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
962169699Skan	(unspec:HI [(reg:CCFP FPSR_REG)] UNSPEC_FNSTSW))]
96390286Sobrien  "TARGET_80387"
96490286Sobrien  "fnstsw\t%0"
96590286Sobrien  [(set_attr "length" "2")
96690286Sobrien   (set_attr "mode" "SI")
967169699Skan   (set_attr "unit" "i387")])
96818334Speter
96990286Sobrien;; FP compares, step 3
97090286Sobrien;; Get ax into flags, general case.
97150650Sobrien
97290286Sobrien(define_insn "x86_sahf_1"
973169699Skan  [(set (reg:CC FLAGS_REG)
974117404Skan	(unspec:CC [(match_operand:HI 0 "register_operand" "a")] UNSPEC_SAHF))]
97590286Sobrien  "!TARGET_64BIT"
97690286Sobrien  "sahf"
97790286Sobrien  [(set_attr "length" "1")
97890286Sobrien   (set_attr "athlon_decode" "vector")
979251212Spfg   (set_attr "amdfam10_decode" "direct")
980169699Skan   (set_attr "mode" "SI")])
98118334Speter
98290286Sobrien;; Pentium Pro can do steps 1 through 3 in one go.
983251212Spfg;; comi*, ucomi*, fcomi*, ficomi*,fucomi* (i387 instructions set condition codes) 
984169699Skan(define_insn "*cmpfp_i_mixed"
985169699Skan  [(set (reg:CCFP FLAGS_REG)
986169699Skan	(compare:CCFP (match_operand 0 "register_operand" "f,x")
987169699Skan		      (match_operand 1 "nonimmediate_operand" "f,xm")))]
988169699Skan  "TARGET_MIX_SSE_I387
98990286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
990169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
99190286Sobrien  "* return output_fp_compare (insn, operands, 1, 0);"
992132727Skan  [(set_attr "type" "fcmp,ssecomi")
993132727Skan   (set (attr "mode")
994132727Skan     (if_then_else (match_operand:SF 1 "" "")
995132727Skan        (const_string "SF")
996132727Skan        (const_string "DF")))
997251212Spfg   (set_attr "athlon_decode" "vector")
998251212Spfg   (set_attr "amdfam10_decode" "direct")])
99918334Speter
1000169699Skan(define_insn "*cmpfp_i_sse"
1001169699Skan  [(set (reg:CCFP FLAGS_REG)
100290286Sobrien	(compare:CCFP (match_operand 0 "register_operand" "x")
100390286Sobrien		      (match_operand 1 "nonimmediate_operand" "xm")))]
1004169699Skan  "TARGET_SSE_MATH
1005169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
1006169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
100790286Sobrien  "* return output_fp_compare (insn, operands, 1, 0);"
1008132727Skan  [(set_attr "type" "ssecomi")
1009132727Skan   (set (attr "mode")
1010132727Skan     (if_then_else (match_operand:SF 1 "" "")
1011132727Skan        (const_string "SF")
1012132727Skan        (const_string "DF")))
1013251212Spfg   (set_attr "athlon_decode" "vector")
1014251212Spfg   (set_attr "amdfam10_decode" "direct")])
101518334Speter
1016169699Skan(define_insn "*cmpfp_i_i387"
1017169699Skan  [(set (reg:CCFP FLAGS_REG)
1018169699Skan	(compare:CCFP (match_operand 0 "register_operand" "f")
1019169699Skan		      (match_operand 1 "register_operand" "f")))]
102090286Sobrien  "TARGET_80387 && TARGET_CMOVE
1021169699Skan   && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
102290286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))
102390286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
1024169699Skan  "* return output_fp_compare (insn, operands, 1, 0);"
102590286Sobrien  [(set_attr "type" "fcmp")
1026132727Skan   (set (attr "mode")
1027132727Skan     (cond [(match_operand:SF 1 "" "")
1028132727Skan	      (const_string "SF")
1029132727Skan	    (match_operand:DF 1 "" "")
1030132727Skan	      (const_string "DF")
1031132727Skan	   ]
1032132727Skan	   (const_string "XF")))
1033251212Spfg   (set_attr "athlon_decode" "vector")
1034251212Spfg   (set_attr "amdfam10_decode" "direct")])
103518334Speter
1036169699Skan(define_insn "*cmpfp_iu_mixed"
1037169699Skan  [(set (reg:CCFPU FLAGS_REG)
1038169699Skan	(compare:CCFPU (match_operand 0 "register_operand" "f,x")
1039169699Skan		       (match_operand 1 "nonimmediate_operand" "f,xm")))]
1040169699Skan  "TARGET_MIX_SSE_I387
104190286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
104290286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
104390286Sobrien  "* return output_fp_compare (insn, operands, 1, 1);"
1044132727Skan  [(set_attr "type" "fcmp,ssecomi")
1045132727Skan   (set (attr "mode")
1046132727Skan     (if_then_else (match_operand:SF 1 "" "")
1047132727Skan        (const_string "SF")
1048132727Skan        (const_string "DF")))
1049251212Spfg   (set_attr "athlon_decode" "vector")
1050251212Spfg   (set_attr "amdfam10_decode" "direct")])
105150650Sobrien
1052169699Skan(define_insn "*cmpfp_iu_sse"
1053169699Skan  [(set (reg:CCFPU FLAGS_REG)
105490286Sobrien	(compare:CCFPU (match_operand 0 "register_operand" "x")
105590286Sobrien		       (match_operand 1 "nonimmediate_operand" "xm")))]
1056169699Skan  "TARGET_SSE_MATH
1057169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
105890286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
105990286Sobrien  "* return output_fp_compare (insn, operands, 1, 1);"
1060132727Skan  [(set_attr "type" "ssecomi")
1061132727Skan   (set (attr "mode")
1062132727Skan     (if_then_else (match_operand:SF 1 "" "")
1063132727Skan        (const_string "SF")
1064132727Skan        (const_string "DF")))
1065251212Spfg   (set_attr "athlon_decode" "vector")
1066251212Spfg   (set_attr "amdfam10_decode" "direct")])
1067169699Skan
1068169699Skan(define_insn "*cmpfp_iu_387"
1069169699Skan  [(set (reg:CCFPU FLAGS_REG)
1070169699Skan	(compare:CCFPU (match_operand 0 "register_operand" "f")
1071169699Skan		       (match_operand 1 "register_operand" "f")))]
1072169699Skan  "TARGET_80387 && TARGET_CMOVE
1073169699Skan   && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
1074169699Skan   && FLOAT_MODE_P (GET_MODE (operands[0]))
1075169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
1076169699Skan  "* return output_fp_compare (insn, operands, 1, 1);"
1077169699Skan  [(set_attr "type" "fcmp")
1078169699Skan   (set (attr "mode")
1079169699Skan     (cond [(match_operand:SF 1 "" "")
1080169699Skan	      (const_string "SF")
1081169699Skan	    (match_operand:DF 1 "" "")
1082169699Skan	      (const_string "DF")
1083169699Skan	   ]
1084169699Skan	   (const_string "XF")))
1085251212Spfg   (set_attr "athlon_decode" "vector")
1086251212Spfg   (set_attr "amdfam10_decode" "direct")])
108790286Sobrien
108890286Sobrien;; Move instructions.
108918334Speter
109018334Speter;; General case of fullword move.
109118334Speter
109218334Speter(define_expand "movsi"
109390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
109418334Speter	(match_operand:SI 1 "general_operand" ""))]
109518334Speter  ""
109690286Sobrien  "ix86_expand_move (SImode, operands); DONE;")
109718334Speter
109890286Sobrien;; Push/pop instructions.  They are separate since autoinc/dec is not a
109990286Sobrien;; general_operand.
110090286Sobrien;;
1101259563Spfg;; %%% We don't use a post-inc memory reference because x86 is not a
110290286Sobrien;; general AUTO_INC_DEC host, which impacts how it is treated in flow.
110390286Sobrien;; Changing this impacts compiler performance on other non-AUTO_INC_DEC
110490286Sobrien;; targets without our curiosities, and it is just as easy to represent
110590286Sobrien;; this differently.
110618334Speter
110790286Sobrien(define_insn "*pushsi2"
110890286Sobrien  [(set (match_operand:SI 0 "push_operand" "=<")
110990286Sobrien	(match_operand:SI 1 "general_no_elim_operand" "ri*m"))]
111090286Sobrien  "!TARGET_64BIT"
111190286Sobrien  "push{l}\t%1"
111290286Sobrien  [(set_attr "type" "push")
111390286Sobrien   (set_attr "mode" "SI")])
111418334Speter
111590286Sobrien;; For 64BIT abi we always round up to 8 bytes.
111690286Sobrien(define_insn "*pushsi2_rex64"
111790286Sobrien  [(set (match_operand:SI 0 "push_operand" "=X")
111890286Sobrien	(match_operand:SI 1 "nonmemory_no_elim_operand" "ri"))]
111990286Sobrien  "TARGET_64BIT"
112090286Sobrien  "push{q}\t%q1"
112190286Sobrien  [(set_attr "type" "push")
112290286Sobrien   (set_attr "mode" "SI")])
112318334Speter
112490286Sobrien(define_insn "*pushsi2_prologue"
112590286Sobrien  [(set (match_operand:SI 0 "push_operand" "=<")
112690286Sobrien	(match_operand:SI 1 "general_no_elim_operand" "ri*m"))
112790286Sobrien   (clobber (mem:BLK (scratch)))]
112890286Sobrien  "!TARGET_64BIT"
112990286Sobrien  "push{l}\t%1"
113090286Sobrien  [(set_attr "type" "push")
113190286Sobrien   (set_attr "mode" "SI")])
113252296Sobrien
113390286Sobrien(define_insn "*popsi1_epilogue"
113490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
1135169699Skan	(mem:SI (reg:SI SP_REG)))
1136169699Skan   (set (reg:SI SP_REG)
1137169699Skan	(plus:SI (reg:SI SP_REG) (const_int 4)))
113890286Sobrien   (clobber (mem:BLK (scratch)))]
113990286Sobrien  "!TARGET_64BIT"
114090286Sobrien  "pop{l}\t%0"
114190286Sobrien  [(set_attr "type" "pop")
114290286Sobrien   (set_attr "mode" "SI")])
114318334Speter
114490286Sobrien(define_insn "popsi1"
114590286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
1146169699Skan	(mem:SI (reg:SI SP_REG)))
1147169699Skan   (set (reg:SI SP_REG)
1148169699Skan	(plus:SI (reg:SI SP_REG) (const_int 4)))]
114990286Sobrien  "!TARGET_64BIT"
115090286Sobrien  "pop{l}\t%0"
115190286Sobrien  [(set_attr "type" "pop")
115290286Sobrien   (set_attr "mode" "SI")])
115318334Speter
115490286Sobrien(define_insn "*movsi_xor"
115590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
115690286Sobrien	(match_operand:SI 1 "const0_operand" "i"))
1157169699Skan   (clobber (reg:CC FLAGS_REG))]
115890286Sobrien  "reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
115990286Sobrien  "xor{l}\t{%0, %0|%0, %0}"
116090286Sobrien  [(set_attr "type" "alu1")
116190286Sobrien   (set_attr "mode" "SI")
116290286Sobrien   (set_attr "length_immediate" "0")])
1163259563Spfg
116490286Sobrien(define_insn "*movsi_or"
116590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
116690286Sobrien	(match_operand:SI 1 "immediate_operand" "i"))
1167169699Skan   (clobber (reg:CC FLAGS_REG))]
1168132727Skan  "reload_completed
1169132727Skan   && operands[1] == constm1_rtx
117090286Sobrien   && (TARGET_PENTIUM || optimize_size)"
117190286Sobrien{
117290286Sobrien  operands[1] = constm1_rtx;
117390286Sobrien  return "or{l}\t{%1, %0|%0, %1}";
117490286Sobrien}
117590286Sobrien  [(set_attr "type" "alu1")
117690286Sobrien   (set_attr "mode" "SI")
117790286Sobrien   (set_attr "length_immediate" "1")])
117818334Speter
117990286Sobrien(define_insn "*movsi_1"
1180169699Skan  [(set (match_operand:SI 0 "nonimmediate_operand"
1181169699Skan			"=r  ,m  ,*y,*y,?rm,?*y,*x,*x,?r,m ,?*Y,*x")
1182169699Skan	(match_operand:SI 1 "general_operand"
1183169699Skan			"rinm,rin,C ,*y,*y ,rm ,C ,*x,*Y,*x,r  ,m "))]
1184169699Skan  "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
118550650Sobrien{
118690286Sobrien  switch (get_attr_type (insn))
118790286Sobrien    {
1188169699Skan    case TYPE_SSELOG1:
1189117404Skan      if (get_attr_mode (insn) == MODE_TI)
1190169699Skan        return "pxor\t%0, %0";
1191169699Skan      return "xorps\t%0, %0";
119252296Sobrien
1193169699Skan    case TYPE_SSEMOV:
1194169699Skan      switch (get_attr_mode (insn))
1195169699Skan	{
1196169699Skan	case MODE_TI:
1197169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
1198169699Skan	case MODE_V4SF:
1199169699Skan	  return "movaps\t{%1, %0|%0, %1}";
1200169699Skan	case MODE_SI:
1201169699Skan          return "movd\t{%1, %0|%0, %1}";
1202169699Skan	case MODE_SF:
1203169699Skan          return "movss\t{%1, %0|%0, %1}";
1204169699Skan	default:
1205169699Skan	  gcc_unreachable ();
1206169699Skan	}
120752296Sobrien
1208169699Skan    case TYPE_MMXADD:
1209169699Skan      return "pxor\t%0, %0";
121018334Speter
1211132727Skan    case TYPE_MMXMOV:
1212132727Skan      if (get_attr_mode (insn) == MODE_DI)
1213132727Skan	return "movq\t{%1, %0|%0, %1}";
1214132727Skan      return "movd\t{%1, %0|%0, %1}";
1215132727Skan
1216132727Skan    case TYPE_LEA:
1217132727Skan      return "lea{l}\t{%1, %0|%0, %1}";
1218132727Skan
1219132727Skan    default:
1220169699Skan      gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
1221132727Skan      return "mov{l}\t{%1, %0|%0, %1}";
1222132727Skan    }
1223132727Skan}
1224132727Skan  [(set (attr "type")
1225169699Skan     (cond [(eq_attr "alternative" "2")
1226169699Skan	      (const_string "mmxadd")
1227169699Skan	    (eq_attr "alternative" "3,4,5")
1228132727Skan	      (const_string "mmxmov")
1229169699Skan	    (eq_attr "alternative" "6")
1230169699Skan	      (const_string "sselog1")
1231169699Skan	    (eq_attr "alternative" "7,8,9,10,11")
1232132727Skan	      (const_string "ssemov")
1233169699Skan 	    (match_operand:DI 1 "pic_32bit_operand" "")
1234132727Skan	      (const_string "lea")
1235132727Skan	   ]
1236132727Skan	   (const_string "imov")))
1237169699Skan   (set (attr "mode")
1238169699Skan     (cond [(eq_attr "alternative" "2,3")
1239169699Skan	      (const_string "DI")
1240169699Skan	    (eq_attr "alternative" "6,7")
1241169699Skan	      (if_then_else
1242169699Skan	        (eq (symbol_ref "TARGET_SSE2") (const_int 0))
1243169699Skan	        (const_string "V4SF")
1244169699Skan	        (const_string "TI"))
1245169699Skan	    (and (eq_attr "alternative" "8,9,10,11")
1246169699Skan	         (eq (symbol_ref "TARGET_SSE2") (const_int 0)))
1247169699Skan	      (const_string "SF")
1248169699Skan	   ]
1249169699Skan	   (const_string "SI")))])
1250132727Skan
1251132727Skan;; Stores and loads of ax to arbitrary constant address.
125290286Sobrien;; We fake an second form of instruction to force reload to load address
125390286Sobrien;; into register when rax is not available
125490286Sobrien(define_insn "*movabssi_1_rex64"
1255117404Skan  [(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1256117404Skan	(match_operand:SI 1 "nonmemory_operand" "a,er"))]
1257117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
125890286Sobrien  "@
125990286Sobrien   movabs{l}\t{%1, %P0|%P0, %1}
1260117404Skan   mov{l}\t{%1, %a0|%a0, %1}"
126190286Sobrien  [(set_attr "type" "imov")
1262117404Skan   (set_attr "modrm" "0,*")
1263117404Skan   (set_attr "length_address" "8,0")
1264117404Skan   (set_attr "length_immediate" "0,*")
126590286Sobrien   (set_attr "memory" "store")
126690286Sobrien   (set_attr "mode" "SI")])
126750650Sobrien
126890286Sobrien(define_insn "*movabssi_2_rex64"
126990286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a,r")
127090286Sobrien        (mem:SI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1271117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
127290286Sobrien  "@
127390286Sobrien   movabs{l}\t{%P1, %0|%0, %P1}
127490286Sobrien   mov{l}\t{%a1, %0|%0, %a1}"
127590286Sobrien  [(set_attr "type" "imov")
127690286Sobrien   (set_attr "modrm" "0,*")
127790286Sobrien   (set_attr "length_address" "8,0")
127890286Sobrien   (set_attr "length_immediate" "0")
127990286Sobrien   (set_attr "memory" "load")
128090286Sobrien   (set_attr "mode" "SI")])
128190286Sobrien
128290286Sobrien(define_insn "*swapsi"
128390286Sobrien  [(set (match_operand:SI 0 "register_operand" "+r")
128490286Sobrien	(match_operand:SI 1 "register_operand" "+r"))
128590286Sobrien   (set (match_dup 1)
128690286Sobrien	(match_dup 0))]
128750650Sobrien  ""
128890286Sobrien  "xchg{l}\t%1, %0"
128990286Sobrien  [(set_attr "type" "imov")
1290146906Skan   (set_attr "mode" "SI")
129190286Sobrien   (set_attr "pent_pair" "np")
1292251212Spfg   (set_attr "athlon_decode" "vector")
1293251212Spfg   (set_attr "amdfam10_decode" "double")])   
129418334Speter
129590286Sobrien(define_expand "movhi"
129690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
129790286Sobrien        (match_operand:HI 1 "general_operand" ""))]
129890286Sobrien  ""
129990286Sobrien  "ix86_expand_move (HImode, operands); DONE;")
130018334Speter
130190286Sobrien(define_insn "*pushhi2"
1302169699Skan  [(set (match_operand:HI 0 "push_operand" "=X")
1303169699Skan	(match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
130490286Sobrien  "!TARGET_64BIT"
1305169699Skan  "push{l}\t%k1"
130690286Sobrien  [(set_attr "type" "push")
1307169699Skan   (set_attr "mode" "SI")])
130818334Speter
130990286Sobrien;; For 64BIT abi we always round up to 8 bytes.
131090286Sobrien(define_insn "*pushhi2_rex64"
131190286Sobrien  [(set (match_operand:HI 0 "push_operand" "=X")
131290286Sobrien	(match_operand:HI 1 "nonmemory_no_elim_operand" "ri"))]
131390286Sobrien  "TARGET_64BIT"
131490286Sobrien  "push{q}\t%q1"
131590286Sobrien  [(set_attr "type" "push")
1316169699Skan   (set_attr "mode" "DI")])
131790286Sobrien
131890286Sobrien(define_insn "*movhi_1"
1319117404Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
1320117404Skan	(match_operand:HI 1 "general_operand" "r,rn,rm,rn"))]
132190286Sobrien  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
132218334Speter{
132390286Sobrien  switch (get_attr_type (insn))
132418334Speter    {
132590286Sobrien    case TYPE_IMOVX:
132690286Sobrien      /* movzwl is faster than movw on p2 due to partial word stalls,
132790286Sobrien	 though not as fast as an aligned movl.  */
132890286Sobrien      return "movz{wl|x}\t{%1, %k0|%k0, %1}";
132990286Sobrien    default:
133090286Sobrien      if (get_attr_mode (insn) == MODE_SI)
133190286Sobrien        return "mov{l}\t{%k1, %k0|%k0, %k1}";
133290286Sobrien      else
133390286Sobrien        return "mov{w}\t{%1, %0|%0, %1}";
133418334Speter    }
133590286Sobrien}
133690286Sobrien  [(set (attr "type")
1337169699Skan     (cond [(ne (symbol_ref "optimize_size") (const_int 0))
1338169699Skan	      (const_string "imov")
1339169699Skan	    (and (eq_attr "alternative" "0")
134090286Sobrien		 (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
134190286Sobrien			  (const_int 0))
134290286Sobrien		      (eq (symbol_ref "TARGET_HIMODE_MATH")
134390286Sobrien			  (const_int 0))))
134490286Sobrien	      (const_string "imov")
1345117404Skan	    (and (eq_attr "alternative" "1,2")
134690286Sobrien		 (match_operand:HI 1 "aligned_operand" ""))
134790286Sobrien	      (const_string "imov")
134890286Sobrien	    (and (ne (symbol_ref "TARGET_MOVX")
134990286Sobrien		     (const_int 0))
1350117404Skan		 (eq_attr "alternative" "0,2"))
135190286Sobrien	      (const_string "imovx")
135290286Sobrien	   ]
135390286Sobrien	   (const_string "imov")))
135490286Sobrien    (set (attr "mode")
135590286Sobrien      (cond [(eq_attr "type" "imovx")
135690286Sobrien	       (const_string "SI")
1357117404Skan	     (and (eq_attr "alternative" "1,2")
135890286Sobrien		  (match_operand:HI 1 "aligned_operand" ""))
135990286Sobrien	       (const_string "SI")
1360117404Skan	     (and (eq_attr "alternative" "0")
136190286Sobrien		  (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
136290286Sobrien			   (const_int 0))
136390286Sobrien		       (eq (symbol_ref "TARGET_HIMODE_MATH")
136490286Sobrien			   (const_int 0))))
136590286Sobrien	       (const_string "SI")
136690286Sobrien	    ]
1367117404Skan	    (const_string "HI")))])
136818334Speter
1369132727Skan;; Stores and loads of ax to arbitrary constant address.
137090286Sobrien;; We fake an second form of instruction to force reload to load address
137190286Sobrien;; into register when rax is not available
137290286Sobrien(define_insn "*movabshi_1_rex64"
1373117404Skan  [(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1374117404Skan	(match_operand:HI 1 "nonmemory_operand" "a,er"))]
1375117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
137690286Sobrien  "@
137790286Sobrien   movabs{w}\t{%1, %P0|%P0, %1}
1378117404Skan   mov{w}\t{%1, %a0|%a0, %1}"
137990286Sobrien  [(set_attr "type" "imov")
1380117404Skan   (set_attr "modrm" "0,*")
1381117404Skan   (set_attr "length_address" "8,0")
1382117404Skan   (set_attr "length_immediate" "0,*")
138390286Sobrien   (set_attr "memory" "store")
138490286Sobrien   (set_attr "mode" "HI")])
138518334Speter
138690286Sobrien(define_insn "*movabshi_2_rex64"
138790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a,r")
138890286Sobrien        (mem:HI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1389117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
139090286Sobrien  "@
139190286Sobrien   movabs{w}\t{%P1, %0|%0, %P1}
139290286Sobrien   mov{w}\t{%a1, %0|%0, %a1}"
139390286Sobrien  [(set_attr "type" "imov")
139490286Sobrien   (set_attr "modrm" "0,*")
139590286Sobrien   (set_attr "length_address" "8,0")
139690286Sobrien   (set_attr "length_immediate" "0")
139790286Sobrien   (set_attr "memory" "load")
139890286Sobrien   (set_attr "mode" "HI")])
139918334Speter
140090286Sobrien(define_insn "*swaphi_1"
140190286Sobrien  [(set (match_operand:HI 0 "register_operand" "+r")
140290286Sobrien	(match_operand:HI 1 "register_operand" "+r"))
140390286Sobrien   (set (match_dup 1)
140490286Sobrien	(match_dup 0))]
1405146906Skan  "!TARGET_PARTIAL_REG_STALL || optimize_size"
1406146906Skan  "xchg{l}\t%k1, %k0"
140790286Sobrien  [(set_attr "type" "imov")
1408146906Skan   (set_attr "mode" "SI")
140990286Sobrien   (set_attr "pent_pair" "np")
1410251212Spfg   (set_attr "athlon_decode" "vector")
1411251212Spfg   (set_attr "amdfam10_decode" "double")])   
141218334Speter
1413251212Spfg;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
141490286Sobrien(define_insn "*swaphi_2"
141590286Sobrien  [(set (match_operand:HI 0 "register_operand" "+r")
141690286Sobrien	(match_operand:HI 1 "register_operand" "+r"))
141790286Sobrien   (set (match_dup 1)
141890286Sobrien	(match_dup 0))]
1419146906Skan  "TARGET_PARTIAL_REG_STALL"
1420146906Skan  "xchg{w}\t%1, %0"
142190286Sobrien  [(set_attr "type" "imov")
1422146906Skan   (set_attr "mode" "HI")
142390286Sobrien   (set_attr "pent_pair" "np")
1424169699Skan   (set_attr "athlon_decode" "vector")])
142518334Speter
142618334Speter(define_expand "movstricthi"
142790286Sobrien  [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
142818334Speter	(match_operand:HI 1 "general_operand" ""))]
142990286Sobrien  "! TARGET_PARTIAL_REG_STALL || optimize_size"
143018334Speter{
143118334Speter  /* Don't generate memory->memory moves, go through a register */
143290286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
143390286Sobrien    operands[1] = force_reg (HImode, operands[1]);
143490286Sobrien})
143518334Speter
143690286Sobrien(define_insn "*movstricthi_1"
143790286Sobrien  [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+rm,r"))
143890286Sobrien	(match_operand:HI 1 "general_operand" "rn,m"))]
143990286Sobrien  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
144090286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
144190286Sobrien  "mov{w}\t{%1, %0|%0, %1}"
144290286Sobrien  [(set_attr "type" "imov")
144390286Sobrien   (set_attr "mode" "HI")])
144452296Sobrien
144590286Sobrien(define_insn "*movstricthi_xor"
144690286Sobrien  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
144790286Sobrien	(match_operand:HI 1 "const0_operand" "i"))
1448169699Skan   (clobber (reg:CC FLAGS_REG))]
144990286Sobrien  "reload_completed
145090286Sobrien   && ((!TARGET_USE_MOV0 && !TARGET_PARTIAL_REG_STALL) || optimize_size)"
145190286Sobrien  "xor{w}\t{%0, %0|%0, %0}"
145290286Sobrien  [(set_attr "type" "alu1")
145390286Sobrien   (set_attr "mode" "HI")
145490286Sobrien   (set_attr "length_immediate" "0")])
145552296Sobrien
145690286Sobrien(define_expand "movqi"
145790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
145890286Sobrien	(match_operand:QI 1 "general_operand" ""))]
145990286Sobrien  ""
146090286Sobrien  "ix86_expand_move (QImode, operands); DONE;")
146118334Speter
146290286Sobrien;; emit_push_insn when it calls move_by_pieces requires an insn to
1463169699Skan;; "push a byte".  But actually we use pushl, which has the effect
1464169699Skan;; of rounding the amount pushed up to a word.
146518334Speter
146690286Sobrien(define_insn "*pushqi2"
1467169699Skan  [(set (match_operand:QI 0 "push_operand" "=X")
1468169699Skan	(match_operand:QI 1 "nonmemory_no_elim_operand" "rn"))]
146990286Sobrien  "!TARGET_64BIT"
1470169699Skan  "push{l}\t%k1"
147190286Sobrien  [(set_attr "type" "push")
1472169699Skan   (set_attr "mode" "SI")])
147318334Speter
147490286Sobrien;; For 64BIT abi we always round up to 8 bytes.
147590286Sobrien(define_insn "*pushqi2_rex64"
147690286Sobrien  [(set (match_operand:QI 0 "push_operand" "=X")
1477102802Skan	(match_operand:QI 1 "nonmemory_no_elim_operand" "qi"))]
147890286Sobrien  "TARGET_64BIT"
147990286Sobrien  "push{q}\t%q1"
148090286Sobrien  [(set_attr "type" "push")
1481169699Skan   (set_attr "mode" "DI")])
148290286Sobrien
148390286Sobrien;; Situation is quite tricky about when to choose full sized (SImode) move
148490286Sobrien;; over QImode moves.  For Q_REG -> Q_REG move we use full size only for
148590286Sobrien;; partial register dependency machines (such as AMD Athlon), where QImode
148690286Sobrien;; moves issue extra dependency and for partial register stalls machines
148790286Sobrien;; that don't use QImode patterns (and QImode move cause stall on the next
148890286Sobrien;; instruction).
148990286Sobrien;;
149090286Sobrien;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial
149190286Sobrien;; register stall machines with, where we use QImode instructions, since
149290286Sobrien;; partial register stall can be caused there.  Then we use movzx.
149390286Sobrien(define_insn "*movqi_1"
149490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m")
149590286Sobrien	(match_operand:QI 1 "general_operand"      " q,qn,qm,q,rn,qm,qn"))]
149690286Sobrien  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
149790286Sobrien{
149890286Sobrien  switch (get_attr_type (insn))
149990286Sobrien    {
150090286Sobrien    case TYPE_IMOVX:
1501169699Skan      gcc_assert (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM);
150290286Sobrien      return "movz{bl|x}\t{%1, %k0|%k0, %1}";
150390286Sobrien    default:
150490286Sobrien      if (get_attr_mode (insn) == MODE_SI)
150590286Sobrien        return "mov{l}\t{%k1, %k0|%k0, %k1}";
150690286Sobrien      else
150790286Sobrien        return "mov{b}\t{%1, %0|%0, %1}";
150890286Sobrien    }
150990286Sobrien}
151090286Sobrien  [(set (attr "type")
1511169699Skan     (cond [(and (eq_attr "alternative" "5")
1512169699Skan		 (not (match_operand:QI 1 "aligned_operand" "")))
1513169699Skan	      (const_string "imovx")
1514169699Skan	    (ne (symbol_ref "optimize_size") (const_int 0))
1515169699Skan	      (const_string "imov")
1516169699Skan	    (and (eq_attr "alternative" "3")
151790286Sobrien		 (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
151890286Sobrien			  (const_int 0))
151990286Sobrien		      (eq (symbol_ref "TARGET_QIMODE_MATH")
152090286Sobrien			  (const_int 0))))
152190286Sobrien	      (const_string "imov")
152290286Sobrien	    (eq_attr "alternative" "3,5")
152390286Sobrien	      (const_string "imovx")
152490286Sobrien	    (and (ne (symbol_ref "TARGET_MOVX")
152590286Sobrien		     (const_int 0))
152690286Sobrien		 (eq_attr "alternative" "2"))
152790286Sobrien	      (const_string "imovx")
152890286Sobrien	   ]
152990286Sobrien	   (const_string "imov")))
153090286Sobrien   (set (attr "mode")
153190286Sobrien      (cond [(eq_attr "alternative" "3,4,5")
153290286Sobrien	       (const_string "SI")
153390286Sobrien	     (eq_attr "alternative" "6")
153490286Sobrien	       (const_string "QI")
153590286Sobrien	     (eq_attr "type" "imovx")
153690286Sobrien	       (const_string "SI")
153790286Sobrien	     (and (eq_attr "type" "imov")
1538169699Skan		  (and (eq_attr "alternative" "0,1")
1539169699Skan		       (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
1540169699Skan				(const_int 0))
1541169699Skan			    (and (eq (symbol_ref "optimize_size")
1542169699Skan				     (const_int 0))
1543169699Skan			    	 (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
1544169699Skan				     (const_int 0))))))
154590286Sobrien	       (const_string "SI")
154690286Sobrien	     ;; Avoid partial register stalls when not using QImode arithmetic
154790286Sobrien	     (and (eq_attr "type" "imov")
1548169699Skan		  (and (eq_attr "alternative" "0,1")
154990286Sobrien		       (and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL")
155090286Sobrien				(const_int 0))
155190286Sobrien			    (eq (symbol_ref "TARGET_QIMODE_MATH")
155290286Sobrien				(const_int 0)))))
155390286Sobrien	       (const_string "SI")
155490286Sobrien	   ]
155590286Sobrien	   (const_string "QI")))])
155690286Sobrien
155790286Sobrien(define_expand "reload_outqi"
155890286Sobrien  [(parallel [(match_operand:QI 0 "" "=m")
155990286Sobrien              (match_operand:QI 1 "register_operand" "r")
156090286Sobrien              (match_operand:QI 2 "register_operand" "=&q")])]
156118334Speter  ""
156290286Sobrien{
156390286Sobrien  rtx op0, op1, op2;
156490286Sobrien  op0 = operands[0]; op1 = operands[1]; op2 = operands[2];
156518334Speter
1566169699Skan  gcc_assert (!reg_overlap_mentioned_p (op2, op0));
156790286Sobrien  if (! q_regs_operand (op1, QImode))
156890286Sobrien    {
156990286Sobrien      emit_insn (gen_movqi (op2, op1));
157090286Sobrien      op1 = op2;
157190286Sobrien    }
157290286Sobrien  emit_insn (gen_movqi (op0, op1));
157390286Sobrien  DONE;
157490286Sobrien})
157590286Sobrien
1576146906Skan(define_insn "*swapqi_1"
157790286Sobrien  [(set (match_operand:QI 0 "register_operand" "+r")
157890286Sobrien	(match_operand:QI 1 "register_operand" "+r"))
157990286Sobrien   (set (match_dup 1)
158090286Sobrien	(match_dup 0))]
1581146906Skan  "!TARGET_PARTIAL_REG_STALL || optimize_size"
1582146906Skan  "xchg{l}\t%k1, %k0"
1583146906Skan  [(set_attr "type" "imov")
1584146906Skan   (set_attr "mode" "SI")
1585146906Skan   (set_attr "pent_pair" "np")
1586251212Spfg   (set_attr "athlon_decode" "vector")
1587251212Spfg   (set_attr "amdfam10_decode" "vector")])   
1588146906Skan
1589251212Spfg;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
1590146906Skan(define_insn "*swapqi_2"
1591146906Skan  [(set (match_operand:QI 0 "register_operand" "+q")
1592146906Skan	(match_operand:QI 1 "register_operand" "+q"))
1593146906Skan   (set (match_dup 1)
1594146906Skan	(match_dup 0))]
1595146906Skan  "TARGET_PARTIAL_REG_STALL"
159690286Sobrien  "xchg{b}\t%1, %0"
159790286Sobrien  [(set_attr "type" "imov")
1598146906Skan   (set_attr "mode" "QI")
159990286Sobrien   (set_attr "pent_pair" "np")
1600169699Skan   (set_attr "athlon_decode" "vector")])
160190286Sobrien
160290286Sobrien(define_expand "movstrictqi"
160390286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
160490286Sobrien	(match_operand:QI 1 "general_operand" ""))]
1605117404Skan  "! TARGET_PARTIAL_REG_STALL || optimize_size"
160618334Speter{
160790286Sobrien  /* Don't generate memory->memory moves, go through a register.  */
160890286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
160990286Sobrien    operands[1] = force_reg (QImode, operands[1]);
161090286Sobrien})
161118334Speter
161290286Sobrien(define_insn "*movstrictqi_1"
161390286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
161490286Sobrien	(match_operand:QI 1 "general_operand" "*qn,m"))]
1615117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
161690286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
161790286Sobrien  "mov{b}\t{%1, %0|%0, %1}"
161890286Sobrien  [(set_attr "type" "imov")
161990286Sobrien   (set_attr "mode" "QI")])
162018334Speter
162190286Sobrien(define_insn "*movstrictqi_xor"
162290286Sobrien  [(set (strict_low_part (match_operand:QI 0 "q_regs_operand" "+q"))
162390286Sobrien	(match_operand:QI 1 "const0_operand" "i"))
1624169699Skan   (clobber (reg:CC FLAGS_REG))]
162590286Sobrien  "reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
162690286Sobrien  "xor{b}\t{%0, %0|%0, %0}"
162790286Sobrien  [(set_attr "type" "alu1")
162890286Sobrien   (set_attr "mode" "QI")
162990286Sobrien   (set_attr "length_immediate" "0")])
163018334Speter
163190286Sobrien(define_insn "*movsi_extv_1"
163290286Sobrien  [(set (match_operand:SI 0 "register_operand" "=R")
163390286Sobrien	(sign_extract:SI (match_operand 1 "ext_register_operand" "Q")
163490286Sobrien			 (const_int 8)
163590286Sobrien			 (const_int 8)))]
163618334Speter  ""
163790286Sobrien  "movs{bl|x}\t{%h1, %0|%0, %h1}"
163890286Sobrien  [(set_attr "type" "imovx")
163990286Sobrien   (set_attr "mode" "SI")])
164090286Sobrien
164190286Sobrien(define_insn "*movhi_extv_1"
164290286Sobrien  [(set (match_operand:HI 0 "register_operand" "=R")
164390286Sobrien	(sign_extract:HI (match_operand 1 "ext_register_operand" "Q")
164490286Sobrien			 (const_int 8)
164590286Sobrien			 (const_int 8)))]
164690286Sobrien  ""
164790286Sobrien  "movs{bl|x}\t{%h1, %k0|%k0, %h1}"
164890286Sobrien  [(set_attr "type" "imovx")
164990286Sobrien   (set_attr "mode" "SI")])
165090286Sobrien
165190286Sobrien(define_insn "*movqi_extv_1"
165290286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?r")
165390286Sobrien        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
165490286Sobrien                         (const_int 8)
165590286Sobrien                         (const_int 8)))]
165690286Sobrien  "!TARGET_64BIT"
165718334Speter{
165890286Sobrien  switch (get_attr_type (insn))
165918334Speter    {
166090286Sobrien    case TYPE_IMOVX:
166190286Sobrien      return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
166290286Sobrien    default:
166390286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
166418334Speter    }
166590286Sobrien}
166690286Sobrien  [(set (attr "type")
166790286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
166890286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
166990286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
167090286Sobrien				 (const_int 0))))
167190286Sobrien	(const_string "imovx")
167290286Sobrien	(const_string "imov")))
167390286Sobrien   (set (attr "mode")
167490286Sobrien     (if_then_else (eq_attr "type" "imovx")
167590286Sobrien	(const_string "SI")
167690286Sobrien	(const_string "QI")))])
167718334Speter
167890286Sobrien(define_insn "*movqi_extv_1_rex64"
167990286Sobrien  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
168090286Sobrien        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
168190286Sobrien                         (const_int 8)
168290286Sobrien                         (const_int 8)))]
168390286Sobrien  "TARGET_64BIT"
168418334Speter{
168590286Sobrien  switch (get_attr_type (insn))
168650650Sobrien    {
168790286Sobrien    case TYPE_IMOVX:
168890286Sobrien      return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
168990286Sobrien    default:
169090286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
169150650Sobrien    }
169290286Sobrien}
169390286Sobrien  [(set (attr "type")
169490286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
169590286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
169690286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
169790286Sobrien				 (const_int 0))))
169890286Sobrien	(const_string "imovx")
169990286Sobrien	(const_string "imov")))
170090286Sobrien   (set (attr "mode")
170190286Sobrien     (if_then_else (eq_attr "type" "imovx")
170290286Sobrien	(const_string "SI")
170390286Sobrien	(const_string "QI")))])
170418334Speter
1705132727Skan;; Stores and loads of ax to arbitrary constant address.
170690286Sobrien;; We fake an second form of instruction to force reload to load address
170790286Sobrien;; into register when rax is not available
170890286Sobrien(define_insn "*movabsqi_1_rex64"
1709117404Skan  [(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1710117404Skan	(match_operand:QI 1 "nonmemory_operand" "a,er"))]
1711117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
171290286Sobrien  "@
171390286Sobrien   movabs{b}\t{%1, %P0|%P0, %1}
1714117404Skan   mov{b}\t{%1, %a0|%a0, %1}"
171590286Sobrien  [(set_attr "type" "imov")
1716117404Skan   (set_attr "modrm" "0,*")
1717117404Skan   (set_attr "length_address" "8,0")
1718117404Skan   (set_attr "length_immediate" "0,*")
171990286Sobrien   (set_attr "memory" "store")
172090286Sobrien   (set_attr "mode" "QI")])
172118334Speter
172290286Sobrien(define_insn "*movabsqi_2_rex64"
172390286Sobrien  [(set (match_operand:QI 0 "register_operand" "=a,r")
172490286Sobrien        (mem:QI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1725117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
172690286Sobrien  "@
172790286Sobrien   movabs{b}\t{%P1, %0|%0, %P1}
172890286Sobrien   mov{b}\t{%a1, %0|%0, %a1}"
172990286Sobrien  [(set_attr "type" "imov")
173090286Sobrien   (set_attr "modrm" "0,*")
173190286Sobrien   (set_attr "length_address" "8,0")
173290286Sobrien   (set_attr "length_immediate" "0")
173390286Sobrien   (set_attr "memory" "load")
173490286Sobrien   (set_attr "mode" "QI")])
173518334Speter
1736169699Skan(define_insn "*movdi_extzv_1"
1737169699Skan  [(set (match_operand:DI 0 "register_operand" "=R")
1738169699Skan	(zero_extract:DI (match_operand 1 "ext_register_operand" "Q")
1739169699Skan			 (const_int 8)
1740169699Skan			 (const_int 8)))]
1741169699Skan  "TARGET_64BIT"
1742169699Skan  "movz{bl|x}\t{%h1, %k0|%k0, %h1}"
1743169699Skan  [(set_attr "type" "imovx")
1744169699Skan   (set_attr "mode" "DI")])
1745169699Skan
174690286Sobrien(define_insn "*movsi_extzv_1"
174790286Sobrien  [(set (match_operand:SI 0 "register_operand" "=R")
174890286Sobrien	(zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
174990286Sobrien			 (const_int 8)
175090286Sobrien			 (const_int 8)))]
175190286Sobrien  ""
175290286Sobrien  "movz{bl|x}\t{%h1, %0|%0, %h1}"
175390286Sobrien  [(set_attr "type" "imovx")
175490286Sobrien   (set_attr "mode" "SI")])
175518334Speter
175690286Sobrien(define_insn "*movqi_extzv_2"
175790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?R")
175890286Sobrien        (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
175990286Sobrien				    (const_int 8)
176090286Sobrien				    (const_int 8)) 0))]
176190286Sobrien  "!TARGET_64BIT"
176218334Speter{
176390286Sobrien  switch (get_attr_type (insn))
176418334Speter    {
176590286Sobrien    case TYPE_IMOVX:
176690286Sobrien      return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
176790286Sobrien    default:
176890286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
176918334Speter    }
177090286Sobrien}
177190286Sobrien  [(set (attr "type")
177290286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
177390286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
177490286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
177590286Sobrien				 (const_int 0))))
177690286Sobrien	(const_string "imovx")
177790286Sobrien	(const_string "imov")))
177890286Sobrien   (set (attr "mode")
177990286Sobrien     (if_then_else (eq_attr "type" "imovx")
178090286Sobrien	(const_string "SI")
178190286Sobrien	(const_string "QI")))])
178218334Speter
178390286Sobrien(define_insn "*movqi_extzv_2_rex64"
178490286Sobrien  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
178590286Sobrien        (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
178690286Sobrien				    (const_int 8)
178790286Sobrien				    (const_int 8)) 0))]
178890286Sobrien  "TARGET_64BIT"
178918334Speter{
179090286Sobrien  switch (get_attr_type (insn))
179190286Sobrien    {
179290286Sobrien    case TYPE_IMOVX:
179390286Sobrien      return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
179490286Sobrien    default:
179590286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
179690286Sobrien    }
179790286Sobrien}
179890286Sobrien  [(set (attr "type")
179990286Sobrien     (if_then_else (ior (not (match_operand:QI 0 "q_regs_operand" ""))
180090286Sobrien			(ne (symbol_ref "TARGET_MOVX")
180190286Sobrien			    (const_int 0)))
180290286Sobrien	(const_string "imovx")
180390286Sobrien	(const_string "imov")))
180490286Sobrien   (set (attr "mode")
180590286Sobrien     (if_then_else (eq_attr "type" "imovx")
180690286Sobrien	(const_string "SI")
180790286Sobrien	(const_string "QI")))])
180818334Speter
180990286Sobrien(define_insn "movsi_insv_1"
181090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
181190286Sobrien			 (const_int 8)
181290286Sobrien			 (const_int 8))
181390286Sobrien	(match_operand:SI 1 "general_operand" "Qmn"))]
181490286Sobrien  "!TARGET_64BIT"
181590286Sobrien  "mov{b}\t{%b1, %h0|%h0, %b1}"
181690286Sobrien  [(set_attr "type" "imov")
181790286Sobrien   (set_attr "mode" "QI")])
181852296Sobrien
1819132727Skan(define_insn "movdi_insv_1_rex64"
1820132727Skan  [(set (zero_extract:DI (match_operand 0 "ext_register_operand" "+Q")
182190286Sobrien			 (const_int 8)
182290286Sobrien			 (const_int 8))
1823132727Skan	(match_operand:DI 1 "nonmemory_operand" "Qn"))]
182490286Sobrien  "TARGET_64BIT"
182590286Sobrien  "mov{b}\t{%b1, %h0|%h0, %b1}"
182690286Sobrien  [(set_attr "type" "imov")
182790286Sobrien   (set_attr "mode" "QI")])
182818334Speter
182990286Sobrien(define_insn "*movqi_insv_2"
183090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
183190286Sobrien			 (const_int 8)
183290286Sobrien			 (const_int 8))
1833132727Skan	(lshiftrt:SI (match_operand:SI 1 "register_operand" "Q")
1834132727Skan		     (const_int 8)))]
183590286Sobrien  ""
183690286Sobrien  "mov{b}\t{%h1, %h0|%h0, %h1}"
183790286Sobrien  [(set_attr "type" "imov")
183890286Sobrien   (set_attr "mode" "QI")])
183918334Speter
184090286Sobrien(define_expand "movdi"
184190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
184290286Sobrien	(match_operand:DI 1 "general_operand" ""))]
184390286Sobrien  ""
184490286Sobrien  "ix86_expand_move (DImode, operands); DONE;")
184518334Speter
184690286Sobrien(define_insn "*pushdi"
184790286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
184890286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "riF*m"))]
184990286Sobrien  "!TARGET_64BIT"
185090286Sobrien  "#")
185190286Sobrien
1852169699Skan(define_insn "*pushdi2_rex64"
185390286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<,!<")
185490286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "re*m,n"))]
185590286Sobrien  "TARGET_64BIT"
185690286Sobrien  "@
185790286Sobrien   push{q}\t%1
185890286Sobrien   #"
185990286Sobrien  [(set_attr "type" "push,multi")
186090286Sobrien   (set_attr "mode" "DI")])
186190286Sobrien
186290286Sobrien;; Convert impossible pushes of immediate to existing instructions.
186390286Sobrien;; First try to get scratch register and go through it.  In case this
186490286Sobrien;; fails, push sign extended lower part first and then overwrite
186590286Sobrien;; upper part by 32bit move.
186690286Sobrien(define_peephole2
186790286Sobrien  [(match_scratch:DI 2 "r")
186890286Sobrien   (set (match_operand:DI 0 "push_operand" "")
186990286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
187090286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
187190286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
187290286Sobrien  [(set (match_dup 2) (match_dup 1))
187390286Sobrien   (set (match_dup 0) (match_dup 2))]
187490286Sobrien  "")
187590286Sobrien
187690286Sobrien;; We need to define this as both peepholer and splitter for case
187790286Sobrien;; peephole2 pass is not run.
1878169699Skan;; "&& 1" is needed to keep it from matching the previous pattern.
187990286Sobrien(define_peephole2
188090286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
188190286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
188290286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
188390286Sobrien   && !x86_64_immediate_operand (operands[1], DImode) && 1"
188490286Sobrien  [(set (match_dup 0) (match_dup 1))
188590286Sobrien   (set (match_dup 2) (match_dup 3))]
188690286Sobrien  "split_di (operands + 1, 1, operands + 2, operands + 3);
188790286Sobrien   operands[1] = gen_lowpart (DImode, operands[2]);
188890286Sobrien   operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
188990286Sobrien						    GEN_INT (4)));
189090286Sobrien  ")
189190286Sobrien
189290286Sobrien(define_split
189390286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
189490286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
1895161660Skan  "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
1896169699Skan		    ? flow2_completed : reload_completed)
189790286Sobrien   && !symbolic_operand (operands[1], DImode)
189890286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
189990286Sobrien  [(set (match_dup 0) (match_dup 1))
190090286Sobrien   (set (match_dup 2) (match_dup 3))]
190190286Sobrien  "split_di (operands + 1, 1, operands + 2, operands + 3);
190290286Sobrien   operands[1] = gen_lowpart (DImode, operands[2]);
190390286Sobrien   operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
190490286Sobrien						    GEN_INT (4)));
190590286Sobrien  ")
190690286Sobrien
190790286Sobrien(define_insn "*pushdi2_prologue_rex64"
190890286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
190990286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "re*m"))
191090286Sobrien   (clobber (mem:BLK (scratch)))]
191190286Sobrien  "TARGET_64BIT"
191290286Sobrien  "push{q}\t%1"
191390286Sobrien  [(set_attr "type" "push")
191490286Sobrien   (set_attr "mode" "DI")])
191590286Sobrien
191690286Sobrien(define_insn "*popdi1_epilogue_rex64"
191790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
1918169699Skan	(mem:DI (reg:DI SP_REG)))
1919169699Skan   (set (reg:DI SP_REG)
1920169699Skan	(plus:DI (reg:DI SP_REG) (const_int 8)))
192190286Sobrien   (clobber (mem:BLK (scratch)))]
192290286Sobrien  "TARGET_64BIT"
192390286Sobrien  "pop{q}\t%0"
192490286Sobrien  [(set_attr "type" "pop")
192590286Sobrien   (set_attr "mode" "DI")])
192690286Sobrien
192790286Sobrien(define_insn "popdi1"
192890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
1929169699Skan	(mem:DI (reg:DI SP_REG)))
1930169699Skan   (set (reg:DI SP_REG)
1931169699Skan	(plus:DI (reg:DI SP_REG) (const_int 8)))]
193290286Sobrien  "TARGET_64BIT"
193390286Sobrien  "pop{q}\t%0"
193490286Sobrien  [(set_attr "type" "pop")
193590286Sobrien   (set_attr "mode" "DI")])
193690286Sobrien
193790286Sobrien(define_insn "*movdi_xor_rex64"
193890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
193990286Sobrien	(match_operand:DI 1 "const0_operand" "i"))
1940169699Skan   (clobber (reg:CC FLAGS_REG))]
194190286Sobrien  "TARGET_64BIT && (!TARGET_USE_MOV0 || optimize_size)
194290286Sobrien   && reload_completed"
194390286Sobrien  "xor{l}\t{%k0, %k0|%k0, %k0}"
194490286Sobrien  [(set_attr "type" "alu1")
194590286Sobrien   (set_attr "mode" "SI")
194690286Sobrien   (set_attr "length_immediate" "0")])
194790286Sobrien
194890286Sobrien(define_insn "*movdi_or_rex64"
194990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
195090286Sobrien	(match_operand:DI 1 "const_int_operand" "i"))
1951169699Skan   (clobber (reg:CC FLAGS_REG))]
195290286Sobrien  "TARGET_64BIT && (TARGET_PENTIUM || optimize_size)
195390286Sobrien   && reload_completed
1954132727Skan   && operands[1] == constm1_rtx"
195518334Speter{
195690286Sobrien  operands[1] = constm1_rtx;
195790286Sobrien  return "or{q}\t{%1, %0|%0, %1}";
195890286Sobrien}
195990286Sobrien  [(set_attr "type" "alu1")
196090286Sobrien   (set_attr "mode" "DI")
196190286Sobrien   (set_attr "length_immediate" "1")])
196218334Speter
196390286Sobrien(define_insn "*movdi_2"
1964169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand"
1965169699Skan				"=r  ,o  ,*y,m*y,*y,*Y,m ,*Y,*Y,*x,m ,*x,*x")
1966169699Skan	(match_operand:DI 1 "general_operand"
1967169699Skan				"riFo,riF,C ,*y ,m ,C ,*Y,*Y,m ,C ,*x,*x,m "))]
1968169699Skan  "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
196990286Sobrien  "@
197090286Sobrien   #
197190286Sobrien   #
1972169699Skan   pxor\t%0, %0
197390286Sobrien   movq\t{%1, %0|%0, %1}
197490286Sobrien   movq\t{%1, %0|%0, %1}
1975169699Skan   pxor\t%0, %0
197690286Sobrien   movq\t{%1, %0|%0, %1}
197790286Sobrien   movdqa\t{%1, %0|%0, %1}
1978169699Skan   movq\t{%1, %0|%0, %1}
1979169699Skan   xorps\t%0, %0
1980169699Skan   movlps\t{%1, %0|%0, %1}
1981169699Skan   movaps\t{%1, %0|%0, %1}
1982169699Skan   movlps\t{%1, %0|%0, %1}"
1983169699Skan  [(set_attr "type" "*,*,mmx,mmxmov,mmxmov,sselog1,ssemov,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov")
1984169699Skan   (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,TI,DI,V4SF,V2SF,V4SF,V2SF")])
198518334Speter
198690286Sobrien(define_split
198790286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
198890286Sobrien        (match_operand:DI 1 "general_operand" ""))]
198990286Sobrien  "!TARGET_64BIT && reload_completed
199090286Sobrien   && (! MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
199190286Sobrien  [(const_int 0)]
199290286Sobrien  "ix86_split_long_move (operands); DONE;")
199318334Speter
199490286Sobrien;; %%% This multiword shite has got to go.
199590286Sobrien(define_split
199690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
199790286Sobrien        (match_operand:DI 1 "general_operand" ""))]
199890286Sobrien  "!TARGET_64BIT && reload_completed
199990286Sobrien   && (!MMX_REG_P (operands[0]) && !SSE_REG_P (operands[0]))
200090286Sobrien   && (!MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
200190286Sobrien  [(const_int 0)]
200290286Sobrien  "ix86_split_long_move (operands); DONE;")
200318334Speter
200490286Sobrien(define_insn "*movdi_1_rex64"
2005169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand"
2006169699Skan		"=r,r  ,r,m ,!m,*y,*y,?rm,?*y,*x,*x,?rm,?*x,?*x,?*y")
2007169699Skan	(match_operand:DI 1 "general_operand"
2008169699Skan		"Z ,rem,i,re,n ,C ,*y,*y ,rm ,C ,*x,*x ,rm ,*y ,*x"))]
2009169699Skan  "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
201090286Sobrien{
201190286Sobrien  switch (get_attr_type (insn))
201290286Sobrien    {
2013169699Skan    case TYPE_SSECVT:
2014169699Skan      if (which_alternative == 13)
2015169699Skan	return "movq2dq\t{%1, %0|%0, %1}";
2016169699Skan      else
2017169699Skan	return "movdq2q\t{%1, %0|%0, %1}";
2018117404Skan    case TYPE_SSEMOV:
2019132727Skan      if (get_attr_mode (insn) == MODE_TI)
202090286Sobrien	  return "movdqa\t{%1, %0|%0, %1}";
202190286Sobrien      /* FALLTHRU */
2022117404Skan    case TYPE_MMXMOV:
2023132727Skan      /* Moves from and into integer register is done using movd opcode with
2024132727Skan 	 REX prefix.  */
2025132727Skan      if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
2026132727Skan	  return "movd\t{%1, %0|%0, %1}";
202790286Sobrien      return "movq\t{%1, %0|%0, %1}";
2028169699Skan    case TYPE_SSELOG1:
2029169699Skan    case TYPE_MMXADD:
2030169699Skan      return "pxor\t%0, %0";
203190286Sobrien    case TYPE_MULTI:
203290286Sobrien      return "#";
203390286Sobrien    case TYPE_LEA:
203490286Sobrien      return "lea{q}\t{%a1, %0|%0, %a1}";
203590286Sobrien    default:
2036169699Skan      gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
203790286Sobrien      if (get_attr_mode (insn) == MODE_SI)
203890286Sobrien	return "mov{l}\t{%k1, %k0|%k0, %k1}";
203990286Sobrien      else if (which_alternative == 2)
204090286Sobrien	return "movabs{q}\t{%1, %0|%0, %1}";
204118334Speter      else
204290286Sobrien	return "mov{q}\t{%1, %0|%0, %1}";
204318334Speter    }
204490286Sobrien}
204590286Sobrien  [(set (attr "type")
2046169699Skan     (cond [(eq_attr "alternative" "5")
2047169699Skan	      (const_string "mmxadd")
2048169699Skan	    (eq_attr "alternative" "6,7,8")
2049117404Skan	      (const_string "mmxmov")
2050169699Skan	    (eq_attr "alternative" "9")
2051169699Skan	      (const_string "sselog1")
2052169699Skan	    (eq_attr "alternative" "10,11,12")
2053117404Skan	      (const_string "ssemov")
2054169699Skan	    (eq_attr "alternative" "13,14")
2055169699Skan	      (const_string "ssecvt")
205690286Sobrien	    (eq_attr "alternative" "4")
205790286Sobrien	      (const_string "multi")
2058169699Skan 	    (match_operand:DI 1 "pic_32bit_operand" "")
205990286Sobrien	      (const_string "lea")
206090286Sobrien	   ]
206190286Sobrien	   (const_string "imov")))
2062169699Skan   (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*")
2063169699Skan   (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*")
2064169699Skan   (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI")])
206550650Sobrien
2066132727Skan;; Stores and loads of ax to arbitrary constant address.
206790286Sobrien;; We fake an second form of instruction to force reload to load address
206890286Sobrien;; into register when rax is not available
206990286Sobrien(define_insn "*movabsdi_1_rex64"
2070102802Skan  [(set (mem:DI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
2071102802Skan	(match_operand:DI 1 "nonmemory_operand" "a,er"))]
2072117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
207390286Sobrien  "@
207490286Sobrien   movabs{q}\t{%1, %P0|%P0, %1}
2075102802Skan   mov{q}\t{%1, %a0|%a0, %1}"
207690286Sobrien  [(set_attr "type" "imov")
2077102802Skan   (set_attr "modrm" "0,*")
2078102802Skan   (set_attr "length_address" "8,0")
2079102802Skan   (set_attr "length_immediate" "0,*")
208090286Sobrien   (set_attr "memory" "store")
208190286Sobrien   (set_attr "mode" "DI")])
208218334Speter
208390286Sobrien(define_insn "*movabsdi_2_rex64"
208490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a,r")
208590286Sobrien        (mem:DI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
2086117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
208790286Sobrien  "@
208890286Sobrien   movabs{q}\t{%P1, %0|%0, %P1}
208990286Sobrien   mov{q}\t{%a1, %0|%0, %a1}"
209090286Sobrien  [(set_attr "type" "imov")
209190286Sobrien   (set_attr "modrm" "0,*")
209290286Sobrien   (set_attr "length_address" "8,0")
209390286Sobrien   (set_attr "length_immediate" "0")
209490286Sobrien   (set_attr "memory" "load")
209590286Sobrien   (set_attr "mode" "DI")])
209690286Sobrien
209790286Sobrien;; Convert impossible stores of immediate to existing instructions.
209890286Sobrien;; First try to get scratch register and go through it.  In case this
209990286Sobrien;; fails, move by 32bit parts.
210090286Sobrien(define_peephole2
210190286Sobrien  [(match_scratch:DI 2 "r")
210290286Sobrien   (set (match_operand:DI 0 "memory_operand" "")
210390286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
210490286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
210590286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
210690286Sobrien  [(set (match_dup 2) (match_dup 1))
210790286Sobrien   (set (match_dup 0) (match_dup 2))]
210852296Sobrien  "")
210950650Sobrien
211090286Sobrien;; We need to define this as both peepholer and splitter for case
211190286Sobrien;; peephole2 pass is not run.
2112169699Skan;; "&& 1" is needed to keep it from matching the previous pattern.
211390286Sobrien(define_peephole2
211490286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
211590286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
211690286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
211790286Sobrien   && !x86_64_immediate_operand (operands[1], DImode) && 1"
211890286Sobrien  [(set (match_dup 2) (match_dup 3))
211990286Sobrien   (set (match_dup 4) (match_dup 5))]
212090286Sobrien  "split_di (operands, 2, operands + 2, operands + 4);")
212190286Sobrien
212290286Sobrien(define_split
212390286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
212490286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
2125161660Skan  "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
2126169699Skan		    ? flow2_completed : reload_completed)
212790286Sobrien   && !symbolic_operand (operands[1], DImode)
212890286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
212990286Sobrien  [(set (match_dup 2) (match_dup 3))
213090286Sobrien   (set (match_dup 4) (match_dup 5))]
213190286Sobrien  "split_di (operands, 2, operands + 2, operands + 4);")
213290286Sobrien
213390286Sobrien(define_insn "*swapdi_rex64"
213490286Sobrien  [(set (match_operand:DI 0 "register_operand" "+r")
213590286Sobrien	(match_operand:DI 1 "register_operand" "+r"))
213690286Sobrien   (set (match_dup 1)
213790286Sobrien	(match_dup 0))]
213890286Sobrien  "TARGET_64BIT"
213990286Sobrien  "xchg{q}\t%1, %0"
214090286Sobrien  [(set_attr "type" "imov")
2141146906Skan   (set_attr "mode" "DI")
214290286Sobrien   (set_attr "pent_pair" "np")
2143251212Spfg   (set_attr "athlon_decode" "vector")
2144251212Spfg   (set_attr "amdfam10_decode" "double")])   
214590286Sobrien
2146169699Skan(define_expand "movti"
2147169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
2148169699Skan	(match_operand:TI 1 "nonimmediate_operand" ""))]
2149169699Skan  "TARGET_SSE || TARGET_64BIT"
2150169699Skan{
2151169699Skan  if (TARGET_64BIT)
2152169699Skan    ix86_expand_move (TImode, operands);
2153169699Skan  else
2154169699Skan    ix86_expand_vector_move (TImode, operands);
2155169699Skan  DONE;
2156169699Skan})
2157169699Skan
2158169699Skan(define_insn "*movti_internal"
2159169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m")
2160169699Skan	(match_operand:TI 1 "vector_move_operand" "C,xm,x"))]
2161169699Skan  "TARGET_SSE && !TARGET_64BIT
2162169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2163169699Skan{
2164169699Skan  switch (which_alternative)
2165169699Skan    {
2166169699Skan    case 0:
2167169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2168169699Skan	return "xorps\t%0, %0";
2169169699Skan      else
2170169699Skan	return "pxor\t%0, %0";
2171169699Skan    case 1:
2172169699Skan    case 2:
2173169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2174169699Skan	return "movaps\t{%1, %0|%0, %1}";
2175169699Skan      else
2176169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2177169699Skan    default:
2178169699Skan      gcc_unreachable ();
2179169699Skan    }
2180169699Skan}
2181169699Skan  [(set_attr "type" "sselog1,ssemov,ssemov")
2182169699Skan   (set (attr "mode")
2183169699Skan	(cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2184169699Skan		    (ne (symbol_ref "optimize_size") (const_int 0)))
2185169699Skan		 (const_string "V4SF")
2186169699Skan	       (and (eq_attr "alternative" "2")
2187169699Skan		    (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2188169699Skan			(const_int 0)))
2189169699Skan		 (const_string "V4SF")]
2190169699Skan	      (const_string "TI")))])
2191169699Skan
2192169699Skan(define_insn "*movti_rex64"
2193169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,x,xm")
2194169699Skan	(match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))]
2195169699Skan  "TARGET_64BIT
2196169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2197169699Skan{
2198169699Skan  switch (which_alternative)
2199169699Skan    {
2200169699Skan    case 0:
2201169699Skan    case 1:
2202169699Skan      return "#";
2203169699Skan    case 2:
2204169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2205169699Skan	return "xorps\t%0, %0";
2206169699Skan      else
2207169699Skan	return "pxor\t%0, %0";
2208169699Skan    case 3:
2209169699Skan    case 4:
2210169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2211169699Skan	return "movaps\t{%1, %0|%0, %1}";
2212169699Skan      else
2213169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2214169699Skan    default:
2215169699Skan      gcc_unreachable ();
2216169699Skan    }
2217169699Skan}
2218169699Skan  [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
2219169699Skan   (set (attr "mode")
2220169699Skan        (cond [(eq_attr "alternative" "2,3")
2221169699Skan		 (if_then_else
2222169699Skan		   (ne (symbol_ref "optimize_size")
2223169699Skan		       (const_int 0))
2224169699Skan		   (const_string "V4SF")
2225169699Skan		   (const_string "TI"))
2226169699Skan	       (eq_attr "alternative" "4")
2227169699Skan		 (if_then_else
2228169699Skan		   (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2229169699Skan			    (const_int 0))
2230169699Skan			(ne (symbol_ref "optimize_size")
2231169699Skan			    (const_int 0)))
2232169699Skan		   (const_string "V4SF")
2233169699Skan		   (const_string "TI"))]
2234169699Skan	       (const_string "DI")))])
2235169699Skan
2236169699Skan(define_split
2237169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
2238169699Skan        (match_operand:TI 1 "general_operand" ""))]
2239169699Skan  "reload_completed && !SSE_REG_P (operands[0])
2240169699Skan   && !SSE_REG_P (operands[1])"
2241169699Skan  [(const_int 0)]
2242169699Skan  "ix86_split_long_move (operands); DONE;")
2243169699Skan
224450650Sobrien(define_expand "movsf"
224590286Sobrien  [(set (match_operand:SF 0 "nonimmediate_operand" "")
224650650Sobrien	(match_operand:SF 1 "general_operand" ""))]
224718334Speter  ""
224890286Sobrien  "ix86_expand_move (SFmode, operands); DONE;")
224990286Sobrien
225090286Sobrien(define_insn "*pushsf"
225190286Sobrien  [(set (match_operand:SF 0 "push_operand" "=<,<,<")
2252169699Skan	(match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
225390286Sobrien  "!TARGET_64BIT"
225418334Speter{
2255169699Skan  /* Anything else should be already split before reg-stack.  */
2256169699Skan  gcc_assert (which_alternative == 1);
2257169699Skan  return "push{l}\t%1";
225890286Sobrien}
225990286Sobrien  [(set_attr "type" "multi,push,multi")
2260169699Skan   (set_attr "unit" "i387,*,*")
226190286Sobrien   (set_attr "mode" "SF,SI,SF")])
226218334Speter
226390286Sobrien(define_insn "*pushsf_rex64"
226490286Sobrien  [(set (match_operand:SF 0 "push_operand" "=X,X,X")
2265169699Skan	(match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
226690286Sobrien  "TARGET_64BIT"
226718334Speter{
2268169699Skan  /* Anything else should be already split before reg-stack.  */
2269169699Skan  gcc_assert (which_alternative == 1);
2270169699Skan  return "push{q}\t%q1";
227190286Sobrien}
227290286Sobrien  [(set_attr "type" "multi,push,multi")
2273169699Skan   (set_attr "unit" "i387,*,*")
227490286Sobrien   (set_attr "mode" "SF,DI,SF")])
227518334Speter
227690286Sobrien(define_split
227790286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
227890286Sobrien	(match_operand:SF 1 "memory_operand" ""))]
227990286Sobrien  "reload_completed
228090286Sobrien   && GET_CODE (operands[1]) == MEM
2281161660Skan   && constant_pool_reference_p (operands[1])"
228290286Sobrien  [(set (match_dup 0)
228390286Sobrien	(match_dup 1))]
2284161660Skan  "operands[1] = avoid_constant_pool_reference (operands[1]);")
228518334Speter
228690286Sobrien
228790286Sobrien;; %%% Kill this when call knows how to work this out.
228890286Sobrien(define_split
228990286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
2290117404Skan	(match_operand:SF 1 "any_fp_register_operand" ""))]
2291117404Skan  "!TARGET_64BIT"
2292169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
2293169699Skan   (set (mem:SF (reg:SI SP_REG)) (match_dup 1))])
229490286Sobrien
229590286Sobrien(define_split
229690286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
2297117404Skan	(match_operand:SF 1 "any_fp_register_operand" ""))]
2298117404Skan  "TARGET_64BIT"
2299169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
2300169699Skan   (set (mem:SF (reg:DI SP_REG)) (match_dup 1))])
230190286Sobrien
230290286Sobrien(define_insn "*movsf_1"
2303169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"
2304169699Skan	  "=f,m   ,f,r  ,m    ,x,x,x ,m   ,!*y,!rm,!*y")
2305169699Skan	(match_operand:SF 1 "general_operand"
2306169699Skan	  "fm,f,G   ,rmF,Fr,C   ,x   ,xm,x,rm ,*y ,*y"))]
2307169699Skan  "!(MEM_P (operands[0]) && MEM_P (operands[1]))
230890286Sobrien   && (reload_in_progress || reload_completed
230990286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
231090286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
2311259563Spfg       || memory_operand (operands[0], SFmode))"
231290286Sobrien{
231390286Sobrien  switch (which_alternative)
231418334Speter    {
231590286Sobrien    case 0:
2316169699Skan      return output_387_reg_move (insn, operands);
231718334Speter
231890286Sobrien    case 1:
231990286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
232090286Sobrien        return "fstp%z0\t%y0";
232190286Sobrien      else
232290286Sobrien        return "fst%z0\t%y0";
232318334Speter
232490286Sobrien    case 2:
2325132727Skan      return standard_80387_constant_opcode (operands[1]);
2326132727Skan
2327132727Skan    case 3:
2328132727Skan    case 4:
2329132727Skan      return "mov{l}\t{%1, %0|%0, %1}";
2330132727Skan    case 5:
2331132727Skan      if (get_attr_mode (insn) == MODE_TI)
2332132727Skan	return "pxor\t%0, %0";
2333132727Skan      else
2334132727Skan	return "xorps\t%0, %0";
2335132727Skan    case 6:
2336132727Skan      if (get_attr_mode (insn) == MODE_V4SF)
2337132727Skan	return "movaps\t{%1, %0|%0, %1}";
2338132727Skan      else
2339132727Skan	return "movss\t{%1, %0|%0, %1}";
2340132727Skan    case 7:
2341132727Skan    case 8:
2342132727Skan      return "movss\t{%1, %0|%0, %1}";
2343132727Skan
2344132727Skan    case 9:
2345132727Skan    case 10:
2346132727Skan      return "movd\t{%1, %0|%0, %1}";
2347132727Skan
2348132727Skan    case 11:
2349132727Skan      return "movq\t{%1, %0|%0, %1}";
2350132727Skan
2351132727Skan    default:
2352169699Skan      gcc_unreachable ();
2353132727Skan    }
2354132727Skan}
2355169699Skan  [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov")
2356132727Skan   (set (attr "mode")
2357132727Skan        (cond [(eq_attr "alternative" "3,4,9,10")
2358132727Skan		 (const_string "SI")
2359132727Skan	       (eq_attr "alternative" "5")
2360132727Skan		 (if_then_else
2361132727Skan		   (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2362132727Skan			    	 (const_int 0))
2363132727Skan			     (ne (symbol_ref "TARGET_SSE2")
2364132727Skan				 (const_int 0)))
2365132727Skan			(eq (symbol_ref "optimize_size")
2366132727Skan			    (const_int 0)))
2367132727Skan		   (const_string "TI")
2368132727Skan		   (const_string "V4SF"))
2369132727Skan	       /* For architectures resolving dependencies on
2370132727Skan		  whole SSE registers use APS move to break dependency
2371259563Spfg		  chains, otherwise use short move to avoid extra work.
237218334Speter
2373132727Skan		  Do the same for architectures resolving dependencies on
2374132727Skan		  the parts.  While in DF mode it is better to always handle
2375132727Skan		  just register parts, the SF mode is different due to lack
2376132727Skan		  of instructions to load just part of the register.  It is
2377132727Skan		  better to maintain the whole registers in single format
2378132727Skan		  to avoid problems on using packed logical operations.  */
2379132727Skan	       (eq_attr "alternative" "6")
2380132727Skan		 (if_then_else
2381132727Skan		   (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2382132727Skan			    (const_int 0))
2383169699Skan			(ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2384132727Skan			    (const_int 0)))
2385132727Skan		   (const_string "V4SF")
2386132727Skan		   (const_string "SF"))
2387132727Skan	       (eq_attr "alternative" "11")
2388132727Skan		 (const_string "DI")]
2389132727Skan	       (const_string "SF")))])
2390132727Skan
239190286Sobrien(define_insn "*swapsf"
2392169699Skan  [(set (match_operand:SF 0 "fp_register_operand" "+f")
2393169699Skan	(match_operand:SF 1 "fp_register_operand" "+f"))
239418334Speter   (set (match_dup 1)
239518334Speter	(match_dup 0))]
2396169699Skan  "reload_completed || TARGET_80387"
239718334Speter{
239818334Speter  if (STACK_TOP_P (operands[0]))
239990286Sobrien    return "fxch\t%1";
240018334Speter  else
240190286Sobrien    return "fxch\t%0";
240290286Sobrien}
240390286Sobrien  [(set_attr "type" "fxch")
240490286Sobrien   (set_attr "mode" "SF")])
240518334Speter
240690286Sobrien(define_expand "movdf"
240790286Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
240890286Sobrien	(match_operand:DF 1 "general_operand" ""))]
240990286Sobrien  ""
241090286Sobrien  "ix86_expand_move (DFmode, operands); DONE;")
241152296Sobrien
241290286Sobrien;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
2413132727Skan;; Size of pushdf using integer instructions is 2+2*memory operand size
241490286Sobrien;; On the average, pushdf using integers can be still shorter.  Allow this
241590286Sobrien;; pattern for optimize_size too.
241690286Sobrien
241790286Sobrien(define_insn "*pushdf_nointeger"
241890286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
2419169699Skan	(match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))]
242090286Sobrien  "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
242118334Speter{
2422132727Skan  /* This insn should be already split before reg-stack.  */
2423169699Skan  gcc_unreachable ();
242490286Sobrien}
242590286Sobrien  [(set_attr "type" "multi")
2426169699Skan   (set_attr "unit" "i387,*,*,*")
242790286Sobrien   (set_attr "mode" "DF,SI,SI,DF")])
242818334Speter
242990286Sobrien(define_insn "*pushdf_integer"
243090286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<,<,<")
2431169699Skan	(match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))]
243290286Sobrien  "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
243390286Sobrien{
2434132727Skan  /* This insn should be already split before reg-stack.  */
2435169699Skan  gcc_unreachable ();
243690286Sobrien}
243790286Sobrien  [(set_attr "type" "multi")
2438169699Skan   (set_attr "unit" "i387,*,*")
243990286Sobrien   (set_attr "mode" "DF,SI,DF")])
244018334Speter
244190286Sobrien;; %%% Kill this when call knows how to work this out.
244252296Sobrien(define_split
244352296Sobrien  [(set (match_operand:DF 0 "push_operand" "")
2444117404Skan	(match_operand:DF 1 "any_fp_register_operand" ""))]
2445117404Skan  "!TARGET_64BIT && reload_completed"
2446169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
2447169699Skan   (set (mem:DF (reg:SI SP_REG)) (match_dup 1))]
244852296Sobrien  "")
244950650Sobrien
245090286Sobrien(define_split
245190286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
2452117404Skan	(match_operand:DF 1 "any_fp_register_operand" ""))]
2453117404Skan  "TARGET_64BIT && reload_completed"
2454169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
2455169699Skan   (set (mem:DF (reg:DI SP_REG)) (match_dup 1))]
245690286Sobrien  "")
245790286Sobrien
245890286Sobrien(define_split
245990286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
246050650Sobrien	(match_operand:DF 1 "general_operand" ""))]
246190286Sobrien  "reload_completed"
246290286Sobrien  [(const_int 0)]
246390286Sobrien  "ix86_split_long_move (operands); DONE;")
246490286Sobrien
246590286Sobrien;; Moving is usually shorter when only FP registers are used. This separate
246690286Sobrien;; movdf pattern avoids the use of integer registers for FP operations
246790286Sobrien;; when optimizing for size.
246890286Sobrien
246990286Sobrien(define_insn "*movdf_nointeger"
2470169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"
2471169699Skan			"=f,m,f,*r  ,o  ,Y*x,Y*x,Y*x ,m  ")
2472169699Skan	(match_operand:DF 1 "general_operand"
2473169699Skan			"fm,f,G,*roF,F*r,C  ,Y*x,mY*x,Y*x"))]
247490286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2475132727Skan   && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
247690286Sobrien   && (reload_in_progress || reload_completed
247790286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
247890286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
2479259563Spfg       || memory_operand (operands[0], DFmode))"
248018334Speter{
248190286Sobrien  switch (which_alternative)
248218334Speter    {
248390286Sobrien    case 0:
2484169699Skan      return output_387_reg_move (insn, operands);
248518334Speter
248690286Sobrien    case 1:
248790286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
248890286Sobrien        return "fstp%z0\t%y0";
248990286Sobrien      else
249090286Sobrien        return "fst%z0\t%y0";
249118334Speter
249290286Sobrien    case 2:
2493132727Skan      return standard_80387_constant_opcode (operands[1]);
249418334Speter
249590286Sobrien    case 3:
249690286Sobrien    case 4:
249790286Sobrien      return "#";
249890286Sobrien    case 5:
2499132727Skan      switch (get_attr_mode (insn))
2500132727Skan	{
2501132727Skan	case MODE_V4SF:
2502132727Skan	  return "xorps\t%0, %0";
2503132727Skan	case MODE_V2DF:
2504132727Skan	  return "xorpd\t%0, %0";
2505132727Skan	case MODE_TI:
2506132727Skan	  return "pxor\t%0, %0";
2507132727Skan	default:
2508169699Skan	  gcc_unreachable ();
2509132727Skan	}
251090286Sobrien    case 6:
2511169699Skan    case 7:
2512169699Skan    case 8:
2513132727Skan      switch (get_attr_mode (insn))
2514132727Skan	{
2515132727Skan	case MODE_V4SF:
2516132727Skan	  return "movaps\t{%1, %0|%0, %1}";
2517132727Skan	case MODE_V2DF:
2518132727Skan	  return "movapd\t{%1, %0|%0, %1}";
2519169699Skan	case MODE_TI:
2520169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
2521169699Skan	case MODE_DI:
2522169699Skan	  return "movq\t{%1, %0|%0, %1}";
2523132727Skan	case MODE_DF:
2524132727Skan	  return "movsd\t{%1, %0|%0, %1}";
2525169699Skan	case MODE_V1DF:
2526169699Skan	  return "movlpd\t{%1, %0|%0, %1}";
2527169699Skan	case MODE_V2SF:
2528169699Skan	  return "movlps\t{%1, %0|%0, %1}";
2529132727Skan	default:
2530169699Skan	  gcc_unreachable ();
2531132727Skan	}
253218334Speter
253390286Sobrien    default:
2534169699Skan      gcc_unreachable ();
253518334Speter    }
253690286Sobrien}
2537169699Skan  [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
2538132727Skan   (set (attr "mode")
2539169699Skan        (cond [(eq_attr "alternative" "0,1,2")
2540169699Skan		 (const_string "DF")
2541169699Skan	       (eq_attr "alternative" "3,4")
2542132727Skan		 (const_string "SI")
2543169699Skan
2544169699Skan	       /* For SSE1, we have many fewer alternatives.  */
2545169699Skan	       (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2546169699Skan		 (cond [(eq_attr "alternative" "5,6")
2547169699Skan			  (const_string "V4SF")
2548169699Skan		       ]
2549169699Skan		   (const_string "V2SF"))
2550169699Skan
2551132727Skan	       /* xorps is one byte shorter.  */
2552132727Skan	       (eq_attr "alternative" "5")
2553132727Skan		 (cond [(ne (symbol_ref "optimize_size")
2554132727Skan			    (const_int 0))
2555132727Skan			  (const_string "V4SF")
2556132727Skan			(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2557132727Skan			    (const_int 0))
2558169699Skan			  (const_string "TI")
2559169699Skan		       ]
2560132727Skan		       (const_string "V2DF"))
2561169699Skan
2562132727Skan	       /* For architectures resolving dependencies on
2563132727Skan		  whole SSE registers use APD move to break dependency
2564132727Skan		  chains, otherwise use short move to avoid extra work.
256518334Speter
2566132727Skan		  movaps encodes one byte shorter.  */
2567132727Skan	       (eq_attr "alternative" "6")
2568132727Skan		 (cond
2569169699Skan		   [(ne (symbol_ref "optimize_size")
2570169699Skan		        (const_int 0))
2571169699Skan		      (const_string "V4SF")
2572169699Skan		    (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2573169699Skan		        (const_int 0))
2574169699Skan		      (const_string "V2DF")
2575169699Skan		   ]
2576132727Skan		   (const_string "DF"))
2577132727Skan	       /* For architectures resolving dependencies on register
2578132727Skan		  parts we may avoid extra work to zero out upper part
2579132727Skan		  of register.  */
2580132727Skan	       (eq_attr "alternative" "7")
2581132727Skan		 (if_then_else
2582169699Skan		   (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2583132727Skan		       (const_int 0))
2584169699Skan		   (const_string "V1DF")
2585169699Skan		   (const_string "DF"))
2586169699Skan	      ]
2587169699Skan	      (const_string "DF")))])
2588132727Skan
258990286Sobrien(define_insn "*movdf_integer"
2590169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"
2591169699Skan		"=f,m,f,r  ,o ,Y*x,Y*x,Y*x,m  ")
2592169699Skan	(match_operand:DF 1 "general_operand"
2593169699Skan		"fm,f,G,roF,Fr,C  ,Y*x,m  ,Y*x"))]
259490286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2595132727Skan   && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
259690286Sobrien   && (reload_in_progress || reload_completed
259790286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
259890286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
2599259563Spfg       || memory_operand (operands[0], DFmode))"
260090286Sobrien{
260190286Sobrien  switch (which_alternative)
260218334Speter    {
260390286Sobrien    case 0:
2604169699Skan      return output_387_reg_move (insn, operands);
260518334Speter
260690286Sobrien    case 1:
260790286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
260890286Sobrien        return "fstp%z0\t%y0";
260990286Sobrien      else
261090286Sobrien        return "fst%z0\t%y0";
261118334Speter
261290286Sobrien    case 2:
2613132727Skan      return standard_80387_constant_opcode (operands[1]);
261418334Speter
261590286Sobrien    case 3:
261690286Sobrien    case 4:
261790286Sobrien      return "#";
261818334Speter
261990286Sobrien    case 5:
2620132727Skan      switch (get_attr_mode (insn))
2621132727Skan	{
2622132727Skan	case MODE_V4SF:
2623132727Skan	  return "xorps\t%0, %0";
2624132727Skan	case MODE_V2DF:
2625132727Skan	  return "xorpd\t%0, %0";
2626132727Skan	case MODE_TI:
2627132727Skan	  return "pxor\t%0, %0";
2628132727Skan	default:
2629169699Skan	  gcc_unreachable ();
2630132727Skan	}
263190286Sobrien    case 6:
2632169699Skan    case 7:
2633169699Skan    case 8:
2634132727Skan      switch (get_attr_mode (insn))
2635132727Skan	{
2636132727Skan	case MODE_V4SF:
2637132727Skan	  return "movaps\t{%1, %0|%0, %1}";
2638132727Skan	case MODE_V2DF:
2639132727Skan	  return "movapd\t{%1, %0|%0, %1}";
2640169699Skan	case MODE_TI:
2641169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
2642169699Skan	case MODE_DI:
2643169699Skan	  return "movq\t{%1, %0|%0, %1}";
2644132727Skan	case MODE_DF:
2645132727Skan	  return "movsd\t{%1, %0|%0, %1}";
2646169699Skan	case MODE_V1DF:
2647169699Skan	  return "movlpd\t{%1, %0|%0, %1}";
2648169699Skan	case MODE_V2SF:
2649169699Skan	  return "movlps\t{%1, %0|%0, %1}";
2650132727Skan	default:
2651169699Skan	  gcc_unreachable ();
2652132727Skan	}
265318334Speter
265490286Sobrien    default:
2655169699Skan      gcc_unreachable();
265690286Sobrien    }
265790286Sobrien}
2658169699Skan  [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
2659132727Skan   (set (attr "mode")
2660169699Skan        (cond [(eq_attr "alternative" "0,1,2")
2661169699Skan		 (const_string "DF")
2662169699Skan	       (eq_attr "alternative" "3,4")
2663132727Skan		 (const_string "SI")
2664169699Skan
2665169699Skan	       /* For SSE1, we have many fewer alternatives.  */
2666169699Skan	       (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2667169699Skan		 (cond [(eq_attr "alternative" "5,6")
2668169699Skan			  (const_string "V4SF")
2669169699Skan		       ]
2670169699Skan		   (const_string "V2SF"))
2671169699Skan
2672132727Skan	       /* xorps is one byte shorter.  */
2673132727Skan	       (eq_attr "alternative" "5")
2674132727Skan		 (cond [(ne (symbol_ref "optimize_size")
2675132727Skan			    (const_int 0))
2676132727Skan			  (const_string "V4SF")
2677132727Skan			(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2678132727Skan			    (const_int 0))
2679169699Skan			  (const_string "TI")
2680169699Skan		       ]
2681132727Skan		       (const_string "V2DF"))
2682169699Skan
2683132727Skan	       /* For architectures resolving dependencies on
2684132727Skan		  whole SSE registers use APD move to break dependency
2685169699Skan		  chains, otherwise use short move to avoid extra work.
268618334Speter
2687132727Skan		  movaps encodes one byte shorter.  */
2688132727Skan	       (eq_attr "alternative" "6")
2689132727Skan		 (cond
2690169699Skan		   [(ne (symbol_ref "optimize_size")
2691169699Skan		        (const_int 0))
2692169699Skan		      (const_string "V4SF")
2693169699Skan		    (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2694169699Skan		        (const_int 0))
2695169699Skan		      (const_string "V2DF")
2696169699Skan		   ]
2697132727Skan		   (const_string "DF"))
2698132727Skan	       /* For architectures resolving dependencies on register
2699132727Skan		  parts we may avoid extra work to zero out upper part
2700132727Skan		  of register.  */
2701132727Skan	       (eq_attr "alternative" "7")
2702132727Skan		 (if_then_else
2703169699Skan		   (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2704132727Skan		       (const_int 0))
2705169699Skan		   (const_string "V1DF")
2706169699Skan		   (const_string "DF"))
2707169699Skan	      ]
2708169699Skan	      (const_string "DF")))])
2709132727Skan
271090286Sobrien(define_split
271190286Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
271290286Sobrien	(match_operand:DF 1 "general_operand" ""))]
271390286Sobrien  "reload_completed
271490286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2715259563Spfg   && ! (ANY_FP_REG_P (operands[0]) ||
271690286Sobrien	 (GET_CODE (operands[0]) == SUBREG
271790286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
2718259563Spfg   && ! (ANY_FP_REG_P (operands[1]) ||
271990286Sobrien	 (GET_CODE (operands[1]) == SUBREG
272090286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
272190286Sobrien  [(const_int 0)]
272290286Sobrien  "ix86_split_long_move (operands); DONE;")
272350650Sobrien
272490286Sobrien(define_insn "*swapdf"
2725169699Skan  [(set (match_operand:DF 0 "fp_register_operand" "+f")
2726169699Skan	(match_operand:DF 1 "fp_register_operand" "+f"))
272718334Speter   (set (match_dup 1)
272818334Speter	(match_dup 0))]
2729169699Skan  "reload_completed || TARGET_80387"
273018334Speter{
273118334Speter  if (STACK_TOP_P (operands[0]))
273290286Sobrien    return "fxch\t%1";
273318334Speter  else
273490286Sobrien    return "fxch\t%0";
273590286Sobrien}
273690286Sobrien  [(set_attr "type" "fxch")
273790286Sobrien   (set_attr "mode" "DF")])
273818334Speter
273990286Sobrien(define_expand "movxf"
274090286Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
274190286Sobrien	(match_operand:XF 1 "general_operand" ""))]
2742132727Skan  ""
274390286Sobrien  "ix86_expand_move (XFmode, operands); DONE;")
274490286Sobrien
274590286Sobrien;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
2746132727Skan;; Size of pushdf using integer instructions is 3+3*memory operand size
274790286Sobrien;; Pushing using integer instructions is longer except for constants
274890286Sobrien;; and direct memory references.
274990286Sobrien;; (assuming that any given constant is pushed only once, but this ought to be
275090286Sobrien;;  handled elsewhere).
275190286Sobrien
275290286Sobrien(define_insn "*pushxf_nointeger"
275390286Sobrien  [(set (match_operand:XF 0 "push_operand" "=X,X,X")
275490286Sobrien	(match_operand:XF 1 "general_no_elim_operand" "f,Fo,*r"))]
275590286Sobrien  "optimize_size"
275690286Sobrien{
2757132727Skan  /* This insn should be already split before reg-stack.  */
2758169699Skan  gcc_unreachable ();
275990286Sobrien}
276090286Sobrien  [(set_attr "type" "multi")
2761169699Skan   (set_attr "unit" "i387,*,*")
276290286Sobrien   (set_attr "mode" "XF,SI,SI")])
276350650Sobrien
276490286Sobrien(define_insn "*pushxf_integer"
276590286Sobrien  [(set (match_operand:XF 0 "push_operand" "=<,<")
2766169699Skan	(match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
276790286Sobrien  "!optimize_size"
276890286Sobrien{
2769132727Skan  /* This insn should be already split before reg-stack.  */
2770169699Skan  gcc_unreachable ();
277190286Sobrien}
277290286Sobrien  [(set_attr "type" "multi")
2773169699Skan   (set_attr "unit" "i387,*")
277490286Sobrien   (set_attr "mode" "XF,SI")])
277590286Sobrien
277652296Sobrien(define_split
277790286Sobrien  [(set (match_operand 0 "push_operand" "")
277890286Sobrien	(match_operand 1 "general_operand" ""))]
277990286Sobrien  "reload_completed
278090286Sobrien   && (GET_MODE (operands[0]) == XFmode
278190286Sobrien       || GET_MODE (operands[0]) == DFmode)
2782117404Skan   && !ANY_FP_REG_P (operands[1])"
278390286Sobrien  [(const_int 0)]
278490286Sobrien  "ix86_split_long_move (operands); DONE;")
278590286Sobrien
278690286Sobrien(define_split
278752296Sobrien  [(set (match_operand:XF 0 "push_operand" "")
2788117404Skan	(match_operand:XF 1 "any_fp_register_operand" ""))]
2789117404Skan  "!TARGET_64BIT"
2790169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
2791169699Skan   (set (mem:XF (reg:SI SP_REG)) (match_dup 1))]
2792132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
279350650Sobrien
279490286Sobrien(define_split
2795132727Skan  [(set (match_operand:XF 0 "push_operand" "")
2796132727Skan	(match_operand:XF 1 "any_fp_register_operand" ""))]
2797117404Skan  "TARGET_64BIT"
2798169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
2799169699Skan   (set (mem:XF (reg:DI SP_REG)) (match_dup 1))]
2800132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
280190286Sobrien
280290286Sobrien;; Do not use integer registers when optimizing for size
280390286Sobrien(define_insn "*movxf_nointeger"
280490286Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o")
280590286Sobrien	(match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))]
2806132727Skan  "optimize_size
280790286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
280890286Sobrien   && (reload_in_progress || reload_completed
280990286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
2810259563Spfg       || memory_operand (operands[0], XFmode))"
281118334Speter{
281290286Sobrien  switch (which_alternative)
281318334Speter    {
281490286Sobrien    case 0:
2815169699Skan      return output_387_reg_move (insn, operands);
281618334Speter
281790286Sobrien    case 1:
281890286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
281990286Sobrien	 we need one, follow the store with a load.  */
282090286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
282190286Sobrien        return "fstp%z0\t%y0\;fld%z0\t%y0";
282290286Sobrien      else
282390286Sobrien        return "fstp%z0\t%y0";
282418334Speter
282590286Sobrien    case 2:
2826132727Skan      return standard_80387_constant_opcode (operands[1]);
282718334Speter
282890286Sobrien    case 3: case 4:
282990286Sobrien      return "#";
2830169699Skan    default:
2831169699Skan      gcc_unreachable ();
283290286Sobrien    }
283390286Sobrien}
283490286Sobrien  [(set_attr "type" "fmov,fmov,fmov,multi,multi")
283590286Sobrien   (set_attr "mode" "XF,XF,XF,SI,SI")])
283618334Speter
283790286Sobrien(define_insn "*movxf_integer"
2838169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
2839169699Skan	(match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
2840132727Skan  "!optimize_size
284190286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
284290286Sobrien   && (reload_in_progress || reload_completed
284390286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
2844259563Spfg       || memory_operand (operands[0], XFmode))"
284590286Sobrien{
284690286Sobrien  switch (which_alternative)
284718334Speter    {
284890286Sobrien    case 0:
2849169699Skan      return output_387_reg_move (insn, operands);
285018334Speter
285190286Sobrien    case 1:
285290286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
285390286Sobrien	 we need one, follow the store with a load.  */
285490286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
285590286Sobrien        return "fstp%z0\t%y0\;fld%z0\t%y0";
285690286Sobrien      else
285790286Sobrien        return "fstp%z0\t%y0";
285818334Speter
285990286Sobrien    case 2:
2860132727Skan      return standard_80387_constant_opcode (operands[1]);
286118334Speter
286290286Sobrien    case 3: case 4:
286390286Sobrien      return "#";
2864169699Skan
2865169699Skan    default:
2866169699Skan      gcc_unreachable ();
286790286Sobrien    }
286890286Sobrien}
286990286Sobrien  [(set_attr "type" "fmov,fmov,fmov,multi,multi")
287090286Sobrien   (set_attr "mode" "XF,XF,XF,SI,SI")])
287118334Speter
287290286Sobrien(define_split
287390286Sobrien  [(set (match_operand 0 "nonimmediate_operand" "")
287490286Sobrien	(match_operand 1 "general_operand" ""))]
287590286Sobrien  "reload_completed
287690286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2877132727Skan   && GET_MODE (operands[0]) == XFmode
2878259563Spfg   && ! (ANY_FP_REG_P (operands[0]) ||
287990286Sobrien	 (GET_CODE (operands[0]) == SUBREG
288090286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
2881259563Spfg   && ! (ANY_FP_REG_P (operands[1]) ||
288290286Sobrien	 (GET_CODE (operands[1]) == SUBREG
288390286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
288490286Sobrien  [(const_int 0)]
288590286Sobrien  "ix86_split_long_move (operands); DONE;")
288618334Speter
288790286Sobrien(define_split
288890286Sobrien  [(set (match_operand 0 "register_operand" "")
288990286Sobrien	(match_operand 1 "memory_operand" ""))]
289090286Sobrien  "reload_completed
289190286Sobrien   && GET_CODE (operands[1]) == MEM
2892132727Skan   && (GET_MODE (operands[0]) == XFmode
289390286Sobrien       || GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode)
2894161660Skan   && constant_pool_reference_p (operands[1])"
2895132727Skan  [(set (match_dup 0) (match_dup 1))]
2896132727Skan{
2897161660Skan  rtx c = avoid_constant_pool_reference (operands[1]);
2898132727Skan  rtx r = operands[0];
289990286Sobrien
2900132727Skan  if (GET_CODE (r) == SUBREG)
2901132727Skan    r = SUBREG_REG (r);
2902132727Skan
2903132727Skan  if (SSE_REG_P (r))
2904132727Skan    {
2905132727Skan      if (!standard_sse_constant_p (c))
2906132727Skan	FAIL;
2907132727Skan    }
2908132727Skan  else if (FP_REG_P (r))
2909132727Skan    {
2910132727Skan      if (!standard_80387_constant_p (c))
2911132727Skan	FAIL;
2912132727Skan    }
2913132727Skan  else if (MMX_REG_P (r))
2914132727Skan    FAIL;
2915132727Skan
2916132727Skan  operands[1] = c;
2917132727Skan})
2918132727Skan
291990286Sobrien(define_insn "swapxf"
292090286Sobrien  [(set (match_operand:XF 0 "register_operand" "+f")
292190286Sobrien	(match_operand:XF 1 "register_operand" "+f"))
292218334Speter   (set (match_dup 1)
292318334Speter	(match_dup 0))]
2924169699Skan  "TARGET_80387"
292518334Speter{
292618334Speter  if (STACK_TOP_P (operands[0]))
292790286Sobrien    return "fxch\t%1";
292818334Speter  else
292990286Sobrien    return "fxch\t%0";
293090286Sobrien}
293190286Sobrien  [(set_attr "type" "fxch")
293290286Sobrien   (set_attr "mode" "XF")])
2933169699Skan
2934169699Skan(define_expand "movtf"
2935169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "")
2936169699Skan	(match_operand:TF 1 "nonimmediate_operand" ""))]
2937169699Skan  "TARGET_64BIT"
2938169699Skan{
2939169699Skan  ix86_expand_move (TFmode, operands);
2940169699Skan  DONE;
2941169699Skan})
2942169699Skan
2943169699Skan(define_insn "*movtf_internal"
2944169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm")
2945169699Skan	(match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))]
2946169699Skan  "TARGET_64BIT
2947169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2948169699Skan{
2949169699Skan  switch (which_alternative)
2950169699Skan    {
2951169699Skan    case 0:
2952169699Skan    case 1:
2953169699Skan      return "#";
2954169699Skan    case 2:
2955169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2956169699Skan	return "xorps\t%0, %0";
2957169699Skan      else
2958169699Skan	return "pxor\t%0, %0";
2959169699Skan    case 3:
2960169699Skan    case 4:
2961169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2962169699Skan	return "movaps\t{%1, %0|%0, %1}";
2963169699Skan      else
2964169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2965169699Skan    default:
2966169699Skan      gcc_unreachable ();
2967169699Skan    }
2968169699Skan}
2969169699Skan  [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
2970169699Skan   (set (attr "mode")
2971169699Skan        (cond [(eq_attr "alternative" "2,3")
2972169699Skan		 (if_then_else
2973169699Skan		   (ne (symbol_ref "optimize_size")
2974169699Skan		       (const_int 0))
2975169699Skan		   (const_string "V4SF")
2976169699Skan		   (const_string "TI"))
2977169699Skan	       (eq_attr "alternative" "4")
2978169699Skan		 (if_then_else
2979169699Skan		   (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2980169699Skan			    (const_int 0))
2981169699Skan			(ne (symbol_ref "optimize_size")
2982169699Skan			    (const_int 0)))
2983169699Skan		   (const_string "V4SF")
2984169699Skan		   (const_string "TI"))]
2985169699Skan	       (const_string "DI")))])
2986169699Skan
2987169699Skan(define_split
2988169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "")
2989169699Skan        (match_operand:TF 1 "general_operand" ""))]
2990169699Skan  "reload_completed && !SSE_REG_P (operands[0])
2991169699Skan   && !SSE_REG_P (operands[1])"
2992169699Skan  [(const_int 0)]
2993169699Skan  "ix86_split_long_move (operands); DONE;")
299418334Speter
299590286Sobrien;; Zero extension instructions
299618334Speter
299752296Sobrien(define_expand "zero_extendhisi2"
299852296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
299990286Sobrien     (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
300052296Sobrien  ""
300190286Sobrien{
300290286Sobrien  if (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
300318334Speter    {
300490286Sobrien      operands[1] = force_reg (HImode, operands[1]);
300590286Sobrien      emit_insn (gen_zero_extendhisi2_and (operands[0], operands[1]));
300690286Sobrien      DONE;
300718334Speter    }
300890286Sobrien})
300918334Speter
301090286Sobrien(define_insn "zero_extendhisi2_and"
301190286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
301290286Sobrien     (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
3013169699Skan   (clobber (reg:CC FLAGS_REG))]
301490286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
301590286Sobrien  "#"
301690286Sobrien  [(set_attr "type" "alu1")
301790286Sobrien   (set_attr "mode" "SI")])
301850650Sobrien
301950650Sobrien(define_split
302050650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
302190286Sobrien	(zero_extend:SI (match_operand:HI 1 "register_operand" "")))
3022169699Skan   (clobber (reg:CC FLAGS_REG))]
302390286Sobrien  "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
302490286Sobrien  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535)))
3025169699Skan	      (clobber (reg:CC FLAGS_REG))])]
302690286Sobrien  "")
302750650Sobrien
302890286Sobrien(define_insn "*zero_extendhisi2_movzwl"
302990286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
303090286Sobrien     (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
303190286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
303290286Sobrien  "movz{wl|x}\t{%1, %0|%0, %1}"
303390286Sobrien  [(set_attr "type" "imovx")
303490286Sobrien   (set_attr "mode" "SI")])
303550650Sobrien
303652296Sobrien(define_expand "zero_extendqihi2"
303790286Sobrien  [(parallel
303890286Sobrien    [(set (match_operand:HI 0 "register_operand" "")
303990286Sobrien       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3040169699Skan     (clobber (reg:CC FLAGS_REG))])]
304152296Sobrien  ""
304252296Sobrien  "")
304352296Sobrien
304490286Sobrien(define_insn "*zero_extendqihi2_and"
304590286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,?&q")
304690286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
3047169699Skan   (clobber (reg:CC FLAGS_REG))]
304890286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
304990286Sobrien  "#"
305090286Sobrien  [(set_attr "type" "alu1")
305190286Sobrien   (set_attr "mode" "HI")])
305252296Sobrien
305390286Sobrien(define_insn "*zero_extendqihi2_movzbw_and"
305490286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
305590286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
3056169699Skan   (clobber (reg:CC FLAGS_REG))]
305790286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
305890286Sobrien  "#"
305990286Sobrien  [(set_attr "type" "imovx,alu1")
306090286Sobrien   (set_attr "mode" "HI")])
306152296Sobrien
3062169699Skan; zero extend to SImode here to avoid partial register stalls
3063169699Skan(define_insn "*zero_extendqihi2_movzbl"
306490286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r")
306590286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
306690286Sobrien  "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
3067169699Skan  "movz{bl|x}\t{%1, %k0|%k0, %k1}"
306890286Sobrien  [(set_attr "type" "imovx")
3069169699Skan   (set_attr "mode" "SI")])
307050650Sobrien
307190286Sobrien;; For the movzbw case strip only the clobber
307250650Sobrien(define_split
307350650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
307490286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3075169699Skan   (clobber (reg:CC FLAGS_REG))]
3076259563Spfg  "reload_completed
307790286Sobrien   && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
307890286Sobrien   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
307990286Sobrien  [(set (match_operand:HI 0 "register_operand" "")
308090286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))])
308150650Sobrien
308290286Sobrien;; When source and destination does not overlap, clear destination
308390286Sobrien;; first and then do the movb
308450650Sobrien(define_split
308550650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
308690286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3087169699Skan   (clobber (reg:CC FLAGS_REG))]
308890286Sobrien  "reload_completed
308990286Sobrien   && ANY_QI_REG_P (operands[0])
309090286Sobrien   && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
309190286Sobrien   && !reg_overlap_mentioned_p (operands[0], operands[1])"
309290286Sobrien  [(set (match_dup 0) (const_int 0))
309390286Sobrien   (set (strict_low_part (match_dup 2)) (match_dup 1))]
309490286Sobrien  "operands[2] = gen_lowpart (QImode, operands[0]);")
309550650Sobrien
309690286Sobrien;; Rest is handled by single and.
309750650Sobrien(define_split
309850650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
309990286Sobrien	(zero_extend:HI (match_operand:QI 1 "register_operand" "")))
3100169699Skan   (clobber (reg:CC FLAGS_REG))]
310190286Sobrien  "reload_completed
310290286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
310390286Sobrien  [(parallel [(set (match_dup 0) (and:HI (match_dup 0) (const_int 255)))
3104169699Skan	      (clobber (reg:CC FLAGS_REG))])]
310590286Sobrien  "")
310650650Sobrien
310752296Sobrien(define_expand "zero_extendqisi2"
310890286Sobrien  [(parallel
310990286Sobrien    [(set (match_operand:SI 0 "register_operand" "")
311090286Sobrien       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3111169699Skan     (clobber (reg:CC FLAGS_REG))])]
311252296Sobrien  ""
311352296Sobrien  "")
311452296Sobrien
311590286Sobrien(define_insn "*zero_extendqisi2_and"
311690286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,?&q")
311790286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
3118169699Skan   (clobber (reg:CC FLAGS_REG))]
311990286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
312090286Sobrien  "#"
312190286Sobrien  [(set_attr "type" "alu1")
312290286Sobrien   (set_attr "mode" "SI")])
312352296Sobrien
312490286Sobrien(define_insn "*zero_extendqisi2_movzbw_and"
312590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
312690286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
3127169699Skan   (clobber (reg:CC FLAGS_REG))]
312890286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
312990286Sobrien  "#"
313090286Sobrien  [(set_attr "type" "imovx,alu1")
313190286Sobrien   (set_attr "mode" "SI")])
313250650Sobrien
313390286Sobrien(define_insn "*zero_extendqisi2_movzbw"
313490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
313590286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
313690286Sobrien  "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
313790286Sobrien  "movz{bl|x}\t{%1, %0|%0, %1}"
313890286Sobrien  [(set_attr "type" "imovx")
313990286Sobrien   (set_attr "mode" "SI")])
314018334Speter
314190286Sobrien;; For the movzbl case strip only the clobber
314250650Sobrien(define_split
314350650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
314490286Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3145169699Skan   (clobber (reg:CC FLAGS_REG))]
3146259563Spfg  "reload_completed
314790286Sobrien   && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
314890286Sobrien   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
314990286Sobrien  [(set (match_dup 0)
315090286Sobrien	(zero_extend:SI (match_dup 1)))])
315150650Sobrien
315290286Sobrien;; When source and destination does not overlap, clear destination
315390286Sobrien;; first and then do the movb
315450650Sobrien(define_split
315550650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
315690286Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3157169699Skan   (clobber (reg:CC FLAGS_REG))]
315890286Sobrien  "reload_completed
315990286Sobrien   && ANY_QI_REG_P (operands[0])
316090286Sobrien   && (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)
316190286Sobrien   && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
316290286Sobrien   && !reg_overlap_mentioned_p (operands[0], operands[1])"
316390286Sobrien  [(set (match_dup 0) (const_int 0))
316490286Sobrien   (set (strict_low_part (match_dup 2)) (match_dup 1))]
316590286Sobrien  "operands[2] = gen_lowpart (QImode, operands[0]);")
316650650Sobrien
316790286Sobrien;; Rest is handled by single and.
316850650Sobrien(define_split
316950650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
317090286Sobrien	(zero_extend:SI (match_operand:QI 1 "register_operand" "")))
3171169699Skan   (clobber (reg:CC FLAGS_REG))]
317290286Sobrien  "reload_completed
317390286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
317490286Sobrien  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 255)))
3175169699Skan	      (clobber (reg:CC FLAGS_REG))])]
317690286Sobrien  "")
317750650Sobrien
317890286Sobrien;; %%% Kill me once multi-word ops are sane.
317990286Sobrien(define_expand "zero_extendsidi2"
318090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
318190286Sobrien     (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
318218334Speter  ""
318390286Sobrien  "if (!TARGET_64BIT)
318490286Sobrien     {
318590286Sobrien       emit_insn (gen_zero_extendsidi2_32 (operands[0], operands[1]));
318690286Sobrien       DONE;
318790286Sobrien     }
318890286Sobrien  ")
318950650Sobrien
319090286Sobrien(define_insn "zero_extendsidi2_32"
3191169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,?*y,?*Y")
3192132727Skan	(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,rm,rm")))
3193169699Skan   (clobber (reg:CC FLAGS_REG))]
3194169699Skan  "!TARGET_64BIT"
3195132727Skan  "@
3196132727Skan   #
3197132727Skan   #
3198132727Skan   #
3199132727Skan   movd\t{%1, %0|%0, %1}
3200132727Skan   movd\t{%1, %0|%0, %1}"
3201132727Skan  [(set_attr "mode" "SI,SI,SI,DI,TI")
3202132727Skan   (set_attr "type" "multi,multi,multi,mmxmov,ssemov")])
3203132727Skan
320490286Sobrien(define_insn "zero_extendsidi2_rex64"
3205169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*y,?*Y")
3206132727Skan     (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,rm,rm")))]
3207169699Skan  "TARGET_64BIT"
3208132727Skan  "@
3209132727Skan   mov\t{%k1, %k0|%k0, %k1}
3210132727Skan   #
3211132727Skan   movd\t{%1, %0|%0, %1}
3212132727Skan   movd\t{%1, %0|%0, %1}"
3213132727Skan  [(set_attr "type" "imovx,imov,mmxmov,ssemov")
3214132727Skan   (set_attr "mode" "SI,DI,SI,SI")])
3215132727Skan
321690286Sobrien(define_split
321790286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
321890286Sobrien     (zero_extend:DI (match_dup 0)))]
321990286Sobrien  "TARGET_64BIT"
322090286Sobrien  [(set (match_dup 4) (const_int 0))]
322190286Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
322290286Sobrien
3223259563Spfg(define_split
322452296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
322590286Sobrien	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
3226169699Skan   (clobber (reg:CC FLAGS_REG))]
322790286Sobrien  "!TARGET_64BIT && reload_completed
322890286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
322952296Sobrien  [(set (match_dup 4) (const_int 0))]
323052296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
323150650Sobrien
3232259563Spfg(define_split
323352296Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
323490286Sobrien	(zero_extend:DI (match_operand:SI 1 "general_operand" "")))
3235169699Skan   (clobber (reg:CC FLAGS_REG))]
3236132727Skan  "!TARGET_64BIT && reload_completed
3237132727Skan   && !SSE_REG_P (operands[0]) && !MMX_REG_P (operands[0])"
323852296Sobrien  [(set (match_dup 3) (match_dup 1))
323952296Sobrien   (set (match_dup 4) (const_int 0))]
324052296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
324190286Sobrien
324290286Sobrien(define_insn "zero_extendhidi2"
3243169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
3244169699Skan     (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
324590286Sobrien  "TARGET_64BIT"
3246169699Skan  "movz{wl|x}\t{%1, %k0|%k0, %1}"
324790286Sobrien  [(set_attr "type" "imovx")
3248169699Skan   (set_attr "mode" "DI")])
324990286Sobrien
325090286Sobrien(define_insn "zero_extendqidi2"
3251169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
3252169699Skan     (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
325390286Sobrien  "TARGET_64BIT"
3254169699Skan  "movz{bl|x}\t{%1, %k0|%k0, %1}"
325590286Sobrien  [(set_attr "type" "imovx")
3256169699Skan   (set_attr "mode" "DI")])
325718334Speter
325890286Sobrien;; Sign extension instructions
325918334Speter
326090286Sobrien(define_expand "extendsidi2"
326190286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
326290286Sobrien		   (sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3263169699Skan	      (clobber (reg:CC FLAGS_REG))
326490286Sobrien	      (clobber (match_scratch:SI 2 ""))])]
326590286Sobrien  ""
326690286Sobrien{
326790286Sobrien  if (TARGET_64BIT)
326890286Sobrien    {
326990286Sobrien      emit_insn (gen_extendsidi2_rex64 (operands[0], operands[1]));
327090286Sobrien      DONE;
327190286Sobrien    }
327290286Sobrien})
327390286Sobrien
327490286Sobrien(define_insn "*extendsidi2_1"
327590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=*A,r,?r,?*o")
327690286Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,r")))
3277169699Skan   (clobber (reg:CC FLAGS_REG))
327852296Sobrien   (clobber (match_scratch:SI 2 "=X,X,X,&r"))]
327990286Sobrien  "!TARGET_64BIT"
328052296Sobrien  "#")
328152296Sobrien
328290286Sobrien(define_insn "extendsidi2_rex64"
328390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*a,r")
328490286Sobrien	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "*0,rm")))]
328590286Sobrien  "TARGET_64BIT"
328690286Sobrien  "@
328790286Sobrien   {cltq|cdqe}
328890286Sobrien   movs{lq|x}\t{%1,%0|%0, %1}"
328990286Sobrien  [(set_attr "type" "imovx")
329090286Sobrien   (set_attr "mode" "DI")
329190286Sobrien   (set_attr "prefix_0f" "0")
329290286Sobrien   (set_attr "modrm" "0,1")])
329390286Sobrien
329490286Sobrien(define_insn "extendhidi2"
329590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
329690286Sobrien	(sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
329790286Sobrien  "TARGET_64BIT"
329890286Sobrien  "movs{wq|x}\t{%1,%0|%0, %1}"
329990286Sobrien  [(set_attr "type" "imovx")
330090286Sobrien   (set_attr "mode" "DI")])
330190286Sobrien
330290286Sobrien(define_insn "extendqidi2"
330390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
330490286Sobrien	(sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
330590286Sobrien  "TARGET_64BIT"
330690286Sobrien  "movs{bq|x}\t{%1,%0|%0, %1}"
330790286Sobrien   [(set_attr "type" "imovx")
330890286Sobrien    (set_attr "mode" "DI")])
330990286Sobrien
331052296Sobrien;; Extend to memory case when source register does die.
3311259563Spfg(define_split
331252296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
331352296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3314169699Skan   (clobber (reg:CC FLAGS_REG))
331552296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
331690286Sobrien  "(reload_completed
331752296Sobrien    && dead_or_set_p (insn, operands[1])
331852296Sobrien    && !reg_mentioned_p (operands[1], operands[0]))"
331952296Sobrien  [(set (match_dup 3) (match_dup 1))
332090286Sobrien   (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
3321169699Skan	      (clobber (reg:CC FLAGS_REG))])
332252296Sobrien   (set (match_dup 4) (match_dup 1))]
332352296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
332452296Sobrien
332552296Sobrien;; Extend to memory case when source register does not die.
3326259563Spfg(define_split
332752296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
332852296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3329169699Skan   (clobber (reg:CC FLAGS_REG))
333052296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
333190286Sobrien  "reload_completed"
333252296Sobrien  [(const_int 0)]
333318334Speter{
333452296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
333552296Sobrien
333652296Sobrien  emit_move_insn (operands[3], operands[1]);
333752296Sobrien
333852296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
333952296Sobrien  if (true_regnum (operands[1]) == 0
334052296Sobrien      && true_regnum (operands[2]) == 1
334190286Sobrien      && (optimize_size || TARGET_USE_CLTD))
334218334Speter    {
334390286Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[1], GEN_INT (31)));
334418334Speter    }
334552296Sobrien  else
334652296Sobrien    {
334752296Sobrien      emit_move_insn (operands[2], operands[1]);
334890286Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[2], GEN_INT (31)));
334952296Sobrien    }
335052296Sobrien  emit_move_insn (operands[4], operands[2]);
335152296Sobrien  DONE;
335290286Sobrien})
335318334Speter
335452296Sobrien;; Extend to register case.  Optimize case where source and destination
335552296Sobrien;; registers match and cases where we can use cltd.
3356259563Spfg(define_split
335752296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
335852296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3359169699Skan   (clobber (reg:CC FLAGS_REG))
336052296Sobrien   (clobber (match_scratch:SI 2 ""))]
336152296Sobrien  "reload_completed"
336252296Sobrien  [(const_int 0)]
336352296Sobrien{
336452296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
336518334Speter
336652296Sobrien  if (true_regnum (operands[3]) != true_regnum (operands[1]))
336752296Sobrien    emit_move_insn (operands[3], operands[1]);
336852296Sobrien
336952296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
337052296Sobrien  if (true_regnum (operands[3]) == 0
337190286Sobrien      && (optimize_size || TARGET_USE_CLTD))
337252296Sobrien    {
337390286Sobrien      emit_insn (gen_ashrsi3_31 (operands[4], operands[3], GEN_INT (31)));
337452296Sobrien      DONE;
337552296Sobrien    }
337652296Sobrien
337752296Sobrien  if (true_regnum (operands[4]) != true_regnum (operands[1]))
337852296Sobrien    emit_move_insn (operands[4], operands[1]);
337952296Sobrien
338090286Sobrien  emit_insn (gen_ashrsi3_31 (operands[4], operands[4], GEN_INT (31)));
338152296Sobrien  DONE;
338290286Sobrien})
338318334Speter
338418334Speter(define_insn "extendhisi2"
338590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=*a,r")
338690286Sobrien	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm")))]
338718334Speter  ""
338818334Speter{
338990286Sobrien  switch (get_attr_prefix_0f (insn))
339090286Sobrien    {
339190286Sobrien    case 0:
339290286Sobrien      return "{cwtl|cwde}";
339390286Sobrien    default:
339490286Sobrien      return "movs{wl|x}\t{%1,%0|%0, %1}";
339590286Sobrien    }
339690286Sobrien}
339790286Sobrien  [(set_attr "type" "imovx")
339890286Sobrien   (set_attr "mode" "SI")
339990286Sobrien   (set (attr "prefix_0f")
340090286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
340190286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
340290286Sobrien			(eq_attr "alternative" "0"))
340390286Sobrien	(const_string "0")
340490286Sobrien	(const_string "1")))
340590286Sobrien   (set (attr "modrm")
340690286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
340790286Sobrien	(const_string "0")
340890286Sobrien	(const_string "1")))])
340918334Speter
341090286Sobrien(define_insn "*extendhisi2_zext"
341190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*a,r")
341290286Sobrien	(zero_extend:DI
341390286Sobrien	  (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm"))))]
341490286Sobrien  "TARGET_64BIT"
341590286Sobrien{
341690286Sobrien  switch (get_attr_prefix_0f (insn))
341790286Sobrien    {
341890286Sobrien    case 0:
341990286Sobrien      return "{cwtl|cwde}";
342090286Sobrien    default:
342190286Sobrien      return "movs{wl|x}\t{%1,%k0|%k0, %1}";
342290286Sobrien    }
342390286Sobrien}
342490286Sobrien  [(set_attr "type" "imovx")
342590286Sobrien   (set_attr "mode" "SI")
342690286Sobrien   (set (attr "prefix_0f")
342790286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
342890286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
342990286Sobrien			(eq_attr "alternative" "0"))
343090286Sobrien	(const_string "0")
343190286Sobrien	(const_string "1")))
343290286Sobrien   (set (attr "modrm")
343390286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
343490286Sobrien	(const_string "0")
343590286Sobrien	(const_string "1")))])
343618334Speter
343718334Speter(define_insn "extendqihi2"
343890286Sobrien  [(set (match_operand:HI 0 "register_operand" "=*a,r")
343990286Sobrien	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "*0,qm")))]
344018334Speter  ""
344118334Speter{
344290286Sobrien  switch (get_attr_prefix_0f (insn))
344390286Sobrien    {
344490286Sobrien    case 0:
344590286Sobrien      return "{cbtw|cbw}";
344690286Sobrien    default:
344790286Sobrien      return "movs{bw|x}\t{%1,%0|%0, %1}";
344890286Sobrien    }
344990286Sobrien}
345090286Sobrien  [(set_attr "type" "imovx")
345190286Sobrien   (set_attr "mode" "HI")
345290286Sobrien   (set (attr "prefix_0f")
345390286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
345490286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
345590286Sobrien			(eq_attr "alternative" "0"))
345690286Sobrien	(const_string "0")
345790286Sobrien	(const_string "1")))
345890286Sobrien   (set (attr "modrm")
345990286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
346090286Sobrien	(const_string "0")
346190286Sobrien	(const_string "1")))])
346218334Speter
346318334Speter(define_insn "extendqisi2"
346450650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
346550650Sobrien	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
346618334Speter  ""
346790286Sobrien  "movs{bl|x}\t{%1,%0|%0, %1}"
346890286Sobrien   [(set_attr "type" "imovx")
346990286Sobrien    (set_attr "mode" "SI")])
347050650Sobrien
347190286Sobrien(define_insn "*extendqisi2_zext"
347290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
347390286Sobrien	(zero_extend:DI
347490286Sobrien	  (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))))]
347590286Sobrien  "TARGET_64BIT"
347690286Sobrien  "movs{bl|x}\t{%1,%k0|%k0, %1}"
347790286Sobrien   [(set_attr "type" "imovx")
347890286Sobrien    (set_attr "mode" "SI")])
347918334Speter
348090286Sobrien;; Conversions between float and double.
348150650Sobrien
348290286Sobrien;; These are all no-ops in the model used for the 80387.  So just
348390286Sobrien;; emit moves.
348450650Sobrien
3485259563Spfg;; %%% Kill these when call knows how to work out a DFmode push earlier.
348690286Sobrien(define_insn "*dummy_extendsfdf2"
348790286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<")
348890286Sobrien	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fY")))]
348990286Sobrien  "0"
349090286Sobrien  "#")
349150650Sobrien
349290286Sobrien(define_split
349390286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
3494117404Skan	(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
3495117404Skan  "!TARGET_64BIT"
3496169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
3497169699Skan   (set (mem:DF (reg:SI SP_REG)) (float_extend:DF (match_dup 1)))])
349850650Sobrien
349990286Sobrien(define_split
350090286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
3501117404Skan	(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
3502117404Skan  "TARGET_64BIT"
3503169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
3504169699Skan   (set (mem:DF (reg:DI SP_REG)) (float_extend:DF (match_dup 1)))])
350550650Sobrien
350690286Sobrien(define_insn "*dummy_extendsfxf2"
350790286Sobrien  [(set (match_operand:XF 0 "push_operand" "=<")
350890286Sobrien	(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "f")))]
350990286Sobrien  "0"
351090286Sobrien  "#")
351150650Sobrien
351290286Sobrien(define_split
351390286Sobrien  [(set (match_operand:XF 0 "push_operand" "")
3514117404Skan	(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
3515132727Skan  ""
3516169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
3517169699Skan   (set (mem:XF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
3518132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
351950650Sobrien
352090286Sobrien(define_split
3521132727Skan  [(set (match_operand:XF 0 "push_operand" "")
3522132727Skan	(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
3523117404Skan  "TARGET_64BIT"
3524169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
3525169699Skan   (set (mem:DF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
3526132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
352718334Speter
352890286Sobrien(define_split
352990286Sobrien  [(set (match_operand:XF 0 "push_operand" "")
3530117404Skan	(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
3531132727Skan  ""
3532169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
3533169699Skan   (set (mem:DF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
3534132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
353552296Sobrien
353652296Sobrien(define_split
3537132727Skan  [(set (match_operand:XF 0 "push_operand" "")
3538132727Skan	(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
3539117404Skan  "TARGET_64BIT"
3540169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
3541169699Skan   (set (mem:XF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
3542132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
354318334Speter
354490286Sobrien(define_expand "extendsfdf2"
354552296Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
3546117404Skan        (float_extend:DF (match_operand:SF 1 "general_operand" "")))]
3547169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
354852296Sobrien{
3549117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3550117404Skan     are LEGITIMATE_CONSTANT_P.  */
3551117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3552169699Skan    {
3553169699Skan      if ((!TARGET_SSE2 || TARGET_MIX_SSE_I387)
3554169699Skan	  && standard_80387_constant_p (operands[1]) > 0)
3555169699Skan	{
3556169699Skan	  operands[1] = simplify_const_unary_operation
3557169699Skan	    (FLOAT_EXTEND, DFmode, operands[1], SFmode);
3558169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3559169699Skan	  DONE;
3560169699Skan	}
3561169699Skan      operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
3562169699Skan    }
356390286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
356490286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
356590286Sobrien})
356618334Speter
3567169699Skan(define_insn "*extendsfdf2_mixed"
3568169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y")
3569169699Skan        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))]
3570169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387
357190286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
357252296Sobrien{
357390286Sobrien  switch (which_alternative)
357490286Sobrien    {
357590286Sobrien    case 0:
3576169699Skan      return output_387_reg_move (insn, operands);
357752296Sobrien
357890286Sobrien    case 1:
357990286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
358090286Sobrien        return "fstp%z0\t%y0";
358190286Sobrien      else
358290286Sobrien        return "fst%z0\t%y0";
3583169699Skan
358490286Sobrien    case 2:
358590286Sobrien      return "cvtss2sd\t{%1, %0|%0, %1}";
358618334Speter
358790286Sobrien    default:
3588169699Skan      gcc_unreachable ();
358990286Sobrien    }
359090286Sobrien}
3591117404Skan  [(set_attr "type" "fmov,fmov,ssecvt")
359290286Sobrien   (set_attr "mode" "SF,XF,DF")])
359318334Speter
3594169699Skan(define_insn "*extendsfdf2_sse"
3595169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y")
359690286Sobrien        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "mY")))]
3597169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
359890286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
359990286Sobrien  "cvtss2sd\t{%1, %0|%0, %1}"
3600117404Skan  [(set_attr "type" "ssecvt")
360190286Sobrien   (set_attr "mode" "DF")])
360218334Speter
3603169699Skan(define_insn "*extendsfdf2_i387"
3604169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
3605169699Skan        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
3606169699Skan  "TARGET_80387
3607169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
3608169699Skan{
3609169699Skan  switch (which_alternative)
3610169699Skan    {
3611169699Skan    case 0:
3612169699Skan      return output_387_reg_move (insn, operands);
3613169699Skan
3614169699Skan    case 1:
3615169699Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3616169699Skan        return "fstp%z0\t%y0";
3617169699Skan      else
3618169699Skan        return "fst%z0\t%y0";
3619169699Skan
3620169699Skan    default:
3621169699Skan      gcc_unreachable ();
3622169699Skan    }
3623169699Skan}
3624169699Skan  [(set_attr "type" "fmov")
3625169699Skan   (set_attr "mode" "SF,XF")])
3626169699Skan
362790286Sobrien(define_expand "extendsfxf2"
362852296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
3629117404Skan        (float_extend:XF (match_operand:SF 1 "general_operand" "")))]
3630132727Skan  "TARGET_80387"
363190286Sobrien{
3632117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3633117404Skan     are LEGITIMATE_CONSTANT_P.  */
3634117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3635169699Skan    {
3636169699Skan      if (standard_80387_constant_p (operands[1]) > 0)
3637169699Skan	{
3638169699Skan	  operands[1] = simplify_const_unary_operation
3639169699Skan	    (FLOAT_EXTEND, XFmode, operands[1], SFmode);
3640169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3641169699Skan	  DONE;
3642169699Skan	}
3643169699Skan      operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
3644169699Skan    }
364590286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
364690286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
364790286Sobrien})
364818334Speter
3649169699Skan(define_insn "*extendsfxf2_i387"
365052296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
365190286Sobrien        (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
365290286Sobrien  "TARGET_80387
365390286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
365418334Speter{
365590286Sobrien  switch (which_alternative)
365690286Sobrien    {
365790286Sobrien    case 0:
3658169699Skan      return output_387_reg_move (insn, operands);
365918334Speter
366090286Sobrien    case 1:
366190286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
366290286Sobrien	 we need one, follow the store with a load.  */
3663169699Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3664169699Skan        return "fstp%z0\t%y0";
3665169699Skan      else
366690286Sobrien        return "fstp%z0\t%y0\n\tfld%z0\t%y0";
366718334Speter
366890286Sobrien    default:
3669169699Skan      gcc_unreachable ();
367090286Sobrien    }
367190286Sobrien}
367290286Sobrien  [(set_attr "type" "fmov")
367390286Sobrien   (set_attr "mode" "SF,XF")])
367418334Speter
367590286Sobrien(define_expand "extenddfxf2"
367652296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
3677117404Skan        (float_extend:XF (match_operand:DF 1 "general_operand" "")))]
3678132727Skan  "TARGET_80387"
367990286Sobrien{
3680117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3681117404Skan     are LEGITIMATE_CONSTANT_P.  */
3682117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3683169699Skan    {
3684169699Skan      if (standard_80387_constant_p (operands[1]) > 0)
3685169699Skan	{
3686169699Skan	  operands[1] = simplify_const_unary_operation
3687169699Skan	    (FLOAT_EXTEND, XFmode, operands[1], DFmode);
3688169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3689169699Skan	  DONE;
3690169699Skan	}
3691169699Skan      operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
3692169699Skan    }
369390286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
369490286Sobrien    operands[1] = force_reg (DFmode, operands[1]);
369590286Sobrien})
369618334Speter
3697169699Skan(define_insn "*extenddfxf2_i387"
369852296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
369990286Sobrien        (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
370090286Sobrien  "TARGET_80387
370190286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
370290286Sobrien{
370390286Sobrien  switch (which_alternative)
370490286Sobrien    {
370590286Sobrien    case 0:
3706169699Skan      return output_387_reg_move (insn, operands);
370790286Sobrien
370890286Sobrien    case 1:
370990286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
371090286Sobrien	 we need one, follow the store with a load.  */
371190286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
371290286Sobrien        return "fstp%z0\t%y0\n\tfld%z0\t%y0";
371390286Sobrien      else
371490286Sobrien        return "fstp%z0\t%y0";
371590286Sobrien
371690286Sobrien    default:
3717169699Skan      gcc_unreachable ();
371890286Sobrien    }
371990286Sobrien}
372090286Sobrien  [(set_attr "type" "fmov")
372190286Sobrien   (set_attr "mode" "DF,XF")])
372290286Sobrien
372390286Sobrien;; %%% This seems bad bad news.
372490286Sobrien;; This cannot output into an f-reg because there is no way to be sure
372590286Sobrien;; of truncating in that case.  Otherwise this is just like a simple move
372690286Sobrien;; insn.  So we pretend we can output to a reg in order to get better
372790286Sobrien;; register preferencing, but we really use a stack slot.
372890286Sobrien
3729169699Skan;; Conversion from DFmode to SFmode.
3730169699Skan
373118334Speter(define_expand "truncdfsf2"
3732169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
373390286Sobrien	(float_truncate:SF
3734169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "")))]
3735169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
373618334Speter{
3737169699Skan  if (MEM_P (operands[0]) && MEM_P (operands[1]))
3738169699Skan    operands[1] = force_reg (DFmode, operands[1]);
3739169699Skan
3740169699Skan  if (TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_MIX_SSE_I387)
3741169699Skan    ;
3742169699Skan  else if (flag_unsafe_math_optimizations)
3743169699Skan    ;
3744169699Skan  else
374590286Sobrien    {
3746171835Skan      rtx temp = assign_386_stack_local (SFmode, SLOT_VIRTUAL);
3747169699Skan      emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
3748169699Skan      DONE;
374990286Sobrien    }
3750169699Skan})
375118334Speter
3752169699Skan(define_expand "truncdfsf2_with_temp"
3753169699Skan  [(parallel [(set (match_operand:SF 0 "" "")
3754169699Skan		   (float_truncate:SF (match_operand:DF 1 "" "")))
3755169699Skan	      (clobber (match_operand:SF 2 "" ""))])]
3756169699Skan  "")
3757169699Skan
3758169699Skan(define_insn "*truncdfsf_fast_mixed"
3759169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,f,Y")
3760169699Skan        (float_truncate:SF
3761169699Skan          (match_operand:DF 1 "nonimmediate_operand" "f ,f,Ym")))]
3762169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387 && flag_unsafe_math_optimizations"
376318334Speter{
376490286Sobrien  switch (which_alternative)
376590286Sobrien    {
376690286Sobrien    case 0:
376790286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
376890286Sobrien	return "fstp%z0\t%y0";
376990286Sobrien      else
377090286Sobrien	return "fst%z0\t%y0";
3771169699Skan    case 1:
3772169699Skan      return output_387_reg_move (insn, operands);
3773169699Skan    case 2:
3774169699Skan      return "cvtsd2ss\t{%1, %0|%0, %1}";
377590286Sobrien    default:
3776169699Skan      gcc_unreachable ();
377790286Sobrien    }
377890286Sobrien}
3779169699Skan  [(set_attr "type" "fmov,fmov,ssecvt")
3780169699Skan   (set_attr "mode" "SF")])
378118334Speter
3782169699Skan;; Yes, this one doesn't depend on flag_unsafe_math_optimizations,
3783169699Skan;; because nothing we do here is unsafe.
3784169699Skan(define_insn "*truncdfsf_fast_sse"
3785169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=Y")
3786169699Skan        (float_truncate:SF
3787169699Skan          (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
3788169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
3789169699Skan  "cvtsd2ss\t{%1, %0|%0, %1}"
3790169699Skan  [(set_attr "type" "ssecvt")
3791169699Skan   (set_attr "mode" "SF")])
3792169699Skan
3793169699Skan(define_insn "*truncdfsf_fast_i387"
3794169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=fm")
3795169699Skan        (float_truncate:SF
3796169699Skan          (match_operand:DF 1 "nonimmediate_operand" "f")))]
3797169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3798169699Skan  "* return output_387_reg_move (insn, operands);"
3799169699Skan  [(set_attr "type" "fmov")
3800169699Skan   (set_attr "mode" "SF")])
3801169699Skan
3802169699Skan(define_insn "*truncdfsf_mixed"
3803169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,?fx*r,Y")
3804132727Skan	(float_truncate:SF
3805169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "f ,f    ,Ym")))
3806169699Skan   (clobber (match_operand:SF 2 "memory_operand"     "=X,m    ,X"))]
3807169699Skan  "TARGET_MIX_SSE_I387"
3808132727Skan{
3809132727Skan  switch (which_alternative)
3810132727Skan    {
3811132727Skan    case 0:
3812132727Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3813132727Skan	return "fstp%z0\t%y0";
3814132727Skan      else
3815132727Skan	return "fst%z0\t%y0";
3816169699Skan    case 1:
3817132727Skan      return "#";
3818169699Skan    case 2:
3819169699Skan      return "cvtsd2ss\t{%1, %0|%0, %1}";
3820132727Skan    default:
3821169699Skan      gcc_unreachable ();
3822132727Skan    }
3823132727Skan}
3824169699Skan  [(set_attr "type" "fmov,multi,ssecvt")
3825169699Skan   (set_attr "unit" "*,i387,*")
3826169699Skan   (set_attr "mode" "SF")])
3827132727Skan
3828169699Skan(define_insn "*truncdfsf_i387"
3829169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r")
383090286Sobrien	(float_truncate:SF
3831169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "f,f")))
3832169699Skan   (clobber (match_operand:SF 2 "memory_operand" "=X,m"))]
3833169699Skan  "TARGET_80387"
3834132727Skan{
3835132727Skan  switch (which_alternative)
3836132727Skan    {
3837132727Skan    case 0:
3838132727Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3839132727Skan	return "fstp%z0\t%y0";
3840132727Skan      else
3841132727Skan	return "fst%z0\t%y0";
3842169699Skan    case 1:
3843132727Skan      return "#";
384490286Sobrien    default:
3845169699Skan      gcc_unreachable ();
384690286Sobrien    }
384790286Sobrien}
3848169699Skan  [(set_attr "type" "fmov,multi")
3849169699Skan   (set_attr "unit" "*,i387")
3850169699Skan   (set_attr "mode" "SF")])
385152296Sobrien
3852169699Skan(define_insn "*truncdfsf2_i387_1"
385390286Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
385490286Sobrien	(float_truncate:SF
3855169699Skan	  (match_operand:DF 1 "register_operand" "f")))]
3856169699Skan  "TARGET_80387
3857169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)
3858169699Skan   && !TARGET_MIX_SSE_I387"
385990286Sobrien{
386090286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
386190286Sobrien    return "fstp%z0\t%y0";
386218334Speter  else
386390286Sobrien    return "fst%z0\t%y0";
386490286Sobrien}
386590286Sobrien  [(set_attr "type" "fmov")
386690286Sobrien   (set_attr "mode" "SF")])
386718334Speter
386852296Sobrien(define_split
3869132727Skan  [(set (match_operand:SF 0 "register_operand" "")
387090286Sobrien	(float_truncate:SF
3871169699Skan	 (match_operand:DF 1 "fp_register_operand" "")))
387290286Sobrien   (clobber (match_operand 2 "" ""))]
3873169699Skan  "reload_completed"
3874169699Skan  [(set (match_dup 2) (match_dup 1))
3875169699Skan   (set (match_dup 0) (match_dup 2))]
3876132727Skan{
3877169699Skan  operands[1] = gen_rtx_REG (SFmode, true_regnum (operands[1]));
3878132727Skan})
387990286Sobrien
3880169699Skan;; Conversion from XFmode to SFmode.
3881132727Skan
388290286Sobrien(define_expand "truncxfsf2"
388390286Sobrien  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
388490286Sobrien		   (float_truncate:SF
388590286Sobrien		    (match_operand:XF 1 "register_operand" "")))
388690286Sobrien	      (clobber (match_dup 2))])]
3887132727Skan  "TARGET_80387"
3888169699Skan{
3889169699Skan  if (flag_unsafe_math_optimizations)
3890169699Skan    {
3891169699Skan      rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SFmode);
3892169699Skan      emit_insn (gen_truncxfsf2_i387_noop (reg, operands[1]));
3893169699Skan      if (reg != operands[0])
3894169699Skan	emit_move_insn (operands[0], reg);
3895169699Skan      DONE;
3896169699Skan    }
3897169699Skan  else
3898171835Skan    operands[2] = assign_386_stack_local (SFmode, SLOT_VIRTUAL);
3899169699Skan})
390052296Sobrien
3901169699Skan(define_insn "*truncxfsf2_mixed"
3902169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x")
390390286Sobrien	(float_truncate:SF
390490286Sobrien	 (match_operand:XF 1 "register_operand" "f,f,f,f")))
390590286Sobrien   (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
3906169699Skan  "TARGET_MIX_SSE_I387"
390790286Sobrien{
3908169699Skan  gcc_assert (!which_alternative);
3909169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3910169699Skan    return "fstp%z0\t%y0";
3911169699Skan  else
3912169699Skan    return "fst%z0\t%y0";
391390286Sobrien}
391490286Sobrien  [(set_attr "type" "fmov,multi,multi,multi")
3915169699Skan   (set_attr "unit" "*,i387,i387,i387")
391690286Sobrien   (set_attr "mode" "SF")])
391790286Sobrien
3918169699Skan(define_insn "truncxfsf2_i387_noop"
3919169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
3920169699Skan	(float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
3921169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3922169699Skan{
3923169699Skan  return output_387_reg_move (insn, operands);
3924169699Skan}
3925169699Skan  [(set_attr "type" "fmov")
3926169699Skan   (set_attr "mode" "SF")])
3927169699Skan
3928169699Skan(define_insn "*truncxfsf2_i387"
3929169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r")
3930169699Skan	(float_truncate:SF
3931169699Skan	 (match_operand:XF 1 "register_operand" "f,f,f")))
3932169699Skan   (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
3933169699Skan  "TARGET_80387"
3934169699Skan{
3935169699Skan  gcc_assert (!which_alternative);
3936169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3937169699Skan    return "fstp%z0\t%y0";
3938169699Skan   else
3939169699Skan     return "fst%z0\t%y0";
3940169699Skan}
3941169699Skan  [(set_attr "type" "fmov,multi,multi")
3942169699Skan   (set_attr "unit" "*,i387,i387")
3943169699Skan   (set_attr "mode" "SF")])
3944169699Skan
3945169699Skan(define_insn "*truncxfsf2_i387_1"
394652296Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
394790286Sobrien	(float_truncate:SF
394890286Sobrien	 (match_operand:XF 1 "register_operand" "f")))]
3949132727Skan  "TARGET_80387"
395018334Speter{
395190286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
395290286Sobrien    return "fstp%z0\t%y0";
395318334Speter  else
395490286Sobrien    return "fst%z0\t%y0";
395590286Sobrien}
395690286Sobrien  [(set_attr "type" "fmov")
395790286Sobrien   (set_attr "mode" "SF")])
395852296Sobrien
395990286Sobrien(define_split
3960169699Skan  [(set (match_operand:SF 0 "register_operand" "")
396190286Sobrien	(float_truncate:SF
396290286Sobrien	 (match_operand:XF 1 "register_operand" "")))
396390286Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
3964169699Skan  "TARGET_80387 && reload_completed"
3965169699Skan  [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
3966169699Skan   (set (match_dup 0) (match_dup 2))]
396790286Sobrien  "")
396890286Sobrien
396990286Sobrien(define_split
3970169699Skan  [(set (match_operand:SF 0 "memory_operand" "")
397190286Sobrien	(float_truncate:SF
397290286Sobrien	 (match_operand:XF 1 "register_operand" "")))
397390286Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
3974169699Skan  "TARGET_80387"
3975169699Skan  [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
397690286Sobrien  "")
397790286Sobrien
3978169699Skan;; Conversion from XFmode to DFmode.
3979169699Skan
398052296Sobrien(define_expand "truncxfdf2"
398152296Sobrien  [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
398252296Sobrien		   (float_truncate:DF
398352296Sobrien		    (match_operand:XF 1 "register_operand" "")))
398452296Sobrien	      (clobber (match_dup 2))])]
3985132727Skan  "TARGET_80387"
3986169699Skan{
3987169699Skan  if (flag_unsafe_math_optimizations)
3988169699Skan    {
3989169699Skan      rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DFmode);
3990169699Skan      emit_insn (gen_truncxfdf2_i387_noop (reg, operands[1]));
3991169699Skan      if (reg != operands[0])
3992169699Skan	emit_move_insn (operands[0], reg);
3993169699Skan      DONE;
3994169699Skan    }
3995169699Skan  else
3996171835Skan    operands[2] = assign_386_stack_local (DFmode, SLOT_VIRTUAL);
3997169699Skan})
399818334Speter
3999169699Skan(define_insn "*truncxfdf2_mixed"
4000169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y")
400152296Sobrien	(float_truncate:DF
400290286Sobrien	 (match_operand:XF 1 "register_operand" "f,f,f,f")))
400390286Sobrien   (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
4004169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387"
400518334Speter{
4006169699Skan  gcc_assert (!which_alternative);
4007169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
4008169699Skan    return "fstp%z0\t%y0";
4009169699Skan  else
4010169699Skan    return "fst%z0\t%y0";
401190286Sobrien}
401290286Sobrien  [(set_attr "type" "fmov,multi,multi,multi")
4013169699Skan   (set_attr "unit" "*,i387,i387,i387")
401490286Sobrien   (set_attr "mode" "DF")])
401552296Sobrien
4016169699Skan(define_insn "truncxfdf2_i387_noop"
4017169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
4018169699Skan	(float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
4019169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
4020169699Skan{
4021169699Skan  return output_387_reg_move (insn, operands);
4022169699Skan}
4023169699Skan  [(set_attr "type" "fmov")
4024169699Skan   (set_attr "mode" "DF")])
4025169699Skan
4026169699Skan(define_insn "*truncxfdf2_i387"
4027169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r")
4028169699Skan	(float_truncate:DF
4029169699Skan	 (match_operand:XF 1 "register_operand" "f,f,f")))
4030169699Skan   (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
4031169699Skan  "TARGET_80387"
4032169699Skan{
4033169699Skan  gcc_assert (!which_alternative);
4034169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
4035169699Skan    return "fstp%z0\t%y0";
4036169699Skan  else
4037169699Skan    return "fst%z0\t%y0";
4038169699Skan}
4039169699Skan  [(set_attr "type" "fmov,multi,multi")
4040169699Skan   (set_attr "unit" "*,i387,i387")
4041169699Skan   (set_attr "mode" "DF")])
4042169699Skan
4043169699Skan(define_insn "*truncxfdf2_i387_1"
404490286Sobrien  [(set (match_operand:DF 0 "memory_operand" "=m")
404590286Sobrien	(float_truncate:DF
404690286Sobrien	  (match_operand:XF 1 "register_operand" "f")))]
4047132727Skan  "TARGET_80387"
404890286Sobrien{
404990286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
405090286Sobrien    return "fstp%z0\t%y0";
405190286Sobrien  else
405290286Sobrien    return "fst%z0\t%y0";
405390286Sobrien}
405490286Sobrien  [(set_attr "type" "fmov")
405590286Sobrien   (set_attr "mode" "DF")])
405652296Sobrien
405752296Sobrien(define_split
4058169699Skan  [(set (match_operand:DF 0 "register_operand" "")
405990286Sobrien	(float_truncate:DF
406090286Sobrien	 (match_operand:XF 1 "register_operand" "")))
406152296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
4062169699Skan  "TARGET_80387 && reload_completed"
4063169699Skan  [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
4064169699Skan   (set (match_dup 0) (match_dup 2))]
406552296Sobrien  "")
406652296Sobrien
406752296Sobrien(define_split
4068169699Skan  [(set (match_operand:DF 0 "memory_operand" "")
406990286Sobrien	(float_truncate:DF
407090286Sobrien	 (match_operand:XF 1 "register_operand" "")))
407152296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
4072169699Skan  "TARGET_80387"
4073169699Skan  [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
407452296Sobrien  "")
407590286Sobrien
407690286Sobrien;; Signed conversion to DImode.
407790286Sobrien
407890286Sobrien(define_expand "fix_truncxfdi2"
4079169699Skan  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4080169699Skan                   (fix:DI (match_operand:XF 1 "register_operand" "")))
4081169699Skan	      (clobber (reg:CC FLAGS_REG))])]
408218334Speter  "TARGET_80387"
408318334Speter{
4084169699Skan  if (TARGET_FISTTP)
408590286Sobrien   {
4086169699Skan     emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
408790286Sobrien     DONE;
408890286Sobrien   }
408990286Sobrien})
409018334Speter
4091169699Skan(define_expand "fix_trunc<mode>di2"
4092169699Skan  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4093169699Skan                   (fix:DI (match_operand:SSEMODEF 1 "register_operand" "")))
4094169699Skan              (clobber (reg:CC FLAGS_REG))])]
4095169699Skan  "TARGET_80387 || (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))"
409690286Sobrien{
4097169699Skan  if (TARGET_FISTTP
4098169699Skan      && !(TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
409990286Sobrien   {
4100169699Skan     emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
4101169699Skan     DONE;
4102169699Skan   }
4103169699Skan  if (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))
4104169699Skan   {
410590286Sobrien     rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
4106169699Skan     emit_insn (gen_fix_trunc<mode>di_sse (out, operands[1]));
410790286Sobrien     if (out != operands[0])
410890286Sobrien	emit_move_insn (operands[0], out);
410990286Sobrien     DONE;
411090286Sobrien   }
411190286Sobrien})
411252296Sobrien
411390286Sobrien;; Signed conversion to SImode.
411490286Sobrien
411552296Sobrien(define_expand "fix_truncxfsi2"
4116169699Skan  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
4117169699Skan                   (fix:SI (match_operand:XF 1 "register_operand" "")))
4118169699Skan	      (clobber (reg:CC FLAGS_REG))])]
411918334Speter  "TARGET_80387"
412018334Speter{
4121169699Skan  if (TARGET_FISTTP)
412290286Sobrien   {
4123169699Skan     emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
412490286Sobrien     DONE;
412590286Sobrien   }
412690286Sobrien})
412718334Speter
4128169699Skan(define_expand "fix_trunc<mode>si2"
4129169699Skan  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
4130169699Skan	           (fix:SI (match_operand:SSEMODEF 1 "register_operand" "")))
4131169699Skan	      (clobber (reg:CC FLAGS_REG))])]
4132169699Skan  "TARGET_80387 || SSE_FLOAT_MODE_P (<MODE>mode)"
413390286Sobrien{
4134169699Skan  if (TARGET_FISTTP
4135169699Skan      && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
413690286Sobrien   {
4137169699Skan     emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
4138169699Skan     DONE;
4139169699Skan   }
4140169699Skan  if (SSE_FLOAT_MODE_P (<MODE>mode))
4141169699Skan   {
414290286Sobrien     rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
4143169699Skan     emit_insn (gen_fix_trunc<mode>si_sse (out, operands[1]));
414490286Sobrien     if (out != operands[0])
414590286Sobrien	emit_move_insn (operands[0], out);
414690286Sobrien     DONE;
414790286Sobrien   }
414890286Sobrien})
414952296Sobrien
4150169699Skan;; Signed conversion to HImode.
4151169699Skan
4152169699Skan(define_expand "fix_trunc<mode>hi2"
4153169699Skan  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
4154169699Skan	           (fix:HI (match_operand:X87MODEF 1 "register_operand" "")))
4155169699Skan              (clobber (reg:CC FLAGS_REG))])]
4156169699Skan  "TARGET_80387
4157169699Skan   && !(SSE_FLOAT_MODE_P (<MODE>mode) && (!TARGET_FISTTP || TARGET_SSE_MATH))"
415818334Speter{
4159169699Skan  if (TARGET_FISTTP)
4160169699Skan   {
4161169699Skan     emit_insn (gen_fix_trunchi_fisttp_i387_1 (operands[0], operands[1]));
4162169699Skan     DONE;
4163169699Skan   }
4164169699Skan})
416518334Speter
4166169699Skan;; When SSE is available, it is always faster to use it!
4167169699Skan(define_insn "fix_truncsfdi_sse"
4168169699Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
4169169699Skan	(fix:DI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
4170169699Skan  "TARGET_64BIT && TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
4171169699Skan  "cvttss2si{q}\t{%1, %0|%0, %1}"
4172169699Skan  [(set_attr "type" "sseicvt")
4173169699Skan   (set_attr "mode" "SF")
4174251212Spfg   (set_attr "athlon_decode" "double,vector")
4175251212Spfg   (set_attr "amdfam10_decode" "double,double")])
417690286Sobrien
4177169699Skan(define_insn "fix_truncdfdi_sse"
4178169699Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
4179169699Skan	(fix:DI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
4180169699Skan  "TARGET_64BIT && TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
4181169699Skan  "cvttsd2si{q}\t{%1, %0|%0, %1}"
4182169699Skan  [(set_attr "type" "sseicvt")
4183169699Skan   (set_attr "mode" "DF")
4184251212Spfg   (set_attr "athlon_decode" "double,vector")
4185251212Spfg   (set_attr "amdfam10_decode" "double,double")])
418618334Speter
418790286Sobrien(define_insn "fix_truncsfsi_sse"
4188132727Skan  [(set (match_operand:SI 0 "register_operand" "=r,r")
4189132727Skan	(fix:SI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
4190169699Skan  "TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
419190286Sobrien  "cvttss2si\t{%1, %0|%0, %1}"
4192132727Skan  [(set_attr "type" "sseicvt")
4193132727Skan   (set_attr "mode" "DF")
4194251212Spfg   (set_attr "athlon_decode" "double,vector")
4195251212Spfg   (set_attr "amdfam10_decode" "double,double")])
419652296Sobrien
419790286Sobrien(define_insn "fix_truncdfsi_sse"
4198132727Skan  [(set (match_operand:SI 0 "register_operand" "=r,r")
4199132727Skan	(fix:SI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
4200169699Skan  "TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
420190286Sobrien  "cvttsd2si\t{%1, %0|%0, %1}"
4202132727Skan  [(set_attr "type" "sseicvt")
4203132727Skan   (set_attr "mode" "DF")
4204251212Spfg   (set_attr "athlon_decode" "double,vector")
4205251212Spfg   (set_attr "amdfam10_decode" "double,double")])
420652296Sobrien
4207169699Skan;; Avoid vector decoded forms of the instruction.
4208132727Skan(define_peephole2
4209132727Skan  [(match_scratch:DF 2 "Y")
4210169699Skan   (set (match_operand:SSEMODEI24 0 "register_operand" "")
4211169699Skan	(fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))]
4212169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
4213132727Skan  [(set (match_dup 2) (match_dup 1))
4214169699Skan   (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
4215132727Skan  "")
4216132727Skan
4217169699Skan(define_peephole2
4218169699Skan  [(match_scratch:SF 2 "x")
4219169699Skan   (set (match_operand:SSEMODEI24 0 "register_operand" "")
4220169699Skan	(fix:SSEMODEI24 (match_operand:SF 1 "memory_operand" "")))]
4221169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
4222169699Skan  [(set (match_dup 2) (match_dup 1))
4223169699Skan   (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
422490286Sobrien  "")
422518334Speter
4226169699Skan(define_insn_and_split "fix_trunc<mode>_fisttp_i387_1"
4227169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4228169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))]
4229169699Skan  "TARGET_FISTTP
4230169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4231169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4232169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4233169699Skan	&& TARGET_SSE_MATH)
4234169699Skan   && !(reload_completed || reload_in_progress)"
4235169699Skan  "#"
4236169699Skan  "&& 1"
4237169699Skan  [(const_int 0)]
4238169699Skan{
4239169699Skan  if (memory_operand (operands[0], VOIDmode))
4240169699Skan    emit_insn (gen_fix_trunc<mode>_i387_fisttp (operands[0], operands[1]));
4241169699Skan  else
4242169699Skan    {
4243169699Skan      operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
4244169699Skan      emit_insn (gen_fix_trunc<mode>_i387_fisttp_with_temp (operands[0],
4245169699Skan							    operands[1],
4246169699Skan							    operands[2]));
4247169699Skan    }
4248169699Skan  DONE;
4249169699Skan}
4250169699Skan  [(set_attr "type" "fisttp")
4251169699Skan   (set_attr "mode" "<MODE>")])
425252296Sobrien
4253169699Skan(define_insn "fix_trunc<mode>_i387_fisttp"
4254169699Skan  [(set (match_operand:X87MODEI 0 "memory_operand" "=m")
4255169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f")))
4256169699Skan   (clobber (match_scratch:XF 2 "=&1f"))]
4257169699Skan  "TARGET_FISTTP
4258169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4259169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4260169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4261169699Skan	&& TARGET_SSE_MATH)"
4262169699Skan  "* return output_fix_trunc (insn, operands, 1);"
4263169699Skan  [(set_attr "type" "fisttp")
4264169699Skan   (set_attr "mode" "<MODE>")])
426590286Sobrien
4266169699Skan(define_insn "fix_trunc<mode>_i387_fisttp_with_temp"
4267169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4268169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
4269169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" "=m,m"))
4270169699Skan   (clobber (match_scratch:XF 3 "=&1f,&1f"))]
4271169699Skan  "TARGET_FISTTP
4272169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4273169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4274169699Skan	&& (TARGET_64BIT || <MODE>mode != DImode))
4275169699Skan	&& TARGET_SSE_MATH)"
4276169699Skan  "#"
4277169699Skan  [(set_attr "type" "fisttp")
4278169699Skan   (set_attr "mode" "<MODE>")])
427918334Speter
4280169699Skan(define_split
4281169699Skan  [(set (match_operand:X87MODEI 0 "register_operand" "")
4282169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "")))
4283169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
4284169699Skan   (clobber (match_scratch 3 ""))]
4285169699Skan  "reload_completed"
4286169699Skan  [(parallel [(set (match_dup 2) (fix:X87MODEI (match_dup 1)))
4287169699Skan	      (clobber (match_dup 3))])
4288169699Skan   (set (match_dup 0) (match_dup 2))]
428990286Sobrien  "")
429018334Speter
4291169699Skan(define_split
4292169699Skan  [(set (match_operand:X87MODEI 0 "memory_operand" "")
4293169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "")))
4294169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
4295169699Skan   (clobber (match_scratch 3 ""))]
4296169699Skan  "reload_completed"
4297169699Skan  [(parallel [(set (match_dup 0) (fix:X87MODEI (match_dup 1)))
4298169699Skan	      (clobber (match_dup 3))])]
429990286Sobrien  "")
430052296Sobrien
430190286Sobrien;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
4302169699Skan;; of the machinery. Please note the clobber of FLAGS_REG. In i387 control
4303169699Skan;; word calculation (inserted by LCM in mode switching pass) a FLAGS_REG
4304169699Skan;; clobbering insns can be used. Look at emit_i387_cw_initialization ()
4305169699Skan;; function in i386.c.
4306169699Skan(define_insn_and_split "*fix_trunc<mode>_i387_1"
4307169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4308169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
4309169699Skan   (clobber (reg:CC FLAGS_REG))]
4310169699Skan  "TARGET_80387 && !TARGET_FISTTP
4311169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4312169699Skan   && !(SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4313169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4314169699Skan   && !(reload_completed || reload_in_progress)"
431590286Sobrien  "#"
4316169699Skan  "&& 1"
431790286Sobrien  [(const_int 0)]
431890286Sobrien{
4319169699Skan  ix86_optimize_mode_switching[I387_TRUNC] = 1;
4320169699Skan
4321169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
4322169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
432390286Sobrien  if (memory_operand (operands[0], VOIDmode))
4324169699Skan    emit_insn (gen_fix_trunc<mode>_i387 (operands[0], operands[1],
4325169699Skan					 operands[2], operands[3]));
432690286Sobrien  else
432790286Sobrien    {
4328169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
4329169699Skan      emit_insn (gen_fix_trunc<mode>_i387_with_temp (operands[0], operands[1],
4330169699Skan						     operands[2], operands[3],
4331169699Skan						     operands[4]));
433290286Sobrien    }
433390286Sobrien  DONE;
433490286Sobrien}
4335132727Skan  [(set_attr "type" "fistp")
4336169699Skan   (set_attr "i387_cw" "trunc")
4337169699Skan   (set_attr "mode" "<MODE>")])
433890286Sobrien
4339169699Skan(define_insn "fix_truncdi_i387"
4340169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
4341169699Skan	(fix:DI (match_operand 1 "register_operand" "f")))
4342169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
4343169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
4344169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
4345169699Skan  "TARGET_80387 && !TARGET_FISTTP
4346169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4347169699Skan   && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
4348169699Skan  "* return output_fix_trunc (insn, operands, 0);"
4349169699Skan  [(set_attr "type" "fistp")
4350169699Skan   (set_attr "i387_cw" "trunc")
4351169699Skan   (set_attr "mode" "DI")])
4352169699Skan
4353169699Skan(define_insn "fix_truncdi_i387_with_temp"
4354169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
4355169699Skan	(fix:DI (match_operand 1 "register_operand" "f,f")))
435690286Sobrien   (use (match_operand:HI 2 "memory_operand" "m,m"))
435790286Sobrien   (use (match_operand:HI 3 "memory_operand" "m,m"))
4358169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
4359169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
4360169699Skan  "TARGET_80387 && !TARGET_FISTTP
4361169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4362169699Skan   && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
436390286Sobrien  "#"
4364132727Skan  [(set_attr "type" "fistp")
4365169699Skan   (set_attr "i387_cw" "trunc")
4366169699Skan   (set_attr "mode" "DI")])
436790286Sobrien
4368259563Spfg(define_split
4369169699Skan  [(set (match_operand:DI 0 "register_operand" "")
4370169699Skan	(fix:DI (match_operand 1 "register_operand" "")))
4371169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
4372169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
4373169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
4374169699Skan   (clobber (match_scratch 5 ""))]
4375169699Skan  "reload_completed"
4376169699Skan  [(parallel [(set (match_dup 4) (fix:DI (match_dup 1)))
4377169699Skan	      (use (match_dup 2))
4378169699Skan	      (use (match_dup 3))
4379169699Skan	      (clobber (match_dup 5))])
4380169699Skan   (set (match_dup 0) (match_dup 4))]
4381169699Skan  "")
4382169699Skan
4383259563Spfg(define_split
4384169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
4385169699Skan	(fix:DI (match_operand 1 "register_operand" "")))
4386169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
4387169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
4388169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
4389169699Skan   (clobber (match_scratch 5 ""))]
4390169699Skan  "reload_completed"
4391169699Skan  [(parallel [(set (match_dup 0) (fix:DI (match_dup 1)))
4392169699Skan	      (use (match_dup 2))
4393169699Skan	      (use (match_dup 3))
4394169699Skan	      (clobber (match_dup 5))])]
4395169699Skan  "")
4396169699Skan
4397169699Skan(define_insn "fix_trunc<mode>_i387"
4398169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
4399169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "f")))
440090286Sobrien   (use (match_operand:HI 2 "memory_operand" "m"))
440190286Sobrien   (use (match_operand:HI 3 "memory_operand" "m"))]
4402169699Skan  "TARGET_80387 && !TARGET_FISTTP
4403169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
440490286Sobrien   && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
4405169699Skan  "* return output_fix_trunc (insn, operands, 0);"
4406132727Skan  [(set_attr "type" "fistp")
4407169699Skan   (set_attr "i387_cw" "trunc")
4408169699Skan   (set_attr "mode" "<MODE>")])
440990286Sobrien
4410169699Skan(define_insn "fix_trunc<mode>_i387_with_temp"
4411169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
4412169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "f,f")))
4413169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
4414169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
4415169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
4416169699Skan  "TARGET_80387 && !TARGET_FISTTP
4417169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4418169699Skan   && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
4419169699Skan  "#"
4420169699Skan  [(set_attr "type" "fistp")
4421169699Skan   (set_attr "i387_cw" "trunc")
4422169699Skan   (set_attr "mode" "<MODE>")])
4423169699Skan
4424259563Spfg(define_split
4425169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
4426169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
442790286Sobrien   (use (match_operand:HI 2 "memory_operand" ""))
442890286Sobrien   (use (match_operand:HI 3 "memory_operand" ""))
4429169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
443090286Sobrien  "reload_completed"
4431169699Skan  [(parallel [(set (match_dup 4) (fix:X87MODEI12 (match_dup 1)))
443290286Sobrien	      (use (match_dup 2))
4433169699Skan	      (use (match_dup 3))])
4434169699Skan   (set (match_dup 0) (match_dup 4))]
443518334Speter  "")
443618334Speter
4437259563Spfg(define_split
4438169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
4439169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
444090286Sobrien   (use (match_operand:HI 2 "memory_operand" ""))
444190286Sobrien   (use (match_operand:HI 3 "memory_operand" ""))
4442169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
444390286Sobrien  "reload_completed"
4444169699Skan  [(parallel [(set (match_dup 0) (fix:X87MODEI12 (match_dup 1)))
444590286Sobrien	      (use (match_dup 2))
4446169699Skan	      (use (match_dup 3))])]
444752296Sobrien  "")
444852296Sobrien
444990286Sobrien(define_insn "x86_fnstcw_1"
445090286Sobrien  [(set (match_operand:HI 0 "memory_operand" "=m")
4451237021Spfg	(unspec:HI [(reg:HI FPSR_REG)] UNSPEC_FSTCW))]
445252296Sobrien  "TARGET_80387"
445390286Sobrien  "fnstcw\t%0"
445490286Sobrien  [(set_attr "length" "2")
445590286Sobrien   (set_attr "mode" "HI")
4456169699Skan   (set_attr "unit" "i387")])
445752296Sobrien
445890286Sobrien(define_insn "x86_fldcw_1"
4459237021Spfg  [(set (reg:HI FPSR_REG)
4460117404Skan	(unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))]
446152296Sobrien  "TARGET_80387"
446290286Sobrien  "fldcw\t%0"
446390286Sobrien  [(set_attr "length" "2")
446490286Sobrien   (set_attr "mode" "HI")
4465117404Skan   (set_attr "unit" "i387")
4466251212Spfg   (set_attr "athlon_decode" "vector")
4467251212Spfg   (set_attr "amdfam10_decode" "vector")])   
446890286Sobrien
446990286Sobrien;; Conversion between fixed point and floating point.
447052296Sobrien
447190286Sobrien;; Even though we only accept memory inputs, the backend _really_
447290286Sobrien;; wants to be able to do this between registers.
447390286Sobrien
4474132727Skan(define_expand "floathisf2"
4475132727Skan  [(set (match_operand:SF 0 "register_operand" "")
4476132727Skan	(float:SF (match_operand:HI 1 "nonimmediate_operand" "")))]
4477169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
4478132727Skan{
4479169699Skan  if (TARGET_SSE_MATH)
4480132727Skan    {
4481132727Skan      emit_insn (gen_floatsisf2 (operands[0],
4482132727Skan				 convert_to_mode (SImode, operands[1], 0)));
4483132727Skan      DONE;
4484132727Skan    }
4485132727Skan})
4486132727Skan
4487169699Skan(define_insn "*floathisf2_i387"
448852296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
4489169699Skan	(float:SF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
4490169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
449190286Sobrien  "@
449290286Sobrien   fild%z1\t%1
449390286Sobrien   #"
449490286Sobrien  [(set_attr "type" "fmov,multi")
449590286Sobrien   (set_attr "mode" "SF")
4496169699Skan   (set_attr "unit" "*,i387")
449790286Sobrien   (set_attr "fp_int_src" "true")])
449852296Sobrien
449990286Sobrien(define_expand "floatsisf2"
450018334Speter  [(set (match_operand:SF 0 "register_operand" "")
450190286Sobrien	(float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
4502169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
450318334Speter  "")
450418334Speter
4505169699Skan(define_insn "*floatsisf2_mixed"
4506169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
4507132727Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
4508169699Skan  "TARGET_MIX_SSE_I387"
450990286Sobrien  "@
451090286Sobrien   fild%z1\t%1
451190286Sobrien   #
4512132727Skan   cvtsi2ss\t{%1, %0|%0, %1}
451390286Sobrien   cvtsi2ss\t{%1, %0|%0, %1}"
4514132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
451590286Sobrien   (set_attr "mode" "SF")
4516169699Skan   (set_attr "unit" "*,i387,*,*")
4517132727Skan   (set_attr "athlon_decode" "*,*,vector,double")
4518251212Spfg   (set_attr "amdfam10_decode" "*,*,vector,double")
451990286Sobrien   (set_attr "fp_int_src" "true")])
452090286Sobrien
452190286Sobrien(define_insn "*floatsisf2_sse"
4522132727Skan  [(set (match_operand:SF 0 "register_operand" "=x,x")
4523132727Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
4524169699Skan  "TARGET_SSE_MATH"
452590286Sobrien  "cvtsi2ss\t{%1, %0|%0, %1}"
4526132727Skan  [(set_attr "type" "sseicvt")
452790286Sobrien   (set_attr "mode" "SF")
4528132727Skan   (set_attr "athlon_decode" "vector,double")
4529251212Spfg   (set_attr "amdfam10_decode" "vector,double")
453090286Sobrien   (set_attr "fp_int_src" "true")])
453190286Sobrien
4532169699Skan(define_insn "*floatsisf2_i387"
4533169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
4534169699Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
4535169699Skan  "TARGET_80387"
453690286Sobrien  "@
453790286Sobrien   fild%z1\t%1
453890286Sobrien   #"
453990286Sobrien  [(set_attr "type" "fmov,multi")
454090286Sobrien   (set_attr "mode" "SF")
4541169699Skan   (set_attr "unit" "*,i387")
454290286Sobrien   (set_attr "fp_int_src" "true")])
454352296Sobrien
4544169699Skan(define_expand "floatdisf2"
4545169699Skan  [(set (match_operand:SF 0 "register_operand" "")
4546169699Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
4547169699Skan  "TARGET_80387 || (TARGET_64BIT && TARGET_SSE_MATH)"
4548169699Skan  "")
4549169699Skan
4550169699Skan(define_insn "*floatdisf2_mixed"
4551169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
4552132727Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
4553169699Skan  "TARGET_64BIT && TARGET_MIX_SSE_I387"
455490286Sobrien  "@
455590286Sobrien   fild%z1\t%1
455690286Sobrien   #
4557132727Skan   cvtsi2ss{q}\t{%1, %0|%0, %1}
455890286Sobrien   cvtsi2ss{q}\t{%1, %0|%0, %1}"
4559132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
456090286Sobrien   (set_attr "mode" "SF")
4561169699Skan   (set_attr "unit" "*,i387,*,*")
4562132727Skan   (set_attr "athlon_decode" "*,*,vector,double")
4563251212Spfg   (set_attr "amdfam10_decode" "*,*,vector,double")
456490286Sobrien   (set_attr "fp_int_src" "true")])
456552296Sobrien
456690286Sobrien(define_insn "*floatdisf2_sse"
4567132727Skan  [(set (match_operand:SF 0 "register_operand" "=x,x")
4568132727Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
4569169699Skan  "TARGET_64BIT && TARGET_SSE_MATH"
457090286Sobrien  "cvtsi2ss{q}\t{%1, %0|%0, %1}"
4571132727Skan  [(set_attr "type" "sseicvt")
457290286Sobrien   (set_attr "mode" "SF")
4573132727Skan   (set_attr "athlon_decode" "vector,double")
4574251212Spfg   (set_attr "amdfam10_decode" "vector,double")
457590286Sobrien   (set_attr "fp_int_src" "true")])
457690286Sobrien
4577169699Skan(define_insn "*floatdisf2_i387"
4578169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
4579169699Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
4580169699Skan  "TARGET_80387"
4581169699Skan  "@
4582169699Skan   fild%z1\t%1
4583169699Skan   #"
4584169699Skan  [(set_attr "type" "fmov,multi")
4585169699Skan   (set_attr "mode" "SF")
4586169699Skan   (set_attr "unit" "*,i387")
4587169699Skan   (set_attr "fp_int_src" "true")])
4588132727Skan
4589132727Skan(define_expand "floathidf2"
4590132727Skan  [(set (match_operand:DF 0 "register_operand" "")
4591132727Skan	(float:DF (match_operand:HI 1 "nonimmediate_operand" "")))]
4592169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
4593132727Skan{
4594169699Skan  if (TARGET_SSE2 && TARGET_SSE_MATH)
4595132727Skan    {
4596132727Skan      emit_insn (gen_floatsidf2 (operands[0],
4597132727Skan				 convert_to_mode (SImode, operands[1], 0)));
4598132727Skan      DONE;
4599132727Skan    }
4600132727Skan})
4601132727Skan
4602169699Skan(define_insn "*floathidf2_i387"
460352296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
4604169699Skan	(float:DF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
4605169699Skan  "TARGET_80387 && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
460690286Sobrien  "@
460790286Sobrien   fild%z1\t%1
460890286Sobrien   #"
460990286Sobrien  [(set_attr "type" "fmov,multi")
461090286Sobrien   (set_attr "mode" "DF")
4611169699Skan   (set_attr "unit" "*,i387")
461290286Sobrien   (set_attr "fp_int_src" "true")])
461352296Sobrien
461490286Sobrien(define_expand "floatsidf2"
461518334Speter  [(set (match_operand:DF 0 "register_operand" "")
461690286Sobrien	(float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
4617169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
461852296Sobrien  "")
461952296Sobrien
4620169699Skan(define_insn "*floatsidf2_mixed"
4621169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
4622132727Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
4623169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387"
462490286Sobrien  "@
462590286Sobrien   fild%z1\t%1
462690286Sobrien   #
4627132727Skan   cvtsi2sd\t{%1, %0|%0, %1}
462890286Sobrien   cvtsi2sd\t{%1, %0|%0, %1}"
4629132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
463090286Sobrien   (set_attr "mode" "DF")
4631169699Skan   (set_attr "unit" "*,i387,*,*")
4632132727Skan   (set_attr "athlon_decode" "*,*,double,direct")
4633251212Spfg   (set_attr "amdfam10_decode" "*,*,vector,double")
463490286Sobrien   (set_attr "fp_int_src" "true")])
463590286Sobrien
463690286Sobrien(define_insn "*floatsidf2_sse"
4637132727Skan  [(set (match_operand:DF 0 "register_operand" "=Y,Y")
4638132727Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
4639169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
464090286Sobrien  "cvtsi2sd\t{%1, %0|%0, %1}"
4641132727Skan  [(set_attr "type" "sseicvt")
464290286Sobrien   (set_attr "mode" "DF")
4643132727Skan   (set_attr "athlon_decode" "double,direct")
4644251212Spfg   (set_attr "amdfam10_decode" "vector,double")
464590286Sobrien   (set_attr "fp_int_src" "true")])
464690286Sobrien
4647169699Skan(define_insn "*floatsidf2_i387"
4648169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
4649169699Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
4650169699Skan  "TARGET_80387"
465190286Sobrien  "@
465290286Sobrien   fild%z1\t%1
465390286Sobrien   #"
465490286Sobrien  [(set_attr "type" "fmov,multi")
465590286Sobrien   (set_attr "mode" "DF")
4656169699Skan   (set_attr "unit" "*,i387")
465790286Sobrien   (set_attr "fp_int_src" "true")])
465890286Sobrien
4659169699Skan(define_expand "floatdidf2"
4660169699Skan  [(set (match_operand:DF 0 "register_operand" "")
4661169699Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
4662169699Skan  "TARGET_80387 || (TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH)"
4663169699Skan  "")
4664169699Skan
4665169699Skan(define_insn "*floatdidf2_mixed"
4666169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
4667132727Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
4668169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
466990286Sobrien  "@
467090286Sobrien   fild%z1\t%1
467190286Sobrien   #
4672132727Skan   cvtsi2sd{q}\t{%1, %0|%0, %1}
467390286Sobrien   cvtsi2sd{q}\t{%1, %0|%0, %1}"
4674132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
467590286Sobrien   (set_attr "mode" "DF")
4676169699Skan   (set_attr "unit" "*,i387,*,*")
4677132727Skan   (set_attr "athlon_decode" "*,*,double,direct")
4678251212Spfg   (set_attr "amdfam10_decode" "*,*,vector,double")
467990286Sobrien   (set_attr "fp_int_src" "true")])
468090286Sobrien
468190286Sobrien(define_insn "*floatdidf2_sse"
4682132727Skan  [(set (match_operand:DF 0 "register_operand" "=Y,Y")
4683132727Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
4684169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
468590286Sobrien  "cvtsi2sd{q}\t{%1, %0|%0, %1}"
4686132727Skan  [(set_attr "type" "sseicvt")
468790286Sobrien   (set_attr "mode" "DF")
4688132727Skan   (set_attr "athlon_decode" "double,direct")
4689251212Spfg   (set_attr "amdfam10_decode" "vector,double")
469090286Sobrien   (set_attr "fp_int_src" "true")])
469190286Sobrien
4692169699Skan(define_insn "*floatdidf2_i387"
4693169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
4694169699Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
4695169699Skan  "TARGET_80387"
4696169699Skan  "@
4697169699Skan   fild%z1\t%1
4698169699Skan   #"
4699169699Skan  [(set_attr "type" "fmov,multi")
4700169699Skan   (set_attr "mode" "DF")
4701169699Skan   (set_attr "unit" "*,i387")
4702169699Skan   (set_attr "fp_int_src" "true")])
4703169699Skan
470490286Sobrien(define_insn "floathixf2"
470590286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4706169699Skan	(float:XF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
470718334Speter  "TARGET_80387"
470890286Sobrien  "@
470990286Sobrien   fild%z1\t%1
471090286Sobrien   #"
471190286Sobrien  [(set_attr "type" "fmov,multi")
471290286Sobrien   (set_attr "mode" "XF")
4713169699Skan   (set_attr "unit" "*,i387")
471490286Sobrien   (set_attr "fp_int_src" "true")])
471552296Sobrien
471690286Sobrien(define_insn "floatsixf2"
471790286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4718169699Skan	(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
471952296Sobrien  "TARGET_80387"
472090286Sobrien  "@
472190286Sobrien   fild%z1\t%1
472290286Sobrien   #"
472390286Sobrien  [(set_attr "type" "fmov,multi")
472490286Sobrien   (set_attr "mode" "XF")
4725169699Skan   (set_attr "unit" "*,i387")
472690286Sobrien   (set_attr "fp_int_src" "true")])
472752296Sobrien
472890286Sobrien(define_insn "floatdixf2"
472990286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4730169699Skan	(float:XF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
473152296Sobrien  "TARGET_80387"
473290286Sobrien  "@
473390286Sobrien   fild%z1\t%1
473490286Sobrien   #"
473590286Sobrien  [(set_attr "type" "fmov,multi")
473690286Sobrien   (set_attr "mode" "XF")
4737169699Skan   (set_attr "unit" "*,i387")
473890286Sobrien   (set_attr "fp_int_src" "true")])
473952296Sobrien
474090286Sobrien;; %%% Kill these when reload knows how to do it.
474152296Sobrien(define_split
4742117404Skan  [(set (match_operand 0 "fp_register_operand" "")
474390286Sobrien	(float (match_operand 1 "register_operand" "")))]
4744169699Skan  "reload_completed
4745169699Skan   && TARGET_80387
4746169699Skan   && FLOAT_MODE_P (GET_MODE (operands[0]))"
474790286Sobrien  [(const_int 0)]
474890286Sobrien{
474990286Sobrien  operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
475090286Sobrien  operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]);
475190286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[2]));
475290286Sobrien  ix86_free_from_memory (GET_MODE (operands[1]));
475390286Sobrien  DONE;
475490286Sobrien})
4755132727Skan
4756132727Skan(define_expand "floatunssisf2"
4757132727Skan  [(use (match_operand:SF 0 "register_operand" ""))
4758132727Skan   (use (match_operand:SI 1 "register_operand" ""))]
4759169699Skan  "!TARGET_64BIT && TARGET_SSE_MATH"
4760132727Skan  "x86_emit_floatuns (operands); DONE;")
4761132727Skan
4762132727Skan(define_expand "floatunsdisf2"
4763132727Skan  [(use (match_operand:SF 0 "register_operand" ""))
4764132727Skan   (use (match_operand:DI 1 "register_operand" ""))]
4765169699Skan  "TARGET_64BIT && TARGET_SSE_MATH"
4766132727Skan  "x86_emit_floatuns (operands); DONE;")
4767132727Skan
4768132727Skan(define_expand "floatunsdidf2"
4769132727Skan  [(use (match_operand:DF 0 "register_operand" ""))
4770132727Skan   (use (match_operand:DI 1 "register_operand" ""))]
4771169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
4772132727Skan  "x86_emit_floatuns (operands); DONE;")
477390286Sobrien
4774132727Skan;; SSE extract/set expanders
4775132727Skan
4776169699Skan
4777169699Skan;; Add instructions
4778132727Skan
4779169699Skan;; %%% splits for addditi3
4780132727Skan
4781169699Skan(define_expand "addti3"
4782169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
4783169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
4784169699Skan		 (match_operand:TI 2 "x86_64_general_operand" "")))
4785169699Skan   (clobber (reg:CC FLAGS_REG))]
4786169699Skan  "TARGET_64BIT"
4787169699Skan  "ix86_expand_binary_operator (PLUS, TImode, operands); DONE;")
4788132727Skan
4789169699Skan(define_insn "*addti3_1"
4790169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
4791169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0")
4792171835Skan		 (match_operand:TI 2 "x86_64_general_operand" "roe,re")))
4793169699Skan   (clobber (reg:CC FLAGS_REG))]
4794169699Skan  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)"
4795169699Skan  "#")
4796132727Skan
4797169699Skan(define_split
4798169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
4799169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
4800171835Skan		 (match_operand:TI 2 "x86_64_general_operand" "")))
4801169699Skan   (clobber (reg:CC FLAGS_REG))]
4802169699Skan  "TARGET_64BIT && reload_completed"
4803169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
4804169699Skan					  UNSPEC_ADD_CARRY))
4805169699Skan	      (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))])
4806169699Skan   (parallel [(set (match_dup 3)
4807169699Skan		   (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
4808169699Skan				     (match_dup 4))
4809169699Skan			    (match_dup 5)))
4810169699Skan	      (clobber (reg:CC FLAGS_REG))])]
4811169699Skan  "split_ti (operands+0, 1, operands+0, operands+3);
4812169699Skan   split_ti (operands+1, 1, operands+1, operands+4);
4813169699Skan   split_ti (operands+2, 1, operands+2, operands+5);")
4814132727Skan
481590286Sobrien;; %%% splits for addsidi3
481690286Sobrien;  [(set (match_operand:DI 0 "nonimmediate_operand" "")
481790286Sobrien;	(plus:DI (match_operand:DI 1 "general_operand" "")
481890286Sobrien;		 (zero_extend:DI (match_operand:SI 2 "general_operand" ""))))]
481952296Sobrien
482090286Sobrien(define_expand "adddi3"
482190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
482290286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
482390286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "")))
4824169699Skan   (clobber (reg:CC FLAGS_REG))]
482590286Sobrien  ""
482690286Sobrien  "ix86_expand_binary_operator (PLUS, DImode, operands); DONE;")
482752296Sobrien
482890286Sobrien(define_insn "*adddi3_1"
482990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
483090286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
483190286Sobrien		 (match_operand:DI 2 "general_operand" "roiF,riF")))
4832169699Skan   (clobber (reg:CC FLAGS_REG))]
4833107605Sobrien  "!TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
483452296Sobrien  "#")
483552296Sobrien
483652296Sobrien(define_split
483790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
483890286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
483990286Sobrien		 (match_operand:DI 2 "general_operand" "")))
4840169699Skan   (clobber (reg:CC FLAGS_REG))]
484190286Sobrien  "!TARGET_64BIT && reload_completed"
4842169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
4843117404Skan					  UNSPEC_ADD_CARRY))
484490286Sobrien	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
484590286Sobrien   (parallel [(set (match_dup 3)
4846169699Skan		   (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
484790286Sobrien				     (match_dup 4))
484890286Sobrien			    (match_dup 5)))
4849169699Skan	      (clobber (reg:CC FLAGS_REG))])]
485090286Sobrien  "split_di (operands+0, 1, operands+0, operands+3);
485190286Sobrien   split_di (operands+1, 1, operands+1, operands+4);
485290286Sobrien   split_di (operands+2, 1, operands+2, operands+5);")
485318334Speter
4854132727Skan(define_insn "adddi3_carry_rex64"
485590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
4856132727Skan	  (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
485790286Sobrien			    (match_operand:DI 1 "nonimmediate_operand" "%0,0"))
485890286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
4859169699Skan   (clobber (reg:CC FLAGS_REG))]
486090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
486190286Sobrien  "adc{q}\t{%2, %0|%0, %2}"
486290286Sobrien  [(set_attr "type" "alu")
486390286Sobrien   (set_attr "pent_pair" "pu")
4864169699Skan   (set_attr "mode" "DI")])
486552296Sobrien
486690286Sobrien(define_insn "*adddi3_cc_rex64"
4867169699Skan  [(set (reg:CC FLAGS_REG)
4868117404Skan	(unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0")
4869117404Skan		    (match_operand:DI 2 "x86_64_general_operand" "re,rm")]
4870117404Skan		   UNSPEC_ADD_CARRY))
487190286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
487290286Sobrien	(plus:DI (match_dup 1) (match_dup 2)))]
487390286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
487490286Sobrien  "add{q}\t{%2, %0|%0, %2}"
487590286Sobrien  [(set_attr "type" "alu")
487690286Sobrien   (set_attr "mode" "DI")])
487752296Sobrien
4878132727Skan(define_insn "addqi3_carry"
4879132727Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
4880132727Skan	  (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
4881132727Skan			    (match_operand:QI 1 "nonimmediate_operand" "%0,0"))
4882132727Skan		   (match_operand:QI 2 "general_operand" "qi,qm")))
4883169699Skan   (clobber (reg:CC FLAGS_REG))]
4884132727Skan  "ix86_binary_operator_ok (PLUS, QImode, operands)"
4885132727Skan  "adc{b}\t{%2, %0|%0, %2}"
4886132727Skan  [(set_attr "type" "alu")
4887132727Skan   (set_attr "pent_pair" "pu")
4888169699Skan   (set_attr "mode" "QI")])
4889132727Skan
4890132727Skan(define_insn "addhi3_carry"
4891132727Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
4892132727Skan	  (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
4893132727Skan			    (match_operand:HI 1 "nonimmediate_operand" "%0,0"))
4894132727Skan		   (match_operand:HI 2 "general_operand" "ri,rm")))
4895169699Skan   (clobber (reg:CC FLAGS_REG))]
4896132727Skan  "ix86_binary_operator_ok (PLUS, HImode, operands)"
4897132727Skan  "adc{w}\t{%2, %0|%0, %2}"
4898132727Skan  [(set_attr "type" "alu")
4899132727Skan   (set_attr "pent_pair" "pu")
4900169699Skan   (set_attr "mode" "HI")])
4901132727Skan
4902132727Skan(define_insn "addsi3_carry"
490390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
4904132727Skan	  (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
490590286Sobrien			    (match_operand:SI 1 "nonimmediate_operand" "%0,0"))
490690286Sobrien		   (match_operand:SI 2 "general_operand" "ri,rm")))
4907169699Skan   (clobber (reg:CC FLAGS_REG))]
490890286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
490990286Sobrien  "adc{l}\t{%2, %0|%0, %2}"
491090286Sobrien  [(set_attr "type" "alu")
491190286Sobrien   (set_attr "pent_pair" "pu")
4912169699Skan   (set_attr "mode" "SI")])
491352296Sobrien
491490286Sobrien(define_insn "*addsi3_carry_zext"
491590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
4916259563Spfg	  (zero_extend:DI
4917132727Skan	    (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
491890286Sobrien			      (match_operand:SI 1 "nonimmediate_operand" "%0"))
491990286Sobrien		     (match_operand:SI 2 "general_operand" "rim"))))
4920169699Skan   (clobber (reg:CC FLAGS_REG))]
492190286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
492290286Sobrien  "adc{l}\t{%2, %k0|%k0, %2}"
492390286Sobrien  [(set_attr "type" "alu")
492490286Sobrien   (set_attr "pent_pair" "pu")
4925169699Skan   (set_attr "mode" "SI")])
492652296Sobrien
492790286Sobrien(define_insn "*addsi3_cc"
4928169699Skan  [(set (reg:CC FLAGS_REG)
4929117404Skan	(unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0")
4930117404Skan		    (match_operand:SI 2 "general_operand" "ri,rm")]
4931117404Skan		   UNSPEC_ADD_CARRY))
493290286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
493390286Sobrien	(plus:SI (match_dup 1) (match_dup 2)))]
493490286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
493590286Sobrien  "add{l}\t{%2, %0|%0, %2}"
493690286Sobrien  [(set_attr "type" "alu")
493790286Sobrien   (set_attr "mode" "SI")])
493818334Speter
493990286Sobrien(define_insn "addqi3_cc"
4940169699Skan  [(set (reg:CC FLAGS_REG)
4941117404Skan	(unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0")
4942117404Skan		    (match_operand:QI 2 "general_operand" "qi,qm")]
4943117404Skan		   UNSPEC_ADD_CARRY))
494490286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
494590286Sobrien	(plus:QI (match_dup 1) (match_dup 2)))]
494690286Sobrien  "ix86_binary_operator_ok (PLUS, QImode, operands)"
494790286Sobrien  "add{b}\t{%2, %0|%0, %2}"
494890286Sobrien  [(set_attr "type" "alu")
494990286Sobrien   (set_attr "mode" "QI")])
495018334Speter
495190286Sobrien(define_expand "addsi3"
495290286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
495390286Sobrien		   (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
495490286Sobrien			    (match_operand:SI 2 "general_operand" "")))
4955169699Skan	      (clobber (reg:CC FLAGS_REG))])]
495690286Sobrien  ""
495790286Sobrien  "ix86_expand_binary_operator (PLUS, SImode, operands); DONE;")
495818334Speter
495990286Sobrien(define_insn "*lea_1"
496090286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
4961132727Skan	(match_operand:SI 1 "no_seg_address_operand" "p"))]
496290286Sobrien  "!TARGET_64BIT"
496390286Sobrien  "lea{l}\t{%a1, %0|%0, %a1}"
496490286Sobrien  [(set_attr "type" "lea")
496590286Sobrien   (set_attr "mode" "SI")])
496618334Speter
496790286Sobrien(define_insn "*lea_1_rex64"
496890286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
4969132727Skan	(subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))]
497090286Sobrien  "TARGET_64BIT"
497190286Sobrien  "lea{l}\t{%a1, %0|%0, %a1}"
497290286Sobrien  [(set_attr "type" "lea")
497390286Sobrien   (set_attr "mode" "SI")])
497418334Speter
497590286Sobrien(define_insn "*lea_1_zext"
497690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
4977132727Skan	(zero_extend:DI
4978132727Skan	 (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))]
497990286Sobrien  "TARGET_64BIT"
498090286Sobrien  "lea{l}\t{%a1, %k0|%k0, %a1}"
498190286Sobrien  [(set_attr "type" "lea")
498290286Sobrien   (set_attr "mode" "SI")])
498390286Sobrien
498490286Sobrien(define_insn "*lea_2_rex64"
498590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
4986132727Skan	(match_operand:DI 1 "no_seg_address_operand" "p"))]
498790286Sobrien  "TARGET_64BIT"
498890286Sobrien  "lea{q}\t{%a1, %0|%0, %a1}"
498990286Sobrien  [(set_attr "type" "lea")
499090286Sobrien   (set_attr "mode" "DI")])
499190286Sobrien
499290286Sobrien;; The lea patterns for non-Pmodes needs to be matched by several
499390286Sobrien;; insns converted to real lea by splitters.
499490286Sobrien
499590286Sobrien(define_insn_and_split "*lea_general_1"
499690286Sobrien  [(set (match_operand 0 "register_operand" "=r")
4997169699Skan	(plus (plus (match_operand 1 "index_register_operand" "l")
499890286Sobrien		    (match_operand 2 "register_operand" "r"))
499990286Sobrien	      (match_operand 3 "immediate_operand" "i")))]
500090286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
500190286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
500290286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
500390286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
500490286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[2])
500590286Sobrien   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
500690286Sobrien       || GET_MODE (operands[3]) == VOIDmode)"
500790286Sobrien  "#"
500890286Sobrien  "&& reload_completed"
500990286Sobrien  [(const_int 0)]
501090286Sobrien{
501190286Sobrien  rtx pat;
501290286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
501390286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
501490286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
501590286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
501690286Sobrien  pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]),
501790286Sobrien  		      operands[3]);
501890286Sobrien  if (Pmode != SImode)
501990286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
502090286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
502190286Sobrien  DONE;
502290286Sobrien}
502390286Sobrien  [(set_attr "type" "lea")
502490286Sobrien   (set_attr "mode" "SI")])
502590286Sobrien
502690286Sobrien(define_insn_and_split "*lea_general_1_zext"
502790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
502890286Sobrien	(zero_extend:DI
5029169699Skan	  (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "l")
503090286Sobrien			    (match_operand:SI 2 "register_operand" "r"))
503190286Sobrien		   (match_operand:SI 3 "immediate_operand" "i"))))]
503290286Sobrien  "TARGET_64BIT"
503390286Sobrien  "#"
503490286Sobrien  "&& reload_completed"
503552296Sobrien  [(set (match_dup 0)
503690286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1)
503790286Sobrien						     (match_dup 2))
503890286Sobrien					    (match_dup 3)) 0)))]
503990286Sobrien{
504090286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
504190286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
504290286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
504390286Sobrien}
504490286Sobrien  [(set_attr "type" "lea")
504590286Sobrien   (set_attr "mode" "SI")])
504652296Sobrien
504790286Sobrien(define_insn_and_split "*lea_general_2"
504890286Sobrien  [(set (match_operand 0 "register_operand" "=r")
5049169699Skan	(plus (mult (match_operand 1 "index_register_operand" "l")
505090286Sobrien		    (match_operand 2 "const248_operand" "i"))
505190286Sobrien	      (match_operand 3 "nonmemory_operand" "ri")))]
505290286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
505390286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
505490286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
505590286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
505690286Sobrien   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
505790286Sobrien       || GET_MODE (operands[3]) == VOIDmode)"
505890286Sobrien  "#"
505990286Sobrien  "&& reload_completed"
506090286Sobrien  [(const_int 0)]
506190286Sobrien{
506290286Sobrien  rtx pat;
506390286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
506490286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
506590286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
506690286Sobrien  pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]),
506790286Sobrien  		      operands[3]);
506890286Sobrien  if (Pmode != SImode)
506990286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
507090286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
507190286Sobrien  DONE;
507290286Sobrien}
507390286Sobrien  [(set_attr "type" "lea")
507490286Sobrien   (set_attr "mode" "SI")])
507552296Sobrien
507690286Sobrien(define_insn_and_split "*lea_general_2_zext"
507790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
507890286Sobrien	(zero_extend:DI
5079169699Skan	  (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "l")
508090286Sobrien			    (match_operand:SI 2 "const248_operand" "n"))
508190286Sobrien		   (match_operand:SI 3 "nonmemory_operand" "ri"))))]
508290286Sobrien  "TARGET_64BIT"
508390286Sobrien  "#"
508490286Sobrien  "&& reload_completed"
508590286Sobrien  [(set (match_dup 0)
508690286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1)
508790286Sobrien						     (match_dup 2))
508890286Sobrien					    (match_dup 3)) 0)))]
508990286Sobrien{
509090286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
509190286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
509290286Sobrien}
509390286Sobrien  [(set_attr "type" "lea")
509490286Sobrien   (set_attr "mode" "SI")])
509518334Speter
509690286Sobrien(define_insn_and_split "*lea_general_3"
509790286Sobrien  [(set (match_operand 0 "register_operand" "=r")
5098169699Skan	(plus (plus (mult (match_operand 1 "index_register_operand" "l")
509990286Sobrien			  (match_operand 2 "const248_operand" "i"))
510090286Sobrien		    (match_operand 3 "register_operand" "r"))
510190286Sobrien	      (match_operand 4 "immediate_operand" "i")))]
510290286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
510390286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
510490286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
510590286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
510690286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[3])"
510790286Sobrien  "#"
510890286Sobrien  "&& reload_completed"
510990286Sobrien  [(const_int 0)]
511090286Sobrien{
511190286Sobrien  rtx pat;
511290286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
511390286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
511490286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
511590286Sobrien  operands[4] = gen_lowpart (Pmode, operands[4]);
511690286Sobrien  pat = gen_rtx_PLUS (Pmode,
511790286Sobrien  		      gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1],
511890286Sobrien		      					 operands[2]),
511990286Sobrien				    operands[3]),
512090286Sobrien  		      operands[4]);
512190286Sobrien  if (Pmode != SImode)
512290286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
512390286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
512490286Sobrien  DONE;
512590286Sobrien}
512690286Sobrien  [(set_attr "type" "lea")
512790286Sobrien   (set_attr "mode" "SI")])
512852296Sobrien
512990286Sobrien(define_insn_and_split "*lea_general_3_zext"
513090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
513190286Sobrien	(zero_extend:DI
5132169699Skan	  (plus:SI (plus:SI (mult:SI
5133169699Skan			      (match_operand:SI 1 "index_register_operand" "l")
5134169699Skan			      (match_operand:SI 2 "const248_operand" "n"))
513590286Sobrien			    (match_operand:SI 3 "register_operand" "r"))
513690286Sobrien		   (match_operand:SI 4 "immediate_operand" "i"))))]
513790286Sobrien  "TARGET_64BIT"
513890286Sobrien  "#"
513990286Sobrien  "&& reload_completed"
514090286Sobrien  [(set (match_dup 0)
514190286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1)
514290286Sobrien							      (match_dup 2))
514390286Sobrien						     (match_dup 3))
514490286Sobrien					    (match_dup 4)) 0)))]
514590286Sobrien{
514690286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
514790286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
514890286Sobrien  operands[4] = gen_lowpart (Pmode, operands[4]);
514990286Sobrien}
515090286Sobrien  [(set_attr "type" "lea")
515190286Sobrien   (set_attr "mode" "SI")])
515218334Speter
515390286Sobrien(define_insn "*adddi_1_rex64"
515490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
515590286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r")
5156169699Skan		 (match_operand:DI 2 "x86_64_general_operand" "rme,re,le")))
5157169699Skan   (clobber (reg:CC FLAGS_REG))]
515890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
515990286Sobrien{
516090286Sobrien  switch (get_attr_type (insn))
516190286Sobrien    {
516290286Sobrien    case TYPE_LEA:
516390286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
516490286Sobrien      return "lea{q}\t{%a2, %0|%0, %a2}";
516590286Sobrien
516690286Sobrien    case TYPE_INCDEC:
5167169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
516890286Sobrien      if (operands[2] == const1_rtx)
516990286Sobrien        return "inc{q}\t%0";
517090286Sobrien      else
5171169699Skan        {
5172169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5173169699Skan          return "dec{q}\t%0";
5174169699Skan	}
517590286Sobrien
517690286Sobrien    default:
5177169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
517890286Sobrien
517990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
518090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
518190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
518290286Sobrien	  /* Avoid overflows.  */
518390286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
518490286Sobrien          && (INTVAL (operands[2]) == 128
518590286Sobrien	      || (INTVAL (operands[2]) < 0
518690286Sobrien		  && INTVAL (operands[2]) != -128)))
518790286Sobrien        {
518890286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
518990286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
519090286Sobrien        }
519190286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
519290286Sobrien    }
519390286Sobrien}
519490286Sobrien  [(set (attr "type")
519590286Sobrien     (cond [(eq_attr "alternative" "2")
519690286Sobrien	      (const_string "lea")
519790286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
519890286Sobrien	    ; ought but a memory context.
519990286Sobrien	    (match_operand:DI 2 "pic_symbolic_operand" "")
520090286Sobrien	      (const_string "lea")
520190286Sobrien	    (match_operand:DI 2 "incdec_operand" "")
520290286Sobrien	      (const_string "incdec")
520390286Sobrien	   ]
520490286Sobrien	   (const_string "alu")))
520590286Sobrien   (set_attr "mode" "DI")])
520690286Sobrien
520790286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
520852296Sobrien(define_split
520990286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
521090286Sobrien	(plus:DI (match_operand:DI 1 "register_operand" "")
521190286Sobrien		 (match_operand:DI 2 "x86_64_nonmemory_operand" "")))
5212169699Skan   (clobber (reg:CC FLAGS_REG))]
521390286Sobrien  "TARGET_64BIT && reload_completed
521490286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
521552296Sobrien  [(set (match_dup 0)
521690286Sobrien	(plus:DI (match_dup 1)
521790286Sobrien		 (match_dup 2)))]
521852296Sobrien  "")
521952296Sobrien
522090286Sobrien(define_insn "*adddi_2_rex64"
5221169699Skan  [(set (reg FLAGS_REG)
522290286Sobrien	(compare
522390286Sobrien	  (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
522490286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "rme,re"))
5225259563Spfg	  (const_int 0)))
522690286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
522790286Sobrien	(plus:DI (match_dup 1) (match_dup 2)))]
522890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
522990286Sobrien   && ix86_binary_operator_ok (PLUS, DImode, operands)
523090286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
523190286Sobrien      ought but a memory context.  */
523290286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
523390286Sobrien{
523490286Sobrien  switch (get_attr_type (insn))
523590286Sobrien    {
523690286Sobrien    case TYPE_INCDEC:
5237169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
523890286Sobrien      if (operands[2] == const1_rtx)
523990286Sobrien        return "inc{q}\t%0";
524090286Sobrien      else
5241169699Skan        {
5242169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5243169699Skan          return "dec{q}\t%0";
5244169699Skan	}
524552296Sobrien
524690286Sobrien    default:
5247169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
524890286Sobrien      /* ???? We ought to handle there the 32bit case too
5249132727Skan	 - do we need new constraint?  */
525090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
525190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
525290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
525390286Sobrien	  /* Avoid overflows.  */
525490286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
525590286Sobrien          && (INTVAL (operands[2]) == 128
525690286Sobrien	      || (INTVAL (operands[2]) < 0
525790286Sobrien		  && INTVAL (operands[2]) != -128)))
525890286Sobrien        {
525990286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
526090286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
526190286Sobrien        }
526290286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
526390286Sobrien    }
526490286Sobrien}
526590286Sobrien  [(set (attr "type")
526690286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
526790286Sobrien	(const_string "incdec")
526890286Sobrien	(const_string "alu")))
526990286Sobrien   (set_attr "mode" "DI")])
527018334Speter
527190286Sobrien(define_insn "*adddi_3_rex64"
5272169699Skan  [(set (reg FLAGS_REG)
527390286Sobrien	(compare (neg:DI (match_operand:DI 2 "x86_64_general_operand" "rme"))
527490286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "%0")))
527590286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
527690286Sobrien  "TARGET_64BIT
527790286Sobrien   && ix86_match_ccmode (insn, CCZmode)
527890286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
527990286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
528090286Sobrien      ought but a memory context.  */
528190286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
528250650Sobrien{
528390286Sobrien  switch (get_attr_type (insn))
528490286Sobrien    {
528590286Sobrien    case TYPE_INCDEC:
5286169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
528790286Sobrien      if (operands[2] == const1_rtx)
528890286Sobrien        return "inc{q}\t%0";
528990286Sobrien      else
5290169699Skan        {
5291169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5292169699Skan          return "dec{q}\t%0";
5293169699Skan	}
529450650Sobrien
529590286Sobrien    default:
5296169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
529790286Sobrien      /* ???? We ought to handle there the 32bit case too
5298132727Skan	 - do we need new constraint?  */
529990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
530090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
530190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
530290286Sobrien	  /* Avoid overflows.  */
530390286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
530490286Sobrien          && (INTVAL (operands[2]) == 128
530590286Sobrien	      || (INTVAL (operands[2]) < 0
530690286Sobrien		  && INTVAL (operands[2]) != -128)))
530790286Sobrien        {
530890286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
530990286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
531090286Sobrien        }
531190286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
531290286Sobrien    }
531390286Sobrien}
531490286Sobrien  [(set (attr "type")
531590286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
531690286Sobrien	(const_string "incdec")
531790286Sobrien	(const_string "alu")))
531890286Sobrien   (set_attr "mode" "DI")])
531950650Sobrien
532090286Sobrien; For comparisons against 1, -1 and 128, we may generate better code
532190286Sobrien; by converting cmp to add, inc or dec as done by peephole2.  This pattern
532290286Sobrien; is matched then.  We can't accept general immediate, because for
532390286Sobrien; case of overflows,  the result is messed up.
532490286Sobrien; This pattern also don't hold of 0x8000000000000000, since the value overflows
532590286Sobrien; when negated.
532690286Sobrien; Also carry flag is reversed compared to cmp, so this conversion is valid
532790286Sobrien; only for comparisons not depending on it.
532890286Sobrien(define_insn "*adddi_4_rex64"
5329169699Skan  [(set (reg FLAGS_REG)
533090286Sobrien	(compare (match_operand:DI 1 "nonimmediate_operand" "0")
533190286Sobrien		 (match_operand:DI 2 "x86_64_immediate_operand" "e")))
533290286Sobrien   (clobber (match_scratch:DI 0 "=rm"))]
533390286Sobrien  "TARGET_64BIT
533490286Sobrien   &&  ix86_match_ccmode (insn, CCGCmode)"
533590286Sobrien{
533690286Sobrien  switch (get_attr_type (insn))
533790286Sobrien    {
533890286Sobrien    case TYPE_INCDEC:
533990286Sobrien      if (operands[2] == constm1_rtx)
534090286Sobrien        return "inc{q}\t%0";
534190286Sobrien      else
5342169699Skan        {
5343169699Skan	  gcc_assert (operands[2] == const1_rtx);
5344169699Skan          return "dec{q}\t%0";
5345169699Skan	}
534650650Sobrien
534790286Sobrien    default:
5348169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
534990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
535090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
535190286Sobrien      if ((INTVAL (operands[2]) == -128
535290286Sobrien	   || (INTVAL (operands[2]) > 0
535390286Sobrien	       && INTVAL (operands[2]) != 128))
535490286Sobrien	  /* Avoid overflows.  */
535590286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))))
535690286Sobrien	return "sub{q}\t{%2, %0|%0, %2}";
535790286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
535890286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
535990286Sobrien    }
536090286Sobrien}
536190286Sobrien  [(set (attr "type")
536290286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
536390286Sobrien	(const_string "incdec")
536490286Sobrien	(const_string "alu")))
536590286Sobrien   (set_attr "mode" "DI")])
536690286Sobrien
536790286Sobrien(define_insn "*adddi_5_rex64"
5368169699Skan  [(set (reg FLAGS_REG)
536990286Sobrien	(compare
537090286Sobrien	  (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
537190286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "rme"))
5372259563Spfg	  (const_int 0)))
537390286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
537490286Sobrien  "TARGET_64BIT
537590286Sobrien   && ix86_match_ccmode (insn, CCGOCmode)
537690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
537790286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
537890286Sobrien      ought but a memory context.  */
537990286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
538090286Sobrien{
538190286Sobrien  switch (get_attr_type (insn))
538250650Sobrien    {
538390286Sobrien    case TYPE_INCDEC:
5384169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
538590286Sobrien      if (operands[2] == const1_rtx)
538690286Sobrien        return "inc{q}\t%0";
538790286Sobrien      else
5388169699Skan        {
5389169699Skan          gcc_assert (operands[2] == constm1_rtx);
5390169699Skan          return "dec{q}\t%0";
5391169699Skan	}
539250650Sobrien
539390286Sobrien    default:
5394169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
539590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
539690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
539790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
539890286Sobrien	  /* Avoid overflows.  */
539990286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
540090286Sobrien          && (INTVAL (operands[2]) == 128
540190286Sobrien	      || (INTVAL (operands[2]) < 0
540290286Sobrien		  && INTVAL (operands[2]) != -128)))
540390286Sobrien        {
540490286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
540590286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
540690286Sobrien        }
540790286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
540850650Sobrien    }
540990286Sobrien}
541090286Sobrien  [(set (attr "type")
541190286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
541290286Sobrien	(const_string "incdec")
541390286Sobrien	(const_string "alu")))
541490286Sobrien   (set_attr "mode" "DI")])
541550650Sobrien
541650650Sobrien
541790286Sobrien(define_insn "*addsi_1"
541890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
541990286Sobrien	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
5420169699Skan		 (match_operand:SI 2 "general_operand" "rmni,rni,lni")))
5421169699Skan   (clobber (reg:CC FLAGS_REG))]
542290286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
542350650Sobrien{
542490286Sobrien  switch (get_attr_type (insn))
542590286Sobrien    {
542690286Sobrien    case TYPE_LEA:
542790286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
542890286Sobrien      return "lea{l}\t{%a2, %0|%0, %a2}";
542950650Sobrien
543090286Sobrien    case TYPE_INCDEC:
5431169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
543290286Sobrien      if (operands[2] == const1_rtx)
543390286Sobrien        return "inc{l}\t%0";
543490286Sobrien      else
5435169699Skan	{
5436169699Skan  	  gcc_assert (operands[2] == constm1_rtx);
5437169699Skan          return "dec{l}\t%0";
5438169699Skan	}
543950650Sobrien
544090286Sobrien    default:
5441169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
544250650Sobrien
544390286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
544490286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
544590286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
544690286Sobrien          && (INTVAL (operands[2]) == 128
544790286Sobrien	      || (INTVAL (operands[2]) < 0
544890286Sobrien		  && INTVAL (operands[2]) != -128)))
544990286Sobrien        {
545090286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
545190286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
545290286Sobrien        }
545390286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
545490286Sobrien    }
545590286Sobrien}
545690286Sobrien  [(set (attr "type")
545790286Sobrien     (cond [(eq_attr "alternative" "2")
545890286Sobrien	      (const_string "lea")
545990286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
546090286Sobrien	    ; ought but a memory context.
546190286Sobrien	    (match_operand:SI 2 "pic_symbolic_operand" "")
546290286Sobrien	      (const_string "lea")
546390286Sobrien	    (match_operand:SI 2 "incdec_operand" "")
546490286Sobrien	      (const_string "incdec")
546590286Sobrien	   ]
546690286Sobrien	   (const_string "alu")))
546790286Sobrien   (set_attr "mode" "SI")])
546890286Sobrien
546990286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
547090286Sobrien(define_split
547190286Sobrien  [(set (match_operand 0 "register_operand" "")
547290286Sobrien	(plus (match_operand 1 "register_operand" "")
547390286Sobrien              (match_operand 2 "nonmemory_operand" "")))
5474169699Skan   (clobber (reg:CC FLAGS_REG))]
547590286Sobrien  "reload_completed
547690286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
547790286Sobrien  [(const_int 0)]
547890286Sobrien{
547990286Sobrien  rtx pat;
548090286Sobrien  /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
548190286Sobrien     may confuse gen_lowpart.  */
548290286Sobrien  if (GET_MODE (operands[0]) != Pmode)
548350650Sobrien    {
548490286Sobrien      operands[1] = gen_lowpart (Pmode, operands[1]);
548590286Sobrien      operands[2] = gen_lowpart (Pmode, operands[2]);
548690286Sobrien    }
548790286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
548890286Sobrien  pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
548990286Sobrien  if (Pmode != SImode)
549090286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
549190286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
549290286Sobrien  DONE;
549390286Sobrien})
549450650Sobrien
549590286Sobrien;; It may seem that nonimmediate operand is proper one for operand 1.
549690286Sobrien;; The addsi_1 pattern allows nonimmediate operand at that place and
549790286Sobrien;; we take care in ix86_binary_operator_ok to not allow two memory
549890286Sobrien;; operands so proper swapping will be done in reload.  This allow
549990286Sobrien;; patterns constructed from addsi_1 to match.
550090286Sobrien(define_insn "addsi_1_zext"
550190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
550290286Sobrien	(zero_extend:DI
550390286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r")
5504169699Skan		   (match_operand:SI 2 "general_operand" "rmni,lni"))))
5505169699Skan   (clobber (reg:CC FLAGS_REG))]
550690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
550790286Sobrien{
550890286Sobrien  switch (get_attr_type (insn))
550990286Sobrien    {
551090286Sobrien    case TYPE_LEA:
551190286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
551290286Sobrien      return "lea{l}\t{%a2, %k0|%k0, %a2}";
551390286Sobrien
551490286Sobrien    case TYPE_INCDEC:
551590286Sobrien      if (operands[2] == const1_rtx)
551690286Sobrien        return "inc{l}\t%k0";
551750650Sobrien      else
5518169699Skan        {
5519169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5520169699Skan          return "dec{l}\t%k0";
5521169699Skan	}
552290286Sobrien
552390286Sobrien    default:
552490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
552590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
552690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
552790286Sobrien          && (INTVAL (operands[2]) == 128
552890286Sobrien	      || (INTVAL (operands[2]) < 0
552990286Sobrien		  && INTVAL (operands[2]) != -128)))
553090286Sobrien        {
553190286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
553290286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
553390286Sobrien        }
553490286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
553550650Sobrien    }
553690286Sobrien}
553790286Sobrien  [(set (attr "type")
553890286Sobrien     (cond [(eq_attr "alternative" "1")
553990286Sobrien	      (const_string "lea")
554090286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
554190286Sobrien	    ; ought but a memory context.
554290286Sobrien	    (match_operand:SI 2 "pic_symbolic_operand" "")
554390286Sobrien	      (const_string "lea")
554490286Sobrien	    (match_operand:SI 2 "incdec_operand" "")
554590286Sobrien	      (const_string "incdec")
554690286Sobrien	   ]
554790286Sobrien	   (const_string "alu")))
554890286Sobrien   (set_attr "mode" "SI")])
554950650Sobrien
555090286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
555190286Sobrien(define_split
555290286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
555390286Sobrien	(zero_extend:DI
555490286Sobrien	  (plus:SI (match_operand:SI 1 "register_operand" "")
555590286Sobrien		   (match_operand:SI 2 "nonmemory_operand" ""))))
5556169699Skan   (clobber (reg:CC FLAGS_REG))]
5557132727Skan  "TARGET_64BIT && reload_completed
555890286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
555990286Sobrien  [(set (match_dup 0)
556090286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))]
556190286Sobrien{
556290286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
556390286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
556490286Sobrien})
556550650Sobrien
556690286Sobrien(define_insn "*addsi_2"
5567169699Skan  [(set (reg FLAGS_REG)
556890286Sobrien	(compare
556990286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
557090286Sobrien		   (match_operand:SI 2 "general_operand" "rmni,rni"))
5571259563Spfg	  (const_int 0)))
557290286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
557390286Sobrien	(plus:SI (match_dup 1) (match_dup 2)))]
557490286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
557590286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
557690286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
557790286Sobrien      ought but a memory context.  */
557890286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
557918334Speter{
558090286Sobrien  switch (get_attr_type (insn))
558190286Sobrien    {
558290286Sobrien    case TYPE_INCDEC:
5583169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
558490286Sobrien      if (operands[2] == const1_rtx)
558590286Sobrien        return "inc{l}\t%0";
558690286Sobrien      else
5587169699Skan        {
5588169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5589169699Skan          return "dec{l}\t%0";
5590169699Skan	}
559118334Speter
559290286Sobrien    default:
5593169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
559490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
559590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
559690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
559790286Sobrien          && (INTVAL (operands[2]) == 128
559890286Sobrien	      || (INTVAL (operands[2]) < 0
559990286Sobrien		  && INTVAL (operands[2]) != -128)))
560090286Sobrien        {
560190286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
560290286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
560390286Sobrien        }
560490286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
560590286Sobrien    }
560690286Sobrien}
560790286Sobrien  [(set (attr "type")
560890286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
560990286Sobrien	(const_string "incdec")
561090286Sobrien	(const_string "alu")))
561190286Sobrien   (set_attr "mode" "SI")])
561218334Speter
561390286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
561490286Sobrien(define_insn "*addsi_2_zext"
5615169699Skan  [(set (reg FLAGS_REG)
561690286Sobrien	(compare
561790286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
561890286Sobrien		   (match_operand:SI 2 "general_operand" "rmni"))
5619259563Spfg	  (const_int 0)))
562090286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
562190286Sobrien	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
562290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
562390286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
562490286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
562590286Sobrien      ought but a memory context.  */
562690286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
562790286Sobrien{
562890286Sobrien  switch (get_attr_type (insn))
562918334Speter    {
563090286Sobrien    case TYPE_INCDEC:
563190286Sobrien      if (operands[2] == const1_rtx)
563290286Sobrien        return "inc{l}\t%k0";
563390286Sobrien      else
5634169699Skan	{
5635169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5636169699Skan          return "dec{l}\t%k0";
5637169699Skan	}
563890286Sobrien
563990286Sobrien    default:
564090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
564190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
564290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
564390286Sobrien          && (INTVAL (operands[2]) == 128
564490286Sobrien	      || (INTVAL (operands[2]) < 0
564590286Sobrien		  && INTVAL (operands[2]) != -128)))
564690286Sobrien        {
564790286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
564890286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
564990286Sobrien        }
565090286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
565118334Speter    }
565290286Sobrien}
565390286Sobrien  [(set (attr "type")
565490286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
565590286Sobrien	(const_string "incdec")
565690286Sobrien	(const_string "alu")))
565790286Sobrien   (set_attr "mode" "SI")])
565818334Speter
565990286Sobrien(define_insn "*addsi_3"
5660169699Skan  [(set (reg FLAGS_REG)
566190286Sobrien	(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
566290286Sobrien		 (match_operand:SI 1 "nonimmediate_operand" "%0")))
566390286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
566490286Sobrien  "ix86_match_ccmode (insn, CCZmode)
566590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
566690286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
566790286Sobrien      ought but a memory context.  */
566890286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
566990286Sobrien{
567090286Sobrien  switch (get_attr_type (insn))
567118334Speter    {
567290286Sobrien    case TYPE_INCDEC:
5673169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
567490286Sobrien      if (operands[2] == const1_rtx)
567590286Sobrien        return "inc{l}\t%0";
567690286Sobrien      else
5677169699Skan        {
5678169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5679169699Skan          return "dec{l}\t%0";
5680169699Skan	}
568118334Speter
568290286Sobrien    default:
5683169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
568490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
568590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
568690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
568790286Sobrien          && (INTVAL (operands[2]) == 128
568890286Sobrien	      || (INTVAL (operands[2]) < 0
568990286Sobrien		  && INTVAL (operands[2]) != -128)))
569090286Sobrien        {
569190286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
569290286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
569390286Sobrien        }
569490286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
569590286Sobrien    }
569690286Sobrien}
569790286Sobrien  [(set (attr "type")
569890286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
569990286Sobrien	(const_string "incdec")
570090286Sobrien	(const_string "alu")))
570190286Sobrien   (set_attr "mode" "SI")])
570290286Sobrien
570390286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
570490286Sobrien(define_insn "*addsi_3_zext"
5705169699Skan  [(set (reg FLAGS_REG)
570690286Sobrien	(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
570790286Sobrien		 (match_operand:SI 1 "nonimmediate_operand" "%0")))
570890286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
570990286Sobrien	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
571090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCZmode)
571190286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
571290286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
571390286Sobrien      ought but a memory context.  */
571490286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
571590286Sobrien{
571690286Sobrien  switch (get_attr_type (insn))
571790286Sobrien    {
571890286Sobrien    case TYPE_INCDEC:
571990286Sobrien      if (operands[2] == const1_rtx)
572090286Sobrien        return "inc{l}\t%k0";
572118334Speter      else
5722169699Skan        {
5723169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5724169699Skan          return "dec{l}\t%k0";
5725169699Skan	}
572690286Sobrien
572790286Sobrien    default:
572890286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
572990286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
573090286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
573190286Sobrien          && (INTVAL (operands[2]) == 128
573290286Sobrien	      || (INTVAL (operands[2]) < 0
573390286Sobrien		  && INTVAL (operands[2]) != -128)))
573490286Sobrien        {
573590286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
573690286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
573790286Sobrien        }
573890286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
573918334Speter    }
574090286Sobrien}
574190286Sobrien  [(set (attr "type")
574290286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
574390286Sobrien	(const_string "incdec")
574490286Sobrien	(const_string "alu")))
574590286Sobrien   (set_attr "mode" "SI")])
574618334Speter
5747132727Skan; For comparisons against 1, -1 and 128, we may generate better code
574890286Sobrien; by converting cmp to add, inc or dec as done by peephole2.  This pattern
574990286Sobrien; is matched then.  We can't accept general immediate, because for
575090286Sobrien; case of overflows,  the result is messed up.
575190286Sobrien; This pattern also don't hold of 0x80000000, since the value overflows
575290286Sobrien; when negated.
575390286Sobrien; Also carry flag is reversed compared to cmp, so this conversion is valid
575490286Sobrien; only for comparisons not depending on it.
575590286Sobrien(define_insn "*addsi_4"
5756169699Skan  [(set (reg FLAGS_REG)
575790286Sobrien	(compare (match_operand:SI 1 "nonimmediate_operand" "0")
575890286Sobrien		 (match_operand:SI 2 "const_int_operand" "n")))
575990286Sobrien   (clobber (match_scratch:SI 0 "=rm"))]
576090286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
576190286Sobrien   && (INTVAL (operands[2]) & 0xffffffff) != 0x80000000"
576290286Sobrien{
576390286Sobrien  switch (get_attr_type (insn))
576418334Speter    {
576590286Sobrien    case TYPE_INCDEC:
576690286Sobrien      if (operands[2] == constm1_rtx)
576790286Sobrien        return "inc{l}\t%0";
576890286Sobrien      else
5769169699Skan        {
5770169699Skan	  gcc_assert (operands[2] == const1_rtx);
5771169699Skan          return "dec{l}\t%0";
5772169699Skan	}
577318334Speter
577490286Sobrien    default:
5775169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
577690286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
577790286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
577890286Sobrien      if ((INTVAL (operands[2]) == -128
577990286Sobrien	   || (INTVAL (operands[2]) > 0
578090286Sobrien	       && INTVAL (operands[2]) != 128)))
578190286Sobrien	return "sub{l}\t{%2, %0|%0, %2}";
578290286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
578390286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
578418334Speter    }
578590286Sobrien}
578690286Sobrien  [(set (attr "type")
578790286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
578890286Sobrien	(const_string "incdec")
578990286Sobrien	(const_string "alu")))
579090286Sobrien   (set_attr "mode" "SI")])
579118334Speter
579290286Sobrien(define_insn "*addsi_5"
5793169699Skan  [(set (reg FLAGS_REG)
579490286Sobrien	(compare
579590286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
579690286Sobrien		   (match_operand:SI 2 "general_operand" "rmni"))
5797259563Spfg	  (const_int 0)))
579890286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
579990286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
580090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
580190286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
580290286Sobrien      ought but a memory context.  */
580390286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
580490286Sobrien{
580590286Sobrien  switch (get_attr_type (insn))
580618334Speter    {
580790286Sobrien    case TYPE_INCDEC:
5808169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
580990286Sobrien      if (operands[2] == const1_rtx)
581090286Sobrien        return "inc{l}\t%0";
581190286Sobrien      else
5812169699Skan        {
5813169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5814169699Skan          return "dec{l}\t%0";
5815169699Skan	}
581690286Sobrien
581790286Sobrien    default:
5818169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
581990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
582090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
582190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
582290286Sobrien          && (INTVAL (operands[2]) == 128
582390286Sobrien	      || (INTVAL (operands[2]) < 0
582490286Sobrien		  && INTVAL (operands[2]) != -128)))
582590286Sobrien        {
582690286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
582790286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
582890286Sobrien        }
582990286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
583018334Speter    }
583190286Sobrien}
583290286Sobrien  [(set (attr "type")
583390286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
583490286Sobrien	(const_string "incdec")
583590286Sobrien	(const_string "alu")))
583690286Sobrien   (set_attr "mode" "SI")])
583718334Speter
583890286Sobrien(define_expand "addhi3"
583990286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
584090286Sobrien		   (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
584190286Sobrien			    (match_operand:HI 2 "general_operand" "")))
5842169699Skan	      (clobber (reg:CC FLAGS_REG))])]
584390286Sobrien  "TARGET_HIMODE_MATH"
584490286Sobrien  "ix86_expand_binary_operator (PLUS, HImode, operands); DONE;")
584518334Speter
584690286Sobrien;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah
584790286Sobrien;; type optimizations enabled by define-splits.  This is not important
584890286Sobrien;; for PII, and in fact harmful because of partial register stalls.
584918334Speter
585090286Sobrien(define_insn "*addhi_1_lea"
585190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
585290286Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
5853169699Skan		 (match_operand:HI 2 "general_operand" "ri,rm,lni")))
5854169699Skan   (clobber (reg:CC FLAGS_REG))]
585590286Sobrien  "!TARGET_PARTIAL_REG_STALL
585690286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
585790286Sobrien{
585890286Sobrien  switch (get_attr_type (insn))
585990286Sobrien    {
586090286Sobrien    case TYPE_LEA:
586190286Sobrien      return "#";
586290286Sobrien    case TYPE_INCDEC:
586390286Sobrien      if (operands[2] == const1_rtx)
586490286Sobrien	return "inc{w}\t%0";
5865169699Skan      else
5866169699Skan	{
5867169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5868169699Skan	  return "dec{w}\t%0";
5869169699Skan	}
587018334Speter
587190286Sobrien    default:
587290286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
587390286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
587490286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
587590286Sobrien          && (INTVAL (operands[2]) == 128
587690286Sobrien	      || (INTVAL (operands[2]) < 0
587790286Sobrien		  && INTVAL (operands[2]) != -128)))
587890286Sobrien	{
587990286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
588090286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
588190286Sobrien	}
588290286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
588390286Sobrien    }
588490286Sobrien}
588590286Sobrien  [(set (attr "type")
588690286Sobrien     (if_then_else (eq_attr "alternative" "2")
588790286Sobrien	(const_string "lea")
588890286Sobrien	(if_then_else (match_operand:HI 2 "incdec_operand" "")
588990286Sobrien	   (const_string "incdec")
589090286Sobrien	   (const_string "alu"))))
589190286Sobrien   (set_attr "mode" "HI,HI,SI")])
589250650Sobrien
589390286Sobrien(define_insn "*addhi_1"
589490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
589590286Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
589690286Sobrien		 (match_operand:HI 2 "general_operand" "ri,rm")))
5897169699Skan   (clobber (reg:CC FLAGS_REG))]
589890286Sobrien  "TARGET_PARTIAL_REG_STALL
589990286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
590018334Speter{
590190286Sobrien  switch (get_attr_type (insn))
590218334Speter    {
590390286Sobrien    case TYPE_INCDEC:
590490286Sobrien      if (operands[2] == const1_rtx)
590590286Sobrien	return "inc{w}\t%0";
5906169699Skan      else
5907169699Skan        {
5908169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5909169699Skan	  return "dec{w}\t%0";
5910169699Skan	}
591118334Speter
591290286Sobrien    default:
591390286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
591490286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
591590286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
591690286Sobrien          && (INTVAL (operands[2]) == 128
591790286Sobrien	      || (INTVAL (operands[2]) < 0
591890286Sobrien		  && INTVAL (operands[2]) != -128)))
591918334Speter	{
592090286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
592190286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
592218334Speter	}
592390286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
592490286Sobrien    }
592590286Sobrien}
592690286Sobrien  [(set (attr "type")
592790286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
592890286Sobrien	(const_string "incdec")
592990286Sobrien	(const_string "alu")))
593090286Sobrien   (set_attr "mode" "HI")])
593118334Speter
593290286Sobrien(define_insn "*addhi_2"
5933169699Skan  [(set (reg FLAGS_REG)
593490286Sobrien	(compare
593590286Sobrien	  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
593690286Sobrien		   (match_operand:HI 2 "general_operand" "rmni,rni"))
5937259563Spfg	  (const_int 0)))
593890286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
593990286Sobrien	(plus:HI (match_dup 1) (match_dup 2)))]
594090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
594190286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
594290286Sobrien{
594390286Sobrien  switch (get_attr_type (insn))
594490286Sobrien    {
594590286Sobrien    case TYPE_INCDEC:
594690286Sobrien      if (operands[2] == const1_rtx)
594790286Sobrien	return "inc{w}\t%0";
5948169699Skan      else
5949169699Skan        {
5950169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5951169699Skan	  return "dec{w}\t%0";
5952169699Skan	}
595390286Sobrien
595490286Sobrien    default:
595590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
595690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
595790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
595890286Sobrien          && (INTVAL (operands[2]) == 128
595990286Sobrien	      || (INTVAL (operands[2]) < 0
596090286Sobrien		  && INTVAL (operands[2]) != -128)))
596118334Speter	{
596290286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
596390286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
596418334Speter	}
596590286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
596618334Speter    }
596790286Sobrien}
596890286Sobrien  [(set (attr "type")
596990286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
597090286Sobrien	(const_string "incdec")
597190286Sobrien	(const_string "alu")))
597290286Sobrien   (set_attr "mode" "HI")])
597318334Speter
597490286Sobrien(define_insn "*addhi_3"
5975169699Skan  [(set (reg FLAGS_REG)
597690286Sobrien	(compare (neg:HI (match_operand:HI 2 "general_operand" "rmni"))
597790286Sobrien		 (match_operand:HI 1 "nonimmediate_operand" "%0")))
597890286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
597990286Sobrien  "ix86_match_ccmode (insn, CCZmode)
598090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
598190286Sobrien{
598290286Sobrien  switch (get_attr_type (insn))
598390286Sobrien    {
598490286Sobrien    case TYPE_INCDEC:
598590286Sobrien      if (operands[2] == const1_rtx)
598690286Sobrien	return "inc{w}\t%0";
5987169699Skan      else
5988169699Skan        {
5989169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5990169699Skan	  return "dec{w}\t%0";
5991169699Skan	}
599250650Sobrien
599390286Sobrien    default:
599490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
599590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
599690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
599790286Sobrien          && (INTVAL (operands[2]) == 128
599890286Sobrien	      || (INTVAL (operands[2]) < 0
599990286Sobrien		  && INTVAL (operands[2]) != -128)))
600090286Sobrien	{
600190286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
600290286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
600390286Sobrien	}
600490286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
600590286Sobrien    }
600690286Sobrien}
600790286Sobrien  [(set (attr "type")
600890286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
600990286Sobrien	(const_string "incdec")
601090286Sobrien	(const_string "alu")))
601190286Sobrien   (set_attr "mode" "HI")])
601218334Speter
6013169699Skan; See comments above addsi_4 for details.
601490286Sobrien(define_insn "*addhi_4"
6015169699Skan  [(set (reg FLAGS_REG)
601690286Sobrien	(compare (match_operand:HI 1 "nonimmediate_operand" "0")
601790286Sobrien		 (match_operand:HI 2 "const_int_operand" "n")))
601890286Sobrien   (clobber (match_scratch:HI 0 "=rm"))]
601990286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
602090286Sobrien   && (INTVAL (operands[2]) & 0xffff) != 0x8000"
602190286Sobrien{
602290286Sobrien  switch (get_attr_type (insn))
602390286Sobrien    {
602490286Sobrien    case TYPE_INCDEC:
6025117404Skan      if (operands[2] == constm1_rtx)
602690286Sobrien        return "inc{w}\t%0";
602790286Sobrien      else
6028169699Skan	{
6029169699Skan	  gcc_assert (operands[2] == const1_rtx);
6030169699Skan          return "dec{w}\t%0";
6031169699Skan	}
603218334Speter
603390286Sobrien    default:
6034169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
603590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
603690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
603790286Sobrien      if ((INTVAL (operands[2]) == -128
603890286Sobrien	   || (INTVAL (operands[2]) > 0
603990286Sobrien	       && INTVAL (operands[2]) != 128)))
604090286Sobrien	return "sub{w}\t{%2, %0|%0, %2}";
604190286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
604290286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
604350650Sobrien    }
604490286Sobrien}
604590286Sobrien  [(set (attr "type")
604690286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
604790286Sobrien	(const_string "incdec")
604890286Sobrien	(const_string "alu")))
604990286Sobrien   (set_attr "mode" "SI")])
605050650Sobrien
605118334Speter
605290286Sobrien(define_insn "*addhi_5"
6053169699Skan  [(set (reg FLAGS_REG)
605490286Sobrien	(compare
605590286Sobrien	  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
605690286Sobrien		   (match_operand:HI 2 "general_operand" "rmni"))
6057259563Spfg	  (const_int 0)))
605890286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
605990286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
606090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
606150650Sobrien{
606290286Sobrien  switch (get_attr_type (insn))
606350650Sobrien    {
606490286Sobrien    case TYPE_INCDEC:
606590286Sobrien      if (operands[2] == const1_rtx)
606690286Sobrien	return "inc{w}\t%0";
6067169699Skan      else
6068169699Skan	{
6069169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6070169699Skan	  return "dec{w}\t%0";
6071169699Skan	}
607250650Sobrien
607390286Sobrien    default:
607490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
607590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
607690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
607790286Sobrien          && (INTVAL (operands[2]) == 128
607890286Sobrien	      || (INTVAL (operands[2]) < 0
607990286Sobrien		  && INTVAL (operands[2]) != -128)))
608090286Sobrien	{
608190286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
608290286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
608390286Sobrien	}
608490286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
608550650Sobrien    }
608690286Sobrien}
608790286Sobrien  [(set (attr "type")
608890286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
608990286Sobrien	(const_string "incdec")
609090286Sobrien	(const_string "alu")))
609190286Sobrien   (set_attr "mode" "HI")])
609250650Sobrien
609390286Sobrien(define_expand "addqi3"
609490286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
609590286Sobrien		   (plus:QI (match_operand:QI 1 "nonimmediate_operand" "")
609690286Sobrien			    (match_operand:QI 2 "general_operand" "")))
6097169699Skan	      (clobber (reg:CC FLAGS_REG))])]
609890286Sobrien  "TARGET_QIMODE_MATH"
609990286Sobrien  "ix86_expand_binary_operator (PLUS, QImode, operands); DONE;")
610050650Sobrien
610190286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
610290286Sobrien(define_insn "*addqi_1_lea"
610390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r")
610490286Sobrien	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r")
6105169699Skan		 (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln")))
6106169699Skan   (clobber (reg:CC FLAGS_REG))]
610790286Sobrien  "!TARGET_PARTIAL_REG_STALL
610890286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
610990286Sobrien{
611090286Sobrien  int widen = (which_alternative == 2);
611190286Sobrien  switch (get_attr_type (insn))
611290286Sobrien    {
611390286Sobrien    case TYPE_LEA:
611490286Sobrien      return "#";
611590286Sobrien    case TYPE_INCDEC:
611690286Sobrien      if (operands[2] == const1_rtx)
611790286Sobrien	return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
6118169699Skan      else
6119169699Skan	{
6120169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6121169699Skan	  return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
6122169699Skan	}
612318334Speter
612490286Sobrien    default:
612590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
612690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
612790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
612890286Sobrien          && (INTVAL (operands[2]) == 128
612990286Sobrien	      || (INTVAL (operands[2]) < 0
613090286Sobrien		  && INTVAL (operands[2]) != -128)))
613190286Sobrien	{
613290286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
613390286Sobrien	  if (widen)
613490286Sobrien	    return "sub{l}\t{%2, %k0|%k0, %2}";
613590286Sobrien	  else
613690286Sobrien	    return "sub{b}\t{%2, %0|%0, %2}";
613790286Sobrien	}
613890286Sobrien      if (widen)
613990286Sobrien        return "add{l}\t{%k2, %k0|%k0, %k2}";
614090286Sobrien      else
614190286Sobrien        return "add{b}\t{%2, %0|%0, %2}";
614290286Sobrien    }
614390286Sobrien}
614490286Sobrien  [(set (attr "type")
614590286Sobrien     (if_then_else (eq_attr "alternative" "3")
614690286Sobrien	(const_string "lea")
614790286Sobrien	(if_then_else (match_operand:QI 2 "incdec_operand" "")
614890286Sobrien	   (const_string "incdec")
614990286Sobrien	   (const_string "alu"))))
615090286Sobrien   (set_attr "mode" "QI,QI,SI,SI")])
615150650Sobrien
615290286Sobrien(define_insn "*addqi_1"
615390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
615490286Sobrien	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
615590286Sobrien		 (match_operand:QI 2 "general_operand" "qn,qmn,rn")))
6156169699Skan   (clobber (reg:CC FLAGS_REG))]
615790286Sobrien  "TARGET_PARTIAL_REG_STALL
615890286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
615918334Speter{
616090286Sobrien  int widen = (which_alternative == 2);
616190286Sobrien  switch (get_attr_type (insn))
616252296Sobrien    {
616390286Sobrien    case TYPE_INCDEC:
616490286Sobrien      if (operands[2] == const1_rtx)
616590286Sobrien	return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
6166169699Skan      else
6167169699Skan	{
6168169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6169169699Skan	  return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
6170169699Skan	}
617152296Sobrien
617290286Sobrien    default:
617390286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
617490286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
617590286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
617690286Sobrien          && (INTVAL (operands[2]) == 128
617790286Sobrien	      || (INTVAL (operands[2]) < 0
617890286Sobrien		  && INTVAL (operands[2]) != -128)))
617990286Sobrien	{
618090286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
618190286Sobrien	  if (widen)
618290286Sobrien	    return "sub{l}\t{%2, %k0|%k0, %2}";
618390286Sobrien	  else
618490286Sobrien	    return "sub{b}\t{%2, %0|%0, %2}";
618590286Sobrien	}
618690286Sobrien      if (widen)
618790286Sobrien        return "add{l}\t{%k2, %k0|%k0, %k2}";
618890286Sobrien      else
618990286Sobrien        return "add{b}\t{%2, %0|%0, %2}";
619052296Sobrien    }
619190286Sobrien}
619290286Sobrien  [(set (attr "type")
619390286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
619490286Sobrien	(const_string "incdec")
619590286Sobrien	(const_string "alu")))
619690286Sobrien   (set_attr "mode" "QI,QI,SI")])
619752296Sobrien
6198117404Skan(define_insn "*addqi_1_slp"
6199117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
6200117404Skan	(plus:QI (match_dup 0)
6201117404Skan		 (match_operand:QI 1 "general_operand" "qn,qnm")))
6202169699Skan   (clobber (reg:CC FLAGS_REG))]
6203117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
6204117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
6205117404Skan{
6206117404Skan  switch (get_attr_type (insn))
6207117404Skan    {
6208117404Skan    case TYPE_INCDEC:
6209117404Skan      if (operands[1] == const1_rtx)
6210117404Skan	return "inc{b}\t%0";
6211169699Skan      else
6212169699Skan	{
6213169699Skan	  gcc_assert (operands[1] == constm1_rtx);
6214169699Skan	  return "dec{b}\t%0";
6215169699Skan	}
6216117404Skan
6217117404Skan    default:
6218117404Skan      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.  */
6219117404Skan      if (GET_CODE (operands[1]) == CONST_INT
6220117404Skan	  && INTVAL (operands[1]) < 0)
6221117404Skan	{
6222132727Skan	  operands[1] = GEN_INT (-INTVAL (operands[1]));
6223117404Skan	  return "sub{b}\t{%1, %0|%0, %1}";
6224117404Skan	}
6225117404Skan      return "add{b}\t{%1, %0|%0, %1}";
6226117404Skan    }
6227117404Skan}
6228117404Skan  [(set (attr "type")
6229146906Skan     (if_then_else (match_operand:QI 1 "incdec_operand" "")
6230117404Skan	(const_string "incdec")
6231117404Skan	(const_string "alu1")))
6232146906Skan   (set (attr "memory")
6233146906Skan     (if_then_else (match_operand 1 "memory_operand" "")
6234146906Skan        (const_string "load")
6235146906Skan        (const_string "none")))
6236117404Skan   (set_attr "mode" "QI")])
6237117404Skan
623890286Sobrien(define_insn "*addqi_2"
6239169699Skan  [(set (reg FLAGS_REG)
624090286Sobrien	(compare
624190286Sobrien	  (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
624290286Sobrien		   (match_operand:QI 2 "general_operand" "qmni,qni"))
624390286Sobrien	  (const_int 0)))
624490286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
624590286Sobrien	(plus:QI (match_dup 1) (match_dup 2)))]
624690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
624790286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
624890286Sobrien{
624990286Sobrien  switch (get_attr_type (insn))
625018334Speter    {
625190286Sobrien    case TYPE_INCDEC:
625290286Sobrien      if (operands[2] == const1_rtx)
625390286Sobrien	return "inc{b}\t%0";
6254169699Skan      else
6255169699Skan        {
6256169699Skan	  gcc_assert (operands[2] == constm1_rtx
6257169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6258169699Skan		          && INTVAL (operands[2]) == 255));
6259169699Skan	  return "dec{b}\t%0";
6260169699Skan	}
626118334Speter
626290286Sobrien    default:
626390286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
626490286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
626590286Sobrien          && INTVAL (operands[2]) < 0)
626690286Sobrien	{
626790286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
626890286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
626990286Sobrien	}
627090286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
627118334Speter    }
627290286Sobrien}
627390286Sobrien  [(set (attr "type")
627490286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
627590286Sobrien	(const_string "incdec")
627690286Sobrien	(const_string "alu")))
627790286Sobrien   (set_attr "mode" "QI")])
627818334Speter
627990286Sobrien(define_insn "*addqi_3"
6280169699Skan  [(set (reg FLAGS_REG)
628190286Sobrien	(compare (neg:QI (match_operand:QI 2 "general_operand" "qmni"))
628290286Sobrien		 (match_operand:QI 1 "nonimmediate_operand" "%0")))
628390286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
628490286Sobrien  "ix86_match_ccmode (insn, CCZmode)
628590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
628690286Sobrien{
628790286Sobrien  switch (get_attr_type (insn))
628850650Sobrien    {
628990286Sobrien    case TYPE_INCDEC:
629090286Sobrien      if (operands[2] == const1_rtx)
629190286Sobrien	return "inc{b}\t%0";
6292169699Skan      else
6293169699Skan        {
6294169699Skan	  gcc_assert (operands[2] == constm1_rtx
6295169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6296169699Skan			  && INTVAL (operands[2]) == 255));
6297169699Skan	  return "dec{b}\t%0";
6298169699Skan	}
629950650Sobrien
630090286Sobrien    default:
630190286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
630290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
630390286Sobrien          && INTVAL (operands[2]) < 0)
630450650Sobrien	{
630590286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
630690286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
630790286Sobrien	}
630890286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
630990286Sobrien    }
631090286Sobrien}
631190286Sobrien  [(set (attr "type")
631290286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
631390286Sobrien	(const_string "incdec")
631490286Sobrien	(const_string "alu")))
631590286Sobrien   (set_attr "mode" "QI")])
631650650Sobrien
6317169699Skan; See comments above addsi_4 for details.
631890286Sobrien(define_insn "*addqi_4"
6319169699Skan  [(set (reg FLAGS_REG)
632090286Sobrien	(compare (match_operand:QI 1 "nonimmediate_operand" "0")
632190286Sobrien		 (match_operand:QI 2 "const_int_operand" "n")))
632290286Sobrien   (clobber (match_scratch:QI 0 "=qm"))]
632390286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
632490286Sobrien   && (INTVAL (operands[2]) & 0xff) != 0x80"
632590286Sobrien{
632690286Sobrien  switch (get_attr_type (insn))
632790286Sobrien    {
632890286Sobrien    case TYPE_INCDEC:
632990286Sobrien      if (operands[2] == constm1_rtx
633090286Sobrien	  || (GET_CODE (operands[2]) == CONST_INT
633190286Sobrien	      && INTVAL (operands[2]) == 255))
633290286Sobrien        return "inc{b}\t%0";
633390286Sobrien      else
6334169699Skan	{
6335169699Skan	  gcc_assert (operands[2] == const1_rtx);
6336169699Skan          return "dec{b}\t%0";
6337169699Skan	}
633850650Sobrien
633990286Sobrien    default:
6340169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
634190286Sobrien      if (INTVAL (operands[2]) < 0)
634290286Sobrien        {
634390286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
634490286Sobrien          return "add{b}\t{%2, %0|%0, %2}";
634590286Sobrien        }
634690286Sobrien      return "sub{b}\t{%2, %0|%0, %2}";
634750650Sobrien    }
634890286Sobrien}
634990286Sobrien  [(set (attr "type")
635090286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
635190286Sobrien	(const_string "incdec")
635290286Sobrien	(const_string "alu")))
635390286Sobrien   (set_attr "mode" "QI")])
635450650Sobrien
635518334Speter
635690286Sobrien(define_insn "*addqi_5"
6357169699Skan  [(set (reg FLAGS_REG)
635890286Sobrien	(compare
635990286Sobrien	  (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
636090286Sobrien		   (match_operand:QI 2 "general_operand" "qmni"))
636190286Sobrien	  (const_int 0)))
636290286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
636390286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
636490286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
636590286Sobrien{
636690286Sobrien  switch (get_attr_type (insn))
636790286Sobrien    {
636890286Sobrien    case TYPE_INCDEC:
636990286Sobrien      if (operands[2] == const1_rtx)
637090286Sobrien	return "inc{b}\t%0";
6371169699Skan      else
6372169699Skan        {
6373169699Skan	  gcc_assert (operands[2] == constm1_rtx
6374169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6375169699Skan			  && INTVAL (operands[2]) == 255));
6376169699Skan	  return "dec{b}\t%0";
6377169699Skan	}
637818334Speter
637990286Sobrien    default:
638090286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
638190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
638290286Sobrien          && INTVAL (operands[2]) < 0)
638390286Sobrien	{
638490286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
638590286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
638690286Sobrien	}
638790286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
638890286Sobrien    }
638990286Sobrien}
639090286Sobrien  [(set (attr "type")
639190286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
639290286Sobrien	(const_string "incdec")
639390286Sobrien	(const_string "alu")))
639490286Sobrien   (set_attr "mode" "QI")])
639518334Speter
639650650Sobrien
639790286Sobrien(define_insn "addqi_ext_1"
639890286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
639990286Sobrien			 (const_int 8)
640090286Sobrien			 (const_int 8))
640190286Sobrien	(plus:SI
640290286Sobrien	  (zero_extract:SI
640390286Sobrien	    (match_operand 1 "ext_register_operand" "0")
640490286Sobrien	    (const_int 8)
640590286Sobrien	    (const_int 8))
640690286Sobrien	  (match_operand:QI 2 "general_operand" "Qmn")))
6407169699Skan   (clobber (reg:CC FLAGS_REG))]
640890286Sobrien  "!TARGET_64BIT"
640918334Speter{
641090286Sobrien  switch (get_attr_type (insn))
641152296Sobrien    {
641290286Sobrien    case TYPE_INCDEC:
641390286Sobrien      if (operands[2] == const1_rtx)
641490286Sobrien	return "inc{b}\t%h0";
6415169699Skan      else
6416169699Skan        {
6417169699Skan	  gcc_assert (operands[2] == constm1_rtx
6418169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6419169699Skan			  && INTVAL (operands[2]) == 255));
6420169699Skan          return "dec{b}\t%h0";
6421169699Skan	}
642252296Sobrien
642390286Sobrien    default:
642490286Sobrien      return "add{b}\t{%2, %h0|%h0, %2}";
642552296Sobrien    }
642690286Sobrien}
642790286Sobrien  [(set (attr "type")
642890286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
642990286Sobrien	(const_string "incdec")
643090286Sobrien	(const_string "alu")))
643190286Sobrien   (set_attr "mode" "QI")])
643218334Speter
643390286Sobrien(define_insn "*addqi_ext_1_rex64"
643490286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
643590286Sobrien			 (const_int 8)
643690286Sobrien			 (const_int 8))
643790286Sobrien	(plus:SI
643890286Sobrien	  (zero_extract:SI
643990286Sobrien	    (match_operand 1 "ext_register_operand" "0")
644090286Sobrien	    (const_int 8)
644190286Sobrien	    (const_int 8))
644290286Sobrien	  (match_operand:QI 2 "nonmemory_operand" "Qn")))
6443169699Skan   (clobber (reg:CC FLAGS_REG))]
644490286Sobrien  "TARGET_64BIT"
644590286Sobrien{
644690286Sobrien  switch (get_attr_type (insn))
644790286Sobrien    {
644890286Sobrien    case TYPE_INCDEC:
644990286Sobrien      if (operands[2] == const1_rtx)
645090286Sobrien	return "inc{b}\t%h0";
6451169699Skan      else
6452169699Skan        {
6453169699Skan	  gcc_assert (operands[2] == constm1_rtx
6454169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6455169699Skan			  && INTVAL (operands[2]) == 255));
6456169699Skan          return "dec{b}\t%h0";
6457169699Skan        }
645818334Speter
645990286Sobrien    default:
646090286Sobrien      return "add{b}\t{%2, %h0|%h0, %2}";
646190286Sobrien    }
646290286Sobrien}
646390286Sobrien  [(set (attr "type")
646490286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
646590286Sobrien	(const_string "incdec")
646690286Sobrien	(const_string "alu")))
646790286Sobrien   (set_attr "mode" "QI")])
646818334Speter
646990286Sobrien(define_insn "*addqi_ext_2"
647090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
647190286Sobrien			 (const_int 8)
647290286Sobrien			 (const_int 8))
647390286Sobrien	(plus:SI
647490286Sobrien	  (zero_extract:SI
647590286Sobrien	    (match_operand 1 "ext_register_operand" "%0")
647690286Sobrien	    (const_int 8)
647790286Sobrien	    (const_int 8))
647890286Sobrien	  (zero_extract:SI
647990286Sobrien	    (match_operand 2 "ext_register_operand" "Q")
648090286Sobrien	    (const_int 8)
648190286Sobrien	    (const_int 8))))
6482169699Skan   (clobber (reg:CC FLAGS_REG))]
648390286Sobrien  ""
648490286Sobrien  "add{b}\t{%h2, %h0|%h0, %h2}"
648590286Sobrien  [(set_attr "type" "alu")
648690286Sobrien   (set_attr "mode" "QI")])
648718334Speter
648818334Speter;; The patterns that match these are at the end of this file.
648918334Speter
649018334Speter(define_expand "addxf3"
649118334Speter  [(set (match_operand:XF 0 "register_operand" "")
649250650Sobrien	(plus:XF (match_operand:XF 1 "register_operand" "")
649350650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
649418334Speter  "TARGET_80387"
649518334Speter  "")
649618334Speter
649718334Speter(define_expand "adddf3"
649818334Speter  [(set (match_operand:DF 0 "register_operand" "")
649990286Sobrien	(plus:DF (match_operand:DF 1 "register_operand" "")
650018334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
650190286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
650218334Speter  "")
650318334Speter
650418334Speter(define_expand "addsf3"
650518334Speter  [(set (match_operand:SF 0 "register_operand" "")
650690286Sobrien	(plus:SF (match_operand:SF 1 "register_operand" "")
650718334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
650890286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
650918334Speter  "")
651018334Speter
651190286Sobrien;; Subtract instructions
651218334Speter
6513169699Skan;; %%% splits for subditi3
6514169699Skan
6515169699Skan(define_expand "subti3"
6516169699Skan  [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
6517169699Skan		   (minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
6518169699Skan			     (match_operand:TI 2 "x86_64_general_operand" "")))
6519169699Skan	      (clobber (reg:CC FLAGS_REG))])]
6520169699Skan  "TARGET_64BIT"
6521169699Skan  "ix86_expand_binary_operator (MINUS, TImode, operands); DONE;")
6522169699Skan
6523169699Skan(define_insn "*subti3_1"
6524169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
6525169699Skan	(minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0")
6526171835Skan		  (match_operand:TI 2 "x86_64_general_operand" "roe,re")))
6527169699Skan   (clobber (reg:CC FLAGS_REG))]
6528169699Skan  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)"
6529169699Skan  "#")
6530169699Skan
6531169699Skan(define_split
6532169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
6533169699Skan	(minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
6534171835Skan		  (match_operand:TI 2 "x86_64_general_operand" "")))
6535169699Skan   (clobber (reg:CC FLAGS_REG))]
6536169699Skan  "TARGET_64BIT && reload_completed"
6537169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
6538169699Skan	      (set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))])
6539169699Skan   (parallel [(set (match_dup 3)
6540169699Skan		   (minus:DI (match_dup 4)
6541169699Skan			     (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
6542169699Skan				      (match_dup 5))))
6543169699Skan	      (clobber (reg:CC FLAGS_REG))])]
6544169699Skan  "split_ti (operands+0, 1, operands+0, operands+3);
6545169699Skan   split_ti (operands+1, 1, operands+1, operands+4);
6546169699Skan   split_ti (operands+2, 1, operands+2, operands+5);")
6547169699Skan
654890286Sobrien;; %%% splits for subsidi3
654950650Sobrien
655090286Sobrien(define_expand "subdi3"
655190286Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
655290286Sobrien		   (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
655390286Sobrien			     (match_operand:DI 2 "x86_64_general_operand" "")))
6554169699Skan	      (clobber (reg:CC FLAGS_REG))])]
655518334Speter  ""
655690286Sobrien  "ix86_expand_binary_operator (MINUS, DImode, operands); DONE;")
655718334Speter
655890286Sobrien(define_insn "*subdi3_1"
655990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
656090286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
656190286Sobrien		  (match_operand:DI 2 "general_operand" "roiF,riF")))
6562169699Skan   (clobber (reg:CC FLAGS_REG))]
6563107605Sobrien  "!TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
656490286Sobrien  "#")
656518334Speter
656690286Sobrien(define_split
656790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
656890286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
656990286Sobrien		  (match_operand:DI 2 "general_operand" "")))
6570169699Skan   (clobber (reg:CC FLAGS_REG))]
657190286Sobrien  "!TARGET_64BIT && reload_completed"
6572169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
657390286Sobrien	      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
657490286Sobrien   (parallel [(set (match_dup 3)
657590286Sobrien		   (minus:SI (match_dup 4)
6576169699Skan			     (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
657790286Sobrien				      (match_dup 5))))
6578169699Skan	      (clobber (reg:CC FLAGS_REG))])]
657990286Sobrien  "split_di (operands+0, 1, operands+0, operands+3);
658090286Sobrien   split_di (operands+1, 1, operands+1, operands+4);
658190286Sobrien   split_di (operands+2, 1, operands+2, operands+5);")
658218334Speter
658390286Sobrien(define_insn "subdi3_carry_rex64"
658490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
658590286Sobrien	  (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
6586132727Skan	    (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
658790286Sobrien	       (match_operand:DI 2 "x86_64_general_operand" "re,rm"))))
6588169699Skan   (clobber (reg:CC FLAGS_REG))]
658990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
659090286Sobrien  "sbb{q}\t{%2, %0|%0, %2}"
659190286Sobrien  [(set_attr "type" "alu")
659290286Sobrien   (set_attr "pent_pair" "pu")
659390286Sobrien   (set_attr "mode" "DI")])
659418334Speter
659590286Sobrien(define_insn "*subdi_1_rex64"
659690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
659790286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
659890286Sobrien		  (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
6599169699Skan   (clobber (reg:CC FLAGS_REG))]
660090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
660190286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
660290286Sobrien  [(set_attr "type" "alu")
660390286Sobrien   (set_attr "mode" "DI")])
660418334Speter
660590286Sobrien(define_insn "*subdi_2_rex64"
6606169699Skan  [(set (reg FLAGS_REG)
660790286Sobrien	(compare
660890286Sobrien	  (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
660990286Sobrien		    (match_operand:DI 2 "x86_64_general_operand" "re,rm"))
661090286Sobrien	  (const_int 0)))
661190286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
661290286Sobrien	(minus:DI (match_dup 1) (match_dup 2)))]
661390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
661490286Sobrien   && ix86_binary_operator_ok (MINUS, DImode, operands)"
661590286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
661690286Sobrien  [(set_attr "type" "alu")
661790286Sobrien   (set_attr "mode" "DI")])
661852296Sobrien
661990286Sobrien(define_insn "*subdi_3_rex63"
6620169699Skan  [(set (reg FLAGS_REG)
662190286Sobrien	(compare (match_operand:DI 1 "nonimmediate_operand" "0,0")
662290286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
662390286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
662490286Sobrien	(minus:DI (match_dup 1) (match_dup 2)))]
662590286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
662690286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
662790286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
662890286Sobrien  [(set_attr "type" "alu")
662990286Sobrien   (set_attr "mode" "DI")])
663018334Speter
6631132727Skan(define_insn "subqi3_carry"
6632132727Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
6633132727Skan	  (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
6634132727Skan	    (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
6635132727Skan	       (match_operand:QI 2 "general_operand" "qi,qm"))))
6636169699Skan   (clobber (reg:CC FLAGS_REG))]
6637132727Skan  "ix86_binary_operator_ok (MINUS, QImode, operands)"
6638132727Skan  "sbb{b}\t{%2, %0|%0, %2}"
6639132727Skan  [(set_attr "type" "alu")
6640132727Skan   (set_attr "pent_pair" "pu")
6641132727Skan   (set_attr "mode" "QI")])
664218334Speter
6643132727Skan(define_insn "subhi3_carry"
6644132727Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
6645132727Skan	  (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
6646132727Skan	    (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
6647132727Skan	       (match_operand:HI 2 "general_operand" "ri,rm"))))
6648169699Skan   (clobber (reg:CC FLAGS_REG))]
6649132727Skan  "ix86_binary_operator_ok (MINUS, HImode, operands)"
6650132727Skan  "sbb{w}\t{%2, %0|%0, %2}"
6651132727Skan  [(set_attr "type" "alu")
6652132727Skan   (set_attr "pent_pair" "pu")
6653132727Skan   (set_attr "mode" "HI")])
6654132727Skan
665590286Sobrien(define_insn "subsi3_carry"
665690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
665790286Sobrien	  (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6658132727Skan	    (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
665990286Sobrien	       (match_operand:SI 2 "general_operand" "ri,rm"))))
6660169699Skan   (clobber (reg:CC FLAGS_REG))]
666190286Sobrien  "ix86_binary_operator_ok (MINUS, SImode, operands)"
666290286Sobrien  "sbb{l}\t{%2, %0|%0, %2}"
666390286Sobrien  [(set_attr "type" "alu")
666490286Sobrien   (set_attr "pent_pair" "pu")
666590286Sobrien   (set_attr "mode" "SI")])
666618334Speter
666790286Sobrien(define_insn "subsi3_carry_zext"
666890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm,r")
666990286Sobrien	  (zero_extend:DI
667090286Sobrien	    (minus:SI (match_operand:SI 1 "register_operand" "0,0")
6671132727Skan	      (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
667290286Sobrien		 (match_operand:SI 2 "general_operand" "ri,rm")))))
6673169699Skan   (clobber (reg:CC FLAGS_REG))]
667490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
667590286Sobrien  "sbb{l}\t{%2, %k0|%k0, %2}"
667690286Sobrien  [(set_attr "type" "alu")
667790286Sobrien   (set_attr "pent_pair" "pu")
667890286Sobrien   (set_attr "mode" "SI")])
667918334Speter
668050650Sobrien(define_expand "subsi3"
668190286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
668290286Sobrien		   (minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
668390286Sobrien			     (match_operand:SI 2 "general_operand" "")))
6684169699Skan	      (clobber (reg:CC FLAGS_REG))])]
668550650Sobrien  ""
668690286Sobrien  "ix86_expand_binary_operator (MINUS, SImode, operands); DONE;")
668750650Sobrien
668890286Sobrien(define_insn "*subsi_1"
668950650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
669050650Sobrien	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
669190286Sobrien		  (match_operand:SI 2 "general_operand" "ri,rm")))
6692169699Skan   (clobber (reg:CC FLAGS_REG))]
669350650Sobrien  "ix86_binary_operator_ok (MINUS, SImode, operands)"
669490286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
669590286Sobrien  [(set_attr "type" "alu")
669690286Sobrien   (set_attr "mode" "SI")])
669718334Speter
669890286Sobrien(define_insn "*subsi_1_zext"
669990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
670090286Sobrien	(zero_extend:DI
670190286Sobrien	  (minus:SI (match_operand:SI 1 "register_operand" "0")
670290286Sobrien		    (match_operand:SI 2 "general_operand" "rim"))))
6703169699Skan   (clobber (reg:CC FLAGS_REG))]
670490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
670590286Sobrien  "sub{l}\t{%2, %k0|%k0, %2}"
670690286Sobrien  [(set_attr "type" "alu")
670790286Sobrien   (set_attr "mode" "SI")])
670890286Sobrien
670990286Sobrien(define_insn "*subsi_2"
6710169699Skan  [(set (reg FLAGS_REG)
671190286Sobrien	(compare
671290286Sobrien	  (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
671390286Sobrien		    (match_operand:SI 2 "general_operand" "ri,rm"))
671490286Sobrien	  (const_int 0)))
671590286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
671690286Sobrien	(minus:SI (match_dup 1) (match_dup 2)))]
671790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
671890286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
671990286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
672090286Sobrien  [(set_attr "type" "alu")
672190286Sobrien   (set_attr "mode" "SI")])
672290286Sobrien
672390286Sobrien(define_insn "*subsi_2_zext"
6724169699Skan  [(set (reg FLAGS_REG)
672590286Sobrien	(compare
672690286Sobrien	  (minus:SI (match_operand:SI 1 "register_operand" "0")
672790286Sobrien		    (match_operand:SI 2 "general_operand" "rim"))
672890286Sobrien	  (const_int 0)))
672990286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
673090286Sobrien	(zero_extend:DI
673190286Sobrien	  (minus:SI (match_dup 1)
673290286Sobrien		    (match_dup 2))))]
673390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
673490286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
673590286Sobrien  "sub{l}\t{%2, %k0|%k0, %2}"
673690286Sobrien  [(set_attr "type" "alu")
673790286Sobrien   (set_attr "mode" "SI")])
673890286Sobrien
673990286Sobrien(define_insn "*subsi_3"
6740169699Skan  [(set (reg FLAGS_REG)
674190286Sobrien	(compare (match_operand:SI 1 "nonimmediate_operand" "0,0")
674290286Sobrien		 (match_operand:SI 2 "general_operand" "ri,rm")))
674390286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
674490286Sobrien	(minus:SI (match_dup 1) (match_dup 2)))]
674590286Sobrien  "ix86_match_ccmode (insn, CCmode)
674690286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
674790286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
674890286Sobrien  [(set_attr "type" "alu")
674990286Sobrien   (set_attr "mode" "SI")])
675090286Sobrien
675190286Sobrien(define_insn "*subsi_3_zext"
6752169699Skan  [(set (reg FLAGS_REG)
6753132727Skan	(compare (match_operand:SI 1 "register_operand" "0")
675490286Sobrien		 (match_operand:SI 2 "general_operand" "rim")))
675590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
675690286Sobrien	(zero_extend:DI
675790286Sobrien	  (minus:SI (match_dup 1)
675890286Sobrien		    (match_dup 2))))]
675990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
676090286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
6761169699Skan  "sub{l}\t{%2, %1|%1, %2}"
676290286Sobrien  [(set_attr "type" "alu")
676390286Sobrien   (set_attr "mode" "DI")])
676490286Sobrien
676550650Sobrien(define_expand "subhi3"
676690286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
676790286Sobrien		   (minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
676890286Sobrien			     (match_operand:HI 2 "general_operand" "")))
6769169699Skan	      (clobber (reg:CC FLAGS_REG))])]
677090286Sobrien  "TARGET_HIMODE_MATH"
677190286Sobrien  "ix86_expand_binary_operator (MINUS, HImode, operands); DONE;")
677250650Sobrien
677390286Sobrien(define_insn "*subhi_1"
677450650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
677550650Sobrien	(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
677690286Sobrien		  (match_operand:HI 2 "general_operand" "ri,rm")))
6777169699Skan   (clobber (reg:CC FLAGS_REG))]
677850650Sobrien  "ix86_binary_operator_ok (MINUS, HImode, operands)"
677990286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
678090286Sobrien  [(set_attr "type" "alu")
678190286Sobrien   (set_attr "mode" "HI")])
678250650Sobrien
678390286Sobrien(define_insn "*subhi_2"
6784169699Skan  [(set (reg FLAGS_REG)
678590286Sobrien	(compare
678690286Sobrien	  (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
678790286Sobrien		    (match_operand:HI 2 "general_operand" "ri,rm"))
678890286Sobrien	  (const_int 0)))
678990286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
679090286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
679190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
679290286Sobrien   && ix86_binary_operator_ok (MINUS, HImode, operands)"
679390286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
679490286Sobrien  [(set_attr "type" "alu")
679590286Sobrien   (set_attr "mode" "HI")])
679690286Sobrien
679790286Sobrien(define_insn "*subhi_3"
6798169699Skan  [(set (reg FLAGS_REG)
679990286Sobrien	(compare (match_operand:HI 1 "nonimmediate_operand" "0,0")
680090286Sobrien		 (match_operand:HI 2 "general_operand" "ri,rm")))
680190286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
680290286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
680390286Sobrien  "ix86_match_ccmode (insn, CCmode)
680490286Sobrien   && ix86_binary_operator_ok (MINUS, HImode, operands)"
680590286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
680690286Sobrien  [(set_attr "type" "alu")
680790286Sobrien   (set_attr "mode" "HI")])
680890286Sobrien
680950650Sobrien(define_expand "subqi3"
681090286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
681190286Sobrien		   (minus:QI (match_operand:QI 1 "nonimmediate_operand" "")
681290286Sobrien			     (match_operand:QI 2 "general_operand" "")))
6813169699Skan	      (clobber (reg:CC FLAGS_REG))])]
681490286Sobrien  "TARGET_QIMODE_MATH"
681590286Sobrien  "ix86_expand_binary_operator (MINUS, QImode, operands); DONE;")
681618334Speter
681790286Sobrien(define_insn "*subqi_1"
681850650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
681950650Sobrien	(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
682090286Sobrien		  (match_operand:QI 2 "general_operand" "qn,qmn")))
6821169699Skan   (clobber (reg:CC FLAGS_REG))]
682250650Sobrien  "ix86_binary_operator_ok (MINUS, QImode, operands)"
682390286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
682490286Sobrien  [(set_attr "type" "alu")
682590286Sobrien   (set_attr "mode" "QI")])
682618334Speter
6827117404Skan(define_insn "*subqi_1_slp"
6828117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
6829117404Skan	(minus:QI (match_dup 0)
6830117404Skan		  (match_operand:QI 1 "general_operand" "qn,qmn")))
6831169699Skan   (clobber (reg:CC FLAGS_REG))]
6832117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
6833117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
6834117404Skan  "sub{b}\t{%1, %0|%0, %1}"
6835117404Skan  [(set_attr "type" "alu1")
6836117404Skan   (set_attr "mode" "QI")])
6837117404Skan
683890286Sobrien(define_insn "*subqi_2"
6839169699Skan  [(set (reg FLAGS_REG)
684090286Sobrien	(compare
684190286Sobrien	  (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
684290286Sobrien		    (match_operand:QI 2 "general_operand" "qi,qm"))
684390286Sobrien	  (const_int 0)))
684490286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
684590286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
684690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
684790286Sobrien   && ix86_binary_operator_ok (MINUS, QImode, operands)"
684890286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
684990286Sobrien  [(set_attr "type" "alu")
685090286Sobrien   (set_attr "mode" "QI")])
685190286Sobrien
685290286Sobrien(define_insn "*subqi_3"
6853169699Skan  [(set (reg FLAGS_REG)
685490286Sobrien	(compare (match_operand:QI 1 "nonimmediate_operand" "0,0")
685590286Sobrien		 (match_operand:QI 2 "general_operand" "qi,qm")))
685690286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
685790286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
685890286Sobrien  "ix86_match_ccmode (insn, CCmode)
685990286Sobrien   && ix86_binary_operator_ok (MINUS, QImode, operands)"
686090286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
686190286Sobrien  [(set_attr "type" "alu")
686290286Sobrien   (set_attr "mode" "QI")])
686390286Sobrien
686418334Speter;; The patterns that match these are at the end of this file.
686518334Speter
686618334Speter(define_expand "subxf3"
686718334Speter  [(set (match_operand:XF 0 "register_operand" "")
686850650Sobrien	(minus:XF (match_operand:XF 1 "register_operand" "")
686950650Sobrien		  (match_operand:XF 2 "register_operand" "")))]
687018334Speter  "TARGET_80387"
687118334Speter  "")
687218334Speter
687318334Speter(define_expand "subdf3"
687418334Speter  [(set (match_operand:DF 0 "register_operand" "")
687590286Sobrien	(minus:DF (match_operand:DF 1 "register_operand" "")
687618334Speter		  (match_operand:DF 2 "nonimmediate_operand" "")))]
687790286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
687818334Speter  "")
687918334Speter
688018334Speter(define_expand "subsf3"
688118334Speter  [(set (match_operand:SF 0 "register_operand" "")
688290286Sobrien	(minus:SF (match_operand:SF 1 "register_operand" "")
688318334Speter		  (match_operand:SF 2 "nonimmediate_operand" "")))]
688490286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
688518334Speter  "")
688618334Speter
688790286Sobrien;; Multiply instructions
688818334Speter
688990286Sobrien(define_expand "muldi3"
689090286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
689190286Sobrien		   (mult:DI (match_operand:DI 1 "register_operand" "")
689290286Sobrien			    (match_operand:DI 2 "x86_64_general_operand" "")))
6893169699Skan	      (clobber (reg:CC FLAGS_REG))])]
689490286Sobrien  "TARGET_64BIT"
689590286Sobrien  "")
689618334Speter
6897251212Spfg;; On AMDFAM10 
6898251212Spfg;; IMUL reg64, reg64, imm8 	Direct
6899251212Spfg;; IMUL reg64, mem64, imm8 	VectorPath
6900251212Spfg;; IMUL reg64, reg64, imm32 	Direct
6901251212Spfg;; IMUL reg64, mem64, imm32 	VectorPath 
6902251212Spfg;; IMUL reg64, reg64 		Direct
6903251212Spfg;; IMUL reg64, mem64 		Direct
6904251212Spfg
690590286Sobrien(define_insn "*muldi3_1_rex64"
690690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6907132727Skan	(mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,rm,0")
690890286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "K,e,mr")))
6909169699Skan   (clobber (reg:CC FLAGS_REG))]
691090286Sobrien  "TARGET_64BIT
691190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
691290286Sobrien  "@
691390286Sobrien   imul{q}\t{%2, %1, %0|%0, %1, %2}
691490286Sobrien   imul{q}\t{%2, %1, %0|%0, %1, %2}
691590286Sobrien   imul{q}\t{%2, %0|%0, %2}"
691690286Sobrien  [(set_attr "type" "imul")
691790286Sobrien   (set_attr "prefix_0f" "0,0,1")
6918132727Skan   (set (attr "athlon_decode")
6919132727Skan	(cond [(eq_attr "cpu" "athlon")
6920132727Skan		  (const_string "vector")
6921132727Skan	       (eq_attr "alternative" "1")
6922132727Skan		  (const_string "vector")
6923132727Skan	       (and (eq_attr "alternative" "2")
6924132727Skan		    (match_operand 1 "memory_operand" ""))
6925132727Skan		  (const_string "vector")]
6926132727Skan	      (const_string "direct")))
6927251212Spfg   (set (attr "amdfam10_decode")
6928251212Spfg	(cond [(and (eq_attr "alternative" "0,1")
6929251212Spfg		    (match_operand 1 "memory_operand" ""))
6930251212Spfg		  (const_string "vector")]
6931251212Spfg	      (const_string "direct")))	      
693290286Sobrien   (set_attr "mode" "DI")])
693318334Speter
693490286Sobrien(define_expand "mulsi3"
693590286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
693690286Sobrien		   (mult:SI (match_operand:SI 1 "register_operand" "")
693790286Sobrien			    (match_operand:SI 2 "general_operand" "")))
6938169699Skan	      (clobber (reg:CC FLAGS_REG))])]
693918334Speter  ""
694090286Sobrien  "")
694118334Speter
6942251212Spfg;; On AMDFAM10 
6943251212Spfg;; IMUL reg32, reg32, imm8 	Direct
6944251212Spfg;; IMUL reg32, mem32, imm8 	VectorPath
6945251212Spfg;; IMUL reg32, reg32, imm32 	Direct
6946251212Spfg;; IMUL reg32, mem32, imm32 	VectorPath
6947251212Spfg;; IMUL reg32, reg32 		Direct
6948251212Spfg;; IMUL reg32, mem32 		Direct
6949251212Spfg
695090286Sobrien(define_insn "*mulsi3_1"
695190286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
6952132727Skan	(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
695390286Sobrien		 (match_operand:SI 2 "general_operand" "K,i,mr")))
6954169699Skan   (clobber (reg:CC FLAGS_REG))]
695590286Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
695690286Sobrien  "@
695790286Sobrien   imul{l}\t{%2, %1, %0|%0, %1, %2}
695890286Sobrien   imul{l}\t{%2, %1, %0|%0, %1, %2}
695990286Sobrien   imul{l}\t{%2, %0|%0, %2}"
696090286Sobrien  [(set_attr "type" "imul")
696190286Sobrien   (set_attr "prefix_0f" "0,0,1")
6962132727Skan   (set (attr "athlon_decode")
6963132727Skan	(cond [(eq_attr "cpu" "athlon")
6964132727Skan		  (const_string "vector")
6965132727Skan	       (eq_attr "alternative" "1")
6966132727Skan		  (const_string "vector")
6967132727Skan	       (and (eq_attr "alternative" "2")
6968132727Skan		    (match_operand 1 "memory_operand" ""))
6969132727Skan		  (const_string "vector")]
6970132727Skan	      (const_string "direct")))
6971251212Spfg   (set (attr "amdfam10_decode")
6972251212Spfg	(cond [(and (eq_attr "alternative" "0,1")
6973251212Spfg		    (match_operand 1 "memory_operand" ""))
6974251212Spfg		  (const_string "vector")]
6975251212Spfg	      (const_string "direct")))	      
697690286Sobrien   (set_attr "mode" "SI")])
697790286Sobrien
697890286Sobrien(define_insn "*mulsi3_1_zext"
697990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
698090286Sobrien	(zero_extend:DI
6981132727Skan	  (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
698290286Sobrien		   (match_operand:SI 2 "general_operand" "K,i,mr"))))
6983169699Skan   (clobber (reg:CC FLAGS_REG))]
698490286Sobrien  "TARGET_64BIT
698590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
698690286Sobrien  "@
698790286Sobrien   imul{l}\t{%2, %1, %k0|%k0, %1, %2}
698890286Sobrien   imul{l}\t{%2, %1, %k0|%k0, %1, %2}
698990286Sobrien   imul{l}\t{%2, %k0|%k0, %2}"
699090286Sobrien  [(set_attr "type" "imul")
699190286Sobrien   (set_attr "prefix_0f" "0,0,1")
6992132727Skan   (set (attr "athlon_decode")
6993132727Skan	(cond [(eq_attr "cpu" "athlon")
6994132727Skan		  (const_string "vector")
6995132727Skan	       (eq_attr "alternative" "1")
6996132727Skan		  (const_string "vector")
6997132727Skan	       (and (eq_attr "alternative" "2")
6998132727Skan		    (match_operand 1 "memory_operand" ""))
6999132727Skan		  (const_string "vector")]
7000132727Skan	      (const_string "direct")))
7001251212Spfg   (set (attr "amdfam10_decode")
7002251212Spfg	(cond [(and (eq_attr "alternative" "0,1")
7003251212Spfg		    (match_operand 1 "memory_operand" ""))
7004251212Spfg		  (const_string "vector")]
7005251212Spfg	      (const_string "direct")))	      
700690286Sobrien   (set_attr "mode" "SI")])
700790286Sobrien
700890286Sobrien(define_expand "mulhi3"
700990286Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
701090286Sobrien		   (mult:HI (match_operand:HI 1 "register_operand" "")
701190286Sobrien			    (match_operand:HI 2 "general_operand" "")))
7012169699Skan	      (clobber (reg:CC FLAGS_REG))])]
701390286Sobrien  "TARGET_HIMODE_MATH"
701490286Sobrien  "")
701590286Sobrien
7016251212Spfg;; On AMDFAM10
7017251212Spfg;; IMUL reg16, reg16, imm8 	VectorPath
7018251212Spfg;; IMUL reg16, mem16, imm8 	VectorPath
7019251212Spfg;; IMUL reg16, reg16, imm16 	VectorPath
7020251212Spfg;; IMUL reg16, mem16, imm16 	VectorPath
7021251212Spfg;; IMUL reg16, reg16 		Direct
7022251212Spfg;; IMUL reg16, mem16 		Direct
702390286Sobrien(define_insn "*mulhi3_1"
702490286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
7025132727Skan	(mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rm,rm,0")
702690286Sobrien		 (match_operand:HI 2 "general_operand" "K,i,mr")))
7027169699Skan   (clobber (reg:CC FLAGS_REG))]
702890286Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
702990286Sobrien  "@
703090286Sobrien   imul{w}\t{%2, %1, %0|%0, %1, %2}
703190286Sobrien   imul{w}\t{%2, %1, %0|%0, %1, %2}
703290286Sobrien   imul{w}\t{%2, %0|%0, %2}"
703390286Sobrien  [(set_attr "type" "imul")
703490286Sobrien   (set_attr "prefix_0f" "0,0,1")
7035132727Skan   (set (attr "athlon_decode")
7036132727Skan	(cond [(eq_attr "cpu" "athlon")
7037132727Skan		  (const_string "vector")
7038132727Skan	       (eq_attr "alternative" "1,2")
7039132727Skan		  (const_string "vector")]
7040132727Skan	      (const_string "direct")))
7041251212Spfg   (set (attr "amdfam10_decode")
7042251212Spfg	(cond [(eq_attr "alternative" "0,1")
7043251212Spfg		  (const_string "vector")]
7044251212Spfg	      (const_string "direct")))
704590286Sobrien   (set_attr "mode" "HI")])
704690286Sobrien
704796294Sobrien(define_expand "mulqi3"
704896294Sobrien  [(parallel [(set (match_operand:QI 0 "register_operand" "")
704996294Sobrien		   (mult:QI (match_operand:QI 1 "nonimmediate_operand" "")
705096294Sobrien			    (match_operand:QI 2 "register_operand" "")))
7051169699Skan	      (clobber (reg:CC FLAGS_REG))])]
705296294Sobrien  "TARGET_QIMODE_MATH"
705396294Sobrien  "")
705496294Sobrien
7055251212Spfg;;On AMDFAM10
7056251212Spfg;; MUL reg8 	Direct
7057251212Spfg;; MUL mem8 	Direct
7058251212Spfg
705996294Sobrien(define_insn "*mulqi3_1"
706090286Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
706196294Sobrien	(mult:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
706290286Sobrien		 (match_operand:QI 2 "nonimmediate_operand" "qm")))
7063169699Skan   (clobber (reg:CC FLAGS_REG))]
706496294Sobrien  "TARGET_QIMODE_MATH
706596294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
706690286Sobrien  "mul{b}\t%2"
706790286Sobrien  [(set_attr "type" "imul")
706890286Sobrien   (set_attr "length_immediate" "0")
7069132727Skan   (set (attr "athlon_decode")
7070132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7071132727Skan        (const_string "vector")
7072132727Skan        (const_string "direct")))
7073251212Spfg   (set_attr "amdfam10_decode" "direct")        
707490286Sobrien   (set_attr "mode" "QI")])
707590286Sobrien
707696294Sobrien(define_expand "umulqihi3"
707796294Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
707896294Sobrien		   (mult:HI (zero_extend:HI
707996294Sobrien			      (match_operand:QI 1 "nonimmediate_operand" ""))
708096294Sobrien			    (zero_extend:HI
708196294Sobrien			      (match_operand:QI 2 "register_operand" ""))))
7082169699Skan	      (clobber (reg:CC FLAGS_REG))])]
708396294Sobrien  "TARGET_QIMODE_MATH"
708496294Sobrien  "")
708596294Sobrien
708696294Sobrien(define_insn "*umulqihi3_1"
708750650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
708896294Sobrien	(mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
708990286Sobrien		 (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
7090169699Skan   (clobber (reg:CC FLAGS_REG))]
709196294Sobrien  "TARGET_QIMODE_MATH
709296294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
709390286Sobrien  "mul{b}\t%2"
709490286Sobrien  [(set_attr "type" "imul")
709590286Sobrien   (set_attr "length_immediate" "0")
7096132727Skan   (set (attr "athlon_decode")
7097132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7098132727Skan        (const_string "vector")
7099132727Skan        (const_string "direct")))
7100251212Spfg   (set_attr "amdfam10_decode" "direct")        
710190286Sobrien   (set_attr "mode" "QI")])
710218334Speter
710396294Sobrien(define_expand "mulqihi3"
710496294Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
710596294Sobrien		   (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))
710696294Sobrien			    (sign_extend:HI (match_operand:QI 2 "register_operand" ""))))
7107169699Skan	      (clobber (reg:CC FLAGS_REG))])]
710896294Sobrien  "TARGET_QIMODE_MATH"
710996294Sobrien  "")
711096294Sobrien
711196294Sobrien(define_insn "*mulqihi3_insn"
711250650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
711396294Sobrien	(mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
711490286Sobrien		 (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
7115169699Skan   (clobber (reg:CC FLAGS_REG))]
711696294Sobrien  "TARGET_QIMODE_MATH
711796294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
711890286Sobrien  "imul{b}\t%2"
711990286Sobrien  [(set_attr "type" "imul")
712090286Sobrien   (set_attr "length_immediate" "0")
7121132727Skan   (set (attr "athlon_decode")
7122132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7123132727Skan        (const_string "vector")
7124132727Skan        (const_string "direct")))
7125251212Spfg   (set_attr "amdfam10_decode" "direct")        
712690286Sobrien   (set_attr "mode" "QI")])
712718334Speter
712896294Sobrien(define_expand "umulditi3"
712996294Sobrien  [(parallel [(set (match_operand:TI 0 "register_operand" "")
713096294Sobrien		   (mult:TI (zero_extend:TI
713196294Sobrien			      (match_operand:DI 1 "nonimmediate_operand" ""))
713296294Sobrien			    (zero_extend:TI
713396294Sobrien			      (match_operand:DI 2 "register_operand" ""))))
7134169699Skan	      (clobber (reg:CC FLAGS_REG))])]
713596294Sobrien  "TARGET_64BIT"
713696294Sobrien  "")
713796294Sobrien
713896294Sobrien(define_insn "*umulditi3_insn"
713990286Sobrien  [(set (match_operand:TI 0 "register_operand" "=A")
714096294Sobrien	(mult:TI (zero_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
714190286Sobrien		 (zero_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
7142169699Skan   (clobber (reg:CC FLAGS_REG))]
714396294Sobrien  "TARGET_64BIT
714496294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
714590286Sobrien  "mul{q}\t%2"
714690286Sobrien  [(set_attr "type" "imul")
714790286Sobrien   (set_attr "length_immediate" "0")
7148132727Skan   (set (attr "athlon_decode")
7149132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7150132727Skan        (const_string "vector")
7151132727Skan        (const_string "double")))
7152251212Spfg   (set_attr "amdfam10_decode" "double")        
715390286Sobrien   (set_attr "mode" "DI")])
715490286Sobrien
715590286Sobrien;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers
715696294Sobrien(define_expand "umulsidi3"
715796294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
715896294Sobrien		   (mult:DI (zero_extend:DI
715996294Sobrien			      (match_operand:SI 1 "nonimmediate_operand" ""))
716096294Sobrien			    (zero_extend:DI
716196294Sobrien			      (match_operand:SI 2 "register_operand" ""))))
7162169699Skan	      (clobber (reg:CC FLAGS_REG))])]
716396294Sobrien  "!TARGET_64BIT"
716496294Sobrien  "")
716596294Sobrien
716696294Sobrien(define_insn "*umulsidi3_insn"
716718334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
716896294Sobrien	(mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
716990286Sobrien		 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
7170169699Skan   (clobber (reg:CC FLAGS_REG))]
717196294Sobrien  "!TARGET_64BIT
717296294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
717390286Sobrien  "mul{l}\t%2"
717490286Sobrien  [(set_attr "type" "imul")
717590286Sobrien   (set_attr "length_immediate" "0")
7176132727Skan   (set (attr "athlon_decode")
7177132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7178132727Skan        (const_string "vector")
7179132727Skan        (const_string "double")))
7180251212Spfg   (set_attr "amdfam10_decode" "double")        
718190286Sobrien   (set_attr "mode" "SI")])
718218334Speter
718396294Sobrien(define_expand "mulditi3"
718496294Sobrien  [(parallel [(set (match_operand:TI 0 "register_operand" "")
718596294Sobrien		   (mult:TI (sign_extend:TI
718696294Sobrien			      (match_operand:DI 1 "nonimmediate_operand" ""))
718796294Sobrien			    (sign_extend:TI
718896294Sobrien			      (match_operand:DI 2 "register_operand" ""))))
7189169699Skan	      (clobber (reg:CC FLAGS_REG))])]
719096294Sobrien  "TARGET_64BIT"
719196294Sobrien  "")
719296294Sobrien
719396294Sobrien(define_insn "*mulditi3_insn"
719490286Sobrien  [(set (match_operand:TI 0 "register_operand" "=A")
719596294Sobrien	(mult:TI (sign_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
719690286Sobrien		 (sign_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
7197169699Skan   (clobber (reg:CC FLAGS_REG))]
719896294Sobrien  "TARGET_64BIT
719996294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
720090286Sobrien  "imul{q}\t%2"
720190286Sobrien  [(set_attr "type" "imul")
720290286Sobrien   (set_attr "length_immediate" "0")
7203132727Skan   (set (attr "athlon_decode")
7204132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7205132727Skan        (const_string "vector")
7206132727Skan        (const_string "double")))
7207251212Spfg   (set_attr "amdfam10_decode" "double")
720890286Sobrien   (set_attr "mode" "DI")])
720990286Sobrien
721096294Sobrien(define_expand "mulsidi3"
721196294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
721296294Sobrien		   (mult:DI (sign_extend:DI
721396294Sobrien			      (match_operand:SI 1 "nonimmediate_operand" ""))
721496294Sobrien			    (sign_extend:DI
721596294Sobrien			      (match_operand:SI 2 "register_operand" ""))))
7216169699Skan	      (clobber (reg:CC FLAGS_REG))])]
721796294Sobrien  "!TARGET_64BIT"
721896294Sobrien  "")
721996294Sobrien
722096294Sobrien(define_insn "*mulsidi3_insn"
722118334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
722296294Sobrien	(mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
722390286Sobrien		 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
7224169699Skan   (clobber (reg:CC FLAGS_REG))]
722596294Sobrien  "!TARGET_64BIT
722696294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
722790286Sobrien  "imul{l}\t%2"
722890286Sobrien  [(set_attr "type" "imul")
722990286Sobrien   (set_attr "length_immediate" "0")
7230132727Skan   (set (attr "athlon_decode")
7231132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7232132727Skan        (const_string "vector")
7233132727Skan        (const_string "double")))
7234251212Spfg   (set_attr "amdfam10_decode" "double")        
723590286Sobrien   (set_attr "mode" "SI")])
723618334Speter
723796294Sobrien(define_expand "umuldi3_highpart"
723896294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
723996294Sobrien		   (truncate:DI
724096294Sobrien		     (lshiftrt:TI
724196294Sobrien		       (mult:TI (zero_extend:TI
724296294Sobrien				  (match_operand:DI 1 "nonimmediate_operand" ""))
724396294Sobrien				(zero_extend:TI
724496294Sobrien				  (match_operand:DI 2 "register_operand" "")))
724596294Sobrien		       (const_int 64))))
724696294Sobrien	      (clobber (match_scratch:DI 3 ""))
7247169699Skan	      (clobber (reg:CC FLAGS_REG))])]
724896294Sobrien  "TARGET_64BIT"
724996294Sobrien  "")
725096294Sobrien
725190286Sobrien(define_insn "*umuldi3_highpart_rex64"
725290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
725390286Sobrien	(truncate:DI
725490286Sobrien	  (lshiftrt:TI
725590286Sobrien	    (mult:TI (zero_extend:TI
725696294Sobrien		       (match_operand:DI 1 "nonimmediate_operand" "%a"))
725790286Sobrien		     (zero_extend:TI
725890286Sobrien		       (match_operand:DI 2 "nonimmediate_operand" "rm")))
725990286Sobrien	    (const_int 64))))
726096294Sobrien   (clobber (match_scratch:DI 3 "=1"))
7261169699Skan   (clobber (reg:CC FLAGS_REG))]
726296294Sobrien  "TARGET_64BIT
726396294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
726490286Sobrien  "mul{q}\t%2"
726590286Sobrien  [(set_attr "type" "imul")
726690286Sobrien   (set_attr "length_immediate" "0")
7267132727Skan   (set (attr "athlon_decode")
7268132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7269132727Skan        (const_string "vector")
7270132727Skan        (const_string "double")))
7271251212Spfg   (set_attr "amdfam10_decode" "double")        
727290286Sobrien   (set_attr "mode" "DI")])
727390286Sobrien
727496294Sobrien(define_expand "umulsi3_highpart"
727596294Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
727696294Sobrien		   (truncate:SI
727796294Sobrien		     (lshiftrt:DI
727896294Sobrien		       (mult:DI (zero_extend:DI
727996294Sobrien				  (match_operand:SI 1 "nonimmediate_operand" ""))
728096294Sobrien				(zero_extend:DI
728196294Sobrien				  (match_operand:SI 2 "register_operand" "")))
728296294Sobrien		       (const_int 32))))
728396294Sobrien	      (clobber (match_scratch:SI 3 ""))
7284169699Skan	      (clobber (reg:CC FLAGS_REG))])]
728596294Sobrien  ""
728696294Sobrien  "")
728796294Sobrien
728896294Sobrien(define_insn "*umulsi3_highpart_insn"
728918334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
729090286Sobrien	(truncate:SI
729190286Sobrien	  (lshiftrt:DI
729290286Sobrien	    (mult:DI (zero_extend:DI
729396294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
729490286Sobrien		     (zero_extend:DI
729590286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
729690286Sobrien	    (const_int 32))))
729796294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7298169699Skan   (clobber (reg:CC FLAGS_REG))]
729996294Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
730090286Sobrien  "mul{l}\t%2"
730190286Sobrien  [(set_attr "type" "imul")
730290286Sobrien   (set_attr "length_immediate" "0")
7303132727Skan   (set (attr "athlon_decode")
7304132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7305132727Skan        (const_string "vector")
7306132727Skan        (const_string "double")))
7307251212Spfg   (set_attr "amdfam10_decode" "double")
730890286Sobrien   (set_attr "mode" "SI")])
730918334Speter
731090286Sobrien(define_insn "*umulsi3_highpart_zext"
731190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
731290286Sobrien	(zero_extend:DI (truncate:SI
731390286Sobrien	  (lshiftrt:DI
731490286Sobrien	    (mult:DI (zero_extend:DI
731596294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
731690286Sobrien		     (zero_extend:DI
731790286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
731890286Sobrien	    (const_int 32)))))
731996294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7320169699Skan   (clobber (reg:CC FLAGS_REG))]
732196294Sobrien  "TARGET_64BIT
732296294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
732390286Sobrien  "mul{l}\t%2"
732490286Sobrien  [(set_attr "type" "imul")
732590286Sobrien   (set_attr "length_immediate" "0")
7326132727Skan   (set (attr "athlon_decode")
7327132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7328132727Skan        (const_string "vector")
7329132727Skan        (const_string "double")))
7330251212Spfg   (set_attr "amdfam10_decode" "double")
733190286Sobrien   (set_attr "mode" "SI")])
733290286Sobrien
733396294Sobrien(define_expand "smuldi3_highpart"
733496294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "=d")
733596294Sobrien		   (truncate:DI
733696294Sobrien		     (lshiftrt:TI
733796294Sobrien		       (mult:TI (sign_extend:TI
733896294Sobrien				  (match_operand:DI 1 "nonimmediate_operand" ""))
733996294Sobrien				(sign_extend:TI
734096294Sobrien				  (match_operand:DI 2 "register_operand" "")))
734196294Sobrien		       (const_int 64))))
734296294Sobrien	      (clobber (match_scratch:DI 3 ""))
7343169699Skan	      (clobber (reg:CC FLAGS_REG))])]
734496294Sobrien  "TARGET_64BIT"
734596294Sobrien  "")
734696294Sobrien
734790286Sobrien(define_insn "*smuldi3_highpart_rex64"
734890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
734990286Sobrien	(truncate:DI
735090286Sobrien	  (lshiftrt:TI
735190286Sobrien	    (mult:TI (sign_extend:TI
735296294Sobrien		       (match_operand:DI 1 "nonimmediate_operand" "%a"))
735390286Sobrien		     (sign_extend:TI
735490286Sobrien		       (match_operand:DI 2 "nonimmediate_operand" "rm")))
735590286Sobrien	    (const_int 64))))
735696294Sobrien   (clobber (match_scratch:DI 3 "=1"))
7357169699Skan   (clobber (reg:CC FLAGS_REG))]
735896294Sobrien  "TARGET_64BIT
735996294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
736090286Sobrien  "imul{q}\t%2"
736190286Sobrien  [(set_attr "type" "imul")
7362132727Skan   (set (attr "athlon_decode")
7363132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7364132727Skan        (const_string "vector")
7365132727Skan        (const_string "double")))
7366251212Spfg   (set_attr "amdfam10_decode" "double")
736790286Sobrien   (set_attr "mode" "DI")])
736890286Sobrien
736996294Sobrien(define_expand "smulsi3_highpart"
737096294Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
737196294Sobrien		   (truncate:SI
737296294Sobrien		     (lshiftrt:DI
737396294Sobrien		       (mult:DI (sign_extend:DI
737496294Sobrien				  (match_operand:SI 1 "nonimmediate_operand" ""))
737596294Sobrien				(sign_extend:DI
737696294Sobrien				  (match_operand:SI 2 "register_operand" "")))
737796294Sobrien		       (const_int 32))))
737896294Sobrien	      (clobber (match_scratch:SI 3 ""))
7379169699Skan	      (clobber (reg:CC FLAGS_REG))])]
738096294Sobrien  ""
738196294Sobrien  "")
738296294Sobrien
738396294Sobrien(define_insn "*smulsi3_highpart_insn"
738418334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
738590286Sobrien	(truncate:SI
738690286Sobrien	  (lshiftrt:DI
738790286Sobrien	    (mult:DI (sign_extend:DI
738896294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
738990286Sobrien		     (sign_extend:DI
739090286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
739190286Sobrien	    (const_int 32))))
739296294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7393169699Skan   (clobber (reg:CC FLAGS_REG))]
739496294Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
739590286Sobrien  "imul{l}\t%2"
739690286Sobrien  [(set_attr "type" "imul")
7397132727Skan   (set (attr "athlon_decode")
7398132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7399132727Skan        (const_string "vector")
7400132727Skan        (const_string "double")))
7401251212Spfg   (set_attr "amdfam10_decode" "double")
740290286Sobrien   (set_attr "mode" "SI")])
740318334Speter
740490286Sobrien(define_insn "*smulsi3_highpart_zext"
740590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
740690286Sobrien	(zero_extend:DI (truncate:SI
740790286Sobrien	  (lshiftrt:DI
740890286Sobrien	    (mult:DI (sign_extend:DI
740996294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
741090286Sobrien		     (sign_extend:DI
741190286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
741290286Sobrien	    (const_int 32)))))
741396294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7414169699Skan   (clobber (reg:CC FLAGS_REG))]
741596294Sobrien  "TARGET_64BIT
741696294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
741790286Sobrien  "imul{l}\t%2"
741890286Sobrien  [(set_attr "type" "imul")
7419132727Skan   (set (attr "athlon_decode")
7420132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7421132727Skan        (const_string "vector")
7422132727Skan        (const_string "double")))
7423251212Spfg   (set_attr "amdfam10_decode" "double")
742490286Sobrien   (set_attr "mode" "SI")])
742590286Sobrien
742618334Speter;; The patterns that match these are at the end of this file.
742718334Speter
742818334Speter(define_expand "mulxf3"
742918334Speter  [(set (match_operand:XF 0 "register_operand" "")
743050650Sobrien	(mult:XF (match_operand:XF 1 "register_operand" "")
743150650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
743218334Speter  "TARGET_80387"
743318334Speter  "")
743418334Speter
743518334Speter(define_expand "muldf3"
743618334Speter  [(set (match_operand:DF 0 "register_operand" "")
743750650Sobrien	(mult:DF (match_operand:DF 1 "register_operand" "")
743818334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
743990286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
744018334Speter  "")
744118334Speter
744218334Speter(define_expand "mulsf3"
744318334Speter  [(set (match_operand:SF 0 "register_operand" "")
744450650Sobrien	(mult:SF (match_operand:SF 1 "register_operand" "")
744518334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
744690286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
744718334Speter  "")
744818334Speter
744990286Sobrien;; Divide instructions
745018334Speter
745118334Speter(define_insn "divqi3"
745250650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
745350650Sobrien	(div:QI (match_operand:HI 1 "register_operand" "0")
745490286Sobrien		(match_operand:QI 2 "nonimmediate_operand" "qm")))
7455169699Skan   (clobber (reg:CC FLAGS_REG))]
745690286Sobrien  "TARGET_QIMODE_MATH"
745790286Sobrien  "idiv{b}\t%2"
745890286Sobrien  [(set_attr "type" "idiv")
7459169699Skan   (set_attr "mode" "QI")])
746018334Speter
746118334Speter(define_insn "udivqi3"
746250650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
746350650Sobrien	(udiv:QI (match_operand:HI 1 "register_operand" "0")
746490286Sobrien		 (match_operand:QI 2 "nonimmediate_operand" "qm")))
7465169699Skan   (clobber (reg:CC FLAGS_REG))]
746690286Sobrien  "TARGET_QIMODE_MATH"
746790286Sobrien  "div{b}\t%2"
746890286Sobrien  [(set_attr "type" "idiv")
7469169699Skan   (set_attr "mode" "QI")])
747018334Speter
747118334Speter;; The patterns that match these are at the end of this file.
747218334Speter
747318334Speter(define_expand "divxf3"
747418334Speter  [(set (match_operand:XF 0 "register_operand" "")
747550650Sobrien	(div:XF (match_operand:XF 1 "register_operand" "")
747650650Sobrien		(match_operand:XF 2 "register_operand" "")))]
747718334Speter  "TARGET_80387"
747818334Speter  "")
747918334Speter
748018334Speter(define_expand "divdf3"
748118334Speter  [(set (match_operand:DF 0 "register_operand" "")
748250650Sobrien 	(div:DF (match_operand:DF 1 "register_operand" "")
748350650Sobrien 		(match_operand:DF 2 "nonimmediate_operand" "")))]
748490286Sobrien   "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
748550650Sobrien   "")
7486259563Spfg
748718334Speter(define_expand "divsf3"
748818334Speter  [(set (match_operand:SF 0 "register_operand" "")
748950650Sobrien	(div:SF (match_operand:SF 1 "register_operand" "")
749018334Speter		(match_operand:SF 2 "nonimmediate_operand" "")))]
749190286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
749218334Speter  "")
749318334Speter
749418334Speter;; Remainder instructions.
749518334Speter
749690286Sobrien(define_expand "divmoddi4"
749790286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
749890286Sobrien		   (div:DI (match_operand:DI 1 "register_operand" "")
749990286Sobrien			   (match_operand:DI 2 "nonimmediate_operand" "")))
750090286Sobrien	      (set (match_operand:DI 3 "register_operand" "")
750190286Sobrien		   (mod:DI (match_dup 1) (match_dup 2)))
7502169699Skan	      (clobber (reg:CC FLAGS_REG))])]
750390286Sobrien  "TARGET_64BIT"
750490286Sobrien  "")
750590286Sobrien
750690286Sobrien;; Allow to come the parameter in eax or edx to avoid extra moves.
7507132727Skan;; Penalize eax case slightly because it results in worse scheduling
750890286Sobrien;; of code.
750990286Sobrien(define_insn "*divmoddi4_nocltd_rex64"
751090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=&a,?a")
751190286Sobrien	(div:DI (match_operand:DI 2 "register_operand" "1,0")
751290286Sobrien		(match_operand:DI 3 "nonimmediate_operand" "rm,rm")))
751390286Sobrien   (set (match_operand:DI 1 "register_operand" "=&d,&d")
751490286Sobrien	(mod:DI (match_dup 2) (match_dup 3)))
7515169699Skan   (clobber (reg:CC FLAGS_REG))]
751690286Sobrien  "TARGET_64BIT && !optimize_size && !TARGET_USE_CLTD"
751790286Sobrien  "#"
751890286Sobrien  [(set_attr "type" "multi")])
751990286Sobrien
752090286Sobrien(define_insn "*divmoddi4_cltd_rex64"
752190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
752290286Sobrien	(div:DI (match_operand:DI 2 "register_operand" "a")
752390286Sobrien		(match_operand:DI 3 "nonimmediate_operand" "rm")))
752490286Sobrien   (set (match_operand:DI 1 "register_operand" "=&d")
752590286Sobrien	(mod:DI (match_dup 2) (match_dup 3)))
7526169699Skan   (clobber (reg:CC FLAGS_REG))]
752790286Sobrien  "TARGET_64BIT && (optimize_size || TARGET_USE_CLTD)"
752890286Sobrien  "#"
752990286Sobrien  [(set_attr "type" "multi")])
753090286Sobrien
753190286Sobrien(define_insn "*divmoddi_noext_rex64"
753290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
753390286Sobrien	(div:DI (match_operand:DI 1 "register_operand" "0")
753490286Sobrien		(match_operand:DI 2 "nonimmediate_operand" "rm")))
753590286Sobrien   (set (match_operand:DI 3 "register_operand" "=d")
753690286Sobrien	(mod:DI (match_dup 1) (match_dup 2)))
753790286Sobrien   (use (match_operand:DI 4 "register_operand" "3"))
7538169699Skan   (clobber (reg:CC FLAGS_REG))]
753990286Sobrien  "TARGET_64BIT"
754090286Sobrien  "idiv{q}\t%2"
754190286Sobrien  [(set_attr "type" "idiv")
7542169699Skan   (set_attr "mode" "DI")])
754390286Sobrien
754490286Sobrien(define_split
754590286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
754690286Sobrien	(div:DI (match_operand:DI 1 "register_operand" "")
754790286Sobrien		(match_operand:DI 2 "nonimmediate_operand" "")))
754890286Sobrien   (set (match_operand:DI 3 "register_operand" "")
754990286Sobrien	(mod:DI (match_dup 1) (match_dup 2)))
7550169699Skan   (clobber (reg:CC FLAGS_REG))]
755190286Sobrien  "TARGET_64BIT && reload_completed"
755290286Sobrien  [(parallel [(set (match_dup 3)
755390286Sobrien		   (ashiftrt:DI (match_dup 4) (const_int 63)))
7554169699Skan	      (clobber (reg:CC FLAGS_REG))])
755590286Sobrien   (parallel [(set (match_dup 0)
755690286Sobrien	           (div:DI (reg:DI 0) (match_dup 2)))
755790286Sobrien	      (set (match_dup 3)
755890286Sobrien		   (mod:DI (reg:DI 0) (match_dup 2)))
755990286Sobrien	      (use (match_dup 3))
7560169699Skan	      (clobber (reg:CC FLAGS_REG))])]
756190286Sobrien{
7562117404Skan  /* Avoid use of cltd in favor of a mov+shift.  */
756390286Sobrien  if (!TARGET_USE_CLTD && !optimize_size)
756490286Sobrien    {
756590286Sobrien      if (true_regnum (operands[1]))
756690286Sobrien        emit_move_insn (operands[0], operands[1]);
756790286Sobrien      else
756890286Sobrien	emit_move_insn (operands[3], operands[1]);
756990286Sobrien      operands[4] = operands[3];
757090286Sobrien    }
757190286Sobrien  else
757290286Sobrien    {
7573169699Skan      gcc_assert (!true_regnum (operands[1]));
757490286Sobrien      operands[4] = operands[1];
757590286Sobrien    }
757690286Sobrien})
757790286Sobrien
757890286Sobrien
757990286Sobrien(define_expand "divmodsi4"
758090286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
758190286Sobrien		   (div:SI (match_operand:SI 1 "register_operand" "")
758290286Sobrien			   (match_operand:SI 2 "nonimmediate_operand" "")))
758390286Sobrien	      (set (match_operand:SI 3 "register_operand" "")
758490286Sobrien		   (mod:SI (match_dup 1) (match_dup 2)))
7585169699Skan	      (clobber (reg:CC FLAGS_REG))])]
758690286Sobrien  ""
758790286Sobrien  "")
758890286Sobrien
758990286Sobrien;; Allow to come the parameter in eax or edx to avoid extra moves.
7590132727Skan;; Penalize eax case slightly because it results in worse scheduling
759190286Sobrien;; of code.
759290286Sobrien(define_insn "*divmodsi4_nocltd"
759390286Sobrien  [(set (match_operand:SI 0 "register_operand" "=&a,?a")
759490286Sobrien	(div:SI (match_operand:SI 2 "register_operand" "1,0")
759590286Sobrien		(match_operand:SI 3 "nonimmediate_operand" "rm,rm")))
759690286Sobrien   (set (match_operand:SI 1 "register_operand" "=&d,&d")
759790286Sobrien	(mod:SI (match_dup 2) (match_dup 3)))
7598169699Skan   (clobber (reg:CC FLAGS_REG))]
759990286Sobrien  "!optimize_size && !TARGET_USE_CLTD"
760090286Sobrien  "#"
760190286Sobrien  [(set_attr "type" "multi")])
760290286Sobrien
760390286Sobrien(define_insn "*divmodsi4_cltd"
760418334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
760590286Sobrien	(div:SI (match_operand:SI 2 "register_operand" "a")
760690286Sobrien		(match_operand:SI 3 "nonimmediate_operand" "rm")))
760790286Sobrien   (set (match_operand:SI 1 "register_operand" "=&d")
760890286Sobrien	(mod:SI (match_dup 2) (match_dup 3)))
7609169699Skan   (clobber (reg:CC FLAGS_REG))]
761090286Sobrien  "optimize_size || TARGET_USE_CLTD"
761190286Sobrien  "#"
761290286Sobrien  [(set_attr "type" "multi")])
761390286Sobrien
761490286Sobrien(define_insn "*divmodsi_noext"
761590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a")
761618334Speter	(div:SI (match_operand:SI 1 "register_operand" "0")
761750650Sobrien		(match_operand:SI 2 "nonimmediate_operand" "rm")))
761890286Sobrien   (set (match_operand:SI 3 "register_operand" "=d")
761990286Sobrien	(mod:SI (match_dup 1) (match_dup 2)))
762090286Sobrien   (use (match_operand:SI 4 "register_operand" "3"))
7621169699Skan   (clobber (reg:CC FLAGS_REG))]
762218334Speter  ""
762390286Sobrien  "idiv{l}\t%2"
762490286Sobrien  [(set_attr "type" "idiv")
7625169699Skan   (set_attr "mode" "SI")])
762690286Sobrien
762790286Sobrien(define_split
762890286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
762990286Sobrien	(div:SI (match_operand:SI 1 "register_operand" "")
763090286Sobrien		(match_operand:SI 2 "nonimmediate_operand" "")))
763190286Sobrien   (set (match_operand:SI 3 "register_operand" "")
763290286Sobrien	(mod:SI (match_dup 1) (match_dup 2)))
7633169699Skan   (clobber (reg:CC FLAGS_REG))]
763490286Sobrien  "reload_completed"
763590286Sobrien  [(parallel [(set (match_dup 3)
763690286Sobrien		   (ashiftrt:SI (match_dup 4) (const_int 31)))
7637169699Skan	      (clobber (reg:CC FLAGS_REG))])
763890286Sobrien   (parallel [(set (match_dup 0)
763990286Sobrien	           (div:SI (reg:SI 0) (match_dup 2)))
764090286Sobrien	      (set (match_dup 3)
764190286Sobrien		   (mod:SI (reg:SI 0) (match_dup 2)))
764290286Sobrien	      (use (match_dup 3))
7643169699Skan	      (clobber (reg:CC FLAGS_REG))])]
764418334Speter{
7645117404Skan  /* Avoid use of cltd in favor of a mov+shift.  */
764690286Sobrien  if (!TARGET_USE_CLTD && !optimize_size)
764790286Sobrien    {
764890286Sobrien      if (true_regnum (operands[1]))
764990286Sobrien        emit_move_insn (operands[0], operands[1]);
765090286Sobrien      else
765190286Sobrien	emit_move_insn (operands[3], operands[1]);
765290286Sobrien      operands[4] = operands[3];
765390286Sobrien    }
765490286Sobrien  else
765590286Sobrien    {
7656169699Skan      gcc_assert (!true_regnum (operands[1]));
765790286Sobrien      operands[4] = operands[1];
765890286Sobrien    }
765990286Sobrien})
766090286Sobrien;; %%% Split me.
766118334Speter(define_insn "divmodhi4"
766218334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
766318334Speter	(div:HI (match_operand:HI 1 "register_operand" "0")
766450650Sobrien		(match_operand:HI 2 "nonimmediate_operand" "rm")))
766518334Speter   (set (match_operand:HI 3 "register_operand" "=&d")
766690286Sobrien	(mod:HI (match_dup 1) (match_dup 2)))
7667169699Skan   (clobber (reg:CC FLAGS_REG))]
766890286Sobrien  "TARGET_HIMODE_MATH"
766990286Sobrien  "cwtd\;idiv{w}\t%2"
767090286Sobrien  [(set_attr "type" "multi")
767190286Sobrien   (set_attr "length_immediate" "0")
767290286Sobrien   (set_attr "mode" "SI")])
767318334Speter
767490286Sobrien(define_insn "udivmoddi4"
767590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
767690286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "0")
767790286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "rm")))
767890286Sobrien   (set (match_operand:DI 3 "register_operand" "=&d")
767990286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
7680169699Skan   (clobber (reg:CC FLAGS_REG))]
768190286Sobrien  "TARGET_64BIT"
768290286Sobrien  "xor{q}\t%3, %3\;div{q}\t%2"
768390286Sobrien  [(set_attr "type" "multi")
768490286Sobrien   (set_attr "length_immediate" "0")
768590286Sobrien   (set_attr "mode" "DI")])
768690286Sobrien
768790286Sobrien(define_insn "*udivmoddi4_noext"
768890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
768990286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "0")
769090286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "rm")))
769190286Sobrien   (set (match_operand:DI 3 "register_operand" "=d")
769290286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
769390286Sobrien   (use (match_dup 3))
7694169699Skan   (clobber (reg:CC FLAGS_REG))]
769590286Sobrien  "TARGET_64BIT"
769690286Sobrien  "div{q}\t%2"
769790286Sobrien  [(set_attr "type" "idiv")
769890286Sobrien   (set_attr "mode" "DI")])
769990286Sobrien
770090286Sobrien(define_split
770190286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
770290286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "")
770390286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "")))
770490286Sobrien   (set (match_operand:DI 3 "register_operand" "")
770590286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
7706169699Skan   (clobber (reg:CC FLAGS_REG))]
770790286Sobrien  "TARGET_64BIT && reload_completed"
770890286Sobrien  [(set (match_dup 3) (const_int 0))
770990286Sobrien   (parallel [(set (match_dup 0)
771090286Sobrien		   (udiv:DI (match_dup 1) (match_dup 2)))
771190286Sobrien	      (set (match_dup 3)
771290286Sobrien		   (umod:DI (match_dup 1) (match_dup 2)))
771390286Sobrien	      (use (match_dup 3))
7714169699Skan	      (clobber (reg:CC FLAGS_REG))])]
771590286Sobrien  "")
771690286Sobrien
771718334Speter(define_insn "udivmodsi4"
771818334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
771918334Speter	(udiv:SI (match_operand:SI 1 "register_operand" "0")
772050650Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
772118334Speter   (set (match_operand:SI 3 "register_operand" "=&d")
772290286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
7723169699Skan   (clobber (reg:CC FLAGS_REG))]
772418334Speter  ""
772590286Sobrien  "xor{l}\t%3, %3\;div{l}\t%2"
772690286Sobrien  [(set_attr "type" "multi")
772790286Sobrien   (set_attr "length_immediate" "0")
772890286Sobrien   (set_attr "mode" "SI")])
772918334Speter
773090286Sobrien(define_insn "*udivmodsi4_noext"
773190286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a")
773290286Sobrien	(udiv:SI (match_operand:SI 1 "register_operand" "0")
773390286Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
773490286Sobrien   (set (match_operand:SI 3 "register_operand" "=d")
773590286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
773690286Sobrien   (use (match_dup 3))
7737169699Skan   (clobber (reg:CC FLAGS_REG))]
773890286Sobrien  ""
773990286Sobrien  "div{l}\t%2"
774090286Sobrien  [(set_attr "type" "idiv")
774190286Sobrien   (set_attr "mode" "SI")])
774290286Sobrien
774390286Sobrien(define_split
774490286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
774590286Sobrien	(udiv:SI (match_operand:SI 1 "register_operand" "")
774690286Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "")))
774790286Sobrien   (set (match_operand:SI 3 "register_operand" "")
774890286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
7749169699Skan   (clobber (reg:CC FLAGS_REG))]
775090286Sobrien  "reload_completed"
775190286Sobrien  [(set (match_dup 3) (const_int 0))
775290286Sobrien   (parallel [(set (match_dup 0)
775390286Sobrien		   (udiv:SI (match_dup 1) (match_dup 2)))
775490286Sobrien	      (set (match_dup 3)
775590286Sobrien		   (umod:SI (match_dup 1) (match_dup 2)))
775690286Sobrien	      (use (match_dup 3))
7757169699Skan	      (clobber (reg:CC FLAGS_REG))])]
775890286Sobrien  "")
775990286Sobrien
776090286Sobrien(define_expand "udivmodhi4"
776190286Sobrien  [(set (match_dup 4) (const_int 0))
776290286Sobrien   (parallel [(set (match_operand:HI 0 "register_operand" "")
776390286Sobrien		   (udiv:HI (match_operand:HI 1 "register_operand" "")
776490286Sobrien		 	    (match_operand:HI 2 "nonimmediate_operand" "")))
776590286Sobrien	      (set (match_operand:HI 3 "register_operand" "")
776690286Sobrien	   	   (umod:HI (match_dup 1) (match_dup 2)))
776790286Sobrien	      (use (match_dup 4))
7768169699Skan	      (clobber (reg:CC FLAGS_REG))])]
776990286Sobrien  "TARGET_HIMODE_MATH"
777090286Sobrien  "operands[4] = gen_reg_rtx (HImode);")
777190286Sobrien
777290286Sobrien(define_insn "*udivmodhi_noext"
777318334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
777418334Speter	(udiv:HI (match_operand:HI 1 "register_operand" "0")
777550650Sobrien		 (match_operand:HI 2 "nonimmediate_operand" "rm")))
777690286Sobrien   (set (match_operand:HI 3 "register_operand" "=d")
777790286Sobrien	(umod:HI (match_dup 1) (match_dup 2)))
777890286Sobrien   (use (match_operand:HI 4 "register_operand" "3"))
7779169699Skan   (clobber (reg:CC FLAGS_REG))]
778018334Speter  ""
778190286Sobrien  "div{w}\t%2"
778290286Sobrien  [(set_attr "type" "idiv")
7783169699Skan   (set_attr "mode" "HI")])
778418334Speter
7785169699Skan;; We cannot use div/idiv for double division, because it causes
778690286Sobrien;; "division by zero" on the overflow and that's not what we expect
778790286Sobrien;; from truncate.  Because true (non truncating) double division is
778890286Sobrien;; never generated, we can't create this insn anyway.
778990286Sobrien;
779090286Sobrien;(define_insn ""
779190286Sobrien;  [(set (match_operand:SI 0 "register_operand" "=a")
779290286Sobrien;	(truncate:SI
779390286Sobrien;	  (udiv:DI (match_operand:DI 1 "register_operand" "A")
779490286Sobrien;		   (zero_extend:DI
779590286Sobrien;		     (match_operand:SI 2 "nonimmediate_operand" "rm")))))
779690286Sobrien;   (set (match_operand:SI 3 "register_operand" "=d")
779790286Sobrien;	(truncate:SI
779890286Sobrien;	  (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))
7799169699Skan;   (clobber (reg:CC FLAGS_REG))]
780090286Sobrien;  ""
780190286Sobrien;  "div{l}\t{%2, %0|%0, %2}"
7802169699Skan;  [(set_attr "type" "idiv")])
780390286Sobrien
780490286Sobrien;;- Logical AND instructions
780518334Speter
780690286Sobrien;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al.
780790286Sobrien;; Note that this excludes ah.
780890286Sobrien
780990286Sobrien(define_insn "*testdi_1_rex64"
7810169699Skan  [(set (reg FLAGS_REG)
781190286Sobrien	(compare
7812132727Skan	  (and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm")
7813132727Skan		  (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re"))
781490286Sobrien	  (const_int 0)))]
7815132727Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
7816132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
781790286Sobrien  "@
7818169699Skan   test{l}\t{%k1, %k0|%k0, %k1}
7819169699Skan   test{l}\t{%k1, %k0|%k0, %k1}
7820169699Skan   test{q}\t{%1, %0|%0, %1}
7821169699Skan   test{q}\t{%1, %0|%0, %1}
782290286Sobrien   test{q}\t{%1, %0|%0, %1}"
782390286Sobrien  [(set_attr "type" "test")
782490286Sobrien   (set_attr "modrm" "0,1,0,1,1")
782590286Sobrien   (set_attr "mode" "SI,SI,DI,DI,DI")
782690286Sobrien   (set_attr "pent_pair" "uv,np,uv,np,uv")])
782790286Sobrien
782890286Sobrien(define_insn "testsi_1"
7829169699Skan  [(set (reg FLAGS_REG)
783090286Sobrien	(compare
7831132727Skan	  (and:SI (match_operand:SI 0 "nonimmediate_operand" "%!*a,r,rm")
7832132727Skan		  (match_operand:SI 1 "general_operand" "in,in,rin"))
783390286Sobrien	  (const_int 0)))]
7834132727Skan  "ix86_match_ccmode (insn, CCNOmode)
7835132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
783690286Sobrien  "test{l}\t{%1, %0|%0, %1}"
783790286Sobrien  [(set_attr "type" "test")
783890286Sobrien   (set_attr "modrm" "0,1,1")
783990286Sobrien   (set_attr "mode" "SI")
784090286Sobrien   (set_attr "pent_pair" "uv,np,uv")])
784190286Sobrien
784290286Sobrien(define_expand "testsi_ccno_1"
7843169699Skan  [(set (reg:CCNO FLAGS_REG)
784490286Sobrien	(compare:CCNO
784590286Sobrien	  (and:SI (match_operand:SI 0 "nonimmediate_operand" "")
784690286Sobrien		  (match_operand:SI 1 "nonmemory_operand" ""))
784790286Sobrien	  (const_int 0)))]
784818334Speter  ""
784990286Sobrien  "")
785018334Speter
785190286Sobrien(define_insn "*testhi_1"
7852169699Skan  [(set (reg FLAGS_REG)
7853132727Skan        (compare (and:HI (match_operand:HI 0 "nonimmediate_operand" "%!*a,r,rm")
7854132727Skan			 (match_operand:HI 1 "general_operand" "n,n,rn"))
785590286Sobrien		 (const_int 0)))]
7856132727Skan  "ix86_match_ccmode (insn, CCNOmode)
7857132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
785890286Sobrien  "test{w}\t{%1, %0|%0, %1}"
785990286Sobrien  [(set_attr "type" "test")
786090286Sobrien   (set_attr "modrm" "0,1,1")
786190286Sobrien   (set_attr "mode" "HI")
786290286Sobrien   (set_attr "pent_pair" "uv,np,uv")])
786318334Speter
786490286Sobrien(define_expand "testqi_ccz_1"
7865169699Skan  [(set (reg:CCZ FLAGS_REG)
786690286Sobrien        (compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand" "")
786790286Sobrien			     (match_operand:QI 1 "nonmemory_operand" ""))
786890286Sobrien		 (const_int 0)))]
786990286Sobrien  ""
787090286Sobrien  "")
787118334Speter
7872146906Skan(define_insn "*testqi_1_maybe_si"
7873169699Skan  [(set (reg FLAGS_REG)
7874146906Skan        (compare
7875146906Skan	  (and:QI
7876146906Skan	    (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm,r")
7877146906Skan	    (match_operand:QI 1 "general_operand" "n,n,qn,n"))
7878146906Skan	  (const_int 0)))]
7879169699Skan   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
7880169699Skan    && ix86_match_ccmode (insn,
7881169699Skan 			 GET_CODE (operands[1]) == CONST_INT
7882169699Skan 			 && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)"
788318334Speter{
788490286Sobrien  if (which_alternative == 3)
788518334Speter    {
7886146906Skan      if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
788790286Sobrien	operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
788890286Sobrien      return "test{l}\t{%1, %k0|%k0, %1}";
788950650Sobrien    }
789090286Sobrien  return "test{b}\t{%1, %0|%0, %1}";
789190286Sobrien}
789290286Sobrien  [(set_attr "type" "test")
789390286Sobrien   (set_attr "modrm" "0,1,1,1")
789490286Sobrien   (set_attr "mode" "QI,QI,QI,SI")
789590286Sobrien   (set_attr "pent_pair" "uv,np,uv,np")])
789618334Speter
7897146906Skan(define_insn "*testqi_1"
7898169699Skan  [(set (reg FLAGS_REG)
7899146906Skan        (compare
7900146906Skan	  (and:QI
7901146906Skan	    (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm")
7902146906Skan	    (match_operand:QI 1 "general_operand" "n,n,qn"))
7903146906Skan	  (const_int 0)))]
7904146906Skan  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
7905146906Skan   && ix86_match_ccmode (insn, CCNOmode)"
7906146906Skan  "test{b}\t{%1, %0|%0, %1}"
7907146906Skan  [(set_attr "type" "test")
7908146906Skan   (set_attr "modrm" "0,1,1")
7909146906Skan   (set_attr "mode" "QI")
7910146906Skan   (set_attr "pent_pair" "uv,np,uv")])
7911146906Skan
791290286Sobrien(define_expand "testqi_ext_ccno_0"
7913169699Skan  [(set (reg:CCNO FLAGS_REG)
791490286Sobrien	(compare:CCNO
791590286Sobrien	  (and:SI
791690286Sobrien	    (zero_extract:SI
791790286Sobrien	      (match_operand 0 "ext_register_operand" "")
791890286Sobrien	      (const_int 8)
791990286Sobrien	      (const_int 8))
792090286Sobrien	    (match_operand 1 "const_int_operand" ""))
792190286Sobrien	  (const_int 0)))]
792290286Sobrien  ""
792390286Sobrien  "")
792418334Speter
792590286Sobrien(define_insn "*testqi_ext_0"
7926169699Skan  [(set (reg FLAGS_REG)
792790286Sobrien	(compare
792890286Sobrien	  (and:SI
792990286Sobrien	    (zero_extract:SI
793090286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
793190286Sobrien	      (const_int 8)
793290286Sobrien	      (const_int 8))
793390286Sobrien	    (match_operand 1 "const_int_operand" "n"))
793490286Sobrien	  (const_int 0)))]
7935117404Skan  "ix86_match_ccmode (insn, CCNOmode)"
793690286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
793790286Sobrien  [(set_attr "type" "test")
793890286Sobrien   (set_attr "mode" "QI")
793990286Sobrien   (set_attr "length_immediate" "1")
794090286Sobrien   (set_attr "pent_pair" "np")])
794150650Sobrien
794290286Sobrien(define_insn "*testqi_ext_1"
7943169699Skan  [(set (reg FLAGS_REG)
794490286Sobrien	(compare
794590286Sobrien	  (and:SI
794690286Sobrien	    (zero_extract:SI
794790286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
794890286Sobrien	      (const_int 8)
794990286Sobrien	      (const_int 8))
795090286Sobrien	    (zero_extend:SI
7951132727Skan	      (match_operand:QI 1 "general_operand" "Qm")))
795290286Sobrien	  (const_int 0)))]
7953132727Skan  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
7954132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
795590286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
795690286Sobrien  [(set_attr "type" "test")
795790286Sobrien   (set_attr "mode" "QI")])
795818334Speter
795990286Sobrien(define_insn "*testqi_ext_1_rex64"
7960169699Skan  [(set (reg FLAGS_REG)
796190286Sobrien	(compare
796290286Sobrien	  (and:SI
796390286Sobrien	    (zero_extract:SI
796490286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
796590286Sobrien	      (const_int 8)
796690286Sobrien	      (const_int 8))
796790286Sobrien	    (zero_extend:SI
796890286Sobrien	      (match_operand:QI 1 "register_operand" "Q")))
796990286Sobrien	  (const_int 0)))]
797090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
797190286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
797290286Sobrien  [(set_attr "type" "test")
797390286Sobrien   (set_attr "mode" "QI")])
797418334Speter
797590286Sobrien(define_insn "*testqi_ext_2"
7976169699Skan  [(set (reg FLAGS_REG)
797790286Sobrien	(compare
797890286Sobrien	  (and:SI
797990286Sobrien	    (zero_extract:SI
798090286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
798190286Sobrien	      (const_int 8)
798290286Sobrien	      (const_int 8))
798390286Sobrien	    (zero_extract:SI
798490286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
798590286Sobrien	      (const_int 8)
798690286Sobrien	      (const_int 8)))
798790286Sobrien	  (const_int 0)))]
798890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
798990286Sobrien  "test{b}\t{%h1, %h0|%h0, %h1}"
799090286Sobrien  [(set_attr "type" "test")
799190286Sobrien   (set_attr "mode" "QI")])
799250650Sobrien
799390286Sobrien;; Combine likes to form bit extractions for some tests.  Humor it.
799490286Sobrien(define_insn "*testqi_ext_3"
7995169699Skan  [(set (reg FLAGS_REG)
799690286Sobrien        (compare (zero_extract:SI
799790286Sobrien		   (match_operand 0 "nonimmediate_operand" "rm")
799890286Sobrien		   (match_operand:SI 1 "const_int_operand" "")
799990286Sobrien		   (match_operand:SI 2 "const_int_operand" ""))
800090286Sobrien		 (const_int 0)))]
800190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
8002169699Skan   && INTVAL (operands[1]) > 0
8003169699Skan   && INTVAL (operands[2]) >= 0
8004169699Skan   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
800590286Sobrien   && (GET_MODE (operands[0]) == SImode
800690286Sobrien       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
800790286Sobrien       || GET_MODE (operands[0]) == HImode
800890286Sobrien       || GET_MODE (operands[0]) == QImode)"
800990286Sobrien  "#")
801050650Sobrien
801190286Sobrien(define_insn "*testqi_ext_3_rex64"
8012169699Skan  [(set (reg FLAGS_REG)
801390286Sobrien        (compare (zero_extract:DI
801490286Sobrien		   (match_operand 0 "nonimmediate_operand" "rm")
801590286Sobrien		   (match_operand:DI 1 "const_int_operand" "")
801690286Sobrien		   (match_operand:DI 2 "const_int_operand" ""))
801790286Sobrien		 (const_int 0)))]
801890286Sobrien  "TARGET_64BIT
801990286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
8020169699Skan   && INTVAL (operands[1]) > 0
8021169699Skan   && INTVAL (operands[2]) >= 0
802290286Sobrien   /* Ensure that resulting mask is zero or sign extended operand.  */
802390286Sobrien   && (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
802490286Sobrien       || (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
802590286Sobrien	   && INTVAL (operands[1]) > 32))
802690286Sobrien   && (GET_MODE (operands[0]) == SImode
802790286Sobrien       || GET_MODE (operands[0]) == DImode
802890286Sobrien       || GET_MODE (operands[0]) == HImode
802990286Sobrien       || GET_MODE (operands[0]) == QImode)"
803090286Sobrien  "#")
803150650Sobrien
803290286Sobrien(define_split
8033146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
8034146906Skan        (match_operator 1 "compare_operator"
8035146906Skan	  [(zero_extract
8036146906Skan	     (match_operand 2 "nonimmediate_operand" "")
8037146906Skan	     (match_operand 3 "const_int_operand" "")
8038146906Skan	     (match_operand 4 "const_int_operand" ""))
8039146906Skan	   (const_int 0)]))]
804090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
8041146906Skan  [(set (match_dup 0) (match_op_dup 1 [(match_dup 2) (const_int 0)]))]
804290286Sobrien{
8043146906Skan  rtx val = operands[2];
8044146906Skan  HOST_WIDE_INT len = INTVAL (operands[3]);
8045146906Skan  HOST_WIDE_INT pos = INTVAL (operands[4]);
804690286Sobrien  HOST_WIDE_INT mask;
804790286Sobrien  enum machine_mode mode, submode;
804818334Speter
8049146906Skan  mode = GET_MODE (val);
8050146906Skan  if (GET_CODE (val) == MEM)
805190286Sobrien    {
805290286Sobrien      /* ??? Combine likes to put non-volatile mem extractions in QImode
805390286Sobrien	 no matter the size of the test.  So find a mode that works.  */
8054146906Skan      if (! MEM_VOLATILE_P (val))
805518334Speter	{
805690286Sobrien	  mode = smallest_mode_for_size (pos + len, MODE_INT);
8057146906Skan	  val = adjust_address (val, mode, 0);
805890286Sobrien	}
805990286Sobrien    }
8060146906Skan  else if (GET_CODE (val) == SUBREG
8061146906Skan	   && (submode = GET_MODE (SUBREG_REG (val)),
806290286Sobrien	       GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (submode))
806390286Sobrien	   && pos + len <= GET_MODE_BITSIZE (submode))
806490286Sobrien    {
806590286Sobrien      /* Narrow a paradoxical subreg to prevent partial register stalls.  */
806690286Sobrien      mode = submode;
8067146906Skan      val = SUBREG_REG (val);
806890286Sobrien    }
806990286Sobrien  else if (mode == HImode && pos + len <= 8)
807090286Sobrien    {
807190286Sobrien      /* Small HImode tests can be converted to QImode.  */
807290286Sobrien      mode = QImode;
8073146906Skan      val = gen_lowpart (QImode, val);
807490286Sobrien    }
807518334Speter
8076169699Skan  if (len == HOST_BITS_PER_WIDE_INT)
8077169699Skan    mask = -1;
8078169699Skan  else
8079169699Skan    mask = ((HOST_WIDE_INT)1 << len) - 1;
8080169699Skan  mask <<= pos;
808118334Speter
8082146906Skan  operands[2] = gen_rtx_AND (mode, val, gen_int_mode (mask, mode));
808390286Sobrien})
808450650Sobrien
8085117404Skan;; Convert HImode/SImode test instructions with immediate to QImode ones.
8086117404Skan;; i386 does not allow to encode test with 8bit sign extended immediate, so
8087117404Skan;; this is relatively important trick.
8088132727Skan;; Do the conversion only post-reload to avoid limiting of the register class
8089117404Skan;; to QI regs.
8090117404Skan(define_split
8091146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
8092146906Skan	(match_operator 1 "compare_operator"
8093146906Skan	  [(and (match_operand 2 "register_operand" "")
8094146906Skan	        (match_operand 3 "const_int_operand" ""))
8095146906Skan	   (const_int 0)]))]
8096117404Skan   "reload_completed
8097146906Skan    && QI_REG_P (operands[2])
8098146906Skan    && GET_MODE (operands[2]) != QImode
8099117404Skan    && ((ix86_match_ccmode (insn, CCZmode)
8100146906Skan    	 && !(INTVAL (operands[3]) & ~(255 << 8)))
8101117404Skan	|| (ix86_match_ccmode (insn, CCNOmode)
8102146906Skan	    && !(INTVAL (operands[3]) & ~(127 << 8))))"
8103146906Skan  [(set (match_dup 0)
8104146906Skan	(match_op_dup 1
8105146906Skan	  [(and:SI (zero_extract:SI (match_dup 2) (const_int 8) (const_int 8))
8106146906Skan		   (match_dup 3))
8107146906Skan	   (const_int 0)]))]
8108146906Skan  "operands[2] = gen_lowpart (SImode, operands[2]);
8109146906Skan   operands[3] = gen_int_mode (INTVAL (operands[3]) >> 8, SImode);")
8110117404Skan
8111117404Skan(define_split
8112146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
8113146906Skan	(match_operator 1 "compare_operator"
8114146906Skan	  [(and (match_operand 2 "nonimmediate_operand" "")
8115146906Skan	        (match_operand 3 "const_int_operand" ""))
8116146906Skan	   (const_int 0)]))]
8117117404Skan   "reload_completed
8118146906Skan    && GET_MODE (operands[2]) != QImode
8119146906Skan    && (!REG_P (operands[2]) || ANY_QI_REG_P (operands[2]))
8120117404Skan    && ((ix86_match_ccmode (insn, CCZmode)
8121146906Skan	 && !(INTVAL (operands[3]) & ~255))
8122117404Skan	|| (ix86_match_ccmode (insn, CCNOmode)
8123146906Skan	    && !(INTVAL (operands[3]) & ~127)))"
8124146906Skan  [(set (match_dup 0)
8125146906Skan	(match_op_dup 1 [(and:QI (match_dup 2) (match_dup 3))
8126146906Skan			 (const_int 0)]))]
8127146906Skan  "operands[2] = gen_lowpart (QImode, operands[2]);
8128146906Skan   operands[3] = gen_lowpart (QImode, operands[3]);")
8129117404Skan
8130117404Skan
813190286Sobrien;; %%% This used to optimize known byte-wide and operations to memory,
813290286Sobrien;; and sometimes to QImode registers.  If this is considered useful,
813390286Sobrien;; it should be done with splitters.
813418334Speter
813590286Sobrien(define_expand "anddi3"
813690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
813790286Sobrien	(and:DI (match_operand:DI 1 "nonimmediate_operand" "")
813890286Sobrien		(match_operand:DI 2 "x86_64_szext_general_operand" "")))
8139169699Skan   (clobber (reg:CC FLAGS_REG))]
814090286Sobrien  "TARGET_64BIT"
814190286Sobrien  "ix86_expand_binary_operator (AND, DImode, operands); DONE;")
814250650Sobrien
814390286Sobrien(define_insn "*anddi_1_rex64"
814490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
814590286Sobrien	(and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm")
814690286Sobrien		(match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L")))
8147169699Skan   (clobber (reg:CC FLAGS_REG))]
814890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)"
814990286Sobrien{
815090286Sobrien  switch (get_attr_type (insn))
815190286Sobrien    {
815290286Sobrien    case TYPE_IMOVX:
815390286Sobrien      {
815490286Sobrien	enum machine_mode mode;
815550650Sobrien
8156169699Skan	gcc_assert (GET_CODE (operands[2]) == CONST_INT);
815790286Sobrien        if (INTVAL (operands[2]) == 0xff)
815890286Sobrien	  mode = QImode;
815990286Sobrien	else
8160169699Skan	  {
8161169699Skan	    gcc_assert (INTVAL (operands[2]) == 0xffff);
8162169699Skan	    mode = HImode;
8163169699Skan	  }
8164259563Spfg
816590286Sobrien	operands[1] = gen_lowpart (mode, operands[1]);
816690286Sobrien	if (mode == QImode)
816790286Sobrien	  return "movz{bq|x}\t{%1,%0|%0, %1}";
816890286Sobrien	else
816990286Sobrien	  return "movz{wq|x}\t{%1,%0|%0, %1}";
817090286Sobrien      }
817150650Sobrien
817250650Sobrien    default:
8173169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
817490286Sobrien      if (get_attr_mode (insn) == MODE_SI)
817590286Sobrien	return "and{l}\t{%k2, %k0|%k0, %k2}";
817690286Sobrien      else
817790286Sobrien	return "and{q}\t{%2, %0|%0, %2}";
817818334Speter    }
817990286Sobrien}
818090286Sobrien  [(set_attr "type" "alu,alu,alu,imovx")
818190286Sobrien   (set_attr "length_immediate" "*,*,*,0")
818290286Sobrien   (set_attr "mode" "SI,DI,DI,DI")])
818318334Speter
818490286Sobrien(define_insn "*anddi_2"
8185169699Skan  [(set (reg FLAGS_REG)
818690286Sobrien	(compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
818790286Sobrien			 (match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re"))
818890286Sobrien		 (const_int 0)))
818990286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm")
819090286Sobrien	(and:DI (match_dup 1) (match_dup 2)))]
819190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
819290286Sobrien   && ix86_binary_operator_ok (AND, DImode, operands)"
819390286Sobrien  "@
8194169699Skan   and{l}\t{%k2, %k0|%k0, %k2}
8195169699Skan   and{q}\t{%2, %0|%0, %2}
819690286Sobrien   and{q}\t{%2, %0|%0, %2}"
819790286Sobrien  [(set_attr "type" "alu")
819890286Sobrien   (set_attr "mode" "SI,DI,DI")])
819918334Speter
820090286Sobrien(define_expand "andsi3"
820190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
820290286Sobrien	(and:SI (match_operand:SI 1 "nonimmediate_operand" "")
820390286Sobrien		(match_operand:SI 2 "general_operand" "")))
8204169699Skan   (clobber (reg:CC FLAGS_REG))]
820518334Speter  ""
820690286Sobrien  "ix86_expand_binary_operator (AND, SImode, operands); DONE;")
820790286Sobrien
820890286Sobrien(define_insn "*andsi_1"
820990286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r")
821090286Sobrien	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm")
821190286Sobrien		(match_operand:SI 2 "general_operand" "ri,rm,L")))
8212169699Skan   (clobber (reg:CC FLAGS_REG))]
821390286Sobrien  "ix86_binary_operator_ok (AND, SImode, operands)"
821418334Speter{
821590286Sobrien  switch (get_attr_type (insn))
821618334Speter    {
821790286Sobrien    case TYPE_IMOVX:
821890286Sobrien      {
821990286Sobrien	enum machine_mode mode;
822018334Speter
8221169699Skan	gcc_assert (GET_CODE (operands[2]) == CONST_INT);
822290286Sobrien        if (INTVAL (operands[2]) == 0xff)
822390286Sobrien	  mode = QImode;
822490286Sobrien	else
8225169699Skan	  {
8226169699Skan	    gcc_assert (INTVAL (operands[2]) == 0xffff);
8227169699Skan	    mode = HImode;
8228169699Skan	  }
8229259563Spfg
823090286Sobrien	operands[1] = gen_lowpart (mode, operands[1]);
823190286Sobrien	if (mode == QImode)
823290286Sobrien	  return "movz{bl|x}\t{%1,%0|%0, %1}";
823390286Sobrien	else
823490286Sobrien	  return "movz{wl|x}\t{%1,%0|%0, %1}";
823590286Sobrien      }
823618334Speter
823790286Sobrien    default:
8238169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
823990286Sobrien      return "and{l}\t{%2, %0|%0, %2}";
824090286Sobrien    }
824190286Sobrien}
824290286Sobrien  [(set_attr "type" "alu,alu,imovx")
824390286Sobrien   (set_attr "length_immediate" "*,*,0")
824490286Sobrien   (set_attr "mode" "SI")])
824518334Speter
824690286Sobrien(define_split
824790286Sobrien  [(set (match_operand 0 "register_operand" "")
824890286Sobrien	(and (match_dup 0)
824990286Sobrien	     (const_int -65536)))
8250169699Skan   (clobber (reg:CC FLAGS_REG))]
8251117404Skan  "optimize_size || (TARGET_FAST_PREFIX && !TARGET_PARTIAL_REG_STALL)"
825290286Sobrien  [(set (strict_low_part (match_dup 1)) (const_int 0))]
825390286Sobrien  "operands[1] = gen_lowpart (HImode, operands[0]);")
825418334Speter
825590286Sobrien(define_split
825690286Sobrien  [(set (match_operand 0 "ext_register_operand" "")
825790286Sobrien	(and (match_dup 0)
825890286Sobrien	     (const_int -256)))
8259169699Skan   (clobber (reg:CC FLAGS_REG))]
826090286Sobrien  "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
826190286Sobrien  [(set (strict_low_part (match_dup 1)) (const_int 0))]
826290286Sobrien  "operands[1] = gen_lowpart (QImode, operands[0]);")
826318334Speter
826490286Sobrien(define_split
826590286Sobrien  [(set (match_operand 0 "ext_register_operand" "")
826690286Sobrien	(and (match_dup 0)
826790286Sobrien	     (const_int -65281)))
8268169699Skan   (clobber (reg:CC FLAGS_REG))]
826990286Sobrien  "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
827090286Sobrien  [(parallel [(set (zero_extract:SI (match_dup 0)
827190286Sobrien				    (const_int 8)
827290286Sobrien				    (const_int 8))
8273259563Spfg		   (xor:SI
827490286Sobrien		     (zero_extract:SI (match_dup 0)
827590286Sobrien				      (const_int 8)
827690286Sobrien				      (const_int 8))
827790286Sobrien		     (zero_extract:SI (match_dup 0)
827890286Sobrien				      (const_int 8)
827990286Sobrien				      (const_int 8))))
8280169699Skan	      (clobber (reg:CC FLAGS_REG))])]
828190286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);")
828250650Sobrien
828390286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
828490286Sobrien(define_insn "*andsi_1_zext"
828590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
828690286Sobrien	(zero_extend:DI
828790286Sobrien	  (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
828890286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8289169699Skan   (clobber (reg:CC FLAGS_REG))]
829090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
829190286Sobrien  "and{l}\t{%2, %k0|%k0, %2}"
829290286Sobrien  [(set_attr "type" "alu")
829390286Sobrien   (set_attr "mode" "SI")])
829418334Speter
829590286Sobrien(define_insn "*andsi_2"
8296169699Skan  [(set (reg FLAGS_REG)
829790286Sobrien	(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
829890286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
829990286Sobrien		 (const_int 0)))
830090286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
830190286Sobrien	(and:SI (match_dup 1) (match_dup 2)))]
830290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
830390286Sobrien   && ix86_binary_operator_ok (AND, SImode, operands)"
830490286Sobrien  "and{l}\t{%2, %0|%0, %2}"
830590286Sobrien  [(set_attr "type" "alu")
830690286Sobrien   (set_attr "mode" "SI")])
830790286Sobrien
830890286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
830990286Sobrien(define_insn "*andsi_2_zext"
8310169699Skan  [(set (reg FLAGS_REG)
831190286Sobrien	(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
831290286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
831390286Sobrien		 (const_int 0)))
831490286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
831590286Sobrien	(zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
831690286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
831790286Sobrien   && ix86_binary_operator_ok (AND, SImode, operands)"
831890286Sobrien  "and{l}\t{%2, %k0|%k0, %2}"
831990286Sobrien  [(set_attr "type" "alu")
832090286Sobrien   (set_attr "mode" "SI")])
832190286Sobrien
832290286Sobrien(define_expand "andhi3"
832390286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
832490286Sobrien	(and:HI (match_operand:HI 1 "nonimmediate_operand" "")
832590286Sobrien		(match_operand:HI 2 "general_operand" "")))
8326169699Skan   (clobber (reg:CC FLAGS_REG))]
832790286Sobrien  "TARGET_HIMODE_MATH"
832890286Sobrien  "ix86_expand_binary_operator (AND, HImode, operands); DONE;")
832990286Sobrien
833090286Sobrien(define_insn "*andhi_1"
833190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
833290286Sobrien	(and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,qm")
833390286Sobrien		(match_operand:HI 2 "general_operand" "ri,rm,L")))
8334169699Skan   (clobber (reg:CC FLAGS_REG))]
833590286Sobrien  "ix86_binary_operator_ok (AND, HImode, operands)"
833690286Sobrien{
833790286Sobrien  switch (get_attr_type (insn))
833850650Sobrien    {
833990286Sobrien    case TYPE_IMOVX:
8340169699Skan      gcc_assert (GET_CODE (operands[2]) == CONST_INT);
8341169699Skan      gcc_assert (INTVAL (operands[2]) == 0xff);
8342169699Skan      return "movz{bl|x}\t{%b1, %k0|%k0, %b1}";
834390286Sobrien
834490286Sobrien    default:
8345169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
834690286Sobrien
834790286Sobrien      return "and{w}\t{%2, %0|%0, %2}";
834850650Sobrien    }
834990286Sobrien}
835090286Sobrien  [(set_attr "type" "alu,alu,imovx")
835190286Sobrien   (set_attr "length_immediate" "*,*,0")
835290286Sobrien   (set_attr "mode" "HI,HI,SI")])
835350650Sobrien
835490286Sobrien(define_insn "*andhi_2"
8355169699Skan  [(set (reg FLAGS_REG)
835690286Sobrien	(compare (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
835790286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
835890286Sobrien		 (const_int 0)))
835990286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
836090286Sobrien	(and:HI (match_dup 1) (match_dup 2)))]
836190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
836290286Sobrien   && ix86_binary_operator_ok (AND, HImode, operands)"
836390286Sobrien  "and{w}\t{%2, %0|%0, %2}"
836490286Sobrien  [(set_attr "type" "alu")
836590286Sobrien   (set_attr "mode" "HI")])
836690286Sobrien
836790286Sobrien(define_expand "andqi3"
836890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
836990286Sobrien	(and:QI (match_operand:QI 1 "nonimmediate_operand" "")
837090286Sobrien		(match_operand:QI 2 "general_operand" "")))
8371169699Skan   (clobber (reg:CC FLAGS_REG))]
837290286Sobrien  "TARGET_QIMODE_MATH"
837390286Sobrien  "ix86_expand_binary_operator (AND, QImode, operands); DONE;")
837490286Sobrien
837590286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
837690286Sobrien(define_insn "*andqi_1"
837790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
837890286Sobrien	(and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
837990286Sobrien		(match_operand:QI 2 "general_operand" "qi,qmi,ri")))
8380169699Skan   (clobber (reg:CC FLAGS_REG))]
838190286Sobrien  "ix86_binary_operator_ok (AND, QImode, operands)"
838290286Sobrien  "@
838390286Sobrien   and{b}\t{%2, %0|%0, %2}
838490286Sobrien   and{b}\t{%2, %0|%0, %2}
838590286Sobrien   and{l}\t{%k2, %k0|%k0, %k2}"
838690286Sobrien  [(set_attr "type" "alu")
838790286Sobrien   (set_attr "mode" "QI,QI,SI")])
838890286Sobrien
838990286Sobrien(define_insn "*andqi_1_slp"
839090286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
839190286Sobrien	(and:QI (match_dup 0)
839290286Sobrien		(match_operand:QI 1 "general_operand" "qi,qmi")))
8393169699Skan   (clobber (reg:CC FLAGS_REG))]
8394117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8395117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
839690286Sobrien  "and{b}\t{%1, %0|%0, %1}"
839790286Sobrien  [(set_attr "type" "alu1")
839890286Sobrien   (set_attr "mode" "QI")])
839990286Sobrien
8400146906Skan(define_insn "*andqi_2_maybe_si"
8401169699Skan  [(set (reg FLAGS_REG)
840290286Sobrien	(compare (and:QI
8403146906Skan		      (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
8404146906Skan		      (match_operand:QI 2 "general_operand" "qim,qi,i"))
840590286Sobrien		 (const_int 0)))
840690286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,*r")
840790286Sobrien	(and:QI (match_dup 1) (match_dup 2)))]
8408146906Skan  "ix86_binary_operator_ok (AND, QImode, operands)
8409146906Skan   && ix86_match_ccmode (insn,
8410146906Skan			 GET_CODE (operands[2]) == CONST_INT
8411146906Skan			 && INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode)"
841290286Sobrien{
841390286Sobrien  if (which_alternative == 2)
841450650Sobrien    {
8415146906Skan      if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
841690286Sobrien        operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
841790286Sobrien      return "and{l}\t{%2, %k0|%k0, %2}";
841850650Sobrien    }
841990286Sobrien  return "and{b}\t{%2, %0|%0, %2}";
842090286Sobrien}
842190286Sobrien  [(set_attr "type" "alu")
842290286Sobrien   (set_attr "mode" "QI,QI,SI")])
842350650Sobrien
8424146906Skan(define_insn "*andqi_2"
8425169699Skan  [(set (reg FLAGS_REG)
8426146906Skan	(compare (and:QI
8427146906Skan		   (match_operand:QI 1 "nonimmediate_operand" "%0,0")
8428146906Skan		   (match_operand:QI 2 "general_operand" "qim,qi"))
8429146906Skan		 (const_int 0)))
8430146906Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
8431146906Skan	(and:QI (match_dup 1) (match_dup 2)))]
8432146906Skan  "ix86_match_ccmode (insn, CCNOmode)
8433146906Skan   && ix86_binary_operator_ok (AND, QImode, operands)"
8434146906Skan  "and{b}\t{%2, %0|%0, %2}"
8435146906Skan  [(set_attr "type" "alu")
8436146906Skan   (set_attr "mode" "QI")])
8437146906Skan
843890286Sobrien(define_insn "*andqi_2_slp"
8439169699Skan  [(set (reg FLAGS_REG)
844090286Sobrien	(compare (and:QI
844190286Sobrien		   (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
844290286Sobrien		   (match_operand:QI 1 "nonimmediate_operand" "qmi,qi"))
844390286Sobrien		 (const_int 0)))
844490286Sobrien   (set (strict_low_part (match_dup 0))
844590286Sobrien	(and:QI (match_dup 0) (match_dup 1)))]
8446117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8447117404Skan   && ix86_match_ccmode (insn, CCNOmode)
8448117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
844990286Sobrien  "and{b}\t{%1, %0|%0, %1}"
845090286Sobrien  [(set_attr "type" "alu1")
845190286Sobrien   (set_attr "mode" "QI")])
845218334Speter
845390286Sobrien;; ??? A bug in recog prevents it from recognizing a const_int as an
845490286Sobrien;; operand to zero_extend in andqi_ext_1.  It was checking explicitly
845590286Sobrien;; for a QImode operand, which of course failed.
845618334Speter
845790286Sobrien(define_insn "andqi_ext_0"
845890286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
845990286Sobrien			 (const_int 8)
846090286Sobrien			 (const_int 8))
8461259563Spfg	(and:SI
846290286Sobrien	  (zero_extract:SI
846390286Sobrien	    (match_operand 1 "ext_register_operand" "0")
846490286Sobrien	    (const_int 8)
846590286Sobrien	    (const_int 8))
846690286Sobrien	  (match_operand 2 "const_int_operand" "n")))
8467169699Skan   (clobber (reg:CC FLAGS_REG))]
8468117404Skan  ""
846990286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
847090286Sobrien  [(set_attr "type" "alu")
847190286Sobrien   (set_attr "length_immediate" "1")
847290286Sobrien   (set_attr "mode" "QI")])
847318334Speter
847490286Sobrien;; Generated by peephole translating test to and.  This shows up
847590286Sobrien;; often in fp comparisons.
847690286Sobrien
847790286Sobrien(define_insn "*andqi_ext_0_cc"
8478169699Skan  [(set (reg FLAGS_REG)
847990286Sobrien	(compare
848090286Sobrien	  (and:SI
848190286Sobrien	    (zero_extract:SI
848290286Sobrien	      (match_operand 1 "ext_register_operand" "0")
848390286Sobrien	      (const_int 8)
848490286Sobrien	      (const_int 8))
848590286Sobrien	    (match_operand 2 "const_int_operand" "n"))
848690286Sobrien	  (const_int 0)))
848790286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
848890286Sobrien			 (const_int 8)
848990286Sobrien			 (const_int 8))
8490259563Spfg	(and:SI
849190286Sobrien	  (zero_extract:SI
849290286Sobrien	    (match_dup 1)
849390286Sobrien	    (const_int 8)
849490286Sobrien	    (const_int 8))
849590286Sobrien	  (match_dup 2)))]
8496117404Skan  "ix86_match_ccmode (insn, CCNOmode)"
849790286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
849890286Sobrien  [(set_attr "type" "alu")
849990286Sobrien   (set_attr "length_immediate" "1")
850090286Sobrien   (set_attr "mode" "QI")])
850190286Sobrien
850290286Sobrien(define_insn "*andqi_ext_1"
850390286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
850490286Sobrien			 (const_int 8)
850590286Sobrien			 (const_int 8))
8506259563Spfg	(and:SI
850790286Sobrien	  (zero_extract:SI
850890286Sobrien	    (match_operand 1 "ext_register_operand" "0")
850990286Sobrien	    (const_int 8)
851090286Sobrien	    (const_int 8))
851190286Sobrien	  (zero_extend:SI
851290286Sobrien	    (match_operand:QI 2 "general_operand" "Qm"))))
8513169699Skan   (clobber (reg:CC FLAGS_REG))]
851490286Sobrien  "!TARGET_64BIT"
851590286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
851690286Sobrien  [(set_attr "type" "alu")
851790286Sobrien   (set_attr "length_immediate" "0")
851890286Sobrien   (set_attr "mode" "QI")])
851990286Sobrien
852090286Sobrien(define_insn "*andqi_ext_1_rex64"
852190286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
852290286Sobrien			 (const_int 8)
852390286Sobrien			 (const_int 8))
8524259563Spfg	(and:SI
852590286Sobrien	  (zero_extract:SI
852690286Sobrien	    (match_operand 1 "ext_register_operand" "0")
852790286Sobrien	    (const_int 8)
852890286Sobrien	    (const_int 8))
852990286Sobrien	  (zero_extend:SI
853090286Sobrien	    (match_operand 2 "ext_register_operand" "Q"))))
8531169699Skan   (clobber (reg:CC FLAGS_REG))]
853290286Sobrien  "TARGET_64BIT"
853390286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
853490286Sobrien  [(set_attr "type" "alu")
853590286Sobrien   (set_attr "length_immediate" "0")
853690286Sobrien   (set_attr "mode" "QI")])
853790286Sobrien
853890286Sobrien(define_insn "*andqi_ext_2"
853990286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
854090286Sobrien			 (const_int 8)
854190286Sobrien			 (const_int 8))
854218334Speter	(and:SI
854390286Sobrien	  (zero_extract:SI
854490286Sobrien	    (match_operand 1 "ext_register_operand" "%0")
854590286Sobrien	    (const_int 8)
854690286Sobrien	    (const_int 8))
854790286Sobrien	  (zero_extract:SI
854890286Sobrien	    (match_operand 2 "ext_register_operand" "Q")
854990286Sobrien	    (const_int 8)
855090286Sobrien	    (const_int 8))))
8551169699Skan   (clobber (reg:CC FLAGS_REG))]
855290286Sobrien  ""
855390286Sobrien  "and{b}\t{%h2, %h0|%h0, %h2}"
855490286Sobrien  [(set_attr "type" "alu")
855590286Sobrien   (set_attr "length_immediate" "0")
855690286Sobrien   (set_attr "mode" "QI")])
8557117404Skan
8558117404Skan;; Convert wide AND instructions with immediate operand to shorter QImode
8559117404Skan;; equivalents when possible.
8560132727Skan;; Don't do the splitting with memory operands, since it introduces risk
8561117404Skan;; of memory mismatch stalls.  We may want to do the splitting for optimizing
8562117404Skan;; for size, but that can (should?) be handled by generic code instead.
8563117404Skan(define_split
8564117404Skan  [(set (match_operand 0 "register_operand" "")
8565117404Skan	(and (match_operand 1 "register_operand" "")
8566117404Skan	     (match_operand 2 "const_int_operand" "")))
8567169699Skan   (clobber (reg:CC FLAGS_REG))]
8568117404Skan   "reload_completed
8569117404Skan    && QI_REG_P (operands[0])
8570117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8571117404Skan    && !(~INTVAL (operands[2]) & ~(255 << 8))
8572117404Skan    && GET_MODE (operands[0]) != QImode"
8573117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
8574117404Skan		   (and:SI (zero_extract:SI (match_dup 1)
8575117404Skan					    (const_int 8) (const_int 8))
8576117404Skan			   (match_dup 2)))
8577169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8578117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
8579117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
8580117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
8581117404Skan
8582117404Skan;; Since AND can be encoded with sign extended immediate, this is only
8583117404Skan;; profitable when 7th bit is not set.
8584117404Skan(define_split
8585117404Skan  [(set (match_operand 0 "register_operand" "")
8586117404Skan	(and (match_operand 1 "general_operand" "")
8587117404Skan	     (match_operand 2 "const_int_operand" "")))
8588169699Skan   (clobber (reg:CC FLAGS_REG))]
8589117404Skan   "reload_completed
8590117404Skan    && ANY_QI_REG_P (operands[0])
8591117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8592117404Skan    && !(~INTVAL (operands[2]) & ~255)
8593117404Skan    && !(INTVAL (operands[2]) & 128)
8594117404Skan    && GET_MODE (operands[0]) != QImode"
8595117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
8596117404Skan		   (and:QI (match_dup 1)
8597117404Skan			   (match_dup 2)))
8598169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8599117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
8600117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
8601117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
860218334Speter
860390286Sobrien;; Logical inclusive OR instructions
860418334Speter
860590286Sobrien;; %%% This used to optimize known byte-wide and operations to memory.
860690286Sobrien;; If this is considered useful, it should be done with splitters.
860790286Sobrien
860890286Sobrien(define_expand "iordi3"
860990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
861090286Sobrien	(ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
861190286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "")))
8612169699Skan   (clobber (reg:CC FLAGS_REG))]
861390286Sobrien  "TARGET_64BIT"
861490286Sobrien  "ix86_expand_binary_operator (IOR, DImode, operands); DONE;")
861590286Sobrien
861690286Sobrien(define_insn "*iordi_1_rex64"
861790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
861890286Sobrien	(ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
861990286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "re,rme")))
8620169699Skan   (clobber (reg:CC FLAGS_REG))]
862190286Sobrien  "TARGET_64BIT
862290286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
862390286Sobrien  "or{q}\t{%2, %0|%0, %2}"
862490286Sobrien  [(set_attr "type" "alu")
862590286Sobrien   (set_attr "mode" "DI")])
862690286Sobrien
862790286Sobrien(define_insn "*iordi_2_rex64"
8628169699Skan  [(set (reg FLAGS_REG)
862990286Sobrien	(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
863090286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
863190286Sobrien		 (const_int 0)))
863290286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
863390286Sobrien	(ior:DI (match_dup 1) (match_dup 2)))]
863490286Sobrien  "TARGET_64BIT
863590286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
863690286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
863790286Sobrien  "or{q}\t{%2, %0|%0, %2}"
863890286Sobrien  [(set_attr "type" "alu")
863990286Sobrien   (set_attr "mode" "DI")])
864090286Sobrien
864190286Sobrien(define_insn "*iordi_3_rex64"
8642169699Skan  [(set (reg FLAGS_REG)
864390286Sobrien	(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
864490286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem"))
864590286Sobrien		 (const_int 0)))
864690286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
864790286Sobrien  "TARGET_64BIT
864890286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
864990286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
865090286Sobrien  "or{q}\t{%2, %0|%0, %2}"
865190286Sobrien  [(set_attr "type" "alu")
865290286Sobrien   (set_attr "mode" "DI")])
865390286Sobrien
865490286Sobrien
865590286Sobrien(define_expand "iorsi3"
865690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
865790286Sobrien	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
865890286Sobrien		(match_operand:SI 2 "general_operand" "")))
8659169699Skan   (clobber (reg:CC FLAGS_REG))]
866090286Sobrien  ""
866190286Sobrien  "ix86_expand_binary_operator (IOR, SImode, operands); DONE;")
866290286Sobrien
866390286Sobrien(define_insn "*iorsi_1"
866450650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
866550650Sobrien	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
866690286Sobrien		(match_operand:SI 2 "general_operand" "ri,rmi")))
8667169699Skan   (clobber (reg:CC FLAGS_REG))]
866890286Sobrien  "ix86_binary_operator_ok (IOR, SImode, operands)"
866990286Sobrien  "or{l}\t{%2, %0|%0, %2}"
867090286Sobrien  [(set_attr "type" "alu")
867190286Sobrien   (set_attr "mode" "SI")])
867250650Sobrien
867390286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
867490286Sobrien(define_insn "*iorsi_1_zext"
867590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm")
867690286Sobrien	(zero_extend:DI
867790286Sobrien	  (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
867890286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8679169699Skan   (clobber (reg:CC FLAGS_REG))]
868090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)"
868190286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
868290286Sobrien  [(set_attr "type" "alu")
868390286Sobrien   (set_attr "mode" "SI")])
868450650Sobrien
868590286Sobrien(define_insn "*iorsi_1_zext_imm"
868690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm")
868790286Sobrien	(ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
868890286Sobrien		(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
8689169699Skan   (clobber (reg:CC FLAGS_REG))]
869090286Sobrien  "TARGET_64BIT"
869190286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
869290286Sobrien  [(set_attr "type" "alu")
869390286Sobrien   (set_attr "mode" "SI")])
869450650Sobrien
869590286Sobrien(define_insn "*iorsi_2"
8696169699Skan  [(set (reg FLAGS_REG)
869790286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
869890286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
869990286Sobrien		 (const_int 0)))
870090286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
870190286Sobrien	(ior:SI (match_dup 1) (match_dup 2)))]
870290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
870390286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
870490286Sobrien  "or{l}\t{%2, %0|%0, %2}"
870590286Sobrien  [(set_attr "type" "alu")
870690286Sobrien   (set_attr "mode" "SI")])
870750650Sobrien
870890286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
870990286Sobrien;; ??? Special case for immediate operand is missing - it is tricky.
871090286Sobrien(define_insn "*iorsi_2_zext"
8711169699Skan  [(set (reg FLAGS_REG)
871290286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
871390286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
871490286Sobrien		 (const_int 0)))
871590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
871690286Sobrien	(zero_extend:DI (ior:SI (match_dup 1) (match_dup 2))))]
871790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
871890286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
871990286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
872090286Sobrien  [(set_attr "type" "alu")
872190286Sobrien   (set_attr "mode" "SI")])
872250650Sobrien
872390286Sobrien(define_insn "*iorsi_2_zext_imm"
8724169699Skan  [(set (reg FLAGS_REG)
872590286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
872690286Sobrien			 (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
872790286Sobrien		 (const_int 0)))
872890286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
872990286Sobrien	(ior:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
873090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
873190286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
873290286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
873390286Sobrien  [(set_attr "type" "alu")
873490286Sobrien   (set_attr "mode" "SI")])
873550650Sobrien
873690286Sobrien(define_insn "*iorsi_3"
8737169699Skan  [(set (reg FLAGS_REG)
873890286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
873990286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
874090286Sobrien		 (const_int 0)))
874190286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
874290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
874390286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
874490286Sobrien  "or{l}\t{%2, %0|%0, %2}"
874590286Sobrien  [(set_attr "type" "alu")
874690286Sobrien   (set_attr "mode" "SI")])
874750650Sobrien
874890286Sobrien(define_expand "iorhi3"
874990286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
875090286Sobrien	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "")
875190286Sobrien		(match_operand:HI 2 "general_operand" "")))
8752169699Skan   (clobber (reg:CC FLAGS_REG))]
875390286Sobrien  "TARGET_HIMODE_MATH"
875490286Sobrien  "ix86_expand_binary_operator (IOR, HImode, operands); DONE;")
875550650Sobrien
875690286Sobrien(define_insn "*iorhi_1"
875790286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
875890286Sobrien	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
875990286Sobrien		(match_operand:HI 2 "general_operand" "rmi,ri")))
8760169699Skan   (clobber (reg:CC FLAGS_REG))]
876190286Sobrien  "ix86_binary_operator_ok (IOR, HImode, operands)"
876290286Sobrien  "or{w}\t{%2, %0|%0, %2}"
876390286Sobrien  [(set_attr "type" "alu")
876490286Sobrien   (set_attr "mode" "HI")])
876518334Speter
876690286Sobrien(define_insn "*iorhi_2"
8767169699Skan  [(set (reg FLAGS_REG)
876890286Sobrien	(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
876990286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
877090286Sobrien		 (const_int 0)))
877190286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
877290286Sobrien	(ior:HI (match_dup 1) (match_dup 2)))]
877390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
877490286Sobrien   && ix86_binary_operator_ok (IOR, HImode, operands)"
877590286Sobrien  "or{w}\t{%2, %0|%0, %2}"
877690286Sobrien  [(set_attr "type" "alu")
877790286Sobrien   (set_attr "mode" "HI")])
877818334Speter
877990286Sobrien(define_insn "*iorhi_3"
8780169699Skan  [(set (reg FLAGS_REG)
878190286Sobrien	(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
878290286Sobrien			 (match_operand:HI 2 "general_operand" "rim"))
878390286Sobrien		 (const_int 0)))
878490286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
878590286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
878690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
878790286Sobrien  "or{w}\t{%2, %0|%0, %2}"
878890286Sobrien  [(set_attr "type" "alu")
878990286Sobrien   (set_attr "mode" "HI")])
879050650Sobrien
879190286Sobrien(define_expand "iorqi3"
879290286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
879390286Sobrien	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "")
879490286Sobrien		(match_operand:QI 2 "general_operand" "")))
8795169699Skan   (clobber (reg:CC FLAGS_REG))]
879690286Sobrien  "TARGET_QIMODE_MATH"
879790286Sobrien  "ix86_expand_binary_operator (IOR, QImode, operands); DONE;")
879818334Speter
879990286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
880090286Sobrien(define_insn "*iorqi_1"
880190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
880290286Sobrien	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
880390286Sobrien		(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
8804169699Skan   (clobber (reg:CC FLAGS_REG))]
880590286Sobrien  "ix86_binary_operator_ok (IOR, QImode, operands)"
880690286Sobrien  "@
880790286Sobrien   or{b}\t{%2, %0|%0, %2}
880890286Sobrien   or{b}\t{%2, %0|%0, %2}
880990286Sobrien   or{l}\t{%k2, %k0|%k0, %k2}"
881090286Sobrien  [(set_attr "type" "alu")
881190286Sobrien   (set_attr "mode" "QI,QI,SI")])
881250650Sobrien
881390286Sobrien(define_insn "*iorqi_1_slp"
881490286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m"))
881590286Sobrien	(ior:QI (match_dup 0)
881690286Sobrien		(match_operand:QI 1 "general_operand" "qmi,qi")))
8817169699Skan   (clobber (reg:CC FLAGS_REG))]
8818117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8819117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
882090286Sobrien  "or{b}\t{%1, %0|%0, %1}"
882190286Sobrien  [(set_attr "type" "alu1")
882290286Sobrien   (set_attr "mode" "QI")])
882318334Speter
882490286Sobrien(define_insn "*iorqi_2"
8825169699Skan  [(set (reg FLAGS_REG)
882690286Sobrien	(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
882790286Sobrien			 (match_operand:QI 2 "general_operand" "qim,qi"))
882890286Sobrien		 (const_int 0)))
882990286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
883090286Sobrien	(ior:QI (match_dup 1) (match_dup 2)))]
883190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
883290286Sobrien   && ix86_binary_operator_ok (IOR, QImode, operands)"
883390286Sobrien  "or{b}\t{%2, %0|%0, %2}"
883490286Sobrien  [(set_attr "type" "alu")
883590286Sobrien   (set_attr "mode" "QI")])
883618334Speter
883790286Sobrien(define_insn "*iorqi_2_slp"
8838169699Skan  [(set (reg FLAGS_REG)
883990286Sobrien	(compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
884090286Sobrien			 (match_operand:QI 1 "general_operand" "qim,qi"))
884190286Sobrien		 (const_int 0)))
884290286Sobrien   (set (strict_low_part (match_dup 0))
884390286Sobrien	(ior:QI (match_dup 0) (match_dup 1)))]
8844117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8845117404Skan   && ix86_match_ccmode (insn, CCNOmode)
8846117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
884790286Sobrien  "or{b}\t{%1, %0|%0, %1}"
884890286Sobrien  [(set_attr "type" "alu1")
884990286Sobrien   (set_attr "mode" "QI")])
885018334Speter
885190286Sobrien(define_insn "*iorqi_3"
8852169699Skan  [(set (reg FLAGS_REG)
885390286Sobrien	(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
885490286Sobrien			 (match_operand:QI 2 "general_operand" "qim"))
885590286Sobrien		 (const_int 0)))
885690286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
885790286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
885890286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
885990286Sobrien  "or{b}\t{%2, %0|%0, %2}"
886090286Sobrien  [(set_attr "type" "alu")
886190286Sobrien   (set_attr "mode" "QI")])
886218334Speter
8863117404Skan(define_insn "iorqi_ext_0"
8864117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8865117404Skan			 (const_int 8)
8866117404Skan			 (const_int 8))
8867259563Spfg	(ior:SI
8868117404Skan	  (zero_extract:SI
8869117404Skan	    (match_operand 1 "ext_register_operand" "0")
8870117404Skan	    (const_int 8)
8871117404Skan	    (const_int 8))
8872117404Skan	  (match_operand 2 "const_int_operand" "n")))
8873169699Skan   (clobber (reg:CC FLAGS_REG))]
8874117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
8875117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8876117404Skan  [(set_attr "type" "alu")
8877117404Skan   (set_attr "length_immediate" "1")
8878117404Skan   (set_attr "mode" "QI")])
8879117404Skan
8880117404Skan(define_insn "*iorqi_ext_1"
8881117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8882117404Skan			 (const_int 8)
8883117404Skan			 (const_int 8))
8884259563Spfg	(ior:SI
8885117404Skan	  (zero_extract:SI
8886117404Skan	    (match_operand 1 "ext_register_operand" "0")
8887117404Skan	    (const_int 8)
8888117404Skan	    (const_int 8))
8889117404Skan	  (zero_extend:SI
8890117404Skan	    (match_operand:QI 2 "general_operand" "Qm"))))
8891169699Skan   (clobber (reg:CC FLAGS_REG))]
8892117404Skan  "!TARGET_64BIT
8893117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
8894117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8895117404Skan  [(set_attr "type" "alu")
8896117404Skan   (set_attr "length_immediate" "0")
8897117404Skan   (set_attr "mode" "QI")])
8898117404Skan
8899117404Skan(define_insn "*iorqi_ext_1_rex64"
8900117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8901117404Skan			 (const_int 8)
8902117404Skan			 (const_int 8))
8903259563Spfg	(ior:SI
8904117404Skan	  (zero_extract:SI
8905117404Skan	    (match_operand 1 "ext_register_operand" "0")
8906117404Skan	    (const_int 8)
8907117404Skan	    (const_int 8))
8908117404Skan	  (zero_extend:SI
8909117404Skan	    (match_operand 2 "ext_register_operand" "Q"))))
8910169699Skan   (clobber (reg:CC FLAGS_REG))]
8911117404Skan  "TARGET_64BIT
8912117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
8913117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8914117404Skan  [(set_attr "type" "alu")
8915117404Skan   (set_attr "length_immediate" "0")
8916117404Skan   (set_attr "mode" "QI")])
8917117404Skan
8918117404Skan(define_insn "*iorqi_ext_2"
8919117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8920117404Skan			 (const_int 8)
8921117404Skan			 (const_int 8))
8922259563Spfg	(ior:SI
8923117404Skan	  (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
8924117404Skan	  		   (const_int 8)
8925117404Skan			   (const_int 8))
8926117404Skan	  (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
8927117404Skan	  		   (const_int 8)
8928117404Skan			   (const_int 8))))
8929169699Skan   (clobber (reg:CC FLAGS_REG))]
8930117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
8931117404Skan  "ior{b}\t{%h2, %h0|%h0, %h2}"
8932117404Skan  [(set_attr "type" "alu")
8933117404Skan   (set_attr "length_immediate" "0")
8934117404Skan   (set_attr "mode" "QI")])
8935117404Skan
8936117404Skan(define_split
8937117404Skan  [(set (match_operand 0 "register_operand" "")
8938117404Skan	(ior (match_operand 1 "register_operand" "")
8939117404Skan	     (match_operand 2 "const_int_operand" "")))
8940169699Skan   (clobber (reg:CC FLAGS_REG))]
8941117404Skan   "reload_completed
8942117404Skan    && QI_REG_P (operands[0])
8943117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8944117404Skan    && !(INTVAL (operands[2]) & ~(255 << 8))
8945117404Skan    && GET_MODE (operands[0]) != QImode"
8946117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
8947117404Skan		   (ior:SI (zero_extract:SI (match_dup 1)
8948117404Skan					    (const_int 8) (const_int 8))
8949117404Skan			   (match_dup 2)))
8950169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8951117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
8952117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
8953117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
8954117404Skan
8955117404Skan;; Since OR can be encoded with sign extended immediate, this is only
8956117404Skan;; profitable when 7th bit is set.
8957117404Skan(define_split
8958117404Skan  [(set (match_operand 0 "register_operand" "")
8959117404Skan	(ior (match_operand 1 "general_operand" "")
8960117404Skan	     (match_operand 2 "const_int_operand" "")))
8961169699Skan   (clobber (reg:CC FLAGS_REG))]
8962117404Skan   "reload_completed
8963117404Skan    && ANY_QI_REG_P (operands[0])
8964117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8965117404Skan    && !(INTVAL (operands[2]) & ~255)
8966117404Skan    && (INTVAL (operands[2]) & 128)
8967117404Skan    && GET_MODE (operands[0]) != QImode"
8968117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
8969117404Skan		   (ior:QI (match_dup 1)
8970117404Skan			   (match_dup 2)))
8971169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8972117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
8973117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
8974117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
897590286Sobrien
897690286Sobrien;; Logical XOR instructions
897790286Sobrien
897890286Sobrien;; %%% This used to optimize known byte-wide and operations to memory.
897990286Sobrien;; If this is considered useful, it should be done with splitters.
898090286Sobrien
898190286Sobrien(define_expand "xordi3"
898290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
898390286Sobrien	(xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
898490286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "")))
8985169699Skan   (clobber (reg:CC FLAGS_REG))]
898690286Sobrien  "TARGET_64BIT"
898790286Sobrien  "ix86_expand_binary_operator (XOR, DImode, operands); DONE;")
898890286Sobrien
898990286Sobrien(define_insn "*xordi_1_rex64"
899090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
899190286Sobrien	(xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
899290286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
8993169699Skan   (clobber (reg:CC FLAGS_REG))]
899490286Sobrien  "TARGET_64BIT
899590286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
899690286Sobrien  "@
8997169699Skan   xor{q}\t{%2, %0|%0, %2}
899890286Sobrien   xor{q}\t{%2, %0|%0, %2}"
899990286Sobrien  [(set_attr "type" "alu")
900090286Sobrien   (set_attr "mode" "DI,DI")])
900190286Sobrien
900290286Sobrien(define_insn "*xordi_2_rex64"
9003169699Skan  [(set (reg FLAGS_REG)
900490286Sobrien	(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
900590286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
900690286Sobrien		 (const_int 0)))
900790286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
900890286Sobrien	(xor:DI (match_dup 1) (match_dup 2)))]
900990286Sobrien  "TARGET_64BIT
901090286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
901190286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
901290286Sobrien  "@
9013169699Skan   xor{q}\t{%2, %0|%0, %2}
901490286Sobrien   xor{q}\t{%2, %0|%0, %2}"
901590286Sobrien  [(set_attr "type" "alu")
901690286Sobrien   (set_attr "mode" "DI,DI")])
901790286Sobrien
901890286Sobrien(define_insn "*xordi_3_rex64"
9019169699Skan  [(set (reg FLAGS_REG)
902090286Sobrien	(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
902190286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem"))
902290286Sobrien		 (const_int 0)))
902390286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
902490286Sobrien  "TARGET_64BIT
902590286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
902690286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
902790286Sobrien  "xor{q}\t{%2, %0|%0, %2}"
902890286Sobrien  [(set_attr "type" "alu")
902990286Sobrien   (set_attr "mode" "DI")])
903090286Sobrien
903190286Sobrien(define_expand "xorsi3"
903290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
903390286Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "")
903490286Sobrien		(match_operand:SI 2 "general_operand" "")))
9035169699Skan   (clobber (reg:CC FLAGS_REG))]
903618334Speter  ""
903790286Sobrien  "ix86_expand_binary_operator (XOR, SImode, operands); DONE;")
903818334Speter
903990286Sobrien(define_insn "*xorsi_1"
904090286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
904190286Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
904290286Sobrien		(match_operand:SI 2 "general_operand" "ri,rm")))
9043169699Skan   (clobber (reg:CC FLAGS_REG))]
904490286Sobrien  "ix86_binary_operator_ok (XOR, SImode, operands)"
904590286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
904690286Sobrien  [(set_attr "type" "alu")
904790286Sobrien   (set_attr "mode" "SI")])
904818334Speter
904990286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
905090286Sobrien;; Add speccase for immediates
905190286Sobrien(define_insn "*xorsi_1_zext"
905290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
905390286Sobrien	(zero_extend:DI
905490286Sobrien	  (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
905590286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
9056169699Skan   (clobber (reg:CC FLAGS_REG))]
905790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
905890286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
905990286Sobrien  [(set_attr "type" "alu")
906090286Sobrien   (set_attr "mode" "SI")])
906150650Sobrien
906290286Sobrien(define_insn "*xorsi_1_zext_imm"
906390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
906490286Sobrien	(xor:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
906590286Sobrien		(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
9066169699Skan   (clobber (reg:CC FLAGS_REG))]
906790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
906890286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
906990286Sobrien  [(set_attr "type" "alu")
907090286Sobrien   (set_attr "mode" "SI")])
907150650Sobrien
907290286Sobrien(define_insn "*xorsi_2"
9073169699Skan  [(set (reg FLAGS_REG)
907490286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
907590286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
907690286Sobrien		 (const_int 0)))
907790286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
907890286Sobrien	(xor:SI (match_dup 1) (match_dup 2)))]
907990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
908090286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
908190286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
908290286Sobrien  [(set_attr "type" "alu")
908390286Sobrien   (set_attr "mode" "SI")])
908450650Sobrien
908590286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
908690286Sobrien;; ??? Special case for immediate operand is missing - it is tricky.
908790286Sobrien(define_insn "*xorsi_2_zext"
9088169699Skan  [(set (reg FLAGS_REG)
908990286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
909090286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
909190286Sobrien		 (const_int 0)))
909290286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
909390286Sobrien	(zero_extend:DI (xor:SI (match_dup 1) (match_dup 2))))]
909490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
909590286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
909690286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
909790286Sobrien  [(set_attr "type" "alu")
909890286Sobrien   (set_attr "mode" "SI")])
909950650Sobrien
910090286Sobrien(define_insn "*xorsi_2_zext_imm"
9101169699Skan  [(set (reg FLAGS_REG)
910290286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
910390286Sobrien			 (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
910490286Sobrien		 (const_int 0)))
910590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
910690286Sobrien	(xor:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
910790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
910890286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
910990286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
911090286Sobrien  [(set_attr "type" "alu")
911190286Sobrien   (set_attr "mode" "SI")])
911250650Sobrien
911390286Sobrien(define_insn "*xorsi_3"
9114169699Skan  [(set (reg FLAGS_REG)
911590286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
911690286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
911790286Sobrien		 (const_int 0)))
911890286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
911990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
912090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
912190286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
912290286Sobrien  [(set_attr "type" "alu")
912390286Sobrien   (set_attr "mode" "SI")])
912418334Speter
912590286Sobrien(define_expand "xorhi3"
912690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
912790286Sobrien	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "")
912890286Sobrien		(match_operand:HI 2 "general_operand" "")))
9129169699Skan   (clobber (reg:CC FLAGS_REG))]
913090286Sobrien  "TARGET_HIMODE_MATH"
913190286Sobrien  "ix86_expand_binary_operator (XOR, HImode, operands); DONE;")
913218334Speter
913390286Sobrien(define_insn "*xorhi_1"
913490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
913590286Sobrien	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
913690286Sobrien		(match_operand:HI 2 "general_operand" "rmi,ri")))
9137169699Skan   (clobber (reg:CC FLAGS_REG))]
913890286Sobrien  "ix86_binary_operator_ok (XOR, HImode, operands)"
913990286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
914090286Sobrien  [(set_attr "type" "alu")
914190286Sobrien   (set_attr "mode" "HI")])
914218334Speter
914390286Sobrien(define_insn "*xorhi_2"
9144169699Skan  [(set (reg FLAGS_REG)
914590286Sobrien	(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
914690286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
914790286Sobrien		 (const_int 0)))
914890286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
914990286Sobrien	(xor:HI (match_dup 1) (match_dup 2)))]
915090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
915190286Sobrien   && ix86_binary_operator_ok (XOR, HImode, operands)"
915290286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
915390286Sobrien  [(set_attr "type" "alu")
915490286Sobrien   (set_attr "mode" "HI")])
915550650Sobrien
915690286Sobrien(define_insn "*xorhi_3"
9157169699Skan  [(set (reg FLAGS_REG)
915890286Sobrien	(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
915990286Sobrien			 (match_operand:HI 2 "general_operand" "rim"))
916090286Sobrien		 (const_int 0)))
916190286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
916290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
916390286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
916490286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
916590286Sobrien  [(set_attr "type" "alu")
916690286Sobrien   (set_attr "mode" "HI")])
916750650Sobrien
916890286Sobrien(define_expand "xorqi3"
916990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
917090286Sobrien	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "")
917190286Sobrien		(match_operand:QI 2 "general_operand" "")))
9172169699Skan   (clobber (reg:CC FLAGS_REG))]
917390286Sobrien  "TARGET_QIMODE_MATH"
917490286Sobrien  "ix86_expand_binary_operator (XOR, QImode, operands); DONE;")
917550650Sobrien
917690286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
917790286Sobrien(define_insn "*xorqi_1"
917890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
917990286Sobrien	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
918090286Sobrien		(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
9181169699Skan   (clobber (reg:CC FLAGS_REG))]
918290286Sobrien  "ix86_binary_operator_ok (XOR, QImode, operands)"
918390286Sobrien  "@
918490286Sobrien   xor{b}\t{%2, %0|%0, %2}
918590286Sobrien   xor{b}\t{%2, %0|%0, %2}
918690286Sobrien   xor{l}\t{%k2, %k0|%k0, %k2}"
918790286Sobrien  [(set_attr "type" "alu")
918890286Sobrien   (set_attr "mode" "QI,QI,SI")])
918918334Speter
9190117404Skan(define_insn "*xorqi_1_slp"
9191117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
9192117404Skan	(xor:QI (match_dup 0)
9193117404Skan		(match_operand:QI 1 "general_operand" "qi,qmi")))
9194169699Skan   (clobber (reg:CC FLAGS_REG))]
9195117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
9196117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
9197117404Skan  "xor{b}\t{%1, %0|%0, %1}"
9198117404Skan  [(set_attr "type" "alu1")
9199117404Skan   (set_attr "mode" "QI")])
9200117404Skan
9201117404Skan(define_insn "xorqi_ext_0"
9202117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9203117404Skan			 (const_int 8)
9204117404Skan			 (const_int 8))
9205259563Spfg	(xor:SI
9206117404Skan	  (zero_extract:SI
9207117404Skan	    (match_operand 1 "ext_register_operand" "0")
9208117404Skan	    (const_int 8)
9209117404Skan	    (const_int 8))
9210117404Skan	  (match_operand 2 "const_int_operand" "n")))
9211169699Skan   (clobber (reg:CC FLAGS_REG))]
9212117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
9213117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9214117404Skan  [(set_attr "type" "alu")
9215117404Skan   (set_attr "length_immediate" "1")
9216117404Skan   (set_attr "mode" "QI")])
9217117404Skan
921890286Sobrien(define_insn "*xorqi_ext_1"
921990286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
922090286Sobrien			 (const_int 8)
922190286Sobrien			 (const_int 8))
9222259563Spfg	(xor:SI
9223117404Skan	  (zero_extract:SI
9224117404Skan	    (match_operand 1 "ext_register_operand" "0")
9225117404Skan	    (const_int 8)
9226117404Skan	    (const_int 8))
9227117404Skan	  (zero_extend:SI
9228117404Skan	    (match_operand:QI 2 "general_operand" "Qm"))))
9229169699Skan   (clobber (reg:CC FLAGS_REG))]
9230117404Skan  "!TARGET_64BIT
9231117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
9232117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9233117404Skan  [(set_attr "type" "alu")
9234117404Skan   (set_attr "length_immediate" "0")
9235117404Skan   (set_attr "mode" "QI")])
9236117404Skan
9237117404Skan(define_insn "*xorqi_ext_1_rex64"
9238117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9239117404Skan			 (const_int 8)
9240117404Skan			 (const_int 8))
9241259563Spfg	(xor:SI
9242117404Skan	  (zero_extract:SI
9243117404Skan	    (match_operand 1 "ext_register_operand" "0")
9244117404Skan	    (const_int 8)
9245117404Skan	    (const_int 8))
9246117404Skan	  (zero_extend:SI
9247117404Skan	    (match_operand 2 "ext_register_operand" "Q"))))
9248169699Skan   (clobber (reg:CC FLAGS_REG))]
9249117404Skan  "TARGET_64BIT
9250117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
9251117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9252117404Skan  [(set_attr "type" "alu")
9253117404Skan   (set_attr "length_immediate" "0")
9254117404Skan   (set_attr "mode" "QI")])
9255117404Skan
9256117404Skan(define_insn "*xorqi_ext_2"
9257117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9258117404Skan			 (const_int 8)
9259117404Skan			 (const_int 8))
9260259563Spfg	(xor:SI
926190286Sobrien	  (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
926290286Sobrien	  		   (const_int 8)
926390286Sobrien			   (const_int 8))
926490286Sobrien	  (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
926590286Sobrien	  		   (const_int 8)
926690286Sobrien			   (const_int 8))))
9267169699Skan   (clobber (reg:CC FLAGS_REG))]
9268117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
926990286Sobrien  "xor{b}\t{%h2, %h0|%h0, %h2}"
927090286Sobrien  [(set_attr "type" "alu")
927190286Sobrien   (set_attr "length_immediate" "0")
927290286Sobrien   (set_attr "mode" "QI")])
927350650Sobrien
927490286Sobrien(define_insn "*xorqi_cc_1"
9275169699Skan  [(set (reg FLAGS_REG)
927690286Sobrien	(compare
927790286Sobrien	  (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
927890286Sobrien		  (match_operand:QI 2 "general_operand" "qim,qi"))
927990286Sobrien	  (const_int 0)))
928090286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
928190286Sobrien	(xor:QI (match_dup 1) (match_dup 2)))]
928290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
928390286Sobrien   && ix86_binary_operator_ok (XOR, QImode, operands)"
928490286Sobrien  "xor{b}\t{%2, %0|%0, %2}"
928590286Sobrien  [(set_attr "type" "alu")
928690286Sobrien   (set_attr "mode" "QI")])
928750650Sobrien
9288117404Skan(define_insn "*xorqi_2_slp"
9289169699Skan  [(set (reg FLAGS_REG)
9290117404Skan	(compare (xor:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
9291117404Skan			 (match_operand:QI 1 "general_operand" "qim,qi"))
9292117404Skan		 (const_int 0)))
9293117404Skan   (set (strict_low_part (match_dup 0))
9294117404Skan	(xor:QI (match_dup 0) (match_dup 1)))]
9295117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
9296117404Skan   && ix86_match_ccmode (insn, CCNOmode)
9297117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
9298117404Skan  "xor{b}\t{%1, %0|%0, %1}"
9299117404Skan  [(set_attr "type" "alu1")
9300117404Skan   (set_attr "mode" "QI")])
9301117404Skan
930290286Sobrien(define_insn "*xorqi_cc_2"
9303169699Skan  [(set (reg FLAGS_REG)
930490286Sobrien	(compare
930590286Sobrien	  (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
930690286Sobrien		  (match_operand:QI 2 "general_operand" "qim"))
930790286Sobrien	  (const_int 0)))
930890286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
930990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
931090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
931190286Sobrien  "xor{b}\t{%2, %0|%0, %2}"
931290286Sobrien  [(set_attr "type" "alu")
931390286Sobrien   (set_attr "mode" "QI")])
931418334Speter
931590286Sobrien(define_insn "*xorqi_cc_ext_1"
9316169699Skan  [(set (reg FLAGS_REG)
931790286Sobrien	(compare
931890286Sobrien	  (xor:SI
931990286Sobrien	    (zero_extract:SI
932090286Sobrien	      (match_operand 1 "ext_register_operand" "0")
932190286Sobrien	      (const_int 8)
932290286Sobrien	      (const_int 8))
932390286Sobrien	    (match_operand:QI 2 "general_operand" "qmn"))
932490286Sobrien	  (const_int 0)))
932590286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=q")
932690286Sobrien			 (const_int 8)
932790286Sobrien			 (const_int 8))
9328259563Spfg	(xor:SI
932990286Sobrien	  (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
933090286Sobrien	  (match_dup 2)))]
933190286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
933290286Sobrien  "xor{b}\t{%2, %h0|%h0, %2}"
933390286Sobrien  [(set_attr "type" "alu")
933490286Sobrien   (set_attr "mode" "QI")])
933590286Sobrien
933690286Sobrien(define_insn "*xorqi_cc_ext_1_rex64"
9337169699Skan  [(set (reg FLAGS_REG)
933890286Sobrien	(compare
933990286Sobrien	  (xor:SI
934090286Sobrien	    (zero_extract:SI
934190286Sobrien	      (match_operand 1 "ext_register_operand" "0")
934290286Sobrien	      (const_int 8)
934390286Sobrien	      (const_int 8))
934490286Sobrien	    (match_operand:QI 2 "nonmemory_operand" "Qn"))
934590286Sobrien	  (const_int 0)))
934690286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
934790286Sobrien			 (const_int 8)
934890286Sobrien			 (const_int 8))
9349259563Spfg	(xor:SI
935090286Sobrien	  (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
935190286Sobrien	  (match_dup 2)))]
935290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
935390286Sobrien  "xor{b}\t{%2, %h0|%h0, %2}"
935490286Sobrien  [(set_attr "type" "alu")
935590286Sobrien   (set_attr "mode" "QI")])
935690286Sobrien
935790286Sobrien(define_expand "xorqi_cc_ext_1"
935890286Sobrien  [(parallel [
9359169699Skan     (set (reg:CCNO FLAGS_REG)
936090286Sobrien	  (compare:CCNO
936190286Sobrien	    (xor:SI
936290286Sobrien	      (zero_extract:SI
936390286Sobrien		(match_operand 1 "ext_register_operand" "")
936490286Sobrien		(const_int 8)
936590286Sobrien		(const_int 8))
936690286Sobrien	      (match_operand:QI 2 "general_operand" ""))
936790286Sobrien	    (const_int 0)))
936890286Sobrien     (set (zero_extract:SI (match_operand 0 "ext_register_operand" "")
936990286Sobrien			   (const_int 8)
937090286Sobrien			   (const_int 8))
9371259563Spfg	  (xor:SI
937290286Sobrien	    (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
937390286Sobrien	    (match_dup 2)))])]
937418334Speter  ""
937590286Sobrien  "")
9376117404Skan
9377117404Skan(define_split
9378117404Skan  [(set (match_operand 0 "register_operand" "")
9379117404Skan	(xor (match_operand 1 "register_operand" "")
9380117404Skan	     (match_operand 2 "const_int_operand" "")))
9381169699Skan   (clobber (reg:CC FLAGS_REG))]
9382117404Skan   "reload_completed
9383117404Skan    && QI_REG_P (operands[0])
9384117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
9385117404Skan    && !(INTVAL (operands[2]) & ~(255 << 8))
9386117404Skan    && GET_MODE (operands[0]) != QImode"
9387117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
9388117404Skan		   (xor:SI (zero_extract:SI (match_dup 1)
9389117404Skan					    (const_int 8) (const_int 8))
9390117404Skan			   (match_dup 2)))
9391169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9392117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
9393117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
9394117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
9395117404Skan
9396117404Skan;; Since XOR can be encoded with sign extended immediate, this is only
9397117404Skan;; profitable when 7th bit is set.
9398117404Skan(define_split
9399117404Skan  [(set (match_operand 0 "register_operand" "")
9400117404Skan	(xor (match_operand 1 "general_operand" "")
9401117404Skan	     (match_operand 2 "const_int_operand" "")))
9402169699Skan   (clobber (reg:CC FLAGS_REG))]
9403117404Skan   "reload_completed
9404117404Skan    && ANY_QI_REG_P (operands[0])
9405117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
9406117404Skan    && !(INTVAL (operands[2]) & ~255)
9407117404Skan    && (INTVAL (operands[2]) & 128)
9408117404Skan    && GET_MODE (operands[0]) != QImode"
9409117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
9410117404Skan		   (xor:QI (match_dup 1)
9411117404Skan			   (match_dup 2)))
9412169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9413117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
9414117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
9415117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
941618334Speter
941790286Sobrien;; Negation instructions
941818334Speter
9419169699Skan(define_expand "negti2"
9420169699Skan  [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
9421169699Skan		   (neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
9422169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9423169699Skan  "TARGET_64BIT"
9424169699Skan  "ix86_expand_unary_operator (NEG, TImode, operands); DONE;")
9425169699Skan
9426169699Skan(define_insn "*negti2_1"
9427169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=ro")
9428171835Skan	(neg:TI (match_operand:TI 1 "nonimmediate_operand" "0")))
9429169699Skan   (clobber (reg:CC FLAGS_REG))]
9430169699Skan  "TARGET_64BIT
9431169699Skan   && ix86_unary_operator_ok (NEG, TImode, operands)"
9432169699Skan  "#")
9433169699Skan
9434169699Skan(define_split
9435169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
9436171835Skan	(neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
9437169699Skan   (clobber (reg:CC FLAGS_REG))]
9438169699Skan  "TARGET_64BIT && reload_completed"
9439169699Skan  [(parallel
9440169699Skan    [(set (reg:CCZ FLAGS_REG)
9441169699Skan	  (compare:CCZ (neg:DI (match_dup 2)) (const_int 0)))
9442169699Skan     (set (match_dup 0) (neg:DI (match_dup 2)))])
9443169699Skan   (parallel
9444169699Skan    [(set (match_dup 1)
9445169699Skan	  (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
9446169699Skan			    (match_dup 3))
9447169699Skan		   (const_int 0)))
9448169699Skan     (clobber (reg:CC FLAGS_REG))])
9449169699Skan   (parallel
9450169699Skan    [(set (match_dup 1)
9451169699Skan	  (neg:DI (match_dup 1)))
9452169699Skan     (clobber (reg:CC FLAGS_REG))])]
9453169699Skan  "split_ti (operands+1, 1, operands+2, operands+3);
9454169699Skan   split_ti (operands+0, 1, operands+0, operands+1);")
9455169699Skan
945690286Sobrien(define_expand "negdi2"
945790286Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
945890286Sobrien		   (neg:DI (match_operand:DI 1 "nonimmediate_operand" "")))
9459169699Skan	      (clobber (reg:CC FLAGS_REG))])]
946018334Speter  ""
946190286Sobrien  "ix86_expand_unary_operator (NEG, DImode, operands); DONE;")
946250650Sobrien
946390286Sobrien(define_insn "*negdi2_1"
946490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=ro")
946590286Sobrien	(neg:DI (match_operand:DI 1 "general_operand" "0")))
9466169699Skan   (clobber (reg:CC FLAGS_REG))]
946790286Sobrien  "!TARGET_64BIT
946890286Sobrien   && ix86_unary_operator_ok (NEG, DImode, operands)"
946990286Sobrien  "#")
947050650Sobrien
947190286Sobrien(define_split
947290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
947390286Sobrien	(neg:DI (match_operand:DI 1 "general_operand" "")))
9474169699Skan   (clobber (reg:CC FLAGS_REG))]
947590286Sobrien  "!TARGET_64BIT && reload_completed"
947690286Sobrien  [(parallel
9477169699Skan    [(set (reg:CCZ FLAGS_REG)
947890286Sobrien	  (compare:CCZ (neg:SI (match_dup 2)) (const_int 0)))
947990286Sobrien     (set (match_dup 0) (neg:SI (match_dup 2)))])
948090286Sobrien   (parallel
948190286Sobrien    [(set (match_dup 1)
9482169699Skan	  (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
948390286Sobrien			    (match_dup 3))
948490286Sobrien		   (const_int 0)))
9485169699Skan     (clobber (reg:CC FLAGS_REG))])
948690286Sobrien   (parallel
948790286Sobrien    [(set (match_dup 1)
948890286Sobrien	  (neg:SI (match_dup 1)))
9489169699Skan     (clobber (reg:CC FLAGS_REG))])]
949090286Sobrien  "split_di (operands+1, 1, operands+2, operands+3);
949190286Sobrien   split_di (operands+0, 1, operands+0, operands+1);")
949250650Sobrien
949390286Sobrien(define_insn "*negdi2_1_rex64"
949490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
949590286Sobrien	(neg:DI (match_operand:DI 1 "nonimmediate_operand" "0")))
9496169699Skan   (clobber (reg:CC FLAGS_REG))]
949790286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
949890286Sobrien  "neg{q}\t%0"
949990286Sobrien  [(set_attr "type" "negnot")
950090286Sobrien   (set_attr "mode" "DI")])
950150650Sobrien
950290286Sobrien;; The problem with neg is that it does not perform (compare x 0),
950390286Sobrien;; it really performs (compare 0 x), which leaves us with the zero
950490286Sobrien;; flag being the only useful item.
950550650Sobrien
950690286Sobrien(define_insn "*negdi2_cmpz_rex64"
9507169699Skan  [(set (reg:CCZ FLAGS_REG)
950890286Sobrien	(compare:CCZ (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
950990286Sobrien		     (const_int 0)))
951090286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
951190286Sobrien	(neg:DI (match_dup 1)))]
951290286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
951390286Sobrien  "neg{q}\t%0"
951490286Sobrien  [(set_attr "type" "negnot")
951590286Sobrien   (set_attr "mode" "DI")])
951650650Sobrien
951718334Speter
951890286Sobrien(define_expand "negsi2"
951990286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
952090286Sobrien		   (neg:SI (match_operand:SI 1 "nonimmediate_operand" "")))
9521169699Skan	      (clobber (reg:CC FLAGS_REG))])]
952290286Sobrien  ""
952390286Sobrien  "ix86_expand_unary_operator (NEG, SImode, operands); DONE;")
952418334Speter
952590286Sobrien(define_insn "*negsi2_1"
952690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
952790286Sobrien	(neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))
9528169699Skan   (clobber (reg:CC FLAGS_REG))]
952990286Sobrien  "ix86_unary_operator_ok (NEG, SImode, operands)"
953090286Sobrien  "neg{l}\t%0"
953190286Sobrien  [(set_attr "type" "negnot")
953290286Sobrien   (set_attr "mode" "SI")])
953350650Sobrien
953490286Sobrien;; Combine is quite creative about this pattern.
953590286Sobrien(define_insn "*negsi2_1_zext"
953690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
953790286Sobrien	(lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0")
953890286Sobrien					(const_int 32)))
953990286Sobrien		     (const_int 32)))
9540169699Skan   (clobber (reg:CC FLAGS_REG))]
954190286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
954290286Sobrien  "neg{l}\t%k0"
954390286Sobrien  [(set_attr "type" "negnot")
954490286Sobrien   (set_attr "mode" "SI")])
954550650Sobrien
954690286Sobrien;; The problem with neg is that it does not perform (compare x 0),
954790286Sobrien;; it really performs (compare 0 x), which leaves us with the zero
954890286Sobrien;; flag being the only useful item.
954918334Speter
955090286Sobrien(define_insn "*negsi2_cmpz"
9551169699Skan  [(set (reg:CCZ FLAGS_REG)
955290286Sobrien	(compare:CCZ (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
955390286Sobrien		     (const_int 0)))
955490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
955590286Sobrien	(neg:SI (match_dup 1)))]
955690286Sobrien  "ix86_unary_operator_ok (NEG, SImode, operands)"
955790286Sobrien  "neg{l}\t%0"
955890286Sobrien  [(set_attr "type" "negnot")
955990286Sobrien   (set_attr "mode" "SI")])
956050650Sobrien
956190286Sobrien(define_insn "*negsi2_cmpz_zext"
9562169699Skan  [(set (reg:CCZ FLAGS_REG)
956390286Sobrien	(compare:CCZ (lshiftrt:DI
956490286Sobrien		       (neg:DI (ashift:DI
956590286Sobrien				 (match_operand:DI 1 "register_operand" "0")
956690286Sobrien				 (const_int 32)))
956790286Sobrien		       (const_int 32))
956890286Sobrien		     (const_int 0)))
956990286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
957090286Sobrien	(lshiftrt:DI (neg:DI (ashift:DI (match_dup 1)
957190286Sobrien					(const_int 32)))
957290286Sobrien		     (const_int 32)))]
957390286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
957490286Sobrien  "neg{l}\t%k0"
957590286Sobrien  [(set_attr "type" "negnot")
957690286Sobrien   (set_attr "mode" "SI")])
957790286Sobrien
957890286Sobrien(define_expand "neghi2"
957990286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
958090286Sobrien		   (neg:HI (match_operand:HI 1 "nonimmediate_operand" "")))
9581169699Skan	      (clobber (reg:CC FLAGS_REG))])]
958290286Sobrien  "TARGET_HIMODE_MATH"
958390286Sobrien  "ix86_expand_unary_operator (NEG, HImode, operands); DONE;")
958490286Sobrien
958590286Sobrien(define_insn "*neghi2_1"
958690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
958790286Sobrien	(neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))
9588169699Skan   (clobber (reg:CC FLAGS_REG))]
958990286Sobrien  "ix86_unary_operator_ok (NEG, HImode, operands)"
959090286Sobrien  "neg{w}\t%0"
959190286Sobrien  [(set_attr "type" "negnot")
959290286Sobrien   (set_attr "mode" "HI")])
959390286Sobrien
959490286Sobrien(define_insn "*neghi2_cmpz"
9595169699Skan  [(set (reg:CCZ FLAGS_REG)
959690286Sobrien	(compare:CCZ (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
959790286Sobrien		     (const_int 0)))
959890286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
959990286Sobrien	(neg:HI (match_dup 1)))]
960090286Sobrien  "ix86_unary_operator_ok (NEG, HImode, operands)"
960190286Sobrien  "neg{w}\t%0"
960290286Sobrien  [(set_attr "type" "negnot")
960390286Sobrien   (set_attr "mode" "HI")])
960490286Sobrien
960590286Sobrien(define_expand "negqi2"
960690286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
960790286Sobrien		   (neg:QI (match_operand:QI 1 "nonimmediate_operand" "")))
9608169699Skan	      (clobber (reg:CC FLAGS_REG))])]
960990286Sobrien  "TARGET_QIMODE_MATH"
961090286Sobrien  "ix86_expand_unary_operator (NEG, QImode, operands); DONE;")
961190286Sobrien
961290286Sobrien(define_insn "*negqi2_1"
961390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
961490286Sobrien	(neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))
9615169699Skan   (clobber (reg:CC FLAGS_REG))]
961690286Sobrien  "ix86_unary_operator_ok (NEG, QImode, operands)"
961790286Sobrien  "neg{b}\t%0"
961890286Sobrien  [(set_attr "type" "negnot")
961990286Sobrien   (set_attr "mode" "QI")])
962090286Sobrien
962190286Sobrien(define_insn "*negqi2_cmpz"
9622169699Skan  [(set (reg:CCZ FLAGS_REG)
962390286Sobrien	(compare:CCZ (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
962490286Sobrien		     (const_int 0)))
962590286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
962690286Sobrien	(neg:QI (match_dup 1)))]
962790286Sobrien  "ix86_unary_operator_ok (NEG, QImode, operands)"
962890286Sobrien  "neg{b}\t%0"
962990286Sobrien  [(set_attr "type" "negnot")
963090286Sobrien   (set_attr "mode" "QI")])
963190286Sobrien
963290286Sobrien;; Changing of sign for FP values is doable using integer unit too.
963390286Sobrien
963490286Sobrien(define_expand "negsf2"
9635169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
9636169699Skan	(neg:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
9637146906Skan  "TARGET_80387 || TARGET_SSE_MATH"
9638169699Skan  "ix86_expand_fp_absneg_operator (NEG, SFmode, operands); DONE;")
963918334Speter
9640169699Skan(define_expand "abssf2"
9641169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
9642169699Skan	(abs:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
9643169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
9644169699Skan  "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
964518334Speter
9646169699Skan(define_insn "*absnegsf2_mixed"
9647169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x  ,x,f,rm")
9648169699Skan	(match_operator:SF 3 "absneg_operator"
9649169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0   ,x,0,0 ")]))
9650169699Skan   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm  ,0,X,X "))
9651169699Skan   (clobber (reg:CC FLAGS_REG))]
9652169699Skan  "TARGET_SSE_MATH && TARGET_MIX_SSE_I387
9653169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
965490286Sobrien  "#")
965518334Speter
9656169699Skan(define_insn "*absnegsf2_sse"
9657169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x,x,rm")
9658169699Skan	(match_operator:SF 3 "absneg_operator"
9659169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0")]))
9660169699Skan   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm,0,X"))
9661169699Skan   (clobber (reg:CC FLAGS_REG))]
9662169699Skan  "TARGET_SSE_MATH
9663169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
966490286Sobrien  "#")
966518334Speter
9666169699Skan(define_insn "*absnegsf2_i387"
9667169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,rm")
9668169699Skan	(match_operator:SF 3 "absneg_operator"
9669169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0,0")]))
9670169699Skan   (use (match_operand 2 "" ""))
9671169699Skan   (clobber (reg:CC FLAGS_REG))]
9672169699Skan  "TARGET_80387 && !TARGET_SSE_MATH
9673169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
9674169699Skan  "#")
967590286Sobrien
9676169699Skan(define_expand "copysignsf3"
9677169699Skan  [(match_operand:SF 0 "register_operand" "")
9678169699Skan   (match_operand:SF 1 "nonmemory_operand" "")
9679169699Skan   (match_operand:SF 2 "register_operand" "")]
9680169699Skan  "TARGET_SSE_MATH"
9681169699Skan{
9682169699Skan  ix86_expand_copysign (operands);
9683169699Skan  DONE;
9684169699Skan})
968590286Sobrien
9686169699Skan(define_insn_and_split "copysignsf3_const"
9687169699Skan  [(set (match_operand:SF 0 "register_operand"          "=x")
9688169699Skan	(unspec:SF
9689169699Skan	  [(match_operand:V4SF 1 "vector_move_operand"  "xmC")
9690169699Skan	   (match_operand:SF 2 "register_operand"       "0")
9691169699Skan	   (match_operand:V4SF 3 "nonimmediate_operand" "xm")]
9692169699Skan	  UNSPEC_COPYSIGN))]
9693169699Skan  "TARGET_SSE_MATH"
9694169699Skan  "#"
9695169699Skan  "&& reload_completed"
9696169699Skan  [(const_int 0)]
969718334Speter{
9698169699Skan  ix86_split_copysign_const (operands);
9699169699Skan  DONE;
970090286Sobrien})
970118334Speter
9702169699Skan(define_insn "copysignsf3_var"
9703169699Skan  [(set (match_operand:SF 0 "register_operand"          "=x, x, x, x,x")
9704169699Skan	(unspec:SF
9705169699Skan	  [(match_operand:SF 2 "register_operand"       " x, 0, 0, x,x")
9706169699Skan	   (match_operand:SF 3 "register_operand"       " 1, 1, x, 1,x")
9707169699Skan	   (match_operand:V4SF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
9708169699Skan	   (match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
9709169699Skan	  UNSPEC_COPYSIGN))
9710169699Skan   (clobber (match_scratch:V4SF 1			"=x, x, x, x,x"))]
9711169699Skan  "TARGET_SSE_MATH"
971290286Sobrien  "#")
971318334Speter
971490286Sobrien(define_split
9715169699Skan  [(set (match_operand:SF 0 "register_operand" "")
9716169699Skan	(unspec:SF
9717169699Skan	  [(match_operand:SF 2 "register_operand" "")
9718169699Skan	   (match_operand:SF 3 "register_operand" "")
9719169699Skan	   (match_operand:V4SF 4 "" "")
9720169699Skan	   (match_operand:V4SF 5 "" "")]
9721169699Skan	  UNSPEC_COPYSIGN))
9722169699Skan   (clobber (match_scratch:V4SF 1 ""))]
9723169699Skan  "TARGET_SSE_MATH && reload_completed"
9724169699Skan  [(const_int 0)]
972590286Sobrien{
9726169699Skan  ix86_split_copysign_var (operands);
9727169699Skan  DONE;
972890286Sobrien})
972990286Sobrien
973090286Sobrien(define_expand "negdf2"
9731169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "")
9732169699Skan	(neg:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
9733146906Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
9734169699Skan  "ix86_expand_fp_absneg_operator (NEG, DFmode, operands); DONE;")
973518334Speter
9736169699Skan(define_expand "absdf2"
9737169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "")
9738169699Skan	(abs:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
9739169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
9740169699Skan  "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
974118334Speter
9742169699Skan(define_insn "*absnegdf2_mixed"
9743169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,f,rm")
9744169699Skan	(match_operator:DF 3 "absneg_operator"
9745169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0,0")]))
9746169699Skan   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X,X"))
9747169699Skan   (clobber (reg:CC FLAGS_REG))]
9748169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
9749169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
975090286Sobrien  "#")
975150650Sobrien
9752169699Skan(define_insn "*absnegdf2_sse"
9753169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,rm")
9754169699Skan	(match_operator:DF 3 "absneg_operator"
9755169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0 ")]))
9756169699Skan   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X "))
9757169699Skan   (clobber (reg:CC FLAGS_REG))]
9758169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
9759169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
976090286Sobrien  "#")
976150650Sobrien
9762169699Skan(define_insn "*absnegdf2_i387"
9763169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,rm")
9764169699Skan	(match_operator:DF 3 "absneg_operator"
9765169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0,0")]))
9766169699Skan   (use (match_operand 2 "" ""))
9767169699Skan   (clobber (reg:CC FLAGS_REG))]
9768169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
9769169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
977090286Sobrien  "#")
977118334Speter
9772169699Skan(define_expand "copysigndf3"
9773169699Skan  [(match_operand:DF 0 "register_operand" "")
9774169699Skan   (match_operand:DF 1 "nonmemory_operand" "")
9775169699Skan   (match_operand:DF 2 "register_operand" "")]
9776169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9777169699Skan{
9778169699Skan  ix86_expand_copysign (operands);
9779169699Skan  DONE;
9780169699Skan})
978150650Sobrien
9782169699Skan(define_insn_and_split "copysigndf3_const"
9783169699Skan  [(set (match_operand:DF 0 "register_operand"          "=x")
9784169699Skan	(unspec:DF
9785169699Skan	  [(match_operand:V2DF 1 "vector_move_operand"  "xmC")
9786169699Skan	   (match_operand:DF 2 "register_operand"       "0")
9787169699Skan	   (match_operand:V2DF 3 "nonimmediate_operand" "xm")]
9788169699Skan	  UNSPEC_COPYSIGN))]
9789169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9790169699Skan  "#"
9791169699Skan  "&& reload_completed"
9792169699Skan  [(const_int 0)]
9793169699Skan{
9794169699Skan  ix86_split_copysign_const (operands);
9795169699Skan  DONE;
9796169699Skan})
979750650Sobrien
9798169699Skan(define_insn "copysigndf3_var"
9799169699Skan  [(set (match_operand:DF 0 "register_operand"          "=x, x, x, x,x")
9800169699Skan	(unspec:DF
9801169699Skan	  [(match_operand:DF 2 "register_operand"       " x, 0, 0, x,x")
9802169699Skan	   (match_operand:DF 3 "register_operand"       " 1, 1, x, 1,x")
9803169699Skan	   (match_operand:V2DF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
9804169699Skan	   (match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
9805169699Skan	  UNSPEC_COPYSIGN))
9806169699Skan   (clobber (match_scratch:V2DF 1			"=x, x, x, x,x"))]
9807169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9808169699Skan  "#")
980952296Sobrien
981090286Sobrien(define_split
981190286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
9812169699Skan	(unspec:DF
9813169699Skan	  [(match_operand:DF 2 "register_operand" "")
9814169699Skan	   (match_operand:DF 3 "register_operand" "")
9815169699Skan	   (match_operand:V2DF 4 "" "")
9816169699Skan	   (match_operand:V2DF 5 "" "")]
9817169699Skan	  UNSPEC_COPYSIGN))
9818169699Skan   (clobber (match_scratch:V2DF 1 ""))]
9819169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
9820169699Skan  [(const_int 0)]
982190286Sobrien{
9822169699Skan  ix86_split_copysign_var (operands);
9823169699Skan  DONE;
982490286Sobrien})
982552296Sobrien
982690286Sobrien(define_expand "negxf2"
9827169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "")
9828169699Skan	(neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
9829132727Skan  "TARGET_80387"
9830169699Skan  "ix86_expand_fp_absneg_operator (NEG, XFmode, operands); DONE;")
983118334Speter
9832169699Skan(define_expand "absxf2"
9833169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "")
9834169699Skan	(abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
983518334Speter  "TARGET_80387"
9836169699Skan  "ix86_expand_fp_absneg_operator (ABS, XFmode, operands); DONE;")
983718334Speter
9838169699Skan(define_insn "*absnegxf2_i387"
9839169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,?rm")
9840169699Skan	(match_operator:XF 3 "absneg_operator"
9841169699Skan	  [(match_operand:XF 1 "nonimmediate_operand" "0,0")]))
9842169699Skan   (use (match_operand 2 "" ""))
9843169699Skan   (clobber (reg:CC FLAGS_REG))]
9844169699Skan  "TARGET_80387
9845169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), XFmode, operands)"
984690286Sobrien  "#")
984790286Sobrien
9848169699Skan;; Splitters for fp abs and neg.
984990286Sobrien
985090286Sobrien(define_split
9851169699Skan  [(set (match_operand 0 "fp_register_operand" "")
9852169699Skan	(match_operator 1 "absneg_operator" [(match_dup 0)]))
9853169699Skan   (use (match_operand 2 "" ""))
9854169699Skan   (clobber (reg:CC FLAGS_REG))]
9855169699Skan  "reload_completed"
9856169699Skan  [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))])
985790286Sobrien
985890286Sobrien(define_split
9859169699Skan  [(set (match_operand 0 "register_operand" "")
9860169699Skan	(match_operator 3 "absneg_operator"
9861169699Skan	  [(match_operand 1 "register_operand" "")]))
9862169699Skan   (use (match_operand 2 "nonimmediate_operand" ""))
9863169699Skan   (clobber (reg:CC FLAGS_REG))]
986490286Sobrien  "reload_completed && SSE_REG_P (operands[0])"
9865169699Skan  [(set (match_dup 0) (match_dup 3))]
9866132727Skan{
9867169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
9868169699Skan  enum machine_mode vmode = GET_MODE (operands[2]);
9869169699Skan  rtx tmp;
9870259563Spfg
9871169699Skan  operands[0] = simplify_gen_subreg (vmode, operands[0], mode, 0);
9872169699Skan  operands[1] = simplify_gen_subreg (vmode, operands[1], mode, 0);
9873132727Skan  if (operands_match_p (operands[0], operands[2]))
9874132727Skan    {
9875132727Skan      tmp = operands[1];
9876132727Skan      operands[1] = operands[2];
9877132727Skan      operands[2] = tmp;
9878132727Skan    }
9879169699Skan  if (GET_CODE (operands[3]) == ABS)
9880169699Skan    tmp = gen_rtx_AND (vmode, operands[1], operands[2]);
9881169699Skan  else
9882169699Skan    tmp = gen_rtx_XOR (vmode, operands[1], operands[2]);
9883169699Skan  operands[3] = tmp;
9884132727Skan})
988590286Sobrien
988690286Sobrien(define_split
9887169699Skan  [(set (match_operand:SF 0 "register_operand" "")
9888169699Skan	(match_operator:SF 1 "absneg_operator" [(match_dup 0)]))
9889169699Skan   (use (match_operand:V4SF 2 "" ""))
9890169699Skan   (clobber (reg:CC FLAGS_REG))]
9891169699Skan  "reload_completed"
9892169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9893169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9894259563Spfg{
9895169699Skan  rtx tmp;
9896169699Skan  operands[0] = gen_lowpart (SImode, operands[0]);
9897169699Skan  if (GET_CODE (operands[1]) == ABS)
9898169699Skan    {
9899169699Skan      tmp = gen_int_mode (0x7fffffff, SImode);
9900169699Skan      tmp = gen_rtx_AND (SImode, operands[0], tmp);
9901169699Skan    }
9902169699Skan  else
9903169699Skan    {
9904169699Skan      tmp = gen_int_mode (0x80000000, SImode);
9905169699Skan      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9906169699Skan    }
9907169699Skan  operands[1] = tmp;
9908169699Skan})
990990286Sobrien
991090286Sobrien(define_split
9911169699Skan  [(set (match_operand:DF 0 "register_operand" "")
9912169699Skan	(match_operator:DF 1 "absneg_operator" [(match_dup 0)]))
9913169699Skan   (use (match_operand 2 "" ""))
9914169699Skan   (clobber (reg:CC FLAGS_REG))]
9915169699Skan  "reload_completed"
9916169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9917169699Skan	      (clobber (reg:CC FLAGS_REG))])]
991890286Sobrien{
9919169699Skan  rtx tmp;
9920169699Skan  if (TARGET_64BIT)
9921169699Skan    {
9922169699Skan      tmp = gen_lowpart (DImode, operands[0]);
9923169699Skan      tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63));
9924169699Skan      operands[0] = tmp;
992590286Sobrien
9926169699Skan      if (GET_CODE (operands[1]) == ABS)
9927169699Skan	tmp = const0_rtx;
9928169699Skan      else
9929169699Skan	tmp = gen_rtx_NOT (DImode, tmp);
9930169699Skan    }
9931169699Skan  else
9932169699Skan    {
9933169699Skan      operands[0] = gen_highpart (SImode, operands[0]);
9934169699Skan      if (GET_CODE (operands[1]) == ABS)
993590286Sobrien	{
9936169699Skan	  tmp = gen_int_mode (0x7fffffff, SImode);
9937169699Skan	  tmp = gen_rtx_AND (SImode, operands[0], tmp);
993890286Sobrien	}
9939169699Skan      else
9940169699Skan	{
9941169699Skan	  tmp = gen_int_mode (0x80000000, SImode);
9942169699Skan	  tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9943169699Skan	}
9944169699Skan    }
9945169699Skan  operands[1] = tmp;
9946169699Skan})
994790286Sobrien
994890286Sobrien(define_split
9949169699Skan  [(set (match_operand:XF 0 "register_operand" "")
9950169699Skan	(match_operator:XF 1 "absneg_operator" [(match_dup 0)]))
9951169699Skan   (use (match_operand 2 "" ""))
9952169699Skan   (clobber (reg:CC FLAGS_REG))]
9953169699Skan  "reload_completed"
9954169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9955169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9956169699Skan{
9957169699Skan  rtx tmp;
9958169699Skan  operands[0] = gen_rtx_REG (SImode,
9959169699Skan			     true_regnum (operands[0])
9960169699Skan			     + (TARGET_64BIT ? 1 : 2));
9961169699Skan  if (GET_CODE (operands[1]) == ABS)
9962169699Skan    {
9963169699Skan      tmp = GEN_INT (0x7fff);
9964169699Skan      tmp = gen_rtx_AND (SImode, operands[0], tmp);
9965169699Skan    }
9966169699Skan  else
9967169699Skan    {
9968169699Skan      tmp = GEN_INT (0x8000);
9969169699Skan      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9970169699Skan    }
9971169699Skan  operands[1] = tmp;
9972169699Skan})
997390286Sobrien
997490286Sobrien(define_split
9975169699Skan  [(set (match_operand 0 "memory_operand" "")
9976169699Skan	(match_operator 1 "absneg_operator" [(match_dup 0)]))
9977169699Skan   (use (match_operand 2 "" ""))
9978169699Skan   (clobber (reg:CC FLAGS_REG))]
9979169699Skan  "reload_completed"
9980169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9981169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9982169699Skan{
9983169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
9984169699Skan  int size = mode == XFmode ? 10 : GET_MODE_SIZE (mode);
9985169699Skan  rtx tmp;
998690286Sobrien
9987169699Skan  operands[0] = adjust_address (operands[0], QImode, size - 1);
9988169699Skan  if (GET_CODE (operands[1]) == ABS)
9989132727Skan    {
9990169699Skan      tmp = gen_int_mode (0x7f, QImode);
9991169699Skan      tmp = gen_rtx_AND (QImode, operands[0], tmp);
9992132727Skan    }
9993169699Skan  else
9994169699Skan    {
9995169699Skan      tmp = gen_int_mode (0x80, QImode);
9996169699Skan      tmp = gen_rtx_XOR (QImode, operands[0], tmp);
9997169699Skan    }
9998169699Skan  operands[1] = tmp;
9999132727Skan})
1000090286Sobrien
10001259563Spfg;; Conditionalize these after reload. If they match before reload, we
10002169699Skan;; lose the clobber and ability to use integer instructions.
1000390286Sobrien
10004169699Skan(define_insn "*negsf2_1"
10005169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
10006169699Skan	(neg:SF (match_operand:SF 1 "register_operand" "0")))]
10007169699Skan  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
10008169699Skan  "fchs"
10009169699Skan  [(set_attr "type" "fsgn")
10010169699Skan   (set_attr "mode" "SF")])
1001190286Sobrien
10012169699Skan(define_insn "*negdf2_1"
10013169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
10014169699Skan	(neg:DF (match_operand:DF 1 "register_operand" "0")))]
10015169699Skan  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
10016169699Skan  "fchs"
10017169699Skan  [(set_attr "type" "fsgn")
10018169699Skan   (set_attr "mode" "DF")])
1001990286Sobrien
10020169699Skan(define_insn "*negxf2_1"
10021169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
10022169699Skan	(neg:XF (match_operand:XF 1 "register_operand" "0")))]
10023132727Skan  "TARGET_80387"
10024169699Skan  "fchs"
10025169699Skan  [(set_attr "type" "fsgn")
10026169699Skan   (set_attr "mode" "XF")])
1002790286Sobrien
1002890286Sobrien(define_insn "*abssf2_1"
1002918334Speter  [(set (match_operand:SF 0 "register_operand" "=f")
1003050650Sobrien	(abs:SF (match_operand:SF 1 "register_operand" "0")))]
10031169699Skan  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
1003250650Sobrien  "fabs"
1003390286Sobrien  [(set_attr "type" "fsgn")
1003490286Sobrien   (set_attr "mode" "SF")])
1003518334Speter
1003690286Sobrien(define_insn "*absdf2_1"
1003718334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
1003850650Sobrien	(abs:DF (match_operand:DF 1 "register_operand" "0")))]
10039169699Skan  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
1004050650Sobrien  "fabs"
1004190286Sobrien  [(set_attr "type" "fsgn")
1004290286Sobrien   (set_attr "mode" "DF")])
1004318334Speter
10044169699Skan(define_insn "*absxf2_1"
10045169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
10046169699Skan	(abs:XF (match_operand:XF 1 "register_operand" "0")))]
1004718334Speter  "TARGET_80387"
1004850650Sobrien  "fabs"
1004990286Sobrien  [(set_attr "type" "fsgn")
1005090286Sobrien   (set_attr "mode" "DF")])
1005118334Speter
10052169699Skan(define_insn "*negextendsfdf2"
10053169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
10054169699Skan	(neg:DF (float_extend:DF
10055169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
10056169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
10057169699Skan  "fchs"
10058169699Skan  [(set_attr "type" "fsgn")
10059169699Skan   (set_attr "mode" "DF")])
10060169699Skan
10061169699Skan(define_insn "*negextenddfxf2"
1006218334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
10063169699Skan	(neg:XF (float_extend:XF
10064169699Skan		  (match_operand:DF 1 "register_operand" "0"))))]
10065169699Skan  "TARGET_80387"
10066169699Skan  "fchs"
10067169699Skan  [(set_attr "type" "fsgn")
10068169699Skan   (set_attr "mode" "XF")])
10069169699Skan
10070169699Skan(define_insn "*negextendsfxf2"
10071169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
10072169699Skan	(neg:XF (float_extend:XF
10073169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
10074169699Skan  "TARGET_80387"
10075169699Skan  "fchs"
10076169699Skan  [(set_attr "type" "fsgn")
10077169699Skan   (set_attr "mode" "XF")])
10078169699Skan
10079169699Skan(define_insn "*absextendsfdf2"
10080169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
10081169699Skan	(abs:DF (float_extend:DF
10082169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
10083169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
1008450650Sobrien  "fabs"
1008590286Sobrien  [(set_attr "type" "fsgn")
1008690286Sobrien   (set_attr "mode" "DF")])
1008718334Speter
1008890286Sobrien(define_insn "*absextenddfxf2"
1008918334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
1009090286Sobrien	(abs:XF (float_extend:XF
1009190286Sobrien	  (match_operand:DF 1 "register_operand" "0"))))]
10092132727Skan  "TARGET_80387"
1009350650Sobrien  "fabs"
1009490286Sobrien  [(set_attr "type" "fsgn")
1009590286Sobrien   (set_attr "mode" "XF")])
1009618334Speter
1009790286Sobrien(define_insn "*absextendsfxf2"
1009890286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1009990286Sobrien	(abs:XF (float_extend:XF
1010090286Sobrien	  (match_operand:SF 1 "register_operand" "0"))))]
1010190286Sobrien  "TARGET_80387"
1010290286Sobrien  "fabs"
1010390286Sobrien  [(set_attr "type" "fsgn")
1010490286Sobrien   (set_attr "mode" "XF")])
1010590286Sobrien
1010690286Sobrien;; One complement instructions
1010718334Speter
1010890286Sobrien(define_expand "one_cmpldi2"
1010990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
1011090286Sobrien	(not:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
1011190286Sobrien  "TARGET_64BIT"
1011290286Sobrien  "ix86_expand_unary_operator (NOT, DImode, operands); DONE;")
1011318334Speter
1011490286Sobrien(define_insn "*one_cmpldi2_1_rex64"
1011590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1011690286Sobrien	(not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
1011790286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NOT, DImode, operands)"
1011890286Sobrien  "not{q}\t%0"
1011990286Sobrien  [(set_attr "type" "negnot")
1012090286Sobrien   (set_attr "mode" "DI")])
1012118334Speter
1012290286Sobrien(define_insn "*one_cmpldi2_2_rex64"
10123169699Skan  [(set (reg FLAGS_REG)
1012490286Sobrien	(compare (not:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
1012590286Sobrien		 (const_int 0)))
1012690286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1012790286Sobrien	(not:DI (match_dup 1)))]
1012890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
1012990286Sobrien   && ix86_unary_operator_ok (NOT, DImode, operands)"
1013090286Sobrien  "#"
1013190286Sobrien  [(set_attr "type" "alu1")
1013290286Sobrien   (set_attr "mode" "DI")])
1013318334Speter
1013490286Sobrien(define_split
10135146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10136146906Skan	(match_operator 2 "compare_operator"
10137146906Skan	  [(not:DI (match_operand:DI 3 "nonimmediate_operand" ""))
10138146906Skan	   (const_int 0)]))
10139146906Skan   (set (match_operand:DI 1 "nonimmediate_operand" "")
10140146906Skan	(not:DI (match_dup 3)))]
1014190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
10142146906Skan  [(parallel [(set (match_dup 0)
10143146906Skan		   (match_op_dup 2
10144146906Skan		     [(xor:DI (match_dup 3) (const_int -1))
10145146906Skan		      (const_int 0)]))
10146146906Skan	      (set (match_dup 1)
10147146906Skan		   (xor:DI (match_dup 3) (const_int -1)))])]
1014890286Sobrien  "")
1014918334Speter
1015090286Sobrien(define_expand "one_cmplsi2"
1015190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1015290286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
1015390286Sobrien  ""
1015490286Sobrien  "ix86_expand_unary_operator (NOT, SImode, operands); DONE;")
1015518334Speter
1015690286Sobrien(define_insn "*one_cmplsi2_1"
1015790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1015890286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
1015990286Sobrien  "ix86_unary_operator_ok (NOT, SImode, operands)"
1016090286Sobrien  "not{l}\t%0"
1016190286Sobrien  [(set_attr "type" "negnot")
1016290286Sobrien   (set_attr "mode" "SI")])
1016318334Speter
1016490286Sobrien;; ??? Currently never generated - xor is used instead.
1016590286Sobrien(define_insn "*one_cmplsi2_1_zext"
1016690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1016790286Sobrien	(zero_extend:DI (not:SI (match_operand:SI 1 "register_operand" "0"))))]
1016890286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NOT, SImode, operands)"
1016990286Sobrien  "not{l}\t%k0"
1017090286Sobrien  [(set_attr "type" "negnot")
1017190286Sobrien   (set_attr "mode" "SI")])
1017218334Speter
1017390286Sobrien(define_insn "*one_cmplsi2_2"
10174169699Skan  [(set (reg FLAGS_REG)
1017590286Sobrien	(compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
1017690286Sobrien		 (const_int 0)))
1017790286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1017890286Sobrien	(not:SI (match_dup 1)))]
1017990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1018090286Sobrien   && ix86_unary_operator_ok (NOT, SImode, operands)"
1018190286Sobrien  "#"
1018290286Sobrien  [(set_attr "type" "alu1")
1018390286Sobrien   (set_attr "mode" "SI")])
1018418334Speter
1018590286Sobrien(define_split
10186146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10187146906Skan	(match_operator 2 "compare_operator"
10188146906Skan	  [(not:SI (match_operand:SI 3 "nonimmediate_operand" ""))
10189146906Skan	   (const_int 0)]))
10190146906Skan   (set (match_operand:SI 1 "nonimmediate_operand" "")
10191146906Skan	(not:SI (match_dup 3)))]
1019290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10193146906Skan  [(parallel [(set (match_dup 0)
10194146906Skan		   (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
10195146906Skan				    (const_int 0)]))
10196146906Skan	      (set (match_dup 1)
10197146906Skan		   (xor:SI (match_dup 3) (const_int -1)))])]
1019890286Sobrien  "")
1019918334Speter
1020090286Sobrien;; ??? Currently never generated - xor is used instead.
1020190286Sobrien(define_insn "*one_cmplsi2_2_zext"
10202169699Skan  [(set (reg FLAGS_REG)
1020390286Sobrien	(compare (not:SI (match_operand:SI 1 "register_operand" "0"))
1020490286Sobrien		 (const_int 0)))
1020590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1020690286Sobrien	(zero_extend:DI (not:SI (match_dup 1))))]
1020790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
1020890286Sobrien   && ix86_unary_operator_ok (NOT, SImode, operands)"
1020990286Sobrien  "#"
1021090286Sobrien  [(set_attr "type" "alu1")
1021190286Sobrien   (set_attr "mode" "SI")])
1021218334Speter
1021390286Sobrien(define_split
10214146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10215146906Skan	(match_operator 2 "compare_operator"
10216146906Skan	  [(not:SI (match_operand:SI 3 "register_operand" ""))
10217146906Skan	   (const_int 0)]))
10218146906Skan   (set (match_operand:DI 1 "register_operand" "")
10219146906Skan	(zero_extend:DI (not:SI (match_dup 3))))]
1022090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10221146906Skan  [(parallel [(set (match_dup 0)
10222146906Skan		   (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
10223146906Skan				    (const_int 0)]))
10224146906Skan	      (set (match_dup 1)
10225146906Skan		   (zero_extend:DI (xor:SI (match_dup 3) (const_int -1))))])]
1022690286Sobrien  "")
1022718334Speter
1022890286Sobrien(define_expand "one_cmplhi2"
1022990286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1023090286Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
1023190286Sobrien  "TARGET_HIMODE_MATH"
1023290286Sobrien  "ix86_expand_unary_operator (NOT, HImode, operands); DONE;")
1023352296Sobrien
1023490286Sobrien(define_insn "*one_cmplhi2_1"
1023550650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1023650650Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
1023790286Sobrien  "ix86_unary_operator_ok (NOT, HImode, operands)"
1023890286Sobrien  "not{w}\t%0"
1023990286Sobrien  [(set_attr "type" "negnot")
1024090286Sobrien   (set_attr "mode" "HI")])
1024118334Speter
1024290286Sobrien(define_insn "*one_cmplhi2_2"
10243169699Skan  [(set (reg FLAGS_REG)
1024490286Sobrien	(compare (not:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
1024590286Sobrien		 (const_int 0)))
1024690286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1024790286Sobrien	(not:HI (match_dup 1)))]
1024890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1024990286Sobrien   && ix86_unary_operator_ok (NEG, HImode, operands)"
1025090286Sobrien  "#"
1025190286Sobrien  [(set_attr "type" "alu1")
1025290286Sobrien   (set_attr "mode" "HI")])
1025352296Sobrien
1025490286Sobrien(define_split
10255146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10256146906Skan	(match_operator 2 "compare_operator"
10257146906Skan	  [(not:HI (match_operand:HI 3 "nonimmediate_operand" ""))
10258146906Skan	   (const_int 0)]))
10259146906Skan   (set (match_operand:HI 1 "nonimmediate_operand" "")
10260146906Skan	(not:HI (match_dup 3)))]
1026190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10262146906Skan  [(parallel [(set (match_dup 0)
10263146906Skan		   (match_op_dup 2 [(xor:HI (match_dup 3) (const_int -1))
10264146906Skan		      		    (const_int 0)]))
10265146906Skan	      (set (match_dup 1)
10266146906Skan		   (xor:HI (match_dup 3) (const_int -1)))])]
1026790286Sobrien  "")
1026852296Sobrien
1026990286Sobrien;; %%% Potential partial reg stall on alternative 1.  What to do?
1027090286Sobrien(define_expand "one_cmplqi2"
1027190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1027290286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
1027390286Sobrien  "TARGET_QIMODE_MATH"
1027490286Sobrien  "ix86_expand_unary_operator (NOT, QImode, operands); DONE;")
1027590286Sobrien
1027690286Sobrien(define_insn "*one_cmplqi2_1"
1027790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
1027890286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))]
1027990286Sobrien  "ix86_unary_operator_ok (NOT, QImode, operands)"
1028090286Sobrien  "@
1028190286Sobrien   not{b}\t%0
1028290286Sobrien   not{l}\t%k0"
1028390286Sobrien  [(set_attr "type" "negnot")
1028490286Sobrien   (set_attr "mode" "QI,SI")])
1028590286Sobrien
1028690286Sobrien(define_insn "*one_cmplqi2_2"
10287169699Skan  [(set (reg FLAGS_REG)
1028890286Sobrien	(compare (not:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
1028990286Sobrien		 (const_int 0)))
1029090286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1029190286Sobrien	(not:QI (match_dup 1)))]
1029290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1029390286Sobrien   && ix86_unary_operator_ok (NOT, QImode, operands)"
1029490286Sobrien  "#"
1029590286Sobrien  [(set_attr "type" "alu1")
1029690286Sobrien   (set_attr "mode" "QI")])
1029790286Sobrien
1029890286Sobrien(define_split
10299146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10300146906Skan	(match_operator 2 "compare_operator"
10301146906Skan	  [(not:QI (match_operand:QI 3 "nonimmediate_operand" ""))
10302146906Skan	   (const_int 0)]))
10303146906Skan   (set (match_operand:QI 1 "nonimmediate_operand" "")
10304146906Skan	(not:QI (match_dup 3)))]
1030590286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10306146906Skan  [(parallel [(set (match_dup 0)
10307146906Skan		   (match_op_dup 2 [(xor:QI (match_dup 3) (const_int -1))
10308146906Skan		      		    (const_int 0)]))
10309146906Skan	      (set (match_dup 1)
10310146906Skan		   (xor:QI (match_dup 3) (const_int -1)))])]
1031190286Sobrien  "")
1031218334Speter
1031390286Sobrien;; Arithmetic shift instructions
1031418334Speter
1031518334Speter;; DImode shifts are implemented using the i386 "shift double" opcode,
1031618334Speter;; which is written as "sh[lr]d[lw] imm,reg,reg/mem".  If the shift count
1031718334Speter;; is variable, then the count is in %cl and the "imm" operand is dropped
1031818334Speter;; from the assembler input.
1031990286Sobrien;;
1032018334Speter;; This instruction shifts the target reg/mem as usual, but instead of
1032118334Speter;; shifting in zeros, bits are shifted in from reg operand.  If the insn
1032218334Speter;; is a left shift double, bits are taken from the high order bits of
1032318334Speter;; reg, else if the insn is a shift right double, bits are taken from the
1032418334Speter;; low order bits of reg.  So if %eax is "1234" and %edx is "5678",
1032518334Speter;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
1032690286Sobrien;;
1032718334Speter;; Since sh[lr]d does not change the `reg' operand, that is done
1032818334Speter;; separately, making all shifts emit pairs of shift double and normal
1032918334Speter;; shift.  Since sh[lr]d does not shift more than 31 bits, and we wish to
1033018334Speter;; support a 63 bit shift, each shift where the count is in a reg expands
1033150650Sobrien;; to a pair of shifts, a branch, a shift by 32 and a label.
1033290286Sobrien;;
1033318334Speter;; If the shift count is a constant, we need never emit more than one
1033418334Speter;; shift pair, instead using moves and sign extension for counts greater
1033518334Speter;; than 31.
1033618334Speter
10337169699Skan(define_expand "ashlti3"
10338169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
10339169699Skan		   (ashift:TI (match_operand:TI 1 "register_operand" "")
1034090286Sobrien			      (match_operand:QI 2 "nonmemory_operand" "")))
10341169699Skan	      (clobber (reg:CC FLAGS_REG))])]
10342169699Skan  "TARGET_64BIT"
1034318334Speter{
10344169699Skan  if (! immediate_operand (operands[2], QImode))
1034518334Speter    {
10346169699Skan      emit_insn (gen_ashlti3_1 (operands[0], operands[1], operands[2]));
1034790286Sobrien      DONE;
1034818334Speter    }
10349169699Skan  ix86_expand_binary_operator (ASHIFT, TImode, operands);
1035018334Speter  DONE;
1035190286Sobrien})
1035218334Speter
10353169699Skan(define_insn "ashlti3_1"
10354169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
10355169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "0")
10356169699Skan		   (match_operand:QI 2 "register_operand" "c")))
10357169699Skan   (clobber (match_scratch:DI 3 "=&r"))
10358169699Skan   (clobber (reg:CC FLAGS_REG))]
10359169699Skan  "TARGET_64BIT"
10360169699Skan  "#"
10361169699Skan  [(set_attr "type" "multi")])
10362169699Skan
10363169699Skan(define_insn "*ashlti3_2"
10364169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
10365169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "0")
10366169699Skan		   (match_operand:QI 2 "immediate_operand" "O")))
10367169699Skan   (clobber (reg:CC FLAGS_REG))]
10368169699Skan  "TARGET_64BIT"
10369169699Skan  "#"
10370169699Skan  [(set_attr "type" "multi")])
10371169699Skan
10372169699Skan(define_split
10373169699Skan  [(set (match_operand:TI 0 "register_operand" "")
10374169699Skan	(ashift:TI (match_operand:TI 1 "nonmemory_operand" "")
10375169699Skan		   (match_operand:QI 2 "register_operand" "")))
10376169699Skan   (clobber (match_scratch:DI 3 ""))
10377169699Skan   (clobber (reg:CC FLAGS_REG))]
10378169699Skan  "TARGET_64BIT && reload_completed"
10379169699Skan  [(const_int 0)]
10380169699Skan  "ix86_split_ashl (operands, operands[3], TImode); DONE;")
10381169699Skan
10382169699Skan(define_split
10383169699Skan  [(set (match_operand:TI 0 "register_operand" "")
10384169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "")
10385169699Skan		   (match_operand:QI 2 "immediate_operand" "")))
10386169699Skan   (clobber (reg:CC FLAGS_REG))]
10387169699Skan  "TARGET_64BIT && reload_completed"
10388169699Skan  [(const_int 0)]
10389169699Skan  "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;")
10390169699Skan
10391169699Skan(define_insn "x86_64_shld"
10392169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
10393169699Skan        (ior:DI (ashift:DI (match_dup 0)
10394169699Skan		  (match_operand:QI 2 "nonmemory_operand" "J,c"))
10395169699Skan		(lshiftrt:DI (match_operand:DI 1 "register_operand" "r,r")
10396169699Skan		  (minus:QI (const_int 64) (match_dup 2)))))
10397169699Skan   (clobber (reg:CC FLAGS_REG))]
10398169699Skan  "TARGET_64BIT"
10399169699Skan  "@
10400169699Skan   shld{q}\t{%2, %1, %0|%0, %1, %2}
10401169699Skan   shld{q}\t{%s2%1, %0|%0, %1, %2}"
10402169699Skan  [(set_attr "type" "ishift")
10403169699Skan   (set_attr "prefix_0f" "1")
10404169699Skan   (set_attr "mode" "DI")
10405251212Spfg   (set_attr "athlon_decode" "vector")
10406251212Spfg   (set_attr "amdfam10_decode" "vector")])   
10407169699Skan
10408169699Skan(define_expand "x86_64_shift_adj"
10409169699Skan  [(set (reg:CCZ FLAGS_REG)
10410169699Skan	(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
10411169699Skan			     (const_int 64))
10412169699Skan		     (const_int 0)))
10413169699Skan   (set (match_operand:DI 0 "register_operand" "")
10414169699Skan        (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
10415169699Skan			 (match_operand:DI 1 "register_operand" "")
10416169699Skan			 (match_dup 0)))
10417169699Skan   (set (match_dup 1)
10418169699Skan	(if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
10419169699Skan			 (match_operand:DI 3 "register_operand" "r")
10420169699Skan			 (match_dup 1)))]
10421169699Skan  "TARGET_64BIT"
10422169699Skan  "")
10423169699Skan
10424169699Skan(define_expand "ashldi3"
10425169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
10426169699Skan	(ashift:DI (match_operand:DI 1 "ashldi_input_operand" "")
10427169699Skan		   (match_operand:QI 2 "nonmemory_operand" "")))]
10428169699Skan  ""
10429169699Skan  "ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;")
10430169699Skan
1043190286Sobrien(define_insn "*ashldi3_1_rex64"
1043290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
10433169699Skan	(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,l")
1043490286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cJ,M")))
10435169699Skan   (clobber (reg:CC FLAGS_REG))]
1043690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
1043718334Speter{
1043890286Sobrien  switch (get_attr_type (insn))
1043990286Sobrien    {
1044090286Sobrien    case TYPE_ALU:
10441169699Skan      gcc_assert (operands[2] == const1_rtx);
10442169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
1044390286Sobrien      return "add{q}\t{%0, %0|%0, %0}";
1044418334Speter
1044590286Sobrien    case TYPE_LEA:
10446169699Skan      gcc_assert (GET_CODE (operands[2]) == CONST_INT);
10447169699Skan      gcc_assert ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) <= 3);
1044890286Sobrien      operands[1] = gen_rtx_MULT (DImode, operands[1],
1044990286Sobrien				  GEN_INT (1 << INTVAL (operands[2])));
1045090286Sobrien      return "lea{q}\t{%a1, %0|%0, %a1}";
1045118334Speter
1045290286Sobrien    default:
1045390286Sobrien      if (REG_P (operands[2]))
1045490286Sobrien	return "sal{q}\t{%b2, %0|%0, %b2}";
10455169699Skan      else if (operands[2] == const1_rtx
10456117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1045790286Sobrien	return "sal{q}\t%0";
1045890286Sobrien      else
1045990286Sobrien	return "sal{q}\t{%2, %0|%0, %2}";
1046090286Sobrien    }
1046190286Sobrien}
1046290286Sobrien  [(set (attr "type")
1046390286Sobrien     (cond [(eq_attr "alternative" "1")
1046490286Sobrien	      (const_string "lea")
1046590286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1046690286Sobrien		          (const_int 0))
1046790286Sobrien		      (match_operand 0 "register_operand" ""))
1046890286Sobrien		 (match_operand 2 "const1_operand" ""))
1046990286Sobrien	      (const_string "alu")
1047090286Sobrien	   ]
1047190286Sobrien	   (const_string "ishift")))
1047290286Sobrien   (set_attr "mode" "DI")])
1047318334Speter
1047490286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1047590286Sobrien(define_split
1047690286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
10477169699Skan	(ashift:DI (match_operand:DI 1 "index_register_operand" "")
1047890286Sobrien		   (match_operand:QI 2 "immediate_operand" "")))
10479169699Skan   (clobber (reg:CC FLAGS_REG))]
1048090286Sobrien  "TARGET_64BIT && reload_completed
1048190286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
1048290286Sobrien  [(set (match_dup 0)
1048390286Sobrien	(mult:DI (match_dup 1)
1048490286Sobrien		 (match_dup 2)))]
10485117404Skan  "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);")
1048690286Sobrien
1048790286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1048890286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1048990286Sobrien;; zero are optimized away.
1049090286Sobrien(define_insn "*ashldi3_cmp_rex64"
10491169699Skan  [(set (reg FLAGS_REG)
1049290286Sobrien	(compare
1049390286Sobrien	  (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1049490286Sobrien		     (match_operand:QI 2 "immediate_operand" "e"))
1049590286Sobrien	  (const_int 0)))
1049690286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1049790286Sobrien	(ashift:DI (match_dup 1) (match_dup 2)))]
1049890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10499169699Skan   && ix86_binary_operator_ok (ASHIFT, DImode, operands)
10500169699Skan   && (optimize_size
10501169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10502169699Skan       || (operands[2] == const1_rtx
10503169699Skan	   && (TARGET_SHIFT1
10504169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1050590286Sobrien{
1050690286Sobrien  switch (get_attr_type (insn))
1050718334Speter    {
1050890286Sobrien    case TYPE_ALU:
10509169699Skan      gcc_assert (operands[2] == const1_rtx);
1051090286Sobrien      return "add{q}\t{%0, %0|%0, %0}";
1051118334Speter
1051290286Sobrien    default:
1051390286Sobrien      if (REG_P (operands[2]))
1051490286Sobrien	return "sal{q}\t{%b2, %0|%0, %b2}";
10515169699Skan      else if (operands[2] == const1_rtx
10516117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1051790286Sobrien	return "sal{q}\t%0";
1051890286Sobrien      else
1051990286Sobrien	return "sal{q}\t{%2, %0|%0, %2}";
1052018334Speter    }
1052190286Sobrien}
1052290286Sobrien  [(set (attr "type")
1052390286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1052490286Sobrien		          (const_int 0))
1052590286Sobrien		      (match_operand 0 "register_operand" ""))
1052690286Sobrien		 (match_operand 2 "const1_operand" ""))
1052790286Sobrien	      (const_string "alu")
1052890286Sobrien	   ]
1052990286Sobrien	   (const_string "ishift")))
1053090286Sobrien   (set_attr "mode" "DI")])
1053118334Speter
10532169699Skan(define_insn "*ashldi3_cconly_rex64"
10533169699Skan  [(set (reg FLAGS_REG)
10534169699Skan	(compare
10535169699Skan	  (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
10536169699Skan		     (match_operand:QI 2 "immediate_operand" "e"))
10537169699Skan	  (const_int 0)))
10538169699Skan   (clobber (match_scratch:DI 0 "=r"))]
10539169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10540169699Skan   && ix86_binary_operator_ok (ASHIFT, DImode, operands)
10541169699Skan   && (optimize_size
10542169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10543169699Skan       || (operands[2] == const1_rtx
10544169699Skan	   && (TARGET_SHIFT1
10545169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10546169699Skan{
10547169699Skan  switch (get_attr_type (insn))
10548169699Skan    {
10549169699Skan    case TYPE_ALU:
10550169699Skan      gcc_assert (operands[2] == const1_rtx);
10551169699Skan      return "add{q}\t{%0, %0|%0, %0}";
1055290286Sobrien
10553169699Skan    default:
10554169699Skan      if (REG_P (operands[2]))
10555169699Skan	return "sal{q}\t{%b2, %0|%0, %b2}";
10556169699Skan      else if (operands[2] == const1_rtx
10557169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10558169699Skan	return "sal{q}\t%0";
10559169699Skan      else
10560169699Skan	return "sal{q}\t{%2, %0|%0, %2}";
10561169699Skan    }
10562169699Skan}
10563169699Skan  [(set (attr "type")
10564169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
10565169699Skan		          (const_int 0))
10566169699Skan		      (match_operand 0 "register_operand" ""))
10567169699Skan		 (match_operand 2 "const1_operand" ""))
10568169699Skan	      (const_string "alu")
10569169699Skan	   ]
10570169699Skan	   (const_string "ishift")))
10571169699Skan   (set_attr "mode" "DI")])
10572169699Skan
10573169699Skan(define_insn "*ashldi3_1"
10574169699Skan  [(set (match_operand:DI 0 "register_operand" "=&r,r")
10575169699Skan	(ashift:DI (match_operand:DI 1 "reg_or_pm1_operand" "n,0")
10576169699Skan		   (match_operand:QI 2 "nonmemory_operand" "Jc,Jc")))
10577169699Skan   (clobber (reg:CC FLAGS_REG))]
1057890286Sobrien  "!TARGET_64BIT"
1057990286Sobrien  "#"
1058090286Sobrien  [(set_attr "type" "multi")])
1058190286Sobrien
10582169699Skan;; By default we don't ask for a scratch register, because when DImode
10583169699Skan;; values are manipulated, registers are already at a premium.  But if
10584169699Skan;; we have one handy, we won't turn it away.
10585169699Skan(define_peephole2
10586169699Skan  [(match_scratch:SI 3 "r")
10587169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
10588169699Skan		   (ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
10589169699Skan			      (match_operand:QI 2 "nonmemory_operand" "")))
10590169699Skan	      (clobber (reg:CC FLAGS_REG))])
10591169699Skan   (match_dup 3)]
10592169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1059390286Sobrien  [(const_int 0)]
10594169699Skan  "ix86_split_ashl (operands, operands[3], DImode); DONE;")
1059590286Sobrien
1059690286Sobrien(define_split
1059790286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
10598169699Skan	(ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
1059990286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10600169699Skan   (clobber (reg:CC FLAGS_REG))]
10601169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
10602169699Skan		     ? flow2_completed : reload_completed)"
1060390286Sobrien  [(const_int 0)]
10604169699Skan  "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;")
1060590286Sobrien
1060690286Sobrien(define_insn "x86_shld_1"
1060790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
1060890286Sobrien        (ior:SI (ashift:SI (match_dup 0)
1060990286Sobrien		  (match_operand:QI 2 "nonmemory_operand" "I,c"))
1061090286Sobrien		(lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
1061190286Sobrien		  (minus:QI (const_int 32) (match_dup 2)))))
10612169699Skan   (clobber (reg:CC FLAGS_REG))]
1061318334Speter  ""
1061490286Sobrien  "@
1061590286Sobrien   shld{l}\t{%2, %1, %0|%0, %1, %2}
1061690286Sobrien   shld{l}\t{%s2%1, %0|%0, %1, %2}"
1061790286Sobrien  [(set_attr "type" "ishift")
1061890286Sobrien   (set_attr "prefix_0f" "1")
1061990286Sobrien   (set_attr "mode" "SI")
1062090286Sobrien   (set_attr "pent_pair" "np")
10621251212Spfg   (set_attr "athlon_decode" "vector")
10622251212Spfg   (set_attr "amdfam10_decode" "vector")])   
1062390286Sobrien
1062490286Sobrien(define_expand "x86_shift_adj_1"
10625169699Skan  [(set (reg:CCZ FLAGS_REG)
1062690286Sobrien	(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
1062790286Sobrien			     (const_int 32))
1062890286Sobrien		     (const_int 0)))
1062990286Sobrien   (set (match_operand:SI 0 "register_operand" "")
10630169699Skan        (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
1063190286Sobrien			 (match_operand:SI 1 "register_operand" "")
1063290286Sobrien			 (match_dup 0)))
1063390286Sobrien   (set (match_dup 1)
10634169699Skan	(if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
1063590286Sobrien			 (match_operand:SI 3 "register_operand" "r")
1063690286Sobrien			 (match_dup 1)))]
1063790286Sobrien  "TARGET_CMOVE"
1063890286Sobrien  "")
1063990286Sobrien
1064090286Sobrien(define_expand "x86_shift_adj_2"
1064190286Sobrien  [(use (match_operand:SI 0 "register_operand" ""))
1064290286Sobrien   (use (match_operand:SI 1 "register_operand" ""))
1064390286Sobrien   (use (match_operand:QI 2 "register_operand" ""))]
1064490286Sobrien  ""
1064518334Speter{
1064690286Sobrien  rtx label = gen_label_rtx ();
1064790286Sobrien  rtx tmp;
1064818334Speter
1064990286Sobrien  emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
1065018334Speter
1065190286Sobrien  tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
1065290286Sobrien  tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1065390286Sobrien  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
1065490286Sobrien			      gen_rtx_LABEL_REF (VOIDmode, label),
1065590286Sobrien			      pc_rtx);
1065690286Sobrien  tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
1065790286Sobrien  JUMP_LABEL (tmp) = label;
1065818334Speter
1065990286Sobrien  emit_move_insn (operands[0], operands[1]);
10660169699Skan  ix86_expand_clear (operands[1]);
1066118334Speter
1066290286Sobrien  emit_label (label);
1066390286Sobrien  LABEL_NUSES (label) = 1;
1066490286Sobrien
1066590286Sobrien  DONE;
1066690286Sobrien})
1066790286Sobrien
1066852296Sobrien(define_expand "ashlsi3"
1066952296Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1067052296Sobrien	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
1067190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10672169699Skan   (clobber (reg:CC FLAGS_REG))]
1067352296Sobrien  ""
1067490286Sobrien  "ix86_expand_binary_operator (ASHIFT, SImode, operands); DONE;")
1067518334Speter
1067690286Sobrien(define_insn "*ashlsi3_1"
1067790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
10678169699Skan	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,l")
1067990286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,M")))
10680169699Skan   (clobber (reg:CC FLAGS_REG))]
1068190286Sobrien  "ix86_binary_operator_ok (ASHIFT, SImode, operands)"
1068290286Sobrien{
1068390286Sobrien  switch (get_attr_type (insn))
1068490286Sobrien    {
1068590286Sobrien    case TYPE_ALU:
10686169699Skan      gcc_assert (operands[2] == const1_rtx);
10687169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
1068890286Sobrien      return "add{l}\t{%0, %0|%0, %0}";
1068990286Sobrien
1069090286Sobrien    case TYPE_LEA:
1069190286Sobrien      return "#";
1069290286Sobrien
1069390286Sobrien    default:
1069490286Sobrien      if (REG_P (operands[2]))
1069590286Sobrien	return "sal{l}\t{%b2, %0|%0, %b2}";
10696169699Skan      else if (operands[2] == const1_rtx
10697117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1069890286Sobrien	return "sal{l}\t%0";
1069990286Sobrien      else
1070090286Sobrien	return "sal{l}\t{%2, %0|%0, %2}";
1070190286Sobrien    }
1070290286Sobrien}
1070390286Sobrien  [(set (attr "type")
1070490286Sobrien     (cond [(eq_attr "alternative" "1")
1070590286Sobrien	      (const_string "lea")
1070690286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1070790286Sobrien		          (const_int 0))
1070890286Sobrien		      (match_operand 0 "register_operand" ""))
1070990286Sobrien		 (match_operand 2 "const1_operand" ""))
1071090286Sobrien	      (const_string "alu")
1071190286Sobrien	   ]
1071290286Sobrien	   (const_string "ishift")))
1071390286Sobrien   (set_attr "mode" "SI")])
1071490286Sobrien
1071590286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1071690286Sobrien(define_split
1071790286Sobrien  [(set (match_operand 0 "register_operand" "")
10718117404Skan	(ashift (match_operand 1 "index_register_operand" "")
1071990286Sobrien                (match_operand:QI 2 "const_int_operand" "")))
10720169699Skan   (clobber (reg:CC FLAGS_REG))]
1072190286Sobrien  "reload_completed
10722169699Skan   && true_regnum (operands[0]) != true_regnum (operands[1])
10723169699Skan   && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4"
1072490286Sobrien  [(const_int 0)]
1072590286Sobrien{
1072690286Sobrien  rtx pat;
10727169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
10728169699Skan
10729169699Skan  if (GET_MODE_SIZE (mode) < 4)
10730169699Skan    operands[0] = gen_lowpart (SImode, operands[0]);
10731169699Skan  if (mode != Pmode)
10732169699Skan    operands[1] = gen_lowpart (Pmode, operands[1]);
10733117404Skan  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
10734169699Skan
1073590286Sobrien  pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
1073690286Sobrien  if (Pmode != SImode)
1073790286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
1073890286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
1073990286Sobrien  DONE;
1074090286Sobrien})
1074190286Sobrien
10742117404Skan;; Rare case of shifting RSP is handled by generating move and shift
10743117404Skan(define_split
10744117404Skan  [(set (match_operand 0 "register_operand" "")
10745117404Skan	(ashift (match_operand 1 "register_operand" "")
10746117404Skan                (match_operand:QI 2 "const_int_operand" "")))
10747169699Skan   (clobber (reg:CC FLAGS_REG))]
10748117404Skan  "reload_completed
10749117404Skan   && true_regnum (operands[0]) != true_regnum (operands[1])"
10750117404Skan  [(const_int 0)]
10751117404Skan{
10752117404Skan  rtx pat, clob;
10753169699Skan  emit_move_insn (operands[0], operands[1]);
10754117404Skan  pat = gen_rtx_SET (VOIDmode, operands[0],
10755117404Skan		     gen_rtx_ASHIFT (GET_MODE (operands[0]),
10756117404Skan				     operands[0], operands[2]));
10757117404Skan  clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
10758117404Skan  emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob)));
10759117404Skan  DONE;
10760117404Skan})
10761117404Skan
1076290286Sobrien(define_insn "*ashlsi3_1_zext"
1076390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
10764169699Skan	(zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l")
1076590286Sobrien			(match_operand:QI 2 "nonmemory_operand" "cI,M"))))
10766169699Skan   (clobber (reg:CC FLAGS_REG))]
1076790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
1076890286Sobrien{
1076990286Sobrien  switch (get_attr_type (insn))
1077090286Sobrien    {
1077190286Sobrien    case TYPE_ALU:
10772169699Skan      gcc_assert (operands[2] == const1_rtx);
1077390286Sobrien      return "add{l}\t{%k0, %k0|%k0, %k0}";
1077490286Sobrien
1077590286Sobrien    case TYPE_LEA:
1077690286Sobrien      return "#";
1077790286Sobrien
1077890286Sobrien    default:
1077990286Sobrien      if (REG_P (operands[2]))
1078090286Sobrien	return "sal{l}\t{%b2, %k0|%k0, %b2}";
10781169699Skan      else if (operands[2] == const1_rtx
10782117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1078390286Sobrien	return "sal{l}\t%k0";
1078490286Sobrien      else
1078590286Sobrien	return "sal{l}\t{%2, %k0|%k0, %2}";
1078690286Sobrien    }
1078790286Sobrien}
1078890286Sobrien  [(set (attr "type")
1078990286Sobrien     (cond [(eq_attr "alternative" "1")
1079090286Sobrien	      (const_string "lea")
1079190286Sobrien            (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1079290286Sobrien		     (const_int 0))
1079390286Sobrien		 (match_operand 2 "const1_operand" ""))
1079490286Sobrien	      (const_string "alu")
1079590286Sobrien	   ]
1079690286Sobrien	   (const_string "ishift")))
1079790286Sobrien   (set_attr "mode" "SI")])
1079890286Sobrien
1079990286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1080090286Sobrien(define_split
1080190286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1080290286Sobrien	(zero_extend:DI (ashift (match_operand 1 "register_operand" "")
1080390286Sobrien				(match_operand:QI 2 "const_int_operand" ""))))
10804169699Skan   (clobber (reg:CC FLAGS_REG))]
10805132727Skan  "TARGET_64BIT && reload_completed
1080690286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
10807132727Skan  [(set (match_dup 0) (zero_extend:DI
10808132727Skan			(subreg:SI (mult:SI (match_dup 1)
10809132727Skan					    (match_dup 2)) 0)))]
1081090286Sobrien{
1081190286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
10812117404Skan  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
1081390286Sobrien})
1081490286Sobrien
1081590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1081690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1081790286Sobrien;; zero are optimized away.
1081890286Sobrien(define_insn "*ashlsi3_cmp"
10819169699Skan  [(set (reg FLAGS_REG)
1082090286Sobrien	(compare
1082190286Sobrien	  (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
10822169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1082390286Sobrien	  (const_int 0)))
1082490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1082590286Sobrien	(ashift:SI (match_dup 1) (match_dup 2)))]
1082690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
10827169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10828169699Skan   && (optimize_size
10829169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10830169699Skan       || (operands[2] == const1_rtx
10831169699Skan	   && (TARGET_SHIFT1
10832169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1083390286Sobrien{
1083490286Sobrien  switch (get_attr_type (insn))
1083590286Sobrien    {
1083690286Sobrien    case TYPE_ALU:
10837169699Skan      gcc_assert (operands[2] == const1_rtx);
1083890286Sobrien      return "add{l}\t{%0, %0|%0, %0}";
1083990286Sobrien
1084090286Sobrien    default:
1084190286Sobrien      if (REG_P (operands[2]))
1084290286Sobrien	return "sal{l}\t{%b2, %0|%0, %b2}";
10843169699Skan      else if (operands[2] == const1_rtx
10844117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1084590286Sobrien	return "sal{l}\t%0";
1084690286Sobrien      else
1084790286Sobrien	return "sal{l}\t{%2, %0|%0, %2}";
1084890286Sobrien    }
1084990286Sobrien}
1085090286Sobrien  [(set (attr "type")
1085190286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1085290286Sobrien		          (const_int 0))
1085390286Sobrien		      (match_operand 0 "register_operand" ""))
1085490286Sobrien		 (match_operand 2 "const1_operand" ""))
1085590286Sobrien	      (const_string "alu")
1085690286Sobrien	   ]
1085790286Sobrien	   (const_string "ishift")))
1085890286Sobrien   (set_attr "mode" "SI")])
1085990286Sobrien
10860169699Skan(define_insn "*ashlsi3_cconly"
10861169699Skan  [(set (reg FLAGS_REG)
10862169699Skan	(compare
10863169699Skan	  (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
10864169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
10865169699Skan	  (const_int 0)))
10866169699Skan   (clobber (match_scratch:SI 0 "=r"))]
10867169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
10868169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10869169699Skan   && (optimize_size
10870169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10871169699Skan       || (operands[2] == const1_rtx
10872169699Skan	   && (TARGET_SHIFT1
10873169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10874169699Skan{
10875169699Skan  switch (get_attr_type (insn))
10876169699Skan    {
10877169699Skan    case TYPE_ALU:
10878169699Skan      gcc_assert (operands[2] == const1_rtx);
10879169699Skan      return "add{l}\t{%0, %0|%0, %0}";
10880169699Skan
10881169699Skan    default:
10882169699Skan      if (REG_P (operands[2]))
10883169699Skan	return "sal{l}\t{%b2, %0|%0, %b2}";
10884169699Skan      else if (operands[2] == const1_rtx
10885169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10886169699Skan	return "sal{l}\t%0";
10887169699Skan      else
10888169699Skan	return "sal{l}\t{%2, %0|%0, %2}";
10889169699Skan    }
10890169699Skan}
10891169699Skan  [(set (attr "type")
10892169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
10893169699Skan		          (const_int 0))
10894169699Skan		      (match_operand 0 "register_operand" ""))
10895169699Skan		 (match_operand 2 "const1_operand" ""))
10896169699Skan	      (const_string "alu")
10897169699Skan	   ]
10898169699Skan	   (const_string "ishift")))
10899169699Skan   (set_attr "mode" "SI")])
10900169699Skan
1090190286Sobrien(define_insn "*ashlsi3_cmp_zext"
10902169699Skan  [(set (reg FLAGS_REG)
1090390286Sobrien	(compare
1090490286Sobrien	  (ashift:SI (match_operand:SI 1 "register_operand" "0")
10905169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1090690286Sobrien	  (const_int 0)))
1090790286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1090890286Sobrien	(zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
1090990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10910169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10911169699Skan   && (optimize_size
10912169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10913169699Skan       || (operands[2] == const1_rtx
10914169699Skan	   && (TARGET_SHIFT1
10915169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
1091690286Sobrien{
1091790286Sobrien  switch (get_attr_type (insn))
1091890286Sobrien    {
1091990286Sobrien    case TYPE_ALU:
10920169699Skan      gcc_assert (operands[2] == const1_rtx);
1092190286Sobrien      return "add{l}\t{%k0, %k0|%k0, %k0}";
1092290286Sobrien
1092390286Sobrien    default:
1092490286Sobrien      if (REG_P (operands[2]))
1092590286Sobrien	return "sal{l}\t{%b2, %k0|%k0, %b2}";
10926169699Skan      else if (operands[2] == const1_rtx
10927117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1092890286Sobrien	return "sal{l}\t%k0";
1092990286Sobrien      else
1093090286Sobrien	return "sal{l}\t{%2, %k0|%k0, %2}";
1093190286Sobrien    }
1093290286Sobrien}
1093390286Sobrien  [(set (attr "type")
1093490286Sobrien     (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1093590286Sobrien		     (const_int 0))
1093690286Sobrien		 (match_operand 2 "const1_operand" ""))
1093790286Sobrien	      (const_string "alu")
1093890286Sobrien	   ]
1093990286Sobrien	   (const_string "ishift")))
1094090286Sobrien   (set_attr "mode" "SI")])
1094190286Sobrien
1094252296Sobrien(define_expand "ashlhi3"
1094352296Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1094452296Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
1094590286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10946169699Skan   (clobber (reg:CC FLAGS_REG))]
1094790286Sobrien  "TARGET_HIMODE_MATH"
1094890286Sobrien  "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;")
1094918334Speter
1095090286Sobrien(define_insn "*ashlhi3_1_lea"
1095190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
10952169699Skan	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l")
1095390286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,M")))
10954169699Skan   (clobber (reg:CC FLAGS_REG))]
1095590286Sobrien  "!TARGET_PARTIAL_REG_STALL
1095690286Sobrien   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
1095790286Sobrien{
1095890286Sobrien  switch (get_attr_type (insn))
1095990286Sobrien    {
1096090286Sobrien    case TYPE_LEA:
1096190286Sobrien      return "#";
1096290286Sobrien    case TYPE_ALU:
10963169699Skan      gcc_assert (operands[2] == const1_rtx);
1096490286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1096590286Sobrien
1096690286Sobrien    default:
1096790286Sobrien      if (REG_P (operands[2]))
1096890286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10969169699Skan      else if (operands[2] == const1_rtx
10970117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1097190286Sobrien	return "sal{w}\t%0";
1097290286Sobrien      else
1097390286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1097490286Sobrien    }
1097590286Sobrien}
1097690286Sobrien  [(set (attr "type")
1097790286Sobrien     (cond [(eq_attr "alternative" "1")
1097890286Sobrien	      (const_string "lea")
1097990286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1098090286Sobrien		          (const_int 0))
1098190286Sobrien		      (match_operand 0 "register_operand" ""))
1098290286Sobrien		 (match_operand 2 "const1_operand" ""))
1098390286Sobrien	      (const_string "alu")
1098490286Sobrien	   ]
1098590286Sobrien	   (const_string "ishift")))
1098690286Sobrien   (set_attr "mode" "HI,SI")])
1098790286Sobrien
1098890286Sobrien(define_insn "*ashlhi3_1"
1098990286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1099090286Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
1099190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI")))
10992169699Skan   (clobber (reg:CC FLAGS_REG))]
1099390286Sobrien  "TARGET_PARTIAL_REG_STALL
1099490286Sobrien   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
1099590286Sobrien{
1099690286Sobrien  switch (get_attr_type (insn))
1099790286Sobrien    {
1099890286Sobrien    case TYPE_ALU:
10999169699Skan      gcc_assert (operands[2] == const1_rtx);
1100090286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1100190286Sobrien
1100290286Sobrien    default:
1100390286Sobrien      if (REG_P (operands[2]))
1100490286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
11005169699Skan      else if (operands[2] == const1_rtx
11006117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1100790286Sobrien	return "sal{w}\t%0";
1100890286Sobrien      else
1100990286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1101090286Sobrien    }
1101190286Sobrien}
1101290286Sobrien  [(set (attr "type")
1101390286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1101490286Sobrien		          (const_int 0))
1101590286Sobrien		      (match_operand 0 "register_operand" ""))
1101690286Sobrien		 (match_operand 2 "const1_operand" ""))
1101790286Sobrien	      (const_string "alu")
1101890286Sobrien	   ]
1101990286Sobrien	   (const_string "ishift")))
1102090286Sobrien   (set_attr "mode" "HI")])
1102190286Sobrien
1102290286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1102390286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1102490286Sobrien;; zero are optimized away.
1102590286Sobrien(define_insn "*ashlhi3_cmp"
11026169699Skan  [(set (reg FLAGS_REG)
1102790286Sobrien	(compare
1102890286Sobrien	  (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11029169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1103090286Sobrien	  (const_int 0)))
1103190286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1103290286Sobrien	(ashift:HI (match_dup 1) (match_dup 2)))]
1103390286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11034169699Skan   && ix86_binary_operator_ok (ASHIFT, HImode, operands)
11035169699Skan   && (optimize_size
11036169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11037169699Skan       || (operands[2] == const1_rtx
11038169699Skan	   && (TARGET_SHIFT1
11039169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1104090286Sobrien{
1104190286Sobrien  switch (get_attr_type (insn))
1104290286Sobrien    {
1104390286Sobrien    case TYPE_ALU:
11044169699Skan      gcc_assert (operands[2] == const1_rtx);
1104590286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1104690286Sobrien
1104790286Sobrien    default:
1104890286Sobrien      if (REG_P (operands[2]))
1104990286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
11050169699Skan      else if (operands[2] == const1_rtx
11051117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1105290286Sobrien	return "sal{w}\t%0";
1105390286Sobrien      else
1105490286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1105590286Sobrien    }
1105690286Sobrien}
1105790286Sobrien  [(set (attr "type")
1105890286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1105990286Sobrien		          (const_int 0))
1106090286Sobrien		      (match_operand 0 "register_operand" ""))
1106190286Sobrien		 (match_operand 2 "const1_operand" ""))
1106290286Sobrien	      (const_string "alu")
1106390286Sobrien	   ]
1106490286Sobrien	   (const_string "ishift")))
1106590286Sobrien   (set_attr "mode" "HI")])
1106690286Sobrien
11067169699Skan(define_insn "*ashlhi3_cconly"
11068169699Skan  [(set (reg FLAGS_REG)
11069169699Skan	(compare
11070169699Skan	  (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11071169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
11072169699Skan	  (const_int 0)))
11073169699Skan   (clobber (match_scratch:HI 0 "=r"))]
11074169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11075169699Skan   && ix86_binary_operator_ok (ASHIFT, HImode, operands)
11076169699Skan   && (optimize_size
11077169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11078169699Skan       || (operands[2] == const1_rtx
11079169699Skan	   && (TARGET_SHIFT1
11080169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
11081169699Skan{
11082169699Skan  switch (get_attr_type (insn))
11083169699Skan    {
11084169699Skan    case TYPE_ALU:
11085169699Skan      gcc_assert (operands[2] == const1_rtx);
11086169699Skan      return "add{w}\t{%0, %0|%0, %0}";
11087169699Skan
11088169699Skan    default:
11089169699Skan      if (REG_P (operands[2]))
11090169699Skan	return "sal{w}\t{%b2, %0|%0, %b2}";
11091169699Skan      else if (operands[2] == const1_rtx
11092169699Skan	       && (TARGET_SHIFT1 || optimize_size))
11093169699Skan	return "sal{w}\t%0";
11094169699Skan      else
11095169699Skan	return "sal{w}\t{%2, %0|%0, %2}";
11096169699Skan    }
11097169699Skan}
11098169699Skan  [(set (attr "type")
11099169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
11100169699Skan		          (const_int 0))
11101169699Skan		      (match_operand 0 "register_operand" ""))
11102169699Skan		 (match_operand 2 "const1_operand" ""))
11103169699Skan	      (const_string "alu")
11104169699Skan	   ]
11105169699Skan	   (const_string "ishift")))
11106169699Skan   (set_attr "mode" "HI")])
11107169699Skan
1110852296Sobrien(define_expand "ashlqi3"
1110952296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1111052296Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
1111190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
11112169699Skan   (clobber (reg:CC FLAGS_REG))]
1111390286Sobrien  "TARGET_QIMODE_MATH"
1111490286Sobrien  "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;")
1111518334Speter
1111690286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
1111718334Speter
1111890286Sobrien(define_insn "*ashlqi3_1_lea"
1111990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r")
11120169699Skan	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l")
1112190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,cI,M")))
11122169699Skan   (clobber (reg:CC FLAGS_REG))]
1112390286Sobrien  "!TARGET_PARTIAL_REG_STALL
1112490286Sobrien   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
1112590286Sobrien{
1112690286Sobrien  switch (get_attr_type (insn))
1112790286Sobrien    {
1112890286Sobrien    case TYPE_LEA:
1112990286Sobrien      return "#";
1113090286Sobrien    case TYPE_ALU:
11131169699Skan      gcc_assert (operands[2] == const1_rtx);
1113290286Sobrien      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
1113390286Sobrien        return "add{l}\t{%k0, %k0|%k0, %k0}";
1113490286Sobrien      else
1113590286Sobrien        return "add{b}\t{%0, %0|%0, %0}";
1113618334Speter
1113790286Sobrien    default:
1113890286Sobrien      if (REG_P (operands[2]))
1113990286Sobrien	{
1114090286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1114190286Sobrien	    return "sal{l}\t{%b2, %k0|%k0, %b2}";
1114290286Sobrien	  else
1114390286Sobrien	    return "sal{b}\t{%b2, %0|%0, %b2}";
1114490286Sobrien	}
11145169699Skan      else if (operands[2] == const1_rtx
11146117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1114790286Sobrien	{
1114890286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1114990286Sobrien	    return "sal{l}\t%0";
1115090286Sobrien	  else
1115190286Sobrien	    return "sal{b}\t%0";
1115290286Sobrien	}
1115390286Sobrien      else
1115490286Sobrien	{
1115590286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1115690286Sobrien	    return "sal{l}\t{%2, %k0|%k0, %2}";
1115790286Sobrien	  else
1115890286Sobrien	    return "sal{b}\t{%2, %0|%0, %2}";
1115990286Sobrien	}
1116090286Sobrien    }
1116190286Sobrien}
1116290286Sobrien  [(set (attr "type")
1116390286Sobrien     (cond [(eq_attr "alternative" "2")
1116490286Sobrien	      (const_string "lea")
1116590286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1116690286Sobrien		          (const_int 0))
1116790286Sobrien		      (match_operand 0 "register_operand" ""))
1116890286Sobrien		 (match_operand 2 "const1_operand" ""))
1116990286Sobrien	      (const_string "alu")
1117090286Sobrien	   ]
1117190286Sobrien	   (const_string "ishift")))
1117290286Sobrien   (set_attr "mode" "QI,SI,SI")])
1117318334Speter
1117490286Sobrien(define_insn "*ashlqi3_1"
1117590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
1117690286Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1117790286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
11178169699Skan   (clobber (reg:CC FLAGS_REG))]
1117990286Sobrien  "TARGET_PARTIAL_REG_STALL
1118090286Sobrien   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
1118190286Sobrien{
1118290286Sobrien  switch (get_attr_type (insn))
1118390286Sobrien    {
1118490286Sobrien    case TYPE_ALU:
11185169699Skan      gcc_assert (operands[2] == const1_rtx);
1118690286Sobrien      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
1118790286Sobrien        return "add{l}\t{%k0, %k0|%k0, %k0}";
1118890286Sobrien      else
1118990286Sobrien        return "add{b}\t{%0, %0|%0, %0}";
1119052296Sobrien
1119190286Sobrien    default:
1119290286Sobrien      if (REG_P (operands[2]))
1119390286Sobrien	{
1119490286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1119590286Sobrien	    return "sal{l}\t{%b2, %k0|%k0, %b2}";
1119690286Sobrien	  else
1119790286Sobrien	    return "sal{b}\t{%b2, %0|%0, %b2}";
1119890286Sobrien	}
11199169699Skan      else if (operands[2] == const1_rtx
11200117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1120190286Sobrien	{
1120290286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1120390286Sobrien	    return "sal{l}\t%0";
1120490286Sobrien	  else
1120590286Sobrien	    return "sal{b}\t%0";
1120690286Sobrien	}
1120790286Sobrien      else
1120890286Sobrien	{
1120990286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1121090286Sobrien	    return "sal{l}\t{%2, %k0|%k0, %2}";
1121190286Sobrien	  else
1121290286Sobrien	    return "sal{b}\t{%2, %0|%0, %2}";
1121390286Sobrien	}
1121490286Sobrien    }
1121590286Sobrien}
1121690286Sobrien  [(set (attr "type")
1121790286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1121890286Sobrien		          (const_int 0))
1121990286Sobrien		      (match_operand 0 "register_operand" ""))
1122090286Sobrien		 (match_operand 2 "const1_operand" ""))
1122190286Sobrien	      (const_string "alu")
1122290286Sobrien	   ]
1122390286Sobrien	   (const_string "ishift")))
1122490286Sobrien   (set_attr "mode" "QI,SI")])
1122518334Speter
1122690286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1122790286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1122890286Sobrien;; zero are optimized away.
1122990286Sobrien(define_insn "*ashlqi3_cmp"
11230169699Skan  [(set (reg FLAGS_REG)
1123190286Sobrien	(compare
1123290286Sobrien	  (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11233169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1123490286Sobrien	  (const_int 0)))
1123590286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1123690286Sobrien	(ashift:QI (match_dup 1) (match_dup 2)))]
1123790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11238169699Skan   && ix86_binary_operator_ok (ASHIFT, QImode, operands)
11239169699Skan   && (optimize_size
11240169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11241169699Skan       || (operands[2] == const1_rtx
11242169699Skan	   && (TARGET_SHIFT1
11243169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1124490286Sobrien{
1124590286Sobrien  switch (get_attr_type (insn))
1124690286Sobrien    {
1124790286Sobrien    case TYPE_ALU:
11248169699Skan      gcc_assert (operands[2] == const1_rtx);
1124990286Sobrien      return "add{b}\t{%0, %0|%0, %0}";
1125018334Speter
1125190286Sobrien    default:
1125290286Sobrien      if (REG_P (operands[2]))
1125390286Sobrien	return "sal{b}\t{%b2, %0|%0, %b2}";
11254169699Skan      else if (operands[2] == const1_rtx
11255117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1125690286Sobrien	return "sal{b}\t%0";
1125790286Sobrien      else
1125890286Sobrien	return "sal{b}\t{%2, %0|%0, %2}";
1125990286Sobrien    }
1126090286Sobrien}
1126190286Sobrien  [(set (attr "type")
1126290286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1126390286Sobrien		          (const_int 0))
1126490286Sobrien		      (match_operand 0 "register_operand" ""))
1126590286Sobrien		 (match_operand 2 "const1_operand" ""))
1126690286Sobrien	      (const_string "alu")
1126790286Sobrien	   ]
1126890286Sobrien	   (const_string "ishift")))
1126990286Sobrien   (set_attr "mode" "QI")])
1127018334Speter
11271169699Skan(define_insn "*ashlqi3_cconly"
11272169699Skan  [(set (reg FLAGS_REG)
11273169699Skan	(compare
11274169699Skan	  (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11275169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
11276169699Skan	  (const_int 0)))
11277169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11278169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11279169699Skan   && ix86_binary_operator_ok (ASHIFT, QImode, operands)
11280169699Skan   && (optimize_size
11281169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11282169699Skan       || (operands[2] == const1_rtx
11283169699Skan	   && (TARGET_SHIFT1
11284169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
11285169699Skan{
11286169699Skan  switch (get_attr_type (insn))
11287169699Skan    {
11288169699Skan    case TYPE_ALU:
11289169699Skan      gcc_assert (operands[2] == const1_rtx);
11290169699Skan      return "add{b}\t{%0, %0|%0, %0}";
11291169699Skan
11292169699Skan    default:
11293169699Skan      if (REG_P (operands[2]))
11294169699Skan	return "sal{b}\t{%b2, %0|%0, %b2}";
11295169699Skan      else if (operands[2] == const1_rtx
11296169699Skan	       && (TARGET_SHIFT1 || optimize_size))
11297169699Skan	return "sal{b}\t%0";
11298169699Skan      else
11299169699Skan	return "sal{b}\t{%2, %0|%0, %2}";
11300169699Skan    }
11301169699Skan}
11302169699Skan  [(set (attr "type")
11303169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
11304169699Skan		          (const_int 0))
11305169699Skan		      (match_operand 0 "register_operand" ""))
11306169699Skan		 (match_operand 2 "const1_operand" ""))
11307169699Skan	      (const_string "alu")
11308169699Skan	   ]
11309169699Skan	   (const_string "ishift")))
11310169699Skan   (set_attr "mode" "QI")])
11311169699Skan
1131218334Speter;; See comment above `ashldi3' about how this works.
1131318334Speter
11314169699Skan(define_expand "ashrti3"
11315169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
11316169699Skan		   (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
1131790286Sobrien				(match_operand:QI 2 "nonmemory_operand" "")))
11318169699Skan	      (clobber (reg:CC FLAGS_REG))])]
11319169699Skan  "TARGET_64BIT"
1132018334Speter{
11321169699Skan  if (! immediate_operand (operands[2], QImode))
1132218334Speter    {
11323169699Skan      emit_insn (gen_ashrti3_1 (operands[0], operands[1], operands[2]));
1132490286Sobrien      DONE;
1132518334Speter    }
11326169699Skan  ix86_expand_binary_operator (ASHIFTRT, TImode, operands);
1132718334Speter  DONE;
1132890286Sobrien})
1132918334Speter
11330169699Skan(define_insn "ashrti3_1"
11331169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11332169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
11333169699Skan		     (match_operand:QI 2 "register_operand" "c")))
11334169699Skan   (clobber (match_scratch:DI 3 "=&r"))
11335169699Skan   (clobber (reg:CC FLAGS_REG))]
11336169699Skan  "TARGET_64BIT"
11337169699Skan  "#"
11338169699Skan  [(set_attr "type" "multi")])
11339169699Skan
11340169699Skan(define_insn "*ashrti3_2"
11341169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11342169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
11343169699Skan		     (match_operand:QI 2 "immediate_operand" "O")))
11344169699Skan   (clobber (reg:CC FLAGS_REG))]
11345169699Skan  "TARGET_64BIT"
11346169699Skan  "#"
11347169699Skan  [(set_attr "type" "multi")])
11348169699Skan
11349169699Skan(define_split
11350169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11351169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "")
11352169699Skan		     (match_operand:QI 2 "register_operand" "")))
11353169699Skan   (clobber (match_scratch:DI 3 ""))
11354169699Skan   (clobber (reg:CC FLAGS_REG))]
11355169699Skan  "TARGET_64BIT && reload_completed"
11356169699Skan  [(const_int 0)]
11357169699Skan  "ix86_split_ashr (operands, operands[3], TImode); DONE;")
11358169699Skan
11359169699Skan(define_split
11360169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11361169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "")
11362169699Skan		     (match_operand:QI 2 "immediate_operand" "")))
11363169699Skan   (clobber (reg:CC FLAGS_REG))]
11364169699Skan  "TARGET_64BIT && reload_completed"
11365169699Skan  [(const_int 0)]
11366169699Skan  "ix86_split_ashr (operands, NULL_RTX, TImode); DONE;")
11367169699Skan
11368169699Skan(define_insn "x86_64_shrd"
11369169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
11370169699Skan        (ior:DI (ashiftrt:DI (match_dup 0)
11371169699Skan		  (match_operand:QI 2 "nonmemory_operand" "J,c"))
11372169699Skan		(ashift:DI (match_operand:DI 1 "register_operand" "r,r")
11373169699Skan		  (minus:QI (const_int 64) (match_dup 2)))))
11374169699Skan   (clobber (reg:CC FLAGS_REG))]
11375169699Skan  "TARGET_64BIT"
11376169699Skan  "@
11377169699Skan   shrd{q}\t{%2, %1, %0|%0, %1, %2}
11378169699Skan   shrd{q}\t{%s2%1, %0|%0, %1, %2}"
11379169699Skan  [(set_attr "type" "ishift")
11380169699Skan   (set_attr "prefix_0f" "1")
11381169699Skan   (set_attr "mode" "DI")
11382251212Spfg   (set_attr "athlon_decode" "vector")
11383251212Spfg   (set_attr "amdfam10_decode" "vector")])   
11384169699Skan
11385169699Skan(define_expand "ashrdi3"
11386169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
11387169699Skan	(ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
11388169699Skan		     (match_operand:QI 2 "nonmemory_operand" "")))]
11389169699Skan  ""
11390169699Skan  "ix86_expand_binary_operator (ASHIFTRT, DImode, operands); DONE;")
11391169699Skan
11392169699Skan(define_insn "*ashrdi3_63_rex64"
1139390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=*d,rm")
1139490286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "*a,0")
1139590286Sobrien		     (match_operand:DI 2 "const_int_operand" "i,i")))
11396169699Skan   (clobber (reg:CC FLAGS_REG))]
11397169699Skan  "TARGET_64BIT && INTVAL (operands[2]) == 63
11398169699Skan   && (TARGET_USE_CLTD || optimize_size)
1139990286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1140090286Sobrien  "@
1140190286Sobrien   {cqto|cqo}
1140290286Sobrien   sar{q}\t{%2, %0|%0, %2}"
1140390286Sobrien  [(set_attr "type" "imovx,ishift")
1140490286Sobrien   (set_attr "prefix_0f" "0,*")
1140590286Sobrien   (set_attr "length_immediate" "0,*")
1140690286Sobrien   (set_attr "modrm" "0,1")
1140790286Sobrien   (set_attr "mode" "DI")])
1140850650Sobrien
1140990286Sobrien(define_insn "*ashrdi3_1_one_bit_rex64"
1141090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1141190286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11412132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11413169699Skan   (clobber (reg:CC FLAGS_REG))]
1141490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11415117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1141690286Sobrien  "sar{q}\t%0"
1141790286Sobrien  [(set_attr "type" "ishift")
11418259563Spfg   (set (attr "length")
11419259563Spfg     (if_then_else (match_operand:DI 0 "register_operand" "")
1142090286Sobrien	(const_string "2")
1142190286Sobrien	(const_string "*")))])
1142250650Sobrien
1142390286Sobrien(define_insn "*ashrdi3_1_rex64"
1142490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1142590286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1142690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
11427169699Skan   (clobber (reg:CC FLAGS_REG))]
1142890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1142990286Sobrien  "@
1143090286Sobrien   sar{q}\t{%2, %0|%0, %2}
1143190286Sobrien   sar{q}\t{%b2, %0|%0, %b2}"
1143290286Sobrien  [(set_attr "type" "ishift")
1143390286Sobrien   (set_attr "mode" "DI")])
1143450650Sobrien
1143590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1143690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1143790286Sobrien;; zero are optimized away.
1143890286Sobrien(define_insn "*ashrdi3_one_bit_cmp_rex64"
11439169699Skan  [(set (reg FLAGS_REG)
1144090286Sobrien	(compare
1144190286Sobrien	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11442132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1144390286Sobrien	  (const_int 0)))
1144490286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1144590286Sobrien	(ashiftrt:DI (match_dup 1) (match_dup 2)))]
1144690286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11447117404Skan   && (TARGET_SHIFT1 || optimize_size)
1144890286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1144990286Sobrien  "sar{q}\t%0"
1145090286Sobrien  [(set_attr "type" "ishift")
11451259563Spfg   (set (attr "length")
11452259563Spfg     (if_then_else (match_operand:DI 0 "register_operand" "")
1145390286Sobrien	(const_string "2")
1145490286Sobrien	(const_string "*")))])
1145550650Sobrien
11456169699Skan(define_insn "*ashrdi3_one_bit_cconly_rex64"
11457169699Skan  [(set (reg FLAGS_REG)
11458169699Skan	(compare
11459169699Skan	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11460169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11461169699Skan	  (const_int 0)))
11462169699Skan   (clobber (match_scratch:DI 0 "=r"))]
11463169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11464169699Skan   && (TARGET_SHIFT1 || optimize_size)
11465169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
11466169699Skan  "sar{q}\t%0"
11467169699Skan  [(set_attr "type" "ishift")
11468169699Skan   (set_attr "length" "2")])
11469169699Skan
1147090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1147190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1147290286Sobrien;; zero are optimized away.
1147390286Sobrien(define_insn "*ashrdi3_cmp_rex64"
11474169699Skan  [(set (reg FLAGS_REG)
1147590286Sobrien	(compare
1147690286Sobrien	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1147790286Sobrien		       (match_operand:QI 2 "const_int_operand" "n"))
1147890286Sobrien	  (const_int 0)))
1147990286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1148090286Sobrien	(ashiftrt:DI (match_dup 1) (match_dup 2)))]
1148190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11482169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11483169699Skan   && (optimize_size
11484169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1148590286Sobrien  "sar{q}\t{%2, %0|%0, %2}"
1148690286Sobrien  [(set_attr "type" "ishift")
1148790286Sobrien   (set_attr "mode" "DI")])
1148818334Speter
11489169699Skan(define_insn "*ashrdi3_cconly_rex64"
11490169699Skan  [(set (reg FLAGS_REG)
11491169699Skan	(compare
11492169699Skan	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11493169699Skan		       (match_operand:QI 2 "const_int_operand" "n"))
11494169699Skan	  (const_int 0)))
11495169699Skan   (clobber (match_scratch:DI 0 "=r"))]
11496169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11497169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11498169699Skan   && (optimize_size
11499169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11500169699Skan  "sar{q}\t{%2, %0|%0, %2}"
11501169699Skan  [(set_attr "type" "ishift")
11502169699Skan   (set_attr "mode" "DI")])
1150318334Speter
11504169699Skan(define_insn "*ashrdi3_1"
1150590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1150690286Sobrien	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
1150790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "Jc")))
11508169699Skan   (clobber (reg:CC FLAGS_REG))]
1150990286Sobrien  "!TARGET_64BIT"
1151090286Sobrien  "#"
1151190286Sobrien  [(set_attr "type" "multi")])
1151218334Speter
11513169699Skan;; By default we don't ask for a scratch register, because when DImode
11514169699Skan;; values are manipulated, registers are already at a premium.  But if
11515169699Skan;; we have one handy, we won't turn it away.
11516169699Skan(define_peephole2
11517169699Skan  [(match_scratch:SI 3 "r")
11518169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
11519169699Skan		   (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
11520169699Skan			        (match_operand:QI 2 "nonmemory_operand" "")))
11521169699Skan	      (clobber (reg:CC FLAGS_REG))])
11522169699Skan   (match_dup 3)]
11523169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1152490286Sobrien  [(const_int 0)]
11525169699Skan  "ix86_split_ashr (operands, operands[3], DImode); DONE;")
1152618334Speter
1152790286Sobrien(define_split
1152890286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1152990286Sobrien	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
1153090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11531169699Skan   (clobber (reg:CC FLAGS_REG))]
11532169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
11533169699Skan		     ? flow2_completed : reload_completed)"
1153490286Sobrien  [(const_int 0)]
11535169699Skan  "ix86_split_ashr (operands, NULL_RTX, DImode); DONE;")
1153618334Speter
1153790286Sobrien(define_insn "x86_shrd_1"
1153890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
1153990286Sobrien        (ior:SI (ashiftrt:SI (match_dup 0)
1154090286Sobrien		  (match_operand:QI 2 "nonmemory_operand" "I,c"))
1154190286Sobrien		(ashift:SI (match_operand:SI 1 "register_operand" "r,r")
1154290286Sobrien		  (minus:QI (const_int 32) (match_dup 2)))))
11543169699Skan   (clobber (reg:CC FLAGS_REG))]
1154418334Speter  ""
1154590286Sobrien  "@
1154690286Sobrien   shrd{l}\t{%2, %1, %0|%0, %1, %2}
1154790286Sobrien   shrd{l}\t{%s2%1, %0|%0, %1, %2}"
1154890286Sobrien  [(set_attr "type" "ishift")
1154990286Sobrien   (set_attr "prefix_0f" "1")
1155090286Sobrien   (set_attr "pent_pair" "np")
1155190286Sobrien   (set_attr "mode" "SI")])
1155290286Sobrien
1155390286Sobrien(define_expand "x86_shift_adj_3"
1155490286Sobrien  [(use (match_operand:SI 0 "register_operand" ""))
1155590286Sobrien   (use (match_operand:SI 1 "register_operand" ""))
1155690286Sobrien   (use (match_operand:QI 2 "register_operand" ""))]
1155790286Sobrien  ""
1155818334Speter{
1155990286Sobrien  rtx label = gen_label_rtx ();
1156090286Sobrien  rtx tmp;
1156118334Speter
1156290286Sobrien  emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
1156318334Speter
1156490286Sobrien  tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
1156590286Sobrien  tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1156690286Sobrien  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
1156790286Sobrien			      gen_rtx_LABEL_REF (VOIDmode, label),
1156890286Sobrien			      pc_rtx);
1156990286Sobrien  tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
1157090286Sobrien  JUMP_LABEL (tmp) = label;
1157118334Speter
1157290286Sobrien  emit_move_insn (operands[0], operands[1]);
1157390286Sobrien  emit_insn (gen_ashrsi3_31 (operands[1], operands[1], GEN_INT (31)));
1157418334Speter
1157590286Sobrien  emit_label (label);
1157690286Sobrien  LABEL_NUSES (label) = 1;
1157790286Sobrien
1157890286Sobrien  DONE;
1157990286Sobrien})
1158090286Sobrien
1158152296Sobrien(define_insn "ashrsi3_31"
1158290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm")
1158390286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0")
1158490286Sobrien		     (match_operand:SI 2 "const_int_operand" "i,i")))
11585169699Skan   (clobber (reg:CC FLAGS_REG))]
1158690286Sobrien  "INTVAL (operands[2]) == 31 && (TARGET_USE_CLTD || optimize_size)
1158790286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1158852296Sobrien  "@
1158990286Sobrien   {cltd|cdq}
1159090286Sobrien   sar{l}\t{%2, %0|%0, %2}"
1159190286Sobrien  [(set_attr "type" "imovx,ishift")
1159290286Sobrien   (set_attr "prefix_0f" "0,*")
1159390286Sobrien   (set_attr "length_immediate" "0,*")
1159490286Sobrien   (set_attr "modrm" "0,1")
1159590286Sobrien   (set_attr "mode" "SI")])
1159652296Sobrien
1159790286Sobrien(define_insn "*ashrsi3_31_zext"
1159890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*d,r")
1159990286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "*a,0")
1160090286Sobrien				     (match_operand:SI 2 "const_int_operand" "i,i"))))
11601169699Skan   (clobber (reg:CC FLAGS_REG))]
1160290286Sobrien  "TARGET_64BIT && (TARGET_USE_CLTD || optimize_size)
1160390286Sobrien   && INTVAL (operands[2]) == 31
1160490286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1160590286Sobrien  "@
1160690286Sobrien   {cltd|cdq}
1160790286Sobrien   sar{l}\t{%2, %k0|%k0, %2}"
1160890286Sobrien  [(set_attr "type" "imovx,ishift")
1160990286Sobrien   (set_attr "prefix_0f" "0,*")
1161090286Sobrien   (set_attr "length_immediate" "0,*")
1161190286Sobrien   (set_attr "modrm" "0,1")
1161290286Sobrien   (set_attr "mode" "SI")])
1161390286Sobrien
1161490286Sobrien(define_expand "ashrsi3"
1161590286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1161690286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
1161790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11618169699Skan   (clobber (reg:CC FLAGS_REG))]
1161990286Sobrien  ""
1162090286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, SImode, operands); DONE;")
1162190286Sobrien
1162290286Sobrien(define_insn "*ashrsi3_1_one_bit"
1162350650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1162450650Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11625132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11626169699Skan   (clobber (reg:CC FLAGS_REG))]
1162790286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11628117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1162990286Sobrien  "sar{l}\t%0"
1163090286Sobrien  [(set_attr "type" "ishift")
11631259563Spfg   (set (attr "length")
11632259563Spfg     (if_then_else (match_operand:SI 0 "register_operand" "")
1163390286Sobrien	(const_string "2")
1163490286Sobrien	(const_string "*")))])
1163518334Speter
1163690286Sobrien(define_insn "*ashrsi3_1_one_bit_zext"
1163790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1163890286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11639132727Skan				     (match_operand:QI 2 "const1_operand" ""))))
11640169699Skan   (clobber (reg:CC FLAGS_REG))]
1164190286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11642117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1164390286Sobrien  "sar{l}\t%k0"
1164490286Sobrien  [(set_attr "type" "ishift")
1164590286Sobrien   (set_attr "length" "2")])
1164690286Sobrien
1164790286Sobrien(define_insn "*ashrsi3_1"
1164890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1164990286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1165090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11651169699Skan   (clobber (reg:CC FLAGS_REG))]
1165290286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1165390286Sobrien  "@
1165490286Sobrien   sar{l}\t{%2, %0|%0, %2}
1165590286Sobrien   sar{l}\t{%b2, %0|%0, %b2}"
1165690286Sobrien  [(set_attr "type" "ishift")
1165790286Sobrien   (set_attr "mode" "SI")])
1165890286Sobrien
1165990286Sobrien(define_insn "*ashrsi3_1_zext"
1166090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1166190286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
1166290286Sobrien				     (match_operand:QI 2 "nonmemory_operand" "I,c"))))
11663169699Skan   (clobber (reg:CC FLAGS_REG))]
1166490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1166590286Sobrien  "@
1166690286Sobrien   sar{l}\t{%2, %k0|%k0, %2}
1166790286Sobrien   sar{l}\t{%b2, %k0|%k0, %b2}"
1166890286Sobrien  [(set_attr "type" "ishift")
1166990286Sobrien   (set_attr "mode" "SI")])
1167090286Sobrien
1167190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1167290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1167390286Sobrien;; zero are optimized away.
1167490286Sobrien(define_insn "*ashrsi3_one_bit_cmp"
11675169699Skan  [(set (reg FLAGS_REG)
1167690286Sobrien	(compare
1167790286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11678132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1167990286Sobrien	  (const_int 0)))
1168090286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1168190286Sobrien	(ashiftrt:SI (match_dup 1) (match_dup 2)))]
1168290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11683117404Skan   && (TARGET_SHIFT1 || optimize_size)
1168490286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1168590286Sobrien  "sar{l}\t%0"
1168690286Sobrien  [(set_attr "type" "ishift")
11687259563Spfg   (set (attr "length")
11688259563Spfg     (if_then_else (match_operand:SI 0 "register_operand" "")
1168990286Sobrien	(const_string "2")
1169090286Sobrien	(const_string "*")))])
1169190286Sobrien
11692169699Skan(define_insn "*ashrsi3_one_bit_cconly"
11693169699Skan  [(set (reg FLAGS_REG)
11694169699Skan	(compare
11695169699Skan	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11696169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11697169699Skan	  (const_int 0)))
11698169699Skan   (clobber (match_scratch:SI 0 "=r"))]
11699169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11700169699Skan   && (TARGET_SHIFT1 || optimize_size)
11701169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
11702169699Skan  "sar{l}\t%0"
11703169699Skan  [(set_attr "type" "ishift")
11704169699Skan   (set_attr "length" "2")])
11705169699Skan
1170690286Sobrien(define_insn "*ashrsi3_one_bit_cmp_zext"
11707169699Skan  [(set (reg FLAGS_REG)
1170890286Sobrien	(compare
1170990286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11710132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1171190286Sobrien	  (const_int 0)))
1171290286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1171390286Sobrien	(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
1171490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
11715117404Skan   && (TARGET_SHIFT1 || optimize_size)
1171690286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1171790286Sobrien  "sar{l}\t%k0"
1171890286Sobrien  [(set_attr "type" "ishift")
1171990286Sobrien   (set_attr "length" "2")])
1172090286Sobrien
1172190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1172290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1172390286Sobrien;; zero are optimized away.
1172490286Sobrien(define_insn "*ashrsi3_cmp"
11725169699Skan  [(set (reg FLAGS_REG)
1172690286Sobrien	(compare
1172790286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11728169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1172990286Sobrien	  (const_int 0)))
1173090286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1173190286Sobrien	(ashiftrt:SI (match_dup 1) (match_dup 2)))]
1173290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11733169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11734169699Skan   && (optimize_size
11735169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1173690286Sobrien  "sar{l}\t{%2, %0|%0, %2}"
1173790286Sobrien  [(set_attr "type" "ishift")
1173890286Sobrien   (set_attr "mode" "SI")])
1173990286Sobrien
11740169699Skan(define_insn "*ashrsi3_cconly"
11741169699Skan  [(set (reg FLAGS_REG)
11742169699Skan	(compare
11743169699Skan	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11744169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11745169699Skan	  (const_int 0)))
11746169699Skan   (clobber (match_scratch:SI 0 "=r"))]
11747169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11748169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11749169699Skan   && (optimize_size
11750169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11751169699Skan  "sar{l}\t{%2, %0|%0, %2}"
11752169699Skan  [(set_attr "type" "ishift")
11753169699Skan   (set_attr "mode" "SI")])
11754169699Skan
1175590286Sobrien(define_insn "*ashrsi3_cmp_zext"
11756169699Skan  [(set (reg FLAGS_REG)
1175790286Sobrien	(compare
1175890286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11759169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1176090286Sobrien	  (const_int 0)))
1176190286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1176290286Sobrien	(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
1176390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11764169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11765169699Skan   && (optimize_size
11766169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1176790286Sobrien  "sar{l}\t{%2, %k0|%k0, %2}"
1176890286Sobrien  [(set_attr "type" "ishift")
1176990286Sobrien   (set_attr "mode" "SI")])
1177090286Sobrien
1177190286Sobrien(define_expand "ashrhi3"
1177290286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1177390286Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
1177490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11775169699Skan   (clobber (reg:CC FLAGS_REG))]
1177690286Sobrien  "TARGET_HIMODE_MATH"
1177790286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, HImode, operands); DONE;")
1177890286Sobrien
1177990286Sobrien(define_insn "*ashrhi3_1_one_bit"
1178050650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1178150650Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11782132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11783169699Skan   (clobber (reg:CC FLAGS_REG))]
1178490286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11785117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1178690286Sobrien  "sar{w}\t%0"
1178790286Sobrien  [(set_attr "type" "ishift")
11788259563Spfg   (set (attr "length")
11789259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1179090286Sobrien	(const_string "2")
1179190286Sobrien	(const_string "*")))])
1179218334Speter
1179390286Sobrien(define_insn "*ashrhi3_1"
1179490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1179590286Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1179690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11797169699Skan   (clobber (reg:CC FLAGS_REG))]
1179890286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
1179990286Sobrien  "@
1180090286Sobrien   sar{w}\t{%2, %0|%0, %2}
1180190286Sobrien   sar{w}\t{%b2, %0|%0, %b2}"
1180290286Sobrien  [(set_attr "type" "ishift")
1180390286Sobrien   (set_attr "mode" "HI")])
1180490286Sobrien
1180590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1180690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1180790286Sobrien;; zero are optimized away.
1180890286Sobrien(define_insn "*ashrhi3_one_bit_cmp"
11809169699Skan  [(set (reg FLAGS_REG)
1181090286Sobrien	(compare
1181190286Sobrien	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11812132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1181390286Sobrien	  (const_int 0)))
1181490286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1181590286Sobrien	(ashiftrt:HI (match_dup 1) (match_dup 2)))]
1181690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11817117404Skan   && (TARGET_SHIFT1 || optimize_size)
1181890286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
1181990286Sobrien  "sar{w}\t%0"
1182090286Sobrien  [(set_attr "type" "ishift")
11821259563Spfg   (set (attr "length")
11822259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1182390286Sobrien	(const_string "2")
1182490286Sobrien	(const_string "*")))])
1182590286Sobrien
11826169699Skan(define_insn "*ashrhi3_one_bit_cconly"
11827169699Skan  [(set (reg FLAGS_REG)
11828169699Skan	(compare
11829169699Skan	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11830169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11831169699Skan	  (const_int 0)))
11832169699Skan   (clobber (match_scratch:HI 0 "=r"))]
11833169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11834169699Skan   && (TARGET_SHIFT1 || optimize_size)
11835169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
11836169699Skan  "sar{w}\t%0"
11837169699Skan  [(set_attr "type" "ishift")
11838169699Skan   (set_attr "length" "2")])
11839169699Skan
1184090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1184190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1184290286Sobrien;; zero are optimized away.
1184390286Sobrien(define_insn "*ashrhi3_cmp"
11844169699Skan  [(set (reg FLAGS_REG)
1184590286Sobrien	(compare
1184690286Sobrien	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11847169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1184890286Sobrien	  (const_int 0)))
1184990286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1185090286Sobrien	(ashiftrt:HI (match_dup 1) (match_dup 2)))]
1185190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11852169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11853169699Skan   && (optimize_size
11854169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1185590286Sobrien  "sar{w}\t{%2, %0|%0, %2}"
1185690286Sobrien  [(set_attr "type" "ishift")
1185790286Sobrien   (set_attr "mode" "HI")])
1185890286Sobrien
11859169699Skan(define_insn "*ashrhi3_cconly"
11860169699Skan  [(set (reg FLAGS_REG)
11861169699Skan	(compare
11862169699Skan	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11863169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11864169699Skan	  (const_int 0)))
11865169699Skan   (clobber (match_scratch:HI 0 "=r"))]
11866169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11867169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11868169699Skan   && (optimize_size
11869169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11870169699Skan  "sar{w}\t{%2, %0|%0, %2}"
11871169699Skan  [(set_attr "type" "ishift")
11872169699Skan   (set_attr "mode" "HI")])
11873169699Skan
1187490286Sobrien(define_expand "ashrqi3"
1187590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1187690286Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
1187790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11878169699Skan   (clobber (reg:CC FLAGS_REG))]
1187990286Sobrien  "TARGET_QIMODE_MATH"
1188090286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, QImode, operands); DONE;")
1188190286Sobrien
1188290286Sobrien(define_insn "*ashrqi3_1_one_bit"
1188350650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1188450650Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11885132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11886169699Skan   (clobber (reg:CC FLAGS_REG))]
1188790286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11888117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1188990286Sobrien  "sar{b}\t%0"
1189090286Sobrien  [(set_attr "type" "ishift")
11891259563Spfg   (set (attr "length")
11892259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1189390286Sobrien	(const_string "2")
1189490286Sobrien	(const_string "*")))])
1189590286Sobrien
11896117404Skan(define_insn "*ashrqi3_1_one_bit_slp"
11897117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
11898117404Skan	(ashiftrt:QI (match_dup 0)
11899132727Skan		     (match_operand:QI 1 "const1_operand" "")))
11900169699Skan   (clobber (reg:CC FLAGS_REG))]
11901117404Skan  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11902117404Skan   && (! TARGET_PARTIAL_REG_STALL || optimize_size)
11903117404Skan   && (TARGET_SHIFT1 || optimize_size)"
11904117404Skan  "sar{b}\t%0"
11905117404Skan  [(set_attr "type" "ishift1")
11906259563Spfg   (set (attr "length")
11907259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
11908117404Skan	(const_string "2")
11909117404Skan	(const_string "*")))])
11910117404Skan
1191190286Sobrien(define_insn "*ashrqi3_1"
1191290286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1191390286Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1191490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11915169699Skan   (clobber (reg:CC FLAGS_REG))]
1191690286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
1191790286Sobrien  "@
1191890286Sobrien   sar{b}\t{%2, %0|%0, %2}
1191990286Sobrien   sar{b}\t{%b2, %0|%0, %b2}"
1192090286Sobrien  [(set_attr "type" "ishift")
1192190286Sobrien   (set_attr "mode" "QI")])
1192290286Sobrien
11923117404Skan(define_insn "*ashrqi3_1_slp"
11924117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
11925117404Skan	(ashiftrt:QI (match_dup 0)
11926117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
11927169699Skan   (clobber (reg:CC FLAGS_REG))]
11928117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
11929117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
11930117404Skan  "@
11931117404Skan   sar{b}\t{%1, %0|%0, %1}
11932117404Skan   sar{b}\t{%b1, %0|%0, %b1}"
11933117404Skan  [(set_attr "type" "ishift1")
11934117404Skan   (set_attr "mode" "QI")])
11935117404Skan
1193690286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1193790286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1193890286Sobrien;; zero are optimized away.
1193990286Sobrien(define_insn "*ashrqi3_one_bit_cmp"
11940169699Skan  [(set (reg FLAGS_REG)
1194190286Sobrien	(compare
1194290286Sobrien	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11943132727Skan		       (match_operand:QI 2 "const1_operand" "I"))
1194490286Sobrien	  (const_int 0)))
11945102802Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1194690286Sobrien	(ashiftrt:QI (match_dup 1) (match_dup 2)))]
1194790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11948117404Skan   && (TARGET_SHIFT1 || optimize_size)
1194990286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
1195090286Sobrien  "sar{b}\t%0"
1195190286Sobrien  [(set_attr "type" "ishift")
11952259563Spfg   (set (attr "length")
11953259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1195490286Sobrien	(const_string "2")
1195590286Sobrien	(const_string "*")))])
1195690286Sobrien
11957169699Skan(define_insn "*ashrqi3_one_bit_cconly"
11958169699Skan  [(set (reg FLAGS_REG)
11959169699Skan	(compare
11960169699Skan	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11961169699Skan		       (match_operand:QI 2 "const1_operand" "I"))
11962169699Skan	  (const_int 0)))
11963169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11964169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11965169699Skan   && (TARGET_SHIFT1 || optimize_size)
11966169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
11967169699Skan  "sar{b}\t%0"
11968169699Skan  [(set_attr "type" "ishift")
11969169699Skan   (set_attr "length" "2")])
11970169699Skan
1197190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1197290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1197390286Sobrien;; zero are optimized away.
1197490286Sobrien(define_insn "*ashrqi3_cmp"
11975169699Skan  [(set (reg FLAGS_REG)
1197690286Sobrien	(compare
1197790286Sobrien	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11978169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1197990286Sobrien	  (const_int 0)))
11980102802Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1198190286Sobrien	(ashiftrt:QI (match_dup 1) (match_dup 2)))]
1198290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11983169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11984169699Skan   && (optimize_size
11985169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1198690286Sobrien  "sar{b}\t{%2, %0|%0, %2}"
1198790286Sobrien  [(set_attr "type" "ishift")
1198890286Sobrien   (set_attr "mode" "QI")])
11989169699Skan
11990169699Skan(define_insn "*ashrqi3_cconly"
11991169699Skan  [(set (reg FLAGS_REG)
11992169699Skan	(compare
11993169699Skan	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11994169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11995169699Skan	  (const_int 0)))
11996169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11997169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11998169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11999169699Skan   && (optimize_size
12000169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12001169699Skan  "sar{b}\t{%2, %0|%0, %2}"
12002169699Skan  [(set_attr "type" "ishift")
12003169699Skan   (set_attr "mode" "QI")])
12004169699Skan
1200518334Speter
1200690286Sobrien;; Logical shift instructions
1200718334Speter
1200818334Speter;; See comment above `ashldi3' about how this works.
1200918334Speter
12010169699Skan(define_expand "lshrti3"
12011169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
12012169699Skan		   (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
1201390286Sobrien			        (match_operand:QI 2 "nonmemory_operand" "")))
12014169699Skan	      (clobber (reg:CC FLAGS_REG))])]
12015169699Skan  "TARGET_64BIT"
1201618334Speter{
12017169699Skan  if (! immediate_operand (operands[2], QImode))
1201818334Speter    {
12019169699Skan      emit_insn (gen_lshrti3_1 (operands[0], operands[1], operands[2]));
1202090286Sobrien      DONE;
1202118334Speter    }
12022169699Skan  ix86_expand_binary_operator (LSHIFTRT, TImode, operands);
1202318334Speter  DONE;
1202490286Sobrien})
1202518334Speter
12026169699Skan(define_insn "lshrti3_1"
12027169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
12028169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
12029169699Skan		     (match_operand:QI 2 "register_operand" "c")))
12030169699Skan   (clobber (match_scratch:DI 3 "=&r"))
12031169699Skan   (clobber (reg:CC FLAGS_REG))]
12032169699Skan  "TARGET_64BIT"
12033169699Skan  "#"
12034169699Skan  [(set_attr "type" "multi")])
12035169699Skan
12036169699Skan(define_insn "*lshrti3_2"
12037169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
12038169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
12039169699Skan		     (match_operand:QI 2 "immediate_operand" "O")))
12040169699Skan   (clobber (reg:CC FLAGS_REG))]
12041169699Skan  "TARGET_64BIT"
12042169699Skan  "#"
12043169699Skan  [(set_attr "type" "multi")])
12044169699Skan
12045259563Spfg(define_split
12046169699Skan  [(set (match_operand:TI 0 "register_operand" "")
12047169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "")
12048169699Skan		     (match_operand:QI 2 "register_operand" "")))
12049169699Skan   (clobber (match_scratch:DI 3 ""))
12050169699Skan   (clobber (reg:CC FLAGS_REG))]
12051169699Skan  "TARGET_64BIT && reload_completed"
12052169699Skan  [(const_int 0)]
12053169699Skan  "ix86_split_lshr (operands, operands[3], TImode); DONE;")
12054169699Skan
12055259563Spfg(define_split
12056169699Skan  [(set (match_operand:TI 0 "register_operand" "")
12057169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "")
12058169699Skan		     (match_operand:QI 2 "immediate_operand" "")))
12059169699Skan   (clobber (reg:CC FLAGS_REG))]
12060169699Skan  "TARGET_64BIT && reload_completed"
12061169699Skan  [(const_int 0)]
12062169699Skan  "ix86_split_lshr (operands, NULL_RTX, TImode); DONE;")
12063169699Skan
12064169699Skan(define_expand "lshrdi3"
12065169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
12066169699Skan	(lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
12067169699Skan		     (match_operand:QI 2 "nonmemory_operand" "")))]
12068169699Skan  ""
12069169699Skan  "ix86_expand_binary_operator (LSHIFTRT, DImode, operands); DONE;")
12070169699Skan
1207190286Sobrien(define_insn "*lshrdi3_1_one_bit_rex64"
1207290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1207390286Sobrien	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12074132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12075169699Skan   (clobber (reg:CC FLAGS_REG))]
1207690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12077117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1207890286Sobrien  "shr{q}\t%0"
1207990286Sobrien  [(set_attr "type" "ishift")
12080259563Spfg   (set (attr "length")
12081259563Spfg     (if_then_else (match_operand:DI 0 "register_operand" "")
1208290286Sobrien	(const_string "2")
1208390286Sobrien	(const_string "*")))])
1208450650Sobrien
1208590286Sobrien(define_insn "*lshrdi3_1_rex64"
1208690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1208790286Sobrien	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1208890286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
12089169699Skan   (clobber (reg:CC FLAGS_REG))]
1209090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1209190286Sobrien  "@
1209290286Sobrien   shr{q}\t{%2, %0|%0, %2}
1209390286Sobrien   shr{q}\t{%b2, %0|%0, %b2}"
1209490286Sobrien  [(set_attr "type" "ishift")
1209590286Sobrien   (set_attr "mode" "DI")])
1209650650Sobrien
1209790286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1209890286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1209990286Sobrien;; zero are optimized away.
1210090286Sobrien(define_insn "*lshrdi3_cmp_one_bit_rex64"
12101169699Skan  [(set (reg FLAGS_REG)
1210290286Sobrien	(compare
1210390286Sobrien	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12104132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1210590286Sobrien	  (const_int 0)))
1210690286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1210790286Sobrien	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
1210890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12109117404Skan   && (TARGET_SHIFT1 || optimize_size)
1211090286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1211190286Sobrien  "shr{q}\t%0"
1211290286Sobrien  [(set_attr "type" "ishift")
12113259563Spfg   (set (attr "length")
12114259563Spfg     (if_then_else (match_operand:DI 0 "register_operand" "")
1211590286Sobrien	(const_string "2")
1211690286Sobrien	(const_string "*")))])
1211750650Sobrien
12118169699Skan(define_insn "*lshrdi3_cconly_one_bit_rex64"
12119169699Skan  [(set (reg FLAGS_REG)
12120169699Skan	(compare
12121169699Skan	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12122169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12123169699Skan	  (const_int 0)))
12124169699Skan   (clobber (match_scratch:DI 0 "=r"))]
12125169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12126169699Skan   && (TARGET_SHIFT1 || optimize_size)
12127169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12128169699Skan  "shr{q}\t%0"
12129169699Skan  [(set_attr "type" "ishift")
12130169699Skan   (set_attr "length" "2")])
12131169699Skan
1213290286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1213390286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1213490286Sobrien;; zero are optimized away.
1213590286Sobrien(define_insn "*lshrdi3_cmp_rex64"
12136169699Skan  [(set (reg FLAGS_REG)
1213790286Sobrien	(compare
1213890286Sobrien	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1213990286Sobrien		       (match_operand:QI 2 "const_int_operand" "e"))
1214090286Sobrien	  (const_int 0)))
1214190286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1214290286Sobrien	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
1214390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12144169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12145169699Skan   && (optimize_size
12146169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1214790286Sobrien  "shr{q}\t{%2, %0|%0, %2}"
1214890286Sobrien  [(set_attr "type" "ishift")
1214990286Sobrien   (set_attr "mode" "DI")])
1215050650Sobrien
12151169699Skan(define_insn "*lshrdi3_cconly_rex64"
12152169699Skan  [(set (reg FLAGS_REG)
12153169699Skan	(compare
12154169699Skan	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12155169699Skan		       (match_operand:QI 2 "const_int_operand" "e"))
12156169699Skan	  (const_int 0)))
12157169699Skan   (clobber (match_scratch:DI 0 "=r"))]
12158169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12159169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12160169699Skan   && (optimize_size
12161169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12162169699Skan  "shr{q}\t{%2, %0|%0, %2}"
12163169699Skan  [(set_attr "type" "ishift")
12164169699Skan   (set_attr "mode" "DI")])
1216518334Speter
12166169699Skan(define_insn "*lshrdi3_1"
1216790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1216890286Sobrien	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
1216990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "Jc")))
12170169699Skan   (clobber (reg:CC FLAGS_REG))]
1217190286Sobrien  "!TARGET_64BIT"
1217290286Sobrien  "#"
1217390286Sobrien  [(set_attr "type" "multi")])
1217418334Speter
12175169699Skan;; By default we don't ask for a scratch register, because when DImode
12176169699Skan;; values are manipulated, registers are already at a premium.  But if
12177169699Skan;; we have one handy, we won't turn it away.
12178169699Skan(define_peephole2
12179169699Skan  [(match_scratch:SI 3 "r")
12180169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
12181169699Skan		   (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
12182169699Skan			        (match_operand:QI 2 "nonmemory_operand" "")))
12183169699Skan	      (clobber (reg:CC FLAGS_REG))])
12184169699Skan   (match_dup 3)]
12185169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1218690286Sobrien  [(const_int 0)]
12187169699Skan  "ix86_split_lshr (operands, operands[3], DImode); DONE;")
1218818334Speter
12189259563Spfg(define_split
1219090286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1219190286Sobrien	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
1219290286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12193169699Skan   (clobber (reg:CC FLAGS_REG))]
12194169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
12195169699Skan		     ? flow2_completed : reload_completed)"
1219690286Sobrien  [(const_int 0)]
12197169699Skan  "ix86_split_lshr (operands, NULL_RTX, DImode); DONE;")
1219818334Speter
1219990286Sobrien(define_expand "lshrsi3"
1220090286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1220190286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
1220290286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12203169699Skan   (clobber (reg:CC FLAGS_REG))]
1220490286Sobrien  ""
1220590286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, SImode, operands); DONE;")
1220618334Speter
1220790286Sobrien(define_insn "*lshrsi3_1_one_bit"
1220890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1220990286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12210132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12211169699Skan   (clobber (reg:CC FLAGS_REG))]
1221290286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12213117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1221490286Sobrien  "shr{l}\t%0"
1221590286Sobrien  [(set_attr "type" "ishift")
12216259563Spfg   (set (attr "length")
12217259563Spfg     (if_then_else (match_operand:SI 0 "register_operand" "")
1221890286Sobrien	(const_string "2")
1221990286Sobrien	(const_string "*")))])
1222018334Speter
1222190286Sobrien(define_insn "*lshrsi3_1_one_bit_zext"
1222290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1222390286Sobrien	(lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0"))
12224132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12225169699Skan   (clobber (reg:CC FLAGS_REG))]
1222690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12227117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1222890286Sobrien  "shr{l}\t%k0"
1222990286Sobrien  [(set_attr "type" "ishift")
1223090286Sobrien   (set_attr "length" "2")])
1223118334Speter
1223290286Sobrien(define_insn "*lshrsi3_1"
1223390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1223490286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1223590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12236169699Skan   (clobber (reg:CC FLAGS_REG))]
1223790286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1223890286Sobrien  "@
1223990286Sobrien   shr{l}\t{%2, %0|%0, %2}
1224090286Sobrien   shr{l}\t{%b2, %0|%0, %b2}"
1224190286Sobrien  [(set_attr "type" "ishift")
1224290286Sobrien   (set_attr "mode" "SI")])
1224318334Speter
1224490286Sobrien(define_insn "*lshrsi3_1_zext"
1224590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1224690286Sobrien	(zero_extend:DI
1224790286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1224890286Sobrien		       (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12249169699Skan   (clobber (reg:CC FLAGS_REG))]
1225090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1225190286Sobrien  "@
1225290286Sobrien   shr{l}\t{%2, %k0|%k0, %2}
1225390286Sobrien   shr{l}\t{%b2, %k0|%k0, %b2}"
1225490286Sobrien  [(set_attr "type" "ishift")
1225590286Sobrien   (set_attr "mode" "SI")])
1225618334Speter
1225790286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1225890286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1225990286Sobrien;; zero are optimized away.
1226090286Sobrien(define_insn "*lshrsi3_one_bit_cmp"
12261169699Skan  [(set (reg FLAGS_REG)
1226290286Sobrien	(compare
1226390286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12264132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1226590286Sobrien	  (const_int 0)))
1226690286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1226790286Sobrien	(lshiftrt:SI (match_dup 1) (match_dup 2)))]
1226890286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12269117404Skan   && (TARGET_SHIFT1 || optimize_size)
1227090286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1227190286Sobrien  "shr{l}\t%0"
1227290286Sobrien  [(set_attr "type" "ishift")
12273259563Spfg   (set (attr "length")
12274259563Spfg     (if_then_else (match_operand:SI 0 "register_operand" "")
1227590286Sobrien	(const_string "2")
1227690286Sobrien	(const_string "*")))])
1227718334Speter
12278169699Skan(define_insn "*lshrsi3_one_bit_cconly"
12279169699Skan  [(set (reg FLAGS_REG)
12280169699Skan	(compare
12281169699Skan	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12282169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12283169699Skan	  (const_int 0)))
12284169699Skan   (clobber (match_scratch:SI 0 "=r"))]
12285169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12286169699Skan   && (TARGET_SHIFT1 || optimize_size)
12287169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12288169699Skan  "shr{l}\t%0"
12289169699Skan  [(set_attr "type" "ishift")
12290169699Skan   (set_attr "length" "2")])
12291169699Skan
1229290286Sobrien(define_insn "*lshrsi3_cmp_one_bit_zext"
12293169699Skan  [(set (reg FLAGS_REG)
1229490286Sobrien	(compare
1229590286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
12296132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1229790286Sobrien	  (const_int 0)))
1229890286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1229990286Sobrien	(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
1230090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12301117404Skan   && (TARGET_SHIFT1 || optimize_size)
1230290286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1230390286Sobrien  "shr{l}\t%k0"
1230490286Sobrien  [(set_attr "type" "ishift")
1230590286Sobrien   (set_attr "length" "2")])
1230618334Speter
1230790286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1230890286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1230990286Sobrien;; zero are optimized away.
1231090286Sobrien(define_insn "*lshrsi3_cmp"
12311169699Skan  [(set (reg FLAGS_REG)
1231290286Sobrien	(compare
1231390286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12314169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1231590286Sobrien	  (const_int 0)))
1231690286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1231790286Sobrien	(lshiftrt:SI (match_dup 1) (match_dup 2)))]
1231890286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12319169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12320169699Skan   && (optimize_size
12321169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1232290286Sobrien  "shr{l}\t{%2, %0|%0, %2}"
1232390286Sobrien  [(set_attr "type" "ishift")
1232490286Sobrien   (set_attr "mode" "SI")])
1232590286Sobrien
12326169699Skan(define_insn "*lshrsi3_cconly"
12327169699Skan  [(set (reg FLAGS_REG)
12328169699Skan      (compare
12329169699Skan	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12330169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
12331169699Skan        (const_int 0)))
12332169699Skan   (clobber (match_scratch:SI 0 "=r"))]
12333169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12334169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12335169699Skan   && (optimize_size
12336169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12337169699Skan  "shr{l}\t{%2, %0|%0, %2}"
12338169699Skan  [(set_attr "type" "ishift")
12339169699Skan   (set_attr "mode" "SI")])
12340169699Skan
1234190286Sobrien(define_insn "*lshrsi3_cmp_zext"
12342169699Skan  [(set (reg FLAGS_REG)
1234390286Sobrien	(compare
1234490286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
12345169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1234690286Sobrien	  (const_int 0)))
1234790286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1234890286Sobrien	(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
1234990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12350169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12351169699Skan   && (optimize_size
12352169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1235390286Sobrien  "shr{l}\t{%2, %k0|%k0, %2}"
1235490286Sobrien  [(set_attr "type" "ishift")
1235590286Sobrien   (set_attr "mode" "SI")])
1235690286Sobrien
1235790286Sobrien(define_expand "lshrhi3"
1235890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1235990286Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
1236090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12361169699Skan   (clobber (reg:CC FLAGS_REG))]
1236290286Sobrien  "TARGET_HIMODE_MATH"
1236390286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, HImode, operands); DONE;")
1236490286Sobrien
1236590286Sobrien(define_insn "*lshrhi3_1_one_bit"
1236650650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1236750650Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12368132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12369169699Skan   (clobber (reg:CC FLAGS_REG))]
1237090286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12371117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1237290286Sobrien  "shr{w}\t%0"
1237390286Sobrien  [(set_attr "type" "ishift")
12374259563Spfg   (set (attr "length")
12375259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1237690286Sobrien	(const_string "2")
1237790286Sobrien	(const_string "*")))])
1237818334Speter
1237990286Sobrien(define_insn "*lshrhi3_1"
1238090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1238190286Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1238290286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12383169699Skan   (clobber (reg:CC FLAGS_REG))]
1238490286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1238590286Sobrien  "@
1238690286Sobrien   shr{w}\t{%2, %0|%0, %2}
1238790286Sobrien   shr{w}\t{%b2, %0|%0, %b2}"
1238890286Sobrien  [(set_attr "type" "ishift")
1238990286Sobrien   (set_attr "mode" "HI")])
1239090286Sobrien
1239190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1239290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1239390286Sobrien;; zero are optimized away.
1239490286Sobrien(define_insn "*lshrhi3_one_bit_cmp"
12395169699Skan  [(set (reg FLAGS_REG)
1239690286Sobrien	(compare
1239790286Sobrien	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12398132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1239990286Sobrien	  (const_int 0)))
1240090286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1240190286Sobrien	(lshiftrt:HI (match_dup 1) (match_dup 2)))]
1240290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12403117404Skan   && (TARGET_SHIFT1 || optimize_size)
1240490286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1240590286Sobrien  "shr{w}\t%0"
1240690286Sobrien  [(set_attr "type" "ishift")
12407259563Spfg   (set (attr "length")
12408259563Spfg     (if_then_else (match_operand:SI 0 "register_operand" "")
1240990286Sobrien	(const_string "2")
1241090286Sobrien	(const_string "*")))])
1241190286Sobrien
12412169699Skan(define_insn "*lshrhi3_one_bit_cconly"
12413169699Skan  [(set (reg FLAGS_REG)
12414169699Skan	(compare
12415169699Skan	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12416169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12417169699Skan	  (const_int 0)))
12418169699Skan   (clobber (match_scratch:HI 0 "=r"))]
12419169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12420169699Skan   && (TARGET_SHIFT1 || optimize_size)
12421169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12422169699Skan  "shr{w}\t%0"
12423169699Skan  [(set_attr "type" "ishift")
12424169699Skan   (set_attr "length" "2")])
12425169699Skan
1242690286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1242790286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1242890286Sobrien;; zero are optimized away.
1242990286Sobrien(define_insn "*lshrhi3_cmp"
12430169699Skan  [(set (reg FLAGS_REG)
1243190286Sobrien	(compare
1243290286Sobrien	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12433169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1243490286Sobrien	  (const_int 0)))
1243590286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1243690286Sobrien	(lshiftrt:HI (match_dup 1) (match_dup 2)))]
1243790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12438169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12439169699Skan   && (optimize_size
12440169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1244190286Sobrien  "shr{w}\t{%2, %0|%0, %2}"
1244290286Sobrien  [(set_attr "type" "ishift")
1244390286Sobrien   (set_attr "mode" "HI")])
1244490286Sobrien
12445169699Skan(define_insn "*lshrhi3_cconly"
12446169699Skan  [(set (reg FLAGS_REG)
12447169699Skan	(compare
12448169699Skan	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12449169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
12450169699Skan	  (const_int 0)))
12451169699Skan   (clobber (match_scratch:HI 0 "=r"))]
12452169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12453169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12454169699Skan   && (optimize_size
12455169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12456169699Skan  "shr{w}\t{%2, %0|%0, %2}"
12457169699Skan  [(set_attr "type" "ishift")
12458169699Skan   (set_attr "mode" "HI")])
12459169699Skan
1246090286Sobrien(define_expand "lshrqi3"
1246190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1246290286Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
1246390286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12464169699Skan   (clobber (reg:CC FLAGS_REG))]
1246590286Sobrien  "TARGET_QIMODE_MATH"
1246690286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, QImode, operands); DONE;")
1246790286Sobrien
1246890286Sobrien(define_insn "*lshrqi3_1_one_bit"
1246950650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1247050650Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12471132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12472169699Skan   (clobber (reg:CC FLAGS_REG))]
1247390286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12474117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1247590286Sobrien  "shr{b}\t%0"
1247690286Sobrien  [(set_attr "type" "ishift")
12477259563Spfg   (set (attr "length")
12478259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1247990286Sobrien	(const_string "2")
1248090286Sobrien	(const_string "*")))])
1248190286Sobrien
12482117404Skan(define_insn "*lshrqi3_1_one_bit_slp"
12483117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12484117404Skan	(lshiftrt:QI (match_dup 0)
12485132727Skan		     (match_operand:QI 1 "const1_operand" "")))
12486169699Skan   (clobber (reg:CC FLAGS_REG))]
12487117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12488117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12489117404Skan  "shr{b}\t%0"
12490117404Skan  [(set_attr "type" "ishift1")
12491259563Spfg   (set (attr "length")
12492259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
12493117404Skan	(const_string "2")
12494117404Skan	(const_string "*")))])
12495117404Skan
1249690286Sobrien(define_insn "*lshrqi3_1"
1249790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1249890286Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1249990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12500169699Skan   (clobber (reg:CC FLAGS_REG))]
1250190286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
1250290286Sobrien  "@
1250390286Sobrien   shr{b}\t{%2, %0|%0, %2}
1250490286Sobrien   shr{b}\t{%b2, %0|%0, %b2}"
1250590286Sobrien  [(set_attr "type" "ishift")
1250690286Sobrien   (set_attr "mode" "QI")])
1250790286Sobrien
12508117404Skan(define_insn "*lshrqi3_1_slp"
12509117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12510117404Skan	(lshiftrt:QI (match_dup 0)
12511117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
12512169699Skan   (clobber (reg:CC FLAGS_REG))]
12513117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12514117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12515117404Skan  "@
12516117404Skan   shr{b}\t{%1, %0|%0, %1}
12517117404Skan   shr{b}\t{%b1, %0|%0, %b1}"
12518117404Skan  [(set_attr "type" "ishift1")
12519117404Skan   (set_attr "mode" "QI")])
12520117404Skan
1252190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1252290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1252390286Sobrien;; zero are optimized away.
1252490286Sobrien(define_insn "*lshrqi2_one_bit_cmp"
12525169699Skan  [(set (reg FLAGS_REG)
1252690286Sobrien	(compare
1252790286Sobrien	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12528132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1252990286Sobrien	  (const_int 0)))
1253090286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1253190286Sobrien	(lshiftrt:QI (match_dup 1) (match_dup 2)))]
1253290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12533117404Skan   && (TARGET_SHIFT1 || optimize_size)
1253490286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
1253590286Sobrien  "shr{b}\t%0"
1253690286Sobrien  [(set_attr "type" "ishift")
12537259563Spfg   (set (attr "length")
12538259563Spfg     (if_then_else (match_operand:SI 0 "register_operand" "")
1253990286Sobrien	(const_string "2")
1254090286Sobrien	(const_string "*")))])
1254190286Sobrien
12542169699Skan(define_insn "*lshrqi2_one_bit_cconly"
12543169699Skan  [(set (reg FLAGS_REG)
12544169699Skan	(compare
12545169699Skan	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12546169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12547169699Skan	  (const_int 0)))
12548169699Skan   (clobber (match_scratch:QI 0 "=q"))]
12549169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12550169699Skan   && (TARGET_SHIFT1 || optimize_size)
12551169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
12552169699Skan  "shr{b}\t%0"
12553169699Skan  [(set_attr "type" "ishift")
12554169699Skan   (set_attr "length" "2")])
12555169699Skan
1255690286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1255790286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1255890286Sobrien;; zero are optimized away.
1255990286Sobrien(define_insn "*lshrqi2_cmp"
12560169699Skan  [(set (reg FLAGS_REG)
1256190286Sobrien	(compare
1256290286Sobrien	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12563169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1256490286Sobrien	  (const_int 0)))
1256590286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1256690286Sobrien	(lshiftrt:QI (match_dup 1) (match_dup 2)))]
1256790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12568169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12569169699Skan   && (optimize_size
12570169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1257190286Sobrien  "shr{b}\t{%2, %0|%0, %2}"
1257290286Sobrien  [(set_attr "type" "ishift")
1257390286Sobrien   (set_attr "mode" "QI")])
12574169699Skan
12575169699Skan(define_insn "*lshrqi2_cconly"
12576169699Skan  [(set (reg FLAGS_REG)
12577169699Skan	(compare
12578169699Skan	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12579169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
12580169699Skan	  (const_int 0)))
12581169699Skan   (clobber (match_scratch:QI 0 "=q"))]
12582169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12583169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12584169699Skan   && (optimize_size
12585169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12586169699Skan  "shr{b}\t{%2, %0|%0, %2}"
12587169699Skan  [(set_attr "type" "ishift")
12588169699Skan   (set_attr "mode" "QI")])
1258918334Speter
1259090286Sobrien;; Rotate instructions
1259118334Speter
1259290286Sobrien(define_expand "rotldi3"
12593169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
12594169699Skan	(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
1259590286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12596169699Skan   (clobber (reg:CC FLAGS_REG))]
12597169699Skan ""
12598169699Skan{
12599169699Skan  if (TARGET_64BIT)
12600169699Skan    {
12601169699Skan      ix86_expand_binary_operator (ROTATE, DImode, operands);
12602169699Skan      DONE;
12603169699Skan    }
12604169699Skan  if (!const_1_to_31_operand (operands[2], VOIDmode))
12605169699Skan    FAIL;
12606169699Skan  emit_insn (gen_ix86_rotldi3 (operands[0], operands[1], operands[2]));
12607169699Skan  DONE;
12608169699Skan})
1260918334Speter
12610169699Skan;; Implement rotation using two double-precision shift instructions
12611259563Spfg;; and a scratch register.
12612169699Skan(define_insn_and_split "ix86_rotldi3"
12613169699Skan [(set (match_operand:DI 0 "register_operand" "=r")
12614169699Skan       (rotate:DI (match_operand:DI 1 "register_operand" "0")
12615169699Skan                  (match_operand:QI 2 "const_1_to_31_operand" "I")))
12616169699Skan  (clobber (reg:CC FLAGS_REG))
12617169699Skan  (clobber (match_scratch:SI 3 "=&r"))]
12618169699Skan "!TARGET_64BIT"
12619259563Spfg ""
12620169699Skan "&& reload_completed"
12621169699Skan [(set (match_dup 3) (match_dup 4))
12622169699Skan  (parallel
12623169699Skan   [(set (match_dup 4)
12624169699Skan         (ior:SI (ashift:SI (match_dup 4) (match_dup 2))
12625169699Skan                 (lshiftrt:SI (match_dup 5)
12626169699Skan                              (minus:QI (const_int 32) (match_dup 2)))))
12627169699Skan    (clobber (reg:CC FLAGS_REG))])
12628169699Skan  (parallel
12629169699Skan   [(set (match_dup 5)
12630169699Skan         (ior:SI (ashift:SI (match_dup 5) (match_dup 2))
12631169699Skan                 (lshiftrt:SI (match_dup 3)
12632169699Skan                              (minus:QI (const_int 32) (match_dup 2)))))
12633169699Skan    (clobber (reg:CC FLAGS_REG))])]
12634169699Skan "split_di (operands, 1, operands + 4, operands + 5);")
12635259563Spfg
1263690286Sobrien(define_insn "*rotlsi3_1_one_bit_rex64"
1263790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1263890286Sobrien	(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12639132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12640169699Skan   (clobber (reg:CC FLAGS_REG))]
1264190286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)
12642117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1264390286Sobrien  "rol{q}\t%0"
12644117404Skan  [(set_attr "type" "rotate")
12645259563Spfg   (set (attr "length")
12646259563Spfg     (if_then_else (match_operand:DI 0 "register_operand" "")
1264790286Sobrien	(const_string "2")
1264890286Sobrien	(const_string "*")))])
1264918334Speter
1265090286Sobrien(define_insn "*rotldi3_1_rex64"
1265190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1265290286Sobrien	(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1265390286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "e,c")))
12654169699Skan   (clobber (reg:CC FLAGS_REG))]
1265590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)"
1265690286Sobrien  "@
1265790286Sobrien   rol{q}\t{%2, %0|%0, %2}
1265890286Sobrien   rol{q}\t{%b2, %0|%0, %b2}"
12659117404Skan  [(set_attr "type" "rotate")
1266090286Sobrien   (set_attr "mode" "DI")])
1266190286Sobrien
1266290286Sobrien(define_expand "rotlsi3"
1266390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1266490286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "")
1266590286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12666169699Skan   (clobber (reg:CC FLAGS_REG))]
1266718334Speter  ""
1266890286Sobrien  "ix86_expand_binary_operator (ROTATE, SImode, operands); DONE;")
1266918334Speter
1267090286Sobrien(define_insn "*rotlsi3_1_one_bit"
1267150650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1267290286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12673132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12674169699Skan   (clobber (reg:CC FLAGS_REG))]
1267590286Sobrien  "ix86_binary_operator_ok (ROTATE, SImode, operands)
12676117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1267790286Sobrien  "rol{l}\t%0"
12678117404Skan  [(set_attr "type" "rotate")
12679259563Spfg   (set (attr "length")
12680259563Spfg     (if_then_else (match_operand:SI 0 "register_operand" "")
1268190286Sobrien	(const_string "2")
1268290286Sobrien	(const_string "*")))])
1268318334Speter
1268490286Sobrien(define_insn "*rotlsi3_1_one_bit_zext"
1268590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1268690286Sobrien	(zero_extend:DI
1268790286Sobrien	  (rotate:SI (match_operand:SI 1 "register_operand" "0")
12688132727Skan		     (match_operand:QI 2 "const1_operand" ""))))
12689169699Skan   (clobber (reg:CC FLAGS_REG))]
1269090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)
12691117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1269290286Sobrien  "rol{l}\t%k0"
12693117404Skan  [(set_attr "type" "rotate")
1269490286Sobrien   (set_attr "length" "2")])
1269518334Speter
1269690286Sobrien(define_insn "*rotlsi3_1"
1269790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1269890286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1269990286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12700169699Skan   (clobber (reg:CC FLAGS_REG))]
1270190286Sobrien  "ix86_binary_operator_ok (ROTATE, SImode, operands)"
1270290286Sobrien  "@
1270390286Sobrien   rol{l}\t{%2, %0|%0, %2}
1270490286Sobrien   rol{l}\t{%b2, %0|%0, %b2}"
12705117404Skan  [(set_attr "type" "rotate")
1270690286Sobrien   (set_attr "mode" "SI")])
1270718334Speter
1270890286Sobrien(define_insn "*rotlsi3_1_zext"
1270990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1271090286Sobrien	(zero_extend:DI
1271190286Sobrien	  (rotate:SI (match_operand:SI 1 "register_operand" "0,0")
1271290286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12713169699Skan   (clobber (reg:CC FLAGS_REG))]
1271490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)"
1271590286Sobrien  "@
1271690286Sobrien   rol{l}\t{%2, %k0|%k0, %2}
1271790286Sobrien   rol{l}\t{%b2, %k0|%k0, %b2}"
12718117404Skan  [(set_attr "type" "rotate")
1271990286Sobrien   (set_attr "mode" "SI")])
1272018334Speter
1272190286Sobrien(define_expand "rotlhi3"
1272290286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1272390286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "")
1272490286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12725169699Skan   (clobber (reg:CC FLAGS_REG))]
1272690286Sobrien  "TARGET_HIMODE_MATH"
1272790286Sobrien  "ix86_expand_binary_operator (ROTATE, HImode, operands); DONE;")
1272818334Speter
1272990286Sobrien(define_insn "*rotlhi3_1_one_bit"
1273090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1273190286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12732132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12733169699Skan   (clobber (reg:CC FLAGS_REG))]
1273490286Sobrien  "ix86_binary_operator_ok (ROTATE, HImode, operands)
12735117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1273690286Sobrien  "rol{w}\t%0"
12737117404Skan  [(set_attr "type" "rotate")
12738259563Spfg   (set (attr "length")
12739259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1274090286Sobrien	(const_string "2")
1274190286Sobrien	(const_string "*")))])
1274218334Speter
1274390286Sobrien(define_insn "*rotlhi3_1"
1274490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1274590286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1274690286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12747169699Skan   (clobber (reg:CC FLAGS_REG))]
1274890286Sobrien  "ix86_binary_operator_ok (ROTATE, HImode, operands)"
1274990286Sobrien  "@
1275090286Sobrien   rol{w}\t{%2, %0|%0, %2}
1275190286Sobrien   rol{w}\t{%b2, %0|%0, %b2}"
12752117404Skan  [(set_attr "type" "rotate")
1275390286Sobrien   (set_attr "mode" "HI")])
1275418334Speter
1275590286Sobrien(define_expand "rotlqi3"
1275690286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1275790286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "")
1275890286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12759169699Skan   (clobber (reg:CC FLAGS_REG))]
1276090286Sobrien  "TARGET_QIMODE_MATH"
1276190286Sobrien  "ix86_expand_binary_operator (ROTATE, QImode, operands); DONE;")
1276218334Speter
12763117404Skan(define_insn "*rotlqi3_1_one_bit_slp"
12764117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12765117404Skan	(rotate:QI (match_dup 0)
12766132727Skan		   (match_operand:QI 1 "const1_operand" "")))
12767169699Skan   (clobber (reg:CC FLAGS_REG))]
12768117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12769117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12770117404Skan  "rol{b}\t%0"
12771117404Skan  [(set_attr "type" "rotate1")
12772259563Spfg   (set (attr "length")
12773259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
12774117404Skan	(const_string "2")
12775117404Skan	(const_string "*")))])
12776117404Skan
1277790286Sobrien(define_insn "*rotlqi3_1_one_bit"
1277890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1277990286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12780132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12781169699Skan   (clobber (reg:CC FLAGS_REG))]
1278290286Sobrien  "ix86_binary_operator_ok (ROTATE, QImode, operands)
12783117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1278490286Sobrien  "rol{b}\t%0"
12785117404Skan  [(set_attr "type" "rotate")
12786259563Spfg   (set (attr "length")
12787259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1278890286Sobrien	(const_string "2")
1278990286Sobrien	(const_string "*")))])
1279018334Speter
12791117404Skan(define_insn "*rotlqi3_1_slp"
12792117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12793117404Skan	(rotate:QI (match_dup 0)
12794117404Skan		   (match_operand:QI 1 "nonmemory_operand" "I,c")))
12795169699Skan   (clobber (reg:CC FLAGS_REG))]
12796117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12797117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12798117404Skan  "@
12799117404Skan   rol{b}\t{%1, %0|%0, %1}
12800117404Skan   rol{b}\t{%b1, %0|%0, %b1}"
12801117404Skan  [(set_attr "type" "rotate1")
12802117404Skan   (set_attr "mode" "QI")])
12803117404Skan
1280490286Sobrien(define_insn "*rotlqi3_1"
1280590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1280690286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1280790286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12808169699Skan   (clobber (reg:CC FLAGS_REG))]
1280990286Sobrien  "ix86_binary_operator_ok (ROTATE, QImode, operands)"
1281090286Sobrien  "@
1281190286Sobrien   rol{b}\t{%2, %0|%0, %2}
1281290286Sobrien   rol{b}\t{%b2, %0|%0, %b2}"
12813117404Skan  [(set_attr "type" "rotate")
1281490286Sobrien   (set_attr "mode" "QI")])
1281518334Speter
1281690286Sobrien(define_expand "rotrdi3"
12817169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
12818169699Skan	(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
12819169699Skan		   (match_operand:QI 2 "nonmemory_operand" "")))
12820169699Skan   (clobber (reg:CC FLAGS_REG))]
12821169699Skan ""
12822169699Skan{
12823169699Skan  if (TARGET_64BIT)
12824169699Skan    {
12825169699Skan      ix86_expand_binary_operator (ROTATERT, DImode, operands);
12826169699Skan      DONE;
12827169699Skan    }
12828169699Skan  if (!const_1_to_31_operand (operands[2], VOIDmode))
12829169699Skan    FAIL;
12830169699Skan  emit_insn (gen_ix86_rotrdi3 (operands[0], operands[1], operands[2]));
12831169699Skan  DONE;
12832169699Skan})
12833259563Spfg
12834169699Skan;; Implement rotation using two double-precision shift instructions
12835259563Spfg;; and a scratch register.
12836169699Skan(define_insn_and_split "ix86_rotrdi3"
12837169699Skan [(set (match_operand:DI 0 "register_operand" "=r")
12838169699Skan       (rotatert:DI (match_operand:DI 1 "register_operand" "0")
12839169699Skan                    (match_operand:QI 2 "const_1_to_31_operand" "I")))
12840169699Skan  (clobber (reg:CC FLAGS_REG))
12841169699Skan  (clobber (match_scratch:SI 3 "=&r"))]
12842169699Skan "!TARGET_64BIT"
12843169699Skan ""
12844169699Skan "&& reload_completed"
12845169699Skan [(set (match_dup 3) (match_dup 4))
12846169699Skan  (parallel
12847169699Skan   [(set (match_dup 4)
12848169699Skan         (ior:SI (ashiftrt:SI (match_dup 4) (match_dup 2))
12849169699Skan                 (ashift:SI (match_dup 5)
12850169699Skan                            (minus:QI (const_int 32) (match_dup 2)))))
12851169699Skan    (clobber (reg:CC FLAGS_REG))])
12852169699Skan  (parallel
12853169699Skan   [(set (match_dup 5)
12854169699Skan         (ior:SI (ashiftrt:SI (match_dup 5) (match_dup 2))
12855169699Skan                 (ashift:SI (match_dup 3)
12856169699Skan                            (minus:QI (const_int 32) (match_dup 2)))))
12857169699Skan    (clobber (reg:CC FLAGS_REG))])]
12858169699Skan "split_di (operands, 1, operands + 4, operands + 5);")
1285918334Speter
1286090286Sobrien(define_insn "*rotrdi3_1_one_bit_rex64"
1286190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1286290286Sobrien	(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12863132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12864169699Skan   (clobber (reg:CC FLAGS_REG))]
1286590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)
12866117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1286790286Sobrien  "ror{q}\t%0"
12868117404Skan  [(set_attr "type" "rotate")
12869259563Spfg   (set (attr "length")
12870259563Spfg     (if_then_else (match_operand:DI 0 "register_operand" "")
1287190286Sobrien	(const_string "2")
1287290286Sobrien	(const_string "*")))])
1287318334Speter
1287490286Sobrien(define_insn "*rotrdi3_1_rex64"
1287590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1287690286Sobrien	(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1287790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
12878169699Skan   (clobber (reg:CC FLAGS_REG))]
1287990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)"
1288090286Sobrien  "@
1288190286Sobrien   ror{q}\t{%2, %0|%0, %2}
1288290286Sobrien   ror{q}\t{%b2, %0|%0, %b2}"
12883117404Skan  [(set_attr "type" "rotate")
1288490286Sobrien   (set_attr "mode" "DI")])
1288590286Sobrien
1288690286Sobrien(define_expand "rotrsi3"
1288790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1288890286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "")
1288990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12890169699Skan   (clobber (reg:CC FLAGS_REG))]
1289190286Sobrien  ""
1289290286Sobrien  "ix86_expand_binary_operator (ROTATERT, SImode, operands); DONE;")
1289390286Sobrien
1289490286Sobrien(define_insn "*rotrsi3_1_one_bit"
1289550650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1289690286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12897132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12898169699Skan   (clobber (reg:CC FLAGS_REG))]
1289990286Sobrien  "ix86_binary_operator_ok (ROTATERT, SImode, operands)
12900117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1290190286Sobrien  "ror{l}\t%0"
12902117404Skan  [(set_attr "type" "rotate")
12903259563Spfg   (set (attr "length")
12904259563Spfg     (if_then_else (match_operand:SI 0 "register_operand" "")
1290590286Sobrien	(const_string "2")
1290690286Sobrien	(const_string "*")))])
1290718334Speter
1290890286Sobrien(define_insn "*rotrsi3_1_one_bit_zext"
1290990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1291090286Sobrien	(zero_extend:DI
1291190286Sobrien	  (rotatert:SI (match_operand:SI 1 "register_operand" "0")
12912132727Skan		       (match_operand:QI 2 "const1_operand" ""))))
12913169699Skan   (clobber (reg:CC FLAGS_REG))]
1291490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)
12915117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1291690286Sobrien  "ror{l}\t%k0"
12917117404Skan  [(set_attr "type" "rotate")
12918259563Spfg   (set (attr "length")
12919259563Spfg     (if_then_else (match_operand:SI 0 "register_operand" "")
1292090286Sobrien	(const_string "2")
1292190286Sobrien	(const_string "*")))])
1292218334Speter
1292390286Sobrien(define_insn "*rotrsi3_1"
1292490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1292590286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1292690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12927169699Skan   (clobber (reg:CC FLAGS_REG))]
1292890286Sobrien  "ix86_binary_operator_ok (ROTATERT, SImode, operands)"
1292990286Sobrien  "@
1293090286Sobrien   ror{l}\t{%2, %0|%0, %2}
1293190286Sobrien   ror{l}\t{%b2, %0|%0, %b2}"
12932117404Skan  [(set_attr "type" "rotate")
1293390286Sobrien   (set_attr "mode" "SI")])
1293418334Speter
1293590286Sobrien(define_insn "*rotrsi3_1_zext"
1293690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1293790286Sobrien	(zero_extend:DI
1293890286Sobrien	  (rotatert:SI (match_operand:SI 1 "register_operand" "0,0")
1293990286Sobrien		       (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12940169699Skan   (clobber (reg:CC FLAGS_REG))]
1294190286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)"
1294290286Sobrien  "@
1294390286Sobrien   ror{l}\t{%2, %k0|%k0, %2}
1294490286Sobrien   ror{l}\t{%b2, %k0|%k0, %b2}"
12945117404Skan  [(set_attr "type" "rotate")
1294690286Sobrien   (set_attr "mode" "SI")])
1294718334Speter
1294890286Sobrien(define_expand "rotrhi3"
1294990286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1295090286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "")
1295190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12952169699Skan   (clobber (reg:CC FLAGS_REG))]
1295390286Sobrien  "TARGET_HIMODE_MATH"
1295490286Sobrien  "ix86_expand_binary_operator (ROTATERT, HImode, operands); DONE;")
1295518334Speter
1295690286Sobrien(define_insn "*rotrhi3_one_bit"
1295790286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1295890286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12959132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12960169699Skan   (clobber (reg:CC FLAGS_REG))]
1296190286Sobrien  "ix86_binary_operator_ok (ROTATERT, HImode, operands)
12962117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1296390286Sobrien  "ror{w}\t%0"
12964117404Skan  [(set_attr "type" "rotate")
12965259563Spfg   (set (attr "length")
12966259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1296790286Sobrien	(const_string "2")
1296890286Sobrien	(const_string "*")))])
1296918334Speter
1297090286Sobrien(define_insn "*rotrhi3"
1297190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1297290286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1297390286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12974169699Skan   (clobber (reg:CC FLAGS_REG))]
1297590286Sobrien  "ix86_binary_operator_ok (ROTATERT, HImode, operands)"
1297690286Sobrien  "@
1297790286Sobrien   ror{w}\t{%2, %0|%0, %2}
1297890286Sobrien   ror{w}\t{%b2, %0|%0, %b2}"
12979117404Skan  [(set_attr "type" "rotate")
1298090286Sobrien   (set_attr "mode" "HI")])
1298118334Speter
1298290286Sobrien(define_expand "rotrqi3"
1298390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1298490286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "")
1298590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12986169699Skan   (clobber (reg:CC FLAGS_REG))]
1298790286Sobrien  "TARGET_QIMODE_MATH"
1298890286Sobrien  "ix86_expand_binary_operator (ROTATERT, QImode, operands); DONE;")
1298918334Speter
1299090286Sobrien(define_insn "*rotrqi3_1_one_bit"
1299190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1299290286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12993132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12994169699Skan   (clobber (reg:CC FLAGS_REG))]
1299590286Sobrien  "ix86_binary_operator_ok (ROTATERT, QImode, operands)
12996117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1299790286Sobrien  "ror{b}\t%0"
12998117404Skan  [(set_attr "type" "rotate")
12999259563Spfg   (set (attr "length")
13000259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
1300190286Sobrien	(const_string "2")
1300290286Sobrien	(const_string "*")))])
1300318334Speter
13004117404Skan(define_insn "*rotrqi3_1_one_bit_slp"
13005117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
13006117404Skan	(rotatert:QI (match_dup 0)
13007132727Skan		     (match_operand:QI 1 "const1_operand" "")))
13008169699Skan   (clobber (reg:CC FLAGS_REG))]
13009117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
13010117404Skan   && (TARGET_SHIFT1 || optimize_size)"
13011117404Skan  "ror{b}\t%0"
13012117404Skan  [(set_attr "type" "rotate1")
13013259563Spfg   (set (attr "length")
13014259563Spfg     (if_then_else (match_operand 0 "register_operand" "")
13015117404Skan	(const_string "2")
13016117404Skan	(const_string "*")))])
13017117404Skan
1301890286Sobrien(define_insn "*rotrqi3_1"
1301990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1302090286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1302190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
13022169699Skan   (clobber (reg:CC FLAGS_REG))]
1302390286Sobrien  "ix86_binary_operator_ok (ROTATERT, QImode, operands)"
1302490286Sobrien  "@
1302590286Sobrien   ror{b}\t{%2, %0|%0, %2}
1302690286Sobrien   ror{b}\t{%b2, %0|%0, %b2}"
13027117404Skan  [(set_attr "type" "rotate")
1302890286Sobrien   (set_attr "mode" "QI")])
13029117404Skan
13030117404Skan(define_insn "*rotrqi3_1_slp"
13031117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
13032117404Skan	(rotatert:QI (match_dup 0)
13033117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
13034169699Skan   (clobber (reg:CC FLAGS_REG))]
13035117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
13036117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
13037117404Skan  "@
13038117404Skan   ror{b}\t{%1, %0|%0, %1}
13039117404Skan   ror{b}\t{%b1, %0|%0, %b1}"
13040117404Skan  [(set_attr "type" "rotate1")
13041117404Skan   (set_attr "mode" "QI")])
1304290286Sobrien
1304390286Sobrien;; Bit set / bit test instructions
1304418334Speter
1304590286Sobrien(define_expand "extv"
1304690286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1304790286Sobrien	(sign_extract:SI (match_operand:SI 1 "register_operand" "")
13048169699Skan			 (match_operand:SI 2 "const8_operand" "")
13049169699Skan			 (match_operand:SI 3 "const8_operand" "")))]
1305090286Sobrien  ""
1305118334Speter{
1305290286Sobrien  /* Handle extractions from %ah et al.  */
1305390286Sobrien  if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8)
1305490286Sobrien    FAIL;
1305518334Speter
1305690286Sobrien  /* From mips.md: extract_bit_field doesn't verify that our source
1305790286Sobrien     matches the predicate, so check it again here.  */
13058169699Skan  if (! ext_register_operand (operands[1], VOIDmode))
1305990286Sobrien    FAIL;
1306090286Sobrien})
1306118334Speter
1306290286Sobrien(define_expand "extzv"
1306390286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1306490286Sobrien	(zero_extract:SI (match_operand 1 "ext_register_operand" "")
13065169699Skan			 (match_operand:SI 2 "const8_operand" "")
13066169699Skan			 (match_operand:SI 3 "const8_operand" "")))]
1306790286Sobrien  ""
1306890286Sobrien{
1306990286Sobrien  /* Handle extractions from %ah et al.  */
1307090286Sobrien  if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8)
1307190286Sobrien    FAIL;
1307218334Speter
1307390286Sobrien  /* From mips.md: extract_bit_field doesn't verify that our source
1307490286Sobrien     matches the predicate, so check it again here.  */
13075169699Skan  if (! ext_register_operand (operands[1], VOIDmode))
1307690286Sobrien    FAIL;
1307790286Sobrien})
1307818334Speter
1307990286Sobrien(define_expand "insv"
13080132727Skan  [(set (zero_extract (match_operand 0 "ext_register_operand" "")
13081169699Skan		      (match_operand 1 "const8_operand" "")
13082169699Skan		      (match_operand 2 "const8_operand" ""))
13083132727Skan        (match_operand 3 "register_operand" ""))]
1308490286Sobrien  ""
1308590286Sobrien{
13086169699Skan  /* Handle insertions to %ah et al.  */
1308790286Sobrien  if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8)
1308890286Sobrien    FAIL;
1308918334Speter
1309090286Sobrien  /* From mips.md: insert_bit_field doesn't verify that our source
1309190286Sobrien     matches the predicate, so check it again here.  */
13092169699Skan  if (! ext_register_operand (operands[0], VOIDmode))
1309390286Sobrien    FAIL;
13094132727Skan
13095132727Skan  if (TARGET_64BIT)
13096132727Skan    emit_insn (gen_movdi_insv_1_rex64 (operands[0], operands[3]));
13097132727Skan  else
13098132727Skan    emit_insn (gen_movsi_insv_1 (operands[0], operands[3]));
13099132727Skan
13100132727Skan  DONE;
1310190286Sobrien})
1310218334Speter
1310390286Sobrien;; %%% bts, btr, btc, bt.
13104169699Skan;; In general these instructions are *slow* when applied to memory,
13105169699Skan;; since they enforce atomic operation.  When applied to registers,
13106169699Skan;; it depends on the cpu implementation.  They're never faster than
13107169699Skan;; the corresponding and/ior/xor operations, so with 32-bit there's
13108169699Skan;; no point.  But in 64-bit, we can't hold the relevant immediates
13109169699Skan;; within the instruction itself, so operating on bits in the high
13110169699Skan;; 32-bits of a register becomes easier.
13111169699Skan;;
13112169699Skan;; These are slow on Nocona, but fast on Athlon64.  We do require the use
13113169699Skan;; of btrq and btcq for corner cases of post-reload expansion of absdf and
13114169699Skan;; negdf respectively, so they can never be disabled entirely.
13115169699Skan
13116169699Skan(define_insn "*btsq"
13117169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13118169699Skan			 (const_int 1)
13119169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13120169699Skan	(const_int 1))
13121169699Skan   (clobber (reg:CC FLAGS_REG))]
13122169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13123169699Skan  "bts{q} %1,%0"
13124169699Skan  [(set_attr "type" "alu1")])
13125169699Skan
13126169699Skan(define_insn "*btrq"
13127169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13128169699Skan			 (const_int 1)
13129169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13130169699Skan	(const_int 0))
13131169699Skan   (clobber (reg:CC FLAGS_REG))]
13132169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13133169699Skan  "btr{q} %1,%0"
13134169699Skan  [(set_attr "type" "alu1")])
13135169699Skan
13136169699Skan(define_insn "*btcq"
13137169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13138169699Skan			 (const_int 1)
13139169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13140169699Skan	(not:DI (zero_extract:DI (match_dup 0) (const_int 1) (match_dup 1))))
13141169699Skan   (clobber (reg:CC FLAGS_REG))]
13142169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13143169699Skan  "btc{q} %1,%0"
13144169699Skan  [(set_attr "type" "alu1")])
13145169699Skan
13146169699Skan;; Allow Nocona to avoid these instructions if a register is available.
13147169699Skan
13148169699Skan(define_peephole2
13149169699Skan  [(match_scratch:DI 2 "r")
13150169699Skan   (parallel [(set (zero_extract:DI
13151169699Skan		     (match_operand:DI 0 "register_operand" "")
13152169699Skan		     (const_int 1)
13153169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13154169699Skan		   (const_int 1))
13155169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13156169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13157169699Skan  [(const_int 0)]
13158169699Skan{
13159169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13160169699Skan  rtx op1;
13161169699Skan
13162169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13163169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13164169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13165169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13166169699Skan  else
13167169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13168169699Skan
13169169699Skan  op1 = immed_double_const (lo, hi, DImode);
13170169699Skan  if (i >= 31)
13171169699Skan    {
13172169699Skan      emit_move_insn (operands[2], op1);
13173169699Skan      op1 = operands[2];
13174169699Skan    }
13175169699Skan
13176169699Skan  emit_insn (gen_iordi3 (operands[0], operands[0], op1));
13177169699Skan  DONE;
13178169699Skan})
13179169699Skan
13180169699Skan(define_peephole2
13181169699Skan  [(match_scratch:DI 2 "r")
13182169699Skan   (parallel [(set (zero_extract:DI
13183169699Skan		     (match_operand:DI 0 "register_operand" "")
13184169699Skan		     (const_int 1)
13185169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13186169699Skan		   (const_int 0))
13187169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13188169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13189169699Skan  [(const_int 0)]
13190169699Skan{
13191169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13192169699Skan  rtx op1;
13193169699Skan
13194169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13195169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13196169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13197169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13198169699Skan  else
13199169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13200169699Skan
13201169699Skan  op1 = immed_double_const (~lo, ~hi, DImode);
13202169699Skan  if (i >= 32)
13203169699Skan    {
13204169699Skan      emit_move_insn (operands[2], op1);
13205169699Skan      op1 = operands[2];
13206169699Skan    }
13207169699Skan
13208169699Skan  emit_insn (gen_anddi3 (operands[0], operands[0], op1));
13209169699Skan  DONE;
13210169699Skan})
13211169699Skan
13212169699Skan(define_peephole2
13213169699Skan  [(match_scratch:DI 2 "r")
13214169699Skan   (parallel [(set (zero_extract:DI
13215169699Skan		     (match_operand:DI 0 "register_operand" "")
13216169699Skan		     (const_int 1)
13217169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13218169699Skan	      (not:DI (zero_extract:DI
13219169699Skan			(match_dup 0) (const_int 1) (match_dup 1))))
13220169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13221169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13222169699Skan  [(const_int 0)]
13223169699Skan{
13224169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13225169699Skan  rtx op1;
13226169699Skan
13227169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13228169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13229169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13230169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13231169699Skan  else
13232169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13233169699Skan
13234169699Skan  op1 = immed_double_const (lo, hi, DImode);
13235169699Skan  if (i >= 31)
13236169699Skan    {
13237169699Skan      emit_move_insn (operands[2], op1);
13238169699Skan      op1 = operands[2];
13239169699Skan    }
13240169699Skan
13241169699Skan  emit_insn (gen_xordi3 (operands[0], operands[0], op1));
13242169699Skan  DONE;
13243169699Skan})
1324418334Speter
1324518334Speter;; Store-flag instructions.
1324618334Speter
1324718334Speter;; For all sCOND expanders, also expand the compare or test insn that
1324818334Speter;; generates cc0.  Generate an equality comparison if `seq' or `sne'.
1324918334Speter
1325090286Sobrien;; %%% Do the expansion to SImode.  If PII, do things the xor+setcc way
1325190286Sobrien;; to avoid partial register stalls.  Otherwise do things the setcc+movzx
1325290286Sobrien;; way, which can later delete the movzx if only QImode is needed.
1325390286Sobrien
1325418334Speter(define_expand "seq"
1325590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13256169699Skan        (eq:QI (reg:CC FLAGS_REG) (const_int 0)))]
1325718334Speter  ""
1325890286Sobrien  "if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;")
1325918334Speter
1326018334Speter(define_expand "sne"
1326190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13262169699Skan        (ne:QI (reg:CC FLAGS_REG) (const_int 0)))]
1326318334Speter  ""
1326490286Sobrien  "if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;")
1326518334Speter
1326618334Speter(define_expand "sgt"
1326790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13268169699Skan        (gt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1326918334Speter  ""
1327090286Sobrien  "if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;")
1327118334Speter
1327218334Speter(define_expand "sgtu"
1327390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13274169699Skan        (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1327518334Speter  ""
1327690286Sobrien  "if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;")
1327718334Speter
1327818334Speter(define_expand "slt"
1327990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13280169699Skan        (lt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1328118334Speter  ""
1328290286Sobrien  "if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;")
1328318334Speter
1328418334Speter(define_expand "sltu"
1328590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13286169699Skan        (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1328718334Speter  ""
1328890286Sobrien  "if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;")
1328918334Speter
1329018334Speter(define_expand "sge"
1329190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13292169699Skan        (ge:QI (reg:CC FLAGS_REG) (const_int 0)))]
1329318334Speter  ""
1329490286Sobrien  "if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;")
1329518334Speter
1329618334Speter(define_expand "sgeu"
1329790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13298169699Skan        (geu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1329918334Speter  ""
1330090286Sobrien  "if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;")
1330118334Speter
1330218334Speter(define_expand "sle"
1330390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13304169699Skan        (le:QI (reg:CC FLAGS_REG) (const_int 0)))]
1330518334Speter  ""
1330690286Sobrien  "if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;")
1330718334Speter
1330818334Speter(define_expand "sleu"
1330990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13310169699Skan        (leu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1331118334Speter  ""
1331290286Sobrien  "if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;")
1331318334Speter
1331490286Sobrien(define_expand "sunordered"
1331590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13316169699Skan        (unordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
1331790286Sobrien  "TARGET_80387 || TARGET_SSE"
1331890286Sobrien  "if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;")
1331952296Sobrien
1332090286Sobrien(define_expand "sordered"
1332190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13322169699Skan        (ordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
1332390286Sobrien  "TARGET_80387"
1332490286Sobrien  "if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;")
1332590286Sobrien
1332690286Sobrien(define_expand "suneq"
1332790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13328169699Skan        (uneq:QI (reg:CC FLAGS_REG) (const_int 0)))]
1332990286Sobrien  "TARGET_80387 || TARGET_SSE"
1333090286Sobrien  "if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;")
1333190286Sobrien
1333290286Sobrien(define_expand "sunge"
1333390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13334169699Skan        (unge:QI (reg:CC FLAGS_REG) (const_int 0)))]
1333590286Sobrien  "TARGET_80387 || TARGET_SSE"
1333690286Sobrien  "if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;")
1333790286Sobrien
1333890286Sobrien(define_expand "sungt"
1333990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13340169699Skan        (ungt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1334190286Sobrien  "TARGET_80387 || TARGET_SSE"
1334290286Sobrien  "if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;")
1334390286Sobrien
1334490286Sobrien(define_expand "sunle"
1334590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13346169699Skan        (unle:QI (reg:CC FLAGS_REG) (const_int 0)))]
1334790286Sobrien  "TARGET_80387 || TARGET_SSE"
1334890286Sobrien  "if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;")
1334990286Sobrien
1335090286Sobrien(define_expand "sunlt"
1335190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13352169699Skan        (unlt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1335390286Sobrien  "TARGET_80387 || TARGET_SSE"
1335490286Sobrien  "if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;")
1335590286Sobrien
1335690286Sobrien(define_expand "sltgt"
1335790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13358169699Skan        (ltgt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1335990286Sobrien  "TARGET_80387 || TARGET_SSE"
1336090286Sobrien  "if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;")
1336190286Sobrien
1336290286Sobrien(define_insn "*setcc_1"
1336352296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1336490286Sobrien	(match_operator:QI 1 "ix86_comparison_operator"
13365169699Skan	  [(reg FLAGS_REG) (const_int 0)]))]
1336690286Sobrien  ""
1336790286Sobrien  "set%C1\t%0"
1336890286Sobrien  [(set_attr "type" "setcc")
1336990286Sobrien   (set_attr "mode" "QI")])
1337090286Sobrien
13371169699Skan(define_insn "*setcc_2"
1337290286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
1337390286Sobrien	(match_operator:QI 1 "ix86_comparison_operator"
13374169699Skan	  [(reg FLAGS_REG) (const_int 0)]))]
1337590286Sobrien  ""
1337690286Sobrien  "set%C1\t%0"
1337790286Sobrien  [(set_attr "type" "setcc")
1337890286Sobrien   (set_attr "mode" "QI")])
1337990286Sobrien
1338090286Sobrien;; In general it is not safe to assume too much about CCmode registers,
13381259563Spfg;; so simplify-rtx stops when it sees a second one.  Under certain
1338290286Sobrien;; conditions this is safe on x86, so help combine not create
1338390286Sobrien;;
1338490286Sobrien;;	seta	%al
1338590286Sobrien;;	testb	%al, %al
1338690286Sobrien;;	sete	%al
1338790286Sobrien
13388259563Spfg(define_split
1338990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1339090286Sobrien	(ne:QI (match_operator 1 "ix86_comparison_operator"
13391169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1339290286Sobrien	    (const_int 0)))]
1339390286Sobrien  ""
1339490286Sobrien  [(set (match_dup 0) (match_dup 1))]
1339552296Sobrien{
1339690286Sobrien  PUT_MODE (operands[1], QImode);
1339790286Sobrien})
1339852296Sobrien
13399259563Spfg(define_split
1340090286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
1340190286Sobrien	(ne:QI (match_operator 1 "ix86_comparison_operator"
13402169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1340390286Sobrien	    (const_int 0)))]
1340490286Sobrien  ""
1340590286Sobrien  [(set (match_dup 0) (match_dup 1))]
1340690286Sobrien{
1340790286Sobrien  PUT_MODE (operands[1], QImode);
1340890286Sobrien})
1340952296Sobrien
13410259563Spfg(define_split
1341190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1341290286Sobrien	(eq:QI (match_operator 1 "ix86_comparison_operator"
13413169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1341490286Sobrien	    (const_int 0)))]
1341590286Sobrien  ""
1341690286Sobrien  [(set (match_dup 0) (match_dup 1))]
1341790286Sobrien{
1341890286Sobrien  rtx new_op1 = copy_rtx (operands[1]);
1341990286Sobrien  operands[1] = new_op1;
1342090286Sobrien  PUT_MODE (new_op1, QImode);
13421169699Skan  PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
13422169699Skan					     GET_MODE (XEXP (new_op1, 0))));
1342390286Sobrien
1342490286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1342590286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1342690286Sobrien  if (! ix86_comparison_operator (new_op1, VOIDmode))
1342790286Sobrien    FAIL;
1342890286Sobrien})
1342990286Sobrien
13430259563Spfg(define_split
1343190286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
1343290286Sobrien	(eq:QI (match_operator 1 "ix86_comparison_operator"
13433169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1343490286Sobrien	    (const_int 0)))]
1343590286Sobrien  ""
1343690286Sobrien  [(set (match_dup 0) (match_dup 1))]
1343790286Sobrien{
1343890286Sobrien  rtx new_op1 = copy_rtx (operands[1]);
1343990286Sobrien  operands[1] = new_op1;
1344090286Sobrien  PUT_MODE (new_op1, QImode);
13441169699Skan  PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
13442169699Skan					     GET_MODE (XEXP (new_op1, 0))));
1344390286Sobrien
1344490286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1344590286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1344690286Sobrien  if (! ix86_comparison_operator (new_op1, VOIDmode))
1344790286Sobrien    FAIL;
1344890286Sobrien})
1344990286Sobrien
1345090286Sobrien;; The SSE store flag instructions saves 0 or 0xffffffff to the result.
1345190286Sobrien;; subsequent logical operations are used to imitate conditional moves.
1345290286Sobrien;; 0xffffffff is NaN, but not in normalized form, so we can't represent
13453169699Skan;; it directly.
1345490286Sobrien
1345590286Sobrien(define_insn "*sse_setccsf"
1345690286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1345790286Sobrien	(match_operator:SF 1 "sse_comparison_operator"
1345890286Sobrien	  [(match_operand:SF 2 "register_operand" "0")
1345990286Sobrien	   (match_operand:SF 3 "nonimmediate_operand" "xm")]))]
13460169699Skan  "TARGET_SSE"
1346190286Sobrien  "cmp%D1ss\t{%3, %0|%0, %3}"
13462117404Skan  [(set_attr "type" "ssecmp")
1346390286Sobrien   (set_attr "mode" "SF")])
1346490286Sobrien
1346590286Sobrien(define_insn "*sse_setccdf"
1346690286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1346790286Sobrien	(match_operator:DF 1 "sse_comparison_operator"
1346890286Sobrien	  [(match_operand:DF 2 "register_operand" "0")
1346990286Sobrien	   (match_operand:DF 3 "nonimmediate_operand" "Ym")]))]
13470169699Skan  "TARGET_SSE2"
1347190286Sobrien  "cmp%D1sd\t{%3, %0|%0, %3}"
13472117404Skan  [(set_attr "type" "ssecmp")
1347390286Sobrien   (set_attr "mode" "DF")])
1347418334Speter
1347518334Speter;; Basic conditional jump instructions.
1347618334Speter;; We ignore the overflow flag for signed branch instructions.
1347718334Speter
1347818334Speter;; For all bCOND expanders, also expand the compare or test insn that
13479169699Skan;; generates reg FLAGS_REG.  Generate an equality comparison if `beq' or `bne'.
1348018334Speter
1348118334Speter(define_expand "beq"
1348290286Sobrien  [(set (pc)
1348390286Sobrien	(if_then_else (match_dup 1)
1348418334Speter		      (label_ref (match_operand 0 "" ""))
1348518334Speter		      (pc)))]
1348618334Speter  ""
1348790286Sobrien  "ix86_expand_branch (EQ, operands[0]); DONE;")
1348818334Speter
1348918334Speter(define_expand "bne"
1349090286Sobrien  [(set (pc)
1349190286Sobrien	(if_then_else (match_dup 1)
1349218334Speter		      (label_ref (match_operand 0 "" ""))
1349318334Speter		      (pc)))]
1349418334Speter  ""
1349590286Sobrien  "ix86_expand_branch (NE, operands[0]); DONE;")
1349618334Speter
1349718334Speter(define_expand "bgt"
1349890286Sobrien  [(set (pc)
1349990286Sobrien	(if_then_else (match_dup 1)
1350018334Speter		      (label_ref (match_operand 0 "" ""))
1350118334Speter		      (pc)))]
1350218334Speter  ""
1350390286Sobrien  "ix86_expand_branch (GT, operands[0]); DONE;")
1350418334Speter
1350518334Speter(define_expand "bgtu"
1350690286Sobrien  [(set (pc)
1350790286Sobrien	(if_then_else (match_dup 1)
1350818334Speter		      (label_ref (match_operand 0 "" ""))
1350918334Speter		      (pc)))]
1351018334Speter  ""
1351190286Sobrien  "ix86_expand_branch (GTU, operands[0]); DONE;")
1351218334Speter
1351318334Speter(define_expand "blt"
1351490286Sobrien  [(set (pc)
1351590286Sobrien	(if_then_else (match_dup 1)
1351618334Speter		      (label_ref (match_operand 0 "" ""))
1351718334Speter		      (pc)))]
1351818334Speter  ""
1351990286Sobrien  "ix86_expand_branch (LT, operands[0]); DONE;")
1352018334Speter
1352118334Speter(define_expand "bltu"
1352290286Sobrien  [(set (pc)
1352390286Sobrien	(if_then_else (match_dup 1)
1352418334Speter		      (label_ref (match_operand 0 "" ""))
1352518334Speter		      (pc)))]
1352618334Speter  ""
1352790286Sobrien  "ix86_expand_branch (LTU, operands[0]); DONE;")
1352818334Speter
1352918334Speter(define_expand "bge"
1353090286Sobrien  [(set (pc)
1353190286Sobrien	(if_then_else (match_dup 1)
1353218334Speter		      (label_ref (match_operand 0 "" ""))
1353318334Speter		      (pc)))]
1353418334Speter  ""
1353590286Sobrien  "ix86_expand_branch (GE, operands[0]); DONE;")
1353618334Speter
1353718334Speter(define_expand "bgeu"
1353890286Sobrien  [(set (pc)
1353990286Sobrien	(if_then_else (match_dup 1)
1354018334Speter		      (label_ref (match_operand 0 "" ""))
1354118334Speter		      (pc)))]
1354218334Speter  ""
1354390286Sobrien  "ix86_expand_branch (GEU, operands[0]); DONE;")
1354418334Speter
1354518334Speter(define_expand "ble"
1354690286Sobrien  [(set (pc)
1354790286Sobrien	(if_then_else (match_dup 1)
1354818334Speter		      (label_ref (match_operand 0 "" ""))
1354918334Speter		      (pc)))]
1355018334Speter  ""
1355190286Sobrien  "ix86_expand_branch (LE, operands[0]); DONE;")
1355218334Speter
1355318334Speter(define_expand "bleu"
1355490286Sobrien  [(set (pc)
1355590286Sobrien	(if_then_else (match_dup 1)
1355618334Speter		      (label_ref (match_operand 0 "" ""))
1355718334Speter		      (pc)))]
1355818334Speter  ""
1355990286Sobrien  "ix86_expand_branch (LEU, operands[0]); DONE;")
1356018334Speter
1356190286Sobrien(define_expand "bunordered"
1356218334Speter  [(set (pc)
1356390286Sobrien	(if_then_else (match_dup 1)
1356490286Sobrien		      (label_ref (match_operand 0 "" ""))
1356518334Speter		      (pc)))]
13566169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1356790286Sobrien  "ix86_expand_branch (UNORDERED, operands[0]); DONE;")
1356818334Speter
1356990286Sobrien(define_expand "bordered"
1357090286Sobrien  [(set (pc)
1357190286Sobrien	(if_then_else (match_dup 1)
1357290286Sobrien		      (label_ref (match_operand 0 "" ""))
1357390286Sobrien		      (pc)))]
13574169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1357590286Sobrien  "ix86_expand_branch (ORDERED, operands[0]); DONE;")
1357618334Speter
1357790286Sobrien(define_expand "buneq"
1357818334Speter  [(set (pc)
1357990286Sobrien	(if_then_else (match_dup 1)
1358090286Sobrien		      (label_ref (match_operand 0 "" ""))
1358190286Sobrien		      (pc)))]
13582169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1358390286Sobrien  "ix86_expand_branch (UNEQ, operands[0]); DONE;")
1358418334Speter
1358590286Sobrien(define_expand "bunge"
1358690286Sobrien  [(set (pc)
1358790286Sobrien	(if_then_else (match_dup 1)
1358890286Sobrien		      (label_ref (match_operand 0 "" ""))
1358990286Sobrien		      (pc)))]
13590169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1359190286Sobrien  "ix86_expand_branch (UNGE, operands[0]); DONE;")
1359218334Speter
1359390286Sobrien(define_expand "bungt"
1359418334Speter  [(set (pc)
1359590286Sobrien	(if_then_else (match_dup 1)
1359690286Sobrien		      (label_ref (match_operand 0 "" ""))
1359790286Sobrien		      (pc)))]
13598169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1359990286Sobrien  "ix86_expand_branch (UNGT, operands[0]); DONE;")
1360018334Speter
1360190286Sobrien(define_expand "bunle"
1360290286Sobrien  [(set (pc)
1360390286Sobrien	(if_then_else (match_dup 1)
1360490286Sobrien		      (label_ref (match_operand 0 "" ""))
1360590286Sobrien		      (pc)))]
13606169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1360790286Sobrien  "ix86_expand_branch (UNLE, operands[0]); DONE;")
1360818334Speter
1360990286Sobrien(define_expand "bunlt"
1361090286Sobrien  [(set (pc)
1361190286Sobrien	(if_then_else (match_dup 1)
1361290286Sobrien		      (label_ref (match_operand 0 "" ""))
1361390286Sobrien		      (pc)))]
13614169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1361590286Sobrien  "ix86_expand_branch (UNLT, operands[0]); DONE;")
1361618334Speter
1361790286Sobrien(define_expand "bltgt"
1361890286Sobrien  [(set (pc)
1361990286Sobrien	(if_then_else (match_dup 1)
1362090286Sobrien		      (label_ref (match_operand 0 "" ""))
1362190286Sobrien		      (pc)))]
13622169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1362390286Sobrien  "ix86_expand_branch (LTGT, operands[0]); DONE;")
1362418334Speter
1362590286Sobrien(define_insn "*jcc_1"
1362690286Sobrien  [(set (pc)
1362790286Sobrien	(if_then_else (match_operator 1 "ix86_comparison_operator"
13628169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1362990286Sobrien		      (label_ref (match_operand 0 "" ""))
1363090286Sobrien		      (pc)))]
1363118334Speter  ""
1363290286Sobrien  "%+j%C1\t%l0"
1363390286Sobrien  [(set_attr "type" "ibr")
13634117404Skan   (set_attr "modrm" "0")
13635117404Skan   (set (attr "length")
1363690286Sobrien	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13637117404Skan				  (const_int -126))
1363890286Sobrien			      (lt (minus (match_dup 0) (pc))
13639117404Skan				  (const_int 128)))
13640117404Skan	     (const_int 2)
13641117404Skan	     (const_int 6)))])
1364218334Speter
1364390286Sobrien(define_insn "*jcc_2"
1364418334Speter  [(set (pc)
1364590286Sobrien	(if_then_else (match_operator 1 "ix86_comparison_operator"
13646169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1364790286Sobrien		      (pc)
1364890286Sobrien		      (label_ref (match_operand 0 "" ""))))]
1364918334Speter  ""
1365090286Sobrien  "%+j%c1\t%l0"
1365190286Sobrien  [(set_attr "type" "ibr")
13652117404Skan   (set_attr "modrm" "0")
13653117404Skan   (set (attr "length")
1365490286Sobrien	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13655117404Skan				  (const_int -126))
1365690286Sobrien			      (lt (minus (match_dup 0) (pc))
13657117404Skan				  (const_int 128)))
13658117404Skan	     (const_int 2)
13659117404Skan	     (const_int 6)))])
1366090286Sobrien
1366190286Sobrien;; In general it is not safe to assume too much about CCmode registers,
13662259563Spfg;; so simplify-rtx stops when it sees a second one.  Under certain
1366390286Sobrien;; conditions this is safe on x86, so help combine not create
1366490286Sobrien;;
1366590286Sobrien;;	seta	%al
1366690286Sobrien;;	testb	%al, %al
1366790286Sobrien;;	je	Lfoo
1366890286Sobrien
13669259563Spfg(define_split
1367090286Sobrien  [(set (pc)
1367190286Sobrien	(if_then_else (ne (match_operator 0 "ix86_comparison_operator"
13672169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1367390286Sobrien			  (const_int 0))
1367490286Sobrien		      (label_ref (match_operand 1 "" ""))
1367590286Sobrien		      (pc)))]
1367690286Sobrien  ""
1367790286Sobrien  [(set (pc)
1367890286Sobrien	(if_then_else (match_dup 0)
1367990286Sobrien		      (label_ref (match_dup 1))
1368090286Sobrien		      (pc)))]
1368118334Speter{
1368290286Sobrien  PUT_MODE (operands[0], VOIDmode);
1368390286Sobrien})
13684259563Spfg
13685259563Spfg(define_split
1368690286Sobrien  [(set (pc)
1368790286Sobrien	(if_then_else (eq (match_operator 0 "ix86_comparison_operator"
13688169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1368990286Sobrien			  (const_int 0))
1369090286Sobrien		      (label_ref (match_operand 1 "" ""))
1369190286Sobrien		      (pc)))]
1369290286Sobrien  ""
1369390286Sobrien  [(set (pc)
1369490286Sobrien	(if_then_else (match_dup 0)
1369590286Sobrien		      (label_ref (match_dup 1))
1369690286Sobrien		      (pc)))]
1369790286Sobrien{
1369890286Sobrien  rtx new_op0 = copy_rtx (operands[0]);
1369990286Sobrien  operands[0] = new_op0;
1370090286Sobrien  PUT_MODE (new_op0, VOIDmode);
13701169699Skan  PUT_CODE (new_op0, ix86_reverse_condition (GET_CODE (new_op0),
13702169699Skan					     GET_MODE (XEXP (new_op0, 0))));
1370352296Sobrien
1370490286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1370590286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1370690286Sobrien  if (! ix86_comparison_operator (new_op0, VOIDmode))
1370790286Sobrien    FAIL;
1370890286Sobrien})
1370952296Sobrien
1371090286Sobrien;; Define combination compare-and-branch fp compare instructions to use
1371190286Sobrien;; during early optimization.  Splitting the operation apart early makes
1371290286Sobrien;; for bad code when we want to reverse the operation.
1371318334Speter
13714169699Skan(define_insn "*fp_jcc_1_mixed"
1371590286Sobrien  [(set (pc)
1371690286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13717169699Skan			[(match_operand 1 "register_operand" "f,x")
13718169699Skan			 (match_operand 2 "nonimmediate_operand" "f,xm")])
1371990286Sobrien	  (label_ref (match_operand 3 "" ""))
1372090286Sobrien	  (pc)))
13721169699Skan   (clobber (reg:CCFP FPSR_REG))
13722169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13723169699Skan  "TARGET_MIX_SSE_I387
13724169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1372590286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1372690286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1372790286Sobrien  "#")
1372818334Speter
1372990286Sobrien(define_insn "*fp_jcc_1_sse"
1373090286Sobrien  [(set (pc)
1373190286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13732169699Skan			[(match_operand 1 "register_operand" "x")
13733169699Skan			 (match_operand 2 "nonimmediate_operand" "xm")])
1373490286Sobrien	  (label_ref (match_operand 3 "" ""))
1373590286Sobrien	  (pc)))
13736169699Skan   (clobber (reg:CCFP FPSR_REG))
13737169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13738169699Skan  "TARGET_SSE_MATH
1373990286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1374090286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1374190286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1374290286Sobrien  "#")
1374318334Speter
13744169699Skan(define_insn "*fp_jcc_1_387"
1374590286Sobrien  [(set (pc)
1374690286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13747169699Skan			[(match_operand 1 "register_operand" "f")
13748169699Skan			 (match_operand 2 "register_operand" "f")])
1374990286Sobrien	  (label_ref (match_operand 3 "" ""))
1375090286Sobrien	  (pc)))
13751169699Skan   (clobber (reg:CCFP FPSR_REG))
13752169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13753169699Skan  "TARGET_CMOVE && TARGET_80387
13754169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
1375590286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1375690286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1375790286Sobrien  "#")
1375818334Speter
13759169699Skan(define_insn "*fp_jcc_2_mixed"
1376018334Speter  [(set (pc)
1376190286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13762169699Skan			[(match_operand 1 "register_operand" "f,x")
13763169699Skan			 (match_operand 2 "nonimmediate_operand" "f,xm")])
1376490286Sobrien	  (pc)
1376590286Sobrien	  (label_ref (match_operand 3 "" ""))))
13766169699Skan   (clobber (reg:CCFP FPSR_REG))
13767169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13768169699Skan  "TARGET_MIX_SSE_I387
13769169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1377090286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1377190286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1377290286Sobrien  "#")
1377318334Speter
1377490286Sobrien(define_insn "*fp_jcc_2_sse"
1377590286Sobrien  [(set (pc)
1377690286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13777169699Skan			[(match_operand 1 "register_operand" "x")
13778169699Skan			 (match_operand 2 "nonimmediate_operand" "xm")])
1377990286Sobrien	  (pc)
1378090286Sobrien	  (label_ref (match_operand 3 "" ""))))
13781169699Skan   (clobber (reg:CCFP FPSR_REG))
13782169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13783169699Skan  "TARGET_SSE_MATH
1378490286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1378590286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1378690286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1378790286Sobrien  "#")
1378818334Speter
13789169699Skan(define_insn "*fp_jcc_2_387"
1379090286Sobrien  [(set (pc)
1379190286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13792169699Skan			[(match_operand 1 "register_operand" "f")
13793169699Skan			 (match_operand 2 "register_operand" "f")])
1379490286Sobrien	  (pc)
1379590286Sobrien	  (label_ref (match_operand 3 "" ""))))
13796169699Skan   (clobber (reg:CCFP FPSR_REG))
13797169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13798169699Skan  "TARGET_CMOVE && TARGET_80387
13799169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
1380090286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1380190286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1380290286Sobrien  "#")
1380318334Speter
13804169699Skan(define_insn "*fp_jcc_3_387"
1380590286Sobrien  [(set (pc)
1380690286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1380790286Sobrien			[(match_operand 1 "register_operand" "f")
1380890286Sobrien			 (match_operand 2 "nonimmediate_operand" "fm")])
1380990286Sobrien	  (label_ref (match_operand 3 "" ""))
1381090286Sobrien	  (pc)))
13811169699Skan   (clobber (reg:CCFP FPSR_REG))
13812169699Skan   (clobber (reg:CCFP FLAGS_REG))
1381390286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1381490286Sobrien  "TARGET_80387
1381590286Sobrien   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
1381690286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1381790286Sobrien   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
1381890286Sobrien   && SELECT_CC_MODE (GET_CODE (operands[0]),
1381990286Sobrien		      operands[1], operands[2]) == CCFPmode
1382090286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1382190286Sobrien  "#")
1382218334Speter
13823169699Skan(define_insn "*fp_jcc_4_387"
1382450650Sobrien  [(set (pc)
1382590286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1382690286Sobrien			[(match_operand 1 "register_operand" "f")
1382790286Sobrien			 (match_operand 2 "nonimmediate_operand" "fm")])
1382890286Sobrien	  (pc)
1382990286Sobrien	  (label_ref (match_operand 3 "" ""))))
13830169699Skan   (clobber (reg:CCFP FPSR_REG))
13831169699Skan   (clobber (reg:CCFP FLAGS_REG))
1383290286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1383390286Sobrien  "TARGET_80387
1383490286Sobrien   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
1383590286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1383690286Sobrien   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
1383790286Sobrien   && SELECT_CC_MODE (GET_CODE (operands[0]),
1383890286Sobrien		      operands[1], operands[2]) == CCFPmode
1383990286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1384090286Sobrien  "#")
1384150650Sobrien
13842169699Skan(define_insn "*fp_jcc_5_387"
1384350650Sobrien  [(set (pc)
1384490286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1384590286Sobrien			[(match_operand 1 "register_operand" "f")
1384690286Sobrien			 (match_operand 2 "register_operand" "f")])
1384790286Sobrien	  (label_ref (match_operand 3 "" ""))
1384890286Sobrien	  (pc)))
13849169699Skan   (clobber (reg:CCFP FPSR_REG))
13850169699Skan   (clobber (reg:CCFP FLAGS_REG))
1385190286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1385290286Sobrien  "TARGET_80387
1385390286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
1385490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1385590286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1385690286Sobrien  "#")
1385750650Sobrien
13858169699Skan(define_insn "*fp_jcc_6_387"
1385950650Sobrien  [(set (pc)
1386090286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1386190286Sobrien			[(match_operand 1 "register_operand" "f")
1386290286Sobrien			 (match_operand 2 "register_operand" "f")])
1386390286Sobrien	  (pc)
1386490286Sobrien	  (label_ref (match_operand 3 "" ""))))
13865169699Skan   (clobber (reg:CCFP FPSR_REG))
13866169699Skan   (clobber (reg:CCFP FLAGS_REG))
1386790286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1386890286Sobrien  "TARGET_80387
1386990286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
1387090286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1387190286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1387290286Sobrien  "#")
1387350650Sobrien
13874169699Skan(define_insn "*fp_jcc_7_387"
13875169699Skan  [(set (pc)
13876169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13877169699Skan			[(match_operand 1 "register_operand" "f")
13878169699Skan			 (match_operand 2 "const0_operand" "X")])
13879169699Skan	  (label_ref (match_operand 3 "" ""))
13880169699Skan	  (pc)))
13881169699Skan   (clobber (reg:CCFP FPSR_REG))
13882169699Skan   (clobber (reg:CCFP FLAGS_REG))
13883169699Skan   (clobber (match_scratch:HI 4 "=a"))]
13884169699Skan  "TARGET_80387
13885169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
13886169699Skan   && GET_MODE (operands[1]) == GET_MODE (operands[2])
13887169699Skan   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
13888169699Skan   && SELECT_CC_MODE (GET_CODE (operands[0]),
13889169699Skan		      operands[1], operands[2]) == CCFPmode
13890169699Skan   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
13891169699Skan  "#")
13892169699Skan
13893169699Skan;; The order of operands in *fp_jcc_8_387 is forced by combine in
13894169699Skan;; simplify_comparison () function. Float operator is treated as RTX_OBJ
13895169699Skan;; with a precedence over other operators and is always put in the first
13896169699Skan;; place. Swap condition and operands to match ficom instruction.
13897169699Skan
13898169699Skan(define_insn "*fp_jcc_8<mode>_387"
13899169699Skan  [(set (pc)
13900169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13901169699Skan			[(match_operator 1 "float_operator"
13902169699Skan			   [(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")])
13903169699Skan			   (match_operand 3 "register_operand" "f,f")])
13904169699Skan	  (label_ref (match_operand 4 "" ""))
13905169699Skan	  (pc)))
13906169699Skan   (clobber (reg:CCFP FPSR_REG))
13907169699Skan   (clobber (reg:CCFP FLAGS_REG))
13908169699Skan   (clobber (match_scratch:HI 5 "=a,a"))]
13909169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
13910169699Skan   && FLOAT_MODE_P (GET_MODE (operands[3]))
13911169699Skan   && GET_MODE (operands[1]) == GET_MODE (operands[3])
13912169699Skan   && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0])))
13913169699Skan   && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
13914169699Skan   && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))"
13915169699Skan  "#")
13916169699Skan
1391790286Sobrien(define_split
1391850650Sobrien  [(set (pc)
1391990286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1392090286Sobrien			[(match_operand 1 "register_operand" "")
1392190286Sobrien			 (match_operand 2 "nonimmediate_operand" "")])
1392290286Sobrien	  (match_operand 3 "" "")
1392390286Sobrien	  (match_operand 4 "" "")))
13924169699Skan   (clobber (reg:CCFP FPSR_REG))
13925169699Skan   (clobber (reg:CCFP FLAGS_REG))]
1392690286Sobrien  "reload_completed"
1392790286Sobrien  [(const_int 0)]
1392850650Sobrien{
1392990286Sobrien  ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
13930169699Skan	                operands[3], operands[4], NULL_RTX, NULL_RTX);
1393190286Sobrien  DONE;
1393290286Sobrien})
1393350650Sobrien
1393490286Sobrien(define_split
1393550650Sobrien  [(set (pc)
1393690286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1393790286Sobrien			[(match_operand 1 "register_operand" "")
13938169699Skan			 (match_operand 2 "general_operand" "")])
1393990286Sobrien	  (match_operand 3 "" "")
1394090286Sobrien	  (match_operand 4 "" "")))
13941169699Skan   (clobber (reg:CCFP FPSR_REG))
13942169699Skan   (clobber (reg:CCFP FLAGS_REG))
1394390286Sobrien   (clobber (match_scratch:HI 5 "=a"))]
1394490286Sobrien  "reload_completed"
13945169699Skan  [(const_int 0)]
1394650650Sobrien{
1394790286Sobrien  ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
13948169699Skan	     		operands[3], operands[4], operands[5], NULL_RTX);
1394990286Sobrien  DONE;
1395090286Sobrien})
13951169699Skan
13952169699Skan(define_split
13953169699Skan  [(set (pc)
13954169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13955169699Skan			[(match_operator 1 "float_operator"
13956169699Skan			   [(match_operand:X87MODEI12 2 "memory_operand" "")])
13957169699Skan			   (match_operand 3 "register_operand" "")])
13958169699Skan	  (match_operand 4 "" "")
13959169699Skan	  (match_operand 5 "" "")))
13960169699Skan   (clobber (reg:CCFP FPSR_REG))
13961169699Skan   (clobber (reg:CCFP FLAGS_REG))
13962169699Skan   (clobber (match_scratch:HI 6 "=a"))]
13963169699Skan  "reload_completed"
13964169699Skan  [(const_int 0)]
13965169699Skan{
13966169699Skan  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[2]);
13967169699Skan  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
13968169699Skan			operands[3], operands[7],
13969169699Skan			operands[4], operands[5], operands[6], NULL_RTX);
13970169699Skan  DONE;
13971169699Skan})
13972169699Skan
13973169699Skan;; %%% Kill this when reload knows how to do it.
13974169699Skan(define_split
13975169699Skan  [(set (pc)
13976169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13977169699Skan			[(match_operator 1 "float_operator"
13978169699Skan			   [(match_operand:X87MODEI12 2 "register_operand" "")])
13979169699Skan			   (match_operand 3 "register_operand" "")])
13980169699Skan	  (match_operand 4 "" "")
13981169699Skan	  (match_operand 5 "" "")))
13982169699Skan   (clobber (reg:CCFP FPSR_REG))
13983169699Skan   (clobber (reg:CCFP FLAGS_REG))
13984169699Skan   (clobber (match_scratch:HI 6 "=a"))]
13985169699Skan  "reload_completed"
13986169699Skan  [(const_int 0)]
13987169699Skan{
13988169699Skan  operands[7] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
13989169699Skan  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[7]);
13990169699Skan  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
13991169699Skan			operands[3], operands[7],
13992169699Skan			operands[4], operands[5], operands[6], operands[2]);
13993169699Skan  DONE;
13994169699Skan})
1399590286Sobrien
1399690286Sobrien;; Unconditional and other jump instructions
1399750650Sobrien
1399890286Sobrien(define_insn "jump"
1399950650Sobrien  [(set (pc)
1400090286Sobrien	(label_ref (match_operand 0 "" "")))]
1400150650Sobrien  ""
1400290286Sobrien  "jmp\t%l0"
14003117404Skan  [(set_attr "type" "ibr")
14004117404Skan   (set (attr "length")
14005117404Skan	   (if_then_else (and (ge (minus (match_dup 0) (pc))
14006117404Skan				  (const_int -126))
14007117404Skan			      (lt (minus (match_dup 0) (pc))
14008117404Skan				  (const_int 128)))
14009117404Skan	     (const_int 2)
14010117404Skan	     (const_int 5)))
14011117404Skan   (set_attr "modrm" "0")])
1401290286Sobrien
1401390286Sobrien(define_expand "indirect_jump"
1401490286Sobrien  [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))]
1401590286Sobrien  ""
1401690286Sobrien  "")
1401790286Sobrien
1401890286Sobrien(define_insn "*indirect_jump"
1401990286Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
1402090286Sobrien  "!TARGET_64BIT"
1402190286Sobrien  "jmp\t%A0"
1402290286Sobrien  [(set_attr "type" "ibr")
1402390286Sobrien   (set_attr "length_immediate" "0")])
1402490286Sobrien
1402590286Sobrien(define_insn "*indirect_jump_rtx64"
1402690286Sobrien  [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm"))]
1402790286Sobrien  "TARGET_64BIT"
1402890286Sobrien  "jmp\t%A0"
1402990286Sobrien  [(set_attr "type" "ibr")
1403090286Sobrien   (set_attr "length_immediate" "0")])
1403190286Sobrien
1403290286Sobrien(define_expand "tablejump"
1403390286Sobrien  [(parallel [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))
1403490286Sobrien	      (use (label_ref (match_operand 1 "" "")))])]
1403590286Sobrien  ""
1403650650Sobrien{
14037117404Skan  /* In PIC mode, the table entries are stored GOT (32-bit) or PC (64-bit)
14038117404Skan     relative.  Convert the relative address to an absolute address.  */
1403990286Sobrien  if (flag_pic)
1404090286Sobrien    {
14041117404Skan      rtx op0, op1;
14042117404Skan      enum rtx_code code;
14043117404Skan
1404490286Sobrien      if (TARGET_64BIT)
1404590286Sobrien	{
14046117404Skan	  code = PLUS;
14047117404Skan	  op0 = operands[0];
14048117404Skan	  op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);
1404990286Sobrien	}
14050117404Skan      else if (TARGET_MACHO || HAVE_AS_GOTOFF_IN_DATA)
14051117404Skan	{
14052117404Skan	  code = PLUS;
14053117404Skan	  op0 = operands[0];
14054117404Skan	  op1 = pic_offset_table_rtx;
14055117404Skan	}
1405690286Sobrien      else
1405790286Sobrien	{
14058117404Skan	  code = MINUS;
14059117404Skan	  op0 = pic_offset_table_rtx;
14060117404Skan	  op1 = operands[0];
1406190286Sobrien	}
14062117404Skan
14063117404Skan      operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0,
14064117404Skan					 OPTAB_DIRECT);
1406590286Sobrien    }
1406690286Sobrien})
1406750650Sobrien
1406890286Sobrien(define_insn "*tablejump_1"
1406990286Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
1407090286Sobrien   (use (label_ref (match_operand 1 "" "")))]
1407190286Sobrien  "!TARGET_64BIT"
1407290286Sobrien  "jmp\t%A0"
1407390286Sobrien  [(set_attr "type" "ibr")
1407490286Sobrien   (set_attr "length_immediate" "0")])
1407518334Speter
1407690286Sobrien(define_insn "*tablejump_1_rtx64"
1407790286Sobrien  [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm"))
1407890286Sobrien   (use (label_ref (match_operand 1 "" "")))]
1407990286Sobrien  "TARGET_64BIT"
1408090286Sobrien  "jmp\t%A0"
1408190286Sobrien  [(set_attr "type" "ibr")
1408290286Sobrien   (set_attr "length_immediate" "0")])
1408390286Sobrien
1408490286Sobrien;; Convert setcc + movzbl to xor + setcc if operands don't overlap.
1408518334Speter
1408690286Sobrien(define_peephole2
14087169699Skan  [(set (reg FLAGS_REG) (match_operand 0 "" ""))
1408890286Sobrien   (set (match_operand:QI 1 "register_operand" "")
1408990286Sobrien	(match_operator:QI 2 "ix86_comparison_operator"
14090169699Skan	  [(reg FLAGS_REG) (const_int 0)]))
1409190286Sobrien   (set (match_operand 3 "q_regs_operand" "")
1409290286Sobrien	(zero_extend (match_dup 1)))]
1409390286Sobrien  "(peep2_reg_dead_p (3, operands[1])
1409490286Sobrien    || operands_match_p (operands[1], operands[3]))
1409590286Sobrien   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
1409690286Sobrien  [(set (match_dup 4) (match_dup 0))
1409790286Sobrien   (set (strict_low_part (match_dup 5))
1409890286Sobrien	(match_dup 2))]
1409918334Speter{
14100169699Skan  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
14101132727Skan  operands[5] = gen_lowpart (QImode, operands[3]);
1410290286Sobrien  ix86_expand_clear (operands[3]);
1410390286Sobrien})
1410418334Speter
1410590286Sobrien;; Similar, but match zero_extendhisi2_and, which adds a clobber.
1410618334Speter
1410790286Sobrien(define_peephole2
14108169699Skan  [(set (reg FLAGS_REG) (match_operand 0 "" ""))
1410990286Sobrien   (set (match_operand:QI 1 "register_operand" "")
1411090286Sobrien	(match_operator:QI 2 "ix86_comparison_operator"
14111169699Skan	  [(reg FLAGS_REG) (const_int 0)]))
1411290286Sobrien   (parallel [(set (match_operand 3 "q_regs_operand" "")
1411390286Sobrien		   (zero_extend (match_dup 1)))
14114169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1411590286Sobrien  "(peep2_reg_dead_p (3, operands[1])
1411690286Sobrien    || operands_match_p (operands[1], operands[3]))
1411790286Sobrien   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
1411890286Sobrien  [(set (match_dup 4) (match_dup 0))
1411990286Sobrien   (set (strict_low_part (match_dup 5))
1412090286Sobrien	(match_dup 2))]
1412190286Sobrien{
14122169699Skan  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
14123132727Skan  operands[5] = gen_lowpart (QImode, operands[3]);
1412490286Sobrien  ix86_expand_clear (operands[3]);
1412590286Sobrien})
1412690286Sobrien
1412790286Sobrien;; Call instructions.
1412818334Speter
1412990286Sobrien;; The predicates normally associated with named expanders are not properly
1413090286Sobrien;; checked for calls.  This is a bug in the generic code, but it isn't that
1413190286Sobrien;; easy to fix.  Ignore it for now and be prepared to fix things up.
1413218334Speter
1413318334Speter;; Call subroutine returning no value.
1413418334Speter
1413518334Speter(define_expand "call_pop"
1413690286Sobrien  [(parallel [(call (match_operand:QI 0 "" "")
1413790286Sobrien		    (match_operand:SI 1 "" ""))
14138169699Skan	      (set (reg:SI SP_REG)
14139169699Skan		   (plus:SI (reg:SI SP_REG)
1414090286Sobrien			    (match_operand:SI 3 "" "")))])]
1414190286Sobrien  "!TARGET_64BIT"
1414218334Speter{
14143132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3], 0);
14144117404Skan  DONE;
1414590286Sobrien})
1414618334Speter
1414790286Sobrien(define_insn "*call_pop_0"
1414890286Sobrien  [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" ""))
1414990286Sobrien	 (match_operand:SI 1 "" ""))
14150169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
1415190286Sobrien			    (match_operand:SI 2 "immediate_operand" "")))]
1415290286Sobrien  "!TARGET_64BIT"
1415318334Speter{
1415490286Sobrien  if (SIBLING_CALL_P (insn))
1415590286Sobrien    return "jmp\t%P0";
1415690286Sobrien  else
1415790286Sobrien    return "call\t%P0";
1415890286Sobrien}
1415990286Sobrien  [(set_attr "type" "call")])
14160259563Spfg
1416190286Sobrien(define_insn "*call_pop_1"
1416290286Sobrien  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
1416390286Sobrien	 (match_operand:SI 1 "" ""))
14164169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
1416590286Sobrien			    (match_operand:SI 2 "immediate_operand" "i")))]
1416690286Sobrien  "!TARGET_64BIT"
1416790286Sobrien{
1416890286Sobrien  if (constant_call_address_operand (operands[0], Pmode))
1416918334Speter    {
1417090286Sobrien      if (SIBLING_CALL_P (insn))
1417190286Sobrien	return "jmp\t%P0";
1417290286Sobrien      else
1417390286Sobrien	return "call\t%P0";
1417418334Speter    }
1417590286Sobrien  if (SIBLING_CALL_P (insn))
1417690286Sobrien    return "jmp\t%A0";
1417718334Speter  else
1417890286Sobrien    return "call\t%A0";
1417990286Sobrien}
1418090286Sobrien  [(set_attr "type" "call")])
1418118334Speter
1418218334Speter(define_expand "call"
1418390286Sobrien  [(call (match_operand:QI 0 "" "")
1418490286Sobrien	 (match_operand 1 "" ""))
1418590286Sobrien   (use (match_operand 2 "" ""))]
1418618334Speter  ""
1418718334Speter{
14188132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 0);
14189117404Skan  DONE;
1419090286Sobrien})
1419118334Speter
14192132727Skan(define_expand "sibcall"
14193132727Skan  [(call (match_operand:QI 0 "" "")
14194132727Skan	 (match_operand 1 "" ""))
14195132727Skan   (use (match_operand 2 "" ""))]
14196132727Skan  ""
14197132727Skan{
14198132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 1);
14199132727Skan  DONE;
14200132727Skan})
14201132727Skan
1420290286Sobrien(define_insn "*call_0"
1420390286Sobrien  [(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
1420490286Sobrien	 (match_operand 1 "" ""))]
1420518334Speter  ""
1420618334Speter{
1420790286Sobrien  if (SIBLING_CALL_P (insn))
1420890286Sobrien    return "jmp\t%P0";
1420990286Sobrien  else
1421090286Sobrien    return "call\t%P0";
1421190286Sobrien}
1421290286Sobrien  [(set_attr "type" "call")])
1421390286Sobrien
1421490286Sobrien(define_insn "*call_1"
1421590286Sobrien  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
1421690286Sobrien	 (match_operand 1 "" ""))]
14217132727Skan  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
1421890286Sobrien{
14219169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14220132727Skan    return "call\t%P0";
14221132727Skan  return "call\t%A0";
1422290286Sobrien}
1422390286Sobrien  [(set_attr "type" "call")])
1422418334Speter
14225132727Skan(define_insn "*sibcall_1"
14226132727Skan  [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,c,d,a"))
14227132727Skan	 (match_operand 1 "" ""))]
14228132727Skan  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
14229132727Skan{
14230169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14231132727Skan    return "jmp\t%P0";
14232132727Skan  return "jmp\t%A0";
14233132727Skan}
14234132727Skan  [(set_attr "type" "call")])
14235132727Skan
1423690286Sobrien(define_insn "*call_1_rex64"
1423790286Sobrien  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
1423890286Sobrien	 (match_operand 1 "" ""))]
14239132727Skan  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
1424090286Sobrien{
14241169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14242132727Skan    return "call\t%P0";
14243132727Skan  return "call\t%A0";
1424490286Sobrien}
1424590286Sobrien  [(set_attr "type" "call")])
1424618334Speter
14247132727Skan(define_insn "*sibcall_1_rex64"
14248132727Skan  [(call (mem:QI (match_operand:DI 0 "constant_call_address_operand" ""))
14249132727Skan	 (match_operand 1 "" ""))]
14250132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
14251132727Skan  "jmp\t%P0"
14252132727Skan  [(set_attr "type" "call")])
14253132727Skan
14254132727Skan(define_insn "*sibcall_1_rex64_v"
14255237021Spfg  [(call (mem:QI (reg:DI 40))
14256132727Skan	 (match_operand 0 "" ""))]
14257132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
14258132727Skan  "jmp\t*%%r11"
14259132727Skan  [(set_attr "type" "call")])
14260132727Skan
14261132727Skan
1426218334Speter;; Call subroutine, returning value in operand 0
1426318334Speter
1426418334Speter(define_expand "call_value_pop"
1426518334Speter  [(parallel [(set (match_operand 0 "" "")
1426690286Sobrien		   (call (match_operand:QI 1 "" "")
1426790286Sobrien			 (match_operand:SI 2 "" "")))
14268169699Skan	      (set (reg:SI SP_REG)
14269169699Skan		   (plus:SI (reg:SI SP_REG)
1427090286Sobrien			    (match_operand:SI 4 "" "")))])]
1427190286Sobrien  "!TARGET_64BIT"
1427218334Speter{
14273117404Skan  ix86_expand_call (operands[0], operands[1], operands[2],
14274132727Skan		    operands[3], operands[4], 0);
14275117404Skan  DONE;
1427690286Sobrien})
1427718334Speter
1427818334Speter(define_expand "call_value"
1427918334Speter  [(set (match_operand 0 "" "")
1428090286Sobrien	(call (match_operand:QI 1 "" "")
1428190286Sobrien	      (match_operand:SI 2 "" "")))
1428290286Sobrien   (use (match_operand:SI 3 "" ""))]
1428318334Speter  ;; Operand 2 not used on the i386.
1428418334Speter  ""
1428518334Speter{
14286132727Skan  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 0);
1428790286Sobrien  DONE;
1428890286Sobrien})
1428918334Speter
14290132727Skan(define_expand "sibcall_value"
14291132727Skan  [(set (match_operand 0 "" "")
14292132727Skan	(call (match_operand:QI 1 "" "")
14293132727Skan	      (match_operand:SI 2 "" "")))
14294132727Skan   (use (match_operand:SI 3 "" ""))]
14295132727Skan  ;; Operand 2 not used on the i386.
14296132727Skan  ""
14297132727Skan{
14298132727Skan  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 1);
14299132727Skan  DONE;
14300132727Skan})
14301132727Skan
1430218334Speter;; Call subroutine returning any type.
1430318334Speter
1430418334Speter(define_expand "untyped_call"
1430518334Speter  [(parallel [(call (match_operand 0 "" "")
1430618334Speter		    (const_int 0))
1430718334Speter	      (match_operand 1 "" "")
1430818334Speter	      (match_operand 2 "" "")])]
1430918334Speter  ""
1431018334Speter{
1431118334Speter  int i;
1431218334Speter
1431318334Speter  /* In order to give reg-stack an easier job in validating two
1431418334Speter     coprocessor registers as containing a possible return value,
1431518334Speter     simply pretend the untyped call returns a complex long double
1431618334Speter     value.  */
1431750650Sobrien
14318117404Skan  ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387
14319117404Skan		     ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL),
14320117404Skan		    operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1),
14321132727Skan		    NULL, 0);
1432218334Speter
1432318334Speter  for (i = 0; i < XVECLEN (operands[2], 0); i++)
1432418334Speter    {
1432518334Speter      rtx set = XVECEXP (operands[2], 0, i);
1432618334Speter      emit_move_insn (SET_DEST (set), SET_SRC (set));
1432718334Speter    }
1432818334Speter
1432918334Speter  /* The optimizer does not know that the call sets the function value
1433018334Speter     registers we stored in the result block.  We avoid problems by
1433118334Speter     claiming that all hard registers are used and clobbered at this
1433218334Speter     point.  */
14333117404Skan  emit_insn (gen_blockage (const0_rtx));
1433418334Speter
1433518334Speter  DONE;
1433690286Sobrien})
1433790286Sobrien
1433890286Sobrien;; Prologue and epilogue instructions
1433918334Speter
1434018334Speter;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
1434118334Speter;; all of memory.  This blocks insns from being moved across this point.
1434218334Speter
1434318334Speter(define_insn "blockage"
14344117404Skan  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_BLOCKAGE)]
1434518334Speter  ""
1434652296Sobrien  ""
1434790286Sobrien  [(set_attr "length" "0")])
1434818334Speter
1434918334Speter;; Insn emitted into the body of a function to return from a function.
1435018334Speter;; This is only done if the function's epilogue is known to be simple.
1435190286Sobrien;; See comments for ix86_can_use_return_insn_p in i386.c.
1435218334Speter
1435350650Sobrien(define_expand "return"
1435418334Speter  [(return)]
1435550650Sobrien  "ix86_can_use_return_insn_p ()"
1435690286Sobrien{
1435790286Sobrien  if (current_function_pops_args)
1435890286Sobrien    {
1435990286Sobrien      rtx popc = GEN_INT (current_function_pops_args);
1436090286Sobrien      emit_jump_insn (gen_return_pop_internal (popc));
1436190286Sobrien      DONE;
1436290286Sobrien    }
1436390286Sobrien})
1436450650Sobrien
1436550650Sobrien(define_insn "return_internal"
1436650650Sobrien  [(return)]
1436750650Sobrien  "reload_completed"
1436852296Sobrien  "ret"
1436990286Sobrien  [(set_attr "length" "1")
1437090286Sobrien   (set_attr "length_immediate" "0")
1437190286Sobrien   (set_attr "modrm" "0")])
1437250650Sobrien
14373132727Skan;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
14374132727Skan;; instruction Athlon and K8 have.
14375132727Skan
14376132727Skan(define_insn "return_internal_long"
14377132727Skan  [(return)
14378132727Skan   (unspec [(const_int 0)] UNSPEC_REP)]
14379132727Skan  "reload_completed"
14380132727Skan  "rep {;} ret"
14381132727Skan  [(set_attr "length" "1")
14382132727Skan   (set_attr "length_immediate" "0")
14383132727Skan   (set_attr "prefix_rep" "1")
14384132727Skan   (set_attr "modrm" "0")])
14385132727Skan
1438650650Sobrien(define_insn "return_pop_internal"
1438750650Sobrien  [(return)
1438850650Sobrien   (use (match_operand:SI 0 "const_int_operand" ""))]
1438950650Sobrien  "reload_completed"
1439090286Sobrien  "ret\t%0"
1439190286Sobrien  [(set_attr "length" "3")
1439290286Sobrien   (set_attr "length_immediate" "2")
1439390286Sobrien   (set_attr "modrm" "0")])
1439450650Sobrien
1439590286Sobrien(define_insn "return_indirect_internal"
1439690286Sobrien  [(return)
1439790286Sobrien   (use (match_operand:SI 0 "register_operand" "r"))]
1439890286Sobrien  "reload_completed"
1439990286Sobrien  "jmp\t%A0"
1440090286Sobrien  [(set_attr "type" "ibr")
1440190286Sobrien   (set_attr "length_immediate" "0")])
1440290286Sobrien
1440350650Sobrien(define_insn "nop"
1440450650Sobrien  [(const_int 0)]
1440550650Sobrien  ""
1440652296Sobrien  "nop"
1440790286Sobrien  [(set_attr "length" "1")
1440890286Sobrien   (set_attr "length_immediate" "0")
14409169699Skan   (set_attr "modrm" "0")])
1441050650Sobrien
14411132727Skan;; Align to 16-byte boundary, max skip in op0.  Used to avoid
14412132727Skan;; branch prediction penalty for the third jump in a 16-byte
14413132727Skan;; block on K8.
14414132727Skan
14415132727Skan(define_insn "align"
14416132727Skan  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_ALIGN)]
14417132727Skan  ""
14418132727Skan{
14419132727Skan#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
14420132727Skan  ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 4, (int)INTVAL (operands[0]));
14421132727Skan#else
14422132727Skan  /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that.
14423132727Skan     The align insn is used to avoid 3 jump instructions in the row to improve
14424169699Skan     branch prediction and the benefits hardly outweigh the cost of extra 8
14425132727Skan     nops on the average inserted by full alignment pseudo operation.  */
14426132727Skan#endif
14427132727Skan  return "";
14428132727Skan}
14429132727Skan  [(set_attr "length" "16")])
14430132727Skan
1443150650Sobrien(define_expand "prologue"
1443250650Sobrien  [(const_int 1)]
1443350650Sobrien  ""
1443490286Sobrien  "ix86_expand_prologue (); DONE;")
1443550650Sobrien
14436117404Skan(define_insn "set_got"
1443790286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
14438117404Skan	(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
14439169699Skan   (clobber (reg:CC FLAGS_REG))]
1444090286Sobrien  "!TARGET_64BIT"
14441169699Skan  { return output_set_got (operands[0], NULL_RTX); }
14442117404Skan  [(set_attr "type" "multi")
14443117404Skan   (set_attr "length" "12")])
1444450650Sobrien
14445169699Skan(define_insn "set_got_labelled"
14446169699Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14447169699Skan	(unspec:SI [(label_ref (match_operand 1 "" ""))]
14448169699Skan	 UNSPEC_SET_GOT))
14449169699Skan   (clobber (reg:CC FLAGS_REG))]
14450169699Skan  "!TARGET_64BIT"
14451169699Skan  { return output_set_got (operands[0], operands[1]); }
14452169699Skan  [(set_attr "type" "multi")
14453169699Skan   (set_attr "length" "12")])
14454169699Skan
14455169699Skan(define_insn "set_got_rex64"
14456169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14457169699Skan	(unspec:DI [(const_int 0)] UNSPEC_SET_GOT))]
14458169699Skan  "TARGET_64BIT"
14459169699Skan  "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
14460169699Skan  [(set_attr "type" "lea")
14461169699Skan   (set_attr "length" "6")])
14462169699Skan
1446350650Sobrien(define_expand "epilogue"
1446450650Sobrien  [(const_int 1)]
1446550650Sobrien  ""
1446690286Sobrien  "ix86_expand_epilogue (1); DONE;")
1446750650Sobrien
1446890286Sobrien(define_expand "sibcall_epilogue"
1446990286Sobrien  [(const_int 1)]
1447050650Sobrien  ""
1447190286Sobrien  "ix86_expand_epilogue (0); DONE;")
1447250650Sobrien
1447390286Sobrien(define_expand "eh_return"
14474117404Skan  [(use (match_operand 0 "register_operand" ""))]
1447550650Sobrien  ""
1447650650Sobrien{
14477117404Skan  rtx tmp, sa = EH_RETURN_STACKADJ_RTX, ra = operands[0];
1447850650Sobrien
1447990286Sobrien  /* Tricky bit: we write the address of the handler to which we will
1448090286Sobrien     be returning into someone else's stack frame, one word below the
1448190286Sobrien     stack address we wish to restore.  */
1448290286Sobrien  tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa);
1448390286Sobrien  tmp = plus_constant (tmp, -UNITS_PER_WORD);
1448490286Sobrien  tmp = gen_rtx_MEM (Pmode, tmp);
1448590286Sobrien  emit_move_insn (tmp, ra);
1448618334Speter
1448790286Sobrien  if (Pmode == SImode)
14488169699Skan    emit_jump_insn (gen_eh_return_si (sa));
1448990286Sobrien  else
14490169699Skan    emit_jump_insn (gen_eh_return_di (sa));
1449190286Sobrien  emit_barrier ();
1449290286Sobrien  DONE;
1449390286Sobrien})
1449418334Speter
1449590286Sobrien(define_insn_and_split "eh_return_si"
14496259563Spfg  [(set (pc)
14497169699Skan        (unspec [(match_operand:SI 0 "register_operand" "c")]
14498169699Skan	         UNSPEC_EH_RETURN))]
1449990286Sobrien  "!TARGET_64BIT"
1450090286Sobrien  "#"
1450190286Sobrien  "reload_completed"
1450290286Sobrien  [(const_int 1)]
1450390286Sobrien  "ix86_expand_epilogue (2); DONE;")
1450418334Speter
1450590286Sobrien(define_insn_and_split "eh_return_di"
14506259563Spfg  [(set (pc)
14507169699Skan        (unspec [(match_operand:DI 0 "register_operand" "c")]
14508169699Skan	         UNSPEC_EH_RETURN))]
1450990286Sobrien  "TARGET_64BIT"
1451090286Sobrien  "#"
1451190286Sobrien  "reload_completed"
1451290286Sobrien  [(const_int 1)]
1451390286Sobrien  "ix86_expand_epilogue (2); DONE;")
1451418334Speter
1451590286Sobrien(define_insn "leave"
14516169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI BP_REG) (const_int 4)))
14517169699Skan   (set (reg:SI BP_REG) (mem:SI (reg:SI BP_REG)))
1451890286Sobrien   (clobber (mem:BLK (scratch)))]
1451990286Sobrien  "!TARGET_64BIT"
1452090286Sobrien  "leave"
14521132727Skan  [(set_attr "type" "leave")])
1452218334Speter
1452390286Sobrien(define_insn "leave_rex64"
14524169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI BP_REG) (const_int 8)))
14525169699Skan   (set (reg:DI BP_REG) (mem:DI (reg:DI BP_REG)))
1452690286Sobrien   (clobber (mem:BLK (scratch)))]
1452790286Sobrien  "TARGET_64BIT"
1452890286Sobrien  "leave"
14529132727Skan  [(set_attr "type" "leave")])
1453090286Sobrien
1453190286Sobrien(define_expand "ffssi2"
14532132727Skan  [(parallel
14533259563Spfg     [(set (match_operand:SI 0 "register_operand" "")
14534132727Skan	   (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "")))
14535132727Skan      (clobber (match_scratch:SI 2 ""))
14536169699Skan      (clobber (reg:CC FLAGS_REG))])]
1453718334Speter  ""
14538132727Skan  "")
1453918334Speter
14540132727Skan(define_insn_and_split "*ffs_cmove"
14541259563Spfg  [(set (match_operand:SI 0 "register_operand" "=r")
14542132727Skan	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14543132727Skan   (clobber (match_scratch:SI 2 "=&r"))
14544169699Skan   (clobber (reg:CC FLAGS_REG))]
14545132727Skan  "TARGET_CMOVE"
14546132727Skan  "#"
14547132727Skan  "&& reload_completed"
14548132727Skan  [(set (match_dup 2) (const_int -1))
14549169699Skan   (parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
14550132727Skan	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
14551132727Skan   (set (match_dup 0) (if_then_else:SI
14552169699Skan			(eq (reg:CCZ FLAGS_REG) (const_int 0))
14553132727Skan			(match_dup 2)
14554132727Skan			(match_dup 0)))
14555132727Skan   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
14556169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14557132727Skan  "")
1455818334Speter
14559132727Skan(define_insn_and_split "*ffs_no_cmove"
14560259563Spfg  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
14561132727Skan	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14562132727Skan   (clobber (match_scratch:SI 2 "=&q"))
14563169699Skan   (clobber (reg:CC FLAGS_REG))]
14564132727Skan  ""
14565132727Skan  "#"
14566132727Skan  "reload_completed"
14567169699Skan  [(parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
14568132727Skan	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
14569132727Skan   (set (strict_low_part (match_dup 3))
14570169699Skan	(eq:QI (reg:CCZ FLAGS_REG) (const_int 0)))
14571132727Skan   (parallel [(set (match_dup 2) (neg:SI (match_dup 2)))
14572169699Skan	      (clobber (reg:CC FLAGS_REG))])
14573132727Skan   (parallel [(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 2)))
14574169699Skan	      (clobber (reg:CC FLAGS_REG))])
14575132727Skan   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
14576169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14577132727Skan{
14578132727Skan  operands[3] = gen_lowpart (QImode, operands[2]);
14579132727Skan  ix86_expand_clear (operands[2]);
1458090286Sobrien})
1458150650Sobrien
14582132727Skan(define_insn "*ffssi_1"
14583169699Skan  [(set (reg:CCZ FLAGS_REG)
14584132727Skan	(compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm")
1458590286Sobrien		     (const_int 0)))
1458690286Sobrien   (set (match_operand:SI 0 "register_operand" "=r")
14587132727Skan	(ctz:SI (match_dup 1)))]
1458818334Speter  ""
1458990286Sobrien  "bsf{l}\t{%1, %0|%0, %1}"
14590169699Skan  [(set_attr "prefix_0f" "1")])
1459118334Speter
14592169699Skan(define_expand "ffsdi2"
14593169699Skan  [(parallel
14594259563Spfg     [(set (match_operand:DI 0 "register_operand" "")
14595169699Skan	   (ffs:DI (match_operand:DI 1 "nonimmediate_operand" "")))
14596169699Skan      (clobber (match_scratch:DI 2 ""))
14597169699Skan      (clobber (reg:CC FLAGS_REG))])]
14598169699Skan  "TARGET_64BIT && TARGET_CMOVE"
14599169699Skan  "")
14600169699Skan
14601169699Skan(define_insn_and_split "*ffs_rex64"
14602259563Spfg  [(set (match_operand:DI 0 "register_operand" "=r")
14603169699Skan	(ffs:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
14604169699Skan   (clobber (match_scratch:DI 2 "=&r"))
14605169699Skan   (clobber (reg:CC FLAGS_REG))]
14606169699Skan  "TARGET_64BIT && TARGET_CMOVE"
14607169699Skan  "#"
14608169699Skan  "&& reload_completed"
14609169699Skan  [(set (match_dup 2) (const_int -1))
14610169699Skan   (parallel [(set (reg:CCZ FLAGS_REG)
14611169699Skan		   (compare:CCZ (match_dup 1) (const_int 0)))
14612169699Skan	      (set (match_dup 0) (ctz:DI (match_dup 1)))])
14613169699Skan   (set (match_dup 0) (if_then_else:DI
14614169699Skan			(eq (reg:CCZ FLAGS_REG) (const_int 0))
14615169699Skan			(match_dup 2)
14616169699Skan			(match_dup 0)))
14617169699Skan   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1)))
14618169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14619169699Skan  "")
14620169699Skan
14621169699Skan(define_insn "*ffsdi_1"
14622169699Skan  [(set (reg:CCZ FLAGS_REG)
14623169699Skan	(compare:CCZ (match_operand:DI 1 "nonimmediate_operand" "rm")
14624169699Skan		     (const_int 0)))
14625169699Skan   (set (match_operand:DI 0 "register_operand" "=r")
14626169699Skan	(ctz:DI (match_dup 1)))]
14627169699Skan  "TARGET_64BIT"
14628169699Skan  "bsf{q}\t{%1, %0|%0, %1}"
14629169699Skan  [(set_attr "prefix_0f" "1")])
14630169699Skan
14631132727Skan(define_insn "ctzsi2"
14632132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14633132727Skan	(ctz:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14634169699Skan   (clobber (reg:CC FLAGS_REG))]
14635132727Skan  ""
14636132727Skan  "bsf{l}\t{%1, %0|%0, %1}"
14637169699Skan  [(set_attr "prefix_0f" "1")])
14638132727Skan
14639169699Skan(define_insn "ctzdi2"
14640169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14641169699Skan	(ctz:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
14642169699Skan   (clobber (reg:CC FLAGS_REG))]
14643169699Skan  "TARGET_64BIT"
14644169699Skan  "bsf{q}\t{%1, %0|%0, %1}"
14645169699Skan  [(set_attr "prefix_0f" "1")])
14646169699Skan
14647132727Skan(define_expand "clzsi2"
14648132727Skan  [(parallel
14649132727Skan     [(set (match_operand:SI 0 "register_operand" "")
14650132727Skan	   (minus:SI (const_int 31)
14651132727Skan		     (clz:SI (match_operand:SI 1 "nonimmediate_operand" ""))))
14652169699Skan      (clobber (reg:CC FLAGS_REG))])
14653132727Skan   (parallel
14654132727Skan     [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 31)))
14655169699Skan      (clobber (reg:CC FLAGS_REG))])]
14656132727Skan  ""
14657251212Spfg{
14658251212Spfg  if (TARGET_ABM)
14659251212Spfg    {
14660251212Spfg      emit_insn (gen_clzsi2_abm (operands[0], operands[1]));
14661251212Spfg      DONE;
14662251212Spfg    }
14663251212Spfg})
14664132727Skan
14665251212Spfg(define_insn "clzsi2_abm"
14666251212Spfg  [(set (match_operand:SI 0 "register_operand" "=r")
14667251212Spfg        (clz:SI (match_operand:SI 1 "nonimmediate_operand" "")))
14668251212Spfg   (clobber (reg:CC FLAGS_REG))]
14669251212Spfg  "TARGET_ABM"
14670251212Spfg  "lzcnt{l}\t{%1, %0|%0, %1}"
14671251212Spfg  [(set_attr "prefix_rep" "1")
14672251212Spfg   (set_attr "type" "bitmanip")
14673251212Spfg   (set_attr "mode" "SI")])
14674251212Spfg
14675132727Skan(define_insn "*bsr"
14676132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14677132727Skan	(minus:SI (const_int 31)
14678132727Skan		  (clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))))
14679169699Skan   (clobber (reg:CC FLAGS_REG))]
14680132727Skan  ""
14681132727Skan  "bsr{l}\t{%1, %0|%0, %1}"
14682251212Spfg  [(set_attr "prefix_0f" "1")
14683251212Spfg   (set_attr "mode" "SI")])
14684169699Skan
14685251212Spfg(define_insn "popcountsi2"
14686251212Spfg  [(set (match_operand:SI 0 "register_operand" "=r")
14687251212Spfg	(popcount:SI (match_operand:SI 1 "nonimmediate_operand" "")))
14688251212Spfg   (clobber (reg:CC FLAGS_REG))]
14689251212Spfg  "TARGET_POPCNT"
14690251212Spfg  "popcnt{l}\t{%1, %0|%0, %1}"
14691251212Spfg  [(set_attr "prefix_rep" "1")
14692251212Spfg   (set_attr "type" "bitmanip")
14693251212Spfg   (set_attr "mode" "SI")])
14694251212Spfg
14695251212Spfg(define_insn "*popcountsi2_cmp"
14696251212Spfg  [(set (reg FLAGS_REG)
14697251212Spfg	(compare
14698251212Spfg	  (popcount:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))
14699251212Spfg	  (const_int 0)))
14700251212Spfg   (set (match_operand:SI 0 "register_operand" "=r")
14701251212Spfg	(popcount:SI (match_dup 1)))]
14702251212Spfg  "TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
14703251212Spfg  "popcnt{l}\t{%1, %0|%0, %1}"
14704251212Spfg  [(set_attr "prefix_rep" "1")
14705251212Spfg   (set_attr "type" "bitmanip")
14706251212Spfg   (set_attr "mode" "SI")])
14707251212Spfg
14708251212Spfg(define_insn "*popcountsi2_cmp_zext"
14709251212Spfg  [(set (reg FLAGS_REG)
14710251212Spfg        (compare
14711251212Spfg          (popcount:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))
14712251212Spfg          (const_int 0)))
14713251212Spfg   (set (match_operand:DI 0 "register_operand" "=r")
14714251212Spfg        (zero_extend:DI(popcount:SI (match_dup 1))))]
14715251212Spfg  "TARGET_64BIT && TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
14716251212Spfg  "popcnt{l}\t{%1, %0|%0, %1}"
14717251212Spfg  [(set_attr "prefix_rep" "1")
14718251212Spfg   (set_attr "type" "bitmanip")
14719251212Spfg   (set_attr "mode" "SI")])
14720251212Spfg
14721259563Spfg(define_insn "bswapsi2"
14722259563Spfg  [(set (match_operand:SI 0 "register_operand" "=r")
14723259563Spfg	(bswap:SI (match_operand:SI 1 "register_operand" "0")))
14724259563Spfg   (clobber (reg:CC FLAGS_REG))]
14725259563Spfg  "TARGET_BSWAP"
14726259563Spfg  "bswap\t%k0"
14727259563Spfg  [(set_attr "prefix_0f" "1")
14728259563Spfg   (set_attr "length" "2")])
14729259563Spfg
14730259563Spfg(define_insn "bswapdi2"
14731259563Spfg  [(set (match_operand:DI 0 "register_operand" "=r")
14732259563Spfg	(bswap:DI (match_operand:DI 1 "register_operand" "0")))
14733259563Spfg   (clobber (reg:CC FLAGS_REG))]
14734259563Spfg  "TARGET_64BIT && TARGET_BSWAP"
14735259563Spfg  "bswap\t%0"
14736259563Spfg  [(set_attr "prefix_0f" "1")
14737259563Spfg   (set_attr "length" "3")])
14738259563Spfg
14739169699Skan(define_expand "clzdi2"
14740169699Skan  [(parallel
14741169699Skan     [(set (match_operand:DI 0 "register_operand" "")
14742169699Skan	   (minus:DI (const_int 63)
14743169699Skan		     (clz:DI (match_operand:DI 1 "nonimmediate_operand" ""))))
14744169699Skan      (clobber (reg:CC FLAGS_REG))])
14745169699Skan   (parallel
14746169699Skan     [(set (match_dup 0) (xor:DI (match_dup 0) (const_int 63)))
14747169699Skan      (clobber (reg:CC FLAGS_REG))])]
14748169699Skan  "TARGET_64BIT"
14749251212Spfg{
14750251212Spfg  if (TARGET_ABM)
14751251212Spfg    {
14752251212Spfg      emit_insn (gen_clzdi2_abm (operands[0], operands[1]));
14753251212Spfg      DONE;
14754251212Spfg    }
14755251212Spfg})
14756169699Skan
14757251212Spfg(define_insn "clzdi2_abm"
14758251212Spfg  [(set (match_operand:DI 0 "register_operand" "=r")
14759251212Spfg	(clz:DI (match_operand:DI 1 "nonimmediate_operand" "")))
14760251212Spfg   (clobber (reg:CC FLAGS_REG))]
14761251212Spfg  "TARGET_64BIT && TARGET_ABM"
14762251212Spfg  "lzcnt{q}\t{%1, %0|%0, %1}"
14763251212Spfg  [(set_attr "prefix_rep" "1")
14764251212Spfg   (set_attr "type" "bitmanip")
14765251212Spfg   (set_attr "mode" "DI")])
14766251212Spfg
14767169699Skan(define_insn "*bsr_rex64"
14768169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14769169699Skan	(minus:DI (const_int 63)
14770169699Skan		  (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))))
14771169699Skan   (clobber (reg:CC FLAGS_REG))]
14772169699Skan  "TARGET_64BIT"
14773169699Skan  "bsr{q}\t{%1, %0|%0, %1}"
14774251212Spfg  [(set_attr "prefix_0f" "1")
14775251212Spfg   (set_attr "mode" "DI")])
14776251212Spfg
14777251212Spfg(define_insn "popcountdi2"
14778251212Spfg  [(set (match_operand:DI 0 "register_operand" "=r")
14779251212Spfg	(popcount:DI (match_operand:DI 1 "nonimmediate_operand" "")))
14780251212Spfg   (clobber (reg:CC FLAGS_REG))]
14781251212Spfg  "TARGET_64BIT && TARGET_POPCNT"
14782251212Spfg  "popcnt{q}\t{%1, %0|%0, %1}"
14783251212Spfg  [(set_attr "prefix_rep" "1")
14784251212Spfg   (set_attr "type" "bitmanip")
14785251212Spfg   (set_attr "mode" "DI")])
14786251212Spfg
14787251212Spfg(define_insn "*popcountdi2_cmp"
14788251212Spfg  [(set (reg FLAGS_REG)
14789251212Spfg	(compare
14790251212Spfg	  (popcount:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))
14791251212Spfg	  (const_int 0)))
14792251212Spfg   (set (match_operand:DI 0 "register_operand" "=r")
14793251212Spfg	(popcount:DI (match_dup 1)))]
14794251212Spfg  "TARGET_64BIT && TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
14795251212Spfg  "popcnt{q}\t{%1, %0|%0, %1}"
14796251212Spfg  [(set_attr "prefix_rep" "1")
14797251212Spfg   (set_attr "type" "bitmanip")
14798251212Spfg   (set_attr "mode" "DI")])
14799251212Spfg
14800251212Spfg(define_expand "clzhi2"
14801251212Spfg  [(parallel
14802251212Spfg     [(set (match_operand:HI 0 "register_operand" "")
14803251212Spfg	   (minus:HI (const_int 15)
14804251212Spfg		     (clz:HI (match_operand:HI 1 "nonimmediate_operand" ""))))
14805251212Spfg      (clobber (reg:CC FLAGS_REG))])
14806251212Spfg   (parallel
14807251212Spfg     [(set (match_dup 0) (xor:HI (match_dup 0) (const_int 15)))
14808251212Spfg      (clobber (reg:CC FLAGS_REG))])]
14809251212Spfg  ""
14810251212Spfg{
14811251212Spfg  if (TARGET_ABM)
14812251212Spfg    {
14813251212Spfg      emit_insn (gen_clzhi2_abm (operands[0], operands[1]));
14814251212Spfg      DONE;
14815251212Spfg    }
14816251212Spfg})
14817251212Spfg
14818251212Spfg(define_insn "clzhi2_abm"
14819251212Spfg  [(set (match_operand:HI 0 "register_operand" "=r")
14820251212Spfg	(clz:HI (match_operand:HI 1 "nonimmediate_operand" "")))
14821251212Spfg   (clobber (reg:CC FLAGS_REG))]
14822251212Spfg  "TARGET_ABM"
14823251212Spfg  "lzcnt{w}\t{%1, %0|%0, %1}"
14824251212Spfg  [(set_attr "prefix_rep" "1")
14825251212Spfg   (set_attr "type" "bitmanip")
14826251212Spfg   (set_attr "mode" "HI")])
14827251212Spfg
14828251212Spfg(define_insn "*bsrhi"
14829251212Spfg  [(set (match_operand:HI 0 "register_operand" "=r")
14830251212Spfg	(minus:HI (const_int 15)
14831251212Spfg		  (clz:HI (match_operand:HI 1 "nonimmediate_operand" "rm"))))
14832251212Spfg   (clobber (reg:CC FLAGS_REG))]
14833251212Spfg  ""
14834251212Spfg  "bsr{w}\t{%1, %0|%0, %1}"
14835251212Spfg  [(set_attr "prefix_0f" "1")
14836251212Spfg   (set_attr "mode" "HI")])
14837251212Spfg
14838251212Spfg(define_insn "popcounthi2"
14839251212Spfg  [(set (match_operand:HI 0 "register_operand" "=r")
14840251212Spfg	(popcount:HI (match_operand:HI 1 "nonimmediate_operand" "")))
14841251212Spfg   (clobber (reg:CC FLAGS_REG))]
14842251212Spfg  "TARGET_POPCNT"
14843251212Spfg  "popcnt{w}\t{%1, %0|%0, %1}"
14844251212Spfg  [(set_attr "prefix_rep" "1")
14845251212Spfg   (set_attr "type" "bitmanip")
14846251212Spfg   (set_attr "mode" "HI")])
14847251212Spfg
14848251212Spfg(define_insn "*popcounthi2_cmp"
14849251212Spfg  [(set (reg FLAGS_REG)
14850251212Spfg        (compare
14851251212Spfg          (popcount:HI (match_operand:HI 1 "nonimmediate_operand" "rm"))
14852251212Spfg          (const_int 0)))
14853251212Spfg   (set (match_operand:HI 0 "register_operand" "=r")
14854251212Spfg        (popcount:HI (match_dup 1)))]
14855251212Spfg  "TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
14856251212Spfg  "popcnt{w}\t{%1, %0|%0, %1}"
14857251212Spfg  [(set_attr "prefix_rep" "1")
14858251212Spfg   (set_attr "type" "bitmanip")
14859251212Spfg   (set_attr "mode" "HI")])
1486090286Sobrien
14861117404Skan;; Thread-local storage patterns for ELF.
14862117404Skan;;
14863117404Skan;; Note that these code sequences must appear exactly as shown
14864117404Skan;; in order to allow linker relaxation.
14865117404Skan
14866117404Skan(define_insn "*tls_global_dynamic_32_gnu"
14867117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14868117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14869117404Skan		    (match_operand:SI 2 "tls_symbolic_operand" "")
14870117404Skan		    (match_operand:SI 3 "call_insn_operand" "")]
14871117404Skan		    UNSPEC_TLS_GD))
14872117404Skan   (clobber (match_scratch:SI 4 "=d"))
14873117404Skan   (clobber (match_scratch:SI 5 "=c"))
14874169699Skan   (clobber (reg:CC FLAGS_REG))]
14875117404Skan  "!TARGET_64BIT && TARGET_GNU_TLS"
14876117404Skan  "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
14877117404Skan  [(set_attr "type" "multi")
14878117404Skan   (set_attr "length" "12")])
14879117404Skan
14880117404Skan(define_insn "*tls_global_dynamic_32_sun"
14881117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14882117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14883117404Skan		    (match_operand:SI 2 "tls_symbolic_operand" "")
14884117404Skan		    (match_operand:SI 3 "call_insn_operand" "")]
14885117404Skan		    UNSPEC_TLS_GD))
14886117404Skan   (clobber (match_scratch:SI 4 "=d"))
14887117404Skan   (clobber (match_scratch:SI 5 "=c"))
14888169699Skan   (clobber (reg:CC FLAGS_REG))]
14889117404Skan  "!TARGET_64BIT && TARGET_SUN_TLS"
14890117404Skan  "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
14891117404Skan	push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
14892117404Skan  [(set_attr "type" "multi")
14893117404Skan   (set_attr "length" "14")])
14894117404Skan
14895117404Skan(define_expand "tls_global_dynamic_32"
14896117404Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
14897117404Skan		   (unspec:SI
14898117404Skan		    [(match_dup 2)
14899117404Skan		     (match_operand:SI 1 "tls_symbolic_operand" "")
14900117404Skan		     (match_dup 3)]
14901117404Skan		    UNSPEC_TLS_GD))
14902117404Skan	      (clobber (match_scratch:SI 4 ""))
14903117404Skan	      (clobber (match_scratch:SI 5 ""))
14904169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14905117404Skan  ""
14906117404Skan{
14907117404Skan  if (flag_pic)
14908117404Skan    operands[2] = pic_offset_table_rtx;
14909117404Skan  else
14910117404Skan    {
14911117404Skan      operands[2] = gen_reg_rtx (Pmode);
14912117404Skan      emit_insn (gen_set_got (operands[2]));
14913117404Skan    }
14914169699Skan  if (TARGET_GNU2_TLS)
14915169699Skan    {
14916169699Skan       emit_insn (gen_tls_dynamic_gnu2_32
14917169699Skan		  (operands[0], operands[1], operands[2]));
14918169699Skan       DONE;
14919169699Skan    }
14920117404Skan  operands[3] = ix86_tls_get_addr ();
14921117404Skan})
14922117404Skan
14923117404Skan(define_insn "*tls_global_dynamic_64"
14924117404Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14925169699Skan	(call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
14926169699Skan		 (match_operand:DI 3 "" "")))
14927117404Skan   (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14928117404Skan	      UNSPEC_TLS_GD)]
14929117404Skan  "TARGET_64BIT"
14930117404Skan  ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%P2"
14931117404Skan  [(set_attr "type" "multi")
14932117404Skan   (set_attr "length" "16")])
14933117404Skan
14934117404Skan(define_expand "tls_global_dynamic_64"
14935117404Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
14936169699Skan		   (call:DI (mem:QI (match_dup 2)) (const_int 0)))
14937117404Skan	      (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14938117404Skan			 UNSPEC_TLS_GD)])]
14939117404Skan  ""
14940117404Skan{
14941169699Skan  if (TARGET_GNU2_TLS)
14942169699Skan    {
14943169699Skan       emit_insn (gen_tls_dynamic_gnu2_64
14944169699Skan		  (operands[0], operands[1]));
14945169699Skan       DONE;
14946169699Skan    }
14947117404Skan  operands[2] = ix86_tls_get_addr ();
14948117404Skan})
14949117404Skan
14950117404Skan(define_insn "*tls_local_dynamic_base_32_gnu"
14951117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14952117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14953117404Skan                    (match_operand:SI 2 "call_insn_operand" "")]
14954117404Skan		   UNSPEC_TLS_LD_BASE))
14955117404Skan   (clobber (match_scratch:SI 3 "=d"))
14956117404Skan   (clobber (match_scratch:SI 4 "=c"))
14957169699Skan   (clobber (reg:CC FLAGS_REG))]
14958117404Skan  "!TARGET_64BIT && TARGET_GNU_TLS"
14959117404Skan  "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
14960117404Skan  [(set_attr "type" "multi")
14961117404Skan   (set_attr "length" "11")])
14962117404Skan
14963117404Skan(define_insn "*tls_local_dynamic_base_32_sun"
14964117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14965117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14966117404Skan                    (match_operand:SI 2 "call_insn_operand" "")]
14967117404Skan		   UNSPEC_TLS_LD_BASE))
14968117404Skan   (clobber (match_scratch:SI 3 "=d"))
14969117404Skan   (clobber (match_scratch:SI 4 "=c"))
14970169699Skan   (clobber (reg:CC FLAGS_REG))]
14971117404Skan  "!TARGET_64BIT && TARGET_SUN_TLS"
14972117404Skan  "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
14973117404Skan	push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
14974117404Skan  [(set_attr "type" "multi")
14975117404Skan   (set_attr "length" "13")])
14976117404Skan
14977117404Skan(define_expand "tls_local_dynamic_base_32"
14978117404Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
14979117404Skan		   (unspec:SI [(match_dup 1) (match_dup 2)]
14980117404Skan			      UNSPEC_TLS_LD_BASE))
14981117404Skan	      (clobber (match_scratch:SI 3 ""))
14982117404Skan	      (clobber (match_scratch:SI 4 ""))
14983169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14984117404Skan  ""
14985117404Skan{
14986117404Skan  if (flag_pic)
14987117404Skan    operands[1] = pic_offset_table_rtx;
14988117404Skan  else
14989117404Skan    {
14990117404Skan      operands[1] = gen_reg_rtx (Pmode);
14991117404Skan      emit_insn (gen_set_got (operands[1]));
14992117404Skan    }
14993169699Skan  if (TARGET_GNU2_TLS)
14994169699Skan    {
14995169699Skan       emit_insn (gen_tls_dynamic_gnu2_32
14996169699Skan		  (operands[0], ix86_tls_module_base (), operands[1]));
14997169699Skan       DONE;
14998169699Skan    }
14999117404Skan  operands[2] = ix86_tls_get_addr ();
15000117404Skan})
15001117404Skan
15002117404Skan(define_insn "*tls_local_dynamic_base_64"
15003117404Skan  [(set (match_operand:DI 0 "register_operand" "=a")
15004169699Skan	(call:DI (mem:QI (match_operand:DI 1 "call_insn_operand" ""))
15005169699Skan		 (match_operand:DI 2 "" "")))
15006117404Skan   (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
15007117404Skan  "TARGET_64BIT"
15008117404Skan  "lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1"
15009117404Skan  [(set_attr "type" "multi")
15010117404Skan   (set_attr "length" "12")])
15011117404Skan
15012117404Skan(define_expand "tls_local_dynamic_base_64"
15013117404Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
15014169699Skan		   (call:DI (mem:QI (match_dup 1)) (const_int 0)))
15015117404Skan	      (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
15016117404Skan  ""
15017117404Skan{
15018169699Skan  if (TARGET_GNU2_TLS)
15019169699Skan    {
15020169699Skan       emit_insn (gen_tls_dynamic_gnu2_64
15021169699Skan		  (operands[0], ix86_tls_module_base ()));
15022169699Skan       DONE;
15023169699Skan    }
15024117404Skan  operands[1] = ix86_tls_get_addr ();
15025117404Skan})
15026117404Skan
15027117404Skan;; Local dynamic of a single variable is a lose.  Show combine how
15028117404Skan;; to convert that back to global dynamic.
15029117404Skan
15030117404Skan(define_insn_and_split "*tls_local_dynamic_32_once"
15031117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
15032117404Skan	(plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b")
15033117404Skan			     (match_operand:SI 2 "call_insn_operand" "")]
15034117404Skan			    UNSPEC_TLS_LD_BASE)
15035117404Skan		 (const:SI (unspec:SI
15036117404Skan			    [(match_operand:SI 3 "tls_symbolic_operand" "")]
15037117404Skan			    UNSPEC_DTPOFF))))
15038117404Skan   (clobber (match_scratch:SI 4 "=d"))
15039117404Skan   (clobber (match_scratch:SI 5 "=c"))
15040169699Skan   (clobber (reg:CC FLAGS_REG))]
15041117404Skan  ""
15042117404Skan  "#"
15043117404Skan  ""
15044117404Skan  [(parallel [(set (match_dup 0)
15045117404Skan		   (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)]
15046117404Skan			      UNSPEC_TLS_GD))
15047117404Skan	      (clobber (match_dup 4))
15048117404Skan	      (clobber (match_dup 5))
15049169699Skan	      (clobber (reg:CC FLAGS_REG))])]
15050117404Skan  "")
15051132727Skan
15052132727Skan;; Load and add the thread base pointer from %gs:0.
15053132727Skan
15054132727Skan(define_insn "*load_tp_si"
15055132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
15056132727Skan	(unspec:SI [(const_int 0)] UNSPEC_TP))]
15057132727Skan  "!TARGET_64BIT"
15058132727Skan  "mov{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
15059132727Skan  [(set_attr "type" "imov")
15060132727Skan   (set_attr "modrm" "0")
15061132727Skan   (set_attr "length" "7")
15062132727Skan   (set_attr "memory" "load")
15063132727Skan   (set_attr "imm_disp" "false")])
15064132727Skan
15065132727Skan(define_insn "*add_tp_si"
15066132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
15067132727Skan	(plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
15068132727Skan		 (match_operand:SI 1 "register_operand" "0")))
15069169699Skan   (clobber (reg:CC FLAGS_REG))]
15070132727Skan  "!TARGET_64BIT"
15071132727Skan  "add{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
15072132727Skan  [(set_attr "type" "alu")
15073132727Skan   (set_attr "modrm" "0")
15074132727Skan   (set_attr "length" "7")
15075132727Skan   (set_attr "memory" "load")
15076132727Skan   (set_attr "imm_disp" "false")])
15077132727Skan
15078132727Skan(define_insn "*load_tp_di"
15079132727Skan  [(set (match_operand:DI 0 "register_operand" "=r")
15080132727Skan	(unspec:DI [(const_int 0)] UNSPEC_TP))]
15081132727Skan  "TARGET_64BIT"
15082132727Skan  "mov{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
15083132727Skan  [(set_attr "type" "imov")
15084132727Skan   (set_attr "modrm" "0")
15085132727Skan   (set_attr "length" "7")
15086132727Skan   (set_attr "memory" "load")
15087132727Skan   (set_attr "imm_disp" "false")])
15088132727Skan
15089132727Skan(define_insn "*add_tp_di"
15090132727Skan  [(set (match_operand:DI 0 "register_operand" "=r")
15091132727Skan	(plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP)
15092132727Skan		 (match_operand:DI 1 "register_operand" "0")))
15093169699Skan   (clobber (reg:CC FLAGS_REG))]
15094132727Skan  "TARGET_64BIT"
15095132727Skan  "add{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
15096132727Skan  [(set_attr "type" "alu")
15097132727Skan   (set_attr "modrm" "0")
15098132727Skan   (set_attr "length" "7")
15099132727Skan   (set_attr "memory" "load")
15100132727Skan   (set_attr "imm_disp" "false")])
15101169699Skan
15102169699Skan;; GNU2 TLS patterns can be split.
15103169699Skan
15104169699Skan(define_expand "tls_dynamic_gnu2_32"
15105169699Skan  [(set (match_dup 3)
15106169699Skan	(plus:SI (match_operand:SI 2 "register_operand" "")
15107169699Skan		 (const:SI
15108169699Skan		  (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")]
15109169699Skan			     UNSPEC_TLSDESC))))
15110169699Skan   (parallel
15111169699Skan    [(set (match_operand:SI 0 "register_operand" "")
15112169699Skan	  (unspec:SI [(match_dup 1) (match_dup 3)
15113169699Skan		      (match_dup 2) (reg:SI SP_REG)]
15114169699Skan		      UNSPEC_TLSDESC))
15115169699Skan     (clobber (reg:CC FLAGS_REG))])]
15116169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
15117169699Skan{
15118169699Skan  operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
15119169699Skan  ix86_tls_descriptor_calls_expanded_in_cfun = true;
15120169699Skan})
15121169699Skan
15122169699Skan(define_insn "*tls_dynamic_lea_32"
15123169699Skan  [(set (match_operand:SI 0 "register_operand" "=r")
15124169699Skan	(plus:SI (match_operand:SI 1 "register_operand" "b")
15125169699Skan		 (const:SI
15126169699Skan		  (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")]
15127169699Skan			      UNSPEC_TLSDESC))))]
15128169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
15129169699Skan  "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}"
15130169699Skan  [(set_attr "type" "lea")
15131169699Skan   (set_attr "mode" "SI")
15132169699Skan   (set_attr "length" "6")
15133169699Skan   (set_attr "length_address" "4")])
15134169699Skan
15135169699Skan(define_insn "*tls_dynamic_call_32"
15136169699Skan  [(set (match_operand:SI 0 "register_operand" "=a")
15137169699Skan	(unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")
15138169699Skan		    (match_operand:SI 2 "register_operand" "0")
15139169699Skan		    ;; we have to make sure %ebx still points to the GOT
15140169699Skan		    (match_operand:SI 3 "register_operand" "b")
15141169699Skan		    (reg:SI SP_REG)]
15142169699Skan		   UNSPEC_TLSDESC))
15143169699Skan   (clobber (reg:CC FLAGS_REG))]
15144169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
15145169699Skan  "call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}"
15146169699Skan  [(set_attr "type" "call")
15147169699Skan   (set_attr "length" "2")
15148169699Skan   (set_attr "length_address" "0")])
15149169699Skan
15150169699Skan(define_insn_and_split "*tls_dynamic_gnu2_combine_32"
15151169699Skan  [(set (match_operand:SI 0 "register_operand" "=&a")
15152169699Skan	(plus:SI
15153169699Skan	 (unspec:SI [(match_operand:SI 3 "tls_modbase_operand" "")
15154169699Skan		     (match_operand:SI 4 "" "")
15155169699Skan		     (match_operand:SI 2 "register_operand" "b")
15156169699Skan		     (reg:SI SP_REG)]
15157169699Skan		    UNSPEC_TLSDESC)
15158169699Skan	 (const:SI (unspec:SI
15159169699Skan		    [(match_operand:SI 1 "tls_symbolic_operand" "")]
15160169699Skan		    UNSPEC_DTPOFF))))
15161169699Skan   (clobber (reg:CC FLAGS_REG))]
15162169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
15163169699Skan  "#"
15164169699Skan  ""
15165169699Skan  [(set (match_dup 0) (match_dup 5))]
15166169699Skan{
15167169699Skan  operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
15168169699Skan  emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2]));
15169169699Skan})
15170169699Skan
15171169699Skan(define_expand "tls_dynamic_gnu2_64"
15172169699Skan  [(set (match_dup 2)
15173169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
15174169699Skan		   UNSPEC_TLSDESC))
15175169699Skan   (parallel
15176169699Skan    [(set (match_operand:DI 0 "register_operand" "")
15177169699Skan	  (unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)]
15178169699Skan		     UNSPEC_TLSDESC))
15179169699Skan     (clobber (reg:CC FLAGS_REG))])]
15180169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
15181169699Skan{
15182169699Skan  operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
15183169699Skan  ix86_tls_descriptor_calls_expanded_in_cfun = true;
15184169699Skan})
15185169699Skan
15186169699Skan(define_insn "*tls_dynamic_lea_64"
15187169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
15188169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
15189169699Skan		   UNSPEC_TLSDESC))]
15190169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
15191169699Skan  "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}"
15192169699Skan  [(set_attr "type" "lea")
15193169699Skan   (set_attr "mode" "DI")
15194169699Skan   (set_attr "length" "7")
15195169699Skan   (set_attr "length_address" "4")])
15196169699Skan
15197169699Skan(define_insn "*tls_dynamic_call_64"
15198169699Skan  [(set (match_operand:DI 0 "register_operand" "=a")
15199169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
15200169699Skan		    (match_operand:DI 2 "register_operand" "0")
15201169699Skan		    (reg:DI SP_REG)]
15202169699Skan		   UNSPEC_TLSDESC))
15203169699Skan   (clobber (reg:CC FLAGS_REG))]
15204169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
15205169699Skan  "call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}"
15206169699Skan  [(set_attr "type" "call")
15207169699Skan   (set_attr "length" "2")
15208169699Skan   (set_attr "length_address" "0")])
15209169699Skan
15210169699Skan(define_insn_and_split "*tls_dynamic_gnu2_combine_64"
15211169699Skan  [(set (match_operand:DI 0 "register_operand" "=&a")
15212169699Skan	(plus:DI
15213169699Skan	 (unspec:DI [(match_operand:DI 2 "tls_modbase_operand" "")
15214169699Skan		     (match_operand:DI 3 "" "")
15215169699Skan		     (reg:DI SP_REG)]
15216169699Skan		    UNSPEC_TLSDESC)
15217169699Skan	 (const:DI (unspec:DI
15218169699Skan		    [(match_operand:DI 1 "tls_symbolic_operand" "")]
15219169699Skan		    UNSPEC_DTPOFF))))
15220169699Skan   (clobber (reg:CC FLAGS_REG))]
15221169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
15222169699Skan  "#"
15223169699Skan  ""
15224169699Skan  [(set (match_dup 0) (match_dup 4))]
15225169699Skan{
15226169699Skan  operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
15227169699Skan  emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
15228169699Skan})
15229169699Skan
15230169699Skan;;
15231117404Skan
1523290286Sobrien;; These patterns match the binary 387 instructions for addM3, subM3,
1523390286Sobrien;; mulM3 and divM3.  There are three patterns for each of DFmode and
1523490286Sobrien;; SFmode.  The first is the normal insn, the second the same insn but
1523590286Sobrien;; with one operand a conversion, and the third the same insn but with
1523690286Sobrien;; the other operand a conversion.  The conversion may be SFmode or
1523790286Sobrien;; SImode if the target mode DFmode, but only SImode if the target mode
1523890286Sobrien;; is SFmode.
1523918334Speter
1524090286Sobrien;; Gcc is slightly more smart about handling normal two address instructions
1524190286Sobrien;; so use special patterns for add and mull.
1524218334Speter
15243169699Skan(define_insn "*fop_sf_comm_mixed"
15244169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,x")
1524590286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1524696294Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "%0,0")
15247169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))]
15248169699Skan  "TARGET_MIX_SSE_I387
15249169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1525096294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1525190286Sobrien  "* return output_387_binary_op (insn, operands);"
15252259563Spfg  [(set (attr "type")
1525390286Sobrien	(if_then_else (eq_attr "alternative" "1")
15254259563Spfg	   (if_then_else (match_operand:SF 3 "mult_operator" "")
15255117404Skan	      (const_string "ssemul")
15256117404Skan	      (const_string "sseadd"))
15257259563Spfg	   (if_then_else (match_operand:SF 3 "mult_operator" "")
1525890286Sobrien	      (const_string "fmul")
1525990286Sobrien	      (const_string "fop"))))
1526090286Sobrien   (set_attr "mode" "SF")])
1526118334Speter
1526290286Sobrien(define_insn "*fop_sf_comm_sse"
1526390286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1526490286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1526596294Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "%0")
1526690286Sobrien			 (match_operand:SF 2 "nonimmediate_operand" "xm")]))]
15267169699Skan  "TARGET_SSE_MATH
15268169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1526996294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1527090286Sobrien  "* return output_387_binary_op (insn, operands);"
15271259563Spfg  [(set (attr "type")
15272259563Spfg        (if_then_else (match_operand:SF 3 "mult_operator" "")
15273117404Skan	   (const_string "ssemul")
15274117404Skan	   (const_string "sseadd")))
1527590286Sobrien   (set_attr "mode" "SF")])
1527618334Speter
15277169699Skan(define_insn "*fop_sf_comm_i387"
15278169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
15279169699Skan	(match_operator:SF 3 "binary_fp_operator"
15280169699Skan			[(match_operand:SF 1 "nonimmediate_operand" "%0")
15281169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm")]))]
15282169699Skan  "TARGET_80387
15283169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1528496294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1528590286Sobrien  "* return output_387_binary_op (insn, operands);"
15286259563Spfg  [(set (attr "type")
15287259563Spfg	(if_then_else (match_operand:SF 3 "mult_operator" "")
1528890286Sobrien	   (const_string "fmul")
1528990286Sobrien	   (const_string "fop")))
1529090286Sobrien   (set_attr "mode" "SF")])
1529118334Speter
15292169699Skan(define_insn "*fop_sf_1_mixed"
1529390286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f,x")
1529490286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1529590286Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
15296169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))]
15297169699Skan  "TARGET_MIX_SSE_I387
15298169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
1529990286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1530090286Sobrien  "* return output_387_binary_op (insn, operands);"
15301259563Spfg  [(set (attr "type")
15302117404Skan        (cond [(and (eq_attr "alternative" "2")
15303117404Skan	            (match_operand:SF 3 "mult_operator" ""))
15304117404Skan                 (const_string "ssemul")
15305117404Skan	       (and (eq_attr "alternative" "2")
15306117404Skan	            (match_operand:SF 3 "div_operator" ""))
15307117404Skan                 (const_string "ssediv")
15308117404Skan	       (eq_attr "alternative" "2")
15309117404Skan                 (const_string "sseadd")
15310259563Spfg	       (match_operand:SF 3 "mult_operator" "")
1531190286Sobrien                 (const_string "fmul")
15312259563Spfg               (match_operand:SF 3 "div_operator" "")
1531390286Sobrien                 (const_string "fdiv")
1531490286Sobrien              ]
1531590286Sobrien              (const_string "fop")))
1531690286Sobrien   (set_attr "mode" "SF")])
1531718334Speter
1531890286Sobrien(define_insn "*fop_sf_1_sse"
1531990286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1532090286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1532190286Sobrien			[(match_operand:SF 1 "register_operand" "0")
1532290286Sobrien			 (match_operand:SF 2 "nonimmediate_operand" "xm")]))]
1532390286Sobrien  "TARGET_SSE_MATH
15324169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1532590286Sobrien  "* return output_387_binary_op (insn, operands);"
15326259563Spfg  [(set (attr "type")
15327117404Skan        (cond [(match_operand:SF 3 "mult_operator" "")
15328117404Skan                 (const_string "ssemul")
15329117404Skan	       (match_operand:SF 3 "div_operator" "")
15330117404Skan                 (const_string "ssediv")
15331117404Skan              ]
15332117404Skan              (const_string "sseadd")))
1533390286Sobrien   (set_attr "mode" "SF")])
1533418334Speter
15335169699Skan;; This pattern is not fully shadowed by the pattern above.
15336169699Skan(define_insn "*fop_sf_1_i387"
15337169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
15338169699Skan	(match_operator:SF 3 "binary_fp_operator"
15339169699Skan			[(match_operand:SF 1 "nonimmediate_operand" "0,fm")
15340169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
15341169699Skan  "TARGET_80387 && !TARGET_SSE_MATH
15342169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
15343169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15344169699Skan  "* return output_387_binary_op (insn, operands);"
15345259563Spfg  [(set (attr "type")
15346259563Spfg        (cond [(match_operand:SF 3 "mult_operator" "")
15347169699Skan                 (const_string "fmul")
15348259563Spfg               (match_operand:SF 3 "div_operator" "")
15349169699Skan                 (const_string "fdiv")
15350169699Skan              ]
15351169699Skan              (const_string "fop")))
15352169699Skan   (set_attr "mode" "SF")])
15353169699Skan
1535490286Sobrien;; ??? Add SSE splitters for these!
15355169699Skan(define_insn "*fop_sf_2<mode>_i387"
1535690286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
1535790286Sobrien	(match_operator:SF 3 "binary_fp_operator"
15358169699Skan	  [(float:SF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1535990286Sobrien	   (match_operand:SF 2 "register_operand" "0,0")]))]
15360169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
1536190286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
15362259563Spfg  [(set (attr "type")
15363259563Spfg        (cond [(match_operand:SF 3 "mult_operator" "")
1536490286Sobrien                 (const_string "fmul")
15365259563Spfg               (match_operand:SF 3 "div_operator" "")
1536690286Sobrien                 (const_string "fdiv")
1536790286Sobrien              ]
1536890286Sobrien              (const_string "fop")))
1536990286Sobrien   (set_attr "fp_int_src" "true")
15370169699Skan   (set_attr "mode" "<MODE>")])
1537118334Speter
15372169699Skan(define_insn "*fop_sf_3<mode>_i387"
1537390286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
1537490286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1537590286Sobrien	  [(match_operand:SF 1 "register_operand" "0,0")
15376169699Skan	   (float:SF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15377169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
1537890286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
15379259563Spfg  [(set (attr "type")
15380259563Spfg        (cond [(match_operand:SF 3 "mult_operator" "")
1538190286Sobrien                 (const_string "fmul")
15382259563Spfg               (match_operand:SF 3 "div_operator" "")
1538390286Sobrien                 (const_string "fdiv")
1538490286Sobrien              ]
1538590286Sobrien              (const_string "fop")))
1538690286Sobrien   (set_attr "fp_int_src" "true")
15387169699Skan   (set_attr "mode" "<MODE>")])
1538818334Speter
15389169699Skan(define_insn "*fop_df_comm_mixed"
15390169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,Y")
1539190286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15392169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0,0")
15393169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))]
15394169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387
15395169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1539690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1539790286Sobrien  "* return output_387_binary_op (insn, operands);"
15398259563Spfg  [(set (attr "type")
15399169699Skan	(if_then_else (eq_attr "alternative" "1")
15400259563Spfg	   (if_then_else (match_operand:DF 3 "mult_operator" "")
15401169699Skan	      (const_string "ssemul")
15402169699Skan	      (const_string "sseadd"))
15403259563Spfg	   (if_then_else (match_operand:DF 3 "mult_operator" "")
15404169699Skan	      (const_string "fmul")
15405169699Skan	      (const_string "fop"))))
1540690286Sobrien   (set_attr "mode" "DF")])
1540718334Speter
15408169699Skan(define_insn "*fop_df_comm_sse"
15409169699Skan  [(set (match_operand:DF 0 "register_operand" "=Y")
15410169699Skan	(match_operator:DF 3 "binary_fp_operator"
15411169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0")
15412169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
15413169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
15414169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
15415169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15416169699Skan  "* return output_387_binary_op (insn, operands);"
15417259563Spfg  [(set (attr "type")
15418259563Spfg        (if_then_else (match_operand:DF 3 "mult_operator" "")
15419169699Skan	   (const_string "ssemul")
15420169699Skan	   (const_string "sseadd")))
15421169699Skan   (set_attr "mode" "DF")])
1542218334Speter
15423169699Skan(define_insn "*fop_df_comm_i387"
15424169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
1542590286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15426169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0")
15427169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm")]))]
15428169699Skan  "TARGET_80387
15429169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
15430169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15431169699Skan  "* return output_387_binary_op (insn, operands);"
15432259563Spfg  [(set (attr "type")
15433259563Spfg	(if_then_else (match_operand:DF 3 "mult_operator" "")
15434169699Skan	   (const_string "fmul")
15435169699Skan	   (const_string "fop")))
15436169699Skan   (set_attr "mode" "DF")])
15437169699Skan
15438169699Skan(define_insn "*fop_df_1_mixed"
15439169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,Y")
15440169699Skan	(match_operator:DF 3 "binary_fp_operator"
1544190286Sobrien			[(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
15442169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))]
15443169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
15444169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
1544590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1544690286Sobrien  "* return output_387_binary_op (insn, operands);"
15447259563Spfg  [(set (attr "type")
15448117404Skan        (cond [(and (eq_attr "alternative" "2")
15449169699Skan	            (match_operand:DF 3 "mult_operator" ""))
15450117404Skan                 (const_string "ssemul")
15451117404Skan	       (and (eq_attr "alternative" "2")
15452169699Skan	            (match_operand:DF 3 "div_operator" ""))
15453117404Skan                 (const_string "ssediv")
15454117404Skan	       (eq_attr "alternative" "2")
15455117404Skan                 (const_string "sseadd")
15456259563Spfg	       (match_operand:DF 3 "mult_operator" "")
1545790286Sobrien                 (const_string "fmul")
15458259563Spfg               (match_operand:DF 3 "div_operator" "")
1545990286Sobrien                 (const_string "fdiv")
1546090286Sobrien              ]
1546190286Sobrien              (const_string "fop")))
1546290286Sobrien   (set_attr "mode" "DF")])
1546318334Speter
1546490286Sobrien(define_insn "*fop_df_1_sse"
1546590286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1546690286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1546790286Sobrien			[(match_operand:DF 1 "register_operand" "0")
1546890286Sobrien			 (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
1546990286Sobrien  "TARGET_SSE2 && TARGET_SSE_MATH
15470169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1547190286Sobrien  "* return output_387_binary_op (insn, operands);"
15472117404Skan  [(set_attr "mode" "DF")
15473259563Spfg   (set (attr "type")
15474169699Skan        (cond [(match_operand:DF 3 "mult_operator" "")
15475117404Skan                 (const_string "ssemul")
15476169699Skan	       (match_operand:DF 3 "div_operator" "")
15477117404Skan                 (const_string "ssediv")
15478117404Skan              ]
15479117404Skan              (const_string "sseadd")))])
1548018334Speter
15481169699Skan;; This pattern is not fully shadowed by the pattern above.
15482169699Skan(define_insn "*fop_df_1_i387"
15483169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
15484169699Skan	(match_operator:DF 3 "binary_fp_operator"
15485169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "0,fm")
15486169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
15487169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
15488169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
15489169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15490169699Skan  "* return output_387_binary_op (insn, operands);"
15491259563Spfg  [(set (attr "type")
15492259563Spfg        (cond [(match_operand:DF 3 "mult_operator" "")
15493169699Skan                 (const_string "fmul")
15494169699Skan               (match_operand:DF 3 "div_operator" "")
15495169699Skan                 (const_string "fdiv")
15496169699Skan              ]
15497169699Skan              (const_string "fop")))
15498169699Skan   (set_attr "mode" "DF")])
15499169699Skan
1550090286Sobrien;; ??? Add SSE splitters for these!
15501169699Skan(define_insn "*fop_df_2<mode>_i387"
1550290286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1550390286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15504169699Skan	   [(float:DF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1550590286Sobrien	    (match_operand:DF 2 "register_operand" "0,0")]))]
15506169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
15507169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1550890286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
15509259563Spfg  [(set (attr "type")
15510259563Spfg        (cond [(match_operand:DF 3 "mult_operator" "")
1551190286Sobrien                 (const_string "fmul")
15512259563Spfg               (match_operand:DF 3 "div_operator" "")
1551390286Sobrien                 (const_string "fdiv")
1551490286Sobrien              ]
1551590286Sobrien              (const_string "fop")))
1551690286Sobrien   (set_attr "fp_int_src" "true")
15517169699Skan   (set_attr "mode" "<MODE>")])
1551818334Speter
15519169699Skan(define_insn "*fop_df_3<mode>_i387"
1552090286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1552190286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1552290286Sobrien	   [(match_operand:DF 1 "register_operand" "0,0")
15523169699Skan	    (float:DF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15524169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
15525169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1552690286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
15527259563Spfg  [(set (attr "type")
15528259563Spfg        (cond [(match_operand:DF 3 "mult_operator" "")
1552990286Sobrien                 (const_string "fmul")
15530259563Spfg               (match_operand:DF 3 "div_operator" "")
1553190286Sobrien                 (const_string "fdiv")
1553290286Sobrien              ]
1553390286Sobrien              (const_string "fop")))
1553490286Sobrien   (set_attr "fp_int_src" "true")
15535169699Skan   (set_attr "mode" "<MODE>")])
1553618334Speter
15537169699Skan(define_insn "*fop_df_4_i387"
1553890286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1553990286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1554090286Sobrien	   [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
1554190286Sobrien	    (match_operand:DF 2 "register_operand" "0,f")]))]
15542169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
1554390286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1554490286Sobrien  "* return output_387_binary_op (insn, operands);"
15545259563Spfg  [(set (attr "type")
15546259563Spfg        (cond [(match_operand:DF 3 "mult_operator" "")
1554790286Sobrien                 (const_string "fmul")
15548259563Spfg               (match_operand:DF 3 "div_operator" "")
1554990286Sobrien                 (const_string "fdiv")
1555090286Sobrien              ]
1555190286Sobrien              (const_string "fop")))
1555290286Sobrien   (set_attr "mode" "SF")])
1555318334Speter
15554169699Skan(define_insn "*fop_df_5_i387"
1555518334Speter  [(set (match_operand:DF 0 "register_operand" "=f,f")
1555690286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1555790286Sobrien	  [(match_operand:DF 1 "register_operand" "0,f")
1555890286Sobrien	   (float_extend:DF
1555990286Sobrien	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
1556090286Sobrien  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1556150650Sobrien  "* return output_387_binary_op (insn, operands);"
15562259563Spfg  [(set (attr "type")
15563259563Spfg        (cond [(match_operand:DF 3 "mult_operator" "")
1556490286Sobrien                 (const_string "fmul")
15565259563Spfg               (match_operand:DF 3 "div_operator" "")
1556690286Sobrien                 (const_string "fdiv")
1556750650Sobrien              ]
1556890286Sobrien              (const_string "fop")))
1556990286Sobrien   (set_attr "mode" "SF")])
1557018334Speter
15571169699Skan(define_insn "*fop_df_6_i387"
15572132727Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
15573132727Skan	(match_operator:DF 3 "binary_fp_operator"
15574132727Skan	  [(float_extend:DF
15575132727Skan	    (match_operand:SF 1 "register_operand" "0,f"))
15576132727Skan	   (float_extend:DF
15577132727Skan	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
15578132727Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1557950650Sobrien  "* return output_387_binary_op (insn, operands);"
15580259563Spfg  [(set (attr "type")
15581259563Spfg        (cond [(match_operand:DF 3 "mult_operator" "")
1558290286Sobrien                 (const_string "fmul")
15583259563Spfg               (match_operand:DF 3 "div_operator" "")
1558490286Sobrien                 (const_string "fdiv")
1558550650Sobrien              ]
1558690286Sobrien              (const_string "fop")))
15587132727Skan   (set_attr "mode" "SF")])
1558818334Speter
15589169699Skan(define_insn "*fop_xf_comm_i387"
15590169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15591169699Skan	(match_operator:XF 3 "binary_fp_operator"
15592169699Skan			[(match_operand:XF 1 "register_operand" "%0")
15593169699Skan			 (match_operand:XF 2 "register_operand" "f")]))]
15594169699Skan  "TARGET_80387
15595169699Skan   && COMMUTATIVE_ARITH_P (operands[3])"
15596169699Skan  "* return output_387_binary_op (insn, operands);"
15597259563Spfg  [(set (attr "type")
15598259563Spfg        (if_then_else (match_operand:XF 3 "mult_operator" "")
15599169699Skan           (const_string "fmul")
15600169699Skan           (const_string "fop")))
15601169699Skan   (set_attr "mode" "XF")])
15602169699Skan
15603169699Skan(define_insn "*fop_xf_1_i387"
15604132727Skan  [(set (match_operand:XF 0 "register_operand" "=f,f")
15605132727Skan	(match_operator:XF 3 "binary_fp_operator"
15606132727Skan			[(match_operand:XF 1 "register_operand" "0,f")
15607132727Skan			 (match_operand:XF 2 "register_operand" "f,0")]))]
1560890286Sobrien  "TARGET_80387
15609169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1561090286Sobrien  "* return output_387_binary_op (insn, operands);"
15611259563Spfg  [(set (attr "type")
15612259563Spfg        (cond [(match_operand:XF 3 "mult_operator" "")
1561390286Sobrien                 (const_string "fmul")
15614259563Spfg               (match_operand:XF 3 "div_operator" "")
1561590286Sobrien                 (const_string "fdiv")
1561690286Sobrien              ]
1561790286Sobrien              (const_string "fop")))
1561890286Sobrien   (set_attr "mode" "XF")])
1561990286Sobrien
15620169699Skan(define_insn "*fop_xf_2<mode>_i387"
1562118334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
1562290286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15623169699Skan	   [(float:XF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1562490286Sobrien	    (match_operand:XF 2 "register_operand" "0,0")]))]
15625169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
1562690286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
15627259563Spfg  [(set (attr "type")
15628259563Spfg        (cond [(match_operand:XF 3 "mult_operator" "")
1562990286Sobrien                 (const_string "fmul")
15630259563Spfg               (match_operand:XF 3 "div_operator" "")
1563190286Sobrien                 (const_string "fdiv")
1563290286Sobrien              ]
1563390286Sobrien              (const_string "fop")))
1563490286Sobrien   (set_attr "fp_int_src" "true")
15635169699Skan   (set_attr "mode" "<MODE>")])
1563690286Sobrien
15637169699Skan(define_insn "*fop_xf_3<mode>_i387"
1563890286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1563990286Sobrien	(match_operator:XF 3 "binary_fp_operator"
1564090286Sobrien	  [(match_operand:XF 1 "register_operand" "0,0")
15641169699Skan	   (float:XF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15642169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
1564390286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
15644259563Spfg  [(set (attr "type")
15645259563Spfg        (cond [(match_operand:XF 3 "mult_operator" "")
1564690286Sobrien                 (const_string "fmul")
15647259563Spfg               (match_operand:XF 3 "div_operator" "")
1564890286Sobrien                 (const_string "fdiv")
1564990286Sobrien              ]
1565090286Sobrien              (const_string "fop")))
1565190286Sobrien   (set_attr "fp_int_src" "true")
15652169699Skan   (set_attr "mode" "<MODE>")])
1565390286Sobrien
15654169699Skan(define_insn "*fop_xf_4_i387"
1565590286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1565690286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15657132727Skan	   [(float_extend:XF (match_operand 1 "nonimmediate_operand" "fm,0"))
1565850650Sobrien	    (match_operand:XF 2 "register_operand" "0,f")]))]
15659132727Skan  "TARGET_80387"
1566090286Sobrien  "* return output_387_binary_op (insn, operands);"
15661259563Spfg  [(set (attr "type")
15662259563Spfg        (cond [(match_operand:XF 3 "mult_operator" "")
1566390286Sobrien                 (const_string "fmul")
15664259563Spfg               (match_operand:XF 3 "div_operator" "")
1566590286Sobrien                 (const_string "fdiv")
1566690286Sobrien              ]
1566790286Sobrien              (const_string "fop")))
1566890286Sobrien   (set_attr "mode" "SF")])
1566990286Sobrien
15670169699Skan(define_insn "*fop_xf_5_i387"
1567118334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
1567290286Sobrien	(match_operator:XF 3 "binary_fp_operator"
1567350650Sobrien	  [(match_operand:XF 1 "register_operand" "0,f")
1567418334Speter	   (float_extend:XF
15675132727Skan	    (match_operand 2 "nonimmediate_operand" "fm,0"))]))]
15676132727Skan  "TARGET_80387"
1567750650Sobrien  "* return output_387_binary_op (insn, operands);"
15678259563Spfg  [(set (attr "type")
15679259563Spfg        (cond [(match_operand:XF 3 "mult_operator" "")
1568090286Sobrien                 (const_string "fmul")
15681259563Spfg               (match_operand:XF 3 "div_operator" "")
1568290286Sobrien                 (const_string "fdiv")
1568350650Sobrien              ]
1568490286Sobrien              (const_string "fop")))
1568590286Sobrien   (set_attr "mode" "SF")])
1568618334Speter
15687169699Skan(define_insn "*fop_xf_6_i387"
1568890286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1568990286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15690132727Skan	  [(float_extend:XF
15691132727Skan	    (match_operand 1 "register_operand" "0,f"))
15692132727Skan	   (float_extend:XF
15693132727Skan	    (match_operand 2 "nonimmediate_operand" "fm,0"))]))]
1569418334Speter  "TARGET_80387"
1569550650Sobrien  "* return output_387_binary_op (insn, operands);"
15696259563Spfg  [(set (attr "type")
15697259563Spfg        (cond [(match_operand:XF 3 "mult_operator" "")
1569890286Sobrien                 (const_string "fmul")
15699259563Spfg               (match_operand:XF 3 "div_operator" "")
1570090286Sobrien                 (const_string "fdiv")
1570190286Sobrien              ]
1570290286Sobrien              (const_string "fop")))
15703132727Skan   (set_attr "mode" "SF")])
1570490286Sobrien
1570590286Sobrien(define_split
1570690286Sobrien  [(set (match_operand 0 "register_operand" "")
1570790286Sobrien	(match_operator 3 "binary_fp_operator"
15708169699Skan	   [(float (match_operand:X87MODEI12 1 "register_operand" ""))
1570990286Sobrien	    (match_operand 2 "register_operand" "")]))]
1571090286Sobrien  "TARGET_80387 && reload_completed
1571190286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))"
1571290286Sobrien  [(const_int 0)]
15713259563Spfg{
1571490286Sobrien  operands[4] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
1571590286Sobrien  operands[4] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[4]);
1571690286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1571790286Sobrien			  gen_rtx_fmt_ee (GET_CODE (operands[3]),
1571890286Sobrien					  GET_MODE (operands[3]),
1571990286Sobrien					  operands[4],
1572090286Sobrien					  operands[2])));
1572190286Sobrien  ix86_free_from_memory (GET_MODE (operands[1]));
1572290286Sobrien  DONE;
1572390286Sobrien})
1572490286Sobrien
1572590286Sobrien(define_split
1572690286Sobrien  [(set (match_operand 0 "register_operand" "")
1572790286Sobrien	(match_operator 3 "binary_fp_operator"
1572890286Sobrien	   [(match_operand 1 "register_operand" "")
15729169699Skan	    (float (match_operand:X87MODEI12 2 "register_operand" ""))]))]
1573090286Sobrien  "TARGET_80387 && reload_completed
1573190286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))"
1573290286Sobrien  [(const_int 0)]
1573390286Sobrien{
1573490286Sobrien  operands[4] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
1573590286Sobrien  operands[4] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[4]);
1573690286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1573790286Sobrien			  gen_rtx_fmt_ee (GET_CODE (operands[3]),
1573890286Sobrien					  GET_MODE (operands[3]),
1573990286Sobrien					  operands[1],
1574090286Sobrien					  operands[4])));
1574190286Sobrien  ix86_free_from_memory (GET_MODE (operands[2]));
1574290286Sobrien  DONE;
1574390286Sobrien})
1574418334Speter
1574590286Sobrien;; FPU special functions.
1574690286Sobrien
1574790286Sobrien(define_expand "sqrtsf2"
1574890286Sobrien  [(set (match_operand:SF 0 "register_operand" "")
1574990286Sobrien	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
15750169699Skan  "TARGET_USE_FANCY_MATH_387 || TARGET_SSE_MATH"
1575190286Sobrien{
1575290286Sobrien  if (!TARGET_SSE_MATH)
1575390286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
1575490286Sobrien})
1575590286Sobrien
15756169699Skan(define_insn "*sqrtsf2_mixed"
15757169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,x")
15758169699Skan	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))]
15759169699Skan  "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387"
1576090286Sobrien  "@
1576190286Sobrien   fsqrt
1576290286Sobrien   sqrtss\t{%1, %0|%0, %1}"
1576390286Sobrien  [(set_attr "type" "fpspc,sse")
1576490286Sobrien   (set_attr "mode" "SF,SF")
15765251212Spfg   (set_attr "athlon_decode" "direct,*")
15766251212Spfg   (set_attr "amdfam10_decode" "direct,*")])
1576790286Sobrien
15768169699Skan(define_insn "*sqrtsf2_sse"
1576990286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1577090286Sobrien	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "xm")))]
15771169699Skan  "TARGET_SSE_MATH"
1577290286Sobrien  "sqrtss\t{%1, %0|%0, %1}"
1577390286Sobrien  [(set_attr "type" "sse")
1577490286Sobrien   (set_attr "mode" "SF")
15775251212Spfg   (set_attr "athlon_decode" "*")
15776251212Spfg   (set_attr "amdfam10_decode" "*")])
1577790286Sobrien
15778169699Skan(define_insn "*sqrtsf2_i387"
1577990286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
1578090286Sobrien	(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
15781169699Skan  "TARGET_USE_FANCY_MATH_387"
1578290286Sobrien  "fsqrt"
1578390286Sobrien  [(set_attr "type" "fpspc")
1578490286Sobrien   (set_attr "mode" "SF")
15785251212Spfg   (set_attr "athlon_decode" "direct")
15786251212Spfg   (set_attr "amdfam10_decode" "direct")])
1578790286Sobrien
1578890286Sobrien(define_expand "sqrtdf2"
1578990286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
1579090286Sobrien	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
15791169699Skan  "TARGET_USE_FANCY_MATH_387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
1579290286Sobrien{
15793169699Skan  if (!(TARGET_SSE2 && TARGET_SSE_MATH))
1579490286Sobrien    operands[1] = force_reg (DFmode, operands[1]);
1579590286Sobrien})
1579690286Sobrien
15797169699Skan(define_insn "*sqrtdf2_mixed"
15798169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,Y")
15799169699Skan	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))]
15800169699Skan  "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387"
1580190286Sobrien  "@
1580290286Sobrien   fsqrt
1580390286Sobrien   sqrtsd\t{%1, %0|%0, %1}"
1580490286Sobrien  [(set_attr "type" "fpspc,sse")
1580590286Sobrien   (set_attr "mode" "DF,DF")
15806251212Spfg   (set_attr "athlon_decode" "direct,*")
15807251212Spfg   (set_attr "amdfam10_decode" "direct,*")])
1580890286Sobrien
15809169699Skan(define_insn "*sqrtdf2_sse"
1581090286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1581190286Sobrien	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
15812169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
1581390286Sobrien  "sqrtsd\t{%1, %0|%0, %1}"
1581490286Sobrien  [(set_attr "type" "sse")
1581590286Sobrien   (set_attr "mode" "DF")
15816251212Spfg   (set_attr "athlon_decode" "*")
15817251212Spfg   (set_attr "amdfam10_decode" "*")])
1581890286Sobrien
15819169699Skan(define_insn "*sqrtdf2_i387"
1582090286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1582190286Sobrien	(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
15822169699Skan  "TARGET_USE_FANCY_MATH_387"
1582390286Sobrien  "fsqrt"
1582490286Sobrien  [(set_attr "type" "fpspc")
1582590286Sobrien   (set_attr "mode" "DF")
15826251212Spfg   (set_attr "athlon_decode" "direct")
15827251212Spfg   (set_attr "amdfam10_decode" "direct")])
1582890286Sobrien
15829169699Skan(define_insn "*sqrtextendsfdf2_i387"
1583090286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1583190286Sobrien	(sqrt:DF (float_extend:DF
1583290286Sobrien		  (match_operand:SF 1 "register_operand" "0"))))]
15833169699Skan  "TARGET_USE_FANCY_MATH_387
15834169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
1583590286Sobrien  "fsqrt"
1583690286Sobrien  [(set_attr "type" "fpspc")
1583790286Sobrien   (set_attr "mode" "DF")
15838251212Spfg   (set_attr "athlon_decode" "direct")
15839251212Spfg   (set_attr "amdfam10_decode" "direct")])
1584090286Sobrien
1584190286Sobrien(define_insn "sqrtxf2"
1584290286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1584390286Sobrien	(sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
15844169699Skan  "TARGET_USE_FANCY_MATH_387"
1584590286Sobrien  "fsqrt"
1584690286Sobrien  [(set_attr "type" "fpspc")
1584790286Sobrien   (set_attr "mode" "XF")
15848251212Spfg   (set_attr "athlon_decode" "direct")
15849251212Spfg   (set_attr "amdfam10_decode" "direct")])
1585090286Sobrien
15851169699Skan(define_insn "*sqrtextendsfxf2_i387"
1585290286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1585390286Sobrien	(sqrt:XF (float_extend:XF
15854169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
15855169699Skan  "TARGET_USE_FANCY_MATH_387"
1585690286Sobrien  "fsqrt"
1585790286Sobrien  [(set_attr "type" "fpspc")
1585890286Sobrien   (set_attr "mode" "XF")
15859251212Spfg   (set_attr "athlon_decode" "direct")
15860251212Spfg   (set_attr "amdfam10_decode" "direct")])
1586190286Sobrien
15862169699Skan(define_insn "*sqrtextenddfxf2_i387"
1586390286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1586490286Sobrien	(sqrt:XF (float_extend:XF
15865169699Skan		  (match_operand:DF 1 "register_operand" "0"))))]
15866169699Skan  "TARGET_USE_FANCY_MATH_387"
1586790286Sobrien  "fsqrt"
1586890286Sobrien  [(set_attr "type" "fpspc")
1586990286Sobrien   (set_attr "mode" "XF")
15870251212Spfg   (set_attr "athlon_decode" "direct")
15871251212Spfg   (set_attr "amdfam10_decode" "direct")])
1587290286Sobrien
15873169699Skan(define_insn "fpremxf4"
15874169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15875169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
15876169699Skan		    (match_operand:XF 3 "register_operand" "1")]
15877169699Skan		   UNSPEC_FPREM_F))
15878169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15879169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
15880169699Skan		   UNSPEC_FPREM_U))
15881169699Skan   (set (reg:CCFP FPSR_REG)
15882169699Skan	(unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
15883169699Skan  "TARGET_USE_FANCY_MATH_387
15884169699Skan   && flag_unsafe_math_optimizations"
15885169699Skan  "fprem"
15886169699Skan  [(set_attr "type" "fpspc")
15887169699Skan   (set_attr "mode" "XF")])
15888169699Skan
15889169699Skan(define_expand "fmodsf3"
15890169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
15891169699Skan   (use (match_operand:SF 1 "register_operand" ""))
15892169699Skan   (use (match_operand:SF 2 "register_operand" ""))]
15893169699Skan  "TARGET_USE_FANCY_MATH_387
15894169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15895169699Skan   && flag_unsafe_math_optimizations"
15896169699Skan{
15897169699Skan  rtx label = gen_label_rtx ();
15898169699Skan
15899169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15900169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15901169699Skan
15902169699Skan  emit_insn(gen_extendsfxf2 (op1, operands[1]));
15903169699Skan  emit_insn(gen_extendsfxf2 (op2, operands[2]));
15904169699Skan
15905169699Skan  emit_label (label);
15906169699Skan
15907169699Skan  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
15908169699Skan  ix86_emit_fp_unordered_jump (label);
15909169699Skan
15910169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
15911169699Skan  DONE;
15912169699Skan})
15913169699Skan
15914169699Skan(define_expand "fmoddf3"
15915169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
15916169699Skan   (use (match_operand:DF 1 "register_operand" ""))
15917169699Skan   (use (match_operand:DF 2 "register_operand" ""))]
15918169699Skan  "TARGET_USE_FANCY_MATH_387
15919169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15920169699Skan   && flag_unsafe_math_optimizations"
15921169699Skan{
15922169699Skan  rtx label = gen_label_rtx ();
15923169699Skan
15924169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15925169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15926169699Skan
15927169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
15928169699Skan  emit_insn (gen_extenddfxf2 (op2, operands[2]));
15929169699Skan
15930169699Skan  emit_label (label);
15931169699Skan
15932169699Skan  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
15933169699Skan  ix86_emit_fp_unordered_jump (label);
15934169699Skan
15935169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
15936169699Skan  DONE;
15937169699Skan})
15938169699Skan
15939169699Skan(define_expand "fmodxf3"
15940169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
15941169699Skan   (use (match_operand:XF 1 "register_operand" ""))
15942169699Skan   (use (match_operand:XF 2 "register_operand" ""))]
15943169699Skan  "TARGET_USE_FANCY_MATH_387
15944169699Skan   && flag_unsafe_math_optimizations"
15945169699Skan{
15946169699Skan  rtx label = gen_label_rtx ();
15947169699Skan
15948169699Skan  emit_label (label);
15949169699Skan
15950169699Skan  emit_insn (gen_fpremxf4 (operands[1], operands[2],
15951169699Skan			   operands[1], operands[2]));
15952169699Skan  ix86_emit_fp_unordered_jump (label);
15953169699Skan
15954169699Skan  emit_move_insn (operands[0], operands[1]);
15955169699Skan  DONE;
15956169699Skan})
15957169699Skan
15958169699Skan(define_insn "fprem1xf4"
15959169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15960169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
15961169699Skan		    (match_operand:XF 3 "register_operand" "1")]
15962169699Skan		   UNSPEC_FPREM1_F))
15963169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15964169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
15965169699Skan		   UNSPEC_FPREM1_U))
15966169699Skan   (set (reg:CCFP FPSR_REG)
15967169699Skan	(unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
15968169699Skan  "TARGET_USE_FANCY_MATH_387
15969169699Skan   && flag_unsafe_math_optimizations"
15970169699Skan  "fprem1"
15971169699Skan  [(set_attr "type" "fpspc")
15972169699Skan   (set_attr "mode" "XF")])
15973169699Skan
15974169699Skan(define_expand "dremsf3"
15975169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
15976169699Skan   (use (match_operand:SF 1 "register_operand" ""))
15977169699Skan   (use (match_operand:SF 2 "register_operand" ""))]
15978169699Skan  "TARGET_USE_FANCY_MATH_387
15979169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15980169699Skan   && flag_unsafe_math_optimizations"
15981169699Skan{
15982169699Skan  rtx label = gen_label_rtx ();
15983169699Skan
15984169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15985169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15986169699Skan
15987169699Skan  emit_insn(gen_extendsfxf2 (op1, operands[1]));
15988169699Skan  emit_insn(gen_extendsfxf2 (op2, operands[2]));
15989169699Skan
15990169699Skan  emit_label (label);
15991169699Skan
15992169699Skan  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
15993169699Skan  ix86_emit_fp_unordered_jump (label);
15994169699Skan
15995169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
15996169699Skan  DONE;
15997169699Skan})
15998169699Skan
15999169699Skan(define_expand "dremdf3"
16000169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
16001169699Skan   (use (match_operand:DF 1 "register_operand" ""))
16002169699Skan   (use (match_operand:DF 2 "register_operand" ""))]
16003169699Skan  "TARGET_USE_FANCY_MATH_387
16004169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16005169699Skan   && flag_unsafe_math_optimizations"
16006169699Skan{
16007169699Skan  rtx label = gen_label_rtx ();
16008169699Skan
16009169699Skan  rtx op1 = gen_reg_rtx (XFmode);
16010169699Skan  rtx op2 = gen_reg_rtx (XFmode);
16011169699Skan
16012169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
16013169699Skan  emit_insn (gen_extenddfxf2 (op2, operands[2]));
16014169699Skan
16015169699Skan  emit_label (label);
16016169699Skan
16017169699Skan  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
16018169699Skan  ix86_emit_fp_unordered_jump (label);
16019169699Skan
16020169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
16021169699Skan  DONE;
16022169699Skan})
16023169699Skan
16024169699Skan(define_expand "dremxf3"
16025169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
16026169699Skan   (use (match_operand:XF 1 "register_operand" ""))
16027169699Skan   (use (match_operand:XF 2 "register_operand" ""))]
16028169699Skan  "TARGET_USE_FANCY_MATH_387
16029169699Skan   && flag_unsafe_math_optimizations"
16030169699Skan{
16031169699Skan  rtx label = gen_label_rtx ();
16032169699Skan
16033169699Skan  emit_label (label);
16034169699Skan
16035169699Skan  emit_insn (gen_fprem1xf4 (operands[1], operands[2],
16036169699Skan			    operands[1], operands[2]));
16037169699Skan  ix86_emit_fp_unordered_jump (label);
16038169699Skan
16039169699Skan  emit_move_insn (operands[0], operands[1]);
16040169699Skan  DONE;
16041169699Skan})
16042169699Skan
16043169699Skan(define_insn "*sindf2"
1604490286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
16045117404Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_SIN))]
16046169699Skan  "TARGET_USE_FANCY_MATH_387
16047169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1604890286Sobrien   && flag_unsafe_math_optimizations"
1604990286Sobrien  "fsin"
1605090286Sobrien  [(set_attr "type" "fpspc")
1605190286Sobrien   (set_attr "mode" "DF")])
1605290286Sobrien
16053169699Skan(define_insn "*sinsf2"
1605490286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
16055117404Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_SIN))]
16056169699Skan  "TARGET_USE_FANCY_MATH_387
16057169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
1605890286Sobrien   && flag_unsafe_math_optimizations"
1605990286Sobrien  "fsin"
1606090286Sobrien  [(set_attr "type" "fpspc")
1606190286Sobrien   (set_attr "mode" "SF")])
1606290286Sobrien
1606390286Sobrien(define_insn "*sinextendsfdf2"
1606490286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1606590286Sobrien	(unspec:DF [(float_extend:DF
16066117404Skan		     (match_operand:SF 1 "register_operand" "0"))]
16067117404Skan		   UNSPEC_SIN))]
16068169699Skan  "TARGET_USE_FANCY_MATH_387
16069169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1607090286Sobrien   && flag_unsafe_math_optimizations"
1607190286Sobrien  "fsin"
1607290286Sobrien  [(set_attr "type" "fpspc")
1607390286Sobrien   (set_attr "mode" "DF")])
1607490286Sobrien
16075169699Skan(define_insn "*sinxf2"
1607690286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
16077117404Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_SIN))]
16078169699Skan  "TARGET_USE_FANCY_MATH_387
1607990286Sobrien   && flag_unsafe_math_optimizations"
1608090286Sobrien  "fsin"
1608190286Sobrien  [(set_attr "type" "fpspc")
1608290286Sobrien   (set_attr "mode" "XF")])
1608390286Sobrien
16084169699Skan(define_insn "*cosdf2"
1608590286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
16086117404Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_COS))]
16087169699Skan  "TARGET_USE_FANCY_MATH_387
16088169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1608990286Sobrien   && flag_unsafe_math_optimizations"
1609090286Sobrien  "fcos"
1609190286Sobrien  [(set_attr "type" "fpspc")
1609290286Sobrien   (set_attr "mode" "DF")])
1609390286Sobrien
16094169699Skan(define_insn "*cossf2"
1609590286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
16096117404Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_COS))]
16097169699Skan  "TARGET_USE_FANCY_MATH_387
16098169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
1609990286Sobrien   && flag_unsafe_math_optimizations"
1610090286Sobrien  "fcos"
1610190286Sobrien  [(set_attr "type" "fpspc")
1610290286Sobrien   (set_attr "mode" "SF")])
1610390286Sobrien
1610490286Sobrien(define_insn "*cosextendsfdf2"
1610590286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1610690286Sobrien	(unspec:DF [(float_extend:DF
16107117404Skan		     (match_operand:SF 1 "register_operand" "0"))]
16108117404Skan		   UNSPEC_COS))]
16109169699Skan  "TARGET_USE_FANCY_MATH_387
16110169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1611190286Sobrien   && flag_unsafe_math_optimizations"
1611290286Sobrien  "fcos"
1611390286Sobrien  [(set_attr "type" "fpspc")
1611490286Sobrien   (set_attr "mode" "DF")])
1611590286Sobrien
16116169699Skan(define_insn "*cosxf2"
1611790286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
16118117404Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_COS))]
16119169699Skan  "TARGET_USE_FANCY_MATH_387
1612090286Sobrien   && flag_unsafe_math_optimizations"
1612190286Sobrien  "fcos"
1612290286Sobrien  [(set_attr "type" "fpspc")
1612390286Sobrien   (set_attr "mode" "XF")])
1612490286Sobrien
16125169699Skan;; With sincos pattern defined, sin and cos builtin function will be
16126259563Spfg;; expanded to sincos pattern with one of its outputs left unused.
16127169699Skan;; Cse pass  will detected, if two sincos patterns can be combined,
16128169699Skan;; otherwise sincos pattern will be split back to sin or cos pattern,
16129169699Skan;; depending on the unused output.
16130169699Skan
16131169699Skan(define_insn "sincosdf3"
16132169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
16133169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")]
16134169699Skan		   UNSPEC_SINCOS_COS))
16135169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
16136169699Skan        (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
16137169699Skan  "TARGET_USE_FANCY_MATH_387
16138169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16139169699Skan   && flag_unsafe_math_optimizations"
16140169699Skan  "fsincos"
16141169699Skan  [(set_attr "type" "fpspc")
16142169699Skan   (set_attr "mode" "DF")])
16143169699Skan
16144169699Skan(define_split
16145169699Skan  [(set (match_operand:DF 0 "register_operand" "")
16146169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "")]
16147169699Skan		   UNSPEC_SINCOS_COS))
16148169699Skan   (set (match_operand:DF 1 "register_operand" "")
16149169699Skan	(unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
16150169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
16151169699Skan   && !reload_completed && !reload_in_progress"
16152169699Skan  [(set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_SIN))]
16153169699Skan  "")
16154169699Skan
16155169699Skan(define_split
16156169699Skan  [(set (match_operand:DF 0 "register_operand" "")
16157169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "")]
16158169699Skan		   UNSPEC_SINCOS_COS))
16159169699Skan   (set (match_operand:DF 1 "register_operand" "")
16160169699Skan	(unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
16161169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
16162169699Skan   && !reload_completed && !reload_in_progress"
16163169699Skan  [(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_COS))]
16164169699Skan  "")
16165169699Skan
16166169699Skan(define_insn "sincossf3"
16167169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
16168169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "0")]
16169169699Skan		   UNSPEC_SINCOS_COS))
16170169699Skan   (set (match_operand:SF 1 "register_operand" "=u")
16171169699Skan        (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
16172169699Skan  "TARGET_USE_FANCY_MATH_387
16173169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16174169699Skan   && flag_unsafe_math_optimizations"
16175169699Skan  "fsincos"
16176169699Skan  [(set_attr "type" "fpspc")
16177169699Skan   (set_attr "mode" "SF")])
16178169699Skan
16179169699Skan(define_split
16180169699Skan  [(set (match_operand:SF 0 "register_operand" "")
16181169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "")]
16182169699Skan		   UNSPEC_SINCOS_COS))
16183169699Skan   (set (match_operand:SF 1 "register_operand" "")
16184169699Skan	(unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
16185169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
16186169699Skan   && !reload_completed && !reload_in_progress"
16187169699Skan  [(set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_SIN))]
16188169699Skan  "")
16189169699Skan
16190169699Skan(define_split
16191169699Skan  [(set (match_operand:SF 0 "register_operand" "")
16192169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "")]
16193169699Skan		   UNSPEC_SINCOS_COS))
16194169699Skan   (set (match_operand:SF 1 "register_operand" "")
16195169699Skan	(unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
16196169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
16197169699Skan   && !reload_completed && !reload_in_progress"
16198169699Skan  [(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_COS))]
16199169699Skan  "")
16200169699Skan
16201169699Skan(define_insn "*sincosextendsfdf3"
16202169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
16203169699Skan	(unspec:DF [(float_extend:DF
16204169699Skan		     (match_operand:SF 2 "register_operand" "0"))]
16205169699Skan		   UNSPEC_SINCOS_COS))
16206169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
16207169699Skan        (unspec:DF [(float_extend:DF
16208169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
16209169699Skan  "TARGET_USE_FANCY_MATH_387
16210169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16211169699Skan   && flag_unsafe_math_optimizations"
16212169699Skan  "fsincos"
16213169699Skan  [(set_attr "type" "fpspc")
16214169699Skan   (set_attr "mode" "DF")])
16215169699Skan
16216169699Skan(define_split
16217169699Skan  [(set (match_operand:DF 0 "register_operand" "")
16218169699Skan	(unspec:DF [(float_extend:DF
16219169699Skan		     (match_operand:SF 2 "register_operand" ""))]
16220169699Skan		   UNSPEC_SINCOS_COS))
16221169699Skan   (set (match_operand:DF 1 "register_operand" "")
16222169699Skan        (unspec:DF [(float_extend:DF
16223169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
16224169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
16225169699Skan   && !reload_completed && !reload_in_progress"
16226169699Skan  [(set (match_dup 1) (unspec:DF [(float_extend:DF
16227169699Skan				   (match_dup 2))] UNSPEC_SIN))]
16228169699Skan  "")
16229169699Skan
16230169699Skan(define_split
16231169699Skan  [(set (match_operand:DF 0 "register_operand" "")
16232169699Skan	(unspec:DF [(float_extend:DF
16233169699Skan		     (match_operand:SF 2 "register_operand" ""))]
16234169699Skan		   UNSPEC_SINCOS_COS))
16235169699Skan   (set (match_operand:DF 1 "register_operand" "")
16236169699Skan        (unspec:DF [(float_extend:DF
16237169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
16238169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
16239169699Skan   && !reload_completed && !reload_in_progress"
16240169699Skan  [(set (match_dup 0) (unspec:DF [(float_extend:DF
16241169699Skan				   (match_dup 2))] UNSPEC_COS))]
16242169699Skan  "")
16243169699Skan
16244169699Skan(define_insn "sincosxf3"
16245169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16246169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
16247169699Skan		   UNSPEC_SINCOS_COS))
16248169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16249169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
16250169699Skan  "TARGET_USE_FANCY_MATH_387
16251169699Skan   && flag_unsafe_math_optimizations"
16252169699Skan  "fsincos"
16253169699Skan  [(set_attr "type" "fpspc")
16254169699Skan   (set_attr "mode" "XF")])
16255169699Skan
16256169699Skan(define_split
16257169699Skan  [(set (match_operand:XF 0 "register_operand" "")
16258169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "")]
16259169699Skan		   UNSPEC_SINCOS_COS))
16260169699Skan   (set (match_operand:XF 1 "register_operand" "")
16261169699Skan	(unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
16262169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
16263169699Skan   && !reload_completed && !reload_in_progress"
16264169699Skan  [(set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_SIN))]
16265169699Skan  "")
16266169699Skan
16267169699Skan(define_split
16268169699Skan  [(set (match_operand:XF 0 "register_operand" "")
16269169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "")]
16270169699Skan		   UNSPEC_SINCOS_COS))
16271169699Skan   (set (match_operand:XF 1 "register_operand" "")
16272169699Skan	(unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
16273169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
16274169699Skan   && !reload_completed && !reload_in_progress"
16275169699Skan  [(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_COS))]
16276169699Skan  "")
16277169699Skan
16278169699Skan(define_insn "*tandf3_1"
16279169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
16280169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")]
16281169699Skan		   UNSPEC_TAN_ONE))
16282169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
16283169699Skan        (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))]
16284169699Skan  "TARGET_USE_FANCY_MATH_387
16285169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16286169699Skan   && flag_unsafe_math_optimizations"
16287169699Skan  "fptan"
16288169699Skan  [(set_attr "type" "fpspc")
16289169699Skan   (set_attr "mode" "DF")])
16290169699Skan
16291169699Skan;; optimize sequence: fptan
16292169699Skan;;		      fstp    %st(0)
16293169699Skan;;		      fld1
16294169699Skan;; into fptan insn.
16295169699Skan
16296169699Skan(define_peephole2
16297169699Skan  [(parallel[(set (match_operand:DF 0 "register_operand" "")
16298169699Skan		  (unspec:DF [(match_operand:DF 2 "register_operand" "")]
16299169699Skan			     UNSPEC_TAN_ONE))
16300169699Skan	     (set (match_operand:DF 1 "register_operand" "")
16301169699Skan		  (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])
16302169699Skan   (set (match_dup 0)
16303169699Skan        (match_operand:DF 3 "immediate_operand" ""))]
16304169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16305169699Skan  [(parallel[(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_TAN_ONE))
16306169699Skan   	     (set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16307169699Skan  "")
16308169699Skan
16309169699Skan(define_expand "tandf2"
16310169699Skan  [(parallel [(set (match_dup 2)
16311169699Skan		   (unspec:DF [(match_operand:DF 1 "register_operand" "")]
16312169699Skan			      UNSPEC_TAN_ONE))
16313169699Skan	      (set (match_operand:DF 0 "register_operand" "")
16314169699Skan		   (unspec:DF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16315169699Skan  "TARGET_USE_FANCY_MATH_387
16316169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16317169699Skan   && flag_unsafe_math_optimizations"
16318169699Skan{
16319169699Skan  operands[2] = gen_reg_rtx (DFmode);
16320169699Skan})
16321169699Skan
16322169699Skan(define_insn "*tansf3_1"
16323169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
16324169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "0")]
16325169699Skan		   UNSPEC_TAN_ONE))
16326169699Skan   (set (match_operand:SF 1 "register_operand" "=u")
16327169699Skan        (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))]
16328169699Skan  "TARGET_USE_FANCY_MATH_387
16329169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16330169699Skan   && flag_unsafe_math_optimizations"
16331169699Skan  "fptan"
16332169699Skan  [(set_attr "type" "fpspc")
16333169699Skan   (set_attr "mode" "SF")])
16334169699Skan
16335169699Skan;; optimize sequence: fptan
16336169699Skan;;		      fstp    %st(0)
16337169699Skan;;		      fld1
16338169699Skan;; into fptan insn.
16339169699Skan
16340169699Skan(define_peephole2
16341169699Skan  [(parallel[(set (match_operand:SF 0 "register_operand" "")
16342169699Skan		  (unspec:SF [(match_operand:SF 2 "register_operand" "")]
16343169699Skan			     UNSPEC_TAN_ONE))
16344169699Skan	     (set (match_operand:SF 1 "register_operand" "")
16345169699Skan		  (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])
16346169699Skan   (set (match_dup 0)
16347169699Skan        (match_operand:SF 3 "immediate_operand" ""))]
16348169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16349169699Skan  [(parallel[(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_TAN_ONE))
16350169699Skan   	     (set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16351169699Skan  "")
16352169699Skan
16353169699Skan(define_expand "tansf2"
16354169699Skan  [(parallel [(set (match_dup 2)
16355169699Skan		   (unspec:SF [(match_operand:SF 1 "register_operand" "")]
16356169699Skan			      UNSPEC_TAN_ONE))
16357169699Skan	      (set (match_operand:SF 0 "register_operand" "")
16358169699Skan		   (unspec:SF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16359169699Skan  "TARGET_USE_FANCY_MATH_387
16360169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16361169699Skan   && flag_unsafe_math_optimizations"
16362169699Skan{
16363169699Skan  operands[2] = gen_reg_rtx (SFmode);
16364169699Skan})
16365169699Skan
16366169699Skan(define_insn "*tanxf3_1"
16367169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16368169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
16369169699Skan		   UNSPEC_TAN_ONE))
16370169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16371169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))]
16372169699Skan  "TARGET_USE_FANCY_MATH_387
16373169699Skan   && flag_unsafe_math_optimizations"
16374169699Skan  "fptan"
16375169699Skan  [(set_attr "type" "fpspc")
16376169699Skan   (set_attr "mode" "XF")])
16377169699Skan
16378169699Skan;; optimize sequence: fptan
16379169699Skan;;		      fstp    %st(0)
16380169699Skan;;		      fld1
16381169699Skan;; into fptan insn.
16382169699Skan
16383169699Skan(define_peephole2
16384169699Skan  [(parallel[(set (match_operand:XF 0 "register_operand" "")
16385169699Skan		  (unspec:XF [(match_operand:XF 2 "register_operand" "")]
16386169699Skan			     UNSPEC_TAN_ONE))
16387169699Skan	     (set (match_operand:XF 1 "register_operand" "")
16388169699Skan		  (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])
16389169699Skan   (set (match_dup 0)
16390169699Skan        (match_operand:XF 3 "immediate_operand" ""))]
16391169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16392169699Skan  [(parallel[(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_TAN_ONE))
16393169699Skan   	     (set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16394169699Skan  "")
16395169699Skan
16396169699Skan(define_expand "tanxf2"
16397169699Skan  [(parallel [(set (match_dup 2)
16398169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16399169699Skan			      UNSPEC_TAN_ONE))
16400169699Skan	      (set (match_operand:XF 0 "register_operand" "")
16401169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16402169699Skan  "TARGET_USE_FANCY_MATH_387
16403169699Skan   && flag_unsafe_math_optimizations"
16404169699Skan{
16405169699Skan  operands[2] = gen_reg_rtx (XFmode);
16406169699Skan})
16407169699Skan
16408132727Skan(define_insn "atan2df3_1"
16409132727Skan  [(set (match_operand:DF 0 "register_operand" "=f")
16410132727Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")
16411132727Skan		    (match_operand:DF 1 "register_operand" "u")]
16412132727Skan		   UNSPEC_FPATAN))
16413132727Skan   (clobber (match_scratch:DF 3 "=1"))]
16414169699Skan  "TARGET_USE_FANCY_MATH_387
16415169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1641690286Sobrien   && flag_unsafe_math_optimizations"
16417132727Skan  "fpatan"
1641890286Sobrien  [(set_attr "type" "fpspc")
16419132727Skan   (set_attr "mode" "DF")])
16420132727Skan
16421132727Skan(define_expand "atan2df3"
16422169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
16423169699Skan   (use (match_operand:DF 2 "register_operand" ""))
16424169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
16425169699Skan  "TARGET_USE_FANCY_MATH_387
16426169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16427132727Skan   && flag_unsafe_math_optimizations"
16428132727Skan{
16429132727Skan  rtx copy = gen_reg_rtx (DFmode);
16430132727Skan  emit_move_insn (copy, operands[1]);
16431132727Skan  emit_insn (gen_atan2df3_1 (operands[0], copy, operands[2]));
16432132727Skan  DONE;
16433132727Skan})
16434132727Skan
16435169699Skan(define_expand "atandf2"
16436169699Skan  [(parallel [(set (match_operand:DF 0 "register_operand" "")
16437169699Skan		   (unspec:DF [(match_dup 2)
16438169699Skan			       (match_operand:DF 1 "register_operand" "")]
16439169699Skan		    UNSPEC_FPATAN))
16440169699Skan	      (clobber (match_scratch:DF 3 ""))])]
16441169699Skan  "TARGET_USE_FANCY_MATH_387
16442169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16443169699Skan   && flag_unsafe_math_optimizations"
16444169699Skan{
16445169699Skan  operands[2] = gen_reg_rtx (DFmode);
16446169699Skan  emit_move_insn (operands[2], CONST1_RTX (DFmode));  /* fld1 */
16447169699Skan})
16448169699Skan
16449132727Skan(define_insn "atan2sf3_1"
16450132727Skan  [(set (match_operand:SF 0 "register_operand" "=f")
16451132727Skan        (unspec:SF [(match_operand:SF 2 "register_operand" "0")
16452132727Skan		    (match_operand:SF 1 "register_operand" "u")]
16453132727Skan		   UNSPEC_FPATAN))
16454132727Skan   (clobber (match_scratch:SF 3 "=1"))]
16455169699Skan  "TARGET_USE_FANCY_MATH_387
16456169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16457132727Skan   && flag_unsafe_math_optimizations"
16458132727Skan  "fpatan"
16459132727Skan  [(set_attr "type" "fpspc")
16460132727Skan   (set_attr "mode" "SF")])
16461132727Skan
16462132727Skan(define_expand "atan2sf3"
16463169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
16464169699Skan   (use (match_operand:SF 2 "register_operand" ""))
16465169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
16466169699Skan  "TARGET_USE_FANCY_MATH_387
16467169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16468132727Skan   && flag_unsafe_math_optimizations"
16469132727Skan{
16470132727Skan  rtx copy = gen_reg_rtx (SFmode);
16471132727Skan  emit_move_insn (copy, operands[1]);
16472132727Skan  emit_insn (gen_atan2sf3_1 (operands[0], copy, operands[2]));
16473132727Skan  DONE;
16474132727Skan})
16475132727Skan
16476169699Skan(define_expand "atansf2"
16477169699Skan  [(parallel [(set (match_operand:SF 0 "register_operand" "")
16478169699Skan		   (unspec:SF [(match_dup 2)
16479169699Skan			       (match_operand:SF 1 "register_operand" "")]
16480169699Skan		    UNSPEC_FPATAN))
16481169699Skan	      (clobber (match_scratch:SF 3 ""))])]
16482169699Skan  "TARGET_USE_FANCY_MATH_387
16483169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16484169699Skan   && flag_unsafe_math_optimizations"
16485169699Skan{
16486169699Skan  operands[2] = gen_reg_rtx (SFmode);
16487169699Skan  emit_move_insn (operands[2], CONST1_RTX (SFmode));  /* fld1 */
16488169699Skan})
16489169699Skan
16490132727Skan(define_insn "atan2xf3_1"
16491132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16492132727Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16493132727Skan	            (match_operand:XF 1 "register_operand" "u")]
16494132727Skan	           UNSPEC_FPATAN))
16495132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16496169699Skan  "TARGET_USE_FANCY_MATH_387
16497132727Skan   && flag_unsafe_math_optimizations"
16498132727Skan  "fpatan"
16499132727Skan  [(set_attr "type" "fpspc")
1650090286Sobrien   (set_attr "mode" "XF")])
16501132727Skan
16502132727Skan(define_expand "atan2xf3"
16503169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
16504169699Skan   (use (match_operand:XF 2 "register_operand" ""))
16505169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
16506169699Skan  "TARGET_USE_FANCY_MATH_387
16507132727Skan   && flag_unsafe_math_optimizations"
16508132727Skan{
16509132727Skan  rtx copy = gen_reg_rtx (XFmode);
16510132727Skan  emit_move_insn (copy, operands[1]);
16511132727Skan  emit_insn (gen_atan2xf3_1 (operands[0], copy, operands[2]));
16512132727Skan  DONE;
16513132727Skan})
16514132727Skan
16515169699Skan(define_expand "atanxf2"
16516169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16517169699Skan		   (unspec:XF [(match_dup 2)
16518169699Skan			       (match_operand:XF 1 "register_operand" "")]
16519169699Skan		    UNSPEC_FPATAN))
16520169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16521169699Skan  "TARGET_USE_FANCY_MATH_387
16522132727Skan   && flag_unsafe_math_optimizations"
16523169699Skan{
16524169699Skan  operands[2] = gen_reg_rtx (XFmode);
16525169699Skan  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
16526169699Skan})
16527132727Skan
16528169699Skan(define_expand "asindf2"
16529169699Skan  [(set (match_dup 2)
16530169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16531169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16532169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16533169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16534169699Skan   (parallel [(set (match_dup 7)
16535169699Skan        	   (unspec:XF [(match_dup 6) (match_dup 2)]
16536169699Skan			      UNSPEC_FPATAN))
16537169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16538169699Skan   (set (match_operand:DF 0 "register_operand" "")
16539169699Skan	(float_truncate:DF (match_dup 7)))]
16540169699Skan  "TARGET_USE_FANCY_MATH_387
16541169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16542132727Skan   && flag_unsafe_math_optimizations"
16543169699Skan{
16544169699Skan  int i;
16545132727Skan
16546169699Skan  for (i=2; i<8; i++)
16547169699Skan    operands[i] = gen_reg_rtx (XFmode);
16548169699Skan
16549169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16550169699Skan})
16551169699Skan
16552169699Skan(define_expand "asinsf2"
16553169699Skan  [(set (match_dup 2)
16554169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16555169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16556169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16557169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16558169699Skan   (parallel [(set (match_dup 7)
16559169699Skan        	   (unspec:XF [(match_dup 6) (match_dup 2)]
16560169699Skan			      UNSPEC_FPATAN))
16561169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16562169699Skan   (set (match_operand:SF 0 "register_operand" "")
16563169699Skan	(float_truncate:SF (match_dup 7)))]
16564169699Skan  "TARGET_USE_FANCY_MATH_387
16565169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16566169699Skan   && flag_unsafe_math_optimizations"
16567169699Skan{
16568169699Skan  int i;
16569169699Skan
16570169699Skan  for (i=2; i<8; i++)
16571169699Skan    operands[i] = gen_reg_rtx (XFmode);
16572169699Skan
16573169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16574169699Skan})
16575169699Skan
16576169699Skan(define_expand "asinxf2"
16577169699Skan  [(set (match_dup 2)
16578169699Skan	(mult:XF (match_operand:XF 1 "register_operand" "")
16579169699Skan		 (match_dup 1)))
16580169699Skan   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
16581169699Skan   (set (match_dup 5) (sqrt:XF (match_dup 4)))
16582169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16583169699Skan        	   (unspec:XF [(match_dup 5) (match_dup 1)]
16584169699Skan			      UNSPEC_FPATAN))
16585169699Skan   	      (clobber (match_scratch:XF 6 ""))])]
16586169699Skan  "TARGET_USE_FANCY_MATH_387
16587169699Skan   && flag_unsafe_math_optimizations"
16588169699Skan{
16589169699Skan  int i;
16590169699Skan
16591169699Skan  for (i=2; i<6; i++)
16592169699Skan    operands[i] = gen_reg_rtx (XFmode);
16593169699Skan
16594169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16595169699Skan})
16596169699Skan
16597169699Skan(define_expand "acosdf2"
16598169699Skan  [(set (match_dup 2)
16599169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16600169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16601169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16602169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16603169699Skan   (parallel [(set (match_dup 7)
16604169699Skan        	   (unspec:XF [(match_dup 2) (match_dup 6)]
16605169699Skan			      UNSPEC_FPATAN))
16606169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16607169699Skan   (set (match_operand:DF 0 "register_operand" "")
16608169699Skan	(float_truncate:DF (match_dup 7)))]
16609169699Skan  "TARGET_USE_FANCY_MATH_387
16610169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16611169699Skan   && flag_unsafe_math_optimizations"
16612169699Skan{
16613169699Skan  int i;
16614169699Skan
16615169699Skan  for (i=2; i<8; i++)
16616169699Skan    operands[i] = gen_reg_rtx (XFmode);
16617169699Skan
16618169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16619169699Skan})
16620169699Skan
16621169699Skan(define_expand "acossf2"
16622169699Skan  [(set (match_dup 2)
16623169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16624169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16625169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16626169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16627169699Skan   (parallel [(set (match_dup 7)
16628169699Skan        	   (unspec:XF [(match_dup 2) (match_dup 6)]
16629169699Skan			      UNSPEC_FPATAN))
16630169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16631169699Skan   (set (match_operand:SF 0 "register_operand" "")
16632169699Skan	(float_truncate:SF (match_dup 7)))]
16633169699Skan  "TARGET_USE_FANCY_MATH_387
16634169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16635169699Skan   && flag_unsafe_math_optimizations"
16636169699Skan{
16637169699Skan  int i;
16638169699Skan
16639169699Skan  for (i=2; i<8; i++)
16640169699Skan    operands[i] = gen_reg_rtx (XFmode);
16641169699Skan
16642169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16643169699Skan})
16644169699Skan
16645169699Skan(define_expand "acosxf2"
16646169699Skan  [(set (match_dup 2)
16647169699Skan	(mult:XF (match_operand:XF 1 "register_operand" "")
16648169699Skan		 (match_dup 1)))
16649169699Skan   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
16650169699Skan   (set (match_dup 5) (sqrt:XF (match_dup 4)))
16651169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16652169699Skan        	   (unspec:XF [(match_dup 1) (match_dup 5)]
16653169699Skan			      UNSPEC_FPATAN))
16654169699Skan   	      (clobber (match_scratch:XF 6 ""))])]
16655169699Skan  "TARGET_USE_FANCY_MATH_387
16656169699Skan   && flag_unsafe_math_optimizations"
16657169699Skan{
16658169699Skan  int i;
16659169699Skan
16660169699Skan  for (i=2; i<6; i++)
16661169699Skan    operands[i] = gen_reg_rtx (XFmode);
16662169699Skan
16663169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16664169699Skan})
16665169699Skan
16666169699Skan(define_insn "fyl2x_xf3"
16667132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16668132727Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16669132727Skan		    (match_operand:XF 1 "register_operand" "u")]
16670132727Skan	           UNSPEC_FYL2X))
16671132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16672169699Skan  "TARGET_USE_FANCY_MATH_387
16673132727Skan   && flag_unsafe_math_optimizations"
16674132727Skan  "fyl2x"
16675132727Skan  [(set_attr "type" "fpspc")
16676132727Skan   (set_attr "mode" "XF")])
16677132727Skan
16678132727Skan(define_expand "logsf2"
16679169699Skan  [(set (match_dup 2)
16680169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16681169699Skan   (parallel [(set (match_dup 4)
16682169699Skan		   (unspec:XF [(match_dup 2)
16683169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16684169699Skan	      (clobber (match_scratch:XF 5 ""))])
16685169699Skan   (set (match_operand:SF 0 "register_operand" "")
16686169699Skan	(float_truncate:SF (match_dup 4)))]
16687169699Skan  "TARGET_USE_FANCY_MATH_387
16688169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16689132727Skan   && flag_unsafe_math_optimizations"
16690132727Skan{
16691132727Skan  rtx temp;
16692132727Skan
16693132727Skan  operands[2] = gen_reg_rtx (XFmode);
16694169699Skan  operands[3] = gen_reg_rtx (XFmode);
16695169699Skan  operands[4] = gen_reg_rtx (XFmode);
16696169699Skan
16697132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16698169699Skan  emit_move_insn (operands[3], temp);
16699132727Skan})
16700132727Skan
16701132727Skan(define_expand "logdf2"
16702169699Skan  [(set (match_dup 2)
16703169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16704169699Skan   (parallel [(set (match_dup 4)
16705169699Skan		   (unspec:XF [(match_dup 2)
16706169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16707169699Skan	      (clobber (match_scratch:XF 5 ""))])
16708169699Skan   (set (match_operand:DF 0 "register_operand" "")
16709169699Skan	(float_truncate:DF (match_dup 4)))]
16710169699Skan  "TARGET_USE_FANCY_MATH_387
16711169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16712132727Skan   && flag_unsafe_math_optimizations"
16713132727Skan{
16714132727Skan  rtx temp;
16715132727Skan
16716132727Skan  operands[2] = gen_reg_rtx (XFmode);
16717169699Skan  operands[3] = gen_reg_rtx (XFmode);
16718169699Skan  operands[4] = gen_reg_rtx (XFmode);
16719169699Skan
16720132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16721169699Skan  emit_move_insn (operands[3], temp);
16722132727Skan})
16723132727Skan
16724132727Skan(define_expand "logxf2"
16725132727Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16726132727Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16727132727Skan			       (match_dup 2)] UNSPEC_FYL2X))
16728132727Skan	      (clobber (match_scratch:XF 3 ""))])]
16729169699Skan  "TARGET_USE_FANCY_MATH_387
16730132727Skan   && flag_unsafe_math_optimizations"
16731132727Skan{
16732132727Skan  rtx temp;
16733132727Skan
16734132727Skan  operands[2] = gen_reg_rtx (XFmode);
16735132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16736132727Skan  emit_move_insn (operands[2], temp);
16737132727Skan})
16738132727Skan
16739169699Skan(define_expand "log10sf2"
16740169699Skan  [(set (match_dup 2)
16741169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16742169699Skan   (parallel [(set (match_dup 4)
16743169699Skan		   (unspec:XF [(match_dup 2)
16744169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16745169699Skan	      (clobber (match_scratch:XF 5 ""))])
16746169699Skan   (set (match_operand:SF 0 "register_operand" "")
16747169699Skan	(float_truncate:SF (match_dup 4)))]
16748169699Skan  "TARGET_USE_FANCY_MATH_387
16749169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16750132727Skan   && flag_unsafe_math_optimizations"
16751169699Skan{
16752169699Skan  rtx temp;
16753132727Skan
16754169699Skan  operands[2] = gen_reg_rtx (XFmode);
16755169699Skan  operands[3] = gen_reg_rtx (XFmode);
16756169699Skan  operands[4] = gen_reg_rtx (XFmode);
16757169699Skan
16758169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16759169699Skan  emit_move_insn (operands[3], temp);
16760169699Skan})
16761169699Skan
16762169699Skan(define_expand "log10df2"
16763169699Skan  [(set (match_dup 2)
16764169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16765169699Skan   (parallel [(set (match_dup 4)
16766169699Skan		   (unspec:XF [(match_dup 2)
16767169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16768169699Skan	      (clobber (match_scratch:XF 5 ""))])
16769169699Skan   (set (match_operand:DF 0 "register_operand" "")
16770169699Skan	(float_truncate:DF (match_dup 4)))]
16771169699Skan  "TARGET_USE_FANCY_MATH_387
16772169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16773132727Skan   && flag_unsafe_math_optimizations"
16774169699Skan{
16775169699Skan  rtx temp;
16776132727Skan
16777169699Skan  operands[2] = gen_reg_rtx (XFmode);
16778169699Skan  operands[3] = gen_reg_rtx (XFmode);
16779169699Skan  operands[4] = gen_reg_rtx (XFmode);
16780169699Skan
16781169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16782169699Skan  emit_move_insn (operands[3], temp);
16783169699Skan})
16784169699Skan
16785169699Skan(define_expand "log10xf2"
16786169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16787169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16788169699Skan			       (match_dup 2)] UNSPEC_FYL2X))
16789169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16790169699Skan  "TARGET_USE_FANCY_MATH_387
16791169699Skan   && flag_unsafe_math_optimizations"
16792169699Skan{
16793169699Skan  rtx temp;
16794169699Skan
16795169699Skan  operands[2] = gen_reg_rtx (XFmode);
16796169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16797169699Skan  emit_move_insn (operands[2], temp);
16798169699Skan})
16799169699Skan
16800169699Skan(define_expand "log2sf2"
16801169699Skan  [(set (match_dup 2)
16802169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16803169699Skan   (parallel [(set (match_dup 4)
16804169699Skan		   (unspec:XF [(match_dup 2)
16805169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16806169699Skan	      (clobber (match_scratch:XF 5 ""))])
16807169699Skan   (set (match_operand:SF 0 "register_operand" "")
16808169699Skan	(float_truncate:SF (match_dup 4)))]
16809169699Skan  "TARGET_USE_FANCY_MATH_387
16810169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16811169699Skan   && flag_unsafe_math_optimizations"
16812169699Skan{
16813169699Skan  operands[2] = gen_reg_rtx (XFmode);
16814169699Skan  operands[3] = gen_reg_rtx (XFmode);
16815169699Skan  operands[4] = gen_reg_rtx (XFmode);
16816169699Skan
16817169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16818169699Skan})
16819169699Skan
16820169699Skan(define_expand "log2df2"
16821169699Skan  [(set (match_dup 2)
16822169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16823169699Skan   (parallel [(set (match_dup 4)
16824169699Skan		   (unspec:XF [(match_dup 2)
16825169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16826169699Skan	      (clobber (match_scratch:XF 5 ""))])
16827169699Skan   (set (match_operand:DF 0 "register_operand" "")
16828169699Skan	(float_truncate:DF (match_dup 4)))]
16829169699Skan  "TARGET_USE_FANCY_MATH_387
16830169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16831169699Skan   && flag_unsafe_math_optimizations"
16832169699Skan{
16833169699Skan  operands[2] = gen_reg_rtx (XFmode);
16834169699Skan  operands[3] = gen_reg_rtx (XFmode);
16835169699Skan  operands[4] = gen_reg_rtx (XFmode);
16836169699Skan
16837169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16838169699Skan})
16839169699Skan
16840169699Skan(define_expand "log2xf2"
16841169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16842169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16843169699Skan			       (match_dup 2)] UNSPEC_FYL2X))
16844169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16845169699Skan  "TARGET_USE_FANCY_MATH_387
16846169699Skan   && flag_unsafe_math_optimizations"
16847169699Skan{
16848169699Skan  operands[2] = gen_reg_rtx (XFmode);
16849169699Skan  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
16850169699Skan})
16851169699Skan
16852169699Skan(define_insn "fyl2xp1_xf3"
16853132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16854169699Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16855132727Skan		    (match_operand:XF 1 "register_operand" "u")]
16856169699Skan	           UNSPEC_FYL2XP1))
16857132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16858169699Skan  "TARGET_USE_FANCY_MATH_387
16859132727Skan   && flag_unsafe_math_optimizations"
16860169699Skan  "fyl2xp1"
16861132727Skan  [(set_attr "type" "fpspc")
16862132727Skan   (set_attr "mode" "XF")])
16863132727Skan
16864169699Skan(define_expand "log1psf2"
16865169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
16866169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
16867169699Skan  "TARGET_USE_FANCY_MATH_387
16868169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16869169699Skan   && flag_unsafe_math_optimizations"
16870169699Skan{
16871169699Skan  rtx op0 = gen_reg_rtx (XFmode);
16872169699Skan  rtx op1 = gen_reg_rtx (XFmode);
16873169699Skan
16874169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
16875169699Skan  ix86_emit_i387_log1p (op0, op1);
16876169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
16877169699Skan  DONE;
16878169699Skan})
16879169699Skan
16880169699Skan(define_expand "log1pdf2"
16881169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
16882169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
16883169699Skan  "TARGET_USE_FANCY_MATH_387
16884169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16885169699Skan   && flag_unsafe_math_optimizations"
16886169699Skan{
16887169699Skan  rtx op0 = gen_reg_rtx (XFmode);
16888169699Skan  rtx op1 = gen_reg_rtx (XFmode);
16889169699Skan
16890169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
16891169699Skan  ix86_emit_i387_log1p (op0, op1);
16892169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
16893169699Skan  DONE;
16894169699Skan})
16895169699Skan
16896169699Skan(define_expand "log1pxf2"
16897169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
16898169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
16899169699Skan  "TARGET_USE_FANCY_MATH_387
16900169699Skan   && flag_unsafe_math_optimizations"
16901169699Skan{
16902169699Skan  ix86_emit_i387_log1p (operands[0], operands[1]);
16903169699Skan  DONE;
16904169699Skan})
16905169699Skan
16906169699Skan(define_insn "*fxtractxf3"
16907132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16908169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
16909169699Skan		   UNSPEC_XTRACT_FRACT))
16910169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16911169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))]
16912169699Skan  "TARGET_USE_FANCY_MATH_387
16913132727Skan   && flag_unsafe_math_optimizations"
16914169699Skan  "fxtract"
16915132727Skan  [(set_attr "type" "fpspc")
16916132727Skan   (set_attr "mode" "XF")])
16917132727Skan
16918169699Skan(define_expand "logbsf2"
16919169699Skan  [(set (match_dup 2)
16920169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16921169699Skan   (parallel [(set (match_dup 3)
16922169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
16923169699Skan	      (set (match_dup 4)
16924169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
16925169699Skan   (set (match_operand:SF 0 "register_operand" "")
16926169699Skan	(float_truncate:SF (match_dup 4)))]
16927169699Skan  "TARGET_USE_FANCY_MATH_387
16928169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16929169699Skan   && flag_unsafe_math_optimizations"
16930169699Skan{
16931169699Skan  operands[2] = gen_reg_rtx (XFmode);
16932169699Skan  operands[3] = gen_reg_rtx (XFmode);
16933169699Skan  operands[4] = gen_reg_rtx (XFmode);
16934169699Skan})
16935169699Skan
16936169699Skan(define_expand "logbdf2"
16937169699Skan  [(set (match_dup 2)
16938169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16939169699Skan   (parallel [(set (match_dup 3)
16940169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
16941169699Skan	      (set (match_dup 4)
16942169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
16943169699Skan   (set (match_operand:DF 0 "register_operand" "")
16944169699Skan	(float_truncate:DF (match_dup 4)))]
16945169699Skan  "TARGET_USE_FANCY_MATH_387
16946169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16947169699Skan   && flag_unsafe_math_optimizations"
16948169699Skan{
16949169699Skan  operands[2] = gen_reg_rtx (XFmode);
16950169699Skan  operands[3] = gen_reg_rtx (XFmode);
16951169699Skan  operands[4] = gen_reg_rtx (XFmode);
16952169699Skan})
16953169699Skan
16954169699Skan(define_expand "logbxf2"
16955169699Skan  [(parallel [(set (match_dup 2)
16956169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16957169699Skan			      UNSPEC_XTRACT_FRACT))
16958169699Skan	      (set (match_operand:XF 0 "register_operand" "")
16959169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])]
16960169699Skan  "TARGET_USE_FANCY_MATH_387
16961169699Skan   && flag_unsafe_math_optimizations"
16962169699Skan{
16963169699Skan  operands[2] = gen_reg_rtx (XFmode);
16964169699Skan})
16965169699Skan
16966169699Skan(define_expand "ilogbsi2"
16967169699Skan  [(parallel [(set (match_dup 2)
16968169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16969169699Skan			      UNSPEC_XTRACT_FRACT))
16970169699Skan	      (set (match_operand:XF 3 "register_operand" "")
16971169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])
16972169699Skan   (parallel [(set (match_operand:SI 0 "register_operand" "")
16973169699Skan	           (fix:SI (match_dup 3)))
16974169699Skan	      (clobber (reg:CC FLAGS_REG))])]
16975169699Skan  "TARGET_USE_FANCY_MATH_387
16976169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16977169699Skan   && flag_unsafe_math_optimizations"
16978169699Skan{
16979169699Skan  operands[2] = gen_reg_rtx (XFmode);
16980169699Skan  operands[3] = gen_reg_rtx (XFmode);
16981169699Skan})
16982169699Skan
16983132727Skan(define_insn "*f2xm1xf2"
16984132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16985132727Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
16986132727Skan	 UNSPEC_F2XM1))]
16987169699Skan  "TARGET_USE_FANCY_MATH_387
16988132727Skan   && flag_unsafe_math_optimizations"
16989132727Skan  "f2xm1"
16990132727Skan  [(set_attr "type" "fpspc")
16991132727Skan   (set_attr "mode" "XF")])
16992132727Skan
16993169699Skan(define_insn "*fscalexf4"
16994169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16995169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
16996169699Skan		    (match_operand:XF 3 "register_operand" "1")]
16997169699Skan		   UNSPEC_FSCALE_FRACT))
16998169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16999169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
17000169699Skan		   UNSPEC_FSCALE_EXP))]
17001169699Skan  "TARGET_USE_FANCY_MATH_387
17002169699Skan   && flag_unsafe_math_optimizations"
17003169699Skan  "fscale"
17004169699Skan  [(set_attr "type" "fpspc")
17005169699Skan   (set_attr "mode" "XF")])
17006169699Skan
17007132727Skan(define_expand "expsf2"
17008132727Skan  [(set (match_dup 2)
17009132727Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17010132727Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
17011132727Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
17012132727Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
17013132727Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
17014132727Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
17015169699Skan   (parallel [(set (match_dup 10)
17016169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
17017169699Skan			      UNSPEC_FSCALE_FRACT))
17018169699Skan	      (set (match_dup 11)
17019169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
17020169699Skan			      UNSPEC_FSCALE_EXP))])
17021169699Skan   (set (match_operand:SF 0 "register_operand" "")
17022169699Skan	(float_truncate:SF (match_dup 10)))]
17023169699Skan  "TARGET_USE_FANCY_MATH_387
17024169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17025132727Skan   && flag_unsafe_math_optimizations"
17026132727Skan{
17027132727Skan  rtx temp;
17028132727Skan  int i;
17029132727Skan
17030169699Skan  for (i=2; i<12; i++)
17031132727Skan    operands[i] = gen_reg_rtx (XFmode);
17032132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17033132727Skan  emit_move_insn (operands[3], temp);
17034132727Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
17035132727Skan})
17036132727Skan
17037132727Skan(define_expand "expdf2"
17038132727Skan  [(set (match_dup 2)
17039132727Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
17040132727Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
17041132727Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
17042132727Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
17043132727Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
17044132727Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
17045169699Skan   (parallel [(set (match_dup 10)
17046169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
17047169699Skan			      UNSPEC_FSCALE_FRACT))
17048169699Skan	      (set (match_dup 11)
17049169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
17050169699Skan			      UNSPEC_FSCALE_EXP))])
17051169699Skan   (set (match_operand:DF 0 "register_operand" "")
17052169699Skan	(float_truncate:DF (match_dup 10)))]
17053169699Skan  "TARGET_USE_FANCY_MATH_387
17054169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17055132727Skan   && flag_unsafe_math_optimizations"
17056132727Skan{
17057132727Skan  rtx temp;
17058132727Skan  int i;
17059132727Skan
17060169699Skan  for (i=2; i<12; i++)
17061132727Skan    operands[i] = gen_reg_rtx (XFmode);
17062132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17063132727Skan  emit_move_insn (operands[3], temp);
17064132727Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
17065132727Skan})
17066132727Skan
17067132727Skan(define_expand "expxf2"
17068132727Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
17069132727Skan			       (match_dup 2)))
17070132727Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
17071132727Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
17072132727Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
17073132727Skan   (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
17074132727Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
17075169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
17076169699Skan			      UNSPEC_FSCALE_FRACT))
17077169699Skan	      (set (match_dup 9)
17078169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
17079169699Skan			      UNSPEC_FSCALE_EXP))])]
17080169699Skan  "TARGET_USE_FANCY_MATH_387
17081132727Skan   && flag_unsafe_math_optimizations"
17082132727Skan{
17083132727Skan  rtx temp;
17084132727Skan  int i;
17085132727Skan
17086169699Skan  for (i=2; i<10; i++)
17087132727Skan    operands[i] = gen_reg_rtx (XFmode);
17088132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17089132727Skan  emit_move_insn (operands[2], temp);
17090132727Skan  emit_move_insn (operands[7], CONST1_RTX (XFmode));  /* fld1 */
17091132727Skan})
17092132727Skan
17093169699Skan(define_expand "exp10sf2"
17094169699Skan  [(set (match_dup 2)
17095169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17096169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
17097169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
17098169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
17099169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
17100169699Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
17101169699Skan   (parallel [(set (match_dup 10)
17102169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
17103169699Skan			      UNSPEC_FSCALE_FRACT))
17104169699Skan	      (set (match_dup 11)
17105169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
17106169699Skan			      UNSPEC_FSCALE_EXP))])
17107169699Skan   (set (match_operand:SF 0 "register_operand" "")
17108169699Skan	(float_truncate:SF (match_dup 10)))]
17109169699Skan  "TARGET_USE_FANCY_MATH_387
17110169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17111132727Skan   && flag_unsafe_math_optimizations"
17112132727Skan{
17113169699Skan  rtx temp;
17114169699Skan  int i;
17115169699Skan
17116169699Skan  for (i=2; i<12; i++)
17117169699Skan    operands[i] = gen_reg_rtx (XFmode);
17118169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
17119169699Skan  emit_move_insn (operands[3], temp);
17120169699Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
17121132727Skan})
17122132727Skan
17123169699Skan(define_expand "exp10df2"
17124169699Skan  [(set (match_dup 2)
17125169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
17126169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
17127169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
17128169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
17129169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
17130169699Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
17131169699Skan   (parallel [(set (match_dup 10)
17132169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
17133169699Skan			      UNSPEC_FSCALE_FRACT))
17134169699Skan	      (set (match_dup 11)
17135169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
17136169699Skan			      UNSPEC_FSCALE_EXP))])
17137169699Skan   (set (match_operand:DF 0 "register_operand" "")
17138169699Skan	(float_truncate:DF (match_dup 10)))]
17139169699Skan  "TARGET_USE_FANCY_MATH_387
17140169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17141132727Skan   && flag_unsafe_math_optimizations"
17142132727Skan{
17143169699Skan  rtx temp;
17144169699Skan  int i;
17145169699Skan
17146169699Skan  for (i=2; i<12; i++)
17147169699Skan    operands[i] = gen_reg_rtx (XFmode);
17148169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
17149169699Skan  emit_move_insn (operands[3], temp);
17150169699Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
17151132727Skan})
17152132727Skan
17153169699Skan(define_expand "exp10xf2"
17154169699Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
17155169699Skan			       (match_dup 2)))
17156169699Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
17157169699Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
17158169699Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
17159169699Skan   (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
17160169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
17161169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
17162169699Skan			      UNSPEC_FSCALE_FRACT))
17163169699Skan	      (set (match_dup 9)
17164169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
17165169699Skan			      UNSPEC_FSCALE_EXP))])]
17166169699Skan  "TARGET_USE_FANCY_MATH_387
17167132727Skan   && flag_unsafe_math_optimizations"
17168132727Skan{
17169169699Skan  rtx temp;
17170169699Skan  int i;
17171169699Skan
17172169699Skan  for (i=2; i<10; i++)
17173169699Skan    operands[i] = gen_reg_rtx (XFmode);
17174169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
17175169699Skan  emit_move_insn (operands[2], temp);
17176169699Skan  emit_move_insn (operands[7], CONST1_RTX (XFmode));  /* fld1 */
17177132727Skan})
17178169699Skan
17179169699Skan(define_expand "exp2sf2"
17180169699Skan  [(set (match_dup 2)
17181169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17182169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
17183169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
17184169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
17185169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
17186169699Skan   (parallel [(set (match_dup 8)
17187169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
17188169699Skan			      UNSPEC_FSCALE_FRACT))
17189169699Skan	      (set (match_dup 9)
17190169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
17191169699Skan			      UNSPEC_FSCALE_EXP))])
17192169699Skan   (set (match_operand:SF 0 "register_operand" "")
17193169699Skan	(float_truncate:SF (match_dup 8)))]
17194169699Skan  "TARGET_USE_FANCY_MATH_387
17195169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17196169699Skan   && flag_unsafe_math_optimizations"
17197169699Skan{
17198169699Skan  int i;
17199169699Skan
17200169699Skan  for (i=2; i<10; i++)
17201169699Skan    operands[i] = gen_reg_rtx (XFmode);
17202169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
17203169699Skan})
17204169699Skan
17205169699Skan(define_expand "exp2df2"
17206169699Skan  [(set (match_dup 2)
17207169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
17208169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
17209169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
17210169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
17211169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
17212169699Skan   (parallel [(set (match_dup 8)
17213169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
17214169699Skan			      UNSPEC_FSCALE_FRACT))
17215169699Skan	      (set (match_dup 9)
17216169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
17217169699Skan			      UNSPEC_FSCALE_EXP))])
17218169699Skan   (set (match_operand:DF 0 "register_operand" "")
17219169699Skan	(float_truncate:DF (match_dup 8)))]
17220169699Skan  "TARGET_USE_FANCY_MATH_387
17221169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17222169699Skan   && flag_unsafe_math_optimizations"
17223169699Skan{
17224169699Skan  int i;
17225169699Skan
17226169699Skan  for (i=2; i<10; i++)
17227169699Skan    operands[i] = gen_reg_rtx (XFmode);
17228169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
17229169699Skan})
17230169699Skan
17231169699Skan(define_expand "exp2xf2"
17232169699Skan  [(set (match_dup 2) (match_operand:XF 1 "register_operand" ""))
17233169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
17234169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
17235169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
17236169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
17237169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
17238169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
17239169699Skan			      UNSPEC_FSCALE_FRACT))
17240169699Skan	      (set (match_dup 8)
17241169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
17242169699Skan			      UNSPEC_FSCALE_EXP))])]
17243169699Skan  "TARGET_USE_FANCY_MATH_387
17244169699Skan   && flag_unsafe_math_optimizations"
17245169699Skan{
17246169699Skan  int i;
17247169699Skan
17248169699Skan  for (i=2; i<9; i++)
17249169699Skan    operands[i] = gen_reg_rtx (XFmode);
17250169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
17251169699Skan})
17252169699Skan
17253169699Skan(define_expand "expm1df2"
17254169699Skan  [(set (match_dup 2)
17255169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
17256169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
17257169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
17258169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
17259169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
17260169699Skan   (parallel [(set (match_dup 8)
17261169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17262169699Skan			      UNSPEC_FSCALE_FRACT))
17263169699Skan		   (set (match_dup 9)
17264169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17265169699Skan			      UNSPEC_FSCALE_EXP))])
17266169699Skan   (parallel [(set (match_dup 11)
17267169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17268169699Skan			      UNSPEC_FSCALE_FRACT))
17269169699Skan	      (set (match_dup 12)
17270169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17271169699Skan			      UNSPEC_FSCALE_EXP))])
17272169699Skan   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
17273169699Skan   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
17274169699Skan   (set (match_operand:DF 0 "register_operand" "")
17275169699Skan	(float_truncate:DF (match_dup 14)))]
17276169699Skan  "TARGET_USE_FANCY_MATH_387
17277169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17278169699Skan   && flag_unsafe_math_optimizations"
17279169699Skan{
17280169699Skan  rtx temp;
17281169699Skan  int i;
17282169699Skan
17283169699Skan  for (i=2; i<15; i++)
17284169699Skan    operands[i] = gen_reg_rtx (XFmode);
17285169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17286169699Skan  emit_move_insn (operands[3], temp);
17287169699Skan  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
17288169699Skan})
17289169699Skan
17290169699Skan(define_expand "expm1sf2"
17291169699Skan  [(set (match_dup 2)
17292169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17293169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
17294169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
17295169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
17296169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
17297169699Skan   (parallel [(set (match_dup 8)
17298169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17299169699Skan			      UNSPEC_FSCALE_FRACT))
17300169699Skan		   (set (match_dup 9)
17301169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17302169699Skan			      UNSPEC_FSCALE_EXP))])
17303169699Skan   (parallel [(set (match_dup 11)
17304169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17305169699Skan			      UNSPEC_FSCALE_FRACT))
17306169699Skan	      (set (match_dup 12)
17307169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17308169699Skan			      UNSPEC_FSCALE_EXP))])
17309169699Skan   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
17310169699Skan   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
17311169699Skan   (set (match_operand:SF 0 "register_operand" "")
17312169699Skan	(float_truncate:SF (match_dup 14)))]
17313169699Skan  "TARGET_USE_FANCY_MATH_387
17314169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17315169699Skan   && flag_unsafe_math_optimizations"
17316169699Skan{
17317169699Skan  rtx temp;
17318169699Skan  int i;
17319169699Skan
17320169699Skan  for (i=2; i<15; i++)
17321169699Skan    operands[i] = gen_reg_rtx (XFmode);
17322169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17323169699Skan  emit_move_insn (operands[3], temp);
17324169699Skan  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
17325169699Skan})
17326169699Skan
17327169699Skan(define_expand "expm1xf2"
17328169699Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
17329169699Skan			       (match_dup 2)))
17330169699Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
17331169699Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
17332169699Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
17333169699Skan   (parallel [(set (match_dup 7)
17334169699Skan		   (unspec:XF [(match_dup 6) (match_dup 4)]
17335169699Skan			      UNSPEC_FSCALE_FRACT))
17336169699Skan		   (set (match_dup 8)
17337169699Skan		   (unspec:XF [(match_dup 6) (match_dup 4)]
17338169699Skan			      UNSPEC_FSCALE_EXP))])
17339169699Skan   (parallel [(set (match_dup 10)
17340169699Skan		   (unspec:XF [(match_dup 9) (match_dup 8)]
17341169699Skan			      UNSPEC_FSCALE_FRACT))
17342169699Skan	      (set (match_dup 11)
17343169699Skan		   (unspec:XF [(match_dup 9) (match_dup 8)]
17344169699Skan			      UNSPEC_FSCALE_EXP))])
17345169699Skan   (set (match_dup 12) (minus:XF (match_dup 10) (match_dup 9)))
17346169699Skan   (set (match_operand:XF 0 "register_operand" "")
17347169699Skan	(plus:XF (match_dup 12) (match_dup 7)))]
17348169699Skan  "TARGET_USE_FANCY_MATH_387
17349169699Skan   && flag_unsafe_math_optimizations"
17350169699Skan{
17351169699Skan  rtx temp;
17352169699Skan  int i;
17353169699Skan
17354169699Skan  for (i=2; i<13; i++)
17355169699Skan    operands[i] = gen_reg_rtx (XFmode);
17356169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17357169699Skan  emit_move_insn (operands[2], temp);
17358169699Skan  emit_move_insn (operands[9], CONST1_RTX (XFmode));  /* fld1 */
17359169699Skan})
17360169699Skan
17361169699Skan(define_expand "ldexpdf3"
17362169699Skan  [(set (match_dup 3)
17363169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
17364169699Skan   (set (match_dup 4)
17365169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17366169699Skan   (parallel [(set (match_dup 5)
17367169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17368169699Skan			      UNSPEC_FSCALE_FRACT))
17369169699Skan	      (set (match_dup 6)
17370169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17371169699Skan			      UNSPEC_FSCALE_EXP))])
17372169699Skan   (set (match_operand:DF 0 "register_operand" "")
17373169699Skan	(float_truncate:DF (match_dup 5)))]
17374169699Skan  "TARGET_USE_FANCY_MATH_387
17375169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17376169699Skan   && flag_unsafe_math_optimizations"
17377169699Skan{
17378169699Skan  int i;
17379169699Skan
17380169699Skan  for (i=3; i<7; i++)
17381169699Skan    operands[i] = gen_reg_rtx (XFmode);
17382169699Skan})
17383169699Skan
17384169699Skan(define_expand "ldexpsf3"
17385169699Skan  [(set (match_dup 3)
17386169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17387169699Skan   (set (match_dup 4)
17388169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17389169699Skan   (parallel [(set (match_dup 5)
17390169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17391169699Skan			      UNSPEC_FSCALE_FRACT))
17392169699Skan	      (set (match_dup 6)
17393169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17394169699Skan			      UNSPEC_FSCALE_EXP))])
17395169699Skan   (set (match_operand:SF 0 "register_operand" "")
17396169699Skan	(float_truncate:SF (match_dup 5)))]
17397169699Skan  "TARGET_USE_FANCY_MATH_387
17398169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17399169699Skan   && flag_unsafe_math_optimizations"
17400169699Skan{
17401169699Skan  int i;
17402169699Skan
17403169699Skan  for (i=3; i<7; i++)
17404169699Skan    operands[i] = gen_reg_rtx (XFmode);
17405169699Skan})
17406169699Skan
17407169699Skan(define_expand "ldexpxf3"
17408169699Skan  [(set (match_dup 3)
17409169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17410169699Skan   (parallel [(set (match_operand:XF 0 " register_operand" "")
17411169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
17412169699Skan			       (match_dup 3)]
17413169699Skan			      UNSPEC_FSCALE_FRACT))
17414169699Skan	      (set (match_dup 4)
17415169699Skan		   (unspec:XF [(match_dup 1) (match_dup 3)]
17416169699Skan			      UNSPEC_FSCALE_EXP))])]
17417169699Skan  "TARGET_USE_FANCY_MATH_387
17418169699Skan   && flag_unsafe_math_optimizations"
17419169699Skan{
17420169699Skan  int i;
17421169699Skan
17422169699Skan  for (i=3; i<5; i++)
17423169699Skan    operands[i] = gen_reg_rtx (XFmode);
17424169699Skan})
1742590286Sobrien
17426169699Skan
17427169699Skan(define_insn "frndintxf2"
17428169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17429169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17430169699Skan	 UNSPEC_FRNDINT))]
17431169699Skan  "TARGET_USE_FANCY_MATH_387
17432169699Skan   && flag_unsafe_math_optimizations"
17433169699Skan  "frndint"
17434169699Skan  [(set_attr "type" "fpspc")
17435169699Skan   (set_attr "mode" "XF")])
17436169699Skan
17437169699Skan(define_expand "rintdf2"
17438169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17439169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17440169699Skan  "TARGET_USE_FANCY_MATH_387
17441169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17442169699Skan   && flag_unsafe_math_optimizations"
17443169699Skan{
17444169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17445169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17446169699Skan
17447169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17448169699Skan  emit_insn (gen_frndintxf2 (op0, op1));
17449169699Skan
17450169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17451169699Skan  DONE;
17452169699Skan})
17453169699Skan
17454169699Skan(define_expand "rintsf2"
17455169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17456169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17457169699Skan  "TARGET_USE_FANCY_MATH_387
17458169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17459169699Skan   && flag_unsafe_math_optimizations"
17460169699Skan{
17461169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17462169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17463169699Skan
17464169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17465169699Skan  emit_insn (gen_frndintxf2 (op0, op1));
17466169699Skan
17467169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17468169699Skan  DONE;
17469169699Skan})
17470169699Skan
17471169699Skan(define_expand "rintxf2"
17472169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17473169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17474169699Skan  "TARGET_USE_FANCY_MATH_387
17475169699Skan   && flag_unsafe_math_optimizations"
17476169699Skan{
17477169699Skan  emit_insn (gen_frndintxf2 (operands[0], operands[1]));
17478169699Skan  DONE;
17479169699Skan})
17480169699Skan
17481169699Skan(define_insn_and_split "*fistdi2_1"
17482169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17483169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17484169699Skan	 UNSPEC_FIST))]
17485169699Skan  "TARGET_USE_FANCY_MATH_387
17486169699Skan   && flag_unsafe_math_optimizations
17487169699Skan   && !(reload_completed || reload_in_progress)"
17488169699Skan  "#"
17489169699Skan  "&& 1"
17490169699Skan  [(const_int 0)]
17491169699Skan{
17492169699Skan  if (memory_operand (operands[0], VOIDmode))
17493169699Skan    emit_insn (gen_fistdi2 (operands[0], operands[1]));
17494169699Skan  else
17495169699Skan    {
17496169699Skan      operands[2] = assign_386_stack_local (DImode, SLOT_TEMP);
17497169699Skan      emit_insn (gen_fistdi2_with_temp (operands[0], operands[1],
17498169699Skan					 operands[2]));
17499169699Skan    }
17500169699Skan  DONE;
17501169699Skan}
17502169699Skan  [(set_attr "type" "fpspc")
17503169699Skan   (set_attr "mode" "DI")])
17504169699Skan
17505169699Skan(define_insn "fistdi2"
17506169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17507169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17508169699Skan	 UNSPEC_FIST))
17509169699Skan   (clobber (match_scratch:XF 2 "=&1f"))]
17510169699Skan  "TARGET_USE_FANCY_MATH_387
17511169699Skan   && flag_unsafe_math_optimizations"
17512169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17513169699Skan  [(set_attr "type" "fpspc")
17514169699Skan   (set_attr "mode" "DI")])
17515169699Skan
17516169699Skan(define_insn "fistdi2_with_temp"
17517169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17518169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17519169699Skan	 UNSPEC_FIST))
17520169699Skan   (clobber (match_operand:DI 2 "memory_operand" "=m,m"))
17521169699Skan   (clobber (match_scratch:XF 3 "=&1f,&1f"))]
17522169699Skan  "TARGET_USE_FANCY_MATH_387
17523169699Skan   && flag_unsafe_math_optimizations"
17524169699Skan  "#"
17525169699Skan  [(set_attr "type" "fpspc")
17526169699Skan   (set_attr "mode" "DI")])
17527169699Skan
17528259563Spfg(define_split
17529169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17530169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17531169699Skan	 UNSPEC_FIST))
17532169699Skan   (clobber (match_operand:DI 2 "memory_operand" ""))
17533169699Skan   (clobber (match_scratch 3 ""))]
17534169699Skan  "reload_completed"
17535169699Skan  [(parallel [(set (match_dup 2) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
17536169699Skan	      (clobber (match_dup 3))])
17537169699Skan   (set (match_dup 0) (match_dup 2))]
17538169699Skan  "")
17539169699Skan
17540259563Spfg(define_split
17541169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17542169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17543169699Skan	 UNSPEC_FIST))
17544169699Skan   (clobber (match_operand:DI 2 "memory_operand" ""))
17545169699Skan   (clobber (match_scratch 3 ""))]
17546169699Skan  "reload_completed"
17547169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
17548169699Skan	      (clobber (match_dup 3))])]
17549169699Skan  "")
17550169699Skan
17551169699Skan(define_insn_and_split "*fist<mode>2_1"
17552169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
17553169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17554169699Skan	 UNSPEC_FIST))]
17555169699Skan  "TARGET_USE_FANCY_MATH_387
17556169699Skan   && flag_unsafe_math_optimizations
17557169699Skan   && !(reload_completed || reload_in_progress)"
17558169699Skan  "#"
17559169699Skan  "&& 1"
17560169699Skan  [(const_int 0)]
17561169699Skan{
17562169699Skan  operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17563169699Skan  emit_insn (gen_fist<mode>2_with_temp (operands[0], operands[1],
17564169699Skan					operands[2]));
17565169699Skan  DONE;
17566169699Skan}
17567169699Skan  [(set_attr "type" "fpspc")
17568169699Skan   (set_attr "mode" "<MODE>")])
17569169699Skan
17570169699Skan(define_insn "fist<mode>2"
17571169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17572169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17573169699Skan	 UNSPEC_FIST))]
17574169699Skan  "TARGET_USE_FANCY_MATH_387
17575169699Skan   && flag_unsafe_math_optimizations"
17576169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17577169699Skan  [(set_attr "type" "fpspc")
17578169699Skan   (set_attr "mode" "<MODE>")])
17579169699Skan
17580169699Skan(define_insn "fist<mode>2_with_temp"
17581169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
17582169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17583169699Skan	 UNSPEC_FIST))
17584169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" "=m"))]
17585169699Skan  "TARGET_USE_FANCY_MATH_387
17586169699Skan   && flag_unsafe_math_optimizations"
17587169699Skan  "#"
17588169699Skan  [(set_attr "type" "fpspc")
17589169699Skan   (set_attr "mode" "<MODE>")])
17590169699Skan
17591259563Spfg(define_split
17592169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17593169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17594169699Skan	 UNSPEC_FIST))
17595169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
17596169699Skan  "reload_completed"
17597169699Skan  [(set (match_dup 2) (unspec:X87MODEI12 [(match_dup 1)]
17598169699Skan		       UNSPEC_FIST))
17599169699Skan   (set (match_dup 0) (match_dup 2))]
17600169699Skan  "")
17601169699Skan
17602259563Spfg(define_split
17603169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17604169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17605169699Skan	 UNSPEC_FIST))
17606169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
17607169699Skan  "reload_completed"
17608169699Skan  [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17609169699Skan		       UNSPEC_FIST))]
17610169699Skan  "")
17611169699Skan
17612169699Skan(define_expand "lrint<mode>2"
17613169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17614169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17615169699Skan	 UNSPEC_FIST))]
17616169699Skan  "TARGET_USE_FANCY_MATH_387
17617169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17618169699Skan   && flag_unsafe_math_optimizations"
17619169699Skan  "")
17620169699Skan
17621169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17622169699Skan(define_insn_and_split "frndintxf2_floor"
17623169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17624169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17625169699Skan	 UNSPEC_FRNDINT_FLOOR))
17626169699Skan   (clobber (reg:CC FLAGS_REG))]
17627169699Skan  "TARGET_USE_FANCY_MATH_387
17628169699Skan   && flag_unsafe_math_optimizations
17629169699Skan   && !(reload_completed || reload_in_progress)"
17630169699Skan  "#"
17631169699Skan  "&& 1"
17632169699Skan  [(const_int 0)]
17633169699Skan{
17634169699Skan  ix86_optimize_mode_switching[I387_FLOOR] = 1;
17635169699Skan
17636169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17637169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
17638169699Skan
17639169699Skan  emit_insn (gen_frndintxf2_floor_i387 (operands[0], operands[1],
17640169699Skan					operands[2], operands[3]));
17641169699Skan  DONE;
17642169699Skan}
17643169699Skan  [(set_attr "type" "frndint")
17644169699Skan   (set_attr "i387_cw" "floor")
17645169699Skan   (set_attr "mode" "XF")])
17646169699Skan
17647169699Skan(define_insn "frndintxf2_floor_i387"
17648169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17649169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17650169699Skan	 UNSPEC_FRNDINT_FLOOR))
17651169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17652169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17653169699Skan  "TARGET_USE_FANCY_MATH_387
17654169699Skan   && flag_unsafe_math_optimizations"
17655169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17656169699Skan  [(set_attr "type" "frndint")
17657169699Skan   (set_attr "i387_cw" "floor")
17658169699Skan   (set_attr "mode" "XF")])
17659169699Skan
17660169699Skan(define_expand "floorxf2"
17661169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17662169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17663169699Skan  "TARGET_USE_FANCY_MATH_387
17664169699Skan   && flag_unsafe_math_optimizations"
17665169699Skan{
17666169699Skan  emit_insn (gen_frndintxf2_floor (operands[0], operands[1]));
17667169699Skan  DONE;
17668169699Skan})
17669169699Skan
17670169699Skan(define_expand "floordf2"
17671169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17672169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17673169699Skan  "TARGET_USE_FANCY_MATH_387
17674169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17675169699Skan   && flag_unsafe_math_optimizations"
17676169699Skan{
17677169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17678169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17679169699Skan
17680169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17681169699Skan  emit_insn (gen_frndintxf2_floor (op0, op1));
17682169699Skan
17683169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17684169699Skan  DONE;
17685169699Skan})
17686169699Skan
17687169699Skan(define_expand "floorsf2"
17688169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17689169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17690169699Skan  "TARGET_USE_FANCY_MATH_387
17691169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17692169699Skan   && flag_unsafe_math_optimizations"
17693169699Skan{
17694169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17695169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17696169699Skan
17697169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17698169699Skan  emit_insn (gen_frndintxf2_floor (op0, op1));
17699169699Skan
17700169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17701169699Skan  DONE;
17702169699Skan})
17703169699Skan
17704169699Skan(define_insn_and_split "*fist<mode>2_floor_1"
17705169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
17706169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
17707169699Skan	 UNSPEC_FIST_FLOOR))
17708169699Skan   (clobber (reg:CC FLAGS_REG))]
17709169699Skan  "TARGET_USE_FANCY_MATH_387
17710169699Skan   && flag_unsafe_math_optimizations
17711169699Skan   && !(reload_completed || reload_in_progress)"
17712169699Skan  "#"
17713169699Skan  "&& 1"
17714169699Skan  [(const_int 0)]
17715169699Skan{
17716169699Skan  ix86_optimize_mode_switching[I387_FLOOR] = 1;
17717169699Skan
17718169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17719169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
17720169699Skan  if (memory_operand (operands[0], VOIDmode))
17721169699Skan    emit_insn (gen_fist<mode>2_floor (operands[0], operands[1],
17722169699Skan				      operands[2], operands[3]));
17723169699Skan  else
17724169699Skan    {
17725169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17726169699Skan      emit_insn (gen_fist<mode>2_floor_with_temp (operands[0], operands[1],
17727169699Skan						  operands[2], operands[3],
17728169699Skan						  operands[4]));
17729169699Skan    }
17730169699Skan  DONE;
17731169699Skan}
17732169699Skan  [(set_attr "type" "fistp")
17733169699Skan   (set_attr "i387_cw" "floor")
17734169699Skan   (set_attr "mode" "<MODE>")])
17735169699Skan
17736169699Skan(define_insn "fistdi2_floor"
17737169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17738169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17739169699Skan	 UNSPEC_FIST_FLOOR))
17740169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17741169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
17742169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
17743169699Skan  "TARGET_USE_FANCY_MATH_387
17744169699Skan   && flag_unsafe_math_optimizations"
17745169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17746169699Skan  [(set_attr "type" "fistp")
17747169699Skan   (set_attr "i387_cw" "floor")
17748169699Skan   (set_attr "mode" "DI")])
17749169699Skan
17750169699Skan(define_insn "fistdi2_floor_with_temp"
17751169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17752169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17753169699Skan	 UNSPEC_FIST_FLOOR))
17754169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17755169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17756169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
17757169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
17758169699Skan  "TARGET_USE_FANCY_MATH_387
17759169699Skan   && flag_unsafe_math_optimizations"
17760169699Skan  "#"
17761169699Skan  [(set_attr "type" "fistp")
17762169699Skan   (set_attr "i387_cw" "floor")
17763169699Skan   (set_attr "mode" "DI")])
17764169699Skan
17765259563Spfg(define_split
17766169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17767169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17768169699Skan	 UNSPEC_FIST_FLOOR))
17769169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17770169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17771169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17772169699Skan   (clobber (match_scratch 5 ""))]
17773169699Skan  "reload_completed"
17774169699Skan  [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
17775169699Skan	      (use (match_dup 2))
17776169699Skan	      (use (match_dup 3))
17777169699Skan	      (clobber (match_dup 5))])
17778169699Skan   (set (match_dup 0) (match_dup 4))]
17779169699Skan  "")
17780169699Skan
17781259563Spfg(define_split
17782169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17783169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17784169699Skan	 UNSPEC_FIST_FLOOR))
17785169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17786169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17787169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17788169699Skan   (clobber (match_scratch 5 ""))]
17789169699Skan  "reload_completed"
17790169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
17791169699Skan	      (use (match_dup 2))
17792169699Skan	      (use (match_dup 3))
17793169699Skan	      (clobber (match_dup 5))])]
17794169699Skan  "")
17795169699Skan
17796169699Skan(define_insn "fist<mode>2_floor"
17797169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17798169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17799169699Skan	 UNSPEC_FIST_FLOOR))
17800169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17801169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17802169699Skan  "TARGET_USE_FANCY_MATH_387
17803169699Skan   && flag_unsafe_math_optimizations"
17804169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17805169699Skan  [(set_attr "type" "fistp")
17806169699Skan   (set_attr "i387_cw" "floor")
17807169699Skan   (set_attr "mode" "<MODE>")])
17808169699Skan
17809169699Skan(define_insn "fist<mode>2_floor_with_temp"
17810169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
17811169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
17812169699Skan	 UNSPEC_FIST_FLOOR))
17813169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17814169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17815169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
17816169699Skan  "TARGET_USE_FANCY_MATH_387
17817169699Skan   && flag_unsafe_math_optimizations"
17818169699Skan  "#"
17819169699Skan  [(set_attr "type" "fistp")
17820169699Skan   (set_attr "i387_cw" "floor")
17821169699Skan   (set_attr "mode" "<MODE>")])
17822169699Skan
17823259563Spfg(define_split
17824169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17825169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17826169699Skan	 UNSPEC_FIST_FLOOR))
17827169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17828169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17829169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17830169699Skan  "reload_completed"
17831169699Skan  [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
17832169699Skan				  UNSPEC_FIST_FLOOR))
17833169699Skan	      (use (match_dup 2))
17834169699Skan	      (use (match_dup 3))])
17835169699Skan   (set (match_dup 0) (match_dup 4))]
17836169699Skan  "")
17837169699Skan
17838259563Spfg(define_split
17839169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17840169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17841169699Skan	 UNSPEC_FIST_FLOOR))
17842169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17843169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17844169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17845169699Skan  "reload_completed"
17846169699Skan  [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17847169699Skan				  UNSPEC_FIST_FLOOR))
17848169699Skan	      (use (match_dup 2))
17849169699Skan	      (use (match_dup 3))])]
17850169699Skan  "")
17851169699Skan
17852169699Skan(define_expand "lfloor<mode>2"
17853169699Skan  [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17854169699Skan		   (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17855169699Skan		    UNSPEC_FIST_FLOOR))
17856169699Skan	      (clobber (reg:CC FLAGS_REG))])]
17857169699Skan  "TARGET_USE_FANCY_MATH_387
17858169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17859169699Skan   && flag_unsafe_math_optimizations"
17860169699Skan  "")
17861169699Skan
17862169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17863169699Skan(define_insn_and_split "frndintxf2_ceil"
17864169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17865169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17866169699Skan	 UNSPEC_FRNDINT_CEIL))
17867169699Skan   (clobber (reg:CC FLAGS_REG))]
17868169699Skan  "TARGET_USE_FANCY_MATH_387
17869169699Skan   && flag_unsafe_math_optimizations
17870169699Skan   && !(reload_completed || reload_in_progress)"
17871169699Skan  "#"
17872169699Skan  "&& 1"
17873169699Skan  [(const_int 0)]
17874169699Skan{
17875169699Skan  ix86_optimize_mode_switching[I387_CEIL] = 1;
17876169699Skan
17877169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17878169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
17879169699Skan
17880169699Skan  emit_insn (gen_frndintxf2_ceil_i387 (operands[0], operands[1],
17881169699Skan				       operands[2], operands[3]));
17882169699Skan  DONE;
17883169699Skan}
17884169699Skan  [(set_attr "type" "frndint")
17885169699Skan   (set_attr "i387_cw" "ceil")
17886169699Skan   (set_attr "mode" "XF")])
17887169699Skan
17888169699Skan(define_insn "frndintxf2_ceil_i387"
17889169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17890169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17891169699Skan	 UNSPEC_FRNDINT_CEIL))
17892169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17893169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17894169699Skan  "TARGET_USE_FANCY_MATH_387
17895169699Skan   && flag_unsafe_math_optimizations"
17896169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17897169699Skan  [(set_attr "type" "frndint")
17898169699Skan   (set_attr "i387_cw" "ceil")
17899169699Skan   (set_attr "mode" "XF")])
17900169699Skan
17901169699Skan(define_expand "ceilxf2"
17902169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17903169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17904169699Skan  "TARGET_USE_FANCY_MATH_387
17905169699Skan   && flag_unsafe_math_optimizations"
17906169699Skan{
17907169699Skan  emit_insn (gen_frndintxf2_ceil (operands[0], operands[1]));
17908169699Skan  DONE;
17909169699Skan})
17910169699Skan
17911169699Skan(define_expand "ceildf2"
17912169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17913169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17914169699Skan  "TARGET_USE_FANCY_MATH_387
17915169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17916169699Skan   && flag_unsafe_math_optimizations"
17917169699Skan{
17918169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17919169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17920169699Skan
17921169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17922169699Skan  emit_insn (gen_frndintxf2_ceil (op0, op1));
17923169699Skan
17924169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17925169699Skan  DONE;
17926169699Skan})
17927169699Skan
17928169699Skan(define_expand "ceilsf2"
17929169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17930169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17931169699Skan  "TARGET_USE_FANCY_MATH_387
17932169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17933169699Skan   && flag_unsafe_math_optimizations"
17934169699Skan{
17935169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17936169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17937169699Skan
17938169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17939169699Skan  emit_insn (gen_frndintxf2_ceil (op0, op1));
17940169699Skan
17941169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17942169699Skan  DONE;
17943169699Skan})
17944169699Skan
17945169699Skan(define_insn_and_split "*fist<mode>2_ceil_1"
17946169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
17947169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
17948169699Skan	 UNSPEC_FIST_CEIL))
17949169699Skan   (clobber (reg:CC FLAGS_REG))]
17950169699Skan  "TARGET_USE_FANCY_MATH_387
17951169699Skan   && flag_unsafe_math_optimizations
17952169699Skan   && !(reload_completed || reload_in_progress)"
17953169699Skan  "#"
17954169699Skan  "&& 1"
17955169699Skan  [(const_int 0)]
17956169699Skan{
17957169699Skan  ix86_optimize_mode_switching[I387_CEIL] = 1;
17958169699Skan
17959169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17960169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
17961169699Skan  if (memory_operand (operands[0], VOIDmode))
17962169699Skan    emit_insn (gen_fist<mode>2_ceil (operands[0], operands[1],
17963169699Skan				     operands[2], operands[3]));
17964169699Skan  else
17965169699Skan    {
17966169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17967169699Skan      emit_insn (gen_fist<mode>2_ceil_with_temp (operands[0], operands[1],
17968169699Skan						 operands[2], operands[3],
17969169699Skan						 operands[4]));
17970169699Skan    }
17971169699Skan  DONE;
17972169699Skan}
17973169699Skan  [(set_attr "type" "fistp")
17974169699Skan   (set_attr "i387_cw" "ceil")
17975169699Skan   (set_attr "mode" "<MODE>")])
17976169699Skan
17977169699Skan(define_insn "fistdi2_ceil"
17978169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17979169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17980169699Skan	 UNSPEC_FIST_CEIL))
17981169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17982169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
17983169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
17984169699Skan  "TARGET_USE_FANCY_MATH_387
17985169699Skan   && flag_unsafe_math_optimizations"
17986169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17987169699Skan  [(set_attr "type" "fistp")
17988169699Skan   (set_attr "i387_cw" "ceil")
17989169699Skan   (set_attr "mode" "DI")])
17990169699Skan
17991169699Skan(define_insn "fistdi2_ceil_with_temp"
17992169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17993169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17994169699Skan	 UNSPEC_FIST_CEIL))
17995169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17996169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17997169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
17998169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
17999169699Skan  "TARGET_USE_FANCY_MATH_387
18000169699Skan   && flag_unsafe_math_optimizations"
18001169699Skan  "#"
18002169699Skan  [(set_attr "type" "fistp")
18003169699Skan   (set_attr "i387_cw" "ceil")
18004169699Skan   (set_attr "mode" "DI")])
18005169699Skan
18006259563Spfg(define_split
18007169699Skan  [(set (match_operand:DI 0 "register_operand" "")
18008169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
18009169699Skan	 UNSPEC_FIST_CEIL))
18010169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
18011169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
18012169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
18013169699Skan   (clobber (match_scratch 5 ""))]
18014169699Skan  "reload_completed"
18015169699Skan  [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
18016169699Skan	      (use (match_dup 2))
18017169699Skan	      (use (match_dup 3))
18018169699Skan	      (clobber (match_dup 5))])
18019169699Skan   (set (match_dup 0) (match_dup 4))]
18020169699Skan  "")
18021169699Skan
18022259563Spfg(define_split
18023169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
18024169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
18025169699Skan	 UNSPEC_FIST_CEIL))
18026169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
18027169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
18028169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
18029169699Skan   (clobber (match_scratch 5 ""))]
18030169699Skan  "reload_completed"
18031169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
18032169699Skan	      (use (match_dup 2))
18033169699Skan	      (use (match_dup 3))
18034169699Skan	      (clobber (match_dup 5))])]
18035169699Skan  "")
18036169699Skan
18037169699Skan(define_insn "fist<mode>2_ceil"
18038169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
18039169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
18040169699Skan	 UNSPEC_FIST_CEIL))
18041169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
18042169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
18043169699Skan  "TARGET_USE_FANCY_MATH_387
18044169699Skan   && flag_unsafe_math_optimizations"
18045169699Skan  "* return output_fix_trunc (insn, operands, 0);"
18046169699Skan  [(set_attr "type" "fistp")
18047169699Skan   (set_attr "i387_cw" "ceil")
18048169699Skan   (set_attr "mode" "<MODE>")])
18049169699Skan
18050169699Skan(define_insn "fist<mode>2_ceil_with_temp"
18051169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
18052169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
18053169699Skan	 UNSPEC_FIST_CEIL))
18054169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
18055169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
18056169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
18057169699Skan  "TARGET_USE_FANCY_MATH_387
18058169699Skan   && flag_unsafe_math_optimizations"
18059169699Skan  "#"
18060169699Skan  [(set_attr "type" "fistp")
18061169699Skan   (set_attr "i387_cw" "ceil")
18062169699Skan   (set_attr "mode" "<MODE>")])
18063169699Skan
18064259563Spfg(define_split
18065169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
18066169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
18067169699Skan	 UNSPEC_FIST_CEIL))
18068169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
18069169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
18070169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
18071169699Skan  "reload_completed"
18072169699Skan  [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
18073169699Skan				  UNSPEC_FIST_CEIL))
18074169699Skan	      (use (match_dup 2))
18075169699Skan	      (use (match_dup 3))])
18076169699Skan   (set (match_dup 0) (match_dup 4))]
18077169699Skan  "")
18078169699Skan
18079259563Spfg(define_split
18080169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
18081169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
18082169699Skan	 UNSPEC_FIST_CEIL))
18083169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
18084169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
18085169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
18086169699Skan  "reload_completed"
18087169699Skan  [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
18088169699Skan				  UNSPEC_FIST_CEIL))
18089169699Skan	      (use (match_dup 2))
18090169699Skan	      (use (match_dup 3))])]
18091169699Skan  "")
18092169699Skan
18093169699Skan(define_expand "lceil<mode>2"
18094169699Skan  [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
18095169699Skan		   (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
18096169699Skan		    UNSPEC_FIST_CEIL))
18097169699Skan	      (clobber (reg:CC FLAGS_REG))])]
18098169699Skan  "TARGET_USE_FANCY_MATH_387
18099169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
18100169699Skan   && flag_unsafe_math_optimizations"
18101169699Skan  "")
18102169699Skan
18103169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
18104169699Skan(define_insn_and_split "frndintxf2_trunc"
18105169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
18106169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
18107169699Skan	 UNSPEC_FRNDINT_TRUNC))
18108169699Skan   (clobber (reg:CC FLAGS_REG))]
18109169699Skan  "TARGET_USE_FANCY_MATH_387
18110169699Skan   && flag_unsafe_math_optimizations
18111169699Skan   && !(reload_completed || reload_in_progress)"
18112169699Skan  "#"
18113169699Skan  "&& 1"
18114169699Skan  [(const_int 0)]
18115169699Skan{
18116169699Skan  ix86_optimize_mode_switching[I387_TRUNC] = 1;
18117169699Skan
18118169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
18119169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
18120169699Skan
18121169699Skan  emit_insn (gen_frndintxf2_trunc_i387 (operands[0], operands[1],
18122169699Skan					operands[2], operands[3]));
18123169699Skan  DONE;
18124169699Skan}
18125169699Skan  [(set_attr "type" "frndint")
18126169699Skan   (set_attr "i387_cw" "trunc")
18127169699Skan   (set_attr "mode" "XF")])
18128169699Skan
18129169699Skan(define_insn "frndintxf2_trunc_i387"
18130169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
18131169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
18132169699Skan	 UNSPEC_FRNDINT_TRUNC))
18133169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
18134169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
18135169699Skan  "TARGET_USE_FANCY_MATH_387
18136169699Skan   && flag_unsafe_math_optimizations"
18137169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
18138169699Skan  [(set_attr "type" "frndint")
18139169699Skan   (set_attr "i387_cw" "trunc")
18140169699Skan   (set_attr "mode" "XF")])
18141169699Skan
18142169699Skan(define_expand "btruncxf2"
18143169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
18144169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
18145169699Skan  "TARGET_USE_FANCY_MATH_387
18146169699Skan   && flag_unsafe_math_optimizations"
18147169699Skan{
18148169699Skan  emit_insn (gen_frndintxf2_trunc (operands[0], operands[1]));
18149169699Skan  DONE;
18150169699Skan})
18151169699Skan
18152169699Skan(define_expand "btruncdf2"
18153169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
18154169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
18155169699Skan  "TARGET_USE_FANCY_MATH_387
18156169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
18157169699Skan   && flag_unsafe_math_optimizations"
18158169699Skan{
18159169699Skan  rtx op0 = gen_reg_rtx (XFmode);
18160169699Skan  rtx op1 = gen_reg_rtx (XFmode);
18161169699Skan
18162169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
18163169699Skan  emit_insn (gen_frndintxf2_trunc (op0, op1));
18164169699Skan
18165169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
18166169699Skan  DONE;
18167169699Skan})
18168169699Skan
18169169699Skan(define_expand "btruncsf2"
18170169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
18171169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
18172169699Skan  "TARGET_USE_FANCY_MATH_387
18173169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
18174169699Skan   && flag_unsafe_math_optimizations"
18175169699Skan{
18176169699Skan  rtx op0 = gen_reg_rtx (XFmode);
18177169699Skan  rtx op1 = gen_reg_rtx (XFmode);
18178169699Skan
18179169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
18180169699Skan  emit_insn (gen_frndintxf2_trunc (op0, op1));
18181169699Skan
18182169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
18183169699Skan  DONE;
18184169699Skan})
18185169699Skan
18186169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
18187169699Skan(define_insn_and_split "frndintxf2_mask_pm"
18188169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
18189169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
18190169699Skan	 UNSPEC_FRNDINT_MASK_PM))
18191169699Skan   (clobber (reg:CC FLAGS_REG))]
18192169699Skan  "TARGET_USE_FANCY_MATH_387
18193169699Skan   && flag_unsafe_math_optimizations
18194169699Skan   && !(reload_completed || reload_in_progress)"
18195169699Skan  "#"
18196169699Skan  "&& 1"
18197169699Skan  [(const_int 0)]
18198169699Skan{
18199169699Skan  ix86_optimize_mode_switching[I387_MASK_PM] = 1;
18200169699Skan
18201169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
18202169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_MASK_PM);
18203169699Skan
18204169699Skan  emit_insn (gen_frndintxf2_mask_pm_i387 (operands[0], operands[1],
18205169699Skan					  operands[2], operands[3]));
18206169699Skan  DONE;
18207169699Skan}
18208169699Skan  [(set_attr "type" "frndint")
18209169699Skan   (set_attr "i387_cw" "mask_pm")
18210169699Skan   (set_attr "mode" "XF")])
18211169699Skan
18212169699Skan(define_insn "frndintxf2_mask_pm_i387"
18213169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
18214169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
18215169699Skan	 UNSPEC_FRNDINT_MASK_PM))
18216169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
18217169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
18218169699Skan  "TARGET_USE_FANCY_MATH_387
18219169699Skan   && flag_unsafe_math_optimizations"
18220169699Skan  "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2"
18221169699Skan  [(set_attr "type" "frndint")
18222169699Skan   (set_attr "i387_cw" "mask_pm")
18223169699Skan   (set_attr "mode" "XF")])
18224169699Skan
18225169699Skan(define_expand "nearbyintxf2"
18226169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
18227169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
18228169699Skan  "TARGET_USE_FANCY_MATH_387
18229169699Skan   && flag_unsafe_math_optimizations"
18230169699Skan{
18231169699Skan  emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1]));
18232169699Skan
18233169699Skan  DONE;
18234169699Skan})
18235169699Skan
18236169699Skan(define_expand "nearbyintdf2"
18237169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
18238169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
18239169699Skan  "TARGET_USE_FANCY_MATH_387
18240169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
18241169699Skan   && flag_unsafe_math_optimizations"
18242169699Skan{
18243169699Skan  rtx op0 = gen_reg_rtx (XFmode);
18244169699Skan  rtx op1 = gen_reg_rtx (XFmode);
18245169699Skan
18246169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
18247169699Skan  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
18248169699Skan
18249169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
18250169699Skan  DONE;
18251169699Skan})
18252169699Skan
18253169699Skan(define_expand "nearbyintsf2"
18254169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
18255169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
18256169699Skan  "TARGET_USE_FANCY_MATH_387
18257169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
18258169699Skan   && flag_unsafe_math_optimizations"
18259169699Skan{
18260169699Skan  rtx op0 = gen_reg_rtx (XFmode);
18261169699Skan  rtx op1 = gen_reg_rtx (XFmode);
18262169699Skan
18263169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
18264169699Skan  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
18265169699Skan
18266169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
18267169699Skan  DONE;
18268169699Skan})
18269169699Skan
18270169699Skan
1827190286Sobrien;; Block operation instructions
1827290286Sobrien
1827390286Sobrien(define_insn "cld"
18274169699Skan [(set (reg:SI DIRFLAG_REG) (const_int 0))]
1827590286Sobrien ""
1827690286Sobrien "cld"
1827790286Sobrien  [(set_attr "type" "cld")])
1827890286Sobrien
18279169699Skan(define_expand "movmemsi"
1828090286Sobrien  [(use (match_operand:BLK 0 "memory_operand" ""))
1828190286Sobrien   (use (match_operand:BLK 1 "memory_operand" ""))
1828290286Sobrien   (use (match_operand:SI 2 "nonmemory_operand" ""))
1828390286Sobrien   (use (match_operand:SI 3 "const_int_operand" ""))]
18284169699Skan  "! optimize_size || TARGET_INLINE_ALL_STRINGOPS"
1828518334Speter{
18286169699Skan if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
1828790286Sobrien   DONE;
1828890286Sobrien else
1828990286Sobrien   FAIL;
1829090286Sobrien})
1829190286Sobrien
18292169699Skan(define_expand "movmemdi"
1829390286Sobrien  [(use (match_operand:BLK 0 "memory_operand" ""))
1829490286Sobrien   (use (match_operand:BLK 1 "memory_operand" ""))
1829590286Sobrien   (use (match_operand:DI 2 "nonmemory_operand" ""))
1829690286Sobrien   (use (match_operand:DI 3 "const_int_operand" ""))]
1829790286Sobrien  "TARGET_64BIT"
1829890286Sobrien{
18299169699Skan if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
1830090286Sobrien   DONE;
1830190286Sobrien else
1830290286Sobrien   FAIL;
1830390286Sobrien})
1830490286Sobrien
1830590286Sobrien;; Most CPUs don't like single string operations
1830690286Sobrien;; Handle this case here to simplify previous expander.
1830790286Sobrien
18308132727Skan(define_expand "strmov"
18309132727Skan  [(set (match_dup 4) (match_operand 3 "memory_operand" ""))
18310132727Skan   (set (match_operand 1 "memory_operand" "") (match_dup 4))
18311132727Skan   (parallel [(set (match_operand 0 "register_operand" "") (match_dup 5))
18312169699Skan	      (clobber (reg:CC FLAGS_REG))])
18313132727Skan   (parallel [(set (match_operand 2 "register_operand" "") (match_dup 6))
18314169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1831590286Sobrien  ""
1831690286Sobrien{
18317132727Skan  rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])));
1831850650Sobrien
18319132727Skan  /* If .md ever supports :P for Pmode, these can be directly
18320132727Skan     in the pattern above.  */
18321132727Skan  operands[5] = gen_rtx_PLUS (Pmode, operands[0], adjust);
18322132727Skan  operands[6] = gen_rtx_PLUS (Pmode, operands[2], adjust);
1832350650Sobrien
1832490286Sobrien  if (TARGET_SINGLE_STRINGOP || optimize_size)
1832590286Sobrien    {
18326132727Skan      emit_insn (gen_strmov_singleop (operands[0], operands[1],
18327132727Skan				      operands[2], operands[3],
18328132727Skan				      operands[5], operands[6]));
1832990286Sobrien      DONE;
1833090286Sobrien    }
1833150650Sobrien
18332132727Skan  operands[4] = gen_reg_rtx (GET_MODE (operands[1]));
1833390286Sobrien})
1833450650Sobrien
18335132727Skan(define_expand "strmov_singleop"
18336132727Skan  [(parallel [(set (match_operand 1 "memory_operand" "")
18337132727Skan		   (match_operand 3 "memory_operand" ""))
18338132727Skan	      (set (match_operand 0 "register_operand" "")
18339132727Skan		   (match_operand 4 "" ""))
18340132727Skan	      (set (match_operand 2 "register_operand" "")
18341132727Skan		   (match_operand 5 "" ""))
18342169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18343132727Skan  "TARGET_SINGLE_STRINGOP || optimize_size"
18344132727Skan  "")
1834518334Speter
18346132727Skan(define_insn "*strmovdi_rex_1"
1834790286Sobrien  [(set (mem:DI (match_operand:DI 2 "register_operand" "0"))
1834890286Sobrien	(mem:DI (match_operand:DI 3 "register_operand" "1")))
1834990286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1835090286Sobrien	(plus:DI (match_dup 2)
1835190286Sobrien		 (const_int 8)))
1835290286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1835390286Sobrien	(plus:DI (match_dup 3)
1835490286Sobrien		 (const_int 8)))
18355169699Skan   (use (reg:SI DIRFLAG_REG))]
1835690286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1835790286Sobrien  "movsq"
1835890286Sobrien  [(set_attr "type" "str")
1835990286Sobrien   (set_attr "mode" "DI")
1836090286Sobrien   (set_attr "memory" "both")])
1836190286Sobrien
18362132727Skan(define_insn "*strmovsi_1"
1836390286Sobrien  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
1836490286Sobrien	(mem:SI (match_operand:SI 3 "register_operand" "1")))
1836590286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1836690286Sobrien	(plus:SI (match_dup 2)
1836790286Sobrien		 (const_int 4)))
1836890286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1836990286Sobrien	(plus:SI (match_dup 3)
1837090286Sobrien		 (const_int 4)))
18371169699Skan   (use (reg:SI DIRFLAG_REG))]
1837290286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1837390286Sobrien  "{movsl|movsd}"
1837490286Sobrien  [(set_attr "type" "str")
1837590286Sobrien   (set_attr "mode" "SI")
1837690286Sobrien   (set_attr "memory" "both")])
1837790286Sobrien
18378132727Skan(define_insn "*strmovsi_rex_1"
1837990286Sobrien  [(set (mem:SI (match_operand:DI 2 "register_operand" "0"))
1838090286Sobrien	(mem:SI (match_operand:DI 3 "register_operand" "1")))
1838190286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1838290286Sobrien	(plus:DI (match_dup 2)
1838390286Sobrien		 (const_int 4)))
1838490286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1838590286Sobrien	(plus:DI (match_dup 3)
1838690286Sobrien		 (const_int 4)))
18387169699Skan   (use (reg:SI DIRFLAG_REG))]
1838890286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1838990286Sobrien  "{movsl|movsd}"
1839090286Sobrien  [(set_attr "type" "str")
1839190286Sobrien   (set_attr "mode" "SI")
1839290286Sobrien   (set_attr "memory" "both")])
1839390286Sobrien
18394132727Skan(define_insn "*strmovhi_1"
1839590286Sobrien  [(set (mem:HI (match_operand:SI 2 "register_operand" "0"))
1839690286Sobrien	(mem:HI (match_operand:SI 3 "register_operand" "1")))
1839790286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1839890286Sobrien	(plus:SI (match_dup 2)
1839990286Sobrien		 (const_int 2)))
1840090286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1840190286Sobrien	(plus:SI (match_dup 3)
1840290286Sobrien		 (const_int 2)))
18403169699Skan   (use (reg:SI DIRFLAG_REG))]
1840490286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1840590286Sobrien  "movsw"
1840690286Sobrien  [(set_attr "type" "str")
1840790286Sobrien   (set_attr "memory" "both")
1840890286Sobrien   (set_attr "mode" "HI")])
1840990286Sobrien
18410132727Skan(define_insn "*strmovhi_rex_1"
1841190286Sobrien  [(set (mem:HI (match_operand:DI 2 "register_operand" "0"))
1841290286Sobrien	(mem:HI (match_operand:DI 3 "register_operand" "1")))
1841390286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1841490286Sobrien	(plus:DI (match_dup 2)
1841590286Sobrien		 (const_int 2)))
1841690286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1841790286Sobrien	(plus:DI (match_dup 3)
1841890286Sobrien		 (const_int 2)))
18419169699Skan   (use (reg:SI DIRFLAG_REG))]
1842090286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1842190286Sobrien  "movsw"
1842290286Sobrien  [(set_attr "type" "str")
1842390286Sobrien   (set_attr "memory" "both")
1842490286Sobrien   (set_attr "mode" "HI")])
1842590286Sobrien
18426132727Skan(define_insn "*strmovqi_1"
1842790286Sobrien  [(set (mem:QI (match_operand:SI 2 "register_operand" "0"))
1842890286Sobrien	(mem:QI (match_operand:SI 3 "register_operand" "1")))
1842990286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1843090286Sobrien	(plus:SI (match_dup 2)
1843190286Sobrien		 (const_int 1)))
1843290286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1843390286Sobrien	(plus:SI (match_dup 3)
1843490286Sobrien		 (const_int 1)))
18435169699Skan   (use (reg:SI DIRFLAG_REG))]
1843690286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1843790286Sobrien  "movsb"
1843890286Sobrien  [(set_attr "type" "str")
1843990286Sobrien   (set_attr "memory" "both")
1844090286Sobrien   (set_attr "mode" "QI")])
1844190286Sobrien
18442132727Skan(define_insn "*strmovqi_rex_1"
1844390286Sobrien  [(set (mem:QI (match_operand:DI 2 "register_operand" "0"))
1844490286Sobrien	(mem:QI (match_operand:DI 3 "register_operand" "1")))
1844590286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1844690286Sobrien	(plus:DI (match_dup 2)
1844790286Sobrien		 (const_int 1)))
1844890286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1844990286Sobrien	(plus:DI (match_dup 3)
1845090286Sobrien		 (const_int 1)))
18451169699Skan   (use (reg:SI DIRFLAG_REG))]
1845290286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1845390286Sobrien  "movsb"
1845490286Sobrien  [(set_attr "type" "str")
1845590286Sobrien   (set_attr "memory" "both")
1845690286Sobrien   (set_attr "mode" "QI")])
1845790286Sobrien
18458132727Skan(define_expand "rep_mov"
18459132727Skan  [(parallel [(set (match_operand 4 "register_operand" "") (const_int 0))
18460132727Skan	      (set (match_operand 0 "register_operand" "")
18461132727Skan		   (match_operand 5 "" ""))
18462132727Skan	      (set (match_operand 2 "register_operand" "")
18463132727Skan		   (match_operand 6 "" ""))
18464132727Skan	      (set (match_operand 1 "memory_operand" "")
18465132727Skan		   (match_operand 3 "memory_operand" ""))
18466132727Skan	      (use (match_dup 4))
18467169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18468132727Skan  ""
18469132727Skan  "")
18470132727Skan
18471132727Skan(define_insn "*rep_movdi_rex64"
1847290286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
18473259563Spfg   (set (match_operand:DI 0 "register_operand" "=D")
1847490286Sobrien        (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
1847590286Sobrien			    (const_int 3))
1847690286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
18477259563Spfg   (set (match_operand:DI 1 "register_operand" "=S")
1847890286Sobrien        (plus:DI (ashift:DI (match_dup 5) (const_int 3))
1847990286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1848090286Sobrien   (set (mem:BLK (match_dup 3))
1848190286Sobrien	(mem:BLK (match_dup 4)))
1848290286Sobrien   (use (match_dup 5))
18483169699Skan   (use (reg:SI DIRFLAG_REG))]
1848490286Sobrien  "TARGET_64BIT"
1848590286Sobrien  "{rep\;movsq|rep movsq}"
1848690286Sobrien  [(set_attr "type" "str")
1848790286Sobrien   (set_attr "prefix_rep" "1")
1848890286Sobrien   (set_attr "memory" "both")
1848990286Sobrien   (set_attr "mode" "DI")])
1849090286Sobrien
18491132727Skan(define_insn "*rep_movsi"
1849290286Sobrien  [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
18493259563Spfg   (set (match_operand:SI 0 "register_operand" "=D")
1849490286Sobrien        (plus:SI (ashift:SI (match_operand:SI 5 "register_operand" "2")
1849590286Sobrien			    (const_int 2))
1849690286Sobrien		 (match_operand:SI 3 "register_operand" "0")))
18497259563Spfg   (set (match_operand:SI 1 "register_operand" "=S")
1849890286Sobrien        (plus:SI (ashift:SI (match_dup 5) (const_int 2))
1849990286Sobrien		 (match_operand:SI 4 "register_operand" "1")))
1850090286Sobrien   (set (mem:BLK (match_dup 3))
1850190286Sobrien	(mem:BLK (match_dup 4)))
1850290286Sobrien   (use (match_dup 5))
18503169699Skan   (use (reg:SI DIRFLAG_REG))]
1850490286Sobrien  "!TARGET_64BIT"
1850590286Sobrien  "{rep\;movsl|rep movsd}"
1850690286Sobrien  [(set_attr "type" "str")
1850790286Sobrien   (set_attr "prefix_rep" "1")
1850890286Sobrien   (set_attr "memory" "both")
1850990286Sobrien   (set_attr "mode" "SI")])
1851090286Sobrien
18511132727Skan(define_insn "*rep_movsi_rex64"
1851290286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
18513259563Spfg   (set (match_operand:DI 0 "register_operand" "=D")
1851490286Sobrien        (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
1851590286Sobrien			    (const_int 2))
1851690286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
18517259563Spfg   (set (match_operand:DI 1 "register_operand" "=S")
1851890286Sobrien        (plus:DI (ashift:DI (match_dup 5) (const_int 2))
1851990286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1852090286Sobrien   (set (mem:BLK (match_dup 3))
1852190286Sobrien	(mem:BLK (match_dup 4)))
1852290286Sobrien   (use (match_dup 5))
18523169699Skan   (use (reg:SI DIRFLAG_REG))]
1852490286Sobrien  "TARGET_64BIT"
1852590286Sobrien  "{rep\;movsl|rep movsd}"
1852690286Sobrien  [(set_attr "type" "str")
1852790286Sobrien   (set_attr "prefix_rep" "1")
1852890286Sobrien   (set_attr "memory" "both")
1852990286Sobrien   (set_attr "mode" "SI")])
1853090286Sobrien
18531132727Skan(define_insn "*rep_movqi"
1853290286Sobrien  [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
18533259563Spfg   (set (match_operand:SI 0 "register_operand" "=D")
1853490286Sobrien        (plus:SI (match_operand:SI 3 "register_operand" "0")
1853590286Sobrien		 (match_operand:SI 5 "register_operand" "2")))
18536259563Spfg   (set (match_operand:SI 1 "register_operand" "=S")
1853790286Sobrien        (plus:SI (match_operand:SI 4 "register_operand" "1") (match_dup 5)))
1853890286Sobrien   (set (mem:BLK (match_dup 3))
1853990286Sobrien	(mem:BLK (match_dup 4)))
1854090286Sobrien   (use (match_dup 5))
18541169699Skan   (use (reg:SI DIRFLAG_REG))]
1854290286Sobrien  "!TARGET_64BIT"
1854390286Sobrien  "{rep\;movsb|rep movsb}"
1854490286Sobrien  [(set_attr "type" "str")
1854590286Sobrien   (set_attr "prefix_rep" "1")
1854690286Sobrien   (set_attr "memory" "both")
1854790286Sobrien   (set_attr "mode" "SI")])
1854890286Sobrien
18549132727Skan(define_insn "*rep_movqi_rex64"
1855090286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
18551259563Spfg   (set (match_operand:DI 0 "register_operand" "=D")
1855290286Sobrien        (plus:DI (match_operand:DI 3 "register_operand" "0")
1855390286Sobrien		 (match_operand:DI 5 "register_operand" "2")))
18554259563Spfg   (set (match_operand:DI 1 "register_operand" "=S")
1855590286Sobrien        (plus:DI (match_operand:DI 4 "register_operand" "1") (match_dup 5)))
1855690286Sobrien   (set (mem:BLK (match_dup 3))
1855790286Sobrien	(mem:BLK (match_dup 4)))
1855890286Sobrien   (use (match_dup 5))
18559169699Skan   (use (reg:SI DIRFLAG_REG))]
1856090286Sobrien  "TARGET_64BIT"
1856190286Sobrien  "{rep\;movsb|rep movsb}"
1856290286Sobrien  [(set_attr "type" "str")
1856390286Sobrien   (set_attr "prefix_rep" "1")
1856490286Sobrien   (set_attr "memory" "both")
1856590286Sobrien   (set_attr "mode" "SI")])
1856690286Sobrien
18567169699Skan(define_expand "setmemsi"
1856890286Sobrien   [(use (match_operand:BLK 0 "memory_operand" ""))
1856990286Sobrien    (use (match_operand:SI 1 "nonmemory_operand" ""))
18570169699Skan    (use (match_operand 2 "const_int_operand" ""))
18571169699Skan    (use (match_operand 3 "const_int_operand" ""))]
1857218334Speter  ""
1857318334Speter{
18574169699Skan /* If value to set is not zero, use the library routine.  */
18575169699Skan if (operands[2] != const0_rtx)
18576169699Skan   FAIL;
18577169699Skan
18578169699Skan if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
1857990286Sobrien   DONE;
1858090286Sobrien else
1858190286Sobrien   FAIL;
1858290286Sobrien})
1858318334Speter
18584169699Skan(define_expand "setmemdi"
1858590286Sobrien   [(use (match_operand:BLK 0 "memory_operand" ""))
1858690286Sobrien    (use (match_operand:DI 1 "nonmemory_operand" ""))
18587169699Skan    (use (match_operand 2 "const_int_operand" ""))
18588169699Skan    (use (match_operand 3 "const_int_operand" ""))]
1858990286Sobrien  "TARGET_64BIT"
1859090286Sobrien{
18591169699Skan /* If value to set is not zero, use the library routine.  */
18592169699Skan if (operands[2] != const0_rtx)
18593169699Skan   FAIL;
18594169699Skan
18595169699Skan if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
1859690286Sobrien   DONE;
1859790286Sobrien else
1859890286Sobrien   FAIL;
1859990286Sobrien})
1860050650Sobrien
1860190286Sobrien;; Most CPUs don't like single string operations
1860290286Sobrien;; Handle this case here to simplify previous expander.
1860350650Sobrien
18604132727Skan(define_expand "strset"
18605132727Skan  [(set (match_operand 1 "memory_operand" "")
18606132727Skan	(match_operand 2 "register_operand" ""))
18607132727Skan   (parallel [(set (match_operand 0 "register_operand" "")
18608132727Skan		   (match_dup 3))
18609169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1861090286Sobrien  ""
1861190286Sobrien{
18612132727Skan  if (GET_MODE (operands[1]) != GET_MODE (operands[2]))
18613132727Skan    operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0);
1861490286Sobrien
18615132727Skan  /* If .md ever supports :P for Pmode, this can be directly
18616132727Skan     in the pattern above.  */
18617132727Skan  operands[3] = gen_rtx_PLUS (Pmode, operands[0],
18618132727Skan			      GEN_INT (GET_MODE_SIZE (GET_MODE
18619132727Skan						      (operands[2]))));
1862090286Sobrien  if (TARGET_SINGLE_STRINGOP || optimize_size)
1862190286Sobrien    {
18622132727Skan      emit_insn (gen_strset_singleop (operands[0], operands[1], operands[2],
18623132727Skan				      operands[3]));
1862490286Sobrien      DONE;
1862590286Sobrien    }
1862690286Sobrien})
1862790286Sobrien
18628132727Skan(define_expand "strset_singleop"
18629132727Skan  [(parallel [(set (match_operand 1 "memory_operand" "")
18630132727Skan		   (match_operand 2 "register_operand" ""))
18631132727Skan	      (set (match_operand 0 "register_operand" "")
18632132727Skan		   (match_operand 3 "" ""))
18633169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18634132727Skan  "TARGET_SINGLE_STRINGOP || optimize_size"
18635132727Skan  "")
1863690286Sobrien
18637132727Skan(define_insn "*strsetdi_rex_1"
18638169699Skan  [(set (mem:DI (match_operand:DI 1 "register_operand" "0"))
18639169699Skan	(match_operand:DI 2 "register_operand" "a"))
1864090286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1864190286Sobrien	(plus:DI (match_dup 1)
1864290286Sobrien		 (const_int 8)))
18643169699Skan   (use (reg:SI DIRFLAG_REG))]
1864490286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1864590286Sobrien  "stosq"
1864690286Sobrien  [(set_attr "type" "str")
1864790286Sobrien   (set_attr "memory" "store")
1864890286Sobrien   (set_attr "mode" "DI")])
1864990286Sobrien
18650132727Skan(define_insn "*strsetsi_1"
1865190286Sobrien  [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
1865290286Sobrien	(match_operand:SI 2 "register_operand" "a"))
1865390286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1865490286Sobrien	(plus:SI (match_dup 1)
1865590286Sobrien		 (const_int 4)))
18656169699Skan   (use (reg:SI DIRFLAG_REG))]
1865790286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1865890286Sobrien  "{stosl|stosd}"
1865990286Sobrien  [(set_attr "type" "str")
1866090286Sobrien   (set_attr "memory" "store")
1866190286Sobrien   (set_attr "mode" "SI")])
1866290286Sobrien
18663132727Skan(define_insn "*strsetsi_rex_1"
1866490286Sobrien  [(set (mem:SI (match_operand:DI 1 "register_operand" "0"))
1866590286Sobrien	(match_operand:SI 2 "register_operand" "a"))
1866690286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1866790286Sobrien	(plus:DI (match_dup 1)
1866890286Sobrien		 (const_int 4)))
18669169699Skan   (use (reg:SI DIRFLAG_REG))]
1867090286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1867190286Sobrien  "{stosl|stosd}"
1867290286Sobrien  [(set_attr "type" "str")
1867390286Sobrien   (set_attr "memory" "store")
1867490286Sobrien   (set_attr "mode" "SI")])
1867590286Sobrien
18676132727Skan(define_insn "*strsethi_1"
1867790286Sobrien  [(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
1867890286Sobrien	(match_operand:HI 2 "register_operand" "a"))
1867990286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1868090286Sobrien	(plus:SI (match_dup 1)
1868190286Sobrien		 (const_int 2)))
18682169699Skan   (use (reg:SI DIRFLAG_REG))]
1868390286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1868490286Sobrien  "stosw"
1868590286Sobrien  [(set_attr "type" "str")
1868690286Sobrien   (set_attr "memory" "store")
1868790286Sobrien   (set_attr "mode" "HI")])
1868890286Sobrien
18689132727Skan(define_insn "*strsethi_rex_1"
1869090286Sobrien  [(set (mem:HI (match_operand:DI 1 "register_operand" "0"))
1869190286Sobrien	(match_operand:HI 2 "register_operand" "a"))
1869290286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1869390286Sobrien	(plus:DI (match_dup 1)
1869490286Sobrien		 (const_int 2)))
18695169699Skan   (use (reg:SI DIRFLAG_REG))]
1869690286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1869790286Sobrien  "stosw"
1869890286Sobrien  [(set_attr "type" "str")
1869990286Sobrien   (set_attr "memory" "store")
1870090286Sobrien   (set_attr "mode" "HI")])
1870190286Sobrien
18702132727Skan(define_insn "*strsetqi_1"
1870390286Sobrien  [(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
1870490286Sobrien	(match_operand:QI 2 "register_operand" "a"))
1870590286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1870690286Sobrien	(plus:SI (match_dup 1)
1870790286Sobrien		 (const_int 1)))
18708169699Skan   (use (reg:SI DIRFLAG_REG))]
1870990286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1871090286Sobrien  "stosb"
1871190286Sobrien  [(set_attr "type" "str")
1871290286Sobrien   (set_attr "memory" "store")
1871390286Sobrien   (set_attr "mode" "QI")])
1871490286Sobrien
18715132727Skan(define_insn "*strsetqi_rex_1"
1871690286Sobrien  [(set (mem:QI (match_operand:DI 1 "register_operand" "0"))
1871790286Sobrien	(match_operand:QI 2 "register_operand" "a"))
1871890286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1871990286Sobrien	(plus:DI (match_dup 1)
1872090286Sobrien		 (const_int 1)))
18721169699Skan   (use (reg:SI DIRFLAG_REG))]
1872290286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1872390286Sobrien  "stosb"
1872490286Sobrien  [(set_attr "type" "str")
1872590286Sobrien   (set_attr "memory" "store")
1872690286Sobrien   (set_attr "mode" "QI")])
1872790286Sobrien
18728132727Skan(define_expand "rep_stos"
18729132727Skan  [(parallel [(set (match_operand 1 "register_operand" "") (const_int 0))
18730132727Skan	      (set (match_operand 0 "register_operand" "")
18731132727Skan		   (match_operand 4 "" ""))
18732132727Skan	      (set (match_operand 2 "memory_operand" "") (const_int 0))
18733132727Skan	      (use (match_operand 3 "register_operand" ""))
18734132727Skan	      (use (match_dup 1))
18735169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18736132727Skan  ""
18737132727Skan  "")
18738132727Skan
18739132727Skan(define_insn "*rep_stosdi_rex64"
1874090286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
18741259563Spfg   (set (match_operand:DI 0 "register_operand" "=D")
1874290286Sobrien        (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
1874390286Sobrien			    (const_int 3))
1874490286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1874590286Sobrien   (set (mem:BLK (match_dup 3))
1874690286Sobrien	(const_int 0))
1874790286Sobrien   (use (match_operand:DI 2 "register_operand" "a"))
1874890286Sobrien   (use (match_dup 4))
18749169699Skan   (use (reg:SI DIRFLAG_REG))]
1875090286Sobrien  "TARGET_64BIT"
1875190286Sobrien  "{rep\;stosq|rep stosq}"
1875290286Sobrien  [(set_attr "type" "str")
1875390286Sobrien   (set_attr "prefix_rep" "1")
1875490286Sobrien   (set_attr "memory" "store")
1875590286Sobrien   (set_attr "mode" "DI")])
1875690286Sobrien
18757132727Skan(define_insn "*rep_stossi"
1875890286Sobrien  [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
18759259563Spfg   (set (match_operand:SI 0 "register_operand" "=D")
1876090286Sobrien        (plus:SI (ashift:SI (match_operand:SI 4 "register_operand" "1")
1876190286Sobrien			    (const_int 2))
1876290286Sobrien		 (match_operand:SI 3 "register_operand" "0")))
1876390286Sobrien   (set (mem:BLK (match_dup 3))
1876490286Sobrien	(const_int 0))
1876590286Sobrien   (use (match_operand:SI 2 "register_operand" "a"))
1876690286Sobrien   (use (match_dup 4))
18767169699Skan   (use (reg:SI DIRFLAG_REG))]
1876890286Sobrien  "!TARGET_64BIT"
1876990286Sobrien  "{rep\;stosl|rep stosd}"
1877090286Sobrien  [(set_attr "type" "str")
1877190286Sobrien   (set_attr "prefix_rep" "1")
1877290286Sobrien   (set_attr "memory" "store")
1877390286Sobrien   (set_attr "mode" "SI")])
1877490286Sobrien
18775132727Skan(define_insn "*rep_stossi_rex64"
1877690286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
18777259563Spfg   (set (match_operand:DI 0 "register_operand" "=D")
1877890286Sobrien        (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
1877990286Sobrien			    (const_int 2))
1878090286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1878190286Sobrien   (set (mem:BLK (match_dup 3))
1878290286Sobrien	(const_int 0))
1878390286Sobrien   (use (match_operand:SI 2 "register_operand" "a"))
1878490286Sobrien   (use (match_dup 4))
18785169699Skan   (use (reg:SI DIRFLAG_REG))]
1878690286Sobrien  "TARGET_64BIT"
1878790286Sobrien  "{rep\;stosl|rep stosd}"
1878890286Sobrien  [(set_attr "type" "str")
1878990286Sobrien   (set_attr "prefix_rep" "1")
1879090286Sobrien   (set_attr "memory" "store")
1879190286Sobrien   (set_attr "mode" "SI")])
1879290286Sobrien
18793132727Skan(define_insn "*rep_stosqi"
1879490286Sobrien  [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
18795259563Spfg   (set (match_operand:SI 0 "register_operand" "=D")
1879690286Sobrien        (plus:SI (match_operand:SI 3 "register_operand" "0")
1879790286Sobrien		 (match_operand:SI 4 "register_operand" "1")))
1879890286Sobrien   (set (mem:BLK (match_dup 3))
1879990286Sobrien	(const_int 0))
1880090286Sobrien   (use (match_operand:QI 2 "register_operand" "a"))
1880190286Sobrien   (use (match_dup 4))
18802169699Skan   (use (reg:SI DIRFLAG_REG))]
1880390286Sobrien  "!TARGET_64BIT"
1880490286Sobrien  "{rep\;stosb|rep stosb}"
1880590286Sobrien  [(set_attr "type" "str")
1880690286Sobrien   (set_attr "prefix_rep" "1")
1880790286Sobrien   (set_attr "memory" "store")
1880890286Sobrien   (set_attr "mode" "QI")])
1880990286Sobrien
18810132727Skan(define_insn "*rep_stosqi_rex64"
1881190286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
18812259563Spfg   (set (match_operand:DI 0 "register_operand" "=D")
1881390286Sobrien        (plus:DI (match_operand:DI 3 "register_operand" "0")
1881490286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1881590286Sobrien   (set (mem:BLK (match_dup 3))
1881690286Sobrien	(const_int 0))
1881790286Sobrien   (use (match_operand:QI 2 "register_operand" "a"))
1881890286Sobrien   (use (match_dup 4))
18819169699Skan   (use (reg:SI DIRFLAG_REG))]
1882090286Sobrien  "TARGET_64BIT"
1882190286Sobrien  "{rep\;stosb|rep stosb}"
1882290286Sobrien  [(set_attr "type" "str")
1882390286Sobrien   (set_attr "prefix_rep" "1")
1882490286Sobrien   (set_attr "memory" "store")
1882590286Sobrien   (set_attr "mode" "QI")])
1882690286Sobrien
18827169699Skan(define_expand "cmpstrnsi"
1882850650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1882990286Sobrien	(compare:SI (match_operand:BLK 1 "general_operand" "")
1883090286Sobrien		    (match_operand:BLK 2 "general_operand" "")))
1883190286Sobrien   (use (match_operand 3 "general_operand" ""))
1883290286Sobrien   (use (match_operand 4 "immediate_operand" ""))]
18833132727Skan  "! optimize_size || TARGET_INLINE_ALL_STRINGOPS"
1883450650Sobrien{
1883590286Sobrien  rtx addr1, addr2, out, outlow, count, countreg, align;
1883650650Sobrien
18837132727Skan  /* Can't use this if the user has appropriated esi or edi.  */
18838132727Skan  if (global_regs[4] || global_regs[5])
18839132727Skan    FAIL;
18840132727Skan
1884190286Sobrien  out = operands[0];
1884290286Sobrien  if (GET_CODE (out) != REG)
1884390286Sobrien    out = gen_reg_rtx (SImode);
1884450650Sobrien
1884590286Sobrien  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1884690286Sobrien  addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
18847132727Skan  if (addr1 != XEXP (operands[1], 0))
18848132727Skan    operands[1] = replace_equiv_address_nv (operands[1], addr1);
18849132727Skan  if (addr2 != XEXP (operands[2], 0))
18850132727Skan    operands[2] = replace_equiv_address_nv (operands[2], addr2);
18851132727Skan
1885290286Sobrien  count = operands[3];
1885390286Sobrien  countreg = ix86_zero_extend_to_Pmode (count);
1885450650Sobrien
1885590286Sobrien  /* %%% Iff we are testing strict equality, we can use known alignment
1885690286Sobrien     to good advantage.  This may be possible with combine, particularly
1885790286Sobrien     once cc0 is dead.  */
1885890286Sobrien  align = operands[4];
1885950650Sobrien
1886090286Sobrien  emit_insn (gen_cld ());
1886190286Sobrien  if (GET_CODE (count) == CONST_INT)
1886290286Sobrien    {
1886390286Sobrien      if (INTVAL (count) == 0)
1886490286Sobrien	{
1886590286Sobrien	  emit_move_insn (operands[0], const0_rtx);
1886690286Sobrien	  DONE;
1886790286Sobrien	}
18868169699Skan      emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, countreg, align,
18869169699Skan				     operands[1], operands[2]));
1887090286Sobrien    }
1887190286Sobrien  else
1887290286Sobrien    {
1887390286Sobrien      if (TARGET_64BIT)
18874132727Skan	emit_insn (gen_cmpdi_1_rex64 (countreg, countreg));
1887590286Sobrien      else
18876132727Skan	emit_insn (gen_cmpsi_1 (countreg, countreg));
18877169699Skan      emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
18878169699Skan				  operands[1], operands[2]));
1887990286Sobrien    }
1888090286Sobrien
1888190286Sobrien  outlow = gen_lowpart (QImode, out);
1888290286Sobrien  emit_insn (gen_cmpintqi (outlow));
1888390286Sobrien  emit_move_insn (out, gen_rtx_SIGN_EXTEND (SImode, outlow));
1888490286Sobrien
1888590286Sobrien  if (operands[0] != out)
1888690286Sobrien    emit_move_insn (operands[0], out);
1888790286Sobrien
1888890286Sobrien  DONE;
1888990286Sobrien})
1889090286Sobrien
1889190286Sobrien;; Produce a tri-state integer (-1, 0, 1) from condition codes.
1889290286Sobrien
1889390286Sobrien(define_expand "cmpintqi"
1889490286Sobrien  [(set (match_dup 1)
18895169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1889690286Sobrien   (set (match_dup 2)
18897169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
1889890286Sobrien   (parallel [(set (match_operand:QI 0 "register_operand" "")
1889990286Sobrien		   (minus:QI (match_dup 1)
1890090286Sobrien			     (match_dup 2)))
18901169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1890290286Sobrien  ""
1890390286Sobrien  "operands[1] = gen_reg_rtx (QImode);
1890490286Sobrien   operands[2] = gen_reg_rtx (QImode);")
1890590286Sobrien
1890690286Sobrien;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
1890790286Sobrien;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
1890890286Sobrien
18909169699Skan(define_expand "cmpstrnqi_nz_1"
18910169699Skan  [(parallel [(set (reg:CC FLAGS_REG)
18911132727Skan		   (compare:CC (match_operand 4 "memory_operand" "")
18912132727Skan			       (match_operand 5 "memory_operand" "")))
18913132727Skan	      (use (match_operand 2 "register_operand" ""))
18914132727Skan	      (use (match_operand:SI 3 "immediate_operand" ""))
18915169699Skan	      (use (reg:SI DIRFLAG_REG))
18916132727Skan	      (clobber (match_operand 0 "register_operand" ""))
18917132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18918132727Skan	      (clobber (match_dup 2))])]
18919132727Skan  ""
18920132727Skan  "")
18921132727Skan
18922169699Skan(define_insn "*cmpstrnqi_nz_1"
18923169699Skan  [(set (reg:CC FLAGS_REG)
1892490286Sobrien	(compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
1892590286Sobrien		    (mem:BLK (match_operand:SI 5 "register_operand" "1"))))
1892690286Sobrien   (use (match_operand:SI 6 "register_operand" "2"))
1892790286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18928169699Skan   (use (reg:SI DIRFLAG_REG))
1892990286Sobrien   (clobber (match_operand:SI 0 "register_operand" "=S"))
1893090286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
1893190286Sobrien   (clobber (match_operand:SI 2 "register_operand" "=c"))]
1893290286Sobrien  "!TARGET_64BIT"
1893390286Sobrien  "repz{\;| }cmpsb"
1893490286Sobrien  [(set_attr "type" "str")
1893590286Sobrien   (set_attr "mode" "QI")
1893690286Sobrien   (set_attr "prefix_rep" "1")])
1893790286Sobrien
18938169699Skan(define_insn "*cmpstrnqi_nz_rex_1"
18939169699Skan  [(set (reg:CC FLAGS_REG)
1894090286Sobrien	(compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
1894190286Sobrien		    (mem:BLK (match_operand:DI 5 "register_operand" "1"))))
1894290286Sobrien   (use (match_operand:DI 6 "register_operand" "2"))
1894390286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18944169699Skan   (use (reg:SI DIRFLAG_REG))
1894590286Sobrien   (clobber (match_operand:DI 0 "register_operand" "=S"))
1894690286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
1894790286Sobrien   (clobber (match_operand:DI 2 "register_operand" "=c"))]
1894890286Sobrien  "TARGET_64BIT"
1894990286Sobrien  "repz{\;| }cmpsb"
1895090286Sobrien  [(set_attr "type" "str")
1895190286Sobrien   (set_attr "mode" "QI")
1895290286Sobrien   (set_attr "prefix_rep" "1")])
1895390286Sobrien
1895490286Sobrien;; The same, but the count is not known to not be zero.
1895590286Sobrien
18956169699Skan(define_expand "cmpstrnqi_1"
18957169699Skan  [(parallel [(set (reg:CC FLAGS_REG)
18958132727Skan		(if_then_else:CC (ne (match_operand 2 "register_operand" "")
18959132727Skan				     (const_int 0))
18960132727Skan		  (compare:CC (match_operand 4 "memory_operand" "")
18961132727Skan			      (match_operand 5 "memory_operand" ""))
18962132727Skan		  (const_int 0)))
18963132727Skan	      (use (match_operand:SI 3 "immediate_operand" ""))
18964169699Skan	      (use (reg:CC FLAGS_REG))
18965169699Skan	      (use (reg:SI DIRFLAG_REG))
18966132727Skan	      (clobber (match_operand 0 "register_operand" ""))
18967132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18968132727Skan	      (clobber (match_dup 2))])]
18969132727Skan  ""
18970132727Skan  "")
18971132727Skan
18972169699Skan(define_insn "*cmpstrnqi_1"
18973169699Skan  [(set (reg:CC FLAGS_REG)
1897490286Sobrien	(if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
1897590286Sobrien			     (const_int 0))
1897690286Sobrien	  (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
1897790286Sobrien		      (mem:BLK (match_operand:SI 5 "register_operand" "1")))
1897890286Sobrien	  (const_int 0)))
1897990286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18980169699Skan   (use (reg:CC FLAGS_REG))
18981169699Skan   (use (reg:SI DIRFLAG_REG))
1898290286Sobrien   (clobber (match_operand:SI 0 "register_operand" "=S"))
1898390286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
1898490286Sobrien   (clobber (match_operand:SI 2 "register_operand" "=c"))]
1898590286Sobrien  "!TARGET_64BIT"
1898690286Sobrien  "repz{\;| }cmpsb"
1898790286Sobrien  [(set_attr "type" "str")
1898890286Sobrien   (set_attr "mode" "QI")
1898990286Sobrien   (set_attr "prefix_rep" "1")])
1899090286Sobrien
18991169699Skan(define_insn "*cmpstrnqi_rex_1"
18992169699Skan  [(set (reg:CC FLAGS_REG)
1899390286Sobrien	(if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2")
1899490286Sobrien			     (const_int 0))
1899590286Sobrien	  (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
1899690286Sobrien		      (mem:BLK (match_operand:DI 5 "register_operand" "1")))
1899790286Sobrien	  (const_int 0)))
1899890286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18999169699Skan   (use (reg:CC FLAGS_REG))
19000169699Skan   (use (reg:SI DIRFLAG_REG))
1900190286Sobrien   (clobber (match_operand:DI 0 "register_operand" "=S"))
1900290286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
1900390286Sobrien   (clobber (match_operand:DI 2 "register_operand" "=c"))]
1900490286Sobrien  "TARGET_64BIT"
1900590286Sobrien  "repz{\;| }cmpsb"
1900690286Sobrien  [(set_attr "type" "str")
1900790286Sobrien   (set_attr "mode" "QI")
1900890286Sobrien   (set_attr "prefix_rep" "1")])
1900990286Sobrien
1901090286Sobrien(define_expand "strlensi"
1901152296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1901290286Sobrien	(unspec:SI [(match_operand:BLK 1 "general_operand" "")
1901390286Sobrien		    (match_operand:QI 2 "immediate_operand" "")
19014117404Skan		    (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
1901590286Sobrien  ""
1901690286Sobrien{
1901790286Sobrien if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
1901890286Sobrien   DONE;
1901990286Sobrien else
1902090286Sobrien   FAIL;
1902190286Sobrien})
1902290286Sobrien
1902390286Sobrien(define_expand "strlendi"
1902490286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1902590286Sobrien	(unspec:DI [(match_operand:BLK 1 "general_operand" "")
1902690286Sobrien		    (match_operand:QI 2 "immediate_operand" "")
19027117404Skan		    (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
1902890286Sobrien  ""
1902990286Sobrien{
1903090286Sobrien if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
1903190286Sobrien   DONE;
1903290286Sobrien else
1903390286Sobrien   FAIL;
1903490286Sobrien})
1903590286Sobrien
19036132727Skan(define_expand "strlenqi_1"
19037132727Skan  [(parallel [(set (match_operand 0 "register_operand" "") (match_operand 2 "" ""))
19038169699Skan	      (use (reg:SI DIRFLAG_REG))
19039132727Skan	      (clobber (match_operand 1 "register_operand" ""))
19040169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19041132727Skan  ""
19042132727Skan  "")
19043132727Skan
19044132727Skan(define_insn "*strlenqi_1"
1904590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=&c")
1904690286Sobrien	(unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1"))
1904790286Sobrien		    (match_operand:QI 2 "register_operand" "a")
1904890286Sobrien		    (match_operand:SI 3 "immediate_operand" "i")
19049117404Skan		    (match_operand:SI 4 "register_operand" "0")] UNSPEC_SCAS))
19050169699Skan   (use (reg:SI DIRFLAG_REG))
1905190286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
19052169699Skan   (clobber (reg:CC FLAGS_REG))]
1905390286Sobrien  "!TARGET_64BIT"
1905490286Sobrien  "repnz{\;| }scasb"
1905590286Sobrien  [(set_attr "type" "str")
1905690286Sobrien   (set_attr "mode" "QI")
1905790286Sobrien   (set_attr "prefix_rep" "1")])
1905890286Sobrien
19059132727Skan(define_insn "*strlenqi_rex_1"
1906090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=&c")
1906190286Sobrien	(unspec:DI [(mem:BLK (match_operand:DI 5 "register_operand" "1"))
1906290286Sobrien		    (match_operand:QI 2 "register_operand" "a")
1906390286Sobrien		    (match_operand:DI 3 "immediate_operand" "i")
19064117404Skan		    (match_operand:DI 4 "register_operand" "0")] UNSPEC_SCAS))
19065169699Skan   (use (reg:SI DIRFLAG_REG))
1906690286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
19067169699Skan   (clobber (reg:CC FLAGS_REG))]
1906890286Sobrien  "TARGET_64BIT"
1906990286Sobrien  "repnz{\;| }scasb"
1907090286Sobrien  [(set_attr "type" "str")
1907190286Sobrien   (set_attr "mode" "QI")
1907290286Sobrien   (set_attr "prefix_rep" "1")])
1907390286Sobrien
19074169699Skan;; Peephole optimizations to clean up after cmpstrn*.  This should be
1907590286Sobrien;; handled in combine, but it is not currently up to the task.
19076169699Skan;; When used for their truth value, the cmpstrn* expanders generate
1907790286Sobrien;; code like this:
1907890286Sobrien;;
1907990286Sobrien;;   repz cmpsb
1908090286Sobrien;;   seta 	%al
1908190286Sobrien;;   setb 	%dl
1908290286Sobrien;;   cmpb 	%al, %dl
1908390286Sobrien;;   jcc	label
1908490286Sobrien;;
1908590286Sobrien;; The intermediate three instructions are unnecessary.
1908690286Sobrien
19087169699Skan;; This one handles cmpstrn*_nz_1...
1908890286Sobrien(define_peephole2
1908990286Sobrien  [(parallel[
19090169699Skan     (set (reg:CC FLAGS_REG)
1909190286Sobrien	  (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
1909290286Sobrien		      (mem:BLK (match_operand 5 "register_operand" ""))))
1909390286Sobrien     (use (match_operand 6 "register_operand" ""))
1909490286Sobrien     (use (match_operand:SI 3 "immediate_operand" ""))
19095169699Skan     (use (reg:SI DIRFLAG_REG))
1909690286Sobrien     (clobber (match_operand 0 "register_operand" ""))
1909790286Sobrien     (clobber (match_operand 1 "register_operand" ""))
1909890286Sobrien     (clobber (match_operand 2 "register_operand" ""))])
1909990286Sobrien   (set (match_operand:QI 7 "register_operand" "")
19100169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1910190286Sobrien   (set (match_operand:QI 8 "register_operand" "")
19102169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
19103169699Skan   (set (reg FLAGS_REG)
1910490286Sobrien	(compare (match_dup 7) (match_dup 8)))
1910590286Sobrien  ]
1910690286Sobrien  "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
1910790286Sobrien  [(parallel[
19108169699Skan     (set (reg:CC FLAGS_REG)
1910990286Sobrien	  (compare:CC (mem:BLK (match_dup 4))
1911090286Sobrien		      (mem:BLK (match_dup 5))))
1911190286Sobrien     (use (match_dup 6))
1911290286Sobrien     (use (match_dup 3))
19113169699Skan     (use (reg:SI DIRFLAG_REG))
1911490286Sobrien     (clobber (match_dup 0))
1911590286Sobrien     (clobber (match_dup 1))
1911690286Sobrien     (clobber (match_dup 2))])]
1911750650Sobrien  "")
1911850650Sobrien
19119169699Skan;; ...and this one handles cmpstrn*_1.
1912090286Sobrien(define_peephole2
1912190286Sobrien  [(parallel[
19122169699Skan     (set (reg:CC FLAGS_REG)
1912390286Sobrien	  (if_then_else:CC (ne (match_operand 6 "register_operand" "")
1912490286Sobrien			       (const_int 0))
1912590286Sobrien	    (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
1912690286Sobrien		        (mem:BLK (match_operand 5 "register_operand" "")))
1912790286Sobrien	    (const_int 0)))
1912890286Sobrien     (use (match_operand:SI 3 "immediate_operand" ""))
19129169699Skan     (use (reg:CC FLAGS_REG))
19130169699Skan     (use (reg:SI DIRFLAG_REG))
1913190286Sobrien     (clobber (match_operand 0 "register_operand" ""))
1913290286Sobrien     (clobber (match_operand 1 "register_operand" ""))
1913390286Sobrien     (clobber (match_operand 2 "register_operand" ""))])
1913490286Sobrien   (set (match_operand:QI 7 "register_operand" "")
19135169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1913690286Sobrien   (set (match_operand:QI 8 "register_operand" "")
19137169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
19138169699Skan   (set (reg FLAGS_REG)
1913990286Sobrien	(compare (match_dup 7) (match_dup 8)))
1914090286Sobrien  ]
1914190286Sobrien  "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
1914290286Sobrien  [(parallel[
19143169699Skan     (set (reg:CC FLAGS_REG)
1914490286Sobrien	  (if_then_else:CC (ne (match_dup 6)
1914590286Sobrien			       (const_int 0))
1914690286Sobrien	    (compare:CC (mem:BLK (match_dup 4))
1914790286Sobrien			(mem:BLK (match_dup 5)))
1914890286Sobrien	    (const_int 0)))
1914990286Sobrien     (use (match_dup 3))
19150169699Skan     (use (reg:CC FLAGS_REG))
19151169699Skan     (use (reg:SI DIRFLAG_REG))
1915290286Sobrien     (clobber (match_dup 0))
1915390286Sobrien     (clobber (match_dup 1))
1915490286Sobrien     (clobber (match_dup 2))])]
1915550650Sobrien  "")
1915650650Sobrien
1915790286Sobrien
1915890286Sobrien
1915990286Sobrien;; Conditional move instructions.
1916090286Sobrien
1916190286Sobrien(define_expand "movdicc"
1916290286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1916390286Sobrien	(if_then_else:DI (match_operand 1 "comparison_operator" "")
1916490286Sobrien			 (match_operand:DI 2 "general_operand" "")
1916590286Sobrien			 (match_operand:DI 3 "general_operand" "")))]
1916690286Sobrien  "TARGET_64BIT"
1916790286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1916890286Sobrien
1916990286Sobrien(define_insn "x86_movdicc_0_m1_rex64"
1917090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
19171132727Skan	(if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "")
1917290286Sobrien	  (const_int -1)
1917390286Sobrien	  (const_int 0)))
19174169699Skan   (clobber (reg:CC FLAGS_REG))]
1917590286Sobrien  "TARGET_64BIT"
1917690286Sobrien  "sbb{q}\t%0, %0"
1917790286Sobrien  ; Since we don't have the proper number of operands for an alu insn,
1917890286Sobrien  ; fill in all the blanks.
1917990286Sobrien  [(set_attr "type" "alu")
19180117404Skan   (set_attr "pent_pair" "pu")
1918190286Sobrien   (set_attr "memory" "none")
1918290286Sobrien   (set_attr "imm_disp" "false")
1918390286Sobrien   (set_attr "mode" "DI")
1918490286Sobrien   (set_attr "length_immediate" "0")])
1918590286Sobrien
19186169699Skan(define_insn "*movdicc_c_rex64"
1918790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
19188259563Spfg	(if_then_else:DI (match_operator 1 "ix86_comparison_operator"
19189169699Skan				[(reg FLAGS_REG) (const_int 0)])
1919090286Sobrien		      (match_operand:DI 2 "nonimmediate_operand" "rm,0")
1919190286Sobrien		      (match_operand:DI 3 "nonimmediate_operand" "0,rm")))]
1919290286Sobrien  "TARGET_64BIT && TARGET_CMOVE
1919390286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1919490286Sobrien  "@
1919596294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1919696294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1919790286Sobrien  [(set_attr "type" "icmov")
1919890286Sobrien   (set_attr "mode" "DI")])
1919990286Sobrien
1920090286Sobrien(define_expand "movsicc"
1920190286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1920290286Sobrien	(if_then_else:SI (match_operand 1 "comparison_operator" "")
1920390286Sobrien			 (match_operand:SI 2 "general_operand" "")
1920490286Sobrien			 (match_operand:SI 3 "general_operand" "")))]
1920590286Sobrien  ""
1920690286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1920790286Sobrien
1920890286Sobrien;; Data flow gets confused by our desire for `sbbl reg,reg', and clearing
1920990286Sobrien;; the register first winds up with `sbbl $0,reg', which is also weird.
1921090286Sobrien;; So just document what we're doing explicitly.
1921190286Sobrien
1921290286Sobrien(define_insn "x86_movsicc_0_m1"
1921390286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
19214132727Skan	(if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "")
1921590286Sobrien	  (const_int -1)
1921690286Sobrien	  (const_int 0)))
19217169699Skan   (clobber (reg:CC FLAGS_REG))]
1921890286Sobrien  ""
1921990286Sobrien  "sbb{l}\t%0, %0"
1922090286Sobrien  ; Since we don't have the proper number of operands for an alu insn,
1922190286Sobrien  ; fill in all the blanks.
1922290286Sobrien  [(set_attr "type" "alu")
19223117404Skan   (set_attr "pent_pair" "pu")
1922490286Sobrien   (set_attr "memory" "none")
1922590286Sobrien   (set_attr "imm_disp" "false")
1922690286Sobrien   (set_attr "mode" "SI")
1922790286Sobrien   (set_attr "length_immediate" "0")])
1922890286Sobrien
1922990286Sobrien(define_insn "*movsicc_noc"
1923050650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
19231259563Spfg	(if_then_else:SI (match_operator 1 "ix86_comparison_operator"
19232169699Skan				[(reg FLAGS_REG) (const_int 0)])
1923350650Sobrien		      (match_operand:SI 2 "nonimmediate_operand" "rm,0")
1923450650Sobrien		      (match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
1923590286Sobrien  "TARGET_CMOVE
1923690286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1923790286Sobrien  "@
1923896294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1923996294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1924090286Sobrien  [(set_attr "type" "icmov")
1924190286Sobrien   (set_attr "mode" "SI")])
1924250650Sobrien
1924350650Sobrien(define_expand "movhicc"
1924450650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
1924550650Sobrien	(if_then_else:HI (match_operand 1 "comparison_operator" "")
19246132727Skan			 (match_operand:HI 2 "general_operand" "")
19247132727Skan			 (match_operand:HI 3 "general_operand" "")))]
19248132727Skan  "TARGET_HIMODE_MATH"
1924990286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1925050650Sobrien
1925190286Sobrien(define_insn "*movhicc_noc"
1925250650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
19253259563Spfg	(if_then_else:HI (match_operator 1 "ix86_comparison_operator"
19254169699Skan				[(reg FLAGS_REG) (const_int 0)])
1925550650Sobrien		      (match_operand:HI 2 "nonimmediate_operand" "rm,0")
1925650650Sobrien		      (match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
1925790286Sobrien  "TARGET_CMOVE
1925890286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1925990286Sobrien  "@
1926096294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1926196294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1926290286Sobrien  [(set_attr "type" "icmov")
1926390286Sobrien   (set_attr "mode" "HI")])
1926450650Sobrien
19265132727Skan(define_expand "movqicc"
19266132727Skan  [(set (match_operand:QI 0 "register_operand" "")
19267132727Skan	(if_then_else:QI (match_operand 1 "comparison_operator" "")
19268132727Skan			 (match_operand:QI 2 "general_operand" "")
19269132727Skan			 (match_operand:QI 3 "general_operand" "")))]
19270132727Skan  "TARGET_QIMODE_MATH"
19271132727Skan  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
19272132727Skan
19273132727Skan(define_insn_and_split "*movqicc_noc"
19274132727Skan  [(set (match_operand:QI 0 "register_operand" "=r,r")
19275259563Spfg	(if_then_else:QI (match_operator 1 "ix86_comparison_operator"
19276169699Skan				[(match_operand 4 "flags_reg_operand" "")
19277169699Skan				 (const_int 0)])
19278132727Skan		      (match_operand:QI 2 "register_operand" "r,0")
19279132727Skan		      (match_operand:QI 3 "register_operand" "0,r")))]
19280132727Skan  "TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL"
19281132727Skan  "#"
19282132727Skan  "&& reload_completed"
19283132727Skan  [(set (match_dup 0)
19284132727Skan	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
19285132727Skan		      (match_dup 2)
19286132727Skan		      (match_dup 3)))]
19287132727Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
19288132727Skan   operands[2] = gen_lowpart (SImode, operands[2]);
19289132727Skan   operands[3] = gen_lowpart (SImode, operands[3]);"
19290132727Skan  [(set_attr "type" "icmov")
19291132727Skan   (set_attr "mode" "SI")])
19292132727Skan
1929350650Sobrien(define_expand "movsfcc"
1929450650Sobrien  [(set (match_operand:SF 0 "register_operand" "")
1929550650Sobrien	(if_then_else:SF (match_operand 1 "comparison_operator" "")
1929650650Sobrien			 (match_operand:SF 2 "register_operand" "")
1929750650Sobrien			 (match_operand:SF 3 "register_operand" "")))]
19298169699Skan  "(TARGET_80387 && TARGET_CMOVE) || TARGET_SSE_MATH"
1929990286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1930050650Sobrien
19301169699Skan(define_insn "*movsfcc_1_387"
19302169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f,r,r")
19303259563Spfg	(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
19304169699Skan				[(reg FLAGS_REG) (const_int 0)])
19305169699Skan		      (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0")
19306169699Skan		      (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))]
19307169699Skan  "TARGET_80387 && TARGET_CMOVE
1930890286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1930990286Sobrien  "@
1931090286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1931190286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1931296294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1931396294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1931490286Sobrien  [(set_attr "type" "fcmov,fcmov,icmov,icmov")
1931590286Sobrien   (set_attr "mode" "SF,SF,SI,SI")])
1931650650Sobrien
1931790286Sobrien(define_expand "movdfcc"
1931890286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
1931990286Sobrien	(if_then_else:DF (match_operand 1 "comparison_operator" "")
1932090286Sobrien			 (match_operand:DF 2 "register_operand" "")
1932190286Sobrien			 (match_operand:DF 3 "register_operand" "")))]
19322169699Skan  "(TARGET_80387 && TARGET_CMOVE) || (TARGET_SSE2 && TARGET_SSE_MATH)"
1932390286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1932450650Sobrien
1932590286Sobrien(define_insn "*movdfcc_1"
19326169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r")
19327259563Spfg	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
19328169699Skan				[(reg FLAGS_REG) (const_int 0)])
19329169699Skan		      (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
19330169699Skan		      (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
19331169699Skan  "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
1933290286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1933390286Sobrien  "@
1933490286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1933590286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1933690286Sobrien   #
1933790286Sobrien   #"
1933890286Sobrien  [(set_attr "type" "fcmov,fcmov,multi,multi")
1933990286Sobrien   (set_attr "mode" "DF")])
1934050650Sobrien
1934190286Sobrien(define_insn "*movdfcc_1_rex64"
19342169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,r,r")
19343259563Spfg	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
19344169699Skan				[(reg FLAGS_REG) (const_int 0)])
19345169699Skan		      (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
19346169699Skan		      (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
19347169699Skan  "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
1934890286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1934990286Sobrien  "@
1935090286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1935190286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1935296294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1935396294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1935490286Sobrien  [(set_attr "type" "fcmov,fcmov,icmov,icmov")
1935590286Sobrien   (set_attr "mode" "DF")])
1935650650Sobrien
1935790286Sobrien(define_split
19358117404Skan  [(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "")
19359259563Spfg	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
19360169699Skan				[(match_operand 4 "flags_reg_operand" "")
19361169699Skan				 (const_int 0)])
1936290286Sobrien		      (match_operand:DF 2 "nonimmediate_operand" "")
1936390286Sobrien		      (match_operand:DF 3 "nonimmediate_operand" "")))]
19364117404Skan  "!TARGET_64BIT && reload_completed"
1936590286Sobrien  [(set (match_dup 2)
1936690286Sobrien	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
1936790286Sobrien		      (match_dup 5)
1936890286Sobrien		      (match_dup 7)))
1936990286Sobrien   (set (match_dup 3)
1937090286Sobrien	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
1937190286Sobrien		      (match_dup 6)
1937290286Sobrien		      (match_dup 8)))]
1937390286Sobrien  "split_di (operands+2, 1, operands+5, operands+6);
1937490286Sobrien   split_di (operands+3, 1, operands+7, operands+8);
1937590286Sobrien   split_di (operands, 1, operands+2, operands+3);")
1937650650Sobrien
1937790286Sobrien(define_expand "movxfcc"
1937890286Sobrien  [(set (match_operand:XF 0 "register_operand" "")
1937990286Sobrien	(if_then_else:XF (match_operand 1 "comparison_operator" "")
1938090286Sobrien			 (match_operand:XF 2 "register_operand" "")
1938190286Sobrien			 (match_operand:XF 3 "register_operand" "")))]
19382169699Skan  "TARGET_80387 && TARGET_CMOVE"
1938390286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1938490286Sobrien
1938590286Sobrien(define_insn "*movxfcc_1"
1938690286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
19387259563Spfg	(if_then_else:XF (match_operator 1 "fcmov_comparison_operator"
19388169699Skan				[(reg FLAGS_REG) (const_int 0)])
1938990286Sobrien		      (match_operand:XF 2 "register_operand" "f,0")
1939090286Sobrien		      (match_operand:XF 3 "register_operand" "0,f")))]
19391169699Skan  "TARGET_80387 && TARGET_CMOVE"
1939290286Sobrien  "@
1939390286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1939490286Sobrien   fcmov%f1\t{%3, %0|%0, %3}"
1939590286Sobrien  [(set_attr "type" "fcmov")
1939690286Sobrien   (set_attr "mode" "XF")])
1939790286Sobrien
19398169699Skan;; These versions of the min/max patterns are intentionally ignorant of
19399169699Skan;; their behavior wrt -0.0 and NaN (via the commutative operand mark).
19400169699Skan;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
19401169699Skan;; are undefined in this condition, we're certain this is correct.
1940290286Sobrien
19403169699Skan(define_insn "sminsf3"
19404169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19405169699Skan	(smin:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
19406169699Skan		 (match_operand:SF 2 "nonimmediate_operand" "xm")))]
19407169699Skan  "TARGET_SSE_MATH"
19408169699Skan  "minss\t{%2, %0|%0, %2}"
19409169699Skan  [(set_attr "type" "sseadd")
19410169699Skan   (set_attr "mode" "SF")])
1941150650Sobrien
19412169699Skan(define_insn "smaxsf3"
19413169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19414169699Skan	(smax:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
19415169699Skan		 (match_operand:SF 2 "nonimmediate_operand" "xm")))]
19416169699Skan  "TARGET_SSE_MATH"
19417169699Skan  "maxss\t{%2, %0|%0, %2}"
19418169699Skan  [(set_attr "type" "sseadd")
19419169699Skan   (set_attr "mode" "SF")])
1942050650Sobrien
19421169699Skan(define_insn "smindf3"
19422169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19423169699Skan	(smin:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
19424169699Skan		 (match_operand:DF 2 "nonimmediate_operand" "xm")))]
19425169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19426169699Skan  "minsd\t{%2, %0|%0, %2}"
19427169699Skan  [(set_attr "type" "sseadd")
19428169699Skan   (set_attr "mode" "DF")])
1942950650Sobrien
19430169699Skan(define_insn "smaxdf3"
19431169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19432169699Skan	(smax:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
19433169699Skan		 (match_operand:DF 2 "nonimmediate_operand" "xm")))]
19434169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19435169699Skan  "maxsd\t{%2, %0|%0, %2}"
19436169699Skan  [(set_attr "type" "sseadd")
19437169699Skan   (set_attr "mode" "DF")])
19438169699Skan
19439169699Skan;; These versions of the min/max patterns implement exactly the operations
19440169699Skan;;   min = (op1 < op2 ? op1 : op2)
19441169699Skan;;   max = (!(op1 < op2) ? op1 : op2)
19442169699Skan;; Their operands are not commutative, and thus they may be used in the
19443169699Skan;; presence of -0.0 and NaN.
19444169699Skan
19445169699Skan(define_insn "*ieee_sminsf3"
19446169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19447169699Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")
19448169699Skan		    (match_operand:SF 2 "nonimmediate_operand" "xm")]
19449169699Skan		   UNSPEC_IEEE_MIN))]
19450169699Skan  "TARGET_SSE_MATH"
19451169699Skan  "minss\t{%2, %0|%0, %2}"
19452169699Skan  [(set_attr "type" "sseadd")
19453169699Skan   (set_attr "mode" "SF")])
19454169699Skan
19455169699Skan(define_insn "*ieee_smaxsf3"
19456169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19457169699Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")
19458169699Skan		    (match_operand:SF 2 "nonimmediate_operand" "xm")]
19459169699Skan		   UNSPEC_IEEE_MAX))]
19460169699Skan  "TARGET_SSE_MATH"
19461169699Skan  "maxss\t{%2, %0|%0, %2}"
19462169699Skan  [(set_attr "type" "sseadd")
19463169699Skan   (set_attr "mode" "SF")])
19464169699Skan
19465169699Skan(define_insn "*ieee_smindf3"
19466169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19467169699Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")
19468169699Skan		    (match_operand:DF 2 "nonimmediate_operand" "xm")]
19469169699Skan		   UNSPEC_IEEE_MIN))]
19470169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19471169699Skan  "minsd\t{%2, %0|%0, %2}"
19472169699Skan  [(set_attr "type" "sseadd")
19473169699Skan   (set_attr "mode" "DF")])
19474169699Skan
19475169699Skan(define_insn "*ieee_smaxdf3"
19476169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19477169699Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")
19478169699Skan		    (match_operand:DF 2 "nonimmediate_operand" "xm")]
19479169699Skan		   UNSPEC_IEEE_MAX))]
19480169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19481169699Skan  "maxsd\t{%2, %0|%0, %2}"
19482169699Skan  [(set_attr "type" "sseadd")
19483169699Skan   (set_attr "mode" "DF")])
19484169699Skan
19485169699Skan;; Make two stack loads independent:
19486169699Skan;;   fld aa              fld aa
19487169699Skan;;   fld %st(0)     ->   fld bb
19488169699Skan;;   fmul bb             fmul %st(1), %st
19489169699Skan;;
19490169699Skan;; Actually we only match the last two instructions for simplicity.
19491169699Skan(define_peephole2
19492169699Skan  [(set (match_operand 0 "fp_register_operand" "")
19493169699Skan	(match_operand 1 "fp_register_operand" ""))
19494169699Skan   (set (match_dup 0)
19495169699Skan	(match_operator 2 "binary_fp_operator"
19496169699Skan	   [(match_dup 0)
19497169699Skan	    (match_operand 3 "memory_operand" "")]))]
19498169699Skan  "REGNO (operands[0]) != REGNO (operands[1])"
19499169699Skan  [(set (match_dup 0) (match_dup 3))
19500169699Skan   (set (match_dup 0) (match_dup 4))]
19501169699Skan
19502169699Skan  ;; The % modifier is not operational anymore in peephole2's, so we have to
19503169699Skan  ;; swap the operands manually in the case of addition and multiplication.
19504169699Skan  "if (COMMUTATIVE_ARITH_P (operands[2]))
19505169699Skan     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
19506169699Skan				 operands[0], operands[1]);
19507169699Skan   else
19508169699Skan     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
19509169699Skan				 operands[1], operands[0]);")
19510169699Skan
19511132727Skan;; Conditional addition patterns
19512132727Skan(define_expand "addqicc"
19513132727Skan  [(match_operand:QI 0 "register_operand" "")
19514132727Skan   (match_operand 1 "comparison_operator" "")
19515132727Skan   (match_operand:QI 2 "register_operand" "")
19516132727Skan   (match_operand:QI 3 "const_int_operand" "")]
19517132727Skan  ""
19518132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19519132727Skan
19520132727Skan(define_expand "addhicc"
19521132727Skan  [(match_operand:HI 0 "register_operand" "")
19522132727Skan   (match_operand 1 "comparison_operator" "")
19523132727Skan   (match_operand:HI 2 "register_operand" "")
19524132727Skan   (match_operand:HI 3 "const_int_operand" "")]
19525132727Skan  ""
19526132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19527132727Skan
19528132727Skan(define_expand "addsicc"
19529132727Skan  [(match_operand:SI 0 "register_operand" "")
19530132727Skan   (match_operand 1 "comparison_operator" "")
19531132727Skan   (match_operand:SI 2 "register_operand" "")
19532132727Skan   (match_operand:SI 3 "const_int_operand" "")]
19533132727Skan  ""
19534132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19535132727Skan
19536132727Skan(define_expand "adddicc"
19537132727Skan  [(match_operand:DI 0 "register_operand" "")
19538132727Skan   (match_operand 1 "comparison_operator" "")
19539132727Skan   (match_operand:DI 2 "register_operand" "")
19540132727Skan   (match_operand:DI 3 "const_int_operand" "")]
19541132727Skan  "TARGET_64BIT"
19542132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19543132727Skan
1954490286Sobrien
1954590286Sobrien;; Misc patterns (?)
1954650650Sobrien
1954790286Sobrien;; This pattern exists to put a dependency on all ebp-based memory accesses.
1954890286Sobrien;; Otherwise there will be nothing to keep
19549259563Spfg;;
1955090286Sobrien;; [(set (reg ebp) (reg esp))]
1955190286Sobrien;; [(set (reg esp) (plus (reg esp) (const_int -160000)))
1955290286Sobrien;;  (clobber (eflags)]
1955390286Sobrien;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))]
1955490286Sobrien;;
1955590286Sobrien;; in proper program order.
19556132727Skan(define_insn "pro_epilogue_adjust_stack_1"
1955790286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
1955890286Sobrien	(plus:SI (match_operand:SI 1 "register_operand" "0,r")
1955990286Sobrien	         (match_operand:SI 2 "immediate_operand" "i,i")))
19560169699Skan   (clobber (reg:CC FLAGS_REG))
1956190286Sobrien   (clobber (mem:BLK (scratch)))]
1956290286Sobrien  "!TARGET_64BIT"
1956390286Sobrien{
1956490286Sobrien  switch (get_attr_type (insn))
1956590286Sobrien    {
1956690286Sobrien    case TYPE_IMOV:
1956790286Sobrien      return "mov{l}\t{%1, %0|%0, %1}";
1956850650Sobrien
1956990286Sobrien    case TYPE_ALU:
1957090286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
1957190286Sobrien          && (INTVAL (operands[2]) == 128
1957290286Sobrien	      || (INTVAL (operands[2]) < 0
1957390286Sobrien	          && INTVAL (operands[2]) != -128)))
1957490286Sobrien	{
1957590286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
1957690286Sobrien	  return "sub{l}\t{%2, %0|%0, %2}";
1957790286Sobrien	}
1957890286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
1957950650Sobrien
1958090286Sobrien    case TYPE_LEA:
1958190286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
1958290286Sobrien      return "lea{l}\t{%a2, %0|%0, %a2}";
1958390286Sobrien
1958490286Sobrien    default:
19585169699Skan      gcc_unreachable ();
1958690286Sobrien    }
1958790286Sobrien}
1958890286Sobrien  [(set (attr "type")
1958990286Sobrien	(cond [(eq_attr "alternative" "0")
1959090286Sobrien		 (const_string "alu")
1959190286Sobrien	       (match_operand:SI 2 "const0_operand" "")
1959290286Sobrien		 (const_string "imov")
1959390286Sobrien	      ]
1959490286Sobrien	      (const_string "lea")))
1959590286Sobrien   (set_attr "mode" "SI")])
1959690286Sobrien
1959790286Sobrien(define_insn "pro_epilogue_adjust_stack_rex64"
1959890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1959990286Sobrien	(plus:DI (match_operand:DI 1 "register_operand" "0,r")
1960090286Sobrien		 (match_operand:DI 2 "x86_64_immediate_operand" "e,e")))
19601169699Skan   (clobber (reg:CC FLAGS_REG))
1960290286Sobrien   (clobber (mem:BLK (scratch)))]
1960390286Sobrien  "TARGET_64BIT"
1960490286Sobrien{
1960590286Sobrien  switch (get_attr_type (insn))
1960650650Sobrien    {
1960790286Sobrien    case TYPE_IMOV:
1960890286Sobrien      return "mov{q}\t{%1, %0|%0, %1}";
1960950650Sobrien
1961090286Sobrien    case TYPE_ALU:
1961190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
19612132727Skan	  /* Avoid overflows.  */
19613132727Skan	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
1961490286Sobrien          && (INTVAL (operands[2]) == 128
1961590286Sobrien	      || (INTVAL (operands[2]) < 0
1961690286Sobrien	          && INTVAL (operands[2]) != -128)))
1961790286Sobrien	{
1961890286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
1961990286Sobrien	  return "sub{q}\t{%2, %0|%0, %2}";
1962090286Sobrien	}
1962190286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
1962250650Sobrien
1962390286Sobrien    case TYPE_LEA:
1962490286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
1962590286Sobrien      return "lea{q}\t{%a2, %0|%0, %a2}";
1962650650Sobrien
1962750650Sobrien    default:
19628169699Skan      gcc_unreachable ();
1962950650Sobrien    }
1963090286Sobrien}
1963190286Sobrien  [(set (attr "type")
1963290286Sobrien	(cond [(eq_attr "alternative" "0")
1963390286Sobrien		 (const_string "alu")
1963490286Sobrien	       (match_operand:DI 2 "const0_operand" "")
1963590286Sobrien		 (const_string "imov")
1963690286Sobrien	      ]
1963790286Sobrien	      (const_string "lea")))
1963890286Sobrien   (set_attr "mode" "DI")])
1963950650Sobrien
19640132727Skan(define_insn "pro_epilogue_adjust_stack_rex64_2"
19641132727Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
19642132727Skan	(plus:DI (match_operand:DI 1 "register_operand" "0,r")
19643132727Skan		 (match_operand:DI 3 "immediate_operand" "i,i")))
19644132727Skan   (use (match_operand:DI 2 "register_operand" "r,r"))
19645169699Skan   (clobber (reg:CC FLAGS_REG))
19646132727Skan   (clobber (mem:BLK (scratch)))]
19647132727Skan  "TARGET_64BIT"
19648132727Skan{
19649132727Skan  switch (get_attr_type (insn))
19650132727Skan    {
19651132727Skan    case TYPE_ALU:
19652132727Skan      return "add{q}\t{%2, %0|%0, %2}";
1965390286Sobrien
19654132727Skan    case TYPE_LEA:
19655132727Skan      operands[2] = gen_rtx_PLUS (DImode, operands[1], operands[2]);
19656132727Skan      return "lea{q}\t{%a2, %0|%0, %a2}";
19657132727Skan
19658132727Skan    default:
19659169699Skan      gcc_unreachable ();
19660132727Skan    }
19661132727Skan}
19662132727Skan  [(set_attr "type" "alu,lea")
19663132727Skan   (set_attr "mode" "DI")])
19664132727Skan
1966590286Sobrien(define_expand "allocate_stack_worker"
1966690286Sobrien  [(match_operand:SI 0 "register_operand" "")]
1966790286Sobrien  "TARGET_STACK_PROBE"
1966890286Sobrien{
19669132727Skan  if (reload_completed)
19670132727Skan    {
19671132727Skan      if (TARGET_64BIT)
19672132727Skan	emit_insn (gen_allocate_stack_worker_rex64_postreload (operands[0]));
19673132727Skan      else
19674132727Skan	emit_insn (gen_allocate_stack_worker_postreload (operands[0]));
19675132727Skan    }
1967690286Sobrien  else
19677132727Skan    {
19678132727Skan      if (TARGET_64BIT)
19679132727Skan	emit_insn (gen_allocate_stack_worker_rex64 (operands[0]));
19680132727Skan      else
19681132727Skan	emit_insn (gen_allocate_stack_worker_1 (operands[0]));
19682132727Skan    }
1968390286Sobrien  DONE;
1968490286Sobrien})
1968550650Sobrien
1968690286Sobrien(define_insn "allocate_stack_worker_1"
19687132727Skan  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
19688132727Skan    UNSPECV_STACK_PROBE)
19689169699Skan   (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
19690132727Skan   (clobber (match_scratch:SI 1 "=0"))
19691169699Skan   (clobber (reg:CC FLAGS_REG))]
1969290286Sobrien  "!TARGET_64BIT && TARGET_STACK_PROBE"
1969390286Sobrien  "call\t__alloca"
1969490286Sobrien  [(set_attr "type" "multi")
1969590286Sobrien   (set_attr "length" "5")])
1969650650Sobrien
19697132727Skan(define_expand "allocate_stack_worker_postreload"
19698132727Skan  [(parallel [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
19699132727Skan				    UNSPECV_STACK_PROBE)
19700169699Skan	      (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
19701132727Skan	      (clobber (match_dup 0))
19702169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19703132727Skan  ""
19704132727Skan  "")
19705132727Skan
1970690286Sobrien(define_insn "allocate_stack_worker_rex64"
19707132727Skan  [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
19708132727Skan    UNSPECV_STACK_PROBE)
19709169699Skan   (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
19710132727Skan   (clobber (match_scratch:DI 1 "=0"))
19711169699Skan   (clobber (reg:CC FLAGS_REG))]
1971290286Sobrien  "TARGET_64BIT && TARGET_STACK_PROBE"
1971390286Sobrien  "call\t__alloca"
1971490286Sobrien  [(set_attr "type" "multi")
1971590286Sobrien   (set_attr "length" "5")])
1971690286Sobrien
19717132727Skan(define_expand "allocate_stack_worker_rex64_postreload"
19718132727Skan  [(parallel [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
19719132727Skan				    UNSPECV_STACK_PROBE)
19720169699Skan	      (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
19721132727Skan	      (clobber (match_dup 0))
19722169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19723132727Skan  ""
19724132727Skan  "")
19725132727Skan
1972650650Sobrien(define_expand "allocate_stack"
1972790286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
19728169699Skan		   (minus:SI (reg:SI SP_REG)
1972990286Sobrien			     (match_operand:SI 1 "general_operand" "")))
19730169699Skan	      (clobber (reg:CC FLAGS_REG))])
19731169699Skan   (parallel [(set (reg:SI SP_REG)
19732169699Skan		   (minus:SI (reg:SI SP_REG) (match_dup 1)))
19733169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1973490286Sobrien  "TARGET_STACK_PROBE"
1973550650Sobrien{
1973650650Sobrien#ifdef CHECK_STACK_LIMIT
1973750650Sobrien  if (GET_CODE (operands[1]) == CONST_INT
1973850650Sobrien      && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
1973950650Sobrien    emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
1974050650Sobrien			   operands[1]));
19741259563Spfg  else
1974250650Sobrien#endif
1974350650Sobrien    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
1974450650Sobrien							    operands[1])));
1974550650Sobrien
1974650650Sobrien  emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
1974750650Sobrien  DONE;
1974890286Sobrien})
1974950650Sobrien
1975090286Sobrien(define_expand "builtin_setjmp_receiver"
1975190286Sobrien  [(label_ref (match_operand 0 "" ""))]
1975290286Sobrien  "!TARGET_64BIT && flag_pic"
1975350650Sobrien{
19754169699Skan  if (TARGET_MACHO)
19755169699Skan    {
19756169699Skan      rtx xops[3];
19757169699Skan      rtx picreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
19758169699Skan      rtx label_rtx = gen_label_rtx ();
19759169699Skan      emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx));
19760169699Skan      xops[0] = xops[1] = picreg;
19761169699Skan      xops[2] = gen_rtx_CONST (SImode,
19762169699Skan	          gen_rtx_MINUS (SImode,
19763169699Skan		    gen_rtx_LABEL_REF (SImode, label_rtx),
19764169699Skan		    gen_rtx_SYMBOL_REF (SImode, GOT_SYMBOL_NAME)));
19765169699Skan      ix86_expand_binary_operator (MINUS, SImode, xops);
19766169699Skan    }
19767169699Skan  else
19768169699Skan    emit_insn (gen_set_got (pic_offset_table_rtx));
1976956391Sobrien  DONE;
1977090286Sobrien})
1977190286Sobrien
1977290286Sobrien;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
1977356391Sobrien
1977490286Sobrien(define_split
1977590286Sobrien  [(set (match_operand 0 "register_operand" "")
1977690286Sobrien	(match_operator 3 "promotable_binary_operator"
1977790286Sobrien	   [(match_operand 1 "register_operand" "")
1977890286Sobrien	    (match_operand 2 "aligned_operand" "")]))
19779169699Skan   (clobber (reg:CC FLAGS_REG))]
1978090286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
19781259563Spfg   && ((GET_MODE (operands[0]) == HImode
19782117404Skan	&& ((!optimize_size && !TARGET_FAST_PREFIX)
19783169699Skan            /* ??? next two lines just !satisfies_constraint_K (...) */
19784117404Skan	    || GET_CODE (operands[2]) != CONST_INT
19785169699Skan	    || satisfies_constraint_K (operands[2])))
19786259563Spfg       || (GET_MODE (operands[0]) == QImode
1978790286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1978890286Sobrien  [(parallel [(set (match_dup 0)
1978990286Sobrien		   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
19790169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1979190286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1979290286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);
1979390286Sobrien   if (GET_CODE (operands[3]) != ASHIFT)
1979490286Sobrien     operands[2] = gen_lowpart (SImode, operands[2]);
1979590286Sobrien   PUT_MODE (operands[3], SImode);")
1979690286Sobrien
19797117404Skan; Promote the QImode tests, as i386 has encoding of the AND
19798117404Skan; instruction with 32-bit sign-extended immediate and thus the
19799117404Skan; instruction size is unchanged, except in the %eax case for
19800117404Skan; which it is increased by one byte, hence the ! optimize_size.
1980190286Sobrien(define_split
19802146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19803146906Skan	(match_operator 2 "compare_operator"
19804146906Skan	  [(and (match_operand 3 "aligned_operand" "")
19805146906Skan		(match_operand 4 "const_int_operand" ""))
19806146906Skan	   (const_int 0)]))
19807146906Skan   (set (match_operand 1 "register_operand" "")
19808146906Skan	(and (match_dup 3) (match_dup 4)))]
1980990286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
19810117404Skan   /* Ensure that the operand will remain sign-extended immediate.  */
19811146906Skan   && ix86_match_ccmode (insn, INTVAL (operands[4]) >= 0 ? CCNOmode : CCZmode)
19812117404Skan   && ! optimize_size
19813146906Skan   && ((GET_MODE (operands[1]) == HImode && ! TARGET_FAST_PREFIX)
19814146906Skan       || (GET_MODE (operands[1]) == QImode && TARGET_PROMOTE_QImode))"
19815146906Skan  [(parallel [(set (match_dup 0)
19816146906Skan		   (match_op_dup 2 [(and:SI (match_dup 3) (match_dup 4))
19817146906Skan			            (const_int 0)]))
19818146906Skan	      (set (match_dup 1)
19819146906Skan		   (and:SI (match_dup 3) (match_dup 4)))])]
19820146906Skan{
19821146906Skan  operands[4]
19822146906Skan    = gen_int_mode (INTVAL (operands[4])
19823146906Skan		    & GET_MODE_MASK (GET_MODE (operands[1])), SImode);
19824146906Skan  operands[1] = gen_lowpart (SImode, operands[1]);
19825146906Skan  operands[3] = gen_lowpart (SImode, operands[3]);
19826146906Skan})
1982790286Sobrien
19828117404Skan; Don't promote the QImode tests, as i386 doesn't have encoding of
19829117404Skan; the TEST instruction with 32-bit sign-extended immediate and thus
19830117404Skan; the instruction size would at least double, which is not what we
19831117404Skan; want even with ! optimize_size.
1983290286Sobrien(define_split
19833146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19834146906Skan	(match_operator 1 "compare_operator"
19835146906Skan	  [(and (match_operand:HI 2 "aligned_operand" "")
19836146906Skan		(match_operand:HI 3 "const_int_operand" ""))
19837146906Skan	   (const_int 0)]))]
1983890286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
19839117404Skan   /* Ensure that the operand will remain sign-extended immediate.  */
19840146906Skan   && ix86_match_ccmode (insn, INTVAL (operands[3]) >= 0 ? CCNOmode : CCZmode)
19841117404Skan   && ! TARGET_FAST_PREFIX
19842117404Skan   && ! optimize_size"
19843146906Skan  [(set (match_dup 0)
19844146906Skan	(match_op_dup 1 [(and:SI (match_dup 2) (match_dup 3))
19845146906Skan		         (const_int 0)]))]
19846146906Skan{
19847146906Skan  operands[3]
19848146906Skan    = gen_int_mode (INTVAL (operands[3])
19849146906Skan		    & GET_MODE_MASK (GET_MODE (operands[2])), SImode);
19850146906Skan  operands[2] = gen_lowpart (SImode, operands[2]);
19851146906Skan})
1985290286Sobrien
1985390286Sobrien(define_split
1985490286Sobrien  [(set (match_operand 0 "register_operand" "")
1985590286Sobrien	(neg (match_operand 1 "register_operand" "")))
19856169699Skan   (clobber (reg:CC FLAGS_REG))]
1985790286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1985890286Sobrien   && (GET_MODE (operands[0]) == HImode
19859259563Spfg       || (GET_MODE (operands[0]) == QImode
1986090286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1986190286Sobrien  [(parallel [(set (match_dup 0)
1986290286Sobrien		   (neg:SI (match_dup 1)))
19863169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1986490286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1986590286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);")
1986690286Sobrien
1986790286Sobrien(define_split
1986890286Sobrien  [(set (match_operand 0 "register_operand" "")
1986990286Sobrien	(not (match_operand 1 "register_operand" "")))]
1987090286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1987190286Sobrien   && (GET_MODE (operands[0]) == HImode
19872259563Spfg       || (GET_MODE (operands[0]) == QImode
1987390286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1987490286Sobrien  [(set (match_dup 0)
1987590286Sobrien	(not:SI (match_dup 1)))]
1987690286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1987790286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);")
1987890286Sobrien
19879259563Spfg(define_split
1988090286Sobrien  [(set (match_operand 0 "register_operand" "")
19881259563Spfg	(if_then_else (match_operator 1 "comparison_operator"
19882169699Skan				[(reg FLAGS_REG) (const_int 0)])
1988390286Sobrien		      (match_operand 2 "register_operand" "")
1988490286Sobrien		      (match_operand 3 "register_operand" "")))]
1988590286Sobrien  "! TARGET_PARTIAL_REG_STALL && TARGET_CMOVE
1988690286Sobrien   && (GET_MODE (operands[0]) == HImode
19887259563Spfg       || (GET_MODE (operands[0]) == QImode
1988890286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1988990286Sobrien  [(set (match_dup 0)
1989090286Sobrien	(if_then_else:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
1989190286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1989290286Sobrien   operands[2] = gen_lowpart (SImode, operands[2]);
1989390286Sobrien   operands[3] = gen_lowpart (SImode, operands[3]);")
19894259563Spfg
1989590286Sobrien
1989690286Sobrien;; RTL Peephole optimizations, run before sched2.  These primarily look to
1989790286Sobrien;; transform a complex memory operation into two memory to register operations.
1989890286Sobrien
1989990286Sobrien;; Don't push memory operands
1990090286Sobrien(define_peephole2
1990190286Sobrien  [(set (match_operand:SI 0 "push_operand" "")
1990290286Sobrien	(match_operand:SI 1 "memory_operand" ""))
1990390286Sobrien   (match_scratch:SI 2 "r")]
19904169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19905169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1990690286Sobrien  [(set (match_dup 2) (match_dup 1))
1990790286Sobrien   (set (match_dup 0) (match_dup 2))]
1990890286Sobrien  "")
1990990286Sobrien
1991090286Sobrien(define_peephole2
1991190286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
1991290286Sobrien	(match_operand:DI 1 "memory_operand" ""))
1991390286Sobrien   (match_scratch:DI 2 "r")]
19914169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19915169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1991690286Sobrien  [(set (match_dup 2) (match_dup 1))
1991790286Sobrien   (set (match_dup 0) (match_dup 2))]
1991890286Sobrien  "")
1991990286Sobrien
1992090286Sobrien;; We need to handle SFmode only, because DFmode and XFmode is split to
1992190286Sobrien;; SImode pushes.
1992290286Sobrien(define_peephole2
1992390286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
1992490286Sobrien	(match_operand:SF 1 "memory_operand" ""))
1992590286Sobrien   (match_scratch:SF 2 "r")]
19926169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19927169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1992890286Sobrien  [(set (match_dup 2) (match_dup 1))
1992990286Sobrien   (set (match_dup 0) (match_dup 2))]
1993090286Sobrien  "")
1993190286Sobrien
1993290286Sobrien(define_peephole2
1993390286Sobrien  [(set (match_operand:HI 0 "push_operand" "")
1993490286Sobrien	(match_operand:HI 1 "memory_operand" ""))
1993590286Sobrien   (match_scratch:HI 2 "r")]
19936169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19937169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1993890286Sobrien  [(set (match_dup 2) (match_dup 1))
1993990286Sobrien   (set (match_dup 0) (match_dup 2))]
1994090286Sobrien  "")
1994190286Sobrien
1994290286Sobrien(define_peephole2
1994390286Sobrien  [(set (match_operand:QI 0 "push_operand" "")
1994490286Sobrien	(match_operand:QI 1 "memory_operand" ""))
1994590286Sobrien   (match_scratch:QI 2 "q")]
19946169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19947169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1994890286Sobrien  [(set (match_dup 2) (match_dup 1))
1994990286Sobrien   (set (match_dup 0) (match_dup 2))]
1995090286Sobrien  "")
1995190286Sobrien
1995290286Sobrien;; Don't move an immediate directly to memory when the instruction
1995390286Sobrien;; gets too big.
1995490286Sobrien(define_peephole2
1995590286Sobrien  [(match_scratch:SI 1 "r")
1995690286Sobrien   (set (match_operand:SI 0 "memory_operand" "")
1995790286Sobrien        (const_int 0))]
1995890286Sobrien  "! optimize_size
1995990286Sobrien   && ! TARGET_USE_MOV0
1996090286Sobrien   && TARGET_SPLIT_LONG_MOVES
1996190286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1996290286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1996390286Sobrien  [(parallel [(set (match_dup 1) (const_int 0))
19964169699Skan	      (clobber (reg:CC FLAGS_REG))])
1996590286Sobrien   (set (match_dup 0) (match_dup 1))]
1996690286Sobrien  "")
1996790286Sobrien
1996890286Sobrien(define_peephole2
1996990286Sobrien  [(match_scratch:HI 1 "r")
1997090286Sobrien   (set (match_operand:HI 0 "memory_operand" "")
1997190286Sobrien        (const_int 0))]
1997290286Sobrien  "! optimize_size
1997390286Sobrien   && ! TARGET_USE_MOV0
1997490286Sobrien   && TARGET_SPLIT_LONG_MOVES
1997590286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1997690286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1997790286Sobrien  [(parallel [(set (match_dup 2) (const_int 0))
19978169699Skan	      (clobber (reg:CC FLAGS_REG))])
1997990286Sobrien   (set (match_dup 0) (match_dup 1))]
19980132727Skan  "operands[2] = gen_lowpart (SImode, operands[1]);")
1998190286Sobrien
1998290286Sobrien(define_peephole2
1998390286Sobrien  [(match_scratch:QI 1 "q")
1998490286Sobrien   (set (match_operand:QI 0 "memory_operand" "")
1998590286Sobrien        (const_int 0))]
1998690286Sobrien  "! optimize_size
1998790286Sobrien   && ! TARGET_USE_MOV0
1998890286Sobrien   && TARGET_SPLIT_LONG_MOVES
1998990286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1999090286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1999190286Sobrien  [(parallel [(set (match_dup 2) (const_int 0))
19992169699Skan	      (clobber (reg:CC FLAGS_REG))])
1999390286Sobrien   (set (match_dup 0) (match_dup 1))]
19994132727Skan  "operands[2] = gen_lowpart (SImode, operands[1]);")
1999590286Sobrien
1999690286Sobrien(define_peephole2
1999790286Sobrien  [(match_scratch:SI 2 "r")
1999890286Sobrien   (set (match_operand:SI 0 "memory_operand" "")
1999990286Sobrien        (match_operand:SI 1 "immediate_operand" ""))]
2000090286Sobrien  "! optimize_size
2000190286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
2000290286Sobrien   && TARGET_SPLIT_LONG_MOVES"
2000390286Sobrien  [(set (match_dup 2) (match_dup 1))
2000490286Sobrien   (set (match_dup 0) (match_dup 2))]
2000590286Sobrien  "")
2000690286Sobrien
2000790286Sobrien(define_peephole2
2000890286Sobrien  [(match_scratch:HI 2 "r")
2000990286Sobrien   (set (match_operand:HI 0 "memory_operand" "")
2001090286Sobrien        (match_operand:HI 1 "immediate_operand" ""))]
2001190286Sobrien  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
2001290286Sobrien  && TARGET_SPLIT_LONG_MOVES"
2001390286Sobrien  [(set (match_dup 2) (match_dup 1))
2001490286Sobrien   (set (match_dup 0) (match_dup 2))]
2001590286Sobrien  "")
2001690286Sobrien
2001790286Sobrien(define_peephole2
2001890286Sobrien  [(match_scratch:QI 2 "q")
2001990286Sobrien   (set (match_operand:QI 0 "memory_operand" "")
2002090286Sobrien        (match_operand:QI 1 "immediate_operand" ""))]
2002190286Sobrien  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
2002290286Sobrien  && TARGET_SPLIT_LONG_MOVES"
2002390286Sobrien  [(set (match_dup 2) (match_dup 1))
2002490286Sobrien   (set (match_dup 0) (match_dup 2))]
2002590286Sobrien  "")
2002690286Sobrien
2002790286Sobrien;; Don't compare memory with zero, load and use a test instead.
2002890286Sobrien(define_peephole2
20029146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
20030146906Skan 	(match_operator 1 "compare_operator"
20031146906Skan	  [(match_operand:SI 2 "memory_operand" "")
20032146906Skan	   (const_int 0)]))
2003390286Sobrien   (match_scratch:SI 3 "r")]
2003490286Sobrien  "ix86_match_ccmode (insn, CCNOmode) && ! optimize_size"
20035146906Skan  [(set (match_dup 3) (match_dup 2))
20036146906Skan   (set (match_dup 0) (match_op_dup 1 [(match_dup 3) (const_int 0)]))]
2003790286Sobrien  "")
2003890286Sobrien
20039259563Spfg;; NOT is not pairable on Pentium, while XOR is, but one byte longer.
2004090286Sobrien;; Don't split NOTs with a displacement operand, because resulting XOR
20041132727Skan;; will not be pairable anyway.
2004290286Sobrien;;
20043169699Skan;; On AMD K6, NOT is vector decoded with memory operand that cannot be
2004490286Sobrien;; represented using a modRM byte.  The XOR replacement is long decoded,
2004590286Sobrien;; so this split helps here as well.
2004690286Sobrien;;
2004790286Sobrien;; Note: Can't do this as a regular split because we can't get proper
2004890286Sobrien;; lifetime information then.
2004990286Sobrien
2005090286Sobrien(define_peephole2
2005190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
2005290286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
2005390286Sobrien  "!optimize_size
2005490286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
20055259563Spfg   && ((TARGET_PENTIUM
2005690286Sobrien        && (GET_CODE (operands[0]) != MEM
2005790286Sobrien            || !memory_displacement_operand (operands[0], SImode)))
2005890286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], SImode)))"
2005990286Sobrien  [(parallel [(set (match_dup 0)
2006090286Sobrien		   (xor:SI (match_dup 1) (const_int -1)))
20061169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2006290286Sobrien  "")
2006390286Sobrien
2006490286Sobrien(define_peephole2
2006590286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
2006690286Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
2006790286Sobrien  "!optimize_size
2006890286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
20069259563Spfg   && ((TARGET_PENTIUM
2007090286Sobrien        && (GET_CODE (operands[0]) != MEM
2007190286Sobrien            || !memory_displacement_operand (operands[0], HImode)))
2007290286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], HImode)))"
2007390286Sobrien  [(parallel [(set (match_dup 0)
2007490286Sobrien		   (xor:HI (match_dup 1) (const_int -1)))
20075169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2007690286Sobrien  "")
2007790286Sobrien
2007890286Sobrien(define_peephole2
2007990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
2008090286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
2008190286Sobrien  "!optimize_size
2008290286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
20083259563Spfg   && ((TARGET_PENTIUM
2008490286Sobrien        && (GET_CODE (operands[0]) != MEM
2008590286Sobrien            || !memory_displacement_operand (operands[0], QImode)))
2008690286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], QImode)))"
2008790286Sobrien  [(parallel [(set (match_dup 0)
2008890286Sobrien		   (xor:QI (match_dup 1) (const_int -1)))
20089169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2009090286Sobrien  "")
2009190286Sobrien
2009290286Sobrien;; Non pairable "test imm, reg" instructions can be translated to
2009390286Sobrien;; "and imm, reg" if reg dies.  The "and" form is also shorter (one
2009490286Sobrien;; byte opcode instead of two, have a short form for byte operands),
2009590286Sobrien;; so do it for other CPUs as well.  Given that the value was dead,
2009690286Sobrien;; this should not create any new dependencies.  Pass on the sub-word
2009790286Sobrien;; versions if we're concerned about partial register stalls.
2009890286Sobrien
2009990286Sobrien(define_peephole2
20100146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
20101146906Skan	(match_operator 1 "compare_operator"
20102146906Skan	  [(and:SI (match_operand:SI 2 "register_operand" "")
20103146906Skan		   (match_operand:SI 3 "immediate_operand" ""))
20104146906Skan	   (const_int 0)]))]
2010590286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
20106146906Skan   && (true_regnum (operands[2]) != 0
20107169699Skan       || satisfies_constraint_K (operands[3]))
20108146906Skan   && peep2_reg_dead_p (1, operands[2])"
2010990286Sobrien  [(parallel
20110146906Skan     [(set (match_dup 0)
20111146906Skan	   (match_op_dup 1 [(and:SI (match_dup 2) (match_dup 3))
20112146906Skan		            (const_int 0)]))
20113146906Skan      (set (match_dup 2)
20114146906Skan	   (and:SI (match_dup 2) (match_dup 3)))])]
2011590286Sobrien  "")
2011690286Sobrien
2011790286Sobrien;; We don't need to handle HImode case, because it will be promoted to SImode
2011890286Sobrien;; on ! TARGET_PARTIAL_REG_STALL
2011990286Sobrien
2012090286Sobrien(define_peephole2
20121146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
20122146906Skan	(match_operator 1 "compare_operator"
20123146906Skan	  [(and:QI (match_operand:QI 2 "register_operand" "")
20124146906Skan		   (match_operand:QI 3 "immediate_operand" ""))
20125146906Skan	   (const_int 0)]))]
2012690286Sobrien  "! TARGET_PARTIAL_REG_STALL
2012790286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
20128146906Skan   && true_regnum (operands[2]) != 0
20129146906Skan   && peep2_reg_dead_p (1, operands[2])"
2013090286Sobrien  [(parallel
20131146906Skan     [(set (match_dup 0)
20132146906Skan	   (match_op_dup 1 [(and:QI (match_dup 2) (match_dup 3))
20133146906Skan		            (const_int 0)]))
20134146906Skan      (set (match_dup 2)
20135146906Skan	   (and:QI (match_dup 2) (match_dup 3)))])]
2013690286Sobrien  "")
2013790286Sobrien
2013890286Sobrien(define_peephole2
20139146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
20140146906Skan	(match_operator 1 "compare_operator"
20141146906Skan	  [(and:SI
20142146906Skan	     (zero_extract:SI
20143146906Skan	       (match_operand 2 "ext_register_operand" "")
20144146906Skan	       (const_int 8)
20145146906Skan	       (const_int 8))
20146146906Skan	     (match_operand 3 "const_int_operand" ""))
20147146906Skan	   (const_int 0)]))]
2014890286Sobrien  "! TARGET_PARTIAL_REG_STALL
2014990286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
20150146906Skan   && true_regnum (operands[2]) != 0
20151146906Skan   && peep2_reg_dead_p (1, operands[2])"
20152146906Skan  [(parallel [(set (match_dup 0)
20153146906Skan		   (match_op_dup 1
20154146906Skan		     [(and:SI
20155146906Skan			(zero_extract:SI
20156146906Skan			  (match_dup 2)
20157146906Skan			  (const_int 8)
20158146906Skan			  (const_int 8))
20159146906Skan			(match_dup 3))
20160146906Skan		      (const_int 0)]))
20161146906Skan	      (set (zero_extract:SI (match_dup 2)
2016290286Sobrien				    (const_int 8)
2016390286Sobrien				    (const_int 8))
20164259563Spfg		   (and:SI
2016590286Sobrien		     (zero_extract:SI
20166146906Skan		       (match_dup 2)
2016790286Sobrien		       (const_int 8)
2016890286Sobrien		       (const_int 8))
20169146906Skan		     (match_dup 3)))])]
2017090286Sobrien  "")
2017190286Sobrien
2017290286Sobrien;; Don't do logical operations with memory inputs.
2017390286Sobrien(define_peephole2
2017490286Sobrien  [(match_scratch:SI 2 "r")
2017590286Sobrien   (parallel [(set (match_operand:SI 0 "register_operand" "")
2017690286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
2017790286Sobrien                     [(match_dup 0)
2017890286Sobrien                      (match_operand:SI 1 "memory_operand" "")]))
20179169699Skan              (clobber (reg:CC FLAGS_REG))])]
2018090286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY"
2018190286Sobrien  [(set (match_dup 2) (match_dup 1))
2018290286Sobrien   (parallel [(set (match_dup 0)
2018390286Sobrien                   (match_op_dup 3 [(match_dup 0) (match_dup 2)]))
20184169699Skan              (clobber (reg:CC FLAGS_REG))])]
2018590286Sobrien  "")
2018690286Sobrien
2018790286Sobrien(define_peephole2
2018890286Sobrien  [(match_scratch:SI 2 "r")
2018990286Sobrien   (parallel [(set (match_operand:SI 0 "register_operand" "")
2019090286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
2019190286Sobrien                     [(match_operand:SI 1 "memory_operand" "")
2019290286Sobrien                      (match_dup 0)]))
20193169699Skan              (clobber (reg:CC FLAGS_REG))])]
2019490286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY"
2019590286Sobrien  [(set (match_dup 2) (match_dup 1))
2019690286Sobrien   (parallel [(set (match_dup 0)
2019790286Sobrien                   (match_op_dup 3 [(match_dup 2) (match_dup 0)]))
20198169699Skan              (clobber (reg:CC FLAGS_REG))])]
2019990286Sobrien  "")
2020090286Sobrien
2020190286Sobrien; Don't do logical operations with memory outputs
2020290286Sobrien;
2020390286Sobrien; These two don't make sense for PPro/PII -- we're expanding a 4-uop
2020490286Sobrien; instruction into two 1-uop insns plus a 2-uop insn.  That last has
2020590286Sobrien; the same decoder scheduling characteristics as the original.
2020690286Sobrien
2020790286Sobrien(define_peephole2
2020890286Sobrien  [(match_scratch:SI 2 "r")
2020990286Sobrien   (parallel [(set (match_operand:SI 0 "memory_operand" "")
2021090286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
2021190286Sobrien                     [(match_dup 0)
2021290286Sobrien                      (match_operand:SI 1 "nonmemory_operand" "")]))
20213169699Skan              (clobber (reg:CC FLAGS_REG))])]
2021490286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY_WRITE"
2021590286Sobrien  [(set (match_dup 2) (match_dup 0))
2021690286Sobrien   (parallel [(set (match_dup 2)
2021790286Sobrien                   (match_op_dup 3 [(match_dup 2) (match_dup 1)]))
20218169699Skan              (clobber (reg:CC FLAGS_REG))])
2021990286Sobrien   (set (match_dup 0) (match_dup 2))]
2022090286Sobrien  "")
2022190286Sobrien
2022290286Sobrien(define_peephole2
2022390286Sobrien  [(match_scratch:SI 2 "r")
2022490286Sobrien   (parallel [(set (match_operand:SI 0 "memory_operand" "")
2022590286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
2022690286Sobrien                     [(match_operand:SI 1 "nonmemory_operand" "")
2022790286Sobrien                      (match_dup 0)]))
20228169699Skan              (clobber (reg:CC FLAGS_REG))])]
2022990286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY_WRITE"
2023090286Sobrien  [(set (match_dup 2) (match_dup 0))
2023190286Sobrien   (parallel [(set (match_dup 2)
2023290286Sobrien                   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
20233169699Skan              (clobber (reg:CC FLAGS_REG))])
2023490286Sobrien   (set (match_dup 0) (match_dup 2))]
2023590286Sobrien  "")
2023690286Sobrien
2023790286Sobrien;; Attempt to always use XOR for zeroing registers.
2023890286Sobrien(define_peephole2
2023990286Sobrien  [(set (match_operand 0 "register_operand" "")
20240169699Skan	(match_operand 1 "const0_operand" ""))]
20241169699Skan  "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
2024290286Sobrien   && (! TARGET_USE_MOV0 || optimize_size)
20243169699Skan   && GENERAL_REG_P (operands[0])
2024490286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2024590286Sobrien  [(parallel [(set (match_dup 0) (const_int 0))
20246169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20247169699Skan{
20248169699Skan  operands[0] = gen_lowpart (word_mode, operands[0]);
20249169699Skan})
2025090286Sobrien
2025190286Sobrien(define_peephole2
2025290286Sobrien  [(set (strict_low_part (match_operand 0 "register_operand" ""))
2025390286Sobrien	(const_int 0))]
2025490286Sobrien  "(GET_MODE (operands[0]) == QImode
2025590286Sobrien    || GET_MODE (operands[0]) == HImode)
2025690286Sobrien   && (! TARGET_USE_MOV0 || optimize_size)
2025790286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2025890286Sobrien  [(parallel [(set (strict_low_part (match_dup 0)) (const_int 0))
20259169699Skan	      (clobber (reg:CC FLAGS_REG))])])
2026090286Sobrien
2026190286Sobrien;; For HI and SI modes, or $-1,reg is smaller than mov $-1,reg.
2026290286Sobrien(define_peephole2
2026390286Sobrien  [(set (match_operand 0 "register_operand" "")
2026490286Sobrien	(const_int -1))]
2026590286Sobrien  "(GET_MODE (operands[0]) == HImode
20266259563Spfg    || GET_MODE (operands[0]) == SImode
2026790286Sobrien    || (GET_MODE (operands[0]) == DImode && TARGET_64BIT))
2026890286Sobrien   && (optimize_size || TARGET_PENTIUM)
2026990286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2027090286Sobrien  [(parallel [(set (match_dup 0) (const_int -1))
20271169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20272132727Skan  "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode,
20273132727Skan			      operands[0]);")
2027490286Sobrien
2027590286Sobrien;; Attempt to convert simple leas to adds. These can be created by
2027690286Sobrien;; move expanders.
2027790286Sobrien(define_peephole2
2027890286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2027990286Sobrien  	(plus:SI (match_dup 0)
2028090286Sobrien		 (match_operand:SI 1 "nonmemory_operand" "")))]
2028190286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG)"
2028290286Sobrien  [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
20283169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2028490286Sobrien  "")
2028590286Sobrien
2028690286Sobrien(define_peephole2
2028790286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2028890286Sobrien  	(subreg:SI (plus:DI (match_operand:DI 1 "register_operand" "")
2028990286Sobrien			    (match_operand:DI 2 "nonmemory_operand" "")) 0))]
2029090286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG) && REGNO (operands[0]) == REGNO (operands[1])"
2029190286Sobrien  [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
20292169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2029390286Sobrien  "operands[2] = gen_lowpart (SImode, operands[2]);")
2029490286Sobrien
2029590286Sobrien(define_peephole2
2029690286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
2029790286Sobrien  	(plus:DI (match_dup 0)
2029890286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "")))]
2029990286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG)"
2030090286Sobrien  [(parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
20301169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2030290286Sobrien  "")
2030390286Sobrien
2030490286Sobrien(define_peephole2
2030590286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2030690286Sobrien  	(mult:SI (match_dup 0)
2030790286Sobrien		 (match_operand:SI 1 "const_int_operand" "")))]
2030890286Sobrien  "exact_log2 (INTVAL (operands[1])) >= 0
2030990286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2031090286Sobrien  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
20311169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2031290286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
2031390286Sobrien
2031490286Sobrien(define_peephole2
2031590286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
2031690286Sobrien  	(mult:DI (match_dup 0)
2031790286Sobrien		 (match_operand:DI 1 "const_int_operand" "")))]
2031890286Sobrien  "exact_log2 (INTVAL (operands[1])) >= 0
2031990286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2032090286Sobrien  [(parallel [(set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))
20321169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2032290286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
2032390286Sobrien
2032490286Sobrien(define_peephole2
2032590286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2032690286Sobrien  	(subreg:SI (mult:DI (match_operand:DI 1 "register_operand" "")
2032790286Sobrien		   (match_operand:DI 2 "const_int_operand" "")) 0))]
20328117404Skan  "exact_log2 (INTVAL (operands[2])) >= 0
2032990286Sobrien   && REGNO (operands[0]) == REGNO (operands[1])
2033090286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2033190286Sobrien  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
20332169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2033390286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));")
2033490286Sobrien
2033590286Sobrien;; The ESP adjustments can be done by the push and pop instructions.  Resulting
2033690286Sobrien;; code is shorter, since push is only 1 byte, while add imm, %esp 3 bytes.  On
2033790286Sobrien;; many CPUs it is also faster, since special hardware to avoid esp
2033890286Sobrien;; dependencies is present.
2033990286Sobrien
2034090286Sobrien;; While some of these conversions may be done using splitters, we use peepholes
2034190286Sobrien;; in order to allow combine_stack_adjustments pass to see nonobfuscated RTL.
2034290286Sobrien
2034390286Sobrien;; Convert prologue esp subtractions to push.
2034490286Sobrien;; We need register to push.  In order to keep verify_flow_info happy we have
2034590286Sobrien;; two choices
2034690286Sobrien;; - use scratch and clobber it in order to avoid dependencies
2034790286Sobrien;; - use already live register
2034890286Sobrien;; We can't use the second way right now, since there is no reliable way how to
2034990286Sobrien;; verify that given register is live.  First choice will also most likely in
2035090286Sobrien;; fewer dependencies.  On the place of esp adjustments it is very likely that
2035190286Sobrien;; call clobbered registers are dead.  We may want to use base pointer as an
2035290286Sobrien;; alternative when no register is available later.
2035390286Sobrien
2035490286Sobrien(define_peephole2
2035590286Sobrien  [(match_scratch:SI 0 "r")
20356169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
20357169699Skan	      (clobber (reg:CC FLAGS_REG))
2035890286Sobrien	      (clobber (mem:BLK (scratch)))])]
2035990286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2036090286Sobrien  [(clobber (match_dup 0))
20361169699Skan   (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
2036290286Sobrien	      (clobber (mem:BLK (scratch)))])])
2036390286Sobrien
2036490286Sobrien(define_peephole2
2036590286Sobrien  [(match_scratch:SI 0 "r")
20366169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
20367169699Skan	      (clobber (reg:CC FLAGS_REG))
2036890286Sobrien	      (clobber (mem:BLK (scratch)))])]
2036990286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2037090286Sobrien  [(clobber (match_dup 0))
20371169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
20372169699Skan   (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
2037390286Sobrien	      (clobber (mem:BLK (scratch)))])])
2037490286Sobrien
2037590286Sobrien;; Convert esp subtractions to push.
2037690286Sobrien(define_peephole2
2037790286Sobrien  [(match_scratch:SI 0 "r")
20378169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
20379169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2038090286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2038190286Sobrien  [(clobber (match_dup 0))
20382169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
2038390286Sobrien
2038490286Sobrien(define_peephole2
2038590286Sobrien  [(match_scratch:SI 0 "r")
20386169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
20387169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2038890286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2038990286Sobrien  [(clobber (match_dup 0))
20390169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
20391169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
2039290286Sobrien
2039390286Sobrien;; Convert epilogue deallocator to pop.
2039490286Sobrien(define_peephole2
2039590286Sobrien  [(match_scratch:SI 0 "r")
20396169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
20397169699Skan	      (clobber (reg:CC FLAGS_REG))
2039890286Sobrien	      (clobber (mem:BLK (scratch)))])]
2039990286Sobrien  "optimize_size || !TARGET_ADD_ESP_4"
20400169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20401169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2040290286Sobrien	      (clobber (mem:BLK (scratch)))])]
2040390286Sobrien  "")
2040490286Sobrien
2040590286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2040690286Sobrien;; We use two registers if available.
2040790286Sobrien(define_peephole2
2040890286Sobrien  [(match_scratch:SI 0 "r")
2040990286Sobrien   (match_scratch:SI 1 "r")
20410169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20411169699Skan	      (clobber (reg:CC FLAGS_REG))
2041290286Sobrien	      (clobber (mem:BLK (scratch)))])]
2041390286Sobrien  "optimize_size || !TARGET_ADD_ESP_8"
20414169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20415169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2041690286Sobrien	      (clobber (mem:BLK (scratch)))])
20417169699Skan   (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
20418169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2041990286Sobrien  "")
2042090286Sobrien
2042190286Sobrien(define_peephole2
2042290286Sobrien  [(match_scratch:SI 0 "r")
20423169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20424169699Skan	      (clobber (reg:CC FLAGS_REG))
2042590286Sobrien	      (clobber (mem:BLK (scratch)))])]
2042690286Sobrien  "optimize_size"
20427169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20428169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2042990286Sobrien	      (clobber (mem:BLK (scratch)))])
20430169699Skan   (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20431169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2043290286Sobrien  "")
2043390286Sobrien
2043490286Sobrien;; Convert esp additions to pop.
2043590286Sobrien(define_peephole2
2043690286Sobrien  [(match_scratch:SI 0 "r")
20437169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
20438169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2043990286Sobrien  ""
20440169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20441169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2044290286Sobrien  "")
2044390286Sobrien
2044490286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2044590286Sobrien;; We use two registers if available.
2044690286Sobrien(define_peephole2
2044790286Sobrien  [(match_scratch:SI 0 "r")
2044890286Sobrien   (match_scratch:SI 1 "r")
20449169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20450169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2045190286Sobrien  ""
20452169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20453169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
20454169699Skan   (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
20455169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2045690286Sobrien  "")
2045790286Sobrien
2045890286Sobrien(define_peephole2
2045990286Sobrien  [(match_scratch:SI 0 "r")
20460169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20461169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2046290286Sobrien  "optimize_size"
20463169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20464169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
20465169699Skan   (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20466169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2046790286Sobrien  "")
2046890286Sobrien
2046990286Sobrien;; Convert compares with 1 to shorter inc/dec operations when CF is not
20470146906Skan;; required and register dies.  Similarly for 128 to plus -128.
2047190286Sobrien(define_peephole2
20472146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
20473146906Skan	(match_operator 1 "compare_operator"
20474146906Skan	  [(match_operand 2 "register_operand" "")
20475146906Skan	   (match_operand 3 "const_int_operand" "")]))]
20476146906Skan  "(INTVAL (operands[3]) == -1
20477146906Skan    || INTVAL (operands[3]) == 1
20478146906Skan    || INTVAL (operands[3]) == 128)
20479146906Skan   && ix86_match_ccmode (insn, CCGCmode)
20480146906Skan   && peep2_reg_dead_p (1, operands[2])"
20481146906Skan  [(parallel [(set (match_dup 0)
20482146906Skan		   (match_op_dup 1 [(match_dup 2) (match_dup 3)]))
20483146906Skan	      (clobber (match_dup 2))])]
2048490286Sobrien  "")
2048590286Sobrien
2048690286Sobrien(define_peephole2
2048790286Sobrien  [(match_scratch:DI 0 "r")
20488169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
20489169699Skan	      (clobber (reg:CC FLAGS_REG))
2049090286Sobrien	      (clobber (mem:BLK (scratch)))])]
2049190286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2049290286Sobrien  [(clobber (match_dup 0))
20493169699Skan   (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
2049490286Sobrien	      (clobber (mem:BLK (scratch)))])])
2049590286Sobrien
2049690286Sobrien(define_peephole2
2049790286Sobrien  [(match_scratch:DI 0 "r")
20498169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
20499169699Skan	      (clobber (reg:CC FLAGS_REG))
2050090286Sobrien	      (clobber (mem:BLK (scratch)))])]
2050190286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2050290286Sobrien  [(clobber (match_dup 0))
20503169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
20504169699Skan   (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
2050590286Sobrien	      (clobber (mem:BLK (scratch)))])])
2050690286Sobrien
2050790286Sobrien;; Convert esp subtractions to push.
2050890286Sobrien(define_peephole2
2050990286Sobrien  [(match_scratch:DI 0 "r")
20510169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
20511169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2051290286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2051390286Sobrien  [(clobber (match_dup 0))
20514169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
2051590286Sobrien
2051690286Sobrien(define_peephole2
2051790286Sobrien  [(match_scratch:DI 0 "r")
20518169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
20519169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2052090286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2052190286Sobrien  [(clobber (match_dup 0))
20522169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
20523169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
2052490286Sobrien
2052590286Sobrien;; Convert epilogue deallocator to pop.
2052690286Sobrien(define_peephole2
2052790286Sobrien  [(match_scratch:DI 0 "r")
20528169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
20529169699Skan	      (clobber (reg:CC FLAGS_REG))
2053090286Sobrien	      (clobber (mem:BLK (scratch)))])]
2053190286Sobrien  "optimize_size || !TARGET_ADD_ESP_4"
20532169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20533169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2053490286Sobrien	      (clobber (mem:BLK (scratch)))])]
2053590286Sobrien  "")
2053690286Sobrien
2053790286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2053890286Sobrien;; We use two registers if available.
2053990286Sobrien(define_peephole2
2054090286Sobrien  [(match_scratch:DI 0 "r")
2054190286Sobrien   (match_scratch:DI 1 "r")
20542169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20543169699Skan	      (clobber (reg:CC FLAGS_REG))
2054490286Sobrien	      (clobber (mem:BLK (scratch)))])]
2054590286Sobrien  "optimize_size || !TARGET_ADD_ESP_8"
20546169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20547169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2054890286Sobrien	      (clobber (mem:BLK (scratch)))])
20549169699Skan   (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
20550169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2055190286Sobrien  "")
2055290286Sobrien
2055390286Sobrien(define_peephole2
2055490286Sobrien  [(match_scratch:DI 0 "r")
20555169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20556169699Skan	      (clobber (reg:CC FLAGS_REG))
2055790286Sobrien	      (clobber (mem:BLK (scratch)))])]
2055890286Sobrien  "optimize_size"
20559169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20560169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2056190286Sobrien	      (clobber (mem:BLK (scratch)))])
20562169699Skan   (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20563169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2056490286Sobrien  "")
2056590286Sobrien
2056690286Sobrien;; Convert esp additions to pop.
2056790286Sobrien(define_peephole2
2056890286Sobrien  [(match_scratch:DI 0 "r")
20569169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
20570169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2057190286Sobrien  ""
20572169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20573169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2057490286Sobrien  "")
2057590286Sobrien
2057690286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2057790286Sobrien;; We use two registers if available.
2057890286Sobrien(define_peephole2
2057990286Sobrien  [(match_scratch:DI 0 "r")
2058090286Sobrien   (match_scratch:DI 1 "r")
20581169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20582169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2058390286Sobrien  ""
20584169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20585169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
20586169699Skan   (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
20587169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2058890286Sobrien  "")
2058990286Sobrien
2059090286Sobrien(define_peephole2
2059190286Sobrien  [(match_scratch:DI 0 "r")
20592169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20593169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2059490286Sobrien  "optimize_size"
20595169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20596169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
20597169699Skan   (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20598169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2059990286Sobrien  "")
2060090286Sobrien
20601169699Skan;; Convert imul by three, five and nine into lea
20602169699Skan(define_peephole2
20603169699Skan  [(parallel
20604169699Skan    [(set (match_operand:SI 0 "register_operand" "")
20605169699Skan	  (mult:SI (match_operand:SI 1 "register_operand" "")
20606169699Skan		   (match_operand:SI 2 "const_int_operand" "")))
20607169699Skan     (clobber (reg:CC FLAGS_REG))])]
20608169699Skan  "INTVAL (operands[2]) == 3
20609169699Skan   || INTVAL (operands[2]) == 5
20610169699Skan   || INTVAL (operands[2]) == 9"
20611169699Skan  [(set (match_dup 0)
20612169699Skan        (plus:SI (mult:SI (match_dup 1) (match_dup 2))
20613169699Skan                 (match_dup 1)))]
20614169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20615169699Skan
20616169699Skan(define_peephole2
20617169699Skan  [(parallel
20618169699Skan    [(set (match_operand:SI 0 "register_operand" "")
20619169699Skan          (mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
20620169699Skan                   (match_operand:SI 2 "const_int_operand" "")))
20621169699Skan     (clobber (reg:CC FLAGS_REG))])]
20622259563Spfg  "!optimize_size
20623169699Skan   && (INTVAL (operands[2]) == 3
20624169699Skan       || INTVAL (operands[2]) == 5
20625169699Skan       || INTVAL (operands[2]) == 9)"
20626169699Skan  [(set (match_dup 0) (match_dup 1))
20627169699Skan   (set (match_dup 0)
20628169699Skan        (plus:SI (mult:SI (match_dup 0) (match_dup 2))
20629169699Skan                 (match_dup 0)))]
20630169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20631169699Skan
20632169699Skan(define_peephole2
20633169699Skan  [(parallel
20634169699Skan    [(set (match_operand:DI 0 "register_operand" "")
20635169699Skan	  (mult:DI (match_operand:DI 1 "register_operand" "")
20636169699Skan		   (match_operand:DI 2 "const_int_operand" "")))
20637169699Skan     (clobber (reg:CC FLAGS_REG))])]
20638169699Skan  "TARGET_64BIT
20639169699Skan   && (INTVAL (operands[2]) == 3
20640169699Skan       || INTVAL (operands[2]) == 5
20641169699Skan       || INTVAL (operands[2]) == 9)"
20642169699Skan  [(set (match_dup 0)
20643169699Skan        (plus:DI (mult:DI (match_dup 1) (match_dup 2))
20644169699Skan                 (match_dup 1)))]
20645169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20646169699Skan
20647169699Skan(define_peephole2
20648169699Skan  [(parallel
20649169699Skan    [(set (match_operand:DI 0 "register_operand" "")
20650169699Skan          (mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
20651169699Skan                   (match_operand:DI 2 "const_int_operand" "")))
20652169699Skan     (clobber (reg:CC FLAGS_REG))])]
20653169699Skan  "TARGET_64BIT
20654259563Spfg   && !optimize_size
20655169699Skan   && (INTVAL (operands[2]) == 3
20656169699Skan       || INTVAL (operands[2]) == 5
20657169699Skan       || INTVAL (operands[2]) == 9)"
20658169699Skan  [(set (match_dup 0) (match_dup 1))
20659169699Skan   (set (match_dup 0)
20660169699Skan        (plus:DI (mult:DI (match_dup 0) (match_dup 2))
20661169699Skan                 (match_dup 0)))]
20662169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20663169699Skan
20664132727Skan;; Imul $32bit_imm, mem, reg is vector decoded, while
20665132727Skan;; imul $32bit_imm, reg, reg is direct decoded.
20666132727Skan(define_peephole2
20667132727Skan  [(match_scratch:DI 3 "r")
20668132727Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
20669132727Skan		   (mult:DI (match_operand:DI 1 "memory_operand" "")
20670132727Skan			    (match_operand:DI 2 "immediate_operand" "")))
20671169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20672251212Spfg  "(TARGET_K8 || TARGET_GENERIC64 || TARGET_AMDFAM10) && !optimize_size
20673169699Skan   && !satisfies_constraint_K (operands[2])"
20674132727Skan  [(set (match_dup 3) (match_dup 1))
20675132727Skan   (parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2)))
20676169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20677132727Skan"")
20678132727Skan
20679132727Skan(define_peephole2
20680132727Skan  [(match_scratch:SI 3 "r")
20681132727Skan   (parallel [(set (match_operand:SI 0 "register_operand" "")
20682132727Skan		   (mult:SI (match_operand:SI 1 "memory_operand" "")
20683132727Skan			    (match_operand:SI 2 "immediate_operand" "")))
20684169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20685251212Spfg  "(TARGET_K8 || TARGET_GENERIC64 || TARGET_AMDFAM10) && !optimize_size
20686169699Skan   && !satisfies_constraint_K (operands[2])"
20687132727Skan  [(set (match_dup 3) (match_dup 1))
20688132727Skan   (parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2)))
20689169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20690132727Skan"")
20691132727Skan
20692132727Skan(define_peephole2
20693132727Skan  [(match_scratch:SI 3 "r")
20694132727Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
20695132727Skan		   (zero_extend:DI
20696132727Skan		     (mult:SI (match_operand:SI 1 "memory_operand" "")
20697132727Skan			      (match_operand:SI 2 "immediate_operand" ""))))
20698169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20699251212Spfg  "(TARGET_K8 || TARGET_GENERIC64 || TARGET_AMDFAM10) && !optimize_size
20700169699Skan   && !satisfies_constraint_K (operands[2])"
20701132727Skan  [(set (match_dup 3) (match_dup 1))
20702132727Skan   (parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2))))
20703169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20704132727Skan"")
20705132727Skan
20706132727Skan;; imul $8/16bit_imm, regmem, reg is vector decoded.
20707132727Skan;; Convert it into imul reg, reg
20708132727Skan;; It would be better to force assembler to encode instruction using long
20709132727Skan;; immediate, but there is apparently no way to do so.
20710132727Skan(define_peephole2
20711132727Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
20712132727Skan		   (mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
20713132727Skan			    (match_operand:DI 2 "const_int_operand" "")))
20714169699Skan	      (clobber (reg:CC FLAGS_REG))])
20715132727Skan   (match_scratch:DI 3 "r")]
20716251212Spfg  "(TARGET_K8 || TARGET_GENERIC64 || TARGET_AMDFAM10) && !optimize_size
20717169699Skan   && satisfies_constraint_K (operands[2])"
20718132727Skan  [(set (match_dup 3) (match_dup 2))
20719132727Skan   (parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3)))
20720169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20721132727Skan{
20722132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20723132727Skan    emit_move_insn (operands[0], operands[1]);
20724132727Skan})
20725132727Skan
20726132727Skan(define_peephole2
20727132727Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
20728132727Skan		   (mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
20729132727Skan			    (match_operand:SI 2 "const_int_operand" "")))
20730169699Skan	      (clobber (reg:CC FLAGS_REG))])
20731132727Skan   (match_scratch:SI 3 "r")]
20732251212Spfg  "(TARGET_K8 || TARGET_GENERIC64 || TARGET_AMDFAM10) && !optimize_size
20733169699Skan   && satisfies_constraint_K (operands[2])"
20734132727Skan  [(set (match_dup 3) (match_dup 2))
20735132727Skan   (parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3)))
20736169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20737132727Skan{
20738132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20739132727Skan    emit_move_insn (operands[0], operands[1]);
20740132727Skan})
20741132727Skan
20742132727Skan(define_peephole2
20743132727Skan  [(parallel [(set (match_operand:HI 0 "register_operand" "")
20744132727Skan		   (mult:HI (match_operand:HI 1 "nonimmediate_operand" "")
20745132727Skan			    (match_operand:HI 2 "immediate_operand" "")))
20746169699Skan	      (clobber (reg:CC FLAGS_REG))])
20747132727Skan   (match_scratch:HI 3 "r")]
20748251212Spfg  "(TARGET_K8 || TARGET_GENERIC64 || TARGET_AMDFAM10) && !optimize_size"
20749132727Skan  [(set (match_dup 3) (match_dup 2))
20750132727Skan   (parallel [(set (match_dup 0) (mult:HI (match_dup 0) (match_dup 3)))
20751169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20752132727Skan{
20753132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20754132727Skan    emit_move_insn (operands[0], operands[1]);
20755132727Skan})
20756169699Skan
20757169699Skan;; After splitting up read-modify operations, array accesses with memory
20758169699Skan;; operands might end up in form:
20759169699Skan;;  sall    $2, %eax
20760169699Skan;;  movl    4(%esp), %edx
20761169699Skan;;  addl    %edx, %eax
20762169699Skan;; instead of pre-splitting:
20763169699Skan;;  sall    $2, %eax
20764169699Skan;;  addl    4(%esp), %eax
20765169699Skan;; Turn it into:
20766169699Skan;;  movl    4(%esp), %edx
20767169699Skan;;  leal    (%edx,%eax,4), %eax
20768169699Skan
20769169699Skan(define_peephole2
20770169699Skan  [(parallel [(set (match_operand 0 "register_operand" "")
20771169699Skan		   (ashift (match_operand 1 "register_operand" "")
20772169699Skan			   (match_operand 2 "const_int_operand" "")))
20773169699Skan	       (clobber (reg:CC FLAGS_REG))])
20774169699Skan   (set (match_operand 3 "register_operand")
20775169699Skan        (match_operand 4 "x86_64_general_operand" ""))
20776169699Skan   (parallel [(set (match_operand 5 "register_operand" "")
20777169699Skan		   (plus (match_operand 6 "register_operand" "")
20778169699Skan			 (match_operand 7 "register_operand" "")))
20779169699Skan		   (clobber (reg:CC FLAGS_REG))])]
20780169699Skan  "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
20781169699Skan   /* Validate MODE for lea.  */
20782169699Skan   && ((!TARGET_PARTIAL_REG_STALL
20783169699Skan	&& (GET_MODE (operands[0]) == QImode
20784169699Skan	    || GET_MODE (operands[0]) == HImode))
20785259563Spfg       || GET_MODE (operands[0]) == SImode
20786169699Skan       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
20787169699Skan   /* We reorder load and the shift.  */
20788169699Skan   && !rtx_equal_p (operands[1], operands[3])
20789169699Skan   && !reg_overlap_mentioned_p (operands[0], operands[4])
20790169699Skan   /* Last PLUS must consist of operand 0 and 3.  */
20791169699Skan   && !rtx_equal_p (operands[0], operands[3])
20792169699Skan   && (rtx_equal_p (operands[3], operands[6])
20793169699Skan       || rtx_equal_p (operands[3], operands[7]))
20794169699Skan   && (rtx_equal_p (operands[0], operands[6])
20795169699Skan       || rtx_equal_p (operands[0], operands[7]))
20796169699Skan   /* The intermediate operand 0 must die or be same as output.  */
20797169699Skan   && (rtx_equal_p (operands[0], operands[5])
20798169699Skan       || peep2_reg_dead_p (3, operands[0]))"
20799169699Skan  [(set (match_dup 3) (match_dup 4))
20800169699Skan   (set (match_dup 0) (match_dup 1))]
20801169699Skan{
20802169699Skan  enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
20803169699Skan  int scale = 1 << INTVAL (operands[2]);
20804169699Skan  rtx index = gen_lowpart (Pmode, operands[1]);
20805169699Skan  rtx base = gen_lowpart (Pmode, operands[3]);
20806169699Skan  rtx dest = gen_lowpart (mode, operands[5]);
20807169699Skan
20808169699Skan  operands[1] = gen_rtx_PLUS (Pmode, base,
20809169699Skan  			      gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
20810169699Skan  if (mode != Pmode)
20811169699Skan    operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
20812169699Skan  operands[0] = dest;
20813169699Skan})
20814132727Skan
2081590286Sobrien;; Call-value patterns last so that the wildcard operand does not
2081690286Sobrien;; disrupt insn-recog's switch tables.
2081790286Sobrien
2081890286Sobrien(define_insn "*call_value_pop_0"
2081990286Sobrien  [(set (match_operand 0 "" "")
2082090286Sobrien	(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
2082190286Sobrien	      (match_operand:SI 2 "" "")))
20822169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
2082390286Sobrien			    (match_operand:SI 3 "immediate_operand" "")))]
2082490286Sobrien  "!TARGET_64BIT"
2082590286Sobrien{
2082690286Sobrien  if (SIBLING_CALL_P (insn))
2082790286Sobrien    return "jmp\t%P1";
2082890286Sobrien  else
2082990286Sobrien    return "call\t%P1";
2083090286Sobrien}
2083190286Sobrien  [(set_attr "type" "callv")])
2083290286Sobrien
2083390286Sobrien(define_insn "*call_value_pop_1"
2083490286Sobrien  [(set (match_operand 0 "" "")
2083590286Sobrien	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
2083690286Sobrien	      (match_operand:SI 2 "" "")))
20837169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
2083890286Sobrien			    (match_operand:SI 3 "immediate_operand" "i")))]
2083990286Sobrien  "!TARGET_64BIT"
2084090286Sobrien{
20841169699Skan  if (constant_call_address_operand (operands[1], Pmode))
2084290286Sobrien    {
2084390286Sobrien      if (SIBLING_CALL_P (insn))
2084490286Sobrien	return "jmp\t%P1";
2084590286Sobrien      else
2084690286Sobrien	return "call\t%P1";
2084790286Sobrien    }
2084890286Sobrien  if (SIBLING_CALL_P (insn))
2084990286Sobrien    return "jmp\t%A1";
2085090286Sobrien  else
2085190286Sobrien    return "call\t%A1";
2085290286Sobrien}
2085390286Sobrien  [(set_attr "type" "callv")])
2085490286Sobrien
2085590286Sobrien(define_insn "*call_value_0"
2085690286Sobrien  [(set (match_operand 0 "" "")
2085790286Sobrien	(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
2085890286Sobrien	      (match_operand:SI 2 "" "")))]
2085990286Sobrien  "!TARGET_64BIT"
2086090286Sobrien{
2086190286Sobrien  if (SIBLING_CALL_P (insn))
2086290286Sobrien    return "jmp\t%P1";
2086390286Sobrien  else
2086490286Sobrien    return "call\t%P1";
2086590286Sobrien}
2086690286Sobrien  [(set_attr "type" "callv")])
2086790286Sobrien
2086890286Sobrien(define_insn "*call_value_0_rex64"
2086990286Sobrien  [(set (match_operand 0 "" "")
2087090286Sobrien	(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
2087190286Sobrien	      (match_operand:DI 2 "const_int_operand" "")))]
2087290286Sobrien  "TARGET_64BIT"
2087390286Sobrien{
2087490286Sobrien  if (SIBLING_CALL_P (insn))
2087590286Sobrien    return "jmp\t%P1";
2087690286Sobrien  else
2087790286Sobrien    return "call\t%P1";
2087890286Sobrien}
2087990286Sobrien  [(set_attr "type" "callv")])
2088090286Sobrien
2088190286Sobrien(define_insn "*call_value_1"
2088290286Sobrien  [(set (match_operand 0 "" "")
2088390286Sobrien	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
2088490286Sobrien	      (match_operand:SI 2 "" "")))]
20885132727Skan  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
2088690286Sobrien{
20887169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20888132727Skan    return "call\t%P1";
20889146906Skan  return "call\t%A1";
2089090286Sobrien}
2089190286Sobrien  [(set_attr "type" "callv")])
2089290286Sobrien
20893132727Skan(define_insn "*sibcall_value_1"
20894132727Skan  [(set (match_operand 0 "" "")
20895132727Skan	(call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,c,d,a"))
20896132727Skan	      (match_operand:SI 2 "" "")))]
20897132727Skan  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
20898132727Skan{
20899169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20900132727Skan    return "jmp\t%P1";
20901146906Skan  return "jmp\t%A1";
20902132727Skan}
20903132727Skan  [(set_attr "type" "callv")])
20904132727Skan
2090590286Sobrien(define_insn "*call_value_1_rex64"
2090690286Sobrien  [(set (match_operand 0 "" "")
2090790286Sobrien	(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
2090890286Sobrien	      (match_operand:DI 2 "" "")))]
20909132727Skan  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
2091090286Sobrien{
20911169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20912132727Skan    return "call\t%P1";
20913132727Skan  return "call\t%A1";
2091490286Sobrien}
2091590286Sobrien  [(set_attr "type" "callv")])
20916132727Skan
20917132727Skan(define_insn "*sibcall_value_1_rex64"
20918132727Skan  [(set (match_operand 0 "" "")
20919132727Skan	(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
20920132727Skan	      (match_operand:DI 2 "" "")))]
20921132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
20922132727Skan  "jmp\t%P1"
20923132727Skan  [(set_attr "type" "callv")])
20924132727Skan
20925132727Skan(define_insn "*sibcall_value_1_rex64_v"
20926132727Skan  [(set (match_operand 0 "" "")
20927237021Spfg	(call (mem:QI (reg:DI 40))
20928132727Skan	      (match_operand:DI 1 "" "")))]
20929132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
20930132727Skan  "jmp\t*%%r11"
20931132727Skan  [(set_attr "type" "callv")])
2093290286Sobrien
20933169699Skan;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5.
20934259563Spfg;; That, however, is usually mapped by the OS to SIGSEGV, which is often
20935169699Skan;; caught for use by garbage collectors and the like.  Using an insn that
20936169699Skan;; maps to SIGILL makes it more likely the program will rightfully die.
20937169699Skan;; Keeping with tradition, "6" is in honor of #UD.
2093890286Sobrien(define_insn "trap"
20939169699Skan  [(trap_if (const_int 1) (const_int 6))]
2094090286Sobrien  ""
20941169699Skan  { return ASM_SHORT "0x0b0f"; }
20942169699Skan  [(set_attr "length" "2")])
2094390286Sobrien
2094490286Sobrien(define_expand "sse_prologue_save"
2094590286Sobrien  [(parallel [(set (match_operand:BLK 0 "" "")
20946237021Spfg		   (unspec:BLK [(reg:DI 21)
20947237021Spfg				(reg:DI 22)
2094890286Sobrien				(reg:DI 23)
2094990286Sobrien				(reg:DI 24)
2095090286Sobrien				(reg:DI 25)
2095190286Sobrien				(reg:DI 26)
2095290286Sobrien				(reg:DI 27)
20953237021Spfg				(reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
2095490286Sobrien	      (use (match_operand:DI 1 "register_operand" ""))
2095590286Sobrien	      (use (match_operand:DI 2 "immediate_operand" ""))
2095690286Sobrien	      (use (label_ref:DI (match_operand 3 "" "")))])]
2095790286Sobrien  "TARGET_64BIT"
2095890286Sobrien  "")
2095990286Sobrien
2096090286Sobrien(define_insn "*sse_prologue_save_insn"
2096190286Sobrien  [(set (mem:BLK (plus:DI (match_operand:DI 0 "register_operand" "R")
2096290286Sobrien			  (match_operand:DI 4 "const_int_operand" "n")))
20963237021Spfg	(unspec:BLK [(reg:DI 21)
20964237021Spfg		     (reg:DI 22)
2096590286Sobrien		     (reg:DI 23)
2096690286Sobrien		     (reg:DI 24)
2096790286Sobrien		     (reg:DI 25)
2096890286Sobrien		     (reg:DI 26)
2096990286Sobrien		     (reg:DI 27)
20970237021Spfg		     (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
2097190286Sobrien   (use (match_operand:DI 1 "register_operand" "r"))
2097290286Sobrien   (use (match_operand:DI 2 "const_int_operand" "i"))
2097390286Sobrien   (use (label_ref:DI (match_operand 3 "" "X")))]
2097490286Sobrien  "TARGET_64BIT
2097590286Sobrien   && INTVAL (operands[4]) + SSE_REGPARM_MAX * 16 - 16 < 128
2097690286Sobrien   && INTVAL (operands[4]) + INTVAL (operands[2]) * 16 >= -128"
2097790286Sobrien  "*
2097890286Sobrien{
2097990286Sobrien  int i;
2098090286Sobrien  operands[0] = gen_rtx_MEM (Pmode,
2098190286Sobrien			     gen_rtx_PLUS (Pmode, operands[0], operands[4]));
2098290286Sobrien  output_asm_insn (\"jmp\\t%A1\", operands);
2098390286Sobrien  for (i = SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--)
2098490286Sobrien    {
2098590286Sobrien      operands[4] = adjust_address (operands[0], DImode, i*16);
2098690286Sobrien      operands[5] = gen_rtx_REG (TImode, SSE_REGNO (i));
2098790286Sobrien      PUT_MODE (operands[4], TImode);
2098890286Sobrien      if (GET_CODE (XEXP (operands[0], 0)) != PLUS)
2098990286Sobrien        output_asm_insn (\"rex\", operands);
2099090286Sobrien      output_asm_insn (\"movaps\\t{%5, %4|%4, %5}\", operands);
2099190286Sobrien    }
20992132727Skan  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
2099390286Sobrien			     CODE_LABEL_NUMBER (operands[3]));
2099490286Sobrien  RET;
2099590286Sobrien}
2099656391Sobrien  "
2099790286Sobrien  [(set_attr "type" "other")
2099890286Sobrien   (set_attr "length_immediate" "0")
2099990286Sobrien   (set_attr "length_address" "0")
2100090286Sobrien   (set_attr "length" "135")
2100190286Sobrien   (set_attr "memory" "store")
2100290286Sobrien   (set_attr "modrm" "0")
2100390286Sobrien   (set_attr "mode" "DI")])
2100490286Sobrien
2100590286Sobrien(define_expand "prefetch"
21006102802Skan  [(prefetch (match_operand 0 "address_operand" "")
2100790286Sobrien	     (match_operand:SI 1 "const_int_operand" "")
2100890286Sobrien	     (match_operand:SI 2 "const_int_operand" ""))]
2100990286Sobrien  "TARGET_PREFETCH_SSE || TARGET_3DNOW"
2101056391Sobrien{
2101190286Sobrien  int rw = INTVAL (operands[1]);
2101290286Sobrien  int locality = INTVAL (operands[2]);
2101390286Sobrien
21014169699Skan  gcc_assert (rw == 0 || rw == 1);
21015169699Skan  gcc_assert (locality >= 0 && locality <= 3);
21016169699Skan  gcc_assert (GET_MODE (operands[0]) == Pmode
21017169699Skan	      || GET_MODE (operands[0]) == VOIDmode);
2101890286Sobrien
2101990286Sobrien  /* Use 3dNOW prefetch in case we are asking for write prefetch not
21020169699Skan     supported by SSE counterpart or the SSE prefetch is not available
2102190286Sobrien     (K6 machines).  Otherwise use SSE prefetch as it allows specifying
2102290286Sobrien     of locality.  */
2102390286Sobrien  if (TARGET_3DNOW && (!TARGET_PREFETCH_SSE || rw))
2102490286Sobrien    operands[2] = GEN_INT (3);
2102590286Sobrien  else
2102690286Sobrien    operands[1] = const0_rtx;
2102790286Sobrien})
2102890286Sobrien
2102990286Sobrien(define_insn "*prefetch_sse"
2103090286Sobrien  [(prefetch (match_operand:SI 0 "address_operand" "p")
2103190286Sobrien	     (const_int 0)
2103290286Sobrien	     (match_operand:SI 1 "const_int_operand" ""))]
21033102802Skan  "TARGET_PREFETCH_SSE && !TARGET_64BIT"
2103490286Sobrien{
2103590286Sobrien  static const char * const patterns[4] = {
2103690286Sobrien   "prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
2103790286Sobrien  };
2103890286Sobrien
2103990286Sobrien  int locality = INTVAL (operands[1]);
21040169699Skan  gcc_assert (locality >= 0 && locality <= 3);
2104190286Sobrien
21042259563Spfg  return patterns[locality];
2104390286Sobrien}
21044102802Skan  [(set_attr "type" "sse")
21045102802Skan   (set_attr "memory" "none")])
21046102802Skan
21047102802Skan(define_insn "*prefetch_sse_rex"
21048102802Skan  [(prefetch (match_operand:DI 0 "address_operand" "p")
21049102802Skan	     (const_int 0)
21050102802Skan	     (match_operand:SI 1 "const_int_operand" ""))]
21051102802Skan  "TARGET_PREFETCH_SSE && TARGET_64BIT"
21052102802Skan{
21053102802Skan  static const char * const patterns[4] = {
21054102802Skan   "prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
21055102802Skan  };
21056102802Skan
21057102802Skan  int locality = INTVAL (operands[1]);
21058169699Skan  gcc_assert (locality >= 0 && locality <= 3);
21059102802Skan
21060259563Spfg  return patterns[locality];
21061102802Skan}
21062117404Skan  [(set_attr "type" "sse")
21063117404Skan   (set_attr "memory" "none")])
2106490286Sobrien
2106590286Sobrien(define_insn "*prefetch_3dnow"
2106690286Sobrien  [(prefetch (match_operand:SI 0 "address_operand" "p")
2106790286Sobrien	     (match_operand:SI 1 "const_int_operand" "n")
2106890286Sobrien	     (const_int 3))]
21069102802Skan  "TARGET_3DNOW && !TARGET_64BIT"
2107090286Sobrien{
2107190286Sobrien  if (INTVAL (operands[1]) == 0)
2107290286Sobrien    return "prefetch\t%a0";
2107390286Sobrien  else
2107490286Sobrien    return "prefetchw\t%a0";
2107590286Sobrien}
21076102802Skan  [(set_attr "type" "mmx")
21077102802Skan   (set_attr "memory" "none")])
21078102802Skan
21079102802Skan(define_insn "*prefetch_3dnow_rex"
21080102802Skan  [(prefetch (match_operand:DI 0 "address_operand" "p")
21081102802Skan	     (match_operand:SI 1 "const_int_operand" "n")
21082102802Skan	     (const_int 3))]
21083102802Skan  "TARGET_3DNOW && TARGET_64BIT"
21084102802Skan{
21085102802Skan  if (INTVAL (operands[1]) == 0)
21086102802Skan    return "prefetch\t%a0";
21087102802Skan  else
21088102802Skan    return "prefetchw\t%a0";
21089102802Skan}
21090117404Skan  [(set_attr "type" "mmx")
21091117404Skan   (set_attr "memory" "none")])
21092117404Skan
21093169699Skan(define_expand "stack_protect_set"
21094169699Skan  [(match_operand 0 "memory_operand" "")
21095169699Skan   (match_operand 1 "memory_operand" "")]
21096169699Skan  ""
21097117404Skan{
21098169699Skan#ifdef TARGET_THREAD_SSP_OFFSET
21099169699Skan  if (TARGET_64BIT)
21100169699Skan    emit_insn (gen_stack_tls_protect_set_di (operands[0],
21101169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
21102117404Skan  else
21103169699Skan    emit_insn (gen_stack_tls_protect_set_si (operands[0],
21104169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
21105169699Skan#else
21106169699Skan  if (TARGET_64BIT)
21107169699Skan    emit_insn (gen_stack_protect_set_di (operands[0], operands[1]));
21108117404Skan  else
21109169699Skan    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
21110169699Skan#endif
21111169699Skan  DONE;
21112169699Skan})
21113117404Skan
21114169699Skan(define_insn "stack_protect_set_si"
21115169699Skan  [(set (match_operand:SI 0 "memory_operand" "=m")
21116169699Skan	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
21117169699Skan   (set (match_scratch:SI 2 "=&r") (const_int 0))
21118169699Skan   (clobber (reg:CC FLAGS_REG))]
21119169699Skan  ""
21120169699Skan  "mov{l}\t{%1, %2|%2, %1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
21121169699Skan  [(set_attr "type" "multi")])
21122117404Skan
21123169699Skan(define_insn "stack_protect_set_di"
21124169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
21125169699Skan	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
21126169699Skan   (set (match_scratch:DI 2 "=&r") (const_int 0))
21127169699Skan   (clobber (reg:CC FLAGS_REG))]
21128169699Skan  "TARGET_64BIT"
21129169699Skan  "mov{q}\t{%1, %2|%2, %1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
21130169699Skan  [(set_attr "type" "multi")])
21131117404Skan
21132169699Skan(define_insn "stack_tls_protect_set_si"
21133117404Skan  [(set (match_operand:SI 0 "memory_operand" "=m")
21134169699Skan	(unspec:SI [(match_operand:SI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
21135169699Skan   (set (match_scratch:SI 2 "=&r") (const_int 0))
21136169699Skan   (clobber (reg:CC FLAGS_REG))]
21137169699Skan  ""
21138169699Skan  "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR %%gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
21139169699Skan  [(set_attr "type" "multi")])
21140117404Skan
21141169699Skan(define_insn "stack_tls_protect_set_di"
21142169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
21143169699Skan	(unspec:DI [(match_operand:DI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
21144169699Skan   (set (match_scratch:DI 2 "=&r") (const_int 0))
21145169699Skan   (clobber (reg:CC FLAGS_REG))]
21146169699Skan  "TARGET_64BIT"
21147169699Skan  {
21148169699Skan     /* The kernel uses a different segment register for performance reasons; a
21149169699Skan        system call would not have to trash the userspace segment register,
21150169699Skan        which would be expensive */
21151169699Skan     if (ix86_cmodel != CM_KERNEL)
21152169699Skan        return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
21153169699Skan     else
21154169699Skan        return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR %%gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
21155169699Skan  }
21156169699Skan  [(set_attr "type" "multi")])
21157117404Skan
21158169699Skan(define_expand "stack_protect_test"
21159169699Skan  [(match_operand 0 "memory_operand" "")
21160169699Skan   (match_operand 1 "memory_operand" "")
21161169699Skan   (match_operand 2 "" "")]
21162169699Skan  ""
21163169699Skan{
21164169699Skan  rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG);
21165169699Skan  ix86_compare_op0 = operands[0];
21166169699Skan  ix86_compare_op1 = operands[1];
21167169699Skan  ix86_compare_emitted = flags;
21168117404Skan
21169169699Skan#ifdef TARGET_THREAD_SSP_OFFSET
21170169699Skan  if (TARGET_64BIT)
21171169699Skan    emit_insn (gen_stack_tls_protect_test_di (flags, operands[0],
21172169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
21173132727Skan  else
21174169699Skan    emit_insn (gen_stack_tls_protect_test_si (flags, operands[0],
21175169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
21176169699Skan#else
21177169699Skan  if (TARGET_64BIT)
21178169699Skan    emit_insn (gen_stack_protect_test_di (flags, operands[0], operands[1]));
21179169699Skan  else
21180169699Skan    emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1]));
21181169699Skan#endif
21182169699Skan  emit_jump_insn (gen_beq (operands[2]));
21183117404Skan  DONE;
21184117404Skan})
21185117404Skan
21186169699Skan(define_insn "stack_protect_test_si"
21187169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
21188169699Skan	(unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
21189169699Skan		     (match_operand:SI 2 "memory_operand" "m")]
21190169699Skan		    UNSPEC_SP_TEST))
21191169699Skan   (clobber (match_scratch:SI 3 "=&r"))]
21192169699Skan  ""
21193169699Skan  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%2, %3|%3, %2}"
21194169699Skan  [(set_attr "type" "multi")])
21195117404Skan
21196169699Skan(define_insn "stack_protect_test_di"
21197169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
21198169699Skan	(unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
21199169699Skan		     (match_operand:DI 2 "memory_operand" "m")]
21200169699Skan		    UNSPEC_SP_TEST))
21201169699Skan   (clobber (match_scratch:DI 3 "=&r"))]
21202169699Skan  "TARGET_64BIT"
21203169699Skan  "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%2, %3|%3, %2}"
21204169699Skan  [(set_attr "type" "multi")])
21205117404Skan
21206169699Skan(define_insn "stack_tls_protect_test_si"
21207169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
21208169699Skan	(unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
21209169699Skan		     (match_operand:SI 2 "const_int_operand" "i")]
21210169699Skan		    UNSPEC_SP_TLS_TEST))
21211169699Skan   (clobber (match_scratch:SI 3 "=r"))]
21212169699Skan  ""
21213169699Skan  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR %%gs:%P2}"
21214169699Skan  [(set_attr "type" "multi")])
21215117404Skan
21216169699Skan(define_insn "stack_tls_protect_test_di"
21217169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
21218169699Skan	(unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
21219169699Skan		     (match_operand:DI 2 "const_int_operand" "i")]
21220169699Skan		    UNSPEC_SP_TLS_TEST))
21221169699Skan   (clobber (match_scratch:DI 3 "=r"))]
21222169699Skan  "TARGET_64BIT"
21223169699Skan  {
21224169699Skan     /* The kernel uses a different segment register for performance reasons; a
21225169699Skan        system call would not have to trash the userspace segment register,
21226169699Skan        which would be expensive */
21227169699Skan     if (ix86_cmodel != CM_KERNEL)
21228169699Skan        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}";
21229169699Skan     else
21230169699Skan        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR %%gs:%P2}";
21231169699Skan  }
21232169699Skan  [(set_attr "type" "multi")])
21233117404Skan
21234219639Smm(include "mmx.md")
21235169699Skan(include "sse.md")
21236169699Skan(include "sync.md")
21237