i386.md revision 219639
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)
107169699Skan   (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)
156117404Skan  ])
157117404Skan
158117404Skan(define_constants
159117404Skan  [(UNSPECV_BLOCKAGE		0)
160169699Skan   (UNSPECV_STACK_PROBE		1)
161169699Skan   (UNSPECV_EMMS		2)
162169699Skan   (UNSPECV_LDMXCSR		3)
163169699Skan   (UNSPECV_STMXCSR		4)
164169699Skan   (UNSPECV_FEMMS		5)
165169699Skan   (UNSPECV_CLFLUSH		6)
166169699Skan   (UNSPECV_ALIGN		7)
167169699Skan   (UNSPECV_MONITOR		8)
168169699Skan   (UNSPECV_MWAIT		9)
169169699Skan   (UNSPECV_CMPXCHG_1		10)
170169699Skan   (UNSPECV_CMPXCHG_2		11)
171169699Skan   (UNSPECV_XCHG		12)
172169699Skan   (UNSPECV_LOCK		13)
173117404Skan  ])
174117404Skan
175169699Skan;; Registers by name.
176169699Skan(define_constants
177169699Skan  [(BP_REG			 6)
178169699Skan   (SP_REG			 7)
179169699Skan   (FLAGS_REG			17)
180169699Skan   (FPSR_REG			18)
181169699Skan   (DIRFLAG_REG			19)
182169699Skan  ])
183169699Skan
18490286Sobrien;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
18590286Sobrien;; from i386.c.
18690286Sobrien
18790286Sobrien;; In C guard expressions, put expressions which may be compile-time
18890286Sobrien;; constants first.  This allows for better optimization.  For
18990286Sobrien;; example, write "TARGET_64BIT && reload_completed", not
19090286Sobrien;; "reload_completed && TARGET_64BIT".
19190286Sobrien
19218334Speter
19390286Sobrien;; Processor type.  This attribute must exactly match the processor_type
19490286Sobrien;; enumeration in i386.h.
195219374Smm(define_attr "cpu" "i386,i486,pentium,pentiumpro,geode,k6,athlon,pentium4,k8,nocona,core2,generic32,generic64"
196132727Skan  (const (symbol_ref "ix86_tune")))
19750650Sobrien
19890286Sobrien;; A basic instruction type.  Refinements due to arguments to be
19990286Sobrien;; provided in other attributes.
20052296Sobrien(define_attr "type"
201117404Skan  "other,multi,
202117404Skan   alu,alu1,negnot,imov,imovx,lea,
203117404Skan   incdec,ishift,ishift1,rotate,rotate1,imul,idiv,
204117404Skan   icmp,test,ibr,setcc,icmov,
205132727Skan   push,pop,call,callv,leave,
206117404Skan   str,cld,
207169699Skan   fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
208169699Skan   sselog,sselog1,sseiadd,sseishft,sseimul,
209132727Skan   sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,
210117404Skan   mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
21190286Sobrien  (const_string "other"))
21250650Sobrien
21390286Sobrien;; Main data type used by the insn
214117404Skan(define_attr "mode"
215169699Skan  "unknown,none,QI,HI,SI,DI,SF,DF,XF,TI,V4SF,V2DF,V2SF,V1DF"
21690286Sobrien  (const_string "unknown"))
21752296Sobrien
218117404Skan;; The CPU unit operations uses.
219117404Skan(define_attr "unit" "integer,i387,sse,mmx,unknown"
220169699Skan  (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint")
221117404Skan	   (const_string "i387")
222169699Skan	 (eq_attr "type" "sselog,sselog1,sseiadd,sseishft,sseimul,
223132727Skan			  sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv")
224117404Skan	   (const_string "sse")
225117404Skan	 (eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft")
226117404Skan	   (const_string "mmx")
227117404Skan	 (eq_attr "type" "other")
228117404Skan	   (const_string "unknown")]
229117404Skan	 (const_string "integer")))
23052296Sobrien
23190286Sobrien;; The (bounding maximum) length of an instruction immediate.
23290286Sobrien(define_attr "length_immediate" ""
233132727Skan  (cond [(eq_attr "type" "incdec,setcc,icmov,str,cld,lea,other,multi,idiv,leave")
23490286Sobrien	   (const_int 0)
235117404Skan	 (eq_attr "unit" "i387,sse,mmx")
23690286Sobrien	   (const_int 0)
237117404Skan	 (eq_attr "type" "alu,alu1,negnot,imovx,ishift,rotate,ishift1,rotate1,
238117404Skan			  imul,icmp,push,pop")
23990286Sobrien	   (symbol_ref "ix86_attr_length_immediate_default(insn,1)")
24090286Sobrien	 (eq_attr "type" "imov,test")
24190286Sobrien	   (symbol_ref "ix86_attr_length_immediate_default(insn,0)")
24290286Sobrien	 (eq_attr "type" "call")
24390286Sobrien	   (if_then_else (match_operand 0 "constant_call_address_operand" "")
24490286Sobrien	     (const_int 4)
24590286Sobrien	     (const_int 0))
24690286Sobrien	 (eq_attr "type" "callv")
24790286Sobrien	   (if_then_else (match_operand 1 "constant_call_address_operand" "")
24890286Sobrien	     (const_int 4)
24990286Sobrien	     (const_int 0))
250117404Skan	 ;; We don't know the size before shorten_branches.  Expect
251117404Skan	 ;; the instruction to fit for better scheduling.
25290286Sobrien	 (eq_attr "type" "ibr")
253117404Skan	   (const_int 1)
25490286Sobrien	 ]
255117404Skan	 (symbol_ref "/* Update immediate_length and other attributes! */
256169699Skan		      gcc_unreachable (),1")))
25752296Sobrien
25890286Sobrien;; The (bounding maximum) length of an instruction address.
25990286Sobrien(define_attr "length_address" ""
26090286Sobrien  (cond [(eq_attr "type" "str,cld,other,multi,fxch")
26190286Sobrien	   (const_int 0)
26290286Sobrien	 (and (eq_attr "type" "call")
263117404Skan	      (match_operand 0 "constant_call_address_operand" ""))
26490286Sobrien	     (const_int 0)
26590286Sobrien	 (and (eq_attr "type" "callv")
26690286Sobrien	      (match_operand 1 "constant_call_address_operand" ""))
26790286Sobrien	     (const_int 0)
26890286Sobrien	 ]
26990286Sobrien	 (symbol_ref "ix86_attr_length_address_default (insn)")))
27052296Sobrien
27190286Sobrien;; Set when length prefix is used.
27290286Sobrien(define_attr "prefix_data16" ""
273117404Skan  (if_then_else (ior (eq_attr "mode" "HI")
274117404Skan		     (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF")))
27590286Sobrien    (const_int 1)
27690286Sobrien    (const_int 0)))
27752296Sobrien
27890286Sobrien;; Set when string REP prefix is used.
279117404Skan(define_attr "prefix_rep" "" 
280117404Skan  (if_then_else (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
281117404Skan    (const_int 1)
282117404Skan    (const_int 0)))
28352296Sobrien
28490286Sobrien;; Set when 0f opcode prefix is used.
28590286Sobrien(define_attr "prefix_0f" ""
286117404Skan  (if_then_else 
287132727Skan    (ior (eq_attr "type" "imovx,setcc,icmov")
288132727Skan	 (eq_attr "unit" "sse,mmx"))
28990286Sobrien    (const_int 1)
29090286Sobrien    (const_int 0)))
29152296Sobrien
292169699Skan;; Set when REX opcode prefix is used.
293132727Skan(define_attr "prefix_rex" ""
294132727Skan  (cond [(and (eq_attr "mode" "DI")
295132727Skan  	      (eq_attr "type" "!push,pop,call,callv,leave,ibr"))
296132727Skan	   (const_int 1)
297132727Skan	 (and (eq_attr "mode" "QI")
298132727Skan	      (ne (symbol_ref "x86_extended_QIreg_mentioned_p (insn)")
299132727Skan		  (const_int 0)))
300132727Skan	   (const_int 1)
301132727Skan	 (ne (symbol_ref "x86_extended_reg_mentioned_p (insn)")
302132727Skan	     (const_int 0))
303132727Skan	   (const_int 1)
304132727Skan	]
305132727Skan	(const_int 0)))
306132727Skan
30790286Sobrien;; Set when modrm byte is used.
30890286Sobrien(define_attr "modrm" ""
309132727Skan  (cond [(eq_attr "type" "str,cld,leave")
31090286Sobrien	   (const_int 0)
311117404Skan	 (eq_attr "unit" "i387")
31290286Sobrien	   (const_int 0)
31390286Sobrien         (and (eq_attr "type" "incdec")
31490286Sobrien	      (ior (match_operand:SI 1 "register_operand" "")
31590286Sobrien		   (match_operand:HI 1 "register_operand" "")))
31690286Sobrien	   (const_int 0)
31790286Sobrien	 (and (eq_attr "type" "push")
31890286Sobrien	      (not (match_operand 1 "memory_operand" "")))
31990286Sobrien	   (const_int 0)
32090286Sobrien	 (and (eq_attr "type" "pop")
32190286Sobrien	      (not (match_operand 0 "memory_operand" "")))
32290286Sobrien	   (const_int 0)
32390286Sobrien	 (and (eq_attr "type" "imov")
324169699Skan	      (ior (and (match_operand 0 "register_operand" "")
325169699Skan			(match_operand 1 "immediate_operand" ""))
326169699Skan		   (ior (and (match_operand 0 "ax_reg_operand" "")
327169699Skan			     (match_operand 1 "memory_displacement_only_operand" ""))
328169699Skan			(and (match_operand 0 "memory_displacement_only_operand" "")
329169699Skan			     (match_operand 1 "ax_reg_operand" "")))))
33090286Sobrien	   (const_int 0)
331117404Skan	 (and (eq_attr "type" "call")
332117404Skan	      (match_operand 0 "constant_call_address_operand" ""))
333117404Skan	     (const_int 0)
334117404Skan	 (and (eq_attr "type" "callv")
335117404Skan	      (match_operand 1 "constant_call_address_operand" ""))
336117404Skan	     (const_int 0)
33790286Sobrien	 ]
33890286Sobrien	 (const_int 1)))
33990286Sobrien
34090286Sobrien;; The (bounding maximum) length of an instruction in bytes.
341169699Skan;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences.
342169699Skan;; Later we may want to split them and compute proper length as for
343169699Skan;; other insns.
34490286Sobrien(define_attr "length" ""
345169699Skan  (cond [(eq_attr "type" "other,multi,fistp,frndint")
34690286Sobrien	   (const_int 16)
347117404Skan	 (eq_attr "type" "fcmp")
348117404Skan	   (const_int 4)
349117404Skan	 (eq_attr "unit" "i387")
350117404Skan	   (plus (const_int 2)
351117404Skan		 (plus (attr "prefix_data16")
352117404Skan		       (attr "length_address")))]
35390286Sobrien	 (plus (plus (attr "modrm")
35490286Sobrien		     (plus (attr "prefix_0f")
355132727Skan			   (plus (attr "prefix_rex")
356132727Skan				 (const_int 1))))
35790286Sobrien	       (plus (attr "prefix_rep")
35890286Sobrien		     (plus (attr "prefix_data16")
35990286Sobrien			   (plus (attr "length_immediate")
36090286Sobrien				 (attr "length_address")))))))
36190286Sobrien
36290286Sobrien;; The `memory' attribute is `none' if no memory is referenced, `load' or
36390286Sobrien;; `store' if there is a simple memory reference therein, or `unknown'
36490286Sobrien;; if the instruction is complex.
36590286Sobrien
36690286Sobrien(define_attr "memory" "none,load,store,both,unknown"
36790286Sobrien  (cond [(eq_attr "type" "other,multi,str")
36890286Sobrien	   (const_string "unknown")
36990286Sobrien	 (eq_attr "type" "lea,fcmov,fpspc,cld")
37090286Sobrien	   (const_string "none")
371132727Skan	 (eq_attr "type" "fistp,leave")
37290286Sobrien	   (const_string "both")
373169699Skan	 (eq_attr "type" "frndint")
374169699Skan	   (const_string "load")
37590286Sobrien	 (eq_attr "type" "push")
37690286Sobrien	   (if_then_else (match_operand 1 "memory_operand" "")
37790286Sobrien	     (const_string "both")
37890286Sobrien	     (const_string "store"))
379132727Skan	 (eq_attr "type" "pop")
38090286Sobrien	   (if_then_else (match_operand 0 "memory_operand" "")
38190286Sobrien	     (const_string "both")
38290286Sobrien	     (const_string "load"))
383132727Skan	 (eq_attr "type" "setcc")
384132727Skan	   (if_then_else (match_operand 0 "memory_operand" "")
385132727Skan	     (const_string "store")
386132727Skan	     (const_string "none"))
387132727Skan	 (eq_attr "type" "icmp,test,ssecmp,ssecomi,mmxcmp,fcmp")
38890286Sobrien	   (if_then_else (ior (match_operand 0 "memory_operand" "")
38990286Sobrien			      (match_operand 1 "memory_operand" ""))
39090286Sobrien	     (const_string "load")
39190286Sobrien	     (const_string "none"))
39290286Sobrien	 (eq_attr "type" "ibr")
39390286Sobrien	   (if_then_else (match_operand 0 "memory_operand" "")
39490286Sobrien	     (const_string "load")
39590286Sobrien	     (const_string "none"))
39690286Sobrien	 (eq_attr "type" "call")
39790286Sobrien	   (if_then_else (match_operand 0 "constant_call_address_operand" "")
39890286Sobrien	     (const_string "none")
39990286Sobrien	     (const_string "load"))
40090286Sobrien	 (eq_attr "type" "callv")
40190286Sobrien	   (if_then_else (match_operand 1 "constant_call_address_operand" "")
40290286Sobrien	     (const_string "none")
40390286Sobrien	     (const_string "load"))
404169699Skan	 (and (eq_attr "type" "alu1,negnot,ishift1,sselog1")
40590286Sobrien	      (match_operand 1 "memory_operand" ""))
40690286Sobrien	   (const_string "both")
40790286Sobrien	 (and (match_operand 0 "memory_operand" "")
40890286Sobrien	      (match_operand 1 "memory_operand" ""))
40990286Sobrien	   (const_string "both")
41090286Sobrien	 (match_operand 0 "memory_operand" "")
41190286Sobrien	   (const_string "store")
41290286Sobrien	 (match_operand 1 "memory_operand" "")
41390286Sobrien	   (const_string "load")
414117404Skan	 (and (eq_attr "type"
415132727Skan		 "!alu1,negnot,ishift1,
416117404Skan		   imov,imovx,icmp,test,
417117404Skan		   fmov,fcmp,fsgn,
418169699Skan		   sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt,sselog1,
419117404Skan		   mmx,mmxmov,mmxcmp,mmxcvt")
42090286Sobrien	      (match_operand 2 "memory_operand" ""))
42190286Sobrien	   (const_string "load")
42290286Sobrien	 (and (eq_attr "type" "icmov")
42390286Sobrien	      (match_operand 3 "memory_operand" ""))
42490286Sobrien	   (const_string "load")
42590286Sobrien	]
42652296Sobrien	(const_string "none")))
42752296Sobrien
42890286Sobrien;; Indicates if an instruction has both an immediate and a displacement.
42950650Sobrien
43090286Sobrien(define_attr "imm_disp" "false,true,unknown"
43190286Sobrien  (cond [(eq_attr "type" "other,multi")
43290286Sobrien	   (const_string "unknown")
433117404Skan	 (and (eq_attr "type" "icmp,test,imov,alu1,ishift1,rotate1")
43490286Sobrien	      (and (match_operand 0 "memory_displacement_operand" "")
43590286Sobrien		   (match_operand 1 "immediate_operand" "")))
43690286Sobrien	   (const_string "true")
437117404Skan	 (and (eq_attr "type" "alu,ishift,rotate,imul,idiv")
43890286Sobrien	      (and (match_operand 0 "memory_displacement_operand" "")
43990286Sobrien		   (match_operand 2 "immediate_operand" "")))
44090286Sobrien	   (const_string "true")
44190286Sobrien	]
44290286Sobrien	(const_string "false")))
44350650Sobrien
44490286Sobrien;; Indicates if an FP operation has an integer source.
44550650Sobrien
44690286Sobrien(define_attr "fp_int_src" "false,true"
44790286Sobrien  (const_string "false"))
44850650Sobrien
449169699Skan;; Defines rounding mode of an FP operation.
450169699Skan
451169699Skan(define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any"
452169699Skan  (const_string "any"))
453169699Skan
45490286Sobrien;; Describe a user's asm statement.
45590286Sobrien(define_asm_attributes
45690286Sobrien  [(set_attr "length" "128")
45790286Sobrien   (set_attr "type" "multi")])
458169699Skan
459169699Skan;; All x87 floating point modes
460169699Skan(define_mode_macro X87MODEF [SF DF XF])
461169699Skan 
462169699Skan;; All integer modes handled by x87 fisttp operator.
463169699Skan(define_mode_macro X87MODEI [HI SI DI])
464169699Skan
465169699Skan;; All integer modes handled by integer x87 operators.
466169699Skan(define_mode_macro X87MODEI12 [HI SI])
467169699Skan
468169699Skan;; All SSE floating point modes
469169699Skan(define_mode_macro SSEMODEF [SF DF])
470169699Skan 
471169699Skan;; All integer modes handled by SSE cvtts?2si* operators.
472169699Skan(define_mode_macro SSEMODEI24 [SI DI])
473169699Skan
47490286Sobrien
475169699Skan;; Scheduling descriptions
476169699Skan
477117404Skan(include "pentium.md")
478117404Skan(include "ppro.md")
479117404Skan(include "k6.md")
480117404Skan(include "athlon.md")
481219374Smm(include "geode.md")
482169699Skan
48390286Sobrien
484169699Skan;; Operand and operator predicates and constraints
485169699Skan
486169699Skan(include "predicates.md")
487169699Skan(include "constraints.md")
488169699Skan
489169699Skan
49090286Sobrien;; Compare instructions.
49190286Sobrien
49290286Sobrien;; All compare insns have expanders that save the operands away without
49390286Sobrien;; actually generating RTL.  The bCOND or sCOND (emitted immediately
49490286Sobrien;; after the cmp) will actually emit the cmpM.
49590286Sobrien
496169699Skan(define_expand "cmpti"
497169699Skan  [(set (reg:CC FLAGS_REG)
498169699Skan	(compare:CC (match_operand:TI 0 "nonimmediate_operand" "")
499169699Skan		    (match_operand:TI 1 "x86_64_general_operand" "")))]
500169699Skan  "TARGET_64BIT"
501169699Skan{
502169699Skan  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
503169699Skan    operands[0] = force_reg (TImode, operands[0]);
504169699Skan  ix86_compare_op0 = operands[0];
505169699Skan  ix86_compare_op1 = operands[1];
506169699Skan  DONE;
507169699Skan})
508169699Skan
50990286Sobrien(define_expand "cmpdi"
510169699Skan  [(set (reg:CC FLAGS_REG)
51190286Sobrien	(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
51290286Sobrien		    (match_operand:DI 1 "x86_64_general_operand" "")))]
51390286Sobrien  ""
51418334Speter{
51590286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
51690286Sobrien    operands[0] = force_reg (DImode, operands[0]);
51790286Sobrien  ix86_compare_op0 = operands[0];
51890286Sobrien  ix86_compare_op1 = operands[1];
51918334Speter  DONE;
52090286Sobrien})
52118334Speter
52218334Speter(define_expand "cmpsi"
523169699Skan  [(set (reg:CC FLAGS_REG)
52490286Sobrien	(compare:CC (match_operand:SI 0 "cmpsi_operand" "")
52590286Sobrien		    (match_operand:SI 1 "general_operand" "")))]
52618334Speter  ""
52718334Speter{
52818334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
52918334Speter    operands[0] = force_reg (SImode, operands[0]);
53090286Sobrien  ix86_compare_op0 = operands[0];
53190286Sobrien  ix86_compare_op1 = operands[1];
53218334Speter  DONE;
53390286Sobrien})
53418334Speter
53518334Speter(define_expand "cmphi"
536169699Skan  [(set (reg:CC FLAGS_REG)
53790286Sobrien	(compare:CC (match_operand:HI 0 "nonimmediate_operand" "")
53890286Sobrien		    (match_operand:HI 1 "general_operand" "")))]
53918334Speter  ""
54018334Speter{
54118334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
54218334Speter    operands[0] = force_reg (HImode, operands[0]);
54390286Sobrien  ix86_compare_op0 = operands[0];
54490286Sobrien  ix86_compare_op1 = operands[1];
54518334Speter  DONE;
54690286Sobrien})
54718334Speter
54818334Speter(define_expand "cmpqi"
549169699Skan  [(set (reg:CC FLAGS_REG)
55090286Sobrien	(compare:CC (match_operand:QI 0 "nonimmediate_operand" "")
55190286Sobrien		    (match_operand:QI 1 "general_operand" "")))]
55290286Sobrien  "TARGET_QIMODE_MATH"
55318334Speter{
55418334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
55518334Speter    operands[0] = force_reg (QImode, operands[0]);
55690286Sobrien  ix86_compare_op0 = operands[0];
55790286Sobrien  ix86_compare_op1 = operands[1];
55818334Speter  DONE;
55990286Sobrien})
56018334Speter
56190286Sobrien(define_insn "cmpdi_ccno_1_rex64"
562169699Skan  [(set (reg FLAGS_REG)
56390286Sobrien	(compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")
56490286Sobrien		 (match_operand:DI 1 "const0_operand" "n,n")))]
56590286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
56690286Sobrien  "@
56790286Sobrien   test{q}\t{%0, %0|%0, %0}
56890286Sobrien   cmp{q}\t{%1, %0|%0, %1}"
56990286Sobrien  [(set_attr "type" "test,icmp")
57090286Sobrien   (set_attr "length_immediate" "0,1")
57190286Sobrien   (set_attr "mode" "DI")])
57218334Speter
57390286Sobrien(define_insn "*cmpdi_minus_1_rex64"
574169699Skan  [(set (reg FLAGS_REG)
57590286Sobrien	(compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r")
57690286Sobrien			   (match_operand:DI 1 "x86_64_general_operand" "re,mr"))
57790286Sobrien		 (const_int 0)))]
57890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)"
57990286Sobrien  "cmp{q}\t{%1, %0|%0, %1}"
58090286Sobrien  [(set_attr "type" "icmp")
58190286Sobrien   (set_attr "mode" "DI")])
58218334Speter
58390286Sobrien(define_expand "cmpdi_1_rex64"
584169699Skan  [(set (reg:CC FLAGS_REG)
58590286Sobrien	(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
58690286Sobrien		    (match_operand:DI 1 "general_operand" "")))]
58790286Sobrien  "TARGET_64BIT"
58890286Sobrien  "")
58918334Speter
59090286Sobrien(define_insn "cmpdi_1_insn_rex64"
591169699Skan  [(set (reg FLAGS_REG)
59290286Sobrien	(compare (match_operand:DI 0 "nonimmediate_operand" "mr,r")
59390286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "re,mr")))]
59490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
59590286Sobrien  "cmp{q}\t{%1, %0|%0, %1}"
59690286Sobrien  [(set_attr "type" "icmp")
59790286Sobrien   (set_attr "mode" "DI")])
59850650Sobrien
59918334Speter
60090286Sobrien(define_insn "*cmpsi_ccno_1"
601169699Skan  [(set (reg FLAGS_REG)
60290286Sobrien	(compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
60390286Sobrien		 (match_operand:SI 1 "const0_operand" "n,n")))]
60490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
60590286Sobrien  "@
60690286Sobrien   test{l}\t{%0, %0|%0, %0}
60790286Sobrien   cmp{l}\t{%1, %0|%0, %1}"
60890286Sobrien  [(set_attr "type" "test,icmp")
60990286Sobrien   (set_attr "length_immediate" "0,1")
61090286Sobrien   (set_attr "mode" "SI")])
61150650Sobrien
61290286Sobrien(define_insn "*cmpsi_minus_1"
613169699Skan  [(set (reg FLAGS_REG)
61490286Sobrien	(compare (minus:SI (match_operand:SI 0 "nonimmediate_operand" "rm,r")
61590286Sobrien			   (match_operand:SI 1 "general_operand" "ri,mr"))
61690286Sobrien		 (const_int 0)))]
61790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
61890286Sobrien  "cmp{l}\t{%1, %0|%0, %1}"
61990286Sobrien  [(set_attr "type" "icmp")
62090286Sobrien   (set_attr "mode" "SI")])
62118334Speter
62290286Sobrien(define_expand "cmpsi_1"
623169699Skan  [(set (reg:CC FLAGS_REG)
62490286Sobrien	(compare:CC (match_operand:SI 0 "nonimmediate_operand" "rm,r")
62590286Sobrien		    (match_operand:SI 1 "general_operand" "ri,mr")))]
62690286Sobrien  ""
62790286Sobrien  "")
62818334Speter
62990286Sobrien(define_insn "*cmpsi_1_insn"
630169699Skan  [(set (reg FLAGS_REG)
63190286Sobrien	(compare (match_operand:SI 0 "nonimmediate_operand" "rm,r")
63290286Sobrien		 (match_operand:SI 1 "general_operand" "ri,mr")))]
63390286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
63490286Sobrien    && ix86_match_ccmode (insn, CCmode)"
63590286Sobrien  "cmp{l}\t{%1, %0|%0, %1}"
63690286Sobrien  [(set_attr "type" "icmp")
63790286Sobrien   (set_attr "mode" "SI")])
63818334Speter
63990286Sobrien(define_insn "*cmphi_ccno_1"
640169699Skan  [(set (reg FLAGS_REG)
64190286Sobrien	(compare (match_operand:HI 0 "nonimmediate_operand" "r,?mr")
64290286Sobrien		 (match_operand:HI 1 "const0_operand" "n,n")))]
64390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
64490286Sobrien  "@
64590286Sobrien   test{w}\t{%0, %0|%0, %0}
64690286Sobrien   cmp{w}\t{%1, %0|%0, %1}"
64790286Sobrien  [(set_attr "type" "test,icmp")
64890286Sobrien   (set_attr "length_immediate" "0,1")
64990286Sobrien   (set_attr "mode" "HI")])
65018334Speter
65190286Sobrien(define_insn "*cmphi_minus_1"
652169699Skan  [(set (reg FLAGS_REG)
65390286Sobrien	(compare (minus:HI (match_operand:HI 0 "nonimmediate_operand" "rm,r")
65490286Sobrien			   (match_operand:HI 1 "general_operand" "ri,mr"))
65590286Sobrien		 (const_int 0)))]
65690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
65790286Sobrien  "cmp{w}\t{%1, %0|%0, %1}"
65890286Sobrien  [(set_attr "type" "icmp")
65990286Sobrien   (set_attr "mode" "HI")])
66050650Sobrien
66190286Sobrien(define_insn "*cmphi_1"
662169699Skan  [(set (reg FLAGS_REG)
66390286Sobrien	(compare (match_operand:HI 0 "nonimmediate_operand" "rm,r")
66490286Sobrien		 (match_operand:HI 1 "general_operand" "ri,mr")))]
66590286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
66690286Sobrien   && ix86_match_ccmode (insn, CCmode)"
66790286Sobrien  "cmp{w}\t{%1, %0|%0, %1}"
66890286Sobrien  [(set_attr "type" "icmp")
66990286Sobrien   (set_attr "mode" "HI")])
67018334Speter
67190286Sobrien(define_insn "*cmpqi_ccno_1"
672169699Skan  [(set (reg FLAGS_REG)
67390286Sobrien	(compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq")
67490286Sobrien		 (match_operand:QI 1 "const0_operand" "n,n")))]
67590286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
67690286Sobrien  "@
67790286Sobrien   test{b}\t{%0, %0|%0, %0}
67890286Sobrien   cmp{b}\t{$0, %0|%0, 0}"
67990286Sobrien  [(set_attr "type" "test,icmp")
68090286Sobrien   (set_attr "length_immediate" "0,1")
68190286Sobrien   (set_attr "mode" "QI")])
68218334Speter
68390286Sobrien(define_insn "*cmpqi_1"
684169699Skan  [(set (reg FLAGS_REG)
68590286Sobrien	(compare (match_operand:QI 0 "nonimmediate_operand" "qm,q")
68690286Sobrien		 (match_operand:QI 1 "general_operand" "qi,mq")))]
68790286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
68890286Sobrien    && ix86_match_ccmode (insn, CCmode)"
68990286Sobrien  "cmp{b}\t{%1, %0|%0, %1}"
69090286Sobrien  [(set_attr "type" "icmp")
69190286Sobrien   (set_attr "mode" "QI")])
69218334Speter
69390286Sobrien(define_insn "*cmpqi_minus_1"
694169699Skan  [(set (reg FLAGS_REG)
69590286Sobrien	(compare (minus:QI (match_operand:QI 0 "nonimmediate_operand" "qm,q")
69690286Sobrien			   (match_operand:QI 1 "general_operand" "qi,mq"))
69790286Sobrien		 (const_int 0)))]
69890286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
69990286Sobrien  "cmp{b}\t{%1, %0|%0, %1}"
70090286Sobrien  [(set_attr "type" "icmp")
70190286Sobrien   (set_attr "mode" "QI")])
70218334Speter
70390286Sobrien(define_insn "*cmpqi_ext_1"
704169699Skan  [(set (reg FLAGS_REG)
70590286Sobrien	(compare
70690286Sobrien	  (match_operand:QI 0 "general_operand" "Qm")
70790286Sobrien	  (subreg:QI
70890286Sobrien	    (zero_extract:SI
70990286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
71090286Sobrien	      (const_int 8)
71190286Sobrien	      (const_int 8)) 0)))]
71290286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
71390286Sobrien  "cmp{b}\t{%h1, %0|%0, %h1}"
71490286Sobrien  [(set_attr "type" "icmp")
71590286Sobrien   (set_attr "mode" "QI")])
71690286Sobrien
71790286Sobrien(define_insn "*cmpqi_ext_1_rex64"
718169699Skan  [(set (reg FLAGS_REG)
71990286Sobrien	(compare
72090286Sobrien	  (match_operand:QI 0 "register_operand" "Q")
72190286Sobrien	  (subreg:QI
72290286Sobrien	    (zero_extract:SI
72390286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
72490286Sobrien	      (const_int 8)
72590286Sobrien	      (const_int 8)) 0)))]
72690286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
72790286Sobrien  "cmp{b}\t{%h1, %0|%0, %h1}"
72890286Sobrien  [(set_attr "type" "icmp")
72990286Sobrien   (set_attr "mode" "QI")])
73090286Sobrien
73190286Sobrien(define_insn "*cmpqi_ext_2"
732169699Skan  [(set (reg FLAGS_REG)
73390286Sobrien	(compare
73490286Sobrien	  (subreg:QI
73590286Sobrien	    (zero_extract:SI
73690286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
73790286Sobrien	      (const_int 8)
73890286Sobrien	      (const_int 8)) 0)
73990286Sobrien	  (match_operand:QI 1 "const0_operand" "n")))]
74090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
74190286Sobrien  "test{b}\t%h0, %h0"
74290286Sobrien  [(set_attr "type" "test")
74390286Sobrien   (set_attr "length_immediate" "0")
74490286Sobrien   (set_attr "mode" "QI")])
74590286Sobrien
74690286Sobrien(define_expand "cmpqi_ext_3"
747169699Skan  [(set (reg:CC FLAGS_REG)
74890286Sobrien	(compare:CC
74990286Sobrien	  (subreg:QI
75090286Sobrien	    (zero_extract:SI
75190286Sobrien	      (match_operand 0 "ext_register_operand" "")
75290286Sobrien	      (const_int 8)
75390286Sobrien	      (const_int 8)) 0)
75490286Sobrien	  (match_operand:QI 1 "general_operand" "")))]
75590286Sobrien  ""
75690286Sobrien  "")
75790286Sobrien
75890286Sobrien(define_insn "cmpqi_ext_3_insn"
759169699Skan  [(set (reg FLAGS_REG)
76090286Sobrien	(compare
76190286Sobrien	  (subreg:QI
76290286Sobrien	    (zero_extract:SI
76390286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
76490286Sobrien	      (const_int 8)
76590286Sobrien	      (const_int 8)) 0)
76690286Sobrien	  (match_operand:QI 1 "general_operand" "Qmn")))]
76790286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
76890286Sobrien  "cmp{b}\t{%1, %h0|%h0, %1}"
76990286Sobrien  [(set_attr "type" "icmp")
77090286Sobrien   (set_attr "mode" "QI")])
77190286Sobrien
77290286Sobrien(define_insn "cmpqi_ext_3_insn_rex64"
773169699Skan  [(set (reg FLAGS_REG)
77490286Sobrien	(compare
77590286Sobrien	  (subreg:QI
77690286Sobrien	    (zero_extract:SI
77790286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
77890286Sobrien	      (const_int 8)
77990286Sobrien	      (const_int 8)) 0)
78090286Sobrien	  (match_operand:QI 1 "nonmemory_operand" "Qn")))]
78190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
78290286Sobrien  "cmp{b}\t{%1, %h0|%h0, %1}"
78390286Sobrien  [(set_attr "type" "icmp")
78490286Sobrien   (set_attr "mode" "QI")])
78590286Sobrien
78690286Sobrien(define_insn "*cmpqi_ext_4"
787169699Skan  [(set (reg FLAGS_REG)
78890286Sobrien	(compare
78990286Sobrien	  (subreg:QI
79090286Sobrien	    (zero_extract:SI
79190286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
79290286Sobrien	      (const_int 8)
79390286Sobrien	      (const_int 8)) 0)
79490286Sobrien	  (subreg:QI
79590286Sobrien	    (zero_extract:SI
79690286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
79790286Sobrien	      (const_int 8)
79890286Sobrien	      (const_int 8)) 0)))]
79990286Sobrien  "ix86_match_ccmode (insn, CCmode)"
80090286Sobrien  "cmp{b}\t{%h1, %h0|%h0, %h1}"
80190286Sobrien  [(set_attr "type" "icmp")
80290286Sobrien   (set_attr "mode" "QI")])
80390286Sobrien
80490286Sobrien;; These implement float point compares.
80590286Sobrien;; %%% See if we can get away with VOIDmode operands on the actual insns,
80690286Sobrien;; which would allow mix and match FP modes on the compares.  Which is what
80790286Sobrien;; the old patterns did, but with many more of them.
80890286Sobrien
80918334Speter(define_expand "cmpxf"
810169699Skan  [(set (reg:CC FLAGS_REG)
811169699Skan	(compare:CC (match_operand:XF 0 "nonmemory_operand" "")
812169699Skan		    (match_operand:XF 1 "nonmemory_operand" "")))]
81318334Speter  "TARGET_80387"
81418334Speter{
81590286Sobrien  ix86_compare_op0 = operands[0];
81690286Sobrien  ix86_compare_op1 = operands[1];
81718334Speter  DONE;
81890286Sobrien})
81918334Speter
82018334Speter(define_expand "cmpdf"
821169699Skan  [(set (reg:CC FLAGS_REG)
82290286Sobrien	(compare:CC (match_operand:DF 0 "cmp_fp_expander_operand" "")
82390286Sobrien		    (match_operand:DF 1 "cmp_fp_expander_operand" "")))]
824169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
82518334Speter{
82690286Sobrien  ix86_compare_op0 = operands[0];
82790286Sobrien  ix86_compare_op1 = operands[1];
82818334Speter  DONE;
82990286Sobrien})
83018334Speter
83118334Speter(define_expand "cmpsf"
832169699Skan  [(set (reg:CC FLAGS_REG)
83390286Sobrien	(compare:CC (match_operand:SF 0 "cmp_fp_expander_operand" "")
83490286Sobrien		    (match_operand:SF 1 "cmp_fp_expander_operand" "")))]
835169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
83618334Speter{
83790286Sobrien  ix86_compare_op0 = operands[0];
83890286Sobrien  ix86_compare_op1 = operands[1];
83918334Speter  DONE;
84090286Sobrien})
84118334Speter
84290286Sobrien;; FP compares, step 1:
84390286Sobrien;; Set the FP condition codes.
84490286Sobrien;;
84590286Sobrien;; CCFPmode	compare with exceptions
84690286Sobrien;; CCFPUmode	compare with no exceptions
84718334Speter
848169699Skan;; We may not use "#" to split and emit these, since the REG_DEAD notes
849169699Skan;; used to manage the reg stack popping would not be preserved.
85018334Speter
85190286Sobrien(define_insn "*cmpfp_0"
85290286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
85390286Sobrien	(unspec:HI
854169699Skan	  [(compare:CCFP
855169699Skan	     (match_operand 1 "register_operand" "f")
856169699Skan	     (match_operand 2 "const0_operand" "X"))]
857169699Skan	UNSPEC_FNSTSW))]
85890286Sobrien  "TARGET_80387
85990286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
86090286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
861169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
86290286Sobrien  [(set_attr "type" "multi")
863169699Skan   (set_attr "unit" "i387")
864132727Skan   (set (attr "mode")
865132727Skan     (cond [(match_operand:SF 1 "" "")
866132727Skan	      (const_string "SF")
867132727Skan	    (match_operand:DF 1 "" "")
868132727Skan	      (const_string "DF")
869132727Skan	   ]
870132727Skan	   (const_string "XF")))])
87190286Sobrien
872169699Skan(define_insn "*cmpfp_sf"
87390286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
87490286Sobrien	(unspec:HI
87590286Sobrien	  [(compare:CCFP
87690286Sobrien	     (match_operand:SF 1 "register_operand" "f")
877117404Skan	     (match_operand:SF 2 "nonimmediate_operand" "fm"))]
878117404Skan	  UNSPEC_FNSTSW))]
87918334Speter  "TARGET_80387"
880169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
881169699Skan  [(set_attr "type" "multi")
882169699Skan   (set_attr "unit" "i387")
88390286Sobrien   (set_attr "mode" "SF")])
88418334Speter
885169699Skan(define_insn "*cmpfp_df"
88690286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
88790286Sobrien	(unspec:HI
88890286Sobrien	  [(compare:CCFP
88990286Sobrien	     (match_operand:DF 1 "register_operand" "f")
890117404Skan	     (match_operand:DF 2 "nonimmediate_operand" "fm"))]
891117404Skan	  UNSPEC_FNSTSW))]
89218334Speter  "TARGET_80387"
893169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
89490286Sobrien  [(set_attr "type" "multi")
895169699Skan   (set_attr "unit" "i387")
89690286Sobrien   (set_attr "mode" "DF")])
89718334Speter
898169699Skan(define_insn "*cmpfp_xf"
89990286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
90090286Sobrien	(unspec:HI
90190286Sobrien	  [(compare:CCFP
90290286Sobrien	     (match_operand:XF 1 "register_operand" "f")
903117404Skan	     (match_operand:XF 2 "register_operand" "f"))]
904117404Skan	  UNSPEC_FNSTSW))]
90590286Sobrien  "TARGET_80387"
906169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
90790286Sobrien  [(set_attr "type" "multi")
908169699Skan   (set_attr "unit" "i387")
90990286Sobrien   (set_attr "mode" "XF")])
91018334Speter
911169699Skan(define_insn "*cmpfp_u"
91290286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
91390286Sobrien	(unspec:HI
91490286Sobrien	  [(compare:CCFPU
91590286Sobrien	     (match_operand 1 "register_operand" "f")
916117404Skan	     (match_operand 2 "register_operand" "f"))]
917117404Skan	  UNSPEC_FNSTSW))]
91890286Sobrien  "TARGET_80387
91990286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
92090286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
921169699Skan  "* return output_fp_compare (insn, operands, 0, 1);"
92290286Sobrien  [(set_attr "type" "multi")
923169699Skan   (set_attr "unit" "i387")
924132727Skan   (set (attr "mode")
925132727Skan     (cond [(match_operand:SF 1 "" "")
926132727Skan	      (const_string "SF")
927132727Skan	    (match_operand:DF 1 "" "")
928132727Skan	      (const_string "DF")
929132727Skan	   ]
930132727Skan	   (const_string "XF")))])
93118334Speter
932169699Skan(define_insn "*cmpfp_<mode>"
933169699Skan  [(set (match_operand:HI 0 "register_operand" "=a")
934169699Skan	(unspec:HI
935169699Skan	  [(compare:CCFP
936169699Skan	     (match_operand 1 "register_operand" "f")
937169699Skan	     (match_operator 3 "float_operator"
938169699Skan	       [(match_operand:X87MODEI12 2 "memory_operand" "m")]))]
939169699Skan	  UNSPEC_FNSTSW))]
940169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
941169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
942169699Skan   && (GET_MODE (operands [3]) == GET_MODE (operands[1]))"
943169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
944169699Skan  [(set_attr "type" "multi")
945169699Skan   (set_attr "unit" "i387")
946169699Skan   (set_attr "fp_int_src" "true")
947169699Skan   (set_attr "mode" "<MODE>")])
94818334Speter
94990286Sobrien;; FP compares, step 2
95090286Sobrien;; Move the fpsw to ax.
95118334Speter
952169699Skan(define_insn "x86_fnstsw_1"
95390286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
954169699Skan	(unspec:HI [(reg:CCFP FPSR_REG)] UNSPEC_FNSTSW))]
95590286Sobrien  "TARGET_80387"
95690286Sobrien  "fnstsw\t%0"
95790286Sobrien  [(set_attr "length" "2")
95890286Sobrien   (set_attr "mode" "SI")
959169699Skan   (set_attr "unit" "i387")])
96018334Speter
96190286Sobrien;; FP compares, step 3
96290286Sobrien;; Get ax into flags, general case.
96350650Sobrien
96490286Sobrien(define_insn "x86_sahf_1"
965169699Skan  [(set (reg:CC FLAGS_REG)
966117404Skan	(unspec:CC [(match_operand:HI 0 "register_operand" "a")] UNSPEC_SAHF))]
96790286Sobrien  "!TARGET_64BIT"
96890286Sobrien  "sahf"
96990286Sobrien  [(set_attr "length" "1")
97090286Sobrien   (set_attr "athlon_decode" "vector")
971169699Skan   (set_attr "mode" "SI")])
97218334Speter
97390286Sobrien;; Pentium Pro can do steps 1 through 3 in one go.
97418334Speter
975169699Skan(define_insn "*cmpfp_i_mixed"
976169699Skan  [(set (reg:CCFP FLAGS_REG)
977169699Skan	(compare:CCFP (match_operand 0 "register_operand" "f,x")
978169699Skan		      (match_operand 1 "nonimmediate_operand" "f,xm")))]
979169699Skan  "TARGET_MIX_SSE_I387
98090286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
981169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
98290286Sobrien  "* return output_fp_compare (insn, operands, 1, 0);"
983132727Skan  [(set_attr "type" "fcmp,ssecomi")
984132727Skan   (set (attr "mode")
985132727Skan     (if_then_else (match_operand:SF 1 "" "")
986132727Skan        (const_string "SF")
987132727Skan        (const_string "DF")))
98890286Sobrien   (set_attr "athlon_decode" "vector")])
98918334Speter
990169699Skan(define_insn "*cmpfp_i_sse"
991169699Skan  [(set (reg:CCFP FLAGS_REG)
99290286Sobrien	(compare:CCFP (match_operand 0 "register_operand" "x")
99390286Sobrien		      (match_operand 1 "nonimmediate_operand" "xm")))]
994169699Skan  "TARGET_SSE_MATH
995169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
996169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
99790286Sobrien  "* return output_fp_compare (insn, operands, 1, 0);"
998132727Skan  [(set_attr "type" "ssecomi")
999132727Skan   (set (attr "mode")
1000132727Skan     (if_then_else (match_operand:SF 1 "" "")
1001132727Skan        (const_string "SF")
1002132727Skan        (const_string "DF")))
100390286Sobrien   (set_attr "athlon_decode" "vector")])
100418334Speter
1005169699Skan(define_insn "*cmpfp_i_i387"
1006169699Skan  [(set (reg:CCFP FLAGS_REG)
1007169699Skan	(compare:CCFP (match_operand 0 "register_operand" "f")
1008169699Skan		      (match_operand 1 "register_operand" "f")))]
100990286Sobrien  "TARGET_80387 && TARGET_CMOVE
1010169699Skan   && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
101190286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))
101290286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
1013169699Skan  "* return output_fp_compare (insn, operands, 1, 0);"
101490286Sobrien  [(set_attr "type" "fcmp")
1015132727Skan   (set (attr "mode")
1016132727Skan     (cond [(match_operand:SF 1 "" "")
1017132727Skan	      (const_string "SF")
1018132727Skan	    (match_operand:DF 1 "" "")
1019132727Skan	      (const_string "DF")
1020132727Skan	   ]
1021132727Skan	   (const_string "XF")))
102290286Sobrien   (set_attr "athlon_decode" "vector")])
102318334Speter
1024169699Skan(define_insn "*cmpfp_iu_mixed"
1025169699Skan  [(set (reg:CCFPU FLAGS_REG)
1026169699Skan	(compare:CCFPU (match_operand 0 "register_operand" "f,x")
1027169699Skan		       (match_operand 1 "nonimmediate_operand" "f,xm")))]
1028169699Skan  "TARGET_MIX_SSE_I387
102990286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
103090286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
103190286Sobrien  "* return output_fp_compare (insn, operands, 1, 1);"
1032132727Skan  [(set_attr "type" "fcmp,ssecomi")
1033132727Skan   (set (attr "mode")
1034132727Skan     (if_then_else (match_operand:SF 1 "" "")
1035132727Skan        (const_string "SF")
1036132727Skan        (const_string "DF")))
103790286Sobrien   (set_attr "athlon_decode" "vector")])
103850650Sobrien
1039169699Skan(define_insn "*cmpfp_iu_sse"
1040169699Skan  [(set (reg:CCFPU FLAGS_REG)
104190286Sobrien	(compare:CCFPU (match_operand 0 "register_operand" "x")
104290286Sobrien		       (match_operand 1 "nonimmediate_operand" "xm")))]
1043169699Skan  "TARGET_SSE_MATH
1044169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
104590286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
104690286Sobrien  "* return output_fp_compare (insn, operands, 1, 1);"
1047132727Skan  [(set_attr "type" "ssecomi")
1048132727Skan   (set (attr "mode")
1049132727Skan     (if_then_else (match_operand:SF 1 "" "")
1050132727Skan        (const_string "SF")
1051132727Skan        (const_string "DF")))
105290286Sobrien   (set_attr "athlon_decode" "vector")])
1053169699Skan
1054169699Skan(define_insn "*cmpfp_iu_387"
1055169699Skan  [(set (reg:CCFPU FLAGS_REG)
1056169699Skan	(compare:CCFPU (match_operand 0 "register_operand" "f")
1057169699Skan		       (match_operand 1 "register_operand" "f")))]
1058169699Skan  "TARGET_80387 && TARGET_CMOVE
1059169699Skan   && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
1060169699Skan   && FLOAT_MODE_P (GET_MODE (operands[0]))
1061169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
1062169699Skan  "* return output_fp_compare (insn, operands, 1, 1);"
1063169699Skan  [(set_attr "type" "fcmp")
1064169699Skan   (set (attr "mode")
1065169699Skan     (cond [(match_operand:SF 1 "" "")
1066169699Skan	      (const_string "SF")
1067169699Skan	    (match_operand:DF 1 "" "")
1068169699Skan	      (const_string "DF")
1069169699Skan	   ]
1070169699Skan	   (const_string "XF")))
1071169699Skan   (set_attr "athlon_decode" "vector")])
107290286Sobrien
107390286Sobrien;; Move instructions.
107418334Speter
107518334Speter;; General case of fullword move.
107618334Speter
107718334Speter(define_expand "movsi"
107890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
107918334Speter	(match_operand:SI 1 "general_operand" ""))]
108018334Speter  ""
108190286Sobrien  "ix86_expand_move (SImode, operands); DONE;")
108218334Speter
108390286Sobrien;; Push/pop instructions.  They are separate since autoinc/dec is not a
108490286Sobrien;; general_operand.
108590286Sobrien;;
108690286Sobrien;; %%% We don't use a post-inc memory reference because x86 is not a 
108790286Sobrien;; general AUTO_INC_DEC host, which impacts how it is treated in flow.
108890286Sobrien;; Changing this impacts compiler performance on other non-AUTO_INC_DEC
108990286Sobrien;; targets without our curiosities, and it is just as easy to represent
109090286Sobrien;; this differently.
109118334Speter
109290286Sobrien(define_insn "*pushsi2"
109390286Sobrien  [(set (match_operand:SI 0 "push_operand" "=<")
109490286Sobrien	(match_operand:SI 1 "general_no_elim_operand" "ri*m"))]
109590286Sobrien  "!TARGET_64BIT"
109690286Sobrien  "push{l}\t%1"
109790286Sobrien  [(set_attr "type" "push")
109890286Sobrien   (set_attr "mode" "SI")])
109918334Speter
110090286Sobrien;; For 64BIT abi we always round up to 8 bytes.
110190286Sobrien(define_insn "*pushsi2_rex64"
110290286Sobrien  [(set (match_operand:SI 0 "push_operand" "=X")
110390286Sobrien	(match_operand:SI 1 "nonmemory_no_elim_operand" "ri"))]
110490286Sobrien  "TARGET_64BIT"
110590286Sobrien  "push{q}\t%q1"
110690286Sobrien  [(set_attr "type" "push")
110790286Sobrien   (set_attr "mode" "SI")])
110818334Speter
110990286Sobrien(define_insn "*pushsi2_prologue"
111090286Sobrien  [(set (match_operand:SI 0 "push_operand" "=<")
111190286Sobrien	(match_operand:SI 1 "general_no_elim_operand" "ri*m"))
111290286Sobrien   (clobber (mem:BLK (scratch)))]
111390286Sobrien  "!TARGET_64BIT"
111490286Sobrien  "push{l}\t%1"
111590286Sobrien  [(set_attr "type" "push")
111690286Sobrien   (set_attr "mode" "SI")])
111752296Sobrien
111890286Sobrien(define_insn "*popsi1_epilogue"
111990286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
1120169699Skan	(mem:SI (reg:SI SP_REG)))
1121169699Skan   (set (reg:SI SP_REG)
1122169699Skan	(plus:SI (reg:SI SP_REG) (const_int 4)))
112390286Sobrien   (clobber (mem:BLK (scratch)))]
112490286Sobrien  "!TARGET_64BIT"
112590286Sobrien  "pop{l}\t%0"
112690286Sobrien  [(set_attr "type" "pop")
112790286Sobrien   (set_attr "mode" "SI")])
112818334Speter
112990286Sobrien(define_insn "popsi1"
113090286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
1131169699Skan	(mem:SI (reg:SI SP_REG)))
1132169699Skan   (set (reg:SI SP_REG)
1133169699Skan	(plus:SI (reg:SI SP_REG) (const_int 4)))]
113490286Sobrien  "!TARGET_64BIT"
113590286Sobrien  "pop{l}\t%0"
113690286Sobrien  [(set_attr "type" "pop")
113790286Sobrien   (set_attr "mode" "SI")])
113818334Speter
113990286Sobrien(define_insn "*movsi_xor"
114090286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
114190286Sobrien	(match_operand:SI 1 "const0_operand" "i"))
1142169699Skan   (clobber (reg:CC FLAGS_REG))]
114390286Sobrien  "reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
114490286Sobrien  "xor{l}\t{%0, %0|%0, %0}"
114590286Sobrien  [(set_attr "type" "alu1")
114690286Sobrien   (set_attr "mode" "SI")
114790286Sobrien   (set_attr "length_immediate" "0")])
1148132727Skan 
114990286Sobrien(define_insn "*movsi_or"
115090286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
115190286Sobrien	(match_operand:SI 1 "immediate_operand" "i"))
1152169699Skan   (clobber (reg:CC FLAGS_REG))]
1153132727Skan  "reload_completed
1154132727Skan   && operands[1] == constm1_rtx
115590286Sobrien   && (TARGET_PENTIUM || optimize_size)"
115690286Sobrien{
115790286Sobrien  operands[1] = constm1_rtx;
115890286Sobrien  return "or{l}\t{%1, %0|%0, %1}";
115990286Sobrien}
116090286Sobrien  [(set_attr "type" "alu1")
116190286Sobrien   (set_attr "mode" "SI")
116290286Sobrien   (set_attr "length_immediate" "1")])
116318334Speter
116490286Sobrien(define_insn "*movsi_1"
1165169699Skan  [(set (match_operand:SI 0 "nonimmediate_operand"
1166169699Skan			"=r  ,m  ,*y,*y,?rm,?*y,*x,*x,?r,m ,?*Y,*x")
1167169699Skan	(match_operand:SI 1 "general_operand"
1168169699Skan			"rinm,rin,C ,*y,*y ,rm ,C ,*x,*Y,*x,r  ,m "))]
1169169699Skan  "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
117050650Sobrien{
117190286Sobrien  switch (get_attr_type (insn))
117290286Sobrien    {
1173169699Skan    case TYPE_SSELOG1:
1174117404Skan      if (get_attr_mode (insn) == MODE_TI)
1175169699Skan        return "pxor\t%0, %0";
1176169699Skan      return "xorps\t%0, %0";
117752296Sobrien
1178169699Skan    case TYPE_SSEMOV:
1179169699Skan      switch (get_attr_mode (insn))
1180169699Skan	{
1181169699Skan	case MODE_TI:
1182169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
1183169699Skan	case MODE_V4SF:
1184169699Skan	  return "movaps\t{%1, %0|%0, %1}";
1185169699Skan	case MODE_SI:
1186169699Skan          return "movd\t{%1, %0|%0, %1}";
1187169699Skan	case MODE_SF:
1188169699Skan          return "movss\t{%1, %0|%0, %1}";
1189169699Skan	default:
1190169699Skan	  gcc_unreachable ();
1191169699Skan	}
119252296Sobrien
1193169699Skan    case TYPE_MMXADD:
1194169699Skan      return "pxor\t%0, %0";
119518334Speter
1196132727Skan    case TYPE_MMXMOV:
1197132727Skan      if (get_attr_mode (insn) == MODE_DI)
1198132727Skan	return "movq\t{%1, %0|%0, %1}";
1199132727Skan      return "movd\t{%1, %0|%0, %1}";
1200132727Skan
1201132727Skan    case TYPE_LEA:
1202132727Skan      return "lea{l}\t{%1, %0|%0, %1}";
1203132727Skan
1204132727Skan    default:
1205169699Skan      gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
1206132727Skan      return "mov{l}\t{%1, %0|%0, %1}";
1207132727Skan    }
1208132727Skan}
1209132727Skan  [(set (attr "type")
1210169699Skan     (cond [(eq_attr "alternative" "2")
1211169699Skan	      (const_string "mmxadd")
1212169699Skan	    (eq_attr "alternative" "3,4,5")
1213132727Skan	      (const_string "mmxmov")
1214169699Skan	    (eq_attr "alternative" "6")
1215169699Skan	      (const_string "sselog1")
1216169699Skan	    (eq_attr "alternative" "7,8,9,10,11")
1217132727Skan	      (const_string "ssemov")
1218169699Skan 	    (match_operand:DI 1 "pic_32bit_operand" "")
1219132727Skan	      (const_string "lea")
1220132727Skan	   ]
1221132727Skan	   (const_string "imov")))
1222169699Skan   (set (attr "mode")
1223169699Skan     (cond [(eq_attr "alternative" "2,3")
1224169699Skan	      (const_string "DI")
1225169699Skan	    (eq_attr "alternative" "6,7")
1226169699Skan	      (if_then_else
1227169699Skan	        (eq (symbol_ref "TARGET_SSE2") (const_int 0))
1228169699Skan	        (const_string "V4SF")
1229169699Skan	        (const_string "TI"))
1230169699Skan	    (and (eq_attr "alternative" "8,9,10,11")
1231169699Skan	         (eq (symbol_ref "TARGET_SSE2") (const_int 0)))
1232169699Skan	      (const_string "SF")
1233169699Skan	   ]
1234169699Skan	   (const_string "SI")))])
1235132727Skan
1236132727Skan;; Stores and loads of ax to arbitrary constant address.
123790286Sobrien;; We fake an second form of instruction to force reload to load address
123890286Sobrien;; into register when rax is not available
123990286Sobrien(define_insn "*movabssi_1_rex64"
1240117404Skan  [(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1241117404Skan	(match_operand:SI 1 "nonmemory_operand" "a,er"))]
1242117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
124390286Sobrien  "@
124490286Sobrien   movabs{l}\t{%1, %P0|%P0, %1}
1245117404Skan   mov{l}\t{%1, %a0|%a0, %1}"
124690286Sobrien  [(set_attr "type" "imov")
1247117404Skan   (set_attr "modrm" "0,*")
1248117404Skan   (set_attr "length_address" "8,0")
1249117404Skan   (set_attr "length_immediate" "0,*")
125090286Sobrien   (set_attr "memory" "store")
125190286Sobrien   (set_attr "mode" "SI")])
125250650Sobrien
125390286Sobrien(define_insn "*movabssi_2_rex64"
125490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a,r")
125590286Sobrien        (mem:SI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1256117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
125790286Sobrien  "@
125890286Sobrien   movabs{l}\t{%P1, %0|%0, %P1}
125990286Sobrien   mov{l}\t{%a1, %0|%0, %a1}"
126090286Sobrien  [(set_attr "type" "imov")
126190286Sobrien   (set_attr "modrm" "0,*")
126290286Sobrien   (set_attr "length_address" "8,0")
126390286Sobrien   (set_attr "length_immediate" "0")
126490286Sobrien   (set_attr "memory" "load")
126590286Sobrien   (set_attr "mode" "SI")])
126690286Sobrien
126790286Sobrien(define_insn "*swapsi"
126890286Sobrien  [(set (match_operand:SI 0 "register_operand" "+r")
126990286Sobrien	(match_operand:SI 1 "register_operand" "+r"))
127090286Sobrien   (set (match_dup 1)
127190286Sobrien	(match_dup 0))]
127250650Sobrien  ""
127390286Sobrien  "xchg{l}\t%1, %0"
127490286Sobrien  [(set_attr "type" "imov")
1275146906Skan   (set_attr "mode" "SI")
127690286Sobrien   (set_attr "pent_pair" "np")
1277169699Skan   (set_attr "athlon_decode" "vector")])
127818334Speter
127990286Sobrien(define_expand "movhi"
128090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
128190286Sobrien        (match_operand:HI 1 "general_operand" ""))]
128290286Sobrien  ""
128390286Sobrien  "ix86_expand_move (HImode, operands); DONE;")
128418334Speter
128590286Sobrien(define_insn "*pushhi2"
1286169699Skan  [(set (match_operand:HI 0 "push_operand" "=X")
1287169699Skan	(match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
128890286Sobrien  "!TARGET_64BIT"
1289169699Skan  "push{l}\t%k1"
129090286Sobrien  [(set_attr "type" "push")
1291169699Skan   (set_attr "mode" "SI")])
129218334Speter
129390286Sobrien;; For 64BIT abi we always round up to 8 bytes.
129490286Sobrien(define_insn "*pushhi2_rex64"
129590286Sobrien  [(set (match_operand:HI 0 "push_operand" "=X")
129690286Sobrien	(match_operand:HI 1 "nonmemory_no_elim_operand" "ri"))]
129790286Sobrien  "TARGET_64BIT"
129890286Sobrien  "push{q}\t%q1"
129990286Sobrien  [(set_attr "type" "push")
1300169699Skan   (set_attr "mode" "DI")])
130190286Sobrien
130290286Sobrien(define_insn "*movhi_1"
1303117404Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
1304117404Skan	(match_operand:HI 1 "general_operand" "r,rn,rm,rn"))]
130590286Sobrien  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
130618334Speter{
130790286Sobrien  switch (get_attr_type (insn))
130818334Speter    {
130990286Sobrien    case TYPE_IMOVX:
131090286Sobrien      /* movzwl is faster than movw on p2 due to partial word stalls,
131190286Sobrien	 though not as fast as an aligned movl.  */
131290286Sobrien      return "movz{wl|x}\t{%1, %k0|%k0, %1}";
131390286Sobrien    default:
131490286Sobrien      if (get_attr_mode (insn) == MODE_SI)
131590286Sobrien        return "mov{l}\t{%k1, %k0|%k0, %k1}";
131690286Sobrien      else
131790286Sobrien        return "mov{w}\t{%1, %0|%0, %1}";
131818334Speter    }
131990286Sobrien}
132090286Sobrien  [(set (attr "type")
1321169699Skan     (cond [(ne (symbol_ref "optimize_size") (const_int 0))
1322169699Skan	      (const_string "imov")
1323169699Skan	    (and (eq_attr "alternative" "0")
132490286Sobrien		 (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
132590286Sobrien			  (const_int 0))
132690286Sobrien		      (eq (symbol_ref "TARGET_HIMODE_MATH")
132790286Sobrien			  (const_int 0))))
132890286Sobrien	      (const_string "imov")
1329117404Skan	    (and (eq_attr "alternative" "1,2")
133090286Sobrien		 (match_operand:HI 1 "aligned_operand" ""))
133190286Sobrien	      (const_string "imov")
133290286Sobrien	    (and (ne (symbol_ref "TARGET_MOVX")
133390286Sobrien		     (const_int 0))
1334117404Skan		 (eq_attr "alternative" "0,2"))
133590286Sobrien	      (const_string "imovx")
133690286Sobrien	   ]
133790286Sobrien	   (const_string "imov")))
133890286Sobrien    (set (attr "mode")
133990286Sobrien      (cond [(eq_attr "type" "imovx")
134090286Sobrien	       (const_string "SI")
1341117404Skan	     (and (eq_attr "alternative" "1,2")
134290286Sobrien		  (match_operand:HI 1 "aligned_operand" ""))
134390286Sobrien	       (const_string "SI")
1344117404Skan	     (and (eq_attr "alternative" "0")
134590286Sobrien		  (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
134690286Sobrien			   (const_int 0))
134790286Sobrien		       (eq (symbol_ref "TARGET_HIMODE_MATH")
134890286Sobrien			   (const_int 0))))
134990286Sobrien	       (const_string "SI")
135090286Sobrien	    ]
1351117404Skan	    (const_string "HI")))])
135218334Speter
1353132727Skan;; Stores and loads of ax to arbitrary constant address.
135490286Sobrien;; We fake an second form of instruction to force reload to load address
135590286Sobrien;; into register when rax is not available
135690286Sobrien(define_insn "*movabshi_1_rex64"
1357117404Skan  [(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1358117404Skan	(match_operand:HI 1 "nonmemory_operand" "a,er"))]
1359117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
136090286Sobrien  "@
136190286Sobrien   movabs{w}\t{%1, %P0|%P0, %1}
1362117404Skan   mov{w}\t{%1, %a0|%a0, %1}"
136390286Sobrien  [(set_attr "type" "imov")
1364117404Skan   (set_attr "modrm" "0,*")
1365117404Skan   (set_attr "length_address" "8,0")
1366117404Skan   (set_attr "length_immediate" "0,*")
136790286Sobrien   (set_attr "memory" "store")
136890286Sobrien   (set_attr "mode" "HI")])
136918334Speter
137090286Sobrien(define_insn "*movabshi_2_rex64"
137190286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a,r")
137290286Sobrien        (mem:HI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1373117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
137490286Sobrien  "@
137590286Sobrien   movabs{w}\t{%P1, %0|%0, %P1}
137690286Sobrien   mov{w}\t{%a1, %0|%0, %a1}"
137790286Sobrien  [(set_attr "type" "imov")
137890286Sobrien   (set_attr "modrm" "0,*")
137990286Sobrien   (set_attr "length_address" "8,0")
138090286Sobrien   (set_attr "length_immediate" "0")
138190286Sobrien   (set_attr "memory" "load")
138290286Sobrien   (set_attr "mode" "HI")])
138318334Speter
138490286Sobrien(define_insn "*swaphi_1"
138590286Sobrien  [(set (match_operand:HI 0 "register_operand" "+r")
138690286Sobrien	(match_operand:HI 1 "register_operand" "+r"))
138790286Sobrien   (set (match_dup 1)
138890286Sobrien	(match_dup 0))]
1389146906Skan  "!TARGET_PARTIAL_REG_STALL || optimize_size"
1390146906Skan  "xchg{l}\t%k1, %k0"
139190286Sobrien  [(set_attr "type" "imov")
1392146906Skan   (set_attr "mode" "SI")
139390286Sobrien   (set_attr "pent_pair" "np")
1394169699Skan   (set_attr "athlon_decode" "vector")])
139518334Speter
139690286Sobrien(define_insn "*swaphi_2"
139790286Sobrien  [(set (match_operand:HI 0 "register_operand" "+r")
139890286Sobrien	(match_operand:HI 1 "register_operand" "+r"))
139990286Sobrien   (set (match_dup 1)
140090286Sobrien	(match_dup 0))]
1401146906Skan  "TARGET_PARTIAL_REG_STALL"
1402146906Skan  "xchg{w}\t%1, %0"
140390286Sobrien  [(set_attr "type" "imov")
1404146906Skan   (set_attr "mode" "HI")
140590286Sobrien   (set_attr "pent_pair" "np")
1406169699Skan   (set_attr "athlon_decode" "vector")])
140718334Speter
140818334Speter(define_expand "movstricthi"
140990286Sobrien  [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
141018334Speter	(match_operand:HI 1 "general_operand" ""))]
141190286Sobrien  "! TARGET_PARTIAL_REG_STALL || optimize_size"
141218334Speter{
141318334Speter  /* Don't generate memory->memory moves, go through a register */
141490286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
141590286Sobrien    operands[1] = force_reg (HImode, operands[1]);
141690286Sobrien})
141718334Speter
141890286Sobrien(define_insn "*movstricthi_1"
141990286Sobrien  [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+rm,r"))
142090286Sobrien	(match_operand:HI 1 "general_operand" "rn,m"))]
142190286Sobrien  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
142290286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
142390286Sobrien  "mov{w}\t{%1, %0|%0, %1}"
142490286Sobrien  [(set_attr "type" "imov")
142590286Sobrien   (set_attr "mode" "HI")])
142652296Sobrien
142790286Sobrien(define_insn "*movstricthi_xor"
142890286Sobrien  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
142990286Sobrien	(match_operand:HI 1 "const0_operand" "i"))
1430169699Skan   (clobber (reg:CC FLAGS_REG))]
143190286Sobrien  "reload_completed
143290286Sobrien   && ((!TARGET_USE_MOV0 && !TARGET_PARTIAL_REG_STALL) || optimize_size)"
143390286Sobrien  "xor{w}\t{%0, %0|%0, %0}"
143490286Sobrien  [(set_attr "type" "alu1")
143590286Sobrien   (set_attr "mode" "HI")
143690286Sobrien   (set_attr "length_immediate" "0")])
143752296Sobrien
143890286Sobrien(define_expand "movqi"
143990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
144090286Sobrien	(match_operand:QI 1 "general_operand" ""))]
144190286Sobrien  ""
144290286Sobrien  "ix86_expand_move (QImode, operands); DONE;")
144318334Speter
144490286Sobrien;; emit_push_insn when it calls move_by_pieces requires an insn to
1445169699Skan;; "push a byte".  But actually we use pushl, which has the effect
1446169699Skan;; of rounding the amount pushed up to a word.
144718334Speter
144890286Sobrien(define_insn "*pushqi2"
1449169699Skan  [(set (match_operand:QI 0 "push_operand" "=X")
1450169699Skan	(match_operand:QI 1 "nonmemory_no_elim_operand" "rn"))]
145190286Sobrien  "!TARGET_64BIT"
1452169699Skan  "push{l}\t%k1"
145390286Sobrien  [(set_attr "type" "push")
1454169699Skan   (set_attr "mode" "SI")])
145518334Speter
145690286Sobrien;; For 64BIT abi we always round up to 8 bytes.
145790286Sobrien(define_insn "*pushqi2_rex64"
145890286Sobrien  [(set (match_operand:QI 0 "push_operand" "=X")
1459102802Skan	(match_operand:QI 1 "nonmemory_no_elim_operand" "qi"))]
146090286Sobrien  "TARGET_64BIT"
146190286Sobrien  "push{q}\t%q1"
146290286Sobrien  [(set_attr "type" "push")
1463169699Skan   (set_attr "mode" "DI")])
146490286Sobrien
146590286Sobrien;; Situation is quite tricky about when to choose full sized (SImode) move
146690286Sobrien;; over QImode moves.  For Q_REG -> Q_REG move we use full size only for
146790286Sobrien;; partial register dependency machines (such as AMD Athlon), where QImode
146890286Sobrien;; moves issue extra dependency and for partial register stalls machines
146990286Sobrien;; that don't use QImode patterns (and QImode move cause stall on the next
147090286Sobrien;; instruction).
147190286Sobrien;;
147290286Sobrien;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial
147390286Sobrien;; register stall machines with, where we use QImode instructions, since
147490286Sobrien;; partial register stall can be caused there.  Then we use movzx.
147590286Sobrien(define_insn "*movqi_1"
147690286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m")
147790286Sobrien	(match_operand:QI 1 "general_operand"      " q,qn,qm,q,rn,qm,qn"))]
147890286Sobrien  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
147990286Sobrien{
148090286Sobrien  switch (get_attr_type (insn))
148190286Sobrien    {
148290286Sobrien    case TYPE_IMOVX:
1483169699Skan      gcc_assert (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM);
148490286Sobrien      return "movz{bl|x}\t{%1, %k0|%k0, %1}";
148590286Sobrien    default:
148690286Sobrien      if (get_attr_mode (insn) == MODE_SI)
148790286Sobrien        return "mov{l}\t{%k1, %k0|%k0, %k1}";
148890286Sobrien      else
148990286Sobrien        return "mov{b}\t{%1, %0|%0, %1}";
149090286Sobrien    }
149190286Sobrien}
149290286Sobrien  [(set (attr "type")
1493169699Skan     (cond [(and (eq_attr "alternative" "5")
1494169699Skan		 (not (match_operand:QI 1 "aligned_operand" "")))
1495169699Skan	      (const_string "imovx")
1496169699Skan	    (ne (symbol_ref "optimize_size") (const_int 0))
1497169699Skan	      (const_string "imov")
1498169699Skan	    (and (eq_attr "alternative" "3")
149990286Sobrien		 (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
150090286Sobrien			  (const_int 0))
150190286Sobrien		      (eq (symbol_ref "TARGET_QIMODE_MATH")
150290286Sobrien			  (const_int 0))))
150390286Sobrien	      (const_string "imov")
150490286Sobrien	    (eq_attr "alternative" "3,5")
150590286Sobrien	      (const_string "imovx")
150690286Sobrien	    (and (ne (symbol_ref "TARGET_MOVX")
150790286Sobrien		     (const_int 0))
150890286Sobrien		 (eq_attr "alternative" "2"))
150990286Sobrien	      (const_string "imovx")
151090286Sobrien	   ]
151190286Sobrien	   (const_string "imov")))
151290286Sobrien   (set (attr "mode")
151390286Sobrien      (cond [(eq_attr "alternative" "3,4,5")
151490286Sobrien	       (const_string "SI")
151590286Sobrien	     (eq_attr "alternative" "6")
151690286Sobrien	       (const_string "QI")
151790286Sobrien	     (eq_attr "type" "imovx")
151890286Sobrien	       (const_string "SI")
151990286Sobrien	     (and (eq_attr "type" "imov")
1520169699Skan		  (and (eq_attr "alternative" "0,1")
1521169699Skan		       (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
1522169699Skan				(const_int 0))
1523169699Skan			    (and (eq (symbol_ref "optimize_size")
1524169699Skan				     (const_int 0))
1525169699Skan			    	 (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
1526169699Skan				     (const_int 0))))))
152790286Sobrien	       (const_string "SI")
152890286Sobrien	     ;; Avoid partial register stalls when not using QImode arithmetic
152990286Sobrien	     (and (eq_attr "type" "imov")
1530169699Skan		  (and (eq_attr "alternative" "0,1")
153190286Sobrien		       (and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL")
153290286Sobrien				(const_int 0))
153390286Sobrien			    (eq (symbol_ref "TARGET_QIMODE_MATH")
153490286Sobrien				(const_int 0)))))
153590286Sobrien	       (const_string "SI")
153690286Sobrien	   ]
153790286Sobrien	   (const_string "QI")))])
153890286Sobrien
153990286Sobrien(define_expand "reload_outqi"
154090286Sobrien  [(parallel [(match_operand:QI 0 "" "=m")
154190286Sobrien              (match_operand:QI 1 "register_operand" "r")
154290286Sobrien              (match_operand:QI 2 "register_operand" "=&q")])]
154318334Speter  ""
154490286Sobrien{
154590286Sobrien  rtx op0, op1, op2;
154690286Sobrien  op0 = operands[0]; op1 = operands[1]; op2 = operands[2];
154718334Speter
1548169699Skan  gcc_assert (!reg_overlap_mentioned_p (op2, op0));
154990286Sobrien  if (! q_regs_operand (op1, QImode))
155090286Sobrien    {
155190286Sobrien      emit_insn (gen_movqi (op2, op1));
155290286Sobrien      op1 = op2;
155390286Sobrien    }
155490286Sobrien  emit_insn (gen_movqi (op0, op1));
155590286Sobrien  DONE;
155690286Sobrien})
155790286Sobrien
1558146906Skan(define_insn "*swapqi_1"
155990286Sobrien  [(set (match_operand:QI 0 "register_operand" "+r")
156090286Sobrien	(match_operand:QI 1 "register_operand" "+r"))
156190286Sobrien   (set (match_dup 1)
156290286Sobrien	(match_dup 0))]
1563146906Skan  "!TARGET_PARTIAL_REG_STALL || optimize_size"
1564146906Skan  "xchg{l}\t%k1, %k0"
1565146906Skan  [(set_attr "type" "imov")
1566146906Skan   (set_attr "mode" "SI")
1567146906Skan   (set_attr "pent_pair" "np")
1568169699Skan   (set_attr "athlon_decode" "vector")])
1569146906Skan
1570146906Skan(define_insn "*swapqi_2"
1571146906Skan  [(set (match_operand:QI 0 "register_operand" "+q")
1572146906Skan	(match_operand:QI 1 "register_operand" "+q"))
1573146906Skan   (set (match_dup 1)
1574146906Skan	(match_dup 0))]
1575146906Skan  "TARGET_PARTIAL_REG_STALL"
157690286Sobrien  "xchg{b}\t%1, %0"
157790286Sobrien  [(set_attr "type" "imov")
1578146906Skan   (set_attr "mode" "QI")
157990286Sobrien   (set_attr "pent_pair" "np")
1580169699Skan   (set_attr "athlon_decode" "vector")])
158190286Sobrien
158290286Sobrien(define_expand "movstrictqi"
158390286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
158490286Sobrien	(match_operand:QI 1 "general_operand" ""))]
1585117404Skan  "! TARGET_PARTIAL_REG_STALL || optimize_size"
158618334Speter{
158790286Sobrien  /* Don't generate memory->memory moves, go through a register.  */
158890286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
158990286Sobrien    operands[1] = force_reg (QImode, operands[1]);
159090286Sobrien})
159118334Speter
159290286Sobrien(define_insn "*movstrictqi_1"
159390286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
159490286Sobrien	(match_operand:QI 1 "general_operand" "*qn,m"))]
1595117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
159690286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
159790286Sobrien  "mov{b}\t{%1, %0|%0, %1}"
159890286Sobrien  [(set_attr "type" "imov")
159990286Sobrien   (set_attr "mode" "QI")])
160018334Speter
160190286Sobrien(define_insn "*movstrictqi_xor"
160290286Sobrien  [(set (strict_low_part (match_operand:QI 0 "q_regs_operand" "+q"))
160390286Sobrien	(match_operand:QI 1 "const0_operand" "i"))
1604169699Skan   (clobber (reg:CC FLAGS_REG))]
160590286Sobrien  "reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
160690286Sobrien  "xor{b}\t{%0, %0|%0, %0}"
160790286Sobrien  [(set_attr "type" "alu1")
160890286Sobrien   (set_attr "mode" "QI")
160990286Sobrien   (set_attr "length_immediate" "0")])
161018334Speter
161190286Sobrien(define_insn "*movsi_extv_1"
161290286Sobrien  [(set (match_operand:SI 0 "register_operand" "=R")
161390286Sobrien	(sign_extract:SI (match_operand 1 "ext_register_operand" "Q")
161490286Sobrien			 (const_int 8)
161590286Sobrien			 (const_int 8)))]
161618334Speter  ""
161790286Sobrien  "movs{bl|x}\t{%h1, %0|%0, %h1}"
161890286Sobrien  [(set_attr "type" "imovx")
161990286Sobrien   (set_attr "mode" "SI")])
162090286Sobrien
162190286Sobrien(define_insn "*movhi_extv_1"
162290286Sobrien  [(set (match_operand:HI 0 "register_operand" "=R")
162390286Sobrien	(sign_extract:HI (match_operand 1 "ext_register_operand" "Q")
162490286Sobrien			 (const_int 8)
162590286Sobrien			 (const_int 8)))]
162690286Sobrien  ""
162790286Sobrien  "movs{bl|x}\t{%h1, %k0|%k0, %h1}"
162890286Sobrien  [(set_attr "type" "imovx")
162990286Sobrien   (set_attr "mode" "SI")])
163090286Sobrien
163190286Sobrien(define_insn "*movqi_extv_1"
163290286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?r")
163390286Sobrien        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
163490286Sobrien                         (const_int 8)
163590286Sobrien                         (const_int 8)))]
163690286Sobrien  "!TARGET_64BIT"
163718334Speter{
163890286Sobrien  switch (get_attr_type (insn))
163918334Speter    {
164090286Sobrien    case TYPE_IMOVX:
164190286Sobrien      return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
164290286Sobrien    default:
164390286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
164418334Speter    }
164590286Sobrien}
164690286Sobrien  [(set (attr "type")
164790286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
164890286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
164990286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
165090286Sobrien				 (const_int 0))))
165190286Sobrien	(const_string "imovx")
165290286Sobrien	(const_string "imov")))
165390286Sobrien   (set (attr "mode")
165490286Sobrien     (if_then_else (eq_attr "type" "imovx")
165590286Sobrien	(const_string "SI")
165690286Sobrien	(const_string "QI")))])
165718334Speter
165890286Sobrien(define_insn "*movqi_extv_1_rex64"
165990286Sobrien  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
166090286Sobrien        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
166190286Sobrien                         (const_int 8)
166290286Sobrien                         (const_int 8)))]
166390286Sobrien  "TARGET_64BIT"
166418334Speter{
166590286Sobrien  switch (get_attr_type (insn))
166650650Sobrien    {
166790286Sobrien    case TYPE_IMOVX:
166890286Sobrien      return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
166990286Sobrien    default:
167090286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
167150650Sobrien    }
167290286Sobrien}
167390286Sobrien  [(set (attr "type")
167490286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
167590286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
167690286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
167790286Sobrien				 (const_int 0))))
167890286Sobrien	(const_string "imovx")
167990286Sobrien	(const_string "imov")))
168090286Sobrien   (set (attr "mode")
168190286Sobrien     (if_then_else (eq_attr "type" "imovx")
168290286Sobrien	(const_string "SI")
168390286Sobrien	(const_string "QI")))])
168418334Speter
1685132727Skan;; Stores and loads of ax to arbitrary constant address.
168690286Sobrien;; We fake an second form of instruction to force reload to load address
168790286Sobrien;; into register when rax is not available
168890286Sobrien(define_insn "*movabsqi_1_rex64"
1689117404Skan  [(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1690117404Skan	(match_operand:QI 1 "nonmemory_operand" "a,er"))]
1691117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
169290286Sobrien  "@
169390286Sobrien   movabs{b}\t{%1, %P0|%P0, %1}
1694117404Skan   mov{b}\t{%1, %a0|%a0, %1}"
169590286Sobrien  [(set_attr "type" "imov")
1696117404Skan   (set_attr "modrm" "0,*")
1697117404Skan   (set_attr "length_address" "8,0")
1698117404Skan   (set_attr "length_immediate" "0,*")
169990286Sobrien   (set_attr "memory" "store")
170090286Sobrien   (set_attr "mode" "QI")])
170118334Speter
170290286Sobrien(define_insn "*movabsqi_2_rex64"
170390286Sobrien  [(set (match_operand:QI 0 "register_operand" "=a,r")
170490286Sobrien        (mem:QI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1705117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
170690286Sobrien  "@
170790286Sobrien   movabs{b}\t{%P1, %0|%0, %P1}
170890286Sobrien   mov{b}\t{%a1, %0|%0, %a1}"
170990286Sobrien  [(set_attr "type" "imov")
171090286Sobrien   (set_attr "modrm" "0,*")
171190286Sobrien   (set_attr "length_address" "8,0")
171290286Sobrien   (set_attr "length_immediate" "0")
171390286Sobrien   (set_attr "memory" "load")
171490286Sobrien   (set_attr "mode" "QI")])
171518334Speter
1716169699Skan(define_insn "*movdi_extzv_1"
1717169699Skan  [(set (match_operand:DI 0 "register_operand" "=R")
1718169699Skan	(zero_extract:DI (match_operand 1 "ext_register_operand" "Q")
1719169699Skan			 (const_int 8)
1720169699Skan			 (const_int 8)))]
1721169699Skan  "TARGET_64BIT"
1722169699Skan  "movz{bl|x}\t{%h1, %k0|%k0, %h1}"
1723169699Skan  [(set_attr "type" "imovx")
1724169699Skan   (set_attr "mode" "DI")])
1725169699Skan
172690286Sobrien(define_insn "*movsi_extzv_1"
172790286Sobrien  [(set (match_operand:SI 0 "register_operand" "=R")
172890286Sobrien	(zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
172990286Sobrien			 (const_int 8)
173090286Sobrien			 (const_int 8)))]
173190286Sobrien  ""
173290286Sobrien  "movz{bl|x}\t{%h1, %0|%0, %h1}"
173390286Sobrien  [(set_attr "type" "imovx")
173490286Sobrien   (set_attr "mode" "SI")])
173518334Speter
173690286Sobrien(define_insn "*movqi_extzv_2"
173790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?R")
173890286Sobrien        (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
173990286Sobrien				    (const_int 8)
174090286Sobrien				    (const_int 8)) 0))]
174190286Sobrien  "!TARGET_64BIT"
174218334Speter{
174390286Sobrien  switch (get_attr_type (insn))
174418334Speter    {
174590286Sobrien    case TYPE_IMOVX:
174690286Sobrien      return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
174790286Sobrien    default:
174890286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
174918334Speter    }
175090286Sobrien}
175190286Sobrien  [(set (attr "type")
175290286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
175390286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
175490286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
175590286Sobrien				 (const_int 0))))
175690286Sobrien	(const_string "imovx")
175790286Sobrien	(const_string "imov")))
175890286Sobrien   (set (attr "mode")
175990286Sobrien     (if_then_else (eq_attr "type" "imovx")
176090286Sobrien	(const_string "SI")
176190286Sobrien	(const_string "QI")))])
176218334Speter
176390286Sobrien(define_insn "*movqi_extzv_2_rex64"
176490286Sobrien  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
176590286Sobrien        (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
176690286Sobrien				    (const_int 8)
176790286Sobrien				    (const_int 8)) 0))]
176890286Sobrien  "TARGET_64BIT"
176918334Speter{
177090286Sobrien  switch (get_attr_type (insn))
177190286Sobrien    {
177290286Sobrien    case TYPE_IMOVX:
177390286Sobrien      return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
177490286Sobrien    default:
177590286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
177690286Sobrien    }
177790286Sobrien}
177890286Sobrien  [(set (attr "type")
177990286Sobrien     (if_then_else (ior (not (match_operand:QI 0 "q_regs_operand" ""))
178090286Sobrien			(ne (symbol_ref "TARGET_MOVX")
178190286Sobrien			    (const_int 0)))
178290286Sobrien	(const_string "imovx")
178390286Sobrien	(const_string "imov")))
178490286Sobrien   (set (attr "mode")
178590286Sobrien     (if_then_else (eq_attr "type" "imovx")
178690286Sobrien	(const_string "SI")
178790286Sobrien	(const_string "QI")))])
178818334Speter
178990286Sobrien(define_insn "movsi_insv_1"
179090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
179190286Sobrien			 (const_int 8)
179290286Sobrien			 (const_int 8))
179390286Sobrien	(match_operand:SI 1 "general_operand" "Qmn"))]
179490286Sobrien  "!TARGET_64BIT"
179590286Sobrien  "mov{b}\t{%b1, %h0|%h0, %b1}"
179690286Sobrien  [(set_attr "type" "imov")
179790286Sobrien   (set_attr "mode" "QI")])
179852296Sobrien
1799132727Skan(define_insn "movdi_insv_1_rex64"
1800132727Skan  [(set (zero_extract:DI (match_operand 0 "ext_register_operand" "+Q")
180190286Sobrien			 (const_int 8)
180290286Sobrien			 (const_int 8))
1803132727Skan	(match_operand:DI 1 "nonmemory_operand" "Qn"))]
180490286Sobrien  "TARGET_64BIT"
180590286Sobrien  "mov{b}\t{%b1, %h0|%h0, %b1}"
180690286Sobrien  [(set_attr "type" "imov")
180790286Sobrien   (set_attr "mode" "QI")])
180818334Speter
180990286Sobrien(define_insn "*movqi_insv_2"
181090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
181190286Sobrien			 (const_int 8)
181290286Sobrien			 (const_int 8))
1813132727Skan	(lshiftrt:SI (match_operand:SI 1 "register_operand" "Q")
1814132727Skan		     (const_int 8)))]
181590286Sobrien  ""
181690286Sobrien  "mov{b}\t{%h1, %h0|%h0, %h1}"
181790286Sobrien  [(set_attr "type" "imov")
181890286Sobrien   (set_attr "mode" "QI")])
181918334Speter
182090286Sobrien(define_expand "movdi"
182190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
182290286Sobrien	(match_operand:DI 1 "general_operand" ""))]
182390286Sobrien  ""
182490286Sobrien  "ix86_expand_move (DImode, operands); DONE;")
182518334Speter
182690286Sobrien(define_insn "*pushdi"
182790286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
182890286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "riF*m"))]
182990286Sobrien  "!TARGET_64BIT"
183090286Sobrien  "#")
183190286Sobrien
1832169699Skan(define_insn "*pushdi2_rex64"
183390286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<,!<")
183490286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "re*m,n"))]
183590286Sobrien  "TARGET_64BIT"
183690286Sobrien  "@
183790286Sobrien   push{q}\t%1
183890286Sobrien   #"
183990286Sobrien  [(set_attr "type" "push,multi")
184090286Sobrien   (set_attr "mode" "DI")])
184190286Sobrien
184290286Sobrien;; Convert impossible pushes of immediate to existing instructions.
184390286Sobrien;; First try to get scratch register and go through it.  In case this
184490286Sobrien;; fails, push sign extended lower part first and then overwrite
184590286Sobrien;; upper part by 32bit move.
184690286Sobrien(define_peephole2
184790286Sobrien  [(match_scratch:DI 2 "r")
184890286Sobrien   (set (match_operand:DI 0 "push_operand" "")
184990286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
185090286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
185190286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
185290286Sobrien  [(set (match_dup 2) (match_dup 1))
185390286Sobrien   (set (match_dup 0) (match_dup 2))]
185490286Sobrien  "")
185590286Sobrien
185690286Sobrien;; We need to define this as both peepholer and splitter for case
185790286Sobrien;; peephole2 pass is not run.
1858169699Skan;; "&& 1" is needed to keep it from matching the previous pattern.
185990286Sobrien(define_peephole2
186090286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
186190286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
186290286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
186390286Sobrien   && !x86_64_immediate_operand (operands[1], DImode) && 1"
186490286Sobrien  [(set (match_dup 0) (match_dup 1))
186590286Sobrien   (set (match_dup 2) (match_dup 3))]
186690286Sobrien  "split_di (operands + 1, 1, operands + 2, operands + 3);
186790286Sobrien   operands[1] = gen_lowpart (DImode, operands[2]);
186890286Sobrien   operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
186990286Sobrien						    GEN_INT (4)));
187090286Sobrien  ")
187190286Sobrien
187290286Sobrien(define_split
187390286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
187490286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
1875161660Skan  "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
1876169699Skan		    ? flow2_completed : reload_completed)
187790286Sobrien   && !symbolic_operand (operands[1], DImode)
187890286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
187990286Sobrien  [(set (match_dup 0) (match_dup 1))
188090286Sobrien   (set (match_dup 2) (match_dup 3))]
188190286Sobrien  "split_di (operands + 1, 1, operands + 2, operands + 3);
188290286Sobrien   operands[1] = gen_lowpart (DImode, operands[2]);
188390286Sobrien   operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
188490286Sobrien						    GEN_INT (4)));
188590286Sobrien  ")
188690286Sobrien
188790286Sobrien(define_insn "*pushdi2_prologue_rex64"
188890286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
188990286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "re*m"))
189090286Sobrien   (clobber (mem:BLK (scratch)))]
189190286Sobrien  "TARGET_64BIT"
189290286Sobrien  "push{q}\t%1"
189390286Sobrien  [(set_attr "type" "push")
189490286Sobrien   (set_attr "mode" "DI")])
189590286Sobrien
189690286Sobrien(define_insn "*popdi1_epilogue_rex64"
189790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
1898169699Skan	(mem:DI (reg:DI SP_REG)))
1899169699Skan   (set (reg:DI SP_REG)
1900169699Skan	(plus:DI (reg:DI SP_REG) (const_int 8)))
190190286Sobrien   (clobber (mem:BLK (scratch)))]
190290286Sobrien  "TARGET_64BIT"
190390286Sobrien  "pop{q}\t%0"
190490286Sobrien  [(set_attr "type" "pop")
190590286Sobrien   (set_attr "mode" "DI")])
190690286Sobrien
190790286Sobrien(define_insn "popdi1"
190890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
1909169699Skan	(mem:DI (reg:DI SP_REG)))
1910169699Skan   (set (reg:DI SP_REG)
1911169699Skan	(plus:DI (reg:DI SP_REG) (const_int 8)))]
191290286Sobrien  "TARGET_64BIT"
191390286Sobrien  "pop{q}\t%0"
191490286Sobrien  [(set_attr "type" "pop")
191590286Sobrien   (set_attr "mode" "DI")])
191690286Sobrien
191790286Sobrien(define_insn "*movdi_xor_rex64"
191890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
191990286Sobrien	(match_operand:DI 1 "const0_operand" "i"))
1920169699Skan   (clobber (reg:CC FLAGS_REG))]
192190286Sobrien  "TARGET_64BIT && (!TARGET_USE_MOV0 || optimize_size)
192290286Sobrien   && reload_completed"
192390286Sobrien  "xor{l}\t{%k0, %k0|%k0, %k0}"
192490286Sobrien  [(set_attr "type" "alu1")
192590286Sobrien   (set_attr "mode" "SI")
192690286Sobrien   (set_attr "length_immediate" "0")])
192790286Sobrien
192890286Sobrien(define_insn "*movdi_or_rex64"
192990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
193090286Sobrien	(match_operand:DI 1 "const_int_operand" "i"))
1931169699Skan   (clobber (reg:CC FLAGS_REG))]
193290286Sobrien  "TARGET_64BIT && (TARGET_PENTIUM || optimize_size)
193390286Sobrien   && reload_completed
1934132727Skan   && operands[1] == constm1_rtx"
193518334Speter{
193690286Sobrien  operands[1] = constm1_rtx;
193790286Sobrien  return "or{q}\t{%1, %0|%0, %1}";
193890286Sobrien}
193990286Sobrien  [(set_attr "type" "alu1")
194090286Sobrien   (set_attr "mode" "DI")
194190286Sobrien   (set_attr "length_immediate" "1")])
194218334Speter
194390286Sobrien(define_insn "*movdi_2"
1944169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand"
1945169699Skan				"=r  ,o  ,*y,m*y,*y,*Y,m ,*Y,*Y,*x,m ,*x,*x")
1946169699Skan	(match_operand:DI 1 "general_operand"
1947169699Skan				"riFo,riF,C ,*y ,m ,C ,*Y,*Y,m ,C ,*x,*x,m "))]
1948169699Skan  "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
194990286Sobrien  "@
195090286Sobrien   #
195190286Sobrien   #
1952169699Skan   pxor\t%0, %0
195390286Sobrien   movq\t{%1, %0|%0, %1}
195490286Sobrien   movq\t{%1, %0|%0, %1}
1955169699Skan   pxor\t%0, %0
195690286Sobrien   movq\t{%1, %0|%0, %1}
195790286Sobrien   movdqa\t{%1, %0|%0, %1}
1958169699Skan   movq\t{%1, %0|%0, %1}
1959169699Skan   xorps\t%0, %0
1960169699Skan   movlps\t{%1, %0|%0, %1}
1961169699Skan   movaps\t{%1, %0|%0, %1}
1962169699Skan   movlps\t{%1, %0|%0, %1}"
1963169699Skan  [(set_attr "type" "*,*,mmx,mmxmov,mmxmov,sselog1,ssemov,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov")
1964169699Skan   (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,TI,DI,V4SF,V2SF,V4SF,V2SF")])
196518334Speter
196690286Sobrien(define_split
196790286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
196890286Sobrien        (match_operand:DI 1 "general_operand" ""))]
196990286Sobrien  "!TARGET_64BIT && reload_completed
197090286Sobrien   && (! MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
197190286Sobrien  [(const_int 0)]
197290286Sobrien  "ix86_split_long_move (operands); DONE;")
197318334Speter
197490286Sobrien;; %%% This multiword shite has got to go.
197590286Sobrien(define_split
197690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
197790286Sobrien        (match_operand:DI 1 "general_operand" ""))]
197890286Sobrien  "!TARGET_64BIT && reload_completed
197990286Sobrien   && (!MMX_REG_P (operands[0]) && !SSE_REG_P (operands[0]))
198090286Sobrien   && (!MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
198190286Sobrien  [(const_int 0)]
198290286Sobrien  "ix86_split_long_move (operands); DONE;")
198318334Speter
198490286Sobrien(define_insn "*movdi_1_rex64"
1985169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand"
1986169699Skan		"=r,r  ,r,m ,!m,*y,*y,?rm,?*y,*x,*x,?rm,?*x,?*x,?*y")
1987169699Skan	(match_operand:DI 1 "general_operand"
1988169699Skan		"Z ,rem,i,re,n ,C ,*y,*y ,rm ,C ,*x,*x ,rm ,*y ,*x"))]
1989169699Skan  "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
199090286Sobrien{
199190286Sobrien  switch (get_attr_type (insn))
199290286Sobrien    {
1993169699Skan    case TYPE_SSECVT:
1994169699Skan      if (which_alternative == 13)
1995169699Skan	return "movq2dq\t{%1, %0|%0, %1}";
1996169699Skan      else
1997169699Skan	return "movdq2q\t{%1, %0|%0, %1}";
1998117404Skan    case TYPE_SSEMOV:
1999132727Skan      if (get_attr_mode (insn) == MODE_TI)
200090286Sobrien	  return "movdqa\t{%1, %0|%0, %1}";
200190286Sobrien      /* FALLTHRU */
2002117404Skan    case TYPE_MMXMOV:
2003132727Skan      /* Moves from and into integer register is done using movd opcode with
2004132727Skan 	 REX prefix.  */
2005132727Skan      if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
2006132727Skan	  return "movd\t{%1, %0|%0, %1}";
200790286Sobrien      return "movq\t{%1, %0|%0, %1}";
2008169699Skan    case TYPE_SSELOG1:
2009169699Skan    case TYPE_MMXADD:
2010169699Skan      return "pxor\t%0, %0";
201190286Sobrien    case TYPE_MULTI:
201290286Sobrien      return "#";
201390286Sobrien    case TYPE_LEA:
201490286Sobrien      return "lea{q}\t{%a1, %0|%0, %a1}";
201590286Sobrien    default:
2016169699Skan      gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
201790286Sobrien      if (get_attr_mode (insn) == MODE_SI)
201890286Sobrien	return "mov{l}\t{%k1, %k0|%k0, %k1}";
201990286Sobrien      else if (which_alternative == 2)
202090286Sobrien	return "movabs{q}\t{%1, %0|%0, %1}";
202118334Speter      else
202290286Sobrien	return "mov{q}\t{%1, %0|%0, %1}";
202318334Speter    }
202490286Sobrien}
202590286Sobrien  [(set (attr "type")
2026169699Skan     (cond [(eq_attr "alternative" "5")
2027169699Skan	      (const_string "mmxadd")
2028169699Skan	    (eq_attr "alternative" "6,7,8")
2029117404Skan	      (const_string "mmxmov")
2030169699Skan	    (eq_attr "alternative" "9")
2031169699Skan	      (const_string "sselog1")
2032169699Skan	    (eq_attr "alternative" "10,11,12")
2033117404Skan	      (const_string "ssemov")
2034169699Skan	    (eq_attr "alternative" "13,14")
2035169699Skan	      (const_string "ssecvt")
203690286Sobrien	    (eq_attr "alternative" "4")
203790286Sobrien	      (const_string "multi")
2038169699Skan 	    (match_operand:DI 1 "pic_32bit_operand" "")
203990286Sobrien	      (const_string "lea")
204090286Sobrien	   ]
204190286Sobrien	   (const_string "imov")))
2042169699Skan   (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*")
2043169699Skan   (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*")
2044169699Skan   (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI")])
204550650Sobrien
2046132727Skan;; Stores and loads of ax to arbitrary constant address.
204790286Sobrien;; We fake an second form of instruction to force reload to load address
204890286Sobrien;; into register when rax is not available
204990286Sobrien(define_insn "*movabsdi_1_rex64"
2050102802Skan  [(set (mem:DI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
2051102802Skan	(match_operand:DI 1 "nonmemory_operand" "a,er"))]
2052117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
205390286Sobrien  "@
205490286Sobrien   movabs{q}\t{%1, %P0|%P0, %1}
2055102802Skan   mov{q}\t{%1, %a0|%a0, %1}"
205690286Sobrien  [(set_attr "type" "imov")
2057102802Skan   (set_attr "modrm" "0,*")
2058102802Skan   (set_attr "length_address" "8,0")
2059102802Skan   (set_attr "length_immediate" "0,*")
206090286Sobrien   (set_attr "memory" "store")
206190286Sobrien   (set_attr "mode" "DI")])
206218334Speter
206390286Sobrien(define_insn "*movabsdi_2_rex64"
206490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a,r")
206590286Sobrien        (mem:DI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
2066117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
206790286Sobrien  "@
206890286Sobrien   movabs{q}\t{%P1, %0|%0, %P1}
206990286Sobrien   mov{q}\t{%a1, %0|%0, %a1}"
207090286Sobrien  [(set_attr "type" "imov")
207190286Sobrien   (set_attr "modrm" "0,*")
207290286Sobrien   (set_attr "length_address" "8,0")
207390286Sobrien   (set_attr "length_immediate" "0")
207490286Sobrien   (set_attr "memory" "load")
207590286Sobrien   (set_attr "mode" "DI")])
207690286Sobrien
207790286Sobrien;; Convert impossible stores of immediate to existing instructions.
207890286Sobrien;; First try to get scratch register and go through it.  In case this
207990286Sobrien;; fails, move by 32bit parts.
208090286Sobrien(define_peephole2
208190286Sobrien  [(match_scratch:DI 2 "r")
208290286Sobrien   (set (match_operand:DI 0 "memory_operand" "")
208390286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
208490286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
208590286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
208690286Sobrien  [(set (match_dup 2) (match_dup 1))
208790286Sobrien   (set (match_dup 0) (match_dup 2))]
208852296Sobrien  "")
208950650Sobrien
209090286Sobrien;; We need to define this as both peepholer and splitter for case
209190286Sobrien;; peephole2 pass is not run.
2092169699Skan;; "&& 1" is needed to keep it from matching the previous pattern.
209390286Sobrien(define_peephole2
209490286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
209590286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
209690286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
209790286Sobrien   && !x86_64_immediate_operand (operands[1], DImode) && 1"
209890286Sobrien  [(set (match_dup 2) (match_dup 3))
209990286Sobrien   (set (match_dup 4) (match_dup 5))]
210090286Sobrien  "split_di (operands, 2, operands + 2, operands + 4);")
210190286Sobrien
210290286Sobrien(define_split
210390286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
210490286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
2105161660Skan  "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
2106169699Skan		    ? flow2_completed : reload_completed)
210790286Sobrien   && !symbolic_operand (operands[1], DImode)
210890286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
210990286Sobrien  [(set (match_dup 2) (match_dup 3))
211090286Sobrien   (set (match_dup 4) (match_dup 5))]
211190286Sobrien  "split_di (operands, 2, operands + 2, operands + 4);")
211290286Sobrien
211390286Sobrien(define_insn "*swapdi_rex64"
211490286Sobrien  [(set (match_operand:DI 0 "register_operand" "+r")
211590286Sobrien	(match_operand:DI 1 "register_operand" "+r"))
211690286Sobrien   (set (match_dup 1)
211790286Sobrien	(match_dup 0))]
211890286Sobrien  "TARGET_64BIT"
211990286Sobrien  "xchg{q}\t%1, %0"
212090286Sobrien  [(set_attr "type" "imov")
2121146906Skan   (set_attr "mode" "DI")
212290286Sobrien   (set_attr "pent_pair" "np")
2123169699Skan   (set_attr "athlon_decode" "vector")])
212490286Sobrien
2125169699Skan(define_expand "movti"
2126169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
2127169699Skan	(match_operand:TI 1 "nonimmediate_operand" ""))]
2128169699Skan  "TARGET_SSE || TARGET_64BIT"
2129169699Skan{
2130169699Skan  if (TARGET_64BIT)
2131169699Skan    ix86_expand_move (TImode, operands);
2132169699Skan  else
2133169699Skan    ix86_expand_vector_move (TImode, operands);
2134169699Skan  DONE;
2135169699Skan})
2136169699Skan
2137169699Skan(define_insn "*movti_internal"
2138169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m")
2139169699Skan	(match_operand:TI 1 "vector_move_operand" "C,xm,x"))]
2140169699Skan  "TARGET_SSE && !TARGET_64BIT
2141169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2142169699Skan{
2143169699Skan  switch (which_alternative)
2144169699Skan    {
2145169699Skan    case 0:
2146169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2147169699Skan	return "xorps\t%0, %0";
2148169699Skan      else
2149169699Skan	return "pxor\t%0, %0";
2150169699Skan    case 1:
2151169699Skan    case 2:
2152169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2153169699Skan	return "movaps\t{%1, %0|%0, %1}";
2154169699Skan      else
2155169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2156169699Skan    default:
2157169699Skan      gcc_unreachable ();
2158169699Skan    }
2159169699Skan}
2160169699Skan  [(set_attr "type" "sselog1,ssemov,ssemov")
2161169699Skan   (set (attr "mode")
2162169699Skan	(cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2163169699Skan		    (ne (symbol_ref "optimize_size") (const_int 0)))
2164169699Skan		 (const_string "V4SF")
2165169699Skan	       (and (eq_attr "alternative" "2")
2166169699Skan		    (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2167169699Skan			(const_int 0)))
2168169699Skan		 (const_string "V4SF")]
2169169699Skan	      (const_string "TI")))])
2170169699Skan
2171169699Skan(define_insn "*movti_rex64"
2172169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,x,xm")
2173169699Skan	(match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))]
2174169699Skan  "TARGET_64BIT
2175169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2176169699Skan{
2177169699Skan  switch (which_alternative)
2178169699Skan    {
2179169699Skan    case 0:
2180169699Skan    case 1:
2181169699Skan      return "#";
2182169699Skan    case 2:
2183169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2184169699Skan	return "xorps\t%0, %0";
2185169699Skan      else
2186169699Skan	return "pxor\t%0, %0";
2187169699Skan    case 3:
2188169699Skan    case 4:
2189169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2190169699Skan	return "movaps\t{%1, %0|%0, %1}";
2191169699Skan      else
2192169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2193169699Skan    default:
2194169699Skan      gcc_unreachable ();
2195169699Skan    }
2196169699Skan}
2197169699Skan  [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
2198169699Skan   (set (attr "mode")
2199169699Skan        (cond [(eq_attr "alternative" "2,3")
2200169699Skan		 (if_then_else
2201169699Skan		   (ne (symbol_ref "optimize_size")
2202169699Skan		       (const_int 0))
2203169699Skan		   (const_string "V4SF")
2204169699Skan		   (const_string "TI"))
2205169699Skan	       (eq_attr "alternative" "4")
2206169699Skan		 (if_then_else
2207169699Skan		   (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2208169699Skan			    (const_int 0))
2209169699Skan			(ne (symbol_ref "optimize_size")
2210169699Skan			    (const_int 0)))
2211169699Skan		   (const_string "V4SF")
2212169699Skan		   (const_string "TI"))]
2213169699Skan	       (const_string "DI")))])
2214169699Skan
2215169699Skan(define_split
2216169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
2217169699Skan        (match_operand:TI 1 "general_operand" ""))]
2218169699Skan  "reload_completed && !SSE_REG_P (operands[0])
2219169699Skan   && !SSE_REG_P (operands[1])"
2220169699Skan  [(const_int 0)]
2221169699Skan  "ix86_split_long_move (operands); DONE;")
2222169699Skan
222350650Sobrien(define_expand "movsf"
222490286Sobrien  [(set (match_operand:SF 0 "nonimmediate_operand" "")
222550650Sobrien	(match_operand:SF 1 "general_operand" ""))]
222618334Speter  ""
222790286Sobrien  "ix86_expand_move (SFmode, operands); DONE;")
222890286Sobrien
222990286Sobrien(define_insn "*pushsf"
223090286Sobrien  [(set (match_operand:SF 0 "push_operand" "=<,<,<")
2231169699Skan	(match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
223290286Sobrien  "!TARGET_64BIT"
223318334Speter{
2234169699Skan  /* Anything else should be already split before reg-stack.  */
2235169699Skan  gcc_assert (which_alternative == 1);
2236169699Skan  return "push{l}\t%1";
223790286Sobrien}
223890286Sobrien  [(set_attr "type" "multi,push,multi")
2239169699Skan   (set_attr "unit" "i387,*,*")
224090286Sobrien   (set_attr "mode" "SF,SI,SF")])
224118334Speter
224290286Sobrien(define_insn "*pushsf_rex64"
224390286Sobrien  [(set (match_operand:SF 0 "push_operand" "=X,X,X")
2244169699Skan	(match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
224590286Sobrien  "TARGET_64BIT"
224618334Speter{
2247169699Skan  /* Anything else should be already split before reg-stack.  */
2248169699Skan  gcc_assert (which_alternative == 1);
2249169699Skan  return "push{q}\t%q1";
225090286Sobrien}
225190286Sobrien  [(set_attr "type" "multi,push,multi")
2252169699Skan   (set_attr "unit" "i387,*,*")
225390286Sobrien   (set_attr "mode" "SF,DI,SF")])
225418334Speter
225590286Sobrien(define_split
225690286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
225790286Sobrien	(match_operand:SF 1 "memory_operand" ""))]
225890286Sobrien  "reload_completed
225990286Sobrien   && GET_CODE (operands[1]) == MEM
2260161660Skan   && constant_pool_reference_p (operands[1])"
226190286Sobrien  [(set (match_dup 0)
226290286Sobrien	(match_dup 1))]
2263161660Skan  "operands[1] = avoid_constant_pool_reference (operands[1]);")
226418334Speter
226590286Sobrien
226690286Sobrien;; %%% Kill this when call knows how to work this out.
226790286Sobrien(define_split
226890286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
2269117404Skan	(match_operand:SF 1 "any_fp_register_operand" ""))]
2270117404Skan  "!TARGET_64BIT"
2271169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
2272169699Skan   (set (mem:SF (reg:SI SP_REG)) (match_dup 1))])
227390286Sobrien
227490286Sobrien(define_split
227590286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
2276117404Skan	(match_operand:SF 1 "any_fp_register_operand" ""))]
2277117404Skan  "TARGET_64BIT"
2278169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
2279169699Skan   (set (mem:SF (reg:DI SP_REG)) (match_dup 1))])
228090286Sobrien
228190286Sobrien(define_insn "*movsf_1"
2282169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"
2283169699Skan	  "=f,m   ,f,r  ,m    ,x,x,x ,m   ,!*y,!rm,!*y")
2284169699Skan	(match_operand:SF 1 "general_operand"
2285169699Skan	  "fm,f,G   ,rmF,Fr,C   ,x   ,xm,x,rm ,*y ,*y"))]
2286169699Skan  "!(MEM_P (operands[0]) && MEM_P (operands[1]))
228790286Sobrien   && (reload_in_progress || reload_completed
228890286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
228990286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
229090286Sobrien       || memory_operand (operands[0], SFmode))" 
229190286Sobrien{
229290286Sobrien  switch (which_alternative)
229318334Speter    {
229490286Sobrien    case 0:
2295169699Skan      return output_387_reg_move (insn, operands);
229618334Speter
229790286Sobrien    case 1:
229890286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
229990286Sobrien        return "fstp%z0\t%y0";
230090286Sobrien      else
230190286Sobrien        return "fst%z0\t%y0";
230218334Speter
230390286Sobrien    case 2:
2304132727Skan      return standard_80387_constant_opcode (operands[1]);
2305132727Skan
2306132727Skan    case 3:
2307132727Skan    case 4:
2308132727Skan      return "mov{l}\t{%1, %0|%0, %1}";
2309132727Skan    case 5:
2310132727Skan      if (get_attr_mode (insn) == MODE_TI)
2311132727Skan	return "pxor\t%0, %0";
2312132727Skan      else
2313132727Skan	return "xorps\t%0, %0";
2314132727Skan    case 6:
2315132727Skan      if (get_attr_mode (insn) == MODE_V4SF)
2316132727Skan	return "movaps\t{%1, %0|%0, %1}";
2317132727Skan      else
2318132727Skan	return "movss\t{%1, %0|%0, %1}";
2319132727Skan    case 7:
2320132727Skan    case 8:
2321132727Skan      return "movss\t{%1, %0|%0, %1}";
2322132727Skan
2323132727Skan    case 9:
2324132727Skan    case 10:
2325132727Skan      return "movd\t{%1, %0|%0, %1}";
2326132727Skan
2327132727Skan    case 11:
2328132727Skan      return "movq\t{%1, %0|%0, %1}";
2329132727Skan
2330132727Skan    default:
2331169699Skan      gcc_unreachable ();
2332132727Skan    }
2333132727Skan}
2334169699Skan  [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov")
2335132727Skan   (set (attr "mode")
2336132727Skan        (cond [(eq_attr "alternative" "3,4,9,10")
2337132727Skan		 (const_string "SI")
2338132727Skan	       (eq_attr "alternative" "5")
2339132727Skan		 (if_then_else
2340132727Skan		   (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2341132727Skan			    	 (const_int 0))
2342132727Skan			     (ne (symbol_ref "TARGET_SSE2")
2343132727Skan				 (const_int 0)))
2344132727Skan			(eq (symbol_ref "optimize_size")
2345132727Skan			    (const_int 0)))
2346132727Skan		   (const_string "TI")
2347132727Skan		   (const_string "V4SF"))
2348132727Skan	       /* For architectures resolving dependencies on
2349132727Skan		  whole SSE registers use APS move to break dependency
2350132727Skan		  chains, otherwise use short move to avoid extra work. 
235118334Speter
2352132727Skan		  Do the same for architectures resolving dependencies on
2353132727Skan		  the parts.  While in DF mode it is better to always handle
2354132727Skan		  just register parts, the SF mode is different due to lack
2355132727Skan		  of instructions to load just part of the register.  It is
2356132727Skan		  better to maintain the whole registers in single format
2357132727Skan		  to avoid problems on using packed logical operations.  */
2358132727Skan	       (eq_attr "alternative" "6")
2359132727Skan		 (if_then_else
2360132727Skan		   (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2361132727Skan			    (const_int 0))
2362169699Skan			(ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2363132727Skan			    (const_int 0)))
2364132727Skan		   (const_string "V4SF")
2365132727Skan		   (const_string "SF"))
2366132727Skan	       (eq_attr "alternative" "11")
2367132727Skan		 (const_string "DI")]
2368132727Skan	       (const_string "SF")))])
2369132727Skan
237090286Sobrien(define_insn "*swapsf"
2371169699Skan  [(set (match_operand:SF 0 "fp_register_operand" "+f")
2372169699Skan	(match_operand:SF 1 "fp_register_operand" "+f"))
237318334Speter   (set (match_dup 1)
237418334Speter	(match_dup 0))]
2375169699Skan  "reload_completed || TARGET_80387"
237618334Speter{
237718334Speter  if (STACK_TOP_P (operands[0]))
237890286Sobrien    return "fxch\t%1";
237918334Speter  else
238090286Sobrien    return "fxch\t%0";
238190286Sobrien}
238290286Sobrien  [(set_attr "type" "fxch")
238390286Sobrien   (set_attr "mode" "SF")])
238418334Speter
238590286Sobrien(define_expand "movdf"
238690286Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
238790286Sobrien	(match_operand:DF 1 "general_operand" ""))]
238890286Sobrien  ""
238990286Sobrien  "ix86_expand_move (DFmode, operands); DONE;")
239052296Sobrien
239190286Sobrien;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
2392132727Skan;; Size of pushdf using integer instructions is 2+2*memory operand size
239390286Sobrien;; On the average, pushdf using integers can be still shorter.  Allow this
239490286Sobrien;; pattern for optimize_size too.
239590286Sobrien
239690286Sobrien(define_insn "*pushdf_nointeger"
239790286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
2398169699Skan	(match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))]
239990286Sobrien  "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
240018334Speter{
2401132727Skan  /* This insn should be already split before reg-stack.  */
2402169699Skan  gcc_unreachable ();
240390286Sobrien}
240490286Sobrien  [(set_attr "type" "multi")
2405169699Skan   (set_attr "unit" "i387,*,*,*")
240690286Sobrien   (set_attr "mode" "DF,SI,SI,DF")])
240718334Speter
240890286Sobrien(define_insn "*pushdf_integer"
240990286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<,<,<")
2410169699Skan	(match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))]
241190286Sobrien  "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
241290286Sobrien{
2413132727Skan  /* This insn should be already split before reg-stack.  */
2414169699Skan  gcc_unreachable ();
241590286Sobrien}
241690286Sobrien  [(set_attr "type" "multi")
2417169699Skan   (set_attr "unit" "i387,*,*")
241890286Sobrien   (set_attr "mode" "DF,SI,DF")])
241918334Speter
242090286Sobrien;; %%% Kill this when call knows how to work this out.
242152296Sobrien(define_split
242252296Sobrien  [(set (match_operand:DF 0 "push_operand" "")
2423117404Skan	(match_operand:DF 1 "any_fp_register_operand" ""))]
2424117404Skan  "!TARGET_64BIT && reload_completed"
2425169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
2426169699Skan   (set (mem:DF (reg:SI SP_REG)) (match_dup 1))]
242752296Sobrien  "")
242850650Sobrien
242990286Sobrien(define_split
243090286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
2431117404Skan	(match_operand:DF 1 "any_fp_register_operand" ""))]
2432117404Skan  "TARGET_64BIT && reload_completed"
2433169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
2434169699Skan   (set (mem:DF (reg:DI SP_REG)) (match_dup 1))]
243590286Sobrien  "")
243690286Sobrien
243790286Sobrien(define_split
243890286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
243950650Sobrien	(match_operand:DF 1 "general_operand" ""))]
244090286Sobrien  "reload_completed"
244190286Sobrien  [(const_int 0)]
244290286Sobrien  "ix86_split_long_move (operands); DONE;")
244390286Sobrien
244490286Sobrien;; Moving is usually shorter when only FP registers are used. This separate
244590286Sobrien;; movdf pattern avoids the use of integer registers for FP operations
244690286Sobrien;; when optimizing for size.
244790286Sobrien
244890286Sobrien(define_insn "*movdf_nointeger"
2449169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"
2450169699Skan			"=f,m,f,*r  ,o  ,Y*x,Y*x,Y*x ,m  ")
2451169699Skan	(match_operand:DF 1 "general_operand"
2452169699Skan			"fm,f,G,*roF,F*r,C  ,Y*x,mY*x,Y*x"))]
245390286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2454132727Skan   && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
245590286Sobrien   && (reload_in_progress || reload_completed
245690286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
245790286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
245890286Sobrien       || memory_operand (operands[0], DFmode))" 
245918334Speter{
246090286Sobrien  switch (which_alternative)
246118334Speter    {
246290286Sobrien    case 0:
2463169699Skan      return output_387_reg_move (insn, operands);
246418334Speter
246590286Sobrien    case 1:
246690286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
246790286Sobrien        return "fstp%z0\t%y0";
246890286Sobrien      else
246990286Sobrien        return "fst%z0\t%y0";
247018334Speter
247190286Sobrien    case 2:
2472132727Skan      return standard_80387_constant_opcode (operands[1]);
247318334Speter
247490286Sobrien    case 3:
247590286Sobrien    case 4:
247690286Sobrien      return "#";
247790286Sobrien    case 5:
2478132727Skan      switch (get_attr_mode (insn))
2479132727Skan	{
2480132727Skan	case MODE_V4SF:
2481132727Skan	  return "xorps\t%0, %0";
2482132727Skan	case MODE_V2DF:
2483132727Skan	  return "xorpd\t%0, %0";
2484132727Skan	case MODE_TI:
2485132727Skan	  return "pxor\t%0, %0";
2486132727Skan	default:
2487169699Skan	  gcc_unreachable ();
2488132727Skan	}
248990286Sobrien    case 6:
2490169699Skan    case 7:
2491169699Skan    case 8:
2492132727Skan      switch (get_attr_mode (insn))
2493132727Skan	{
2494132727Skan	case MODE_V4SF:
2495132727Skan	  return "movaps\t{%1, %0|%0, %1}";
2496132727Skan	case MODE_V2DF:
2497132727Skan	  return "movapd\t{%1, %0|%0, %1}";
2498169699Skan	case MODE_TI:
2499169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
2500169699Skan	case MODE_DI:
2501169699Skan	  return "movq\t{%1, %0|%0, %1}";
2502132727Skan	case MODE_DF:
2503132727Skan	  return "movsd\t{%1, %0|%0, %1}";
2504169699Skan	case MODE_V1DF:
2505169699Skan	  return "movlpd\t{%1, %0|%0, %1}";
2506169699Skan	case MODE_V2SF:
2507169699Skan	  return "movlps\t{%1, %0|%0, %1}";
2508132727Skan	default:
2509169699Skan	  gcc_unreachable ();
2510132727Skan	}
251118334Speter
251290286Sobrien    default:
2513169699Skan      gcc_unreachable ();
251418334Speter    }
251590286Sobrien}
2516169699Skan  [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
2517132727Skan   (set (attr "mode")
2518169699Skan        (cond [(eq_attr "alternative" "0,1,2")
2519169699Skan		 (const_string "DF")
2520169699Skan	       (eq_attr "alternative" "3,4")
2521132727Skan		 (const_string "SI")
2522169699Skan
2523169699Skan	       /* For SSE1, we have many fewer alternatives.  */
2524169699Skan	       (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2525169699Skan		 (cond [(eq_attr "alternative" "5,6")
2526169699Skan			  (const_string "V4SF")
2527169699Skan		       ]
2528169699Skan		   (const_string "V2SF"))
2529169699Skan
2530132727Skan	       /* xorps is one byte shorter.  */
2531132727Skan	       (eq_attr "alternative" "5")
2532132727Skan		 (cond [(ne (symbol_ref "optimize_size")
2533132727Skan			    (const_int 0))
2534132727Skan			  (const_string "V4SF")
2535132727Skan			(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2536132727Skan			    (const_int 0))
2537169699Skan			  (const_string "TI")
2538169699Skan		       ]
2539132727Skan		       (const_string "V2DF"))
2540169699Skan
2541132727Skan	       /* For architectures resolving dependencies on
2542132727Skan		  whole SSE registers use APD move to break dependency
2543132727Skan		  chains, otherwise use short move to avoid extra work.
254418334Speter
2545132727Skan		  movaps encodes one byte shorter.  */
2546132727Skan	       (eq_attr "alternative" "6")
2547132727Skan		 (cond
2548169699Skan		   [(ne (symbol_ref "optimize_size")
2549169699Skan		        (const_int 0))
2550169699Skan		      (const_string "V4SF")
2551169699Skan		    (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2552169699Skan		        (const_int 0))
2553169699Skan		      (const_string "V2DF")
2554169699Skan		   ]
2555132727Skan		   (const_string "DF"))
2556132727Skan	       /* For architectures resolving dependencies on register
2557132727Skan		  parts we may avoid extra work to zero out upper part
2558132727Skan		  of register.  */
2559132727Skan	       (eq_attr "alternative" "7")
2560132727Skan		 (if_then_else
2561169699Skan		   (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2562132727Skan		       (const_int 0))
2563169699Skan		   (const_string "V1DF")
2564169699Skan		   (const_string "DF"))
2565169699Skan	      ]
2566169699Skan	      (const_string "DF")))])
2567132727Skan
256890286Sobrien(define_insn "*movdf_integer"
2569169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"
2570169699Skan		"=f,m,f,r  ,o ,Y*x,Y*x,Y*x,m  ")
2571169699Skan	(match_operand:DF 1 "general_operand"
2572169699Skan		"fm,f,G,roF,Fr,C  ,Y*x,m  ,Y*x"))]
257390286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2574132727Skan   && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
257590286Sobrien   && (reload_in_progress || reload_completed
257690286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
257790286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
257890286Sobrien       || memory_operand (operands[0], DFmode))" 
257990286Sobrien{
258090286Sobrien  switch (which_alternative)
258118334Speter    {
258290286Sobrien    case 0:
2583169699Skan      return output_387_reg_move (insn, operands);
258418334Speter
258590286Sobrien    case 1:
258690286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
258790286Sobrien        return "fstp%z0\t%y0";
258890286Sobrien      else
258990286Sobrien        return "fst%z0\t%y0";
259018334Speter
259190286Sobrien    case 2:
2592132727Skan      return standard_80387_constant_opcode (operands[1]);
259318334Speter
259490286Sobrien    case 3:
259590286Sobrien    case 4:
259690286Sobrien      return "#";
259718334Speter
259890286Sobrien    case 5:
2599132727Skan      switch (get_attr_mode (insn))
2600132727Skan	{
2601132727Skan	case MODE_V4SF:
2602132727Skan	  return "xorps\t%0, %0";
2603132727Skan	case MODE_V2DF:
2604132727Skan	  return "xorpd\t%0, %0";
2605132727Skan	case MODE_TI:
2606132727Skan	  return "pxor\t%0, %0";
2607132727Skan	default:
2608169699Skan	  gcc_unreachable ();
2609132727Skan	}
261090286Sobrien    case 6:
2611169699Skan    case 7:
2612169699Skan    case 8:
2613132727Skan      switch (get_attr_mode (insn))
2614132727Skan	{
2615132727Skan	case MODE_V4SF:
2616132727Skan	  return "movaps\t{%1, %0|%0, %1}";
2617132727Skan	case MODE_V2DF:
2618132727Skan	  return "movapd\t{%1, %0|%0, %1}";
2619169699Skan	case MODE_TI:
2620169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
2621169699Skan	case MODE_DI:
2622169699Skan	  return "movq\t{%1, %0|%0, %1}";
2623132727Skan	case MODE_DF:
2624132727Skan	  return "movsd\t{%1, %0|%0, %1}";
2625169699Skan	case MODE_V1DF:
2626169699Skan	  return "movlpd\t{%1, %0|%0, %1}";
2627169699Skan	case MODE_V2SF:
2628169699Skan	  return "movlps\t{%1, %0|%0, %1}";
2629132727Skan	default:
2630169699Skan	  gcc_unreachable ();
2631132727Skan	}
263218334Speter
263390286Sobrien    default:
2634169699Skan      gcc_unreachable();
263590286Sobrien    }
263690286Sobrien}
2637169699Skan  [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
2638132727Skan   (set (attr "mode")
2639169699Skan        (cond [(eq_attr "alternative" "0,1,2")
2640169699Skan		 (const_string "DF")
2641169699Skan	       (eq_attr "alternative" "3,4")
2642132727Skan		 (const_string "SI")
2643169699Skan
2644169699Skan	       /* For SSE1, we have many fewer alternatives.  */
2645169699Skan	       (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2646169699Skan		 (cond [(eq_attr "alternative" "5,6")
2647169699Skan			  (const_string "V4SF")
2648169699Skan		       ]
2649169699Skan		   (const_string "V2SF"))
2650169699Skan
2651132727Skan	       /* xorps is one byte shorter.  */
2652132727Skan	       (eq_attr "alternative" "5")
2653132727Skan		 (cond [(ne (symbol_ref "optimize_size")
2654132727Skan			    (const_int 0))
2655132727Skan			  (const_string "V4SF")
2656132727Skan			(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2657132727Skan			    (const_int 0))
2658169699Skan			  (const_string "TI")
2659169699Skan		       ]
2660132727Skan		       (const_string "V2DF"))
2661169699Skan
2662132727Skan	       /* For architectures resolving dependencies on
2663132727Skan		  whole SSE registers use APD move to break dependency
2664169699Skan		  chains, otherwise use short move to avoid extra work.
266518334Speter
2666132727Skan		  movaps encodes one byte shorter.  */
2667132727Skan	       (eq_attr "alternative" "6")
2668132727Skan		 (cond
2669169699Skan		   [(ne (symbol_ref "optimize_size")
2670169699Skan		        (const_int 0))
2671169699Skan		      (const_string "V4SF")
2672169699Skan		    (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2673169699Skan		        (const_int 0))
2674169699Skan		      (const_string "V2DF")
2675169699Skan		   ]
2676132727Skan		   (const_string "DF"))
2677132727Skan	       /* For architectures resolving dependencies on register
2678132727Skan		  parts we may avoid extra work to zero out upper part
2679132727Skan		  of register.  */
2680132727Skan	       (eq_attr "alternative" "7")
2681132727Skan		 (if_then_else
2682169699Skan		   (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2683132727Skan		       (const_int 0))
2684169699Skan		   (const_string "V1DF")
2685169699Skan		   (const_string "DF"))
2686169699Skan	      ]
2687169699Skan	      (const_string "DF")))])
2688132727Skan
268990286Sobrien(define_split
269090286Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
269190286Sobrien	(match_operand:DF 1 "general_operand" ""))]
269290286Sobrien  "reload_completed
269390286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
269490286Sobrien   && ! (ANY_FP_REG_P (operands[0]) || 
269590286Sobrien	 (GET_CODE (operands[0]) == SUBREG
269690286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
269790286Sobrien   && ! (ANY_FP_REG_P (operands[1]) || 
269890286Sobrien	 (GET_CODE (operands[1]) == SUBREG
269990286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
270090286Sobrien  [(const_int 0)]
270190286Sobrien  "ix86_split_long_move (operands); DONE;")
270250650Sobrien
270390286Sobrien(define_insn "*swapdf"
2704169699Skan  [(set (match_operand:DF 0 "fp_register_operand" "+f")
2705169699Skan	(match_operand:DF 1 "fp_register_operand" "+f"))
270618334Speter   (set (match_dup 1)
270718334Speter	(match_dup 0))]
2708169699Skan  "reload_completed || TARGET_80387"
270918334Speter{
271018334Speter  if (STACK_TOP_P (operands[0]))
271190286Sobrien    return "fxch\t%1";
271218334Speter  else
271390286Sobrien    return "fxch\t%0";
271490286Sobrien}
271590286Sobrien  [(set_attr "type" "fxch")
271690286Sobrien   (set_attr "mode" "DF")])
271718334Speter
271890286Sobrien(define_expand "movxf"
271990286Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
272090286Sobrien	(match_operand:XF 1 "general_operand" ""))]
2721132727Skan  ""
272290286Sobrien  "ix86_expand_move (XFmode, operands); DONE;")
272390286Sobrien
272490286Sobrien;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
2725132727Skan;; Size of pushdf using integer instructions is 3+3*memory operand size
272690286Sobrien;; Pushing using integer instructions is longer except for constants
272790286Sobrien;; and direct memory references.
272890286Sobrien;; (assuming that any given constant is pushed only once, but this ought to be
272990286Sobrien;;  handled elsewhere).
273090286Sobrien
273190286Sobrien(define_insn "*pushxf_nointeger"
273290286Sobrien  [(set (match_operand:XF 0 "push_operand" "=X,X,X")
273390286Sobrien	(match_operand:XF 1 "general_no_elim_operand" "f,Fo,*r"))]
273490286Sobrien  "optimize_size"
273590286Sobrien{
2736132727Skan  /* This insn should be already split before reg-stack.  */
2737169699Skan  gcc_unreachable ();
273890286Sobrien}
273990286Sobrien  [(set_attr "type" "multi")
2740169699Skan   (set_attr "unit" "i387,*,*")
274190286Sobrien   (set_attr "mode" "XF,SI,SI")])
274250650Sobrien
274390286Sobrien(define_insn "*pushxf_integer"
274490286Sobrien  [(set (match_operand:XF 0 "push_operand" "=<,<")
2745169699Skan	(match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
274690286Sobrien  "!optimize_size"
274790286Sobrien{
2748132727Skan  /* This insn should be already split before reg-stack.  */
2749169699Skan  gcc_unreachable ();
275090286Sobrien}
275190286Sobrien  [(set_attr "type" "multi")
2752169699Skan   (set_attr "unit" "i387,*")
275390286Sobrien   (set_attr "mode" "XF,SI")])
275490286Sobrien
275552296Sobrien(define_split
275690286Sobrien  [(set (match_operand 0 "push_operand" "")
275790286Sobrien	(match_operand 1 "general_operand" ""))]
275890286Sobrien  "reload_completed
275990286Sobrien   && (GET_MODE (operands[0]) == XFmode
276090286Sobrien       || GET_MODE (operands[0]) == DFmode)
2761117404Skan   && !ANY_FP_REG_P (operands[1])"
276290286Sobrien  [(const_int 0)]
276390286Sobrien  "ix86_split_long_move (operands); DONE;")
276490286Sobrien
276590286Sobrien(define_split
276652296Sobrien  [(set (match_operand:XF 0 "push_operand" "")
2767117404Skan	(match_operand:XF 1 "any_fp_register_operand" ""))]
2768117404Skan  "!TARGET_64BIT"
2769169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
2770169699Skan   (set (mem:XF (reg:SI SP_REG)) (match_dup 1))]
2771132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
277250650Sobrien
277390286Sobrien(define_split
2774132727Skan  [(set (match_operand:XF 0 "push_operand" "")
2775132727Skan	(match_operand:XF 1 "any_fp_register_operand" ""))]
2776117404Skan  "TARGET_64BIT"
2777169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
2778169699Skan   (set (mem:XF (reg:DI SP_REG)) (match_dup 1))]
2779132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
278090286Sobrien
278190286Sobrien;; Do not use integer registers when optimizing for size
278290286Sobrien(define_insn "*movxf_nointeger"
278390286Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o")
278490286Sobrien	(match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))]
2785132727Skan  "optimize_size
278690286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
278790286Sobrien   && (reload_in_progress || reload_completed
278890286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
278990286Sobrien       || memory_operand (operands[0], XFmode))" 
279018334Speter{
279190286Sobrien  switch (which_alternative)
279218334Speter    {
279390286Sobrien    case 0:
2794169699Skan      return output_387_reg_move (insn, operands);
279518334Speter
279690286Sobrien    case 1:
279790286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
279890286Sobrien	 we need one, follow the store with a load.  */
279990286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
280090286Sobrien        return "fstp%z0\t%y0\;fld%z0\t%y0";
280190286Sobrien      else
280290286Sobrien        return "fstp%z0\t%y0";
280318334Speter
280490286Sobrien    case 2:
2805132727Skan      return standard_80387_constant_opcode (operands[1]);
280618334Speter
280790286Sobrien    case 3: case 4:
280890286Sobrien      return "#";
2809169699Skan    default:
2810169699Skan      gcc_unreachable ();
281190286Sobrien    }
281290286Sobrien}
281390286Sobrien  [(set_attr "type" "fmov,fmov,fmov,multi,multi")
281490286Sobrien   (set_attr "mode" "XF,XF,XF,SI,SI")])
281518334Speter
281690286Sobrien(define_insn "*movxf_integer"
2817169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
2818169699Skan	(match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
2819132727Skan  "!optimize_size
282090286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
282190286Sobrien   && (reload_in_progress || reload_completed
282290286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
282390286Sobrien       || memory_operand (operands[0], XFmode))" 
282490286Sobrien{
282590286Sobrien  switch (which_alternative)
282618334Speter    {
282790286Sobrien    case 0:
2828169699Skan      return output_387_reg_move (insn, operands);
282918334Speter
283090286Sobrien    case 1:
283190286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
283290286Sobrien	 we need one, follow the store with a load.  */
283390286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
283490286Sobrien        return "fstp%z0\t%y0\;fld%z0\t%y0";
283590286Sobrien      else
283690286Sobrien        return "fstp%z0\t%y0";
283718334Speter
283890286Sobrien    case 2:
2839132727Skan      return standard_80387_constant_opcode (operands[1]);
284018334Speter
284190286Sobrien    case 3: case 4:
284290286Sobrien      return "#";
2843169699Skan
2844169699Skan    default:
2845169699Skan      gcc_unreachable ();
284690286Sobrien    }
284790286Sobrien}
284890286Sobrien  [(set_attr "type" "fmov,fmov,fmov,multi,multi")
284990286Sobrien   (set_attr "mode" "XF,XF,XF,SI,SI")])
285018334Speter
285190286Sobrien(define_split
285290286Sobrien  [(set (match_operand 0 "nonimmediate_operand" "")
285390286Sobrien	(match_operand 1 "general_operand" ""))]
285490286Sobrien  "reload_completed
285590286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2856132727Skan   && GET_MODE (operands[0]) == XFmode
285790286Sobrien   && ! (ANY_FP_REG_P (operands[0]) || 
285890286Sobrien	 (GET_CODE (operands[0]) == SUBREG
285990286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
286090286Sobrien   && ! (ANY_FP_REG_P (operands[1]) || 
286190286Sobrien	 (GET_CODE (operands[1]) == SUBREG
286290286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
286390286Sobrien  [(const_int 0)]
286490286Sobrien  "ix86_split_long_move (operands); DONE;")
286518334Speter
286690286Sobrien(define_split
286790286Sobrien  [(set (match_operand 0 "register_operand" "")
286890286Sobrien	(match_operand 1 "memory_operand" ""))]
286990286Sobrien  "reload_completed
287090286Sobrien   && GET_CODE (operands[1]) == MEM
2871132727Skan   && (GET_MODE (operands[0]) == XFmode
287290286Sobrien       || GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode)
2873161660Skan   && constant_pool_reference_p (operands[1])"
2874132727Skan  [(set (match_dup 0) (match_dup 1))]
2875132727Skan{
2876161660Skan  rtx c = avoid_constant_pool_reference (operands[1]);
2877132727Skan  rtx r = operands[0];
287890286Sobrien
2879132727Skan  if (GET_CODE (r) == SUBREG)
2880132727Skan    r = SUBREG_REG (r);
2881132727Skan
2882132727Skan  if (SSE_REG_P (r))
2883132727Skan    {
2884132727Skan      if (!standard_sse_constant_p (c))
2885132727Skan	FAIL;
2886132727Skan    }
2887132727Skan  else if (FP_REG_P (r))
2888132727Skan    {
2889132727Skan      if (!standard_80387_constant_p (c))
2890132727Skan	FAIL;
2891132727Skan    }
2892132727Skan  else if (MMX_REG_P (r))
2893132727Skan    FAIL;
2894132727Skan
2895132727Skan  operands[1] = c;
2896132727Skan})
2897132727Skan
289890286Sobrien(define_insn "swapxf"
289990286Sobrien  [(set (match_operand:XF 0 "register_operand" "+f")
290090286Sobrien	(match_operand:XF 1 "register_operand" "+f"))
290118334Speter   (set (match_dup 1)
290218334Speter	(match_dup 0))]
2903169699Skan  "TARGET_80387"
290418334Speter{
290518334Speter  if (STACK_TOP_P (operands[0]))
290690286Sobrien    return "fxch\t%1";
290718334Speter  else
290890286Sobrien    return "fxch\t%0";
290990286Sobrien}
291090286Sobrien  [(set_attr "type" "fxch")
291190286Sobrien   (set_attr "mode" "XF")])
2912169699Skan
2913169699Skan(define_expand "movtf"
2914169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "")
2915169699Skan	(match_operand:TF 1 "nonimmediate_operand" ""))]
2916169699Skan  "TARGET_64BIT"
2917169699Skan{
2918169699Skan  ix86_expand_move (TFmode, operands);
2919169699Skan  DONE;
2920169699Skan})
2921169699Skan
2922169699Skan(define_insn "*movtf_internal"
2923169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm")
2924169699Skan	(match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))]
2925169699Skan  "TARGET_64BIT
2926169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2927169699Skan{
2928169699Skan  switch (which_alternative)
2929169699Skan    {
2930169699Skan    case 0:
2931169699Skan    case 1:
2932169699Skan      return "#";
2933169699Skan    case 2:
2934169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2935169699Skan	return "xorps\t%0, %0";
2936169699Skan      else
2937169699Skan	return "pxor\t%0, %0";
2938169699Skan    case 3:
2939169699Skan    case 4:
2940169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2941169699Skan	return "movaps\t{%1, %0|%0, %1}";
2942169699Skan      else
2943169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2944169699Skan    default:
2945169699Skan      gcc_unreachable ();
2946169699Skan    }
2947169699Skan}
2948169699Skan  [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
2949169699Skan   (set (attr "mode")
2950169699Skan        (cond [(eq_attr "alternative" "2,3")
2951169699Skan		 (if_then_else
2952169699Skan		   (ne (symbol_ref "optimize_size")
2953169699Skan		       (const_int 0))
2954169699Skan		   (const_string "V4SF")
2955169699Skan		   (const_string "TI"))
2956169699Skan	       (eq_attr "alternative" "4")
2957169699Skan		 (if_then_else
2958169699Skan		   (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2959169699Skan			    (const_int 0))
2960169699Skan			(ne (symbol_ref "optimize_size")
2961169699Skan			    (const_int 0)))
2962169699Skan		   (const_string "V4SF")
2963169699Skan		   (const_string "TI"))]
2964169699Skan	       (const_string "DI")))])
2965169699Skan
2966169699Skan(define_split
2967169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "")
2968169699Skan        (match_operand:TF 1 "general_operand" ""))]
2969169699Skan  "reload_completed && !SSE_REG_P (operands[0])
2970169699Skan   && !SSE_REG_P (operands[1])"
2971169699Skan  [(const_int 0)]
2972169699Skan  "ix86_split_long_move (operands); DONE;")
297318334Speter
297490286Sobrien;; Zero extension instructions
297518334Speter
297652296Sobrien(define_expand "zero_extendhisi2"
297752296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
297890286Sobrien     (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
297952296Sobrien  ""
298090286Sobrien{
298190286Sobrien  if (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
298218334Speter    {
298390286Sobrien      operands[1] = force_reg (HImode, operands[1]);
298490286Sobrien      emit_insn (gen_zero_extendhisi2_and (operands[0], operands[1]));
298590286Sobrien      DONE;
298618334Speter    }
298790286Sobrien})
298818334Speter
298990286Sobrien(define_insn "zero_extendhisi2_and"
299090286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
299190286Sobrien     (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
2992169699Skan   (clobber (reg:CC FLAGS_REG))]
299390286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
299490286Sobrien  "#"
299590286Sobrien  [(set_attr "type" "alu1")
299690286Sobrien   (set_attr "mode" "SI")])
299750650Sobrien
299850650Sobrien(define_split
299950650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
300090286Sobrien	(zero_extend:SI (match_operand:HI 1 "register_operand" "")))
3001169699Skan   (clobber (reg:CC FLAGS_REG))]
300290286Sobrien  "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
300390286Sobrien  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535)))
3004169699Skan	      (clobber (reg:CC FLAGS_REG))])]
300590286Sobrien  "")
300650650Sobrien
300790286Sobrien(define_insn "*zero_extendhisi2_movzwl"
300890286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
300990286Sobrien     (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
301090286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
301190286Sobrien  "movz{wl|x}\t{%1, %0|%0, %1}"
301290286Sobrien  [(set_attr "type" "imovx")
301390286Sobrien   (set_attr "mode" "SI")])
301450650Sobrien
301552296Sobrien(define_expand "zero_extendqihi2"
301690286Sobrien  [(parallel
301790286Sobrien    [(set (match_operand:HI 0 "register_operand" "")
301890286Sobrien       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3019169699Skan     (clobber (reg:CC FLAGS_REG))])]
302052296Sobrien  ""
302152296Sobrien  "")
302252296Sobrien
302390286Sobrien(define_insn "*zero_extendqihi2_and"
302490286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,?&q")
302590286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
3026169699Skan   (clobber (reg:CC FLAGS_REG))]
302790286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
302890286Sobrien  "#"
302990286Sobrien  [(set_attr "type" "alu1")
303090286Sobrien   (set_attr "mode" "HI")])
303152296Sobrien
303290286Sobrien(define_insn "*zero_extendqihi2_movzbw_and"
303390286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
303490286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
3035169699Skan   (clobber (reg:CC FLAGS_REG))]
303690286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
303790286Sobrien  "#"
303890286Sobrien  [(set_attr "type" "imovx,alu1")
303990286Sobrien   (set_attr "mode" "HI")])
304052296Sobrien
3041169699Skan; zero extend to SImode here to avoid partial register stalls
3042169699Skan(define_insn "*zero_extendqihi2_movzbl"
304390286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r")
304490286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
304590286Sobrien  "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
3046169699Skan  "movz{bl|x}\t{%1, %k0|%k0, %k1}"
304790286Sobrien  [(set_attr "type" "imovx")
3048169699Skan   (set_attr "mode" "SI")])
304950650Sobrien
305090286Sobrien;; For the movzbw case strip only the clobber
305150650Sobrien(define_split
305250650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
305390286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3054169699Skan   (clobber (reg:CC FLAGS_REG))]
305590286Sobrien  "reload_completed 
305690286Sobrien   && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
305790286Sobrien   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
305890286Sobrien  [(set (match_operand:HI 0 "register_operand" "")
305990286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))])
306050650Sobrien
306190286Sobrien;; When source and destination does not overlap, clear destination
306290286Sobrien;; first and then do the movb
306350650Sobrien(define_split
306450650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
306590286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3066169699Skan   (clobber (reg:CC FLAGS_REG))]
306790286Sobrien  "reload_completed
306890286Sobrien   && ANY_QI_REG_P (operands[0])
306990286Sobrien   && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
307090286Sobrien   && !reg_overlap_mentioned_p (operands[0], operands[1])"
307190286Sobrien  [(set (match_dup 0) (const_int 0))
307290286Sobrien   (set (strict_low_part (match_dup 2)) (match_dup 1))]
307390286Sobrien  "operands[2] = gen_lowpart (QImode, operands[0]);")
307450650Sobrien
307590286Sobrien;; Rest is handled by single and.
307650650Sobrien(define_split
307750650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
307890286Sobrien	(zero_extend:HI (match_operand:QI 1 "register_operand" "")))
3079169699Skan   (clobber (reg:CC FLAGS_REG))]
308090286Sobrien  "reload_completed
308190286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
308290286Sobrien  [(parallel [(set (match_dup 0) (and:HI (match_dup 0) (const_int 255)))
3083169699Skan	      (clobber (reg:CC FLAGS_REG))])]
308490286Sobrien  "")
308550650Sobrien
308652296Sobrien(define_expand "zero_extendqisi2"
308790286Sobrien  [(parallel
308890286Sobrien    [(set (match_operand:SI 0 "register_operand" "")
308990286Sobrien       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3090169699Skan     (clobber (reg:CC FLAGS_REG))])]
309152296Sobrien  ""
309252296Sobrien  "")
309352296Sobrien
309490286Sobrien(define_insn "*zero_extendqisi2_and"
309590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,?&q")
309690286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
3097169699Skan   (clobber (reg:CC FLAGS_REG))]
309890286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
309990286Sobrien  "#"
310090286Sobrien  [(set_attr "type" "alu1")
310190286Sobrien   (set_attr "mode" "SI")])
310252296Sobrien
310390286Sobrien(define_insn "*zero_extendqisi2_movzbw_and"
310490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
310590286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
3106169699Skan   (clobber (reg:CC FLAGS_REG))]
310790286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
310890286Sobrien  "#"
310990286Sobrien  [(set_attr "type" "imovx,alu1")
311090286Sobrien   (set_attr "mode" "SI")])
311150650Sobrien
311290286Sobrien(define_insn "*zero_extendqisi2_movzbw"
311390286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
311490286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
311590286Sobrien  "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
311690286Sobrien  "movz{bl|x}\t{%1, %0|%0, %1}"
311790286Sobrien  [(set_attr "type" "imovx")
311890286Sobrien   (set_attr "mode" "SI")])
311918334Speter
312090286Sobrien;; For the movzbl case strip only the clobber
312150650Sobrien(define_split
312250650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
312390286Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3124169699Skan   (clobber (reg:CC FLAGS_REG))]
312590286Sobrien  "reload_completed 
312690286Sobrien   && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
312790286Sobrien   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
312890286Sobrien  [(set (match_dup 0)
312990286Sobrien	(zero_extend:SI (match_dup 1)))])
313050650Sobrien
313190286Sobrien;; When source and destination does not overlap, clear destination
313290286Sobrien;; first and then do the movb
313350650Sobrien(define_split
313450650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
313590286Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3136169699Skan   (clobber (reg:CC FLAGS_REG))]
313790286Sobrien  "reload_completed
313890286Sobrien   && ANY_QI_REG_P (operands[0])
313990286Sobrien   && (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)
314090286Sobrien   && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
314190286Sobrien   && !reg_overlap_mentioned_p (operands[0], operands[1])"
314290286Sobrien  [(set (match_dup 0) (const_int 0))
314390286Sobrien   (set (strict_low_part (match_dup 2)) (match_dup 1))]
314490286Sobrien  "operands[2] = gen_lowpart (QImode, operands[0]);")
314550650Sobrien
314690286Sobrien;; Rest is handled by single and.
314750650Sobrien(define_split
314850650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
314990286Sobrien	(zero_extend:SI (match_operand:QI 1 "register_operand" "")))
3150169699Skan   (clobber (reg:CC FLAGS_REG))]
315190286Sobrien  "reload_completed
315290286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
315390286Sobrien  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 255)))
3154169699Skan	      (clobber (reg:CC FLAGS_REG))])]
315590286Sobrien  "")
315650650Sobrien
315790286Sobrien;; %%% Kill me once multi-word ops are sane.
315890286Sobrien(define_expand "zero_extendsidi2"
315990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
316090286Sobrien     (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
316118334Speter  ""
316290286Sobrien  "if (!TARGET_64BIT)
316390286Sobrien     {
316490286Sobrien       emit_insn (gen_zero_extendsidi2_32 (operands[0], operands[1]));
316590286Sobrien       DONE;
316690286Sobrien     }
316790286Sobrien  ")
316850650Sobrien
316990286Sobrien(define_insn "zero_extendsidi2_32"
3170169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,?*y,?*Y")
3171132727Skan	(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,rm,rm")))
3172169699Skan   (clobber (reg:CC FLAGS_REG))]
3173169699Skan  "!TARGET_64BIT"
3174132727Skan  "@
3175132727Skan   #
3176132727Skan   #
3177132727Skan   #
3178132727Skan   movd\t{%1, %0|%0, %1}
3179132727Skan   movd\t{%1, %0|%0, %1}"
3180132727Skan  [(set_attr "mode" "SI,SI,SI,DI,TI")
3181132727Skan   (set_attr "type" "multi,multi,multi,mmxmov,ssemov")])
3182132727Skan
318390286Sobrien(define_insn "zero_extendsidi2_rex64"
3184169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*y,?*Y")
3185132727Skan     (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,rm,rm")))]
3186169699Skan  "TARGET_64BIT"
3187132727Skan  "@
3188132727Skan   mov\t{%k1, %k0|%k0, %k1}
3189132727Skan   #
3190132727Skan   movd\t{%1, %0|%0, %1}
3191132727Skan   movd\t{%1, %0|%0, %1}"
3192132727Skan  [(set_attr "type" "imovx,imov,mmxmov,ssemov")
3193132727Skan   (set_attr "mode" "SI,DI,SI,SI")])
3194132727Skan
319590286Sobrien(define_split
319690286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
319790286Sobrien     (zero_extend:DI (match_dup 0)))]
319890286Sobrien  "TARGET_64BIT"
319990286Sobrien  [(set (match_dup 4) (const_int 0))]
320090286Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
320190286Sobrien
320252296Sobrien(define_split 
320352296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
320490286Sobrien	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
3205169699Skan   (clobber (reg:CC FLAGS_REG))]
320690286Sobrien  "!TARGET_64BIT && reload_completed
320790286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
320852296Sobrien  [(set (match_dup 4) (const_int 0))]
320952296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
321050650Sobrien
321152296Sobrien(define_split 
321252296Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
321390286Sobrien	(zero_extend:DI (match_operand:SI 1 "general_operand" "")))
3214169699Skan   (clobber (reg:CC FLAGS_REG))]
3215132727Skan  "!TARGET_64BIT && reload_completed
3216132727Skan   && !SSE_REG_P (operands[0]) && !MMX_REG_P (operands[0])"
321752296Sobrien  [(set (match_dup 3) (match_dup 1))
321852296Sobrien   (set (match_dup 4) (const_int 0))]
321952296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
322090286Sobrien
322190286Sobrien(define_insn "zero_extendhidi2"
3222169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
3223169699Skan     (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
322490286Sobrien  "TARGET_64BIT"
3225169699Skan  "movz{wl|x}\t{%1, %k0|%k0, %1}"
322690286Sobrien  [(set_attr "type" "imovx")
3227169699Skan   (set_attr "mode" "DI")])
322890286Sobrien
322990286Sobrien(define_insn "zero_extendqidi2"
3230169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
3231169699Skan     (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
323290286Sobrien  "TARGET_64BIT"
3233169699Skan  "movz{bl|x}\t{%1, %k0|%k0, %1}"
323490286Sobrien  [(set_attr "type" "imovx")
3235169699Skan   (set_attr "mode" "DI")])
323618334Speter
323790286Sobrien;; Sign extension instructions
323818334Speter
323990286Sobrien(define_expand "extendsidi2"
324090286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
324190286Sobrien		   (sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3242169699Skan	      (clobber (reg:CC FLAGS_REG))
324390286Sobrien	      (clobber (match_scratch:SI 2 ""))])]
324490286Sobrien  ""
324590286Sobrien{
324690286Sobrien  if (TARGET_64BIT)
324790286Sobrien    {
324890286Sobrien      emit_insn (gen_extendsidi2_rex64 (operands[0], operands[1]));
324990286Sobrien      DONE;
325090286Sobrien    }
325190286Sobrien})
325290286Sobrien
325390286Sobrien(define_insn "*extendsidi2_1"
325490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=*A,r,?r,?*o")
325590286Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,r")))
3256169699Skan   (clobber (reg:CC FLAGS_REG))
325752296Sobrien   (clobber (match_scratch:SI 2 "=X,X,X,&r"))]
325890286Sobrien  "!TARGET_64BIT"
325952296Sobrien  "#")
326052296Sobrien
326190286Sobrien(define_insn "extendsidi2_rex64"
326290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*a,r")
326390286Sobrien	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "*0,rm")))]
326490286Sobrien  "TARGET_64BIT"
326590286Sobrien  "@
326690286Sobrien   {cltq|cdqe}
326790286Sobrien   movs{lq|x}\t{%1,%0|%0, %1}"
326890286Sobrien  [(set_attr "type" "imovx")
326990286Sobrien   (set_attr "mode" "DI")
327090286Sobrien   (set_attr "prefix_0f" "0")
327190286Sobrien   (set_attr "modrm" "0,1")])
327290286Sobrien
327390286Sobrien(define_insn "extendhidi2"
327490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
327590286Sobrien	(sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
327690286Sobrien  "TARGET_64BIT"
327790286Sobrien  "movs{wq|x}\t{%1,%0|%0, %1}"
327890286Sobrien  [(set_attr "type" "imovx")
327990286Sobrien   (set_attr "mode" "DI")])
328090286Sobrien
328190286Sobrien(define_insn "extendqidi2"
328290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
328390286Sobrien	(sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
328490286Sobrien  "TARGET_64BIT"
328590286Sobrien  "movs{bq|x}\t{%1,%0|%0, %1}"
328690286Sobrien   [(set_attr "type" "imovx")
328790286Sobrien    (set_attr "mode" "DI")])
328890286Sobrien
328952296Sobrien;; Extend to memory case when source register does die.
329052296Sobrien(define_split 
329152296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
329252296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3293169699Skan   (clobber (reg:CC FLAGS_REG))
329452296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
329590286Sobrien  "(reload_completed
329652296Sobrien    && dead_or_set_p (insn, operands[1])
329752296Sobrien    && !reg_mentioned_p (operands[1], operands[0]))"
329852296Sobrien  [(set (match_dup 3) (match_dup 1))
329990286Sobrien   (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
3300169699Skan	      (clobber (reg:CC FLAGS_REG))])
330152296Sobrien   (set (match_dup 4) (match_dup 1))]
330252296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
330352296Sobrien
330452296Sobrien;; Extend to memory case when source register does not die.
330552296Sobrien(define_split 
330652296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
330752296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3308169699Skan   (clobber (reg:CC FLAGS_REG))
330952296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
331090286Sobrien  "reload_completed"
331152296Sobrien  [(const_int 0)]
331218334Speter{
331352296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
331452296Sobrien
331552296Sobrien  emit_move_insn (operands[3], operands[1]);
331652296Sobrien
331752296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
331852296Sobrien  if (true_regnum (operands[1]) == 0
331952296Sobrien      && true_regnum (operands[2]) == 1
332090286Sobrien      && (optimize_size || TARGET_USE_CLTD))
332118334Speter    {
332290286Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[1], GEN_INT (31)));
332318334Speter    }
332452296Sobrien  else
332552296Sobrien    {
332652296Sobrien      emit_move_insn (operands[2], operands[1]);
332790286Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[2], GEN_INT (31)));
332852296Sobrien    }
332952296Sobrien  emit_move_insn (operands[4], operands[2]);
333052296Sobrien  DONE;
333190286Sobrien})
333218334Speter
333352296Sobrien;; Extend to register case.  Optimize case where source and destination
333452296Sobrien;; registers match and cases where we can use cltd.
333552296Sobrien(define_split 
333652296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
333752296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3338169699Skan   (clobber (reg:CC FLAGS_REG))
333952296Sobrien   (clobber (match_scratch:SI 2 ""))]
334052296Sobrien  "reload_completed"
334152296Sobrien  [(const_int 0)]
334252296Sobrien{
334352296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
334418334Speter
334552296Sobrien  if (true_regnum (operands[3]) != true_regnum (operands[1]))
334652296Sobrien    emit_move_insn (operands[3], operands[1]);
334752296Sobrien
334852296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
334952296Sobrien  if (true_regnum (operands[3]) == 0
335090286Sobrien      && (optimize_size || TARGET_USE_CLTD))
335152296Sobrien    {
335290286Sobrien      emit_insn (gen_ashrsi3_31 (operands[4], operands[3], GEN_INT (31)));
335352296Sobrien      DONE;
335452296Sobrien    }
335552296Sobrien
335652296Sobrien  if (true_regnum (operands[4]) != true_regnum (operands[1]))
335752296Sobrien    emit_move_insn (operands[4], operands[1]);
335852296Sobrien
335990286Sobrien  emit_insn (gen_ashrsi3_31 (operands[4], operands[4], GEN_INT (31)));
336052296Sobrien  DONE;
336190286Sobrien})
336218334Speter
336318334Speter(define_insn "extendhisi2"
336490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=*a,r")
336590286Sobrien	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm")))]
336618334Speter  ""
336718334Speter{
336890286Sobrien  switch (get_attr_prefix_0f (insn))
336990286Sobrien    {
337090286Sobrien    case 0:
337190286Sobrien      return "{cwtl|cwde}";
337290286Sobrien    default:
337390286Sobrien      return "movs{wl|x}\t{%1,%0|%0, %1}";
337490286Sobrien    }
337590286Sobrien}
337690286Sobrien  [(set_attr "type" "imovx")
337790286Sobrien   (set_attr "mode" "SI")
337890286Sobrien   (set (attr "prefix_0f")
337990286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
338090286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
338190286Sobrien			(eq_attr "alternative" "0"))
338290286Sobrien	(const_string "0")
338390286Sobrien	(const_string "1")))
338490286Sobrien   (set (attr "modrm")
338590286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
338690286Sobrien	(const_string "0")
338790286Sobrien	(const_string "1")))])
338818334Speter
338990286Sobrien(define_insn "*extendhisi2_zext"
339090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*a,r")
339190286Sobrien	(zero_extend:DI
339290286Sobrien	  (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm"))))]
339390286Sobrien  "TARGET_64BIT"
339490286Sobrien{
339590286Sobrien  switch (get_attr_prefix_0f (insn))
339690286Sobrien    {
339790286Sobrien    case 0:
339890286Sobrien      return "{cwtl|cwde}";
339990286Sobrien    default:
340090286Sobrien      return "movs{wl|x}\t{%1,%k0|%k0, %1}";
340190286Sobrien    }
340290286Sobrien}
340390286Sobrien  [(set_attr "type" "imovx")
340490286Sobrien   (set_attr "mode" "SI")
340590286Sobrien   (set (attr "prefix_0f")
340690286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
340790286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
340890286Sobrien			(eq_attr "alternative" "0"))
340990286Sobrien	(const_string "0")
341090286Sobrien	(const_string "1")))
341190286Sobrien   (set (attr "modrm")
341290286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
341390286Sobrien	(const_string "0")
341490286Sobrien	(const_string "1")))])
341518334Speter
341618334Speter(define_insn "extendqihi2"
341790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=*a,r")
341890286Sobrien	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "*0,qm")))]
341918334Speter  ""
342018334Speter{
342190286Sobrien  switch (get_attr_prefix_0f (insn))
342290286Sobrien    {
342390286Sobrien    case 0:
342490286Sobrien      return "{cbtw|cbw}";
342590286Sobrien    default:
342690286Sobrien      return "movs{bw|x}\t{%1,%0|%0, %1}";
342790286Sobrien    }
342890286Sobrien}
342990286Sobrien  [(set_attr "type" "imovx")
343090286Sobrien   (set_attr "mode" "HI")
343190286Sobrien   (set (attr "prefix_0f")
343290286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
343390286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
343490286Sobrien			(eq_attr "alternative" "0"))
343590286Sobrien	(const_string "0")
343690286Sobrien	(const_string "1")))
343790286Sobrien   (set (attr "modrm")
343890286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
343990286Sobrien	(const_string "0")
344090286Sobrien	(const_string "1")))])
344118334Speter
344218334Speter(define_insn "extendqisi2"
344350650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
344450650Sobrien	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
344518334Speter  ""
344690286Sobrien  "movs{bl|x}\t{%1,%0|%0, %1}"
344790286Sobrien   [(set_attr "type" "imovx")
344890286Sobrien    (set_attr "mode" "SI")])
344950650Sobrien
345090286Sobrien(define_insn "*extendqisi2_zext"
345190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
345290286Sobrien	(zero_extend:DI
345390286Sobrien	  (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))))]
345490286Sobrien  "TARGET_64BIT"
345590286Sobrien  "movs{bl|x}\t{%1,%k0|%k0, %1}"
345690286Sobrien   [(set_attr "type" "imovx")
345790286Sobrien    (set_attr "mode" "SI")])
345818334Speter
345990286Sobrien;; Conversions between float and double.
346050650Sobrien
346190286Sobrien;; These are all no-ops in the model used for the 80387.  So just
346290286Sobrien;; emit moves.
346350650Sobrien
346490286Sobrien;; %%% Kill these when call knows how to work out a DFmode push earlier. 
346590286Sobrien(define_insn "*dummy_extendsfdf2"
346690286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<")
346790286Sobrien	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fY")))]
346890286Sobrien  "0"
346990286Sobrien  "#")
347050650Sobrien
347190286Sobrien(define_split
347290286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
3473117404Skan	(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
3474117404Skan  "!TARGET_64BIT"
3475169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
3476169699Skan   (set (mem:DF (reg:SI SP_REG)) (float_extend:DF (match_dup 1)))])
347750650Sobrien
347890286Sobrien(define_split
347990286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
3480117404Skan	(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
3481117404Skan  "TARGET_64BIT"
3482169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
3483169699Skan   (set (mem:DF (reg:DI SP_REG)) (float_extend:DF (match_dup 1)))])
348450650Sobrien
348590286Sobrien(define_insn "*dummy_extendsfxf2"
348690286Sobrien  [(set (match_operand:XF 0 "push_operand" "=<")
348790286Sobrien	(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "f")))]
348890286Sobrien  "0"
348990286Sobrien  "#")
349050650Sobrien
349190286Sobrien(define_split
349290286Sobrien  [(set (match_operand:XF 0 "push_operand" "")
3493117404Skan	(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
3494132727Skan  ""
3495169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
3496169699Skan   (set (mem:XF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
3497132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
349850650Sobrien
349990286Sobrien(define_split
3500132727Skan  [(set (match_operand:XF 0 "push_operand" "")
3501132727Skan	(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
3502117404Skan  "TARGET_64BIT"
3503169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
3504169699Skan   (set (mem:DF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
3505132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
350618334Speter
350790286Sobrien(define_split
350890286Sobrien  [(set (match_operand:XF 0 "push_operand" "")
3509117404Skan	(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
3510132727Skan  ""
3511169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
3512169699Skan   (set (mem:DF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
3513132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
351452296Sobrien
351552296Sobrien(define_split
3516132727Skan  [(set (match_operand:XF 0 "push_operand" "")
3517132727Skan	(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
3518117404Skan  "TARGET_64BIT"
3519169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
3520169699Skan   (set (mem:XF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
3521132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
352218334Speter
352390286Sobrien(define_expand "extendsfdf2"
352452296Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
3525117404Skan        (float_extend:DF (match_operand:SF 1 "general_operand" "")))]
3526169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
352752296Sobrien{
3528117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3529117404Skan     are LEGITIMATE_CONSTANT_P.  */
3530117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3531169699Skan    {
3532169699Skan      if ((!TARGET_SSE2 || TARGET_MIX_SSE_I387)
3533169699Skan	  && standard_80387_constant_p (operands[1]) > 0)
3534169699Skan	{
3535169699Skan	  operands[1] = simplify_const_unary_operation
3536169699Skan	    (FLOAT_EXTEND, DFmode, operands[1], SFmode);
3537169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3538169699Skan	  DONE;
3539169699Skan	}
3540169699Skan      operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
3541169699Skan    }
354290286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
354390286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
354490286Sobrien})
354518334Speter
3546169699Skan(define_insn "*extendsfdf2_mixed"
3547169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y")
3548169699Skan        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))]
3549169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387
355090286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
355152296Sobrien{
355290286Sobrien  switch (which_alternative)
355390286Sobrien    {
355490286Sobrien    case 0:
3555169699Skan      return output_387_reg_move (insn, operands);
355652296Sobrien
355790286Sobrien    case 1:
355890286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
355990286Sobrien        return "fstp%z0\t%y0";
356090286Sobrien      else
356190286Sobrien        return "fst%z0\t%y0";
3562169699Skan
356390286Sobrien    case 2:
356490286Sobrien      return "cvtss2sd\t{%1, %0|%0, %1}";
356518334Speter
356690286Sobrien    default:
3567169699Skan      gcc_unreachable ();
356890286Sobrien    }
356990286Sobrien}
3570117404Skan  [(set_attr "type" "fmov,fmov,ssecvt")
357190286Sobrien   (set_attr "mode" "SF,XF,DF")])
357218334Speter
3573169699Skan(define_insn "*extendsfdf2_sse"
3574169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y")
357590286Sobrien        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "mY")))]
3576169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
357790286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
357890286Sobrien  "cvtss2sd\t{%1, %0|%0, %1}"
3579117404Skan  [(set_attr "type" "ssecvt")
358090286Sobrien   (set_attr "mode" "DF")])
358118334Speter
3582169699Skan(define_insn "*extendsfdf2_i387"
3583169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
3584169699Skan        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
3585169699Skan  "TARGET_80387
3586169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
3587169699Skan{
3588169699Skan  switch (which_alternative)
3589169699Skan    {
3590169699Skan    case 0:
3591169699Skan      return output_387_reg_move (insn, operands);
3592169699Skan
3593169699Skan    case 1:
3594169699Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3595169699Skan        return "fstp%z0\t%y0";
3596169699Skan      else
3597169699Skan        return "fst%z0\t%y0";
3598169699Skan
3599169699Skan    default:
3600169699Skan      gcc_unreachable ();
3601169699Skan    }
3602169699Skan}
3603169699Skan  [(set_attr "type" "fmov")
3604169699Skan   (set_attr "mode" "SF,XF")])
3605169699Skan
360690286Sobrien(define_expand "extendsfxf2"
360752296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
3608117404Skan        (float_extend:XF (match_operand:SF 1 "general_operand" "")))]
3609132727Skan  "TARGET_80387"
361090286Sobrien{
3611117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3612117404Skan     are LEGITIMATE_CONSTANT_P.  */
3613117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3614169699Skan    {
3615169699Skan      if (standard_80387_constant_p (operands[1]) > 0)
3616169699Skan	{
3617169699Skan	  operands[1] = simplify_const_unary_operation
3618169699Skan	    (FLOAT_EXTEND, XFmode, operands[1], SFmode);
3619169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3620169699Skan	  DONE;
3621169699Skan	}
3622169699Skan      operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
3623169699Skan    }
362490286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
362590286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
362690286Sobrien})
362718334Speter
3628169699Skan(define_insn "*extendsfxf2_i387"
362952296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
363090286Sobrien        (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
363190286Sobrien  "TARGET_80387
363290286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
363318334Speter{
363490286Sobrien  switch (which_alternative)
363590286Sobrien    {
363690286Sobrien    case 0:
3637169699Skan      return output_387_reg_move (insn, operands);
363818334Speter
363990286Sobrien    case 1:
364090286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
364190286Sobrien	 we need one, follow the store with a load.  */
3642169699Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3643169699Skan        return "fstp%z0\t%y0";
3644169699Skan      else
364590286Sobrien        return "fstp%z0\t%y0\n\tfld%z0\t%y0";
364618334Speter
364790286Sobrien    default:
3648169699Skan      gcc_unreachable ();
364990286Sobrien    }
365090286Sobrien}
365190286Sobrien  [(set_attr "type" "fmov")
365290286Sobrien   (set_attr "mode" "SF,XF")])
365318334Speter
365490286Sobrien(define_expand "extenddfxf2"
365552296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
3656117404Skan        (float_extend:XF (match_operand:DF 1 "general_operand" "")))]
3657132727Skan  "TARGET_80387"
365890286Sobrien{
3659117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3660117404Skan     are LEGITIMATE_CONSTANT_P.  */
3661117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3662169699Skan    {
3663169699Skan      if (standard_80387_constant_p (operands[1]) > 0)
3664169699Skan	{
3665169699Skan	  operands[1] = simplify_const_unary_operation
3666169699Skan	    (FLOAT_EXTEND, XFmode, operands[1], DFmode);
3667169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3668169699Skan	  DONE;
3669169699Skan	}
3670169699Skan      operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
3671169699Skan    }
367290286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
367390286Sobrien    operands[1] = force_reg (DFmode, operands[1]);
367490286Sobrien})
367518334Speter
3676169699Skan(define_insn "*extenddfxf2_i387"
367752296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
367890286Sobrien        (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
367990286Sobrien  "TARGET_80387
368090286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
368190286Sobrien{
368290286Sobrien  switch (which_alternative)
368390286Sobrien    {
368490286Sobrien    case 0:
3685169699Skan      return output_387_reg_move (insn, operands);
368690286Sobrien
368790286Sobrien    case 1:
368890286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
368990286Sobrien	 we need one, follow the store with a load.  */
369090286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
369190286Sobrien        return "fstp%z0\t%y0\n\tfld%z0\t%y0";
369290286Sobrien      else
369390286Sobrien        return "fstp%z0\t%y0";
369490286Sobrien
369590286Sobrien    default:
3696169699Skan      gcc_unreachable ();
369790286Sobrien    }
369890286Sobrien}
369990286Sobrien  [(set_attr "type" "fmov")
370090286Sobrien   (set_attr "mode" "DF,XF")])
370190286Sobrien
370290286Sobrien;; %%% This seems bad bad news.
370390286Sobrien;; This cannot output into an f-reg because there is no way to be sure
370490286Sobrien;; of truncating in that case.  Otherwise this is just like a simple move
370590286Sobrien;; insn.  So we pretend we can output to a reg in order to get better
370690286Sobrien;; register preferencing, but we really use a stack slot.
370790286Sobrien
3708169699Skan;; Conversion from DFmode to SFmode.
3709169699Skan
371018334Speter(define_expand "truncdfsf2"
3711169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
371290286Sobrien	(float_truncate:SF
3713169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "")))]
3714169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
371518334Speter{
3716169699Skan  if (MEM_P (operands[0]) && MEM_P (operands[1]))
3717169699Skan    operands[1] = force_reg (DFmode, operands[1]);
3718169699Skan
3719169699Skan  if (TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_MIX_SSE_I387)
3720169699Skan    ;
3721169699Skan  else if (flag_unsafe_math_optimizations)
3722169699Skan    ;
3723169699Skan  else
372490286Sobrien    {
3725171835Skan      rtx temp = assign_386_stack_local (SFmode, SLOT_VIRTUAL);
3726169699Skan      emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
3727169699Skan      DONE;
372890286Sobrien    }
3729169699Skan})
373018334Speter
3731169699Skan(define_expand "truncdfsf2_with_temp"
3732169699Skan  [(parallel [(set (match_operand:SF 0 "" "")
3733169699Skan		   (float_truncate:SF (match_operand:DF 1 "" "")))
3734169699Skan	      (clobber (match_operand:SF 2 "" ""))])]
3735169699Skan  "")
3736169699Skan
3737169699Skan(define_insn "*truncdfsf_fast_mixed"
3738169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,f,Y")
3739169699Skan        (float_truncate:SF
3740169699Skan          (match_operand:DF 1 "nonimmediate_operand" "f ,f,Ym")))]
3741169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387 && flag_unsafe_math_optimizations"
374218334Speter{
374390286Sobrien  switch (which_alternative)
374490286Sobrien    {
374590286Sobrien    case 0:
374690286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
374790286Sobrien	return "fstp%z0\t%y0";
374890286Sobrien      else
374990286Sobrien	return "fst%z0\t%y0";
3750169699Skan    case 1:
3751169699Skan      return output_387_reg_move (insn, operands);
3752169699Skan    case 2:
3753169699Skan      return "cvtsd2ss\t{%1, %0|%0, %1}";
375490286Sobrien    default:
3755169699Skan      gcc_unreachable ();
375690286Sobrien    }
375790286Sobrien}
3758169699Skan  [(set_attr "type" "fmov,fmov,ssecvt")
3759169699Skan   (set_attr "mode" "SF")])
376018334Speter
3761169699Skan;; Yes, this one doesn't depend on flag_unsafe_math_optimizations,
3762169699Skan;; because nothing we do here is unsafe.
3763169699Skan(define_insn "*truncdfsf_fast_sse"
3764169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=Y")
3765169699Skan        (float_truncate:SF
3766169699Skan          (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
3767169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
3768169699Skan  "cvtsd2ss\t{%1, %0|%0, %1}"
3769169699Skan  [(set_attr "type" "ssecvt")
3770169699Skan   (set_attr "mode" "SF")])
3771169699Skan
3772169699Skan(define_insn "*truncdfsf_fast_i387"
3773169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=fm")
3774169699Skan        (float_truncate:SF
3775169699Skan          (match_operand:DF 1 "nonimmediate_operand" "f")))]
3776169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3777169699Skan  "* return output_387_reg_move (insn, operands);"
3778169699Skan  [(set_attr "type" "fmov")
3779169699Skan   (set_attr "mode" "SF")])
3780169699Skan
3781169699Skan(define_insn "*truncdfsf_mixed"
3782169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,?fx*r,Y")
3783132727Skan	(float_truncate:SF
3784169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "f ,f    ,Ym")))
3785169699Skan   (clobber (match_operand:SF 2 "memory_operand"     "=X,m    ,X"))]
3786169699Skan  "TARGET_MIX_SSE_I387"
3787132727Skan{
3788132727Skan  switch (which_alternative)
3789132727Skan    {
3790132727Skan    case 0:
3791132727Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3792132727Skan	return "fstp%z0\t%y0";
3793132727Skan      else
3794132727Skan	return "fst%z0\t%y0";
3795169699Skan    case 1:
3796132727Skan      return "#";
3797169699Skan    case 2:
3798169699Skan      return "cvtsd2ss\t{%1, %0|%0, %1}";
3799132727Skan    default:
3800169699Skan      gcc_unreachable ();
3801132727Skan    }
3802132727Skan}
3803169699Skan  [(set_attr "type" "fmov,multi,ssecvt")
3804169699Skan   (set_attr "unit" "*,i387,*")
3805169699Skan   (set_attr "mode" "SF")])
3806132727Skan
3807169699Skan(define_insn "*truncdfsf_i387"
3808169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r")
380990286Sobrien	(float_truncate:SF
3810169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "f,f")))
3811169699Skan   (clobber (match_operand:SF 2 "memory_operand" "=X,m"))]
3812169699Skan  "TARGET_80387"
3813132727Skan{
3814132727Skan  switch (which_alternative)
3815132727Skan    {
3816132727Skan    case 0:
3817132727Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3818132727Skan	return "fstp%z0\t%y0";
3819132727Skan      else
3820132727Skan	return "fst%z0\t%y0";
3821169699Skan    case 1:
3822132727Skan      return "#";
382390286Sobrien    default:
3824169699Skan      gcc_unreachable ();
382590286Sobrien    }
382690286Sobrien}
3827169699Skan  [(set_attr "type" "fmov,multi")
3828169699Skan   (set_attr "unit" "*,i387")
3829169699Skan   (set_attr "mode" "SF")])
383052296Sobrien
3831169699Skan(define_insn "*truncdfsf2_i387_1"
383290286Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
383390286Sobrien	(float_truncate:SF
3834169699Skan	  (match_operand:DF 1 "register_operand" "f")))]
3835169699Skan  "TARGET_80387
3836169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)
3837169699Skan   && !TARGET_MIX_SSE_I387"
383890286Sobrien{
383990286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
384090286Sobrien    return "fstp%z0\t%y0";
384118334Speter  else
384290286Sobrien    return "fst%z0\t%y0";
384390286Sobrien}
384490286Sobrien  [(set_attr "type" "fmov")
384590286Sobrien   (set_attr "mode" "SF")])
384618334Speter
384752296Sobrien(define_split
3848132727Skan  [(set (match_operand:SF 0 "register_operand" "")
384990286Sobrien	(float_truncate:SF
3850169699Skan	 (match_operand:DF 1 "fp_register_operand" "")))
385190286Sobrien   (clobber (match_operand 2 "" ""))]
3852169699Skan  "reload_completed"
3853169699Skan  [(set (match_dup 2) (match_dup 1))
3854169699Skan   (set (match_dup 0) (match_dup 2))]
3855132727Skan{
3856169699Skan  operands[1] = gen_rtx_REG (SFmode, true_regnum (operands[1]));
3857132727Skan})
385890286Sobrien
3859169699Skan;; Conversion from XFmode to SFmode.
3860132727Skan
386190286Sobrien(define_expand "truncxfsf2"
386290286Sobrien  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
386390286Sobrien		   (float_truncate:SF
386490286Sobrien		    (match_operand:XF 1 "register_operand" "")))
386590286Sobrien	      (clobber (match_dup 2))])]
3866132727Skan  "TARGET_80387"
3867169699Skan{
3868169699Skan  if (flag_unsafe_math_optimizations)
3869169699Skan    {
3870169699Skan      rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SFmode);
3871169699Skan      emit_insn (gen_truncxfsf2_i387_noop (reg, operands[1]));
3872169699Skan      if (reg != operands[0])
3873169699Skan	emit_move_insn (operands[0], reg);
3874169699Skan      DONE;
3875169699Skan    }
3876169699Skan  else
3877171835Skan    operands[2] = assign_386_stack_local (SFmode, SLOT_VIRTUAL);
3878169699Skan})
387952296Sobrien
3880169699Skan(define_insn "*truncxfsf2_mixed"
3881169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x")
388290286Sobrien	(float_truncate:SF
388390286Sobrien	 (match_operand:XF 1 "register_operand" "f,f,f,f")))
388490286Sobrien   (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
3885169699Skan  "TARGET_MIX_SSE_I387"
388690286Sobrien{
3887169699Skan  gcc_assert (!which_alternative);
3888169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3889169699Skan    return "fstp%z0\t%y0";
3890169699Skan  else
3891169699Skan    return "fst%z0\t%y0";
389290286Sobrien}
389390286Sobrien  [(set_attr "type" "fmov,multi,multi,multi")
3894169699Skan   (set_attr "unit" "*,i387,i387,i387")
389590286Sobrien   (set_attr "mode" "SF")])
389690286Sobrien
3897169699Skan(define_insn "truncxfsf2_i387_noop"
3898169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
3899169699Skan	(float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
3900169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3901169699Skan{
3902169699Skan  return output_387_reg_move (insn, operands);
3903169699Skan}
3904169699Skan  [(set_attr "type" "fmov")
3905169699Skan   (set_attr "mode" "SF")])
3906169699Skan
3907169699Skan(define_insn "*truncxfsf2_i387"
3908169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r")
3909169699Skan	(float_truncate:SF
3910169699Skan	 (match_operand:XF 1 "register_operand" "f,f,f")))
3911169699Skan   (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
3912169699Skan  "TARGET_80387"
3913169699Skan{
3914169699Skan  gcc_assert (!which_alternative);
3915169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3916169699Skan    return "fstp%z0\t%y0";
3917169699Skan   else
3918169699Skan     return "fst%z0\t%y0";
3919169699Skan}
3920169699Skan  [(set_attr "type" "fmov,multi,multi")
3921169699Skan   (set_attr "unit" "*,i387,i387")
3922169699Skan   (set_attr "mode" "SF")])
3923169699Skan
3924169699Skan(define_insn "*truncxfsf2_i387_1"
392552296Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
392690286Sobrien	(float_truncate:SF
392790286Sobrien	 (match_operand:XF 1 "register_operand" "f")))]
3928132727Skan  "TARGET_80387"
392918334Speter{
393090286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
393190286Sobrien    return "fstp%z0\t%y0";
393218334Speter  else
393390286Sobrien    return "fst%z0\t%y0";
393490286Sobrien}
393590286Sobrien  [(set_attr "type" "fmov")
393690286Sobrien   (set_attr "mode" "SF")])
393752296Sobrien
393890286Sobrien(define_split
3939169699Skan  [(set (match_operand:SF 0 "register_operand" "")
394090286Sobrien	(float_truncate:SF
394190286Sobrien	 (match_operand:XF 1 "register_operand" "")))
394290286Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
3943169699Skan  "TARGET_80387 && reload_completed"
3944169699Skan  [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
3945169699Skan   (set (match_dup 0) (match_dup 2))]
394690286Sobrien  "")
394790286Sobrien
394890286Sobrien(define_split
3949169699Skan  [(set (match_operand:SF 0 "memory_operand" "")
395090286Sobrien	(float_truncate:SF
395190286Sobrien	 (match_operand:XF 1 "register_operand" "")))
395290286Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
3953169699Skan  "TARGET_80387"
3954169699Skan  [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
395590286Sobrien  "")
395690286Sobrien
3957169699Skan;; Conversion from XFmode to DFmode.
3958169699Skan
395952296Sobrien(define_expand "truncxfdf2"
396052296Sobrien  [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
396152296Sobrien		   (float_truncate:DF
396252296Sobrien		    (match_operand:XF 1 "register_operand" "")))
396352296Sobrien	      (clobber (match_dup 2))])]
3964132727Skan  "TARGET_80387"
3965169699Skan{
3966169699Skan  if (flag_unsafe_math_optimizations)
3967169699Skan    {
3968169699Skan      rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DFmode);
3969169699Skan      emit_insn (gen_truncxfdf2_i387_noop (reg, operands[1]));
3970169699Skan      if (reg != operands[0])
3971169699Skan	emit_move_insn (operands[0], reg);
3972169699Skan      DONE;
3973169699Skan    }
3974169699Skan  else
3975171835Skan    operands[2] = assign_386_stack_local (DFmode, SLOT_VIRTUAL);
3976169699Skan})
397718334Speter
3978169699Skan(define_insn "*truncxfdf2_mixed"
3979169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y")
398052296Sobrien	(float_truncate:DF
398190286Sobrien	 (match_operand:XF 1 "register_operand" "f,f,f,f")))
398290286Sobrien   (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
3983169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387"
398418334Speter{
3985169699Skan  gcc_assert (!which_alternative);
3986169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3987169699Skan    return "fstp%z0\t%y0";
3988169699Skan  else
3989169699Skan    return "fst%z0\t%y0";
399090286Sobrien}
399190286Sobrien  [(set_attr "type" "fmov,multi,multi,multi")
3992169699Skan   (set_attr "unit" "*,i387,i387,i387")
399390286Sobrien   (set_attr "mode" "DF")])
399452296Sobrien
3995169699Skan(define_insn "truncxfdf2_i387_noop"
3996169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
3997169699Skan	(float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
3998169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3999169699Skan{
4000169699Skan  return output_387_reg_move (insn, operands);
4001169699Skan}
4002169699Skan  [(set_attr "type" "fmov")
4003169699Skan   (set_attr "mode" "DF")])
4004169699Skan
4005169699Skan(define_insn "*truncxfdf2_i387"
4006169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r")
4007169699Skan	(float_truncate:DF
4008169699Skan	 (match_operand:XF 1 "register_operand" "f,f,f")))
4009169699Skan   (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
4010169699Skan  "TARGET_80387"
4011169699Skan{
4012169699Skan  gcc_assert (!which_alternative);
4013169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
4014169699Skan    return "fstp%z0\t%y0";
4015169699Skan  else
4016169699Skan    return "fst%z0\t%y0";
4017169699Skan}
4018169699Skan  [(set_attr "type" "fmov,multi,multi")
4019169699Skan   (set_attr "unit" "*,i387,i387")
4020169699Skan   (set_attr "mode" "DF")])
4021169699Skan
4022169699Skan(define_insn "*truncxfdf2_i387_1"
402390286Sobrien  [(set (match_operand:DF 0 "memory_operand" "=m")
402490286Sobrien	(float_truncate:DF
402590286Sobrien	  (match_operand:XF 1 "register_operand" "f")))]
4026132727Skan  "TARGET_80387"
402790286Sobrien{
402890286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
402990286Sobrien    return "fstp%z0\t%y0";
403090286Sobrien  else
403190286Sobrien    return "fst%z0\t%y0";
403290286Sobrien}
403390286Sobrien  [(set_attr "type" "fmov")
403490286Sobrien   (set_attr "mode" "DF")])
403552296Sobrien
403652296Sobrien(define_split
4037169699Skan  [(set (match_operand:DF 0 "register_operand" "")
403890286Sobrien	(float_truncate:DF
403990286Sobrien	 (match_operand:XF 1 "register_operand" "")))
404052296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
4041169699Skan  "TARGET_80387 && reload_completed"
4042169699Skan  [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
4043169699Skan   (set (match_dup 0) (match_dup 2))]
404452296Sobrien  "")
404552296Sobrien
404652296Sobrien(define_split
4047169699Skan  [(set (match_operand:DF 0 "memory_operand" "")
404890286Sobrien	(float_truncate:DF
404990286Sobrien	 (match_operand:XF 1 "register_operand" "")))
405052296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
4051169699Skan  "TARGET_80387"
4052169699Skan  [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
405352296Sobrien  "")
405490286Sobrien
405590286Sobrien;; Signed conversion to DImode.
405690286Sobrien
405790286Sobrien(define_expand "fix_truncxfdi2"
4058169699Skan  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4059169699Skan                   (fix:DI (match_operand:XF 1 "register_operand" "")))
4060169699Skan	      (clobber (reg:CC FLAGS_REG))])]
406118334Speter  "TARGET_80387"
406218334Speter{
4063169699Skan  if (TARGET_FISTTP)
406490286Sobrien   {
4065169699Skan     emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
406690286Sobrien     DONE;
406790286Sobrien   }
406890286Sobrien})
406918334Speter
4070169699Skan(define_expand "fix_trunc<mode>di2"
4071169699Skan  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4072169699Skan                   (fix:DI (match_operand:SSEMODEF 1 "register_operand" "")))
4073169699Skan              (clobber (reg:CC FLAGS_REG))])]
4074169699Skan  "TARGET_80387 || (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))"
407590286Sobrien{
4076169699Skan  if (TARGET_FISTTP
4077169699Skan      && !(TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
407890286Sobrien   {
4079169699Skan     emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
4080169699Skan     DONE;
4081169699Skan   }
4082169699Skan  if (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))
4083169699Skan   {
408490286Sobrien     rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
4085169699Skan     emit_insn (gen_fix_trunc<mode>di_sse (out, operands[1]));
408690286Sobrien     if (out != operands[0])
408790286Sobrien	emit_move_insn (operands[0], out);
408890286Sobrien     DONE;
408990286Sobrien   }
409090286Sobrien})
409152296Sobrien
409290286Sobrien;; Signed conversion to SImode.
409390286Sobrien
409452296Sobrien(define_expand "fix_truncxfsi2"
4095169699Skan  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
4096169699Skan                   (fix:SI (match_operand:XF 1 "register_operand" "")))
4097169699Skan	      (clobber (reg:CC FLAGS_REG))])]
409818334Speter  "TARGET_80387"
409918334Speter{
4100169699Skan  if (TARGET_FISTTP)
410190286Sobrien   {
4102169699Skan     emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
410390286Sobrien     DONE;
410490286Sobrien   }
410590286Sobrien})
410618334Speter
4107169699Skan(define_expand "fix_trunc<mode>si2"
4108169699Skan  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
4109169699Skan	           (fix:SI (match_operand:SSEMODEF 1 "register_operand" "")))
4110169699Skan	      (clobber (reg:CC FLAGS_REG))])]
4111169699Skan  "TARGET_80387 || SSE_FLOAT_MODE_P (<MODE>mode)"
411290286Sobrien{
4113169699Skan  if (TARGET_FISTTP
4114169699Skan      && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
411590286Sobrien   {
4116169699Skan     emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
4117169699Skan     DONE;
4118169699Skan   }
4119169699Skan  if (SSE_FLOAT_MODE_P (<MODE>mode))
4120169699Skan   {
412190286Sobrien     rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
4122169699Skan     emit_insn (gen_fix_trunc<mode>si_sse (out, operands[1]));
412390286Sobrien     if (out != operands[0])
412490286Sobrien	emit_move_insn (operands[0], out);
412590286Sobrien     DONE;
412690286Sobrien   }
412790286Sobrien})
412852296Sobrien
4129169699Skan;; Signed conversion to HImode.
4130169699Skan
4131169699Skan(define_expand "fix_trunc<mode>hi2"
4132169699Skan  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
4133169699Skan	           (fix:HI (match_operand:X87MODEF 1 "register_operand" "")))
4134169699Skan              (clobber (reg:CC FLAGS_REG))])]
4135169699Skan  "TARGET_80387
4136169699Skan   && !(SSE_FLOAT_MODE_P (<MODE>mode) && (!TARGET_FISTTP || TARGET_SSE_MATH))"
413718334Speter{
4138169699Skan  if (TARGET_FISTTP)
4139169699Skan   {
4140169699Skan     emit_insn (gen_fix_trunchi_fisttp_i387_1 (operands[0], operands[1]));
4141169699Skan     DONE;
4142169699Skan   }
4143169699Skan})
414418334Speter
4145169699Skan;; When SSE is available, it is always faster to use it!
4146169699Skan(define_insn "fix_truncsfdi_sse"
4147169699Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
4148169699Skan	(fix:DI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
4149169699Skan  "TARGET_64BIT && TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
4150169699Skan  "cvttss2si{q}\t{%1, %0|%0, %1}"
4151169699Skan  [(set_attr "type" "sseicvt")
4152169699Skan   (set_attr "mode" "SF")
4153169699Skan   (set_attr "athlon_decode" "double,vector")])
415490286Sobrien
4155169699Skan(define_insn "fix_truncdfdi_sse"
4156169699Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
4157169699Skan	(fix:DI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
4158169699Skan  "TARGET_64BIT && TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
4159169699Skan  "cvttsd2si{q}\t{%1, %0|%0, %1}"
4160169699Skan  [(set_attr "type" "sseicvt")
4161169699Skan   (set_attr "mode" "DF")
4162169699Skan   (set_attr "athlon_decode" "double,vector")])
416318334Speter
416490286Sobrien(define_insn "fix_truncsfsi_sse"
4165132727Skan  [(set (match_operand:SI 0 "register_operand" "=r,r")
4166132727Skan	(fix:SI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
4167169699Skan  "TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
416890286Sobrien  "cvttss2si\t{%1, %0|%0, %1}"
4169132727Skan  [(set_attr "type" "sseicvt")
4170132727Skan   (set_attr "mode" "DF")
4171132727Skan   (set_attr "athlon_decode" "double,vector")])
417252296Sobrien
417390286Sobrien(define_insn "fix_truncdfsi_sse"
4174132727Skan  [(set (match_operand:SI 0 "register_operand" "=r,r")
4175132727Skan	(fix:SI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
4176169699Skan  "TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
417790286Sobrien  "cvttsd2si\t{%1, %0|%0, %1}"
4178132727Skan  [(set_attr "type" "sseicvt")
4179132727Skan   (set_attr "mode" "DF")
4180132727Skan   (set_attr "athlon_decode" "double,vector")])
418152296Sobrien
4182169699Skan;; Avoid vector decoded forms of the instruction.
4183132727Skan(define_peephole2
4184132727Skan  [(match_scratch:DF 2 "Y")
4185169699Skan   (set (match_operand:SSEMODEI24 0 "register_operand" "")
4186169699Skan	(fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))]
4187169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
4188132727Skan  [(set (match_dup 2) (match_dup 1))
4189169699Skan   (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
4190132727Skan  "")
4191132727Skan
4192169699Skan(define_peephole2
4193169699Skan  [(match_scratch:SF 2 "x")
4194169699Skan   (set (match_operand:SSEMODEI24 0 "register_operand" "")
4195169699Skan	(fix:SSEMODEI24 (match_operand:SF 1 "memory_operand" "")))]
4196169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
4197169699Skan  [(set (match_dup 2) (match_dup 1))
4198169699Skan   (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
419990286Sobrien  "")
420018334Speter
4201169699Skan(define_insn_and_split "fix_trunc<mode>_fisttp_i387_1"
4202169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4203169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))]
4204169699Skan  "TARGET_FISTTP
4205169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4206169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4207169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4208169699Skan	&& TARGET_SSE_MATH)
4209169699Skan   && !(reload_completed || reload_in_progress)"
4210169699Skan  "#"
4211169699Skan  "&& 1"
4212169699Skan  [(const_int 0)]
4213169699Skan{
4214169699Skan  if (memory_operand (operands[0], VOIDmode))
4215169699Skan    emit_insn (gen_fix_trunc<mode>_i387_fisttp (operands[0], operands[1]));
4216169699Skan  else
4217169699Skan    {
4218169699Skan      operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
4219169699Skan      emit_insn (gen_fix_trunc<mode>_i387_fisttp_with_temp (operands[0],
4220169699Skan							    operands[1],
4221169699Skan							    operands[2]));
4222169699Skan    }
4223169699Skan  DONE;
4224169699Skan}
4225169699Skan  [(set_attr "type" "fisttp")
4226169699Skan   (set_attr "mode" "<MODE>")])
422752296Sobrien
4228169699Skan(define_insn "fix_trunc<mode>_i387_fisttp"
4229169699Skan  [(set (match_operand:X87MODEI 0 "memory_operand" "=m")
4230169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f")))
4231169699Skan   (clobber (match_scratch:XF 2 "=&1f"))]
4232169699Skan  "TARGET_FISTTP
4233169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4234169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4235169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4236169699Skan	&& TARGET_SSE_MATH)"
4237169699Skan  "* return output_fix_trunc (insn, operands, 1);"
4238169699Skan  [(set_attr "type" "fisttp")
4239169699Skan   (set_attr "mode" "<MODE>")])
424090286Sobrien
4241169699Skan(define_insn "fix_trunc<mode>_i387_fisttp_with_temp"
4242169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4243169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
4244169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" "=m,m"))
4245169699Skan   (clobber (match_scratch:XF 3 "=&1f,&1f"))]
4246169699Skan  "TARGET_FISTTP
4247169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4248169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4249169699Skan	&& (TARGET_64BIT || <MODE>mode != DImode))
4250169699Skan	&& TARGET_SSE_MATH)"
4251169699Skan  "#"
4252169699Skan  [(set_attr "type" "fisttp")
4253169699Skan   (set_attr "mode" "<MODE>")])
425418334Speter
4255169699Skan(define_split
4256169699Skan  [(set (match_operand:X87MODEI 0 "register_operand" "")
4257169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "")))
4258169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
4259169699Skan   (clobber (match_scratch 3 ""))]
4260169699Skan  "reload_completed"
4261169699Skan  [(parallel [(set (match_dup 2) (fix:X87MODEI (match_dup 1)))
4262169699Skan	      (clobber (match_dup 3))])
4263169699Skan   (set (match_dup 0) (match_dup 2))]
426490286Sobrien  "")
426518334Speter
4266169699Skan(define_split
4267169699Skan  [(set (match_operand:X87MODEI 0 "memory_operand" "")
4268169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "")))
4269169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
4270169699Skan   (clobber (match_scratch 3 ""))]
4271169699Skan  "reload_completed"
4272169699Skan  [(parallel [(set (match_dup 0) (fix:X87MODEI (match_dup 1)))
4273169699Skan	      (clobber (match_dup 3))])]
427490286Sobrien  "")
427552296Sobrien
427690286Sobrien;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
4277169699Skan;; of the machinery. Please note the clobber of FLAGS_REG. In i387 control
4278169699Skan;; word calculation (inserted by LCM in mode switching pass) a FLAGS_REG
4279169699Skan;; clobbering insns can be used. Look at emit_i387_cw_initialization ()
4280169699Skan;; function in i386.c.
4281169699Skan(define_insn_and_split "*fix_trunc<mode>_i387_1"
4282169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4283169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
4284169699Skan   (clobber (reg:CC FLAGS_REG))]
4285169699Skan  "TARGET_80387 && !TARGET_FISTTP
4286169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4287169699Skan   && !(SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4288169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4289169699Skan   && !(reload_completed || reload_in_progress)"
429090286Sobrien  "#"
4291169699Skan  "&& 1"
429290286Sobrien  [(const_int 0)]
429390286Sobrien{
4294169699Skan  ix86_optimize_mode_switching[I387_TRUNC] = 1;
4295169699Skan
4296169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
4297169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
429890286Sobrien  if (memory_operand (operands[0], VOIDmode))
4299169699Skan    emit_insn (gen_fix_trunc<mode>_i387 (operands[0], operands[1],
4300169699Skan					 operands[2], operands[3]));
430190286Sobrien  else
430290286Sobrien    {
4303169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
4304169699Skan      emit_insn (gen_fix_trunc<mode>_i387_with_temp (operands[0], operands[1],
4305169699Skan						     operands[2], operands[3],
4306169699Skan						     operands[4]));
430790286Sobrien    }
430890286Sobrien  DONE;
430990286Sobrien}
4310132727Skan  [(set_attr "type" "fistp")
4311169699Skan   (set_attr "i387_cw" "trunc")
4312169699Skan   (set_attr "mode" "<MODE>")])
431390286Sobrien
4314169699Skan(define_insn "fix_truncdi_i387"
4315169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
4316169699Skan	(fix:DI (match_operand 1 "register_operand" "f")))
4317169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
4318169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
4319169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
4320169699Skan  "TARGET_80387 && !TARGET_FISTTP
4321169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4322169699Skan   && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
4323169699Skan  "* return output_fix_trunc (insn, operands, 0);"
4324169699Skan  [(set_attr "type" "fistp")
4325169699Skan   (set_attr "i387_cw" "trunc")
4326169699Skan   (set_attr "mode" "DI")])
4327169699Skan
4328169699Skan(define_insn "fix_truncdi_i387_with_temp"
4329169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
4330169699Skan	(fix:DI (match_operand 1 "register_operand" "f,f")))
433190286Sobrien   (use (match_operand:HI 2 "memory_operand" "m,m"))
433290286Sobrien   (use (match_operand:HI 3 "memory_operand" "m,m"))
4333169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
4334169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
4335169699Skan  "TARGET_80387 && !TARGET_FISTTP
4336169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4337169699Skan   && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
433890286Sobrien  "#"
4339132727Skan  [(set_attr "type" "fistp")
4340169699Skan   (set_attr "i387_cw" "trunc")
4341169699Skan   (set_attr "mode" "DI")])
434290286Sobrien
4343169699Skan(define_split 
4344169699Skan  [(set (match_operand:DI 0 "register_operand" "")
4345169699Skan	(fix:DI (match_operand 1 "register_operand" "")))
4346169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
4347169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
4348169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
4349169699Skan   (clobber (match_scratch 5 ""))]
4350169699Skan  "reload_completed"
4351169699Skan  [(parallel [(set (match_dup 4) (fix:DI (match_dup 1)))
4352169699Skan	      (use (match_dup 2))
4353169699Skan	      (use (match_dup 3))
4354169699Skan	      (clobber (match_dup 5))])
4355169699Skan   (set (match_dup 0) (match_dup 4))]
4356169699Skan  "")
4357169699Skan
4358169699Skan(define_split 
4359169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
4360169699Skan	(fix:DI (match_operand 1 "register_operand" "")))
4361169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
4362169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
4363169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
4364169699Skan   (clobber (match_scratch 5 ""))]
4365169699Skan  "reload_completed"
4366169699Skan  [(parallel [(set (match_dup 0) (fix:DI (match_dup 1)))
4367169699Skan	      (use (match_dup 2))
4368169699Skan	      (use (match_dup 3))
4369169699Skan	      (clobber (match_dup 5))])]
4370169699Skan  "")
4371169699Skan
4372169699Skan(define_insn "fix_trunc<mode>_i387"
4373169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
4374169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "f")))
437590286Sobrien   (use (match_operand:HI 2 "memory_operand" "m"))
437690286Sobrien   (use (match_operand:HI 3 "memory_operand" "m"))]
4377169699Skan  "TARGET_80387 && !TARGET_FISTTP
4378169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
437990286Sobrien   && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
4380169699Skan  "* return output_fix_trunc (insn, operands, 0);"
4381132727Skan  [(set_attr "type" "fistp")
4382169699Skan   (set_attr "i387_cw" "trunc")
4383169699Skan   (set_attr "mode" "<MODE>")])
438490286Sobrien
4385169699Skan(define_insn "fix_trunc<mode>_i387_with_temp"
4386169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
4387169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "f,f")))
4388169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
4389169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
4390169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
4391169699Skan  "TARGET_80387 && !TARGET_FISTTP
4392169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4393169699Skan   && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
4394169699Skan  "#"
4395169699Skan  [(set_attr "type" "fistp")
4396169699Skan   (set_attr "i387_cw" "trunc")
4397169699Skan   (set_attr "mode" "<MODE>")])
4398169699Skan
439990286Sobrien(define_split 
4400169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
4401169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
440290286Sobrien   (use (match_operand:HI 2 "memory_operand" ""))
440390286Sobrien   (use (match_operand:HI 3 "memory_operand" ""))
4404169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
440590286Sobrien  "reload_completed"
4406169699Skan  [(parallel [(set (match_dup 4) (fix:X87MODEI12 (match_dup 1)))
440790286Sobrien	      (use (match_dup 2))
4408169699Skan	      (use (match_dup 3))])
4409169699Skan   (set (match_dup 0) (match_dup 4))]
441018334Speter  "")
441118334Speter
441290286Sobrien(define_split 
4413169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
4414169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
441590286Sobrien   (use (match_operand:HI 2 "memory_operand" ""))
441690286Sobrien   (use (match_operand:HI 3 "memory_operand" ""))
4417169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
441890286Sobrien  "reload_completed"
4419169699Skan  [(parallel [(set (match_dup 0) (fix:X87MODEI12 (match_dup 1)))
442090286Sobrien	      (use (match_dup 2))
4421169699Skan	      (use (match_dup 3))])]
442252296Sobrien  "")
442352296Sobrien
442490286Sobrien(define_insn "x86_fnstcw_1"
442590286Sobrien  [(set (match_operand:HI 0 "memory_operand" "=m")
4426169699Skan	(unspec:HI [(reg:HI FPSR_REG)] UNSPEC_FSTCW))]
442752296Sobrien  "TARGET_80387"
442890286Sobrien  "fnstcw\t%0"
442990286Sobrien  [(set_attr "length" "2")
443090286Sobrien   (set_attr "mode" "HI")
4431169699Skan   (set_attr "unit" "i387")])
443252296Sobrien
443390286Sobrien(define_insn "x86_fldcw_1"
4434169699Skan  [(set (reg:HI FPSR_REG)
4435117404Skan	(unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))]
443652296Sobrien  "TARGET_80387"
443790286Sobrien  "fldcw\t%0"
443890286Sobrien  [(set_attr "length" "2")
443990286Sobrien   (set_attr "mode" "HI")
4440117404Skan   (set_attr "unit" "i387")
4441169699Skan   (set_attr "athlon_decode" "vector")])
444290286Sobrien
444390286Sobrien;; Conversion between fixed point and floating point.
444452296Sobrien
444590286Sobrien;; Even though we only accept memory inputs, the backend _really_
444690286Sobrien;; wants to be able to do this between registers.
444790286Sobrien
4448132727Skan(define_expand "floathisf2"
4449132727Skan  [(set (match_operand:SF 0 "register_operand" "")
4450132727Skan	(float:SF (match_operand:HI 1 "nonimmediate_operand" "")))]
4451169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
4452132727Skan{
4453169699Skan  if (TARGET_SSE_MATH)
4454132727Skan    {
4455132727Skan      emit_insn (gen_floatsisf2 (operands[0],
4456132727Skan				 convert_to_mode (SImode, operands[1], 0)));
4457132727Skan      DONE;
4458132727Skan    }
4459132727Skan})
4460132727Skan
4461169699Skan(define_insn "*floathisf2_i387"
446252296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
4463169699Skan	(float:SF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
4464169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
446590286Sobrien  "@
446690286Sobrien   fild%z1\t%1
446790286Sobrien   #"
446890286Sobrien  [(set_attr "type" "fmov,multi")
446990286Sobrien   (set_attr "mode" "SF")
4470169699Skan   (set_attr "unit" "*,i387")
447190286Sobrien   (set_attr "fp_int_src" "true")])
447252296Sobrien
447390286Sobrien(define_expand "floatsisf2"
447418334Speter  [(set (match_operand:SF 0 "register_operand" "")
447590286Sobrien	(float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
4476169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
447718334Speter  "")
447818334Speter
4479169699Skan(define_insn "*floatsisf2_mixed"
4480169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
4481132727Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
4482169699Skan  "TARGET_MIX_SSE_I387"
448390286Sobrien  "@
448490286Sobrien   fild%z1\t%1
448590286Sobrien   #
4486132727Skan   cvtsi2ss\t{%1, %0|%0, %1}
448790286Sobrien   cvtsi2ss\t{%1, %0|%0, %1}"
4488132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
448990286Sobrien   (set_attr "mode" "SF")
4490169699Skan   (set_attr "unit" "*,i387,*,*")
4491132727Skan   (set_attr "athlon_decode" "*,*,vector,double")
449290286Sobrien   (set_attr "fp_int_src" "true")])
449390286Sobrien
449490286Sobrien(define_insn "*floatsisf2_sse"
4495132727Skan  [(set (match_operand:SF 0 "register_operand" "=x,x")
4496132727Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
4497169699Skan  "TARGET_SSE_MATH"
449890286Sobrien  "cvtsi2ss\t{%1, %0|%0, %1}"
4499132727Skan  [(set_attr "type" "sseicvt")
450090286Sobrien   (set_attr "mode" "SF")
4501132727Skan   (set_attr "athlon_decode" "vector,double")
450290286Sobrien   (set_attr "fp_int_src" "true")])
450390286Sobrien
4504169699Skan(define_insn "*floatsisf2_i387"
4505169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
4506169699Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
4507169699Skan  "TARGET_80387"
450890286Sobrien  "@
450990286Sobrien   fild%z1\t%1
451090286Sobrien   #"
451190286Sobrien  [(set_attr "type" "fmov,multi")
451290286Sobrien   (set_attr "mode" "SF")
4513169699Skan   (set_attr "unit" "*,i387")
451490286Sobrien   (set_attr "fp_int_src" "true")])
451552296Sobrien
4516169699Skan(define_expand "floatdisf2"
4517169699Skan  [(set (match_operand:SF 0 "register_operand" "")
4518169699Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
4519169699Skan  "TARGET_80387 || (TARGET_64BIT && TARGET_SSE_MATH)"
4520169699Skan  "")
4521169699Skan
4522169699Skan(define_insn "*floatdisf2_mixed"
4523169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
4524132727Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
4525169699Skan  "TARGET_64BIT && TARGET_MIX_SSE_I387"
452690286Sobrien  "@
452790286Sobrien   fild%z1\t%1
452890286Sobrien   #
4529132727Skan   cvtsi2ss{q}\t{%1, %0|%0, %1}
453090286Sobrien   cvtsi2ss{q}\t{%1, %0|%0, %1}"
4531132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
453290286Sobrien   (set_attr "mode" "SF")
4533169699Skan   (set_attr "unit" "*,i387,*,*")
4534132727Skan   (set_attr "athlon_decode" "*,*,vector,double")
453590286Sobrien   (set_attr "fp_int_src" "true")])
453652296Sobrien
453790286Sobrien(define_insn "*floatdisf2_sse"
4538132727Skan  [(set (match_operand:SF 0 "register_operand" "=x,x")
4539132727Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
4540169699Skan  "TARGET_64BIT && TARGET_SSE_MATH"
454190286Sobrien  "cvtsi2ss{q}\t{%1, %0|%0, %1}"
4542132727Skan  [(set_attr "type" "sseicvt")
454390286Sobrien   (set_attr "mode" "SF")
4544132727Skan   (set_attr "athlon_decode" "vector,double")
454590286Sobrien   (set_attr "fp_int_src" "true")])
454690286Sobrien
4547169699Skan(define_insn "*floatdisf2_i387"
4548169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
4549169699Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
4550169699Skan  "TARGET_80387"
4551169699Skan  "@
4552169699Skan   fild%z1\t%1
4553169699Skan   #"
4554169699Skan  [(set_attr "type" "fmov,multi")
4555169699Skan   (set_attr "mode" "SF")
4556169699Skan   (set_attr "unit" "*,i387")
4557169699Skan   (set_attr "fp_int_src" "true")])
4558132727Skan
4559132727Skan(define_expand "floathidf2"
4560132727Skan  [(set (match_operand:DF 0 "register_operand" "")
4561132727Skan	(float:DF (match_operand:HI 1 "nonimmediate_operand" "")))]
4562169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
4563132727Skan{
4564169699Skan  if (TARGET_SSE2 && TARGET_SSE_MATH)
4565132727Skan    {
4566132727Skan      emit_insn (gen_floatsidf2 (operands[0],
4567132727Skan				 convert_to_mode (SImode, operands[1], 0)));
4568132727Skan      DONE;
4569132727Skan    }
4570132727Skan})
4571132727Skan
4572169699Skan(define_insn "*floathidf2_i387"
457352296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
4574169699Skan	(float:DF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
4575169699Skan  "TARGET_80387 && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
457690286Sobrien  "@
457790286Sobrien   fild%z1\t%1
457890286Sobrien   #"
457990286Sobrien  [(set_attr "type" "fmov,multi")
458090286Sobrien   (set_attr "mode" "DF")
4581169699Skan   (set_attr "unit" "*,i387")
458290286Sobrien   (set_attr "fp_int_src" "true")])
458352296Sobrien
458490286Sobrien(define_expand "floatsidf2"
458518334Speter  [(set (match_operand:DF 0 "register_operand" "")
458690286Sobrien	(float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
4587169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
458852296Sobrien  "")
458952296Sobrien
4590169699Skan(define_insn "*floatsidf2_mixed"
4591169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
4592132727Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
4593169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387"
459490286Sobrien  "@
459590286Sobrien   fild%z1\t%1
459690286Sobrien   #
4597132727Skan   cvtsi2sd\t{%1, %0|%0, %1}
459890286Sobrien   cvtsi2sd\t{%1, %0|%0, %1}"
4599132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
460090286Sobrien   (set_attr "mode" "DF")
4601169699Skan   (set_attr "unit" "*,i387,*,*")
4602132727Skan   (set_attr "athlon_decode" "*,*,double,direct")
460390286Sobrien   (set_attr "fp_int_src" "true")])
460490286Sobrien
460590286Sobrien(define_insn "*floatsidf2_sse"
4606132727Skan  [(set (match_operand:DF 0 "register_operand" "=Y,Y")
4607132727Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
4608169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
460990286Sobrien  "cvtsi2sd\t{%1, %0|%0, %1}"
4610132727Skan  [(set_attr "type" "sseicvt")
461190286Sobrien   (set_attr "mode" "DF")
4612132727Skan   (set_attr "athlon_decode" "double,direct")
461390286Sobrien   (set_attr "fp_int_src" "true")])
461490286Sobrien
4615169699Skan(define_insn "*floatsidf2_i387"
4616169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
4617169699Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
4618169699Skan  "TARGET_80387"
461990286Sobrien  "@
462090286Sobrien   fild%z1\t%1
462190286Sobrien   #"
462290286Sobrien  [(set_attr "type" "fmov,multi")
462390286Sobrien   (set_attr "mode" "DF")
4624169699Skan   (set_attr "unit" "*,i387")
462590286Sobrien   (set_attr "fp_int_src" "true")])
462690286Sobrien
4627169699Skan(define_expand "floatdidf2"
4628169699Skan  [(set (match_operand:DF 0 "register_operand" "")
4629169699Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
4630169699Skan  "TARGET_80387 || (TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH)"
4631169699Skan  "")
4632169699Skan
4633169699Skan(define_insn "*floatdidf2_mixed"
4634169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
4635132727Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
4636169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
463790286Sobrien  "@
463890286Sobrien   fild%z1\t%1
463990286Sobrien   #
4640132727Skan   cvtsi2sd{q}\t{%1, %0|%0, %1}
464190286Sobrien   cvtsi2sd{q}\t{%1, %0|%0, %1}"
4642132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
464390286Sobrien   (set_attr "mode" "DF")
4644169699Skan   (set_attr "unit" "*,i387,*,*")
4645132727Skan   (set_attr "athlon_decode" "*,*,double,direct")
464690286Sobrien   (set_attr "fp_int_src" "true")])
464790286Sobrien
464890286Sobrien(define_insn "*floatdidf2_sse"
4649132727Skan  [(set (match_operand:DF 0 "register_operand" "=Y,Y")
4650132727Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
4651169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
465290286Sobrien  "cvtsi2sd{q}\t{%1, %0|%0, %1}"
4653132727Skan  [(set_attr "type" "sseicvt")
465490286Sobrien   (set_attr "mode" "DF")
4655132727Skan   (set_attr "athlon_decode" "double,direct")
465690286Sobrien   (set_attr "fp_int_src" "true")])
465790286Sobrien
4658169699Skan(define_insn "*floatdidf2_i387"
4659169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
4660169699Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
4661169699Skan  "TARGET_80387"
4662169699Skan  "@
4663169699Skan   fild%z1\t%1
4664169699Skan   #"
4665169699Skan  [(set_attr "type" "fmov,multi")
4666169699Skan   (set_attr "mode" "DF")
4667169699Skan   (set_attr "unit" "*,i387")
4668169699Skan   (set_attr "fp_int_src" "true")])
4669169699Skan
467090286Sobrien(define_insn "floathixf2"
467190286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4672169699Skan	(float:XF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
467318334Speter  "TARGET_80387"
467490286Sobrien  "@
467590286Sobrien   fild%z1\t%1
467690286Sobrien   #"
467790286Sobrien  [(set_attr "type" "fmov,multi")
467890286Sobrien   (set_attr "mode" "XF")
4679169699Skan   (set_attr "unit" "*,i387")
468090286Sobrien   (set_attr "fp_int_src" "true")])
468152296Sobrien
468290286Sobrien(define_insn "floatsixf2"
468390286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4684169699Skan	(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
468552296Sobrien  "TARGET_80387"
468690286Sobrien  "@
468790286Sobrien   fild%z1\t%1
468890286Sobrien   #"
468990286Sobrien  [(set_attr "type" "fmov,multi")
469090286Sobrien   (set_attr "mode" "XF")
4691169699Skan   (set_attr "unit" "*,i387")
469290286Sobrien   (set_attr "fp_int_src" "true")])
469352296Sobrien
469490286Sobrien(define_insn "floatdixf2"
469590286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4696169699Skan	(float:XF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
469752296Sobrien  "TARGET_80387"
469890286Sobrien  "@
469990286Sobrien   fild%z1\t%1
470090286Sobrien   #"
470190286Sobrien  [(set_attr "type" "fmov,multi")
470290286Sobrien   (set_attr "mode" "XF")
4703169699Skan   (set_attr "unit" "*,i387")
470490286Sobrien   (set_attr "fp_int_src" "true")])
470552296Sobrien
470690286Sobrien;; %%% Kill these when reload knows how to do it.
470752296Sobrien(define_split
4708117404Skan  [(set (match_operand 0 "fp_register_operand" "")
470990286Sobrien	(float (match_operand 1 "register_operand" "")))]
4710169699Skan  "reload_completed
4711169699Skan   && TARGET_80387
4712169699Skan   && FLOAT_MODE_P (GET_MODE (operands[0]))"
471390286Sobrien  [(const_int 0)]
471490286Sobrien{
471590286Sobrien  operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
471690286Sobrien  operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]);
471790286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[2]));
471890286Sobrien  ix86_free_from_memory (GET_MODE (operands[1]));
471990286Sobrien  DONE;
472090286Sobrien})
4721132727Skan
4722132727Skan(define_expand "floatunssisf2"
4723132727Skan  [(use (match_operand:SF 0 "register_operand" ""))
4724132727Skan   (use (match_operand:SI 1 "register_operand" ""))]
4725169699Skan  "!TARGET_64BIT && TARGET_SSE_MATH"
4726132727Skan  "x86_emit_floatuns (operands); DONE;")
4727132727Skan
4728132727Skan(define_expand "floatunsdisf2"
4729132727Skan  [(use (match_operand:SF 0 "register_operand" ""))
4730132727Skan   (use (match_operand:DI 1 "register_operand" ""))]
4731169699Skan  "TARGET_64BIT && TARGET_SSE_MATH"
4732132727Skan  "x86_emit_floatuns (operands); DONE;")
4733132727Skan
4734132727Skan(define_expand "floatunsdidf2"
4735132727Skan  [(use (match_operand:DF 0 "register_operand" ""))
4736132727Skan   (use (match_operand:DI 1 "register_operand" ""))]
4737169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
4738132727Skan  "x86_emit_floatuns (operands); DONE;")
473990286Sobrien
4740132727Skan;; SSE extract/set expanders
4741132727Skan
4742169699Skan
4743169699Skan;; Add instructions
4744132727Skan
4745169699Skan;; %%% splits for addditi3
4746132727Skan
4747169699Skan(define_expand "addti3"
4748169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
4749169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
4750169699Skan		 (match_operand:TI 2 "x86_64_general_operand" "")))
4751169699Skan   (clobber (reg:CC FLAGS_REG))]
4752169699Skan  "TARGET_64BIT"
4753169699Skan  "ix86_expand_binary_operator (PLUS, TImode, operands); DONE;")
4754132727Skan
4755169699Skan(define_insn "*addti3_1"
4756169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
4757169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0")
4758171835Skan		 (match_operand:TI 2 "x86_64_general_operand" "roe,re")))
4759169699Skan   (clobber (reg:CC FLAGS_REG))]
4760169699Skan  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)"
4761169699Skan  "#")
4762132727Skan
4763169699Skan(define_split
4764169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
4765169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
4766171835Skan		 (match_operand:TI 2 "x86_64_general_operand" "")))
4767169699Skan   (clobber (reg:CC FLAGS_REG))]
4768169699Skan  "TARGET_64BIT && reload_completed"
4769169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
4770169699Skan					  UNSPEC_ADD_CARRY))
4771169699Skan	      (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))])
4772169699Skan   (parallel [(set (match_dup 3)
4773169699Skan		   (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
4774169699Skan				     (match_dup 4))
4775169699Skan			    (match_dup 5)))
4776169699Skan	      (clobber (reg:CC FLAGS_REG))])]
4777169699Skan  "split_ti (operands+0, 1, operands+0, operands+3);
4778169699Skan   split_ti (operands+1, 1, operands+1, operands+4);
4779169699Skan   split_ti (operands+2, 1, operands+2, operands+5);")
4780132727Skan
478190286Sobrien;; %%% splits for addsidi3
478290286Sobrien;  [(set (match_operand:DI 0 "nonimmediate_operand" "")
478390286Sobrien;	(plus:DI (match_operand:DI 1 "general_operand" "")
478490286Sobrien;		 (zero_extend:DI (match_operand:SI 2 "general_operand" ""))))]
478552296Sobrien
478690286Sobrien(define_expand "adddi3"
478790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
478890286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
478990286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "")))
4790169699Skan   (clobber (reg:CC FLAGS_REG))]
479190286Sobrien  ""
479290286Sobrien  "ix86_expand_binary_operator (PLUS, DImode, operands); DONE;")
479352296Sobrien
479490286Sobrien(define_insn "*adddi3_1"
479590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
479690286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
479790286Sobrien		 (match_operand:DI 2 "general_operand" "roiF,riF")))
4798169699Skan   (clobber (reg:CC FLAGS_REG))]
4799107605Sobrien  "!TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
480052296Sobrien  "#")
480152296Sobrien
480252296Sobrien(define_split
480390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
480490286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
480590286Sobrien		 (match_operand:DI 2 "general_operand" "")))
4806169699Skan   (clobber (reg:CC FLAGS_REG))]
480790286Sobrien  "!TARGET_64BIT && reload_completed"
4808169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
4809117404Skan					  UNSPEC_ADD_CARRY))
481090286Sobrien	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
481190286Sobrien   (parallel [(set (match_dup 3)
4812169699Skan		   (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
481390286Sobrien				     (match_dup 4))
481490286Sobrien			    (match_dup 5)))
4815169699Skan	      (clobber (reg:CC FLAGS_REG))])]
481690286Sobrien  "split_di (operands+0, 1, operands+0, operands+3);
481790286Sobrien   split_di (operands+1, 1, operands+1, operands+4);
481890286Sobrien   split_di (operands+2, 1, operands+2, operands+5);")
481918334Speter
4820132727Skan(define_insn "adddi3_carry_rex64"
482190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
4822132727Skan	  (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
482390286Sobrien			    (match_operand:DI 1 "nonimmediate_operand" "%0,0"))
482490286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
4825169699Skan   (clobber (reg:CC FLAGS_REG))]
482690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
482790286Sobrien  "adc{q}\t{%2, %0|%0, %2}"
482890286Sobrien  [(set_attr "type" "alu")
482990286Sobrien   (set_attr "pent_pair" "pu")
4830169699Skan   (set_attr "mode" "DI")])
483152296Sobrien
483290286Sobrien(define_insn "*adddi3_cc_rex64"
4833169699Skan  [(set (reg:CC FLAGS_REG)
4834117404Skan	(unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0")
4835117404Skan		    (match_operand:DI 2 "x86_64_general_operand" "re,rm")]
4836117404Skan		   UNSPEC_ADD_CARRY))
483790286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
483890286Sobrien	(plus:DI (match_dup 1) (match_dup 2)))]
483990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
484090286Sobrien  "add{q}\t{%2, %0|%0, %2}"
484190286Sobrien  [(set_attr "type" "alu")
484290286Sobrien   (set_attr "mode" "DI")])
484352296Sobrien
4844132727Skan(define_insn "addqi3_carry"
4845132727Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
4846132727Skan	  (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
4847132727Skan			    (match_operand:QI 1 "nonimmediate_operand" "%0,0"))
4848132727Skan		   (match_operand:QI 2 "general_operand" "qi,qm")))
4849169699Skan   (clobber (reg:CC FLAGS_REG))]
4850132727Skan  "ix86_binary_operator_ok (PLUS, QImode, operands)"
4851132727Skan  "adc{b}\t{%2, %0|%0, %2}"
4852132727Skan  [(set_attr "type" "alu")
4853132727Skan   (set_attr "pent_pair" "pu")
4854169699Skan   (set_attr "mode" "QI")])
4855132727Skan
4856132727Skan(define_insn "addhi3_carry"
4857132727Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
4858132727Skan	  (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
4859132727Skan			    (match_operand:HI 1 "nonimmediate_operand" "%0,0"))
4860132727Skan		   (match_operand:HI 2 "general_operand" "ri,rm")))
4861169699Skan   (clobber (reg:CC FLAGS_REG))]
4862132727Skan  "ix86_binary_operator_ok (PLUS, HImode, operands)"
4863132727Skan  "adc{w}\t{%2, %0|%0, %2}"
4864132727Skan  [(set_attr "type" "alu")
4865132727Skan   (set_attr "pent_pair" "pu")
4866169699Skan   (set_attr "mode" "HI")])
4867132727Skan
4868132727Skan(define_insn "addsi3_carry"
486990286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
4870132727Skan	  (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
487190286Sobrien			    (match_operand:SI 1 "nonimmediate_operand" "%0,0"))
487290286Sobrien		   (match_operand:SI 2 "general_operand" "ri,rm")))
4873169699Skan   (clobber (reg:CC FLAGS_REG))]
487490286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
487590286Sobrien  "adc{l}\t{%2, %0|%0, %2}"
487690286Sobrien  [(set_attr "type" "alu")
487790286Sobrien   (set_attr "pent_pair" "pu")
4878169699Skan   (set_attr "mode" "SI")])
487952296Sobrien
488090286Sobrien(define_insn "*addsi3_carry_zext"
488190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
488290286Sobrien	  (zero_extend:DI 
4883132727Skan	    (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
488490286Sobrien			      (match_operand:SI 1 "nonimmediate_operand" "%0"))
488590286Sobrien		     (match_operand:SI 2 "general_operand" "rim"))))
4886169699Skan   (clobber (reg:CC FLAGS_REG))]
488790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
488890286Sobrien  "adc{l}\t{%2, %k0|%k0, %2}"
488990286Sobrien  [(set_attr "type" "alu")
489090286Sobrien   (set_attr "pent_pair" "pu")
4891169699Skan   (set_attr "mode" "SI")])
489252296Sobrien
489390286Sobrien(define_insn "*addsi3_cc"
4894169699Skan  [(set (reg:CC FLAGS_REG)
4895117404Skan	(unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0")
4896117404Skan		    (match_operand:SI 2 "general_operand" "ri,rm")]
4897117404Skan		   UNSPEC_ADD_CARRY))
489890286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
489990286Sobrien	(plus:SI (match_dup 1) (match_dup 2)))]
490090286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
490190286Sobrien  "add{l}\t{%2, %0|%0, %2}"
490290286Sobrien  [(set_attr "type" "alu")
490390286Sobrien   (set_attr "mode" "SI")])
490418334Speter
490590286Sobrien(define_insn "addqi3_cc"
4906169699Skan  [(set (reg:CC FLAGS_REG)
4907117404Skan	(unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0")
4908117404Skan		    (match_operand:QI 2 "general_operand" "qi,qm")]
4909117404Skan		   UNSPEC_ADD_CARRY))
491090286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
491190286Sobrien	(plus:QI (match_dup 1) (match_dup 2)))]
491290286Sobrien  "ix86_binary_operator_ok (PLUS, QImode, operands)"
491390286Sobrien  "add{b}\t{%2, %0|%0, %2}"
491490286Sobrien  [(set_attr "type" "alu")
491590286Sobrien   (set_attr "mode" "QI")])
491618334Speter
491790286Sobrien(define_expand "addsi3"
491890286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
491990286Sobrien		   (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
492090286Sobrien			    (match_operand:SI 2 "general_operand" "")))
4921169699Skan	      (clobber (reg:CC FLAGS_REG))])]
492290286Sobrien  ""
492390286Sobrien  "ix86_expand_binary_operator (PLUS, SImode, operands); DONE;")
492418334Speter
492590286Sobrien(define_insn "*lea_1"
492690286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
4927132727Skan	(match_operand:SI 1 "no_seg_address_operand" "p"))]
492890286Sobrien  "!TARGET_64BIT"
492990286Sobrien  "lea{l}\t{%a1, %0|%0, %a1}"
493090286Sobrien  [(set_attr "type" "lea")
493190286Sobrien   (set_attr "mode" "SI")])
493218334Speter
493390286Sobrien(define_insn "*lea_1_rex64"
493490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
4935132727Skan	(subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))]
493690286Sobrien  "TARGET_64BIT"
493790286Sobrien  "lea{l}\t{%a1, %0|%0, %a1}"
493890286Sobrien  [(set_attr "type" "lea")
493990286Sobrien   (set_attr "mode" "SI")])
494018334Speter
494190286Sobrien(define_insn "*lea_1_zext"
494290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
4943132727Skan	(zero_extend:DI
4944132727Skan	 (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))]
494590286Sobrien  "TARGET_64BIT"
494690286Sobrien  "lea{l}\t{%a1, %k0|%k0, %a1}"
494790286Sobrien  [(set_attr "type" "lea")
494890286Sobrien   (set_attr "mode" "SI")])
494990286Sobrien
495090286Sobrien(define_insn "*lea_2_rex64"
495190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
4952132727Skan	(match_operand:DI 1 "no_seg_address_operand" "p"))]
495390286Sobrien  "TARGET_64BIT"
495490286Sobrien  "lea{q}\t{%a1, %0|%0, %a1}"
495590286Sobrien  [(set_attr "type" "lea")
495690286Sobrien   (set_attr "mode" "DI")])
495790286Sobrien
495890286Sobrien;; The lea patterns for non-Pmodes needs to be matched by several
495990286Sobrien;; insns converted to real lea by splitters.
496090286Sobrien
496190286Sobrien(define_insn_and_split "*lea_general_1"
496290286Sobrien  [(set (match_operand 0 "register_operand" "=r")
4963169699Skan	(plus (plus (match_operand 1 "index_register_operand" "l")
496490286Sobrien		    (match_operand 2 "register_operand" "r"))
496590286Sobrien	      (match_operand 3 "immediate_operand" "i")))]
496690286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
496790286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
496890286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
496990286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
497090286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[2])
497190286Sobrien   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
497290286Sobrien       || GET_MODE (operands[3]) == VOIDmode)"
497390286Sobrien  "#"
497490286Sobrien  "&& reload_completed"
497590286Sobrien  [(const_int 0)]
497690286Sobrien{
497790286Sobrien  rtx pat;
497890286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
497990286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
498090286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
498190286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
498290286Sobrien  pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]),
498390286Sobrien  		      operands[3]);
498490286Sobrien  if (Pmode != SImode)
498590286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
498690286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
498790286Sobrien  DONE;
498890286Sobrien}
498990286Sobrien  [(set_attr "type" "lea")
499090286Sobrien   (set_attr "mode" "SI")])
499190286Sobrien
499290286Sobrien(define_insn_and_split "*lea_general_1_zext"
499390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
499490286Sobrien	(zero_extend:DI
4995169699Skan	  (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "l")
499690286Sobrien			    (match_operand:SI 2 "register_operand" "r"))
499790286Sobrien		   (match_operand:SI 3 "immediate_operand" "i"))))]
499890286Sobrien  "TARGET_64BIT"
499990286Sobrien  "#"
500090286Sobrien  "&& reload_completed"
500152296Sobrien  [(set (match_dup 0)
500290286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1)
500390286Sobrien						     (match_dup 2))
500490286Sobrien					    (match_dup 3)) 0)))]
500590286Sobrien{
500690286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
500790286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
500890286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
500990286Sobrien}
501090286Sobrien  [(set_attr "type" "lea")
501190286Sobrien   (set_attr "mode" "SI")])
501252296Sobrien
501390286Sobrien(define_insn_and_split "*lea_general_2"
501490286Sobrien  [(set (match_operand 0 "register_operand" "=r")
5015169699Skan	(plus (mult (match_operand 1 "index_register_operand" "l")
501690286Sobrien		    (match_operand 2 "const248_operand" "i"))
501790286Sobrien	      (match_operand 3 "nonmemory_operand" "ri")))]
501890286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
501990286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
502090286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
502190286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
502290286Sobrien   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
502390286Sobrien       || GET_MODE (operands[3]) == VOIDmode)"
502490286Sobrien  "#"
502590286Sobrien  "&& reload_completed"
502690286Sobrien  [(const_int 0)]
502790286Sobrien{
502890286Sobrien  rtx pat;
502990286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
503090286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
503190286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
503290286Sobrien  pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]),
503390286Sobrien  		      operands[3]);
503490286Sobrien  if (Pmode != SImode)
503590286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
503690286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
503790286Sobrien  DONE;
503890286Sobrien}
503990286Sobrien  [(set_attr "type" "lea")
504090286Sobrien   (set_attr "mode" "SI")])
504152296Sobrien
504290286Sobrien(define_insn_and_split "*lea_general_2_zext"
504390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
504490286Sobrien	(zero_extend:DI
5045169699Skan	  (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "l")
504690286Sobrien			    (match_operand:SI 2 "const248_operand" "n"))
504790286Sobrien		   (match_operand:SI 3 "nonmemory_operand" "ri"))))]
504890286Sobrien  "TARGET_64BIT"
504990286Sobrien  "#"
505090286Sobrien  "&& reload_completed"
505190286Sobrien  [(set (match_dup 0)
505290286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1)
505390286Sobrien						     (match_dup 2))
505490286Sobrien					    (match_dup 3)) 0)))]
505590286Sobrien{
505690286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
505790286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
505890286Sobrien}
505990286Sobrien  [(set_attr "type" "lea")
506090286Sobrien   (set_attr "mode" "SI")])
506118334Speter
506290286Sobrien(define_insn_and_split "*lea_general_3"
506390286Sobrien  [(set (match_operand 0 "register_operand" "=r")
5064169699Skan	(plus (plus (mult (match_operand 1 "index_register_operand" "l")
506590286Sobrien			  (match_operand 2 "const248_operand" "i"))
506690286Sobrien		    (match_operand 3 "register_operand" "r"))
506790286Sobrien	      (match_operand 4 "immediate_operand" "i")))]
506890286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
506990286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
507090286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
507190286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
507290286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[3])"
507390286Sobrien  "#"
507490286Sobrien  "&& reload_completed"
507590286Sobrien  [(const_int 0)]
507690286Sobrien{
507790286Sobrien  rtx pat;
507890286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
507990286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
508090286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
508190286Sobrien  operands[4] = gen_lowpart (Pmode, operands[4]);
508290286Sobrien  pat = gen_rtx_PLUS (Pmode,
508390286Sobrien  		      gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1],
508490286Sobrien		      					 operands[2]),
508590286Sobrien				    operands[3]),
508690286Sobrien  		      operands[4]);
508790286Sobrien  if (Pmode != SImode)
508890286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
508990286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
509090286Sobrien  DONE;
509190286Sobrien}
509290286Sobrien  [(set_attr "type" "lea")
509390286Sobrien   (set_attr "mode" "SI")])
509452296Sobrien
509590286Sobrien(define_insn_and_split "*lea_general_3_zext"
509690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
509790286Sobrien	(zero_extend:DI
5098169699Skan	  (plus:SI (plus:SI (mult:SI
5099169699Skan			      (match_operand:SI 1 "index_register_operand" "l")
5100169699Skan			      (match_operand:SI 2 "const248_operand" "n"))
510190286Sobrien			    (match_operand:SI 3 "register_operand" "r"))
510290286Sobrien		   (match_operand:SI 4 "immediate_operand" "i"))))]
510390286Sobrien  "TARGET_64BIT"
510490286Sobrien  "#"
510590286Sobrien  "&& reload_completed"
510690286Sobrien  [(set (match_dup 0)
510790286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1)
510890286Sobrien							      (match_dup 2))
510990286Sobrien						     (match_dup 3))
511090286Sobrien					    (match_dup 4)) 0)))]
511190286Sobrien{
511290286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
511390286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
511490286Sobrien  operands[4] = gen_lowpart (Pmode, operands[4]);
511590286Sobrien}
511690286Sobrien  [(set_attr "type" "lea")
511790286Sobrien   (set_attr "mode" "SI")])
511818334Speter
511990286Sobrien(define_insn "*adddi_1_rex64"
512090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
512190286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r")
5122169699Skan		 (match_operand:DI 2 "x86_64_general_operand" "rme,re,le")))
5123169699Skan   (clobber (reg:CC FLAGS_REG))]
512490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
512590286Sobrien{
512690286Sobrien  switch (get_attr_type (insn))
512790286Sobrien    {
512890286Sobrien    case TYPE_LEA:
512990286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
513090286Sobrien      return "lea{q}\t{%a2, %0|%0, %a2}";
513190286Sobrien
513290286Sobrien    case TYPE_INCDEC:
5133169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
513490286Sobrien      if (operands[2] == const1_rtx)
513590286Sobrien        return "inc{q}\t%0";
513690286Sobrien      else
5137169699Skan        {
5138169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5139169699Skan          return "dec{q}\t%0";
5140169699Skan	}
514190286Sobrien
514290286Sobrien    default:
5143169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
514490286Sobrien
514590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
514690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
514790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
514890286Sobrien	  /* Avoid overflows.  */
514990286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
515090286Sobrien          && (INTVAL (operands[2]) == 128
515190286Sobrien	      || (INTVAL (operands[2]) < 0
515290286Sobrien		  && INTVAL (operands[2]) != -128)))
515390286Sobrien        {
515490286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
515590286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
515690286Sobrien        }
515790286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
515890286Sobrien    }
515990286Sobrien}
516090286Sobrien  [(set (attr "type")
516190286Sobrien     (cond [(eq_attr "alternative" "2")
516290286Sobrien	      (const_string "lea")
516390286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
516490286Sobrien	    ; ought but a memory context.
516590286Sobrien	    (match_operand:DI 2 "pic_symbolic_operand" "")
516690286Sobrien	      (const_string "lea")
516790286Sobrien	    (match_operand:DI 2 "incdec_operand" "")
516890286Sobrien	      (const_string "incdec")
516990286Sobrien	   ]
517090286Sobrien	   (const_string "alu")))
517190286Sobrien   (set_attr "mode" "DI")])
517290286Sobrien
517390286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
517452296Sobrien(define_split
517590286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
517690286Sobrien	(plus:DI (match_operand:DI 1 "register_operand" "")
517790286Sobrien		 (match_operand:DI 2 "x86_64_nonmemory_operand" "")))
5178169699Skan   (clobber (reg:CC FLAGS_REG))]
517990286Sobrien  "TARGET_64BIT && reload_completed
518090286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
518152296Sobrien  [(set (match_dup 0)
518290286Sobrien	(plus:DI (match_dup 1)
518390286Sobrien		 (match_dup 2)))]
518452296Sobrien  "")
518552296Sobrien
518690286Sobrien(define_insn "*adddi_2_rex64"
5187169699Skan  [(set (reg FLAGS_REG)
518890286Sobrien	(compare
518990286Sobrien	  (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
519090286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "rme,re"))
519190286Sobrien	  (const_int 0)))			
519290286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
519390286Sobrien	(plus:DI (match_dup 1) (match_dup 2)))]
519490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
519590286Sobrien   && ix86_binary_operator_ok (PLUS, DImode, operands)
519690286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
519790286Sobrien      ought but a memory context.  */
519890286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
519990286Sobrien{
520090286Sobrien  switch (get_attr_type (insn))
520190286Sobrien    {
520290286Sobrien    case TYPE_INCDEC:
5203169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
520490286Sobrien      if (operands[2] == const1_rtx)
520590286Sobrien        return "inc{q}\t%0";
520690286Sobrien      else
5207169699Skan        {
5208169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5209169699Skan          return "dec{q}\t%0";
5210169699Skan	}
521152296Sobrien
521290286Sobrien    default:
5213169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
521490286Sobrien      /* ???? We ought to handle there the 32bit case too
5215132727Skan	 - do we need new constraint?  */
521690286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
521790286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
521890286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
521990286Sobrien	  /* Avoid overflows.  */
522090286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
522190286Sobrien          && (INTVAL (operands[2]) == 128
522290286Sobrien	      || (INTVAL (operands[2]) < 0
522390286Sobrien		  && INTVAL (operands[2]) != -128)))
522490286Sobrien        {
522590286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
522690286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
522790286Sobrien        }
522890286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
522990286Sobrien    }
523090286Sobrien}
523190286Sobrien  [(set (attr "type")
523290286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
523390286Sobrien	(const_string "incdec")
523490286Sobrien	(const_string "alu")))
523590286Sobrien   (set_attr "mode" "DI")])
523618334Speter
523790286Sobrien(define_insn "*adddi_3_rex64"
5238169699Skan  [(set (reg FLAGS_REG)
523990286Sobrien	(compare (neg:DI (match_operand:DI 2 "x86_64_general_operand" "rme"))
524090286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "%0")))
524190286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
524290286Sobrien  "TARGET_64BIT
524390286Sobrien   && ix86_match_ccmode (insn, CCZmode)
524490286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
524590286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
524690286Sobrien      ought but a memory context.  */
524790286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
524850650Sobrien{
524990286Sobrien  switch (get_attr_type (insn))
525090286Sobrien    {
525190286Sobrien    case TYPE_INCDEC:
5252169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
525390286Sobrien      if (operands[2] == const1_rtx)
525490286Sobrien        return "inc{q}\t%0";
525590286Sobrien      else
5256169699Skan        {
5257169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5258169699Skan          return "dec{q}\t%0";
5259169699Skan	}
526050650Sobrien
526190286Sobrien    default:
5262169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
526390286Sobrien      /* ???? We ought to handle there the 32bit case too
5264132727Skan	 - do we need new constraint?  */
526590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
526690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
526790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
526890286Sobrien	  /* Avoid overflows.  */
526990286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
527090286Sobrien          && (INTVAL (operands[2]) == 128
527190286Sobrien	      || (INTVAL (operands[2]) < 0
527290286Sobrien		  && INTVAL (operands[2]) != -128)))
527390286Sobrien        {
527490286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
527590286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
527690286Sobrien        }
527790286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
527890286Sobrien    }
527990286Sobrien}
528090286Sobrien  [(set (attr "type")
528190286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
528290286Sobrien	(const_string "incdec")
528390286Sobrien	(const_string "alu")))
528490286Sobrien   (set_attr "mode" "DI")])
528550650Sobrien
528690286Sobrien; For comparisons against 1, -1 and 128, we may generate better code
528790286Sobrien; by converting cmp to add, inc or dec as done by peephole2.  This pattern
528890286Sobrien; is matched then.  We can't accept general immediate, because for
528990286Sobrien; case of overflows,  the result is messed up.
529090286Sobrien; This pattern also don't hold of 0x8000000000000000, since the value overflows
529190286Sobrien; when negated.
529290286Sobrien; Also carry flag is reversed compared to cmp, so this conversion is valid
529390286Sobrien; only for comparisons not depending on it.
529490286Sobrien(define_insn "*adddi_4_rex64"
5295169699Skan  [(set (reg FLAGS_REG)
529690286Sobrien	(compare (match_operand:DI 1 "nonimmediate_operand" "0")
529790286Sobrien		 (match_operand:DI 2 "x86_64_immediate_operand" "e")))
529890286Sobrien   (clobber (match_scratch:DI 0 "=rm"))]
529990286Sobrien  "TARGET_64BIT
530090286Sobrien   &&  ix86_match_ccmode (insn, CCGCmode)"
530190286Sobrien{
530290286Sobrien  switch (get_attr_type (insn))
530390286Sobrien    {
530490286Sobrien    case TYPE_INCDEC:
530590286Sobrien      if (operands[2] == constm1_rtx)
530690286Sobrien        return "inc{q}\t%0";
530790286Sobrien      else
5308169699Skan        {
5309169699Skan	  gcc_assert (operands[2] == const1_rtx);
5310169699Skan          return "dec{q}\t%0";
5311169699Skan	}
531250650Sobrien
531390286Sobrien    default:
5314169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
531590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
531690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
531790286Sobrien      if ((INTVAL (operands[2]) == -128
531890286Sobrien	   || (INTVAL (operands[2]) > 0
531990286Sobrien	       && INTVAL (operands[2]) != 128))
532090286Sobrien	  /* Avoid overflows.  */
532190286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))))
532290286Sobrien	return "sub{q}\t{%2, %0|%0, %2}";
532390286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
532490286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
532590286Sobrien    }
532690286Sobrien}
532790286Sobrien  [(set (attr "type")
532890286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
532990286Sobrien	(const_string "incdec")
533090286Sobrien	(const_string "alu")))
533190286Sobrien   (set_attr "mode" "DI")])
533290286Sobrien
533390286Sobrien(define_insn "*adddi_5_rex64"
5334169699Skan  [(set (reg FLAGS_REG)
533590286Sobrien	(compare
533690286Sobrien	  (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
533790286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "rme"))
533890286Sobrien	  (const_int 0)))			
533990286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
534090286Sobrien  "TARGET_64BIT
534190286Sobrien   && ix86_match_ccmode (insn, CCGOCmode)
534290286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
534390286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
534490286Sobrien      ought but a memory context.  */
534590286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
534690286Sobrien{
534790286Sobrien  switch (get_attr_type (insn))
534850650Sobrien    {
534990286Sobrien    case TYPE_INCDEC:
5350169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
535190286Sobrien      if (operands[2] == const1_rtx)
535290286Sobrien        return "inc{q}\t%0";
535390286Sobrien      else
5354169699Skan        {
5355169699Skan          gcc_assert (operands[2] == constm1_rtx);
5356169699Skan          return "dec{q}\t%0";
5357169699Skan	}
535850650Sobrien
535990286Sobrien    default:
5360169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
536190286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
536290286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
536390286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
536490286Sobrien	  /* Avoid overflows.  */
536590286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
536690286Sobrien          && (INTVAL (operands[2]) == 128
536790286Sobrien	      || (INTVAL (operands[2]) < 0
536890286Sobrien		  && INTVAL (operands[2]) != -128)))
536990286Sobrien        {
537090286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
537190286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
537290286Sobrien        }
537390286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
537450650Sobrien    }
537590286Sobrien}
537690286Sobrien  [(set (attr "type")
537790286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
537890286Sobrien	(const_string "incdec")
537990286Sobrien	(const_string "alu")))
538090286Sobrien   (set_attr "mode" "DI")])
538150650Sobrien
538250650Sobrien
538390286Sobrien(define_insn "*addsi_1"
538490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
538590286Sobrien	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
5386169699Skan		 (match_operand:SI 2 "general_operand" "rmni,rni,lni")))
5387169699Skan   (clobber (reg:CC FLAGS_REG))]
538890286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
538950650Sobrien{
539090286Sobrien  switch (get_attr_type (insn))
539190286Sobrien    {
539290286Sobrien    case TYPE_LEA:
539390286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
539490286Sobrien      return "lea{l}\t{%a2, %0|%0, %a2}";
539550650Sobrien
539690286Sobrien    case TYPE_INCDEC:
5397169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
539890286Sobrien      if (operands[2] == const1_rtx)
539990286Sobrien        return "inc{l}\t%0";
540090286Sobrien      else
5401169699Skan	{
5402169699Skan  	  gcc_assert (operands[2] == constm1_rtx);
5403169699Skan          return "dec{l}\t%0";
5404169699Skan	}
540550650Sobrien
540690286Sobrien    default:
5407169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
540850650Sobrien
540990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
541090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
541190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
541290286Sobrien          && (INTVAL (operands[2]) == 128
541390286Sobrien	      || (INTVAL (operands[2]) < 0
541490286Sobrien		  && INTVAL (operands[2]) != -128)))
541590286Sobrien        {
541690286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
541790286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
541890286Sobrien        }
541990286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
542090286Sobrien    }
542190286Sobrien}
542290286Sobrien  [(set (attr "type")
542390286Sobrien     (cond [(eq_attr "alternative" "2")
542490286Sobrien	      (const_string "lea")
542590286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
542690286Sobrien	    ; ought but a memory context.
542790286Sobrien	    (match_operand:SI 2 "pic_symbolic_operand" "")
542890286Sobrien	      (const_string "lea")
542990286Sobrien	    (match_operand:SI 2 "incdec_operand" "")
543090286Sobrien	      (const_string "incdec")
543190286Sobrien	   ]
543290286Sobrien	   (const_string "alu")))
543390286Sobrien   (set_attr "mode" "SI")])
543490286Sobrien
543590286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
543690286Sobrien(define_split
543790286Sobrien  [(set (match_operand 0 "register_operand" "")
543890286Sobrien	(plus (match_operand 1 "register_operand" "")
543990286Sobrien              (match_operand 2 "nonmemory_operand" "")))
5440169699Skan   (clobber (reg:CC FLAGS_REG))]
544190286Sobrien  "reload_completed
544290286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
544390286Sobrien  [(const_int 0)]
544490286Sobrien{
544590286Sobrien  rtx pat;
544690286Sobrien  /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
544790286Sobrien     may confuse gen_lowpart.  */
544890286Sobrien  if (GET_MODE (operands[0]) != Pmode)
544950650Sobrien    {
545090286Sobrien      operands[1] = gen_lowpart (Pmode, operands[1]);
545190286Sobrien      operands[2] = gen_lowpart (Pmode, operands[2]);
545290286Sobrien    }
545390286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
545490286Sobrien  pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
545590286Sobrien  if (Pmode != SImode)
545690286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
545790286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
545890286Sobrien  DONE;
545990286Sobrien})
546050650Sobrien
546190286Sobrien;; It may seem that nonimmediate operand is proper one for operand 1.
546290286Sobrien;; The addsi_1 pattern allows nonimmediate operand at that place and
546390286Sobrien;; we take care in ix86_binary_operator_ok to not allow two memory
546490286Sobrien;; operands so proper swapping will be done in reload.  This allow
546590286Sobrien;; patterns constructed from addsi_1 to match.
546690286Sobrien(define_insn "addsi_1_zext"
546790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
546890286Sobrien	(zero_extend:DI
546990286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r")
5470169699Skan		   (match_operand:SI 2 "general_operand" "rmni,lni"))))
5471169699Skan   (clobber (reg:CC FLAGS_REG))]
547290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
547390286Sobrien{
547490286Sobrien  switch (get_attr_type (insn))
547590286Sobrien    {
547690286Sobrien    case TYPE_LEA:
547790286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
547890286Sobrien      return "lea{l}\t{%a2, %k0|%k0, %a2}";
547990286Sobrien
548090286Sobrien    case TYPE_INCDEC:
548190286Sobrien      if (operands[2] == const1_rtx)
548290286Sobrien        return "inc{l}\t%k0";
548350650Sobrien      else
5484169699Skan        {
5485169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5486169699Skan          return "dec{l}\t%k0";
5487169699Skan	}
548890286Sobrien
548990286Sobrien    default:
549090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
549190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
549290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
549390286Sobrien          && (INTVAL (operands[2]) == 128
549490286Sobrien	      || (INTVAL (operands[2]) < 0
549590286Sobrien		  && INTVAL (operands[2]) != -128)))
549690286Sobrien        {
549790286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
549890286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
549990286Sobrien        }
550090286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
550150650Sobrien    }
550290286Sobrien}
550390286Sobrien  [(set (attr "type")
550490286Sobrien     (cond [(eq_attr "alternative" "1")
550590286Sobrien	      (const_string "lea")
550690286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
550790286Sobrien	    ; ought but a memory context.
550890286Sobrien	    (match_operand:SI 2 "pic_symbolic_operand" "")
550990286Sobrien	      (const_string "lea")
551090286Sobrien	    (match_operand:SI 2 "incdec_operand" "")
551190286Sobrien	      (const_string "incdec")
551290286Sobrien	   ]
551390286Sobrien	   (const_string "alu")))
551490286Sobrien   (set_attr "mode" "SI")])
551550650Sobrien
551690286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
551790286Sobrien(define_split
551890286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
551990286Sobrien	(zero_extend:DI
552090286Sobrien	  (plus:SI (match_operand:SI 1 "register_operand" "")
552190286Sobrien		   (match_operand:SI 2 "nonmemory_operand" ""))))
5522169699Skan   (clobber (reg:CC FLAGS_REG))]
5523132727Skan  "TARGET_64BIT && reload_completed
552490286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
552590286Sobrien  [(set (match_dup 0)
552690286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))]
552790286Sobrien{
552890286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
552990286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
553090286Sobrien})
553150650Sobrien
553290286Sobrien(define_insn "*addsi_2"
5533169699Skan  [(set (reg FLAGS_REG)
553490286Sobrien	(compare
553590286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
553690286Sobrien		   (match_operand:SI 2 "general_operand" "rmni,rni"))
553790286Sobrien	  (const_int 0)))			
553890286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
553990286Sobrien	(plus:SI (match_dup 1) (match_dup 2)))]
554090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
554190286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
554290286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
554390286Sobrien      ought but a memory context.  */
554490286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
554518334Speter{
554690286Sobrien  switch (get_attr_type (insn))
554790286Sobrien    {
554890286Sobrien    case TYPE_INCDEC:
5549169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
555090286Sobrien      if (operands[2] == const1_rtx)
555190286Sobrien        return "inc{l}\t%0";
555290286Sobrien      else
5553169699Skan        {
5554169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5555169699Skan          return "dec{l}\t%0";
5556169699Skan	}
555718334Speter
555890286Sobrien    default:
5559169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
556090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
556190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
556290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
556390286Sobrien          && (INTVAL (operands[2]) == 128
556490286Sobrien	      || (INTVAL (operands[2]) < 0
556590286Sobrien		  && INTVAL (operands[2]) != -128)))
556690286Sobrien        {
556790286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
556890286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
556990286Sobrien        }
557090286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
557190286Sobrien    }
557290286Sobrien}
557390286Sobrien  [(set (attr "type")
557490286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
557590286Sobrien	(const_string "incdec")
557690286Sobrien	(const_string "alu")))
557790286Sobrien   (set_attr "mode" "SI")])
557818334Speter
557990286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
558090286Sobrien(define_insn "*addsi_2_zext"
5581169699Skan  [(set (reg FLAGS_REG)
558290286Sobrien	(compare
558390286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
558490286Sobrien		   (match_operand:SI 2 "general_operand" "rmni"))
558590286Sobrien	  (const_int 0)))			
558690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
558790286Sobrien	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
558890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
558990286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
559090286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
559190286Sobrien      ought but a memory context.  */
559290286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
559390286Sobrien{
559490286Sobrien  switch (get_attr_type (insn))
559518334Speter    {
559690286Sobrien    case TYPE_INCDEC:
559790286Sobrien      if (operands[2] == const1_rtx)
559890286Sobrien        return "inc{l}\t%k0";
559990286Sobrien      else
5600169699Skan	{
5601169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5602169699Skan          return "dec{l}\t%k0";
5603169699Skan	}
560490286Sobrien
560590286Sobrien    default:
560690286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
560790286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
560890286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
560990286Sobrien          && (INTVAL (operands[2]) == 128
561090286Sobrien	      || (INTVAL (operands[2]) < 0
561190286Sobrien		  && INTVAL (operands[2]) != -128)))
561290286Sobrien        {
561390286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
561490286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
561590286Sobrien        }
561690286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
561718334Speter    }
561890286Sobrien}
561990286Sobrien  [(set (attr "type")
562090286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
562190286Sobrien	(const_string "incdec")
562290286Sobrien	(const_string "alu")))
562390286Sobrien   (set_attr "mode" "SI")])
562418334Speter
562590286Sobrien(define_insn "*addsi_3"
5626169699Skan  [(set (reg FLAGS_REG)
562790286Sobrien	(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
562890286Sobrien		 (match_operand:SI 1 "nonimmediate_operand" "%0")))
562990286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
563090286Sobrien  "ix86_match_ccmode (insn, CCZmode)
563190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
563290286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
563390286Sobrien      ought but a memory context.  */
563490286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
563590286Sobrien{
563690286Sobrien  switch (get_attr_type (insn))
563718334Speter    {
563890286Sobrien    case TYPE_INCDEC:
5639169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
564090286Sobrien      if (operands[2] == const1_rtx)
564190286Sobrien        return "inc{l}\t%0";
564290286Sobrien      else
5643169699Skan        {
5644169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5645169699Skan          return "dec{l}\t%0";
5646169699Skan	}
564718334Speter
564890286Sobrien    default:
5649169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
565090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
565190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
565290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
565390286Sobrien          && (INTVAL (operands[2]) == 128
565490286Sobrien	      || (INTVAL (operands[2]) < 0
565590286Sobrien		  && INTVAL (operands[2]) != -128)))
565690286Sobrien        {
565790286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
565890286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
565990286Sobrien        }
566090286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
566190286Sobrien    }
566290286Sobrien}
566390286Sobrien  [(set (attr "type")
566490286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
566590286Sobrien	(const_string "incdec")
566690286Sobrien	(const_string "alu")))
566790286Sobrien   (set_attr "mode" "SI")])
566890286Sobrien
566990286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
567090286Sobrien(define_insn "*addsi_3_zext"
5671169699Skan  [(set (reg FLAGS_REG)
567290286Sobrien	(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
567390286Sobrien		 (match_operand:SI 1 "nonimmediate_operand" "%0")))
567490286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
567590286Sobrien	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
567690286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCZmode)
567790286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
567890286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
567990286Sobrien      ought but a memory context.  */
568090286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
568190286Sobrien{
568290286Sobrien  switch (get_attr_type (insn))
568390286Sobrien    {
568490286Sobrien    case TYPE_INCDEC:
568590286Sobrien      if (operands[2] == const1_rtx)
568690286Sobrien        return "inc{l}\t%k0";
568718334Speter      else
5688169699Skan        {
5689169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5690169699Skan          return "dec{l}\t%k0";
5691169699Skan	}
569290286Sobrien
569390286Sobrien    default:
569490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
569590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
569690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
569790286Sobrien          && (INTVAL (operands[2]) == 128
569890286Sobrien	      || (INTVAL (operands[2]) < 0
569990286Sobrien		  && INTVAL (operands[2]) != -128)))
570090286Sobrien        {
570190286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
570290286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
570390286Sobrien        }
570490286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
570518334Speter    }
570690286Sobrien}
570790286Sobrien  [(set (attr "type")
570890286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
570990286Sobrien	(const_string "incdec")
571090286Sobrien	(const_string "alu")))
571190286Sobrien   (set_attr "mode" "SI")])
571218334Speter
5713132727Skan; For comparisons against 1, -1 and 128, we may generate better code
571490286Sobrien; by converting cmp to add, inc or dec as done by peephole2.  This pattern
571590286Sobrien; is matched then.  We can't accept general immediate, because for
571690286Sobrien; case of overflows,  the result is messed up.
571790286Sobrien; This pattern also don't hold of 0x80000000, since the value overflows
571890286Sobrien; when negated.
571990286Sobrien; Also carry flag is reversed compared to cmp, so this conversion is valid
572090286Sobrien; only for comparisons not depending on it.
572190286Sobrien(define_insn "*addsi_4"
5722169699Skan  [(set (reg FLAGS_REG)
572390286Sobrien	(compare (match_operand:SI 1 "nonimmediate_operand" "0")
572490286Sobrien		 (match_operand:SI 2 "const_int_operand" "n")))
572590286Sobrien   (clobber (match_scratch:SI 0 "=rm"))]
572690286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
572790286Sobrien   && (INTVAL (operands[2]) & 0xffffffff) != 0x80000000"
572890286Sobrien{
572990286Sobrien  switch (get_attr_type (insn))
573018334Speter    {
573190286Sobrien    case TYPE_INCDEC:
573290286Sobrien      if (operands[2] == constm1_rtx)
573390286Sobrien        return "inc{l}\t%0";
573490286Sobrien      else
5735169699Skan        {
5736169699Skan	  gcc_assert (operands[2] == const1_rtx);
5737169699Skan          return "dec{l}\t%0";
5738169699Skan	}
573918334Speter
574090286Sobrien    default:
5741169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
574290286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
574390286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
574490286Sobrien      if ((INTVAL (operands[2]) == -128
574590286Sobrien	   || (INTVAL (operands[2]) > 0
574690286Sobrien	       && INTVAL (operands[2]) != 128)))
574790286Sobrien	return "sub{l}\t{%2, %0|%0, %2}";
574890286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
574990286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
575018334Speter    }
575190286Sobrien}
575290286Sobrien  [(set (attr "type")
575390286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
575490286Sobrien	(const_string "incdec")
575590286Sobrien	(const_string "alu")))
575690286Sobrien   (set_attr "mode" "SI")])
575718334Speter
575890286Sobrien(define_insn "*addsi_5"
5759169699Skan  [(set (reg FLAGS_REG)
576090286Sobrien	(compare
576190286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
576290286Sobrien		   (match_operand:SI 2 "general_operand" "rmni"))
576390286Sobrien	  (const_int 0)))			
576490286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
576590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
576690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
576790286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
576890286Sobrien      ought but a memory context.  */
576990286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
577090286Sobrien{
577190286Sobrien  switch (get_attr_type (insn))
577218334Speter    {
577390286Sobrien    case TYPE_INCDEC:
5774169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
577590286Sobrien      if (operands[2] == const1_rtx)
577690286Sobrien        return "inc{l}\t%0";
577790286Sobrien      else
5778169699Skan        {
5779169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5780169699Skan          return "dec{l}\t%0";
5781169699Skan	}
578290286Sobrien
578390286Sobrien    default:
5784169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
578590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
578690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
578790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
578890286Sobrien          && (INTVAL (operands[2]) == 128
578990286Sobrien	      || (INTVAL (operands[2]) < 0
579090286Sobrien		  && INTVAL (operands[2]) != -128)))
579190286Sobrien        {
579290286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
579390286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
579490286Sobrien        }
579590286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
579618334Speter    }
579790286Sobrien}
579890286Sobrien  [(set (attr "type")
579990286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
580090286Sobrien	(const_string "incdec")
580190286Sobrien	(const_string "alu")))
580290286Sobrien   (set_attr "mode" "SI")])
580318334Speter
580490286Sobrien(define_expand "addhi3"
580590286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
580690286Sobrien		   (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
580790286Sobrien			    (match_operand:HI 2 "general_operand" "")))
5808169699Skan	      (clobber (reg:CC FLAGS_REG))])]
580990286Sobrien  "TARGET_HIMODE_MATH"
581090286Sobrien  "ix86_expand_binary_operator (PLUS, HImode, operands); DONE;")
581118334Speter
581290286Sobrien;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah
581390286Sobrien;; type optimizations enabled by define-splits.  This is not important
581490286Sobrien;; for PII, and in fact harmful because of partial register stalls.
581518334Speter
581690286Sobrien(define_insn "*addhi_1_lea"
581790286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
581890286Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
5819169699Skan		 (match_operand:HI 2 "general_operand" "ri,rm,lni")))
5820169699Skan   (clobber (reg:CC FLAGS_REG))]
582190286Sobrien  "!TARGET_PARTIAL_REG_STALL
582290286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
582390286Sobrien{
582490286Sobrien  switch (get_attr_type (insn))
582590286Sobrien    {
582690286Sobrien    case TYPE_LEA:
582790286Sobrien      return "#";
582890286Sobrien    case TYPE_INCDEC:
582990286Sobrien      if (operands[2] == const1_rtx)
583090286Sobrien	return "inc{w}\t%0";
5831169699Skan      else
5832169699Skan	{
5833169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5834169699Skan	  return "dec{w}\t%0";
5835169699Skan	}
583618334Speter
583790286Sobrien    default:
583890286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
583990286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
584090286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
584190286Sobrien          && (INTVAL (operands[2]) == 128
584290286Sobrien	      || (INTVAL (operands[2]) < 0
584390286Sobrien		  && INTVAL (operands[2]) != -128)))
584490286Sobrien	{
584590286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
584690286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
584790286Sobrien	}
584890286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
584990286Sobrien    }
585090286Sobrien}
585190286Sobrien  [(set (attr "type")
585290286Sobrien     (if_then_else (eq_attr "alternative" "2")
585390286Sobrien	(const_string "lea")
585490286Sobrien	(if_then_else (match_operand:HI 2 "incdec_operand" "")
585590286Sobrien	   (const_string "incdec")
585690286Sobrien	   (const_string "alu"))))
585790286Sobrien   (set_attr "mode" "HI,HI,SI")])
585850650Sobrien
585990286Sobrien(define_insn "*addhi_1"
586090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
586190286Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
586290286Sobrien		 (match_operand:HI 2 "general_operand" "ri,rm")))
5863169699Skan   (clobber (reg:CC FLAGS_REG))]
586490286Sobrien  "TARGET_PARTIAL_REG_STALL
586590286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
586618334Speter{
586790286Sobrien  switch (get_attr_type (insn))
586818334Speter    {
586990286Sobrien    case TYPE_INCDEC:
587090286Sobrien      if (operands[2] == const1_rtx)
587190286Sobrien	return "inc{w}\t%0";
5872169699Skan      else
5873169699Skan        {
5874169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5875169699Skan	  return "dec{w}\t%0";
5876169699Skan	}
587718334Speter
587890286Sobrien    default:
587990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
588090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
588190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
588290286Sobrien          && (INTVAL (operands[2]) == 128
588390286Sobrien	      || (INTVAL (operands[2]) < 0
588490286Sobrien		  && INTVAL (operands[2]) != -128)))
588518334Speter	{
588690286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
588790286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
588818334Speter	}
588990286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
589090286Sobrien    }
589190286Sobrien}
589290286Sobrien  [(set (attr "type")
589390286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
589490286Sobrien	(const_string "incdec")
589590286Sobrien	(const_string "alu")))
589690286Sobrien   (set_attr "mode" "HI")])
589718334Speter
589890286Sobrien(define_insn "*addhi_2"
5899169699Skan  [(set (reg FLAGS_REG)
590090286Sobrien	(compare
590190286Sobrien	  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
590290286Sobrien		   (match_operand:HI 2 "general_operand" "rmni,rni"))
590390286Sobrien	  (const_int 0)))			
590490286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
590590286Sobrien	(plus:HI (match_dup 1) (match_dup 2)))]
590690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
590790286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
590890286Sobrien{
590990286Sobrien  switch (get_attr_type (insn))
591090286Sobrien    {
591190286Sobrien    case TYPE_INCDEC:
591290286Sobrien      if (operands[2] == const1_rtx)
591390286Sobrien	return "inc{w}\t%0";
5914169699Skan      else
5915169699Skan        {
5916169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5917169699Skan	  return "dec{w}\t%0";
5918169699Skan	}
591990286Sobrien
592090286Sobrien    default:
592190286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
592290286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
592390286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
592490286Sobrien          && (INTVAL (operands[2]) == 128
592590286Sobrien	      || (INTVAL (operands[2]) < 0
592690286Sobrien		  && INTVAL (operands[2]) != -128)))
592718334Speter	{
592890286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
592990286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
593018334Speter	}
593190286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
593218334Speter    }
593390286Sobrien}
593490286Sobrien  [(set (attr "type")
593590286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
593690286Sobrien	(const_string "incdec")
593790286Sobrien	(const_string "alu")))
593890286Sobrien   (set_attr "mode" "HI")])
593918334Speter
594090286Sobrien(define_insn "*addhi_3"
5941169699Skan  [(set (reg FLAGS_REG)
594290286Sobrien	(compare (neg:HI (match_operand:HI 2 "general_operand" "rmni"))
594390286Sobrien		 (match_operand:HI 1 "nonimmediate_operand" "%0")))
594490286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
594590286Sobrien  "ix86_match_ccmode (insn, CCZmode)
594690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
594790286Sobrien{
594890286Sobrien  switch (get_attr_type (insn))
594990286Sobrien    {
595090286Sobrien    case TYPE_INCDEC:
595190286Sobrien      if (operands[2] == const1_rtx)
595290286Sobrien	return "inc{w}\t%0";
5953169699Skan      else
5954169699Skan        {
5955169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5956169699Skan	  return "dec{w}\t%0";
5957169699Skan	}
595850650Sobrien
595990286Sobrien    default:
596090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
596190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
596290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
596390286Sobrien          && (INTVAL (operands[2]) == 128
596490286Sobrien	      || (INTVAL (operands[2]) < 0
596590286Sobrien		  && INTVAL (operands[2]) != -128)))
596690286Sobrien	{
596790286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
596890286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
596990286Sobrien	}
597090286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
597190286Sobrien    }
597290286Sobrien}
597390286Sobrien  [(set (attr "type")
597490286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
597590286Sobrien	(const_string "incdec")
597690286Sobrien	(const_string "alu")))
597790286Sobrien   (set_attr "mode" "HI")])
597818334Speter
5979169699Skan; See comments above addsi_4 for details.
598090286Sobrien(define_insn "*addhi_4"
5981169699Skan  [(set (reg FLAGS_REG)
598290286Sobrien	(compare (match_operand:HI 1 "nonimmediate_operand" "0")
598390286Sobrien		 (match_operand:HI 2 "const_int_operand" "n")))
598490286Sobrien   (clobber (match_scratch:HI 0 "=rm"))]
598590286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
598690286Sobrien   && (INTVAL (operands[2]) & 0xffff) != 0x8000"
598790286Sobrien{
598890286Sobrien  switch (get_attr_type (insn))
598990286Sobrien    {
599090286Sobrien    case TYPE_INCDEC:
5991117404Skan      if (operands[2] == constm1_rtx)
599290286Sobrien        return "inc{w}\t%0";
599390286Sobrien      else
5994169699Skan	{
5995169699Skan	  gcc_assert (operands[2] == const1_rtx);
5996169699Skan          return "dec{w}\t%0";
5997169699Skan	}
599818334Speter
599990286Sobrien    default:
6000169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
600190286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
600290286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
600390286Sobrien      if ((INTVAL (operands[2]) == -128
600490286Sobrien	   || (INTVAL (operands[2]) > 0
600590286Sobrien	       && INTVAL (operands[2]) != 128)))
600690286Sobrien	return "sub{w}\t{%2, %0|%0, %2}";
600790286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
600890286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
600950650Sobrien    }
601090286Sobrien}
601190286Sobrien  [(set (attr "type")
601290286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
601390286Sobrien	(const_string "incdec")
601490286Sobrien	(const_string "alu")))
601590286Sobrien   (set_attr "mode" "SI")])
601650650Sobrien
601718334Speter
601890286Sobrien(define_insn "*addhi_5"
6019169699Skan  [(set (reg FLAGS_REG)
602090286Sobrien	(compare
602190286Sobrien	  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
602290286Sobrien		   (match_operand:HI 2 "general_operand" "rmni"))
602390286Sobrien	  (const_int 0)))			
602490286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
602590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
602690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
602750650Sobrien{
602890286Sobrien  switch (get_attr_type (insn))
602950650Sobrien    {
603090286Sobrien    case TYPE_INCDEC:
603190286Sobrien      if (operands[2] == const1_rtx)
603290286Sobrien	return "inc{w}\t%0";
6033169699Skan      else
6034169699Skan	{
6035169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6036169699Skan	  return "dec{w}\t%0";
6037169699Skan	}
603850650Sobrien
603990286Sobrien    default:
604090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
604190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
604290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
604390286Sobrien          && (INTVAL (operands[2]) == 128
604490286Sobrien	      || (INTVAL (operands[2]) < 0
604590286Sobrien		  && INTVAL (operands[2]) != -128)))
604690286Sobrien	{
604790286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
604890286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
604990286Sobrien	}
605090286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
605150650Sobrien    }
605290286Sobrien}
605390286Sobrien  [(set (attr "type")
605490286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
605590286Sobrien	(const_string "incdec")
605690286Sobrien	(const_string "alu")))
605790286Sobrien   (set_attr "mode" "HI")])
605850650Sobrien
605990286Sobrien(define_expand "addqi3"
606090286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
606190286Sobrien		   (plus:QI (match_operand:QI 1 "nonimmediate_operand" "")
606290286Sobrien			    (match_operand:QI 2 "general_operand" "")))
6063169699Skan	      (clobber (reg:CC FLAGS_REG))])]
606490286Sobrien  "TARGET_QIMODE_MATH"
606590286Sobrien  "ix86_expand_binary_operator (PLUS, QImode, operands); DONE;")
606650650Sobrien
606790286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
606890286Sobrien(define_insn "*addqi_1_lea"
606990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r")
607090286Sobrien	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r")
6071169699Skan		 (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln")))
6072169699Skan   (clobber (reg:CC FLAGS_REG))]
607390286Sobrien  "!TARGET_PARTIAL_REG_STALL
607490286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
607590286Sobrien{
607690286Sobrien  int widen = (which_alternative == 2);
607790286Sobrien  switch (get_attr_type (insn))
607890286Sobrien    {
607990286Sobrien    case TYPE_LEA:
608090286Sobrien      return "#";
608190286Sobrien    case TYPE_INCDEC:
608290286Sobrien      if (operands[2] == const1_rtx)
608390286Sobrien	return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
6084169699Skan      else
6085169699Skan	{
6086169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6087169699Skan	  return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
6088169699Skan	}
608918334Speter
609090286Sobrien    default:
609190286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
609290286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
609390286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
609490286Sobrien          && (INTVAL (operands[2]) == 128
609590286Sobrien	      || (INTVAL (operands[2]) < 0
609690286Sobrien		  && INTVAL (operands[2]) != -128)))
609790286Sobrien	{
609890286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
609990286Sobrien	  if (widen)
610090286Sobrien	    return "sub{l}\t{%2, %k0|%k0, %2}";
610190286Sobrien	  else
610290286Sobrien	    return "sub{b}\t{%2, %0|%0, %2}";
610390286Sobrien	}
610490286Sobrien      if (widen)
610590286Sobrien        return "add{l}\t{%k2, %k0|%k0, %k2}";
610690286Sobrien      else
610790286Sobrien        return "add{b}\t{%2, %0|%0, %2}";
610890286Sobrien    }
610990286Sobrien}
611090286Sobrien  [(set (attr "type")
611190286Sobrien     (if_then_else (eq_attr "alternative" "3")
611290286Sobrien	(const_string "lea")
611390286Sobrien	(if_then_else (match_operand:QI 2 "incdec_operand" "")
611490286Sobrien	   (const_string "incdec")
611590286Sobrien	   (const_string "alu"))))
611690286Sobrien   (set_attr "mode" "QI,QI,SI,SI")])
611750650Sobrien
611890286Sobrien(define_insn "*addqi_1"
611990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
612090286Sobrien	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
612190286Sobrien		 (match_operand:QI 2 "general_operand" "qn,qmn,rn")))
6122169699Skan   (clobber (reg:CC FLAGS_REG))]
612390286Sobrien  "TARGET_PARTIAL_REG_STALL
612490286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
612518334Speter{
612690286Sobrien  int widen = (which_alternative == 2);
612790286Sobrien  switch (get_attr_type (insn))
612852296Sobrien    {
612990286Sobrien    case TYPE_INCDEC:
613090286Sobrien      if (operands[2] == const1_rtx)
613190286Sobrien	return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
6132169699Skan      else
6133169699Skan	{
6134169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6135169699Skan	  return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
6136169699Skan	}
613752296Sobrien
613890286Sobrien    default:
613990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
614090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
614190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
614290286Sobrien          && (INTVAL (operands[2]) == 128
614390286Sobrien	      || (INTVAL (operands[2]) < 0
614490286Sobrien		  && INTVAL (operands[2]) != -128)))
614590286Sobrien	{
614690286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
614790286Sobrien	  if (widen)
614890286Sobrien	    return "sub{l}\t{%2, %k0|%k0, %2}";
614990286Sobrien	  else
615090286Sobrien	    return "sub{b}\t{%2, %0|%0, %2}";
615190286Sobrien	}
615290286Sobrien      if (widen)
615390286Sobrien        return "add{l}\t{%k2, %k0|%k0, %k2}";
615490286Sobrien      else
615590286Sobrien        return "add{b}\t{%2, %0|%0, %2}";
615652296Sobrien    }
615790286Sobrien}
615890286Sobrien  [(set (attr "type")
615990286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
616090286Sobrien	(const_string "incdec")
616190286Sobrien	(const_string "alu")))
616290286Sobrien   (set_attr "mode" "QI,QI,SI")])
616352296Sobrien
6164117404Skan(define_insn "*addqi_1_slp"
6165117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
6166117404Skan	(plus:QI (match_dup 0)
6167117404Skan		 (match_operand:QI 1 "general_operand" "qn,qnm")))
6168169699Skan   (clobber (reg:CC FLAGS_REG))]
6169117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
6170117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
6171117404Skan{
6172117404Skan  switch (get_attr_type (insn))
6173117404Skan    {
6174117404Skan    case TYPE_INCDEC:
6175117404Skan      if (operands[1] == const1_rtx)
6176117404Skan	return "inc{b}\t%0";
6177169699Skan      else
6178169699Skan	{
6179169699Skan	  gcc_assert (operands[1] == constm1_rtx);
6180169699Skan	  return "dec{b}\t%0";
6181169699Skan	}
6182117404Skan
6183117404Skan    default:
6184117404Skan      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.  */
6185117404Skan      if (GET_CODE (operands[1]) == CONST_INT
6186117404Skan	  && INTVAL (operands[1]) < 0)
6187117404Skan	{
6188132727Skan	  operands[1] = GEN_INT (-INTVAL (operands[1]));
6189117404Skan	  return "sub{b}\t{%1, %0|%0, %1}";
6190117404Skan	}
6191117404Skan      return "add{b}\t{%1, %0|%0, %1}";
6192117404Skan    }
6193117404Skan}
6194117404Skan  [(set (attr "type")
6195146906Skan     (if_then_else (match_operand:QI 1 "incdec_operand" "")
6196117404Skan	(const_string "incdec")
6197117404Skan	(const_string "alu1")))
6198146906Skan   (set (attr "memory")
6199146906Skan     (if_then_else (match_operand 1 "memory_operand" "")
6200146906Skan        (const_string "load")
6201146906Skan        (const_string "none")))
6202117404Skan   (set_attr "mode" "QI")])
6203117404Skan
620490286Sobrien(define_insn "*addqi_2"
6205169699Skan  [(set (reg FLAGS_REG)
620690286Sobrien	(compare
620790286Sobrien	  (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
620890286Sobrien		   (match_operand:QI 2 "general_operand" "qmni,qni"))
620990286Sobrien	  (const_int 0)))
621090286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
621190286Sobrien	(plus:QI (match_dup 1) (match_dup 2)))]
621290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
621390286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
621490286Sobrien{
621590286Sobrien  switch (get_attr_type (insn))
621618334Speter    {
621790286Sobrien    case TYPE_INCDEC:
621890286Sobrien      if (operands[2] == const1_rtx)
621990286Sobrien	return "inc{b}\t%0";
6220169699Skan      else
6221169699Skan        {
6222169699Skan	  gcc_assert (operands[2] == constm1_rtx
6223169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6224169699Skan		          && INTVAL (operands[2]) == 255));
6225169699Skan	  return "dec{b}\t%0";
6226169699Skan	}
622718334Speter
622890286Sobrien    default:
622990286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
623090286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
623190286Sobrien          && INTVAL (operands[2]) < 0)
623290286Sobrien	{
623390286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
623490286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
623590286Sobrien	}
623690286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
623718334Speter    }
623890286Sobrien}
623990286Sobrien  [(set (attr "type")
624090286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
624190286Sobrien	(const_string "incdec")
624290286Sobrien	(const_string "alu")))
624390286Sobrien   (set_attr "mode" "QI")])
624418334Speter
624590286Sobrien(define_insn "*addqi_3"
6246169699Skan  [(set (reg FLAGS_REG)
624790286Sobrien	(compare (neg:QI (match_operand:QI 2 "general_operand" "qmni"))
624890286Sobrien		 (match_operand:QI 1 "nonimmediate_operand" "%0")))
624990286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
625090286Sobrien  "ix86_match_ccmode (insn, CCZmode)
625190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
625290286Sobrien{
625390286Sobrien  switch (get_attr_type (insn))
625450650Sobrien    {
625590286Sobrien    case TYPE_INCDEC:
625690286Sobrien      if (operands[2] == const1_rtx)
625790286Sobrien	return "inc{b}\t%0";
6258169699Skan      else
6259169699Skan        {
6260169699Skan	  gcc_assert (operands[2] == constm1_rtx
6261169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6262169699Skan			  && INTVAL (operands[2]) == 255));
6263169699Skan	  return "dec{b}\t%0";
6264169699Skan	}
626550650Sobrien
626690286Sobrien    default:
626790286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
626890286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
626990286Sobrien          && INTVAL (operands[2]) < 0)
627050650Sobrien	{
627190286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
627290286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
627390286Sobrien	}
627490286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
627590286Sobrien    }
627690286Sobrien}
627790286Sobrien  [(set (attr "type")
627890286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
627990286Sobrien	(const_string "incdec")
628090286Sobrien	(const_string "alu")))
628190286Sobrien   (set_attr "mode" "QI")])
628250650Sobrien
6283169699Skan; See comments above addsi_4 for details.
628490286Sobrien(define_insn "*addqi_4"
6285169699Skan  [(set (reg FLAGS_REG)
628690286Sobrien	(compare (match_operand:QI 1 "nonimmediate_operand" "0")
628790286Sobrien		 (match_operand:QI 2 "const_int_operand" "n")))
628890286Sobrien   (clobber (match_scratch:QI 0 "=qm"))]
628990286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
629090286Sobrien   && (INTVAL (operands[2]) & 0xff) != 0x80"
629190286Sobrien{
629290286Sobrien  switch (get_attr_type (insn))
629390286Sobrien    {
629490286Sobrien    case TYPE_INCDEC:
629590286Sobrien      if (operands[2] == constm1_rtx
629690286Sobrien	  || (GET_CODE (operands[2]) == CONST_INT
629790286Sobrien	      && INTVAL (operands[2]) == 255))
629890286Sobrien        return "inc{b}\t%0";
629990286Sobrien      else
6300169699Skan	{
6301169699Skan	  gcc_assert (operands[2] == const1_rtx);
6302169699Skan          return "dec{b}\t%0";
6303169699Skan	}
630450650Sobrien
630590286Sobrien    default:
6306169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
630790286Sobrien      if (INTVAL (operands[2]) < 0)
630890286Sobrien        {
630990286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
631090286Sobrien          return "add{b}\t{%2, %0|%0, %2}";
631190286Sobrien        }
631290286Sobrien      return "sub{b}\t{%2, %0|%0, %2}";
631350650Sobrien    }
631490286Sobrien}
631590286Sobrien  [(set (attr "type")
631690286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
631790286Sobrien	(const_string "incdec")
631890286Sobrien	(const_string "alu")))
631990286Sobrien   (set_attr "mode" "QI")])
632050650Sobrien
632118334Speter
632290286Sobrien(define_insn "*addqi_5"
6323169699Skan  [(set (reg FLAGS_REG)
632490286Sobrien	(compare
632590286Sobrien	  (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
632690286Sobrien		   (match_operand:QI 2 "general_operand" "qmni"))
632790286Sobrien	  (const_int 0)))
632890286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
632990286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
633090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
633190286Sobrien{
633290286Sobrien  switch (get_attr_type (insn))
633390286Sobrien    {
633490286Sobrien    case TYPE_INCDEC:
633590286Sobrien      if (operands[2] == const1_rtx)
633690286Sobrien	return "inc{b}\t%0";
6337169699Skan      else
6338169699Skan        {
6339169699Skan	  gcc_assert (operands[2] == constm1_rtx
6340169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6341169699Skan			  && INTVAL (operands[2]) == 255));
6342169699Skan	  return "dec{b}\t%0";
6343169699Skan	}
634418334Speter
634590286Sobrien    default:
634690286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
634790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
634890286Sobrien          && INTVAL (operands[2]) < 0)
634990286Sobrien	{
635090286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
635190286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
635290286Sobrien	}
635390286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
635490286Sobrien    }
635590286Sobrien}
635690286Sobrien  [(set (attr "type")
635790286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
635890286Sobrien	(const_string "incdec")
635990286Sobrien	(const_string "alu")))
636090286Sobrien   (set_attr "mode" "QI")])
636118334Speter
636250650Sobrien
636390286Sobrien(define_insn "addqi_ext_1"
636490286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
636590286Sobrien			 (const_int 8)
636690286Sobrien			 (const_int 8))
636790286Sobrien	(plus:SI
636890286Sobrien	  (zero_extract:SI
636990286Sobrien	    (match_operand 1 "ext_register_operand" "0")
637090286Sobrien	    (const_int 8)
637190286Sobrien	    (const_int 8))
637290286Sobrien	  (match_operand:QI 2 "general_operand" "Qmn")))
6373169699Skan   (clobber (reg:CC FLAGS_REG))]
637490286Sobrien  "!TARGET_64BIT"
637518334Speter{
637690286Sobrien  switch (get_attr_type (insn))
637752296Sobrien    {
637890286Sobrien    case TYPE_INCDEC:
637990286Sobrien      if (operands[2] == const1_rtx)
638090286Sobrien	return "inc{b}\t%h0";
6381169699Skan      else
6382169699Skan        {
6383169699Skan	  gcc_assert (operands[2] == constm1_rtx
6384169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6385169699Skan			  && INTVAL (operands[2]) == 255));
6386169699Skan          return "dec{b}\t%h0";
6387169699Skan	}
638852296Sobrien
638990286Sobrien    default:
639090286Sobrien      return "add{b}\t{%2, %h0|%h0, %2}";
639152296Sobrien    }
639290286Sobrien}
639390286Sobrien  [(set (attr "type")
639490286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
639590286Sobrien	(const_string "incdec")
639690286Sobrien	(const_string "alu")))
639790286Sobrien   (set_attr "mode" "QI")])
639818334Speter
639990286Sobrien(define_insn "*addqi_ext_1_rex64"
640090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
640190286Sobrien			 (const_int 8)
640290286Sobrien			 (const_int 8))
640390286Sobrien	(plus:SI
640490286Sobrien	  (zero_extract:SI
640590286Sobrien	    (match_operand 1 "ext_register_operand" "0")
640690286Sobrien	    (const_int 8)
640790286Sobrien	    (const_int 8))
640890286Sobrien	  (match_operand:QI 2 "nonmemory_operand" "Qn")))
6409169699Skan   (clobber (reg:CC FLAGS_REG))]
641090286Sobrien  "TARGET_64BIT"
641190286Sobrien{
641290286Sobrien  switch (get_attr_type (insn))
641390286Sobrien    {
641490286Sobrien    case TYPE_INCDEC:
641590286Sobrien      if (operands[2] == const1_rtx)
641690286Sobrien	return "inc{b}\t%h0";
6417169699Skan      else
6418169699Skan        {
6419169699Skan	  gcc_assert (operands[2] == constm1_rtx
6420169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6421169699Skan			  && INTVAL (operands[2]) == 255));
6422169699Skan          return "dec{b}\t%h0";
6423169699Skan        }
642418334Speter
642590286Sobrien    default:
642690286Sobrien      return "add{b}\t{%2, %h0|%h0, %2}";
642790286Sobrien    }
642890286Sobrien}
642990286Sobrien  [(set (attr "type")
643090286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
643190286Sobrien	(const_string "incdec")
643290286Sobrien	(const_string "alu")))
643390286Sobrien   (set_attr "mode" "QI")])
643418334Speter
643590286Sobrien(define_insn "*addqi_ext_2"
643690286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
643790286Sobrien			 (const_int 8)
643890286Sobrien			 (const_int 8))
643990286Sobrien	(plus:SI
644090286Sobrien	  (zero_extract:SI
644190286Sobrien	    (match_operand 1 "ext_register_operand" "%0")
644290286Sobrien	    (const_int 8)
644390286Sobrien	    (const_int 8))
644490286Sobrien	  (zero_extract:SI
644590286Sobrien	    (match_operand 2 "ext_register_operand" "Q")
644690286Sobrien	    (const_int 8)
644790286Sobrien	    (const_int 8))))
6448169699Skan   (clobber (reg:CC FLAGS_REG))]
644990286Sobrien  ""
645090286Sobrien  "add{b}\t{%h2, %h0|%h0, %h2}"
645190286Sobrien  [(set_attr "type" "alu")
645290286Sobrien   (set_attr "mode" "QI")])
645318334Speter
645418334Speter;; The patterns that match these are at the end of this file.
645518334Speter
645618334Speter(define_expand "addxf3"
645718334Speter  [(set (match_operand:XF 0 "register_operand" "")
645850650Sobrien	(plus:XF (match_operand:XF 1 "register_operand" "")
645950650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
646018334Speter  "TARGET_80387"
646118334Speter  "")
646218334Speter
646318334Speter(define_expand "adddf3"
646418334Speter  [(set (match_operand:DF 0 "register_operand" "")
646590286Sobrien	(plus:DF (match_operand:DF 1 "register_operand" "")
646618334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
646790286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
646818334Speter  "")
646918334Speter
647018334Speter(define_expand "addsf3"
647118334Speter  [(set (match_operand:SF 0 "register_operand" "")
647290286Sobrien	(plus:SF (match_operand:SF 1 "register_operand" "")
647318334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
647490286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
647518334Speter  "")
647618334Speter
647790286Sobrien;; Subtract instructions
647818334Speter
6479169699Skan;; %%% splits for subditi3
6480169699Skan
6481169699Skan(define_expand "subti3"
6482169699Skan  [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
6483169699Skan		   (minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
6484169699Skan			     (match_operand:TI 2 "x86_64_general_operand" "")))
6485169699Skan	      (clobber (reg:CC FLAGS_REG))])]
6486169699Skan  "TARGET_64BIT"
6487169699Skan  "ix86_expand_binary_operator (MINUS, TImode, operands); DONE;")
6488169699Skan
6489169699Skan(define_insn "*subti3_1"
6490169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
6491169699Skan	(minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0")
6492171835Skan		  (match_operand:TI 2 "x86_64_general_operand" "roe,re")))
6493169699Skan   (clobber (reg:CC FLAGS_REG))]
6494169699Skan  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)"
6495169699Skan  "#")
6496169699Skan
6497169699Skan(define_split
6498169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
6499169699Skan	(minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
6500171835Skan		  (match_operand:TI 2 "x86_64_general_operand" "")))
6501169699Skan   (clobber (reg:CC FLAGS_REG))]
6502169699Skan  "TARGET_64BIT && reload_completed"
6503169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
6504169699Skan	      (set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))])
6505169699Skan   (parallel [(set (match_dup 3)
6506169699Skan		   (minus:DI (match_dup 4)
6507169699Skan			     (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
6508169699Skan				      (match_dup 5))))
6509169699Skan	      (clobber (reg:CC FLAGS_REG))])]
6510169699Skan  "split_ti (operands+0, 1, operands+0, operands+3);
6511169699Skan   split_ti (operands+1, 1, operands+1, operands+4);
6512169699Skan   split_ti (operands+2, 1, operands+2, operands+5);")
6513169699Skan
651490286Sobrien;; %%% splits for subsidi3
651550650Sobrien
651690286Sobrien(define_expand "subdi3"
651790286Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
651890286Sobrien		   (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
651990286Sobrien			     (match_operand:DI 2 "x86_64_general_operand" "")))
6520169699Skan	      (clobber (reg:CC FLAGS_REG))])]
652118334Speter  ""
652290286Sobrien  "ix86_expand_binary_operator (MINUS, DImode, operands); DONE;")
652318334Speter
652490286Sobrien(define_insn "*subdi3_1"
652590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
652690286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
652790286Sobrien		  (match_operand:DI 2 "general_operand" "roiF,riF")))
6528169699Skan   (clobber (reg:CC FLAGS_REG))]
6529107605Sobrien  "!TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
653090286Sobrien  "#")
653118334Speter
653290286Sobrien(define_split
653390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
653490286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
653590286Sobrien		  (match_operand:DI 2 "general_operand" "")))
6536169699Skan   (clobber (reg:CC FLAGS_REG))]
653790286Sobrien  "!TARGET_64BIT && reload_completed"
6538169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
653990286Sobrien	      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
654090286Sobrien   (parallel [(set (match_dup 3)
654190286Sobrien		   (minus:SI (match_dup 4)
6542169699Skan			     (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
654390286Sobrien				      (match_dup 5))))
6544169699Skan	      (clobber (reg:CC FLAGS_REG))])]
654590286Sobrien  "split_di (operands+0, 1, operands+0, operands+3);
654690286Sobrien   split_di (operands+1, 1, operands+1, operands+4);
654790286Sobrien   split_di (operands+2, 1, operands+2, operands+5);")
654818334Speter
654990286Sobrien(define_insn "subdi3_carry_rex64"
655090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
655190286Sobrien	  (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
6552132727Skan	    (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
655390286Sobrien	       (match_operand:DI 2 "x86_64_general_operand" "re,rm"))))
6554169699Skan   (clobber (reg:CC FLAGS_REG))]
655590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
655690286Sobrien  "sbb{q}\t{%2, %0|%0, %2}"
655790286Sobrien  [(set_attr "type" "alu")
655890286Sobrien   (set_attr "pent_pair" "pu")
655990286Sobrien   (set_attr "mode" "DI")])
656018334Speter
656190286Sobrien(define_insn "*subdi_1_rex64"
656290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
656390286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
656490286Sobrien		  (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
6565169699Skan   (clobber (reg:CC FLAGS_REG))]
656690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
656790286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
656890286Sobrien  [(set_attr "type" "alu")
656990286Sobrien   (set_attr "mode" "DI")])
657018334Speter
657190286Sobrien(define_insn "*subdi_2_rex64"
6572169699Skan  [(set (reg FLAGS_REG)
657390286Sobrien	(compare
657490286Sobrien	  (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
657590286Sobrien		    (match_operand:DI 2 "x86_64_general_operand" "re,rm"))
657690286Sobrien	  (const_int 0)))
657790286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
657890286Sobrien	(minus:DI (match_dup 1) (match_dup 2)))]
657990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
658090286Sobrien   && ix86_binary_operator_ok (MINUS, DImode, operands)"
658190286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
658290286Sobrien  [(set_attr "type" "alu")
658390286Sobrien   (set_attr "mode" "DI")])
658452296Sobrien
658590286Sobrien(define_insn "*subdi_3_rex63"
6586169699Skan  [(set (reg FLAGS_REG)
658790286Sobrien	(compare (match_operand:DI 1 "nonimmediate_operand" "0,0")
658890286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
658990286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
659090286Sobrien	(minus:DI (match_dup 1) (match_dup 2)))]
659190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
659290286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
659390286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
659490286Sobrien  [(set_attr "type" "alu")
659590286Sobrien   (set_attr "mode" "DI")])
659618334Speter
6597132727Skan(define_insn "subqi3_carry"
6598132727Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
6599132727Skan	  (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
6600132727Skan	    (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
6601132727Skan	       (match_operand:QI 2 "general_operand" "qi,qm"))))
6602169699Skan   (clobber (reg:CC FLAGS_REG))]
6603132727Skan  "ix86_binary_operator_ok (MINUS, QImode, operands)"
6604132727Skan  "sbb{b}\t{%2, %0|%0, %2}"
6605132727Skan  [(set_attr "type" "alu")
6606132727Skan   (set_attr "pent_pair" "pu")
6607132727Skan   (set_attr "mode" "QI")])
660818334Speter
6609132727Skan(define_insn "subhi3_carry"
6610132727Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
6611132727Skan	  (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
6612132727Skan	    (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
6613132727Skan	       (match_operand:HI 2 "general_operand" "ri,rm"))))
6614169699Skan   (clobber (reg:CC FLAGS_REG))]
6615132727Skan  "ix86_binary_operator_ok (MINUS, HImode, operands)"
6616132727Skan  "sbb{w}\t{%2, %0|%0, %2}"
6617132727Skan  [(set_attr "type" "alu")
6618132727Skan   (set_attr "pent_pair" "pu")
6619132727Skan   (set_attr "mode" "HI")])
6620132727Skan
662190286Sobrien(define_insn "subsi3_carry"
662290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
662390286Sobrien	  (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6624132727Skan	    (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
662590286Sobrien	       (match_operand:SI 2 "general_operand" "ri,rm"))))
6626169699Skan   (clobber (reg:CC FLAGS_REG))]
662790286Sobrien  "ix86_binary_operator_ok (MINUS, SImode, operands)"
662890286Sobrien  "sbb{l}\t{%2, %0|%0, %2}"
662990286Sobrien  [(set_attr "type" "alu")
663090286Sobrien   (set_attr "pent_pair" "pu")
663190286Sobrien   (set_attr "mode" "SI")])
663218334Speter
663390286Sobrien(define_insn "subsi3_carry_zext"
663490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm,r")
663590286Sobrien	  (zero_extend:DI
663690286Sobrien	    (minus:SI (match_operand:SI 1 "register_operand" "0,0")
6637132727Skan	      (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
663890286Sobrien		 (match_operand:SI 2 "general_operand" "ri,rm")))))
6639169699Skan   (clobber (reg:CC FLAGS_REG))]
664090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
664190286Sobrien  "sbb{l}\t{%2, %k0|%k0, %2}"
664290286Sobrien  [(set_attr "type" "alu")
664390286Sobrien   (set_attr "pent_pair" "pu")
664490286Sobrien   (set_attr "mode" "SI")])
664518334Speter
664650650Sobrien(define_expand "subsi3"
664790286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
664890286Sobrien		   (minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
664990286Sobrien			     (match_operand:SI 2 "general_operand" "")))
6650169699Skan	      (clobber (reg:CC FLAGS_REG))])]
665150650Sobrien  ""
665290286Sobrien  "ix86_expand_binary_operator (MINUS, SImode, operands); DONE;")
665350650Sobrien
665490286Sobrien(define_insn "*subsi_1"
665550650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
665650650Sobrien	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
665790286Sobrien		  (match_operand:SI 2 "general_operand" "ri,rm")))
6658169699Skan   (clobber (reg:CC FLAGS_REG))]
665950650Sobrien  "ix86_binary_operator_ok (MINUS, SImode, operands)"
666090286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
666190286Sobrien  [(set_attr "type" "alu")
666290286Sobrien   (set_attr "mode" "SI")])
666318334Speter
666490286Sobrien(define_insn "*subsi_1_zext"
666590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
666690286Sobrien	(zero_extend:DI
666790286Sobrien	  (minus:SI (match_operand:SI 1 "register_operand" "0")
666890286Sobrien		    (match_operand:SI 2 "general_operand" "rim"))))
6669169699Skan   (clobber (reg:CC FLAGS_REG))]
667090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
667190286Sobrien  "sub{l}\t{%2, %k0|%k0, %2}"
667290286Sobrien  [(set_attr "type" "alu")
667390286Sobrien   (set_attr "mode" "SI")])
667490286Sobrien
667590286Sobrien(define_insn "*subsi_2"
6676169699Skan  [(set (reg FLAGS_REG)
667790286Sobrien	(compare
667890286Sobrien	  (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
667990286Sobrien		    (match_operand:SI 2 "general_operand" "ri,rm"))
668090286Sobrien	  (const_int 0)))
668190286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
668290286Sobrien	(minus:SI (match_dup 1) (match_dup 2)))]
668390286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
668490286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
668590286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
668690286Sobrien  [(set_attr "type" "alu")
668790286Sobrien   (set_attr "mode" "SI")])
668890286Sobrien
668990286Sobrien(define_insn "*subsi_2_zext"
6690169699Skan  [(set (reg FLAGS_REG)
669190286Sobrien	(compare
669290286Sobrien	  (minus:SI (match_operand:SI 1 "register_operand" "0")
669390286Sobrien		    (match_operand:SI 2 "general_operand" "rim"))
669490286Sobrien	  (const_int 0)))
669590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
669690286Sobrien	(zero_extend:DI
669790286Sobrien	  (minus:SI (match_dup 1)
669890286Sobrien		    (match_dup 2))))]
669990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
670090286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
670190286Sobrien  "sub{l}\t{%2, %k0|%k0, %2}"
670290286Sobrien  [(set_attr "type" "alu")
670390286Sobrien   (set_attr "mode" "SI")])
670490286Sobrien
670590286Sobrien(define_insn "*subsi_3"
6706169699Skan  [(set (reg FLAGS_REG)
670790286Sobrien	(compare (match_operand:SI 1 "nonimmediate_operand" "0,0")
670890286Sobrien		 (match_operand:SI 2 "general_operand" "ri,rm")))
670990286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
671090286Sobrien	(minus:SI (match_dup 1) (match_dup 2)))]
671190286Sobrien  "ix86_match_ccmode (insn, CCmode)
671290286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
671390286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
671490286Sobrien  [(set_attr "type" "alu")
671590286Sobrien   (set_attr "mode" "SI")])
671690286Sobrien
671790286Sobrien(define_insn "*subsi_3_zext"
6718169699Skan  [(set (reg FLAGS_REG)
6719132727Skan	(compare (match_operand:SI 1 "register_operand" "0")
672090286Sobrien		 (match_operand:SI 2 "general_operand" "rim")))
672190286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
672290286Sobrien	(zero_extend:DI
672390286Sobrien	  (minus:SI (match_dup 1)
672490286Sobrien		    (match_dup 2))))]
672590286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
672690286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
6727169699Skan  "sub{l}\t{%2, %1|%1, %2}"
672890286Sobrien  [(set_attr "type" "alu")
672990286Sobrien   (set_attr "mode" "DI")])
673090286Sobrien
673150650Sobrien(define_expand "subhi3"
673290286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
673390286Sobrien		   (minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
673490286Sobrien			     (match_operand:HI 2 "general_operand" "")))
6735169699Skan	      (clobber (reg:CC FLAGS_REG))])]
673690286Sobrien  "TARGET_HIMODE_MATH"
673790286Sobrien  "ix86_expand_binary_operator (MINUS, HImode, operands); DONE;")
673850650Sobrien
673990286Sobrien(define_insn "*subhi_1"
674050650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
674150650Sobrien	(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
674290286Sobrien		  (match_operand:HI 2 "general_operand" "ri,rm")))
6743169699Skan   (clobber (reg:CC FLAGS_REG))]
674450650Sobrien  "ix86_binary_operator_ok (MINUS, HImode, operands)"
674590286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
674690286Sobrien  [(set_attr "type" "alu")
674790286Sobrien   (set_attr "mode" "HI")])
674850650Sobrien
674990286Sobrien(define_insn "*subhi_2"
6750169699Skan  [(set (reg FLAGS_REG)
675190286Sobrien	(compare
675290286Sobrien	  (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
675390286Sobrien		    (match_operand:HI 2 "general_operand" "ri,rm"))
675490286Sobrien	  (const_int 0)))
675590286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
675690286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
675790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
675890286Sobrien   && ix86_binary_operator_ok (MINUS, HImode, operands)"
675990286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
676090286Sobrien  [(set_attr "type" "alu")
676190286Sobrien   (set_attr "mode" "HI")])
676290286Sobrien
676390286Sobrien(define_insn "*subhi_3"
6764169699Skan  [(set (reg FLAGS_REG)
676590286Sobrien	(compare (match_operand:HI 1 "nonimmediate_operand" "0,0")
676690286Sobrien		 (match_operand:HI 2 "general_operand" "ri,rm")))
676790286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
676890286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
676990286Sobrien  "ix86_match_ccmode (insn, CCmode)
677090286Sobrien   && ix86_binary_operator_ok (MINUS, HImode, operands)"
677190286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
677290286Sobrien  [(set_attr "type" "alu")
677390286Sobrien   (set_attr "mode" "HI")])
677490286Sobrien
677550650Sobrien(define_expand "subqi3"
677690286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
677790286Sobrien		   (minus:QI (match_operand:QI 1 "nonimmediate_operand" "")
677890286Sobrien			     (match_operand:QI 2 "general_operand" "")))
6779169699Skan	      (clobber (reg:CC FLAGS_REG))])]
678090286Sobrien  "TARGET_QIMODE_MATH"
678190286Sobrien  "ix86_expand_binary_operator (MINUS, QImode, operands); DONE;")
678218334Speter
678390286Sobrien(define_insn "*subqi_1"
678450650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
678550650Sobrien	(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
678690286Sobrien		  (match_operand:QI 2 "general_operand" "qn,qmn")))
6787169699Skan   (clobber (reg:CC FLAGS_REG))]
678850650Sobrien  "ix86_binary_operator_ok (MINUS, QImode, operands)"
678990286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
679090286Sobrien  [(set_attr "type" "alu")
679190286Sobrien   (set_attr "mode" "QI")])
679218334Speter
6793117404Skan(define_insn "*subqi_1_slp"
6794117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
6795117404Skan	(minus:QI (match_dup 0)
6796117404Skan		  (match_operand:QI 1 "general_operand" "qn,qmn")))
6797169699Skan   (clobber (reg:CC FLAGS_REG))]
6798117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
6799117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
6800117404Skan  "sub{b}\t{%1, %0|%0, %1}"
6801117404Skan  [(set_attr "type" "alu1")
6802117404Skan   (set_attr "mode" "QI")])
6803117404Skan
680490286Sobrien(define_insn "*subqi_2"
6805169699Skan  [(set (reg FLAGS_REG)
680690286Sobrien	(compare
680790286Sobrien	  (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
680890286Sobrien		    (match_operand:QI 2 "general_operand" "qi,qm"))
680990286Sobrien	  (const_int 0)))
681090286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
681190286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
681290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
681390286Sobrien   && ix86_binary_operator_ok (MINUS, QImode, operands)"
681490286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
681590286Sobrien  [(set_attr "type" "alu")
681690286Sobrien   (set_attr "mode" "QI")])
681790286Sobrien
681890286Sobrien(define_insn "*subqi_3"
6819169699Skan  [(set (reg FLAGS_REG)
682090286Sobrien	(compare (match_operand:QI 1 "nonimmediate_operand" "0,0")
682190286Sobrien		 (match_operand:QI 2 "general_operand" "qi,qm")))
682290286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
682390286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
682490286Sobrien  "ix86_match_ccmode (insn, CCmode)
682590286Sobrien   && ix86_binary_operator_ok (MINUS, QImode, operands)"
682690286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
682790286Sobrien  [(set_attr "type" "alu")
682890286Sobrien   (set_attr "mode" "QI")])
682990286Sobrien
683018334Speter;; The patterns that match these are at the end of this file.
683118334Speter
683218334Speter(define_expand "subxf3"
683318334Speter  [(set (match_operand:XF 0 "register_operand" "")
683450650Sobrien	(minus:XF (match_operand:XF 1 "register_operand" "")
683550650Sobrien		  (match_operand:XF 2 "register_operand" "")))]
683618334Speter  "TARGET_80387"
683718334Speter  "")
683818334Speter
683918334Speter(define_expand "subdf3"
684018334Speter  [(set (match_operand:DF 0 "register_operand" "")
684190286Sobrien	(minus:DF (match_operand:DF 1 "register_operand" "")
684218334Speter		  (match_operand:DF 2 "nonimmediate_operand" "")))]
684390286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
684418334Speter  "")
684518334Speter
684618334Speter(define_expand "subsf3"
684718334Speter  [(set (match_operand:SF 0 "register_operand" "")
684890286Sobrien	(minus:SF (match_operand:SF 1 "register_operand" "")
684918334Speter		  (match_operand:SF 2 "nonimmediate_operand" "")))]
685090286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
685118334Speter  "")
685218334Speter
685390286Sobrien;; Multiply instructions
685418334Speter
685590286Sobrien(define_expand "muldi3"
685690286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
685790286Sobrien		   (mult:DI (match_operand:DI 1 "register_operand" "")
685890286Sobrien			    (match_operand:DI 2 "x86_64_general_operand" "")))
6859169699Skan	      (clobber (reg:CC FLAGS_REG))])]
686090286Sobrien  "TARGET_64BIT"
686190286Sobrien  "")
686218334Speter
686390286Sobrien(define_insn "*muldi3_1_rex64"
686490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6865132727Skan	(mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,rm,0")
686690286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "K,e,mr")))
6867169699Skan   (clobber (reg:CC FLAGS_REG))]
686890286Sobrien  "TARGET_64BIT
686990286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
687090286Sobrien  "@
687190286Sobrien   imul{q}\t{%2, %1, %0|%0, %1, %2}
687290286Sobrien   imul{q}\t{%2, %1, %0|%0, %1, %2}
687390286Sobrien   imul{q}\t{%2, %0|%0, %2}"
687490286Sobrien  [(set_attr "type" "imul")
687590286Sobrien   (set_attr "prefix_0f" "0,0,1")
6876132727Skan   (set (attr "athlon_decode")
6877132727Skan	(cond [(eq_attr "cpu" "athlon")
6878132727Skan		  (const_string "vector")
6879132727Skan	       (eq_attr "alternative" "1")
6880132727Skan		  (const_string "vector")
6881132727Skan	       (and (eq_attr "alternative" "2")
6882132727Skan		    (match_operand 1 "memory_operand" ""))
6883132727Skan		  (const_string "vector")]
6884132727Skan	      (const_string "direct")))
688590286Sobrien   (set_attr "mode" "DI")])
688618334Speter
688790286Sobrien(define_expand "mulsi3"
688890286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
688990286Sobrien		   (mult:SI (match_operand:SI 1 "register_operand" "")
689090286Sobrien			    (match_operand:SI 2 "general_operand" "")))
6891169699Skan	      (clobber (reg:CC FLAGS_REG))])]
689218334Speter  ""
689390286Sobrien  "")
689418334Speter
689590286Sobrien(define_insn "*mulsi3_1"
689690286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
6897132727Skan	(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
689890286Sobrien		 (match_operand:SI 2 "general_operand" "K,i,mr")))
6899169699Skan   (clobber (reg:CC FLAGS_REG))]
690090286Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
690190286Sobrien  "@
690290286Sobrien   imul{l}\t{%2, %1, %0|%0, %1, %2}
690390286Sobrien   imul{l}\t{%2, %1, %0|%0, %1, %2}
690490286Sobrien   imul{l}\t{%2, %0|%0, %2}"
690590286Sobrien  [(set_attr "type" "imul")
690690286Sobrien   (set_attr "prefix_0f" "0,0,1")
6907132727Skan   (set (attr "athlon_decode")
6908132727Skan	(cond [(eq_attr "cpu" "athlon")
6909132727Skan		  (const_string "vector")
6910132727Skan	       (eq_attr "alternative" "1")
6911132727Skan		  (const_string "vector")
6912132727Skan	       (and (eq_attr "alternative" "2")
6913132727Skan		    (match_operand 1 "memory_operand" ""))
6914132727Skan		  (const_string "vector")]
6915132727Skan	      (const_string "direct")))
691690286Sobrien   (set_attr "mode" "SI")])
691790286Sobrien
691890286Sobrien(define_insn "*mulsi3_1_zext"
691990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
692090286Sobrien	(zero_extend:DI
6921132727Skan	  (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
692290286Sobrien		   (match_operand:SI 2 "general_operand" "K,i,mr"))))
6923169699Skan   (clobber (reg:CC FLAGS_REG))]
692490286Sobrien  "TARGET_64BIT
692590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
692690286Sobrien  "@
692790286Sobrien   imul{l}\t{%2, %1, %k0|%k0, %1, %2}
692890286Sobrien   imul{l}\t{%2, %1, %k0|%k0, %1, %2}
692990286Sobrien   imul{l}\t{%2, %k0|%k0, %2}"
693090286Sobrien  [(set_attr "type" "imul")
693190286Sobrien   (set_attr "prefix_0f" "0,0,1")
6932132727Skan   (set (attr "athlon_decode")
6933132727Skan	(cond [(eq_attr "cpu" "athlon")
6934132727Skan		  (const_string "vector")
6935132727Skan	       (eq_attr "alternative" "1")
6936132727Skan		  (const_string "vector")
6937132727Skan	       (and (eq_attr "alternative" "2")
6938132727Skan		    (match_operand 1 "memory_operand" ""))
6939132727Skan		  (const_string "vector")]
6940132727Skan	      (const_string "direct")))
694190286Sobrien   (set_attr "mode" "SI")])
694290286Sobrien
694390286Sobrien(define_expand "mulhi3"
694490286Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
694590286Sobrien		   (mult:HI (match_operand:HI 1 "register_operand" "")
694690286Sobrien			    (match_operand:HI 2 "general_operand" "")))
6947169699Skan	      (clobber (reg:CC FLAGS_REG))])]
694890286Sobrien  "TARGET_HIMODE_MATH"
694990286Sobrien  "")
695090286Sobrien
695190286Sobrien(define_insn "*mulhi3_1"
695290286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
6953132727Skan	(mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rm,rm,0")
695490286Sobrien		 (match_operand:HI 2 "general_operand" "K,i,mr")))
6955169699Skan   (clobber (reg:CC FLAGS_REG))]
695690286Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
695790286Sobrien  "@
695890286Sobrien   imul{w}\t{%2, %1, %0|%0, %1, %2}
695990286Sobrien   imul{w}\t{%2, %1, %0|%0, %1, %2}
696090286Sobrien   imul{w}\t{%2, %0|%0, %2}"
696190286Sobrien  [(set_attr "type" "imul")
696290286Sobrien   (set_attr "prefix_0f" "0,0,1")
6963132727Skan   (set (attr "athlon_decode")
6964132727Skan	(cond [(eq_attr "cpu" "athlon")
6965132727Skan		  (const_string "vector")
6966132727Skan	       (eq_attr "alternative" "1,2")
6967132727Skan		  (const_string "vector")]
6968132727Skan	      (const_string "direct")))
696990286Sobrien   (set_attr "mode" "HI")])
697090286Sobrien
697196294Sobrien(define_expand "mulqi3"
697296294Sobrien  [(parallel [(set (match_operand:QI 0 "register_operand" "")
697396294Sobrien		   (mult:QI (match_operand:QI 1 "nonimmediate_operand" "")
697496294Sobrien			    (match_operand:QI 2 "register_operand" "")))
6975169699Skan	      (clobber (reg:CC FLAGS_REG))])]
697696294Sobrien  "TARGET_QIMODE_MATH"
697796294Sobrien  "")
697896294Sobrien
697996294Sobrien(define_insn "*mulqi3_1"
698090286Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
698196294Sobrien	(mult:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
698290286Sobrien		 (match_operand:QI 2 "nonimmediate_operand" "qm")))
6983169699Skan   (clobber (reg:CC FLAGS_REG))]
698496294Sobrien  "TARGET_QIMODE_MATH
698596294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
698690286Sobrien  "mul{b}\t%2"
698790286Sobrien  [(set_attr "type" "imul")
698890286Sobrien   (set_attr "length_immediate" "0")
6989132727Skan   (set (attr "athlon_decode")
6990132727Skan     (if_then_else (eq_attr "cpu" "athlon")
6991132727Skan        (const_string "vector")
6992132727Skan        (const_string "direct")))
699390286Sobrien   (set_attr "mode" "QI")])
699490286Sobrien
699596294Sobrien(define_expand "umulqihi3"
699696294Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
699796294Sobrien		   (mult:HI (zero_extend:HI
699896294Sobrien			      (match_operand:QI 1 "nonimmediate_operand" ""))
699996294Sobrien			    (zero_extend:HI
700096294Sobrien			      (match_operand:QI 2 "register_operand" ""))))
7001169699Skan	      (clobber (reg:CC FLAGS_REG))])]
700296294Sobrien  "TARGET_QIMODE_MATH"
700396294Sobrien  "")
700496294Sobrien
700596294Sobrien(define_insn "*umulqihi3_1"
700650650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
700796294Sobrien	(mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
700890286Sobrien		 (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
7009169699Skan   (clobber (reg:CC FLAGS_REG))]
701096294Sobrien  "TARGET_QIMODE_MATH
701196294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
701290286Sobrien  "mul{b}\t%2"
701390286Sobrien  [(set_attr "type" "imul")
701490286Sobrien   (set_attr "length_immediate" "0")
7015132727Skan   (set (attr "athlon_decode")
7016132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7017132727Skan        (const_string "vector")
7018132727Skan        (const_string "direct")))
701990286Sobrien   (set_attr "mode" "QI")])
702018334Speter
702196294Sobrien(define_expand "mulqihi3"
702296294Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
702396294Sobrien		   (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))
702496294Sobrien			    (sign_extend:HI (match_operand:QI 2 "register_operand" ""))))
7025169699Skan	      (clobber (reg:CC FLAGS_REG))])]
702696294Sobrien  "TARGET_QIMODE_MATH"
702796294Sobrien  "")
702896294Sobrien
702996294Sobrien(define_insn "*mulqihi3_insn"
703050650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
703196294Sobrien	(mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
703290286Sobrien		 (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
7033169699Skan   (clobber (reg:CC FLAGS_REG))]
703496294Sobrien  "TARGET_QIMODE_MATH
703596294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
703690286Sobrien  "imul{b}\t%2"
703790286Sobrien  [(set_attr "type" "imul")
703890286Sobrien   (set_attr "length_immediate" "0")
7039132727Skan   (set (attr "athlon_decode")
7040132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7041132727Skan        (const_string "vector")
7042132727Skan        (const_string "direct")))
704390286Sobrien   (set_attr "mode" "QI")])
704418334Speter
704596294Sobrien(define_expand "umulditi3"
704696294Sobrien  [(parallel [(set (match_operand:TI 0 "register_operand" "")
704796294Sobrien		   (mult:TI (zero_extend:TI
704896294Sobrien			      (match_operand:DI 1 "nonimmediate_operand" ""))
704996294Sobrien			    (zero_extend:TI
705096294Sobrien			      (match_operand:DI 2 "register_operand" ""))))
7051169699Skan	      (clobber (reg:CC FLAGS_REG))])]
705296294Sobrien  "TARGET_64BIT"
705396294Sobrien  "")
705496294Sobrien
705596294Sobrien(define_insn "*umulditi3_insn"
705690286Sobrien  [(set (match_operand:TI 0 "register_operand" "=A")
705796294Sobrien	(mult:TI (zero_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
705890286Sobrien		 (zero_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
7059169699Skan   (clobber (reg:CC FLAGS_REG))]
706096294Sobrien  "TARGET_64BIT
706196294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
706290286Sobrien  "mul{q}\t%2"
706390286Sobrien  [(set_attr "type" "imul")
706490286Sobrien   (set_attr "length_immediate" "0")
7065132727Skan   (set (attr "athlon_decode")
7066132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7067132727Skan        (const_string "vector")
7068132727Skan        (const_string "double")))
706990286Sobrien   (set_attr "mode" "DI")])
707090286Sobrien
707190286Sobrien;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers
707296294Sobrien(define_expand "umulsidi3"
707396294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
707496294Sobrien		   (mult:DI (zero_extend:DI
707596294Sobrien			      (match_operand:SI 1 "nonimmediate_operand" ""))
707696294Sobrien			    (zero_extend:DI
707796294Sobrien			      (match_operand:SI 2 "register_operand" ""))))
7078169699Skan	      (clobber (reg:CC FLAGS_REG))])]
707996294Sobrien  "!TARGET_64BIT"
708096294Sobrien  "")
708196294Sobrien
708296294Sobrien(define_insn "*umulsidi3_insn"
708318334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
708496294Sobrien	(mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
708590286Sobrien		 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
7086169699Skan   (clobber (reg:CC FLAGS_REG))]
708796294Sobrien  "!TARGET_64BIT
708896294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
708990286Sobrien  "mul{l}\t%2"
709090286Sobrien  [(set_attr "type" "imul")
709190286Sobrien   (set_attr "length_immediate" "0")
7092132727Skan   (set (attr "athlon_decode")
7093132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7094132727Skan        (const_string "vector")
7095132727Skan        (const_string "double")))
709690286Sobrien   (set_attr "mode" "SI")])
709718334Speter
709896294Sobrien(define_expand "mulditi3"
709996294Sobrien  [(parallel [(set (match_operand:TI 0 "register_operand" "")
710096294Sobrien		   (mult:TI (sign_extend:TI
710196294Sobrien			      (match_operand:DI 1 "nonimmediate_operand" ""))
710296294Sobrien			    (sign_extend:TI
710396294Sobrien			      (match_operand:DI 2 "register_operand" ""))))
7104169699Skan	      (clobber (reg:CC FLAGS_REG))])]
710596294Sobrien  "TARGET_64BIT"
710696294Sobrien  "")
710796294Sobrien
710896294Sobrien(define_insn "*mulditi3_insn"
710990286Sobrien  [(set (match_operand:TI 0 "register_operand" "=A")
711096294Sobrien	(mult:TI (sign_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
711190286Sobrien		 (sign_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
7112169699Skan   (clobber (reg:CC FLAGS_REG))]
711396294Sobrien  "TARGET_64BIT
711496294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
711590286Sobrien  "imul{q}\t%2"
711690286Sobrien  [(set_attr "type" "imul")
711790286Sobrien   (set_attr "length_immediate" "0")
7118132727Skan   (set (attr "athlon_decode")
7119132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7120132727Skan        (const_string "vector")
7121132727Skan        (const_string "double")))
712290286Sobrien   (set_attr "mode" "DI")])
712390286Sobrien
712496294Sobrien(define_expand "mulsidi3"
712596294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
712696294Sobrien		   (mult:DI (sign_extend:DI
712796294Sobrien			      (match_operand:SI 1 "nonimmediate_operand" ""))
712896294Sobrien			    (sign_extend:DI
712996294Sobrien			      (match_operand:SI 2 "register_operand" ""))))
7130169699Skan	      (clobber (reg:CC FLAGS_REG))])]
713196294Sobrien  "!TARGET_64BIT"
713296294Sobrien  "")
713396294Sobrien
713496294Sobrien(define_insn "*mulsidi3_insn"
713518334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
713696294Sobrien	(mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
713790286Sobrien		 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
7138169699Skan   (clobber (reg:CC FLAGS_REG))]
713996294Sobrien  "!TARGET_64BIT
714096294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
714190286Sobrien  "imul{l}\t%2"
714290286Sobrien  [(set_attr "type" "imul")
714390286Sobrien   (set_attr "length_immediate" "0")
7144132727Skan   (set (attr "athlon_decode")
7145132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7146132727Skan        (const_string "vector")
7147132727Skan        (const_string "double")))
714890286Sobrien   (set_attr "mode" "SI")])
714918334Speter
715096294Sobrien(define_expand "umuldi3_highpart"
715196294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
715296294Sobrien		   (truncate:DI
715396294Sobrien		     (lshiftrt:TI
715496294Sobrien		       (mult:TI (zero_extend:TI
715596294Sobrien				  (match_operand:DI 1 "nonimmediate_operand" ""))
715696294Sobrien				(zero_extend:TI
715796294Sobrien				  (match_operand:DI 2 "register_operand" "")))
715896294Sobrien		       (const_int 64))))
715996294Sobrien	      (clobber (match_scratch:DI 3 ""))
7160169699Skan	      (clobber (reg:CC FLAGS_REG))])]
716196294Sobrien  "TARGET_64BIT"
716296294Sobrien  "")
716396294Sobrien
716490286Sobrien(define_insn "*umuldi3_highpart_rex64"
716590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
716690286Sobrien	(truncate:DI
716790286Sobrien	  (lshiftrt:TI
716890286Sobrien	    (mult:TI (zero_extend:TI
716996294Sobrien		       (match_operand:DI 1 "nonimmediate_operand" "%a"))
717090286Sobrien		     (zero_extend:TI
717190286Sobrien		       (match_operand:DI 2 "nonimmediate_operand" "rm")))
717290286Sobrien	    (const_int 64))))
717396294Sobrien   (clobber (match_scratch:DI 3 "=1"))
7174169699Skan   (clobber (reg:CC FLAGS_REG))]
717596294Sobrien  "TARGET_64BIT
717696294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
717790286Sobrien  "mul{q}\t%2"
717890286Sobrien  [(set_attr "type" "imul")
717990286Sobrien   (set_attr "length_immediate" "0")
7180132727Skan   (set (attr "athlon_decode")
7181132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7182132727Skan        (const_string "vector")
7183132727Skan        (const_string "double")))
718490286Sobrien   (set_attr "mode" "DI")])
718590286Sobrien
718696294Sobrien(define_expand "umulsi3_highpart"
718796294Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
718896294Sobrien		   (truncate:SI
718996294Sobrien		     (lshiftrt:DI
719096294Sobrien		       (mult:DI (zero_extend:DI
719196294Sobrien				  (match_operand:SI 1 "nonimmediate_operand" ""))
719296294Sobrien				(zero_extend:DI
719396294Sobrien				  (match_operand:SI 2 "register_operand" "")))
719496294Sobrien		       (const_int 32))))
719596294Sobrien	      (clobber (match_scratch:SI 3 ""))
7196169699Skan	      (clobber (reg:CC FLAGS_REG))])]
719796294Sobrien  ""
719896294Sobrien  "")
719996294Sobrien
720096294Sobrien(define_insn "*umulsi3_highpart_insn"
720118334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
720290286Sobrien	(truncate:SI
720390286Sobrien	  (lshiftrt:DI
720490286Sobrien	    (mult:DI (zero_extend:DI
720596294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
720690286Sobrien		     (zero_extend:DI
720790286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
720890286Sobrien	    (const_int 32))))
720996294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7210169699Skan   (clobber (reg:CC FLAGS_REG))]
721196294Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
721290286Sobrien  "mul{l}\t%2"
721390286Sobrien  [(set_attr "type" "imul")
721490286Sobrien   (set_attr "length_immediate" "0")
7215132727Skan   (set (attr "athlon_decode")
7216132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7217132727Skan        (const_string "vector")
7218132727Skan        (const_string "double")))
721990286Sobrien   (set_attr "mode" "SI")])
722018334Speter
722190286Sobrien(define_insn "*umulsi3_highpart_zext"
722290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
722390286Sobrien	(zero_extend:DI (truncate:SI
722490286Sobrien	  (lshiftrt:DI
722590286Sobrien	    (mult:DI (zero_extend:DI
722696294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
722790286Sobrien		     (zero_extend:DI
722890286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
722990286Sobrien	    (const_int 32)))))
723096294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7231169699Skan   (clobber (reg:CC FLAGS_REG))]
723296294Sobrien  "TARGET_64BIT
723396294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
723490286Sobrien  "mul{l}\t%2"
723590286Sobrien  [(set_attr "type" "imul")
723690286Sobrien   (set_attr "length_immediate" "0")
7237132727Skan   (set (attr "athlon_decode")
7238132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7239132727Skan        (const_string "vector")
7240132727Skan        (const_string "double")))
724190286Sobrien   (set_attr "mode" "SI")])
724290286Sobrien
724396294Sobrien(define_expand "smuldi3_highpart"
724496294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "=d")
724596294Sobrien		   (truncate:DI
724696294Sobrien		     (lshiftrt:TI
724796294Sobrien		       (mult:TI (sign_extend:TI
724896294Sobrien				  (match_operand:DI 1 "nonimmediate_operand" ""))
724996294Sobrien				(sign_extend:TI
725096294Sobrien				  (match_operand:DI 2 "register_operand" "")))
725196294Sobrien		       (const_int 64))))
725296294Sobrien	      (clobber (match_scratch:DI 3 ""))
7253169699Skan	      (clobber (reg:CC FLAGS_REG))])]
725496294Sobrien  "TARGET_64BIT"
725596294Sobrien  "")
725696294Sobrien
725790286Sobrien(define_insn "*smuldi3_highpart_rex64"
725890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
725990286Sobrien	(truncate:DI
726090286Sobrien	  (lshiftrt:TI
726190286Sobrien	    (mult:TI (sign_extend:TI
726296294Sobrien		       (match_operand:DI 1 "nonimmediate_operand" "%a"))
726390286Sobrien		     (sign_extend:TI
726490286Sobrien		       (match_operand:DI 2 "nonimmediate_operand" "rm")))
726590286Sobrien	    (const_int 64))))
726696294Sobrien   (clobber (match_scratch:DI 3 "=1"))
7267169699Skan   (clobber (reg:CC FLAGS_REG))]
726896294Sobrien  "TARGET_64BIT
726996294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
727090286Sobrien  "imul{q}\t%2"
727190286Sobrien  [(set_attr "type" "imul")
7272132727Skan   (set (attr "athlon_decode")
7273132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7274132727Skan        (const_string "vector")
7275132727Skan        (const_string "double")))
727690286Sobrien   (set_attr "mode" "DI")])
727790286Sobrien
727896294Sobrien(define_expand "smulsi3_highpart"
727996294Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
728096294Sobrien		   (truncate:SI
728196294Sobrien		     (lshiftrt:DI
728296294Sobrien		       (mult:DI (sign_extend:DI
728396294Sobrien				  (match_operand:SI 1 "nonimmediate_operand" ""))
728496294Sobrien				(sign_extend:DI
728596294Sobrien				  (match_operand:SI 2 "register_operand" "")))
728696294Sobrien		       (const_int 32))))
728796294Sobrien	      (clobber (match_scratch:SI 3 ""))
7288169699Skan	      (clobber (reg:CC FLAGS_REG))])]
728996294Sobrien  ""
729096294Sobrien  "")
729196294Sobrien
729296294Sobrien(define_insn "*smulsi3_highpart_insn"
729318334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
729490286Sobrien	(truncate:SI
729590286Sobrien	  (lshiftrt:DI
729690286Sobrien	    (mult:DI (sign_extend:DI
729796294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
729890286Sobrien		     (sign_extend:DI
729990286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
730090286Sobrien	    (const_int 32))))
730196294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7302169699Skan   (clobber (reg:CC FLAGS_REG))]
730396294Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
730490286Sobrien  "imul{l}\t%2"
730590286Sobrien  [(set_attr "type" "imul")
7306132727Skan   (set (attr "athlon_decode")
7307132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7308132727Skan        (const_string "vector")
7309132727Skan        (const_string "double")))
731090286Sobrien   (set_attr "mode" "SI")])
731118334Speter
731290286Sobrien(define_insn "*smulsi3_highpart_zext"
731390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
731490286Sobrien	(zero_extend:DI (truncate:SI
731590286Sobrien	  (lshiftrt:DI
731690286Sobrien	    (mult:DI (sign_extend:DI
731796294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
731890286Sobrien		     (sign_extend:DI
731990286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
732090286Sobrien	    (const_int 32)))))
732196294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7322169699Skan   (clobber (reg:CC FLAGS_REG))]
732396294Sobrien  "TARGET_64BIT
732496294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
732590286Sobrien  "imul{l}\t%2"
732690286Sobrien  [(set_attr "type" "imul")
7327132727Skan   (set (attr "athlon_decode")
7328132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7329132727Skan        (const_string "vector")
7330132727Skan        (const_string "double")))
733190286Sobrien   (set_attr "mode" "SI")])
733290286Sobrien
733318334Speter;; The patterns that match these are at the end of this file.
733418334Speter
733518334Speter(define_expand "mulxf3"
733618334Speter  [(set (match_operand:XF 0 "register_operand" "")
733750650Sobrien	(mult:XF (match_operand:XF 1 "register_operand" "")
733850650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
733918334Speter  "TARGET_80387"
734018334Speter  "")
734118334Speter
734218334Speter(define_expand "muldf3"
734318334Speter  [(set (match_operand:DF 0 "register_operand" "")
734450650Sobrien	(mult:DF (match_operand:DF 1 "register_operand" "")
734518334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
734690286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
734718334Speter  "")
734818334Speter
734918334Speter(define_expand "mulsf3"
735018334Speter  [(set (match_operand:SF 0 "register_operand" "")
735150650Sobrien	(mult:SF (match_operand:SF 1 "register_operand" "")
735218334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
735390286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
735418334Speter  "")
735518334Speter
735690286Sobrien;; Divide instructions
735718334Speter
735818334Speter(define_insn "divqi3"
735950650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
736050650Sobrien	(div:QI (match_operand:HI 1 "register_operand" "0")
736190286Sobrien		(match_operand:QI 2 "nonimmediate_operand" "qm")))
7362169699Skan   (clobber (reg:CC FLAGS_REG))]
736390286Sobrien  "TARGET_QIMODE_MATH"
736490286Sobrien  "idiv{b}\t%2"
736590286Sobrien  [(set_attr "type" "idiv")
7366169699Skan   (set_attr "mode" "QI")])
736718334Speter
736818334Speter(define_insn "udivqi3"
736950650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
737050650Sobrien	(udiv:QI (match_operand:HI 1 "register_operand" "0")
737190286Sobrien		 (match_operand:QI 2 "nonimmediate_operand" "qm")))
7372169699Skan   (clobber (reg:CC FLAGS_REG))]
737390286Sobrien  "TARGET_QIMODE_MATH"
737490286Sobrien  "div{b}\t%2"
737590286Sobrien  [(set_attr "type" "idiv")
7376169699Skan   (set_attr "mode" "QI")])
737718334Speter
737818334Speter;; The patterns that match these are at the end of this file.
737918334Speter
738018334Speter(define_expand "divxf3"
738118334Speter  [(set (match_operand:XF 0 "register_operand" "")
738250650Sobrien	(div:XF (match_operand:XF 1 "register_operand" "")
738350650Sobrien		(match_operand:XF 2 "register_operand" "")))]
738418334Speter  "TARGET_80387"
738518334Speter  "")
738618334Speter
738718334Speter(define_expand "divdf3"
738818334Speter  [(set (match_operand:DF 0 "register_operand" "")
738950650Sobrien 	(div:DF (match_operand:DF 1 "register_operand" "")
739050650Sobrien 		(match_operand:DF 2 "nonimmediate_operand" "")))]
739190286Sobrien   "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
739250650Sobrien   "")
739350650Sobrien 
739418334Speter(define_expand "divsf3"
739518334Speter  [(set (match_operand:SF 0 "register_operand" "")
739650650Sobrien	(div:SF (match_operand:SF 1 "register_operand" "")
739718334Speter		(match_operand:SF 2 "nonimmediate_operand" "")))]
739890286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
739918334Speter  "")
740018334Speter
740118334Speter;; Remainder instructions.
740218334Speter
740390286Sobrien(define_expand "divmoddi4"
740490286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
740590286Sobrien		   (div:DI (match_operand:DI 1 "register_operand" "")
740690286Sobrien			   (match_operand:DI 2 "nonimmediate_operand" "")))
740790286Sobrien	      (set (match_operand:DI 3 "register_operand" "")
740890286Sobrien		   (mod:DI (match_dup 1) (match_dup 2)))
7409169699Skan	      (clobber (reg:CC FLAGS_REG))])]
741090286Sobrien  "TARGET_64BIT"
741190286Sobrien  "")
741290286Sobrien
741390286Sobrien;; Allow to come the parameter in eax or edx to avoid extra moves.
7414132727Skan;; Penalize eax case slightly because it results in worse scheduling
741590286Sobrien;; of code.
741690286Sobrien(define_insn "*divmoddi4_nocltd_rex64"
741790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=&a,?a")
741890286Sobrien	(div:DI (match_operand:DI 2 "register_operand" "1,0")
741990286Sobrien		(match_operand:DI 3 "nonimmediate_operand" "rm,rm")))
742090286Sobrien   (set (match_operand:DI 1 "register_operand" "=&d,&d")
742190286Sobrien	(mod:DI (match_dup 2) (match_dup 3)))
7422169699Skan   (clobber (reg:CC FLAGS_REG))]
742390286Sobrien  "TARGET_64BIT && !optimize_size && !TARGET_USE_CLTD"
742490286Sobrien  "#"
742590286Sobrien  [(set_attr "type" "multi")])
742690286Sobrien
742790286Sobrien(define_insn "*divmoddi4_cltd_rex64"
742890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
742990286Sobrien	(div:DI (match_operand:DI 2 "register_operand" "a")
743090286Sobrien		(match_operand:DI 3 "nonimmediate_operand" "rm")))
743190286Sobrien   (set (match_operand:DI 1 "register_operand" "=&d")
743290286Sobrien	(mod:DI (match_dup 2) (match_dup 3)))
7433169699Skan   (clobber (reg:CC FLAGS_REG))]
743490286Sobrien  "TARGET_64BIT && (optimize_size || TARGET_USE_CLTD)"
743590286Sobrien  "#"
743690286Sobrien  [(set_attr "type" "multi")])
743790286Sobrien
743890286Sobrien(define_insn "*divmoddi_noext_rex64"
743990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
744090286Sobrien	(div:DI (match_operand:DI 1 "register_operand" "0")
744190286Sobrien		(match_operand:DI 2 "nonimmediate_operand" "rm")))
744290286Sobrien   (set (match_operand:DI 3 "register_operand" "=d")
744390286Sobrien	(mod:DI (match_dup 1) (match_dup 2)))
744490286Sobrien   (use (match_operand:DI 4 "register_operand" "3"))
7445169699Skan   (clobber (reg:CC FLAGS_REG))]
744690286Sobrien  "TARGET_64BIT"
744790286Sobrien  "idiv{q}\t%2"
744890286Sobrien  [(set_attr "type" "idiv")
7449169699Skan   (set_attr "mode" "DI")])
745090286Sobrien
745190286Sobrien(define_split
745290286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
745390286Sobrien	(div:DI (match_operand:DI 1 "register_operand" "")
745490286Sobrien		(match_operand:DI 2 "nonimmediate_operand" "")))
745590286Sobrien   (set (match_operand:DI 3 "register_operand" "")
745690286Sobrien	(mod:DI (match_dup 1) (match_dup 2)))
7457169699Skan   (clobber (reg:CC FLAGS_REG))]
745890286Sobrien  "TARGET_64BIT && reload_completed"
745990286Sobrien  [(parallel [(set (match_dup 3)
746090286Sobrien		   (ashiftrt:DI (match_dup 4) (const_int 63)))
7461169699Skan	      (clobber (reg:CC FLAGS_REG))])
746290286Sobrien   (parallel [(set (match_dup 0)
746390286Sobrien	           (div:DI (reg:DI 0) (match_dup 2)))
746490286Sobrien	      (set (match_dup 3)
746590286Sobrien		   (mod:DI (reg:DI 0) (match_dup 2)))
746690286Sobrien	      (use (match_dup 3))
7467169699Skan	      (clobber (reg:CC FLAGS_REG))])]
746890286Sobrien{
7469117404Skan  /* Avoid use of cltd in favor of a mov+shift.  */
747090286Sobrien  if (!TARGET_USE_CLTD && !optimize_size)
747190286Sobrien    {
747290286Sobrien      if (true_regnum (operands[1]))
747390286Sobrien        emit_move_insn (operands[0], operands[1]);
747490286Sobrien      else
747590286Sobrien	emit_move_insn (operands[3], operands[1]);
747690286Sobrien      operands[4] = operands[3];
747790286Sobrien    }
747890286Sobrien  else
747990286Sobrien    {
7480169699Skan      gcc_assert (!true_regnum (operands[1]));
748190286Sobrien      operands[4] = operands[1];
748290286Sobrien    }
748390286Sobrien})
748490286Sobrien
748590286Sobrien
748690286Sobrien(define_expand "divmodsi4"
748790286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
748890286Sobrien		   (div:SI (match_operand:SI 1 "register_operand" "")
748990286Sobrien			   (match_operand:SI 2 "nonimmediate_operand" "")))
749090286Sobrien	      (set (match_operand:SI 3 "register_operand" "")
749190286Sobrien		   (mod:SI (match_dup 1) (match_dup 2)))
7492169699Skan	      (clobber (reg:CC FLAGS_REG))])]
749390286Sobrien  ""
749490286Sobrien  "")
749590286Sobrien
749690286Sobrien;; Allow to come the parameter in eax or edx to avoid extra moves.
7497132727Skan;; Penalize eax case slightly because it results in worse scheduling
749890286Sobrien;; of code.
749990286Sobrien(define_insn "*divmodsi4_nocltd"
750090286Sobrien  [(set (match_operand:SI 0 "register_operand" "=&a,?a")
750190286Sobrien	(div:SI (match_operand:SI 2 "register_operand" "1,0")
750290286Sobrien		(match_operand:SI 3 "nonimmediate_operand" "rm,rm")))
750390286Sobrien   (set (match_operand:SI 1 "register_operand" "=&d,&d")
750490286Sobrien	(mod:SI (match_dup 2) (match_dup 3)))
7505169699Skan   (clobber (reg:CC FLAGS_REG))]
750690286Sobrien  "!optimize_size && !TARGET_USE_CLTD"
750790286Sobrien  "#"
750890286Sobrien  [(set_attr "type" "multi")])
750990286Sobrien
751090286Sobrien(define_insn "*divmodsi4_cltd"
751118334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
751290286Sobrien	(div:SI (match_operand:SI 2 "register_operand" "a")
751390286Sobrien		(match_operand:SI 3 "nonimmediate_operand" "rm")))
751490286Sobrien   (set (match_operand:SI 1 "register_operand" "=&d")
751590286Sobrien	(mod:SI (match_dup 2) (match_dup 3)))
7516169699Skan   (clobber (reg:CC FLAGS_REG))]
751790286Sobrien  "optimize_size || TARGET_USE_CLTD"
751890286Sobrien  "#"
751990286Sobrien  [(set_attr "type" "multi")])
752090286Sobrien
752190286Sobrien(define_insn "*divmodsi_noext"
752290286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a")
752318334Speter	(div:SI (match_operand:SI 1 "register_operand" "0")
752450650Sobrien		(match_operand:SI 2 "nonimmediate_operand" "rm")))
752590286Sobrien   (set (match_operand:SI 3 "register_operand" "=d")
752690286Sobrien	(mod:SI (match_dup 1) (match_dup 2)))
752790286Sobrien   (use (match_operand:SI 4 "register_operand" "3"))
7528169699Skan   (clobber (reg:CC FLAGS_REG))]
752918334Speter  ""
753090286Sobrien  "idiv{l}\t%2"
753190286Sobrien  [(set_attr "type" "idiv")
7532169699Skan   (set_attr "mode" "SI")])
753390286Sobrien
753490286Sobrien(define_split
753590286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
753690286Sobrien	(div:SI (match_operand:SI 1 "register_operand" "")
753790286Sobrien		(match_operand:SI 2 "nonimmediate_operand" "")))
753890286Sobrien   (set (match_operand:SI 3 "register_operand" "")
753990286Sobrien	(mod:SI (match_dup 1) (match_dup 2)))
7540169699Skan   (clobber (reg:CC FLAGS_REG))]
754190286Sobrien  "reload_completed"
754290286Sobrien  [(parallel [(set (match_dup 3)
754390286Sobrien		   (ashiftrt:SI (match_dup 4) (const_int 31)))
7544169699Skan	      (clobber (reg:CC FLAGS_REG))])
754590286Sobrien   (parallel [(set (match_dup 0)
754690286Sobrien	           (div:SI (reg:SI 0) (match_dup 2)))
754790286Sobrien	      (set (match_dup 3)
754890286Sobrien		   (mod:SI (reg:SI 0) (match_dup 2)))
754990286Sobrien	      (use (match_dup 3))
7550169699Skan	      (clobber (reg:CC FLAGS_REG))])]
755118334Speter{
7552117404Skan  /* Avoid use of cltd in favor of a mov+shift.  */
755390286Sobrien  if (!TARGET_USE_CLTD && !optimize_size)
755490286Sobrien    {
755590286Sobrien      if (true_regnum (operands[1]))
755690286Sobrien        emit_move_insn (operands[0], operands[1]);
755790286Sobrien      else
755890286Sobrien	emit_move_insn (operands[3], operands[1]);
755990286Sobrien      operands[4] = operands[3];
756090286Sobrien    }
756190286Sobrien  else
756290286Sobrien    {
7563169699Skan      gcc_assert (!true_regnum (operands[1]));
756490286Sobrien      operands[4] = operands[1];
756590286Sobrien    }
756690286Sobrien})
756790286Sobrien;; %%% Split me.
756818334Speter(define_insn "divmodhi4"
756918334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
757018334Speter	(div:HI (match_operand:HI 1 "register_operand" "0")
757150650Sobrien		(match_operand:HI 2 "nonimmediate_operand" "rm")))
757218334Speter   (set (match_operand:HI 3 "register_operand" "=&d")
757390286Sobrien	(mod:HI (match_dup 1) (match_dup 2)))
7574169699Skan   (clobber (reg:CC FLAGS_REG))]
757590286Sobrien  "TARGET_HIMODE_MATH"
757690286Sobrien  "cwtd\;idiv{w}\t%2"
757790286Sobrien  [(set_attr "type" "multi")
757890286Sobrien   (set_attr "length_immediate" "0")
757990286Sobrien   (set_attr "mode" "SI")])
758018334Speter
758190286Sobrien(define_insn "udivmoddi4"
758290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
758390286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "0")
758490286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "rm")))
758590286Sobrien   (set (match_operand:DI 3 "register_operand" "=&d")
758690286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
7587169699Skan   (clobber (reg:CC FLAGS_REG))]
758890286Sobrien  "TARGET_64BIT"
758990286Sobrien  "xor{q}\t%3, %3\;div{q}\t%2"
759090286Sobrien  [(set_attr "type" "multi")
759190286Sobrien   (set_attr "length_immediate" "0")
759290286Sobrien   (set_attr "mode" "DI")])
759390286Sobrien
759490286Sobrien(define_insn "*udivmoddi4_noext"
759590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
759690286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "0")
759790286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "rm")))
759890286Sobrien   (set (match_operand:DI 3 "register_operand" "=d")
759990286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
760090286Sobrien   (use (match_dup 3))
7601169699Skan   (clobber (reg:CC FLAGS_REG))]
760290286Sobrien  "TARGET_64BIT"
760390286Sobrien  "div{q}\t%2"
760490286Sobrien  [(set_attr "type" "idiv")
760590286Sobrien   (set_attr "mode" "DI")])
760690286Sobrien
760790286Sobrien(define_split
760890286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
760990286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "")
761090286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "")))
761190286Sobrien   (set (match_operand:DI 3 "register_operand" "")
761290286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
7613169699Skan   (clobber (reg:CC FLAGS_REG))]
761490286Sobrien  "TARGET_64BIT && reload_completed"
761590286Sobrien  [(set (match_dup 3) (const_int 0))
761690286Sobrien   (parallel [(set (match_dup 0)
761790286Sobrien		   (udiv:DI (match_dup 1) (match_dup 2)))
761890286Sobrien	      (set (match_dup 3)
761990286Sobrien		   (umod:DI (match_dup 1) (match_dup 2)))
762090286Sobrien	      (use (match_dup 3))
7621169699Skan	      (clobber (reg:CC FLAGS_REG))])]
762290286Sobrien  "")
762390286Sobrien
762418334Speter(define_insn "udivmodsi4"
762518334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
762618334Speter	(udiv:SI (match_operand:SI 1 "register_operand" "0")
762750650Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
762818334Speter   (set (match_operand:SI 3 "register_operand" "=&d")
762990286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
7630169699Skan   (clobber (reg:CC FLAGS_REG))]
763118334Speter  ""
763290286Sobrien  "xor{l}\t%3, %3\;div{l}\t%2"
763390286Sobrien  [(set_attr "type" "multi")
763490286Sobrien   (set_attr "length_immediate" "0")
763590286Sobrien   (set_attr "mode" "SI")])
763618334Speter
763790286Sobrien(define_insn "*udivmodsi4_noext"
763890286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a")
763990286Sobrien	(udiv:SI (match_operand:SI 1 "register_operand" "0")
764090286Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
764190286Sobrien   (set (match_operand:SI 3 "register_operand" "=d")
764290286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
764390286Sobrien   (use (match_dup 3))
7644169699Skan   (clobber (reg:CC FLAGS_REG))]
764590286Sobrien  ""
764690286Sobrien  "div{l}\t%2"
764790286Sobrien  [(set_attr "type" "idiv")
764890286Sobrien   (set_attr "mode" "SI")])
764990286Sobrien
765090286Sobrien(define_split
765190286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
765290286Sobrien	(udiv:SI (match_operand:SI 1 "register_operand" "")
765390286Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "")))
765490286Sobrien   (set (match_operand:SI 3 "register_operand" "")
765590286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
7656169699Skan   (clobber (reg:CC FLAGS_REG))]
765790286Sobrien  "reload_completed"
765890286Sobrien  [(set (match_dup 3) (const_int 0))
765990286Sobrien   (parallel [(set (match_dup 0)
766090286Sobrien		   (udiv:SI (match_dup 1) (match_dup 2)))
766190286Sobrien	      (set (match_dup 3)
766290286Sobrien		   (umod:SI (match_dup 1) (match_dup 2)))
766390286Sobrien	      (use (match_dup 3))
7664169699Skan	      (clobber (reg:CC FLAGS_REG))])]
766590286Sobrien  "")
766690286Sobrien
766790286Sobrien(define_expand "udivmodhi4"
766890286Sobrien  [(set (match_dup 4) (const_int 0))
766990286Sobrien   (parallel [(set (match_operand:HI 0 "register_operand" "")
767090286Sobrien		   (udiv:HI (match_operand:HI 1 "register_operand" "")
767190286Sobrien		 	    (match_operand:HI 2 "nonimmediate_operand" "")))
767290286Sobrien	      (set (match_operand:HI 3 "register_operand" "")
767390286Sobrien	   	   (umod:HI (match_dup 1) (match_dup 2)))
767490286Sobrien	      (use (match_dup 4))
7675169699Skan	      (clobber (reg:CC FLAGS_REG))])]
767690286Sobrien  "TARGET_HIMODE_MATH"
767790286Sobrien  "operands[4] = gen_reg_rtx (HImode);")
767890286Sobrien
767990286Sobrien(define_insn "*udivmodhi_noext"
768018334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
768118334Speter	(udiv:HI (match_operand:HI 1 "register_operand" "0")
768250650Sobrien		 (match_operand:HI 2 "nonimmediate_operand" "rm")))
768390286Sobrien   (set (match_operand:HI 3 "register_operand" "=d")
768490286Sobrien	(umod:HI (match_dup 1) (match_dup 2)))
768590286Sobrien   (use (match_operand:HI 4 "register_operand" "3"))
7686169699Skan   (clobber (reg:CC FLAGS_REG))]
768718334Speter  ""
768890286Sobrien  "div{w}\t%2"
768990286Sobrien  [(set_attr "type" "idiv")
7690169699Skan   (set_attr "mode" "HI")])
769118334Speter
7692169699Skan;; We cannot use div/idiv for double division, because it causes
769390286Sobrien;; "division by zero" on the overflow and that's not what we expect
769490286Sobrien;; from truncate.  Because true (non truncating) double division is
769590286Sobrien;; never generated, we can't create this insn anyway.
769690286Sobrien;
769790286Sobrien;(define_insn ""
769890286Sobrien;  [(set (match_operand:SI 0 "register_operand" "=a")
769990286Sobrien;	(truncate:SI
770090286Sobrien;	  (udiv:DI (match_operand:DI 1 "register_operand" "A")
770190286Sobrien;		   (zero_extend:DI
770290286Sobrien;		     (match_operand:SI 2 "nonimmediate_operand" "rm")))))
770390286Sobrien;   (set (match_operand:SI 3 "register_operand" "=d")
770490286Sobrien;	(truncate:SI
770590286Sobrien;	  (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))
7706169699Skan;   (clobber (reg:CC FLAGS_REG))]
770790286Sobrien;  ""
770890286Sobrien;  "div{l}\t{%2, %0|%0, %2}"
7709169699Skan;  [(set_attr "type" "idiv")])
771090286Sobrien
771190286Sobrien;;- Logical AND instructions
771218334Speter
771390286Sobrien;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al.
771490286Sobrien;; Note that this excludes ah.
771590286Sobrien
771690286Sobrien(define_insn "*testdi_1_rex64"
7717169699Skan  [(set (reg FLAGS_REG)
771890286Sobrien	(compare
7719132727Skan	  (and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm")
7720132727Skan		  (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re"))
772190286Sobrien	  (const_int 0)))]
7722132727Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
7723132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
772490286Sobrien  "@
7725169699Skan   test{l}\t{%k1, %k0|%k0, %k1}
7726169699Skan   test{l}\t{%k1, %k0|%k0, %k1}
7727169699Skan   test{q}\t{%1, %0|%0, %1}
7728169699Skan   test{q}\t{%1, %0|%0, %1}
772990286Sobrien   test{q}\t{%1, %0|%0, %1}"
773090286Sobrien  [(set_attr "type" "test")
773190286Sobrien   (set_attr "modrm" "0,1,0,1,1")
773290286Sobrien   (set_attr "mode" "SI,SI,DI,DI,DI")
773390286Sobrien   (set_attr "pent_pair" "uv,np,uv,np,uv")])
773490286Sobrien
773590286Sobrien(define_insn "testsi_1"
7736169699Skan  [(set (reg FLAGS_REG)
773790286Sobrien	(compare
7738132727Skan	  (and:SI (match_operand:SI 0 "nonimmediate_operand" "%!*a,r,rm")
7739132727Skan		  (match_operand:SI 1 "general_operand" "in,in,rin"))
774090286Sobrien	  (const_int 0)))]
7741132727Skan  "ix86_match_ccmode (insn, CCNOmode)
7742132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
774390286Sobrien  "test{l}\t{%1, %0|%0, %1}"
774490286Sobrien  [(set_attr "type" "test")
774590286Sobrien   (set_attr "modrm" "0,1,1")
774690286Sobrien   (set_attr "mode" "SI")
774790286Sobrien   (set_attr "pent_pair" "uv,np,uv")])
774890286Sobrien
774990286Sobrien(define_expand "testsi_ccno_1"
7750169699Skan  [(set (reg:CCNO FLAGS_REG)
775190286Sobrien	(compare:CCNO
775290286Sobrien	  (and:SI (match_operand:SI 0 "nonimmediate_operand" "")
775390286Sobrien		  (match_operand:SI 1 "nonmemory_operand" ""))
775490286Sobrien	  (const_int 0)))]
775518334Speter  ""
775690286Sobrien  "")
775718334Speter
775890286Sobrien(define_insn "*testhi_1"
7759169699Skan  [(set (reg FLAGS_REG)
7760132727Skan        (compare (and:HI (match_operand:HI 0 "nonimmediate_operand" "%!*a,r,rm")
7761132727Skan			 (match_operand:HI 1 "general_operand" "n,n,rn"))
776290286Sobrien		 (const_int 0)))]
7763132727Skan  "ix86_match_ccmode (insn, CCNOmode)
7764132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
776590286Sobrien  "test{w}\t{%1, %0|%0, %1}"
776690286Sobrien  [(set_attr "type" "test")
776790286Sobrien   (set_attr "modrm" "0,1,1")
776890286Sobrien   (set_attr "mode" "HI")
776990286Sobrien   (set_attr "pent_pair" "uv,np,uv")])
777018334Speter
777190286Sobrien(define_expand "testqi_ccz_1"
7772169699Skan  [(set (reg:CCZ FLAGS_REG)
777390286Sobrien        (compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand" "")
777490286Sobrien			     (match_operand:QI 1 "nonmemory_operand" ""))
777590286Sobrien		 (const_int 0)))]
777690286Sobrien  ""
777790286Sobrien  "")
777818334Speter
7779146906Skan(define_insn "*testqi_1_maybe_si"
7780169699Skan  [(set (reg FLAGS_REG)
7781146906Skan        (compare
7782146906Skan	  (and:QI
7783146906Skan	    (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm,r")
7784146906Skan	    (match_operand:QI 1 "general_operand" "n,n,qn,n"))
7785146906Skan	  (const_int 0)))]
7786169699Skan   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
7787169699Skan    && ix86_match_ccmode (insn,
7788169699Skan 			 GET_CODE (operands[1]) == CONST_INT
7789169699Skan 			 && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)"
779018334Speter{
779190286Sobrien  if (which_alternative == 3)
779218334Speter    {
7793146906Skan      if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
779490286Sobrien	operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
779590286Sobrien      return "test{l}\t{%1, %k0|%k0, %1}";
779650650Sobrien    }
779790286Sobrien  return "test{b}\t{%1, %0|%0, %1}";
779890286Sobrien}
779990286Sobrien  [(set_attr "type" "test")
780090286Sobrien   (set_attr "modrm" "0,1,1,1")
780190286Sobrien   (set_attr "mode" "QI,QI,QI,SI")
780290286Sobrien   (set_attr "pent_pair" "uv,np,uv,np")])
780318334Speter
7804146906Skan(define_insn "*testqi_1"
7805169699Skan  [(set (reg FLAGS_REG)
7806146906Skan        (compare
7807146906Skan	  (and:QI
7808146906Skan	    (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm")
7809146906Skan	    (match_operand:QI 1 "general_operand" "n,n,qn"))
7810146906Skan	  (const_int 0)))]
7811146906Skan  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
7812146906Skan   && ix86_match_ccmode (insn, CCNOmode)"
7813146906Skan  "test{b}\t{%1, %0|%0, %1}"
7814146906Skan  [(set_attr "type" "test")
7815146906Skan   (set_attr "modrm" "0,1,1")
7816146906Skan   (set_attr "mode" "QI")
7817146906Skan   (set_attr "pent_pair" "uv,np,uv")])
7818146906Skan
781990286Sobrien(define_expand "testqi_ext_ccno_0"
7820169699Skan  [(set (reg:CCNO FLAGS_REG)
782190286Sobrien	(compare:CCNO
782290286Sobrien	  (and:SI
782390286Sobrien	    (zero_extract:SI
782490286Sobrien	      (match_operand 0 "ext_register_operand" "")
782590286Sobrien	      (const_int 8)
782690286Sobrien	      (const_int 8))
782790286Sobrien	    (match_operand 1 "const_int_operand" ""))
782890286Sobrien	  (const_int 0)))]
782990286Sobrien  ""
783090286Sobrien  "")
783118334Speter
783290286Sobrien(define_insn "*testqi_ext_0"
7833169699Skan  [(set (reg FLAGS_REG)
783490286Sobrien	(compare
783590286Sobrien	  (and:SI
783690286Sobrien	    (zero_extract:SI
783790286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
783890286Sobrien	      (const_int 8)
783990286Sobrien	      (const_int 8))
784090286Sobrien	    (match_operand 1 "const_int_operand" "n"))
784190286Sobrien	  (const_int 0)))]
7842117404Skan  "ix86_match_ccmode (insn, CCNOmode)"
784390286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
784490286Sobrien  [(set_attr "type" "test")
784590286Sobrien   (set_attr "mode" "QI")
784690286Sobrien   (set_attr "length_immediate" "1")
784790286Sobrien   (set_attr "pent_pair" "np")])
784850650Sobrien
784990286Sobrien(define_insn "*testqi_ext_1"
7850169699Skan  [(set (reg FLAGS_REG)
785190286Sobrien	(compare
785290286Sobrien	  (and:SI
785390286Sobrien	    (zero_extract:SI
785490286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
785590286Sobrien	      (const_int 8)
785690286Sobrien	      (const_int 8))
785790286Sobrien	    (zero_extend:SI
7858132727Skan	      (match_operand:QI 1 "general_operand" "Qm")))
785990286Sobrien	  (const_int 0)))]
7860132727Skan  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
7861132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
786290286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
786390286Sobrien  [(set_attr "type" "test")
786490286Sobrien   (set_attr "mode" "QI")])
786518334Speter
786690286Sobrien(define_insn "*testqi_ext_1_rex64"
7867169699Skan  [(set (reg FLAGS_REG)
786890286Sobrien	(compare
786990286Sobrien	  (and:SI
787090286Sobrien	    (zero_extract:SI
787190286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
787290286Sobrien	      (const_int 8)
787390286Sobrien	      (const_int 8))
787490286Sobrien	    (zero_extend:SI
787590286Sobrien	      (match_operand:QI 1 "register_operand" "Q")))
787690286Sobrien	  (const_int 0)))]
787790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
787890286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
787990286Sobrien  [(set_attr "type" "test")
788090286Sobrien   (set_attr "mode" "QI")])
788118334Speter
788290286Sobrien(define_insn "*testqi_ext_2"
7883169699Skan  [(set (reg FLAGS_REG)
788490286Sobrien	(compare
788590286Sobrien	  (and:SI
788690286Sobrien	    (zero_extract:SI
788790286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
788890286Sobrien	      (const_int 8)
788990286Sobrien	      (const_int 8))
789090286Sobrien	    (zero_extract:SI
789190286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
789290286Sobrien	      (const_int 8)
789390286Sobrien	      (const_int 8)))
789490286Sobrien	  (const_int 0)))]
789590286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
789690286Sobrien  "test{b}\t{%h1, %h0|%h0, %h1}"
789790286Sobrien  [(set_attr "type" "test")
789890286Sobrien   (set_attr "mode" "QI")])
789950650Sobrien
790090286Sobrien;; Combine likes to form bit extractions for some tests.  Humor it.
790190286Sobrien(define_insn "*testqi_ext_3"
7902169699Skan  [(set (reg FLAGS_REG)
790390286Sobrien        (compare (zero_extract:SI
790490286Sobrien		   (match_operand 0 "nonimmediate_operand" "rm")
790590286Sobrien		   (match_operand:SI 1 "const_int_operand" "")
790690286Sobrien		   (match_operand:SI 2 "const_int_operand" ""))
790790286Sobrien		 (const_int 0)))]
790890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
7909169699Skan   && INTVAL (operands[1]) > 0
7910169699Skan   && INTVAL (operands[2]) >= 0
7911169699Skan   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
791290286Sobrien   && (GET_MODE (operands[0]) == SImode
791390286Sobrien       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
791490286Sobrien       || GET_MODE (operands[0]) == HImode
791590286Sobrien       || GET_MODE (operands[0]) == QImode)"
791690286Sobrien  "#")
791750650Sobrien
791890286Sobrien(define_insn "*testqi_ext_3_rex64"
7919169699Skan  [(set (reg FLAGS_REG)
792090286Sobrien        (compare (zero_extract:DI
792190286Sobrien		   (match_operand 0 "nonimmediate_operand" "rm")
792290286Sobrien		   (match_operand:DI 1 "const_int_operand" "")
792390286Sobrien		   (match_operand:DI 2 "const_int_operand" ""))
792490286Sobrien		 (const_int 0)))]
792590286Sobrien  "TARGET_64BIT
792690286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
7927169699Skan   && INTVAL (operands[1]) > 0
7928169699Skan   && INTVAL (operands[2]) >= 0
792990286Sobrien   /* Ensure that resulting mask is zero or sign extended operand.  */
793090286Sobrien   && (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
793190286Sobrien       || (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
793290286Sobrien	   && INTVAL (operands[1]) > 32))
793390286Sobrien   && (GET_MODE (operands[0]) == SImode
793490286Sobrien       || GET_MODE (operands[0]) == DImode
793590286Sobrien       || GET_MODE (operands[0]) == HImode
793690286Sobrien       || GET_MODE (operands[0]) == QImode)"
793790286Sobrien  "#")
793850650Sobrien
793990286Sobrien(define_split
7940146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
7941146906Skan        (match_operator 1 "compare_operator"
7942146906Skan	  [(zero_extract
7943146906Skan	     (match_operand 2 "nonimmediate_operand" "")
7944146906Skan	     (match_operand 3 "const_int_operand" "")
7945146906Skan	     (match_operand 4 "const_int_operand" ""))
7946146906Skan	   (const_int 0)]))]
794790286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
7948146906Skan  [(set (match_dup 0) (match_op_dup 1 [(match_dup 2) (const_int 0)]))]
794990286Sobrien{
7950146906Skan  rtx val = operands[2];
7951146906Skan  HOST_WIDE_INT len = INTVAL (operands[3]);
7952146906Skan  HOST_WIDE_INT pos = INTVAL (operands[4]);
795390286Sobrien  HOST_WIDE_INT mask;
795490286Sobrien  enum machine_mode mode, submode;
795518334Speter
7956146906Skan  mode = GET_MODE (val);
7957146906Skan  if (GET_CODE (val) == MEM)
795890286Sobrien    {
795990286Sobrien      /* ??? Combine likes to put non-volatile mem extractions in QImode
796090286Sobrien	 no matter the size of the test.  So find a mode that works.  */
7961146906Skan      if (! MEM_VOLATILE_P (val))
796218334Speter	{
796390286Sobrien	  mode = smallest_mode_for_size (pos + len, MODE_INT);
7964146906Skan	  val = adjust_address (val, mode, 0);
796590286Sobrien	}
796690286Sobrien    }
7967146906Skan  else if (GET_CODE (val) == SUBREG
7968146906Skan	   && (submode = GET_MODE (SUBREG_REG (val)),
796990286Sobrien	       GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (submode))
797090286Sobrien	   && pos + len <= GET_MODE_BITSIZE (submode))
797190286Sobrien    {
797290286Sobrien      /* Narrow a paradoxical subreg to prevent partial register stalls.  */
797390286Sobrien      mode = submode;
7974146906Skan      val = SUBREG_REG (val);
797590286Sobrien    }
797690286Sobrien  else if (mode == HImode && pos + len <= 8)
797790286Sobrien    {
797890286Sobrien      /* Small HImode tests can be converted to QImode.  */
797990286Sobrien      mode = QImode;
7980146906Skan      val = gen_lowpart (QImode, val);
798190286Sobrien    }
798218334Speter
7983169699Skan  if (len == HOST_BITS_PER_WIDE_INT)
7984169699Skan    mask = -1;
7985169699Skan  else
7986169699Skan    mask = ((HOST_WIDE_INT)1 << len) - 1;
7987169699Skan  mask <<= pos;
798818334Speter
7989146906Skan  operands[2] = gen_rtx_AND (mode, val, gen_int_mode (mask, mode));
799090286Sobrien})
799150650Sobrien
7992117404Skan;; Convert HImode/SImode test instructions with immediate to QImode ones.
7993117404Skan;; i386 does not allow to encode test with 8bit sign extended immediate, so
7994117404Skan;; this is relatively important trick.
7995132727Skan;; Do the conversion only post-reload to avoid limiting of the register class
7996117404Skan;; to QI regs.
7997117404Skan(define_split
7998146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
7999146906Skan	(match_operator 1 "compare_operator"
8000146906Skan	  [(and (match_operand 2 "register_operand" "")
8001146906Skan	        (match_operand 3 "const_int_operand" ""))
8002146906Skan	   (const_int 0)]))]
8003117404Skan   "reload_completed
8004146906Skan    && QI_REG_P (operands[2])
8005146906Skan    && GET_MODE (operands[2]) != QImode
8006117404Skan    && ((ix86_match_ccmode (insn, CCZmode)
8007146906Skan    	 && !(INTVAL (operands[3]) & ~(255 << 8)))
8008117404Skan	|| (ix86_match_ccmode (insn, CCNOmode)
8009146906Skan	    && !(INTVAL (operands[3]) & ~(127 << 8))))"
8010146906Skan  [(set (match_dup 0)
8011146906Skan	(match_op_dup 1
8012146906Skan	  [(and:SI (zero_extract:SI (match_dup 2) (const_int 8) (const_int 8))
8013146906Skan		   (match_dup 3))
8014146906Skan	   (const_int 0)]))]
8015146906Skan  "operands[2] = gen_lowpart (SImode, operands[2]);
8016146906Skan   operands[3] = gen_int_mode (INTVAL (operands[3]) >> 8, SImode);")
8017117404Skan
8018117404Skan(define_split
8019146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
8020146906Skan	(match_operator 1 "compare_operator"
8021146906Skan	  [(and (match_operand 2 "nonimmediate_operand" "")
8022146906Skan	        (match_operand 3 "const_int_operand" ""))
8023146906Skan	   (const_int 0)]))]
8024117404Skan   "reload_completed
8025146906Skan    && GET_MODE (operands[2]) != QImode
8026146906Skan    && (!REG_P (operands[2]) || ANY_QI_REG_P (operands[2]))
8027117404Skan    && ((ix86_match_ccmode (insn, CCZmode)
8028146906Skan	 && !(INTVAL (operands[3]) & ~255))
8029117404Skan	|| (ix86_match_ccmode (insn, CCNOmode)
8030146906Skan	    && !(INTVAL (operands[3]) & ~127)))"
8031146906Skan  [(set (match_dup 0)
8032146906Skan	(match_op_dup 1 [(and:QI (match_dup 2) (match_dup 3))
8033146906Skan			 (const_int 0)]))]
8034146906Skan  "operands[2] = gen_lowpart (QImode, operands[2]);
8035146906Skan   operands[3] = gen_lowpart (QImode, operands[3]);")
8036117404Skan
8037117404Skan
803890286Sobrien;; %%% This used to optimize known byte-wide and operations to memory,
803990286Sobrien;; and sometimes to QImode registers.  If this is considered useful,
804090286Sobrien;; it should be done with splitters.
804118334Speter
804290286Sobrien(define_expand "anddi3"
804390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
804490286Sobrien	(and:DI (match_operand:DI 1 "nonimmediate_operand" "")
804590286Sobrien		(match_operand:DI 2 "x86_64_szext_general_operand" "")))
8046169699Skan   (clobber (reg:CC FLAGS_REG))]
804790286Sobrien  "TARGET_64BIT"
804890286Sobrien  "ix86_expand_binary_operator (AND, DImode, operands); DONE;")
804950650Sobrien
805090286Sobrien(define_insn "*anddi_1_rex64"
805190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
805290286Sobrien	(and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm")
805390286Sobrien		(match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L")))
8054169699Skan   (clobber (reg:CC FLAGS_REG))]
805590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)"
805690286Sobrien{
805790286Sobrien  switch (get_attr_type (insn))
805890286Sobrien    {
805990286Sobrien    case TYPE_IMOVX:
806090286Sobrien      {
806190286Sobrien	enum machine_mode mode;
806250650Sobrien
8063169699Skan	gcc_assert (GET_CODE (operands[2]) == CONST_INT);
806490286Sobrien        if (INTVAL (operands[2]) == 0xff)
806590286Sobrien	  mode = QImode;
806690286Sobrien	else
8067169699Skan	  {
8068169699Skan	    gcc_assert (INTVAL (operands[2]) == 0xffff);
8069169699Skan	    mode = HImode;
8070169699Skan	  }
807190286Sobrien	
807290286Sobrien	operands[1] = gen_lowpart (mode, operands[1]);
807390286Sobrien	if (mode == QImode)
807490286Sobrien	  return "movz{bq|x}\t{%1,%0|%0, %1}";
807590286Sobrien	else
807690286Sobrien	  return "movz{wq|x}\t{%1,%0|%0, %1}";
807790286Sobrien      }
807850650Sobrien
807950650Sobrien    default:
8080169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
808190286Sobrien      if (get_attr_mode (insn) == MODE_SI)
808290286Sobrien	return "and{l}\t{%k2, %k0|%k0, %k2}";
808390286Sobrien      else
808490286Sobrien	return "and{q}\t{%2, %0|%0, %2}";
808518334Speter    }
808690286Sobrien}
808790286Sobrien  [(set_attr "type" "alu,alu,alu,imovx")
808890286Sobrien   (set_attr "length_immediate" "*,*,*,0")
808990286Sobrien   (set_attr "mode" "SI,DI,DI,DI")])
809018334Speter
809190286Sobrien(define_insn "*anddi_2"
8092169699Skan  [(set (reg FLAGS_REG)
809390286Sobrien	(compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
809490286Sobrien			 (match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re"))
809590286Sobrien		 (const_int 0)))
809690286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm")
809790286Sobrien	(and:DI (match_dup 1) (match_dup 2)))]
809890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
809990286Sobrien   && ix86_binary_operator_ok (AND, DImode, operands)"
810090286Sobrien  "@
8101169699Skan   and{l}\t{%k2, %k0|%k0, %k2}
8102169699Skan   and{q}\t{%2, %0|%0, %2}
810390286Sobrien   and{q}\t{%2, %0|%0, %2}"
810490286Sobrien  [(set_attr "type" "alu")
810590286Sobrien   (set_attr "mode" "SI,DI,DI")])
810618334Speter
810790286Sobrien(define_expand "andsi3"
810890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
810990286Sobrien	(and:SI (match_operand:SI 1 "nonimmediate_operand" "")
811090286Sobrien		(match_operand:SI 2 "general_operand" "")))
8111169699Skan   (clobber (reg:CC FLAGS_REG))]
811218334Speter  ""
811390286Sobrien  "ix86_expand_binary_operator (AND, SImode, operands); DONE;")
811490286Sobrien
811590286Sobrien(define_insn "*andsi_1"
811690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r")
811790286Sobrien	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm")
811890286Sobrien		(match_operand:SI 2 "general_operand" "ri,rm,L")))
8119169699Skan   (clobber (reg:CC FLAGS_REG))]
812090286Sobrien  "ix86_binary_operator_ok (AND, SImode, operands)"
812118334Speter{
812290286Sobrien  switch (get_attr_type (insn))
812318334Speter    {
812490286Sobrien    case TYPE_IMOVX:
812590286Sobrien      {
812690286Sobrien	enum machine_mode mode;
812718334Speter
8128169699Skan	gcc_assert (GET_CODE (operands[2]) == CONST_INT);
812990286Sobrien        if (INTVAL (operands[2]) == 0xff)
813090286Sobrien	  mode = QImode;
813190286Sobrien	else
8132169699Skan	  {
8133169699Skan	    gcc_assert (INTVAL (operands[2]) == 0xffff);
8134169699Skan	    mode = HImode;
8135169699Skan	  }
813690286Sobrien	
813790286Sobrien	operands[1] = gen_lowpart (mode, operands[1]);
813890286Sobrien	if (mode == QImode)
813990286Sobrien	  return "movz{bl|x}\t{%1,%0|%0, %1}";
814090286Sobrien	else
814190286Sobrien	  return "movz{wl|x}\t{%1,%0|%0, %1}";
814290286Sobrien      }
814318334Speter
814490286Sobrien    default:
8145169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
814690286Sobrien      return "and{l}\t{%2, %0|%0, %2}";
814790286Sobrien    }
814890286Sobrien}
814990286Sobrien  [(set_attr "type" "alu,alu,imovx")
815090286Sobrien   (set_attr "length_immediate" "*,*,0")
815190286Sobrien   (set_attr "mode" "SI")])
815218334Speter
815390286Sobrien(define_split
815490286Sobrien  [(set (match_operand 0 "register_operand" "")
815590286Sobrien	(and (match_dup 0)
815690286Sobrien	     (const_int -65536)))
8157169699Skan   (clobber (reg:CC FLAGS_REG))]
8158117404Skan  "optimize_size || (TARGET_FAST_PREFIX && !TARGET_PARTIAL_REG_STALL)"
815990286Sobrien  [(set (strict_low_part (match_dup 1)) (const_int 0))]
816090286Sobrien  "operands[1] = gen_lowpart (HImode, operands[0]);")
816118334Speter
816290286Sobrien(define_split
816390286Sobrien  [(set (match_operand 0 "ext_register_operand" "")
816490286Sobrien	(and (match_dup 0)
816590286Sobrien	     (const_int -256)))
8166169699Skan   (clobber (reg:CC FLAGS_REG))]
816790286Sobrien  "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
816890286Sobrien  [(set (strict_low_part (match_dup 1)) (const_int 0))]
816990286Sobrien  "operands[1] = gen_lowpart (QImode, operands[0]);")
817018334Speter
817190286Sobrien(define_split
817290286Sobrien  [(set (match_operand 0 "ext_register_operand" "")
817390286Sobrien	(and (match_dup 0)
817490286Sobrien	     (const_int -65281)))
8175169699Skan   (clobber (reg:CC FLAGS_REG))]
817690286Sobrien  "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
817790286Sobrien  [(parallel [(set (zero_extract:SI (match_dup 0)
817890286Sobrien				    (const_int 8)
817990286Sobrien				    (const_int 8))
818090286Sobrien		   (xor:SI 
818190286Sobrien		     (zero_extract:SI (match_dup 0)
818290286Sobrien				      (const_int 8)
818390286Sobrien				      (const_int 8))
818490286Sobrien		     (zero_extract:SI (match_dup 0)
818590286Sobrien				      (const_int 8)
818690286Sobrien				      (const_int 8))))
8187169699Skan	      (clobber (reg:CC FLAGS_REG))])]
818890286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);")
818950650Sobrien
819090286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
819190286Sobrien(define_insn "*andsi_1_zext"
819290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
819390286Sobrien	(zero_extend:DI
819490286Sobrien	  (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
819590286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8196169699Skan   (clobber (reg:CC FLAGS_REG))]
819790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
819890286Sobrien  "and{l}\t{%2, %k0|%k0, %2}"
819990286Sobrien  [(set_attr "type" "alu")
820090286Sobrien   (set_attr "mode" "SI")])
820118334Speter
820290286Sobrien(define_insn "*andsi_2"
8203169699Skan  [(set (reg FLAGS_REG)
820490286Sobrien	(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
820590286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
820690286Sobrien		 (const_int 0)))
820790286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
820890286Sobrien	(and:SI (match_dup 1) (match_dup 2)))]
820990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
821090286Sobrien   && ix86_binary_operator_ok (AND, SImode, operands)"
821190286Sobrien  "and{l}\t{%2, %0|%0, %2}"
821290286Sobrien  [(set_attr "type" "alu")
821390286Sobrien   (set_attr "mode" "SI")])
821490286Sobrien
821590286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
821690286Sobrien(define_insn "*andsi_2_zext"
8217169699Skan  [(set (reg FLAGS_REG)
821890286Sobrien	(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
821990286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
822090286Sobrien		 (const_int 0)))
822190286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
822290286Sobrien	(zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
822390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
822490286Sobrien   && ix86_binary_operator_ok (AND, SImode, operands)"
822590286Sobrien  "and{l}\t{%2, %k0|%k0, %2}"
822690286Sobrien  [(set_attr "type" "alu")
822790286Sobrien   (set_attr "mode" "SI")])
822890286Sobrien
822990286Sobrien(define_expand "andhi3"
823090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
823190286Sobrien	(and:HI (match_operand:HI 1 "nonimmediate_operand" "")
823290286Sobrien		(match_operand:HI 2 "general_operand" "")))
8233169699Skan   (clobber (reg:CC FLAGS_REG))]
823490286Sobrien  "TARGET_HIMODE_MATH"
823590286Sobrien  "ix86_expand_binary_operator (AND, HImode, operands); DONE;")
823690286Sobrien
823790286Sobrien(define_insn "*andhi_1"
823890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
823990286Sobrien	(and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,qm")
824090286Sobrien		(match_operand:HI 2 "general_operand" "ri,rm,L")))
8241169699Skan   (clobber (reg:CC FLAGS_REG))]
824290286Sobrien  "ix86_binary_operator_ok (AND, HImode, operands)"
824390286Sobrien{
824490286Sobrien  switch (get_attr_type (insn))
824550650Sobrien    {
824690286Sobrien    case TYPE_IMOVX:
8247169699Skan      gcc_assert (GET_CODE (operands[2]) == CONST_INT);
8248169699Skan      gcc_assert (INTVAL (operands[2]) == 0xff);
8249169699Skan      return "movz{bl|x}\t{%b1, %k0|%k0, %b1}";
825090286Sobrien
825190286Sobrien    default:
8252169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
825390286Sobrien
825490286Sobrien      return "and{w}\t{%2, %0|%0, %2}";
825550650Sobrien    }
825690286Sobrien}
825790286Sobrien  [(set_attr "type" "alu,alu,imovx")
825890286Sobrien   (set_attr "length_immediate" "*,*,0")
825990286Sobrien   (set_attr "mode" "HI,HI,SI")])
826050650Sobrien
826190286Sobrien(define_insn "*andhi_2"
8262169699Skan  [(set (reg FLAGS_REG)
826390286Sobrien	(compare (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
826490286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
826590286Sobrien		 (const_int 0)))
826690286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
826790286Sobrien	(and:HI (match_dup 1) (match_dup 2)))]
826890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
826990286Sobrien   && ix86_binary_operator_ok (AND, HImode, operands)"
827090286Sobrien  "and{w}\t{%2, %0|%0, %2}"
827190286Sobrien  [(set_attr "type" "alu")
827290286Sobrien   (set_attr "mode" "HI")])
827390286Sobrien
827490286Sobrien(define_expand "andqi3"
827590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
827690286Sobrien	(and:QI (match_operand:QI 1 "nonimmediate_operand" "")
827790286Sobrien		(match_operand:QI 2 "general_operand" "")))
8278169699Skan   (clobber (reg:CC FLAGS_REG))]
827990286Sobrien  "TARGET_QIMODE_MATH"
828090286Sobrien  "ix86_expand_binary_operator (AND, QImode, operands); DONE;")
828190286Sobrien
828290286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
828390286Sobrien(define_insn "*andqi_1"
828490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
828590286Sobrien	(and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
828690286Sobrien		(match_operand:QI 2 "general_operand" "qi,qmi,ri")))
8287169699Skan   (clobber (reg:CC FLAGS_REG))]
828890286Sobrien  "ix86_binary_operator_ok (AND, QImode, operands)"
828990286Sobrien  "@
829090286Sobrien   and{b}\t{%2, %0|%0, %2}
829190286Sobrien   and{b}\t{%2, %0|%0, %2}
829290286Sobrien   and{l}\t{%k2, %k0|%k0, %k2}"
829390286Sobrien  [(set_attr "type" "alu")
829490286Sobrien   (set_attr "mode" "QI,QI,SI")])
829590286Sobrien
829690286Sobrien(define_insn "*andqi_1_slp"
829790286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
829890286Sobrien	(and:QI (match_dup 0)
829990286Sobrien		(match_operand:QI 1 "general_operand" "qi,qmi")))
8300169699Skan   (clobber (reg:CC FLAGS_REG))]
8301117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8302117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
830390286Sobrien  "and{b}\t{%1, %0|%0, %1}"
830490286Sobrien  [(set_attr "type" "alu1")
830590286Sobrien   (set_attr "mode" "QI")])
830690286Sobrien
8307146906Skan(define_insn "*andqi_2_maybe_si"
8308169699Skan  [(set (reg FLAGS_REG)
830990286Sobrien	(compare (and:QI
8310146906Skan		      (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
8311146906Skan		      (match_operand:QI 2 "general_operand" "qim,qi,i"))
831290286Sobrien		 (const_int 0)))
831390286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,*r")
831490286Sobrien	(and:QI (match_dup 1) (match_dup 2)))]
8315146906Skan  "ix86_binary_operator_ok (AND, QImode, operands)
8316146906Skan   && ix86_match_ccmode (insn,
8317146906Skan			 GET_CODE (operands[2]) == CONST_INT
8318146906Skan			 && INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode)"
831990286Sobrien{
832090286Sobrien  if (which_alternative == 2)
832150650Sobrien    {
8322146906Skan      if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
832390286Sobrien        operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
832490286Sobrien      return "and{l}\t{%2, %k0|%k0, %2}";
832550650Sobrien    }
832690286Sobrien  return "and{b}\t{%2, %0|%0, %2}";
832790286Sobrien}
832890286Sobrien  [(set_attr "type" "alu")
832990286Sobrien   (set_attr "mode" "QI,QI,SI")])
833050650Sobrien
8331146906Skan(define_insn "*andqi_2"
8332169699Skan  [(set (reg FLAGS_REG)
8333146906Skan	(compare (and:QI
8334146906Skan		   (match_operand:QI 1 "nonimmediate_operand" "%0,0")
8335146906Skan		   (match_operand:QI 2 "general_operand" "qim,qi"))
8336146906Skan		 (const_int 0)))
8337146906Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
8338146906Skan	(and:QI (match_dup 1) (match_dup 2)))]
8339146906Skan  "ix86_match_ccmode (insn, CCNOmode)
8340146906Skan   && ix86_binary_operator_ok (AND, QImode, operands)"
8341146906Skan  "and{b}\t{%2, %0|%0, %2}"
8342146906Skan  [(set_attr "type" "alu")
8343146906Skan   (set_attr "mode" "QI")])
8344146906Skan
834590286Sobrien(define_insn "*andqi_2_slp"
8346169699Skan  [(set (reg FLAGS_REG)
834790286Sobrien	(compare (and:QI
834890286Sobrien		   (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
834990286Sobrien		   (match_operand:QI 1 "nonimmediate_operand" "qmi,qi"))
835090286Sobrien		 (const_int 0)))
835190286Sobrien   (set (strict_low_part (match_dup 0))
835290286Sobrien	(and:QI (match_dup 0) (match_dup 1)))]
8353117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8354117404Skan   && ix86_match_ccmode (insn, CCNOmode)
8355117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
835690286Sobrien  "and{b}\t{%1, %0|%0, %1}"
835790286Sobrien  [(set_attr "type" "alu1")
835890286Sobrien   (set_attr "mode" "QI")])
835918334Speter
836090286Sobrien;; ??? A bug in recog prevents it from recognizing a const_int as an
836190286Sobrien;; operand to zero_extend in andqi_ext_1.  It was checking explicitly
836290286Sobrien;; for a QImode operand, which of course failed.
836318334Speter
836490286Sobrien(define_insn "andqi_ext_0"
836590286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
836690286Sobrien			 (const_int 8)
836790286Sobrien			 (const_int 8))
836890286Sobrien	(and:SI 
836990286Sobrien	  (zero_extract:SI
837090286Sobrien	    (match_operand 1 "ext_register_operand" "0")
837190286Sobrien	    (const_int 8)
837290286Sobrien	    (const_int 8))
837390286Sobrien	  (match_operand 2 "const_int_operand" "n")))
8374169699Skan   (clobber (reg:CC FLAGS_REG))]
8375117404Skan  ""
837690286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
837790286Sobrien  [(set_attr "type" "alu")
837890286Sobrien   (set_attr "length_immediate" "1")
837990286Sobrien   (set_attr "mode" "QI")])
838018334Speter
838190286Sobrien;; Generated by peephole translating test to and.  This shows up
838290286Sobrien;; often in fp comparisons.
838390286Sobrien
838490286Sobrien(define_insn "*andqi_ext_0_cc"
8385169699Skan  [(set (reg FLAGS_REG)
838690286Sobrien	(compare
838790286Sobrien	  (and:SI
838890286Sobrien	    (zero_extract:SI
838990286Sobrien	      (match_operand 1 "ext_register_operand" "0")
839090286Sobrien	      (const_int 8)
839190286Sobrien	      (const_int 8))
839290286Sobrien	    (match_operand 2 "const_int_operand" "n"))
839390286Sobrien	  (const_int 0)))
839490286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
839590286Sobrien			 (const_int 8)
839690286Sobrien			 (const_int 8))
839790286Sobrien	(and:SI 
839890286Sobrien	  (zero_extract:SI
839990286Sobrien	    (match_dup 1)
840090286Sobrien	    (const_int 8)
840190286Sobrien	    (const_int 8))
840290286Sobrien	  (match_dup 2)))]
8403117404Skan  "ix86_match_ccmode (insn, CCNOmode)"
840490286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
840590286Sobrien  [(set_attr "type" "alu")
840690286Sobrien   (set_attr "length_immediate" "1")
840790286Sobrien   (set_attr "mode" "QI")])
840890286Sobrien
840990286Sobrien(define_insn "*andqi_ext_1"
841090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
841190286Sobrien			 (const_int 8)
841290286Sobrien			 (const_int 8))
841390286Sobrien	(and:SI 
841490286Sobrien	  (zero_extract:SI
841590286Sobrien	    (match_operand 1 "ext_register_operand" "0")
841690286Sobrien	    (const_int 8)
841790286Sobrien	    (const_int 8))
841890286Sobrien	  (zero_extend:SI
841990286Sobrien	    (match_operand:QI 2 "general_operand" "Qm"))))
8420169699Skan   (clobber (reg:CC FLAGS_REG))]
842190286Sobrien  "!TARGET_64BIT"
842290286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
842390286Sobrien  [(set_attr "type" "alu")
842490286Sobrien   (set_attr "length_immediate" "0")
842590286Sobrien   (set_attr "mode" "QI")])
842690286Sobrien
842790286Sobrien(define_insn "*andqi_ext_1_rex64"
842890286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
842990286Sobrien			 (const_int 8)
843090286Sobrien			 (const_int 8))
843190286Sobrien	(and:SI 
843290286Sobrien	  (zero_extract:SI
843390286Sobrien	    (match_operand 1 "ext_register_operand" "0")
843490286Sobrien	    (const_int 8)
843590286Sobrien	    (const_int 8))
843690286Sobrien	  (zero_extend:SI
843790286Sobrien	    (match_operand 2 "ext_register_operand" "Q"))))
8438169699Skan   (clobber (reg:CC FLAGS_REG))]
843990286Sobrien  "TARGET_64BIT"
844090286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
844190286Sobrien  [(set_attr "type" "alu")
844290286Sobrien   (set_attr "length_immediate" "0")
844390286Sobrien   (set_attr "mode" "QI")])
844490286Sobrien
844590286Sobrien(define_insn "*andqi_ext_2"
844690286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
844790286Sobrien			 (const_int 8)
844890286Sobrien			 (const_int 8))
844918334Speter	(and:SI
845090286Sobrien	  (zero_extract:SI
845190286Sobrien	    (match_operand 1 "ext_register_operand" "%0")
845290286Sobrien	    (const_int 8)
845390286Sobrien	    (const_int 8))
845490286Sobrien	  (zero_extract:SI
845590286Sobrien	    (match_operand 2 "ext_register_operand" "Q")
845690286Sobrien	    (const_int 8)
845790286Sobrien	    (const_int 8))))
8458169699Skan   (clobber (reg:CC FLAGS_REG))]
845990286Sobrien  ""
846090286Sobrien  "and{b}\t{%h2, %h0|%h0, %h2}"
846190286Sobrien  [(set_attr "type" "alu")
846290286Sobrien   (set_attr "length_immediate" "0")
846390286Sobrien   (set_attr "mode" "QI")])
8464117404Skan
8465117404Skan;; Convert wide AND instructions with immediate operand to shorter QImode
8466117404Skan;; equivalents when possible.
8467132727Skan;; Don't do the splitting with memory operands, since it introduces risk
8468117404Skan;; of memory mismatch stalls.  We may want to do the splitting for optimizing
8469117404Skan;; for size, but that can (should?) be handled by generic code instead.
8470117404Skan(define_split
8471117404Skan  [(set (match_operand 0 "register_operand" "")
8472117404Skan	(and (match_operand 1 "register_operand" "")
8473117404Skan	     (match_operand 2 "const_int_operand" "")))
8474169699Skan   (clobber (reg:CC FLAGS_REG))]
8475117404Skan   "reload_completed
8476117404Skan    && QI_REG_P (operands[0])
8477117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8478117404Skan    && !(~INTVAL (operands[2]) & ~(255 << 8))
8479117404Skan    && GET_MODE (operands[0]) != QImode"
8480117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
8481117404Skan		   (and:SI (zero_extract:SI (match_dup 1)
8482117404Skan					    (const_int 8) (const_int 8))
8483117404Skan			   (match_dup 2)))
8484169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8485117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
8486117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
8487117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
8488117404Skan
8489117404Skan;; Since AND can be encoded with sign extended immediate, this is only
8490117404Skan;; profitable when 7th bit is not set.
8491117404Skan(define_split
8492117404Skan  [(set (match_operand 0 "register_operand" "")
8493117404Skan	(and (match_operand 1 "general_operand" "")
8494117404Skan	     (match_operand 2 "const_int_operand" "")))
8495169699Skan   (clobber (reg:CC FLAGS_REG))]
8496117404Skan   "reload_completed
8497117404Skan    && ANY_QI_REG_P (operands[0])
8498117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8499117404Skan    && !(~INTVAL (operands[2]) & ~255)
8500117404Skan    && !(INTVAL (operands[2]) & 128)
8501117404Skan    && GET_MODE (operands[0]) != QImode"
8502117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
8503117404Skan		   (and:QI (match_dup 1)
8504117404Skan			   (match_dup 2)))
8505169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8506117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
8507117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
8508117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
850918334Speter
851090286Sobrien;; Logical inclusive OR instructions
851118334Speter
851290286Sobrien;; %%% This used to optimize known byte-wide and operations to memory.
851390286Sobrien;; If this is considered useful, it should be done with splitters.
851490286Sobrien
851590286Sobrien(define_expand "iordi3"
851690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
851790286Sobrien	(ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
851890286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "")))
8519169699Skan   (clobber (reg:CC FLAGS_REG))]
852090286Sobrien  "TARGET_64BIT"
852190286Sobrien  "ix86_expand_binary_operator (IOR, DImode, operands); DONE;")
852290286Sobrien
852390286Sobrien(define_insn "*iordi_1_rex64"
852490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
852590286Sobrien	(ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
852690286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "re,rme")))
8527169699Skan   (clobber (reg:CC FLAGS_REG))]
852890286Sobrien  "TARGET_64BIT
852990286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
853090286Sobrien  "or{q}\t{%2, %0|%0, %2}"
853190286Sobrien  [(set_attr "type" "alu")
853290286Sobrien   (set_attr "mode" "DI")])
853390286Sobrien
853490286Sobrien(define_insn "*iordi_2_rex64"
8535169699Skan  [(set (reg FLAGS_REG)
853690286Sobrien	(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
853790286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
853890286Sobrien		 (const_int 0)))
853990286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
854090286Sobrien	(ior:DI (match_dup 1) (match_dup 2)))]
854190286Sobrien  "TARGET_64BIT
854290286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
854390286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
854490286Sobrien  "or{q}\t{%2, %0|%0, %2}"
854590286Sobrien  [(set_attr "type" "alu")
854690286Sobrien   (set_attr "mode" "DI")])
854790286Sobrien
854890286Sobrien(define_insn "*iordi_3_rex64"
8549169699Skan  [(set (reg FLAGS_REG)
855090286Sobrien	(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
855190286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem"))
855290286Sobrien		 (const_int 0)))
855390286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
855490286Sobrien  "TARGET_64BIT
855590286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
855690286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
855790286Sobrien  "or{q}\t{%2, %0|%0, %2}"
855890286Sobrien  [(set_attr "type" "alu")
855990286Sobrien   (set_attr "mode" "DI")])
856090286Sobrien
856190286Sobrien
856290286Sobrien(define_expand "iorsi3"
856390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
856490286Sobrien	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
856590286Sobrien		(match_operand:SI 2 "general_operand" "")))
8566169699Skan   (clobber (reg:CC FLAGS_REG))]
856790286Sobrien  ""
856890286Sobrien  "ix86_expand_binary_operator (IOR, SImode, operands); DONE;")
856990286Sobrien
857090286Sobrien(define_insn "*iorsi_1"
857150650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
857250650Sobrien	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
857390286Sobrien		(match_operand:SI 2 "general_operand" "ri,rmi")))
8574169699Skan   (clobber (reg:CC FLAGS_REG))]
857590286Sobrien  "ix86_binary_operator_ok (IOR, SImode, operands)"
857690286Sobrien  "or{l}\t{%2, %0|%0, %2}"
857790286Sobrien  [(set_attr "type" "alu")
857890286Sobrien   (set_attr "mode" "SI")])
857950650Sobrien
858090286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
858190286Sobrien(define_insn "*iorsi_1_zext"
858290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm")
858390286Sobrien	(zero_extend:DI
858490286Sobrien	  (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
858590286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8586169699Skan   (clobber (reg:CC FLAGS_REG))]
858790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)"
858890286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
858990286Sobrien  [(set_attr "type" "alu")
859090286Sobrien   (set_attr "mode" "SI")])
859150650Sobrien
859290286Sobrien(define_insn "*iorsi_1_zext_imm"
859390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm")
859490286Sobrien	(ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
859590286Sobrien		(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
8596169699Skan   (clobber (reg:CC FLAGS_REG))]
859790286Sobrien  "TARGET_64BIT"
859890286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
859990286Sobrien  [(set_attr "type" "alu")
860090286Sobrien   (set_attr "mode" "SI")])
860150650Sobrien
860290286Sobrien(define_insn "*iorsi_2"
8603169699Skan  [(set (reg FLAGS_REG)
860490286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
860590286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
860690286Sobrien		 (const_int 0)))
860790286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
860890286Sobrien	(ior:SI (match_dup 1) (match_dup 2)))]
860990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
861090286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
861190286Sobrien  "or{l}\t{%2, %0|%0, %2}"
861290286Sobrien  [(set_attr "type" "alu")
861390286Sobrien   (set_attr "mode" "SI")])
861450650Sobrien
861590286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
861690286Sobrien;; ??? Special case for immediate operand is missing - it is tricky.
861790286Sobrien(define_insn "*iorsi_2_zext"
8618169699Skan  [(set (reg FLAGS_REG)
861990286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
862090286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
862190286Sobrien		 (const_int 0)))
862290286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
862390286Sobrien	(zero_extend:DI (ior:SI (match_dup 1) (match_dup 2))))]
862490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
862590286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
862690286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
862790286Sobrien  [(set_attr "type" "alu")
862890286Sobrien   (set_attr "mode" "SI")])
862950650Sobrien
863090286Sobrien(define_insn "*iorsi_2_zext_imm"
8631169699Skan  [(set (reg FLAGS_REG)
863290286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
863390286Sobrien			 (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
863490286Sobrien		 (const_int 0)))
863590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
863690286Sobrien	(ior:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
863790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
863890286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
863990286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
864090286Sobrien  [(set_attr "type" "alu")
864190286Sobrien   (set_attr "mode" "SI")])
864250650Sobrien
864390286Sobrien(define_insn "*iorsi_3"
8644169699Skan  [(set (reg FLAGS_REG)
864590286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
864690286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
864790286Sobrien		 (const_int 0)))
864890286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
864990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
865090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
865190286Sobrien  "or{l}\t{%2, %0|%0, %2}"
865290286Sobrien  [(set_attr "type" "alu")
865390286Sobrien   (set_attr "mode" "SI")])
865450650Sobrien
865590286Sobrien(define_expand "iorhi3"
865690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
865790286Sobrien	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "")
865890286Sobrien		(match_operand:HI 2 "general_operand" "")))
8659169699Skan   (clobber (reg:CC FLAGS_REG))]
866090286Sobrien  "TARGET_HIMODE_MATH"
866190286Sobrien  "ix86_expand_binary_operator (IOR, HImode, operands); DONE;")
866250650Sobrien
866390286Sobrien(define_insn "*iorhi_1"
866490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
866590286Sobrien	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
866690286Sobrien		(match_operand:HI 2 "general_operand" "rmi,ri")))
8667169699Skan   (clobber (reg:CC FLAGS_REG))]
866890286Sobrien  "ix86_binary_operator_ok (IOR, HImode, operands)"
866990286Sobrien  "or{w}\t{%2, %0|%0, %2}"
867090286Sobrien  [(set_attr "type" "alu")
867190286Sobrien   (set_attr "mode" "HI")])
867218334Speter
867390286Sobrien(define_insn "*iorhi_2"
8674169699Skan  [(set (reg FLAGS_REG)
867590286Sobrien	(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
867690286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
867790286Sobrien		 (const_int 0)))
867890286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
867990286Sobrien	(ior:HI (match_dup 1) (match_dup 2)))]
868090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
868190286Sobrien   && ix86_binary_operator_ok (IOR, HImode, operands)"
868290286Sobrien  "or{w}\t{%2, %0|%0, %2}"
868390286Sobrien  [(set_attr "type" "alu")
868490286Sobrien   (set_attr "mode" "HI")])
868518334Speter
868690286Sobrien(define_insn "*iorhi_3"
8687169699Skan  [(set (reg FLAGS_REG)
868890286Sobrien	(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
868990286Sobrien			 (match_operand:HI 2 "general_operand" "rim"))
869090286Sobrien		 (const_int 0)))
869190286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
869290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
869390286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
869490286Sobrien  "or{w}\t{%2, %0|%0, %2}"
869590286Sobrien  [(set_attr "type" "alu")
869690286Sobrien   (set_attr "mode" "HI")])
869750650Sobrien
869890286Sobrien(define_expand "iorqi3"
869990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
870090286Sobrien	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "")
870190286Sobrien		(match_operand:QI 2 "general_operand" "")))
8702169699Skan   (clobber (reg:CC FLAGS_REG))]
870390286Sobrien  "TARGET_QIMODE_MATH"
870490286Sobrien  "ix86_expand_binary_operator (IOR, QImode, operands); DONE;")
870518334Speter
870690286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
870790286Sobrien(define_insn "*iorqi_1"
870890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
870990286Sobrien	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
871090286Sobrien		(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
8711169699Skan   (clobber (reg:CC FLAGS_REG))]
871290286Sobrien  "ix86_binary_operator_ok (IOR, QImode, operands)"
871390286Sobrien  "@
871490286Sobrien   or{b}\t{%2, %0|%0, %2}
871590286Sobrien   or{b}\t{%2, %0|%0, %2}
871690286Sobrien   or{l}\t{%k2, %k0|%k0, %k2}"
871790286Sobrien  [(set_attr "type" "alu")
871890286Sobrien   (set_attr "mode" "QI,QI,SI")])
871950650Sobrien
872090286Sobrien(define_insn "*iorqi_1_slp"
872190286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m"))
872290286Sobrien	(ior:QI (match_dup 0)
872390286Sobrien		(match_operand:QI 1 "general_operand" "qmi,qi")))
8724169699Skan   (clobber (reg:CC FLAGS_REG))]
8725117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8726117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
872790286Sobrien  "or{b}\t{%1, %0|%0, %1}"
872890286Sobrien  [(set_attr "type" "alu1")
872990286Sobrien   (set_attr "mode" "QI")])
873018334Speter
873190286Sobrien(define_insn "*iorqi_2"
8732169699Skan  [(set (reg FLAGS_REG)
873390286Sobrien	(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
873490286Sobrien			 (match_operand:QI 2 "general_operand" "qim,qi"))
873590286Sobrien		 (const_int 0)))
873690286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
873790286Sobrien	(ior:QI (match_dup 1) (match_dup 2)))]
873890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
873990286Sobrien   && ix86_binary_operator_ok (IOR, QImode, operands)"
874090286Sobrien  "or{b}\t{%2, %0|%0, %2}"
874190286Sobrien  [(set_attr "type" "alu")
874290286Sobrien   (set_attr "mode" "QI")])
874318334Speter
874490286Sobrien(define_insn "*iorqi_2_slp"
8745169699Skan  [(set (reg FLAGS_REG)
874690286Sobrien	(compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
874790286Sobrien			 (match_operand:QI 1 "general_operand" "qim,qi"))
874890286Sobrien		 (const_int 0)))
874990286Sobrien   (set (strict_low_part (match_dup 0))
875090286Sobrien	(ior:QI (match_dup 0) (match_dup 1)))]
8751117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8752117404Skan   && ix86_match_ccmode (insn, CCNOmode)
8753117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
875490286Sobrien  "or{b}\t{%1, %0|%0, %1}"
875590286Sobrien  [(set_attr "type" "alu1")
875690286Sobrien   (set_attr "mode" "QI")])
875718334Speter
875890286Sobrien(define_insn "*iorqi_3"
8759169699Skan  [(set (reg FLAGS_REG)
876090286Sobrien	(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
876190286Sobrien			 (match_operand:QI 2 "general_operand" "qim"))
876290286Sobrien		 (const_int 0)))
876390286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
876490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
876590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
876690286Sobrien  "or{b}\t{%2, %0|%0, %2}"
876790286Sobrien  [(set_attr "type" "alu")
876890286Sobrien   (set_attr "mode" "QI")])
876918334Speter
8770117404Skan(define_insn "iorqi_ext_0"
8771117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8772117404Skan			 (const_int 8)
8773117404Skan			 (const_int 8))
8774117404Skan	(ior:SI 
8775117404Skan	  (zero_extract:SI
8776117404Skan	    (match_operand 1 "ext_register_operand" "0")
8777117404Skan	    (const_int 8)
8778117404Skan	    (const_int 8))
8779117404Skan	  (match_operand 2 "const_int_operand" "n")))
8780169699Skan   (clobber (reg:CC FLAGS_REG))]
8781117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
8782117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8783117404Skan  [(set_attr "type" "alu")
8784117404Skan   (set_attr "length_immediate" "1")
8785117404Skan   (set_attr "mode" "QI")])
8786117404Skan
8787117404Skan(define_insn "*iorqi_ext_1"
8788117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8789117404Skan			 (const_int 8)
8790117404Skan			 (const_int 8))
8791117404Skan	(ior:SI 
8792117404Skan	  (zero_extract:SI
8793117404Skan	    (match_operand 1 "ext_register_operand" "0")
8794117404Skan	    (const_int 8)
8795117404Skan	    (const_int 8))
8796117404Skan	  (zero_extend:SI
8797117404Skan	    (match_operand:QI 2 "general_operand" "Qm"))))
8798169699Skan   (clobber (reg:CC FLAGS_REG))]
8799117404Skan  "!TARGET_64BIT
8800117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
8801117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8802117404Skan  [(set_attr "type" "alu")
8803117404Skan   (set_attr "length_immediate" "0")
8804117404Skan   (set_attr "mode" "QI")])
8805117404Skan
8806117404Skan(define_insn "*iorqi_ext_1_rex64"
8807117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8808117404Skan			 (const_int 8)
8809117404Skan			 (const_int 8))
8810117404Skan	(ior:SI 
8811117404Skan	  (zero_extract:SI
8812117404Skan	    (match_operand 1 "ext_register_operand" "0")
8813117404Skan	    (const_int 8)
8814117404Skan	    (const_int 8))
8815117404Skan	  (zero_extend:SI
8816117404Skan	    (match_operand 2 "ext_register_operand" "Q"))))
8817169699Skan   (clobber (reg:CC FLAGS_REG))]
8818117404Skan  "TARGET_64BIT
8819117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
8820117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8821117404Skan  [(set_attr "type" "alu")
8822117404Skan   (set_attr "length_immediate" "0")
8823117404Skan   (set_attr "mode" "QI")])
8824117404Skan
8825117404Skan(define_insn "*iorqi_ext_2"
8826117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8827117404Skan			 (const_int 8)
8828117404Skan			 (const_int 8))
8829117404Skan	(ior:SI 
8830117404Skan	  (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
8831117404Skan	  		   (const_int 8)
8832117404Skan			   (const_int 8))
8833117404Skan	  (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
8834117404Skan	  		   (const_int 8)
8835117404Skan			   (const_int 8))))
8836169699Skan   (clobber (reg:CC FLAGS_REG))]
8837117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
8838117404Skan  "ior{b}\t{%h2, %h0|%h0, %h2}"
8839117404Skan  [(set_attr "type" "alu")
8840117404Skan   (set_attr "length_immediate" "0")
8841117404Skan   (set_attr "mode" "QI")])
8842117404Skan
8843117404Skan(define_split
8844117404Skan  [(set (match_operand 0 "register_operand" "")
8845117404Skan	(ior (match_operand 1 "register_operand" "")
8846117404Skan	     (match_operand 2 "const_int_operand" "")))
8847169699Skan   (clobber (reg:CC FLAGS_REG))]
8848117404Skan   "reload_completed
8849117404Skan    && QI_REG_P (operands[0])
8850117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8851117404Skan    && !(INTVAL (operands[2]) & ~(255 << 8))
8852117404Skan    && GET_MODE (operands[0]) != QImode"
8853117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
8854117404Skan		   (ior:SI (zero_extract:SI (match_dup 1)
8855117404Skan					    (const_int 8) (const_int 8))
8856117404Skan			   (match_dup 2)))
8857169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8858117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
8859117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
8860117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
8861117404Skan
8862117404Skan;; Since OR can be encoded with sign extended immediate, this is only
8863117404Skan;; profitable when 7th bit is set.
8864117404Skan(define_split
8865117404Skan  [(set (match_operand 0 "register_operand" "")
8866117404Skan	(ior (match_operand 1 "general_operand" "")
8867117404Skan	     (match_operand 2 "const_int_operand" "")))
8868169699Skan   (clobber (reg:CC FLAGS_REG))]
8869117404Skan   "reload_completed
8870117404Skan    && ANY_QI_REG_P (operands[0])
8871117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8872117404Skan    && !(INTVAL (operands[2]) & ~255)
8873117404Skan    && (INTVAL (operands[2]) & 128)
8874117404Skan    && GET_MODE (operands[0]) != QImode"
8875117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
8876117404Skan		   (ior:QI (match_dup 1)
8877117404Skan			   (match_dup 2)))
8878169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8879117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
8880117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
8881117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
888290286Sobrien
888390286Sobrien;; Logical XOR instructions
888490286Sobrien
888590286Sobrien;; %%% This used to optimize known byte-wide and operations to memory.
888690286Sobrien;; If this is considered useful, it should be done with splitters.
888790286Sobrien
888890286Sobrien(define_expand "xordi3"
888990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
889090286Sobrien	(xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
889190286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "")))
8892169699Skan   (clobber (reg:CC FLAGS_REG))]
889390286Sobrien  "TARGET_64BIT"
889490286Sobrien  "ix86_expand_binary_operator (XOR, DImode, operands); DONE;")
889590286Sobrien
889690286Sobrien(define_insn "*xordi_1_rex64"
889790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
889890286Sobrien	(xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
889990286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
8900169699Skan   (clobber (reg:CC FLAGS_REG))]
890190286Sobrien  "TARGET_64BIT
890290286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
890390286Sobrien  "@
8904169699Skan   xor{q}\t{%2, %0|%0, %2}
890590286Sobrien   xor{q}\t{%2, %0|%0, %2}"
890690286Sobrien  [(set_attr "type" "alu")
890790286Sobrien   (set_attr "mode" "DI,DI")])
890890286Sobrien
890990286Sobrien(define_insn "*xordi_2_rex64"
8910169699Skan  [(set (reg FLAGS_REG)
891190286Sobrien	(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
891290286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
891390286Sobrien		 (const_int 0)))
891490286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
891590286Sobrien	(xor:DI (match_dup 1) (match_dup 2)))]
891690286Sobrien  "TARGET_64BIT
891790286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
891890286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
891990286Sobrien  "@
8920169699Skan   xor{q}\t{%2, %0|%0, %2}
892190286Sobrien   xor{q}\t{%2, %0|%0, %2}"
892290286Sobrien  [(set_attr "type" "alu")
892390286Sobrien   (set_attr "mode" "DI,DI")])
892490286Sobrien
892590286Sobrien(define_insn "*xordi_3_rex64"
8926169699Skan  [(set (reg FLAGS_REG)
892790286Sobrien	(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
892890286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem"))
892990286Sobrien		 (const_int 0)))
893090286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
893190286Sobrien  "TARGET_64BIT
893290286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
893390286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
893490286Sobrien  "xor{q}\t{%2, %0|%0, %2}"
893590286Sobrien  [(set_attr "type" "alu")
893690286Sobrien   (set_attr "mode" "DI")])
893790286Sobrien
893890286Sobrien(define_expand "xorsi3"
893990286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
894090286Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "")
894190286Sobrien		(match_operand:SI 2 "general_operand" "")))
8942169699Skan   (clobber (reg:CC FLAGS_REG))]
894318334Speter  ""
894490286Sobrien  "ix86_expand_binary_operator (XOR, SImode, operands); DONE;")
894518334Speter
894690286Sobrien(define_insn "*xorsi_1"
894790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
894890286Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
894990286Sobrien		(match_operand:SI 2 "general_operand" "ri,rm")))
8950169699Skan   (clobber (reg:CC FLAGS_REG))]
895190286Sobrien  "ix86_binary_operator_ok (XOR, SImode, operands)"
895290286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
895390286Sobrien  [(set_attr "type" "alu")
895490286Sobrien   (set_attr "mode" "SI")])
895518334Speter
895690286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
895790286Sobrien;; Add speccase for immediates
895890286Sobrien(define_insn "*xorsi_1_zext"
895990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
896090286Sobrien	(zero_extend:DI
896190286Sobrien	  (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
896290286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8963169699Skan   (clobber (reg:CC FLAGS_REG))]
896490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
896590286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
896690286Sobrien  [(set_attr "type" "alu")
896790286Sobrien   (set_attr "mode" "SI")])
896850650Sobrien
896990286Sobrien(define_insn "*xorsi_1_zext_imm"
897090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
897190286Sobrien	(xor:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
897290286Sobrien		(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
8973169699Skan   (clobber (reg:CC FLAGS_REG))]
897490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
897590286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
897690286Sobrien  [(set_attr "type" "alu")
897790286Sobrien   (set_attr "mode" "SI")])
897850650Sobrien
897990286Sobrien(define_insn "*xorsi_2"
8980169699Skan  [(set (reg FLAGS_REG)
898190286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
898290286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
898390286Sobrien		 (const_int 0)))
898490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
898590286Sobrien	(xor:SI (match_dup 1) (match_dup 2)))]
898690286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
898790286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
898890286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
898990286Sobrien  [(set_attr "type" "alu")
899090286Sobrien   (set_attr "mode" "SI")])
899150650Sobrien
899290286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
899390286Sobrien;; ??? Special case for immediate operand is missing - it is tricky.
899490286Sobrien(define_insn "*xorsi_2_zext"
8995169699Skan  [(set (reg FLAGS_REG)
899690286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
899790286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
899890286Sobrien		 (const_int 0)))
899990286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
900090286Sobrien	(zero_extend:DI (xor:SI (match_dup 1) (match_dup 2))))]
900190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
900290286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
900390286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
900490286Sobrien  [(set_attr "type" "alu")
900590286Sobrien   (set_attr "mode" "SI")])
900650650Sobrien
900790286Sobrien(define_insn "*xorsi_2_zext_imm"
9008169699Skan  [(set (reg FLAGS_REG)
900990286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
901090286Sobrien			 (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
901190286Sobrien		 (const_int 0)))
901290286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
901390286Sobrien	(xor:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
901490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
901590286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
901690286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
901790286Sobrien  [(set_attr "type" "alu")
901890286Sobrien   (set_attr "mode" "SI")])
901950650Sobrien
902090286Sobrien(define_insn "*xorsi_3"
9021169699Skan  [(set (reg FLAGS_REG)
902290286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
902390286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
902490286Sobrien		 (const_int 0)))
902590286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
902690286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
902790286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
902890286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
902990286Sobrien  [(set_attr "type" "alu")
903090286Sobrien   (set_attr "mode" "SI")])
903118334Speter
903290286Sobrien(define_expand "xorhi3"
903390286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
903490286Sobrien	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "")
903590286Sobrien		(match_operand:HI 2 "general_operand" "")))
9036169699Skan   (clobber (reg:CC FLAGS_REG))]
903790286Sobrien  "TARGET_HIMODE_MATH"
903890286Sobrien  "ix86_expand_binary_operator (XOR, HImode, operands); DONE;")
903918334Speter
904090286Sobrien(define_insn "*xorhi_1"
904190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
904290286Sobrien	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
904390286Sobrien		(match_operand:HI 2 "general_operand" "rmi,ri")))
9044169699Skan   (clobber (reg:CC FLAGS_REG))]
904590286Sobrien  "ix86_binary_operator_ok (XOR, HImode, operands)"
904690286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
904790286Sobrien  [(set_attr "type" "alu")
904890286Sobrien   (set_attr "mode" "HI")])
904918334Speter
905090286Sobrien(define_insn "*xorhi_2"
9051169699Skan  [(set (reg FLAGS_REG)
905290286Sobrien	(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
905390286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
905490286Sobrien		 (const_int 0)))
905590286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
905690286Sobrien	(xor:HI (match_dup 1) (match_dup 2)))]
905790286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
905890286Sobrien   && ix86_binary_operator_ok (XOR, HImode, operands)"
905990286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
906090286Sobrien  [(set_attr "type" "alu")
906190286Sobrien   (set_attr "mode" "HI")])
906250650Sobrien
906390286Sobrien(define_insn "*xorhi_3"
9064169699Skan  [(set (reg FLAGS_REG)
906590286Sobrien	(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
906690286Sobrien			 (match_operand:HI 2 "general_operand" "rim"))
906790286Sobrien		 (const_int 0)))
906890286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
906990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
907090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
907190286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
907290286Sobrien  [(set_attr "type" "alu")
907390286Sobrien   (set_attr "mode" "HI")])
907450650Sobrien
907590286Sobrien(define_expand "xorqi3"
907690286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
907790286Sobrien	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "")
907890286Sobrien		(match_operand:QI 2 "general_operand" "")))
9079169699Skan   (clobber (reg:CC FLAGS_REG))]
908090286Sobrien  "TARGET_QIMODE_MATH"
908190286Sobrien  "ix86_expand_binary_operator (XOR, QImode, operands); DONE;")
908250650Sobrien
908390286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
908490286Sobrien(define_insn "*xorqi_1"
908590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
908690286Sobrien	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
908790286Sobrien		(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
9088169699Skan   (clobber (reg:CC FLAGS_REG))]
908990286Sobrien  "ix86_binary_operator_ok (XOR, QImode, operands)"
909090286Sobrien  "@
909190286Sobrien   xor{b}\t{%2, %0|%0, %2}
909290286Sobrien   xor{b}\t{%2, %0|%0, %2}
909390286Sobrien   xor{l}\t{%k2, %k0|%k0, %k2}"
909490286Sobrien  [(set_attr "type" "alu")
909590286Sobrien   (set_attr "mode" "QI,QI,SI")])
909618334Speter
9097117404Skan(define_insn "*xorqi_1_slp"
9098117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
9099117404Skan	(xor:QI (match_dup 0)
9100117404Skan		(match_operand:QI 1 "general_operand" "qi,qmi")))
9101169699Skan   (clobber (reg:CC FLAGS_REG))]
9102117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
9103117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
9104117404Skan  "xor{b}\t{%1, %0|%0, %1}"
9105117404Skan  [(set_attr "type" "alu1")
9106117404Skan   (set_attr "mode" "QI")])
9107117404Skan
9108117404Skan(define_insn "xorqi_ext_0"
9109117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9110117404Skan			 (const_int 8)
9111117404Skan			 (const_int 8))
9112117404Skan	(xor:SI 
9113117404Skan	  (zero_extract:SI
9114117404Skan	    (match_operand 1 "ext_register_operand" "0")
9115117404Skan	    (const_int 8)
9116117404Skan	    (const_int 8))
9117117404Skan	  (match_operand 2 "const_int_operand" "n")))
9118169699Skan   (clobber (reg:CC FLAGS_REG))]
9119117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
9120117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9121117404Skan  [(set_attr "type" "alu")
9122117404Skan   (set_attr "length_immediate" "1")
9123117404Skan   (set_attr "mode" "QI")])
9124117404Skan
912590286Sobrien(define_insn "*xorqi_ext_1"
912690286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
912790286Sobrien			 (const_int 8)
912890286Sobrien			 (const_int 8))
912990286Sobrien	(xor:SI 
9130117404Skan	  (zero_extract:SI
9131117404Skan	    (match_operand 1 "ext_register_operand" "0")
9132117404Skan	    (const_int 8)
9133117404Skan	    (const_int 8))
9134117404Skan	  (zero_extend:SI
9135117404Skan	    (match_operand:QI 2 "general_operand" "Qm"))))
9136169699Skan   (clobber (reg:CC FLAGS_REG))]
9137117404Skan  "!TARGET_64BIT
9138117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
9139117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9140117404Skan  [(set_attr "type" "alu")
9141117404Skan   (set_attr "length_immediate" "0")
9142117404Skan   (set_attr "mode" "QI")])
9143117404Skan
9144117404Skan(define_insn "*xorqi_ext_1_rex64"
9145117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9146117404Skan			 (const_int 8)
9147117404Skan			 (const_int 8))
9148117404Skan	(xor:SI 
9149117404Skan	  (zero_extract:SI
9150117404Skan	    (match_operand 1 "ext_register_operand" "0")
9151117404Skan	    (const_int 8)
9152117404Skan	    (const_int 8))
9153117404Skan	  (zero_extend:SI
9154117404Skan	    (match_operand 2 "ext_register_operand" "Q"))))
9155169699Skan   (clobber (reg:CC FLAGS_REG))]
9156117404Skan  "TARGET_64BIT
9157117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
9158117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9159117404Skan  [(set_attr "type" "alu")
9160117404Skan   (set_attr "length_immediate" "0")
9161117404Skan   (set_attr "mode" "QI")])
9162117404Skan
9163117404Skan(define_insn "*xorqi_ext_2"
9164117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9165117404Skan			 (const_int 8)
9166117404Skan			 (const_int 8))
9167117404Skan	(xor:SI 
916890286Sobrien	  (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
916990286Sobrien	  		   (const_int 8)
917090286Sobrien			   (const_int 8))
917190286Sobrien	  (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
917290286Sobrien	  		   (const_int 8)
917390286Sobrien			   (const_int 8))))
9174169699Skan   (clobber (reg:CC FLAGS_REG))]
9175117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
917690286Sobrien  "xor{b}\t{%h2, %h0|%h0, %h2}"
917790286Sobrien  [(set_attr "type" "alu")
917890286Sobrien   (set_attr "length_immediate" "0")
917990286Sobrien   (set_attr "mode" "QI")])
918050650Sobrien
918190286Sobrien(define_insn "*xorqi_cc_1"
9182169699Skan  [(set (reg FLAGS_REG)
918390286Sobrien	(compare
918490286Sobrien	  (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
918590286Sobrien		  (match_operand:QI 2 "general_operand" "qim,qi"))
918690286Sobrien	  (const_int 0)))
918790286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
918890286Sobrien	(xor:QI (match_dup 1) (match_dup 2)))]
918990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
919090286Sobrien   && ix86_binary_operator_ok (XOR, QImode, operands)"
919190286Sobrien  "xor{b}\t{%2, %0|%0, %2}"
919290286Sobrien  [(set_attr "type" "alu")
919390286Sobrien   (set_attr "mode" "QI")])
919450650Sobrien
9195117404Skan(define_insn "*xorqi_2_slp"
9196169699Skan  [(set (reg FLAGS_REG)
9197117404Skan	(compare (xor:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
9198117404Skan			 (match_operand:QI 1 "general_operand" "qim,qi"))
9199117404Skan		 (const_int 0)))
9200117404Skan   (set (strict_low_part (match_dup 0))
9201117404Skan	(xor:QI (match_dup 0) (match_dup 1)))]
9202117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
9203117404Skan   && ix86_match_ccmode (insn, CCNOmode)
9204117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
9205117404Skan  "xor{b}\t{%1, %0|%0, %1}"
9206117404Skan  [(set_attr "type" "alu1")
9207117404Skan   (set_attr "mode" "QI")])
9208117404Skan
920990286Sobrien(define_insn "*xorqi_cc_2"
9210169699Skan  [(set (reg FLAGS_REG)
921190286Sobrien	(compare
921290286Sobrien	  (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
921390286Sobrien		  (match_operand:QI 2 "general_operand" "qim"))
921490286Sobrien	  (const_int 0)))
921590286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
921690286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
921790286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
921890286Sobrien  "xor{b}\t{%2, %0|%0, %2}"
921990286Sobrien  [(set_attr "type" "alu")
922090286Sobrien   (set_attr "mode" "QI")])
922118334Speter
922290286Sobrien(define_insn "*xorqi_cc_ext_1"
9223169699Skan  [(set (reg FLAGS_REG)
922490286Sobrien	(compare
922590286Sobrien	  (xor:SI
922690286Sobrien	    (zero_extract:SI
922790286Sobrien	      (match_operand 1 "ext_register_operand" "0")
922890286Sobrien	      (const_int 8)
922990286Sobrien	      (const_int 8))
923090286Sobrien	    (match_operand:QI 2 "general_operand" "qmn"))
923190286Sobrien	  (const_int 0)))
923290286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=q")
923390286Sobrien			 (const_int 8)
923490286Sobrien			 (const_int 8))
923590286Sobrien	(xor:SI 
923690286Sobrien	  (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
923790286Sobrien	  (match_dup 2)))]
923890286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
923990286Sobrien  "xor{b}\t{%2, %h0|%h0, %2}"
924090286Sobrien  [(set_attr "type" "alu")
924190286Sobrien   (set_attr "mode" "QI")])
924290286Sobrien
924390286Sobrien(define_insn "*xorqi_cc_ext_1_rex64"
9244169699Skan  [(set (reg FLAGS_REG)
924590286Sobrien	(compare
924690286Sobrien	  (xor:SI
924790286Sobrien	    (zero_extract:SI
924890286Sobrien	      (match_operand 1 "ext_register_operand" "0")
924990286Sobrien	      (const_int 8)
925090286Sobrien	      (const_int 8))
925190286Sobrien	    (match_operand:QI 2 "nonmemory_operand" "Qn"))
925290286Sobrien	  (const_int 0)))
925390286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
925490286Sobrien			 (const_int 8)
925590286Sobrien			 (const_int 8))
925690286Sobrien	(xor:SI 
925790286Sobrien	  (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
925890286Sobrien	  (match_dup 2)))]
925990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
926090286Sobrien  "xor{b}\t{%2, %h0|%h0, %2}"
926190286Sobrien  [(set_attr "type" "alu")
926290286Sobrien   (set_attr "mode" "QI")])
926390286Sobrien
926490286Sobrien(define_expand "xorqi_cc_ext_1"
926590286Sobrien  [(parallel [
9266169699Skan     (set (reg:CCNO FLAGS_REG)
926790286Sobrien	  (compare:CCNO
926890286Sobrien	    (xor:SI
926990286Sobrien	      (zero_extract:SI
927090286Sobrien		(match_operand 1 "ext_register_operand" "")
927190286Sobrien		(const_int 8)
927290286Sobrien		(const_int 8))
927390286Sobrien	      (match_operand:QI 2 "general_operand" ""))
927490286Sobrien	    (const_int 0)))
927590286Sobrien     (set (zero_extract:SI (match_operand 0 "ext_register_operand" "")
927690286Sobrien			   (const_int 8)
927790286Sobrien			   (const_int 8))
927890286Sobrien	  (xor:SI 
927990286Sobrien	    (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
928090286Sobrien	    (match_dup 2)))])]
928118334Speter  ""
928290286Sobrien  "")
9283117404Skan
9284117404Skan(define_split
9285117404Skan  [(set (match_operand 0 "register_operand" "")
9286117404Skan	(xor (match_operand 1 "register_operand" "")
9287117404Skan	     (match_operand 2 "const_int_operand" "")))
9288169699Skan   (clobber (reg:CC FLAGS_REG))]
9289117404Skan   "reload_completed
9290117404Skan    && QI_REG_P (operands[0])
9291117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
9292117404Skan    && !(INTVAL (operands[2]) & ~(255 << 8))
9293117404Skan    && GET_MODE (operands[0]) != QImode"
9294117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
9295117404Skan		   (xor:SI (zero_extract:SI (match_dup 1)
9296117404Skan					    (const_int 8) (const_int 8))
9297117404Skan			   (match_dup 2)))
9298169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9299117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
9300117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
9301117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
9302117404Skan
9303117404Skan;; Since XOR can be encoded with sign extended immediate, this is only
9304117404Skan;; profitable when 7th bit is set.
9305117404Skan(define_split
9306117404Skan  [(set (match_operand 0 "register_operand" "")
9307117404Skan	(xor (match_operand 1 "general_operand" "")
9308117404Skan	     (match_operand 2 "const_int_operand" "")))
9309169699Skan   (clobber (reg:CC FLAGS_REG))]
9310117404Skan   "reload_completed
9311117404Skan    && ANY_QI_REG_P (operands[0])
9312117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
9313117404Skan    && !(INTVAL (operands[2]) & ~255)
9314117404Skan    && (INTVAL (operands[2]) & 128)
9315117404Skan    && GET_MODE (operands[0]) != QImode"
9316117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
9317117404Skan		   (xor:QI (match_dup 1)
9318117404Skan			   (match_dup 2)))
9319169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9320117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
9321117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
9322117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
932318334Speter
932490286Sobrien;; Negation instructions
932518334Speter
9326169699Skan(define_expand "negti2"
9327169699Skan  [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
9328169699Skan		   (neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
9329169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9330169699Skan  "TARGET_64BIT"
9331169699Skan  "ix86_expand_unary_operator (NEG, TImode, operands); DONE;")
9332169699Skan
9333169699Skan(define_insn "*negti2_1"
9334169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=ro")
9335171835Skan	(neg:TI (match_operand:TI 1 "nonimmediate_operand" "0")))
9336169699Skan   (clobber (reg:CC FLAGS_REG))]
9337169699Skan  "TARGET_64BIT
9338169699Skan   && ix86_unary_operator_ok (NEG, TImode, operands)"
9339169699Skan  "#")
9340169699Skan
9341169699Skan(define_split
9342169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
9343171835Skan	(neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
9344169699Skan   (clobber (reg:CC FLAGS_REG))]
9345169699Skan  "TARGET_64BIT && reload_completed"
9346169699Skan  [(parallel
9347169699Skan    [(set (reg:CCZ FLAGS_REG)
9348169699Skan	  (compare:CCZ (neg:DI (match_dup 2)) (const_int 0)))
9349169699Skan     (set (match_dup 0) (neg:DI (match_dup 2)))])
9350169699Skan   (parallel
9351169699Skan    [(set (match_dup 1)
9352169699Skan	  (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
9353169699Skan			    (match_dup 3))
9354169699Skan		   (const_int 0)))
9355169699Skan     (clobber (reg:CC FLAGS_REG))])
9356169699Skan   (parallel
9357169699Skan    [(set (match_dup 1)
9358169699Skan	  (neg:DI (match_dup 1)))
9359169699Skan     (clobber (reg:CC FLAGS_REG))])]
9360169699Skan  "split_ti (operands+1, 1, operands+2, operands+3);
9361169699Skan   split_ti (operands+0, 1, operands+0, operands+1);")
9362169699Skan
936390286Sobrien(define_expand "negdi2"
936490286Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
936590286Sobrien		   (neg:DI (match_operand:DI 1 "nonimmediate_operand" "")))
9366169699Skan	      (clobber (reg:CC FLAGS_REG))])]
936718334Speter  ""
936890286Sobrien  "ix86_expand_unary_operator (NEG, DImode, operands); DONE;")
936950650Sobrien
937090286Sobrien(define_insn "*negdi2_1"
937190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=ro")
937290286Sobrien	(neg:DI (match_operand:DI 1 "general_operand" "0")))
9373169699Skan   (clobber (reg:CC FLAGS_REG))]
937490286Sobrien  "!TARGET_64BIT
937590286Sobrien   && ix86_unary_operator_ok (NEG, DImode, operands)"
937690286Sobrien  "#")
937750650Sobrien
937890286Sobrien(define_split
937990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
938090286Sobrien	(neg:DI (match_operand:DI 1 "general_operand" "")))
9381169699Skan   (clobber (reg:CC FLAGS_REG))]
938290286Sobrien  "!TARGET_64BIT && reload_completed"
938390286Sobrien  [(parallel
9384169699Skan    [(set (reg:CCZ FLAGS_REG)
938590286Sobrien	  (compare:CCZ (neg:SI (match_dup 2)) (const_int 0)))
938690286Sobrien     (set (match_dup 0) (neg:SI (match_dup 2)))])
938790286Sobrien   (parallel
938890286Sobrien    [(set (match_dup 1)
9389169699Skan	  (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
939090286Sobrien			    (match_dup 3))
939190286Sobrien		   (const_int 0)))
9392169699Skan     (clobber (reg:CC FLAGS_REG))])
939390286Sobrien   (parallel
939490286Sobrien    [(set (match_dup 1)
939590286Sobrien	  (neg:SI (match_dup 1)))
9396169699Skan     (clobber (reg:CC FLAGS_REG))])]
939790286Sobrien  "split_di (operands+1, 1, operands+2, operands+3);
939890286Sobrien   split_di (operands+0, 1, operands+0, operands+1);")
939950650Sobrien
940090286Sobrien(define_insn "*negdi2_1_rex64"
940190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
940290286Sobrien	(neg:DI (match_operand:DI 1 "nonimmediate_operand" "0")))
9403169699Skan   (clobber (reg:CC FLAGS_REG))]
940490286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
940590286Sobrien  "neg{q}\t%0"
940690286Sobrien  [(set_attr "type" "negnot")
940790286Sobrien   (set_attr "mode" "DI")])
940850650Sobrien
940990286Sobrien;; The problem with neg is that it does not perform (compare x 0),
941090286Sobrien;; it really performs (compare 0 x), which leaves us with the zero
941190286Sobrien;; flag being the only useful item.
941250650Sobrien
941390286Sobrien(define_insn "*negdi2_cmpz_rex64"
9414169699Skan  [(set (reg:CCZ FLAGS_REG)
941590286Sobrien	(compare:CCZ (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
941690286Sobrien		     (const_int 0)))
941790286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
941890286Sobrien	(neg:DI (match_dup 1)))]
941990286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
942090286Sobrien  "neg{q}\t%0"
942190286Sobrien  [(set_attr "type" "negnot")
942290286Sobrien   (set_attr "mode" "DI")])
942350650Sobrien
942418334Speter
942590286Sobrien(define_expand "negsi2"
942690286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
942790286Sobrien		   (neg:SI (match_operand:SI 1 "nonimmediate_operand" "")))
9428169699Skan	      (clobber (reg:CC FLAGS_REG))])]
942990286Sobrien  ""
943090286Sobrien  "ix86_expand_unary_operator (NEG, SImode, operands); DONE;")
943118334Speter
943290286Sobrien(define_insn "*negsi2_1"
943390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
943490286Sobrien	(neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))
9435169699Skan   (clobber (reg:CC FLAGS_REG))]
943690286Sobrien  "ix86_unary_operator_ok (NEG, SImode, operands)"
943790286Sobrien  "neg{l}\t%0"
943890286Sobrien  [(set_attr "type" "negnot")
943990286Sobrien   (set_attr "mode" "SI")])
944050650Sobrien
944190286Sobrien;; Combine is quite creative about this pattern.
944290286Sobrien(define_insn "*negsi2_1_zext"
944390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
944490286Sobrien	(lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0")
944590286Sobrien					(const_int 32)))
944690286Sobrien		     (const_int 32)))
9447169699Skan   (clobber (reg:CC FLAGS_REG))]
944890286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
944990286Sobrien  "neg{l}\t%k0"
945090286Sobrien  [(set_attr "type" "negnot")
945190286Sobrien   (set_attr "mode" "SI")])
945250650Sobrien
945390286Sobrien;; The problem with neg is that it does not perform (compare x 0),
945490286Sobrien;; it really performs (compare 0 x), which leaves us with the zero
945590286Sobrien;; flag being the only useful item.
945618334Speter
945790286Sobrien(define_insn "*negsi2_cmpz"
9458169699Skan  [(set (reg:CCZ FLAGS_REG)
945990286Sobrien	(compare:CCZ (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
946090286Sobrien		     (const_int 0)))
946190286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
946290286Sobrien	(neg:SI (match_dup 1)))]
946390286Sobrien  "ix86_unary_operator_ok (NEG, SImode, operands)"
946490286Sobrien  "neg{l}\t%0"
946590286Sobrien  [(set_attr "type" "negnot")
946690286Sobrien   (set_attr "mode" "SI")])
946750650Sobrien
946890286Sobrien(define_insn "*negsi2_cmpz_zext"
9469169699Skan  [(set (reg:CCZ FLAGS_REG)
947090286Sobrien	(compare:CCZ (lshiftrt:DI
947190286Sobrien		       (neg:DI (ashift:DI
947290286Sobrien				 (match_operand:DI 1 "register_operand" "0")
947390286Sobrien				 (const_int 32)))
947490286Sobrien		       (const_int 32))
947590286Sobrien		     (const_int 0)))
947690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
947790286Sobrien	(lshiftrt:DI (neg:DI (ashift:DI (match_dup 1)
947890286Sobrien					(const_int 32)))
947990286Sobrien		     (const_int 32)))]
948090286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
948190286Sobrien  "neg{l}\t%k0"
948290286Sobrien  [(set_attr "type" "negnot")
948390286Sobrien   (set_attr "mode" "SI")])
948490286Sobrien
948590286Sobrien(define_expand "neghi2"
948690286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
948790286Sobrien		   (neg:HI (match_operand:HI 1 "nonimmediate_operand" "")))
9488169699Skan	      (clobber (reg:CC FLAGS_REG))])]
948990286Sobrien  "TARGET_HIMODE_MATH"
949090286Sobrien  "ix86_expand_unary_operator (NEG, HImode, operands); DONE;")
949190286Sobrien
949290286Sobrien(define_insn "*neghi2_1"
949390286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
949490286Sobrien	(neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))
9495169699Skan   (clobber (reg:CC FLAGS_REG))]
949690286Sobrien  "ix86_unary_operator_ok (NEG, HImode, operands)"
949790286Sobrien  "neg{w}\t%0"
949890286Sobrien  [(set_attr "type" "negnot")
949990286Sobrien   (set_attr "mode" "HI")])
950090286Sobrien
950190286Sobrien(define_insn "*neghi2_cmpz"
9502169699Skan  [(set (reg:CCZ FLAGS_REG)
950390286Sobrien	(compare:CCZ (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
950490286Sobrien		     (const_int 0)))
950590286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
950690286Sobrien	(neg:HI (match_dup 1)))]
950790286Sobrien  "ix86_unary_operator_ok (NEG, HImode, operands)"
950890286Sobrien  "neg{w}\t%0"
950990286Sobrien  [(set_attr "type" "negnot")
951090286Sobrien   (set_attr "mode" "HI")])
951190286Sobrien
951290286Sobrien(define_expand "negqi2"
951390286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
951490286Sobrien		   (neg:QI (match_operand:QI 1 "nonimmediate_operand" "")))
9515169699Skan	      (clobber (reg:CC FLAGS_REG))])]
951690286Sobrien  "TARGET_QIMODE_MATH"
951790286Sobrien  "ix86_expand_unary_operator (NEG, QImode, operands); DONE;")
951890286Sobrien
951990286Sobrien(define_insn "*negqi2_1"
952090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
952190286Sobrien	(neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))
9522169699Skan   (clobber (reg:CC FLAGS_REG))]
952390286Sobrien  "ix86_unary_operator_ok (NEG, QImode, operands)"
952490286Sobrien  "neg{b}\t%0"
952590286Sobrien  [(set_attr "type" "negnot")
952690286Sobrien   (set_attr "mode" "QI")])
952790286Sobrien
952890286Sobrien(define_insn "*negqi2_cmpz"
9529169699Skan  [(set (reg:CCZ FLAGS_REG)
953090286Sobrien	(compare:CCZ (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
953190286Sobrien		     (const_int 0)))
953290286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
953390286Sobrien	(neg:QI (match_dup 1)))]
953490286Sobrien  "ix86_unary_operator_ok (NEG, QImode, operands)"
953590286Sobrien  "neg{b}\t%0"
953690286Sobrien  [(set_attr "type" "negnot")
953790286Sobrien   (set_attr "mode" "QI")])
953890286Sobrien
953990286Sobrien;; Changing of sign for FP values is doable using integer unit too.
954090286Sobrien
954190286Sobrien(define_expand "negsf2"
9542169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
9543169699Skan	(neg:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
9544146906Skan  "TARGET_80387 || TARGET_SSE_MATH"
9545169699Skan  "ix86_expand_fp_absneg_operator (NEG, SFmode, operands); DONE;")
954618334Speter
9547169699Skan(define_expand "abssf2"
9548169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
9549169699Skan	(abs:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
9550169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
9551169699Skan  "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
955218334Speter
9553169699Skan(define_insn "*absnegsf2_mixed"
9554169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x  ,x,f,rm")
9555169699Skan	(match_operator:SF 3 "absneg_operator"
9556169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0   ,x,0,0 ")]))
9557169699Skan   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm  ,0,X,X "))
9558169699Skan   (clobber (reg:CC FLAGS_REG))]
9559169699Skan  "TARGET_SSE_MATH && TARGET_MIX_SSE_I387
9560169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
956190286Sobrien  "#")
956218334Speter
9563169699Skan(define_insn "*absnegsf2_sse"
9564169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x,x,rm")
9565169699Skan	(match_operator:SF 3 "absneg_operator"
9566169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0")]))
9567169699Skan   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm,0,X"))
9568169699Skan   (clobber (reg:CC FLAGS_REG))]
9569169699Skan  "TARGET_SSE_MATH
9570169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
957190286Sobrien  "#")
957218334Speter
9573169699Skan(define_insn "*absnegsf2_i387"
9574169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,rm")
9575169699Skan	(match_operator:SF 3 "absneg_operator"
9576169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0,0")]))
9577169699Skan   (use (match_operand 2 "" ""))
9578169699Skan   (clobber (reg:CC FLAGS_REG))]
9579169699Skan  "TARGET_80387 && !TARGET_SSE_MATH
9580169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
9581169699Skan  "#")
958290286Sobrien
9583169699Skan(define_expand "copysignsf3"
9584169699Skan  [(match_operand:SF 0 "register_operand" "")
9585169699Skan   (match_operand:SF 1 "nonmemory_operand" "")
9586169699Skan   (match_operand:SF 2 "register_operand" "")]
9587169699Skan  "TARGET_SSE_MATH"
9588169699Skan{
9589169699Skan  ix86_expand_copysign (operands);
9590169699Skan  DONE;
9591169699Skan})
959290286Sobrien
9593169699Skan(define_insn_and_split "copysignsf3_const"
9594169699Skan  [(set (match_operand:SF 0 "register_operand"          "=x")
9595169699Skan	(unspec:SF
9596169699Skan	  [(match_operand:V4SF 1 "vector_move_operand"  "xmC")
9597169699Skan	   (match_operand:SF 2 "register_operand"       "0")
9598169699Skan	   (match_operand:V4SF 3 "nonimmediate_operand" "xm")]
9599169699Skan	  UNSPEC_COPYSIGN))]
9600169699Skan  "TARGET_SSE_MATH"
9601169699Skan  "#"
9602169699Skan  "&& reload_completed"
9603169699Skan  [(const_int 0)]
960418334Speter{
9605169699Skan  ix86_split_copysign_const (operands);
9606169699Skan  DONE;
960790286Sobrien})
960818334Speter
9609169699Skan(define_insn "copysignsf3_var"
9610169699Skan  [(set (match_operand:SF 0 "register_operand"          "=x, x, x, x,x")
9611169699Skan	(unspec:SF
9612169699Skan	  [(match_operand:SF 2 "register_operand"       " x, 0, 0, x,x")
9613169699Skan	   (match_operand:SF 3 "register_operand"       " 1, 1, x, 1,x")
9614169699Skan	   (match_operand:V4SF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
9615169699Skan	   (match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
9616169699Skan	  UNSPEC_COPYSIGN))
9617169699Skan   (clobber (match_scratch:V4SF 1			"=x, x, x, x,x"))]
9618169699Skan  "TARGET_SSE_MATH"
961990286Sobrien  "#")
962018334Speter
962190286Sobrien(define_split
9622169699Skan  [(set (match_operand:SF 0 "register_operand" "")
9623169699Skan	(unspec:SF
9624169699Skan	  [(match_operand:SF 2 "register_operand" "")
9625169699Skan	   (match_operand:SF 3 "register_operand" "")
9626169699Skan	   (match_operand:V4SF 4 "" "")
9627169699Skan	   (match_operand:V4SF 5 "" "")]
9628169699Skan	  UNSPEC_COPYSIGN))
9629169699Skan   (clobber (match_scratch:V4SF 1 ""))]
9630169699Skan  "TARGET_SSE_MATH && reload_completed"
9631169699Skan  [(const_int 0)]
963290286Sobrien{
9633169699Skan  ix86_split_copysign_var (operands);
9634169699Skan  DONE;
963590286Sobrien})
963690286Sobrien
963790286Sobrien(define_expand "negdf2"
9638169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "")
9639169699Skan	(neg:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
9640146906Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
9641169699Skan  "ix86_expand_fp_absneg_operator (NEG, DFmode, operands); DONE;")
964218334Speter
9643169699Skan(define_expand "absdf2"
9644169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "")
9645169699Skan	(abs:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
9646169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
9647169699Skan  "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
964818334Speter
9649169699Skan(define_insn "*absnegdf2_mixed"
9650169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,f,rm")
9651169699Skan	(match_operator:DF 3 "absneg_operator"
9652169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0,0")]))
9653169699Skan   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X,X"))
9654169699Skan   (clobber (reg:CC FLAGS_REG))]
9655169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
9656169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
965790286Sobrien  "#")
965850650Sobrien
9659169699Skan(define_insn "*absnegdf2_sse"
9660169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,rm")
9661169699Skan	(match_operator:DF 3 "absneg_operator"
9662169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0 ")]))
9663169699Skan   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X "))
9664169699Skan   (clobber (reg:CC FLAGS_REG))]
9665169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
9666169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
966790286Sobrien  "#")
966850650Sobrien
9669169699Skan(define_insn "*absnegdf2_i387"
9670169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,rm")
9671169699Skan	(match_operator:DF 3 "absneg_operator"
9672169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0,0")]))
9673169699Skan   (use (match_operand 2 "" ""))
9674169699Skan   (clobber (reg:CC FLAGS_REG))]
9675169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
9676169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
967790286Sobrien  "#")
967818334Speter
9679169699Skan(define_expand "copysigndf3"
9680169699Skan  [(match_operand:DF 0 "register_operand" "")
9681169699Skan   (match_operand:DF 1 "nonmemory_operand" "")
9682169699Skan   (match_operand:DF 2 "register_operand" "")]
9683169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9684169699Skan{
9685169699Skan  ix86_expand_copysign (operands);
9686169699Skan  DONE;
9687169699Skan})
968850650Sobrien
9689169699Skan(define_insn_and_split "copysigndf3_const"
9690169699Skan  [(set (match_operand:DF 0 "register_operand"          "=x")
9691169699Skan	(unspec:DF
9692169699Skan	  [(match_operand:V2DF 1 "vector_move_operand"  "xmC")
9693169699Skan	   (match_operand:DF 2 "register_operand"       "0")
9694169699Skan	   (match_operand:V2DF 3 "nonimmediate_operand" "xm")]
9695169699Skan	  UNSPEC_COPYSIGN))]
9696169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9697169699Skan  "#"
9698169699Skan  "&& reload_completed"
9699169699Skan  [(const_int 0)]
9700169699Skan{
9701169699Skan  ix86_split_copysign_const (operands);
9702169699Skan  DONE;
9703169699Skan})
970450650Sobrien
9705169699Skan(define_insn "copysigndf3_var"
9706169699Skan  [(set (match_operand:DF 0 "register_operand"          "=x, x, x, x,x")
9707169699Skan	(unspec:DF
9708169699Skan	  [(match_operand:DF 2 "register_operand"       " x, 0, 0, x,x")
9709169699Skan	   (match_operand:DF 3 "register_operand"       " 1, 1, x, 1,x")
9710169699Skan	   (match_operand:V2DF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
9711169699Skan	   (match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
9712169699Skan	  UNSPEC_COPYSIGN))
9713169699Skan   (clobber (match_scratch:V2DF 1			"=x, x, x, x,x"))]
9714169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9715169699Skan  "#")
971652296Sobrien
971790286Sobrien(define_split
971890286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
9719169699Skan	(unspec:DF
9720169699Skan	  [(match_operand:DF 2 "register_operand" "")
9721169699Skan	   (match_operand:DF 3 "register_operand" "")
9722169699Skan	   (match_operand:V2DF 4 "" "")
9723169699Skan	   (match_operand:V2DF 5 "" "")]
9724169699Skan	  UNSPEC_COPYSIGN))
9725169699Skan   (clobber (match_scratch:V2DF 1 ""))]
9726169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
9727169699Skan  [(const_int 0)]
972890286Sobrien{
9729169699Skan  ix86_split_copysign_var (operands);
9730169699Skan  DONE;
973190286Sobrien})
973252296Sobrien
973390286Sobrien(define_expand "negxf2"
9734169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "")
9735169699Skan	(neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
9736132727Skan  "TARGET_80387"
9737169699Skan  "ix86_expand_fp_absneg_operator (NEG, XFmode, operands); DONE;")
973818334Speter
9739169699Skan(define_expand "absxf2"
9740169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "")
9741169699Skan	(abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
974218334Speter  "TARGET_80387"
9743169699Skan  "ix86_expand_fp_absneg_operator (ABS, XFmode, operands); DONE;")
974418334Speter
9745169699Skan(define_insn "*absnegxf2_i387"
9746169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,?rm")
9747169699Skan	(match_operator:XF 3 "absneg_operator"
9748169699Skan	  [(match_operand:XF 1 "nonimmediate_operand" "0,0")]))
9749169699Skan   (use (match_operand 2 "" ""))
9750169699Skan   (clobber (reg:CC FLAGS_REG))]
9751169699Skan  "TARGET_80387
9752169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), XFmode, operands)"
975390286Sobrien  "#")
975490286Sobrien
9755169699Skan;; Splitters for fp abs and neg.
975690286Sobrien
975790286Sobrien(define_split
9758169699Skan  [(set (match_operand 0 "fp_register_operand" "")
9759169699Skan	(match_operator 1 "absneg_operator" [(match_dup 0)]))
9760169699Skan   (use (match_operand 2 "" ""))
9761169699Skan   (clobber (reg:CC FLAGS_REG))]
9762169699Skan  "reload_completed"
9763169699Skan  [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))])
976490286Sobrien
976590286Sobrien(define_split
9766169699Skan  [(set (match_operand 0 "register_operand" "")
9767169699Skan	(match_operator 3 "absneg_operator"
9768169699Skan	  [(match_operand 1 "register_operand" "")]))
9769169699Skan   (use (match_operand 2 "nonimmediate_operand" ""))
9770169699Skan   (clobber (reg:CC FLAGS_REG))]
977190286Sobrien  "reload_completed && SSE_REG_P (operands[0])"
9772169699Skan  [(set (match_dup 0) (match_dup 3))]
9773132727Skan{
9774169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
9775169699Skan  enum machine_mode vmode = GET_MODE (operands[2]);
9776169699Skan  rtx tmp;
9777169699Skan  
9778169699Skan  operands[0] = simplify_gen_subreg (vmode, operands[0], mode, 0);
9779169699Skan  operands[1] = simplify_gen_subreg (vmode, operands[1], mode, 0);
9780132727Skan  if (operands_match_p (operands[0], operands[2]))
9781132727Skan    {
9782132727Skan      tmp = operands[1];
9783132727Skan      operands[1] = operands[2];
9784132727Skan      operands[2] = tmp;
9785132727Skan    }
9786169699Skan  if (GET_CODE (operands[3]) == ABS)
9787169699Skan    tmp = gen_rtx_AND (vmode, operands[1], operands[2]);
9788169699Skan  else
9789169699Skan    tmp = gen_rtx_XOR (vmode, operands[1], operands[2]);
9790169699Skan  operands[3] = tmp;
9791132727Skan})
979290286Sobrien
979390286Sobrien(define_split
9794169699Skan  [(set (match_operand:SF 0 "register_operand" "")
9795169699Skan	(match_operator:SF 1 "absneg_operator" [(match_dup 0)]))
9796169699Skan   (use (match_operand:V4SF 2 "" ""))
9797169699Skan   (clobber (reg:CC FLAGS_REG))]
9798169699Skan  "reload_completed"
9799169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9800169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9801169699Skan{ 
9802169699Skan  rtx tmp;
9803169699Skan  operands[0] = gen_lowpart (SImode, operands[0]);
9804169699Skan  if (GET_CODE (operands[1]) == ABS)
9805169699Skan    {
9806169699Skan      tmp = gen_int_mode (0x7fffffff, SImode);
9807169699Skan      tmp = gen_rtx_AND (SImode, operands[0], tmp);
9808169699Skan    }
9809169699Skan  else
9810169699Skan    {
9811169699Skan      tmp = gen_int_mode (0x80000000, SImode);
9812169699Skan      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9813169699Skan    }
9814169699Skan  operands[1] = tmp;
9815169699Skan})
981690286Sobrien
981790286Sobrien(define_split
9818169699Skan  [(set (match_operand:DF 0 "register_operand" "")
9819169699Skan	(match_operator:DF 1 "absneg_operator" [(match_dup 0)]))
9820169699Skan   (use (match_operand 2 "" ""))
9821169699Skan   (clobber (reg:CC FLAGS_REG))]
9822169699Skan  "reload_completed"
9823169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9824169699Skan	      (clobber (reg:CC FLAGS_REG))])]
982590286Sobrien{
9826169699Skan  rtx tmp;
9827169699Skan  if (TARGET_64BIT)
9828169699Skan    {
9829169699Skan      tmp = gen_lowpart (DImode, operands[0]);
9830169699Skan      tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63));
9831169699Skan      operands[0] = tmp;
983290286Sobrien
9833169699Skan      if (GET_CODE (operands[1]) == ABS)
9834169699Skan	tmp = const0_rtx;
9835169699Skan      else
9836169699Skan	tmp = gen_rtx_NOT (DImode, tmp);
9837169699Skan    }
9838169699Skan  else
9839169699Skan    {
9840169699Skan      operands[0] = gen_highpart (SImode, operands[0]);
9841169699Skan      if (GET_CODE (operands[1]) == ABS)
984290286Sobrien	{
9843169699Skan	  tmp = gen_int_mode (0x7fffffff, SImode);
9844169699Skan	  tmp = gen_rtx_AND (SImode, operands[0], tmp);
984590286Sobrien	}
9846169699Skan      else
9847169699Skan	{
9848169699Skan	  tmp = gen_int_mode (0x80000000, SImode);
9849169699Skan	  tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9850169699Skan	}
9851169699Skan    }
9852169699Skan  operands[1] = tmp;
9853169699Skan})
985490286Sobrien
985590286Sobrien(define_split
9856169699Skan  [(set (match_operand:XF 0 "register_operand" "")
9857169699Skan	(match_operator:XF 1 "absneg_operator" [(match_dup 0)]))
9858169699Skan   (use (match_operand 2 "" ""))
9859169699Skan   (clobber (reg:CC FLAGS_REG))]
9860169699Skan  "reload_completed"
9861169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9862169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9863169699Skan{
9864169699Skan  rtx tmp;
9865169699Skan  operands[0] = gen_rtx_REG (SImode,
9866169699Skan			     true_regnum (operands[0])
9867169699Skan			     + (TARGET_64BIT ? 1 : 2));
9868169699Skan  if (GET_CODE (operands[1]) == ABS)
9869169699Skan    {
9870169699Skan      tmp = GEN_INT (0x7fff);
9871169699Skan      tmp = gen_rtx_AND (SImode, operands[0], tmp);
9872169699Skan    }
9873169699Skan  else
9874169699Skan    {
9875169699Skan      tmp = GEN_INT (0x8000);
9876169699Skan      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9877169699Skan    }
9878169699Skan  operands[1] = tmp;
9879169699Skan})
988090286Sobrien
988190286Sobrien(define_split
9882169699Skan  [(set (match_operand 0 "memory_operand" "")
9883169699Skan	(match_operator 1 "absneg_operator" [(match_dup 0)]))
9884169699Skan   (use (match_operand 2 "" ""))
9885169699Skan   (clobber (reg:CC FLAGS_REG))]
9886169699Skan  "reload_completed"
9887169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9888169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9889169699Skan{
9890169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
9891169699Skan  int size = mode == XFmode ? 10 : GET_MODE_SIZE (mode);
9892169699Skan  rtx tmp;
989390286Sobrien
9894169699Skan  operands[0] = adjust_address (operands[0], QImode, size - 1);
9895169699Skan  if (GET_CODE (operands[1]) == ABS)
9896132727Skan    {
9897169699Skan      tmp = gen_int_mode (0x7f, QImode);
9898169699Skan      tmp = gen_rtx_AND (QImode, operands[0], tmp);
9899132727Skan    }
9900169699Skan  else
9901169699Skan    {
9902169699Skan      tmp = gen_int_mode (0x80, QImode);
9903169699Skan      tmp = gen_rtx_XOR (QImode, operands[0], tmp);
9904169699Skan    }
9905169699Skan  operands[1] = tmp;
9906132727Skan})
990790286Sobrien
9908169699Skan;; Conditionalize these after reload. If they match before reload, we 
9909169699Skan;; lose the clobber and ability to use integer instructions.
991090286Sobrien
9911169699Skan(define_insn "*negsf2_1"
9912169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
9913169699Skan	(neg:SF (match_operand:SF 1 "register_operand" "0")))]
9914169699Skan  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
9915169699Skan  "fchs"
9916169699Skan  [(set_attr "type" "fsgn")
9917169699Skan   (set_attr "mode" "SF")])
991890286Sobrien
9919169699Skan(define_insn "*negdf2_1"
9920169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
9921169699Skan	(neg:DF (match_operand:DF 1 "register_operand" "0")))]
9922169699Skan  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
9923169699Skan  "fchs"
9924169699Skan  [(set_attr "type" "fsgn")
9925169699Skan   (set_attr "mode" "DF")])
992690286Sobrien
9927169699Skan(define_insn "*negxf2_1"
9928169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
9929169699Skan	(neg:XF (match_operand:XF 1 "register_operand" "0")))]
9930132727Skan  "TARGET_80387"
9931169699Skan  "fchs"
9932169699Skan  [(set_attr "type" "fsgn")
9933169699Skan   (set_attr "mode" "XF")])
993490286Sobrien
993590286Sobrien(define_insn "*abssf2_1"
993618334Speter  [(set (match_operand:SF 0 "register_operand" "=f")
993750650Sobrien	(abs:SF (match_operand:SF 1 "register_operand" "0")))]
9938169699Skan  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
993950650Sobrien  "fabs"
994090286Sobrien  [(set_attr "type" "fsgn")
994190286Sobrien   (set_attr "mode" "SF")])
994218334Speter
994390286Sobrien(define_insn "*absdf2_1"
994418334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
994550650Sobrien	(abs:DF (match_operand:DF 1 "register_operand" "0")))]
9946169699Skan  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
994750650Sobrien  "fabs"
994890286Sobrien  [(set_attr "type" "fsgn")
994990286Sobrien   (set_attr "mode" "DF")])
995018334Speter
9951169699Skan(define_insn "*absxf2_1"
9952169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
9953169699Skan	(abs:XF (match_operand:XF 1 "register_operand" "0")))]
995418334Speter  "TARGET_80387"
995550650Sobrien  "fabs"
995690286Sobrien  [(set_attr "type" "fsgn")
995790286Sobrien   (set_attr "mode" "DF")])
995818334Speter
9959169699Skan(define_insn "*negextendsfdf2"
9960169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
9961169699Skan	(neg:DF (float_extend:DF
9962169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
9963169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
9964169699Skan  "fchs"
9965169699Skan  [(set_attr "type" "fsgn")
9966169699Skan   (set_attr "mode" "DF")])
9967169699Skan
9968169699Skan(define_insn "*negextenddfxf2"
996918334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
9970169699Skan	(neg:XF (float_extend:XF
9971169699Skan		  (match_operand:DF 1 "register_operand" "0"))))]
9972169699Skan  "TARGET_80387"
9973169699Skan  "fchs"
9974169699Skan  [(set_attr "type" "fsgn")
9975169699Skan   (set_attr "mode" "XF")])
9976169699Skan
9977169699Skan(define_insn "*negextendsfxf2"
9978169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
9979169699Skan	(neg:XF (float_extend:XF
9980169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
9981169699Skan  "TARGET_80387"
9982169699Skan  "fchs"
9983169699Skan  [(set_attr "type" "fsgn")
9984169699Skan   (set_attr "mode" "XF")])
9985169699Skan
9986169699Skan(define_insn "*absextendsfdf2"
9987169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
9988169699Skan	(abs:DF (float_extend:DF
9989169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
9990169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
999150650Sobrien  "fabs"
999290286Sobrien  [(set_attr "type" "fsgn")
999390286Sobrien   (set_attr "mode" "DF")])
999418334Speter
999590286Sobrien(define_insn "*absextenddfxf2"
999618334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
999790286Sobrien	(abs:XF (float_extend:XF
999890286Sobrien	  (match_operand:DF 1 "register_operand" "0"))))]
9999132727Skan  "TARGET_80387"
1000050650Sobrien  "fabs"
1000190286Sobrien  [(set_attr "type" "fsgn")
1000290286Sobrien   (set_attr "mode" "XF")])
1000318334Speter
1000490286Sobrien(define_insn "*absextendsfxf2"
1000590286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1000690286Sobrien	(abs:XF (float_extend:XF
1000790286Sobrien	  (match_operand:SF 1 "register_operand" "0"))))]
1000890286Sobrien  "TARGET_80387"
1000990286Sobrien  "fabs"
1001090286Sobrien  [(set_attr "type" "fsgn")
1001190286Sobrien   (set_attr "mode" "XF")])
1001290286Sobrien
1001390286Sobrien;; One complement instructions
1001418334Speter
1001590286Sobrien(define_expand "one_cmpldi2"
1001690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
1001790286Sobrien	(not:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
1001890286Sobrien  "TARGET_64BIT"
1001990286Sobrien  "ix86_expand_unary_operator (NOT, DImode, operands); DONE;")
1002018334Speter
1002190286Sobrien(define_insn "*one_cmpldi2_1_rex64"
1002290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1002390286Sobrien	(not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
1002490286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NOT, DImode, operands)"
1002590286Sobrien  "not{q}\t%0"
1002690286Sobrien  [(set_attr "type" "negnot")
1002790286Sobrien   (set_attr "mode" "DI")])
1002818334Speter
1002990286Sobrien(define_insn "*one_cmpldi2_2_rex64"
10030169699Skan  [(set (reg FLAGS_REG)
1003190286Sobrien	(compare (not:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
1003290286Sobrien		 (const_int 0)))
1003390286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1003490286Sobrien	(not:DI (match_dup 1)))]
1003590286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
1003690286Sobrien   && ix86_unary_operator_ok (NOT, DImode, operands)"
1003790286Sobrien  "#"
1003890286Sobrien  [(set_attr "type" "alu1")
1003990286Sobrien   (set_attr "mode" "DI")])
1004018334Speter
1004190286Sobrien(define_split
10042146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10043146906Skan	(match_operator 2 "compare_operator"
10044146906Skan	  [(not:DI (match_operand:DI 3 "nonimmediate_operand" ""))
10045146906Skan	   (const_int 0)]))
10046146906Skan   (set (match_operand:DI 1 "nonimmediate_operand" "")
10047146906Skan	(not:DI (match_dup 3)))]
1004890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
10049146906Skan  [(parallel [(set (match_dup 0)
10050146906Skan		   (match_op_dup 2
10051146906Skan		     [(xor:DI (match_dup 3) (const_int -1))
10052146906Skan		      (const_int 0)]))
10053146906Skan	      (set (match_dup 1)
10054146906Skan		   (xor:DI (match_dup 3) (const_int -1)))])]
1005590286Sobrien  "")
1005618334Speter
1005790286Sobrien(define_expand "one_cmplsi2"
1005890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1005990286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
1006090286Sobrien  ""
1006190286Sobrien  "ix86_expand_unary_operator (NOT, SImode, operands); DONE;")
1006218334Speter
1006390286Sobrien(define_insn "*one_cmplsi2_1"
1006490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1006590286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
1006690286Sobrien  "ix86_unary_operator_ok (NOT, SImode, operands)"
1006790286Sobrien  "not{l}\t%0"
1006890286Sobrien  [(set_attr "type" "negnot")
1006990286Sobrien   (set_attr "mode" "SI")])
1007018334Speter
1007190286Sobrien;; ??? Currently never generated - xor is used instead.
1007290286Sobrien(define_insn "*one_cmplsi2_1_zext"
1007390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1007490286Sobrien	(zero_extend:DI (not:SI (match_operand:SI 1 "register_operand" "0"))))]
1007590286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NOT, SImode, operands)"
1007690286Sobrien  "not{l}\t%k0"
1007790286Sobrien  [(set_attr "type" "negnot")
1007890286Sobrien   (set_attr "mode" "SI")])
1007918334Speter
1008090286Sobrien(define_insn "*one_cmplsi2_2"
10081169699Skan  [(set (reg FLAGS_REG)
1008290286Sobrien	(compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
1008390286Sobrien		 (const_int 0)))
1008490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1008590286Sobrien	(not:SI (match_dup 1)))]
1008690286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1008790286Sobrien   && ix86_unary_operator_ok (NOT, SImode, operands)"
1008890286Sobrien  "#"
1008990286Sobrien  [(set_attr "type" "alu1")
1009090286Sobrien   (set_attr "mode" "SI")])
1009118334Speter
1009290286Sobrien(define_split
10093146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10094146906Skan	(match_operator 2 "compare_operator"
10095146906Skan	  [(not:SI (match_operand:SI 3 "nonimmediate_operand" ""))
10096146906Skan	   (const_int 0)]))
10097146906Skan   (set (match_operand:SI 1 "nonimmediate_operand" "")
10098146906Skan	(not:SI (match_dup 3)))]
1009990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10100146906Skan  [(parallel [(set (match_dup 0)
10101146906Skan		   (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
10102146906Skan				    (const_int 0)]))
10103146906Skan	      (set (match_dup 1)
10104146906Skan		   (xor:SI (match_dup 3) (const_int -1)))])]
1010590286Sobrien  "")
1010618334Speter
1010790286Sobrien;; ??? Currently never generated - xor is used instead.
1010890286Sobrien(define_insn "*one_cmplsi2_2_zext"
10109169699Skan  [(set (reg FLAGS_REG)
1011090286Sobrien	(compare (not:SI (match_operand:SI 1 "register_operand" "0"))
1011190286Sobrien		 (const_int 0)))
1011290286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1011390286Sobrien	(zero_extend:DI (not:SI (match_dup 1))))]
1011490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
1011590286Sobrien   && ix86_unary_operator_ok (NOT, SImode, operands)"
1011690286Sobrien  "#"
1011790286Sobrien  [(set_attr "type" "alu1")
1011890286Sobrien   (set_attr "mode" "SI")])
1011918334Speter
1012090286Sobrien(define_split
10121146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10122146906Skan	(match_operator 2 "compare_operator"
10123146906Skan	  [(not:SI (match_operand:SI 3 "register_operand" ""))
10124146906Skan	   (const_int 0)]))
10125146906Skan   (set (match_operand:DI 1 "register_operand" "")
10126146906Skan	(zero_extend:DI (not:SI (match_dup 3))))]
1012790286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10128146906Skan  [(parallel [(set (match_dup 0)
10129146906Skan		   (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
10130146906Skan				    (const_int 0)]))
10131146906Skan	      (set (match_dup 1)
10132146906Skan		   (zero_extend:DI (xor:SI (match_dup 3) (const_int -1))))])]
1013390286Sobrien  "")
1013418334Speter
1013590286Sobrien(define_expand "one_cmplhi2"
1013690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1013790286Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
1013890286Sobrien  "TARGET_HIMODE_MATH"
1013990286Sobrien  "ix86_expand_unary_operator (NOT, HImode, operands); DONE;")
1014052296Sobrien
1014190286Sobrien(define_insn "*one_cmplhi2_1"
1014250650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1014350650Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
1014490286Sobrien  "ix86_unary_operator_ok (NOT, HImode, operands)"
1014590286Sobrien  "not{w}\t%0"
1014690286Sobrien  [(set_attr "type" "negnot")
1014790286Sobrien   (set_attr "mode" "HI")])
1014818334Speter
1014990286Sobrien(define_insn "*one_cmplhi2_2"
10150169699Skan  [(set (reg FLAGS_REG)
1015190286Sobrien	(compare (not:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
1015290286Sobrien		 (const_int 0)))
1015390286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1015490286Sobrien	(not:HI (match_dup 1)))]
1015590286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1015690286Sobrien   && ix86_unary_operator_ok (NEG, HImode, operands)"
1015790286Sobrien  "#"
1015890286Sobrien  [(set_attr "type" "alu1")
1015990286Sobrien   (set_attr "mode" "HI")])
1016052296Sobrien
1016190286Sobrien(define_split
10162146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10163146906Skan	(match_operator 2 "compare_operator"
10164146906Skan	  [(not:HI (match_operand:HI 3 "nonimmediate_operand" ""))
10165146906Skan	   (const_int 0)]))
10166146906Skan   (set (match_operand:HI 1 "nonimmediate_operand" "")
10167146906Skan	(not:HI (match_dup 3)))]
1016890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10169146906Skan  [(parallel [(set (match_dup 0)
10170146906Skan		   (match_op_dup 2 [(xor:HI (match_dup 3) (const_int -1))
10171146906Skan		      		    (const_int 0)]))
10172146906Skan	      (set (match_dup 1)
10173146906Skan		   (xor:HI (match_dup 3) (const_int -1)))])]
1017490286Sobrien  "")
1017552296Sobrien
1017690286Sobrien;; %%% Potential partial reg stall on alternative 1.  What to do?
1017790286Sobrien(define_expand "one_cmplqi2"
1017890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1017990286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
1018090286Sobrien  "TARGET_QIMODE_MATH"
1018190286Sobrien  "ix86_expand_unary_operator (NOT, QImode, operands); DONE;")
1018290286Sobrien
1018390286Sobrien(define_insn "*one_cmplqi2_1"
1018490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
1018590286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))]
1018690286Sobrien  "ix86_unary_operator_ok (NOT, QImode, operands)"
1018790286Sobrien  "@
1018890286Sobrien   not{b}\t%0
1018990286Sobrien   not{l}\t%k0"
1019090286Sobrien  [(set_attr "type" "negnot")
1019190286Sobrien   (set_attr "mode" "QI,SI")])
1019290286Sobrien
1019390286Sobrien(define_insn "*one_cmplqi2_2"
10194169699Skan  [(set (reg FLAGS_REG)
1019590286Sobrien	(compare (not:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
1019690286Sobrien		 (const_int 0)))
1019790286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1019890286Sobrien	(not:QI (match_dup 1)))]
1019990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1020090286Sobrien   && ix86_unary_operator_ok (NOT, QImode, operands)"
1020190286Sobrien  "#"
1020290286Sobrien  [(set_attr "type" "alu1")
1020390286Sobrien   (set_attr "mode" "QI")])
1020490286Sobrien
1020590286Sobrien(define_split
10206146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10207146906Skan	(match_operator 2 "compare_operator"
10208146906Skan	  [(not:QI (match_operand:QI 3 "nonimmediate_operand" ""))
10209146906Skan	   (const_int 0)]))
10210146906Skan   (set (match_operand:QI 1 "nonimmediate_operand" "")
10211146906Skan	(not:QI (match_dup 3)))]
1021290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10213146906Skan  [(parallel [(set (match_dup 0)
10214146906Skan		   (match_op_dup 2 [(xor:QI (match_dup 3) (const_int -1))
10215146906Skan		      		    (const_int 0)]))
10216146906Skan	      (set (match_dup 1)
10217146906Skan		   (xor:QI (match_dup 3) (const_int -1)))])]
1021890286Sobrien  "")
1021918334Speter
1022090286Sobrien;; Arithmetic shift instructions
1022118334Speter
1022218334Speter;; DImode shifts are implemented using the i386 "shift double" opcode,
1022318334Speter;; which is written as "sh[lr]d[lw] imm,reg,reg/mem".  If the shift count
1022418334Speter;; is variable, then the count is in %cl and the "imm" operand is dropped
1022518334Speter;; from the assembler input.
1022690286Sobrien;;
1022718334Speter;; This instruction shifts the target reg/mem as usual, but instead of
1022818334Speter;; shifting in zeros, bits are shifted in from reg operand.  If the insn
1022918334Speter;; is a left shift double, bits are taken from the high order bits of
1023018334Speter;; reg, else if the insn is a shift right double, bits are taken from the
1023118334Speter;; low order bits of reg.  So if %eax is "1234" and %edx is "5678",
1023218334Speter;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
1023390286Sobrien;;
1023418334Speter;; Since sh[lr]d does not change the `reg' operand, that is done
1023518334Speter;; separately, making all shifts emit pairs of shift double and normal
1023618334Speter;; shift.  Since sh[lr]d does not shift more than 31 bits, and we wish to
1023718334Speter;; support a 63 bit shift, each shift where the count is in a reg expands
1023850650Sobrien;; to a pair of shifts, a branch, a shift by 32 and a label.
1023990286Sobrien;;
1024018334Speter;; If the shift count is a constant, we need never emit more than one
1024118334Speter;; shift pair, instead using moves and sign extension for counts greater
1024218334Speter;; than 31.
1024318334Speter
10244169699Skan(define_expand "ashlti3"
10245169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
10246169699Skan		   (ashift:TI (match_operand:TI 1 "register_operand" "")
1024790286Sobrien			      (match_operand:QI 2 "nonmemory_operand" "")))
10248169699Skan	      (clobber (reg:CC FLAGS_REG))])]
10249169699Skan  "TARGET_64BIT"
1025018334Speter{
10251169699Skan  if (! immediate_operand (operands[2], QImode))
1025218334Speter    {
10253169699Skan      emit_insn (gen_ashlti3_1 (operands[0], operands[1], operands[2]));
1025490286Sobrien      DONE;
1025518334Speter    }
10256169699Skan  ix86_expand_binary_operator (ASHIFT, TImode, operands);
1025718334Speter  DONE;
1025890286Sobrien})
1025918334Speter
10260169699Skan(define_insn "ashlti3_1"
10261169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
10262169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "0")
10263169699Skan		   (match_operand:QI 2 "register_operand" "c")))
10264169699Skan   (clobber (match_scratch:DI 3 "=&r"))
10265169699Skan   (clobber (reg:CC FLAGS_REG))]
10266169699Skan  "TARGET_64BIT"
10267169699Skan  "#"
10268169699Skan  [(set_attr "type" "multi")])
10269169699Skan
10270169699Skan(define_insn "*ashlti3_2"
10271169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
10272169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "0")
10273169699Skan		   (match_operand:QI 2 "immediate_operand" "O")))
10274169699Skan   (clobber (reg:CC FLAGS_REG))]
10275169699Skan  "TARGET_64BIT"
10276169699Skan  "#"
10277169699Skan  [(set_attr "type" "multi")])
10278169699Skan
10279169699Skan(define_split
10280169699Skan  [(set (match_operand:TI 0 "register_operand" "")
10281169699Skan	(ashift:TI (match_operand:TI 1 "nonmemory_operand" "")
10282169699Skan		   (match_operand:QI 2 "register_operand" "")))
10283169699Skan   (clobber (match_scratch:DI 3 ""))
10284169699Skan   (clobber (reg:CC FLAGS_REG))]
10285169699Skan  "TARGET_64BIT && reload_completed"
10286169699Skan  [(const_int 0)]
10287169699Skan  "ix86_split_ashl (operands, operands[3], TImode); DONE;")
10288169699Skan
10289169699Skan(define_split
10290169699Skan  [(set (match_operand:TI 0 "register_operand" "")
10291169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "")
10292169699Skan		   (match_operand:QI 2 "immediate_operand" "")))
10293169699Skan   (clobber (reg:CC FLAGS_REG))]
10294169699Skan  "TARGET_64BIT && reload_completed"
10295169699Skan  [(const_int 0)]
10296169699Skan  "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;")
10297169699Skan
10298169699Skan(define_insn "x86_64_shld"
10299169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
10300169699Skan        (ior:DI (ashift:DI (match_dup 0)
10301169699Skan		  (match_operand:QI 2 "nonmemory_operand" "J,c"))
10302169699Skan		(lshiftrt:DI (match_operand:DI 1 "register_operand" "r,r")
10303169699Skan		  (minus:QI (const_int 64) (match_dup 2)))))
10304169699Skan   (clobber (reg:CC FLAGS_REG))]
10305169699Skan  "TARGET_64BIT"
10306169699Skan  "@
10307169699Skan   shld{q}\t{%2, %1, %0|%0, %1, %2}
10308169699Skan   shld{q}\t{%s2%1, %0|%0, %1, %2}"
10309169699Skan  [(set_attr "type" "ishift")
10310169699Skan   (set_attr "prefix_0f" "1")
10311169699Skan   (set_attr "mode" "DI")
10312169699Skan   (set_attr "athlon_decode" "vector")])
10313169699Skan
10314169699Skan(define_expand "x86_64_shift_adj"
10315169699Skan  [(set (reg:CCZ FLAGS_REG)
10316169699Skan	(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
10317169699Skan			     (const_int 64))
10318169699Skan		     (const_int 0)))
10319169699Skan   (set (match_operand:DI 0 "register_operand" "")
10320169699Skan        (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
10321169699Skan			 (match_operand:DI 1 "register_operand" "")
10322169699Skan			 (match_dup 0)))
10323169699Skan   (set (match_dup 1)
10324169699Skan	(if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
10325169699Skan			 (match_operand:DI 3 "register_operand" "r")
10326169699Skan			 (match_dup 1)))]
10327169699Skan  "TARGET_64BIT"
10328169699Skan  "")
10329169699Skan
10330169699Skan(define_expand "ashldi3"
10331169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
10332169699Skan	(ashift:DI (match_operand:DI 1 "ashldi_input_operand" "")
10333169699Skan		   (match_operand:QI 2 "nonmemory_operand" "")))]
10334169699Skan  ""
10335169699Skan  "ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;")
10336169699Skan
1033790286Sobrien(define_insn "*ashldi3_1_rex64"
1033890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
10339169699Skan	(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,l")
1034090286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cJ,M")))
10341169699Skan   (clobber (reg:CC FLAGS_REG))]
1034290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
1034318334Speter{
1034490286Sobrien  switch (get_attr_type (insn))
1034590286Sobrien    {
1034690286Sobrien    case TYPE_ALU:
10347169699Skan      gcc_assert (operands[2] == const1_rtx);
10348169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
1034990286Sobrien      return "add{q}\t{%0, %0|%0, %0}";
1035018334Speter
1035190286Sobrien    case TYPE_LEA:
10352169699Skan      gcc_assert (GET_CODE (operands[2]) == CONST_INT);
10353169699Skan      gcc_assert ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) <= 3);
1035490286Sobrien      operands[1] = gen_rtx_MULT (DImode, operands[1],
1035590286Sobrien				  GEN_INT (1 << INTVAL (operands[2])));
1035690286Sobrien      return "lea{q}\t{%a1, %0|%0, %a1}";
1035718334Speter
1035890286Sobrien    default:
1035990286Sobrien      if (REG_P (operands[2]))
1036090286Sobrien	return "sal{q}\t{%b2, %0|%0, %b2}";
10361169699Skan      else if (operands[2] == const1_rtx
10362117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1036390286Sobrien	return "sal{q}\t%0";
1036490286Sobrien      else
1036590286Sobrien	return "sal{q}\t{%2, %0|%0, %2}";
1036690286Sobrien    }
1036790286Sobrien}
1036890286Sobrien  [(set (attr "type")
1036990286Sobrien     (cond [(eq_attr "alternative" "1")
1037090286Sobrien	      (const_string "lea")
1037190286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1037290286Sobrien		          (const_int 0))
1037390286Sobrien		      (match_operand 0 "register_operand" ""))
1037490286Sobrien		 (match_operand 2 "const1_operand" ""))
1037590286Sobrien	      (const_string "alu")
1037690286Sobrien	   ]
1037790286Sobrien	   (const_string "ishift")))
1037890286Sobrien   (set_attr "mode" "DI")])
1037918334Speter
1038090286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1038190286Sobrien(define_split
1038290286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
10383169699Skan	(ashift:DI (match_operand:DI 1 "index_register_operand" "")
1038490286Sobrien		   (match_operand:QI 2 "immediate_operand" "")))
10385169699Skan   (clobber (reg:CC FLAGS_REG))]
1038690286Sobrien  "TARGET_64BIT && reload_completed
1038790286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
1038890286Sobrien  [(set (match_dup 0)
1038990286Sobrien	(mult:DI (match_dup 1)
1039090286Sobrien		 (match_dup 2)))]
10391117404Skan  "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);")
1039290286Sobrien
1039390286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1039490286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1039590286Sobrien;; zero are optimized away.
1039690286Sobrien(define_insn "*ashldi3_cmp_rex64"
10397169699Skan  [(set (reg FLAGS_REG)
1039890286Sobrien	(compare
1039990286Sobrien	  (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1040090286Sobrien		     (match_operand:QI 2 "immediate_operand" "e"))
1040190286Sobrien	  (const_int 0)))
1040290286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1040390286Sobrien	(ashift:DI (match_dup 1) (match_dup 2)))]
1040490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10405169699Skan   && ix86_binary_operator_ok (ASHIFT, DImode, operands)
10406169699Skan   && (optimize_size
10407169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10408169699Skan       || (operands[2] == const1_rtx
10409169699Skan	   && (TARGET_SHIFT1
10410169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1041190286Sobrien{
1041290286Sobrien  switch (get_attr_type (insn))
1041318334Speter    {
1041490286Sobrien    case TYPE_ALU:
10415169699Skan      gcc_assert (operands[2] == const1_rtx);
1041690286Sobrien      return "add{q}\t{%0, %0|%0, %0}";
1041718334Speter
1041890286Sobrien    default:
1041990286Sobrien      if (REG_P (operands[2]))
1042090286Sobrien	return "sal{q}\t{%b2, %0|%0, %b2}";
10421169699Skan      else if (operands[2] == const1_rtx
10422117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1042390286Sobrien	return "sal{q}\t%0";
1042490286Sobrien      else
1042590286Sobrien	return "sal{q}\t{%2, %0|%0, %2}";
1042618334Speter    }
1042790286Sobrien}
1042890286Sobrien  [(set (attr "type")
1042990286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1043090286Sobrien		          (const_int 0))
1043190286Sobrien		      (match_operand 0 "register_operand" ""))
1043290286Sobrien		 (match_operand 2 "const1_operand" ""))
1043390286Sobrien	      (const_string "alu")
1043490286Sobrien	   ]
1043590286Sobrien	   (const_string "ishift")))
1043690286Sobrien   (set_attr "mode" "DI")])
1043718334Speter
10438169699Skan(define_insn "*ashldi3_cconly_rex64"
10439169699Skan  [(set (reg FLAGS_REG)
10440169699Skan	(compare
10441169699Skan	  (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
10442169699Skan		     (match_operand:QI 2 "immediate_operand" "e"))
10443169699Skan	  (const_int 0)))
10444169699Skan   (clobber (match_scratch:DI 0 "=r"))]
10445169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10446169699Skan   && ix86_binary_operator_ok (ASHIFT, DImode, operands)
10447169699Skan   && (optimize_size
10448169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10449169699Skan       || (operands[2] == const1_rtx
10450169699Skan	   && (TARGET_SHIFT1
10451169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10452169699Skan{
10453169699Skan  switch (get_attr_type (insn))
10454169699Skan    {
10455169699Skan    case TYPE_ALU:
10456169699Skan      gcc_assert (operands[2] == const1_rtx);
10457169699Skan      return "add{q}\t{%0, %0|%0, %0}";
1045890286Sobrien
10459169699Skan    default:
10460169699Skan      if (REG_P (operands[2]))
10461169699Skan	return "sal{q}\t{%b2, %0|%0, %b2}";
10462169699Skan      else if (operands[2] == const1_rtx
10463169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10464169699Skan	return "sal{q}\t%0";
10465169699Skan      else
10466169699Skan	return "sal{q}\t{%2, %0|%0, %2}";
10467169699Skan    }
10468169699Skan}
10469169699Skan  [(set (attr "type")
10470169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
10471169699Skan		          (const_int 0))
10472169699Skan		      (match_operand 0 "register_operand" ""))
10473169699Skan		 (match_operand 2 "const1_operand" ""))
10474169699Skan	      (const_string "alu")
10475169699Skan	   ]
10476169699Skan	   (const_string "ishift")))
10477169699Skan   (set_attr "mode" "DI")])
10478169699Skan
10479169699Skan(define_insn "*ashldi3_1"
10480169699Skan  [(set (match_operand:DI 0 "register_operand" "=&r,r")
10481169699Skan	(ashift:DI (match_operand:DI 1 "reg_or_pm1_operand" "n,0")
10482169699Skan		   (match_operand:QI 2 "nonmemory_operand" "Jc,Jc")))
10483169699Skan   (clobber (reg:CC FLAGS_REG))]
1048490286Sobrien  "!TARGET_64BIT"
1048590286Sobrien  "#"
1048690286Sobrien  [(set_attr "type" "multi")])
1048790286Sobrien
10488169699Skan;; By default we don't ask for a scratch register, because when DImode
10489169699Skan;; values are manipulated, registers are already at a premium.  But if
10490169699Skan;; we have one handy, we won't turn it away.
10491169699Skan(define_peephole2
10492169699Skan  [(match_scratch:SI 3 "r")
10493169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
10494169699Skan		   (ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
10495169699Skan			      (match_operand:QI 2 "nonmemory_operand" "")))
10496169699Skan	      (clobber (reg:CC FLAGS_REG))])
10497169699Skan   (match_dup 3)]
10498169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1049990286Sobrien  [(const_int 0)]
10500169699Skan  "ix86_split_ashl (operands, operands[3], DImode); DONE;")
1050190286Sobrien
1050290286Sobrien(define_split
1050390286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
10504169699Skan	(ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
1050590286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10506169699Skan   (clobber (reg:CC FLAGS_REG))]
10507169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
10508169699Skan		     ? flow2_completed : reload_completed)"
1050990286Sobrien  [(const_int 0)]
10510169699Skan  "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;")
1051190286Sobrien
1051290286Sobrien(define_insn "x86_shld_1"
1051390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
1051490286Sobrien        (ior:SI (ashift:SI (match_dup 0)
1051590286Sobrien		  (match_operand:QI 2 "nonmemory_operand" "I,c"))
1051690286Sobrien		(lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
1051790286Sobrien		  (minus:QI (const_int 32) (match_dup 2)))))
10518169699Skan   (clobber (reg:CC FLAGS_REG))]
1051918334Speter  ""
1052090286Sobrien  "@
1052190286Sobrien   shld{l}\t{%2, %1, %0|%0, %1, %2}
1052290286Sobrien   shld{l}\t{%s2%1, %0|%0, %1, %2}"
1052390286Sobrien  [(set_attr "type" "ishift")
1052490286Sobrien   (set_attr "prefix_0f" "1")
1052590286Sobrien   (set_attr "mode" "SI")
1052690286Sobrien   (set_attr "pent_pair" "np")
10527169699Skan   (set_attr "athlon_decode" "vector")])
1052890286Sobrien
1052990286Sobrien(define_expand "x86_shift_adj_1"
10530169699Skan  [(set (reg:CCZ FLAGS_REG)
1053190286Sobrien	(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
1053290286Sobrien			     (const_int 32))
1053390286Sobrien		     (const_int 0)))
1053490286Sobrien   (set (match_operand:SI 0 "register_operand" "")
10535169699Skan        (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
1053690286Sobrien			 (match_operand:SI 1 "register_operand" "")
1053790286Sobrien			 (match_dup 0)))
1053890286Sobrien   (set (match_dup 1)
10539169699Skan	(if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
1054090286Sobrien			 (match_operand:SI 3 "register_operand" "r")
1054190286Sobrien			 (match_dup 1)))]
1054290286Sobrien  "TARGET_CMOVE"
1054390286Sobrien  "")
1054490286Sobrien
1054590286Sobrien(define_expand "x86_shift_adj_2"
1054690286Sobrien  [(use (match_operand:SI 0 "register_operand" ""))
1054790286Sobrien   (use (match_operand:SI 1 "register_operand" ""))
1054890286Sobrien   (use (match_operand:QI 2 "register_operand" ""))]
1054990286Sobrien  ""
1055018334Speter{
1055190286Sobrien  rtx label = gen_label_rtx ();
1055290286Sobrien  rtx tmp;
1055318334Speter
1055490286Sobrien  emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
1055518334Speter
1055690286Sobrien  tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
1055790286Sobrien  tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1055890286Sobrien  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
1055990286Sobrien			      gen_rtx_LABEL_REF (VOIDmode, label),
1056090286Sobrien			      pc_rtx);
1056190286Sobrien  tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
1056290286Sobrien  JUMP_LABEL (tmp) = label;
1056318334Speter
1056490286Sobrien  emit_move_insn (operands[0], operands[1]);
10565169699Skan  ix86_expand_clear (operands[1]);
1056618334Speter
1056790286Sobrien  emit_label (label);
1056890286Sobrien  LABEL_NUSES (label) = 1;
1056990286Sobrien
1057090286Sobrien  DONE;
1057190286Sobrien})
1057290286Sobrien
1057352296Sobrien(define_expand "ashlsi3"
1057452296Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1057552296Sobrien	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
1057690286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10577169699Skan   (clobber (reg:CC FLAGS_REG))]
1057852296Sobrien  ""
1057990286Sobrien  "ix86_expand_binary_operator (ASHIFT, SImode, operands); DONE;")
1058018334Speter
1058190286Sobrien(define_insn "*ashlsi3_1"
1058290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
10583169699Skan	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,l")
1058490286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,M")))
10585169699Skan   (clobber (reg:CC FLAGS_REG))]
1058690286Sobrien  "ix86_binary_operator_ok (ASHIFT, SImode, operands)"
1058790286Sobrien{
1058890286Sobrien  switch (get_attr_type (insn))
1058990286Sobrien    {
1059090286Sobrien    case TYPE_ALU:
10591169699Skan      gcc_assert (operands[2] == const1_rtx);
10592169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
1059390286Sobrien      return "add{l}\t{%0, %0|%0, %0}";
1059490286Sobrien
1059590286Sobrien    case TYPE_LEA:
1059690286Sobrien      return "#";
1059790286Sobrien
1059890286Sobrien    default:
1059990286Sobrien      if (REG_P (operands[2]))
1060090286Sobrien	return "sal{l}\t{%b2, %0|%0, %b2}";
10601169699Skan      else if (operands[2] == const1_rtx
10602117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1060390286Sobrien	return "sal{l}\t%0";
1060490286Sobrien      else
1060590286Sobrien	return "sal{l}\t{%2, %0|%0, %2}";
1060690286Sobrien    }
1060790286Sobrien}
1060890286Sobrien  [(set (attr "type")
1060990286Sobrien     (cond [(eq_attr "alternative" "1")
1061090286Sobrien	      (const_string "lea")
1061190286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1061290286Sobrien		          (const_int 0))
1061390286Sobrien		      (match_operand 0 "register_operand" ""))
1061490286Sobrien		 (match_operand 2 "const1_operand" ""))
1061590286Sobrien	      (const_string "alu")
1061690286Sobrien	   ]
1061790286Sobrien	   (const_string "ishift")))
1061890286Sobrien   (set_attr "mode" "SI")])
1061990286Sobrien
1062090286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1062190286Sobrien(define_split
1062290286Sobrien  [(set (match_operand 0 "register_operand" "")
10623117404Skan	(ashift (match_operand 1 "index_register_operand" "")
1062490286Sobrien                (match_operand:QI 2 "const_int_operand" "")))
10625169699Skan   (clobber (reg:CC FLAGS_REG))]
1062690286Sobrien  "reload_completed
10627169699Skan   && true_regnum (operands[0]) != true_regnum (operands[1])
10628169699Skan   && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4"
1062990286Sobrien  [(const_int 0)]
1063090286Sobrien{
1063190286Sobrien  rtx pat;
10632169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
10633169699Skan
10634169699Skan  if (GET_MODE_SIZE (mode) < 4)
10635169699Skan    operands[0] = gen_lowpart (SImode, operands[0]);
10636169699Skan  if (mode != Pmode)
10637169699Skan    operands[1] = gen_lowpart (Pmode, operands[1]);
10638117404Skan  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
10639169699Skan
1064090286Sobrien  pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
1064190286Sobrien  if (Pmode != SImode)
1064290286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
1064390286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
1064490286Sobrien  DONE;
1064590286Sobrien})
1064690286Sobrien
10647117404Skan;; Rare case of shifting RSP is handled by generating move and shift
10648117404Skan(define_split
10649117404Skan  [(set (match_operand 0 "register_operand" "")
10650117404Skan	(ashift (match_operand 1 "register_operand" "")
10651117404Skan                (match_operand:QI 2 "const_int_operand" "")))
10652169699Skan   (clobber (reg:CC FLAGS_REG))]
10653117404Skan  "reload_completed
10654117404Skan   && true_regnum (operands[0]) != true_regnum (operands[1])"
10655117404Skan  [(const_int 0)]
10656117404Skan{
10657117404Skan  rtx pat, clob;
10658169699Skan  emit_move_insn (operands[0], operands[1]);
10659117404Skan  pat = gen_rtx_SET (VOIDmode, operands[0],
10660117404Skan		     gen_rtx_ASHIFT (GET_MODE (operands[0]),
10661117404Skan				     operands[0], operands[2]));
10662117404Skan  clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
10663117404Skan  emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob)));
10664117404Skan  DONE;
10665117404Skan})
10666117404Skan
1066790286Sobrien(define_insn "*ashlsi3_1_zext"
1066890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
10669169699Skan	(zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l")
1067090286Sobrien			(match_operand:QI 2 "nonmemory_operand" "cI,M"))))
10671169699Skan   (clobber (reg:CC FLAGS_REG))]
1067290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
1067390286Sobrien{
1067490286Sobrien  switch (get_attr_type (insn))
1067590286Sobrien    {
1067690286Sobrien    case TYPE_ALU:
10677169699Skan      gcc_assert (operands[2] == const1_rtx);
1067890286Sobrien      return "add{l}\t{%k0, %k0|%k0, %k0}";
1067990286Sobrien
1068090286Sobrien    case TYPE_LEA:
1068190286Sobrien      return "#";
1068290286Sobrien
1068390286Sobrien    default:
1068490286Sobrien      if (REG_P (operands[2]))
1068590286Sobrien	return "sal{l}\t{%b2, %k0|%k0, %b2}";
10686169699Skan      else if (operands[2] == const1_rtx
10687117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1068890286Sobrien	return "sal{l}\t%k0";
1068990286Sobrien      else
1069090286Sobrien	return "sal{l}\t{%2, %k0|%k0, %2}";
1069190286Sobrien    }
1069290286Sobrien}
1069390286Sobrien  [(set (attr "type")
1069490286Sobrien     (cond [(eq_attr "alternative" "1")
1069590286Sobrien	      (const_string "lea")
1069690286Sobrien            (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1069790286Sobrien		     (const_int 0))
1069890286Sobrien		 (match_operand 2 "const1_operand" ""))
1069990286Sobrien	      (const_string "alu")
1070090286Sobrien	   ]
1070190286Sobrien	   (const_string "ishift")))
1070290286Sobrien   (set_attr "mode" "SI")])
1070390286Sobrien
1070490286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1070590286Sobrien(define_split
1070690286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1070790286Sobrien	(zero_extend:DI (ashift (match_operand 1 "register_operand" "")
1070890286Sobrien				(match_operand:QI 2 "const_int_operand" ""))))
10709169699Skan   (clobber (reg:CC FLAGS_REG))]
10710132727Skan  "TARGET_64BIT && reload_completed
1071190286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
10712132727Skan  [(set (match_dup 0) (zero_extend:DI
10713132727Skan			(subreg:SI (mult:SI (match_dup 1)
10714132727Skan					    (match_dup 2)) 0)))]
1071590286Sobrien{
1071690286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
10717117404Skan  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
1071890286Sobrien})
1071990286Sobrien
1072090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1072190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1072290286Sobrien;; zero are optimized away.
1072390286Sobrien(define_insn "*ashlsi3_cmp"
10724169699Skan  [(set (reg FLAGS_REG)
1072590286Sobrien	(compare
1072690286Sobrien	  (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
10727169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1072890286Sobrien	  (const_int 0)))
1072990286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1073090286Sobrien	(ashift:SI (match_dup 1) (match_dup 2)))]
1073190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
10732169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10733169699Skan   && (optimize_size
10734169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10735169699Skan       || (operands[2] == const1_rtx
10736169699Skan	   && (TARGET_SHIFT1
10737169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1073890286Sobrien{
1073990286Sobrien  switch (get_attr_type (insn))
1074090286Sobrien    {
1074190286Sobrien    case TYPE_ALU:
10742169699Skan      gcc_assert (operands[2] == const1_rtx);
1074390286Sobrien      return "add{l}\t{%0, %0|%0, %0}";
1074490286Sobrien
1074590286Sobrien    default:
1074690286Sobrien      if (REG_P (operands[2]))
1074790286Sobrien	return "sal{l}\t{%b2, %0|%0, %b2}";
10748169699Skan      else if (operands[2] == const1_rtx
10749117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1075090286Sobrien	return "sal{l}\t%0";
1075190286Sobrien      else
1075290286Sobrien	return "sal{l}\t{%2, %0|%0, %2}";
1075390286Sobrien    }
1075490286Sobrien}
1075590286Sobrien  [(set (attr "type")
1075690286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1075790286Sobrien		          (const_int 0))
1075890286Sobrien		      (match_operand 0 "register_operand" ""))
1075990286Sobrien		 (match_operand 2 "const1_operand" ""))
1076090286Sobrien	      (const_string "alu")
1076190286Sobrien	   ]
1076290286Sobrien	   (const_string "ishift")))
1076390286Sobrien   (set_attr "mode" "SI")])
1076490286Sobrien
10765169699Skan(define_insn "*ashlsi3_cconly"
10766169699Skan  [(set (reg FLAGS_REG)
10767169699Skan	(compare
10768169699Skan	  (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
10769169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
10770169699Skan	  (const_int 0)))
10771169699Skan   (clobber (match_scratch:SI 0 "=r"))]
10772169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
10773169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10774169699Skan   && (optimize_size
10775169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10776169699Skan       || (operands[2] == const1_rtx
10777169699Skan	   && (TARGET_SHIFT1
10778169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10779169699Skan{
10780169699Skan  switch (get_attr_type (insn))
10781169699Skan    {
10782169699Skan    case TYPE_ALU:
10783169699Skan      gcc_assert (operands[2] == const1_rtx);
10784169699Skan      return "add{l}\t{%0, %0|%0, %0}";
10785169699Skan
10786169699Skan    default:
10787169699Skan      if (REG_P (operands[2]))
10788169699Skan	return "sal{l}\t{%b2, %0|%0, %b2}";
10789169699Skan      else if (operands[2] == const1_rtx
10790169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10791169699Skan	return "sal{l}\t%0";
10792169699Skan      else
10793169699Skan	return "sal{l}\t{%2, %0|%0, %2}";
10794169699Skan    }
10795169699Skan}
10796169699Skan  [(set (attr "type")
10797169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
10798169699Skan		          (const_int 0))
10799169699Skan		      (match_operand 0 "register_operand" ""))
10800169699Skan		 (match_operand 2 "const1_operand" ""))
10801169699Skan	      (const_string "alu")
10802169699Skan	   ]
10803169699Skan	   (const_string "ishift")))
10804169699Skan   (set_attr "mode" "SI")])
10805169699Skan
1080690286Sobrien(define_insn "*ashlsi3_cmp_zext"
10807169699Skan  [(set (reg FLAGS_REG)
1080890286Sobrien	(compare
1080990286Sobrien	  (ashift:SI (match_operand:SI 1 "register_operand" "0")
10810169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1081190286Sobrien	  (const_int 0)))
1081290286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1081390286Sobrien	(zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
1081490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10815169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10816169699Skan   && (optimize_size
10817169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10818169699Skan       || (operands[2] == const1_rtx
10819169699Skan	   && (TARGET_SHIFT1
10820169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
1082190286Sobrien{
1082290286Sobrien  switch (get_attr_type (insn))
1082390286Sobrien    {
1082490286Sobrien    case TYPE_ALU:
10825169699Skan      gcc_assert (operands[2] == const1_rtx);
1082690286Sobrien      return "add{l}\t{%k0, %k0|%k0, %k0}";
1082790286Sobrien
1082890286Sobrien    default:
1082990286Sobrien      if (REG_P (operands[2]))
1083090286Sobrien	return "sal{l}\t{%b2, %k0|%k0, %b2}";
10831169699Skan      else if (operands[2] == const1_rtx
10832117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1083390286Sobrien	return "sal{l}\t%k0";
1083490286Sobrien      else
1083590286Sobrien	return "sal{l}\t{%2, %k0|%k0, %2}";
1083690286Sobrien    }
1083790286Sobrien}
1083890286Sobrien  [(set (attr "type")
1083990286Sobrien     (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1084090286Sobrien		     (const_int 0))
1084190286Sobrien		 (match_operand 2 "const1_operand" ""))
1084290286Sobrien	      (const_string "alu")
1084390286Sobrien	   ]
1084490286Sobrien	   (const_string "ishift")))
1084590286Sobrien   (set_attr "mode" "SI")])
1084690286Sobrien
1084752296Sobrien(define_expand "ashlhi3"
1084852296Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1084952296Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
1085090286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10851169699Skan   (clobber (reg:CC FLAGS_REG))]
1085290286Sobrien  "TARGET_HIMODE_MATH"
1085390286Sobrien  "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;")
1085418334Speter
1085590286Sobrien(define_insn "*ashlhi3_1_lea"
1085690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
10857169699Skan	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l")
1085890286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,M")))
10859169699Skan   (clobber (reg:CC FLAGS_REG))]
1086090286Sobrien  "!TARGET_PARTIAL_REG_STALL
1086190286Sobrien   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
1086290286Sobrien{
1086390286Sobrien  switch (get_attr_type (insn))
1086490286Sobrien    {
1086590286Sobrien    case TYPE_LEA:
1086690286Sobrien      return "#";
1086790286Sobrien    case TYPE_ALU:
10868169699Skan      gcc_assert (operands[2] == const1_rtx);
1086990286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1087090286Sobrien
1087190286Sobrien    default:
1087290286Sobrien      if (REG_P (operands[2]))
1087390286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10874169699Skan      else if (operands[2] == const1_rtx
10875117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1087690286Sobrien	return "sal{w}\t%0";
1087790286Sobrien      else
1087890286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1087990286Sobrien    }
1088090286Sobrien}
1088190286Sobrien  [(set (attr "type")
1088290286Sobrien     (cond [(eq_attr "alternative" "1")
1088390286Sobrien	      (const_string "lea")
1088490286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1088590286Sobrien		          (const_int 0))
1088690286Sobrien		      (match_operand 0 "register_operand" ""))
1088790286Sobrien		 (match_operand 2 "const1_operand" ""))
1088890286Sobrien	      (const_string "alu")
1088990286Sobrien	   ]
1089090286Sobrien	   (const_string "ishift")))
1089190286Sobrien   (set_attr "mode" "HI,SI")])
1089290286Sobrien
1089390286Sobrien(define_insn "*ashlhi3_1"
1089490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1089590286Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
1089690286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI")))
10897169699Skan   (clobber (reg:CC FLAGS_REG))]
1089890286Sobrien  "TARGET_PARTIAL_REG_STALL
1089990286Sobrien   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
1090090286Sobrien{
1090190286Sobrien  switch (get_attr_type (insn))
1090290286Sobrien    {
1090390286Sobrien    case TYPE_ALU:
10904169699Skan      gcc_assert (operands[2] == const1_rtx);
1090590286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1090690286Sobrien
1090790286Sobrien    default:
1090890286Sobrien      if (REG_P (operands[2]))
1090990286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10910169699Skan      else if (operands[2] == const1_rtx
10911117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1091290286Sobrien	return "sal{w}\t%0";
1091390286Sobrien      else
1091490286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1091590286Sobrien    }
1091690286Sobrien}
1091790286Sobrien  [(set (attr "type")
1091890286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1091990286Sobrien		          (const_int 0))
1092090286Sobrien		      (match_operand 0 "register_operand" ""))
1092190286Sobrien		 (match_operand 2 "const1_operand" ""))
1092290286Sobrien	      (const_string "alu")
1092390286Sobrien	   ]
1092490286Sobrien	   (const_string "ishift")))
1092590286Sobrien   (set_attr "mode" "HI")])
1092690286Sobrien
1092790286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1092890286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1092990286Sobrien;; zero are optimized away.
1093090286Sobrien(define_insn "*ashlhi3_cmp"
10931169699Skan  [(set (reg FLAGS_REG)
1093290286Sobrien	(compare
1093390286Sobrien	  (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
10934169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1093590286Sobrien	  (const_int 0)))
1093690286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1093790286Sobrien	(ashift:HI (match_dup 1) (match_dup 2)))]
1093890286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
10939169699Skan   && ix86_binary_operator_ok (ASHIFT, HImode, operands)
10940169699Skan   && (optimize_size
10941169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10942169699Skan       || (operands[2] == const1_rtx
10943169699Skan	   && (TARGET_SHIFT1
10944169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1094590286Sobrien{
1094690286Sobrien  switch (get_attr_type (insn))
1094790286Sobrien    {
1094890286Sobrien    case TYPE_ALU:
10949169699Skan      gcc_assert (operands[2] == const1_rtx);
1095090286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1095190286Sobrien
1095290286Sobrien    default:
1095390286Sobrien      if (REG_P (operands[2]))
1095490286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10955169699Skan      else if (operands[2] == const1_rtx
10956117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1095790286Sobrien	return "sal{w}\t%0";
1095890286Sobrien      else
1095990286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1096090286Sobrien    }
1096190286Sobrien}
1096290286Sobrien  [(set (attr "type")
1096390286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1096490286Sobrien		          (const_int 0))
1096590286Sobrien		      (match_operand 0 "register_operand" ""))
1096690286Sobrien		 (match_operand 2 "const1_operand" ""))
1096790286Sobrien	      (const_string "alu")
1096890286Sobrien	   ]
1096990286Sobrien	   (const_string "ishift")))
1097090286Sobrien   (set_attr "mode" "HI")])
1097190286Sobrien
10972169699Skan(define_insn "*ashlhi3_cconly"
10973169699Skan  [(set (reg FLAGS_REG)
10974169699Skan	(compare
10975169699Skan	  (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
10976169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
10977169699Skan	  (const_int 0)))
10978169699Skan   (clobber (match_scratch:HI 0 "=r"))]
10979169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
10980169699Skan   && ix86_binary_operator_ok (ASHIFT, HImode, operands)
10981169699Skan   && (optimize_size
10982169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10983169699Skan       || (operands[2] == const1_rtx
10984169699Skan	   && (TARGET_SHIFT1
10985169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10986169699Skan{
10987169699Skan  switch (get_attr_type (insn))
10988169699Skan    {
10989169699Skan    case TYPE_ALU:
10990169699Skan      gcc_assert (operands[2] == const1_rtx);
10991169699Skan      return "add{w}\t{%0, %0|%0, %0}";
10992169699Skan
10993169699Skan    default:
10994169699Skan      if (REG_P (operands[2]))
10995169699Skan	return "sal{w}\t{%b2, %0|%0, %b2}";
10996169699Skan      else if (operands[2] == const1_rtx
10997169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10998169699Skan	return "sal{w}\t%0";
10999169699Skan      else
11000169699Skan	return "sal{w}\t{%2, %0|%0, %2}";
11001169699Skan    }
11002169699Skan}
11003169699Skan  [(set (attr "type")
11004169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
11005169699Skan		          (const_int 0))
11006169699Skan		      (match_operand 0 "register_operand" ""))
11007169699Skan		 (match_operand 2 "const1_operand" ""))
11008169699Skan	      (const_string "alu")
11009169699Skan	   ]
11010169699Skan	   (const_string "ishift")))
11011169699Skan   (set_attr "mode" "HI")])
11012169699Skan
1101352296Sobrien(define_expand "ashlqi3"
1101452296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1101552296Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
1101690286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
11017169699Skan   (clobber (reg:CC FLAGS_REG))]
1101890286Sobrien  "TARGET_QIMODE_MATH"
1101990286Sobrien  "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;")
1102018334Speter
1102190286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
1102218334Speter
1102390286Sobrien(define_insn "*ashlqi3_1_lea"
1102490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r")
11025169699Skan	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l")
1102690286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,cI,M")))
11027169699Skan   (clobber (reg:CC FLAGS_REG))]
1102890286Sobrien  "!TARGET_PARTIAL_REG_STALL
1102990286Sobrien   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
1103090286Sobrien{
1103190286Sobrien  switch (get_attr_type (insn))
1103290286Sobrien    {
1103390286Sobrien    case TYPE_LEA:
1103490286Sobrien      return "#";
1103590286Sobrien    case TYPE_ALU:
11036169699Skan      gcc_assert (operands[2] == const1_rtx);
1103790286Sobrien      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
1103890286Sobrien        return "add{l}\t{%k0, %k0|%k0, %k0}";
1103990286Sobrien      else
1104090286Sobrien        return "add{b}\t{%0, %0|%0, %0}";
1104118334Speter
1104290286Sobrien    default:
1104390286Sobrien      if (REG_P (operands[2]))
1104490286Sobrien	{
1104590286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1104690286Sobrien	    return "sal{l}\t{%b2, %k0|%k0, %b2}";
1104790286Sobrien	  else
1104890286Sobrien	    return "sal{b}\t{%b2, %0|%0, %b2}";
1104990286Sobrien	}
11050169699Skan      else if (operands[2] == const1_rtx
11051117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1105290286Sobrien	{
1105390286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1105490286Sobrien	    return "sal{l}\t%0";
1105590286Sobrien	  else
1105690286Sobrien	    return "sal{b}\t%0";
1105790286Sobrien	}
1105890286Sobrien      else
1105990286Sobrien	{
1106090286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1106190286Sobrien	    return "sal{l}\t{%2, %k0|%k0, %2}";
1106290286Sobrien	  else
1106390286Sobrien	    return "sal{b}\t{%2, %0|%0, %2}";
1106490286Sobrien	}
1106590286Sobrien    }
1106690286Sobrien}
1106790286Sobrien  [(set (attr "type")
1106890286Sobrien     (cond [(eq_attr "alternative" "2")
1106990286Sobrien	      (const_string "lea")
1107090286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1107190286Sobrien		          (const_int 0))
1107290286Sobrien		      (match_operand 0 "register_operand" ""))
1107390286Sobrien		 (match_operand 2 "const1_operand" ""))
1107490286Sobrien	      (const_string "alu")
1107590286Sobrien	   ]
1107690286Sobrien	   (const_string "ishift")))
1107790286Sobrien   (set_attr "mode" "QI,SI,SI")])
1107818334Speter
1107990286Sobrien(define_insn "*ashlqi3_1"
1108090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
1108190286Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1108290286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
11083169699Skan   (clobber (reg:CC FLAGS_REG))]
1108490286Sobrien  "TARGET_PARTIAL_REG_STALL
1108590286Sobrien   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
1108690286Sobrien{
1108790286Sobrien  switch (get_attr_type (insn))
1108890286Sobrien    {
1108990286Sobrien    case TYPE_ALU:
11090169699Skan      gcc_assert (operands[2] == const1_rtx);
1109190286Sobrien      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
1109290286Sobrien        return "add{l}\t{%k0, %k0|%k0, %k0}";
1109390286Sobrien      else
1109490286Sobrien        return "add{b}\t{%0, %0|%0, %0}";
1109552296Sobrien
1109690286Sobrien    default:
1109790286Sobrien      if (REG_P (operands[2]))
1109890286Sobrien	{
1109990286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1110090286Sobrien	    return "sal{l}\t{%b2, %k0|%k0, %b2}";
1110190286Sobrien	  else
1110290286Sobrien	    return "sal{b}\t{%b2, %0|%0, %b2}";
1110390286Sobrien	}
11104169699Skan      else if (operands[2] == const1_rtx
11105117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1110690286Sobrien	{
1110790286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1110890286Sobrien	    return "sal{l}\t%0";
1110990286Sobrien	  else
1111090286Sobrien	    return "sal{b}\t%0";
1111190286Sobrien	}
1111290286Sobrien      else
1111390286Sobrien	{
1111490286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1111590286Sobrien	    return "sal{l}\t{%2, %k0|%k0, %2}";
1111690286Sobrien	  else
1111790286Sobrien	    return "sal{b}\t{%2, %0|%0, %2}";
1111890286Sobrien	}
1111990286Sobrien    }
1112090286Sobrien}
1112190286Sobrien  [(set (attr "type")
1112290286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1112390286Sobrien		          (const_int 0))
1112490286Sobrien		      (match_operand 0 "register_operand" ""))
1112590286Sobrien		 (match_operand 2 "const1_operand" ""))
1112690286Sobrien	      (const_string "alu")
1112790286Sobrien	   ]
1112890286Sobrien	   (const_string "ishift")))
1112990286Sobrien   (set_attr "mode" "QI,SI")])
1113018334Speter
1113190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1113290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1113390286Sobrien;; zero are optimized away.
1113490286Sobrien(define_insn "*ashlqi3_cmp"
11135169699Skan  [(set (reg FLAGS_REG)
1113690286Sobrien	(compare
1113790286Sobrien	  (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11138169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1113990286Sobrien	  (const_int 0)))
1114090286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1114190286Sobrien	(ashift:QI (match_dup 1) (match_dup 2)))]
1114290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11143169699Skan   && ix86_binary_operator_ok (ASHIFT, QImode, operands)
11144169699Skan   && (optimize_size
11145169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11146169699Skan       || (operands[2] == const1_rtx
11147169699Skan	   && (TARGET_SHIFT1
11148169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1114990286Sobrien{
1115090286Sobrien  switch (get_attr_type (insn))
1115190286Sobrien    {
1115290286Sobrien    case TYPE_ALU:
11153169699Skan      gcc_assert (operands[2] == const1_rtx);
1115490286Sobrien      return "add{b}\t{%0, %0|%0, %0}";
1115518334Speter
1115690286Sobrien    default:
1115790286Sobrien      if (REG_P (operands[2]))
1115890286Sobrien	return "sal{b}\t{%b2, %0|%0, %b2}";
11159169699Skan      else if (operands[2] == const1_rtx
11160117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1116190286Sobrien	return "sal{b}\t%0";
1116290286Sobrien      else
1116390286Sobrien	return "sal{b}\t{%2, %0|%0, %2}";
1116490286Sobrien    }
1116590286Sobrien}
1116690286Sobrien  [(set (attr "type")
1116790286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1116890286Sobrien		          (const_int 0))
1116990286Sobrien		      (match_operand 0 "register_operand" ""))
1117090286Sobrien		 (match_operand 2 "const1_operand" ""))
1117190286Sobrien	      (const_string "alu")
1117290286Sobrien	   ]
1117390286Sobrien	   (const_string "ishift")))
1117490286Sobrien   (set_attr "mode" "QI")])
1117518334Speter
11176169699Skan(define_insn "*ashlqi3_cconly"
11177169699Skan  [(set (reg FLAGS_REG)
11178169699Skan	(compare
11179169699Skan	  (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11180169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
11181169699Skan	  (const_int 0)))
11182169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11183169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11184169699Skan   && ix86_binary_operator_ok (ASHIFT, QImode, operands)
11185169699Skan   && (optimize_size
11186169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11187169699Skan       || (operands[2] == const1_rtx
11188169699Skan	   && (TARGET_SHIFT1
11189169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
11190169699Skan{
11191169699Skan  switch (get_attr_type (insn))
11192169699Skan    {
11193169699Skan    case TYPE_ALU:
11194169699Skan      gcc_assert (operands[2] == const1_rtx);
11195169699Skan      return "add{b}\t{%0, %0|%0, %0}";
11196169699Skan
11197169699Skan    default:
11198169699Skan      if (REG_P (operands[2]))
11199169699Skan	return "sal{b}\t{%b2, %0|%0, %b2}";
11200169699Skan      else if (operands[2] == const1_rtx
11201169699Skan	       && (TARGET_SHIFT1 || optimize_size))
11202169699Skan	return "sal{b}\t%0";
11203169699Skan      else
11204169699Skan	return "sal{b}\t{%2, %0|%0, %2}";
11205169699Skan    }
11206169699Skan}
11207169699Skan  [(set (attr "type")
11208169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
11209169699Skan		          (const_int 0))
11210169699Skan		      (match_operand 0 "register_operand" ""))
11211169699Skan		 (match_operand 2 "const1_operand" ""))
11212169699Skan	      (const_string "alu")
11213169699Skan	   ]
11214169699Skan	   (const_string "ishift")))
11215169699Skan   (set_attr "mode" "QI")])
11216169699Skan
1121718334Speter;; See comment above `ashldi3' about how this works.
1121818334Speter
11219169699Skan(define_expand "ashrti3"
11220169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
11221169699Skan		   (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
1122290286Sobrien				(match_operand:QI 2 "nonmemory_operand" "")))
11223169699Skan	      (clobber (reg:CC FLAGS_REG))])]
11224169699Skan  "TARGET_64BIT"
1122518334Speter{
11226169699Skan  if (! immediate_operand (operands[2], QImode))
1122718334Speter    {
11228169699Skan      emit_insn (gen_ashrti3_1 (operands[0], operands[1], operands[2]));
1122990286Sobrien      DONE;
1123018334Speter    }
11231169699Skan  ix86_expand_binary_operator (ASHIFTRT, TImode, operands);
1123218334Speter  DONE;
1123390286Sobrien})
1123418334Speter
11235169699Skan(define_insn "ashrti3_1"
11236169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11237169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
11238169699Skan		     (match_operand:QI 2 "register_operand" "c")))
11239169699Skan   (clobber (match_scratch:DI 3 "=&r"))
11240169699Skan   (clobber (reg:CC FLAGS_REG))]
11241169699Skan  "TARGET_64BIT"
11242169699Skan  "#"
11243169699Skan  [(set_attr "type" "multi")])
11244169699Skan
11245169699Skan(define_insn "*ashrti3_2"
11246169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11247169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
11248169699Skan		     (match_operand:QI 2 "immediate_operand" "O")))
11249169699Skan   (clobber (reg:CC FLAGS_REG))]
11250169699Skan  "TARGET_64BIT"
11251169699Skan  "#"
11252169699Skan  [(set_attr "type" "multi")])
11253169699Skan
11254169699Skan(define_split
11255169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11256169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "")
11257169699Skan		     (match_operand:QI 2 "register_operand" "")))
11258169699Skan   (clobber (match_scratch:DI 3 ""))
11259169699Skan   (clobber (reg:CC FLAGS_REG))]
11260169699Skan  "TARGET_64BIT && reload_completed"
11261169699Skan  [(const_int 0)]
11262169699Skan  "ix86_split_ashr (operands, operands[3], TImode); DONE;")
11263169699Skan
11264169699Skan(define_split
11265169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11266169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "")
11267169699Skan		     (match_operand:QI 2 "immediate_operand" "")))
11268169699Skan   (clobber (reg:CC FLAGS_REG))]
11269169699Skan  "TARGET_64BIT && reload_completed"
11270169699Skan  [(const_int 0)]
11271169699Skan  "ix86_split_ashr (operands, NULL_RTX, TImode); DONE;")
11272169699Skan
11273169699Skan(define_insn "x86_64_shrd"
11274169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
11275169699Skan        (ior:DI (ashiftrt:DI (match_dup 0)
11276169699Skan		  (match_operand:QI 2 "nonmemory_operand" "J,c"))
11277169699Skan		(ashift:DI (match_operand:DI 1 "register_operand" "r,r")
11278169699Skan		  (minus:QI (const_int 64) (match_dup 2)))))
11279169699Skan   (clobber (reg:CC FLAGS_REG))]
11280169699Skan  "TARGET_64BIT"
11281169699Skan  "@
11282169699Skan   shrd{q}\t{%2, %1, %0|%0, %1, %2}
11283169699Skan   shrd{q}\t{%s2%1, %0|%0, %1, %2}"
11284169699Skan  [(set_attr "type" "ishift")
11285169699Skan   (set_attr "prefix_0f" "1")
11286169699Skan   (set_attr "mode" "DI")
11287169699Skan   (set_attr "athlon_decode" "vector")])
11288169699Skan
11289169699Skan(define_expand "ashrdi3"
11290169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
11291169699Skan	(ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
11292169699Skan		     (match_operand:QI 2 "nonmemory_operand" "")))]
11293169699Skan  ""
11294169699Skan  "ix86_expand_binary_operator (ASHIFTRT, DImode, operands); DONE;")
11295169699Skan
11296169699Skan(define_insn "*ashrdi3_63_rex64"
1129790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=*d,rm")
1129890286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "*a,0")
1129990286Sobrien		     (match_operand:DI 2 "const_int_operand" "i,i")))
11300169699Skan   (clobber (reg:CC FLAGS_REG))]
11301169699Skan  "TARGET_64BIT && INTVAL (operands[2]) == 63
11302169699Skan   && (TARGET_USE_CLTD || optimize_size)
1130390286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1130490286Sobrien  "@
1130590286Sobrien   {cqto|cqo}
1130690286Sobrien   sar{q}\t{%2, %0|%0, %2}"
1130790286Sobrien  [(set_attr "type" "imovx,ishift")
1130890286Sobrien   (set_attr "prefix_0f" "0,*")
1130990286Sobrien   (set_attr "length_immediate" "0,*")
1131090286Sobrien   (set_attr "modrm" "0,1")
1131190286Sobrien   (set_attr "mode" "DI")])
1131250650Sobrien
1131390286Sobrien(define_insn "*ashrdi3_1_one_bit_rex64"
1131490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1131590286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11316132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11317169699Skan   (clobber (reg:CC FLAGS_REG))]
1131890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11319117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1132090286Sobrien  "sar{q}\t%0"
1132190286Sobrien  [(set_attr "type" "ishift")
1132290286Sobrien   (set (attr "length") 
1132390286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1132490286Sobrien	(const_string "2")
1132590286Sobrien	(const_string "*")))])
1132650650Sobrien
1132790286Sobrien(define_insn "*ashrdi3_1_rex64"
1132890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1132990286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1133090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
11331169699Skan   (clobber (reg:CC FLAGS_REG))]
1133290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1133390286Sobrien  "@
1133490286Sobrien   sar{q}\t{%2, %0|%0, %2}
1133590286Sobrien   sar{q}\t{%b2, %0|%0, %b2}"
1133690286Sobrien  [(set_attr "type" "ishift")
1133790286Sobrien   (set_attr "mode" "DI")])
1133850650Sobrien
1133990286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1134090286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1134190286Sobrien;; zero are optimized away.
1134290286Sobrien(define_insn "*ashrdi3_one_bit_cmp_rex64"
11343169699Skan  [(set (reg FLAGS_REG)
1134490286Sobrien	(compare
1134590286Sobrien	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11346132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1134790286Sobrien	  (const_int 0)))
1134890286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1134990286Sobrien	(ashiftrt:DI (match_dup 1) (match_dup 2)))]
1135090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11351117404Skan   && (TARGET_SHIFT1 || optimize_size)
1135290286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1135390286Sobrien  "sar{q}\t%0"
1135490286Sobrien  [(set_attr "type" "ishift")
1135590286Sobrien   (set (attr "length") 
1135690286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1135790286Sobrien	(const_string "2")
1135890286Sobrien	(const_string "*")))])
1135950650Sobrien
11360169699Skan(define_insn "*ashrdi3_one_bit_cconly_rex64"
11361169699Skan  [(set (reg FLAGS_REG)
11362169699Skan	(compare
11363169699Skan	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11364169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11365169699Skan	  (const_int 0)))
11366169699Skan   (clobber (match_scratch:DI 0 "=r"))]
11367169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11368169699Skan   && (TARGET_SHIFT1 || optimize_size)
11369169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
11370169699Skan  "sar{q}\t%0"
11371169699Skan  [(set_attr "type" "ishift")
11372169699Skan   (set_attr "length" "2")])
11373169699Skan
1137490286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1137590286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1137690286Sobrien;; zero are optimized away.
1137790286Sobrien(define_insn "*ashrdi3_cmp_rex64"
11378169699Skan  [(set (reg FLAGS_REG)
1137990286Sobrien	(compare
1138090286Sobrien	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1138190286Sobrien		       (match_operand:QI 2 "const_int_operand" "n"))
1138290286Sobrien	  (const_int 0)))
1138390286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1138490286Sobrien	(ashiftrt:DI (match_dup 1) (match_dup 2)))]
1138590286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11386169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11387169699Skan   && (optimize_size
11388169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1138990286Sobrien  "sar{q}\t{%2, %0|%0, %2}"
1139090286Sobrien  [(set_attr "type" "ishift")
1139190286Sobrien   (set_attr "mode" "DI")])
1139218334Speter
11393169699Skan(define_insn "*ashrdi3_cconly_rex64"
11394169699Skan  [(set (reg FLAGS_REG)
11395169699Skan	(compare
11396169699Skan	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11397169699Skan		       (match_operand:QI 2 "const_int_operand" "n"))
11398169699Skan	  (const_int 0)))
11399169699Skan   (clobber (match_scratch:DI 0 "=r"))]
11400169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11401169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11402169699Skan   && (optimize_size
11403169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11404169699Skan  "sar{q}\t{%2, %0|%0, %2}"
11405169699Skan  [(set_attr "type" "ishift")
11406169699Skan   (set_attr "mode" "DI")])
1140718334Speter
11408169699Skan(define_insn "*ashrdi3_1"
1140990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1141090286Sobrien	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
1141190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "Jc")))
11412169699Skan   (clobber (reg:CC FLAGS_REG))]
1141390286Sobrien  "!TARGET_64BIT"
1141490286Sobrien  "#"
1141590286Sobrien  [(set_attr "type" "multi")])
1141618334Speter
11417169699Skan;; By default we don't ask for a scratch register, because when DImode
11418169699Skan;; values are manipulated, registers are already at a premium.  But if
11419169699Skan;; we have one handy, we won't turn it away.
11420169699Skan(define_peephole2
11421169699Skan  [(match_scratch:SI 3 "r")
11422169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
11423169699Skan		   (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
11424169699Skan			        (match_operand:QI 2 "nonmemory_operand" "")))
11425169699Skan	      (clobber (reg:CC FLAGS_REG))])
11426169699Skan   (match_dup 3)]
11427169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1142890286Sobrien  [(const_int 0)]
11429169699Skan  "ix86_split_ashr (operands, operands[3], DImode); DONE;")
1143018334Speter
1143190286Sobrien(define_split
1143290286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1143390286Sobrien	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
1143490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11435169699Skan   (clobber (reg:CC FLAGS_REG))]
11436169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
11437169699Skan		     ? flow2_completed : reload_completed)"
1143890286Sobrien  [(const_int 0)]
11439169699Skan  "ix86_split_ashr (operands, NULL_RTX, DImode); DONE;")
1144018334Speter
1144190286Sobrien(define_insn "x86_shrd_1"
1144290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
1144390286Sobrien        (ior:SI (ashiftrt:SI (match_dup 0)
1144490286Sobrien		  (match_operand:QI 2 "nonmemory_operand" "I,c"))
1144590286Sobrien		(ashift:SI (match_operand:SI 1 "register_operand" "r,r")
1144690286Sobrien		  (minus:QI (const_int 32) (match_dup 2)))))
11447169699Skan   (clobber (reg:CC FLAGS_REG))]
1144818334Speter  ""
1144990286Sobrien  "@
1145090286Sobrien   shrd{l}\t{%2, %1, %0|%0, %1, %2}
1145190286Sobrien   shrd{l}\t{%s2%1, %0|%0, %1, %2}"
1145290286Sobrien  [(set_attr "type" "ishift")
1145390286Sobrien   (set_attr "prefix_0f" "1")
1145490286Sobrien   (set_attr "pent_pair" "np")
1145590286Sobrien   (set_attr "mode" "SI")])
1145690286Sobrien
1145790286Sobrien(define_expand "x86_shift_adj_3"
1145890286Sobrien  [(use (match_operand:SI 0 "register_operand" ""))
1145990286Sobrien   (use (match_operand:SI 1 "register_operand" ""))
1146090286Sobrien   (use (match_operand:QI 2 "register_operand" ""))]
1146190286Sobrien  ""
1146218334Speter{
1146390286Sobrien  rtx label = gen_label_rtx ();
1146490286Sobrien  rtx tmp;
1146518334Speter
1146690286Sobrien  emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
1146718334Speter
1146890286Sobrien  tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
1146990286Sobrien  tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1147090286Sobrien  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
1147190286Sobrien			      gen_rtx_LABEL_REF (VOIDmode, label),
1147290286Sobrien			      pc_rtx);
1147390286Sobrien  tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
1147490286Sobrien  JUMP_LABEL (tmp) = label;
1147518334Speter
1147690286Sobrien  emit_move_insn (operands[0], operands[1]);
1147790286Sobrien  emit_insn (gen_ashrsi3_31 (operands[1], operands[1], GEN_INT (31)));
1147818334Speter
1147990286Sobrien  emit_label (label);
1148090286Sobrien  LABEL_NUSES (label) = 1;
1148190286Sobrien
1148290286Sobrien  DONE;
1148390286Sobrien})
1148490286Sobrien
1148552296Sobrien(define_insn "ashrsi3_31"
1148690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm")
1148790286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0")
1148890286Sobrien		     (match_operand:SI 2 "const_int_operand" "i,i")))
11489169699Skan   (clobber (reg:CC FLAGS_REG))]
1149090286Sobrien  "INTVAL (operands[2]) == 31 && (TARGET_USE_CLTD || optimize_size)
1149190286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1149252296Sobrien  "@
1149390286Sobrien   {cltd|cdq}
1149490286Sobrien   sar{l}\t{%2, %0|%0, %2}"
1149590286Sobrien  [(set_attr "type" "imovx,ishift")
1149690286Sobrien   (set_attr "prefix_0f" "0,*")
1149790286Sobrien   (set_attr "length_immediate" "0,*")
1149890286Sobrien   (set_attr "modrm" "0,1")
1149990286Sobrien   (set_attr "mode" "SI")])
1150052296Sobrien
1150190286Sobrien(define_insn "*ashrsi3_31_zext"
1150290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*d,r")
1150390286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "*a,0")
1150490286Sobrien				     (match_operand:SI 2 "const_int_operand" "i,i"))))
11505169699Skan   (clobber (reg:CC FLAGS_REG))]
1150690286Sobrien  "TARGET_64BIT && (TARGET_USE_CLTD || optimize_size)
1150790286Sobrien   && INTVAL (operands[2]) == 31
1150890286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1150990286Sobrien  "@
1151090286Sobrien   {cltd|cdq}
1151190286Sobrien   sar{l}\t{%2, %k0|%k0, %2}"
1151290286Sobrien  [(set_attr "type" "imovx,ishift")
1151390286Sobrien   (set_attr "prefix_0f" "0,*")
1151490286Sobrien   (set_attr "length_immediate" "0,*")
1151590286Sobrien   (set_attr "modrm" "0,1")
1151690286Sobrien   (set_attr "mode" "SI")])
1151790286Sobrien
1151890286Sobrien(define_expand "ashrsi3"
1151990286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1152090286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
1152190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11522169699Skan   (clobber (reg:CC FLAGS_REG))]
1152390286Sobrien  ""
1152490286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, SImode, operands); DONE;")
1152590286Sobrien
1152690286Sobrien(define_insn "*ashrsi3_1_one_bit"
1152750650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1152850650Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11529132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11530169699Skan   (clobber (reg:CC FLAGS_REG))]
1153190286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11532117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1153390286Sobrien  "sar{l}\t%0"
1153490286Sobrien  [(set_attr "type" "ishift")
1153590286Sobrien   (set (attr "length") 
1153690286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1153790286Sobrien	(const_string "2")
1153890286Sobrien	(const_string "*")))])
1153918334Speter
1154090286Sobrien(define_insn "*ashrsi3_1_one_bit_zext"
1154190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1154290286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11543132727Skan				     (match_operand:QI 2 "const1_operand" ""))))
11544169699Skan   (clobber (reg:CC FLAGS_REG))]
1154590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11546117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1154790286Sobrien  "sar{l}\t%k0"
1154890286Sobrien  [(set_attr "type" "ishift")
1154990286Sobrien   (set_attr "length" "2")])
1155090286Sobrien
1155190286Sobrien(define_insn "*ashrsi3_1"
1155290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1155390286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1155490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11555169699Skan   (clobber (reg:CC FLAGS_REG))]
1155690286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1155790286Sobrien  "@
1155890286Sobrien   sar{l}\t{%2, %0|%0, %2}
1155990286Sobrien   sar{l}\t{%b2, %0|%0, %b2}"
1156090286Sobrien  [(set_attr "type" "ishift")
1156190286Sobrien   (set_attr "mode" "SI")])
1156290286Sobrien
1156390286Sobrien(define_insn "*ashrsi3_1_zext"
1156490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1156590286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
1156690286Sobrien				     (match_operand:QI 2 "nonmemory_operand" "I,c"))))
11567169699Skan   (clobber (reg:CC FLAGS_REG))]
1156890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1156990286Sobrien  "@
1157090286Sobrien   sar{l}\t{%2, %k0|%k0, %2}
1157190286Sobrien   sar{l}\t{%b2, %k0|%k0, %b2}"
1157290286Sobrien  [(set_attr "type" "ishift")
1157390286Sobrien   (set_attr "mode" "SI")])
1157490286Sobrien
1157590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1157690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1157790286Sobrien;; zero are optimized away.
1157890286Sobrien(define_insn "*ashrsi3_one_bit_cmp"
11579169699Skan  [(set (reg FLAGS_REG)
1158090286Sobrien	(compare
1158190286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11582132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1158390286Sobrien	  (const_int 0)))
1158490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1158590286Sobrien	(ashiftrt:SI (match_dup 1) (match_dup 2)))]
1158690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11587117404Skan   && (TARGET_SHIFT1 || optimize_size)
1158890286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1158990286Sobrien  "sar{l}\t%0"
1159090286Sobrien  [(set_attr "type" "ishift")
1159190286Sobrien   (set (attr "length") 
1159290286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1159390286Sobrien	(const_string "2")
1159490286Sobrien	(const_string "*")))])
1159590286Sobrien
11596169699Skan(define_insn "*ashrsi3_one_bit_cconly"
11597169699Skan  [(set (reg FLAGS_REG)
11598169699Skan	(compare
11599169699Skan	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11600169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11601169699Skan	  (const_int 0)))
11602169699Skan   (clobber (match_scratch:SI 0 "=r"))]
11603169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11604169699Skan   && (TARGET_SHIFT1 || optimize_size)
11605169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
11606169699Skan  "sar{l}\t%0"
11607169699Skan  [(set_attr "type" "ishift")
11608169699Skan   (set_attr "length" "2")])
11609169699Skan
1161090286Sobrien(define_insn "*ashrsi3_one_bit_cmp_zext"
11611169699Skan  [(set (reg FLAGS_REG)
1161290286Sobrien	(compare
1161390286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11614132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1161590286Sobrien	  (const_int 0)))
1161690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1161790286Sobrien	(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
1161890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
11619117404Skan   && (TARGET_SHIFT1 || optimize_size)
1162090286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1162190286Sobrien  "sar{l}\t%k0"
1162290286Sobrien  [(set_attr "type" "ishift")
1162390286Sobrien   (set_attr "length" "2")])
1162490286Sobrien
1162590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1162690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1162790286Sobrien;; zero are optimized away.
1162890286Sobrien(define_insn "*ashrsi3_cmp"
11629169699Skan  [(set (reg FLAGS_REG)
1163090286Sobrien	(compare
1163190286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11632169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1163390286Sobrien	  (const_int 0)))
1163490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1163590286Sobrien	(ashiftrt:SI (match_dup 1) (match_dup 2)))]
1163690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11637169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11638169699Skan   && (optimize_size
11639169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1164090286Sobrien  "sar{l}\t{%2, %0|%0, %2}"
1164190286Sobrien  [(set_attr "type" "ishift")
1164290286Sobrien   (set_attr "mode" "SI")])
1164390286Sobrien
11644169699Skan(define_insn "*ashrsi3_cconly"
11645169699Skan  [(set (reg FLAGS_REG)
11646169699Skan	(compare
11647169699Skan	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11648169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11649169699Skan	  (const_int 0)))
11650169699Skan   (clobber (match_scratch:SI 0 "=r"))]
11651169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11652169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11653169699Skan   && (optimize_size
11654169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11655169699Skan  "sar{l}\t{%2, %0|%0, %2}"
11656169699Skan  [(set_attr "type" "ishift")
11657169699Skan   (set_attr "mode" "SI")])
11658169699Skan
1165990286Sobrien(define_insn "*ashrsi3_cmp_zext"
11660169699Skan  [(set (reg FLAGS_REG)
1166190286Sobrien	(compare
1166290286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11663169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1166490286Sobrien	  (const_int 0)))
1166590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1166690286Sobrien	(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
1166790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11668169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11669169699Skan   && (optimize_size
11670169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1167190286Sobrien  "sar{l}\t{%2, %k0|%k0, %2}"
1167290286Sobrien  [(set_attr "type" "ishift")
1167390286Sobrien   (set_attr "mode" "SI")])
1167490286Sobrien
1167590286Sobrien(define_expand "ashrhi3"
1167690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1167790286Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
1167890286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11679169699Skan   (clobber (reg:CC FLAGS_REG))]
1168090286Sobrien  "TARGET_HIMODE_MATH"
1168190286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, HImode, operands); DONE;")
1168290286Sobrien
1168390286Sobrien(define_insn "*ashrhi3_1_one_bit"
1168450650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1168550650Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11686132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11687169699Skan   (clobber (reg:CC FLAGS_REG))]
1168890286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11689117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1169090286Sobrien  "sar{w}\t%0"
1169190286Sobrien  [(set_attr "type" "ishift")
1169290286Sobrien   (set (attr "length") 
1169390286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1169490286Sobrien	(const_string "2")
1169590286Sobrien	(const_string "*")))])
1169618334Speter
1169790286Sobrien(define_insn "*ashrhi3_1"
1169890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1169990286Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1170090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11701169699Skan   (clobber (reg:CC FLAGS_REG))]
1170290286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
1170390286Sobrien  "@
1170490286Sobrien   sar{w}\t{%2, %0|%0, %2}
1170590286Sobrien   sar{w}\t{%b2, %0|%0, %b2}"
1170690286Sobrien  [(set_attr "type" "ishift")
1170790286Sobrien   (set_attr "mode" "HI")])
1170890286Sobrien
1170990286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1171090286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1171190286Sobrien;; zero are optimized away.
1171290286Sobrien(define_insn "*ashrhi3_one_bit_cmp"
11713169699Skan  [(set (reg FLAGS_REG)
1171490286Sobrien	(compare
1171590286Sobrien	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11716132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1171790286Sobrien	  (const_int 0)))
1171890286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1171990286Sobrien	(ashiftrt:HI (match_dup 1) (match_dup 2)))]
1172090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11721117404Skan   && (TARGET_SHIFT1 || optimize_size)
1172290286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
1172390286Sobrien  "sar{w}\t%0"
1172490286Sobrien  [(set_attr "type" "ishift")
1172590286Sobrien   (set (attr "length") 
1172690286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1172790286Sobrien	(const_string "2")
1172890286Sobrien	(const_string "*")))])
1172990286Sobrien
11730169699Skan(define_insn "*ashrhi3_one_bit_cconly"
11731169699Skan  [(set (reg FLAGS_REG)
11732169699Skan	(compare
11733169699Skan	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11734169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11735169699Skan	  (const_int 0)))
11736169699Skan   (clobber (match_scratch:HI 0 "=r"))]
11737169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11738169699Skan   && (TARGET_SHIFT1 || optimize_size)
11739169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
11740169699Skan  "sar{w}\t%0"
11741169699Skan  [(set_attr "type" "ishift")
11742169699Skan   (set_attr "length" "2")])
11743169699Skan
1174490286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1174590286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1174690286Sobrien;; zero are optimized away.
1174790286Sobrien(define_insn "*ashrhi3_cmp"
11748169699Skan  [(set (reg FLAGS_REG)
1174990286Sobrien	(compare
1175090286Sobrien	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11751169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1175290286Sobrien	  (const_int 0)))
1175390286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1175490286Sobrien	(ashiftrt:HI (match_dup 1) (match_dup 2)))]
1175590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11756169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11757169699Skan   && (optimize_size
11758169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1175990286Sobrien  "sar{w}\t{%2, %0|%0, %2}"
1176090286Sobrien  [(set_attr "type" "ishift")
1176190286Sobrien   (set_attr "mode" "HI")])
1176290286Sobrien
11763169699Skan(define_insn "*ashrhi3_cconly"
11764169699Skan  [(set (reg FLAGS_REG)
11765169699Skan	(compare
11766169699Skan	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11767169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11768169699Skan	  (const_int 0)))
11769169699Skan   (clobber (match_scratch:HI 0 "=r"))]
11770169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11771169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11772169699Skan   && (optimize_size
11773169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11774169699Skan  "sar{w}\t{%2, %0|%0, %2}"
11775169699Skan  [(set_attr "type" "ishift")
11776169699Skan   (set_attr "mode" "HI")])
11777169699Skan
1177890286Sobrien(define_expand "ashrqi3"
1177990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1178090286Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
1178190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11782169699Skan   (clobber (reg:CC FLAGS_REG))]
1178390286Sobrien  "TARGET_QIMODE_MATH"
1178490286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, QImode, operands); DONE;")
1178590286Sobrien
1178690286Sobrien(define_insn "*ashrqi3_1_one_bit"
1178750650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1178850650Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11789132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11790169699Skan   (clobber (reg:CC FLAGS_REG))]
1179190286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11792117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1179390286Sobrien  "sar{b}\t%0"
1179490286Sobrien  [(set_attr "type" "ishift")
1179590286Sobrien   (set (attr "length") 
1179690286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1179790286Sobrien	(const_string "2")
1179890286Sobrien	(const_string "*")))])
1179990286Sobrien
11800117404Skan(define_insn "*ashrqi3_1_one_bit_slp"
11801117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
11802117404Skan	(ashiftrt:QI (match_dup 0)
11803132727Skan		     (match_operand:QI 1 "const1_operand" "")))
11804169699Skan   (clobber (reg:CC FLAGS_REG))]
11805117404Skan  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11806117404Skan   && (! TARGET_PARTIAL_REG_STALL || optimize_size)
11807117404Skan   && (TARGET_SHIFT1 || optimize_size)"
11808117404Skan  "sar{b}\t%0"
11809117404Skan  [(set_attr "type" "ishift1")
11810117404Skan   (set (attr "length") 
11811117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
11812117404Skan	(const_string "2")
11813117404Skan	(const_string "*")))])
11814117404Skan
1181590286Sobrien(define_insn "*ashrqi3_1"
1181690286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1181790286Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1181890286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11819169699Skan   (clobber (reg:CC FLAGS_REG))]
1182090286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
1182190286Sobrien  "@
1182290286Sobrien   sar{b}\t{%2, %0|%0, %2}
1182390286Sobrien   sar{b}\t{%b2, %0|%0, %b2}"
1182490286Sobrien  [(set_attr "type" "ishift")
1182590286Sobrien   (set_attr "mode" "QI")])
1182690286Sobrien
11827117404Skan(define_insn "*ashrqi3_1_slp"
11828117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
11829117404Skan	(ashiftrt:QI (match_dup 0)
11830117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
11831169699Skan   (clobber (reg:CC FLAGS_REG))]
11832117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
11833117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
11834117404Skan  "@
11835117404Skan   sar{b}\t{%1, %0|%0, %1}
11836117404Skan   sar{b}\t{%b1, %0|%0, %b1}"
11837117404Skan  [(set_attr "type" "ishift1")
11838117404Skan   (set_attr "mode" "QI")])
11839117404Skan
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 "*ashrqi3_one_bit_cmp"
11844169699Skan  [(set (reg FLAGS_REG)
1184590286Sobrien	(compare
1184690286Sobrien	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11847132727Skan		       (match_operand:QI 2 "const1_operand" "I"))
1184890286Sobrien	  (const_int 0)))
11849102802Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1185090286Sobrien	(ashiftrt:QI (match_dup 1) (match_dup 2)))]
1185190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11852117404Skan   && (TARGET_SHIFT1 || optimize_size)
1185390286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
1185490286Sobrien  "sar{b}\t%0"
1185590286Sobrien  [(set_attr "type" "ishift")
1185690286Sobrien   (set (attr "length") 
1185790286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1185890286Sobrien	(const_string "2")
1185990286Sobrien	(const_string "*")))])
1186090286Sobrien
11861169699Skan(define_insn "*ashrqi3_one_bit_cconly"
11862169699Skan  [(set (reg FLAGS_REG)
11863169699Skan	(compare
11864169699Skan	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11865169699Skan		       (match_operand:QI 2 "const1_operand" "I"))
11866169699Skan	  (const_int 0)))
11867169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11868169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11869169699Skan   && (TARGET_SHIFT1 || optimize_size)
11870169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
11871169699Skan  "sar{b}\t%0"
11872169699Skan  [(set_attr "type" "ishift")
11873169699Skan   (set_attr "length" "2")])
11874169699Skan
1187590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1187690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1187790286Sobrien;; zero are optimized away.
1187890286Sobrien(define_insn "*ashrqi3_cmp"
11879169699Skan  [(set (reg FLAGS_REG)
1188090286Sobrien	(compare
1188190286Sobrien	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11882169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1188390286Sobrien	  (const_int 0)))
11884102802Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1188590286Sobrien	(ashiftrt:QI (match_dup 1) (match_dup 2)))]
1188690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11887169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11888169699Skan   && (optimize_size
11889169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1189090286Sobrien  "sar{b}\t{%2, %0|%0, %2}"
1189190286Sobrien  [(set_attr "type" "ishift")
1189290286Sobrien   (set_attr "mode" "QI")])
11893169699Skan
11894169699Skan(define_insn "*ashrqi3_cconly"
11895169699Skan  [(set (reg FLAGS_REG)
11896169699Skan	(compare
11897169699Skan	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11898169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11899169699Skan	  (const_int 0)))
11900169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11901169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11902169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11903169699Skan   && (optimize_size
11904169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11905169699Skan  "sar{b}\t{%2, %0|%0, %2}"
11906169699Skan  [(set_attr "type" "ishift")
11907169699Skan   (set_attr "mode" "QI")])
11908169699Skan
1190918334Speter
1191090286Sobrien;; Logical shift instructions
1191118334Speter
1191218334Speter;; See comment above `ashldi3' about how this works.
1191318334Speter
11914169699Skan(define_expand "lshrti3"
11915169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
11916169699Skan		   (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
1191790286Sobrien			        (match_operand:QI 2 "nonmemory_operand" "")))
11918169699Skan	      (clobber (reg:CC FLAGS_REG))])]
11919169699Skan  "TARGET_64BIT"
1192018334Speter{
11921169699Skan  if (! immediate_operand (operands[2], QImode))
1192218334Speter    {
11923169699Skan      emit_insn (gen_lshrti3_1 (operands[0], operands[1], operands[2]));
1192490286Sobrien      DONE;
1192518334Speter    }
11926169699Skan  ix86_expand_binary_operator (LSHIFTRT, TImode, operands);
1192718334Speter  DONE;
1192890286Sobrien})
1192918334Speter
11930169699Skan(define_insn "lshrti3_1"
11931169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11932169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
11933169699Skan		     (match_operand:QI 2 "register_operand" "c")))
11934169699Skan   (clobber (match_scratch:DI 3 "=&r"))
11935169699Skan   (clobber (reg:CC FLAGS_REG))]
11936169699Skan  "TARGET_64BIT"
11937169699Skan  "#"
11938169699Skan  [(set_attr "type" "multi")])
11939169699Skan
11940169699Skan(define_insn "*lshrti3_2"
11941169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11942169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
11943169699Skan		     (match_operand:QI 2 "immediate_operand" "O")))
11944169699Skan   (clobber (reg:CC FLAGS_REG))]
11945169699Skan  "TARGET_64BIT"
11946169699Skan  "#"
11947169699Skan  [(set_attr "type" "multi")])
11948169699Skan
11949169699Skan(define_split 
11950169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11951169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "")
11952169699Skan		     (match_operand:QI 2 "register_operand" "")))
11953169699Skan   (clobber (match_scratch:DI 3 ""))
11954169699Skan   (clobber (reg:CC FLAGS_REG))]
11955169699Skan  "TARGET_64BIT && reload_completed"
11956169699Skan  [(const_int 0)]
11957169699Skan  "ix86_split_lshr (operands, operands[3], TImode); DONE;")
11958169699Skan
11959169699Skan(define_split 
11960169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11961169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "")
11962169699Skan		     (match_operand:QI 2 "immediate_operand" "")))
11963169699Skan   (clobber (reg:CC FLAGS_REG))]
11964169699Skan  "TARGET_64BIT && reload_completed"
11965169699Skan  [(const_int 0)]
11966169699Skan  "ix86_split_lshr (operands, NULL_RTX, TImode); DONE;")
11967169699Skan
11968169699Skan(define_expand "lshrdi3"
11969169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
11970169699Skan	(lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
11971169699Skan		     (match_operand:QI 2 "nonmemory_operand" "")))]
11972169699Skan  ""
11973169699Skan  "ix86_expand_binary_operator (LSHIFTRT, DImode, operands); DONE;")
11974169699Skan
1197590286Sobrien(define_insn "*lshrdi3_1_one_bit_rex64"
1197690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1197790286Sobrien	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11978132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11979169699Skan   (clobber (reg:CC FLAGS_REG))]
1198090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
11981117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1198290286Sobrien  "shr{q}\t%0"
1198390286Sobrien  [(set_attr "type" "ishift")
1198490286Sobrien   (set (attr "length") 
1198590286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1198690286Sobrien	(const_string "2")
1198790286Sobrien	(const_string "*")))])
1198850650Sobrien
1198990286Sobrien(define_insn "*lshrdi3_1_rex64"
1199090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1199190286Sobrien	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1199290286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
11993169699Skan   (clobber (reg:CC FLAGS_REG))]
1199490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1199590286Sobrien  "@
1199690286Sobrien   shr{q}\t{%2, %0|%0, %2}
1199790286Sobrien   shr{q}\t{%b2, %0|%0, %b2}"
1199890286Sobrien  [(set_attr "type" "ishift")
1199990286Sobrien   (set_attr "mode" "DI")])
1200050650Sobrien
1200190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1200290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1200390286Sobrien;; zero are optimized away.
1200490286Sobrien(define_insn "*lshrdi3_cmp_one_bit_rex64"
12005169699Skan  [(set (reg FLAGS_REG)
1200690286Sobrien	(compare
1200790286Sobrien	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12008132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1200990286Sobrien	  (const_int 0)))
1201090286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1201190286Sobrien	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
1201290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12013117404Skan   && (TARGET_SHIFT1 || optimize_size)
1201490286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1201590286Sobrien  "shr{q}\t%0"
1201690286Sobrien  [(set_attr "type" "ishift")
1201790286Sobrien   (set (attr "length") 
1201890286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1201990286Sobrien	(const_string "2")
1202090286Sobrien	(const_string "*")))])
1202150650Sobrien
12022169699Skan(define_insn "*lshrdi3_cconly_one_bit_rex64"
12023169699Skan  [(set (reg FLAGS_REG)
12024169699Skan	(compare
12025169699Skan	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12026169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12027169699Skan	  (const_int 0)))
12028169699Skan   (clobber (match_scratch:DI 0 "=r"))]
12029169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12030169699Skan   && (TARGET_SHIFT1 || optimize_size)
12031169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12032169699Skan  "shr{q}\t%0"
12033169699Skan  [(set_attr "type" "ishift")
12034169699Skan   (set_attr "length" "2")])
12035169699Skan
1203690286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1203790286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1203890286Sobrien;; zero are optimized away.
1203990286Sobrien(define_insn "*lshrdi3_cmp_rex64"
12040169699Skan  [(set (reg FLAGS_REG)
1204190286Sobrien	(compare
1204290286Sobrien	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1204390286Sobrien		       (match_operand:QI 2 "const_int_operand" "e"))
1204490286Sobrien	  (const_int 0)))
1204590286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1204690286Sobrien	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
1204790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12048169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12049169699Skan   && (optimize_size
12050169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1205190286Sobrien  "shr{q}\t{%2, %0|%0, %2}"
1205290286Sobrien  [(set_attr "type" "ishift")
1205390286Sobrien   (set_attr "mode" "DI")])
1205450650Sobrien
12055169699Skan(define_insn "*lshrdi3_cconly_rex64"
12056169699Skan  [(set (reg FLAGS_REG)
12057169699Skan	(compare
12058169699Skan	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12059169699Skan		       (match_operand:QI 2 "const_int_operand" "e"))
12060169699Skan	  (const_int 0)))
12061169699Skan   (clobber (match_scratch:DI 0 "=r"))]
12062169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12063169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12064169699Skan   && (optimize_size
12065169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12066169699Skan  "shr{q}\t{%2, %0|%0, %2}"
12067169699Skan  [(set_attr "type" "ishift")
12068169699Skan   (set_attr "mode" "DI")])
1206918334Speter
12070169699Skan(define_insn "*lshrdi3_1"
1207190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1207290286Sobrien	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
1207390286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "Jc")))
12074169699Skan   (clobber (reg:CC FLAGS_REG))]
1207590286Sobrien  "!TARGET_64BIT"
1207690286Sobrien  "#"
1207790286Sobrien  [(set_attr "type" "multi")])
1207818334Speter
12079169699Skan;; By default we don't ask for a scratch register, because when DImode
12080169699Skan;; values are manipulated, registers are already at a premium.  But if
12081169699Skan;; we have one handy, we won't turn it away.
12082169699Skan(define_peephole2
12083169699Skan  [(match_scratch:SI 3 "r")
12084169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
12085169699Skan		   (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
12086169699Skan			        (match_operand:QI 2 "nonmemory_operand" "")))
12087169699Skan	      (clobber (reg:CC FLAGS_REG))])
12088169699Skan   (match_dup 3)]
12089169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1209090286Sobrien  [(const_int 0)]
12091169699Skan  "ix86_split_lshr (operands, operands[3], DImode); DONE;")
1209218334Speter
1209390286Sobrien(define_split 
1209490286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1209590286Sobrien	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
1209690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12097169699Skan   (clobber (reg:CC FLAGS_REG))]
12098169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
12099169699Skan		     ? flow2_completed : reload_completed)"
1210090286Sobrien  [(const_int 0)]
12101169699Skan  "ix86_split_lshr (operands, NULL_RTX, DImode); DONE;")
1210218334Speter
1210390286Sobrien(define_expand "lshrsi3"
1210490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1210590286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
1210690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12107169699Skan   (clobber (reg:CC FLAGS_REG))]
1210890286Sobrien  ""
1210990286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, SImode, operands); DONE;")
1211018334Speter
1211190286Sobrien(define_insn "*lshrsi3_1_one_bit"
1211290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1211390286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12114132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12115169699Skan   (clobber (reg:CC FLAGS_REG))]
1211690286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12117117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1211890286Sobrien  "shr{l}\t%0"
1211990286Sobrien  [(set_attr "type" "ishift")
1212090286Sobrien   (set (attr "length") 
1212190286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1212290286Sobrien	(const_string "2")
1212390286Sobrien	(const_string "*")))])
1212418334Speter
1212590286Sobrien(define_insn "*lshrsi3_1_one_bit_zext"
1212690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1212790286Sobrien	(lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0"))
12128132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12129169699Skan   (clobber (reg:CC FLAGS_REG))]
1213090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12131117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1213290286Sobrien  "shr{l}\t%k0"
1213390286Sobrien  [(set_attr "type" "ishift")
1213490286Sobrien   (set_attr "length" "2")])
1213518334Speter
1213690286Sobrien(define_insn "*lshrsi3_1"
1213790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1213890286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1213990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12140169699Skan   (clobber (reg:CC FLAGS_REG))]
1214190286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1214290286Sobrien  "@
1214390286Sobrien   shr{l}\t{%2, %0|%0, %2}
1214490286Sobrien   shr{l}\t{%b2, %0|%0, %b2}"
1214590286Sobrien  [(set_attr "type" "ishift")
1214690286Sobrien   (set_attr "mode" "SI")])
1214718334Speter
1214890286Sobrien(define_insn "*lshrsi3_1_zext"
1214990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1215090286Sobrien	(zero_extend:DI
1215190286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1215290286Sobrien		       (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12153169699Skan   (clobber (reg:CC FLAGS_REG))]
1215490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1215590286Sobrien  "@
1215690286Sobrien   shr{l}\t{%2, %k0|%k0, %2}
1215790286Sobrien   shr{l}\t{%b2, %k0|%k0, %b2}"
1215890286Sobrien  [(set_attr "type" "ishift")
1215990286Sobrien   (set_attr "mode" "SI")])
1216018334Speter
1216190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1216290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1216390286Sobrien;; zero are optimized away.
1216490286Sobrien(define_insn "*lshrsi3_one_bit_cmp"
12165169699Skan  [(set (reg FLAGS_REG)
1216690286Sobrien	(compare
1216790286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12168132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1216990286Sobrien	  (const_int 0)))
1217090286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1217190286Sobrien	(lshiftrt:SI (match_dup 1) (match_dup 2)))]
1217290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12173117404Skan   && (TARGET_SHIFT1 || optimize_size)
1217490286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1217590286Sobrien  "shr{l}\t%0"
1217690286Sobrien  [(set_attr "type" "ishift")
1217790286Sobrien   (set (attr "length") 
1217890286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1217990286Sobrien	(const_string "2")
1218090286Sobrien	(const_string "*")))])
1218118334Speter
12182169699Skan(define_insn "*lshrsi3_one_bit_cconly"
12183169699Skan  [(set (reg FLAGS_REG)
12184169699Skan	(compare
12185169699Skan	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12186169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12187169699Skan	  (const_int 0)))
12188169699Skan   (clobber (match_scratch:SI 0 "=r"))]
12189169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12190169699Skan   && (TARGET_SHIFT1 || optimize_size)
12191169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12192169699Skan  "shr{l}\t%0"
12193169699Skan  [(set_attr "type" "ishift")
12194169699Skan   (set_attr "length" "2")])
12195169699Skan
1219690286Sobrien(define_insn "*lshrsi3_cmp_one_bit_zext"
12197169699Skan  [(set (reg FLAGS_REG)
1219890286Sobrien	(compare
1219990286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
12200132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1220190286Sobrien	  (const_int 0)))
1220290286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1220390286Sobrien	(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
1220490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12205117404Skan   && (TARGET_SHIFT1 || optimize_size)
1220690286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1220790286Sobrien  "shr{l}\t%k0"
1220890286Sobrien  [(set_attr "type" "ishift")
1220990286Sobrien   (set_attr "length" "2")])
1221018334Speter
1221190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1221290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1221390286Sobrien;; zero are optimized away.
1221490286Sobrien(define_insn "*lshrsi3_cmp"
12215169699Skan  [(set (reg FLAGS_REG)
1221690286Sobrien	(compare
1221790286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12218169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1221990286Sobrien	  (const_int 0)))
1222090286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1222190286Sobrien	(lshiftrt:SI (match_dup 1) (match_dup 2)))]
1222290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12223169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12224169699Skan   && (optimize_size
12225169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1222690286Sobrien  "shr{l}\t{%2, %0|%0, %2}"
1222790286Sobrien  [(set_attr "type" "ishift")
1222890286Sobrien   (set_attr "mode" "SI")])
1222990286Sobrien
12230169699Skan(define_insn "*lshrsi3_cconly"
12231169699Skan  [(set (reg FLAGS_REG)
12232169699Skan      (compare
12233169699Skan	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12234169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
12235169699Skan        (const_int 0)))
12236169699Skan   (clobber (match_scratch:SI 0 "=r"))]
12237169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12238169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12239169699Skan   && (optimize_size
12240169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12241169699Skan  "shr{l}\t{%2, %0|%0, %2}"
12242169699Skan  [(set_attr "type" "ishift")
12243169699Skan   (set_attr "mode" "SI")])
12244169699Skan
1224590286Sobrien(define_insn "*lshrsi3_cmp_zext"
12246169699Skan  [(set (reg FLAGS_REG)
1224790286Sobrien	(compare
1224890286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
12249169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1225090286Sobrien	  (const_int 0)))
1225190286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1225290286Sobrien	(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
1225390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12254169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12255169699Skan   && (optimize_size
12256169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1225790286Sobrien  "shr{l}\t{%2, %k0|%k0, %2}"
1225890286Sobrien  [(set_attr "type" "ishift")
1225990286Sobrien   (set_attr "mode" "SI")])
1226090286Sobrien
1226190286Sobrien(define_expand "lshrhi3"
1226290286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1226390286Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
1226490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12265169699Skan   (clobber (reg:CC FLAGS_REG))]
1226690286Sobrien  "TARGET_HIMODE_MATH"
1226790286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, HImode, operands); DONE;")
1226890286Sobrien
1226990286Sobrien(define_insn "*lshrhi3_1_one_bit"
1227050650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1227150650Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12272132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12273169699Skan   (clobber (reg:CC FLAGS_REG))]
1227490286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12275117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1227690286Sobrien  "shr{w}\t%0"
1227790286Sobrien  [(set_attr "type" "ishift")
1227890286Sobrien   (set (attr "length") 
1227990286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1228090286Sobrien	(const_string "2")
1228190286Sobrien	(const_string "*")))])
1228218334Speter
1228390286Sobrien(define_insn "*lshrhi3_1"
1228490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1228590286Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1228690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12287169699Skan   (clobber (reg:CC FLAGS_REG))]
1228890286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1228990286Sobrien  "@
1229090286Sobrien   shr{w}\t{%2, %0|%0, %2}
1229190286Sobrien   shr{w}\t{%b2, %0|%0, %b2}"
1229290286Sobrien  [(set_attr "type" "ishift")
1229390286Sobrien   (set_attr "mode" "HI")])
1229490286Sobrien
1229590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1229690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1229790286Sobrien;; zero are optimized away.
1229890286Sobrien(define_insn "*lshrhi3_one_bit_cmp"
12299169699Skan  [(set (reg FLAGS_REG)
1230090286Sobrien	(compare
1230190286Sobrien	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12302132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1230390286Sobrien	  (const_int 0)))
1230490286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1230590286Sobrien	(lshiftrt:HI (match_dup 1) (match_dup 2)))]
1230690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12307117404Skan   && (TARGET_SHIFT1 || optimize_size)
1230890286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1230990286Sobrien  "shr{w}\t%0"
1231090286Sobrien  [(set_attr "type" "ishift")
1231190286Sobrien   (set (attr "length") 
1231290286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1231390286Sobrien	(const_string "2")
1231490286Sobrien	(const_string "*")))])
1231590286Sobrien
12316169699Skan(define_insn "*lshrhi3_one_bit_cconly"
12317169699Skan  [(set (reg FLAGS_REG)
12318169699Skan	(compare
12319169699Skan	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12320169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12321169699Skan	  (const_int 0)))
12322169699Skan   (clobber (match_scratch:HI 0 "=r"))]
12323169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12324169699Skan   && (TARGET_SHIFT1 || optimize_size)
12325169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12326169699Skan  "shr{w}\t%0"
12327169699Skan  [(set_attr "type" "ishift")
12328169699Skan   (set_attr "length" "2")])
12329169699Skan
1233090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1233190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1233290286Sobrien;; zero are optimized away.
1233390286Sobrien(define_insn "*lshrhi3_cmp"
12334169699Skan  [(set (reg FLAGS_REG)
1233590286Sobrien	(compare
1233690286Sobrien	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12337169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1233890286Sobrien	  (const_int 0)))
1233990286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1234090286Sobrien	(lshiftrt:HI (match_dup 1) (match_dup 2)))]
1234190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12342169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12343169699Skan   && (optimize_size
12344169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1234590286Sobrien  "shr{w}\t{%2, %0|%0, %2}"
1234690286Sobrien  [(set_attr "type" "ishift")
1234790286Sobrien   (set_attr "mode" "HI")])
1234890286Sobrien
12349169699Skan(define_insn "*lshrhi3_cconly"
12350169699Skan  [(set (reg FLAGS_REG)
12351169699Skan	(compare
12352169699Skan	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12353169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
12354169699Skan	  (const_int 0)))
12355169699Skan   (clobber (match_scratch:HI 0 "=r"))]
12356169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12357169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12358169699Skan   && (optimize_size
12359169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12360169699Skan  "shr{w}\t{%2, %0|%0, %2}"
12361169699Skan  [(set_attr "type" "ishift")
12362169699Skan   (set_attr "mode" "HI")])
12363169699Skan
1236490286Sobrien(define_expand "lshrqi3"
1236590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1236690286Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
1236790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12368169699Skan   (clobber (reg:CC FLAGS_REG))]
1236990286Sobrien  "TARGET_QIMODE_MATH"
1237090286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, QImode, operands); DONE;")
1237190286Sobrien
1237290286Sobrien(define_insn "*lshrqi3_1_one_bit"
1237350650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1237450650Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12375132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12376169699Skan   (clobber (reg:CC FLAGS_REG))]
1237790286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12378117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1237990286Sobrien  "shr{b}\t%0"
1238090286Sobrien  [(set_attr "type" "ishift")
1238190286Sobrien   (set (attr "length") 
1238290286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1238390286Sobrien	(const_string "2")
1238490286Sobrien	(const_string "*")))])
1238590286Sobrien
12386117404Skan(define_insn "*lshrqi3_1_one_bit_slp"
12387117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12388117404Skan	(lshiftrt:QI (match_dup 0)
12389132727Skan		     (match_operand:QI 1 "const1_operand" "")))
12390169699Skan   (clobber (reg:CC FLAGS_REG))]
12391117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12392117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12393117404Skan  "shr{b}\t%0"
12394117404Skan  [(set_attr "type" "ishift1")
12395117404Skan   (set (attr "length") 
12396117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
12397117404Skan	(const_string "2")
12398117404Skan	(const_string "*")))])
12399117404Skan
1240090286Sobrien(define_insn "*lshrqi3_1"
1240190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1240290286Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1240390286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12404169699Skan   (clobber (reg:CC FLAGS_REG))]
1240590286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
1240690286Sobrien  "@
1240790286Sobrien   shr{b}\t{%2, %0|%0, %2}
1240890286Sobrien   shr{b}\t{%b2, %0|%0, %b2}"
1240990286Sobrien  [(set_attr "type" "ishift")
1241090286Sobrien   (set_attr "mode" "QI")])
1241190286Sobrien
12412117404Skan(define_insn "*lshrqi3_1_slp"
12413117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12414117404Skan	(lshiftrt:QI (match_dup 0)
12415117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
12416169699Skan   (clobber (reg:CC FLAGS_REG))]
12417117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12418117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12419117404Skan  "@
12420117404Skan   shr{b}\t{%1, %0|%0, %1}
12421117404Skan   shr{b}\t{%b1, %0|%0, %b1}"
12422117404Skan  [(set_attr "type" "ishift1")
12423117404Skan   (set_attr "mode" "QI")])
12424117404Skan
1242590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1242690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1242790286Sobrien;; zero are optimized away.
1242890286Sobrien(define_insn "*lshrqi2_one_bit_cmp"
12429169699Skan  [(set (reg FLAGS_REG)
1243090286Sobrien	(compare
1243190286Sobrien	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12432132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1243390286Sobrien	  (const_int 0)))
1243490286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1243590286Sobrien	(lshiftrt:QI (match_dup 1) (match_dup 2)))]
1243690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12437117404Skan   && (TARGET_SHIFT1 || optimize_size)
1243890286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
1243990286Sobrien  "shr{b}\t%0"
1244090286Sobrien  [(set_attr "type" "ishift")
1244190286Sobrien   (set (attr "length") 
1244290286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1244390286Sobrien	(const_string "2")
1244490286Sobrien	(const_string "*")))])
1244590286Sobrien
12446169699Skan(define_insn "*lshrqi2_one_bit_cconly"
12447169699Skan  [(set (reg FLAGS_REG)
12448169699Skan	(compare
12449169699Skan	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12450169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12451169699Skan	  (const_int 0)))
12452169699Skan   (clobber (match_scratch:QI 0 "=q"))]
12453169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12454169699Skan   && (TARGET_SHIFT1 || optimize_size)
12455169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
12456169699Skan  "shr{b}\t%0"
12457169699Skan  [(set_attr "type" "ishift")
12458169699Skan   (set_attr "length" "2")])
12459169699Skan
1246090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1246190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1246290286Sobrien;; zero are optimized away.
1246390286Sobrien(define_insn "*lshrqi2_cmp"
12464169699Skan  [(set (reg FLAGS_REG)
1246590286Sobrien	(compare
1246690286Sobrien	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12467169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1246890286Sobrien	  (const_int 0)))
1246990286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1247090286Sobrien	(lshiftrt:QI (match_dup 1) (match_dup 2)))]
1247190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12472169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12473169699Skan   && (optimize_size
12474169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1247590286Sobrien  "shr{b}\t{%2, %0|%0, %2}"
1247690286Sobrien  [(set_attr "type" "ishift")
1247790286Sobrien   (set_attr "mode" "QI")])
12478169699Skan
12479169699Skan(define_insn "*lshrqi2_cconly"
12480169699Skan  [(set (reg FLAGS_REG)
12481169699Skan	(compare
12482169699Skan	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12483169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
12484169699Skan	  (const_int 0)))
12485169699Skan   (clobber (match_scratch:QI 0 "=q"))]
12486169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12487169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12488169699Skan   && (optimize_size
12489169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12490169699Skan  "shr{b}\t{%2, %0|%0, %2}"
12491169699Skan  [(set_attr "type" "ishift")
12492169699Skan   (set_attr "mode" "QI")])
1249318334Speter
1249490286Sobrien;; Rotate instructions
1249518334Speter
1249690286Sobrien(define_expand "rotldi3"
12497169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
12498169699Skan	(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
1249990286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12500169699Skan   (clobber (reg:CC FLAGS_REG))]
12501169699Skan ""
12502169699Skan{
12503169699Skan  if (TARGET_64BIT)
12504169699Skan    {
12505169699Skan      ix86_expand_binary_operator (ROTATE, DImode, operands);
12506169699Skan      DONE;
12507169699Skan    }
12508169699Skan  if (!const_1_to_31_operand (operands[2], VOIDmode))
12509169699Skan    FAIL;
12510169699Skan  emit_insn (gen_ix86_rotldi3 (operands[0], operands[1], operands[2]));
12511169699Skan  DONE;
12512169699Skan})
1251318334Speter
12514169699Skan;; Implement rotation using two double-precision shift instructions
12515169699Skan;; and a scratch register.   
12516169699Skan(define_insn_and_split "ix86_rotldi3"
12517169699Skan [(set (match_operand:DI 0 "register_operand" "=r")
12518169699Skan       (rotate:DI (match_operand:DI 1 "register_operand" "0")
12519169699Skan                  (match_operand:QI 2 "const_1_to_31_operand" "I")))
12520169699Skan  (clobber (reg:CC FLAGS_REG))
12521169699Skan  (clobber (match_scratch:SI 3 "=&r"))]
12522169699Skan "!TARGET_64BIT"
12523169699Skan "" 
12524169699Skan "&& reload_completed"
12525169699Skan [(set (match_dup 3) (match_dup 4))
12526169699Skan  (parallel
12527169699Skan   [(set (match_dup 4)
12528169699Skan         (ior:SI (ashift:SI (match_dup 4) (match_dup 2))
12529169699Skan                 (lshiftrt:SI (match_dup 5)
12530169699Skan                              (minus:QI (const_int 32) (match_dup 2)))))
12531169699Skan    (clobber (reg:CC FLAGS_REG))])
12532169699Skan  (parallel
12533169699Skan   [(set (match_dup 5)
12534169699Skan         (ior:SI (ashift:SI (match_dup 5) (match_dup 2))
12535169699Skan                 (lshiftrt:SI (match_dup 3)
12536169699Skan                              (minus:QI (const_int 32) (match_dup 2)))))
12537169699Skan    (clobber (reg:CC FLAGS_REG))])]
12538169699Skan "split_di (operands, 1, operands + 4, operands + 5);")
12539169699Skan 
1254090286Sobrien(define_insn "*rotlsi3_1_one_bit_rex64"
1254190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1254290286Sobrien	(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12543132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12544169699Skan   (clobber (reg:CC FLAGS_REG))]
1254590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)
12546117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1254790286Sobrien  "rol{q}\t%0"
12548117404Skan  [(set_attr "type" "rotate")
1254990286Sobrien   (set (attr "length") 
1255090286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1255190286Sobrien	(const_string "2")
1255290286Sobrien	(const_string "*")))])
1255318334Speter
1255490286Sobrien(define_insn "*rotldi3_1_rex64"
1255590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1255690286Sobrien	(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1255790286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "e,c")))
12558169699Skan   (clobber (reg:CC FLAGS_REG))]
1255990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)"
1256090286Sobrien  "@
1256190286Sobrien   rol{q}\t{%2, %0|%0, %2}
1256290286Sobrien   rol{q}\t{%b2, %0|%0, %b2}"
12563117404Skan  [(set_attr "type" "rotate")
1256490286Sobrien   (set_attr "mode" "DI")])
1256590286Sobrien
1256690286Sobrien(define_expand "rotlsi3"
1256790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1256890286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "")
1256990286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12570169699Skan   (clobber (reg:CC FLAGS_REG))]
1257118334Speter  ""
1257290286Sobrien  "ix86_expand_binary_operator (ROTATE, SImode, operands); DONE;")
1257318334Speter
1257490286Sobrien(define_insn "*rotlsi3_1_one_bit"
1257550650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1257690286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12577132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12578169699Skan   (clobber (reg:CC FLAGS_REG))]
1257990286Sobrien  "ix86_binary_operator_ok (ROTATE, SImode, operands)
12580117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1258190286Sobrien  "rol{l}\t%0"
12582117404Skan  [(set_attr "type" "rotate")
1258390286Sobrien   (set (attr "length") 
1258490286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1258590286Sobrien	(const_string "2")
1258690286Sobrien	(const_string "*")))])
1258718334Speter
1258890286Sobrien(define_insn "*rotlsi3_1_one_bit_zext"
1258990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1259090286Sobrien	(zero_extend:DI
1259190286Sobrien	  (rotate:SI (match_operand:SI 1 "register_operand" "0")
12592132727Skan		     (match_operand:QI 2 "const1_operand" ""))))
12593169699Skan   (clobber (reg:CC FLAGS_REG))]
1259490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)
12595117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1259690286Sobrien  "rol{l}\t%k0"
12597117404Skan  [(set_attr "type" "rotate")
1259890286Sobrien   (set_attr "length" "2")])
1259918334Speter
1260090286Sobrien(define_insn "*rotlsi3_1"
1260190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1260290286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1260390286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12604169699Skan   (clobber (reg:CC FLAGS_REG))]
1260590286Sobrien  "ix86_binary_operator_ok (ROTATE, SImode, operands)"
1260690286Sobrien  "@
1260790286Sobrien   rol{l}\t{%2, %0|%0, %2}
1260890286Sobrien   rol{l}\t{%b2, %0|%0, %b2}"
12609117404Skan  [(set_attr "type" "rotate")
1261090286Sobrien   (set_attr "mode" "SI")])
1261118334Speter
1261290286Sobrien(define_insn "*rotlsi3_1_zext"
1261390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1261490286Sobrien	(zero_extend:DI
1261590286Sobrien	  (rotate:SI (match_operand:SI 1 "register_operand" "0,0")
1261690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12617169699Skan   (clobber (reg:CC FLAGS_REG))]
1261890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)"
1261990286Sobrien  "@
1262090286Sobrien   rol{l}\t{%2, %k0|%k0, %2}
1262190286Sobrien   rol{l}\t{%b2, %k0|%k0, %b2}"
12622117404Skan  [(set_attr "type" "rotate")
1262390286Sobrien   (set_attr "mode" "SI")])
1262418334Speter
1262590286Sobrien(define_expand "rotlhi3"
1262690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1262790286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "")
1262890286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12629169699Skan   (clobber (reg:CC FLAGS_REG))]
1263090286Sobrien  "TARGET_HIMODE_MATH"
1263190286Sobrien  "ix86_expand_binary_operator (ROTATE, HImode, operands); DONE;")
1263218334Speter
1263390286Sobrien(define_insn "*rotlhi3_1_one_bit"
1263490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1263590286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12636132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12637169699Skan   (clobber (reg:CC FLAGS_REG))]
1263890286Sobrien  "ix86_binary_operator_ok (ROTATE, HImode, operands)
12639117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1264090286Sobrien  "rol{w}\t%0"
12641117404Skan  [(set_attr "type" "rotate")
1264290286Sobrien   (set (attr "length") 
1264390286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1264490286Sobrien	(const_string "2")
1264590286Sobrien	(const_string "*")))])
1264618334Speter
1264790286Sobrien(define_insn "*rotlhi3_1"
1264890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1264990286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1265090286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12651169699Skan   (clobber (reg:CC FLAGS_REG))]
1265290286Sobrien  "ix86_binary_operator_ok (ROTATE, HImode, operands)"
1265390286Sobrien  "@
1265490286Sobrien   rol{w}\t{%2, %0|%0, %2}
1265590286Sobrien   rol{w}\t{%b2, %0|%0, %b2}"
12656117404Skan  [(set_attr "type" "rotate")
1265790286Sobrien   (set_attr "mode" "HI")])
1265818334Speter
1265990286Sobrien(define_expand "rotlqi3"
1266090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1266190286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "")
1266290286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12663169699Skan   (clobber (reg:CC FLAGS_REG))]
1266490286Sobrien  "TARGET_QIMODE_MATH"
1266590286Sobrien  "ix86_expand_binary_operator (ROTATE, QImode, operands); DONE;")
1266618334Speter
12667117404Skan(define_insn "*rotlqi3_1_one_bit_slp"
12668117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12669117404Skan	(rotate:QI (match_dup 0)
12670132727Skan		   (match_operand:QI 1 "const1_operand" "")))
12671169699Skan   (clobber (reg:CC FLAGS_REG))]
12672117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12673117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12674117404Skan  "rol{b}\t%0"
12675117404Skan  [(set_attr "type" "rotate1")
12676117404Skan   (set (attr "length") 
12677117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
12678117404Skan	(const_string "2")
12679117404Skan	(const_string "*")))])
12680117404Skan
1268190286Sobrien(define_insn "*rotlqi3_1_one_bit"
1268290286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1268390286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12684132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12685169699Skan   (clobber (reg:CC FLAGS_REG))]
1268690286Sobrien  "ix86_binary_operator_ok (ROTATE, QImode, operands)
12687117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1268890286Sobrien  "rol{b}\t%0"
12689117404Skan  [(set_attr "type" "rotate")
1269090286Sobrien   (set (attr "length") 
1269190286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1269290286Sobrien	(const_string "2")
1269390286Sobrien	(const_string "*")))])
1269418334Speter
12695117404Skan(define_insn "*rotlqi3_1_slp"
12696117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12697117404Skan	(rotate:QI (match_dup 0)
12698117404Skan		   (match_operand:QI 1 "nonmemory_operand" "I,c")))
12699169699Skan   (clobber (reg:CC FLAGS_REG))]
12700117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12701117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12702117404Skan  "@
12703117404Skan   rol{b}\t{%1, %0|%0, %1}
12704117404Skan   rol{b}\t{%b1, %0|%0, %b1}"
12705117404Skan  [(set_attr "type" "rotate1")
12706117404Skan   (set_attr "mode" "QI")])
12707117404Skan
1270890286Sobrien(define_insn "*rotlqi3_1"
1270990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1271090286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1271190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12712169699Skan   (clobber (reg:CC FLAGS_REG))]
1271390286Sobrien  "ix86_binary_operator_ok (ROTATE, QImode, operands)"
1271490286Sobrien  "@
1271590286Sobrien   rol{b}\t{%2, %0|%0, %2}
1271690286Sobrien   rol{b}\t{%b2, %0|%0, %b2}"
12717117404Skan  [(set_attr "type" "rotate")
1271890286Sobrien   (set_attr "mode" "QI")])
1271918334Speter
1272090286Sobrien(define_expand "rotrdi3"
12721169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
12722169699Skan	(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
12723169699Skan		   (match_operand:QI 2 "nonmemory_operand" "")))
12724169699Skan   (clobber (reg:CC FLAGS_REG))]
12725169699Skan ""
12726169699Skan{
12727169699Skan  if (TARGET_64BIT)
12728169699Skan    {
12729169699Skan      ix86_expand_binary_operator (ROTATERT, DImode, operands);
12730169699Skan      DONE;
12731169699Skan    }
12732169699Skan  if (!const_1_to_31_operand (operands[2], VOIDmode))
12733169699Skan    FAIL;
12734169699Skan  emit_insn (gen_ix86_rotrdi3 (operands[0], operands[1], operands[2]));
12735169699Skan  DONE;
12736169699Skan})
12737169699Skan  
12738169699Skan;; Implement rotation using two double-precision shift instructions
12739169699Skan;; and a scratch register.   
12740169699Skan(define_insn_and_split "ix86_rotrdi3"
12741169699Skan [(set (match_operand:DI 0 "register_operand" "=r")
12742169699Skan       (rotatert:DI (match_operand:DI 1 "register_operand" "0")
12743169699Skan                    (match_operand:QI 2 "const_1_to_31_operand" "I")))
12744169699Skan  (clobber (reg:CC FLAGS_REG))
12745169699Skan  (clobber (match_scratch:SI 3 "=&r"))]
12746169699Skan "!TARGET_64BIT"
12747169699Skan ""
12748169699Skan "&& reload_completed"
12749169699Skan [(set (match_dup 3) (match_dup 4))
12750169699Skan  (parallel
12751169699Skan   [(set (match_dup 4)
12752169699Skan         (ior:SI (ashiftrt:SI (match_dup 4) (match_dup 2))
12753169699Skan                 (ashift:SI (match_dup 5)
12754169699Skan                            (minus:QI (const_int 32) (match_dup 2)))))
12755169699Skan    (clobber (reg:CC FLAGS_REG))])
12756169699Skan  (parallel
12757169699Skan   [(set (match_dup 5)
12758169699Skan         (ior:SI (ashiftrt:SI (match_dup 5) (match_dup 2))
12759169699Skan                 (ashift:SI (match_dup 3)
12760169699Skan                            (minus:QI (const_int 32) (match_dup 2)))))
12761169699Skan    (clobber (reg:CC FLAGS_REG))])]
12762169699Skan "split_di (operands, 1, operands + 4, operands + 5);")
1276318334Speter
1276490286Sobrien(define_insn "*rotrdi3_1_one_bit_rex64"
1276590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1276690286Sobrien	(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12767132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12768169699Skan   (clobber (reg:CC FLAGS_REG))]
1276990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)
12770117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1277190286Sobrien  "ror{q}\t%0"
12772117404Skan  [(set_attr "type" "rotate")
1277390286Sobrien   (set (attr "length") 
1277490286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1277590286Sobrien	(const_string "2")
1277690286Sobrien	(const_string "*")))])
1277718334Speter
1277890286Sobrien(define_insn "*rotrdi3_1_rex64"
1277990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1278090286Sobrien	(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1278190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
12782169699Skan   (clobber (reg:CC FLAGS_REG))]
1278390286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)"
1278490286Sobrien  "@
1278590286Sobrien   ror{q}\t{%2, %0|%0, %2}
1278690286Sobrien   ror{q}\t{%b2, %0|%0, %b2}"
12787117404Skan  [(set_attr "type" "rotate")
1278890286Sobrien   (set_attr "mode" "DI")])
1278990286Sobrien
1279090286Sobrien(define_expand "rotrsi3"
1279190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1279290286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "")
1279390286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12794169699Skan   (clobber (reg:CC FLAGS_REG))]
1279590286Sobrien  ""
1279690286Sobrien  "ix86_expand_binary_operator (ROTATERT, SImode, operands); DONE;")
1279790286Sobrien
1279890286Sobrien(define_insn "*rotrsi3_1_one_bit"
1279950650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1280090286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12801132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12802169699Skan   (clobber (reg:CC FLAGS_REG))]
1280390286Sobrien  "ix86_binary_operator_ok (ROTATERT, SImode, operands)
12804117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1280590286Sobrien  "ror{l}\t%0"
12806117404Skan  [(set_attr "type" "rotate")
1280790286Sobrien   (set (attr "length") 
1280890286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1280990286Sobrien	(const_string "2")
1281090286Sobrien	(const_string "*")))])
1281118334Speter
1281290286Sobrien(define_insn "*rotrsi3_1_one_bit_zext"
1281390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1281490286Sobrien	(zero_extend:DI
1281590286Sobrien	  (rotatert:SI (match_operand:SI 1 "register_operand" "0")
12816132727Skan		       (match_operand:QI 2 "const1_operand" ""))))
12817169699Skan   (clobber (reg:CC FLAGS_REG))]
1281890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)
12819117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1282090286Sobrien  "ror{l}\t%k0"
12821117404Skan  [(set_attr "type" "rotate")
1282290286Sobrien   (set (attr "length") 
1282390286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1282490286Sobrien	(const_string "2")
1282590286Sobrien	(const_string "*")))])
1282618334Speter
1282790286Sobrien(define_insn "*rotrsi3_1"
1282890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1282990286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1283090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12831169699Skan   (clobber (reg:CC FLAGS_REG))]
1283290286Sobrien  "ix86_binary_operator_ok (ROTATERT, SImode, operands)"
1283390286Sobrien  "@
1283490286Sobrien   ror{l}\t{%2, %0|%0, %2}
1283590286Sobrien   ror{l}\t{%b2, %0|%0, %b2}"
12836117404Skan  [(set_attr "type" "rotate")
1283790286Sobrien   (set_attr "mode" "SI")])
1283818334Speter
1283990286Sobrien(define_insn "*rotrsi3_1_zext"
1284090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1284190286Sobrien	(zero_extend:DI
1284290286Sobrien	  (rotatert:SI (match_operand:SI 1 "register_operand" "0,0")
1284390286Sobrien		       (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12844169699Skan   (clobber (reg:CC FLAGS_REG))]
1284590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)"
1284690286Sobrien  "@
1284790286Sobrien   ror{l}\t{%2, %k0|%k0, %2}
1284890286Sobrien   ror{l}\t{%b2, %k0|%k0, %b2}"
12849117404Skan  [(set_attr "type" "rotate")
1285090286Sobrien   (set_attr "mode" "SI")])
1285118334Speter
1285290286Sobrien(define_expand "rotrhi3"
1285390286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1285490286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "")
1285590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12856169699Skan   (clobber (reg:CC FLAGS_REG))]
1285790286Sobrien  "TARGET_HIMODE_MATH"
1285890286Sobrien  "ix86_expand_binary_operator (ROTATERT, HImode, operands); DONE;")
1285918334Speter
1286090286Sobrien(define_insn "*rotrhi3_one_bit"
1286190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1286290286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12863132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12864169699Skan   (clobber (reg:CC FLAGS_REG))]
1286590286Sobrien  "ix86_binary_operator_ok (ROTATERT, HImode, operands)
12866117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1286790286Sobrien  "ror{w}\t%0"
12868117404Skan  [(set_attr "type" "rotate")
1286990286Sobrien   (set (attr "length") 
1287090286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1287190286Sobrien	(const_string "2")
1287290286Sobrien	(const_string "*")))])
1287318334Speter
1287490286Sobrien(define_insn "*rotrhi3"
1287590286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1287690286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1287790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12878169699Skan   (clobber (reg:CC FLAGS_REG))]
1287990286Sobrien  "ix86_binary_operator_ok (ROTATERT, HImode, operands)"
1288090286Sobrien  "@
1288190286Sobrien   ror{w}\t{%2, %0|%0, %2}
1288290286Sobrien   ror{w}\t{%b2, %0|%0, %b2}"
12883117404Skan  [(set_attr "type" "rotate")
1288490286Sobrien   (set_attr "mode" "HI")])
1288518334Speter
1288690286Sobrien(define_expand "rotrqi3"
1288790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1288890286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "")
1288990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12890169699Skan   (clobber (reg:CC FLAGS_REG))]
1289190286Sobrien  "TARGET_QIMODE_MATH"
1289290286Sobrien  "ix86_expand_binary_operator (ROTATERT, QImode, operands); DONE;")
1289318334Speter
1289490286Sobrien(define_insn "*rotrqi3_1_one_bit"
1289590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1289690286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12897132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12898169699Skan   (clobber (reg:CC FLAGS_REG))]
1289990286Sobrien  "ix86_binary_operator_ok (ROTATERT, QImode, operands)
12900117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1290190286Sobrien  "ror{b}\t%0"
12902117404Skan  [(set_attr "type" "rotate")
1290390286Sobrien   (set (attr "length") 
1290490286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1290590286Sobrien	(const_string "2")
1290690286Sobrien	(const_string "*")))])
1290718334Speter
12908117404Skan(define_insn "*rotrqi3_1_one_bit_slp"
12909117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12910117404Skan	(rotatert:QI (match_dup 0)
12911132727Skan		     (match_operand:QI 1 "const1_operand" "")))
12912169699Skan   (clobber (reg:CC FLAGS_REG))]
12913117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12914117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12915117404Skan  "ror{b}\t%0"
12916117404Skan  [(set_attr "type" "rotate1")
12917117404Skan   (set (attr "length") 
12918117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
12919117404Skan	(const_string "2")
12920117404Skan	(const_string "*")))])
12921117404Skan
1292290286Sobrien(define_insn "*rotrqi3_1"
1292390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1292490286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1292590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12926169699Skan   (clobber (reg:CC FLAGS_REG))]
1292790286Sobrien  "ix86_binary_operator_ok (ROTATERT, QImode, operands)"
1292890286Sobrien  "@
1292990286Sobrien   ror{b}\t{%2, %0|%0, %2}
1293090286Sobrien   ror{b}\t{%b2, %0|%0, %b2}"
12931117404Skan  [(set_attr "type" "rotate")
1293290286Sobrien   (set_attr "mode" "QI")])
12933117404Skan
12934117404Skan(define_insn "*rotrqi3_1_slp"
12935117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12936117404Skan	(rotatert:QI (match_dup 0)
12937117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
12938169699Skan   (clobber (reg:CC FLAGS_REG))]
12939117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12940117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12941117404Skan  "@
12942117404Skan   ror{b}\t{%1, %0|%0, %1}
12943117404Skan   ror{b}\t{%b1, %0|%0, %b1}"
12944117404Skan  [(set_attr "type" "rotate1")
12945117404Skan   (set_attr "mode" "QI")])
1294690286Sobrien
1294790286Sobrien;; Bit set / bit test instructions
1294818334Speter
1294990286Sobrien(define_expand "extv"
1295090286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1295190286Sobrien	(sign_extract:SI (match_operand:SI 1 "register_operand" "")
12952169699Skan			 (match_operand:SI 2 "const8_operand" "")
12953169699Skan			 (match_operand:SI 3 "const8_operand" "")))]
1295490286Sobrien  ""
1295518334Speter{
1295690286Sobrien  /* Handle extractions from %ah et al.  */
1295790286Sobrien  if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8)
1295890286Sobrien    FAIL;
1295918334Speter
1296090286Sobrien  /* From mips.md: extract_bit_field doesn't verify that our source
1296190286Sobrien     matches the predicate, so check it again here.  */
12962169699Skan  if (! ext_register_operand (operands[1], VOIDmode))
1296390286Sobrien    FAIL;
1296490286Sobrien})
1296518334Speter
1296690286Sobrien(define_expand "extzv"
1296790286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1296890286Sobrien	(zero_extract:SI (match_operand 1 "ext_register_operand" "")
12969169699Skan			 (match_operand:SI 2 "const8_operand" "")
12970169699Skan			 (match_operand:SI 3 "const8_operand" "")))]
1297190286Sobrien  ""
1297290286Sobrien{
1297390286Sobrien  /* Handle extractions from %ah et al.  */
1297490286Sobrien  if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8)
1297590286Sobrien    FAIL;
1297618334Speter
1297790286Sobrien  /* From mips.md: extract_bit_field doesn't verify that our source
1297890286Sobrien     matches the predicate, so check it again here.  */
12979169699Skan  if (! ext_register_operand (operands[1], VOIDmode))
1298090286Sobrien    FAIL;
1298190286Sobrien})
1298218334Speter
1298390286Sobrien(define_expand "insv"
12984132727Skan  [(set (zero_extract (match_operand 0 "ext_register_operand" "")
12985169699Skan		      (match_operand 1 "const8_operand" "")
12986169699Skan		      (match_operand 2 "const8_operand" ""))
12987132727Skan        (match_operand 3 "register_operand" ""))]
1298890286Sobrien  ""
1298990286Sobrien{
12990169699Skan  /* Handle insertions to %ah et al.  */
1299190286Sobrien  if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8)
1299290286Sobrien    FAIL;
1299318334Speter
1299490286Sobrien  /* From mips.md: insert_bit_field doesn't verify that our source
1299590286Sobrien     matches the predicate, so check it again here.  */
12996169699Skan  if (! ext_register_operand (operands[0], VOIDmode))
1299790286Sobrien    FAIL;
12998132727Skan
12999132727Skan  if (TARGET_64BIT)
13000132727Skan    emit_insn (gen_movdi_insv_1_rex64 (operands[0], operands[3]));
13001132727Skan  else
13002132727Skan    emit_insn (gen_movsi_insv_1 (operands[0], operands[3]));
13003132727Skan
13004132727Skan  DONE;
1300590286Sobrien})
1300618334Speter
1300790286Sobrien;; %%% bts, btr, btc, bt.
13008169699Skan;; In general these instructions are *slow* when applied to memory,
13009169699Skan;; since they enforce atomic operation.  When applied to registers,
13010169699Skan;; it depends on the cpu implementation.  They're never faster than
13011169699Skan;; the corresponding and/ior/xor operations, so with 32-bit there's
13012169699Skan;; no point.  But in 64-bit, we can't hold the relevant immediates
13013169699Skan;; within the instruction itself, so operating on bits in the high
13014169699Skan;; 32-bits of a register becomes easier.
13015169699Skan;;
13016169699Skan;; These are slow on Nocona, but fast on Athlon64.  We do require the use
13017169699Skan;; of btrq and btcq for corner cases of post-reload expansion of absdf and
13018169699Skan;; negdf respectively, so they can never be disabled entirely.
13019169699Skan
13020169699Skan(define_insn "*btsq"
13021169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13022169699Skan			 (const_int 1)
13023169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13024169699Skan	(const_int 1))
13025169699Skan   (clobber (reg:CC FLAGS_REG))]
13026169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13027169699Skan  "bts{q} %1,%0"
13028169699Skan  [(set_attr "type" "alu1")])
13029169699Skan
13030169699Skan(define_insn "*btrq"
13031169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13032169699Skan			 (const_int 1)
13033169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13034169699Skan	(const_int 0))
13035169699Skan   (clobber (reg:CC FLAGS_REG))]
13036169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13037169699Skan  "btr{q} %1,%0"
13038169699Skan  [(set_attr "type" "alu1")])
13039169699Skan
13040169699Skan(define_insn "*btcq"
13041169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13042169699Skan			 (const_int 1)
13043169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13044169699Skan	(not:DI (zero_extract:DI (match_dup 0) (const_int 1) (match_dup 1))))
13045169699Skan   (clobber (reg:CC FLAGS_REG))]
13046169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13047169699Skan  "btc{q} %1,%0"
13048169699Skan  [(set_attr "type" "alu1")])
13049169699Skan
13050169699Skan;; Allow Nocona to avoid these instructions if a register is available.
13051169699Skan
13052169699Skan(define_peephole2
13053169699Skan  [(match_scratch:DI 2 "r")
13054169699Skan   (parallel [(set (zero_extract:DI
13055169699Skan		     (match_operand:DI 0 "register_operand" "")
13056169699Skan		     (const_int 1)
13057169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13058169699Skan		   (const_int 1))
13059169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13060169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13061169699Skan  [(const_int 0)]
13062169699Skan{
13063169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13064169699Skan  rtx op1;
13065169699Skan
13066169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13067169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13068169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13069169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13070169699Skan  else
13071169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13072169699Skan
13073169699Skan  op1 = immed_double_const (lo, hi, DImode);
13074169699Skan  if (i >= 31)
13075169699Skan    {
13076169699Skan      emit_move_insn (operands[2], op1);
13077169699Skan      op1 = operands[2];
13078169699Skan    }
13079169699Skan
13080169699Skan  emit_insn (gen_iordi3 (operands[0], operands[0], op1));
13081169699Skan  DONE;
13082169699Skan})
13083169699Skan
13084169699Skan(define_peephole2
13085169699Skan  [(match_scratch:DI 2 "r")
13086169699Skan   (parallel [(set (zero_extract:DI
13087169699Skan		     (match_operand:DI 0 "register_operand" "")
13088169699Skan		     (const_int 1)
13089169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13090169699Skan		   (const_int 0))
13091169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13092169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13093169699Skan  [(const_int 0)]
13094169699Skan{
13095169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13096169699Skan  rtx op1;
13097169699Skan
13098169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13099169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13100169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13101169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13102169699Skan  else
13103169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13104169699Skan
13105169699Skan  op1 = immed_double_const (~lo, ~hi, DImode);
13106169699Skan  if (i >= 32)
13107169699Skan    {
13108169699Skan      emit_move_insn (operands[2], op1);
13109169699Skan      op1 = operands[2];
13110169699Skan    }
13111169699Skan
13112169699Skan  emit_insn (gen_anddi3 (operands[0], operands[0], op1));
13113169699Skan  DONE;
13114169699Skan})
13115169699Skan
13116169699Skan(define_peephole2
13117169699Skan  [(match_scratch:DI 2 "r")
13118169699Skan   (parallel [(set (zero_extract:DI
13119169699Skan		     (match_operand:DI 0 "register_operand" "")
13120169699Skan		     (const_int 1)
13121169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13122169699Skan	      (not:DI (zero_extract:DI
13123169699Skan			(match_dup 0) (const_int 1) (match_dup 1))))
13124169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13125169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13126169699Skan  [(const_int 0)]
13127169699Skan{
13128169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13129169699Skan  rtx op1;
13130169699Skan
13131169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13132169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13133169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13134169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13135169699Skan  else
13136169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13137169699Skan
13138169699Skan  op1 = immed_double_const (lo, hi, DImode);
13139169699Skan  if (i >= 31)
13140169699Skan    {
13141169699Skan      emit_move_insn (operands[2], op1);
13142169699Skan      op1 = operands[2];
13143169699Skan    }
13144169699Skan
13145169699Skan  emit_insn (gen_xordi3 (operands[0], operands[0], op1));
13146169699Skan  DONE;
13147169699Skan})
1314818334Speter
1314918334Speter;; Store-flag instructions.
1315018334Speter
1315118334Speter;; For all sCOND expanders, also expand the compare or test insn that
1315218334Speter;; generates cc0.  Generate an equality comparison if `seq' or `sne'.
1315318334Speter
1315490286Sobrien;; %%% Do the expansion to SImode.  If PII, do things the xor+setcc way
1315590286Sobrien;; to avoid partial register stalls.  Otherwise do things the setcc+movzx
1315690286Sobrien;; way, which can later delete the movzx if only QImode is needed.
1315790286Sobrien
1315818334Speter(define_expand "seq"
1315990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13160169699Skan        (eq:QI (reg:CC FLAGS_REG) (const_int 0)))]
1316118334Speter  ""
1316290286Sobrien  "if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;")
1316318334Speter
1316418334Speter(define_expand "sne"
1316590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13166169699Skan        (ne:QI (reg:CC FLAGS_REG) (const_int 0)))]
1316718334Speter  ""
1316890286Sobrien  "if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;")
1316918334Speter
1317018334Speter(define_expand "sgt"
1317190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13172169699Skan        (gt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1317318334Speter  ""
1317490286Sobrien  "if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;")
1317518334Speter
1317618334Speter(define_expand "sgtu"
1317790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13178169699Skan        (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1317918334Speter  ""
1318090286Sobrien  "if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;")
1318118334Speter
1318218334Speter(define_expand "slt"
1318390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13184169699Skan        (lt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1318518334Speter  ""
1318690286Sobrien  "if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;")
1318718334Speter
1318818334Speter(define_expand "sltu"
1318990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13190169699Skan        (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1319118334Speter  ""
1319290286Sobrien  "if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;")
1319318334Speter
1319418334Speter(define_expand "sge"
1319590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13196169699Skan        (ge:QI (reg:CC FLAGS_REG) (const_int 0)))]
1319718334Speter  ""
1319890286Sobrien  "if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;")
1319918334Speter
1320018334Speter(define_expand "sgeu"
1320190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13202169699Skan        (geu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1320318334Speter  ""
1320490286Sobrien  "if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;")
1320518334Speter
1320618334Speter(define_expand "sle"
1320790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13208169699Skan        (le:QI (reg:CC FLAGS_REG) (const_int 0)))]
1320918334Speter  ""
1321090286Sobrien  "if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;")
1321118334Speter
1321218334Speter(define_expand "sleu"
1321390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13214169699Skan        (leu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1321518334Speter  ""
1321690286Sobrien  "if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;")
1321718334Speter
1321890286Sobrien(define_expand "sunordered"
1321990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13220169699Skan        (unordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
1322190286Sobrien  "TARGET_80387 || TARGET_SSE"
1322290286Sobrien  "if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;")
1322352296Sobrien
1322490286Sobrien(define_expand "sordered"
1322590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13226169699Skan        (ordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
1322790286Sobrien  "TARGET_80387"
1322890286Sobrien  "if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;")
1322990286Sobrien
1323090286Sobrien(define_expand "suneq"
1323190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13232169699Skan        (uneq:QI (reg:CC FLAGS_REG) (const_int 0)))]
1323390286Sobrien  "TARGET_80387 || TARGET_SSE"
1323490286Sobrien  "if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;")
1323590286Sobrien
1323690286Sobrien(define_expand "sunge"
1323790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13238169699Skan        (unge:QI (reg:CC FLAGS_REG) (const_int 0)))]
1323990286Sobrien  "TARGET_80387 || TARGET_SSE"
1324090286Sobrien  "if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;")
1324190286Sobrien
1324290286Sobrien(define_expand "sungt"
1324390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13244169699Skan        (ungt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1324590286Sobrien  "TARGET_80387 || TARGET_SSE"
1324690286Sobrien  "if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;")
1324790286Sobrien
1324890286Sobrien(define_expand "sunle"
1324990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13250169699Skan        (unle:QI (reg:CC FLAGS_REG) (const_int 0)))]
1325190286Sobrien  "TARGET_80387 || TARGET_SSE"
1325290286Sobrien  "if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;")
1325390286Sobrien
1325490286Sobrien(define_expand "sunlt"
1325590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13256169699Skan        (unlt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1325790286Sobrien  "TARGET_80387 || TARGET_SSE"
1325890286Sobrien  "if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;")
1325990286Sobrien
1326090286Sobrien(define_expand "sltgt"
1326190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13262169699Skan        (ltgt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1326390286Sobrien  "TARGET_80387 || TARGET_SSE"
1326490286Sobrien  "if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;")
1326590286Sobrien
1326690286Sobrien(define_insn "*setcc_1"
1326752296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1326890286Sobrien	(match_operator:QI 1 "ix86_comparison_operator"
13269169699Skan	  [(reg FLAGS_REG) (const_int 0)]))]
1327090286Sobrien  ""
1327190286Sobrien  "set%C1\t%0"
1327290286Sobrien  [(set_attr "type" "setcc")
1327390286Sobrien   (set_attr "mode" "QI")])
1327490286Sobrien
13275169699Skan(define_insn "*setcc_2"
1327690286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
1327790286Sobrien	(match_operator:QI 1 "ix86_comparison_operator"
13278169699Skan	  [(reg FLAGS_REG) (const_int 0)]))]
1327990286Sobrien  ""
1328090286Sobrien  "set%C1\t%0"
1328190286Sobrien  [(set_attr "type" "setcc")
1328290286Sobrien   (set_attr "mode" "QI")])
1328390286Sobrien
1328490286Sobrien;; In general it is not safe to assume too much about CCmode registers,
1328590286Sobrien;; so simplify-rtx stops when it sees a second one.  Under certain 
1328690286Sobrien;; conditions this is safe on x86, so help combine not create
1328790286Sobrien;;
1328890286Sobrien;;	seta	%al
1328990286Sobrien;;	testb	%al, %al
1329090286Sobrien;;	sete	%al
1329190286Sobrien
1329290286Sobrien(define_split 
1329390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1329490286Sobrien	(ne:QI (match_operator 1 "ix86_comparison_operator"
13295169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1329690286Sobrien	    (const_int 0)))]
1329790286Sobrien  ""
1329890286Sobrien  [(set (match_dup 0) (match_dup 1))]
1329952296Sobrien{
1330090286Sobrien  PUT_MODE (operands[1], QImode);
1330190286Sobrien})
1330252296Sobrien
1330390286Sobrien(define_split 
1330490286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
1330590286Sobrien	(ne:QI (match_operator 1 "ix86_comparison_operator"
13306169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1330790286Sobrien	    (const_int 0)))]
1330890286Sobrien  ""
1330990286Sobrien  [(set (match_dup 0) (match_dup 1))]
1331090286Sobrien{
1331190286Sobrien  PUT_MODE (operands[1], QImode);
1331290286Sobrien})
1331352296Sobrien
1331490286Sobrien(define_split 
1331590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1331690286Sobrien	(eq:QI (match_operator 1 "ix86_comparison_operator"
13317169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1331890286Sobrien	    (const_int 0)))]
1331990286Sobrien  ""
1332090286Sobrien  [(set (match_dup 0) (match_dup 1))]
1332190286Sobrien{
1332290286Sobrien  rtx new_op1 = copy_rtx (operands[1]);
1332390286Sobrien  operands[1] = new_op1;
1332490286Sobrien  PUT_MODE (new_op1, QImode);
13325169699Skan  PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
13326169699Skan					     GET_MODE (XEXP (new_op1, 0))));
1332790286Sobrien
1332890286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1332990286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1333090286Sobrien  if (! ix86_comparison_operator (new_op1, VOIDmode))
1333190286Sobrien    FAIL;
1333290286Sobrien})
1333390286Sobrien
1333490286Sobrien(define_split 
1333590286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
1333690286Sobrien	(eq:QI (match_operator 1 "ix86_comparison_operator"
13337169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1333890286Sobrien	    (const_int 0)))]
1333990286Sobrien  ""
1334090286Sobrien  [(set (match_dup 0) (match_dup 1))]
1334190286Sobrien{
1334290286Sobrien  rtx new_op1 = copy_rtx (operands[1]);
1334390286Sobrien  operands[1] = new_op1;
1334490286Sobrien  PUT_MODE (new_op1, QImode);
13345169699Skan  PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
13346169699Skan					     GET_MODE (XEXP (new_op1, 0))));
1334790286Sobrien
1334890286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1334990286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1335090286Sobrien  if (! ix86_comparison_operator (new_op1, VOIDmode))
1335190286Sobrien    FAIL;
1335290286Sobrien})
1335390286Sobrien
1335490286Sobrien;; The SSE store flag instructions saves 0 or 0xffffffff to the result.
1335590286Sobrien;; subsequent logical operations are used to imitate conditional moves.
1335690286Sobrien;; 0xffffffff is NaN, but not in normalized form, so we can't represent
13357169699Skan;; it directly.
1335890286Sobrien
1335990286Sobrien(define_insn "*sse_setccsf"
1336090286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1336190286Sobrien	(match_operator:SF 1 "sse_comparison_operator"
1336290286Sobrien	  [(match_operand:SF 2 "register_operand" "0")
1336390286Sobrien	   (match_operand:SF 3 "nonimmediate_operand" "xm")]))]
13364169699Skan  "TARGET_SSE"
1336590286Sobrien  "cmp%D1ss\t{%3, %0|%0, %3}"
13366117404Skan  [(set_attr "type" "ssecmp")
1336790286Sobrien   (set_attr "mode" "SF")])
1336890286Sobrien
1336990286Sobrien(define_insn "*sse_setccdf"
1337090286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1337190286Sobrien	(match_operator:DF 1 "sse_comparison_operator"
1337290286Sobrien	  [(match_operand:DF 2 "register_operand" "0")
1337390286Sobrien	   (match_operand:DF 3 "nonimmediate_operand" "Ym")]))]
13374169699Skan  "TARGET_SSE2"
1337590286Sobrien  "cmp%D1sd\t{%3, %0|%0, %3}"
13376117404Skan  [(set_attr "type" "ssecmp")
1337790286Sobrien   (set_attr "mode" "DF")])
1337818334Speter
1337918334Speter;; Basic conditional jump instructions.
1338018334Speter;; We ignore the overflow flag for signed branch instructions.
1338118334Speter
1338218334Speter;; For all bCOND expanders, also expand the compare or test insn that
13383169699Skan;; generates reg FLAGS_REG.  Generate an equality comparison if `beq' or `bne'.
1338418334Speter
1338518334Speter(define_expand "beq"
1338690286Sobrien  [(set (pc)
1338790286Sobrien	(if_then_else (match_dup 1)
1338818334Speter		      (label_ref (match_operand 0 "" ""))
1338918334Speter		      (pc)))]
1339018334Speter  ""
1339190286Sobrien  "ix86_expand_branch (EQ, operands[0]); DONE;")
1339218334Speter
1339318334Speter(define_expand "bne"
1339490286Sobrien  [(set (pc)
1339590286Sobrien	(if_then_else (match_dup 1)
1339618334Speter		      (label_ref (match_operand 0 "" ""))
1339718334Speter		      (pc)))]
1339818334Speter  ""
1339990286Sobrien  "ix86_expand_branch (NE, operands[0]); DONE;")
1340018334Speter
1340118334Speter(define_expand "bgt"
1340290286Sobrien  [(set (pc)
1340390286Sobrien	(if_then_else (match_dup 1)
1340418334Speter		      (label_ref (match_operand 0 "" ""))
1340518334Speter		      (pc)))]
1340618334Speter  ""
1340790286Sobrien  "ix86_expand_branch (GT, operands[0]); DONE;")
1340818334Speter
1340918334Speter(define_expand "bgtu"
1341090286Sobrien  [(set (pc)
1341190286Sobrien	(if_then_else (match_dup 1)
1341218334Speter		      (label_ref (match_operand 0 "" ""))
1341318334Speter		      (pc)))]
1341418334Speter  ""
1341590286Sobrien  "ix86_expand_branch (GTU, operands[0]); DONE;")
1341618334Speter
1341718334Speter(define_expand "blt"
1341890286Sobrien  [(set (pc)
1341990286Sobrien	(if_then_else (match_dup 1)
1342018334Speter		      (label_ref (match_operand 0 "" ""))
1342118334Speter		      (pc)))]
1342218334Speter  ""
1342390286Sobrien  "ix86_expand_branch (LT, operands[0]); DONE;")
1342418334Speter
1342518334Speter(define_expand "bltu"
1342690286Sobrien  [(set (pc)
1342790286Sobrien	(if_then_else (match_dup 1)
1342818334Speter		      (label_ref (match_operand 0 "" ""))
1342918334Speter		      (pc)))]
1343018334Speter  ""
1343190286Sobrien  "ix86_expand_branch (LTU, operands[0]); DONE;")
1343218334Speter
1343318334Speter(define_expand "bge"
1343490286Sobrien  [(set (pc)
1343590286Sobrien	(if_then_else (match_dup 1)
1343618334Speter		      (label_ref (match_operand 0 "" ""))
1343718334Speter		      (pc)))]
1343818334Speter  ""
1343990286Sobrien  "ix86_expand_branch (GE, operands[0]); DONE;")
1344018334Speter
1344118334Speter(define_expand "bgeu"
1344290286Sobrien  [(set (pc)
1344390286Sobrien	(if_then_else (match_dup 1)
1344418334Speter		      (label_ref (match_operand 0 "" ""))
1344518334Speter		      (pc)))]
1344618334Speter  ""
1344790286Sobrien  "ix86_expand_branch (GEU, operands[0]); DONE;")
1344818334Speter
1344918334Speter(define_expand "ble"
1345090286Sobrien  [(set (pc)
1345190286Sobrien	(if_then_else (match_dup 1)
1345218334Speter		      (label_ref (match_operand 0 "" ""))
1345318334Speter		      (pc)))]
1345418334Speter  ""
1345590286Sobrien  "ix86_expand_branch (LE, operands[0]); DONE;")
1345618334Speter
1345718334Speter(define_expand "bleu"
1345890286Sobrien  [(set (pc)
1345990286Sobrien	(if_then_else (match_dup 1)
1346018334Speter		      (label_ref (match_operand 0 "" ""))
1346118334Speter		      (pc)))]
1346218334Speter  ""
1346390286Sobrien  "ix86_expand_branch (LEU, operands[0]); DONE;")
1346418334Speter
1346590286Sobrien(define_expand "bunordered"
1346618334Speter  [(set (pc)
1346790286Sobrien	(if_then_else (match_dup 1)
1346890286Sobrien		      (label_ref (match_operand 0 "" ""))
1346918334Speter		      (pc)))]
13470169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1347190286Sobrien  "ix86_expand_branch (UNORDERED, operands[0]); DONE;")
1347218334Speter
1347390286Sobrien(define_expand "bordered"
1347490286Sobrien  [(set (pc)
1347590286Sobrien	(if_then_else (match_dup 1)
1347690286Sobrien		      (label_ref (match_operand 0 "" ""))
1347790286Sobrien		      (pc)))]
13478169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1347990286Sobrien  "ix86_expand_branch (ORDERED, operands[0]); DONE;")
1348018334Speter
1348190286Sobrien(define_expand "buneq"
1348218334Speter  [(set (pc)
1348390286Sobrien	(if_then_else (match_dup 1)
1348490286Sobrien		      (label_ref (match_operand 0 "" ""))
1348590286Sobrien		      (pc)))]
13486169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1348790286Sobrien  "ix86_expand_branch (UNEQ, operands[0]); DONE;")
1348818334Speter
1348990286Sobrien(define_expand "bunge"
1349090286Sobrien  [(set (pc)
1349190286Sobrien	(if_then_else (match_dup 1)
1349290286Sobrien		      (label_ref (match_operand 0 "" ""))
1349390286Sobrien		      (pc)))]
13494169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1349590286Sobrien  "ix86_expand_branch (UNGE, operands[0]); DONE;")
1349618334Speter
1349790286Sobrien(define_expand "bungt"
1349818334Speter  [(set (pc)
1349990286Sobrien	(if_then_else (match_dup 1)
1350090286Sobrien		      (label_ref (match_operand 0 "" ""))
1350190286Sobrien		      (pc)))]
13502169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1350390286Sobrien  "ix86_expand_branch (UNGT, operands[0]); DONE;")
1350418334Speter
1350590286Sobrien(define_expand "bunle"
1350690286Sobrien  [(set (pc)
1350790286Sobrien	(if_then_else (match_dup 1)
1350890286Sobrien		      (label_ref (match_operand 0 "" ""))
1350990286Sobrien		      (pc)))]
13510169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1351190286Sobrien  "ix86_expand_branch (UNLE, operands[0]); DONE;")
1351218334Speter
1351390286Sobrien(define_expand "bunlt"
1351490286Sobrien  [(set (pc)
1351590286Sobrien	(if_then_else (match_dup 1)
1351690286Sobrien		      (label_ref (match_operand 0 "" ""))
1351790286Sobrien		      (pc)))]
13518169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1351990286Sobrien  "ix86_expand_branch (UNLT, operands[0]); DONE;")
1352018334Speter
1352190286Sobrien(define_expand "bltgt"
1352290286Sobrien  [(set (pc)
1352390286Sobrien	(if_then_else (match_dup 1)
1352490286Sobrien		      (label_ref (match_operand 0 "" ""))
1352590286Sobrien		      (pc)))]
13526169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1352790286Sobrien  "ix86_expand_branch (LTGT, operands[0]); DONE;")
1352818334Speter
1352990286Sobrien(define_insn "*jcc_1"
1353090286Sobrien  [(set (pc)
1353190286Sobrien	(if_then_else (match_operator 1 "ix86_comparison_operator"
13532169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1353390286Sobrien		      (label_ref (match_operand 0 "" ""))
1353490286Sobrien		      (pc)))]
1353518334Speter  ""
1353690286Sobrien  "%+j%C1\t%l0"
1353790286Sobrien  [(set_attr "type" "ibr")
13538117404Skan   (set_attr "modrm" "0")
13539117404Skan   (set (attr "length")
1354090286Sobrien	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13541117404Skan				  (const_int -126))
1354290286Sobrien			      (lt (minus (match_dup 0) (pc))
13543117404Skan				  (const_int 128)))
13544117404Skan	     (const_int 2)
13545117404Skan	     (const_int 6)))])
1354618334Speter
1354790286Sobrien(define_insn "*jcc_2"
1354818334Speter  [(set (pc)
1354990286Sobrien	(if_then_else (match_operator 1 "ix86_comparison_operator"
13550169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1355190286Sobrien		      (pc)
1355290286Sobrien		      (label_ref (match_operand 0 "" ""))))]
1355318334Speter  ""
1355490286Sobrien  "%+j%c1\t%l0"
1355590286Sobrien  [(set_attr "type" "ibr")
13556117404Skan   (set_attr "modrm" "0")
13557117404Skan   (set (attr "length")
1355890286Sobrien	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13559117404Skan				  (const_int -126))
1356090286Sobrien			      (lt (minus (match_dup 0) (pc))
13561117404Skan				  (const_int 128)))
13562117404Skan	     (const_int 2)
13563117404Skan	     (const_int 6)))])
1356490286Sobrien
1356590286Sobrien;; In general it is not safe to assume too much about CCmode registers,
1356690286Sobrien;; so simplify-rtx stops when it sees a second one.  Under certain 
1356790286Sobrien;; conditions this is safe on x86, so help combine not create
1356890286Sobrien;;
1356990286Sobrien;;	seta	%al
1357090286Sobrien;;	testb	%al, %al
1357190286Sobrien;;	je	Lfoo
1357290286Sobrien
1357390286Sobrien(define_split 
1357490286Sobrien  [(set (pc)
1357590286Sobrien	(if_then_else (ne (match_operator 0 "ix86_comparison_operator"
13576169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1357790286Sobrien			  (const_int 0))
1357890286Sobrien		      (label_ref (match_operand 1 "" ""))
1357990286Sobrien		      (pc)))]
1358090286Sobrien  ""
1358190286Sobrien  [(set (pc)
1358290286Sobrien	(if_then_else (match_dup 0)
1358390286Sobrien		      (label_ref (match_dup 1))
1358490286Sobrien		      (pc)))]
1358518334Speter{
1358690286Sobrien  PUT_MODE (operands[0], VOIDmode);
1358790286Sobrien})
1358890286Sobrien  
1358990286Sobrien(define_split 
1359090286Sobrien  [(set (pc)
1359190286Sobrien	(if_then_else (eq (match_operator 0 "ix86_comparison_operator"
13592169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1359390286Sobrien			  (const_int 0))
1359490286Sobrien		      (label_ref (match_operand 1 "" ""))
1359590286Sobrien		      (pc)))]
1359690286Sobrien  ""
1359790286Sobrien  [(set (pc)
1359890286Sobrien	(if_then_else (match_dup 0)
1359990286Sobrien		      (label_ref (match_dup 1))
1360090286Sobrien		      (pc)))]
1360190286Sobrien{
1360290286Sobrien  rtx new_op0 = copy_rtx (operands[0]);
1360390286Sobrien  operands[0] = new_op0;
1360490286Sobrien  PUT_MODE (new_op0, VOIDmode);
13605169699Skan  PUT_CODE (new_op0, ix86_reverse_condition (GET_CODE (new_op0),
13606169699Skan					     GET_MODE (XEXP (new_op0, 0))));
1360752296Sobrien
1360890286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1360990286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1361090286Sobrien  if (! ix86_comparison_operator (new_op0, VOIDmode))
1361190286Sobrien    FAIL;
1361290286Sobrien})
1361352296Sobrien
1361490286Sobrien;; Define combination compare-and-branch fp compare instructions to use
1361590286Sobrien;; during early optimization.  Splitting the operation apart early makes
1361690286Sobrien;; for bad code when we want to reverse the operation.
1361718334Speter
13618169699Skan(define_insn "*fp_jcc_1_mixed"
1361990286Sobrien  [(set (pc)
1362090286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13621169699Skan			[(match_operand 1 "register_operand" "f,x")
13622169699Skan			 (match_operand 2 "nonimmediate_operand" "f,xm")])
1362390286Sobrien	  (label_ref (match_operand 3 "" ""))
1362490286Sobrien	  (pc)))
13625169699Skan   (clobber (reg:CCFP FPSR_REG))
13626169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13627169699Skan  "TARGET_MIX_SSE_I387
13628169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1362990286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1363090286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1363190286Sobrien  "#")
1363218334Speter
1363390286Sobrien(define_insn "*fp_jcc_1_sse"
1363490286Sobrien  [(set (pc)
1363590286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13636169699Skan			[(match_operand 1 "register_operand" "x")
13637169699Skan			 (match_operand 2 "nonimmediate_operand" "xm")])
1363890286Sobrien	  (label_ref (match_operand 3 "" ""))
1363990286Sobrien	  (pc)))
13640169699Skan   (clobber (reg:CCFP FPSR_REG))
13641169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13642169699Skan  "TARGET_SSE_MATH
1364390286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1364490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1364590286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1364690286Sobrien  "#")
1364718334Speter
13648169699Skan(define_insn "*fp_jcc_1_387"
1364990286Sobrien  [(set (pc)
1365090286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13651169699Skan			[(match_operand 1 "register_operand" "f")
13652169699Skan			 (match_operand 2 "register_operand" "f")])
1365390286Sobrien	  (label_ref (match_operand 3 "" ""))
1365490286Sobrien	  (pc)))
13655169699Skan   (clobber (reg:CCFP FPSR_REG))
13656169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13657169699Skan  "TARGET_CMOVE && TARGET_80387
13658169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
1365990286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1366090286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1366190286Sobrien  "#")
1366218334Speter
13663169699Skan(define_insn "*fp_jcc_2_mixed"
1366418334Speter  [(set (pc)
1366590286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13666169699Skan			[(match_operand 1 "register_operand" "f,x")
13667169699Skan			 (match_operand 2 "nonimmediate_operand" "f,xm")])
1366890286Sobrien	  (pc)
1366990286Sobrien	  (label_ref (match_operand 3 "" ""))))
13670169699Skan   (clobber (reg:CCFP FPSR_REG))
13671169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13672169699Skan  "TARGET_MIX_SSE_I387
13673169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1367490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1367590286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1367690286Sobrien  "#")
1367718334Speter
1367890286Sobrien(define_insn "*fp_jcc_2_sse"
1367990286Sobrien  [(set (pc)
1368090286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13681169699Skan			[(match_operand 1 "register_operand" "x")
13682169699Skan			 (match_operand 2 "nonimmediate_operand" "xm")])
1368390286Sobrien	  (pc)
1368490286Sobrien	  (label_ref (match_operand 3 "" ""))))
13685169699Skan   (clobber (reg:CCFP FPSR_REG))
13686169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13687169699Skan  "TARGET_SSE_MATH
1368890286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1368990286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1369090286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1369190286Sobrien  "#")
1369218334Speter
13693169699Skan(define_insn "*fp_jcc_2_387"
1369490286Sobrien  [(set (pc)
1369590286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13696169699Skan			[(match_operand 1 "register_operand" "f")
13697169699Skan			 (match_operand 2 "register_operand" "f")])
1369890286Sobrien	  (pc)
1369990286Sobrien	  (label_ref (match_operand 3 "" ""))))
13700169699Skan   (clobber (reg:CCFP FPSR_REG))
13701169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13702169699Skan  "TARGET_CMOVE && TARGET_80387
13703169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
1370490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1370590286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1370690286Sobrien  "#")
1370718334Speter
13708169699Skan(define_insn "*fp_jcc_3_387"
1370990286Sobrien  [(set (pc)
1371090286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1371190286Sobrien			[(match_operand 1 "register_operand" "f")
1371290286Sobrien			 (match_operand 2 "nonimmediate_operand" "fm")])
1371390286Sobrien	  (label_ref (match_operand 3 "" ""))
1371490286Sobrien	  (pc)))
13715169699Skan   (clobber (reg:CCFP FPSR_REG))
13716169699Skan   (clobber (reg:CCFP FLAGS_REG))
1371790286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1371890286Sobrien  "TARGET_80387
1371990286Sobrien   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
1372090286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1372190286Sobrien   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
1372290286Sobrien   && SELECT_CC_MODE (GET_CODE (operands[0]),
1372390286Sobrien		      operands[1], operands[2]) == CCFPmode
1372490286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1372590286Sobrien  "#")
1372618334Speter
13727169699Skan(define_insn "*fp_jcc_4_387"
1372850650Sobrien  [(set (pc)
1372990286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1373090286Sobrien			[(match_operand 1 "register_operand" "f")
1373190286Sobrien			 (match_operand 2 "nonimmediate_operand" "fm")])
1373290286Sobrien	  (pc)
1373390286Sobrien	  (label_ref (match_operand 3 "" ""))))
13734169699Skan   (clobber (reg:CCFP FPSR_REG))
13735169699Skan   (clobber (reg:CCFP FLAGS_REG))
1373690286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1373790286Sobrien  "TARGET_80387
1373890286Sobrien   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
1373990286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1374090286Sobrien   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
1374190286Sobrien   && SELECT_CC_MODE (GET_CODE (operands[0]),
1374290286Sobrien		      operands[1], operands[2]) == CCFPmode
1374390286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1374490286Sobrien  "#")
1374550650Sobrien
13746169699Skan(define_insn "*fp_jcc_5_387"
1374750650Sobrien  [(set (pc)
1374890286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1374990286Sobrien			[(match_operand 1 "register_operand" "f")
1375090286Sobrien			 (match_operand 2 "register_operand" "f")])
1375190286Sobrien	  (label_ref (match_operand 3 "" ""))
1375290286Sobrien	  (pc)))
13753169699Skan   (clobber (reg:CCFP FPSR_REG))
13754169699Skan   (clobber (reg:CCFP FLAGS_REG))
1375590286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1375690286Sobrien  "TARGET_80387
1375790286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
1375890286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1375990286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1376090286Sobrien  "#")
1376150650Sobrien
13762169699Skan(define_insn "*fp_jcc_6_387"
1376350650Sobrien  [(set (pc)
1376490286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1376590286Sobrien			[(match_operand 1 "register_operand" "f")
1376690286Sobrien			 (match_operand 2 "register_operand" "f")])
1376790286Sobrien	  (pc)
1376890286Sobrien	  (label_ref (match_operand 3 "" ""))))
13769169699Skan   (clobber (reg:CCFP FPSR_REG))
13770169699Skan   (clobber (reg:CCFP FLAGS_REG))
1377190286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1377290286Sobrien  "TARGET_80387
1377390286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
1377490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1377590286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1377690286Sobrien  "#")
1377750650Sobrien
13778169699Skan(define_insn "*fp_jcc_7_387"
13779169699Skan  [(set (pc)
13780169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13781169699Skan			[(match_operand 1 "register_operand" "f")
13782169699Skan			 (match_operand 2 "const0_operand" "X")])
13783169699Skan	  (label_ref (match_operand 3 "" ""))
13784169699Skan	  (pc)))
13785169699Skan   (clobber (reg:CCFP FPSR_REG))
13786169699Skan   (clobber (reg:CCFP FLAGS_REG))
13787169699Skan   (clobber (match_scratch:HI 4 "=a"))]
13788169699Skan  "TARGET_80387
13789169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
13790169699Skan   && GET_MODE (operands[1]) == GET_MODE (operands[2])
13791169699Skan   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
13792169699Skan   && SELECT_CC_MODE (GET_CODE (operands[0]),
13793169699Skan		      operands[1], operands[2]) == CCFPmode
13794169699Skan   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
13795169699Skan  "#")
13796169699Skan
13797169699Skan;; The order of operands in *fp_jcc_8_387 is forced by combine in
13798169699Skan;; simplify_comparison () function. Float operator is treated as RTX_OBJ
13799169699Skan;; with a precedence over other operators and is always put in the first
13800169699Skan;; place. Swap condition and operands to match ficom instruction.
13801169699Skan
13802169699Skan(define_insn "*fp_jcc_8<mode>_387"
13803169699Skan  [(set (pc)
13804169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13805169699Skan			[(match_operator 1 "float_operator"
13806169699Skan			   [(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")])
13807169699Skan			   (match_operand 3 "register_operand" "f,f")])
13808169699Skan	  (label_ref (match_operand 4 "" ""))
13809169699Skan	  (pc)))
13810169699Skan   (clobber (reg:CCFP FPSR_REG))
13811169699Skan   (clobber (reg:CCFP FLAGS_REG))
13812169699Skan   (clobber (match_scratch:HI 5 "=a,a"))]
13813169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
13814169699Skan   && FLOAT_MODE_P (GET_MODE (operands[3]))
13815169699Skan   && GET_MODE (operands[1]) == GET_MODE (operands[3])
13816169699Skan   && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0])))
13817169699Skan   && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
13818169699Skan   && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))"
13819169699Skan  "#")
13820169699Skan
1382190286Sobrien(define_split
1382250650Sobrien  [(set (pc)
1382390286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1382490286Sobrien			[(match_operand 1 "register_operand" "")
1382590286Sobrien			 (match_operand 2 "nonimmediate_operand" "")])
1382690286Sobrien	  (match_operand 3 "" "")
1382790286Sobrien	  (match_operand 4 "" "")))
13828169699Skan   (clobber (reg:CCFP FPSR_REG))
13829169699Skan   (clobber (reg:CCFP FLAGS_REG))]
1383090286Sobrien  "reload_completed"
1383190286Sobrien  [(const_int 0)]
1383250650Sobrien{
1383390286Sobrien  ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
13834169699Skan	                operands[3], operands[4], NULL_RTX, NULL_RTX);
1383590286Sobrien  DONE;
1383690286Sobrien})
1383750650Sobrien
1383890286Sobrien(define_split
1383950650Sobrien  [(set (pc)
1384090286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1384190286Sobrien			[(match_operand 1 "register_operand" "")
13842169699Skan			 (match_operand 2 "general_operand" "")])
1384390286Sobrien	  (match_operand 3 "" "")
1384490286Sobrien	  (match_operand 4 "" "")))
13845169699Skan   (clobber (reg:CCFP FPSR_REG))
13846169699Skan   (clobber (reg:CCFP FLAGS_REG))
1384790286Sobrien   (clobber (match_scratch:HI 5 "=a"))]
1384890286Sobrien  "reload_completed"
13849169699Skan  [(const_int 0)]
1385050650Sobrien{
1385190286Sobrien  ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
13852169699Skan	     		operands[3], operands[4], operands[5], NULL_RTX);
1385390286Sobrien  DONE;
1385490286Sobrien})
13855169699Skan
13856169699Skan(define_split
13857169699Skan  [(set (pc)
13858169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13859169699Skan			[(match_operator 1 "float_operator"
13860169699Skan			   [(match_operand:X87MODEI12 2 "memory_operand" "")])
13861169699Skan			   (match_operand 3 "register_operand" "")])
13862169699Skan	  (match_operand 4 "" "")
13863169699Skan	  (match_operand 5 "" "")))
13864169699Skan   (clobber (reg:CCFP FPSR_REG))
13865169699Skan   (clobber (reg:CCFP FLAGS_REG))
13866169699Skan   (clobber (match_scratch:HI 6 "=a"))]
13867169699Skan  "reload_completed"
13868169699Skan  [(const_int 0)]
13869169699Skan{
13870169699Skan  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[2]);
13871169699Skan  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
13872169699Skan			operands[3], operands[7],
13873169699Skan			operands[4], operands[5], operands[6], NULL_RTX);
13874169699Skan  DONE;
13875169699Skan})
13876169699Skan
13877169699Skan;; %%% Kill this when reload knows how to do it.
13878169699Skan(define_split
13879169699Skan  [(set (pc)
13880169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13881169699Skan			[(match_operator 1 "float_operator"
13882169699Skan			   [(match_operand:X87MODEI12 2 "register_operand" "")])
13883169699Skan			   (match_operand 3 "register_operand" "")])
13884169699Skan	  (match_operand 4 "" "")
13885169699Skan	  (match_operand 5 "" "")))
13886169699Skan   (clobber (reg:CCFP FPSR_REG))
13887169699Skan   (clobber (reg:CCFP FLAGS_REG))
13888169699Skan   (clobber (match_scratch:HI 6 "=a"))]
13889169699Skan  "reload_completed"
13890169699Skan  [(const_int 0)]
13891169699Skan{
13892169699Skan  operands[7] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
13893169699Skan  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[7]);
13894169699Skan  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
13895169699Skan			operands[3], operands[7],
13896169699Skan			operands[4], operands[5], operands[6], operands[2]);
13897169699Skan  DONE;
13898169699Skan})
1389990286Sobrien
1390090286Sobrien;; Unconditional and other jump instructions
1390150650Sobrien
1390290286Sobrien(define_insn "jump"
1390350650Sobrien  [(set (pc)
1390490286Sobrien	(label_ref (match_operand 0 "" "")))]
1390550650Sobrien  ""
1390690286Sobrien  "jmp\t%l0"
13907117404Skan  [(set_attr "type" "ibr")
13908117404Skan   (set (attr "length")
13909117404Skan	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13910117404Skan				  (const_int -126))
13911117404Skan			      (lt (minus (match_dup 0) (pc))
13912117404Skan				  (const_int 128)))
13913117404Skan	     (const_int 2)
13914117404Skan	     (const_int 5)))
13915117404Skan   (set_attr "modrm" "0")])
1391690286Sobrien
1391790286Sobrien(define_expand "indirect_jump"
1391890286Sobrien  [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))]
1391990286Sobrien  ""
1392090286Sobrien  "")
1392190286Sobrien
1392290286Sobrien(define_insn "*indirect_jump"
1392390286Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
1392490286Sobrien  "!TARGET_64BIT"
1392590286Sobrien  "jmp\t%A0"
1392690286Sobrien  [(set_attr "type" "ibr")
1392790286Sobrien   (set_attr "length_immediate" "0")])
1392890286Sobrien
1392990286Sobrien(define_insn "*indirect_jump_rtx64"
1393090286Sobrien  [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm"))]
1393190286Sobrien  "TARGET_64BIT"
1393290286Sobrien  "jmp\t%A0"
1393390286Sobrien  [(set_attr "type" "ibr")
1393490286Sobrien   (set_attr "length_immediate" "0")])
1393590286Sobrien
1393690286Sobrien(define_expand "tablejump"
1393790286Sobrien  [(parallel [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))
1393890286Sobrien	      (use (label_ref (match_operand 1 "" "")))])]
1393990286Sobrien  ""
1394050650Sobrien{
13941117404Skan  /* In PIC mode, the table entries are stored GOT (32-bit) or PC (64-bit)
13942117404Skan     relative.  Convert the relative address to an absolute address.  */
1394390286Sobrien  if (flag_pic)
1394490286Sobrien    {
13945117404Skan      rtx op0, op1;
13946117404Skan      enum rtx_code code;
13947117404Skan
1394890286Sobrien      if (TARGET_64BIT)
1394990286Sobrien	{
13950117404Skan	  code = PLUS;
13951117404Skan	  op0 = operands[0];
13952117404Skan	  op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);
1395390286Sobrien	}
13954117404Skan      else if (TARGET_MACHO || HAVE_AS_GOTOFF_IN_DATA)
13955117404Skan	{
13956117404Skan	  code = PLUS;
13957117404Skan	  op0 = operands[0];
13958117404Skan	  op1 = pic_offset_table_rtx;
13959117404Skan	}
1396090286Sobrien      else
1396190286Sobrien	{
13962117404Skan	  code = MINUS;
13963117404Skan	  op0 = pic_offset_table_rtx;
13964117404Skan	  op1 = operands[0];
1396590286Sobrien	}
13966117404Skan
13967117404Skan      operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0,
13968117404Skan					 OPTAB_DIRECT);
1396990286Sobrien    }
1397090286Sobrien})
1397150650Sobrien
1397290286Sobrien(define_insn "*tablejump_1"
1397390286Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
1397490286Sobrien   (use (label_ref (match_operand 1 "" "")))]
1397590286Sobrien  "!TARGET_64BIT"
1397690286Sobrien  "jmp\t%A0"
1397790286Sobrien  [(set_attr "type" "ibr")
1397890286Sobrien   (set_attr "length_immediate" "0")])
1397918334Speter
1398090286Sobrien(define_insn "*tablejump_1_rtx64"
1398190286Sobrien  [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm"))
1398290286Sobrien   (use (label_ref (match_operand 1 "" "")))]
1398390286Sobrien  "TARGET_64BIT"
1398490286Sobrien  "jmp\t%A0"
1398590286Sobrien  [(set_attr "type" "ibr")
1398690286Sobrien   (set_attr "length_immediate" "0")])
1398790286Sobrien
1398890286Sobrien;; Convert setcc + movzbl to xor + setcc if operands don't overlap.
1398918334Speter
1399090286Sobrien(define_peephole2
13991169699Skan  [(set (reg FLAGS_REG) (match_operand 0 "" ""))
1399290286Sobrien   (set (match_operand:QI 1 "register_operand" "")
1399390286Sobrien	(match_operator:QI 2 "ix86_comparison_operator"
13994169699Skan	  [(reg FLAGS_REG) (const_int 0)]))
1399590286Sobrien   (set (match_operand 3 "q_regs_operand" "")
1399690286Sobrien	(zero_extend (match_dup 1)))]
1399790286Sobrien  "(peep2_reg_dead_p (3, operands[1])
1399890286Sobrien    || operands_match_p (operands[1], operands[3]))
1399990286Sobrien   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
1400090286Sobrien  [(set (match_dup 4) (match_dup 0))
1400190286Sobrien   (set (strict_low_part (match_dup 5))
1400290286Sobrien	(match_dup 2))]
1400318334Speter{
14004169699Skan  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
14005132727Skan  operands[5] = gen_lowpart (QImode, operands[3]);
1400690286Sobrien  ix86_expand_clear (operands[3]);
1400790286Sobrien})
1400818334Speter
1400990286Sobrien;; Similar, but match zero_extendhisi2_and, which adds a clobber.
1401018334Speter
1401190286Sobrien(define_peephole2
14012169699Skan  [(set (reg FLAGS_REG) (match_operand 0 "" ""))
1401390286Sobrien   (set (match_operand:QI 1 "register_operand" "")
1401490286Sobrien	(match_operator:QI 2 "ix86_comparison_operator"
14015169699Skan	  [(reg FLAGS_REG) (const_int 0)]))
1401690286Sobrien   (parallel [(set (match_operand 3 "q_regs_operand" "")
1401790286Sobrien		   (zero_extend (match_dup 1)))
14018169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1401990286Sobrien  "(peep2_reg_dead_p (3, operands[1])
1402090286Sobrien    || operands_match_p (operands[1], operands[3]))
1402190286Sobrien   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
1402290286Sobrien  [(set (match_dup 4) (match_dup 0))
1402390286Sobrien   (set (strict_low_part (match_dup 5))
1402490286Sobrien	(match_dup 2))]
1402590286Sobrien{
14026169699Skan  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
14027132727Skan  operands[5] = gen_lowpart (QImode, operands[3]);
1402890286Sobrien  ix86_expand_clear (operands[3]);
1402990286Sobrien})
1403090286Sobrien
1403190286Sobrien;; Call instructions.
1403218334Speter
1403390286Sobrien;; The predicates normally associated with named expanders are not properly
1403490286Sobrien;; checked for calls.  This is a bug in the generic code, but it isn't that
1403590286Sobrien;; easy to fix.  Ignore it for now and be prepared to fix things up.
1403618334Speter
1403718334Speter;; Call subroutine returning no value.
1403818334Speter
1403918334Speter(define_expand "call_pop"
1404090286Sobrien  [(parallel [(call (match_operand:QI 0 "" "")
1404190286Sobrien		    (match_operand:SI 1 "" ""))
14042169699Skan	      (set (reg:SI SP_REG)
14043169699Skan		   (plus:SI (reg:SI SP_REG)
1404490286Sobrien			    (match_operand:SI 3 "" "")))])]
1404590286Sobrien  "!TARGET_64BIT"
1404618334Speter{
14047132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3], 0);
14048117404Skan  DONE;
1404990286Sobrien})
1405018334Speter
1405190286Sobrien(define_insn "*call_pop_0"
1405290286Sobrien  [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" ""))
1405390286Sobrien	 (match_operand:SI 1 "" ""))
14054169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
1405590286Sobrien			    (match_operand:SI 2 "immediate_operand" "")))]
1405690286Sobrien  "!TARGET_64BIT"
1405718334Speter{
1405890286Sobrien  if (SIBLING_CALL_P (insn))
1405990286Sobrien    return "jmp\t%P0";
1406090286Sobrien  else
1406190286Sobrien    return "call\t%P0";
1406290286Sobrien}
1406390286Sobrien  [(set_attr "type" "call")])
1406490286Sobrien  
1406590286Sobrien(define_insn "*call_pop_1"
1406690286Sobrien  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
1406790286Sobrien	 (match_operand:SI 1 "" ""))
14068169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
1406990286Sobrien			    (match_operand:SI 2 "immediate_operand" "i")))]
1407090286Sobrien  "!TARGET_64BIT"
1407190286Sobrien{
1407290286Sobrien  if (constant_call_address_operand (operands[0], Pmode))
1407318334Speter    {
1407490286Sobrien      if (SIBLING_CALL_P (insn))
1407590286Sobrien	return "jmp\t%P0";
1407690286Sobrien      else
1407790286Sobrien	return "call\t%P0";
1407818334Speter    }
1407990286Sobrien  if (SIBLING_CALL_P (insn))
1408090286Sobrien    return "jmp\t%A0";
1408118334Speter  else
1408290286Sobrien    return "call\t%A0";
1408390286Sobrien}
1408490286Sobrien  [(set_attr "type" "call")])
1408518334Speter
1408618334Speter(define_expand "call"
1408790286Sobrien  [(call (match_operand:QI 0 "" "")
1408890286Sobrien	 (match_operand 1 "" ""))
1408990286Sobrien   (use (match_operand 2 "" ""))]
1409018334Speter  ""
1409118334Speter{
14092132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 0);
14093117404Skan  DONE;
1409490286Sobrien})
1409518334Speter
14096132727Skan(define_expand "sibcall"
14097132727Skan  [(call (match_operand:QI 0 "" "")
14098132727Skan	 (match_operand 1 "" ""))
14099132727Skan   (use (match_operand 2 "" ""))]
14100132727Skan  ""
14101132727Skan{
14102132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 1);
14103132727Skan  DONE;
14104132727Skan})
14105132727Skan
1410690286Sobrien(define_insn "*call_0"
1410790286Sobrien  [(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
1410890286Sobrien	 (match_operand 1 "" ""))]
1410918334Speter  ""
1411018334Speter{
1411190286Sobrien  if (SIBLING_CALL_P (insn))
1411290286Sobrien    return "jmp\t%P0";
1411390286Sobrien  else
1411490286Sobrien    return "call\t%P0";
1411590286Sobrien}
1411690286Sobrien  [(set_attr "type" "call")])
1411790286Sobrien
1411890286Sobrien(define_insn "*call_1"
1411990286Sobrien  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
1412090286Sobrien	 (match_operand 1 "" ""))]
14121132727Skan  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
1412290286Sobrien{
14123169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14124132727Skan    return "call\t%P0";
14125132727Skan  return "call\t%A0";
1412690286Sobrien}
1412790286Sobrien  [(set_attr "type" "call")])
1412818334Speter
14129132727Skan(define_insn "*sibcall_1"
14130132727Skan  [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,c,d,a"))
14131132727Skan	 (match_operand 1 "" ""))]
14132132727Skan  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
14133132727Skan{
14134169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14135132727Skan    return "jmp\t%P0";
14136132727Skan  return "jmp\t%A0";
14137132727Skan}
14138132727Skan  [(set_attr "type" "call")])
14139132727Skan
1414090286Sobrien(define_insn "*call_1_rex64"
1414190286Sobrien  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
1414290286Sobrien	 (match_operand 1 "" ""))]
14143132727Skan  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
1414490286Sobrien{
14145169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14146132727Skan    return "call\t%P0";
14147132727Skan  return "call\t%A0";
1414890286Sobrien}
1414990286Sobrien  [(set_attr "type" "call")])
1415018334Speter
14151132727Skan(define_insn "*sibcall_1_rex64"
14152132727Skan  [(call (mem:QI (match_operand:DI 0 "constant_call_address_operand" ""))
14153132727Skan	 (match_operand 1 "" ""))]
14154132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
14155132727Skan  "jmp\t%P0"
14156132727Skan  [(set_attr "type" "call")])
14157132727Skan
14158132727Skan(define_insn "*sibcall_1_rex64_v"
14159132727Skan  [(call (mem:QI (reg:DI 40))
14160132727Skan	 (match_operand 0 "" ""))]
14161132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
14162132727Skan  "jmp\t*%%r11"
14163132727Skan  [(set_attr "type" "call")])
14164132727Skan
14165132727Skan
1416618334Speter;; Call subroutine, returning value in operand 0
1416718334Speter
1416818334Speter(define_expand "call_value_pop"
1416918334Speter  [(parallel [(set (match_operand 0 "" "")
1417090286Sobrien		   (call (match_operand:QI 1 "" "")
1417190286Sobrien			 (match_operand:SI 2 "" "")))
14172169699Skan	      (set (reg:SI SP_REG)
14173169699Skan		   (plus:SI (reg:SI SP_REG)
1417490286Sobrien			    (match_operand:SI 4 "" "")))])]
1417590286Sobrien  "!TARGET_64BIT"
1417618334Speter{
14177117404Skan  ix86_expand_call (operands[0], operands[1], operands[2],
14178132727Skan		    operands[3], operands[4], 0);
14179117404Skan  DONE;
1418090286Sobrien})
1418118334Speter
1418218334Speter(define_expand "call_value"
1418318334Speter  [(set (match_operand 0 "" "")
1418490286Sobrien	(call (match_operand:QI 1 "" "")
1418590286Sobrien	      (match_operand:SI 2 "" "")))
1418690286Sobrien   (use (match_operand:SI 3 "" ""))]
1418718334Speter  ;; Operand 2 not used on the i386.
1418818334Speter  ""
1418918334Speter{
14190132727Skan  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 0);
1419190286Sobrien  DONE;
1419290286Sobrien})
1419318334Speter
14194132727Skan(define_expand "sibcall_value"
14195132727Skan  [(set (match_operand 0 "" "")
14196132727Skan	(call (match_operand:QI 1 "" "")
14197132727Skan	      (match_operand:SI 2 "" "")))
14198132727Skan   (use (match_operand:SI 3 "" ""))]
14199132727Skan  ;; Operand 2 not used on the i386.
14200132727Skan  ""
14201132727Skan{
14202132727Skan  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 1);
14203132727Skan  DONE;
14204132727Skan})
14205132727Skan
1420618334Speter;; Call subroutine returning any type.
1420718334Speter
1420818334Speter(define_expand "untyped_call"
1420918334Speter  [(parallel [(call (match_operand 0 "" "")
1421018334Speter		    (const_int 0))
1421118334Speter	      (match_operand 1 "" "")
1421218334Speter	      (match_operand 2 "" "")])]
1421318334Speter  ""
1421418334Speter{
1421518334Speter  int i;
1421618334Speter
1421718334Speter  /* In order to give reg-stack an easier job in validating two
1421818334Speter     coprocessor registers as containing a possible return value,
1421918334Speter     simply pretend the untyped call returns a complex long double
1422018334Speter     value.  */
1422150650Sobrien
14222117404Skan  ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387
14223117404Skan		     ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL),
14224117404Skan		    operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1),
14225132727Skan		    NULL, 0);
1422618334Speter
1422718334Speter  for (i = 0; i < XVECLEN (operands[2], 0); i++)
1422818334Speter    {
1422918334Speter      rtx set = XVECEXP (operands[2], 0, i);
1423018334Speter      emit_move_insn (SET_DEST (set), SET_SRC (set));
1423118334Speter    }
1423218334Speter
1423318334Speter  /* The optimizer does not know that the call sets the function value
1423418334Speter     registers we stored in the result block.  We avoid problems by
1423518334Speter     claiming that all hard registers are used and clobbered at this
1423618334Speter     point.  */
14237117404Skan  emit_insn (gen_blockage (const0_rtx));
1423818334Speter
1423918334Speter  DONE;
1424090286Sobrien})
1424190286Sobrien
1424290286Sobrien;; Prologue and epilogue instructions
1424318334Speter
1424418334Speter;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
1424518334Speter;; all of memory.  This blocks insns from being moved across this point.
1424618334Speter
1424718334Speter(define_insn "blockage"
14248117404Skan  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_BLOCKAGE)]
1424918334Speter  ""
1425052296Sobrien  ""
1425190286Sobrien  [(set_attr "length" "0")])
1425218334Speter
1425318334Speter;; Insn emitted into the body of a function to return from a function.
1425418334Speter;; This is only done if the function's epilogue is known to be simple.
1425590286Sobrien;; See comments for ix86_can_use_return_insn_p in i386.c.
1425618334Speter
1425750650Sobrien(define_expand "return"
1425818334Speter  [(return)]
1425950650Sobrien  "ix86_can_use_return_insn_p ()"
1426090286Sobrien{
1426190286Sobrien  if (current_function_pops_args)
1426290286Sobrien    {
1426390286Sobrien      rtx popc = GEN_INT (current_function_pops_args);
1426490286Sobrien      emit_jump_insn (gen_return_pop_internal (popc));
1426590286Sobrien      DONE;
1426690286Sobrien    }
1426790286Sobrien})
1426850650Sobrien
1426950650Sobrien(define_insn "return_internal"
1427050650Sobrien  [(return)]
1427150650Sobrien  "reload_completed"
1427252296Sobrien  "ret"
1427390286Sobrien  [(set_attr "length" "1")
1427490286Sobrien   (set_attr "length_immediate" "0")
1427590286Sobrien   (set_attr "modrm" "0")])
1427650650Sobrien
14277132727Skan;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
14278132727Skan;; instruction Athlon and K8 have.
14279132727Skan
14280132727Skan(define_insn "return_internal_long"
14281132727Skan  [(return)
14282132727Skan   (unspec [(const_int 0)] UNSPEC_REP)]
14283132727Skan  "reload_completed"
14284132727Skan  "rep {;} ret"
14285132727Skan  [(set_attr "length" "1")
14286132727Skan   (set_attr "length_immediate" "0")
14287132727Skan   (set_attr "prefix_rep" "1")
14288132727Skan   (set_attr "modrm" "0")])
14289132727Skan
1429050650Sobrien(define_insn "return_pop_internal"
1429150650Sobrien  [(return)
1429250650Sobrien   (use (match_operand:SI 0 "const_int_operand" ""))]
1429350650Sobrien  "reload_completed"
1429490286Sobrien  "ret\t%0"
1429590286Sobrien  [(set_attr "length" "3")
1429690286Sobrien   (set_attr "length_immediate" "2")
1429790286Sobrien   (set_attr "modrm" "0")])
1429850650Sobrien
1429990286Sobrien(define_insn "return_indirect_internal"
1430090286Sobrien  [(return)
1430190286Sobrien   (use (match_operand:SI 0 "register_operand" "r"))]
1430290286Sobrien  "reload_completed"
1430390286Sobrien  "jmp\t%A0"
1430490286Sobrien  [(set_attr "type" "ibr")
1430590286Sobrien   (set_attr "length_immediate" "0")])
1430690286Sobrien
1430750650Sobrien(define_insn "nop"
1430850650Sobrien  [(const_int 0)]
1430950650Sobrien  ""
1431052296Sobrien  "nop"
1431190286Sobrien  [(set_attr "length" "1")
1431290286Sobrien   (set_attr "length_immediate" "0")
14313169699Skan   (set_attr "modrm" "0")])
1431450650Sobrien
14315132727Skan;; Align to 16-byte boundary, max skip in op0.  Used to avoid
14316132727Skan;; branch prediction penalty for the third jump in a 16-byte
14317132727Skan;; block on K8.
14318132727Skan
14319132727Skan(define_insn "align"
14320132727Skan  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_ALIGN)]
14321132727Skan  ""
14322132727Skan{
14323132727Skan#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
14324132727Skan  ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 4, (int)INTVAL (operands[0]));
14325132727Skan#else
14326132727Skan  /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that.
14327132727Skan     The align insn is used to avoid 3 jump instructions in the row to improve
14328169699Skan     branch prediction and the benefits hardly outweigh the cost of extra 8
14329132727Skan     nops on the average inserted by full alignment pseudo operation.  */
14330132727Skan#endif
14331132727Skan  return "";
14332132727Skan}
14333132727Skan  [(set_attr "length" "16")])
14334132727Skan
1433550650Sobrien(define_expand "prologue"
1433650650Sobrien  [(const_int 1)]
1433750650Sobrien  ""
1433890286Sobrien  "ix86_expand_prologue (); DONE;")
1433950650Sobrien
14340117404Skan(define_insn "set_got"
1434190286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
14342117404Skan	(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
14343169699Skan   (clobber (reg:CC FLAGS_REG))]
1434490286Sobrien  "!TARGET_64BIT"
14345169699Skan  { return output_set_got (operands[0], NULL_RTX); }
14346117404Skan  [(set_attr "type" "multi")
14347117404Skan   (set_attr "length" "12")])
1434850650Sobrien
14349169699Skan(define_insn "set_got_labelled"
14350169699Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14351169699Skan	(unspec:SI [(label_ref (match_operand 1 "" ""))]
14352169699Skan	 UNSPEC_SET_GOT))
14353169699Skan   (clobber (reg:CC FLAGS_REG))]
14354169699Skan  "!TARGET_64BIT"
14355169699Skan  { return output_set_got (operands[0], operands[1]); }
14356169699Skan  [(set_attr "type" "multi")
14357169699Skan   (set_attr "length" "12")])
14358169699Skan
14359169699Skan(define_insn "set_got_rex64"
14360169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14361169699Skan	(unspec:DI [(const_int 0)] UNSPEC_SET_GOT))]
14362169699Skan  "TARGET_64BIT"
14363169699Skan  "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
14364169699Skan  [(set_attr "type" "lea")
14365169699Skan   (set_attr "length" "6")])
14366169699Skan
1436750650Sobrien(define_expand "epilogue"
1436850650Sobrien  [(const_int 1)]
1436950650Sobrien  ""
1437090286Sobrien  "ix86_expand_epilogue (1); DONE;")
1437150650Sobrien
1437290286Sobrien(define_expand "sibcall_epilogue"
1437390286Sobrien  [(const_int 1)]
1437450650Sobrien  ""
1437590286Sobrien  "ix86_expand_epilogue (0); DONE;")
1437650650Sobrien
1437790286Sobrien(define_expand "eh_return"
14378117404Skan  [(use (match_operand 0 "register_operand" ""))]
1437950650Sobrien  ""
1438050650Sobrien{
14381117404Skan  rtx tmp, sa = EH_RETURN_STACKADJ_RTX, ra = operands[0];
1438250650Sobrien
1438390286Sobrien  /* Tricky bit: we write the address of the handler to which we will
1438490286Sobrien     be returning into someone else's stack frame, one word below the
1438590286Sobrien     stack address we wish to restore.  */
1438690286Sobrien  tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa);
1438790286Sobrien  tmp = plus_constant (tmp, -UNITS_PER_WORD);
1438890286Sobrien  tmp = gen_rtx_MEM (Pmode, tmp);
1438990286Sobrien  emit_move_insn (tmp, ra);
1439018334Speter
1439190286Sobrien  if (Pmode == SImode)
14392169699Skan    emit_jump_insn (gen_eh_return_si (sa));
1439390286Sobrien  else
14394169699Skan    emit_jump_insn (gen_eh_return_di (sa));
1439590286Sobrien  emit_barrier ();
1439690286Sobrien  DONE;
1439790286Sobrien})
1439818334Speter
1439990286Sobrien(define_insn_and_split "eh_return_si"
14400169699Skan  [(set (pc) 
14401169699Skan        (unspec [(match_operand:SI 0 "register_operand" "c")]
14402169699Skan	         UNSPEC_EH_RETURN))]
1440390286Sobrien  "!TARGET_64BIT"
1440490286Sobrien  "#"
1440590286Sobrien  "reload_completed"
1440690286Sobrien  [(const_int 1)]
1440790286Sobrien  "ix86_expand_epilogue (2); DONE;")
1440818334Speter
1440990286Sobrien(define_insn_and_split "eh_return_di"
14410169699Skan  [(set (pc) 
14411169699Skan        (unspec [(match_operand:DI 0 "register_operand" "c")]
14412169699Skan	         UNSPEC_EH_RETURN))]
1441390286Sobrien  "TARGET_64BIT"
1441490286Sobrien  "#"
1441590286Sobrien  "reload_completed"
1441690286Sobrien  [(const_int 1)]
1441790286Sobrien  "ix86_expand_epilogue (2); DONE;")
1441818334Speter
1441990286Sobrien(define_insn "leave"
14420169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI BP_REG) (const_int 4)))
14421169699Skan   (set (reg:SI BP_REG) (mem:SI (reg:SI BP_REG)))
1442290286Sobrien   (clobber (mem:BLK (scratch)))]
1442390286Sobrien  "!TARGET_64BIT"
1442490286Sobrien  "leave"
14425132727Skan  [(set_attr "type" "leave")])
1442618334Speter
1442790286Sobrien(define_insn "leave_rex64"
14428169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI BP_REG) (const_int 8)))
14429169699Skan   (set (reg:DI BP_REG) (mem:DI (reg:DI BP_REG)))
1443090286Sobrien   (clobber (mem:BLK (scratch)))]
1443190286Sobrien  "TARGET_64BIT"
1443290286Sobrien  "leave"
14433132727Skan  [(set_attr "type" "leave")])
1443490286Sobrien
1443590286Sobrien(define_expand "ffssi2"
14436132727Skan  [(parallel
14437132727Skan     [(set (match_operand:SI 0 "register_operand" "") 
14438132727Skan	   (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "")))
14439132727Skan      (clobber (match_scratch:SI 2 ""))
14440169699Skan      (clobber (reg:CC FLAGS_REG))])]
1444118334Speter  ""
14442132727Skan  "")
1444318334Speter
14444132727Skan(define_insn_and_split "*ffs_cmove"
14445132727Skan  [(set (match_operand:SI 0 "register_operand" "=r") 
14446132727Skan	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14447132727Skan   (clobber (match_scratch:SI 2 "=&r"))
14448169699Skan   (clobber (reg:CC FLAGS_REG))]
14449132727Skan  "TARGET_CMOVE"
14450132727Skan  "#"
14451132727Skan  "&& reload_completed"
14452132727Skan  [(set (match_dup 2) (const_int -1))
14453169699Skan   (parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
14454132727Skan	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
14455132727Skan   (set (match_dup 0) (if_then_else:SI
14456169699Skan			(eq (reg:CCZ FLAGS_REG) (const_int 0))
14457132727Skan			(match_dup 2)
14458132727Skan			(match_dup 0)))
14459132727Skan   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
14460169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14461132727Skan  "")
1446218334Speter
14463132727Skan(define_insn_and_split "*ffs_no_cmove"
14464132727Skan  [(set (match_operand:SI 0 "nonimmediate_operand" "=r") 
14465132727Skan	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14466132727Skan   (clobber (match_scratch:SI 2 "=&q"))
14467169699Skan   (clobber (reg:CC FLAGS_REG))]
14468132727Skan  ""
14469132727Skan  "#"
14470132727Skan  "reload_completed"
14471169699Skan  [(parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
14472132727Skan	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
14473132727Skan   (set (strict_low_part (match_dup 3))
14474169699Skan	(eq:QI (reg:CCZ FLAGS_REG) (const_int 0)))
14475132727Skan   (parallel [(set (match_dup 2) (neg:SI (match_dup 2)))
14476169699Skan	      (clobber (reg:CC FLAGS_REG))])
14477132727Skan   (parallel [(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 2)))
14478169699Skan	      (clobber (reg:CC FLAGS_REG))])
14479132727Skan   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
14480169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14481132727Skan{
14482132727Skan  operands[3] = gen_lowpart (QImode, operands[2]);
14483132727Skan  ix86_expand_clear (operands[2]);
1448490286Sobrien})
1448550650Sobrien
14486132727Skan(define_insn "*ffssi_1"
14487169699Skan  [(set (reg:CCZ FLAGS_REG)
14488132727Skan	(compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm")
1448990286Sobrien		     (const_int 0)))
1449090286Sobrien   (set (match_operand:SI 0 "register_operand" "=r")
14491132727Skan	(ctz:SI (match_dup 1)))]
1449218334Speter  ""
1449390286Sobrien  "bsf{l}\t{%1, %0|%0, %1}"
14494169699Skan  [(set_attr "prefix_0f" "1")])
1449518334Speter
14496169699Skan(define_expand "ffsdi2"
14497169699Skan  [(parallel
14498169699Skan     [(set (match_operand:DI 0 "register_operand" "") 
14499169699Skan	   (ffs:DI (match_operand:DI 1 "nonimmediate_operand" "")))
14500169699Skan      (clobber (match_scratch:DI 2 ""))
14501169699Skan      (clobber (reg:CC FLAGS_REG))])]
14502169699Skan  "TARGET_64BIT && TARGET_CMOVE"
14503169699Skan  "")
14504169699Skan
14505169699Skan(define_insn_and_split "*ffs_rex64"
14506169699Skan  [(set (match_operand:DI 0 "register_operand" "=r") 
14507169699Skan	(ffs:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
14508169699Skan   (clobber (match_scratch:DI 2 "=&r"))
14509169699Skan   (clobber (reg:CC FLAGS_REG))]
14510169699Skan  "TARGET_64BIT && TARGET_CMOVE"
14511169699Skan  "#"
14512169699Skan  "&& reload_completed"
14513169699Skan  [(set (match_dup 2) (const_int -1))
14514169699Skan   (parallel [(set (reg:CCZ FLAGS_REG)
14515169699Skan		   (compare:CCZ (match_dup 1) (const_int 0)))
14516169699Skan	      (set (match_dup 0) (ctz:DI (match_dup 1)))])
14517169699Skan   (set (match_dup 0) (if_then_else:DI
14518169699Skan			(eq (reg:CCZ FLAGS_REG) (const_int 0))
14519169699Skan			(match_dup 2)
14520169699Skan			(match_dup 0)))
14521169699Skan   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1)))
14522169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14523169699Skan  "")
14524169699Skan
14525169699Skan(define_insn "*ffsdi_1"
14526169699Skan  [(set (reg:CCZ FLAGS_REG)
14527169699Skan	(compare:CCZ (match_operand:DI 1 "nonimmediate_operand" "rm")
14528169699Skan		     (const_int 0)))
14529169699Skan   (set (match_operand:DI 0 "register_operand" "=r")
14530169699Skan	(ctz:DI (match_dup 1)))]
14531169699Skan  "TARGET_64BIT"
14532169699Skan  "bsf{q}\t{%1, %0|%0, %1}"
14533169699Skan  [(set_attr "prefix_0f" "1")])
14534169699Skan
14535132727Skan(define_insn "ctzsi2"
14536132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14537132727Skan	(ctz:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14538169699Skan   (clobber (reg:CC FLAGS_REG))]
14539132727Skan  ""
14540132727Skan  "bsf{l}\t{%1, %0|%0, %1}"
14541169699Skan  [(set_attr "prefix_0f" "1")])
14542132727Skan
14543169699Skan(define_insn "ctzdi2"
14544169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14545169699Skan	(ctz:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
14546169699Skan   (clobber (reg:CC FLAGS_REG))]
14547169699Skan  "TARGET_64BIT"
14548169699Skan  "bsf{q}\t{%1, %0|%0, %1}"
14549169699Skan  [(set_attr "prefix_0f" "1")])
14550169699Skan
14551132727Skan(define_expand "clzsi2"
14552132727Skan  [(parallel
14553132727Skan     [(set (match_operand:SI 0 "register_operand" "")
14554132727Skan	   (minus:SI (const_int 31)
14555132727Skan		     (clz:SI (match_operand:SI 1 "nonimmediate_operand" ""))))
14556169699Skan      (clobber (reg:CC FLAGS_REG))])
14557132727Skan   (parallel
14558132727Skan     [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 31)))
14559169699Skan      (clobber (reg:CC FLAGS_REG))])]
14560132727Skan  ""
14561132727Skan  "")
14562132727Skan
14563132727Skan(define_insn "*bsr"
14564132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14565132727Skan	(minus:SI (const_int 31)
14566132727Skan		  (clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))))
14567169699Skan   (clobber (reg:CC FLAGS_REG))]
14568132727Skan  ""
14569132727Skan  "bsr{l}\t{%1, %0|%0, %1}"
14570169699Skan  [(set_attr "prefix_0f" "1")])
14571169699Skan
14572169699Skan(define_expand "clzdi2"
14573169699Skan  [(parallel
14574169699Skan     [(set (match_operand:DI 0 "register_operand" "")
14575169699Skan	   (minus:DI (const_int 63)
14576169699Skan		     (clz:DI (match_operand:DI 1 "nonimmediate_operand" ""))))
14577169699Skan      (clobber (reg:CC FLAGS_REG))])
14578169699Skan   (parallel
14579169699Skan     [(set (match_dup 0) (xor:DI (match_dup 0) (const_int 63)))
14580169699Skan      (clobber (reg:CC FLAGS_REG))])]
14581169699Skan  "TARGET_64BIT"
14582169699Skan  "")
14583169699Skan
14584169699Skan(define_insn "*bsr_rex64"
14585169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14586169699Skan	(minus:DI (const_int 63)
14587169699Skan		  (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))))
14588169699Skan   (clobber (reg:CC FLAGS_REG))]
14589169699Skan  "TARGET_64BIT"
14590169699Skan  "bsr{q}\t{%1, %0|%0, %1}"
14591169699Skan  [(set_attr "prefix_0f" "1")])
1459290286Sobrien
14593117404Skan;; Thread-local storage patterns for ELF.
14594117404Skan;;
14595117404Skan;; Note that these code sequences must appear exactly as shown
14596117404Skan;; in order to allow linker relaxation.
14597117404Skan
14598117404Skan(define_insn "*tls_global_dynamic_32_gnu"
14599117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14600117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14601117404Skan		    (match_operand:SI 2 "tls_symbolic_operand" "")
14602117404Skan		    (match_operand:SI 3 "call_insn_operand" "")]
14603117404Skan		    UNSPEC_TLS_GD))
14604117404Skan   (clobber (match_scratch:SI 4 "=d"))
14605117404Skan   (clobber (match_scratch:SI 5 "=c"))
14606169699Skan   (clobber (reg:CC FLAGS_REG))]
14607117404Skan  "!TARGET_64BIT && TARGET_GNU_TLS"
14608117404Skan  "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
14609117404Skan  [(set_attr "type" "multi")
14610117404Skan   (set_attr "length" "12")])
14611117404Skan
14612117404Skan(define_insn "*tls_global_dynamic_32_sun"
14613117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14614117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14615117404Skan		    (match_operand:SI 2 "tls_symbolic_operand" "")
14616117404Skan		    (match_operand:SI 3 "call_insn_operand" "")]
14617117404Skan		    UNSPEC_TLS_GD))
14618117404Skan   (clobber (match_scratch:SI 4 "=d"))
14619117404Skan   (clobber (match_scratch:SI 5 "=c"))
14620169699Skan   (clobber (reg:CC FLAGS_REG))]
14621117404Skan  "!TARGET_64BIT && TARGET_SUN_TLS"
14622117404Skan  "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
14623117404Skan	push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
14624117404Skan  [(set_attr "type" "multi")
14625117404Skan   (set_attr "length" "14")])
14626117404Skan
14627117404Skan(define_expand "tls_global_dynamic_32"
14628117404Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
14629117404Skan		   (unspec:SI
14630117404Skan		    [(match_dup 2)
14631117404Skan		     (match_operand:SI 1 "tls_symbolic_operand" "")
14632117404Skan		     (match_dup 3)]
14633117404Skan		    UNSPEC_TLS_GD))
14634117404Skan	      (clobber (match_scratch:SI 4 ""))
14635117404Skan	      (clobber (match_scratch:SI 5 ""))
14636169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14637117404Skan  ""
14638117404Skan{
14639117404Skan  if (flag_pic)
14640117404Skan    operands[2] = pic_offset_table_rtx;
14641117404Skan  else
14642117404Skan    {
14643117404Skan      operands[2] = gen_reg_rtx (Pmode);
14644117404Skan      emit_insn (gen_set_got (operands[2]));
14645117404Skan    }
14646169699Skan  if (TARGET_GNU2_TLS)
14647169699Skan    {
14648169699Skan       emit_insn (gen_tls_dynamic_gnu2_32
14649169699Skan		  (operands[0], operands[1], operands[2]));
14650169699Skan       DONE;
14651169699Skan    }
14652117404Skan  operands[3] = ix86_tls_get_addr ();
14653117404Skan})
14654117404Skan
14655117404Skan(define_insn "*tls_global_dynamic_64"
14656117404Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14657169699Skan	(call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
14658169699Skan		 (match_operand:DI 3 "" "")))
14659117404Skan   (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14660117404Skan	      UNSPEC_TLS_GD)]
14661117404Skan  "TARGET_64BIT"
14662117404Skan  ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%P2"
14663117404Skan  [(set_attr "type" "multi")
14664117404Skan   (set_attr "length" "16")])
14665117404Skan
14666117404Skan(define_expand "tls_global_dynamic_64"
14667117404Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
14668169699Skan		   (call:DI (mem:QI (match_dup 2)) (const_int 0)))
14669117404Skan	      (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14670117404Skan			 UNSPEC_TLS_GD)])]
14671117404Skan  ""
14672117404Skan{
14673169699Skan  if (TARGET_GNU2_TLS)
14674169699Skan    {
14675169699Skan       emit_insn (gen_tls_dynamic_gnu2_64
14676169699Skan		  (operands[0], operands[1]));
14677169699Skan       DONE;
14678169699Skan    }
14679117404Skan  operands[2] = ix86_tls_get_addr ();
14680117404Skan})
14681117404Skan
14682117404Skan(define_insn "*tls_local_dynamic_base_32_gnu"
14683117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14684117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14685117404Skan                    (match_operand:SI 2 "call_insn_operand" "")]
14686117404Skan		   UNSPEC_TLS_LD_BASE))
14687117404Skan   (clobber (match_scratch:SI 3 "=d"))
14688117404Skan   (clobber (match_scratch:SI 4 "=c"))
14689169699Skan   (clobber (reg:CC FLAGS_REG))]
14690117404Skan  "!TARGET_64BIT && TARGET_GNU_TLS"
14691117404Skan  "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
14692117404Skan  [(set_attr "type" "multi")
14693117404Skan   (set_attr "length" "11")])
14694117404Skan
14695117404Skan(define_insn "*tls_local_dynamic_base_32_sun"
14696117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14697117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14698117404Skan                    (match_operand:SI 2 "call_insn_operand" "")]
14699117404Skan		   UNSPEC_TLS_LD_BASE))
14700117404Skan   (clobber (match_scratch:SI 3 "=d"))
14701117404Skan   (clobber (match_scratch:SI 4 "=c"))
14702169699Skan   (clobber (reg:CC FLAGS_REG))]
14703117404Skan  "!TARGET_64BIT && TARGET_SUN_TLS"
14704117404Skan  "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
14705117404Skan	push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
14706117404Skan  [(set_attr "type" "multi")
14707117404Skan   (set_attr "length" "13")])
14708117404Skan
14709117404Skan(define_expand "tls_local_dynamic_base_32"
14710117404Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
14711117404Skan		   (unspec:SI [(match_dup 1) (match_dup 2)]
14712117404Skan			      UNSPEC_TLS_LD_BASE))
14713117404Skan	      (clobber (match_scratch:SI 3 ""))
14714117404Skan	      (clobber (match_scratch:SI 4 ""))
14715169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14716117404Skan  ""
14717117404Skan{
14718117404Skan  if (flag_pic)
14719117404Skan    operands[1] = pic_offset_table_rtx;
14720117404Skan  else
14721117404Skan    {
14722117404Skan      operands[1] = gen_reg_rtx (Pmode);
14723117404Skan      emit_insn (gen_set_got (operands[1]));
14724117404Skan    }
14725169699Skan  if (TARGET_GNU2_TLS)
14726169699Skan    {
14727169699Skan       emit_insn (gen_tls_dynamic_gnu2_32
14728169699Skan		  (operands[0], ix86_tls_module_base (), operands[1]));
14729169699Skan       DONE;
14730169699Skan    }
14731117404Skan  operands[2] = ix86_tls_get_addr ();
14732117404Skan})
14733117404Skan
14734117404Skan(define_insn "*tls_local_dynamic_base_64"
14735117404Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14736169699Skan	(call:DI (mem:QI (match_operand:DI 1 "call_insn_operand" ""))
14737169699Skan		 (match_operand:DI 2 "" "")))
14738117404Skan   (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
14739117404Skan  "TARGET_64BIT"
14740117404Skan  "lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1"
14741117404Skan  [(set_attr "type" "multi")
14742117404Skan   (set_attr "length" "12")])
14743117404Skan
14744117404Skan(define_expand "tls_local_dynamic_base_64"
14745117404Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
14746169699Skan		   (call:DI (mem:QI (match_dup 1)) (const_int 0)))
14747117404Skan	      (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
14748117404Skan  ""
14749117404Skan{
14750169699Skan  if (TARGET_GNU2_TLS)
14751169699Skan    {
14752169699Skan       emit_insn (gen_tls_dynamic_gnu2_64
14753169699Skan		  (operands[0], ix86_tls_module_base ()));
14754169699Skan       DONE;
14755169699Skan    }
14756117404Skan  operands[1] = ix86_tls_get_addr ();
14757117404Skan})
14758117404Skan
14759117404Skan;; Local dynamic of a single variable is a lose.  Show combine how
14760117404Skan;; to convert that back to global dynamic.
14761117404Skan
14762117404Skan(define_insn_and_split "*tls_local_dynamic_32_once"
14763117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14764117404Skan	(plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b")
14765117404Skan			     (match_operand:SI 2 "call_insn_operand" "")]
14766117404Skan			    UNSPEC_TLS_LD_BASE)
14767117404Skan		 (const:SI (unspec:SI
14768117404Skan			    [(match_operand:SI 3 "tls_symbolic_operand" "")]
14769117404Skan			    UNSPEC_DTPOFF))))
14770117404Skan   (clobber (match_scratch:SI 4 "=d"))
14771117404Skan   (clobber (match_scratch:SI 5 "=c"))
14772169699Skan   (clobber (reg:CC FLAGS_REG))]
14773117404Skan  ""
14774117404Skan  "#"
14775117404Skan  ""
14776117404Skan  [(parallel [(set (match_dup 0)
14777117404Skan		   (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)]
14778117404Skan			      UNSPEC_TLS_GD))
14779117404Skan	      (clobber (match_dup 4))
14780117404Skan	      (clobber (match_dup 5))
14781169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14782117404Skan  "")
14783132727Skan
14784132727Skan;; Load and add the thread base pointer from %gs:0.
14785132727Skan
14786132727Skan(define_insn "*load_tp_si"
14787132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14788132727Skan	(unspec:SI [(const_int 0)] UNSPEC_TP))]
14789132727Skan  "!TARGET_64BIT"
14790132727Skan  "mov{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
14791132727Skan  [(set_attr "type" "imov")
14792132727Skan   (set_attr "modrm" "0")
14793132727Skan   (set_attr "length" "7")
14794132727Skan   (set_attr "memory" "load")
14795132727Skan   (set_attr "imm_disp" "false")])
14796132727Skan
14797132727Skan(define_insn "*add_tp_si"
14798132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14799132727Skan	(plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
14800132727Skan		 (match_operand:SI 1 "register_operand" "0")))
14801169699Skan   (clobber (reg:CC FLAGS_REG))]
14802132727Skan  "!TARGET_64BIT"
14803132727Skan  "add{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
14804132727Skan  [(set_attr "type" "alu")
14805132727Skan   (set_attr "modrm" "0")
14806132727Skan   (set_attr "length" "7")
14807132727Skan   (set_attr "memory" "load")
14808132727Skan   (set_attr "imm_disp" "false")])
14809132727Skan
14810132727Skan(define_insn "*load_tp_di"
14811132727Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14812132727Skan	(unspec:DI [(const_int 0)] UNSPEC_TP))]
14813132727Skan  "TARGET_64BIT"
14814132727Skan  "mov{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
14815132727Skan  [(set_attr "type" "imov")
14816132727Skan   (set_attr "modrm" "0")
14817132727Skan   (set_attr "length" "7")
14818132727Skan   (set_attr "memory" "load")
14819132727Skan   (set_attr "imm_disp" "false")])
14820132727Skan
14821132727Skan(define_insn "*add_tp_di"
14822132727Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14823132727Skan	(plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP)
14824132727Skan		 (match_operand:DI 1 "register_operand" "0")))
14825169699Skan   (clobber (reg:CC FLAGS_REG))]
14826132727Skan  "TARGET_64BIT"
14827132727Skan  "add{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
14828132727Skan  [(set_attr "type" "alu")
14829132727Skan   (set_attr "modrm" "0")
14830132727Skan   (set_attr "length" "7")
14831132727Skan   (set_attr "memory" "load")
14832132727Skan   (set_attr "imm_disp" "false")])
14833169699Skan
14834169699Skan;; GNU2 TLS patterns can be split.
14835169699Skan
14836169699Skan(define_expand "tls_dynamic_gnu2_32"
14837169699Skan  [(set (match_dup 3)
14838169699Skan	(plus:SI (match_operand:SI 2 "register_operand" "")
14839169699Skan		 (const:SI
14840169699Skan		  (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")]
14841169699Skan			     UNSPEC_TLSDESC))))
14842169699Skan   (parallel
14843169699Skan    [(set (match_operand:SI 0 "register_operand" "")
14844169699Skan	  (unspec:SI [(match_dup 1) (match_dup 3)
14845169699Skan		      (match_dup 2) (reg:SI SP_REG)]
14846169699Skan		      UNSPEC_TLSDESC))
14847169699Skan     (clobber (reg:CC FLAGS_REG))])]
14848169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14849169699Skan{
14850169699Skan  operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14851169699Skan  ix86_tls_descriptor_calls_expanded_in_cfun = true;
14852169699Skan})
14853169699Skan
14854169699Skan(define_insn "*tls_dynamic_lea_32"
14855169699Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14856169699Skan	(plus:SI (match_operand:SI 1 "register_operand" "b")
14857169699Skan		 (const:SI
14858169699Skan		  (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")]
14859169699Skan			      UNSPEC_TLSDESC))))]
14860169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14861169699Skan  "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}"
14862169699Skan  [(set_attr "type" "lea")
14863169699Skan   (set_attr "mode" "SI")
14864169699Skan   (set_attr "length" "6")
14865169699Skan   (set_attr "length_address" "4")])
14866169699Skan
14867169699Skan(define_insn "*tls_dynamic_call_32"
14868169699Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14869169699Skan	(unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")
14870169699Skan		    (match_operand:SI 2 "register_operand" "0")
14871169699Skan		    ;; we have to make sure %ebx still points to the GOT
14872169699Skan		    (match_operand:SI 3 "register_operand" "b")
14873169699Skan		    (reg:SI SP_REG)]
14874169699Skan		   UNSPEC_TLSDESC))
14875169699Skan   (clobber (reg:CC FLAGS_REG))]
14876169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14877169699Skan  "call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}"
14878169699Skan  [(set_attr "type" "call")
14879169699Skan   (set_attr "length" "2")
14880169699Skan   (set_attr "length_address" "0")])
14881169699Skan
14882169699Skan(define_insn_and_split "*tls_dynamic_gnu2_combine_32"
14883169699Skan  [(set (match_operand:SI 0 "register_operand" "=&a")
14884169699Skan	(plus:SI
14885169699Skan	 (unspec:SI [(match_operand:SI 3 "tls_modbase_operand" "")
14886169699Skan		     (match_operand:SI 4 "" "")
14887169699Skan		     (match_operand:SI 2 "register_operand" "b")
14888169699Skan		     (reg:SI SP_REG)]
14889169699Skan		    UNSPEC_TLSDESC)
14890169699Skan	 (const:SI (unspec:SI
14891169699Skan		    [(match_operand:SI 1 "tls_symbolic_operand" "")]
14892169699Skan		    UNSPEC_DTPOFF))))
14893169699Skan   (clobber (reg:CC FLAGS_REG))]
14894169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14895169699Skan  "#"
14896169699Skan  ""
14897169699Skan  [(set (match_dup 0) (match_dup 5))]
14898169699Skan{
14899169699Skan  operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14900169699Skan  emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2]));
14901169699Skan})
14902169699Skan
14903169699Skan(define_expand "tls_dynamic_gnu2_64"
14904169699Skan  [(set (match_dup 2)
14905169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14906169699Skan		   UNSPEC_TLSDESC))
14907169699Skan   (parallel
14908169699Skan    [(set (match_operand:DI 0 "register_operand" "")
14909169699Skan	  (unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)]
14910169699Skan		     UNSPEC_TLSDESC))
14911169699Skan     (clobber (reg:CC FLAGS_REG))])]
14912169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14913169699Skan{
14914169699Skan  operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14915169699Skan  ix86_tls_descriptor_calls_expanded_in_cfun = true;
14916169699Skan})
14917169699Skan
14918169699Skan(define_insn "*tls_dynamic_lea_64"
14919169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14920169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14921169699Skan		   UNSPEC_TLSDESC))]
14922169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14923169699Skan  "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}"
14924169699Skan  [(set_attr "type" "lea")
14925169699Skan   (set_attr "mode" "DI")
14926169699Skan   (set_attr "length" "7")
14927169699Skan   (set_attr "length_address" "4")])
14928169699Skan
14929169699Skan(define_insn "*tls_dynamic_call_64"
14930169699Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14931169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
14932169699Skan		    (match_operand:DI 2 "register_operand" "0")
14933169699Skan		    (reg:DI SP_REG)]
14934169699Skan		   UNSPEC_TLSDESC))
14935169699Skan   (clobber (reg:CC FLAGS_REG))]
14936169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14937169699Skan  "call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}"
14938169699Skan  [(set_attr "type" "call")
14939169699Skan   (set_attr "length" "2")
14940169699Skan   (set_attr "length_address" "0")])
14941169699Skan
14942169699Skan(define_insn_and_split "*tls_dynamic_gnu2_combine_64"
14943169699Skan  [(set (match_operand:DI 0 "register_operand" "=&a")
14944169699Skan	(plus:DI
14945169699Skan	 (unspec:DI [(match_operand:DI 2 "tls_modbase_operand" "")
14946169699Skan		     (match_operand:DI 3 "" "")
14947169699Skan		     (reg:DI SP_REG)]
14948169699Skan		    UNSPEC_TLSDESC)
14949169699Skan	 (const:DI (unspec:DI
14950169699Skan		    [(match_operand:DI 1 "tls_symbolic_operand" "")]
14951169699Skan		    UNSPEC_DTPOFF))))
14952169699Skan   (clobber (reg:CC FLAGS_REG))]
14953169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14954169699Skan  "#"
14955169699Skan  ""
14956169699Skan  [(set (match_dup 0) (match_dup 4))]
14957169699Skan{
14958169699Skan  operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14959169699Skan  emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
14960169699Skan})
14961169699Skan
14962169699Skan;;
14963117404Skan
1496490286Sobrien;; These patterns match the binary 387 instructions for addM3, subM3,
1496590286Sobrien;; mulM3 and divM3.  There are three patterns for each of DFmode and
1496690286Sobrien;; SFmode.  The first is the normal insn, the second the same insn but
1496790286Sobrien;; with one operand a conversion, and the third the same insn but with
1496890286Sobrien;; the other operand a conversion.  The conversion may be SFmode or
1496990286Sobrien;; SImode if the target mode DFmode, but only SImode if the target mode
1497090286Sobrien;; is SFmode.
1497118334Speter
1497290286Sobrien;; Gcc is slightly more smart about handling normal two address instructions
1497390286Sobrien;; so use special patterns for add and mull.
1497418334Speter
14975169699Skan(define_insn "*fop_sf_comm_mixed"
14976169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,x")
1497790286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1497896294Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "%0,0")
14979169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))]
14980169699Skan  "TARGET_MIX_SSE_I387
14981169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1498296294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1498390286Sobrien  "* return output_387_binary_op (insn, operands);"
1498490286Sobrien  [(set (attr "type") 
1498590286Sobrien	(if_then_else (eq_attr "alternative" "1")
1498690286Sobrien	   (if_then_else (match_operand:SF 3 "mult_operator" "") 
14987117404Skan	      (const_string "ssemul")
14988117404Skan	      (const_string "sseadd"))
14989117404Skan	   (if_then_else (match_operand:SF 3 "mult_operator" "") 
1499090286Sobrien	      (const_string "fmul")
1499190286Sobrien	      (const_string "fop"))))
1499290286Sobrien   (set_attr "mode" "SF")])
1499318334Speter
1499490286Sobrien(define_insn "*fop_sf_comm_sse"
1499590286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1499690286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1499796294Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "%0")
1499890286Sobrien			 (match_operand:SF 2 "nonimmediate_operand" "xm")]))]
14999169699Skan  "TARGET_SSE_MATH
15000169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1500196294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1500290286Sobrien  "* return output_387_binary_op (insn, operands);"
15003117404Skan  [(set (attr "type") 
15004117404Skan        (if_then_else (match_operand:SF 3 "mult_operator" "") 
15005117404Skan	   (const_string "ssemul")
15006117404Skan	   (const_string "sseadd")))
1500790286Sobrien   (set_attr "mode" "SF")])
1500818334Speter
15009169699Skan(define_insn "*fop_sf_comm_i387"
15010169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
15011169699Skan	(match_operator:SF 3 "binary_fp_operator"
15012169699Skan			[(match_operand:SF 1 "nonimmediate_operand" "%0")
15013169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm")]))]
15014169699Skan  "TARGET_80387
15015169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1501696294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1501790286Sobrien  "* return output_387_binary_op (insn, operands);"
1501890286Sobrien  [(set (attr "type") 
1501990286Sobrien	(if_then_else (match_operand:SF 3 "mult_operator" "") 
1502090286Sobrien	   (const_string "fmul")
1502190286Sobrien	   (const_string "fop")))
1502290286Sobrien   (set_attr "mode" "SF")])
1502318334Speter
15024169699Skan(define_insn "*fop_sf_1_mixed"
1502590286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f,x")
1502690286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1502790286Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
15028169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))]
15029169699Skan  "TARGET_MIX_SSE_I387
15030169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
1503190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1503290286Sobrien  "* return output_387_binary_op (insn, operands);"
1503390286Sobrien  [(set (attr "type") 
15034117404Skan        (cond [(and (eq_attr "alternative" "2")
15035117404Skan	            (match_operand:SF 3 "mult_operator" ""))
15036117404Skan                 (const_string "ssemul")
15037117404Skan	       (and (eq_attr "alternative" "2")
15038117404Skan	            (match_operand:SF 3 "div_operator" ""))
15039117404Skan                 (const_string "ssediv")
15040117404Skan	       (eq_attr "alternative" "2")
15041117404Skan                 (const_string "sseadd")
1504290286Sobrien	       (match_operand:SF 3 "mult_operator" "") 
1504390286Sobrien                 (const_string "fmul")
1504490286Sobrien               (match_operand:SF 3 "div_operator" "") 
1504590286Sobrien                 (const_string "fdiv")
1504690286Sobrien              ]
1504790286Sobrien              (const_string "fop")))
1504890286Sobrien   (set_attr "mode" "SF")])
1504918334Speter
1505090286Sobrien(define_insn "*fop_sf_1_sse"
1505190286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1505290286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1505390286Sobrien			[(match_operand:SF 1 "register_operand" "0")
1505490286Sobrien			 (match_operand:SF 2 "nonimmediate_operand" "xm")]))]
1505590286Sobrien  "TARGET_SSE_MATH
15056169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1505790286Sobrien  "* return output_387_binary_op (insn, operands);"
15058117404Skan  [(set (attr "type") 
15059117404Skan        (cond [(match_operand:SF 3 "mult_operator" "")
15060117404Skan                 (const_string "ssemul")
15061117404Skan	       (match_operand:SF 3 "div_operator" "")
15062117404Skan                 (const_string "ssediv")
15063117404Skan              ]
15064117404Skan              (const_string "sseadd")))
1506590286Sobrien   (set_attr "mode" "SF")])
1506618334Speter
15067169699Skan;; This pattern is not fully shadowed by the pattern above.
15068169699Skan(define_insn "*fop_sf_1_i387"
15069169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
15070169699Skan	(match_operator:SF 3 "binary_fp_operator"
15071169699Skan			[(match_operand:SF 1 "nonimmediate_operand" "0,fm")
15072169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
15073169699Skan  "TARGET_80387 && !TARGET_SSE_MATH
15074169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
15075169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15076169699Skan  "* return output_387_binary_op (insn, operands);"
15077169699Skan  [(set (attr "type") 
15078169699Skan        (cond [(match_operand:SF 3 "mult_operator" "") 
15079169699Skan                 (const_string "fmul")
15080169699Skan               (match_operand:SF 3 "div_operator" "") 
15081169699Skan                 (const_string "fdiv")
15082169699Skan              ]
15083169699Skan              (const_string "fop")))
15084169699Skan   (set_attr "mode" "SF")])
15085169699Skan
1508690286Sobrien;; ??? Add SSE splitters for these!
15087169699Skan(define_insn "*fop_sf_2<mode>_i387"
1508890286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
1508990286Sobrien	(match_operator:SF 3 "binary_fp_operator"
15090169699Skan	  [(float:SF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1509190286Sobrien	   (match_operand:SF 2 "register_operand" "0,0")]))]
15092169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
1509390286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1509490286Sobrien  [(set (attr "type") 
1509590286Sobrien        (cond [(match_operand:SF 3 "mult_operator" "") 
1509690286Sobrien                 (const_string "fmul")
1509790286Sobrien               (match_operand:SF 3 "div_operator" "") 
1509890286Sobrien                 (const_string "fdiv")
1509990286Sobrien              ]
1510090286Sobrien              (const_string "fop")))
1510190286Sobrien   (set_attr "fp_int_src" "true")
15102169699Skan   (set_attr "mode" "<MODE>")])
1510318334Speter
15104169699Skan(define_insn "*fop_sf_3<mode>_i387"
1510590286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
1510690286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1510790286Sobrien	  [(match_operand:SF 1 "register_operand" "0,0")
15108169699Skan	   (float:SF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15109169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
1511090286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1511190286Sobrien  [(set (attr "type") 
1511290286Sobrien        (cond [(match_operand:SF 3 "mult_operator" "") 
1511390286Sobrien                 (const_string "fmul")
1511490286Sobrien               (match_operand:SF 3 "div_operator" "") 
1511590286Sobrien                 (const_string "fdiv")
1511690286Sobrien              ]
1511790286Sobrien              (const_string "fop")))
1511890286Sobrien   (set_attr "fp_int_src" "true")
15119169699Skan   (set_attr "mode" "<MODE>")])
1512018334Speter
15121169699Skan(define_insn "*fop_df_comm_mixed"
15122169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,Y")
1512390286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15124169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0,0")
15125169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))]
15126169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387
15127169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1512890286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1512990286Sobrien  "* return output_387_binary_op (insn, operands);"
1513090286Sobrien  [(set (attr "type") 
15131169699Skan	(if_then_else (eq_attr "alternative" "1")
15132169699Skan	   (if_then_else (match_operand:DF 3 "mult_operator" "") 
15133169699Skan	      (const_string "ssemul")
15134169699Skan	      (const_string "sseadd"))
15135169699Skan	   (if_then_else (match_operand:DF 3 "mult_operator" "") 
15136169699Skan	      (const_string "fmul")
15137169699Skan	      (const_string "fop"))))
1513890286Sobrien   (set_attr "mode" "DF")])
1513918334Speter
15140169699Skan(define_insn "*fop_df_comm_sse"
15141169699Skan  [(set (match_operand:DF 0 "register_operand" "=Y")
15142169699Skan	(match_operator:DF 3 "binary_fp_operator"
15143169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0")
15144169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
15145169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
15146169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
15147169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15148169699Skan  "* return output_387_binary_op (insn, operands);"
15149169699Skan  [(set (attr "type") 
15150169699Skan        (if_then_else (match_operand:DF 3 "mult_operator" "") 
15151169699Skan	   (const_string "ssemul")
15152169699Skan	   (const_string "sseadd")))
15153169699Skan   (set_attr "mode" "DF")])
1515418334Speter
15155169699Skan(define_insn "*fop_df_comm_i387"
15156169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
1515790286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15158169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0")
15159169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm")]))]
15160169699Skan  "TARGET_80387
15161169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
15162169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15163169699Skan  "* return output_387_binary_op (insn, operands);"
15164169699Skan  [(set (attr "type") 
15165169699Skan	(if_then_else (match_operand:DF 3 "mult_operator" "") 
15166169699Skan	   (const_string "fmul")
15167169699Skan	   (const_string "fop")))
15168169699Skan   (set_attr "mode" "DF")])
15169169699Skan
15170169699Skan(define_insn "*fop_df_1_mixed"
15171169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,Y")
15172169699Skan	(match_operator:DF 3 "binary_fp_operator"
1517390286Sobrien			[(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
15174169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))]
15175169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
15176169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
1517790286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1517890286Sobrien  "* return output_387_binary_op (insn, operands);"
1517990286Sobrien  [(set (attr "type") 
15180117404Skan        (cond [(and (eq_attr "alternative" "2")
15181169699Skan	            (match_operand:DF 3 "mult_operator" ""))
15182117404Skan                 (const_string "ssemul")
15183117404Skan	       (and (eq_attr "alternative" "2")
15184169699Skan	            (match_operand:DF 3 "div_operator" ""))
15185117404Skan                 (const_string "ssediv")
15186117404Skan	       (eq_attr "alternative" "2")
15187117404Skan                 (const_string "sseadd")
1518890286Sobrien	       (match_operand:DF 3 "mult_operator" "") 
1518990286Sobrien                 (const_string "fmul")
1519090286Sobrien               (match_operand:DF 3 "div_operator" "") 
1519190286Sobrien                 (const_string "fdiv")
1519290286Sobrien              ]
1519390286Sobrien              (const_string "fop")))
1519490286Sobrien   (set_attr "mode" "DF")])
1519518334Speter
1519690286Sobrien(define_insn "*fop_df_1_sse"
1519790286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1519890286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1519990286Sobrien			[(match_operand:DF 1 "register_operand" "0")
1520090286Sobrien			 (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
1520190286Sobrien  "TARGET_SSE2 && TARGET_SSE_MATH
15202169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1520390286Sobrien  "* return output_387_binary_op (insn, operands);"
15204117404Skan  [(set_attr "mode" "DF")
15205117404Skan   (set (attr "type") 
15206169699Skan        (cond [(match_operand:DF 3 "mult_operator" "")
15207117404Skan                 (const_string "ssemul")
15208169699Skan	       (match_operand:DF 3 "div_operator" "")
15209117404Skan                 (const_string "ssediv")
15210117404Skan              ]
15211117404Skan              (const_string "sseadd")))])
1521218334Speter
15213169699Skan;; This pattern is not fully shadowed by the pattern above.
15214169699Skan(define_insn "*fop_df_1_i387"
15215169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
15216169699Skan	(match_operator:DF 3 "binary_fp_operator"
15217169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "0,fm")
15218169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
15219169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
15220169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
15221169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15222169699Skan  "* return output_387_binary_op (insn, operands);"
15223169699Skan  [(set (attr "type") 
15224169699Skan        (cond [(match_operand:DF 3 "mult_operator" "") 
15225169699Skan                 (const_string "fmul")
15226169699Skan               (match_operand:DF 3 "div_operator" "")
15227169699Skan                 (const_string "fdiv")
15228169699Skan              ]
15229169699Skan              (const_string "fop")))
15230169699Skan   (set_attr "mode" "DF")])
15231169699Skan
1523290286Sobrien;; ??? Add SSE splitters for these!
15233169699Skan(define_insn "*fop_df_2<mode>_i387"
1523490286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1523590286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15236169699Skan	   [(float:DF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1523790286Sobrien	    (match_operand:DF 2 "register_operand" "0,0")]))]
15238169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
15239169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1524090286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1524190286Sobrien  [(set (attr "type") 
1524290286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1524390286Sobrien                 (const_string "fmul")
1524490286Sobrien               (match_operand:DF 3 "div_operator" "") 
1524590286Sobrien                 (const_string "fdiv")
1524690286Sobrien              ]
1524790286Sobrien              (const_string "fop")))
1524890286Sobrien   (set_attr "fp_int_src" "true")
15249169699Skan   (set_attr "mode" "<MODE>")])
1525018334Speter
15251169699Skan(define_insn "*fop_df_3<mode>_i387"
1525290286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1525390286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1525490286Sobrien	   [(match_operand:DF 1 "register_operand" "0,0")
15255169699Skan	    (float:DF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15256169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
15257169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1525890286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1525990286Sobrien  [(set (attr "type") 
1526090286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1526190286Sobrien                 (const_string "fmul")
1526290286Sobrien               (match_operand:DF 3 "div_operator" "") 
1526390286Sobrien                 (const_string "fdiv")
1526490286Sobrien              ]
1526590286Sobrien              (const_string "fop")))
1526690286Sobrien   (set_attr "fp_int_src" "true")
15267169699Skan   (set_attr "mode" "<MODE>")])
1526818334Speter
15269169699Skan(define_insn "*fop_df_4_i387"
1527090286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1527190286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1527290286Sobrien	   [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
1527390286Sobrien	    (match_operand:DF 2 "register_operand" "0,f")]))]
15274169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
1527590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1527690286Sobrien  "* return output_387_binary_op (insn, operands);"
1527790286Sobrien  [(set (attr "type") 
1527890286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1527990286Sobrien                 (const_string "fmul")
1528090286Sobrien               (match_operand:DF 3 "div_operator" "") 
1528190286Sobrien                 (const_string "fdiv")
1528290286Sobrien              ]
1528390286Sobrien              (const_string "fop")))
1528490286Sobrien   (set_attr "mode" "SF")])
1528518334Speter
15286169699Skan(define_insn "*fop_df_5_i387"
1528718334Speter  [(set (match_operand:DF 0 "register_operand" "=f,f")
1528890286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1528990286Sobrien	  [(match_operand:DF 1 "register_operand" "0,f")
1529090286Sobrien	   (float_extend:DF
1529190286Sobrien	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
1529290286Sobrien  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1529350650Sobrien  "* return output_387_binary_op (insn, operands);"
1529450650Sobrien  [(set (attr "type") 
1529590286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1529690286Sobrien                 (const_string "fmul")
1529790286Sobrien               (match_operand:DF 3 "div_operator" "") 
1529890286Sobrien                 (const_string "fdiv")
1529950650Sobrien              ]
1530090286Sobrien              (const_string "fop")))
1530190286Sobrien   (set_attr "mode" "SF")])
1530218334Speter
15303169699Skan(define_insn "*fop_df_6_i387"
15304132727Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
15305132727Skan	(match_operator:DF 3 "binary_fp_operator"
15306132727Skan	  [(float_extend:DF
15307132727Skan	    (match_operand:SF 1 "register_operand" "0,f"))
15308132727Skan	   (float_extend:DF
15309132727Skan	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
15310132727Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1531150650Sobrien  "* return output_387_binary_op (insn, operands);"
1531250650Sobrien  [(set (attr "type") 
15313132727Skan        (cond [(match_operand:DF 3 "mult_operator" "") 
1531490286Sobrien                 (const_string "fmul")
15315132727Skan               (match_operand:DF 3 "div_operator" "") 
1531690286Sobrien                 (const_string "fdiv")
1531750650Sobrien              ]
1531890286Sobrien              (const_string "fop")))
15319132727Skan   (set_attr "mode" "SF")])
1532018334Speter
15321169699Skan(define_insn "*fop_xf_comm_i387"
15322169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15323169699Skan	(match_operator:XF 3 "binary_fp_operator"
15324169699Skan			[(match_operand:XF 1 "register_operand" "%0")
15325169699Skan			 (match_operand:XF 2 "register_operand" "f")]))]
15326169699Skan  "TARGET_80387
15327169699Skan   && COMMUTATIVE_ARITH_P (operands[3])"
15328169699Skan  "* return output_387_binary_op (insn, operands);"
15329169699Skan  [(set (attr "type") 
15330169699Skan        (if_then_else (match_operand:XF 3 "mult_operator" "") 
15331169699Skan           (const_string "fmul")
15332169699Skan           (const_string "fop")))
15333169699Skan   (set_attr "mode" "XF")])
15334169699Skan
15335169699Skan(define_insn "*fop_xf_1_i387"
15336132727Skan  [(set (match_operand:XF 0 "register_operand" "=f,f")
15337132727Skan	(match_operator:XF 3 "binary_fp_operator"
15338132727Skan			[(match_operand:XF 1 "register_operand" "0,f")
15339132727Skan			 (match_operand:XF 2 "register_operand" "f,0")]))]
1534090286Sobrien  "TARGET_80387
15341169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1534290286Sobrien  "* return output_387_binary_op (insn, operands);"
1534390286Sobrien  [(set (attr "type") 
15344132727Skan        (cond [(match_operand:XF 3 "mult_operator" "") 
1534590286Sobrien                 (const_string "fmul")
15346132727Skan               (match_operand:XF 3 "div_operator" "") 
1534790286Sobrien                 (const_string "fdiv")
1534890286Sobrien              ]
1534990286Sobrien              (const_string "fop")))
1535090286Sobrien   (set_attr "mode" "XF")])
1535190286Sobrien
15352169699Skan(define_insn "*fop_xf_2<mode>_i387"
1535318334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
1535490286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15355169699Skan	   [(float:XF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1535690286Sobrien	    (match_operand:XF 2 "register_operand" "0,0")]))]
15357169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
1535890286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1535990286Sobrien  [(set (attr "type") 
1536090286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1536190286Sobrien                 (const_string "fmul")
1536290286Sobrien               (match_operand:XF 3 "div_operator" "") 
1536390286Sobrien                 (const_string "fdiv")
1536490286Sobrien              ]
1536590286Sobrien              (const_string "fop")))
1536690286Sobrien   (set_attr "fp_int_src" "true")
15367169699Skan   (set_attr "mode" "<MODE>")])
1536890286Sobrien
15369169699Skan(define_insn "*fop_xf_3<mode>_i387"
1537090286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1537190286Sobrien	(match_operator:XF 3 "binary_fp_operator"
1537290286Sobrien	  [(match_operand:XF 1 "register_operand" "0,0")
15373169699Skan	   (float:XF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15374169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
1537590286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1537690286Sobrien  [(set (attr "type") 
1537790286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1537890286Sobrien                 (const_string "fmul")
1537990286Sobrien               (match_operand:XF 3 "div_operator" "") 
1538090286Sobrien                 (const_string "fdiv")
1538190286Sobrien              ]
1538290286Sobrien              (const_string "fop")))
1538390286Sobrien   (set_attr "fp_int_src" "true")
15384169699Skan   (set_attr "mode" "<MODE>")])
1538590286Sobrien
15386169699Skan(define_insn "*fop_xf_4_i387"
1538790286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1538890286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15389132727Skan	   [(float_extend:XF (match_operand 1 "nonimmediate_operand" "fm,0"))
1539050650Sobrien	    (match_operand:XF 2 "register_operand" "0,f")]))]
15391132727Skan  "TARGET_80387"
1539290286Sobrien  "* return output_387_binary_op (insn, operands);"
1539390286Sobrien  [(set (attr "type") 
1539490286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1539590286Sobrien                 (const_string "fmul")
1539690286Sobrien               (match_operand:XF 3 "div_operator" "") 
1539790286Sobrien                 (const_string "fdiv")
1539890286Sobrien              ]
1539990286Sobrien              (const_string "fop")))
1540090286Sobrien   (set_attr "mode" "SF")])
1540190286Sobrien
15402169699Skan(define_insn "*fop_xf_5_i387"
1540318334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
1540490286Sobrien	(match_operator:XF 3 "binary_fp_operator"
1540550650Sobrien	  [(match_operand:XF 1 "register_operand" "0,f")
1540618334Speter	   (float_extend:XF
15407132727Skan	    (match_operand 2 "nonimmediate_operand" "fm,0"))]))]
15408132727Skan  "TARGET_80387"
1540950650Sobrien  "* return output_387_binary_op (insn, operands);"
1541050650Sobrien  [(set (attr "type") 
1541190286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1541290286Sobrien                 (const_string "fmul")
1541390286Sobrien               (match_operand:XF 3 "div_operator" "") 
1541490286Sobrien                 (const_string "fdiv")
1541550650Sobrien              ]
1541690286Sobrien              (const_string "fop")))
1541790286Sobrien   (set_attr "mode" "SF")])
1541818334Speter
15419169699Skan(define_insn "*fop_xf_6_i387"
1542090286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1542190286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15422132727Skan	  [(float_extend:XF
15423132727Skan	    (match_operand 1 "register_operand" "0,f"))
15424132727Skan	   (float_extend:XF
15425132727Skan	    (match_operand 2 "nonimmediate_operand" "fm,0"))]))]
1542618334Speter  "TARGET_80387"
1542750650Sobrien  "* return output_387_binary_op (insn, operands);"
1542850650Sobrien  [(set (attr "type") 
1542990286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1543090286Sobrien                 (const_string "fmul")
1543190286Sobrien               (match_operand:XF 3 "div_operator" "") 
1543290286Sobrien                 (const_string "fdiv")
1543390286Sobrien              ]
1543490286Sobrien              (const_string "fop")))
15435132727Skan   (set_attr "mode" "SF")])
1543690286Sobrien
1543790286Sobrien(define_split
1543890286Sobrien  [(set (match_operand 0 "register_operand" "")
1543990286Sobrien	(match_operator 3 "binary_fp_operator"
15440169699Skan	   [(float (match_operand:X87MODEI12 1 "register_operand" ""))
1544190286Sobrien	    (match_operand 2 "register_operand" "")]))]
1544290286Sobrien  "TARGET_80387 && reload_completed
1544390286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))"
1544490286Sobrien  [(const_int 0)]
1544590286Sobrien{ 
1544690286Sobrien  operands[4] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
1544790286Sobrien  operands[4] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[4]);
1544890286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1544990286Sobrien			  gen_rtx_fmt_ee (GET_CODE (operands[3]),
1545090286Sobrien					  GET_MODE (operands[3]),
1545190286Sobrien					  operands[4],
1545290286Sobrien					  operands[2])));
1545390286Sobrien  ix86_free_from_memory (GET_MODE (operands[1]));
1545490286Sobrien  DONE;
1545590286Sobrien})
1545690286Sobrien
1545790286Sobrien(define_split
1545890286Sobrien  [(set (match_operand 0 "register_operand" "")
1545990286Sobrien	(match_operator 3 "binary_fp_operator"
1546090286Sobrien	   [(match_operand 1 "register_operand" "")
15461169699Skan	    (float (match_operand:X87MODEI12 2 "register_operand" ""))]))]
1546290286Sobrien  "TARGET_80387 && reload_completed
1546390286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))"
1546490286Sobrien  [(const_int 0)]
1546590286Sobrien{
1546690286Sobrien  operands[4] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
1546790286Sobrien  operands[4] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[4]);
1546890286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1546990286Sobrien			  gen_rtx_fmt_ee (GET_CODE (operands[3]),
1547090286Sobrien					  GET_MODE (operands[3]),
1547190286Sobrien					  operands[1],
1547290286Sobrien					  operands[4])));
1547390286Sobrien  ix86_free_from_memory (GET_MODE (operands[2]));
1547490286Sobrien  DONE;
1547590286Sobrien})
1547618334Speter
1547790286Sobrien;; FPU special functions.
1547890286Sobrien
1547990286Sobrien(define_expand "sqrtsf2"
1548090286Sobrien  [(set (match_operand:SF 0 "register_operand" "")
1548190286Sobrien	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
15482169699Skan  "TARGET_USE_FANCY_MATH_387 || TARGET_SSE_MATH"
1548390286Sobrien{
1548490286Sobrien  if (!TARGET_SSE_MATH)
1548590286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
1548690286Sobrien})
1548790286Sobrien
15488169699Skan(define_insn "*sqrtsf2_mixed"
15489169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,x")
15490169699Skan	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))]
15491169699Skan  "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387"
1549290286Sobrien  "@
1549390286Sobrien   fsqrt
1549490286Sobrien   sqrtss\t{%1, %0|%0, %1}"
1549590286Sobrien  [(set_attr "type" "fpspc,sse")
1549690286Sobrien   (set_attr "mode" "SF,SF")
1549790286Sobrien   (set_attr "athlon_decode" "direct,*")])
1549890286Sobrien
15499169699Skan(define_insn "*sqrtsf2_sse"
1550090286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1550190286Sobrien	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "xm")))]
15502169699Skan  "TARGET_SSE_MATH"
1550390286Sobrien  "sqrtss\t{%1, %0|%0, %1}"
1550490286Sobrien  [(set_attr "type" "sse")
1550590286Sobrien   (set_attr "mode" "SF")
1550690286Sobrien   (set_attr "athlon_decode" "*")])
1550790286Sobrien
15508169699Skan(define_insn "*sqrtsf2_i387"
1550990286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
1551090286Sobrien	(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
15511169699Skan  "TARGET_USE_FANCY_MATH_387"
1551290286Sobrien  "fsqrt"
1551390286Sobrien  [(set_attr "type" "fpspc")
1551490286Sobrien   (set_attr "mode" "SF")
1551590286Sobrien   (set_attr "athlon_decode" "direct")])
1551690286Sobrien
1551790286Sobrien(define_expand "sqrtdf2"
1551890286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
1551990286Sobrien	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
15520169699Skan  "TARGET_USE_FANCY_MATH_387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
1552190286Sobrien{
15522169699Skan  if (!(TARGET_SSE2 && TARGET_SSE_MATH))
1552390286Sobrien    operands[1] = force_reg (DFmode, operands[1]);
1552490286Sobrien})
1552590286Sobrien
15526169699Skan(define_insn "*sqrtdf2_mixed"
15527169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,Y")
15528169699Skan	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))]
15529169699Skan  "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387"
1553090286Sobrien  "@
1553190286Sobrien   fsqrt
1553290286Sobrien   sqrtsd\t{%1, %0|%0, %1}"
1553390286Sobrien  [(set_attr "type" "fpspc,sse")
1553490286Sobrien   (set_attr "mode" "DF,DF")
1553590286Sobrien   (set_attr "athlon_decode" "direct,*")])
1553690286Sobrien
15537169699Skan(define_insn "*sqrtdf2_sse"
1553890286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1553990286Sobrien	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
15540169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
1554190286Sobrien  "sqrtsd\t{%1, %0|%0, %1}"
1554290286Sobrien  [(set_attr "type" "sse")
1554390286Sobrien   (set_attr "mode" "DF")
1554490286Sobrien   (set_attr "athlon_decode" "*")])
1554590286Sobrien
15546169699Skan(define_insn "*sqrtdf2_i387"
1554790286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1554890286Sobrien	(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
15549169699Skan  "TARGET_USE_FANCY_MATH_387"
1555090286Sobrien  "fsqrt"
1555190286Sobrien  [(set_attr "type" "fpspc")
1555290286Sobrien   (set_attr "mode" "DF")
1555390286Sobrien   (set_attr "athlon_decode" "direct")])
1555490286Sobrien
15555169699Skan(define_insn "*sqrtextendsfdf2_i387"
1555690286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1555790286Sobrien	(sqrt:DF (float_extend:DF
1555890286Sobrien		  (match_operand:SF 1 "register_operand" "0"))))]
15559169699Skan  "TARGET_USE_FANCY_MATH_387
15560169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
1556190286Sobrien  "fsqrt"
1556290286Sobrien  [(set_attr "type" "fpspc")
1556390286Sobrien   (set_attr "mode" "DF")
1556490286Sobrien   (set_attr "athlon_decode" "direct")])
1556590286Sobrien
1556690286Sobrien(define_insn "sqrtxf2"
1556790286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1556890286Sobrien	(sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
15569169699Skan  "TARGET_USE_FANCY_MATH_387"
1557090286Sobrien  "fsqrt"
1557190286Sobrien  [(set_attr "type" "fpspc")
1557290286Sobrien   (set_attr "mode" "XF")
1557390286Sobrien   (set_attr "athlon_decode" "direct")])
1557490286Sobrien
15575169699Skan(define_insn "*sqrtextendsfxf2_i387"
1557690286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1557790286Sobrien	(sqrt:XF (float_extend:XF
15578169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
15579169699Skan  "TARGET_USE_FANCY_MATH_387"
1558090286Sobrien  "fsqrt"
1558190286Sobrien  [(set_attr "type" "fpspc")
1558290286Sobrien   (set_attr "mode" "XF")
1558390286Sobrien   (set_attr "athlon_decode" "direct")])
1558490286Sobrien
15585169699Skan(define_insn "*sqrtextenddfxf2_i387"
1558690286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1558790286Sobrien	(sqrt:XF (float_extend:XF
15588169699Skan		  (match_operand:DF 1 "register_operand" "0"))))]
15589169699Skan  "TARGET_USE_FANCY_MATH_387"
1559090286Sobrien  "fsqrt"
1559190286Sobrien  [(set_attr "type" "fpspc")
1559290286Sobrien   (set_attr "mode" "XF")
1559390286Sobrien   (set_attr "athlon_decode" "direct")])
1559490286Sobrien
15595169699Skan(define_insn "fpremxf4"
15596169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15597169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
15598169699Skan		    (match_operand:XF 3 "register_operand" "1")]
15599169699Skan		   UNSPEC_FPREM_F))
15600169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15601169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
15602169699Skan		   UNSPEC_FPREM_U))
15603169699Skan   (set (reg:CCFP FPSR_REG)
15604169699Skan	(unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
15605169699Skan  "TARGET_USE_FANCY_MATH_387
15606169699Skan   && flag_unsafe_math_optimizations"
15607169699Skan  "fprem"
15608169699Skan  [(set_attr "type" "fpspc")
15609169699Skan   (set_attr "mode" "XF")])
15610169699Skan
15611169699Skan(define_expand "fmodsf3"
15612169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
15613169699Skan   (use (match_operand:SF 1 "register_operand" ""))
15614169699Skan   (use (match_operand:SF 2 "register_operand" ""))]
15615169699Skan  "TARGET_USE_FANCY_MATH_387
15616169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15617169699Skan   && flag_unsafe_math_optimizations"
15618169699Skan{
15619169699Skan  rtx label = gen_label_rtx ();
15620169699Skan
15621169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15622169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15623169699Skan
15624169699Skan  emit_insn(gen_extendsfxf2 (op1, operands[1]));
15625169699Skan  emit_insn(gen_extendsfxf2 (op2, operands[2]));
15626169699Skan
15627169699Skan  emit_label (label);
15628169699Skan
15629169699Skan  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
15630169699Skan  ix86_emit_fp_unordered_jump (label);
15631169699Skan
15632169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
15633169699Skan  DONE;
15634169699Skan})
15635169699Skan
15636169699Skan(define_expand "fmoddf3"
15637169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
15638169699Skan   (use (match_operand:DF 1 "register_operand" ""))
15639169699Skan   (use (match_operand:DF 2 "register_operand" ""))]
15640169699Skan  "TARGET_USE_FANCY_MATH_387
15641169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15642169699Skan   && flag_unsafe_math_optimizations"
15643169699Skan{
15644169699Skan  rtx label = gen_label_rtx ();
15645169699Skan
15646169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15647169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15648169699Skan
15649169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
15650169699Skan  emit_insn (gen_extenddfxf2 (op2, operands[2]));
15651169699Skan
15652169699Skan  emit_label (label);
15653169699Skan
15654169699Skan  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
15655169699Skan  ix86_emit_fp_unordered_jump (label);
15656169699Skan
15657169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
15658169699Skan  DONE;
15659169699Skan})
15660169699Skan
15661169699Skan(define_expand "fmodxf3"
15662169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
15663169699Skan   (use (match_operand:XF 1 "register_operand" ""))
15664169699Skan   (use (match_operand:XF 2 "register_operand" ""))]
15665169699Skan  "TARGET_USE_FANCY_MATH_387
15666169699Skan   && flag_unsafe_math_optimizations"
15667169699Skan{
15668169699Skan  rtx label = gen_label_rtx ();
15669169699Skan
15670169699Skan  emit_label (label);
15671169699Skan
15672169699Skan  emit_insn (gen_fpremxf4 (operands[1], operands[2],
15673169699Skan			   operands[1], operands[2]));
15674169699Skan  ix86_emit_fp_unordered_jump (label);
15675169699Skan
15676169699Skan  emit_move_insn (operands[0], operands[1]);
15677169699Skan  DONE;
15678169699Skan})
15679169699Skan
15680169699Skan(define_insn "fprem1xf4"
15681169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15682169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
15683169699Skan		    (match_operand:XF 3 "register_operand" "1")]
15684169699Skan		   UNSPEC_FPREM1_F))
15685169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15686169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
15687169699Skan		   UNSPEC_FPREM1_U))
15688169699Skan   (set (reg:CCFP FPSR_REG)
15689169699Skan	(unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
15690169699Skan  "TARGET_USE_FANCY_MATH_387
15691169699Skan   && flag_unsafe_math_optimizations"
15692169699Skan  "fprem1"
15693169699Skan  [(set_attr "type" "fpspc")
15694169699Skan   (set_attr "mode" "XF")])
15695169699Skan
15696169699Skan(define_expand "dremsf3"
15697169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
15698169699Skan   (use (match_operand:SF 1 "register_operand" ""))
15699169699Skan   (use (match_operand:SF 2 "register_operand" ""))]
15700169699Skan  "TARGET_USE_FANCY_MATH_387
15701169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15702169699Skan   && flag_unsafe_math_optimizations"
15703169699Skan{
15704169699Skan  rtx label = gen_label_rtx ();
15705169699Skan
15706169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15707169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15708169699Skan
15709169699Skan  emit_insn(gen_extendsfxf2 (op1, operands[1]));
15710169699Skan  emit_insn(gen_extendsfxf2 (op2, operands[2]));
15711169699Skan
15712169699Skan  emit_label (label);
15713169699Skan
15714169699Skan  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
15715169699Skan  ix86_emit_fp_unordered_jump (label);
15716169699Skan
15717169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
15718169699Skan  DONE;
15719169699Skan})
15720169699Skan
15721169699Skan(define_expand "dremdf3"
15722169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
15723169699Skan   (use (match_operand:DF 1 "register_operand" ""))
15724169699Skan   (use (match_operand:DF 2 "register_operand" ""))]
15725169699Skan  "TARGET_USE_FANCY_MATH_387
15726169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15727169699Skan   && flag_unsafe_math_optimizations"
15728169699Skan{
15729169699Skan  rtx label = gen_label_rtx ();
15730169699Skan
15731169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15732169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15733169699Skan
15734169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
15735169699Skan  emit_insn (gen_extenddfxf2 (op2, operands[2]));
15736169699Skan
15737169699Skan  emit_label (label);
15738169699Skan
15739169699Skan  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
15740169699Skan  ix86_emit_fp_unordered_jump (label);
15741169699Skan
15742169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
15743169699Skan  DONE;
15744169699Skan})
15745169699Skan
15746169699Skan(define_expand "dremxf3"
15747169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
15748169699Skan   (use (match_operand:XF 1 "register_operand" ""))
15749169699Skan   (use (match_operand:XF 2 "register_operand" ""))]
15750169699Skan  "TARGET_USE_FANCY_MATH_387
15751169699Skan   && flag_unsafe_math_optimizations"
15752169699Skan{
15753169699Skan  rtx label = gen_label_rtx ();
15754169699Skan
15755169699Skan  emit_label (label);
15756169699Skan
15757169699Skan  emit_insn (gen_fprem1xf4 (operands[1], operands[2],
15758169699Skan			    operands[1], operands[2]));
15759169699Skan  ix86_emit_fp_unordered_jump (label);
15760169699Skan
15761169699Skan  emit_move_insn (operands[0], operands[1]);
15762169699Skan  DONE;
15763169699Skan})
15764169699Skan
15765169699Skan(define_insn "*sindf2"
1576690286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
15767117404Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_SIN))]
15768169699Skan  "TARGET_USE_FANCY_MATH_387
15769169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1577090286Sobrien   && flag_unsafe_math_optimizations"
1577190286Sobrien  "fsin"
1577290286Sobrien  [(set_attr "type" "fpspc")
1577390286Sobrien   (set_attr "mode" "DF")])
1577490286Sobrien
15775169699Skan(define_insn "*sinsf2"
1577690286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
15777117404Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_SIN))]
15778169699Skan  "TARGET_USE_FANCY_MATH_387
15779169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
1578090286Sobrien   && flag_unsafe_math_optimizations"
1578190286Sobrien  "fsin"
1578290286Sobrien  [(set_attr "type" "fpspc")
1578390286Sobrien   (set_attr "mode" "SF")])
1578490286Sobrien
1578590286Sobrien(define_insn "*sinextendsfdf2"
1578690286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1578790286Sobrien	(unspec:DF [(float_extend:DF
15788117404Skan		     (match_operand:SF 1 "register_operand" "0"))]
15789117404Skan		   UNSPEC_SIN))]
15790169699Skan  "TARGET_USE_FANCY_MATH_387
15791169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1579290286Sobrien   && flag_unsafe_math_optimizations"
1579390286Sobrien  "fsin"
1579490286Sobrien  [(set_attr "type" "fpspc")
1579590286Sobrien   (set_attr "mode" "DF")])
1579690286Sobrien
15797169699Skan(define_insn "*sinxf2"
1579890286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
15799117404Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_SIN))]
15800169699Skan  "TARGET_USE_FANCY_MATH_387
1580190286Sobrien   && flag_unsafe_math_optimizations"
1580290286Sobrien  "fsin"
1580390286Sobrien  [(set_attr "type" "fpspc")
1580490286Sobrien   (set_attr "mode" "XF")])
1580590286Sobrien
15806169699Skan(define_insn "*cosdf2"
1580790286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
15808117404Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_COS))]
15809169699Skan  "TARGET_USE_FANCY_MATH_387
15810169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1581190286Sobrien   && flag_unsafe_math_optimizations"
1581290286Sobrien  "fcos"
1581390286Sobrien  [(set_attr "type" "fpspc")
1581490286Sobrien   (set_attr "mode" "DF")])
1581590286Sobrien
15816169699Skan(define_insn "*cossf2"
1581790286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
15818117404Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_COS))]
15819169699Skan  "TARGET_USE_FANCY_MATH_387
15820169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
1582190286Sobrien   && flag_unsafe_math_optimizations"
1582290286Sobrien  "fcos"
1582390286Sobrien  [(set_attr "type" "fpspc")
1582490286Sobrien   (set_attr "mode" "SF")])
1582590286Sobrien
1582690286Sobrien(define_insn "*cosextendsfdf2"
1582790286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1582890286Sobrien	(unspec:DF [(float_extend:DF
15829117404Skan		     (match_operand:SF 1 "register_operand" "0"))]
15830117404Skan		   UNSPEC_COS))]
15831169699Skan  "TARGET_USE_FANCY_MATH_387
15832169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1583390286Sobrien   && flag_unsafe_math_optimizations"
1583490286Sobrien  "fcos"
1583590286Sobrien  [(set_attr "type" "fpspc")
1583690286Sobrien   (set_attr "mode" "DF")])
1583790286Sobrien
15838169699Skan(define_insn "*cosxf2"
1583990286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
15840117404Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_COS))]
15841169699Skan  "TARGET_USE_FANCY_MATH_387
1584290286Sobrien   && flag_unsafe_math_optimizations"
1584390286Sobrien  "fcos"
1584490286Sobrien  [(set_attr "type" "fpspc")
1584590286Sobrien   (set_attr "mode" "XF")])
1584690286Sobrien
15847169699Skan;; With sincos pattern defined, sin and cos builtin function will be
15848169699Skan;; expanded to sincos pattern with one of its outputs left unused. 
15849169699Skan;; Cse pass  will detected, if two sincos patterns can be combined,
15850169699Skan;; otherwise sincos pattern will be split back to sin or cos pattern,
15851169699Skan;; depending on the unused output.
15852169699Skan
15853169699Skan(define_insn "sincosdf3"
15854169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
15855169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")]
15856169699Skan		   UNSPEC_SINCOS_COS))
15857169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
15858169699Skan        (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15859169699Skan  "TARGET_USE_FANCY_MATH_387
15860169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15861169699Skan   && flag_unsafe_math_optimizations"
15862169699Skan  "fsincos"
15863169699Skan  [(set_attr "type" "fpspc")
15864169699Skan   (set_attr "mode" "DF")])
15865169699Skan
15866169699Skan(define_split
15867169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15868169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "")]
15869169699Skan		   UNSPEC_SINCOS_COS))
15870169699Skan   (set (match_operand:DF 1 "register_operand" "")
15871169699Skan	(unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15872169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15873169699Skan   && !reload_completed && !reload_in_progress"
15874169699Skan  [(set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_SIN))]
15875169699Skan  "")
15876169699Skan
15877169699Skan(define_split
15878169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15879169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "")]
15880169699Skan		   UNSPEC_SINCOS_COS))
15881169699Skan   (set (match_operand:DF 1 "register_operand" "")
15882169699Skan	(unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15883169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15884169699Skan   && !reload_completed && !reload_in_progress"
15885169699Skan  [(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_COS))]
15886169699Skan  "")
15887169699Skan
15888169699Skan(define_insn "sincossf3"
15889169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
15890169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "0")]
15891169699Skan		   UNSPEC_SINCOS_COS))
15892169699Skan   (set (match_operand:SF 1 "register_operand" "=u")
15893169699Skan        (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15894169699Skan  "TARGET_USE_FANCY_MATH_387
15895169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15896169699Skan   && flag_unsafe_math_optimizations"
15897169699Skan  "fsincos"
15898169699Skan  [(set_attr "type" "fpspc")
15899169699Skan   (set_attr "mode" "SF")])
15900169699Skan
15901169699Skan(define_split
15902169699Skan  [(set (match_operand:SF 0 "register_operand" "")
15903169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "")]
15904169699Skan		   UNSPEC_SINCOS_COS))
15905169699Skan   (set (match_operand:SF 1 "register_operand" "")
15906169699Skan	(unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15907169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15908169699Skan   && !reload_completed && !reload_in_progress"
15909169699Skan  [(set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_SIN))]
15910169699Skan  "")
15911169699Skan
15912169699Skan(define_split
15913169699Skan  [(set (match_operand:SF 0 "register_operand" "")
15914169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "")]
15915169699Skan		   UNSPEC_SINCOS_COS))
15916169699Skan   (set (match_operand:SF 1 "register_operand" "")
15917169699Skan	(unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15918169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15919169699Skan   && !reload_completed && !reload_in_progress"
15920169699Skan  [(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_COS))]
15921169699Skan  "")
15922169699Skan
15923169699Skan(define_insn "*sincosextendsfdf3"
15924169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
15925169699Skan	(unspec:DF [(float_extend:DF
15926169699Skan		     (match_operand:SF 2 "register_operand" "0"))]
15927169699Skan		   UNSPEC_SINCOS_COS))
15928169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
15929169699Skan        (unspec:DF [(float_extend:DF
15930169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
15931169699Skan  "TARGET_USE_FANCY_MATH_387
15932169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15933169699Skan   && flag_unsafe_math_optimizations"
15934169699Skan  "fsincos"
15935169699Skan  [(set_attr "type" "fpspc")
15936169699Skan   (set_attr "mode" "DF")])
15937169699Skan
15938169699Skan(define_split
15939169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15940169699Skan	(unspec:DF [(float_extend:DF
15941169699Skan		     (match_operand:SF 2 "register_operand" ""))]
15942169699Skan		   UNSPEC_SINCOS_COS))
15943169699Skan   (set (match_operand:DF 1 "register_operand" "")
15944169699Skan        (unspec:DF [(float_extend:DF
15945169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
15946169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15947169699Skan   && !reload_completed && !reload_in_progress"
15948169699Skan  [(set (match_dup 1) (unspec:DF [(float_extend:DF
15949169699Skan				   (match_dup 2))] UNSPEC_SIN))]
15950169699Skan  "")
15951169699Skan
15952169699Skan(define_split
15953169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15954169699Skan	(unspec:DF [(float_extend:DF
15955169699Skan		     (match_operand:SF 2 "register_operand" ""))]
15956169699Skan		   UNSPEC_SINCOS_COS))
15957169699Skan   (set (match_operand:DF 1 "register_operand" "")
15958169699Skan        (unspec:DF [(float_extend:DF
15959169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
15960169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15961169699Skan   && !reload_completed && !reload_in_progress"
15962169699Skan  [(set (match_dup 0) (unspec:DF [(float_extend:DF
15963169699Skan				   (match_dup 2))] UNSPEC_COS))]
15964169699Skan  "")
15965169699Skan
15966169699Skan(define_insn "sincosxf3"
15967169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15968169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
15969169699Skan		   UNSPEC_SINCOS_COS))
15970169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15971169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15972169699Skan  "TARGET_USE_FANCY_MATH_387
15973169699Skan   && flag_unsafe_math_optimizations"
15974169699Skan  "fsincos"
15975169699Skan  [(set_attr "type" "fpspc")
15976169699Skan   (set_attr "mode" "XF")])
15977169699Skan
15978169699Skan(define_split
15979169699Skan  [(set (match_operand:XF 0 "register_operand" "")
15980169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "")]
15981169699Skan		   UNSPEC_SINCOS_COS))
15982169699Skan   (set (match_operand:XF 1 "register_operand" "")
15983169699Skan	(unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15984169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15985169699Skan   && !reload_completed && !reload_in_progress"
15986169699Skan  [(set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_SIN))]
15987169699Skan  "")
15988169699Skan
15989169699Skan(define_split
15990169699Skan  [(set (match_operand:XF 0 "register_operand" "")
15991169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "")]
15992169699Skan		   UNSPEC_SINCOS_COS))
15993169699Skan   (set (match_operand:XF 1 "register_operand" "")
15994169699Skan	(unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15995169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15996169699Skan   && !reload_completed && !reload_in_progress"
15997169699Skan  [(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_COS))]
15998169699Skan  "")
15999169699Skan
16000169699Skan(define_insn "*tandf3_1"
16001169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
16002169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")]
16003169699Skan		   UNSPEC_TAN_ONE))
16004169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
16005169699Skan        (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))]
16006169699Skan  "TARGET_USE_FANCY_MATH_387
16007169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16008169699Skan   && flag_unsafe_math_optimizations"
16009169699Skan  "fptan"
16010169699Skan  [(set_attr "type" "fpspc")
16011169699Skan   (set_attr "mode" "DF")])
16012169699Skan
16013169699Skan;; optimize sequence: fptan
16014169699Skan;;		      fstp    %st(0)
16015169699Skan;;		      fld1
16016169699Skan;; into fptan insn.
16017169699Skan
16018169699Skan(define_peephole2
16019169699Skan  [(parallel[(set (match_operand:DF 0 "register_operand" "")
16020169699Skan		  (unspec:DF [(match_operand:DF 2 "register_operand" "")]
16021169699Skan			     UNSPEC_TAN_ONE))
16022169699Skan	     (set (match_operand:DF 1 "register_operand" "")
16023169699Skan		  (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])
16024169699Skan   (set (match_dup 0)
16025169699Skan        (match_operand:DF 3 "immediate_operand" ""))]
16026169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16027169699Skan  [(parallel[(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_TAN_ONE))
16028169699Skan   	     (set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16029169699Skan  "")
16030169699Skan
16031169699Skan(define_expand "tandf2"
16032169699Skan  [(parallel [(set (match_dup 2)
16033169699Skan		   (unspec:DF [(match_operand:DF 1 "register_operand" "")]
16034169699Skan			      UNSPEC_TAN_ONE))
16035169699Skan	      (set (match_operand:DF 0 "register_operand" "")
16036169699Skan		   (unspec:DF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16037169699Skan  "TARGET_USE_FANCY_MATH_387
16038169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16039169699Skan   && flag_unsafe_math_optimizations"
16040169699Skan{
16041169699Skan  operands[2] = gen_reg_rtx (DFmode);
16042169699Skan})
16043169699Skan
16044169699Skan(define_insn "*tansf3_1"
16045169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
16046169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "0")]
16047169699Skan		   UNSPEC_TAN_ONE))
16048169699Skan   (set (match_operand:SF 1 "register_operand" "=u")
16049169699Skan        (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))]
16050169699Skan  "TARGET_USE_FANCY_MATH_387
16051169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16052169699Skan   && flag_unsafe_math_optimizations"
16053169699Skan  "fptan"
16054169699Skan  [(set_attr "type" "fpspc")
16055169699Skan   (set_attr "mode" "SF")])
16056169699Skan
16057169699Skan;; optimize sequence: fptan
16058169699Skan;;		      fstp    %st(0)
16059169699Skan;;		      fld1
16060169699Skan;; into fptan insn.
16061169699Skan
16062169699Skan(define_peephole2
16063169699Skan  [(parallel[(set (match_operand:SF 0 "register_operand" "")
16064169699Skan		  (unspec:SF [(match_operand:SF 2 "register_operand" "")]
16065169699Skan			     UNSPEC_TAN_ONE))
16066169699Skan	     (set (match_operand:SF 1 "register_operand" "")
16067169699Skan		  (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])
16068169699Skan   (set (match_dup 0)
16069169699Skan        (match_operand:SF 3 "immediate_operand" ""))]
16070169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16071169699Skan  [(parallel[(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_TAN_ONE))
16072169699Skan   	     (set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16073169699Skan  "")
16074169699Skan
16075169699Skan(define_expand "tansf2"
16076169699Skan  [(parallel [(set (match_dup 2)
16077169699Skan		   (unspec:SF [(match_operand:SF 1 "register_operand" "")]
16078169699Skan			      UNSPEC_TAN_ONE))
16079169699Skan	      (set (match_operand:SF 0 "register_operand" "")
16080169699Skan		   (unspec:SF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16081169699Skan  "TARGET_USE_FANCY_MATH_387
16082169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16083169699Skan   && flag_unsafe_math_optimizations"
16084169699Skan{
16085169699Skan  operands[2] = gen_reg_rtx (SFmode);
16086169699Skan})
16087169699Skan
16088169699Skan(define_insn "*tanxf3_1"
16089169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16090169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
16091169699Skan		   UNSPEC_TAN_ONE))
16092169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16093169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))]
16094169699Skan  "TARGET_USE_FANCY_MATH_387
16095169699Skan   && flag_unsafe_math_optimizations"
16096169699Skan  "fptan"
16097169699Skan  [(set_attr "type" "fpspc")
16098169699Skan   (set_attr "mode" "XF")])
16099169699Skan
16100169699Skan;; optimize sequence: fptan
16101169699Skan;;		      fstp    %st(0)
16102169699Skan;;		      fld1
16103169699Skan;; into fptan insn.
16104169699Skan
16105169699Skan(define_peephole2
16106169699Skan  [(parallel[(set (match_operand:XF 0 "register_operand" "")
16107169699Skan		  (unspec:XF [(match_operand:XF 2 "register_operand" "")]
16108169699Skan			     UNSPEC_TAN_ONE))
16109169699Skan	     (set (match_operand:XF 1 "register_operand" "")
16110169699Skan		  (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])
16111169699Skan   (set (match_dup 0)
16112169699Skan        (match_operand:XF 3 "immediate_operand" ""))]
16113169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16114169699Skan  [(parallel[(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_TAN_ONE))
16115169699Skan   	     (set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16116169699Skan  "")
16117169699Skan
16118169699Skan(define_expand "tanxf2"
16119169699Skan  [(parallel [(set (match_dup 2)
16120169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16121169699Skan			      UNSPEC_TAN_ONE))
16122169699Skan	      (set (match_operand:XF 0 "register_operand" "")
16123169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16124169699Skan  "TARGET_USE_FANCY_MATH_387
16125169699Skan   && flag_unsafe_math_optimizations"
16126169699Skan{
16127169699Skan  operands[2] = gen_reg_rtx (XFmode);
16128169699Skan})
16129169699Skan
16130132727Skan(define_insn "atan2df3_1"
16131132727Skan  [(set (match_operand:DF 0 "register_operand" "=f")
16132132727Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")
16133132727Skan		    (match_operand:DF 1 "register_operand" "u")]
16134132727Skan		   UNSPEC_FPATAN))
16135132727Skan   (clobber (match_scratch:DF 3 "=1"))]
16136169699Skan  "TARGET_USE_FANCY_MATH_387
16137169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1613890286Sobrien   && flag_unsafe_math_optimizations"
16139132727Skan  "fpatan"
1614090286Sobrien  [(set_attr "type" "fpspc")
16141132727Skan   (set_attr "mode" "DF")])
16142132727Skan
16143132727Skan(define_expand "atan2df3"
16144169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
16145169699Skan   (use (match_operand:DF 2 "register_operand" ""))
16146169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
16147169699Skan  "TARGET_USE_FANCY_MATH_387
16148169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16149132727Skan   && flag_unsafe_math_optimizations"
16150132727Skan{
16151132727Skan  rtx copy = gen_reg_rtx (DFmode);
16152132727Skan  emit_move_insn (copy, operands[1]);
16153132727Skan  emit_insn (gen_atan2df3_1 (operands[0], copy, operands[2]));
16154132727Skan  DONE;
16155132727Skan})
16156132727Skan
16157169699Skan(define_expand "atandf2"
16158169699Skan  [(parallel [(set (match_operand:DF 0 "register_operand" "")
16159169699Skan		   (unspec:DF [(match_dup 2)
16160169699Skan			       (match_operand:DF 1 "register_operand" "")]
16161169699Skan		    UNSPEC_FPATAN))
16162169699Skan	      (clobber (match_scratch:DF 3 ""))])]
16163169699Skan  "TARGET_USE_FANCY_MATH_387
16164169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16165169699Skan   && flag_unsafe_math_optimizations"
16166169699Skan{
16167169699Skan  operands[2] = gen_reg_rtx (DFmode);
16168169699Skan  emit_move_insn (operands[2], CONST1_RTX (DFmode));  /* fld1 */
16169169699Skan})
16170169699Skan
16171132727Skan(define_insn "atan2sf3_1"
16172132727Skan  [(set (match_operand:SF 0 "register_operand" "=f")
16173132727Skan        (unspec:SF [(match_operand:SF 2 "register_operand" "0")
16174132727Skan		    (match_operand:SF 1 "register_operand" "u")]
16175132727Skan		   UNSPEC_FPATAN))
16176132727Skan   (clobber (match_scratch:SF 3 "=1"))]
16177169699Skan  "TARGET_USE_FANCY_MATH_387
16178169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16179132727Skan   && flag_unsafe_math_optimizations"
16180132727Skan  "fpatan"
16181132727Skan  [(set_attr "type" "fpspc")
16182132727Skan   (set_attr "mode" "SF")])
16183132727Skan
16184132727Skan(define_expand "atan2sf3"
16185169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
16186169699Skan   (use (match_operand:SF 2 "register_operand" ""))
16187169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
16188169699Skan  "TARGET_USE_FANCY_MATH_387
16189169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16190132727Skan   && flag_unsafe_math_optimizations"
16191132727Skan{
16192132727Skan  rtx copy = gen_reg_rtx (SFmode);
16193132727Skan  emit_move_insn (copy, operands[1]);
16194132727Skan  emit_insn (gen_atan2sf3_1 (operands[0], copy, operands[2]));
16195132727Skan  DONE;
16196132727Skan})
16197132727Skan
16198169699Skan(define_expand "atansf2"
16199169699Skan  [(parallel [(set (match_operand:SF 0 "register_operand" "")
16200169699Skan		   (unspec:SF [(match_dup 2)
16201169699Skan			       (match_operand:SF 1 "register_operand" "")]
16202169699Skan		    UNSPEC_FPATAN))
16203169699Skan	      (clobber (match_scratch:SF 3 ""))])]
16204169699Skan  "TARGET_USE_FANCY_MATH_387
16205169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16206169699Skan   && flag_unsafe_math_optimizations"
16207169699Skan{
16208169699Skan  operands[2] = gen_reg_rtx (SFmode);
16209169699Skan  emit_move_insn (operands[2], CONST1_RTX (SFmode));  /* fld1 */
16210169699Skan})
16211169699Skan
16212132727Skan(define_insn "atan2xf3_1"
16213132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16214132727Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16215132727Skan	            (match_operand:XF 1 "register_operand" "u")]
16216132727Skan	           UNSPEC_FPATAN))
16217132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16218169699Skan  "TARGET_USE_FANCY_MATH_387
16219132727Skan   && flag_unsafe_math_optimizations"
16220132727Skan  "fpatan"
16221132727Skan  [(set_attr "type" "fpspc")
1622290286Sobrien   (set_attr "mode" "XF")])
16223132727Skan
16224132727Skan(define_expand "atan2xf3"
16225169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
16226169699Skan   (use (match_operand:XF 2 "register_operand" ""))
16227169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
16228169699Skan  "TARGET_USE_FANCY_MATH_387
16229132727Skan   && flag_unsafe_math_optimizations"
16230132727Skan{
16231132727Skan  rtx copy = gen_reg_rtx (XFmode);
16232132727Skan  emit_move_insn (copy, operands[1]);
16233132727Skan  emit_insn (gen_atan2xf3_1 (operands[0], copy, operands[2]));
16234132727Skan  DONE;
16235132727Skan})
16236132727Skan
16237169699Skan(define_expand "atanxf2"
16238169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16239169699Skan		   (unspec:XF [(match_dup 2)
16240169699Skan			       (match_operand:XF 1 "register_operand" "")]
16241169699Skan		    UNSPEC_FPATAN))
16242169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16243169699Skan  "TARGET_USE_FANCY_MATH_387
16244132727Skan   && flag_unsafe_math_optimizations"
16245169699Skan{
16246169699Skan  operands[2] = gen_reg_rtx (XFmode);
16247169699Skan  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
16248169699Skan})
16249132727Skan
16250169699Skan(define_expand "asindf2"
16251169699Skan  [(set (match_dup 2)
16252169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16253169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16254169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16255169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16256169699Skan   (parallel [(set (match_dup 7)
16257169699Skan        	   (unspec:XF [(match_dup 6) (match_dup 2)]
16258169699Skan			      UNSPEC_FPATAN))
16259169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16260169699Skan   (set (match_operand:DF 0 "register_operand" "")
16261169699Skan	(float_truncate:DF (match_dup 7)))]
16262169699Skan  "TARGET_USE_FANCY_MATH_387
16263169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16264132727Skan   && flag_unsafe_math_optimizations"
16265169699Skan{
16266169699Skan  int i;
16267132727Skan
16268169699Skan  for (i=2; i<8; i++)
16269169699Skan    operands[i] = gen_reg_rtx (XFmode);
16270169699Skan
16271169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16272169699Skan})
16273169699Skan
16274169699Skan(define_expand "asinsf2"
16275169699Skan  [(set (match_dup 2)
16276169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16277169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16278169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16279169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16280169699Skan   (parallel [(set (match_dup 7)
16281169699Skan        	   (unspec:XF [(match_dup 6) (match_dup 2)]
16282169699Skan			      UNSPEC_FPATAN))
16283169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16284169699Skan   (set (match_operand:SF 0 "register_operand" "")
16285169699Skan	(float_truncate:SF (match_dup 7)))]
16286169699Skan  "TARGET_USE_FANCY_MATH_387
16287169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16288169699Skan   && flag_unsafe_math_optimizations"
16289169699Skan{
16290169699Skan  int i;
16291169699Skan
16292169699Skan  for (i=2; i<8; i++)
16293169699Skan    operands[i] = gen_reg_rtx (XFmode);
16294169699Skan
16295169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16296169699Skan})
16297169699Skan
16298169699Skan(define_expand "asinxf2"
16299169699Skan  [(set (match_dup 2)
16300169699Skan	(mult:XF (match_operand:XF 1 "register_operand" "")
16301169699Skan		 (match_dup 1)))
16302169699Skan   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
16303169699Skan   (set (match_dup 5) (sqrt:XF (match_dup 4)))
16304169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16305169699Skan        	   (unspec:XF [(match_dup 5) (match_dup 1)]
16306169699Skan			      UNSPEC_FPATAN))
16307169699Skan   	      (clobber (match_scratch:XF 6 ""))])]
16308169699Skan  "TARGET_USE_FANCY_MATH_387
16309169699Skan   && flag_unsafe_math_optimizations"
16310169699Skan{
16311169699Skan  int i;
16312169699Skan
16313169699Skan  for (i=2; i<6; i++)
16314169699Skan    operands[i] = gen_reg_rtx (XFmode);
16315169699Skan
16316169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16317169699Skan})
16318169699Skan
16319169699Skan(define_expand "acosdf2"
16320169699Skan  [(set (match_dup 2)
16321169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16322169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16323169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16324169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16325169699Skan   (parallel [(set (match_dup 7)
16326169699Skan        	   (unspec:XF [(match_dup 2) (match_dup 6)]
16327169699Skan			      UNSPEC_FPATAN))
16328169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16329169699Skan   (set (match_operand:DF 0 "register_operand" "")
16330169699Skan	(float_truncate:DF (match_dup 7)))]
16331169699Skan  "TARGET_USE_FANCY_MATH_387
16332169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16333169699Skan   && flag_unsafe_math_optimizations"
16334169699Skan{
16335169699Skan  int i;
16336169699Skan
16337169699Skan  for (i=2; i<8; i++)
16338169699Skan    operands[i] = gen_reg_rtx (XFmode);
16339169699Skan
16340169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16341169699Skan})
16342169699Skan
16343169699Skan(define_expand "acossf2"
16344169699Skan  [(set (match_dup 2)
16345169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16346169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16347169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16348169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16349169699Skan   (parallel [(set (match_dup 7)
16350169699Skan        	   (unspec:XF [(match_dup 2) (match_dup 6)]
16351169699Skan			      UNSPEC_FPATAN))
16352169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16353169699Skan   (set (match_operand:SF 0 "register_operand" "")
16354169699Skan	(float_truncate:SF (match_dup 7)))]
16355169699Skan  "TARGET_USE_FANCY_MATH_387
16356169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16357169699Skan   && flag_unsafe_math_optimizations"
16358169699Skan{
16359169699Skan  int i;
16360169699Skan
16361169699Skan  for (i=2; i<8; i++)
16362169699Skan    operands[i] = gen_reg_rtx (XFmode);
16363169699Skan
16364169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16365169699Skan})
16366169699Skan
16367169699Skan(define_expand "acosxf2"
16368169699Skan  [(set (match_dup 2)
16369169699Skan	(mult:XF (match_operand:XF 1 "register_operand" "")
16370169699Skan		 (match_dup 1)))
16371169699Skan   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
16372169699Skan   (set (match_dup 5) (sqrt:XF (match_dup 4)))
16373169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16374169699Skan        	   (unspec:XF [(match_dup 1) (match_dup 5)]
16375169699Skan			      UNSPEC_FPATAN))
16376169699Skan   	      (clobber (match_scratch:XF 6 ""))])]
16377169699Skan  "TARGET_USE_FANCY_MATH_387
16378169699Skan   && flag_unsafe_math_optimizations"
16379169699Skan{
16380169699Skan  int i;
16381169699Skan
16382169699Skan  for (i=2; i<6; i++)
16383169699Skan    operands[i] = gen_reg_rtx (XFmode);
16384169699Skan
16385169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16386169699Skan})
16387169699Skan
16388169699Skan(define_insn "fyl2x_xf3"
16389132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16390132727Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16391132727Skan		    (match_operand:XF 1 "register_operand" "u")]
16392132727Skan	           UNSPEC_FYL2X))
16393132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16394169699Skan  "TARGET_USE_FANCY_MATH_387
16395132727Skan   && flag_unsafe_math_optimizations"
16396132727Skan  "fyl2x"
16397132727Skan  [(set_attr "type" "fpspc")
16398132727Skan   (set_attr "mode" "XF")])
16399132727Skan
16400132727Skan(define_expand "logsf2"
16401169699Skan  [(set (match_dup 2)
16402169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16403169699Skan   (parallel [(set (match_dup 4)
16404169699Skan		   (unspec:XF [(match_dup 2)
16405169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16406169699Skan	      (clobber (match_scratch:XF 5 ""))])
16407169699Skan   (set (match_operand:SF 0 "register_operand" "")
16408169699Skan	(float_truncate:SF (match_dup 4)))]
16409169699Skan  "TARGET_USE_FANCY_MATH_387
16410169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16411132727Skan   && flag_unsafe_math_optimizations"
16412132727Skan{
16413132727Skan  rtx temp;
16414132727Skan
16415132727Skan  operands[2] = gen_reg_rtx (XFmode);
16416169699Skan  operands[3] = gen_reg_rtx (XFmode);
16417169699Skan  operands[4] = gen_reg_rtx (XFmode);
16418169699Skan
16419132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16420169699Skan  emit_move_insn (operands[3], temp);
16421132727Skan})
16422132727Skan
16423132727Skan(define_expand "logdf2"
16424169699Skan  [(set (match_dup 2)
16425169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16426169699Skan   (parallel [(set (match_dup 4)
16427169699Skan		   (unspec:XF [(match_dup 2)
16428169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16429169699Skan	      (clobber (match_scratch:XF 5 ""))])
16430169699Skan   (set (match_operand:DF 0 "register_operand" "")
16431169699Skan	(float_truncate:DF (match_dup 4)))]
16432169699Skan  "TARGET_USE_FANCY_MATH_387
16433169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16434132727Skan   && flag_unsafe_math_optimizations"
16435132727Skan{
16436132727Skan  rtx temp;
16437132727Skan
16438132727Skan  operands[2] = gen_reg_rtx (XFmode);
16439169699Skan  operands[3] = gen_reg_rtx (XFmode);
16440169699Skan  operands[4] = gen_reg_rtx (XFmode);
16441169699Skan
16442132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16443169699Skan  emit_move_insn (operands[3], temp);
16444132727Skan})
16445132727Skan
16446132727Skan(define_expand "logxf2"
16447132727Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16448132727Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16449132727Skan			       (match_dup 2)] UNSPEC_FYL2X))
16450132727Skan	      (clobber (match_scratch:XF 3 ""))])]
16451169699Skan  "TARGET_USE_FANCY_MATH_387
16452132727Skan   && flag_unsafe_math_optimizations"
16453132727Skan{
16454132727Skan  rtx temp;
16455132727Skan
16456132727Skan  operands[2] = gen_reg_rtx (XFmode);
16457132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16458132727Skan  emit_move_insn (operands[2], temp);
16459132727Skan})
16460132727Skan
16461169699Skan(define_expand "log10sf2"
16462169699Skan  [(set (match_dup 2)
16463169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16464169699Skan   (parallel [(set (match_dup 4)
16465169699Skan		   (unspec:XF [(match_dup 2)
16466169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16467169699Skan	      (clobber (match_scratch:XF 5 ""))])
16468169699Skan   (set (match_operand:SF 0 "register_operand" "")
16469169699Skan	(float_truncate:SF (match_dup 4)))]
16470169699Skan  "TARGET_USE_FANCY_MATH_387
16471169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16472132727Skan   && flag_unsafe_math_optimizations"
16473169699Skan{
16474169699Skan  rtx temp;
16475132727Skan
16476169699Skan  operands[2] = gen_reg_rtx (XFmode);
16477169699Skan  operands[3] = gen_reg_rtx (XFmode);
16478169699Skan  operands[4] = gen_reg_rtx (XFmode);
16479169699Skan
16480169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16481169699Skan  emit_move_insn (operands[3], temp);
16482169699Skan})
16483169699Skan
16484169699Skan(define_expand "log10df2"
16485169699Skan  [(set (match_dup 2)
16486169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16487169699Skan   (parallel [(set (match_dup 4)
16488169699Skan		   (unspec:XF [(match_dup 2)
16489169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16490169699Skan	      (clobber (match_scratch:XF 5 ""))])
16491169699Skan   (set (match_operand:DF 0 "register_operand" "")
16492169699Skan	(float_truncate:DF (match_dup 4)))]
16493169699Skan  "TARGET_USE_FANCY_MATH_387
16494169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16495132727Skan   && flag_unsafe_math_optimizations"
16496169699Skan{
16497169699Skan  rtx temp;
16498132727Skan
16499169699Skan  operands[2] = gen_reg_rtx (XFmode);
16500169699Skan  operands[3] = gen_reg_rtx (XFmode);
16501169699Skan  operands[4] = gen_reg_rtx (XFmode);
16502169699Skan
16503169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16504169699Skan  emit_move_insn (operands[3], temp);
16505169699Skan})
16506169699Skan
16507169699Skan(define_expand "log10xf2"
16508169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16509169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16510169699Skan			       (match_dup 2)] UNSPEC_FYL2X))
16511169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16512169699Skan  "TARGET_USE_FANCY_MATH_387
16513169699Skan   && flag_unsafe_math_optimizations"
16514169699Skan{
16515169699Skan  rtx temp;
16516169699Skan
16517169699Skan  operands[2] = gen_reg_rtx (XFmode);
16518169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16519169699Skan  emit_move_insn (operands[2], temp);
16520169699Skan})
16521169699Skan
16522169699Skan(define_expand "log2sf2"
16523169699Skan  [(set (match_dup 2)
16524169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16525169699Skan   (parallel [(set (match_dup 4)
16526169699Skan		   (unspec:XF [(match_dup 2)
16527169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16528169699Skan	      (clobber (match_scratch:XF 5 ""))])
16529169699Skan   (set (match_operand:SF 0 "register_operand" "")
16530169699Skan	(float_truncate:SF (match_dup 4)))]
16531169699Skan  "TARGET_USE_FANCY_MATH_387
16532169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16533169699Skan   && flag_unsafe_math_optimizations"
16534169699Skan{
16535169699Skan  operands[2] = gen_reg_rtx (XFmode);
16536169699Skan  operands[3] = gen_reg_rtx (XFmode);
16537169699Skan  operands[4] = gen_reg_rtx (XFmode);
16538169699Skan
16539169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16540169699Skan})
16541169699Skan
16542169699Skan(define_expand "log2df2"
16543169699Skan  [(set (match_dup 2)
16544169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16545169699Skan   (parallel [(set (match_dup 4)
16546169699Skan		   (unspec:XF [(match_dup 2)
16547169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16548169699Skan	      (clobber (match_scratch:XF 5 ""))])
16549169699Skan   (set (match_operand:DF 0 "register_operand" "")
16550169699Skan	(float_truncate:DF (match_dup 4)))]
16551169699Skan  "TARGET_USE_FANCY_MATH_387
16552169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16553169699Skan   && flag_unsafe_math_optimizations"
16554169699Skan{
16555169699Skan  operands[2] = gen_reg_rtx (XFmode);
16556169699Skan  operands[3] = gen_reg_rtx (XFmode);
16557169699Skan  operands[4] = gen_reg_rtx (XFmode);
16558169699Skan
16559169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16560169699Skan})
16561169699Skan
16562169699Skan(define_expand "log2xf2"
16563169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16564169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16565169699Skan			       (match_dup 2)] UNSPEC_FYL2X))
16566169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16567169699Skan  "TARGET_USE_FANCY_MATH_387
16568169699Skan   && flag_unsafe_math_optimizations"
16569169699Skan{
16570169699Skan  operands[2] = gen_reg_rtx (XFmode);
16571169699Skan  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
16572169699Skan})
16573169699Skan
16574169699Skan(define_insn "fyl2xp1_xf3"
16575132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16576169699Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16577132727Skan		    (match_operand:XF 1 "register_operand" "u")]
16578169699Skan	           UNSPEC_FYL2XP1))
16579132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16580169699Skan  "TARGET_USE_FANCY_MATH_387
16581132727Skan   && flag_unsafe_math_optimizations"
16582169699Skan  "fyl2xp1"
16583132727Skan  [(set_attr "type" "fpspc")
16584132727Skan   (set_attr "mode" "XF")])
16585132727Skan
16586169699Skan(define_expand "log1psf2"
16587169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
16588169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
16589169699Skan  "TARGET_USE_FANCY_MATH_387
16590169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16591169699Skan   && flag_unsafe_math_optimizations"
16592169699Skan{
16593169699Skan  rtx op0 = gen_reg_rtx (XFmode);
16594169699Skan  rtx op1 = gen_reg_rtx (XFmode);
16595169699Skan
16596169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
16597169699Skan  ix86_emit_i387_log1p (op0, op1);
16598169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
16599169699Skan  DONE;
16600169699Skan})
16601169699Skan
16602169699Skan(define_expand "log1pdf2"
16603169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
16604169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
16605169699Skan  "TARGET_USE_FANCY_MATH_387
16606169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16607169699Skan   && flag_unsafe_math_optimizations"
16608169699Skan{
16609169699Skan  rtx op0 = gen_reg_rtx (XFmode);
16610169699Skan  rtx op1 = gen_reg_rtx (XFmode);
16611169699Skan
16612169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
16613169699Skan  ix86_emit_i387_log1p (op0, op1);
16614169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
16615169699Skan  DONE;
16616169699Skan})
16617169699Skan
16618169699Skan(define_expand "log1pxf2"
16619169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
16620169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
16621169699Skan  "TARGET_USE_FANCY_MATH_387
16622169699Skan   && flag_unsafe_math_optimizations"
16623169699Skan{
16624169699Skan  ix86_emit_i387_log1p (operands[0], operands[1]);
16625169699Skan  DONE;
16626169699Skan})
16627169699Skan
16628169699Skan(define_insn "*fxtractxf3"
16629132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16630169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
16631169699Skan		   UNSPEC_XTRACT_FRACT))
16632169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16633169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))]
16634169699Skan  "TARGET_USE_FANCY_MATH_387
16635132727Skan   && flag_unsafe_math_optimizations"
16636169699Skan  "fxtract"
16637132727Skan  [(set_attr "type" "fpspc")
16638132727Skan   (set_attr "mode" "XF")])
16639132727Skan
16640169699Skan(define_expand "logbsf2"
16641169699Skan  [(set (match_dup 2)
16642169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16643169699Skan   (parallel [(set (match_dup 3)
16644169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
16645169699Skan	      (set (match_dup 4)
16646169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
16647169699Skan   (set (match_operand:SF 0 "register_operand" "")
16648169699Skan	(float_truncate:SF (match_dup 4)))]
16649169699Skan  "TARGET_USE_FANCY_MATH_387
16650169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16651169699Skan   && flag_unsafe_math_optimizations"
16652169699Skan{
16653169699Skan  operands[2] = gen_reg_rtx (XFmode);
16654169699Skan  operands[3] = gen_reg_rtx (XFmode);
16655169699Skan  operands[4] = gen_reg_rtx (XFmode);
16656169699Skan})
16657169699Skan
16658169699Skan(define_expand "logbdf2"
16659169699Skan  [(set (match_dup 2)
16660169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16661169699Skan   (parallel [(set (match_dup 3)
16662169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
16663169699Skan	      (set (match_dup 4)
16664169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
16665169699Skan   (set (match_operand:DF 0 "register_operand" "")
16666169699Skan	(float_truncate:DF (match_dup 4)))]
16667169699Skan  "TARGET_USE_FANCY_MATH_387
16668169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16669169699Skan   && flag_unsafe_math_optimizations"
16670169699Skan{
16671169699Skan  operands[2] = gen_reg_rtx (XFmode);
16672169699Skan  operands[3] = gen_reg_rtx (XFmode);
16673169699Skan  operands[4] = gen_reg_rtx (XFmode);
16674169699Skan})
16675169699Skan
16676169699Skan(define_expand "logbxf2"
16677169699Skan  [(parallel [(set (match_dup 2)
16678169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16679169699Skan			      UNSPEC_XTRACT_FRACT))
16680169699Skan	      (set (match_operand:XF 0 "register_operand" "")
16681169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])]
16682169699Skan  "TARGET_USE_FANCY_MATH_387
16683169699Skan   && flag_unsafe_math_optimizations"
16684169699Skan{
16685169699Skan  operands[2] = gen_reg_rtx (XFmode);
16686169699Skan})
16687169699Skan
16688169699Skan(define_expand "ilogbsi2"
16689169699Skan  [(parallel [(set (match_dup 2)
16690169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16691169699Skan			      UNSPEC_XTRACT_FRACT))
16692169699Skan	      (set (match_operand:XF 3 "register_operand" "")
16693169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])
16694169699Skan   (parallel [(set (match_operand:SI 0 "register_operand" "")
16695169699Skan	           (fix:SI (match_dup 3)))
16696169699Skan	      (clobber (reg:CC FLAGS_REG))])]
16697169699Skan  "TARGET_USE_FANCY_MATH_387
16698169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16699169699Skan   && flag_unsafe_math_optimizations"
16700169699Skan{
16701169699Skan  operands[2] = gen_reg_rtx (XFmode);
16702169699Skan  operands[3] = gen_reg_rtx (XFmode);
16703169699Skan})
16704169699Skan
16705132727Skan(define_insn "*f2xm1xf2"
16706132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16707132727Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
16708132727Skan	 UNSPEC_F2XM1))]
16709169699Skan  "TARGET_USE_FANCY_MATH_387
16710132727Skan   && flag_unsafe_math_optimizations"
16711132727Skan  "f2xm1"
16712132727Skan  [(set_attr "type" "fpspc")
16713132727Skan   (set_attr "mode" "XF")])
16714132727Skan
16715169699Skan(define_insn "*fscalexf4"
16716169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16717169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
16718169699Skan		    (match_operand:XF 3 "register_operand" "1")]
16719169699Skan		   UNSPEC_FSCALE_FRACT))
16720169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16721169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
16722169699Skan		   UNSPEC_FSCALE_EXP))]
16723169699Skan  "TARGET_USE_FANCY_MATH_387
16724169699Skan   && flag_unsafe_math_optimizations"
16725169699Skan  "fscale"
16726169699Skan  [(set_attr "type" "fpspc")
16727169699Skan   (set_attr "mode" "XF")])
16728169699Skan
16729132727Skan(define_expand "expsf2"
16730132727Skan  [(set (match_dup 2)
16731132727Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16732132727Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16733132727Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16734132727Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16735132727Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16736132727Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16737169699Skan   (parallel [(set (match_dup 10)
16738169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16739169699Skan			      UNSPEC_FSCALE_FRACT))
16740169699Skan	      (set (match_dup 11)
16741169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16742169699Skan			      UNSPEC_FSCALE_EXP))])
16743169699Skan   (set (match_operand:SF 0 "register_operand" "")
16744169699Skan	(float_truncate:SF (match_dup 10)))]
16745169699Skan  "TARGET_USE_FANCY_MATH_387
16746169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16747132727Skan   && flag_unsafe_math_optimizations"
16748132727Skan{
16749132727Skan  rtx temp;
16750132727Skan  int i;
16751132727Skan
16752169699Skan  for (i=2; i<12; i++)
16753132727Skan    operands[i] = gen_reg_rtx (XFmode);
16754132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
16755132727Skan  emit_move_insn (operands[3], temp);
16756132727Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16757132727Skan})
16758132727Skan
16759132727Skan(define_expand "expdf2"
16760132727Skan  [(set (match_dup 2)
16761132727Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16762132727Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16763132727Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16764132727Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16765132727Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16766132727Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16767169699Skan   (parallel [(set (match_dup 10)
16768169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16769169699Skan			      UNSPEC_FSCALE_FRACT))
16770169699Skan	      (set (match_dup 11)
16771169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16772169699Skan			      UNSPEC_FSCALE_EXP))])
16773169699Skan   (set (match_operand:DF 0 "register_operand" "")
16774169699Skan	(float_truncate:DF (match_dup 10)))]
16775169699Skan  "TARGET_USE_FANCY_MATH_387
16776169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16777132727Skan   && flag_unsafe_math_optimizations"
16778132727Skan{
16779132727Skan  rtx temp;
16780132727Skan  int i;
16781132727Skan
16782169699Skan  for (i=2; i<12; i++)
16783132727Skan    operands[i] = gen_reg_rtx (XFmode);
16784132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
16785132727Skan  emit_move_insn (operands[3], temp);
16786132727Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16787132727Skan})
16788132727Skan
16789132727Skan(define_expand "expxf2"
16790132727Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
16791132727Skan			       (match_dup 2)))
16792132727Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
16793132727Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
16794132727Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
16795132727Skan   (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
16796132727Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16797169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16798169699Skan			      UNSPEC_FSCALE_FRACT))
16799169699Skan	      (set (match_dup 9)
16800169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16801169699Skan			      UNSPEC_FSCALE_EXP))])]
16802169699Skan  "TARGET_USE_FANCY_MATH_387
16803132727Skan   && flag_unsafe_math_optimizations"
16804132727Skan{
16805132727Skan  rtx temp;
16806132727Skan  int i;
16807132727Skan
16808169699Skan  for (i=2; i<10; i++)
16809132727Skan    operands[i] = gen_reg_rtx (XFmode);
16810132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
16811132727Skan  emit_move_insn (operands[2], temp);
16812132727Skan  emit_move_insn (operands[7], CONST1_RTX (XFmode));  /* fld1 */
16813132727Skan})
16814132727Skan
16815169699Skan(define_expand "exp10sf2"
16816169699Skan  [(set (match_dup 2)
16817169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16818169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16819169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16820169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16821169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16822169699Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16823169699Skan   (parallel [(set (match_dup 10)
16824169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16825169699Skan			      UNSPEC_FSCALE_FRACT))
16826169699Skan	      (set (match_dup 11)
16827169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16828169699Skan			      UNSPEC_FSCALE_EXP))])
16829169699Skan   (set (match_operand:SF 0 "register_operand" "")
16830169699Skan	(float_truncate:SF (match_dup 10)))]
16831169699Skan  "TARGET_USE_FANCY_MATH_387
16832169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16833132727Skan   && flag_unsafe_math_optimizations"
16834132727Skan{
16835169699Skan  rtx temp;
16836169699Skan  int i;
16837169699Skan
16838169699Skan  for (i=2; i<12; i++)
16839169699Skan    operands[i] = gen_reg_rtx (XFmode);
16840169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
16841169699Skan  emit_move_insn (operands[3], temp);
16842169699Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16843132727Skan})
16844132727Skan
16845169699Skan(define_expand "exp10df2"
16846169699Skan  [(set (match_dup 2)
16847169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16848169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16849169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16850169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16851169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16852169699Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16853169699Skan   (parallel [(set (match_dup 10)
16854169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16855169699Skan			      UNSPEC_FSCALE_FRACT))
16856169699Skan	      (set (match_dup 11)
16857169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16858169699Skan			      UNSPEC_FSCALE_EXP))])
16859169699Skan   (set (match_operand:DF 0 "register_operand" "")
16860169699Skan	(float_truncate:DF (match_dup 10)))]
16861169699Skan  "TARGET_USE_FANCY_MATH_387
16862169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16863132727Skan   && flag_unsafe_math_optimizations"
16864132727Skan{
16865169699Skan  rtx temp;
16866169699Skan  int i;
16867169699Skan
16868169699Skan  for (i=2; i<12; i++)
16869169699Skan    operands[i] = gen_reg_rtx (XFmode);
16870169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
16871169699Skan  emit_move_insn (operands[3], temp);
16872169699Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16873132727Skan})
16874132727Skan
16875169699Skan(define_expand "exp10xf2"
16876169699Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
16877169699Skan			       (match_dup 2)))
16878169699Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
16879169699Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
16880169699Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
16881169699Skan   (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
16882169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16883169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16884169699Skan			      UNSPEC_FSCALE_FRACT))
16885169699Skan	      (set (match_dup 9)
16886169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16887169699Skan			      UNSPEC_FSCALE_EXP))])]
16888169699Skan  "TARGET_USE_FANCY_MATH_387
16889132727Skan   && flag_unsafe_math_optimizations"
16890132727Skan{
16891169699Skan  rtx temp;
16892169699Skan  int i;
16893169699Skan
16894169699Skan  for (i=2; i<10; i++)
16895169699Skan    operands[i] = gen_reg_rtx (XFmode);
16896169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
16897169699Skan  emit_move_insn (operands[2], temp);
16898169699Skan  emit_move_insn (operands[7], CONST1_RTX (XFmode));  /* fld1 */
16899132727Skan})
16900169699Skan
16901169699Skan(define_expand "exp2sf2"
16902169699Skan  [(set (match_dup 2)
16903169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16904169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
16905169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
16906169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
16907169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
16908169699Skan   (parallel [(set (match_dup 8)
16909169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16910169699Skan			      UNSPEC_FSCALE_FRACT))
16911169699Skan	      (set (match_dup 9)
16912169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16913169699Skan			      UNSPEC_FSCALE_EXP))])
16914169699Skan   (set (match_operand:SF 0 "register_operand" "")
16915169699Skan	(float_truncate:SF (match_dup 8)))]
16916169699Skan  "TARGET_USE_FANCY_MATH_387
16917169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16918169699Skan   && flag_unsafe_math_optimizations"
16919169699Skan{
16920169699Skan  int i;
16921169699Skan
16922169699Skan  for (i=2; i<10; i++)
16923169699Skan    operands[i] = gen_reg_rtx (XFmode);
16924169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
16925169699Skan})
16926169699Skan
16927169699Skan(define_expand "exp2df2"
16928169699Skan  [(set (match_dup 2)
16929169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16930169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
16931169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
16932169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
16933169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
16934169699Skan   (parallel [(set (match_dup 8)
16935169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16936169699Skan			      UNSPEC_FSCALE_FRACT))
16937169699Skan	      (set (match_dup 9)
16938169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16939169699Skan			      UNSPEC_FSCALE_EXP))])
16940169699Skan   (set (match_operand:DF 0 "register_operand" "")
16941169699Skan	(float_truncate:DF (match_dup 8)))]
16942169699Skan  "TARGET_USE_FANCY_MATH_387
16943169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16944169699Skan   && flag_unsafe_math_optimizations"
16945169699Skan{
16946169699Skan  int i;
16947169699Skan
16948169699Skan  for (i=2; i<10; i++)
16949169699Skan    operands[i] = gen_reg_rtx (XFmode);
16950169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
16951169699Skan})
16952169699Skan
16953169699Skan(define_expand "exp2xf2"
16954169699Skan  [(set (match_dup 2) (match_operand:XF 1 "register_operand" ""))
16955169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
16956169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
16957169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
16958169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
16959169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16960169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16961169699Skan			      UNSPEC_FSCALE_FRACT))
16962169699Skan	      (set (match_dup 8)
16963169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16964169699Skan			      UNSPEC_FSCALE_EXP))])]
16965169699Skan  "TARGET_USE_FANCY_MATH_387
16966169699Skan   && flag_unsafe_math_optimizations"
16967169699Skan{
16968169699Skan  int i;
16969169699Skan
16970169699Skan  for (i=2; i<9; i++)
16971169699Skan    operands[i] = gen_reg_rtx (XFmode);
16972169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
16973169699Skan})
16974169699Skan
16975169699Skan(define_expand "expm1df2"
16976169699Skan  [(set (match_dup 2)
16977169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16978169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16979169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16980169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16981169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16982169699Skan   (parallel [(set (match_dup 8)
16983169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
16984169699Skan			      UNSPEC_FSCALE_FRACT))
16985169699Skan		   (set (match_dup 9)
16986169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
16987169699Skan			      UNSPEC_FSCALE_EXP))])
16988169699Skan   (parallel [(set (match_dup 11)
16989169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
16990169699Skan			      UNSPEC_FSCALE_FRACT))
16991169699Skan	      (set (match_dup 12)
16992169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
16993169699Skan			      UNSPEC_FSCALE_EXP))])
16994169699Skan   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
16995169699Skan   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
16996169699Skan   (set (match_operand:DF 0 "register_operand" "")
16997169699Skan	(float_truncate:DF (match_dup 14)))]
16998169699Skan  "TARGET_USE_FANCY_MATH_387
16999169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17000169699Skan   && flag_unsafe_math_optimizations"
17001169699Skan{
17002169699Skan  rtx temp;
17003169699Skan  int i;
17004169699Skan
17005169699Skan  for (i=2; i<15; i++)
17006169699Skan    operands[i] = gen_reg_rtx (XFmode);
17007169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17008169699Skan  emit_move_insn (operands[3], temp);
17009169699Skan  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
17010169699Skan})
17011169699Skan
17012169699Skan(define_expand "expm1sf2"
17013169699Skan  [(set (match_dup 2)
17014169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17015169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
17016169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
17017169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
17018169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
17019169699Skan   (parallel [(set (match_dup 8)
17020169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17021169699Skan			      UNSPEC_FSCALE_FRACT))
17022169699Skan		   (set (match_dup 9)
17023169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17024169699Skan			      UNSPEC_FSCALE_EXP))])
17025169699Skan   (parallel [(set (match_dup 11)
17026169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17027169699Skan			      UNSPEC_FSCALE_FRACT))
17028169699Skan	      (set (match_dup 12)
17029169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17030169699Skan			      UNSPEC_FSCALE_EXP))])
17031169699Skan   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
17032169699Skan   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
17033169699Skan   (set (match_operand:SF 0 "register_operand" "")
17034169699Skan	(float_truncate:SF (match_dup 14)))]
17035169699Skan  "TARGET_USE_FANCY_MATH_387
17036169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17037169699Skan   && flag_unsafe_math_optimizations"
17038169699Skan{
17039169699Skan  rtx temp;
17040169699Skan  int i;
17041169699Skan
17042169699Skan  for (i=2; i<15; i++)
17043169699Skan    operands[i] = gen_reg_rtx (XFmode);
17044169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17045169699Skan  emit_move_insn (operands[3], temp);
17046169699Skan  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
17047169699Skan})
17048169699Skan
17049169699Skan(define_expand "expm1xf2"
17050169699Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
17051169699Skan			       (match_dup 2)))
17052169699Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
17053169699Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
17054169699Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
17055169699Skan   (parallel [(set (match_dup 7)
17056169699Skan		   (unspec:XF [(match_dup 6) (match_dup 4)]
17057169699Skan			      UNSPEC_FSCALE_FRACT))
17058169699Skan		   (set (match_dup 8)
17059169699Skan		   (unspec:XF [(match_dup 6) (match_dup 4)]
17060169699Skan			      UNSPEC_FSCALE_EXP))])
17061169699Skan   (parallel [(set (match_dup 10)
17062169699Skan		   (unspec:XF [(match_dup 9) (match_dup 8)]
17063169699Skan			      UNSPEC_FSCALE_FRACT))
17064169699Skan	      (set (match_dup 11)
17065169699Skan		   (unspec:XF [(match_dup 9) (match_dup 8)]
17066169699Skan			      UNSPEC_FSCALE_EXP))])
17067169699Skan   (set (match_dup 12) (minus:XF (match_dup 10) (match_dup 9)))
17068169699Skan   (set (match_operand:XF 0 "register_operand" "")
17069169699Skan	(plus:XF (match_dup 12) (match_dup 7)))]
17070169699Skan  "TARGET_USE_FANCY_MATH_387
17071169699Skan   && flag_unsafe_math_optimizations"
17072169699Skan{
17073169699Skan  rtx temp;
17074169699Skan  int i;
17075169699Skan
17076169699Skan  for (i=2; i<13; i++)
17077169699Skan    operands[i] = gen_reg_rtx (XFmode);
17078169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17079169699Skan  emit_move_insn (operands[2], temp);
17080169699Skan  emit_move_insn (operands[9], CONST1_RTX (XFmode));  /* fld1 */
17081169699Skan})
17082169699Skan
17083169699Skan(define_expand "ldexpdf3"
17084169699Skan  [(set (match_dup 3)
17085169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
17086169699Skan   (set (match_dup 4)
17087169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17088169699Skan   (parallel [(set (match_dup 5)
17089169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17090169699Skan			      UNSPEC_FSCALE_FRACT))
17091169699Skan	      (set (match_dup 6)
17092169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17093169699Skan			      UNSPEC_FSCALE_EXP))])
17094169699Skan   (set (match_operand:DF 0 "register_operand" "")
17095169699Skan	(float_truncate:DF (match_dup 5)))]
17096169699Skan  "TARGET_USE_FANCY_MATH_387
17097169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17098169699Skan   && flag_unsafe_math_optimizations"
17099169699Skan{
17100169699Skan  int i;
17101169699Skan
17102169699Skan  for (i=3; i<7; i++)
17103169699Skan    operands[i] = gen_reg_rtx (XFmode);
17104169699Skan})
17105169699Skan
17106169699Skan(define_expand "ldexpsf3"
17107169699Skan  [(set (match_dup 3)
17108169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17109169699Skan   (set (match_dup 4)
17110169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17111169699Skan   (parallel [(set (match_dup 5)
17112169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17113169699Skan			      UNSPEC_FSCALE_FRACT))
17114169699Skan	      (set (match_dup 6)
17115169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17116169699Skan			      UNSPEC_FSCALE_EXP))])
17117169699Skan   (set (match_operand:SF 0 "register_operand" "")
17118169699Skan	(float_truncate:SF (match_dup 5)))]
17119169699Skan  "TARGET_USE_FANCY_MATH_387
17120169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17121169699Skan   && flag_unsafe_math_optimizations"
17122169699Skan{
17123169699Skan  int i;
17124169699Skan
17125169699Skan  for (i=3; i<7; i++)
17126169699Skan    operands[i] = gen_reg_rtx (XFmode);
17127169699Skan})
17128169699Skan
17129169699Skan(define_expand "ldexpxf3"
17130169699Skan  [(set (match_dup 3)
17131169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17132169699Skan   (parallel [(set (match_operand:XF 0 " register_operand" "")
17133169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
17134169699Skan			       (match_dup 3)]
17135169699Skan			      UNSPEC_FSCALE_FRACT))
17136169699Skan	      (set (match_dup 4)
17137169699Skan		   (unspec:XF [(match_dup 1) (match_dup 3)]
17138169699Skan			      UNSPEC_FSCALE_EXP))])]
17139169699Skan  "TARGET_USE_FANCY_MATH_387
17140169699Skan   && flag_unsafe_math_optimizations"
17141169699Skan{
17142169699Skan  int i;
17143169699Skan
17144169699Skan  for (i=3; i<5; i++)
17145169699Skan    operands[i] = gen_reg_rtx (XFmode);
17146169699Skan})
1714790286Sobrien
17148169699Skan
17149169699Skan(define_insn "frndintxf2"
17150169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17151169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17152169699Skan	 UNSPEC_FRNDINT))]
17153169699Skan  "TARGET_USE_FANCY_MATH_387
17154169699Skan   && flag_unsafe_math_optimizations"
17155169699Skan  "frndint"
17156169699Skan  [(set_attr "type" "fpspc")
17157169699Skan   (set_attr "mode" "XF")])
17158169699Skan
17159169699Skan(define_expand "rintdf2"
17160169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17161169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17162169699Skan  "TARGET_USE_FANCY_MATH_387
17163169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17164169699Skan   && flag_unsafe_math_optimizations"
17165169699Skan{
17166169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17167169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17168169699Skan
17169169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17170169699Skan  emit_insn (gen_frndintxf2 (op0, op1));
17171169699Skan
17172169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17173169699Skan  DONE;
17174169699Skan})
17175169699Skan
17176169699Skan(define_expand "rintsf2"
17177169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17178169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17179169699Skan  "TARGET_USE_FANCY_MATH_387
17180169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17181169699Skan   && flag_unsafe_math_optimizations"
17182169699Skan{
17183169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17184169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17185169699Skan
17186169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17187169699Skan  emit_insn (gen_frndintxf2 (op0, op1));
17188169699Skan
17189169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17190169699Skan  DONE;
17191169699Skan})
17192169699Skan
17193169699Skan(define_expand "rintxf2"
17194169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17195169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17196169699Skan  "TARGET_USE_FANCY_MATH_387
17197169699Skan   && flag_unsafe_math_optimizations"
17198169699Skan{
17199169699Skan  emit_insn (gen_frndintxf2 (operands[0], operands[1]));
17200169699Skan  DONE;
17201169699Skan})
17202169699Skan
17203169699Skan(define_insn_and_split "*fistdi2_1"
17204169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17205169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17206169699Skan	 UNSPEC_FIST))]
17207169699Skan  "TARGET_USE_FANCY_MATH_387
17208169699Skan   && flag_unsafe_math_optimizations
17209169699Skan   && !(reload_completed || reload_in_progress)"
17210169699Skan  "#"
17211169699Skan  "&& 1"
17212169699Skan  [(const_int 0)]
17213169699Skan{
17214169699Skan  if (memory_operand (operands[0], VOIDmode))
17215169699Skan    emit_insn (gen_fistdi2 (operands[0], operands[1]));
17216169699Skan  else
17217169699Skan    {
17218169699Skan      operands[2] = assign_386_stack_local (DImode, SLOT_TEMP);
17219169699Skan      emit_insn (gen_fistdi2_with_temp (operands[0], operands[1],
17220169699Skan					 operands[2]));
17221169699Skan    }
17222169699Skan  DONE;
17223169699Skan}
17224169699Skan  [(set_attr "type" "fpspc")
17225169699Skan   (set_attr "mode" "DI")])
17226169699Skan
17227169699Skan(define_insn "fistdi2"
17228169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17229169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17230169699Skan	 UNSPEC_FIST))
17231169699Skan   (clobber (match_scratch:XF 2 "=&1f"))]
17232169699Skan  "TARGET_USE_FANCY_MATH_387
17233169699Skan   && flag_unsafe_math_optimizations"
17234169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17235169699Skan  [(set_attr "type" "fpspc")
17236169699Skan   (set_attr "mode" "DI")])
17237169699Skan
17238169699Skan(define_insn "fistdi2_with_temp"
17239169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17240169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17241169699Skan	 UNSPEC_FIST))
17242169699Skan   (clobber (match_operand:DI 2 "memory_operand" "=m,m"))
17243169699Skan   (clobber (match_scratch:XF 3 "=&1f,&1f"))]
17244169699Skan  "TARGET_USE_FANCY_MATH_387
17245169699Skan   && flag_unsafe_math_optimizations"
17246169699Skan  "#"
17247169699Skan  [(set_attr "type" "fpspc")
17248169699Skan   (set_attr "mode" "DI")])
17249169699Skan
17250169699Skan(define_split 
17251169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17252169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17253169699Skan	 UNSPEC_FIST))
17254169699Skan   (clobber (match_operand:DI 2 "memory_operand" ""))
17255169699Skan   (clobber (match_scratch 3 ""))]
17256169699Skan  "reload_completed"
17257169699Skan  [(parallel [(set (match_dup 2) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
17258169699Skan	      (clobber (match_dup 3))])
17259169699Skan   (set (match_dup 0) (match_dup 2))]
17260169699Skan  "")
17261169699Skan
17262169699Skan(define_split 
17263169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17264169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17265169699Skan	 UNSPEC_FIST))
17266169699Skan   (clobber (match_operand:DI 2 "memory_operand" ""))
17267169699Skan   (clobber (match_scratch 3 ""))]
17268169699Skan  "reload_completed"
17269169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
17270169699Skan	      (clobber (match_dup 3))])]
17271169699Skan  "")
17272169699Skan
17273169699Skan(define_insn_and_split "*fist<mode>2_1"
17274169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
17275169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17276169699Skan	 UNSPEC_FIST))]
17277169699Skan  "TARGET_USE_FANCY_MATH_387
17278169699Skan   && flag_unsafe_math_optimizations
17279169699Skan   && !(reload_completed || reload_in_progress)"
17280169699Skan  "#"
17281169699Skan  "&& 1"
17282169699Skan  [(const_int 0)]
17283169699Skan{
17284169699Skan  operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17285169699Skan  emit_insn (gen_fist<mode>2_with_temp (operands[0], operands[1],
17286169699Skan					operands[2]));
17287169699Skan  DONE;
17288169699Skan}
17289169699Skan  [(set_attr "type" "fpspc")
17290169699Skan   (set_attr "mode" "<MODE>")])
17291169699Skan
17292169699Skan(define_insn "fist<mode>2"
17293169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17294169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17295169699Skan	 UNSPEC_FIST))]
17296169699Skan  "TARGET_USE_FANCY_MATH_387
17297169699Skan   && flag_unsafe_math_optimizations"
17298169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17299169699Skan  [(set_attr "type" "fpspc")
17300169699Skan   (set_attr "mode" "<MODE>")])
17301169699Skan
17302169699Skan(define_insn "fist<mode>2_with_temp"
17303169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
17304169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17305169699Skan	 UNSPEC_FIST))
17306169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" "=m"))]
17307169699Skan  "TARGET_USE_FANCY_MATH_387
17308169699Skan   && flag_unsafe_math_optimizations"
17309169699Skan  "#"
17310169699Skan  [(set_attr "type" "fpspc")
17311169699Skan   (set_attr "mode" "<MODE>")])
17312169699Skan
17313169699Skan(define_split 
17314169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17315169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17316169699Skan	 UNSPEC_FIST))
17317169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
17318169699Skan  "reload_completed"
17319169699Skan  [(set (match_dup 2) (unspec:X87MODEI12 [(match_dup 1)]
17320169699Skan		       UNSPEC_FIST))
17321169699Skan   (set (match_dup 0) (match_dup 2))]
17322169699Skan  "")
17323169699Skan
17324169699Skan(define_split 
17325169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17326169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17327169699Skan	 UNSPEC_FIST))
17328169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
17329169699Skan  "reload_completed"
17330169699Skan  [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17331169699Skan		       UNSPEC_FIST))]
17332169699Skan  "")
17333169699Skan
17334169699Skan(define_expand "lrint<mode>2"
17335169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17336169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17337169699Skan	 UNSPEC_FIST))]
17338169699Skan  "TARGET_USE_FANCY_MATH_387
17339169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17340169699Skan   && flag_unsafe_math_optimizations"
17341169699Skan  "")
17342169699Skan
17343169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17344169699Skan(define_insn_and_split "frndintxf2_floor"
17345169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17346169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17347169699Skan	 UNSPEC_FRNDINT_FLOOR))
17348169699Skan   (clobber (reg:CC FLAGS_REG))]
17349169699Skan  "TARGET_USE_FANCY_MATH_387
17350169699Skan   && flag_unsafe_math_optimizations
17351169699Skan   && !(reload_completed || reload_in_progress)"
17352169699Skan  "#"
17353169699Skan  "&& 1"
17354169699Skan  [(const_int 0)]
17355169699Skan{
17356169699Skan  ix86_optimize_mode_switching[I387_FLOOR] = 1;
17357169699Skan
17358169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17359169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
17360169699Skan
17361169699Skan  emit_insn (gen_frndintxf2_floor_i387 (operands[0], operands[1],
17362169699Skan					operands[2], operands[3]));
17363169699Skan  DONE;
17364169699Skan}
17365169699Skan  [(set_attr "type" "frndint")
17366169699Skan   (set_attr "i387_cw" "floor")
17367169699Skan   (set_attr "mode" "XF")])
17368169699Skan
17369169699Skan(define_insn "frndintxf2_floor_i387"
17370169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17371169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17372169699Skan	 UNSPEC_FRNDINT_FLOOR))
17373169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17374169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17375169699Skan  "TARGET_USE_FANCY_MATH_387
17376169699Skan   && flag_unsafe_math_optimizations"
17377169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17378169699Skan  [(set_attr "type" "frndint")
17379169699Skan   (set_attr "i387_cw" "floor")
17380169699Skan   (set_attr "mode" "XF")])
17381169699Skan
17382169699Skan(define_expand "floorxf2"
17383169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17384169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17385169699Skan  "TARGET_USE_FANCY_MATH_387
17386169699Skan   && flag_unsafe_math_optimizations"
17387169699Skan{
17388169699Skan  emit_insn (gen_frndintxf2_floor (operands[0], operands[1]));
17389169699Skan  DONE;
17390169699Skan})
17391169699Skan
17392169699Skan(define_expand "floordf2"
17393169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17394169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17395169699Skan  "TARGET_USE_FANCY_MATH_387
17396169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17397169699Skan   && flag_unsafe_math_optimizations"
17398169699Skan{
17399169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17400169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17401169699Skan
17402169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17403169699Skan  emit_insn (gen_frndintxf2_floor (op0, op1));
17404169699Skan
17405169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17406169699Skan  DONE;
17407169699Skan})
17408169699Skan
17409169699Skan(define_expand "floorsf2"
17410169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17411169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17412169699Skan  "TARGET_USE_FANCY_MATH_387
17413169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17414169699Skan   && flag_unsafe_math_optimizations"
17415169699Skan{
17416169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17417169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17418169699Skan
17419169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17420169699Skan  emit_insn (gen_frndintxf2_floor (op0, op1));
17421169699Skan
17422169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17423169699Skan  DONE;
17424169699Skan})
17425169699Skan
17426169699Skan(define_insn_and_split "*fist<mode>2_floor_1"
17427169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
17428169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
17429169699Skan	 UNSPEC_FIST_FLOOR))
17430169699Skan   (clobber (reg:CC FLAGS_REG))]
17431169699Skan  "TARGET_USE_FANCY_MATH_387
17432169699Skan   && flag_unsafe_math_optimizations
17433169699Skan   && !(reload_completed || reload_in_progress)"
17434169699Skan  "#"
17435169699Skan  "&& 1"
17436169699Skan  [(const_int 0)]
17437169699Skan{
17438169699Skan  ix86_optimize_mode_switching[I387_FLOOR] = 1;
17439169699Skan
17440169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17441169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
17442169699Skan  if (memory_operand (operands[0], VOIDmode))
17443169699Skan    emit_insn (gen_fist<mode>2_floor (operands[0], operands[1],
17444169699Skan				      operands[2], operands[3]));
17445169699Skan  else
17446169699Skan    {
17447169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17448169699Skan      emit_insn (gen_fist<mode>2_floor_with_temp (operands[0], operands[1],
17449169699Skan						  operands[2], operands[3],
17450169699Skan						  operands[4]));
17451169699Skan    }
17452169699Skan  DONE;
17453169699Skan}
17454169699Skan  [(set_attr "type" "fistp")
17455169699Skan   (set_attr "i387_cw" "floor")
17456169699Skan   (set_attr "mode" "<MODE>")])
17457169699Skan
17458169699Skan(define_insn "fistdi2_floor"
17459169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17460169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17461169699Skan	 UNSPEC_FIST_FLOOR))
17462169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17463169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
17464169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
17465169699Skan  "TARGET_USE_FANCY_MATH_387
17466169699Skan   && flag_unsafe_math_optimizations"
17467169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17468169699Skan  [(set_attr "type" "fistp")
17469169699Skan   (set_attr "i387_cw" "floor")
17470169699Skan   (set_attr "mode" "DI")])
17471169699Skan
17472169699Skan(define_insn "fistdi2_floor_with_temp"
17473169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17474169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17475169699Skan	 UNSPEC_FIST_FLOOR))
17476169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17477169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17478169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
17479169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
17480169699Skan  "TARGET_USE_FANCY_MATH_387
17481169699Skan   && flag_unsafe_math_optimizations"
17482169699Skan  "#"
17483169699Skan  [(set_attr "type" "fistp")
17484169699Skan   (set_attr "i387_cw" "floor")
17485169699Skan   (set_attr "mode" "DI")])
17486169699Skan
17487169699Skan(define_split 
17488169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17489169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17490169699Skan	 UNSPEC_FIST_FLOOR))
17491169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17492169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17493169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17494169699Skan   (clobber (match_scratch 5 ""))]
17495169699Skan  "reload_completed"
17496169699Skan  [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
17497169699Skan	      (use (match_dup 2))
17498169699Skan	      (use (match_dup 3))
17499169699Skan	      (clobber (match_dup 5))])
17500169699Skan   (set (match_dup 0) (match_dup 4))]
17501169699Skan  "")
17502169699Skan
17503169699Skan(define_split 
17504169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17505169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17506169699Skan	 UNSPEC_FIST_FLOOR))
17507169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17508169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17509169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17510169699Skan   (clobber (match_scratch 5 ""))]
17511169699Skan  "reload_completed"
17512169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
17513169699Skan	      (use (match_dup 2))
17514169699Skan	      (use (match_dup 3))
17515169699Skan	      (clobber (match_dup 5))])]
17516169699Skan  "")
17517169699Skan
17518169699Skan(define_insn "fist<mode>2_floor"
17519169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17520169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17521169699Skan	 UNSPEC_FIST_FLOOR))
17522169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17523169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17524169699Skan  "TARGET_USE_FANCY_MATH_387
17525169699Skan   && flag_unsafe_math_optimizations"
17526169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17527169699Skan  [(set_attr "type" "fistp")
17528169699Skan   (set_attr "i387_cw" "floor")
17529169699Skan   (set_attr "mode" "<MODE>")])
17530169699Skan
17531169699Skan(define_insn "fist<mode>2_floor_with_temp"
17532169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
17533169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
17534169699Skan	 UNSPEC_FIST_FLOOR))
17535169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17536169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17537169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
17538169699Skan  "TARGET_USE_FANCY_MATH_387
17539169699Skan   && flag_unsafe_math_optimizations"
17540169699Skan  "#"
17541169699Skan  [(set_attr "type" "fistp")
17542169699Skan   (set_attr "i387_cw" "floor")
17543169699Skan   (set_attr "mode" "<MODE>")])
17544169699Skan
17545169699Skan(define_split 
17546169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17547169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17548169699Skan	 UNSPEC_FIST_FLOOR))
17549169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17550169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17551169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17552169699Skan  "reload_completed"
17553169699Skan  [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
17554169699Skan				  UNSPEC_FIST_FLOOR))
17555169699Skan	      (use (match_dup 2))
17556169699Skan	      (use (match_dup 3))])
17557169699Skan   (set (match_dup 0) (match_dup 4))]
17558169699Skan  "")
17559169699Skan
17560169699Skan(define_split 
17561169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17562169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17563169699Skan	 UNSPEC_FIST_FLOOR))
17564169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17565169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17566169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17567169699Skan  "reload_completed"
17568169699Skan  [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17569169699Skan				  UNSPEC_FIST_FLOOR))
17570169699Skan	      (use (match_dup 2))
17571169699Skan	      (use (match_dup 3))])]
17572169699Skan  "")
17573169699Skan
17574169699Skan(define_expand "lfloor<mode>2"
17575169699Skan  [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17576169699Skan		   (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17577169699Skan		    UNSPEC_FIST_FLOOR))
17578169699Skan	      (clobber (reg:CC FLAGS_REG))])]
17579169699Skan  "TARGET_USE_FANCY_MATH_387
17580169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17581169699Skan   && flag_unsafe_math_optimizations"
17582169699Skan  "")
17583169699Skan
17584169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17585169699Skan(define_insn_and_split "frndintxf2_ceil"
17586169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17587169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17588169699Skan	 UNSPEC_FRNDINT_CEIL))
17589169699Skan   (clobber (reg:CC FLAGS_REG))]
17590169699Skan  "TARGET_USE_FANCY_MATH_387
17591169699Skan   && flag_unsafe_math_optimizations
17592169699Skan   && !(reload_completed || reload_in_progress)"
17593169699Skan  "#"
17594169699Skan  "&& 1"
17595169699Skan  [(const_int 0)]
17596169699Skan{
17597169699Skan  ix86_optimize_mode_switching[I387_CEIL] = 1;
17598169699Skan
17599169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17600169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
17601169699Skan
17602169699Skan  emit_insn (gen_frndintxf2_ceil_i387 (operands[0], operands[1],
17603169699Skan				       operands[2], operands[3]));
17604169699Skan  DONE;
17605169699Skan}
17606169699Skan  [(set_attr "type" "frndint")
17607169699Skan   (set_attr "i387_cw" "ceil")
17608169699Skan   (set_attr "mode" "XF")])
17609169699Skan
17610169699Skan(define_insn "frndintxf2_ceil_i387"
17611169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17612169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17613169699Skan	 UNSPEC_FRNDINT_CEIL))
17614169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17615169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17616169699Skan  "TARGET_USE_FANCY_MATH_387
17617169699Skan   && flag_unsafe_math_optimizations"
17618169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17619169699Skan  [(set_attr "type" "frndint")
17620169699Skan   (set_attr "i387_cw" "ceil")
17621169699Skan   (set_attr "mode" "XF")])
17622169699Skan
17623169699Skan(define_expand "ceilxf2"
17624169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17625169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17626169699Skan  "TARGET_USE_FANCY_MATH_387
17627169699Skan   && flag_unsafe_math_optimizations"
17628169699Skan{
17629169699Skan  emit_insn (gen_frndintxf2_ceil (operands[0], operands[1]));
17630169699Skan  DONE;
17631169699Skan})
17632169699Skan
17633169699Skan(define_expand "ceildf2"
17634169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17635169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17636169699Skan  "TARGET_USE_FANCY_MATH_387
17637169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17638169699Skan   && flag_unsafe_math_optimizations"
17639169699Skan{
17640169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17641169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17642169699Skan
17643169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17644169699Skan  emit_insn (gen_frndintxf2_ceil (op0, op1));
17645169699Skan
17646169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17647169699Skan  DONE;
17648169699Skan})
17649169699Skan
17650169699Skan(define_expand "ceilsf2"
17651169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17652169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17653169699Skan  "TARGET_USE_FANCY_MATH_387
17654169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17655169699Skan   && flag_unsafe_math_optimizations"
17656169699Skan{
17657169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17658169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17659169699Skan
17660169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17661169699Skan  emit_insn (gen_frndintxf2_ceil (op0, op1));
17662169699Skan
17663169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17664169699Skan  DONE;
17665169699Skan})
17666169699Skan
17667169699Skan(define_insn_and_split "*fist<mode>2_ceil_1"
17668169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
17669169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
17670169699Skan	 UNSPEC_FIST_CEIL))
17671169699Skan   (clobber (reg:CC FLAGS_REG))]
17672169699Skan  "TARGET_USE_FANCY_MATH_387
17673169699Skan   && flag_unsafe_math_optimizations
17674169699Skan   && !(reload_completed || reload_in_progress)"
17675169699Skan  "#"
17676169699Skan  "&& 1"
17677169699Skan  [(const_int 0)]
17678169699Skan{
17679169699Skan  ix86_optimize_mode_switching[I387_CEIL] = 1;
17680169699Skan
17681169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17682169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
17683169699Skan  if (memory_operand (operands[0], VOIDmode))
17684169699Skan    emit_insn (gen_fist<mode>2_ceil (operands[0], operands[1],
17685169699Skan				     operands[2], operands[3]));
17686169699Skan  else
17687169699Skan    {
17688169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17689169699Skan      emit_insn (gen_fist<mode>2_ceil_with_temp (operands[0], operands[1],
17690169699Skan						 operands[2], operands[3],
17691169699Skan						 operands[4]));
17692169699Skan    }
17693169699Skan  DONE;
17694169699Skan}
17695169699Skan  [(set_attr "type" "fistp")
17696169699Skan   (set_attr "i387_cw" "ceil")
17697169699Skan   (set_attr "mode" "<MODE>")])
17698169699Skan
17699169699Skan(define_insn "fistdi2_ceil"
17700169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17701169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17702169699Skan	 UNSPEC_FIST_CEIL))
17703169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17704169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
17705169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
17706169699Skan  "TARGET_USE_FANCY_MATH_387
17707169699Skan   && flag_unsafe_math_optimizations"
17708169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17709169699Skan  [(set_attr "type" "fistp")
17710169699Skan   (set_attr "i387_cw" "ceil")
17711169699Skan   (set_attr "mode" "DI")])
17712169699Skan
17713169699Skan(define_insn "fistdi2_ceil_with_temp"
17714169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17715169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17716169699Skan	 UNSPEC_FIST_CEIL))
17717169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17718169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17719169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
17720169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
17721169699Skan  "TARGET_USE_FANCY_MATH_387
17722169699Skan   && flag_unsafe_math_optimizations"
17723169699Skan  "#"
17724169699Skan  [(set_attr "type" "fistp")
17725169699Skan   (set_attr "i387_cw" "ceil")
17726169699Skan   (set_attr "mode" "DI")])
17727169699Skan
17728169699Skan(define_split 
17729169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17730169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17731169699Skan	 UNSPEC_FIST_CEIL))
17732169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17733169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17734169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17735169699Skan   (clobber (match_scratch 5 ""))]
17736169699Skan  "reload_completed"
17737169699Skan  [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
17738169699Skan	      (use (match_dup 2))
17739169699Skan	      (use (match_dup 3))
17740169699Skan	      (clobber (match_dup 5))])
17741169699Skan   (set (match_dup 0) (match_dup 4))]
17742169699Skan  "")
17743169699Skan
17744169699Skan(define_split 
17745169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17746169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17747169699Skan	 UNSPEC_FIST_CEIL))
17748169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17749169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17750169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17751169699Skan   (clobber (match_scratch 5 ""))]
17752169699Skan  "reload_completed"
17753169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
17754169699Skan	      (use (match_dup 2))
17755169699Skan	      (use (match_dup 3))
17756169699Skan	      (clobber (match_dup 5))])]
17757169699Skan  "")
17758169699Skan
17759169699Skan(define_insn "fist<mode>2_ceil"
17760169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17761169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17762169699Skan	 UNSPEC_FIST_CEIL))
17763169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17764169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17765169699Skan  "TARGET_USE_FANCY_MATH_387
17766169699Skan   && flag_unsafe_math_optimizations"
17767169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17768169699Skan  [(set_attr "type" "fistp")
17769169699Skan   (set_attr "i387_cw" "ceil")
17770169699Skan   (set_attr "mode" "<MODE>")])
17771169699Skan
17772169699Skan(define_insn "fist<mode>2_ceil_with_temp"
17773169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
17774169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
17775169699Skan	 UNSPEC_FIST_CEIL))
17776169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17777169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17778169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
17779169699Skan  "TARGET_USE_FANCY_MATH_387
17780169699Skan   && flag_unsafe_math_optimizations"
17781169699Skan  "#"
17782169699Skan  [(set_attr "type" "fistp")
17783169699Skan   (set_attr "i387_cw" "ceil")
17784169699Skan   (set_attr "mode" "<MODE>")])
17785169699Skan
17786169699Skan(define_split 
17787169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17788169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17789169699Skan	 UNSPEC_FIST_CEIL))
17790169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17791169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17792169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17793169699Skan  "reload_completed"
17794169699Skan  [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
17795169699Skan				  UNSPEC_FIST_CEIL))
17796169699Skan	      (use (match_dup 2))
17797169699Skan	      (use (match_dup 3))])
17798169699Skan   (set (match_dup 0) (match_dup 4))]
17799169699Skan  "")
17800169699Skan
17801169699Skan(define_split 
17802169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17803169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17804169699Skan	 UNSPEC_FIST_CEIL))
17805169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17806169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17807169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17808169699Skan  "reload_completed"
17809169699Skan  [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17810169699Skan				  UNSPEC_FIST_CEIL))
17811169699Skan	      (use (match_dup 2))
17812169699Skan	      (use (match_dup 3))])]
17813169699Skan  "")
17814169699Skan
17815169699Skan(define_expand "lceil<mode>2"
17816169699Skan  [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17817169699Skan		   (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17818169699Skan		    UNSPEC_FIST_CEIL))
17819169699Skan	      (clobber (reg:CC FLAGS_REG))])]
17820169699Skan  "TARGET_USE_FANCY_MATH_387
17821169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17822169699Skan   && flag_unsafe_math_optimizations"
17823169699Skan  "")
17824169699Skan
17825169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17826169699Skan(define_insn_and_split "frndintxf2_trunc"
17827169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17828169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17829169699Skan	 UNSPEC_FRNDINT_TRUNC))
17830169699Skan   (clobber (reg:CC FLAGS_REG))]
17831169699Skan  "TARGET_USE_FANCY_MATH_387
17832169699Skan   && flag_unsafe_math_optimizations
17833169699Skan   && !(reload_completed || reload_in_progress)"
17834169699Skan  "#"
17835169699Skan  "&& 1"
17836169699Skan  [(const_int 0)]
17837169699Skan{
17838169699Skan  ix86_optimize_mode_switching[I387_TRUNC] = 1;
17839169699Skan
17840169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17841169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
17842169699Skan
17843169699Skan  emit_insn (gen_frndintxf2_trunc_i387 (operands[0], operands[1],
17844169699Skan					operands[2], operands[3]));
17845169699Skan  DONE;
17846169699Skan}
17847169699Skan  [(set_attr "type" "frndint")
17848169699Skan   (set_attr "i387_cw" "trunc")
17849169699Skan   (set_attr "mode" "XF")])
17850169699Skan
17851169699Skan(define_insn "frndintxf2_trunc_i387"
17852169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17853169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17854169699Skan	 UNSPEC_FRNDINT_TRUNC))
17855169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17856169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17857169699Skan  "TARGET_USE_FANCY_MATH_387
17858169699Skan   && flag_unsafe_math_optimizations"
17859169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17860169699Skan  [(set_attr "type" "frndint")
17861169699Skan   (set_attr "i387_cw" "trunc")
17862169699Skan   (set_attr "mode" "XF")])
17863169699Skan
17864169699Skan(define_expand "btruncxf2"
17865169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17866169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17867169699Skan  "TARGET_USE_FANCY_MATH_387
17868169699Skan   && flag_unsafe_math_optimizations"
17869169699Skan{
17870169699Skan  emit_insn (gen_frndintxf2_trunc (operands[0], operands[1]));
17871169699Skan  DONE;
17872169699Skan})
17873169699Skan
17874169699Skan(define_expand "btruncdf2"
17875169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17876169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17877169699Skan  "TARGET_USE_FANCY_MATH_387
17878169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17879169699Skan   && flag_unsafe_math_optimizations"
17880169699Skan{
17881169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17882169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17883169699Skan
17884169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17885169699Skan  emit_insn (gen_frndintxf2_trunc (op0, op1));
17886169699Skan
17887169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17888169699Skan  DONE;
17889169699Skan})
17890169699Skan
17891169699Skan(define_expand "btruncsf2"
17892169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17893169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17894169699Skan  "TARGET_USE_FANCY_MATH_387
17895169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17896169699Skan   && flag_unsafe_math_optimizations"
17897169699Skan{
17898169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17899169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17900169699Skan
17901169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17902169699Skan  emit_insn (gen_frndintxf2_trunc (op0, op1));
17903169699Skan
17904169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17905169699Skan  DONE;
17906169699Skan})
17907169699Skan
17908169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17909169699Skan(define_insn_and_split "frndintxf2_mask_pm"
17910169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17911169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17912169699Skan	 UNSPEC_FRNDINT_MASK_PM))
17913169699Skan   (clobber (reg:CC FLAGS_REG))]
17914169699Skan  "TARGET_USE_FANCY_MATH_387
17915169699Skan   && flag_unsafe_math_optimizations
17916169699Skan   && !(reload_completed || reload_in_progress)"
17917169699Skan  "#"
17918169699Skan  "&& 1"
17919169699Skan  [(const_int 0)]
17920169699Skan{
17921169699Skan  ix86_optimize_mode_switching[I387_MASK_PM] = 1;
17922169699Skan
17923169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17924169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_MASK_PM);
17925169699Skan
17926169699Skan  emit_insn (gen_frndintxf2_mask_pm_i387 (operands[0], operands[1],
17927169699Skan					  operands[2], operands[3]));
17928169699Skan  DONE;
17929169699Skan}
17930169699Skan  [(set_attr "type" "frndint")
17931169699Skan   (set_attr "i387_cw" "mask_pm")
17932169699Skan   (set_attr "mode" "XF")])
17933169699Skan
17934169699Skan(define_insn "frndintxf2_mask_pm_i387"
17935169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17936169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17937169699Skan	 UNSPEC_FRNDINT_MASK_PM))
17938169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17939169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17940169699Skan  "TARGET_USE_FANCY_MATH_387
17941169699Skan   && flag_unsafe_math_optimizations"
17942169699Skan  "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2"
17943169699Skan  [(set_attr "type" "frndint")
17944169699Skan   (set_attr "i387_cw" "mask_pm")
17945169699Skan   (set_attr "mode" "XF")])
17946169699Skan
17947169699Skan(define_expand "nearbyintxf2"
17948169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17949169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17950169699Skan  "TARGET_USE_FANCY_MATH_387
17951169699Skan   && flag_unsafe_math_optimizations"
17952169699Skan{
17953169699Skan  emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1]));
17954169699Skan
17955169699Skan  DONE;
17956169699Skan})
17957169699Skan
17958169699Skan(define_expand "nearbyintdf2"
17959169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17960169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17961169699Skan  "TARGET_USE_FANCY_MATH_387
17962169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17963169699Skan   && flag_unsafe_math_optimizations"
17964169699Skan{
17965169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17966169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17967169699Skan
17968169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17969169699Skan  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
17970169699Skan
17971169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17972169699Skan  DONE;
17973169699Skan})
17974169699Skan
17975169699Skan(define_expand "nearbyintsf2"
17976169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17977169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17978169699Skan  "TARGET_USE_FANCY_MATH_387
17979169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17980169699Skan   && flag_unsafe_math_optimizations"
17981169699Skan{
17982169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17983169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17984169699Skan
17985169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17986169699Skan  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
17987169699Skan
17988169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17989169699Skan  DONE;
17990169699Skan})
17991169699Skan
17992169699Skan
1799390286Sobrien;; Block operation instructions
1799490286Sobrien
1799590286Sobrien(define_insn "cld"
17996169699Skan [(set (reg:SI DIRFLAG_REG) (const_int 0))]
1799790286Sobrien ""
1799890286Sobrien "cld"
1799990286Sobrien  [(set_attr "type" "cld")])
1800090286Sobrien
18001169699Skan(define_expand "movmemsi"
1800290286Sobrien  [(use (match_operand:BLK 0 "memory_operand" ""))
1800390286Sobrien   (use (match_operand:BLK 1 "memory_operand" ""))
1800490286Sobrien   (use (match_operand:SI 2 "nonmemory_operand" ""))
1800590286Sobrien   (use (match_operand:SI 3 "const_int_operand" ""))]
18006169699Skan  "! optimize_size || TARGET_INLINE_ALL_STRINGOPS"
1800718334Speter{
18008169699Skan if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
1800990286Sobrien   DONE;
1801090286Sobrien else
1801190286Sobrien   FAIL;
1801290286Sobrien})
1801390286Sobrien
18014169699Skan(define_expand "movmemdi"
1801590286Sobrien  [(use (match_operand:BLK 0 "memory_operand" ""))
1801690286Sobrien   (use (match_operand:BLK 1 "memory_operand" ""))
1801790286Sobrien   (use (match_operand:DI 2 "nonmemory_operand" ""))
1801890286Sobrien   (use (match_operand:DI 3 "const_int_operand" ""))]
1801990286Sobrien  "TARGET_64BIT"
1802090286Sobrien{
18021169699Skan if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
1802290286Sobrien   DONE;
1802390286Sobrien else
1802490286Sobrien   FAIL;
1802590286Sobrien})
1802690286Sobrien
1802790286Sobrien;; Most CPUs don't like single string operations
1802890286Sobrien;; Handle this case here to simplify previous expander.
1802990286Sobrien
18030132727Skan(define_expand "strmov"
18031132727Skan  [(set (match_dup 4) (match_operand 3 "memory_operand" ""))
18032132727Skan   (set (match_operand 1 "memory_operand" "") (match_dup 4))
18033132727Skan   (parallel [(set (match_operand 0 "register_operand" "") (match_dup 5))
18034169699Skan	      (clobber (reg:CC FLAGS_REG))])
18035132727Skan   (parallel [(set (match_operand 2 "register_operand" "") (match_dup 6))
18036169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1803790286Sobrien  ""
1803890286Sobrien{
18039132727Skan  rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])));
1804050650Sobrien
18041132727Skan  /* If .md ever supports :P for Pmode, these can be directly
18042132727Skan     in the pattern above.  */
18043132727Skan  operands[5] = gen_rtx_PLUS (Pmode, operands[0], adjust);
18044132727Skan  operands[6] = gen_rtx_PLUS (Pmode, operands[2], adjust);
1804550650Sobrien
1804690286Sobrien  if (TARGET_SINGLE_STRINGOP || optimize_size)
1804790286Sobrien    {
18048132727Skan      emit_insn (gen_strmov_singleop (operands[0], operands[1],
18049132727Skan				      operands[2], operands[3],
18050132727Skan				      operands[5], operands[6]));
1805190286Sobrien      DONE;
1805290286Sobrien    }
1805350650Sobrien
18054132727Skan  operands[4] = gen_reg_rtx (GET_MODE (operands[1]));
1805590286Sobrien})
1805650650Sobrien
18057132727Skan(define_expand "strmov_singleop"
18058132727Skan  [(parallel [(set (match_operand 1 "memory_operand" "")
18059132727Skan		   (match_operand 3 "memory_operand" ""))
18060132727Skan	      (set (match_operand 0 "register_operand" "")
18061132727Skan		   (match_operand 4 "" ""))
18062132727Skan	      (set (match_operand 2 "register_operand" "")
18063132727Skan		   (match_operand 5 "" ""))
18064169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18065132727Skan  "TARGET_SINGLE_STRINGOP || optimize_size"
18066132727Skan  "")
1806718334Speter
18068132727Skan(define_insn "*strmovdi_rex_1"
1806990286Sobrien  [(set (mem:DI (match_operand:DI 2 "register_operand" "0"))
1807090286Sobrien	(mem:DI (match_operand:DI 3 "register_operand" "1")))
1807190286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1807290286Sobrien	(plus:DI (match_dup 2)
1807390286Sobrien		 (const_int 8)))
1807490286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1807590286Sobrien	(plus:DI (match_dup 3)
1807690286Sobrien		 (const_int 8)))
18077169699Skan   (use (reg:SI DIRFLAG_REG))]
1807890286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1807990286Sobrien  "movsq"
1808090286Sobrien  [(set_attr "type" "str")
1808190286Sobrien   (set_attr "mode" "DI")
1808290286Sobrien   (set_attr "memory" "both")])
1808390286Sobrien
18084132727Skan(define_insn "*strmovsi_1"
1808590286Sobrien  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
1808690286Sobrien	(mem:SI (match_operand:SI 3 "register_operand" "1")))
1808790286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1808890286Sobrien	(plus:SI (match_dup 2)
1808990286Sobrien		 (const_int 4)))
1809090286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1809190286Sobrien	(plus:SI (match_dup 3)
1809290286Sobrien		 (const_int 4)))
18093169699Skan   (use (reg:SI DIRFLAG_REG))]
1809490286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1809590286Sobrien  "{movsl|movsd}"
1809690286Sobrien  [(set_attr "type" "str")
1809790286Sobrien   (set_attr "mode" "SI")
1809890286Sobrien   (set_attr "memory" "both")])
1809990286Sobrien
18100132727Skan(define_insn "*strmovsi_rex_1"
1810190286Sobrien  [(set (mem:SI (match_operand:DI 2 "register_operand" "0"))
1810290286Sobrien	(mem:SI (match_operand:DI 3 "register_operand" "1")))
1810390286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1810490286Sobrien	(plus:DI (match_dup 2)
1810590286Sobrien		 (const_int 4)))
1810690286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1810790286Sobrien	(plus:DI (match_dup 3)
1810890286Sobrien		 (const_int 4)))
18109169699Skan   (use (reg:SI DIRFLAG_REG))]
1811090286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1811190286Sobrien  "{movsl|movsd}"
1811290286Sobrien  [(set_attr "type" "str")
1811390286Sobrien   (set_attr "mode" "SI")
1811490286Sobrien   (set_attr "memory" "both")])
1811590286Sobrien
18116132727Skan(define_insn "*strmovhi_1"
1811790286Sobrien  [(set (mem:HI (match_operand:SI 2 "register_operand" "0"))
1811890286Sobrien	(mem:HI (match_operand:SI 3 "register_operand" "1")))
1811990286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1812090286Sobrien	(plus:SI (match_dup 2)
1812190286Sobrien		 (const_int 2)))
1812290286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1812390286Sobrien	(plus:SI (match_dup 3)
1812490286Sobrien		 (const_int 2)))
18125169699Skan   (use (reg:SI DIRFLAG_REG))]
1812690286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1812790286Sobrien  "movsw"
1812890286Sobrien  [(set_attr "type" "str")
1812990286Sobrien   (set_attr "memory" "both")
1813090286Sobrien   (set_attr "mode" "HI")])
1813190286Sobrien
18132132727Skan(define_insn "*strmovhi_rex_1"
1813390286Sobrien  [(set (mem:HI (match_operand:DI 2 "register_operand" "0"))
1813490286Sobrien	(mem:HI (match_operand:DI 3 "register_operand" "1")))
1813590286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1813690286Sobrien	(plus:DI (match_dup 2)
1813790286Sobrien		 (const_int 2)))
1813890286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1813990286Sobrien	(plus:DI (match_dup 3)
1814090286Sobrien		 (const_int 2)))
18141169699Skan   (use (reg:SI DIRFLAG_REG))]
1814290286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1814390286Sobrien  "movsw"
1814490286Sobrien  [(set_attr "type" "str")
1814590286Sobrien   (set_attr "memory" "both")
1814690286Sobrien   (set_attr "mode" "HI")])
1814790286Sobrien
18148132727Skan(define_insn "*strmovqi_1"
1814990286Sobrien  [(set (mem:QI (match_operand:SI 2 "register_operand" "0"))
1815090286Sobrien	(mem:QI (match_operand:SI 3 "register_operand" "1")))
1815190286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1815290286Sobrien	(plus:SI (match_dup 2)
1815390286Sobrien		 (const_int 1)))
1815490286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1815590286Sobrien	(plus:SI (match_dup 3)
1815690286Sobrien		 (const_int 1)))
18157169699Skan   (use (reg:SI DIRFLAG_REG))]
1815890286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1815990286Sobrien  "movsb"
1816090286Sobrien  [(set_attr "type" "str")
1816190286Sobrien   (set_attr "memory" "both")
1816290286Sobrien   (set_attr "mode" "QI")])
1816390286Sobrien
18164132727Skan(define_insn "*strmovqi_rex_1"
1816590286Sobrien  [(set (mem:QI (match_operand:DI 2 "register_operand" "0"))
1816690286Sobrien	(mem:QI (match_operand:DI 3 "register_operand" "1")))
1816790286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1816890286Sobrien	(plus:DI (match_dup 2)
1816990286Sobrien		 (const_int 1)))
1817090286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1817190286Sobrien	(plus:DI (match_dup 3)
1817290286Sobrien		 (const_int 1)))
18173169699Skan   (use (reg:SI DIRFLAG_REG))]
1817490286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1817590286Sobrien  "movsb"
1817690286Sobrien  [(set_attr "type" "str")
1817790286Sobrien   (set_attr "memory" "both")
1817890286Sobrien   (set_attr "mode" "QI")])
1817990286Sobrien
18180132727Skan(define_expand "rep_mov"
18181132727Skan  [(parallel [(set (match_operand 4 "register_operand" "") (const_int 0))
18182132727Skan	      (set (match_operand 0 "register_operand" "")
18183132727Skan		   (match_operand 5 "" ""))
18184132727Skan	      (set (match_operand 2 "register_operand" "")
18185132727Skan		   (match_operand 6 "" ""))
18186132727Skan	      (set (match_operand 1 "memory_operand" "")
18187132727Skan		   (match_operand 3 "memory_operand" ""))
18188132727Skan	      (use (match_dup 4))
18189169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18190132727Skan  ""
18191132727Skan  "")
18192132727Skan
18193132727Skan(define_insn "*rep_movdi_rex64"
1819490286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
1819590286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1819690286Sobrien        (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
1819790286Sobrien			    (const_int 3))
1819890286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1819990286Sobrien   (set (match_operand:DI 1 "register_operand" "=S") 
1820090286Sobrien        (plus:DI (ashift:DI (match_dup 5) (const_int 3))
1820190286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1820290286Sobrien   (set (mem:BLK (match_dup 3))
1820390286Sobrien	(mem:BLK (match_dup 4)))
1820490286Sobrien   (use (match_dup 5))
18205169699Skan   (use (reg:SI DIRFLAG_REG))]
1820690286Sobrien  "TARGET_64BIT"
1820790286Sobrien  "{rep\;movsq|rep movsq}"
1820890286Sobrien  [(set_attr "type" "str")
1820990286Sobrien   (set_attr "prefix_rep" "1")
1821090286Sobrien   (set_attr "memory" "both")
1821190286Sobrien   (set_attr "mode" "DI")])
1821290286Sobrien
18213132727Skan(define_insn "*rep_movsi"
1821490286Sobrien  [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
1821590286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1821690286Sobrien        (plus:SI (ashift:SI (match_operand:SI 5 "register_operand" "2")
1821790286Sobrien			    (const_int 2))
1821890286Sobrien		 (match_operand:SI 3 "register_operand" "0")))
1821990286Sobrien   (set (match_operand:SI 1 "register_operand" "=S") 
1822090286Sobrien        (plus:SI (ashift:SI (match_dup 5) (const_int 2))
1822190286Sobrien		 (match_operand:SI 4 "register_operand" "1")))
1822290286Sobrien   (set (mem:BLK (match_dup 3))
1822390286Sobrien	(mem:BLK (match_dup 4)))
1822490286Sobrien   (use (match_dup 5))
18225169699Skan   (use (reg:SI DIRFLAG_REG))]
1822690286Sobrien  "!TARGET_64BIT"
1822790286Sobrien  "{rep\;movsl|rep movsd}"
1822890286Sobrien  [(set_attr "type" "str")
1822990286Sobrien   (set_attr "prefix_rep" "1")
1823090286Sobrien   (set_attr "memory" "both")
1823190286Sobrien   (set_attr "mode" "SI")])
1823290286Sobrien
18233132727Skan(define_insn "*rep_movsi_rex64"
1823490286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
1823590286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1823690286Sobrien        (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
1823790286Sobrien			    (const_int 2))
1823890286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1823990286Sobrien   (set (match_operand:DI 1 "register_operand" "=S") 
1824090286Sobrien        (plus:DI (ashift:DI (match_dup 5) (const_int 2))
1824190286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1824290286Sobrien   (set (mem:BLK (match_dup 3))
1824390286Sobrien	(mem:BLK (match_dup 4)))
1824490286Sobrien   (use (match_dup 5))
18245169699Skan   (use (reg:SI DIRFLAG_REG))]
1824690286Sobrien  "TARGET_64BIT"
1824790286Sobrien  "{rep\;movsl|rep movsd}"
1824890286Sobrien  [(set_attr "type" "str")
1824990286Sobrien   (set_attr "prefix_rep" "1")
1825090286Sobrien   (set_attr "memory" "both")
1825190286Sobrien   (set_attr "mode" "SI")])
1825290286Sobrien
18253132727Skan(define_insn "*rep_movqi"
1825490286Sobrien  [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
1825590286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1825690286Sobrien        (plus:SI (match_operand:SI 3 "register_operand" "0")
1825790286Sobrien		 (match_operand:SI 5 "register_operand" "2")))
1825890286Sobrien   (set (match_operand:SI 1 "register_operand" "=S") 
1825990286Sobrien        (plus:SI (match_operand:SI 4 "register_operand" "1") (match_dup 5)))
1826090286Sobrien   (set (mem:BLK (match_dup 3))
1826190286Sobrien	(mem:BLK (match_dup 4)))
1826290286Sobrien   (use (match_dup 5))
18263169699Skan   (use (reg:SI DIRFLAG_REG))]
1826490286Sobrien  "!TARGET_64BIT"
1826590286Sobrien  "{rep\;movsb|rep movsb}"
1826690286Sobrien  [(set_attr "type" "str")
1826790286Sobrien   (set_attr "prefix_rep" "1")
1826890286Sobrien   (set_attr "memory" "both")
1826990286Sobrien   (set_attr "mode" "SI")])
1827090286Sobrien
18271132727Skan(define_insn "*rep_movqi_rex64"
1827290286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
1827390286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1827490286Sobrien        (plus:DI (match_operand:DI 3 "register_operand" "0")
1827590286Sobrien		 (match_operand:DI 5 "register_operand" "2")))
1827690286Sobrien   (set (match_operand:DI 1 "register_operand" "=S") 
1827790286Sobrien        (plus:DI (match_operand:DI 4 "register_operand" "1") (match_dup 5)))
1827890286Sobrien   (set (mem:BLK (match_dup 3))
1827990286Sobrien	(mem:BLK (match_dup 4)))
1828090286Sobrien   (use (match_dup 5))
18281169699Skan   (use (reg:SI DIRFLAG_REG))]
1828290286Sobrien  "TARGET_64BIT"
1828390286Sobrien  "{rep\;movsb|rep movsb}"
1828490286Sobrien  [(set_attr "type" "str")
1828590286Sobrien   (set_attr "prefix_rep" "1")
1828690286Sobrien   (set_attr "memory" "both")
1828790286Sobrien   (set_attr "mode" "SI")])
1828890286Sobrien
18289169699Skan(define_expand "setmemsi"
1829090286Sobrien   [(use (match_operand:BLK 0 "memory_operand" ""))
1829190286Sobrien    (use (match_operand:SI 1 "nonmemory_operand" ""))
18292169699Skan    (use (match_operand 2 "const_int_operand" ""))
18293169699Skan    (use (match_operand 3 "const_int_operand" ""))]
1829418334Speter  ""
1829518334Speter{
18296169699Skan /* If value to set is not zero, use the library routine.  */
18297169699Skan if (operands[2] != const0_rtx)
18298169699Skan   FAIL;
18299169699Skan
18300169699Skan if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
1830190286Sobrien   DONE;
1830290286Sobrien else
1830390286Sobrien   FAIL;
1830490286Sobrien})
1830518334Speter
18306169699Skan(define_expand "setmemdi"
1830790286Sobrien   [(use (match_operand:BLK 0 "memory_operand" ""))
1830890286Sobrien    (use (match_operand:DI 1 "nonmemory_operand" ""))
18309169699Skan    (use (match_operand 2 "const_int_operand" ""))
18310169699Skan    (use (match_operand 3 "const_int_operand" ""))]
1831190286Sobrien  "TARGET_64BIT"
1831290286Sobrien{
18313169699Skan /* If value to set is not zero, use the library routine.  */
18314169699Skan if (operands[2] != const0_rtx)
18315169699Skan   FAIL;
18316169699Skan
18317169699Skan if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
1831890286Sobrien   DONE;
1831990286Sobrien else
1832090286Sobrien   FAIL;
1832190286Sobrien})
1832250650Sobrien
1832390286Sobrien;; Most CPUs don't like single string operations
1832490286Sobrien;; Handle this case here to simplify previous expander.
1832550650Sobrien
18326132727Skan(define_expand "strset"
18327132727Skan  [(set (match_operand 1 "memory_operand" "")
18328132727Skan	(match_operand 2 "register_operand" ""))
18329132727Skan   (parallel [(set (match_operand 0 "register_operand" "")
18330132727Skan		   (match_dup 3))
18331169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1833290286Sobrien  ""
1833390286Sobrien{
18334132727Skan  if (GET_MODE (operands[1]) != GET_MODE (operands[2]))
18335132727Skan    operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0);
1833690286Sobrien
18337132727Skan  /* If .md ever supports :P for Pmode, this can be directly
18338132727Skan     in the pattern above.  */
18339132727Skan  operands[3] = gen_rtx_PLUS (Pmode, operands[0],
18340132727Skan			      GEN_INT (GET_MODE_SIZE (GET_MODE
18341132727Skan						      (operands[2]))));
1834290286Sobrien  if (TARGET_SINGLE_STRINGOP || optimize_size)
1834390286Sobrien    {
18344132727Skan      emit_insn (gen_strset_singleop (operands[0], operands[1], operands[2],
18345132727Skan				      operands[3]));
1834690286Sobrien      DONE;
1834790286Sobrien    }
1834890286Sobrien})
1834990286Sobrien
18350132727Skan(define_expand "strset_singleop"
18351132727Skan  [(parallel [(set (match_operand 1 "memory_operand" "")
18352132727Skan		   (match_operand 2 "register_operand" ""))
18353132727Skan	      (set (match_operand 0 "register_operand" "")
18354132727Skan		   (match_operand 3 "" ""))
18355169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18356132727Skan  "TARGET_SINGLE_STRINGOP || optimize_size"
18357132727Skan  "")
1835890286Sobrien
18359132727Skan(define_insn "*strsetdi_rex_1"
18360169699Skan  [(set (mem:DI (match_operand:DI 1 "register_operand" "0"))
18361169699Skan	(match_operand:DI 2 "register_operand" "a"))
1836290286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1836390286Sobrien	(plus:DI (match_dup 1)
1836490286Sobrien		 (const_int 8)))
18365169699Skan   (use (reg:SI DIRFLAG_REG))]
1836690286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1836790286Sobrien  "stosq"
1836890286Sobrien  [(set_attr "type" "str")
1836990286Sobrien   (set_attr "memory" "store")
1837090286Sobrien   (set_attr "mode" "DI")])
1837190286Sobrien
18372132727Skan(define_insn "*strsetsi_1"
1837390286Sobrien  [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
1837490286Sobrien	(match_operand:SI 2 "register_operand" "a"))
1837590286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1837690286Sobrien	(plus:SI (match_dup 1)
1837790286Sobrien		 (const_int 4)))
18378169699Skan   (use (reg:SI DIRFLAG_REG))]
1837990286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1838090286Sobrien  "{stosl|stosd}"
1838190286Sobrien  [(set_attr "type" "str")
1838290286Sobrien   (set_attr "memory" "store")
1838390286Sobrien   (set_attr "mode" "SI")])
1838490286Sobrien
18385132727Skan(define_insn "*strsetsi_rex_1"
1838690286Sobrien  [(set (mem:SI (match_operand:DI 1 "register_operand" "0"))
1838790286Sobrien	(match_operand:SI 2 "register_operand" "a"))
1838890286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1838990286Sobrien	(plus:DI (match_dup 1)
1839090286Sobrien		 (const_int 4)))
18391169699Skan   (use (reg:SI DIRFLAG_REG))]
1839290286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1839390286Sobrien  "{stosl|stosd}"
1839490286Sobrien  [(set_attr "type" "str")
1839590286Sobrien   (set_attr "memory" "store")
1839690286Sobrien   (set_attr "mode" "SI")])
1839790286Sobrien
18398132727Skan(define_insn "*strsethi_1"
1839990286Sobrien  [(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
1840090286Sobrien	(match_operand:HI 2 "register_operand" "a"))
1840190286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1840290286Sobrien	(plus:SI (match_dup 1)
1840390286Sobrien		 (const_int 2)))
18404169699Skan   (use (reg:SI DIRFLAG_REG))]
1840590286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1840690286Sobrien  "stosw"
1840790286Sobrien  [(set_attr "type" "str")
1840890286Sobrien   (set_attr "memory" "store")
1840990286Sobrien   (set_attr "mode" "HI")])
1841090286Sobrien
18411132727Skan(define_insn "*strsethi_rex_1"
1841290286Sobrien  [(set (mem:HI (match_operand:DI 1 "register_operand" "0"))
1841390286Sobrien	(match_operand:HI 2 "register_operand" "a"))
1841490286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1841590286Sobrien	(plus:DI (match_dup 1)
1841690286Sobrien		 (const_int 2)))
18417169699Skan   (use (reg:SI DIRFLAG_REG))]
1841890286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1841990286Sobrien  "stosw"
1842090286Sobrien  [(set_attr "type" "str")
1842190286Sobrien   (set_attr "memory" "store")
1842290286Sobrien   (set_attr "mode" "HI")])
1842390286Sobrien
18424132727Skan(define_insn "*strsetqi_1"
1842590286Sobrien  [(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
1842690286Sobrien	(match_operand:QI 2 "register_operand" "a"))
1842790286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1842890286Sobrien	(plus:SI (match_dup 1)
1842990286Sobrien		 (const_int 1)))
18430169699Skan   (use (reg:SI DIRFLAG_REG))]
1843190286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1843290286Sobrien  "stosb"
1843390286Sobrien  [(set_attr "type" "str")
1843490286Sobrien   (set_attr "memory" "store")
1843590286Sobrien   (set_attr "mode" "QI")])
1843690286Sobrien
18437132727Skan(define_insn "*strsetqi_rex_1"
1843890286Sobrien  [(set (mem:QI (match_operand:DI 1 "register_operand" "0"))
1843990286Sobrien	(match_operand:QI 2 "register_operand" "a"))
1844090286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1844190286Sobrien	(plus:DI (match_dup 1)
1844290286Sobrien		 (const_int 1)))
18443169699Skan   (use (reg:SI DIRFLAG_REG))]
1844490286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1844590286Sobrien  "stosb"
1844690286Sobrien  [(set_attr "type" "str")
1844790286Sobrien   (set_attr "memory" "store")
1844890286Sobrien   (set_attr "mode" "QI")])
1844990286Sobrien
18450132727Skan(define_expand "rep_stos"
18451132727Skan  [(parallel [(set (match_operand 1 "register_operand" "") (const_int 0))
18452132727Skan	      (set (match_operand 0 "register_operand" "")
18453132727Skan		   (match_operand 4 "" ""))
18454132727Skan	      (set (match_operand 2 "memory_operand" "") (const_int 0))
18455132727Skan	      (use (match_operand 3 "register_operand" ""))
18456132727Skan	      (use (match_dup 1))
18457169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18458132727Skan  ""
18459132727Skan  "")
18460132727Skan
18461132727Skan(define_insn "*rep_stosdi_rex64"
1846290286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
1846390286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1846490286Sobrien        (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
1846590286Sobrien			    (const_int 3))
1846690286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1846790286Sobrien   (set (mem:BLK (match_dup 3))
1846890286Sobrien	(const_int 0))
1846990286Sobrien   (use (match_operand:DI 2 "register_operand" "a"))
1847090286Sobrien   (use (match_dup 4))
18471169699Skan   (use (reg:SI DIRFLAG_REG))]
1847290286Sobrien  "TARGET_64BIT"
1847390286Sobrien  "{rep\;stosq|rep stosq}"
1847490286Sobrien  [(set_attr "type" "str")
1847590286Sobrien   (set_attr "prefix_rep" "1")
1847690286Sobrien   (set_attr "memory" "store")
1847790286Sobrien   (set_attr "mode" "DI")])
1847890286Sobrien
18479132727Skan(define_insn "*rep_stossi"
1848090286Sobrien  [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
1848190286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1848290286Sobrien        (plus:SI (ashift:SI (match_operand:SI 4 "register_operand" "1")
1848390286Sobrien			    (const_int 2))
1848490286Sobrien		 (match_operand:SI 3 "register_operand" "0")))
1848590286Sobrien   (set (mem:BLK (match_dup 3))
1848690286Sobrien	(const_int 0))
1848790286Sobrien   (use (match_operand:SI 2 "register_operand" "a"))
1848890286Sobrien   (use (match_dup 4))
18489169699Skan   (use (reg:SI DIRFLAG_REG))]
1849090286Sobrien  "!TARGET_64BIT"
1849190286Sobrien  "{rep\;stosl|rep stosd}"
1849290286Sobrien  [(set_attr "type" "str")
1849390286Sobrien   (set_attr "prefix_rep" "1")
1849490286Sobrien   (set_attr "memory" "store")
1849590286Sobrien   (set_attr "mode" "SI")])
1849690286Sobrien
18497132727Skan(define_insn "*rep_stossi_rex64"
1849890286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
1849990286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1850090286Sobrien        (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
1850190286Sobrien			    (const_int 2))
1850290286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1850390286Sobrien   (set (mem:BLK (match_dup 3))
1850490286Sobrien	(const_int 0))
1850590286Sobrien   (use (match_operand:SI 2 "register_operand" "a"))
1850690286Sobrien   (use (match_dup 4))
18507169699Skan   (use (reg:SI DIRFLAG_REG))]
1850890286Sobrien  "TARGET_64BIT"
1850990286Sobrien  "{rep\;stosl|rep stosd}"
1851090286Sobrien  [(set_attr "type" "str")
1851190286Sobrien   (set_attr "prefix_rep" "1")
1851290286Sobrien   (set_attr "memory" "store")
1851390286Sobrien   (set_attr "mode" "SI")])
1851490286Sobrien
18515132727Skan(define_insn "*rep_stosqi"
1851690286Sobrien  [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
1851790286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1851890286Sobrien        (plus:SI (match_operand:SI 3 "register_operand" "0")
1851990286Sobrien		 (match_operand:SI 4 "register_operand" "1")))
1852090286Sobrien   (set (mem:BLK (match_dup 3))
1852190286Sobrien	(const_int 0))
1852290286Sobrien   (use (match_operand:QI 2 "register_operand" "a"))
1852390286Sobrien   (use (match_dup 4))
18524169699Skan   (use (reg:SI DIRFLAG_REG))]
1852590286Sobrien  "!TARGET_64BIT"
1852690286Sobrien  "{rep\;stosb|rep stosb}"
1852790286Sobrien  [(set_attr "type" "str")
1852890286Sobrien   (set_attr "prefix_rep" "1")
1852990286Sobrien   (set_attr "memory" "store")
1853090286Sobrien   (set_attr "mode" "QI")])
1853190286Sobrien
18532132727Skan(define_insn "*rep_stosqi_rex64"
1853390286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
1853490286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1853590286Sobrien        (plus:DI (match_operand:DI 3 "register_operand" "0")
1853690286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1853790286Sobrien   (set (mem:BLK (match_dup 3))
1853890286Sobrien	(const_int 0))
1853990286Sobrien   (use (match_operand:QI 2 "register_operand" "a"))
1854090286Sobrien   (use (match_dup 4))
18541169699Skan   (use (reg:SI DIRFLAG_REG))]
1854290286Sobrien  "TARGET_64BIT"
1854390286Sobrien  "{rep\;stosb|rep stosb}"
1854490286Sobrien  [(set_attr "type" "str")
1854590286Sobrien   (set_attr "prefix_rep" "1")
1854690286Sobrien   (set_attr "memory" "store")
1854790286Sobrien   (set_attr "mode" "QI")])
1854890286Sobrien
18549169699Skan(define_expand "cmpstrnsi"
1855050650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1855190286Sobrien	(compare:SI (match_operand:BLK 1 "general_operand" "")
1855290286Sobrien		    (match_operand:BLK 2 "general_operand" "")))
1855390286Sobrien   (use (match_operand 3 "general_operand" ""))
1855490286Sobrien   (use (match_operand 4 "immediate_operand" ""))]
18555132727Skan  "! optimize_size || TARGET_INLINE_ALL_STRINGOPS"
1855650650Sobrien{
1855790286Sobrien  rtx addr1, addr2, out, outlow, count, countreg, align;
1855850650Sobrien
18559132727Skan  /* Can't use this if the user has appropriated esi or edi.  */
18560132727Skan  if (global_regs[4] || global_regs[5])
18561132727Skan    FAIL;
18562132727Skan
1856390286Sobrien  out = operands[0];
1856490286Sobrien  if (GET_CODE (out) != REG)
1856590286Sobrien    out = gen_reg_rtx (SImode);
1856650650Sobrien
1856790286Sobrien  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1856890286Sobrien  addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
18569132727Skan  if (addr1 != XEXP (operands[1], 0))
18570132727Skan    operands[1] = replace_equiv_address_nv (operands[1], addr1);
18571132727Skan  if (addr2 != XEXP (operands[2], 0))
18572132727Skan    operands[2] = replace_equiv_address_nv (operands[2], addr2);
18573132727Skan
1857490286Sobrien  count = operands[3];
1857590286Sobrien  countreg = ix86_zero_extend_to_Pmode (count);
1857650650Sobrien
1857790286Sobrien  /* %%% Iff we are testing strict equality, we can use known alignment
1857890286Sobrien     to good advantage.  This may be possible with combine, particularly
1857990286Sobrien     once cc0 is dead.  */
1858090286Sobrien  align = operands[4];
1858150650Sobrien
1858290286Sobrien  emit_insn (gen_cld ());
1858390286Sobrien  if (GET_CODE (count) == CONST_INT)
1858490286Sobrien    {
1858590286Sobrien      if (INTVAL (count) == 0)
1858690286Sobrien	{
1858790286Sobrien	  emit_move_insn (operands[0], const0_rtx);
1858890286Sobrien	  DONE;
1858990286Sobrien	}
18590169699Skan      emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, countreg, align,
18591169699Skan				     operands[1], operands[2]));
1859290286Sobrien    }
1859390286Sobrien  else
1859490286Sobrien    {
1859590286Sobrien      if (TARGET_64BIT)
18596132727Skan	emit_insn (gen_cmpdi_1_rex64 (countreg, countreg));
1859790286Sobrien      else
18598132727Skan	emit_insn (gen_cmpsi_1 (countreg, countreg));
18599169699Skan      emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
18600169699Skan				  operands[1], operands[2]));
1860190286Sobrien    }
1860290286Sobrien
1860390286Sobrien  outlow = gen_lowpart (QImode, out);
1860490286Sobrien  emit_insn (gen_cmpintqi (outlow));
1860590286Sobrien  emit_move_insn (out, gen_rtx_SIGN_EXTEND (SImode, outlow));
1860690286Sobrien
1860790286Sobrien  if (operands[0] != out)
1860890286Sobrien    emit_move_insn (operands[0], out);
1860990286Sobrien
1861090286Sobrien  DONE;
1861190286Sobrien})
1861290286Sobrien
1861390286Sobrien;; Produce a tri-state integer (-1, 0, 1) from condition codes.
1861490286Sobrien
1861590286Sobrien(define_expand "cmpintqi"
1861690286Sobrien  [(set (match_dup 1)
18617169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1861890286Sobrien   (set (match_dup 2)
18619169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
1862090286Sobrien   (parallel [(set (match_operand:QI 0 "register_operand" "")
1862190286Sobrien		   (minus:QI (match_dup 1)
1862290286Sobrien			     (match_dup 2)))
18623169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1862490286Sobrien  ""
1862590286Sobrien  "operands[1] = gen_reg_rtx (QImode);
1862690286Sobrien   operands[2] = gen_reg_rtx (QImode);")
1862790286Sobrien
1862890286Sobrien;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
1862990286Sobrien;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
1863090286Sobrien
18631169699Skan(define_expand "cmpstrnqi_nz_1"
18632169699Skan  [(parallel [(set (reg:CC FLAGS_REG)
18633132727Skan		   (compare:CC (match_operand 4 "memory_operand" "")
18634132727Skan			       (match_operand 5 "memory_operand" "")))
18635132727Skan	      (use (match_operand 2 "register_operand" ""))
18636132727Skan	      (use (match_operand:SI 3 "immediate_operand" ""))
18637169699Skan	      (use (reg:SI DIRFLAG_REG))
18638132727Skan	      (clobber (match_operand 0 "register_operand" ""))
18639132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18640132727Skan	      (clobber (match_dup 2))])]
18641132727Skan  ""
18642132727Skan  "")
18643132727Skan
18644169699Skan(define_insn "*cmpstrnqi_nz_1"
18645169699Skan  [(set (reg:CC FLAGS_REG)
1864690286Sobrien	(compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
1864790286Sobrien		    (mem:BLK (match_operand:SI 5 "register_operand" "1"))))
1864890286Sobrien   (use (match_operand:SI 6 "register_operand" "2"))
1864990286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18650169699Skan   (use (reg:SI DIRFLAG_REG))
1865190286Sobrien   (clobber (match_operand:SI 0 "register_operand" "=S"))
1865290286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
1865390286Sobrien   (clobber (match_operand:SI 2 "register_operand" "=c"))]
1865490286Sobrien  "!TARGET_64BIT"
1865590286Sobrien  "repz{\;| }cmpsb"
1865690286Sobrien  [(set_attr "type" "str")
1865790286Sobrien   (set_attr "mode" "QI")
1865890286Sobrien   (set_attr "prefix_rep" "1")])
1865990286Sobrien
18660169699Skan(define_insn "*cmpstrnqi_nz_rex_1"
18661169699Skan  [(set (reg:CC FLAGS_REG)
1866290286Sobrien	(compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
1866390286Sobrien		    (mem:BLK (match_operand:DI 5 "register_operand" "1"))))
1866490286Sobrien   (use (match_operand:DI 6 "register_operand" "2"))
1866590286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18666169699Skan   (use (reg:SI DIRFLAG_REG))
1866790286Sobrien   (clobber (match_operand:DI 0 "register_operand" "=S"))
1866890286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
1866990286Sobrien   (clobber (match_operand:DI 2 "register_operand" "=c"))]
1867090286Sobrien  "TARGET_64BIT"
1867190286Sobrien  "repz{\;| }cmpsb"
1867290286Sobrien  [(set_attr "type" "str")
1867390286Sobrien   (set_attr "mode" "QI")
1867490286Sobrien   (set_attr "prefix_rep" "1")])
1867590286Sobrien
1867690286Sobrien;; The same, but the count is not known to not be zero.
1867790286Sobrien
18678169699Skan(define_expand "cmpstrnqi_1"
18679169699Skan  [(parallel [(set (reg:CC FLAGS_REG)
18680132727Skan		(if_then_else:CC (ne (match_operand 2 "register_operand" "")
18681132727Skan				     (const_int 0))
18682132727Skan		  (compare:CC (match_operand 4 "memory_operand" "")
18683132727Skan			      (match_operand 5 "memory_operand" ""))
18684132727Skan		  (const_int 0)))
18685132727Skan	      (use (match_operand:SI 3 "immediate_operand" ""))
18686169699Skan	      (use (reg:CC FLAGS_REG))
18687169699Skan	      (use (reg:SI DIRFLAG_REG))
18688132727Skan	      (clobber (match_operand 0 "register_operand" ""))
18689132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18690132727Skan	      (clobber (match_dup 2))])]
18691132727Skan  ""
18692132727Skan  "")
18693132727Skan
18694169699Skan(define_insn "*cmpstrnqi_1"
18695169699Skan  [(set (reg:CC FLAGS_REG)
1869690286Sobrien	(if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
1869790286Sobrien			     (const_int 0))
1869890286Sobrien	  (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
1869990286Sobrien		      (mem:BLK (match_operand:SI 5 "register_operand" "1")))
1870090286Sobrien	  (const_int 0)))
1870190286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18702169699Skan   (use (reg:CC FLAGS_REG))
18703169699Skan   (use (reg:SI DIRFLAG_REG))
1870490286Sobrien   (clobber (match_operand:SI 0 "register_operand" "=S"))
1870590286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
1870690286Sobrien   (clobber (match_operand:SI 2 "register_operand" "=c"))]
1870790286Sobrien  "!TARGET_64BIT"
1870890286Sobrien  "repz{\;| }cmpsb"
1870990286Sobrien  [(set_attr "type" "str")
1871090286Sobrien   (set_attr "mode" "QI")
1871190286Sobrien   (set_attr "prefix_rep" "1")])
1871290286Sobrien
18713169699Skan(define_insn "*cmpstrnqi_rex_1"
18714169699Skan  [(set (reg:CC FLAGS_REG)
1871590286Sobrien	(if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2")
1871690286Sobrien			     (const_int 0))
1871790286Sobrien	  (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
1871890286Sobrien		      (mem:BLK (match_operand:DI 5 "register_operand" "1")))
1871990286Sobrien	  (const_int 0)))
1872090286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18721169699Skan   (use (reg:CC FLAGS_REG))
18722169699Skan   (use (reg:SI DIRFLAG_REG))
1872390286Sobrien   (clobber (match_operand:DI 0 "register_operand" "=S"))
1872490286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
1872590286Sobrien   (clobber (match_operand:DI 2 "register_operand" "=c"))]
1872690286Sobrien  "TARGET_64BIT"
1872790286Sobrien  "repz{\;| }cmpsb"
1872890286Sobrien  [(set_attr "type" "str")
1872990286Sobrien   (set_attr "mode" "QI")
1873090286Sobrien   (set_attr "prefix_rep" "1")])
1873190286Sobrien
1873290286Sobrien(define_expand "strlensi"
1873352296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1873490286Sobrien	(unspec:SI [(match_operand:BLK 1 "general_operand" "")
1873590286Sobrien		    (match_operand:QI 2 "immediate_operand" "")
18736117404Skan		    (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
1873790286Sobrien  ""
1873890286Sobrien{
1873990286Sobrien if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
1874090286Sobrien   DONE;
1874190286Sobrien else
1874290286Sobrien   FAIL;
1874390286Sobrien})
1874490286Sobrien
1874590286Sobrien(define_expand "strlendi"
1874690286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1874790286Sobrien	(unspec:DI [(match_operand:BLK 1 "general_operand" "")
1874890286Sobrien		    (match_operand:QI 2 "immediate_operand" "")
18749117404Skan		    (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
1875090286Sobrien  ""
1875190286Sobrien{
1875290286Sobrien if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
1875390286Sobrien   DONE;
1875490286Sobrien else
1875590286Sobrien   FAIL;
1875690286Sobrien})
1875790286Sobrien
18758132727Skan(define_expand "strlenqi_1"
18759132727Skan  [(parallel [(set (match_operand 0 "register_operand" "") (match_operand 2 "" ""))
18760169699Skan	      (use (reg:SI DIRFLAG_REG))
18761132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18762169699Skan	      (clobber (reg:CC FLAGS_REG))])]
18763132727Skan  ""
18764132727Skan  "")
18765132727Skan
18766132727Skan(define_insn "*strlenqi_1"
1876790286Sobrien  [(set (match_operand:SI 0 "register_operand" "=&c")
1876890286Sobrien	(unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1"))
1876990286Sobrien		    (match_operand:QI 2 "register_operand" "a")
1877090286Sobrien		    (match_operand:SI 3 "immediate_operand" "i")
18771117404Skan		    (match_operand:SI 4 "register_operand" "0")] UNSPEC_SCAS))
18772169699Skan   (use (reg:SI DIRFLAG_REG))
1877390286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
18774169699Skan   (clobber (reg:CC FLAGS_REG))]
1877590286Sobrien  "!TARGET_64BIT"
1877690286Sobrien  "repnz{\;| }scasb"
1877790286Sobrien  [(set_attr "type" "str")
1877890286Sobrien   (set_attr "mode" "QI")
1877990286Sobrien   (set_attr "prefix_rep" "1")])
1878090286Sobrien
18781132727Skan(define_insn "*strlenqi_rex_1"
1878290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=&c")
1878390286Sobrien	(unspec:DI [(mem:BLK (match_operand:DI 5 "register_operand" "1"))
1878490286Sobrien		    (match_operand:QI 2 "register_operand" "a")
1878590286Sobrien		    (match_operand:DI 3 "immediate_operand" "i")
18786117404Skan		    (match_operand:DI 4 "register_operand" "0")] UNSPEC_SCAS))
18787169699Skan   (use (reg:SI DIRFLAG_REG))
1878890286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
18789169699Skan   (clobber (reg:CC FLAGS_REG))]
1879090286Sobrien  "TARGET_64BIT"
1879190286Sobrien  "repnz{\;| }scasb"
1879290286Sobrien  [(set_attr "type" "str")
1879390286Sobrien   (set_attr "mode" "QI")
1879490286Sobrien   (set_attr "prefix_rep" "1")])
1879590286Sobrien
18796169699Skan;; Peephole optimizations to clean up after cmpstrn*.  This should be
1879790286Sobrien;; handled in combine, but it is not currently up to the task.
18798169699Skan;; When used for their truth value, the cmpstrn* expanders generate
1879990286Sobrien;; code like this:
1880090286Sobrien;;
1880190286Sobrien;;   repz cmpsb
1880290286Sobrien;;   seta 	%al
1880390286Sobrien;;   setb 	%dl
1880490286Sobrien;;   cmpb 	%al, %dl
1880590286Sobrien;;   jcc	label
1880690286Sobrien;;
1880790286Sobrien;; The intermediate three instructions are unnecessary.
1880890286Sobrien
18809169699Skan;; This one handles cmpstrn*_nz_1...
1881090286Sobrien(define_peephole2
1881190286Sobrien  [(parallel[
18812169699Skan     (set (reg:CC FLAGS_REG)
1881390286Sobrien	  (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
1881490286Sobrien		      (mem:BLK (match_operand 5 "register_operand" ""))))
1881590286Sobrien     (use (match_operand 6 "register_operand" ""))
1881690286Sobrien     (use (match_operand:SI 3 "immediate_operand" ""))
18817169699Skan     (use (reg:SI DIRFLAG_REG))
1881890286Sobrien     (clobber (match_operand 0 "register_operand" ""))
1881990286Sobrien     (clobber (match_operand 1 "register_operand" ""))
1882090286Sobrien     (clobber (match_operand 2 "register_operand" ""))])
1882190286Sobrien   (set (match_operand:QI 7 "register_operand" "")
18822169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1882390286Sobrien   (set (match_operand:QI 8 "register_operand" "")
18824169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
18825169699Skan   (set (reg FLAGS_REG)
1882690286Sobrien	(compare (match_dup 7) (match_dup 8)))
1882790286Sobrien  ]
1882890286Sobrien  "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
1882990286Sobrien  [(parallel[
18830169699Skan     (set (reg:CC FLAGS_REG)
1883190286Sobrien	  (compare:CC (mem:BLK (match_dup 4))
1883290286Sobrien		      (mem:BLK (match_dup 5))))
1883390286Sobrien     (use (match_dup 6))
1883490286Sobrien     (use (match_dup 3))
18835169699Skan     (use (reg:SI DIRFLAG_REG))
1883690286Sobrien     (clobber (match_dup 0))
1883790286Sobrien     (clobber (match_dup 1))
1883890286Sobrien     (clobber (match_dup 2))])]
1883950650Sobrien  "")
1884050650Sobrien
18841169699Skan;; ...and this one handles cmpstrn*_1.
1884290286Sobrien(define_peephole2
1884390286Sobrien  [(parallel[
18844169699Skan     (set (reg:CC FLAGS_REG)
1884590286Sobrien	  (if_then_else:CC (ne (match_operand 6 "register_operand" "")
1884690286Sobrien			       (const_int 0))
1884790286Sobrien	    (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
1884890286Sobrien		        (mem:BLK (match_operand 5 "register_operand" "")))
1884990286Sobrien	    (const_int 0)))
1885090286Sobrien     (use (match_operand:SI 3 "immediate_operand" ""))
18851169699Skan     (use (reg:CC FLAGS_REG))
18852169699Skan     (use (reg:SI DIRFLAG_REG))
1885390286Sobrien     (clobber (match_operand 0 "register_operand" ""))
1885490286Sobrien     (clobber (match_operand 1 "register_operand" ""))
1885590286Sobrien     (clobber (match_operand 2 "register_operand" ""))])
1885690286Sobrien   (set (match_operand:QI 7 "register_operand" "")
18857169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1885890286Sobrien   (set (match_operand:QI 8 "register_operand" "")
18859169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
18860169699Skan   (set (reg FLAGS_REG)
1886190286Sobrien	(compare (match_dup 7) (match_dup 8)))
1886290286Sobrien  ]
1886390286Sobrien  "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
1886490286Sobrien  [(parallel[
18865169699Skan     (set (reg:CC FLAGS_REG)
1886690286Sobrien	  (if_then_else:CC (ne (match_dup 6)
1886790286Sobrien			       (const_int 0))
1886890286Sobrien	    (compare:CC (mem:BLK (match_dup 4))
1886990286Sobrien			(mem:BLK (match_dup 5)))
1887090286Sobrien	    (const_int 0)))
1887190286Sobrien     (use (match_dup 3))
18872169699Skan     (use (reg:CC FLAGS_REG))
18873169699Skan     (use (reg:SI DIRFLAG_REG))
1887490286Sobrien     (clobber (match_dup 0))
1887590286Sobrien     (clobber (match_dup 1))
1887690286Sobrien     (clobber (match_dup 2))])]
1887750650Sobrien  "")
1887850650Sobrien
1887990286Sobrien
1888090286Sobrien
1888190286Sobrien;; Conditional move instructions.
1888290286Sobrien
1888390286Sobrien(define_expand "movdicc"
1888490286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1888590286Sobrien	(if_then_else:DI (match_operand 1 "comparison_operator" "")
1888690286Sobrien			 (match_operand:DI 2 "general_operand" "")
1888790286Sobrien			 (match_operand:DI 3 "general_operand" "")))]
1888890286Sobrien  "TARGET_64BIT"
1888990286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1889090286Sobrien
1889190286Sobrien(define_insn "x86_movdicc_0_m1_rex64"
1889290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
18893132727Skan	(if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "")
1889490286Sobrien	  (const_int -1)
1889590286Sobrien	  (const_int 0)))
18896169699Skan   (clobber (reg:CC FLAGS_REG))]
1889790286Sobrien  "TARGET_64BIT"
1889890286Sobrien  "sbb{q}\t%0, %0"
1889990286Sobrien  ; Since we don't have the proper number of operands for an alu insn,
1890090286Sobrien  ; fill in all the blanks.
1890190286Sobrien  [(set_attr "type" "alu")
18902117404Skan   (set_attr "pent_pair" "pu")
1890390286Sobrien   (set_attr "memory" "none")
1890490286Sobrien   (set_attr "imm_disp" "false")
1890590286Sobrien   (set_attr "mode" "DI")
1890690286Sobrien   (set_attr "length_immediate" "0")])
1890790286Sobrien
18908169699Skan(define_insn "*movdicc_c_rex64"
1890990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1891090286Sobrien	(if_then_else:DI (match_operator 1 "ix86_comparison_operator" 
18911169699Skan				[(reg FLAGS_REG) (const_int 0)])
1891290286Sobrien		      (match_operand:DI 2 "nonimmediate_operand" "rm,0")
1891390286Sobrien		      (match_operand:DI 3 "nonimmediate_operand" "0,rm")))]
1891490286Sobrien  "TARGET_64BIT && TARGET_CMOVE
1891590286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1891690286Sobrien  "@
1891796294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1891896294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1891990286Sobrien  [(set_attr "type" "icmov")
1892090286Sobrien   (set_attr "mode" "DI")])
1892190286Sobrien
1892290286Sobrien(define_expand "movsicc"
1892390286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1892490286Sobrien	(if_then_else:SI (match_operand 1 "comparison_operator" "")
1892590286Sobrien			 (match_operand:SI 2 "general_operand" "")
1892690286Sobrien			 (match_operand:SI 3 "general_operand" "")))]
1892790286Sobrien  ""
1892890286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1892990286Sobrien
1893090286Sobrien;; Data flow gets confused by our desire for `sbbl reg,reg', and clearing
1893190286Sobrien;; the register first winds up with `sbbl $0,reg', which is also weird.
1893290286Sobrien;; So just document what we're doing explicitly.
1893390286Sobrien
1893490286Sobrien(define_insn "x86_movsicc_0_m1"
1893590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
18936132727Skan	(if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "")
1893790286Sobrien	  (const_int -1)
1893890286Sobrien	  (const_int 0)))
18939169699Skan   (clobber (reg:CC FLAGS_REG))]
1894090286Sobrien  ""
1894190286Sobrien  "sbb{l}\t%0, %0"
1894290286Sobrien  ; Since we don't have the proper number of operands for an alu insn,
1894390286Sobrien  ; fill in all the blanks.
1894490286Sobrien  [(set_attr "type" "alu")
18945117404Skan   (set_attr "pent_pair" "pu")
1894690286Sobrien   (set_attr "memory" "none")
1894790286Sobrien   (set_attr "imm_disp" "false")
1894890286Sobrien   (set_attr "mode" "SI")
1894990286Sobrien   (set_attr "length_immediate" "0")])
1895090286Sobrien
1895190286Sobrien(define_insn "*movsicc_noc"
1895250650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
1895390286Sobrien	(if_then_else:SI (match_operator 1 "ix86_comparison_operator" 
18954169699Skan				[(reg FLAGS_REG) (const_int 0)])
1895550650Sobrien		      (match_operand:SI 2 "nonimmediate_operand" "rm,0")
1895650650Sobrien		      (match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
1895790286Sobrien  "TARGET_CMOVE
1895890286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1895990286Sobrien  "@
1896096294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1896196294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1896290286Sobrien  [(set_attr "type" "icmov")
1896390286Sobrien   (set_attr "mode" "SI")])
1896450650Sobrien
1896550650Sobrien(define_expand "movhicc"
1896650650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
1896750650Sobrien	(if_then_else:HI (match_operand 1 "comparison_operator" "")
18968132727Skan			 (match_operand:HI 2 "general_operand" "")
18969132727Skan			 (match_operand:HI 3 "general_operand" "")))]
18970132727Skan  "TARGET_HIMODE_MATH"
1897190286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1897250650Sobrien
1897390286Sobrien(define_insn "*movhicc_noc"
1897450650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
1897590286Sobrien	(if_then_else:HI (match_operator 1 "ix86_comparison_operator" 
18976169699Skan				[(reg FLAGS_REG) (const_int 0)])
1897750650Sobrien		      (match_operand:HI 2 "nonimmediate_operand" "rm,0")
1897850650Sobrien		      (match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
1897990286Sobrien  "TARGET_CMOVE
1898090286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1898190286Sobrien  "@
1898296294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1898396294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1898490286Sobrien  [(set_attr "type" "icmov")
1898590286Sobrien   (set_attr "mode" "HI")])
1898650650Sobrien
18987132727Skan(define_expand "movqicc"
18988132727Skan  [(set (match_operand:QI 0 "register_operand" "")
18989132727Skan	(if_then_else:QI (match_operand 1 "comparison_operator" "")
18990132727Skan			 (match_operand:QI 2 "general_operand" "")
18991132727Skan			 (match_operand:QI 3 "general_operand" "")))]
18992132727Skan  "TARGET_QIMODE_MATH"
18993132727Skan  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
18994132727Skan
18995132727Skan(define_insn_and_split "*movqicc_noc"
18996132727Skan  [(set (match_operand:QI 0 "register_operand" "=r,r")
18997132727Skan	(if_then_else:QI (match_operator 1 "ix86_comparison_operator" 
18998169699Skan				[(match_operand 4 "flags_reg_operand" "")
18999169699Skan				 (const_int 0)])
19000132727Skan		      (match_operand:QI 2 "register_operand" "r,0")
19001132727Skan		      (match_operand:QI 3 "register_operand" "0,r")))]
19002132727Skan  "TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL"
19003132727Skan  "#"
19004132727Skan  "&& reload_completed"
19005132727Skan  [(set (match_dup 0)
19006132727Skan	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
19007132727Skan		      (match_dup 2)
19008132727Skan		      (match_dup 3)))]
19009132727Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
19010132727Skan   operands[2] = gen_lowpart (SImode, operands[2]);
19011132727Skan   operands[3] = gen_lowpart (SImode, operands[3]);"
19012132727Skan  [(set_attr "type" "icmov")
19013132727Skan   (set_attr "mode" "SI")])
19014132727Skan
1901550650Sobrien(define_expand "movsfcc"
1901650650Sobrien  [(set (match_operand:SF 0 "register_operand" "")
1901750650Sobrien	(if_then_else:SF (match_operand 1 "comparison_operator" "")
1901850650Sobrien			 (match_operand:SF 2 "register_operand" "")
1901950650Sobrien			 (match_operand:SF 3 "register_operand" "")))]
19020169699Skan  "(TARGET_80387 && TARGET_CMOVE) || TARGET_SSE_MATH"
1902190286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1902250650Sobrien
19023169699Skan(define_insn "*movsfcc_1_387"
19024169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f,r,r")
1902590286Sobrien	(if_then_else:SF (match_operator 1 "fcmov_comparison_operator" 
19026169699Skan				[(reg FLAGS_REG) (const_int 0)])
19027169699Skan		      (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0")
19028169699Skan		      (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))]
19029169699Skan  "TARGET_80387 && TARGET_CMOVE
1903090286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1903190286Sobrien  "@
1903290286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1903390286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1903496294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1903596294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1903690286Sobrien  [(set_attr "type" "fcmov,fcmov,icmov,icmov")
1903790286Sobrien   (set_attr "mode" "SF,SF,SI,SI")])
1903850650Sobrien
1903990286Sobrien(define_expand "movdfcc"
1904090286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
1904190286Sobrien	(if_then_else:DF (match_operand 1 "comparison_operator" "")
1904290286Sobrien			 (match_operand:DF 2 "register_operand" "")
1904390286Sobrien			 (match_operand:DF 3 "register_operand" "")))]
19044169699Skan  "(TARGET_80387 && TARGET_CMOVE) || (TARGET_SSE2 && TARGET_SSE_MATH)"
1904590286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1904650650Sobrien
1904790286Sobrien(define_insn "*movdfcc_1"
19048169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r")
1904990286Sobrien	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
19050169699Skan				[(reg FLAGS_REG) (const_int 0)])
19051169699Skan		      (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
19052169699Skan		      (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
19053169699Skan  "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
1905490286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1905590286Sobrien  "@
1905690286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1905790286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1905890286Sobrien   #
1905990286Sobrien   #"
1906090286Sobrien  [(set_attr "type" "fcmov,fcmov,multi,multi")
1906190286Sobrien   (set_attr "mode" "DF")])
1906250650Sobrien
1906390286Sobrien(define_insn "*movdfcc_1_rex64"
19064169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,r,r")
1906590286Sobrien	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
19066169699Skan				[(reg FLAGS_REG) (const_int 0)])
19067169699Skan		      (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
19068169699Skan		      (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
19069169699Skan  "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
1907090286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1907190286Sobrien  "@
1907290286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1907390286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1907496294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1907596294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1907690286Sobrien  [(set_attr "type" "fcmov,fcmov,icmov,icmov")
1907790286Sobrien   (set_attr "mode" "DF")])
1907850650Sobrien
1907990286Sobrien(define_split
19080117404Skan  [(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "")
1908190286Sobrien	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
19082169699Skan				[(match_operand 4 "flags_reg_operand" "")
19083169699Skan				 (const_int 0)])
1908490286Sobrien		      (match_operand:DF 2 "nonimmediate_operand" "")
1908590286Sobrien		      (match_operand:DF 3 "nonimmediate_operand" "")))]
19086117404Skan  "!TARGET_64BIT && reload_completed"
1908790286Sobrien  [(set (match_dup 2)
1908890286Sobrien	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
1908990286Sobrien		      (match_dup 5)
1909090286Sobrien		      (match_dup 7)))
1909190286Sobrien   (set (match_dup 3)
1909290286Sobrien	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
1909390286Sobrien		      (match_dup 6)
1909490286Sobrien		      (match_dup 8)))]
1909590286Sobrien  "split_di (operands+2, 1, operands+5, operands+6);
1909690286Sobrien   split_di (operands+3, 1, operands+7, operands+8);
1909790286Sobrien   split_di (operands, 1, operands+2, operands+3);")
1909850650Sobrien
1909990286Sobrien(define_expand "movxfcc"
1910090286Sobrien  [(set (match_operand:XF 0 "register_operand" "")
1910190286Sobrien	(if_then_else:XF (match_operand 1 "comparison_operator" "")
1910290286Sobrien			 (match_operand:XF 2 "register_operand" "")
1910390286Sobrien			 (match_operand:XF 3 "register_operand" "")))]
19104169699Skan  "TARGET_80387 && TARGET_CMOVE"
1910590286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1910690286Sobrien
1910790286Sobrien(define_insn "*movxfcc_1"
1910890286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1910990286Sobrien	(if_then_else:XF (match_operator 1 "fcmov_comparison_operator" 
19110169699Skan				[(reg FLAGS_REG) (const_int 0)])
1911190286Sobrien		      (match_operand:XF 2 "register_operand" "f,0")
1911290286Sobrien		      (match_operand:XF 3 "register_operand" "0,f")))]
19113169699Skan  "TARGET_80387 && TARGET_CMOVE"
1911490286Sobrien  "@
1911590286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1911690286Sobrien   fcmov%f1\t{%3, %0|%0, %3}"
1911790286Sobrien  [(set_attr "type" "fcmov")
1911890286Sobrien   (set_attr "mode" "XF")])
1911990286Sobrien
19120169699Skan;; These versions of the min/max patterns are intentionally ignorant of
19121169699Skan;; their behavior wrt -0.0 and NaN (via the commutative operand mark).
19122169699Skan;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
19123169699Skan;; are undefined in this condition, we're certain this is correct.
1912490286Sobrien
19125169699Skan(define_insn "sminsf3"
19126169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19127169699Skan	(smin:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
19128169699Skan		 (match_operand:SF 2 "nonimmediate_operand" "xm")))]
19129169699Skan  "TARGET_SSE_MATH"
19130169699Skan  "minss\t{%2, %0|%0, %2}"
19131169699Skan  [(set_attr "type" "sseadd")
19132169699Skan   (set_attr "mode" "SF")])
1913350650Sobrien
19134169699Skan(define_insn "smaxsf3"
19135169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19136169699Skan	(smax:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
19137169699Skan		 (match_operand:SF 2 "nonimmediate_operand" "xm")))]
19138169699Skan  "TARGET_SSE_MATH"
19139169699Skan  "maxss\t{%2, %0|%0, %2}"
19140169699Skan  [(set_attr "type" "sseadd")
19141169699Skan   (set_attr "mode" "SF")])
1914250650Sobrien
19143169699Skan(define_insn "smindf3"
19144169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19145169699Skan	(smin:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
19146169699Skan		 (match_operand:DF 2 "nonimmediate_operand" "xm")))]
19147169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19148169699Skan  "minsd\t{%2, %0|%0, %2}"
19149169699Skan  [(set_attr "type" "sseadd")
19150169699Skan   (set_attr "mode" "DF")])
1915150650Sobrien
19152169699Skan(define_insn "smaxdf3"
19153169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19154169699Skan	(smax:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
19155169699Skan		 (match_operand:DF 2 "nonimmediate_operand" "xm")))]
19156169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19157169699Skan  "maxsd\t{%2, %0|%0, %2}"
19158169699Skan  [(set_attr "type" "sseadd")
19159169699Skan   (set_attr "mode" "DF")])
19160169699Skan
19161169699Skan;; These versions of the min/max patterns implement exactly the operations
19162169699Skan;;   min = (op1 < op2 ? op1 : op2)
19163169699Skan;;   max = (!(op1 < op2) ? op1 : op2)
19164169699Skan;; Their operands are not commutative, and thus they may be used in the
19165169699Skan;; presence of -0.0 and NaN.
19166169699Skan
19167169699Skan(define_insn "*ieee_sminsf3"
19168169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19169169699Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")
19170169699Skan		    (match_operand:SF 2 "nonimmediate_operand" "xm")]
19171169699Skan		   UNSPEC_IEEE_MIN))]
19172169699Skan  "TARGET_SSE_MATH"
19173169699Skan  "minss\t{%2, %0|%0, %2}"
19174169699Skan  [(set_attr "type" "sseadd")
19175169699Skan   (set_attr "mode" "SF")])
19176169699Skan
19177169699Skan(define_insn "*ieee_smaxsf3"
19178169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19179169699Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")
19180169699Skan		    (match_operand:SF 2 "nonimmediate_operand" "xm")]
19181169699Skan		   UNSPEC_IEEE_MAX))]
19182169699Skan  "TARGET_SSE_MATH"
19183169699Skan  "maxss\t{%2, %0|%0, %2}"
19184169699Skan  [(set_attr "type" "sseadd")
19185169699Skan   (set_attr "mode" "SF")])
19186169699Skan
19187169699Skan(define_insn "*ieee_smindf3"
19188169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19189169699Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")
19190169699Skan		    (match_operand:DF 2 "nonimmediate_operand" "xm")]
19191169699Skan		   UNSPEC_IEEE_MIN))]
19192169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19193169699Skan  "minsd\t{%2, %0|%0, %2}"
19194169699Skan  [(set_attr "type" "sseadd")
19195169699Skan   (set_attr "mode" "DF")])
19196169699Skan
19197169699Skan(define_insn "*ieee_smaxdf3"
19198169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19199169699Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")
19200169699Skan		    (match_operand:DF 2 "nonimmediate_operand" "xm")]
19201169699Skan		   UNSPEC_IEEE_MAX))]
19202169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19203169699Skan  "maxsd\t{%2, %0|%0, %2}"
19204169699Skan  [(set_attr "type" "sseadd")
19205169699Skan   (set_attr "mode" "DF")])
19206169699Skan
19207169699Skan;; Make two stack loads independent:
19208169699Skan;;   fld aa              fld aa
19209169699Skan;;   fld %st(0)     ->   fld bb
19210169699Skan;;   fmul bb             fmul %st(1), %st
19211169699Skan;;
19212169699Skan;; Actually we only match the last two instructions for simplicity.
19213169699Skan(define_peephole2
19214169699Skan  [(set (match_operand 0 "fp_register_operand" "")
19215169699Skan	(match_operand 1 "fp_register_operand" ""))
19216169699Skan   (set (match_dup 0)
19217169699Skan	(match_operator 2 "binary_fp_operator"
19218169699Skan	   [(match_dup 0)
19219169699Skan	    (match_operand 3 "memory_operand" "")]))]
19220169699Skan  "REGNO (operands[0]) != REGNO (operands[1])"
19221169699Skan  [(set (match_dup 0) (match_dup 3))
19222169699Skan   (set (match_dup 0) (match_dup 4))]
19223169699Skan
19224169699Skan  ;; The % modifier is not operational anymore in peephole2's, so we have to
19225169699Skan  ;; swap the operands manually in the case of addition and multiplication.
19226169699Skan  "if (COMMUTATIVE_ARITH_P (operands[2]))
19227169699Skan     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
19228169699Skan				 operands[0], operands[1]);
19229169699Skan   else
19230169699Skan     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
19231169699Skan				 operands[1], operands[0]);")
19232169699Skan
19233132727Skan;; Conditional addition patterns
19234132727Skan(define_expand "addqicc"
19235132727Skan  [(match_operand:QI 0 "register_operand" "")
19236132727Skan   (match_operand 1 "comparison_operator" "")
19237132727Skan   (match_operand:QI 2 "register_operand" "")
19238132727Skan   (match_operand:QI 3 "const_int_operand" "")]
19239132727Skan  ""
19240132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19241132727Skan
19242132727Skan(define_expand "addhicc"
19243132727Skan  [(match_operand:HI 0 "register_operand" "")
19244132727Skan   (match_operand 1 "comparison_operator" "")
19245132727Skan   (match_operand:HI 2 "register_operand" "")
19246132727Skan   (match_operand:HI 3 "const_int_operand" "")]
19247132727Skan  ""
19248132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19249132727Skan
19250132727Skan(define_expand "addsicc"
19251132727Skan  [(match_operand:SI 0 "register_operand" "")
19252132727Skan   (match_operand 1 "comparison_operator" "")
19253132727Skan   (match_operand:SI 2 "register_operand" "")
19254132727Skan   (match_operand:SI 3 "const_int_operand" "")]
19255132727Skan  ""
19256132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19257132727Skan
19258132727Skan(define_expand "adddicc"
19259132727Skan  [(match_operand:DI 0 "register_operand" "")
19260132727Skan   (match_operand 1 "comparison_operator" "")
19261132727Skan   (match_operand:DI 2 "register_operand" "")
19262132727Skan   (match_operand:DI 3 "const_int_operand" "")]
19263132727Skan  "TARGET_64BIT"
19264132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19265132727Skan
1926690286Sobrien
1926790286Sobrien;; Misc patterns (?)
1926850650Sobrien
1926990286Sobrien;; This pattern exists to put a dependency on all ebp-based memory accesses.
1927090286Sobrien;; Otherwise there will be nothing to keep
1927190286Sobrien;; 
1927290286Sobrien;; [(set (reg ebp) (reg esp))]
1927390286Sobrien;; [(set (reg esp) (plus (reg esp) (const_int -160000)))
1927490286Sobrien;;  (clobber (eflags)]
1927590286Sobrien;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))]
1927690286Sobrien;;
1927790286Sobrien;; in proper program order.
19278132727Skan(define_insn "pro_epilogue_adjust_stack_1"
1927990286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
1928090286Sobrien	(plus:SI (match_operand:SI 1 "register_operand" "0,r")
1928190286Sobrien	         (match_operand:SI 2 "immediate_operand" "i,i")))
19282169699Skan   (clobber (reg:CC FLAGS_REG))
1928390286Sobrien   (clobber (mem:BLK (scratch)))]
1928490286Sobrien  "!TARGET_64BIT"
1928590286Sobrien{
1928690286Sobrien  switch (get_attr_type (insn))
1928790286Sobrien    {
1928890286Sobrien    case TYPE_IMOV:
1928990286Sobrien      return "mov{l}\t{%1, %0|%0, %1}";
1929050650Sobrien
1929190286Sobrien    case TYPE_ALU:
1929290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
1929390286Sobrien          && (INTVAL (operands[2]) == 128
1929490286Sobrien	      || (INTVAL (operands[2]) < 0
1929590286Sobrien	          && INTVAL (operands[2]) != -128)))
1929690286Sobrien	{
1929790286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
1929890286Sobrien	  return "sub{l}\t{%2, %0|%0, %2}";
1929990286Sobrien	}
1930090286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
1930150650Sobrien
1930290286Sobrien    case TYPE_LEA:
1930390286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
1930490286Sobrien      return "lea{l}\t{%a2, %0|%0, %a2}";
1930590286Sobrien
1930690286Sobrien    default:
19307169699Skan      gcc_unreachable ();
1930890286Sobrien    }
1930990286Sobrien}
1931090286Sobrien  [(set (attr "type")
1931190286Sobrien	(cond [(eq_attr "alternative" "0")
1931290286Sobrien		 (const_string "alu")
1931390286Sobrien	       (match_operand:SI 2 "const0_operand" "")
1931490286Sobrien		 (const_string "imov")
1931590286Sobrien	      ]
1931690286Sobrien	      (const_string "lea")))
1931790286Sobrien   (set_attr "mode" "SI")])
1931890286Sobrien
1931990286Sobrien(define_insn "pro_epilogue_adjust_stack_rex64"
1932090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1932190286Sobrien	(plus:DI (match_operand:DI 1 "register_operand" "0,r")
1932290286Sobrien		 (match_operand:DI 2 "x86_64_immediate_operand" "e,e")))
19323169699Skan   (clobber (reg:CC FLAGS_REG))
1932490286Sobrien   (clobber (mem:BLK (scratch)))]
1932590286Sobrien  "TARGET_64BIT"
1932690286Sobrien{
1932790286Sobrien  switch (get_attr_type (insn))
1932850650Sobrien    {
1932990286Sobrien    case TYPE_IMOV:
1933090286Sobrien      return "mov{q}\t{%1, %0|%0, %1}";
1933150650Sobrien
1933290286Sobrien    case TYPE_ALU:
1933390286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
19334132727Skan	  /* Avoid overflows.  */
19335132727Skan	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
1933690286Sobrien          && (INTVAL (operands[2]) == 128
1933790286Sobrien	      || (INTVAL (operands[2]) < 0
1933890286Sobrien	          && INTVAL (operands[2]) != -128)))
1933990286Sobrien	{
1934090286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
1934190286Sobrien	  return "sub{q}\t{%2, %0|%0, %2}";
1934290286Sobrien	}
1934390286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
1934450650Sobrien
1934590286Sobrien    case TYPE_LEA:
1934690286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
1934790286Sobrien      return "lea{q}\t{%a2, %0|%0, %a2}";
1934850650Sobrien
1934950650Sobrien    default:
19350169699Skan      gcc_unreachable ();
1935150650Sobrien    }
1935290286Sobrien}
1935390286Sobrien  [(set (attr "type")
1935490286Sobrien	(cond [(eq_attr "alternative" "0")
1935590286Sobrien		 (const_string "alu")
1935690286Sobrien	       (match_operand:DI 2 "const0_operand" "")
1935790286Sobrien		 (const_string "imov")
1935890286Sobrien	      ]
1935990286Sobrien	      (const_string "lea")))
1936090286Sobrien   (set_attr "mode" "DI")])
1936150650Sobrien
19362132727Skan(define_insn "pro_epilogue_adjust_stack_rex64_2"
19363132727Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
19364132727Skan	(plus:DI (match_operand:DI 1 "register_operand" "0,r")
19365132727Skan		 (match_operand:DI 3 "immediate_operand" "i,i")))
19366132727Skan   (use (match_operand:DI 2 "register_operand" "r,r"))
19367169699Skan   (clobber (reg:CC FLAGS_REG))
19368132727Skan   (clobber (mem:BLK (scratch)))]
19369132727Skan  "TARGET_64BIT"
19370132727Skan{
19371132727Skan  switch (get_attr_type (insn))
19372132727Skan    {
19373132727Skan    case TYPE_ALU:
19374132727Skan      return "add{q}\t{%2, %0|%0, %2}";
1937590286Sobrien
19376132727Skan    case TYPE_LEA:
19377132727Skan      operands[2] = gen_rtx_PLUS (DImode, operands[1], operands[2]);
19378132727Skan      return "lea{q}\t{%a2, %0|%0, %a2}";
19379132727Skan
19380132727Skan    default:
19381169699Skan      gcc_unreachable ();
19382132727Skan    }
19383132727Skan}
19384132727Skan  [(set_attr "type" "alu,lea")
19385132727Skan   (set_attr "mode" "DI")])
19386132727Skan
1938790286Sobrien(define_expand "allocate_stack_worker"
1938890286Sobrien  [(match_operand:SI 0 "register_operand" "")]
1938990286Sobrien  "TARGET_STACK_PROBE"
1939090286Sobrien{
19391132727Skan  if (reload_completed)
19392132727Skan    {
19393132727Skan      if (TARGET_64BIT)
19394132727Skan	emit_insn (gen_allocate_stack_worker_rex64_postreload (operands[0]));
19395132727Skan      else
19396132727Skan	emit_insn (gen_allocate_stack_worker_postreload (operands[0]));
19397132727Skan    }
1939890286Sobrien  else
19399132727Skan    {
19400132727Skan      if (TARGET_64BIT)
19401132727Skan	emit_insn (gen_allocate_stack_worker_rex64 (operands[0]));
19402132727Skan      else
19403132727Skan	emit_insn (gen_allocate_stack_worker_1 (operands[0]));
19404132727Skan    }
1940590286Sobrien  DONE;
1940690286Sobrien})
1940750650Sobrien
1940890286Sobrien(define_insn "allocate_stack_worker_1"
19409132727Skan  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
19410132727Skan    UNSPECV_STACK_PROBE)
19411169699Skan   (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
19412132727Skan   (clobber (match_scratch:SI 1 "=0"))
19413169699Skan   (clobber (reg:CC FLAGS_REG))]
1941490286Sobrien  "!TARGET_64BIT && TARGET_STACK_PROBE"
1941590286Sobrien  "call\t__alloca"
1941690286Sobrien  [(set_attr "type" "multi")
1941790286Sobrien   (set_attr "length" "5")])
1941850650Sobrien
19419132727Skan(define_expand "allocate_stack_worker_postreload"
19420132727Skan  [(parallel [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
19421132727Skan				    UNSPECV_STACK_PROBE)
19422169699Skan	      (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
19423132727Skan	      (clobber (match_dup 0))
19424169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19425132727Skan  ""
19426132727Skan  "")
19427132727Skan
1942890286Sobrien(define_insn "allocate_stack_worker_rex64"
19429132727Skan  [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
19430132727Skan    UNSPECV_STACK_PROBE)
19431169699Skan   (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
19432132727Skan   (clobber (match_scratch:DI 1 "=0"))
19433169699Skan   (clobber (reg:CC FLAGS_REG))]
1943490286Sobrien  "TARGET_64BIT && TARGET_STACK_PROBE"
1943590286Sobrien  "call\t__alloca"
1943690286Sobrien  [(set_attr "type" "multi")
1943790286Sobrien   (set_attr "length" "5")])
1943890286Sobrien
19439132727Skan(define_expand "allocate_stack_worker_rex64_postreload"
19440132727Skan  [(parallel [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
19441132727Skan				    UNSPECV_STACK_PROBE)
19442169699Skan	      (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
19443132727Skan	      (clobber (match_dup 0))
19444169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19445132727Skan  ""
19446132727Skan  "")
19447132727Skan
1944850650Sobrien(define_expand "allocate_stack"
1944990286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
19450169699Skan		   (minus:SI (reg:SI SP_REG)
1945190286Sobrien			     (match_operand:SI 1 "general_operand" "")))
19452169699Skan	      (clobber (reg:CC FLAGS_REG))])
19453169699Skan   (parallel [(set (reg:SI SP_REG)
19454169699Skan		   (minus:SI (reg:SI SP_REG) (match_dup 1)))
19455169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1945690286Sobrien  "TARGET_STACK_PROBE"
1945750650Sobrien{
1945850650Sobrien#ifdef CHECK_STACK_LIMIT
1945950650Sobrien  if (GET_CODE (operands[1]) == CONST_INT
1946050650Sobrien      && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
1946150650Sobrien    emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
1946250650Sobrien			   operands[1]));
1946350650Sobrien  else 
1946450650Sobrien#endif
1946550650Sobrien    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
1946650650Sobrien							    operands[1])));
1946750650Sobrien
1946850650Sobrien  emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
1946950650Sobrien  DONE;
1947090286Sobrien})
1947150650Sobrien
1947290286Sobrien(define_expand "builtin_setjmp_receiver"
1947390286Sobrien  [(label_ref (match_operand 0 "" ""))]
1947490286Sobrien  "!TARGET_64BIT && flag_pic"
1947550650Sobrien{
19476169699Skan  if (TARGET_MACHO)
19477169699Skan    {
19478169699Skan      rtx xops[3];
19479169699Skan      rtx picreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
19480169699Skan      rtx label_rtx = gen_label_rtx ();
19481169699Skan      emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx));
19482169699Skan      xops[0] = xops[1] = picreg;
19483169699Skan      xops[2] = gen_rtx_CONST (SImode,
19484169699Skan	          gen_rtx_MINUS (SImode,
19485169699Skan		    gen_rtx_LABEL_REF (SImode, label_rtx),
19486169699Skan		    gen_rtx_SYMBOL_REF (SImode, GOT_SYMBOL_NAME)));
19487169699Skan      ix86_expand_binary_operator (MINUS, SImode, xops);
19488169699Skan    }
19489169699Skan  else
19490169699Skan    emit_insn (gen_set_got (pic_offset_table_rtx));
1949156391Sobrien  DONE;
1949290286Sobrien})
1949390286Sobrien
1949490286Sobrien;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
1949556391Sobrien
1949690286Sobrien(define_split
1949790286Sobrien  [(set (match_operand 0 "register_operand" "")
1949890286Sobrien	(match_operator 3 "promotable_binary_operator"
1949990286Sobrien	   [(match_operand 1 "register_operand" "")
1950090286Sobrien	    (match_operand 2 "aligned_operand" "")]))
19501169699Skan   (clobber (reg:CC FLAGS_REG))]
1950290286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1950390286Sobrien   && ((GET_MODE (operands[0]) == HImode 
19504117404Skan	&& ((!optimize_size && !TARGET_FAST_PREFIX)
19505169699Skan            /* ??? next two lines just !satisfies_constraint_K (...) */
19506117404Skan	    || GET_CODE (operands[2]) != CONST_INT
19507169699Skan	    || satisfies_constraint_K (operands[2])))
1950890286Sobrien       || (GET_MODE (operands[0]) == QImode 
1950990286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1951090286Sobrien  [(parallel [(set (match_dup 0)
1951190286Sobrien		   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
19512169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1951390286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1951490286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);
1951590286Sobrien   if (GET_CODE (operands[3]) != ASHIFT)
1951690286Sobrien     operands[2] = gen_lowpart (SImode, operands[2]);
1951790286Sobrien   PUT_MODE (operands[3], SImode);")
1951890286Sobrien
19519117404Skan; Promote the QImode tests, as i386 has encoding of the AND
19520117404Skan; instruction with 32-bit sign-extended immediate and thus the
19521117404Skan; instruction size is unchanged, except in the %eax case for
19522117404Skan; which it is increased by one byte, hence the ! optimize_size.
1952390286Sobrien(define_split
19524146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19525146906Skan	(match_operator 2 "compare_operator"
19526146906Skan	  [(and (match_operand 3 "aligned_operand" "")
19527146906Skan		(match_operand 4 "const_int_operand" ""))
19528146906Skan	   (const_int 0)]))
19529146906Skan   (set (match_operand 1 "register_operand" "")
19530146906Skan	(and (match_dup 3) (match_dup 4)))]
1953190286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
19532117404Skan   /* Ensure that the operand will remain sign-extended immediate.  */
19533146906Skan   && ix86_match_ccmode (insn, INTVAL (operands[4]) >= 0 ? CCNOmode : CCZmode)
19534117404Skan   && ! optimize_size
19535146906Skan   && ((GET_MODE (operands[1]) == HImode && ! TARGET_FAST_PREFIX)
19536146906Skan       || (GET_MODE (operands[1]) == QImode && TARGET_PROMOTE_QImode))"
19537146906Skan  [(parallel [(set (match_dup 0)
19538146906Skan		   (match_op_dup 2 [(and:SI (match_dup 3) (match_dup 4))
19539146906Skan			            (const_int 0)]))
19540146906Skan	      (set (match_dup 1)
19541146906Skan		   (and:SI (match_dup 3) (match_dup 4)))])]
19542146906Skan{
19543146906Skan  operands[4]
19544146906Skan    = gen_int_mode (INTVAL (operands[4])
19545146906Skan		    & GET_MODE_MASK (GET_MODE (operands[1])), SImode);
19546146906Skan  operands[1] = gen_lowpart (SImode, operands[1]);
19547146906Skan  operands[3] = gen_lowpart (SImode, operands[3]);
19548146906Skan})
1954990286Sobrien
19550117404Skan; Don't promote the QImode tests, as i386 doesn't have encoding of
19551117404Skan; the TEST instruction with 32-bit sign-extended immediate and thus
19552117404Skan; the instruction size would at least double, which is not what we
19553117404Skan; want even with ! optimize_size.
1955490286Sobrien(define_split
19555146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19556146906Skan	(match_operator 1 "compare_operator"
19557146906Skan	  [(and (match_operand:HI 2 "aligned_operand" "")
19558146906Skan		(match_operand:HI 3 "const_int_operand" ""))
19559146906Skan	   (const_int 0)]))]
1956090286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
19561117404Skan   /* Ensure that the operand will remain sign-extended immediate.  */
19562146906Skan   && ix86_match_ccmode (insn, INTVAL (operands[3]) >= 0 ? CCNOmode : CCZmode)
19563117404Skan   && ! TARGET_FAST_PREFIX
19564117404Skan   && ! optimize_size"
19565146906Skan  [(set (match_dup 0)
19566146906Skan	(match_op_dup 1 [(and:SI (match_dup 2) (match_dup 3))
19567146906Skan		         (const_int 0)]))]
19568146906Skan{
19569146906Skan  operands[3]
19570146906Skan    = gen_int_mode (INTVAL (operands[3])
19571146906Skan		    & GET_MODE_MASK (GET_MODE (operands[2])), SImode);
19572146906Skan  operands[2] = gen_lowpart (SImode, operands[2]);
19573146906Skan})
1957490286Sobrien
1957590286Sobrien(define_split
1957690286Sobrien  [(set (match_operand 0 "register_operand" "")
1957790286Sobrien	(neg (match_operand 1 "register_operand" "")))
19578169699Skan   (clobber (reg:CC FLAGS_REG))]
1957990286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1958090286Sobrien   && (GET_MODE (operands[0]) == HImode
1958190286Sobrien       || (GET_MODE (operands[0]) == QImode 
1958290286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1958390286Sobrien  [(parallel [(set (match_dup 0)
1958490286Sobrien		   (neg:SI (match_dup 1)))
19585169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1958690286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1958790286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);")
1958890286Sobrien
1958990286Sobrien(define_split
1959090286Sobrien  [(set (match_operand 0 "register_operand" "")
1959190286Sobrien	(not (match_operand 1 "register_operand" "")))]
1959290286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1959390286Sobrien   && (GET_MODE (operands[0]) == HImode
1959490286Sobrien       || (GET_MODE (operands[0]) == QImode 
1959590286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1959690286Sobrien  [(set (match_dup 0)
1959790286Sobrien	(not:SI (match_dup 1)))]
1959890286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1959990286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);")
1960090286Sobrien
1960190286Sobrien(define_split 
1960290286Sobrien  [(set (match_operand 0 "register_operand" "")
1960390286Sobrien	(if_then_else (match_operator 1 "comparison_operator" 
19604169699Skan				[(reg FLAGS_REG) (const_int 0)])
1960590286Sobrien		      (match_operand 2 "register_operand" "")
1960690286Sobrien		      (match_operand 3 "register_operand" "")))]
1960790286Sobrien  "! TARGET_PARTIAL_REG_STALL && TARGET_CMOVE
1960890286Sobrien   && (GET_MODE (operands[0]) == HImode
1960990286Sobrien       || (GET_MODE (operands[0]) == QImode 
1961090286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1961190286Sobrien  [(set (match_dup 0)
1961290286Sobrien	(if_then_else:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
1961390286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1961490286Sobrien   operands[2] = gen_lowpart (SImode, operands[2]);
1961590286Sobrien   operands[3] = gen_lowpart (SImode, operands[3]);")
1961690286Sobrien			
1961790286Sobrien
1961890286Sobrien;; RTL Peephole optimizations, run before sched2.  These primarily look to
1961990286Sobrien;; transform a complex memory operation into two memory to register operations.
1962090286Sobrien
1962190286Sobrien;; Don't push memory operands
1962290286Sobrien(define_peephole2
1962390286Sobrien  [(set (match_operand:SI 0 "push_operand" "")
1962490286Sobrien	(match_operand:SI 1 "memory_operand" ""))
1962590286Sobrien   (match_scratch:SI 2 "r")]
19626169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19627169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1962890286Sobrien  [(set (match_dup 2) (match_dup 1))
1962990286Sobrien   (set (match_dup 0) (match_dup 2))]
1963090286Sobrien  "")
1963190286Sobrien
1963290286Sobrien(define_peephole2
1963390286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
1963490286Sobrien	(match_operand:DI 1 "memory_operand" ""))
1963590286Sobrien   (match_scratch:DI 2 "r")]
19636169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19637169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1963890286Sobrien  [(set (match_dup 2) (match_dup 1))
1963990286Sobrien   (set (match_dup 0) (match_dup 2))]
1964090286Sobrien  "")
1964190286Sobrien
1964290286Sobrien;; We need to handle SFmode only, because DFmode and XFmode is split to
1964390286Sobrien;; SImode pushes.
1964490286Sobrien(define_peephole2
1964590286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
1964690286Sobrien	(match_operand:SF 1 "memory_operand" ""))
1964790286Sobrien   (match_scratch:SF 2 "r")]
19648169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19649169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1965090286Sobrien  [(set (match_dup 2) (match_dup 1))
1965190286Sobrien   (set (match_dup 0) (match_dup 2))]
1965290286Sobrien  "")
1965390286Sobrien
1965490286Sobrien(define_peephole2
1965590286Sobrien  [(set (match_operand:HI 0 "push_operand" "")
1965690286Sobrien	(match_operand:HI 1 "memory_operand" ""))
1965790286Sobrien   (match_scratch:HI 2 "r")]
19658169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19659169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1966090286Sobrien  [(set (match_dup 2) (match_dup 1))
1966190286Sobrien   (set (match_dup 0) (match_dup 2))]
1966290286Sobrien  "")
1966390286Sobrien
1966490286Sobrien(define_peephole2
1966590286Sobrien  [(set (match_operand:QI 0 "push_operand" "")
1966690286Sobrien	(match_operand:QI 1 "memory_operand" ""))
1966790286Sobrien   (match_scratch:QI 2 "q")]
19668169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19669169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1967090286Sobrien  [(set (match_dup 2) (match_dup 1))
1967190286Sobrien   (set (match_dup 0) (match_dup 2))]
1967290286Sobrien  "")
1967390286Sobrien
1967490286Sobrien;; Don't move an immediate directly to memory when the instruction
1967590286Sobrien;; gets too big.
1967690286Sobrien(define_peephole2
1967790286Sobrien  [(match_scratch:SI 1 "r")
1967890286Sobrien   (set (match_operand:SI 0 "memory_operand" "")
1967990286Sobrien        (const_int 0))]
1968090286Sobrien  "! optimize_size
1968190286Sobrien   && ! TARGET_USE_MOV0
1968290286Sobrien   && TARGET_SPLIT_LONG_MOVES
1968390286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1968490286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1968590286Sobrien  [(parallel [(set (match_dup 1) (const_int 0))
19686169699Skan	      (clobber (reg:CC FLAGS_REG))])
1968790286Sobrien   (set (match_dup 0) (match_dup 1))]
1968890286Sobrien  "")
1968990286Sobrien
1969090286Sobrien(define_peephole2
1969190286Sobrien  [(match_scratch:HI 1 "r")
1969290286Sobrien   (set (match_operand:HI 0 "memory_operand" "")
1969390286Sobrien        (const_int 0))]
1969490286Sobrien  "! optimize_size
1969590286Sobrien   && ! TARGET_USE_MOV0
1969690286Sobrien   && TARGET_SPLIT_LONG_MOVES
1969790286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1969890286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1969990286Sobrien  [(parallel [(set (match_dup 2) (const_int 0))
19700169699Skan	      (clobber (reg:CC FLAGS_REG))])
1970190286Sobrien   (set (match_dup 0) (match_dup 1))]
19702132727Skan  "operands[2] = gen_lowpart (SImode, operands[1]);")
1970390286Sobrien
1970490286Sobrien(define_peephole2
1970590286Sobrien  [(match_scratch:QI 1 "q")
1970690286Sobrien   (set (match_operand:QI 0 "memory_operand" "")
1970790286Sobrien        (const_int 0))]
1970890286Sobrien  "! optimize_size
1970990286Sobrien   && ! TARGET_USE_MOV0
1971090286Sobrien   && TARGET_SPLIT_LONG_MOVES
1971190286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1971290286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1971390286Sobrien  [(parallel [(set (match_dup 2) (const_int 0))
19714169699Skan	      (clobber (reg:CC FLAGS_REG))])
1971590286Sobrien   (set (match_dup 0) (match_dup 1))]
19716132727Skan  "operands[2] = gen_lowpart (SImode, operands[1]);")
1971790286Sobrien
1971890286Sobrien(define_peephole2
1971990286Sobrien  [(match_scratch:SI 2 "r")
1972090286Sobrien   (set (match_operand:SI 0 "memory_operand" "")
1972190286Sobrien        (match_operand:SI 1 "immediate_operand" ""))]
1972290286Sobrien  "! optimize_size
1972390286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1972490286Sobrien   && TARGET_SPLIT_LONG_MOVES"
1972590286Sobrien  [(set (match_dup 2) (match_dup 1))
1972690286Sobrien   (set (match_dup 0) (match_dup 2))]
1972790286Sobrien  "")
1972890286Sobrien
1972990286Sobrien(define_peephole2
1973090286Sobrien  [(match_scratch:HI 2 "r")
1973190286Sobrien   (set (match_operand:HI 0 "memory_operand" "")
1973290286Sobrien        (match_operand:HI 1 "immediate_operand" ""))]
1973390286Sobrien  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
1973490286Sobrien  && TARGET_SPLIT_LONG_MOVES"
1973590286Sobrien  [(set (match_dup 2) (match_dup 1))
1973690286Sobrien   (set (match_dup 0) (match_dup 2))]
1973790286Sobrien  "")
1973890286Sobrien
1973990286Sobrien(define_peephole2
1974090286Sobrien  [(match_scratch:QI 2 "q")
1974190286Sobrien   (set (match_operand:QI 0 "memory_operand" "")
1974290286Sobrien        (match_operand:QI 1 "immediate_operand" ""))]
1974390286Sobrien  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
1974490286Sobrien  && TARGET_SPLIT_LONG_MOVES"
1974590286Sobrien  [(set (match_dup 2) (match_dup 1))
1974690286Sobrien   (set (match_dup 0) (match_dup 2))]
1974790286Sobrien  "")
1974890286Sobrien
1974990286Sobrien;; Don't compare memory with zero, load and use a test instead.
1975090286Sobrien(define_peephole2
19751146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19752146906Skan 	(match_operator 1 "compare_operator"
19753146906Skan	  [(match_operand:SI 2 "memory_operand" "")
19754146906Skan	   (const_int 0)]))
1975590286Sobrien   (match_scratch:SI 3 "r")]
1975690286Sobrien  "ix86_match_ccmode (insn, CCNOmode) && ! optimize_size"
19757146906Skan  [(set (match_dup 3) (match_dup 2))
19758146906Skan   (set (match_dup 0) (match_op_dup 1 [(match_dup 3) (const_int 0)]))]
1975990286Sobrien  "")
1976090286Sobrien
1976190286Sobrien;; NOT is not pairable on Pentium, while XOR is, but one byte longer. 
1976290286Sobrien;; Don't split NOTs with a displacement operand, because resulting XOR
19763132727Skan;; will not be pairable anyway.
1976490286Sobrien;;
19765169699Skan;; On AMD K6, NOT is vector decoded with memory operand that cannot be
1976690286Sobrien;; represented using a modRM byte.  The XOR replacement is long decoded,
1976790286Sobrien;; so this split helps here as well.
1976890286Sobrien;;
1976990286Sobrien;; Note: Can't do this as a regular split because we can't get proper
1977090286Sobrien;; lifetime information then.
1977190286Sobrien
1977290286Sobrien(define_peephole2
1977390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1977490286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
1977590286Sobrien  "!optimize_size
1977690286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
1977790286Sobrien   && ((TARGET_PENTIUM 
1977890286Sobrien        && (GET_CODE (operands[0]) != MEM
1977990286Sobrien            || !memory_displacement_operand (operands[0], SImode)))
1978090286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], SImode)))"
1978190286Sobrien  [(parallel [(set (match_dup 0)
1978290286Sobrien		   (xor:SI (match_dup 1) (const_int -1)))
19783169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1978490286Sobrien  "")
1978590286Sobrien
1978690286Sobrien(define_peephole2
1978790286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1978890286Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
1978990286Sobrien  "!optimize_size
1979090286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
1979190286Sobrien   && ((TARGET_PENTIUM 
1979290286Sobrien        && (GET_CODE (operands[0]) != MEM
1979390286Sobrien            || !memory_displacement_operand (operands[0], HImode)))
1979490286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], HImode)))"
1979590286Sobrien  [(parallel [(set (match_dup 0)
1979690286Sobrien		   (xor:HI (match_dup 1) (const_int -1)))
19797169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1979890286Sobrien  "")
1979990286Sobrien
1980090286Sobrien(define_peephole2
1980190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1980290286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
1980390286Sobrien  "!optimize_size
1980490286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
1980590286Sobrien   && ((TARGET_PENTIUM 
1980690286Sobrien        && (GET_CODE (operands[0]) != MEM
1980790286Sobrien            || !memory_displacement_operand (operands[0], QImode)))
1980890286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], QImode)))"
1980990286Sobrien  [(parallel [(set (match_dup 0)
1981090286Sobrien		   (xor:QI (match_dup 1) (const_int -1)))
19811169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1981290286Sobrien  "")
1981390286Sobrien
1981490286Sobrien;; Non pairable "test imm, reg" instructions can be translated to
1981590286Sobrien;; "and imm, reg" if reg dies.  The "and" form is also shorter (one
1981690286Sobrien;; byte opcode instead of two, have a short form for byte operands),
1981790286Sobrien;; so do it for other CPUs as well.  Given that the value was dead,
1981890286Sobrien;; this should not create any new dependencies.  Pass on the sub-word
1981990286Sobrien;; versions if we're concerned about partial register stalls.
1982090286Sobrien
1982190286Sobrien(define_peephole2
19822146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19823146906Skan	(match_operator 1 "compare_operator"
19824146906Skan	  [(and:SI (match_operand:SI 2 "register_operand" "")
19825146906Skan		   (match_operand:SI 3 "immediate_operand" ""))
19826146906Skan	   (const_int 0)]))]
1982790286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
19828146906Skan   && (true_regnum (operands[2]) != 0
19829169699Skan       || satisfies_constraint_K (operands[3]))
19830146906Skan   && peep2_reg_dead_p (1, operands[2])"
1983190286Sobrien  [(parallel
19832146906Skan     [(set (match_dup 0)
19833146906Skan	   (match_op_dup 1 [(and:SI (match_dup 2) (match_dup 3))
19834146906Skan		            (const_int 0)]))
19835146906Skan      (set (match_dup 2)
19836146906Skan	   (and:SI (match_dup 2) (match_dup 3)))])]
1983790286Sobrien  "")
1983890286Sobrien
1983990286Sobrien;; We don't need to handle HImode case, because it will be promoted to SImode
1984090286Sobrien;; on ! TARGET_PARTIAL_REG_STALL
1984190286Sobrien
1984290286Sobrien(define_peephole2
19843146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19844146906Skan	(match_operator 1 "compare_operator"
19845146906Skan	  [(and:QI (match_operand:QI 2 "register_operand" "")
19846146906Skan		   (match_operand:QI 3 "immediate_operand" ""))
19847146906Skan	   (const_int 0)]))]
1984890286Sobrien  "! TARGET_PARTIAL_REG_STALL
1984990286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
19850146906Skan   && true_regnum (operands[2]) != 0
19851146906Skan   && peep2_reg_dead_p (1, operands[2])"
1985290286Sobrien  [(parallel
19853146906Skan     [(set (match_dup 0)
19854146906Skan	   (match_op_dup 1 [(and:QI (match_dup 2) (match_dup 3))
19855146906Skan		            (const_int 0)]))
19856146906Skan      (set (match_dup 2)
19857146906Skan	   (and:QI (match_dup 2) (match_dup 3)))])]
1985890286Sobrien  "")
1985990286Sobrien
1986090286Sobrien(define_peephole2
19861146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19862146906Skan	(match_operator 1 "compare_operator"
19863146906Skan	  [(and:SI
19864146906Skan	     (zero_extract:SI
19865146906Skan	       (match_operand 2 "ext_register_operand" "")
19866146906Skan	       (const_int 8)
19867146906Skan	       (const_int 8))
19868146906Skan	     (match_operand 3 "const_int_operand" ""))
19869146906Skan	   (const_int 0)]))]
1987090286Sobrien  "! TARGET_PARTIAL_REG_STALL
1987190286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
19872146906Skan   && true_regnum (operands[2]) != 0
19873146906Skan   && peep2_reg_dead_p (1, operands[2])"
19874146906Skan  [(parallel [(set (match_dup 0)
19875146906Skan		   (match_op_dup 1
19876146906Skan		     [(and:SI
19877146906Skan			(zero_extract:SI
19878146906Skan			  (match_dup 2)
19879146906Skan			  (const_int 8)
19880146906Skan			  (const_int 8))
19881146906Skan			(match_dup 3))
19882146906Skan		      (const_int 0)]))
19883146906Skan	      (set (zero_extract:SI (match_dup 2)
1988490286Sobrien				    (const_int 8)
1988590286Sobrien				    (const_int 8))
1988690286Sobrien		   (and:SI 
1988790286Sobrien		     (zero_extract:SI
19888146906Skan		       (match_dup 2)
1988990286Sobrien		       (const_int 8)
1989090286Sobrien		       (const_int 8))
19891146906Skan		     (match_dup 3)))])]
1989290286Sobrien  "")
1989390286Sobrien
1989490286Sobrien;; Don't do logical operations with memory inputs.
1989590286Sobrien(define_peephole2
1989690286Sobrien  [(match_scratch:SI 2 "r")
1989790286Sobrien   (parallel [(set (match_operand:SI 0 "register_operand" "")
1989890286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1989990286Sobrien                     [(match_dup 0)
1990090286Sobrien                      (match_operand:SI 1 "memory_operand" "")]))
19901169699Skan              (clobber (reg:CC FLAGS_REG))])]
1990290286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY"
1990390286Sobrien  [(set (match_dup 2) (match_dup 1))
1990490286Sobrien   (parallel [(set (match_dup 0)
1990590286Sobrien                   (match_op_dup 3 [(match_dup 0) (match_dup 2)]))
19906169699Skan              (clobber (reg:CC FLAGS_REG))])]
1990790286Sobrien  "")
1990890286Sobrien
1990990286Sobrien(define_peephole2
1991090286Sobrien  [(match_scratch:SI 2 "r")
1991190286Sobrien   (parallel [(set (match_operand:SI 0 "register_operand" "")
1991290286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1991390286Sobrien                     [(match_operand:SI 1 "memory_operand" "")
1991490286Sobrien                      (match_dup 0)]))
19915169699Skan              (clobber (reg:CC FLAGS_REG))])]
1991690286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY"
1991790286Sobrien  [(set (match_dup 2) (match_dup 1))
1991890286Sobrien   (parallel [(set (match_dup 0)
1991990286Sobrien                   (match_op_dup 3 [(match_dup 2) (match_dup 0)]))
19920169699Skan              (clobber (reg:CC FLAGS_REG))])]
1992190286Sobrien  "")
1992290286Sobrien
1992390286Sobrien; Don't do logical operations with memory outputs
1992490286Sobrien;
1992590286Sobrien; These two don't make sense for PPro/PII -- we're expanding a 4-uop
1992690286Sobrien; instruction into two 1-uop insns plus a 2-uop insn.  That last has
1992790286Sobrien; the same decoder scheduling characteristics as the original.
1992890286Sobrien
1992990286Sobrien(define_peephole2
1993090286Sobrien  [(match_scratch:SI 2 "r")
1993190286Sobrien   (parallel [(set (match_operand:SI 0 "memory_operand" "")
1993290286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1993390286Sobrien                     [(match_dup 0)
1993490286Sobrien                      (match_operand:SI 1 "nonmemory_operand" "")]))
19935169699Skan              (clobber (reg:CC FLAGS_REG))])]
1993690286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY_WRITE"
1993790286Sobrien  [(set (match_dup 2) (match_dup 0))
1993890286Sobrien   (parallel [(set (match_dup 2)
1993990286Sobrien                   (match_op_dup 3 [(match_dup 2) (match_dup 1)]))
19940169699Skan              (clobber (reg:CC FLAGS_REG))])
1994190286Sobrien   (set (match_dup 0) (match_dup 2))]
1994290286Sobrien  "")
1994390286Sobrien
1994490286Sobrien(define_peephole2
1994590286Sobrien  [(match_scratch:SI 2 "r")
1994690286Sobrien   (parallel [(set (match_operand:SI 0 "memory_operand" "")
1994790286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1994890286Sobrien                     [(match_operand:SI 1 "nonmemory_operand" "")
1994990286Sobrien                      (match_dup 0)]))
19950169699Skan              (clobber (reg:CC FLAGS_REG))])]
1995190286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY_WRITE"
1995290286Sobrien  [(set (match_dup 2) (match_dup 0))
1995390286Sobrien   (parallel [(set (match_dup 2)
1995490286Sobrien                   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
19955169699Skan              (clobber (reg:CC FLAGS_REG))])
1995690286Sobrien   (set (match_dup 0) (match_dup 2))]
1995790286Sobrien  "")
1995890286Sobrien
1995990286Sobrien;; Attempt to always use XOR for zeroing registers.
1996090286Sobrien(define_peephole2
1996190286Sobrien  [(set (match_operand 0 "register_operand" "")
19962169699Skan	(match_operand 1 "const0_operand" ""))]
19963169699Skan  "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
1996490286Sobrien   && (! TARGET_USE_MOV0 || optimize_size)
19965169699Skan   && GENERAL_REG_P (operands[0])
1996690286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1996790286Sobrien  [(parallel [(set (match_dup 0) (const_int 0))
19968169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19969169699Skan{
19970169699Skan  operands[0] = gen_lowpart (word_mode, operands[0]);
19971169699Skan})
1997290286Sobrien
1997390286Sobrien(define_peephole2
1997490286Sobrien  [(set (strict_low_part (match_operand 0 "register_operand" ""))
1997590286Sobrien	(const_int 0))]
1997690286Sobrien  "(GET_MODE (operands[0]) == QImode
1997790286Sobrien    || GET_MODE (operands[0]) == HImode)
1997890286Sobrien   && (! TARGET_USE_MOV0 || optimize_size)
1997990286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1998090286Sobrien  [(parallel [(set (strict_low_part (match_dup 0)) (const_int 0))
19981169699Skan	      (clobber (reg:CC FLAGS_REG))])])
1998290286Sobrien
1998390286Sobrien;; For HI and SI modes, or $-1,reg is smaller than mov $-1,reg.
1998490286Sobrien(define_peephole2
1998590286Sobrien  [(set (match_operand 0 "register_operand" "")
1998690286Sobrien	(const_int -1))]
1998790286Sobrien  "(GET_MODE (operands[0]) == HImode
1998890286Sobrien    || GET_MODE (operands[0]) == SImode 
1998990286Sobrien    || (GET_MODE (operands[0]) == DImode && TARGET_64BIT))
1999090286Sobrien   && (optimize_size || TARGET_PENTIUM)
1999190286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1999290286Sobrien  [(parallel [(set (match_dup 0) (const_int -1))
19993169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19994132727Skan  "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode,
19995132727Skan			      operands[0]);")
1999690286Sobrien
1999790286Sobrien;; Attempt to convert simple leas to adds. These can be created by
1999890286Sobrien;; move expanders.
1999990286Sobrien(define_peephole2
2000090286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2000190286Sobrien  	(plus:SI (match_dup 0)
2000290286Sobrien		 (match_operand:SI 1 "nonmemory_operand" "")))]
2000390286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG)"
2000490286Sobrien  [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
20005169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2000690286Sobrien  "")
2000790286Sobrien
2000890286Sobrien(define_peephole2
2000990286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2001090286Sobrien  	(subreg:SI (plus:DI (match_operand:DI 1 "register_operand" "")
2001190286Sobrien			    (match_operand:DI 2 "nonmemory_operand" "")) 0))]
2001290286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG) && REGNO (operands[0]) == REGNO (operands[1])"
2001390286Sobrien  [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
20014169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2001590286Sobrien  "operands[2] = gen_lowpart (SImode, operands[2]);")
2001690286Sobrien
2001790286Sobrien(define_peephole2
2001890286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
2001990286Sobrien  	(plus:DI (match_dup 0)
2002090286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "")))]
2002190286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG)"
2002290286Sobrien  [(parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
20023169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2002490286Sobrien  "")
2002590286Sobrien
2002690286Sobrien(define_peephole2
2002790286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2002890286Sobrien  	(mult:SI (match_dup 0)
2002990286Sobrien		 (match_operand:SI 1 "const_int_operand" "")))]
2003090286Sobrien  "exact_log2 (INTVAL (operands[1])) >= 0
2003190286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2003290286Sobrien  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
20033169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2003490286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
2003590286Sobrien
2003690286Sobrien(define_peephole2
2003790286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
2003890286Sobrien  	(mult:DI (match_dup 0)
2003990286Sobrien		 (match_operand:DI 1 "const_int_operand" "")))]
2004090286Sobrien  "exact_log2 (INTVAL (operands[1])) >= 0
2004190286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2004290286Sobrien  [(parallel [(set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))
20043169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2004490286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
2004590286Sobrien
2004690286Sobrien(define_peephole2
2004790286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2004890286Sobrien  	(subreg:SI (mult:DI (match_operand:DI 1 "register_operand" "")
2004990286Sobrien		   (match_operand:DI 2 "const_int_operand" "")) 0))]
20050117404Skan  "exact_log2 (INTVAL (operands[2])) >= 0
2005190286Sobrien   && REGNO (operands[0]) == REGNO (operands[1])
2005290286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2005390286Sobrien  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
20054169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2005590286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));")
2005690286Sobrien
2005790286Sobrien;; The ESP adjustments can be done by the push and pop instructions.  Resulting
2005890286Sobrien;; code is shorter, since push is only 1 byte, while add imm, %esp 3 bytes.  On
2005990286Sobrien;; many CPUs it is also faster, since special hardware to avoid esp
2006090286Sobrien;; dependencies is present.
2006190286Sobrien
2006290286Sobrien;; While some of these conversions may be done using splitters, we use peepholes
2006390286Sobrien;; in order to allow combine_stack_adjustments pass to see nonobfuscated RTL.
2006490286Sobrien
2006590286Sobrien;; Convert prologue esp subtractions to push.
2006690286Sobrien;; We need register to push.  In order to keep verify_flow_info happy we have
2006790286Sobrien;; two choices
2006890286Sobrien;; - use scratch and clobber it in order to avoid dependencies
2006990286Sobrien;; - use already live register
2007090286Sobrien;; We can't use the second way right now, since there is no reliable way how to
2007190286Sobrien;; verify that given register is live.  First choice will also most likely in
2007290286Sobrien;; fewer dependencies.  On the place of esp adjustments it is very likely that
2007390286Sobrien;; call clobbered registers are dead.  We may want to use base pointer as an
2007490286Sobrien;; alternative when no register is available later.
2007590286Sobrien
2007690286Sobrien(define_peephole2
2007790286Sobrien  [(match_scratch:SI 0 "r")
20078169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
20079169699Skan	      (clobber (reg:CC FLAGS_REG))
2008090286Sobrien	      (clobber (mem:BLK (scratch)))])]
2008190286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2008290286Sobrien  [(clobber (match_dup 0))
20083169699Skan   (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
2008490286Sobrien	      (clobber (mem:BLK (scratch)))])])
2008590286Sobrien
2008690286Sobrien(define_peephole2
2008790286Sobrien  [(match_scratch:SI 0 "r")
20088169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
20089169699Skan	      (clobber (reg:CC FLAGS_REG))
2009090286Sobrien	      (clobber (mem:BLK (scratch)))])]
2009190286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2009290286Sobrien  [(clobber (match_dup 0))
20093169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
20094169699Skan   (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
2009590286Sobrien	      (clobber (mem:BLK (scratch)))])])
2009690286Sobrien
2009790286Sobrien;; Convert esp subtractions to push.
2009890286Sobrien(define_peephole2
2009990286Sobrien  [(match_scratch:SI 0 "r")
20100169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
20101169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2010290286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2010390286Sobrien  [(clobber (match_dup 0))
20104169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
2010590286Sobrien
2010690286Sobrien(define_peephole2
2010790286Sobrien  [(match_scratch:SI 0 "r")
20108169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
20109169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2011090286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2011190286Sobrien  [(clobber (match_dup 0))
20112169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
20113169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
2011490286Sobrien
2011590286Sobrien;; Convert epilogue deallocator to pop.
2011690286Sobrien(define_peephole2
2011790286Sobrien  [(match_scratch:SI 0 "r")
20118169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
20119169699Skan	      (clobber (reg:CC FLAGS_REG))
2012090286Sobrien	      (clobber (mem:BLK (scratch)))])]
2012190286Sobrien  "optimize_size || !TARGET_ADD_ESP_4"
20122169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20123169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2012490286Sobrien	      (clobber (mem:BLK (scratch)))])]
2012590286Sobrien  "")
2012690286Sobrien
2012790286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2012890286Sobrien;; We use two registers if available.
2012990286Sobrien(define_peephole2
2013090286Sobrien  [(match_scratch:SI 0 "r")
2013190286Sobrien   (match_scratch:SI 1 "r")
20132169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20133169699Skan	      (clobber (reg:CC FLAGS_REG))
2013490286Sobrien	      (clobber (mem:BLK (scratch)))])]
2013590286Sobrien  "optimize_size || !TARGET_ADD_ESP_8"
20136169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20137169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2013890286Sobrien	      (clobber (mem:BLK (scratch)))])
20139169699Skan   (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
20140169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2014190286Sobrien  "")
2014290286Sobrien
2014390286Sobrien(define_peephole2
2014490286Sobrien  [(match_scratch:SI 0 "r")
20145169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20146169699Skan	      (clobber (reg:CC FLAGS_REG))
2014790286Sobrien	      (clobber (mem:BLK (scratch)))])]
2014890286Sobrien  "optimize_size"
20149169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20150169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2015190286Sobrien	      (clobber (mem:BLK (scratch)))])
20152169699Skan   (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20153169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2015490286Sobrien  "")
2015590286Sobrien
2015690286Sobrien;; Convert esp additions to pop.
2015790286Sobrien(define_peephole2
2015890286Sobrien  [(match_scratch:SI 0 "r")
20159169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
20160169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2016190286Sobrien  ""
20162169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20163169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2016490286Sobrien  "")
2016590286Sobrien
2016690286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2016790286Sobrien;; We use two registers if available.
2016890286Sobrien(define_peephole2
2016990286Sobrien  [(match_scratch:SI 0 "r")
2017090286Sobrien   (match_scratch:SI 1 "r")
20171169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20172169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2017390286Sobrien  ""
20174169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20175169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
20176169699Skan   (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
20177169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2017890286Sobrien  "")
2017990286Sobrien
2018090286Sobrien(define_peephole2
2018190286Sobrien  [(match_scratch:SI 0 "r")
20182169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20183169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2018490286Sobrien  "optimize_size"
20185169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20186169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
20187169699Skan   (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20188169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2018990286Sobrien  "")
2019090286Sobrien
2019190286Sobrien;; Convert compares with 1 to shorter inc/dec operations when CF is not
20192146906Skan;; required and register dies.  Similarly for 128 to plus -128.
2019390286Sobrien(define_peephole2
20194146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
20195146906Skan	(match_operator 1 "compare_operator"
20196146906Skan	  [(match_operand 2 "register_operand" "")
20197146906Skan	   (match_operand 3 "const_int_operand" "")]))]
20198146906Skan  "(INTVAL (operands[3]) == -1
20199146906Skan    || INTVAL (operands[3]) == 1
20200146906Skan    || INTVAL (operands[3]) == 128)
20201146906Skan   && ix86_match_ccmode (insn, CCGCmode)
20202146906Skan   && peep2_reg_dead_p (1, operands[2])"
20203146906Skan  [(parallel [(set (match_dup 0)
20204146906Skan		   (match_op_dup 1 [(match_dup 2) (match_dup 3)]))
20205146906Skan	      (clobber (match_dup 2))])]
2020690286Sobrien  "")
2020790286Sobrien
2020890286Sobrien(define_peephole2
2020990286Sobrien  [(match_scratch:DI 0 "r")
20210169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
20211169699Skan	      (clobber (reg:CC FLAGS_REG))
2021290286Sobrien	      (clobber (mem:BLK (scratch)))])]
2021390286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2021490286Sobrien  [(clobber (match_dup 0))
20215169699Skan   (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
2021690286Sobrien	      (clobber (mem:BLK (scratch)))])])
2021790286Sobrien
2021890286Sobrien(define_peephole2
2021990286Sobrien  [(match_scratch:DI 0 "r")
20220169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
20221169699Skan	      (clobber (reg:CC FLAGS_REG))
2022290286Sobrien	      (clobber (mem:BLK (scratch)))])]
2022390286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2022490286Sobrien  [(clobber (match_dup 0))
20225169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
20226169699Skan   (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
2022790286Sobrien	      (clobber (mem:BLK (scratch)))])])
2022890286Sobrien
2022990286Sobrien;; Convert esp subtractions to push.
2023090286Sobrien(define_peephole2
2023190286Sobrien  [(match_scratch:DI 0 "r")
20232169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
20233169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2023490286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2023590286Sobrien  [(clobber (match_dup 0))
20236169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
2023790286Sobrien
2023890286Sobrien(define_peephole2
2023990286Sobrien  [(match_scratch:DI 0 "r")
20240169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
20241169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2024290286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2024390286Sobrien  [(clobber (match_dup 0))
20244169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
20245169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
2024690286Sobrien
2024790286Sobrien;; Convert epilogue deallocator to pop.
2024890286Sobrien(define_peephole2
2024990286Sobrien  [(match_scratch:DI 0 "r")
20250169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
20251169699Skan	      (clobber (reg:CC FLAGS_REG))
2025290286Sobrien	      (clobber (mem:BLK (scratch)))])]
2025390286Sobrien  "optimize_size || !TARGET_ADD_ESP_4"
20254169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20255169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2025690286Sobrien	      (clobber (mem:BLK (scratch)))])]
2025790286Sobrien  "")
2025890286Sobrien
2025990286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2026090286Sobrien;; We use two registers if available.
2026190286Sobrien(define_peephole2
2026290286Sobrien  [(match_scratch:DI 0 "r")
2026390286Sobrien   (match_scratch:DI 1 "r")
20264169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20265169699Skan	      (clobber (reg:CC FLAGS_REG))
2026690286Sobrien	      (clobber (mem:BLK (scratch)))])]
2026790286Sobrien  "optimize_size || !TARGET_ADD_ESP_8"
20268169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20269169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2027090286Sobrien	      (clobber (mem:BLK (scratch)))])
20271169699Skan   (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
20272169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2027390286Sobrien  "")
2027490286Sobrien
2027590286Sobrien(define_peephole2
2027690286Sobrien  [(match_scratch:DI 0 "r")
20277169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20278169699Skan	      (clobber (reg:CC FLAGS_REG))
2027990286Sobrien	      (clobber (mem:BLK (scratch)))])]
2028090286Sobrien  "optimize_size"
20281169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20282169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2028390286Sobrien	      (clobber (mem:BLK (scratch)))])
20284169699Skan   (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20285169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2028690286Sobrien  "")
2028790286Sobrien
2028890286Sobrien;; Convert esp additions to pop.
2028990286Sobrien(define_peephole2
2029090286Sobrien  [(match_scratch:DI 0 "r")
20291169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
20292169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2029390286Sobrien  ""
20294169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20295169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2029690286Sobrien  "")
2029790286Sobrien
2029890286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2029990286Sobrien;; We use two registers if available.
2030090286Sobrien(define_peephole2
2030190286Sobrien  [(match_scratch:DI 0 "r")
2030290286Sobrien   (match_scratch:DI 1 "r")
20303169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20304169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2030590286Sobrien  ""
20306169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20307169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
20308169699Skan   (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
20309169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2031090286Sobrien  "")
2031190286Sobrien
2031290286Sobrien(define_peephole2
2031390286Sobrien  [(match_scratch:DI 0 "r")
20314169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20315169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2031690286Sobrien  "optimize_size"
20317169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20318169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
20319169699Skan   (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20320169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2032190286Sobrien  "")
2032290286Sobrien
20323169699Skan;; Convert imul by three, five and nine into lea
20324169699Skan(define_peephole2
20325169699Skan  [(parallel
20326169699Skan    [(set (match_operand:SI 0 "register_operand" "")
20327169699Skan	  (mult:SI (match_operand:SI 1 "register_operand" "")
20328169699Skan		   (match_operand:SI 2 "const_int_operand" "")))
20329169699Skan     (clobber (reg:CC FLAGS_REG))])]
20330169699Skan  "INTVAL (operands[2]) == 3
20331169699Skan   || INTVAL (operands[2]) == 5
20332169699Skan   || INTVAL (operands[2]) == 9"
20333169699Skan  [(set (match_dup 0)
20334169699Skan        (plus:SI (mult:SI (match_dup 1) (match_dup 2))
20335169699Skan                 (match_dup 1)))]
20336169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20337169699Skan
20338169699Skan(define_peephole2
20339169699Skan  [(parallel
20340169699Skan    [(set (match_operand:SI 0 "register_operand" "")
20341169699Skan          (mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
20342169699Skan                   (match_operand:SI 2 "const_int_operand" "")))
20343169699Skan     (clobber (reg:CC FLAGS_REG))])]
20344169699Skan  "!optimize_size 
20345169699Skan   && (INTVAL (operands[2]) == 3
20346169699Skan       || INTVAL (operands[2]) == 5
20347169699Skan       || INTVAL (operands[2]) == 9)"
20348169699Skan  [(set (match_dup 0) (match_dup 1))
20349169699Skan   (set (match_dup 0)
20350169699Skan        (plus:SI (mult:SI (match_dup 0) (match_dup 2))
20351169699Skan                 (match_dup 0)))]
20352169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20353169699Skan
20354169699Skan(define_peephole2
20355169699Skan  [(parallel
20356169699Skan    [(set (match_operand:DI 0 "register_operand" "")
20357169699Skan	  (mult:DI (match_operand:DI 1 "register_operand" "")
20358169699Skan		   (match_operand:DI 2 "const_int_operand" "")))
20359169699Skan     (clobber (reg:CC FLAGS_REG))])]
20360169699Skan  "TARGET_64BIT
20361169699Skan   && (INTVAL (operands[2]) == 3
20362169699Skan       || INTVAL (operands[2]) == 5
20363169699Skan       || INTVAL (operands[2]) == 9)"
20364169699Skan  [(set (match_dup 0)
20365169699Skan        (plus:DI (mult:DI (match_dup 1) (match_dup 2))
20366169699Skan                 (match_dup 1)))]
20367169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20368169699Skan
20369169699Skan(define_peephole2
20370169699Skan  [(parallel
20371169699Skan    [(set (match_operand:DI 0 "register_operand" "")
20372169699Skan          (mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
20373169699Skan                   (match_operand:DI 2 "const_int_operand" "")))
20374169699Skan     (clobber (reg:CC FLAGS_REG))])]
20375169699Skan  "TARGET_64BIT
20376169699Skan   && !optimize_size 
20377169699Skan   && (INTVAL (operands[2]) == 3
20378169699Skan       || INTVAL (operands[2]) == 5
20379169699Skan       || INTVAL (operands[2]) == 9)"
20380169699Skan  [(set (match_dup 0) (match_dup 1))
20381169699Skan   (set (match_dup 0)
20382169699Skan        (plus:DI (mult:DI (match_dup 0) (match_dup 2))
20383169699Skan                 (match_dup 0)))]
20384169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20385169699Skan
20386132727Skan;; Imul $32bit_imm, mem, reg is vector decoded, while
20387132727Skan;; imul $32bit_imm, reg, reg is direct decoded.
20388132727Skan(define_peephole2
20389132727Skan  [(match_scratch:DI 3 "r")
20390132727Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
20391132727Skan		   (mult:DI (match_operand:DI 1 "memory_operand" "")
20392132727Skan			    (match_operand:DI 2 "immediate_operand" "")))
20393169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20394169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20395169699Skan   && !satisfies_constraint_K (operands[2])"
20396132727Skan  [(set (match_dup 3) (match_dup 1))
20397132727Skan   (parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2)))
20398169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20399132727Skan"")
20400132727Skan
20401132727Skan(define_peephole2
20402132727Skan  [(match_scratch:SI 3 "r")
20403132727Skan   (parallel [(set (match_operand:SI 0 "register_operand" "")
20404132727Skan		   (mult:SI (match_operand:SI 1 "memory_operand" "")
20405132727Skan			    (match_operand:SI 2 "immediate_operand" "")))
20406169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20407169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20408169699Skan   && !satisfies_constraint_K (operands[2])"
20409132727Skan  [(set (match_dup 3) (match_dup 1))
20410132727Skan   (parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2)))
20411169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20412132727Skan"")
20413132727Skan
20414132727Skan(define_peephole2
20415132727Skan  [(match_scratch:SI 3 "r")
20416132727Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
20417132727Skan		   (zero_extend:DI
20418132727Skan		     (mult:SI (match_operand:SI 1 "memory_operand" "")
20419132727Skan			      (match_operand:SI 2 "immediate_operand" ""))))
20420169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20421169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20422169699Skan   && !satisfies_constraint_K (operands[2])"
20423132727Skan  [(set (match_dup 3) (match_dup 1))
20424132727Skan   (parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2))))
20425169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20426132727Skan"")
20427132727Skan
20428132727Skan;; imul $8/16bit_imm, regmem, reg is vector decoded.
20429132727Skan;; Convert it into imul reg, reg
20430132727Skan;; It would be better to force assembler to encode instruction using long
20431132727Skan;; immediate, but there is apparently no way to do so.
20432132727Skan(define_peephole2
20433132727Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
20434132727Skan		   (mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
20435132727Skan			    (match_operand:DI 2 "const_int_operand" "")))
20436169699Skan	      (clobber (reg:CC FLAGS_REG))])
20437132727Skan   (match_scratch:DI 3 "r")]
20438169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20439169699Skan   && satisfies_constraint_K (operands[2])"
20440132727Skan  [(set (match_dup 3) (match_dup 2))
20441132727Skan   (parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3)))
20442169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20443132727Skan{
20444132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20445132727Skan    emit_move_insn (operands[0], operands[1]);
20446132727Skan})
20447132727Skan
20448132727Skan(define_peephole2
20449132727Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
20450132727Skan		   (mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
20451132727Skan			    (match_operand:SI 2 "const_int_operand" "")))
20452169699Skan	      (clobber (reg:CC FLAGS_REG))])
20453132727Skan   (match_scratch:SI 3 "r")]
20454169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20455169699Skan   && satisfies_constraint_K (operands[2])"
20456132727Skan  [(set (match_dup 3) (match_dup 2))
20457132727Skan   (parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3)))
20458169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20459132727Skan{
20460132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20461132727Skan    emit_move_insn (operands[0], operands[1]);
20462132727Skan})
20463132727Skan
20464132727Skan(define_peephole2
20465132727Skan  [(parallel [(set (match_operand:HI 0 "register_operand" "")
20466132727Skan		   (mult:HI (match_operand:HI 1 "nonimmediate_operand" "")
20467132727Skan			    (match_operand:HI 2 "immediate_operand" "")))
20468169699Skan	      (clobber (reg:CC FLAGS_REG))])
20469132727Skan   (match_scratch:HI 3 "r")]
20470169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
20471132727Skan  [(set (match_dup 3) (match_dup 2))
20472132727Skan   (parallel [(set (match_dup 0) (mult:HI (match_dup 0) (match_dup 3)))
20473169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20474132727Skan{
20475132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20476132727Skan    emit_move_insn (operands[0], operands[1]);
20477132727Skan})
20478169699Skan
20479169699Skan;; After splitting up read-modify operations, array accesses with memory
20480169699Skan;; operands might end up in form:
20481169699Skan;;  sall    $2, %eax
20482169699Skan;;  movl    4(%esp), %edx
20483169699Skan;;  addl    %edx, %eax
20484169699Skan;; instead of pre-splitting:
20485169699Skan;;  sall    $2, %eax
20486169699Skan;;  addl    4(%esp), %eax
20487169699Skan;; Turn it into:
20488169699Skan;;  movl    4(%esp), %edx
20489169699Skan;;  leal    (%edx,%eax,4), %eax
20490169699Skan
20491169699Skan(define_peephole2
20492169699Skan  [(parallel [(set (match_operand 0 "register_operand" "")
20493169699Skan		   (ashift (match_operand 1 "register_operand" "")
20494169699Skan			   (match_operand 2 "const_int_operand" "")))
20495169699Skan	       (clobber (reg:CC FLAGS_REG))])
20496169699Skan   (set (match_operand 3 "register_operand")
20497169699Skan        (match_operand 4 "x86_64_general_operand" ""))
20498169699Skan   (parallel [(set (match_operand 5 "register_operand" "")
20499169699Skan		   (plus (match_operand 6 "register_operand" "")
20500169699Skan			 (match_operand 7 "register_operand" "")))
20501169699Skan		   (clobber (reg:CC FLAGS_REG))])]
20502169699Skan  "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
20503169699Skan   /* Validate MODE for lea.  */
20504169699Skan   && ((!TARGET_PARTIAL_REG_STALL
20505169699Skan	&& (GET_MODE (operands[0]) == QImode
20506169699Skan	    || GET_MODE (operands[0]) == HImode))
20507169699Skan       || GET_MODE (operands[0]) == SImode 
20508169699Skan       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
20509169699Skan   /* We reorder load and the shift.  */
20510169699Skan   && !rtx_equal_p (operands[1], operands[3])
20511169699Skan   && !reg_overlap_mentioned_p (operands[0], operands[4])
20512169699Skan   /* Last PLUS must consist of operand 0 and 3.  */
20513169699Skan   && !rtx_equal_p (operands[0], operands[3])
20514169699Skan   && (rtx_equal_p (operands[3], operands[6])
20515169699Skan       || rtx_equal_p (operands[3], operands[7]))
20516169699Skan   && (rtx_equal_p (operands[0], operands[6])
20517169699Skan       || rtx_equal_p (operands[0], operands[7]))
20518169699Skan   /* The intermediate operand 0 must die or be same as output.  */
20519169699Skan   && (rtx_equal_p (operands[0], operands[5])
20520169699Skan       || peep2_reg_dead_p (3, operands[0]))"
20521169699Skan  [(set (match_dup 3) (match_dup 4))
20522169699Skan   (set (match_dup 0) (match_dup 1))]
20523169699Skan{
20524169699Skan  enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
20525169699Skan  int scale = 1 << INTVAL (operands[2]);
20526169699Skan  rtx index = gen_lowpart (Pmode, operands[1]);
20527169699Skan  rtx base = gen_lowpart (Pmode, operands[3]);
20528169699Skan  rtx dest = gen_lowpart (mode, operands[5]);
20529169699Skan
20530169699Skan  operands[1] = gen_rtx_PLUS (Pmode, base,
20531169699Skan  			      gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
20532169699Skan  if (mode != Pmode)
20533169699Skan    operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
20534169699Skan  operands[0] = dest;
20535169699Skan})
20536132727Skan
2053790286Sobrien;; Call-value patterns last so that the wildcard operand does not
2053890286Sobrien;; disrupt insn-recog's switch tables.
2053990286Sobrien
2054090286Sobrien(define_insn "*call_value_pop_0"
2054190286Sobrien  [(set (match_operand 0 "" "")
2054290286Sobrien	(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
2054390286Sobrien	      (match_operand:SI 2 "" "")))
20544169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
2054590286Sobrien			    (match_operand:SI 3 "immediate_operand" "")))]
2054690286Sobrien  "!TARGET_64BIT"
2054790286Sobrien{
2054890286Sobrien  if (SIBLING_CALL_P (insn))
2054990286Sobrien    return "jmp\t%P1";
2055090286Sobrien  else
2055190286Sobrien    return "call\t%P1";
2055290286Sobrien}
2055390286Sobrien  [(set_attr "type" "callv")])
2055490286Sobrien
2055590286Sobrien(define_insn "*call_value_pop_1"
2055690286Sobrien  [(set (match_operand 0 "" "")
2055790286Sobrien	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
2055890286Sobrien	      (match_operand:SI 2 "" "")))
20559169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
2056090286Sobrien			    (match_operand:SI 3 "immediate_operand" "i")))]
2056190286Sobrien  "!TARGET_64BIT"
2056290286Sobrien{
20563169699Skan  if (constant_call_address_operand (operands[1], Pmode))
2056490286Sobrien    {
2056590286Sobrien      if (SIBLING_CALL_P (insn))
2056690286Sobrien	return "jmp\t%P1";
2056790286Sobrien      else
2056890286Sobrien	return "call\t%P1";
2056990286Sobrien    }
2057090286Sobrien  if (SIBLING_CALL_P (insn))
2057190286Sobrien    return "jmp\t%A1";
2057290286Sobrien  else
2057390286Sobrien    return "call\t%A1";
2057490286Sobrien}
2057590286Sobrien  [(set_attr "type" "callv")])
2057690286Sobrien
2057790286Sobrien(define_insn "*call_value_0"
2057890286Sobrien  [(set (match_operand 0 "" "")
2057990286Sobrien	(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
2058090286Sobrien	      (match_operand:SI 2 "" "")))]
2058190286Sobrien  "!TARGET_64BIT"
2058290286Sobrien{
2058390286Sobrien  if (SIBLING_CALL_P (insn))
2058490286Sobrien    return "jmp\t%P1";
2058590286Sobrien  else
2058690286Sobrien    return "call\t%P1";
2058790286Sobrien}
2058890286Sobrien  [(set_attr "type" "callv")])
2058990286Sobrien
2059090286Sobrien(define_insn "*call_value_0_rex64"
2059190286Sobrien  [(set (match_operand 0 "" "")
2059290286Sobrien	(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
2059390286Sobrien	      (match_operand:DI 2 "const_int_operand" "")))]
2059490286Sobrien  "TARGET_64BIT"
2059590286Sobrien{
2059690286Sobrien  if (SIBLING_CALL_P (insn))
2059790286Sobrien    return "jmp\t%P1";
2059890286Sobrien  else
2059990286Sobrien    return "call\t%P1";
2060090286Sobrien}
2060190286Sobrien  [(set_attr "type" "callv")])
2060290286Sobrien
2060390286Sobrien(define_insn "*call_value_1"
2060490286Sobrien  [(set (match_operand 0 "" "")
2060590286Sobrien	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
2060690286Sobrien	      (match_operand:SI 2 "" "")))]
20607132727Skan  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
2060890286Sobrien{
20609169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20610132727Skan    return "call\t%P1";
20611146906Skan  return "call\t%A1";
2061290286Sobrien}
2061390286Sobrien  [(set_attr "type" "callv")])
2061490286Sobrien
20615132727Skan(define_insn "*sibcall_value_1"
20616132727Skan  [(set (match_operand 0 "" "")
20617132727Skan	(call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,c,d,a"))
20618132727Skan	      (match_operand:SI 2 "" "")))]
20619132727Skan  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
20620132727Skan{
20621169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20622132727Skan    return "jmp\t%P1";
20623146906Skan  return "jmp\t%A1";
20624132727Skan}
20625132727Skan  [(set_attr "type" "callv")])
20626132727Skan
2062790286Sobrien(define_insn "*call_value_1_rex64"
2062890286Sobrien  [(set (match_operand 0 "" "")
2062990286Sobrien	(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
2063090286Sobrien	      (match_operand:DI 2 "" "")))]
20631132727Skan  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
2063290286Sobrien{
20633169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20634132727Skan    return "call\t%P1";
20635132727Skan  return "call\t%A1";
2063690286Sobrien}
2063790286Sobrien  [(set_attr "type" "callv")])
20638132727Skan
20639132727Skan(define_insn "*sibcall_value_1_rex64"
20640132727Skan  [(set (match_operand 0 "" "")
20641132727Skan	(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
20642132727Skan	      (match_operand:DI 2 "" "")))]
20643132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
20644132727Skan  "jmp\t%P1"
20645132727Skan  [(set_attr "type" "callv")])
20646132727Skan
20647132727Skan(define_insn "*sibcall_value_1_rex64_v"
20648132727Skan  [(set (match_operand 0 "" "")
20649132727Skan	(call (mem:QI (reg:DI 40))
20650132727Skan	      (match_operand:DI 1 "" "")))]
20651132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
20652132727Skan  "jmp\t*%%r11"
20653132727Skan  [(set_attr "type" "callv")])
2065490286Sobrien
20655169699Skan;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5.
20656169699Skan;; That, however, is usually mapped by the OS to SIGSEGV, which is often 
20657169699Skan;; caught for use by garbage collectors and the like.  Using an insn that
20658169699Skan;; maps to SIGILL makes it more likely the program will rightfully die.
20659169699Skan;; Keeping with tradition, "6" is in honor of #UD.
2066090286Sobrien(define_insn "trap"
20661169699Skan  [(trap_if (const_int 1) (const_int 6))]
2066290286Sobrien  ""
20663169699Skan  { return ASM_SHORT "0x0b0f"; }
20664169699Skan  [(set_attr "length" "2")])
2066590286Sobrien
2066690286Sobrien(define_expand "sse_prologue_save"
2066790286Sobrien  [(parallel [(set (match_operand:BLK 0 "" "")
2066890286Sobrien		   (unspec:BLK [(reg:DI 21)
2066990286Sobrien				(reg:DI 22)
2067090286Sobrien				(reg:DI 23)
2067190286Sobrien				(reg:DI 24)
2067290286Sobrien				(reg:DI 25)
2067390286Sobrien				(reg:DI 26)
2067490286Sobrien				(reg:DI 27)
20675117404Skan				(reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
2067690286Sobrien	      (use (match_operand:DI 1 "register_operand" ""))
2067790286Sobrien	      (use (match_operand:DI 2 "immediate_operand" ""))
2067890286Sobrien	      (use (label_ref:DI (match_operand 3 "" "")))])]
2067990286Sobrien  "TARGET_64BIT"
2068090286Sobrien  "")
2068190286Sobrien
2068290286Sobrien(define_insn "*sse_prologue_save_insn"
2068390286Sobrien  [(set (mem:BLK (plus:DI (match_operand:DI 0 "register_operand" "R")
2068490286Sobrien			  (match_operand:DI 4 "const_int_operand" "n")))
2068590286Sobrien	(unspec:BLK [(reg:DI 21)
2068690286Sobrien		     (reg:DI 22)
2068790286Sobrien		     (reg:DI 23)
2068890286Sobrien		     (reg:DI 24)
2068990286Sobrien		     (reg:DI 25)
2069090286Sobrien		     (reg:DI 26)
2069190286Sobrien		     (reg:DI 27)
20692117404Skan		     (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
2069390286Sobrien   (use (match_operand:DI 1 "register_operand" "r"))
2069490286Sobrien   (use (match_operand:DI 2 "const_int_operand" "i"))
2069590286Sobrien   (use (label_ref:DI (match_operand 3 "" "X")))]
2069690286Sobrien  "TARGET_64BIT
2069790286Sobrien   && INTVAL (operands[4]) + SSE_REGPARM_MAX * 16 - 16 < 128
2069890286Sobrien   && INTVAL (operands[4]) + INTVAL (operands[2]) * 16 >= -128"
2069990286Sobrien  "*
2070090286Sobrien{
2070190286Sobrien  int i;
2070290286Sobrien  operands[0] = gen_rtx_MEM (Pmode,
2070390286Sobrien			     gen_rtx_PLUS (Pmode, operands[0], operands[4]));
2070490286Sobrien  output_asm_insn (\"jmp\\t%A1\", operands);
2070590286Sobrien  for (i = SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--)
2070690286Sobrien    {
2070790286Sobrien      operands[4] = adjust_address (operands[0], DImode, i*16);
2070890286Sobrien      operands[5] = gen_rtx_REG (TImode, SSE_REGNO (i));
2070990286Sobrien      PUT_MODE (operands[4], TImode);
2071090286Sobrien      if (GET_CODE (XEXP (operands[0], 0)) != PLUS)
2071190286Sobrien        output_asm_insn (\"rex\", operands);
2071290286Sobrien      output_asm_insn (\"movaps\\t{%5, %4|%4, %5}\", operands);
2071390286Sobrien    }
20714132727Skan  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
2071590286Sobrien			     CODE_LABEL_NUMBER (operands[3]));
2071690286Sobrien  RET;
2071790286Sobrien}
2071856391Sobrien  "
2071990286Sobrien  [(set_attr "type" "other")
2072090286Sobrien   (set_attr "length_immediate" "0")
2072190286Sobrien   (set_attr "length_address" "0")
2072290286Sobrien   (set_attr "length" "135")
2072390286Sobrien   (set_attr "memory" "store")
2072490286Sobrien   (set_attr "modrm" "0")
2072590286Sobrien   (set_attr "mode" "DI")])
2072690286Sobrien
2072790286Sobrien(define_expand "prefetch"
20728102802Skan  [(prefetch (match_operand 0 "address_operand" "")
2072990286Sobrien	     (match_operand:SI 1 "const_int_operand" "")
2073090286Sobrien	     (match_operand:SI 2 "const_int_operand" ""))]
2073190286Sobrien  "TARGET_PREFETCH_SSE || TARGET_3DNOW"
2073256391Sobrien{
2073390286Sobrien  int rw = INTVAL (operands[1]);
2073490286Sobrien  int locality = INTVAL (operands[2]);
2073590286Sobrien
20736169699Skan  gcc_assert (rw == 0 || rw == 1);
20737169699Skan  gcc_assert (locality >= 0 && locality <= 3);
20738169699Skan  gcc_assert (GET_MODE (operands[0]) == Pmode
20739169699Skan	      || GET_MODE (operands[0]) == VOIDmode);
2074090286Sobrien
2074190286Sobrien  /* Use 3dNOW prefetch in case we are asking for write prefetch not
20742169699Skan     supported by SSE counterpart or the SSE prefetch is not available
2074390286Sobrien     (K6 machines).  Otherwise use SSE prefetch as it allows specifying
2074490286Sobrien     of locality.  */
2074590286Sobrien  if (TARGET_3DNOW && (!TARGET_PREFETCH_SSE || rw))
2074690286Sobrien    operands[2] = GEN_INT (3);
2074790286Sobrien  else
2074890286Sobrien    operands[1] = const0_rtx;
2074990286Sobrien})
2075090286Sobrien
2075190286Sobrien(define_insn "*prefetch_sse"
2075290286Sobrien  [(prefetch (match_operand:SI 0 "address_operand" "p")
2075390286Sobrien	     (const_int 0)
2075490286Sobrien	     (match_operand:SI 1 "const_int_operand" ""))]
20755102802Skan  "TARGET_PREFETCH_SSE && !TARGET_64BIT"
2075690286Sobrien{
2075790286Sobrien  static const char * const patterns[4] = {
2075890286Sobrien   "prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
2075990286Sobrien  };
2076090286Sobrien
2076190286Sobrien  int locality = INTVAL (operands[1]);
20762169699Skan  gcc_assert (locality >= 0 && locality <= 3);
2076390286Sobrien
2076490286Sobrien  return patterns[locality];  
2076590286Sobrien}
20766102802Skan  [(set_attr "type" "sse")
20767102802Skan   (set_attr "memory" "none")])
20768102802Skan
20769102802Skan(define_insn "*prefetch_sse_rex"
20770102802Skan  [(prefetch (match_operand:DI 0 "address_operand" "p")
20771102802Skan	     (const_int 0)
20772102802Skan	     (match_operand:SI 1 "const_int_operand" ""))]
20773102802Skan  "TARGET_PREFETCH_SSE && TARGET_64BIT"
20774102802Skan{
20775102802Skan  static const char * const patterns[4] = {
20776102802Skan   "prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
20777102802Skan  };
20778102802Skan
20779102802Skan  int locality = INTVAL (operands[1]);
20780169699Skan  gcc_assert (locality >= 0 && locality <= 3);
20781102802Skan
20782102802Skan  return patterns[locality];  
20783102802Skan}
20784117404Skan  [(set_attr "type" "sse")
20785117404Skan   (set_attr "memory" "none")])
2078690286Sobrien
2078790286Sobrien(define_insn "*prefetch_3dnow"
2078890286Sobrien  [(prefetch (match_operand:SI 0 "address_operand" "p")
2078990286Sobrien	     (match_operand:SI 1 "const_int_operand" "n")
2079090286Sobrien	     (const_int 3))]
20791102802Skan  "TARGET_3DNOW && !TARGET_64BIT"
2079290286Sobrien{
2079390286Sobrien  if (INTVAL (operands[1]) == 0)
2079490286Sobrien    return "prefetch\t%a0";
2079590286Sobrien  else
2079690286Sobrien    return "prefetchw\t%a0";
2079790286Sobrien}
20798102802Skan  [(set_attr "type" "mmx")
20799102802Skan   (set_attr "memory" "none")])
20800102802Skan
20801102802Skan(define_insn "*prefetch_3dnow_rex"
20802102802Skan  [(prefetch (match_operand:DI 0 "address_operand" "p")
20803102802Skan	     (match_operand:SI 1 "const_int_operand" "n")
20804102802Skan	     (const_int 3))]
20805102802Skan  "TARGET_3DNOW && TARGET_64BIT"
20806102802Skan{
20807102802Skan  if (INTVAL (operands[1]) == 0)
20808102802Skan    return "prefetch\t%a0";
20809102802Skan  else
20810102802Skan    return "prefetchw\t%a0";
20811102802Skan}
20812117404Skan  [(set_attr "type" "mmx")
20813117404Skan   (set_attr "memory" "none")])
20814117404Skan
20815169699Skan(define_expand "stack_protect_set"
20816169699Skan  [(match_operand 0 "memory_operand" "")
20817169699Skan   (match_operand 1 "memory_operand" "")]
20818169699Skan  ""
20819117404Skan{
20820169699Skan#ifdef TARGET_THREAD_SSP_OFFSET
20821169699Skan  if (TARGET_64BIT)
20822169699Skan    emit_insn (gen_stack_tls_protect_set_di (operands[0],
20823169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20824117404Skan  else
20825169699Skan    emit_insn (gen_stack_tls_protect_set_si (operands[0],
20826169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20827169699Skan#else
20828169699Skan  if (TARGET_64BIT)
20829169699Skan    emit_insn (gen_stack_protect_set_di (operands[0], operands[1]));
20830117404Skan  else
20831169699Skan    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
20832169699Skan#endif
20833169699Skan  DONE;
20834169699Skan})
20835117404Skan
20836169699Skan(define_insn "stack_protect_set_si"
20837169699Skan  [(set (match_operand:SI 0 "memory_operand" "=m")
20838169699Skan	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
20839169699Skan   (set (match_scratch:SI 2 "=&r") (const_int 0))
20840169699Skan   (clobber (reg:CC FLAGS_REG))]
20841169699Skan  ""
20842169699Skan  "mov{l}\t{%1, %2|%2, %1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
20843169699Skan  [(set_attr "type" "multi")])
20844117404Skan
20845169699Skan(define_insn "stack_protect_set_di"
20846169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
20847169699Skan	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
20848169699Skan   (set (match_scratch:DI 2 "=&r") (const_int 0))
20849169699Skan   (clobber (reg:CC FLAGS_REG))]
20850169699Skan  "TARGET_64BIT"
20851169699Skan  "mov{q}\t{%1, %2|%2, %1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
20852169699Skan  [(set_attr "type" "multi")])
20853117404Skan
20854169699Skan(define_insn "stack_tls_protect_set_si"
20855117404Skan  [(set (match_operand:SI 0 "memory_operand" "=m")
20856169699Skan	(unspec:SI [(match_operand:SI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
20857169699Skan   (set (match_scratch:SI 2 "=&r") (const_int 0))
20858169699Skan   (clobber (reg:CC FLAGS_REG))]
20859169699Skan  ""
20860169699Skan  "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR %%gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
20861169699Skan  [(set_attr "type" "multi")])
20862117404Skan
20863169699Skan(define_insn "stack_tls_protect_set_di"
20864169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
20865169699Skan	(unspec:DI [(match_operand:DI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
20866169699Skan   (set (match_scratch:DI 2 "=&r") (const_int 0))
20867169699Skan   (clobber (reg:CC FLAGS_REG))]
20868169699Skan  "TARGET_64BIT"
20869169699Skan  {
20870169699Skan     /* The kernel uses a different segment register for performance reasons; a
20871169699Skan        system call would not have to trash the userspace segment register,
20872169699Skan        which would be expensive */
20873169699Skan     if (ix86_cmodel != CM_KERNEL)
20874169699Skan        return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
20875169699Skan     else
20876169699Skan        return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR %%gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
20877169699Skan  }
20878169699Skan  [(set_attr "type" "multi")])
20879117404Skan
20880169699Skan(define_expand "stack_protect_test"
20881169699Skan  [(match_operand 0 "memory_operand" "")
20882169699Skan   (match_operand 1 "memory_operand" "")
20883169699Skan   (match_operand 2 "" "")]
20884169699Skan  ""
20885169699Skan{
20886169699Skan  rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG);
20887169699Skan  ix86_compare_op0 = operands[0];
20888169699Skan  ix86_compare_op1 = operands[1];
20889169699Skan  ix86_compare_emitted = flags;
20890117404Skan
20891169699Skan#ifdef TARGET_THREAD_SSP_OFFSET
20892169699Skan  if (TARGET_64BIT)
20893169699Skan    emit_insn (gen_stack_tls_protect_test_di (flags, operands[0],
20894169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20895132727Skan  else
20896169699Skan    emit_insn (gen_stack_tls_protect_test_si (flags, operands[0],
20897169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20898169699Skan#else
20899169699Skan  if (TARGET_64BIT)
20900169699Skan    emit_insn (gen_stack_protect_test_di (flags, operands[0], operands[1]));
20901169699Skan  else
20902169699Skan    emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1]));
20903169699Skan#endif
20904169699Skan  emit_jump_insn (gen_beq (operands[2]));
20905117404Skan  DONE;
20906117404Skan})
20907117404Skan
20908169699Skan(define_insn "stack_protect_test_si"
20909169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20910169699Skan	(unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
20911169699Skan		     (match_operand:SI 2 "memory_operand" "m")]
20912169699Skan		    UNSPEC_SP_TEST))
20913169699Skan   (clobber (match_scratch:SI 3 "=&r"))]
20914169699Skan  ""
20915169699Skan  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%2, %3|%3, %2}"
20916169699Skan  [(set_attr "type" "multi")])
20917117404Skan
20918169699Skan(define_insn "stack_protect_test_di"
20919169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20920169699Skan	(unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
20921169699Skan		     (match_operand:DI 2 "memory_operand" "m")]
20922169699Skan		    UNSPEC_SP_TEST))
20923169699Skan   (clobber (match_scratch:DI 3 "=&r"))]
20924169699Skan  "TARGET_64BIT"
20925169699Skan  "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%2, %3|%3, %2}"
20926169699Skan  [(set_attr "type" "multi")])
20927117404Skan
20928169699Skan(define_insn "stack_tls_protect_test_si"
20929169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20930169699Skan	(unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
20931169699Skan		     (match_operand:SI 2 "const_int_operand" "i")]
20932169699Skan		    UNSPEC_SP_TLS_TEST))
20933169699Skan   (clobber (match_scratch:SI 3 "=r"))]
20934169699Skan  ""
20935169699Skan  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR %%gs:%P2}"
20936169699Skan  [(set_attr "type" "multi")])
20937117404Skan
20938169699Skan(define_insn "stack_tls_protect_test_di"
20939169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20940169699Skan	(unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
20941169699Skan		     (match_operand:DI 2 "const_int_operand" "i")]
20942169699Skan		    UNSPEC_SP_TLS_TEST))
20943169699Skan   (clobber (match_scratch:DI 3 "=r"))]
20944169699Skan  "TARGET_64BIT"
20945169699Skan  {
20946169699Skan     /* The kernel uses a different segment register for performance reasons; a
20947169699Skan        system call would not have to trash the userspace segment register,
20948169699Skan        which would be expensive */
20949169699Skan     if (ix86_cmodel != CM_KERNEL)
20950169699Skan        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}";
20951169699Skan     else
20952169699Skan        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR %%gs:%P2}";
20953169699Skan  }
20954169699Skan  [(set_attr "type" "multi")])
20955117404Skan
20956219639Smm(include "mmx.md")
20957169699Skan(include "sse.md")
20958169699Skan(include "sync.md")
20959