i386.md revision 171835
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)
151117404Skan  ])
152117404Skan
153117404Skan(define_constants
154117404Skan  [(UNSPECV_BLOCKAGE		0)
155169699Skan   (UNSPECV_STACK_PROBE		1)
156169699Skan   (UNSPECV_EMMS		2)
157169699Skan   (UNSPECV_LDMXCSR		3)
158169699Skan   (UNSPECV_STMXCSR		4)
159169699Skan   (UNSPECV_FEMMS		5)
160169699Skan   (UNSPECV_CLFLUSH		6)
161169699Skan   (UNSPECV_ALIGN		7)
162169699Skan   (UNSPECV_MONITOR		8)
163169699Skan   (UNSPECV_MWAIT		9)
164169699Skan   (UNSPECV_CMPXCHG_1		10)
165169699Skan   (UNSPECV_CMPXCHG_2		11)
166169699Skan   (UNSPECV_XCHG		12)
167169699Skan   (UNSPECV_LOCK		13)
168117404Skan  ])
169117404Skan
170169699Skan;; Registers by name.
171169699Skan(define_constants
172169699Skan  [(BP_REG			 6)
173169699Skan   (SP_REG			 7)
174169699Skan   (FLAGS_REG			17)
175169699Skan   (FPSR_REG			18)
176169699Skan   (DIRFLAG_REG			19)
177169699Skan  ])
178169699Skan
17990286Sobrien;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
18090286Sobrien;; from i386.c.
18190286Sobrien
18290286Sobrien;; In C guard expressions, put expressions which may be compile-time
18390286Sobrien;; constants first.  This allows for better optimization.  For
18490286Sobrien;; example, write "TARGET_64BIT && reload_completed", not
18590286Sobrien;; "reload_completed && TARGET_64BIT".
18690286Sobrien
18718334Speter
18890286Sobrien;; Processor type.  This attribute must exactly match the processor_type
18990286Sobrien;; enumeration in i386.h.
190169699Skan(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8,nocona,generic32,generic64"
191132727Skan  (const (symbol_ref "ix86_tune")))
19250650Sobrien
19390286Sobrien;; A basic instruction type.  Refinements due to arguments to be
19490286Sobrien;; provided in other attributes.
19552296Sobrien(define_attr "type"
196117404Skan  "other,multi,
197117404Skan   alu,alu1,negnot,imov,imovx,lea,
198117404Skan   incdec,ishift,ishift1,rotate,rotate1,imul,idiv,
199117404Skan   icmp,test,ibr,setcc,icmov,
200132727Skan   push,pop,call,callv,leave,
201117404Skan   str,cld,
202169699Skan   fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
203169699Skan   sselog,sselog1,sseiadd,sseishft,sseimul,
204132727Skan   sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,
205117404Skan   mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
20690286Sobrien  (const_string "other"))
20750650Sobrien
20890286Sobrien;; Main data type used by the insn
209117404Skan(define_attr "mode"
210169699Skan  "unknown,none,QI,HI,SI,DI,SF,DF,XF,TI,V4SF,V2DF,V2SF,V1DF"
21190286Sobrien  (const_string "unknown"))
21252296Sobrien
213117404Skan;; The CPU unit operations uses.
214117404Skan(define_attr "unit" "integer,i387,sse,mmx,unknown"
215169699Skan  (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint")
216117404Skan	   (const_string "i387")
217169699Skan	 (eq_attr "type" "sselog,sselog1,sseiadd,sseishft,sseimul,
218132727Skan			  sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv")
219117404Skan	   (const_string "sse")
220117404Skan	 (eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft")
221117404Skan	   (const_string "mmx")
222117404Skan	 (eq_attr "type" "other")
223117404Skan	   (const_string "unknown")]
224117404Skan	 (const_string "integer")))
22552296Sobrien
22690286Sobrien;; The (bounding maximum) length of an instruction immediate.
22790286Sobrien(define_attr "length_immediate" ""
228132727Skan  (cond [(eq_attr "type" "incdec,setcc,icmov,str,cld,lea,other,multi,idiv,leave")
22990286Sobrien	   (const_int 0)
230117404Skan	 (eq_attr "unit" "i387,sse,mmx")
23190286Sobrien	   (const_int 0)
232117404Skan	 (eq_attr "type" "alu,alu1,negnot,imovx,ishift,rotate,ishift1,rotate1,
233117404Skan			  imul,icmp,push,pop")
23490286Sobrien	   (symbol_ref "ix86_attr_length_immediate_default(insn,1)")
23590286Sobrien	 (eq_attr "type" "imov,test")
23690286Sobrien	   (symbol_ref "ix86_attr_length_immediate_default(insn,0)")
23790286Sobrien	 (eq_attr "type" "call")
23890286Sobrien	   (if_then_else (match_operand 0 "constant_call_address_operand" "")
23990286Sobrien	     (const_int 4)
24090286Sobrien	     (const_int 0))
24190286Sobrien	 (eq_attr "type" "callv")
24290286Sobrien	   (if_then_else (match_operand 1 "constant_call_address_operand" "")
24390286Sobrien	     (const_int 4)
24490286Sobrien	     (const_int 0))
245117404Skan	 ;; We don't know the size before shorten_branches.  Expect
246117404Skan	 ;; the instruction to fit for better scheduling.
24790286Sobrien	 (eq_attr "type" "ibr")
248117404Skan	   (const_int 1)
24990286Sobrien	 ]
250117404Skan	 (symbol_ref "/* Update immediate_length and other attributes! */
251169699Skan		      gcc_unreachable (),1")))
25252296Sobrien
25390286Sobrien;; The (bounding maximum) length of an instruction address.
25490286Sobrien(define_attr "length_address" ""
25590286Sobrien  (cond [(eq_attr "type" "str,cld,other,multi,fxch")
25690286Sobrien	   (const_int 0)
25790286Sobrien	 (and (eq_attr "type" "call")
258117404Skan	      (match_operand 0 "constant_call_address_operand" ""))
25990286Sobrien	     (const_int 0)
26090286Sobrien	 (and (eq_attr "type" "callv")
26190286Sobrien	      (match_operand 1 "constant_call_address_operand" ""))
26290286Sobrien	     (const_int 0)
26390286Sobrien	 ]
26490286Sobrien	 (symbol_ref "ix86_attr_length_address_default (insn)")))
26552296Sobrien
26690286Sobrien;; Set when length prefix is used.
26790286Sobrien(define_attr "prefix_data16" ""
268117404Skan  (if_then_else (ior (eq_attr "mode" "HI")
269117404Skan		     (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF")))
27090286Sobrien    (const_int 1)
27190286Sobrien    (const_int 0)))
27252296Sobrien
27390286Sobrien;; Set when string REP prefix is used.
274117404Skan(define_attr "prefix_rep" "" 
275117404Skan  (if_then_else (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
276117404Skan    (const_int 1)
277117404Skan    (const_int 0)))
27852296Sobrien
27990286Sobrien;; Set when 0f opcode prefix is used.
28090286Sobrien(define_attr "prefix_0f" ""
281117404Skan  (if_then_else 
282132727Skan    (ior (eq_attr "type" "imovx,setcc,icmov")
283132727Skan	 (eq_attr "unit" "sse,mmx"))
28490286Sobrien    (const_int 1)
28590286Sobrien    (const_int 0)))
28652296Sobrien
287169699Skan;; Set when REX opcode prefix is used.
288132727Skan(define_attr "prefix_rex" ""
289132727Skan  (cond [(and (eq_attr "mode" "DI")
290132727Skan  	      (eq_attr "type" "!push,pop,call,callv,leave,ibr"))
291132727Skan	   (const_int 1)
292132727Skan	 (and (eq_attr "mode" "QI")
293132727Skan	      (ne (symbol_ref "x86_extended_QIreg_mentioned_p (insn)")
294132727Skan		  (const_int 0)))
295132727Skan	   (const_int 1)
296132727Skan	 (ne (symbol_ref "x86_extended_reg_mentioned_p (insn)")
297132727Skan	     (const_int 0))
298132727Skan	   (const_int 1)
299132727Skan	]
300132727Skan	(const_int 0)))
301132727Skan
30290286Sobrien;; Set when modrm byte is used.
30390286Sobrien(define_attr "modrm" ""
304132727Skan  (cond [(eq_attr "type" "str,cld,leave")
30590286Sobrien	   (const_int 0)
306117404Skan	 (eq_attr "unit" "i387")
30790286Sobrien	   (const_int 0)
30890286Sobrien         (and (eq_attr "type" "incdec")
30990286Sobrien	      (ior (match_operand:SI 1 "register_operand" "")
31090286Sobrien		   (match_operand:HI 1 "register_operand" "")))
31190286Sobrien	   (const_int 0)
31290286Sobrien	 (and (eq_attr "type" "push")
31390286Sobrien	      (not (match_operand 1 "memory_operand" "")))
31490286Sobrien	   (const_int 0)
31590286Sobrien	 (and (eq_attr "type" "pop")
31690286Sobrien	      (not (match_operand 0 "memory_operand" "")))
31790286Sobrien	   (const_int 0)
31890286Sobrien	 (and (eq_attr "type" "imov")
319169699Skan	      (ior (and (match_operand 0 "register_operand" "")
320169699Skan			(match_operand 1 "immediate_operand" ""))
321169699Skan		   (ior (and (match_operand 0 "ax_reg_operand" "")
322169699Skan			     (match_operand 1 "memory_displacement_only_operand" ""))
323169699Skan			(and (match_operand 0 "memory_displacement_only_operand" "")
324169699Skan			     (match_operand 1 "ax_reg_operand" "")))))
32590286Sobrien	   (const_int 0)
326117404Skan	 (and (eq_attr "type" "call")
327117404Skan	      (match_operand 0 "constant_call_address_operand" ""))
328117404Skan	     (const_int 0)
329117404Skan	 (and (eq_attr "type" "callv")
330117404Skan	      (match_operand 1 "constant_call_address_operand" ""))
331117404Skan	     (const_int 0)
33290286Sobrien	 ]
33390286Sobrien	 (const_int 1)))
33490286Sobrien
33590286Sobrien;; The (bounding maximum) length of an instruction in bytes.
336169699Skan;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences.
337169699Skan;; Later we may want to split them and compute proper length as for
338169699Skan;; other insns.
33990286Sobrien(define_attr "length" ""
340169699Skan  (cond [(eq_attr "type" "other,multi,fistp,frndint")
34190286Sobrien	   (const_int 16)
342117404Skan	 (eq_attr "type" "fcmp")
343117404Skan	   (const_int 4)
344117404Skan	 (eq_attr "unit" "i387")
345117404Skan	   (plus (const_int 2)
346117404Skan		 (plus (attr "prefix_data16")
347117404Skan		       (attr "length_address")))]
34890286Sobrien	 (plus (plus (attr "modrm")
34990286Sobrien		     (plus (attr "prefix_0f")
350132727Skan			   (plus (attr "prefix_rex")
351132727Skan				 (const_int 1))))
35290286Sobrien	       (plus (attr "prefix_rep")
35390286Sobrien		     (plus (attr "prefix_data16")
35490286Sobrien			   (plus (attr "length_immediate")
35590286Sobrien				 (attr "length_address")))))))
35690286Sobrien
35790286Sobrien;; The `memory' attribute is `none' if no memory is referenced, `load' or
35890286Sobrien;; `store' if there is a simple memory reference therein, or `unknown'
35990286Sobrien;; if the instruction is complex.
36090286Sobrien
36190286Sobrien(define_attr "memory" "none,load,store,both,unknown"
36290286Sobrien  (cond [(eq_attr "type" "other,multi,str")
36390286Sobrien	   (const_string "unknown")
36490286Sobrien	 (eq_attr "type" "lea,fcmov,fpspc,cld")
36590286Sobrien	   (const_string "none")
366132727Skan	 (eq_attr "type" "fistp,leave")
36790286Sobrien	   (const_string "both")
368169699Skan	 (eq_attr "type" "frndint")
369169699Skan	   (const_string "load")
37090286Sobrien	 (eq_attr "type" "push")
37190286Sobrien	   (if_then_else (match_operand 1 "memory_operand" "")
37290286Sobrien	     (const_string "both")
37390286Sobrien	     (const_string "store"))
374132727Skan	 (eq_attr "type" "pop")
37590286Sobrien	   (if_then_else (match_operand 0 "memory_operand" "")
37690286Sobrien	     (const_string "both")
37790286Sobrien	     (const_string "load"))
378132727Skan	 (eq_attr "type" "setcc")
379132727Skan	   (if_then_else (match_operand 0 "memory_operand" "")
380132727Skan	     (const_string "store")
381132727Skan	     (const_string "none"))
382132727Skan	 (eq_attr "type" "icmp,test,ssecmp,ssecomi,mmxcmp,fcmp")
38390286Sobrien	   (if_then_else (ior (match_operand 0 "memory_operand" "")
38490286Sobrien			      (match_operand 1 "memory_operand" ""))
38590286Sobrien	     (const_string "load")
38690286Sobrien	     (const_string "none"))
38790286Sobrien	 (eq_attr "type" "ibr")
38890286Sobrien	   (if_then_else (match_operand 0 "memory_operand" "")
38990286Sobrien	     (const_string "load")
39090286Sobrien	     (const_string "none"))
39190286Sobrien	 (eq_attr "type" "call")
39290286Sobrien	   (if_then_else (match_operand 0 "constant_call_address_operand" "")
39390286Sobrien	     (const_string "none")
39490286Sobrien	     (const_string "load"))
39590286Sobrien	 (eq_attr "type" "callv")
39690286Sobrien	   (if_then_else (match_operand 1 "constant_call_address_operand" "")
39790286Sobrien	     (const_string "none")
39890286Sobrien	     (const_string "load"))
399169699Skan	 (and (eq_attr "type" "alu1,negnot,ishift1,sselog1")
40090286Sobrien	      (match_operand 1 "memory_operand" ""))
40190286Sobrien	   (const_string "both")
40290286Sobrien	 (and (match_operand 0 "memory_operand" "")
40390286Sobrien	      (match_operand 1 "memory_operand" ""))
40490286Sobrien	   (const_string "both")
40590286Sobrien	 (match_operand 0 "memory_operand" "")
40690286Sobrien	   (const_string "store")
40790286Sobrien	 (match_operand 1 "memory_operand" "")
40890286Sobrien	   (const_string "load")
409117404Skan	 (and (eq_attr "type"
410132727Skan		 "!alu1,negnot,ishift1,
411117404Skan		   imov,imovx,icmp,test,
412117404Skan		   fmov,fcmp,fsgn,
413169699Skan		   sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt,sselog1,
414117404Skan		   mmx,mmxmov,mmxcmp,mmxcvt")
41590286Sobrien	      (match_operand 2 "memory_operand" ""))
41690286Sobrien	   (const_string "load")
41790286Sobrien	 (and (eq_attr "type" "icmov")
41890286Sobrien	      (match_operand 3 "memory_operand" ""))
41990286Sobrien	   (const_string "load")
42090286Sobrien	]
42152296Sobrien	(const_string "none")))
42252296Sobrien
42390286Sobrien;; Indicates if an instruction has both an immediate and a displacement.
42450650Sobrien
42590286Sobrien(define_attr "imm_disp" "false,true,unknown"
42690286Sobrien  (cond [(eq_attr "type" "other,multi")
42790286Sobrien	   (const_string "unknown")
428117404Skan	 (and (eq_attr "type" "icmp,test,imov,alu1,ishift1,rotate1")
42990286Sobrien	      (and (match_operand 0 "memory_displacement_operand" "")
43090286Sobrien		   (match_operand 1 "immediate_operand" "")))
43190286Sobrien	   (const_string "true")
432117404Skan	 (and (eq_attr "type" "alu,ishift,rotate,imul,idiv")
43390286Sobrien	      (and (match_operand 0 "memory_displacement_operand" "")
43490286Sobrien		   (match_operand 2 "immediate_operand" "")))
43590286Sobrien	   (const_string "true")
43690286Sobrien	]
43790286Sobrien	(const_string "false")))
43850650Sobrien
43990286Sobrien;; Indicates if an FP operation has an integer source.
44050650Sobrien
44190286Sobrien(define_attr "fp_int_src" "false,true"
44290286Sobrien  (const_string "false"))
44350650Sobrien
444169699Skan;; Defines rounding mode of an FP operation.
445169699Skan
446169699Skan(define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any"
447169699Skan  (const_string "any"))
448169699Skan
44990286Sobrien;; Describe a user's asm statement.
45090286Sobrien(define_asm_attributes
45190286Sobrien  [(set_attr "length" "128")
45290286Sobrien   (set_attr "type" "multi")])
453169699Skan
454169699Skan;; All x87 floating point modes
455169699Skan(define_mode_macro X87MODEF [SF DF XF])
456169699Skan 
457169699Skan;; All integer modes handled by x87 fisttp operator.
458169699Skan(define_mode_macro X87MODEI [HI SI DI])
459169699Skan
460169699Skan;; All integer modes handled by integer x87 operators.
461169699Skan(define_mode_macro X87MODEI12 [HI SI])
462169699Skan
463169699Skan;; All SSE floating point modes
464169699Skan(define_mode_macro SSEMODEF [SF DF])
465169699Skan 
466169699Skan;; All integer modes handled by SSE cvtts?2si* operators.
467169699Skan(define_mode_macro SSEMODEI24 [SI DI])
468169699Skan
46990286Sobrien
470169699Skan;; Scheduling descriptions
471169699Skan
472117404Skan(include "pentium.md")
473117404Skan(include "ppro.md")
474117404Skan(include "k6.md")
475117404Skan(include "athlon.md")
476169699Skan
47790286Sobrien
478169699Skan;; Operand and operator predicates and constraints
479169699Skan
480169699Skan(include "predicates.md")
481169699Skan(include "constraints.md")
482169699Skan
483169699Skan
48490286Sobrien;; Compare instructions.
48590286Sobrien
48690286Sobrien;; All compare insns have expanders that save the operands away without
48790286Sobrien;; actually generating RTL.  The bCOND or sCOND (emitted immediately
48890286Sobrien;; after the cmp) will actually emit the cmpM.
48990286Sobrien
490169699Skan(define_expand "cmpti"
491169699Skan  [(set (reg:CC FLAGS_REG)
492169699Skan	(compare:CC (match_operand:TI 0 "nonimmediate_operand" "")
493169699Skan		    (match_operand:TI 1 "x86_64_general_operand" "")))]
494169699Skan  "TARGET_64BIT"
495169699Skan{
496169699Skan  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
497169699Skan    operands[0] = force_reg (TImode, operands[0]);
498169699Skan  ix86_compare_op0 = operands[0];
499169699Skan  ix86_compare_op1 = operands[1];
500169699Skan  DONE;
501169699Skan})
502169699Skan
50390286Sobrien(define_expand "cmpdi"
504169699Skan  [(set (reg:CC FLAGS_REG)
50590286Sobrien	(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
50690286Sobrien		    (match_operand:DI 1 "x86_64_general_operand" "")))]
50790286Sobrien  ""
50818334Speter{
50990286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
51090286Sobrien    operands[0] = force_reg (DImode, operands[0]);
51190286Sobrien  ix86_compare_op0 = operands[0];
51290286Sobrien  ix86_compare_op1 = operands[1];
51318334Speter  DONE;
51490286Sobrien})
51518334Speter
51618334Speter(define_expand "cmpsi"
517169699Skan  [(set (reg:CC FLAGS_REG)
51890286Sobrien	(compare:CC (match_operand:SI 0 "cmpsi_operand" "")
51990286Sobrien		    (match_operand:SI 1 "general_operand" "")))]
52018334Speter  ""
52118334Speter{
52218334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
52318334Speter    operands[0] = force_reg (SImode, operands[0]);
52490286Sobrien  ix86_compare_op0 = operands[0];
52590286Sobrien  ix86_compare_op1 = operands[1];
52618334Speter  DONE;
52790286Sobrien})
52818334Speter
52918334Speter(define_expand "cmphi"
530169699Skan  [(set (reg:CC FLAGS_REG)
53190286Sobrien	(compare:CC (match_operand:HI 0 "nonimmediate_operand" "")
53290286Sobrien		    (match_operand:HI 1 "general_operand" "")))]
53318334Speter  ""
53418334Speter{
53518334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
53618334Speter    operands[0] = force_reg (HImode, operands[0]);
53790286Sobrien  ix86_compare_op0 = operands[0];
53890286Sobrien  ix86_compare_op1 = operands[1];
53918334Speter  DONE;
54090286Sobrien})
54118334Speter
54218334Speter(define_expand "cmpqi"
543169699Skan  [(set (reg:CC FLAGS_REG)
54490286Sobrien	(compare:CC (match_operand:QI 0 "nonimmediate_operand" "")
54590286Sobrien		    (match_operand:QI 1 "general_operand" "")))]
54690286Sobrien  "TARGET_QIMODE_MATH"
54718334Speter{
54818334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
54918334Speter    operands[0] = force_reg (QImode, operands[0]);
55090286Sobrien  ix86_compare_op0 = operands[0];
55190286Sobrien  ix86_compare_op1 = operands[1];
55218334Speter  DONE;
55390286Sobrien})
55418334Speter
55590286Sobrien(define_insn "cmpdi_ccno_1_rex64"
556169699Skan  [(set (reg FLAGS_REG)
55790286Sobrien	(compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")
55890286Sobrien		 (match_operand:DI 1 "const0_operand" "n,n")))]
55990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
56090286Sobrien  "@
56190286Sobrien   test{q}\t{%0, %0|%0, %0}
56290286Sobrien   cmp{q}\t{%1, %0|%0, %1}"
56390286Sobrien  [(set_attr "type" "test,icmp")
56490286Sobrien   (set_attr "length_immediate" "0,1")
56590286Sobrien   (set_attr "mode" "DI")])
56618334Speter
56790286Sobrien(define_insn "*cmpdi_minus_1_rex64"
568169699Skan  [(set (reg FLAGS_REG)
56990286Sobrien	(compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r")
57090286Sobrien			   (match_operand:DI 1 "x86_64_general_operand" "re,mr"))
57190286Sobrien		 (const_int 0)))]
57290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)"
57390286Sobrien  "cmp{q}\t{%1, %0|%0, %1}"
57490286Sobrien  [(set_attr "type" "icmp")
57590286Sobrien   (set_attr "mode" "DI")])
57618334Speter
57790286Sobrien(define_expand "cmpdi_1_rex64"
578169699Skan  [(set (reg:CC FLAGS_REG)
57990286Sobrien	(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
58090286Sobrien		    (match_operand:DI 1 "general_operand" "")))]
58190286Sobrien  "TARGET_64BIT"
58290286Sobrien  "")
58318334Speter
58490286Sobrien(define_insn "cmpdi_1_insn_rex64"
585169699Skan  [(set (reg FLAGS_REG)
58690286Sobrien	(compare (match_operand:DI 0 "nonimmediate_operand" "mr,r")
58790286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "re,mr")))]
58890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
58990286Sobrien  "cmp{q}\t{%1, %0|%0, %1}"
59090286Sobrien  [(set_attr "type" "icmp")
59190286Sobrien   (set_attr "mode" "DI")])
59250650Sobrien
59318334Speter
59490286Sobrien(define_insn "*cmpsi_ccno_1"
595169699Skan  [(set (reg FLAGS_REG)
59690286Sobrien	(compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
59790286Sobrien		 (match_operand:SI 1 "const0_operand" "n,n")))]
59890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
59990286Sobrien  "@
60090286Sobrien   test{l}\t{%0, %0|%0, %0}
60190286Sobrien   cmp{l}\t{%1, %0|%0, %1}"
60290286Sobrien  [(set_attr "type" "test,icmp")
60390286Sobrien   (set_attr "length_immediate" "0,1")
60490286Sobrien   (set_attr "mode" "SI")])
60550650Sobrien
60690286Sobrien(define_insn "*cmpsi_minus_1"
607169699Skan  [(set (reg FLAGS_REG)
60890286Sobrien	(compare (minus:SI (match_operand:SI 0 "nonimmediate_operand" "rm,r")
60990286Sobrien			   (match_operand:SI 1 "general_operand" "ri,mr"))
61090286Sobrien		 (const_int 0)))]
61190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
61290286Sobrien  "cmp{l}\t{%1, %0|%0, %1}"
61390286Sobrien  [(set_attr "type" "icmp")
61490286Sobrien   (set_attr "mode" "SI")])
61518334Speter
61690286Sobrien(define_expand "cmpsi_1"
617169699Skan  [(set (reg:CC FLAGS_REG)
61890286Sobrien	(compare:CC (match_operand:SI 0 "nonimmediate_operand" "rm,r")
61990286Sobrien		    (match_operand:SI 1 "general_operand" "ri,mr")))]
62090286Sobrien  ""
62190286Sobrien  "")
62218334Speter
62390286Sobrien(define_insn "*cmpsi_1_insn"
624169699Skan  [(set (reg FLAGS_REG)
62590286Sobrien	(compare (match_operand:SI 0 "nonimmediate_operand" "rm,r")
62690286Sobrien		 (match_operand:SI 1 "general_operand" "ri,mr")))]
62790286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
62890286Sobrien    && ix86_match_ccmode (insn, CCmode)"
62990286Sobrien  "cmp{l}\t{%1, %0|%0, %1}"
63090286Sobrien  [(set_attr "type" "icmp")
63190286Sobrien   (set_attr "mode" "SI")])
63218334Speter
63390286Sobrien(define_insn "*cmphi_ccno_1"
634169699Skan  [(set (reg FLAGS_REG)
63590286Sobrien	(compare (match_operand:HI 0 "nonimmediate_operand" "r,?mr")
63690286Sobrien		 (match_operand:HI 1 "const0_operand" "n,n")))]
63790286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
63890286Sobrien  "@
63990286Sobrien   test{w}\t{%0, %0|%0, %0}
64090286Sobrien   cmp{w}\t{%1, %0|%0, %1}"
64190286Sobrien  [(set_attr "type" "test,icmp")
64290286Sobrien   (set_attr "length_immediate" "0,1")
64390286Sobrien   (set_attr "mode" "HI")])
64418334Speter
64590286Sobrien(define_insn "*cmphi_minus_1"
646169699Skan  [(set (reg FLAGS_REG)
64790286Sobrien	(compare (minus:HI (match_operand:HI 0 "nonimmediate_operand" "rm,r")
64890286Sobrien			   (match_operand:HI 1 "general_operand" "ri,mr"))
64990286Sobrien		 (const_int 0)))]
65090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
65190286Sobrien  "cmp{w}\t{%1, %0|%0, %1}"
65290286Sobrien  [(set_attr "type" "icmp")
65390286Sobrien   (set_attr "mode" "HI")])
65450650Sobrien
65590286Sobrien(define_insn "*cmphi_1"
656169699Skan  [(set (reg FLAGS_REG)
65790286Sobrien	(compare (match_operand:HI 0 "nonimmediate_operand" "rm,r")
65890286Sobrien		 (match_operand:HI 1 "general_operand" "ri,mr")))]
65990286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
66090286Sobrien   && ix86_match_ccmode (insn, CCmode)"
66190286Sobrien  "cmp{w}\t{%1, %0|%0, %1}"
66290286Sobrien  [(set_attr "type" "icmp")
66390286Sobrien   (set_attr "mode" "HI")])
66418334Speter
66590286Sobrien(define_insn "*cmpqi_ccno_1"
666169699Skan  [(set (reg FLAGS_REG)
66790286Sobrien	(compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq")
66890286Sobrien		 (match_operand:QI 1 "const0_operand" "n,n")))]
66990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
67090286Sobrien  "@
67190286Sobrien   test{b}\t{%0, %0|%0, %0}
67290286Sobrien   cmp{b}\t{$0, %0|%0, 0}"
67390286Sobrien  [(set_attr "type" "test,icmp")
67490286Sobrien   (set_attr "length_immediate" "0,1")
67590286Sobrien   (set_attr "mode" "QI")])
67618334Speter
67790286Sobrien(define_insn "*cmpqi_1"
678169699Skan  [(set (reg FLAGS_REG)
67990286Sobrien	(compare (match_operand:QI 0 "nonimmediate_operand" "qm,q")
68090286Sobrien		 (match_operand:QI 1 "general_operand" "qi,mq")))]
68190286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
68290286Sobrien    && ix86_match_ccmode (insn, CCmode)"
68390286Sobrien  "cmp{b}\t{%1, %0|%0, %1}"
68490286Sobrien  [(set_attr "type" "icmp")
68590286Sobrien   (set_attr "mode" "QI")])
68618334Speter
68790286Sobrien(define_insn "*cmpqi_minus_1"
688169699Skan  [(set (reg FLAGS_REG)
68990286Sobrien	(compare (minus:QI (match_operand:QI 0 "nonimmediate_operand" "qm,q")
69090286Sobrien			   (match_operand:QI 1 "general_operand" "qi,mq"))
69190286Sobrien		 (const_int 0)))]
69290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
69390286Sobrien  "cmp{b}\t{%1, %0|%0, %1}"
69490286Sobrien  [(set_attr "type" "icmp")
69590286Sobrien   (set_attr "mode" "QI")])
69618334Speter
69790286Sobrien(define_insn "*cmpqi_ext_1"
698169699Skan  [(set (reg FLAGS_REG)
69990286Sobrien	(compare
70090286Sobrien	  (match_operand:QI 0 "general_operand" "Qm")
70190286Sobrien	  (subreg:QI
70290286Sobrien	    (zero_extract:SI
70390286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
70490286Sobrien	      (const_int 8)
70590286Sobrien	      (const_int 8)) 0)))]
70690286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
70790286Sobrien  "cmp{b}\t{%h1, %0|%0, %h1}"
70890286Sobrien  [(set_attr "type" "icmp")
70990286Sobrien   (set_attr "mode" "QI")])
71090286Sobrien
71190286Sobrien(define_insn "*cmpqi_ext_1_rex64"
712169699Skan  [(set (reg FLAGS_REG)
71390286Sobrien	(compare
71490286Sobrien	  (match_operand:QI 0 "register_operand" "Q")
71590286Sobrien	  (subreg:QI
71690286Sobrien	    (zero_extract:SI
71790286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
71890286Sobrien	      (const_int 8)
71990286Sobrien	      (const_int 8)) 0)))]
72090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
72190286Sobrien  "cmp{b}\t{%h1, %0|%0, %h1}"
72290286Sobrien  [(set_attr "type" "icmp")
72390286Sobrien   (set_attr "mode" "QI")])
72490286Sobrien
72590286Sobrien(define_insn "*cmpqi_ext_2"
726169699Skan  [(set (reg FLAGS_REG)
72790286Sobrien	(compare
72890286Sobrien	  (subreg:QI
72990286Sobrien	    (zero_extract:SI
73090286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
73190286Sobrien	      (const_int 8)
73290286Sobrien	      (const_int 8)) 0)
73390286Sobrien	  (match_operand:QI 1 "const0_operand" "n")))]
73490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
73590286Sobrien  "test{b}\t%h0, %h0"
73690286Sobrien  [(set_attr "type" "test")
73790286Sobrien   (set_attr "length_immediate" "0")
73890286Sobrien   (set_attr "mode" "QI")])
73990286Sobrien
74090286Sobrien(define_expand "cmpqi_ext_3"
741169699Skan  [(set (reg:CC FLAGS_REG)
74290286Sobrien	(compare:CC
74390286Sobrien	  (subreg:QI
74490286Sobrien	    (zero_extract:SI
74590286Sobrien	      (match_operand 0 "ext_register_operand" "")
74690286Sobrien	      (const_int 8)
74790286Sobrien	      (const_int 8)) 0)
74890286Sobrien	  (match_operand:QI 1 "general_operand" "")))]
74990286Sobrien  ""
75090286Sobrien  "")
75190286Sobrien
75290286Sobrien(define_insn "cmpqi_ext_3_insn"
753169699Skan  [(set (reg FLAGS_REG)
75490286Sobrien	(compare
75590286Sobrien	  (subreg:QI
75690286Sobrien	    (zero_extract:SI
75790286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
75890286Sobrien	      (const_int 8)
75990286Sobrien	      (const_int 8)) 0)
76090286Sobrien	  (match_operand:QI 1 "general_operand" "Qmn")))]
76190286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
76290286Sobrien  "cmp{b}\t{%1, %h0|%h0, %1}"
76390286Sobrien  [(set_attr "type" "icmp")
76490286Sobrien   (set_attr "mode" "QI")])
76590286Sobrien
76690286Sobrien(define_insn "cmpqi_ext_3_insn_rex64"
767169699Skan  [(set (reg FLAGS_REG)
76890286Sobrien	(compare
76990286Sobrien	  (subreg:QI
77090286Sobrien	    (zero_extract:SI
77190286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
77290286Sobrien	      (const_int 8)
77390286Sobrien	      (const_int 8)) 0)
77490286Sobrien	  (match_operand:QI 1 "nonmemory_operand" "Qn")))]
77590286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
77690286Sobrien  "cmp{b}\t{%1, %h0|%h0, %1}"
77790286Sobrien  [(set_attr "type" "icmp")
77890286Sobrien   (set_attr "mode" "QI")])
77990286Sobrien
78090286Sobrien(define_insn "*cmpqi_ext_4"
781169699Skan  [(set (reg FLAGS_REG)
78290286Sobrien	(compare
78390286Sobrien	  (subreg:QI
78490286Sobrien	    (zero_extract:SI
78590286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
78690286Sobrien	      (const_int 8)
78790286Sobrien	      (const_int 8)) 0)
78890286Sobrien	  (subreg:QI
78990286Sobrien	    (zero_extract:SI
79090286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
79190286Sobrien	      (const_int 8)
79290286Sobrien	      (const_int 8)) 0)))]
79390286Sobrien  "ix86_match_ccmode (insn, CCmode)"
79490286Sobrien  "cmp{b}\t{%h1, %h0|%h0, %h1}"
79590286Sobrien  [(set_attr "type" "icmp")
79690286Sobrien   (set_attr "mode" "QI")])
79790286Sobrien
79890286Sobrien;; These implement float point compares.
79990286Sobrien;; %%% See if we can get away with VOIDmode operands on the actual insns,
80090286Sobrien;; which would allow mix and match FP modes on the compares.  Which is what
80190286Sobrien;; the old patterns did, but with many more of them.
80290286Sobrien
80318334Speter(define_expand "cmpxf"
804169699Skan  [(set (reg:CC FLAGS_REG)
805169699Skan	(compare:CC (match_operand:XF 0 "nonmemory_operand" "")
806169699Skan		    (match_operand:XF 1 "nonmemory_operand" "")))]
80718334Speter  "TARGET_80387"
80818334Speter{
80990286Sobrien  ix86_compare_op0 = operands[0];
81090286Sobrien  ix86_compare_op1 = operands[1];
81118334Speter  DONE;
81290286Sobrien})
81318334Speter
81418334Speter(define_expand "cmpdf"
815169699Skan  [(set (reg:CC FLAGS_REG)
81690286Sobrien	(compare:CC (match_operand:DF 0 "cmp_fp_expander_operand" "")
81790286Sobrien		    (match_operand:DF 1 "cmp_fp_expander_operand" "")))]
818169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
81918334Speter{
82090286Sobrien  ix86_compare_op0 = operands[0];
82190286Sobrien  ix86_compare_op1 = operands[1];
82218334Speter  DONE;
82390286Sobrien})
82418334Speter
82518334Speter(define_expand "cmpsf"
826169699Skan  [(set (reg:CC FLAGS_REG)
82790286Sobrien	(compare:CC (match_operand:SF 0 "cmp_fp_expander_operand" "")
82890286Sobrien		    (match_operand:SF 1 "cmp_fp_expander_operand" "")))]
829169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
83018334Speter{
83190286Sobrien  ix86_compare_op0 = operands[0];
83290286Sobrien  ix86_compare_op1 = operands[1];
83318334Speter  DONE;
83490286Sobrien})
83518334Speter
83690286Sobrien;; FP compares, step 1:
83790286Sobrien;; Set the FP condition codes.
83890286Sobrien;;
83990286Sobrien;; CCFPmode	compare with exceptions
84090286Sobrien;; CCFPUmode	compare with no exceptions
84118334Speter
842169699Skan;; We may not use "#" to split and emit these, since the REG_DEAD notes
843169699Skan;; used to manage the reg stack popping would not be preserved.
84418334Speter
84590286Sobrien(define_insn "*cmpfp_0"
84690286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
84790286Sobrien	(unspec:HI
848169699Skan	  [(compare:CCFP
849169699Skan	     (match_operand 1 "register_operand" "f")
850169699Skan	     (match_operand 2 "const0_operand" "X"))]
851169699Skan	UNSPEC_FNSTSW))]
85290286Sobrien  "TARGET_80387
85390286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
85490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
855169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
85690286Sobrien  [(set_attr "type" "multi")
857169699Skan   (set_attr "unit" "i387")
858132727Skan   (set (attr "mode")
859132727Skan     (cond [(match_operand:SF 1 "" "")
860132727Skan	      (const_string "SF")
861132727Skan	    (match_operand:DF 1 "" "")
862132727Skan	      (const_string "DF")
863132727Skan	   ]
864132727Skan	   (const_string "XF")))])
86590286Sobrien
866169699Skan(define_insn "*cmpfp_sf"
86790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
86890286Sobrien	(unspec:HI
86990286Sobrien	  [(compare:CCFP
87090286Sobrien	     (match_operand:SF 1 "register_operand" "f")
871117404Skan	     (match_operand:SF 2 "nonimmediate_operand" "fm"))]
872117404Skan	  UNSPEC_FNSTSW))]
87318334Speter  "TARGET_80387"
874169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
875169699Skan  [(set_attr "type" "multi")
876169699Skan   (set_attr "unit" "i387")
87790286Sobrien   (set_attr "mode" "SF")])
87818334Speter
879169699Skan(define_insn "*cmpfp_df"
88090286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
88190286Sobrien	(unspec:HI
88290286Sobrien	  [(compare:CCFP
88390286Sobrien	     (match_operand:DF 1 "register_operand" "f")
884117404Skan	     (match_operand:DF 2 "nonimmediate_operand" "fm"))]
885117404Skan	  UNSPEC_FNSTSW))]
88618334Speter  "TARGET_80387"
887169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
88890286Sobrien  [(set_attr "type" "multi")
889169699Skan   (set_attr "unit" "i387")
89090286Sobrien   (set_attr "mode" "DF")])
89118334Speter
892169699Skan(define_insn "*cmpfp_xf"
89390286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
89490286Sobrien	(unspec:HI
89590286Sobrien	  [(compare:CCFP
89690286Sobrien	     (match_operand:XF 1 "register_operand" "f")
897117404Skan	     (match_operand:XF 2 "register_operand" "f"))]
898117404Skan	  UNSPEC_FNSTSW))]
89990286Sobrien  "TARGET_80387"
900169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
90190286Sobrien  [(set_attr "type" "multi")
902169699Skan   (set_attr "unit" "i387")
90390286Sobrien   (set_attr "mode" "XF")])
90418334Speter
905169699Skan(define_insn "*cmpfp_u"
90690286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
90790286Sobrien	(unspec:HI
90890286Sobrien	  [(compare:CCFPU
90990286Sobrien	     (match_operand 1 "register_operand" "f")
910117404Skan	     (match_operand 2 "register_operand" "f"))]
911117404Skan	  UNSPEC_FNSTSW))]
91290286Sobrien  "TARGET_80387
91390286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
91490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
915169699Skan  "* return output_fp_compare (insn, operands, 0, 1);"
91690286Sobrien  [(set_attr "type" "multi")
917169699Skan   (set_attr "unit" "i387")
918132727Skan   (set (attr "mode")
919132727Skan     (cond [(match_operand:SF 1 "" "")
920132727Skan	      (const_string "SF")
921132727Skan	    (match_operand:DF 1 "" "")
922132727Skan	      (const_string "DF")
923132727Skan	   ]
924132727Skan	   (const_string "XF")))])
92518334Speter
926169699Skan(define_insn "*cmpfp_<mode>"
927169699Skan  [(set (match_operand:HI 0 "register_operand" "=a")
928169699Skan	(unspec:HI
929169699Skan	  [(compare:CCFP
930169699Skan	     (match_operand 1 "register_operand" "f")
931169699Skan	     (match_operator 3 "float_operator"
932169699Skan	       [(match_operand:X87MODEI12 2 "memory_operand" "m")]))]
933169699Skan	  UNSPEC_FNSTSW))]
934169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
935169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
936169699Skan   && (GET_MODE (operands [3]) == GET_MODE (operands[1]))"
937169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
938169699Skan  [(set_attr "type" "multi")
939169699Skan   (set_attr "unit" "i387")
940169699Skan   (set_attr "fp_int_src" "true")
941169699Skan   (set_attr "mode" "<MODE>")])
94218334Speter
94390286Sobrien;; FP compares, step 2
94490286Sobrien;; Move the fpsw to ax.
94518334Speter
946169699Skan(define_insn "x86_fnstsw_1"
94790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
948169699Skan	(unspec:HI [(reg:CCFP FPSR_REG)] UNSPEC_FNSTSW))]
94990286Sobrien  "TARGET_80387"
95090286Sobrien  "fnstsw\t%0"
95190286Sobrien  [(set_attr "length" "2")
95290286Sobrien   (set_attr "mode" "SI")
953169699Skan   (set_attr "unit" "i387")])
95418334Speter
95590286Sobrien;; FP compares, step 3
95690286Sobrien;; Get ax into flags, general case.
95750650Sobrien
95890286Sobrien(define_insn "x86_sahf_1"
959169699Skan  [(set (reg:CC FLAGS_REG)
960117404Skan	(unspec:CC [(match_operand:HI 0 "register_operand" "a")] UNSPEC_SAHF))]
96190286Sobrien  "!TARGET_64BIT"
96290286Sobrien  "sahf"
96390286Sobrien  [(set_attr "length" "1")
96490286Sobrien   (set_attr "athlon_decode" "vector")
965169699Skan   (set_attr "mode" "SI")])
96618334Speter
96790286Sobrien;; Pentium Pro can do steps 1 through 3 in one go.
96818334Speter
969169699Skan(define_insn "*cmpfp_i_mixed"
970169699Skan  [(set (reg:CCFP FLAGS_REG)
971169699Skan	(compare:CCFP (match_operand 0 "register_operand" "f,x")
972169699Skan		      (match_operand 1 "nonimmediate_operand" "f,xm")))]
973169699Skan  "TARGET_MIX_SSE_I387
97490286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
975169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
97690286Sobrien  "* return output_fp_compare (insn, operands, 1, 0);"
977132727Skan  [(set_attr "type" "fcmp,ssecomi")
978132727Skan   (set (attr "mode")
979132727Skan     (if_then_else (match_operand:SF 1 "" "")
980132727Skan        (const_string "SF")
981132727Skan        (const_string "DF")))
98290286Sobrien   (set_attr "athlon_decode" "vector")])
98318334Speter
984169699Skan(define_insn "*cmpfp_i_sse"
985169699Skan  [(set (reg:CCFP FLAGS_REG)
98690286Sobrien	(compare:CCFP (match_operand 0 "register_operand" "x")
98790286Sobrien		      (match_operand 1 "nonimmediate_operand" "xm")))]
988169699Skan  "TARGET_SSE_MATH
989169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
990169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
99190286Sobrien  "* return output_fp_compare (insn, operands, 1, 0);"
992132727Skan  [(set_attr "type" "ssecomi")
993132727Skan   (set (attr "mode")
994132727Skan     (if_then_else (match_operand:SF 1 "" "")
995132727Skan        (const_string "SF")
996132727Skan        (const_string "DF")))
99790286Sobrien   (set_attr "athlon_decode" "vector")])
99818334Speter
999169699Skan(define_insn "*cmpfp_i_i387"
1000169699Skan  [(set (reg:CCFP FLAGS_REG)
1001169699Skan	(compare:CCFP (match_operand 0 "register_operand" "f")
1002169699Skan		      (match_operand 1 "register_operand" "f")))]
100390286Sobrien  "TARGET_80387 && TARGET_CMOVE
1004169699Skan   && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
100590286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))
100690286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
1007169699Skan  "* return output_fp_compare (insn, operands, 1, 0);"
100890286Sobrien  [(set_attr "type" "fcmp")
1009132727Skan   (set (attr "mode")
1010132727Skan     (cond [(match_operand:SF 1 "" "")
1011132727Skan	      (const_string "SF")
1012132727Skan	    (match_operand:DF 1 "" "")
1013132727Skan	      (const_string "DF")
1014132727Skan	   ]
1015132727Skan	   (const_string "XF")))
101690286Sobrien   (set_attr "athlon_decode" "vector")])
101718334Speter
1018169699Skan(define_insn "*cmpfp_iu_mixed"
1019169699Skan  [(set (reg:CCFPU FLAGS_REG)
1020169699Skan	(compare:CCFPU (match_operand 0 "register_operand" "f,x")
1021169699Skan		       (match_operand 1 "nonimmediate_operand" "f,xm")))]
1022169699Skan  "TARGET_MIX_SSE_I387
102390286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
102490286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
102590286Sobrien  "* return output_fp_compare (insn, operands, 1, 1);"
1026132727Skan  [(set_attr "type" "fcmp,ssecomi")
1027132727Skan   (set (attr "mode")
1028132727Skan     (if_then_else (match_operand:SF 1 "" "")
1029132727Skan        (const_string "SF")
1030132727Skan        (const_string "DF")))
103190286Sobrien   (set_attr "athlon_decode" "vector")])
103250650Sobrien
1033169699Skan(define_insn "*cmpfp_iu_sse"
1034169699Skan  [(set (reg:CCFPU FLAGS_REG)
103590286Sobrien	(compare:CCFPU (match_operand 0 "register_operand" "x")
103690286Sobrien		       (match_operand 1 "nonimmediate_operand" "xm")))]
1037169699Skan  "TARGET_SSE_MATH
1038169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
103990286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
104090286Sobrien  "* return output_fp_compare (insn, operands, 1, 1);"
1041132727Skan  [(set_attr "type" "ssecomi")
1042132727Skan   (set (attr "mode")
1043132727Skan     (if_then_else (match_operand:SF 1 "" "")
1044132727Skan        (const_string "SF")
1045132727Skan        (const_string "DF")))
104690286Sobrien   (set_attr "athlon_decode" "vector")])
1047169699Skan
1048169699Skan(define_insn "*cmpfp_iu_387"
1049169699Skan  [(set (reg:CCFPU FLAGS_REG)
1050169699Skan	(compare:CCFPU (match_operand 0 "register_operand" "f")
1051169699Skan		       (match_operand 1 "register_operand" "f")))]
1052169699Skan  "TARGET_80387 && TARGET_CMOVE
1053169699Skan   && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
1054169699Skan   && FLOAT_MODE_P (GET_MODE (operands[0]))
1055169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
1056169699Skan  "* return output_fp_compare (insn, operands, 1, 1);"
1057169699Skan  [(set_attr "type" "fcmp")
1058169699Skan   (set (attr "mode")
1059169699Skan     (cond [(match_operand:SF 1 "" "")
1060169699Skan	      (const_string "SF")
1061169699Skan	    (match_operand:DF 1 "" "")
1062169699Skan	      (const_string "DF")
1063169699Skan	   ]
1064169699Skan	   (const_string "XF")))
1065169699Skan   (set_attr "athlon_decode" "vector")])
106690286Sobrien
106790286Sobrien;; Move instructions.
106818334Speter
106918334Speter;; General case of fullword move.
107018334Speter
107118334Speter(define_expand "movsi"
107290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
107318334Speter	(match_operand:SI 1 "general_operand" ""))]
107418334Speter  ""
107590286Sobrien  "ix86_expand_move (SImode, operands); DONE;")
107618334Speter
107790286Sobrien;; Push/pop instructions.  They are separate since autoinc/dec is not a
107890286Sobrien;; general_operand.
107990286Sobrien;;
108090286Sobrien;; %%% We don't use a post-inc memory reference because x86 is not a 
108190286Sobrien;; general AUTO_INC_DEC host, which impacts how it is treated in flow.
108290286Sobrien;; Changing this impacts compiler performance on other non-AUTO_INC_DEC
108390286Sobrien;; targets without our curiosities, and it is just as easy to represent
108490286Sobrien;; this differently.
108518334Speter
108690286Sobrien(define_insn "*pushsi2"
108790286Sobrien  [(set (match_operand:SI 0 "push_operand" "=<")
108890286Sobrien	(match_operand:SI 1 "general_no_elim_operand" "ri*m"))]
108990286Sobrien  "!TARGET_64BIT"
109090286Sobrien  "push{l}\t%1"
109190286Sobrien  [(set_attr "type" "push")
109290286Sobrien   (set_attr "mode" "SI")])
109318334Speter
109490286Sobrien;; For 64BIT abi we always round up to 8 bytes.
109590286Sobrien(define_insn "*pushsi2_rex64"
109690286Sobrien  [(set (match_operand:SI 0 "push_operand" "=X")
109790286Sobrien	(match_operand:SI 1 "nonmemory_no_elim_operand" "ri"))]
109890286Sobrien  "TARGET_64BIT"
109990286Sobrien  "push{q}\t%q1"
110090286Sobrien  [(set_attr "type" "push")
110190286Sobrien   (set_attr "mode" "SI")])
110218334Speter
110390286Sobrien(define_insn "*pushsi2_prologue"
110490286Sobrien  [(set (match_operand:SI 0 "push_operand" "=<")
110590286Sobrien	(match_operand:SI 1 "general_no_elim_operand" "ri*m"))
110690286Sobrien   (clobber (mem:BLK (scratch)))]
110790286Sobrien  "!TARGET_64BIT"
110890286Sobrien  "push{l}\t%1"
110990286Sobrien  [(set_attr "type" "push")
111090286Sobrien   (set_attr "mode" "SI")])
111152296Sobrien
111290286Sobrien(define_insn "*popsi1_epilogue"
111390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
1114169699Skan	(mem:SI (reg:SI SP_REG)))
1115169699Skan   (set (reg:SI SP_REG)
1116169699Skan	(plus:SI (reg:SI SP_REG) (const_int 4)))
111790286Sobrien   (clobber (mem:BLK (scratch)))]
111890286Sobrien  "!TARGET_64BIT"
111990286Sobrien  "pop{l}\t%0"
112090286Sobrien  [(set_attr "type" "pop")
112190286Sobrien   (set_attr "mode" "SI")])
112218334Speter
112390286Sobrien(define_insn "popsi1"
112490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
1125169699Skan	(mem:SI (reg:SI SP_REG)))
1126169699Skan   (set (reg:SI SP_REG)
1127169699Skan	(plus:SI (reg:SI SP_REG) (const_int 4)))]
112890286Sobrien  "!TARGET_64BIT"
112990286Sobrien  "pop{l}\t%0"
113090286Sobrien  [(set_attr "type" "pop")
113190286Sobrien   (set_attr "mode" "SI")])
113218334Speter
113390286Sobrien(define_insn "*movsi_xor"
113490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
113590286Sobrien	(match_operand:SI 1 "const0_operand" "i"))
1136169699Skan   (clobber (reg:CC FLAGS_REG))]
113790286Sobrien  "reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
113890286Sobrien  "xor{l}\t{%0, %0|%0, %0}"
113990286Sobrien  [(set_attr "type" "alu1")
114090286Sobrien   (set_attr "mode" "SI")
114190286Sobrien   (set_attr "length_immediate" "0")])
1142132727Skan 
114390286Sobrien(define_insn "*movsi_or"
114490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
114590286Sobrien	(match_operand:SI 1 "immediate_operand" "i"))
1146169699Skan   (clobber (reg:CC FLAGS_REG))]
1147132727Skan  "reload_completed
1148132727Skan   && operands[1] == constm1_rtx
114990286Sobrien   && (TARGET_PENTIUM || optimize_size)"
115090286Sobrien{
115190286Sobrien  operands[1] = constm1_rtx;
115290286Sobrien  return "or{l}\t{%1, %0|%0, %1}";
115390286Sobrien}
115490286Sobrien  [(set_attr "type" "alu1")
115590286Sobrien   (set_attr "mode" "SI")
115690286Sobrien   (set_attr "length_immediate" "1")])
115718334Speter
115890286Sobrien(define_insn "*movsi_1"
1159169699Skan  [(set (match_operand:SI 0 "nonimmediate_operand"
1160169699Skan			"=r  ,m  ,*y,*y,?rm,?*y,*x,*x,?r,m ,?*Y,*x")
1161169699Skan	(match_operand:SI 1 "general_operand"
1162169699Skan			"rinm,rin,C ,*y,*y ,rm ,C ,*x,*Y,*x,r  ,m "))]
1163169699Skan  "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
116450650Sobrien{
116590286Sobrien  switch (get_attr_type (insn))
116690286Sobrien    {
1167169699Skan    case TYPE_SSELOG1:
1168117404Skan      if (get_attr_mode (insn) == MODE_TI)
1169169699Skan        return "pxor\t%0, %0";
1170169699Skan      return "xorps\t%0, %0";
117152296Sobrien
1172169699Skan    case TYPE_SSEMOV:
1173169699Skan      switch (get_attr_mode (insn))
1174169699Skan	{
1175169699Skan	case MODE_TI:
1176169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
1177169699Skan	case MODE_V4SF:
1178169699Skan	  return "movaps\t{%1, %0|%0, %1}";
1179169699Skan	case MODE_SI:
1180169699Skan          return "movd\t{%1, %0|%0, %1}";
1181169699Skan	case MODE_SF:
1182169699Skan          return "movss\t{%1, %0|%0, %1}";
1183169699Skan	default:
1184169699Skan	  gcc_unreachable ();
1185169699Skan	}
118652296Sobrien
1187169699Skan    case TYPE_MMXADD:
1188169699Skan      return "pxor\t%0, %0";
118918334Speter
1190132727Skan    case TYPE_MMXMOV:
1191132727Skan      if (get_attr_mode (insn) == MODE_DI)
1192132727Skan	return "movq\t{%1, %0|%0, %1}";
1193132727Skan      return "movd\t{%1, %0|%0, %1}";
1194132727Skan
1195132727Skan    case TYPE_LEA:
1196132727Skan      return "lea{l}\t{%1, %0|%0, %1}";
1197132727Skan
1198132727Skan    default:
1199169699Skan      gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
1200132727Skan      return "mov{l}\t{%1, %0|%0, %1}";
1201132727Skan    }
1202132727Skan}
1203132727Skan  [(set (attr "type")
1204169699Skan     (cond [(eq_attr "alternative" "2")
1205169699Skan	      (const_string "mmxadd")
1206169699Skan	    (eq_attr "alternative" "3,4,5")
1207132727Skan	      (const_string "mmxmov")
1208169699Skan	    (eq_attr "alternative" "6")
1209169699Skan	      (const_string "sselog1")
1210169699Skan	    (eq_attr "alternative" "7,8,9,10,11")
1211132727Skan	      (const_string "ssemov")
1212169699Skan 	    (match_operand:DI 1 "pic_32bit_operand" "")
1213132727Skan	      (const_string "lea")
1214132727Skan	   ]
1215132727Skan	   (const_string "imov")))
1216169699Skan   (set (attr "mode")
1217169699Skan     (cond [(eq_attr "alternative" "2,3")
1218169699Skan	      (const_string "DI")
1219169699Skan	    (eq_attr "alternative" "6,7")
1220169699Skan	      (if_then_else
1221169699Skan	        (eq (symbol_ref "TARGET_SSE2") (const_int 0))
1222169699Skan	        (const_string "V4SF")
1223169699Skan	        (const_string "TI"))
1224169699Skan	    (and (eq_attr "alternative" "8,9,10,11")
1225169699Skan	         (eq (symbol_ref "TARGET_SSE2") (const_int 0)))
1226169699Skan	      (const_string "SF")
1227169699Skan	   ]
1228169699Skan	   (const_string "SI")))])
1229132727Skan
1230132727Skan;; Stores and loads of ax to arbitrary constant address.
123190286Sobrien;; We fake an second form of instruction to force reload to load address
123290286Sobrien;; into register when rax is not available
123390286Sobrien(define_insn "*movabssi_1_rex64"
1234117404Skan  [(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1235117404Skan	(match_operand:SI 1 "nonmemory_operand" "a,er"))]
1236117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
123790286Sobrien  "@
123890286Sobrien   movabs{l}\t{%1, %P0|%P0, %1}
1239117404Skan   mov{l}\t{%1, %a0|%a0, %1}"
124090286Sobrien  [(set_attr "type" "imov")
1241117404Skan   (set_attr "modrm" "0,*")
1242117404Skan   (set_attr "length_address" "8,0")
1243117404Skan   (set_attr "length_immediate" "0,*")
124490286Sobrien   (set_attr "memory" "store")
124590286Sobrien   (set_attr "mode" "SI")])
124650650Sobrien
124790286Sobrien(define_insn "*movabssi_2_rex64"
124890286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a,r")
124990286Sobrien        (mem:SI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1250117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
125190286Sobrien  "@
125290286Sobrien   movabs{l}\t{%P1, %0|%0, %P1}
125390286Sobrien   mov{l}\t{%a1, %0|%0, %a1}"
125490286Sobrien  [(set_attr "type" "imov")
125590286Sobrien   (set_attr "modrm" "0,*")
125690286Sobrien   (set_attr "length_address" "8,0")
125790286Sobrien   (set_attr "length_immediate" "0")
125890286Sobrien   (set_attr "memory" "load")
125990286Sobrien   (set_attr "mode" "SI")])
126090286Sobrien
126190286Sobrien(define_insn "*swapsi"
126290286Sobrien  [(set (match_operand:SI 0 "register_operand" "+r")
126390286Sobrien	(match_operand:SI 1 "register_operand" "+r"))
126490286Sobrien   (set (match_dup 1)
126590286Sobrien	(match_dup 0))]
126650650Sobrien  ""
126790286Sobrien  "xchg{l}\t%1, %0"
126890286Sobrien  [(set_attr "type" "imov")
1269146906Skan   (set_attr "mode" "SI")
127090286Sobrien   (set_attr "pent_pair" "np")
1271169699Skan   (set_attr "athlon_decode" "vector")])
127218334Speter
127390286Sobrien(define_expand "movhi"
127490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
127590286Sobrien        (match_operand:HI 1 "general_operand" ""))]
127690286Sobrien  ""
127790286Sobrien  "ix86_expand_move (HImode, operands); DONE;")
127818334Speter
127990286Sobrien(define_insn "*pushhi2"
1280169699Skan  [(set (match_operand:HI 0 "push_operand" "=X")
1281169699Skan	(match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
128290286Sobrien  "!TARGET_64BIT"
1283169699Skan  "push{l}\t%k1"
128490286Sobrien  [(set_attr "type" "push")
1285169699Skan   (set_attr "mode" "SI")])
128618334Speter
128790286Sobrien;; For 64BIT abi we always round up to 8 bytes.
128890286Sobrien(define_insn "*pushhi2_rex64"
128990286Sobrien  [(set (match_operand:HI 0 "push_operand" "=X")
129090286Sobrien	(match_operand:HI 1 "nonmemory_no_elim_operand" "ri"))]
129190286Sobrien  "TARGET_64BIT"
129290286Sobrien  "push{q}\t%q1"
129390286Sobrien  [(set_attr "type" "push")
1294169699Skan   (set_attr "mode" "DI")])
129590286Sobrien
129690286Sobrien(define_insn "*movhi_1"
1297117404Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
1298117404Skan	(match_operand:HI 1 "general_operand" "r,rn,rm,rn"))]
129990286Sobrien  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
130018334Speter{
130190286Sobrien  switch (get_attr_type (insn))
130218334Speter    {
130390286Sobrien    case TYPE_IMOVX:
130490286Sobrien      /* movzwl is faster than movw on p2 due to partial word stalls,
130590286Sobrien	 though not as fast as an aligned movl.  */
130690286Sobrien      return "movz{wl|x}\t{%1, %k0|%k0, %1}";
130790286Sobrien    default:
130890286Sobrien      if (get_attr_mode (insn) == MODE_SI)
130990286Sobrien        return "mov{l}\t{%k1, %k0|%k0, %k1}";
131090286Sobrien      else
131190286Sobrien        return "mov{w}\t{%1, %0|%0, %1}";
131218334Speter    }
131390286Sobrien}
131490286Sobrien  [(set (attr "type")
1315169699Skan     (cond [(ne (symbol_ref "optimize_size") (const_int 0))
1316169699Skan	      (const_string "imov")
1317169699Skan	    (and (eq_attr "alternative" "0")
131890286Sobrien		 (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
131990286Sobrien			  (const_int 0))
132090286Sobrien		      (eq (symbol_ref "TARGET_HIMODE_MATH")
132190286Sobrien			  (const_int 0))))
132290286Sobrien	      (const_string "imov")
1323117404Skan	    (and (eq_attr "alternative" "1,2")
132490286Sobrien		 (match_operand:HI 1 "aligned_operand" ""))
132590286Sobrien	      (const_string "imov")
132690286Sobrien	    (and (ne (symbol_ref "TARGET_MOVX")
132790286Sobrien		     (const_int 0))
1328117404Skan		 (eq_attr "alternative" "0,2"))
132990286Sobrien	      (const_string "imovx")
133090286Sobrien	   ]
133190286Sobrien	   (const_string "imov")))
133290286Sobrien    (set (attr "mode")
133390286Sobrien      (cond [(eq_attr "type" "imovx")
133490286Sobrien	       (const_string "SI")
1335117404Skan	     (and (eq_attr "alternative" "1,2")
133690286Sobrien		  (match_operand:HI 1 "aligned_operand" ""))
133790286Sobrien	       (const_string "SI")
1338117404Skan	     (and (eq_attr "alternative" "0")
133990286Sobrien		  (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
134090286Sobrien			   (const_int 0))
134190286Sobrien		       (eq (symbol_ref "TARGET_HIMODE_MATH")
134290286Sobrien			   (const_int 0))))
134390286Sobrien	       (const_string "SI")
134490286Sobrien	    ]
1345117404Skan	    (const_string "HI")))])
134618334Speter
1347132727Skan;; Stores and loads of ax to arbitrary constant address.
134890286Sobrien;; We fake an second form of instruction to force reload to load address
134990286Sobrien;; into register when rax is not available
135090286Sobrien(define_insn "*movabshi_1_rex64"
1351117404Skan  [(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1352117404Skan	(match_operand:HI 1 "nonmemory_operand" "a,er"))]
1353117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
135490286Sobrien  "@
135590286Sobrien   movabs{w}\t{%1, %P0|%P0, %1}
1356117404Skan   mov{w}\t{%1, %a0|%a0, %1}"
135790286Sobrien  [(set_attr "type" "imov")
1358117404Skan   (set_attr "modrm" "0,*")
1359117404Skan   (set_attr "length_address" "8,0")
1360117404Skan   (set_attr "length_immediate" "0,*")
136190286Sobrien   (set_attr "memory" "store")
136290286Sobrien   (set_attr "mode" "HI")])
136318334Speter
136490286Sobrien(define_insn "*movabshi_2_rex64"
136590286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a,r")
136690286Sobrien        (mem:HI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1367117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
136890286Sobrien  "@
136990286Sobrien   movabs{w}\t{%P1, %0|%0, %P1}
137090286Sobrien   mov{w}\t{%a1, %0|%0, %a1}"
137190286Sobrien  [(set_attr "type" "imov")
137290286Sobrien   (set_attr "modrm" "0,*")
137390286Sobrien   (set_attr "length_address" "8,0")
137490286Sobrien   (set_attr "length_immediate" "0")
137590286Sobrien   (set_attr "memory" "load")
137690286Sobrien   (set_attr "mode" "HI")])
137718334Speter
137890286Sobrien(define_insn "*swaphi_1"
137990286Sobrien  [(set (match_operand:HI 0 "register_operand" "+r")
138090286Sobrien	(match_operand:HI 1 "register_operand" "+r"))
138190286Sobrien   (set (match_dup 1)
138290286Sobrien	(match_dup 0))]
1383146906Skan  "!TARGET_PARTIAL_REG_STALL || optimize_size"
1384146906Skan  "xchg{l}\t%k1, %k0"
138590286Sobrien  [(set_attr "type" "imov")
1386146906Skan   (set_attr "mode" "SI")
138790286Sobrien   (set_attr "pent_pair" "np")
1388169699Skan   (set_attr "athlon_decode" "vector")])
138918334Speter
139090286Sobrien(define_insn "*swaphi_2"
139190286Sobrien  [(set (match_operand:HI 0 "register_operand" "+r")
139290286Sobrien	(match_operand:HI 1 "register_operand" "+r"))
139390286Sobrien   (set (match_dup 1)
139490286Sobrien	(match_dup 0))]
1395146906Skan  "TARGET_PARTIAL_REG_STALL"
1396146906Skan  "xchg{w}\t%1, %0"
139790286Sobrien  [(set_attr "type" "imov")
1398146906Skan   (set_attr "mode" "HI")
139990286Sobrien   (set_attr "pent_pair" "np")
1400169699Skan   (set_attr "athlon_decode" "vector")])
140118334Speter
140218334Speter(define_expand "movstricthi"
140390286Sobrien  [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
140418334Speter	(match_operand:HI 1 "general_operand" ""))]
140590286Sobrien  "! TARGET_PARTIAL_REG_STALL || optimize_size"
140618334Speter{
140718334Speter  /* Don't generate memory->memory moves, go through a register */
140890286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
140990286Sobrien    operands[1] = force_reg (HImode, operands[1]);
141090286Sobrien})
141118334Speter
141290286Sobrien(define_insn "*movstricthi_1"
141390286Sobrien  [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+rm,r"))
141490286Sobrien	(match_operand:HI 1 "general_operand" "rn,m"))]
141590286Sobrien  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
141690286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
141790286Sobrien  "mov{w}\t{%1, %0|%0, %1}"
141890286Sobrien  [(set_attr "type" "imov")
141990286Sobrien   (set_attr "mode" "HI")])
142052296Sobrien
142190286Sobrien(define_insn "*movstricthi_xor"
142290286Sobrien  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
142390286Sobrien	(match_operand:HI 1 "const0_operand" "i"))
1424169699Skan   (clobber (reg:CC FLAGS_REG))]
142590286Sobrien  "reload_completed
142690286Sobrien   && ((!TARGET_USE_MOV0 && !TARGET_PARTIAL_REG_STALL) || optimize_size)"
142790286Sobrien  "xor{w}\t{%0, %0|%0, %0}"
142890286Sobrien  [(set_attr "type" "alu1")
142990286Sobrien   (set_attr "mode" "HI")
143090286Sobrien   (set_attr "length_immediate" "0")])
143152296Sobrien
143290286Sobrien(define_expand "movqi"
143390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
143490286Sobrien	(match_operand:QI 1 "general_operand" ""))]
143590286Sobrien  ""
143690286Sobrien  "ix86_expand_move (QImode, operands); DONE;")
143718334Speter
143890286Sobrien;; emit_push_insn when it calls move_by_pieces requires an insn to
1439169699Skan;; "push a byte".  But actually we use pushl, which has the effect
1440169699Skan;; of rounding the amount pushed up to a word.
144118334Speter
144290286Sobrien(define_insn "*pushqi2"
1443169699Skan  [(set (match_operand:QI 0 "push_operand" "=X")
1444169699Skan	(match_operand:QI 1 "nonmemory_no_elim_operand" "rn"))]
144590286Sobrien  "!TARGET_64BIT"
1446169699Skan  "push{l}\t%k1"
144790286Sobrien  [(set_attr "type" "push")
1448169699Skan   (set_attr "mode" "SI")])
144918334Speter
145090286Sobrien;; For 64BIT abi we always round up to 8 bytes.
145190286Sobrien(define_insn "*pushqi2_rex64"
145290286Sobrien  [(set (match_operand:QI 0 "push_operand" "=X")
1453102802Skan	(match_operand:QI 1 "nonmemory_no_elim_operand" "qi"))]
145490286Sobrien  "TARGET_64BIT"
145590286Sobrien  "push{q}\t%q1"
145690286Sobrien  [(set_attr "type" "push")
1457169699Skan   (set_attr "mode" "DI")])
145890286Sobrien
145990286Sobrien;; Situation is quite tricky about when to choose full sized (SImode) move
146090286Sobrien;; over QImode moves.  For Q_REG -> Q_REG move we use full size only for
146190286Sobrien;; partial register dependency machines (such as AMD Athlon), where QImode
146290286Sobrien;; moves issue extra dependency and for partial register stalls machines
146390286Sobrien;; that don't use QImode patterns (and QImode move cause stall on the next
146490286Sobrien;; instruction).
146590286Sobrien;;
146690286Sobrien;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial
146790286Sobrien;; register stall machines with, where we use QImode instructions, since
146890286Sobrien;; partial register stall can be caused there.  Then we use movzx.
146990286Sobrien(define_insn "*movqi_1"
147090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m")
147190286Sobrien	(match_operand:QI 1 "general_operand"      " q,qn,qm,q,rn,qm,qn"))]
147290286Sobrien  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
147390286Sobrien{
147490286Sobrien  switch (get_attr_type (insn))
147590286Sobrien    {
147690286Sobrien    case TYPE_IMOVX:
1477169699Skan      gcc_assert (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM);
147890286Sobrien      return "movz{bl|x}\t{%1, %k0|%k0, %1}";
147990286Sobrien    default:
148090286Sobrien      if (get_attr_mode (insn) == MODE_SI)
148190286Sobrien        return "mov{l}\t{%k1, %k0|%k0, %k1}";
148290286Sobrien      else
148390286Sobrien        return "mov{b}\t{%1, %0|%0, %1}";
148490286Sobrien    }
148590286Sobrien}
148690286Sobrien  [(set (attr "type")
1487169699Skan     (cond [(and (eq_attr "alternative" "5")
1488169699Skan		 (not (match_operand:QI 1 "aligned_operand" "")))
1489169699Skan	      (const_string "imovx")
1490169699Skan	    (ne (symbol_ref "optimize_size") (const_int 0))
1491169699Skan	      (const_string "imov")
1492169699Skan	    (and (eq_attr "alternative" "3")
149390286Sobrien		 (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
149490286Sobrien			  (const_int 0))
149590286Sobrien		      (eq (symbol_ref "TARGET_QIMODE_MATH")
149690286Sobrien			  (const_int 0))))
149790286Sobrien	      (const_string "imov")
149890286Sobrien	    (eq_attr "alternative" "3,5")
149990286Sobrien	      (const_string "imovx")
150090286Sobrien	    (and (ne (symbol_ref "TARGET_MOVX")
150190286Sobrien		     (const_int 0))
150290286Sobrien		 (eq_attr "alternative" "2"))
150390286Sobrien	      (const_string "imovx")
150490286Sobrien	   ]
150590286Sobrien	   (const_string "imov")))
150690286Sobrien   (set (attr "mode")
150790286Sobrien      (cond [(eq_attr "alternative" "3,4,5")
150890286Sobrien	       (const_string "SI")
150990286Sobrien	     (eq_attr "alternative" "6")
151090286Sobrien	       (const_string "QI")
151190286Sobrien	     (eq_attr "type" "imovx")
151290286Sobrien	       (const_string "SI")
151390286Sobrien	     (and (eq_attr "type" "imov")
1514169699Skan		  (and (eq_attr "alternative" "0,1")
1515169699Skan		       (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
1516169699Skan				(const_int 0))
1517169699Skan			    (and (eq (symbol_ref "optimize_size")
1518169699Skan				     (const_int 0))
1519169699Skan			    	 (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
1520169699Skan				     (const_int 0))))))
152190286Sobrien	       (const_string "SI")
152290286Sobrien	     ;; Avoid partial register stalls when not using QImode arithmetic
152390286Sobrien	     (and (eq_attr "type" "imov")
1524169699Skan		  (and (eq_attr "alternative" "0,1")
152590286Sobrien		       (and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL")
152690286Sobrien				(const_int 0))
152790286Sobrien			    (eq (symbol_ref "TARGET_QIMODE_MATH")
152890286Sobrien				(const_int 0)))))
152990286Sobrien	       (const_string "SI")
153090286Sobrien	   ]
153190286Sobrien	   (const_string "QI")))])
153290286Sobrien
153390286Sobrien(define_expand "reload_outqi"
153490286Sobrien  [(parallel [(match_operand:QI 0 "" "=m")
153590286Sobrien              (match_operand:QI 1 "register_operand" "r")
153690286Sobrien              (match_operand:QI 2 "register_operand" "=&q")])]
153718334Speter  ""
153890286Sobrien{
153990286Sobrien  rtx op0, op1, op2;
154090286Sobrien  op0 = operands[0]; op1 = operands[1]; op2 = operands[2];
154118334Speter
1542169699Skan  gcc_assert (!reg_overlap_mentioned_p (op2, op0));
154390286Sobrien  if (! q_regs_operand (op1, QImode))
154490286Sobrien    {
154590286Sobrien      emit_insn (gen_movqi (op2, op1));
154690286Sobrien      op1 = op2;
154790286Sobrien    }
154890286Sobrien  emit_insn (gen_movqi (op0, op1));
154990286Sobrien  DONE;
155090286Sobrien})
155190286Sobrien
1552146906Skan(define_insn "*swapqi_1"
155390286Sobrien  [(set (match_operand:QI 0 "register_operand" "+r")
155490286Sobrien	(match_operand:QI 1 "register_operand" "+r"))
155590286Sobrien   (set (match_dup 1)
155690286Sobrien	(match_dup 0))]
1557146906Skan  "!TARGET_PARTIAL_REG_STALL || optimize_size"
1558146906Skan  "xchg{l}\t%k1, %k0"
1559146906Skan  [(set_attr "type" "imov")
1560146906Skan   (set_attr "mode" "SI")
1561146906Skan   (set_attr "pent_pair" "np")
1562169699Skan   (set_attr "athlon_decode" "vector")])
1563146906Skan
1564146906Skan(define_insn "*swapqi_2"
1565146906Skan  [(set (match_operand:QI 0 "register_operand" "+q")
1566146906Skan	(match_operand:QI 1 "register_operand" "+q"))
1567146906Skan   (set (match_dup 1)
1568146906Skan	(match_dup 0))]
1569146906Skan  "TARGET_PARTIAL_REG_STALL"
157090286Sobrien  "xchg{b}\t%1, %0"
157190286Sobrien  [(set_attr "type" "imov")
1572146906Skan   (set_attr "mode" "QI")
157390286Sobrien   (set_attr "pent_pair" "np")
1574169699Skan   (set_attr "athlon_decode" "vector")])
157590286Sobrien
157690286Sobrien(define_expand "movstrictqi"
157790286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
157890286Sobrien	(match_operand:QI 1 "general_operand" ""))]
1579117404Skan  "! TARGET_PARTIAL_REG_STALL || optimize_size"
158018334Speter{
158190286Sobrien  /* Don't generate memory->memory moves, go through a register.  */
158290286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
158390286Sobrien    operands[1] = force_reg (QImode, operands[1]);
158490286Sobrien})
158518334Speter
158690286Sobrien(define_insn "*movstrictqi_1"
158790286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
158890286Sobrien	(match_operand:QI 1 "general_operand" "*qn,m"))]
1589117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
159090286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
159190286Sobrien  "mov{b}\t{%1, %0|%0, %1}"
159290286Sobrien  [(set_attr "type" "imov")
159390286Sobrien   (set_attr "mode" "QI")])
159418334Speter
159590286Sobrien(define_insn "*movstrictqi_xor"
159690286Sobrien  [(set (strict_low_part (match_operand:QI 0 "q_regs_operand" "+q"))
159790286Sobrien	(match_operand:QI 1 "const0_operand" "i"))
1598169699Skan   (clobber (reg:CC FLAGS_REG))]
159990286Sobrien  "reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
160090286Sobrien  "xor{b}\t{%0, %0|%0, %0}"
160190286Sobrien  [(set_attr "type" "alu1")
160290286Sobrien   (set_attr "mode" "QI")
160390286Sobrien   (set_attr "length_immediate" "0")])
160418334Speter
160590286Sobrien(define_insn "*movsi_extv_1"
160690286Sobrien  [(set (match_operand:SI 0 "register_operand" "=R")
160790286Sobrien	(sign_extract:SI (match_operand 1 "ext_register_operand" "Q")
160890286Sobrien			 (const_int 8)
160990286Sobrien			 (const_int 8)))]
161018334Speter  ""
161190286Sobrien  "movs{bl|x}\t{%h1, %0|%0, %h1}"
161290286Sobrien  [(set_attr "type" "imovx")
161390286Sobrien   (set_attr "mode" "SI")])
161490286Sobrien
161590286Sobrien(define_insn "*movhi_extv_1"
161690286Sobrien  [(set (match_operand:HI 0 "register_operand" "=R")
161790286Sobrien	(sign_extract:HI (match_operand 1 "ext_register_operand" "Q")
161890286Sobrien			 (const_int 8)
161990286Sobrien			 (const_int 8)))]
162090286Sobrien  ""
162190286Sobrien  "movs{bl|x}\t{%h1, %k0|%k0, %h1}"
162290286Sobrien  [(set_attr "type" "imovx")
162390286Sobrien   (set_attr "mode" "SI")])
162490286Sobrien
162590286Sobrien(define_insn "*movqi_extv_1"
162690286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?r")
162790286Sobrien        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
162890286Sobrien                         (const_int 8)
162990286Sobrien                         (const_int 8)))]
163090286Sobrien  "!TARGET_64BIT"
163118334Speter{
163290286Sobrien  switch (get_attr_type (insn))
163318334Speter    {
163490286Sobrien    case TYPE_IMOVX:
163590286Sobrien      return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
163690286Sobrien    default:
163790286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
163818334Speter    }
163990286Sobrien}
164090286Sobrien  [(set (attr "type")
164190286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
164290286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
164390286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
164490286Sobrien				 (const_int 0))))
164590286Sobrien	(const_string "imovx")
164690286Sobrien	(const_string "imov")))
164790286Sobrien   (set (attr "mode")
164890286Sobrien     (if_then_else (eq_attr "type" "imovx")
164990286Sobrien	(const_string "SI")
165090286Sobrien	(const_string "QI")))])
165118334Speter
165290286Sobrien(define_insn "*movqi_extv_1_rex64"
165390286Sobrien  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
165490286Sobrien        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
165590286Sobrien                         (const_int 8)
165690286Sobrien                         (const_int 8)))]
165790286Sobrien  "TARGET_64BIT"
165818334Speter{
165990286Sobrien  switch (get_attr_type (insn))
166050650Sobrien    {
166190286Sobrien    case TYPE_IMOVX:
166290286Sobrien      return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
166390286Sobrien    default:
166490286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
166550650Sobrien    }
166690286Sobrien}
166790286Sobrien  [(set (attr "type")
166890286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
166990286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
167090286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
167190286Sobrien				 (const_int 0))))
167290286Sobrien	(const_string "imovx")
167390286Sobrien	(const_string "imov")))
167490286Sobrien   (set (attr "mode")
167590286Sobrien     (if_then_else (eq_attr "type" "imovx")
167690286Sobrien	(const_string "SI")
167790286Sobrien	(const_string "QI")))])
167818334Speter
1679132727Skan;; Stores and loads of ax to arbitrary constant address.
168090286Sobrien;; We fake an second form of instruction to force reload to load address
168190286Sobrien;; into register when rax is not available
168290286Sobrien(define_insn "*movabsqi_1_rex64"
1683117404Skan  [(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1684117404Skan	(match_operand:QI 1 "nonmemory_operand" "a,er"))]
1685117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
168690286Sobrien  "@
168790286Sobrien   movabs{b}\t{%1, %P0|%P0, %1}
1688117404Skan   mov{b}\t{%1, %a0|%a0, %1}"
168990286Sobrien  [(set_attr "type" "imov")
1690117404Skan   (set_attr "modrm" "0,*")
1691117404Skan   (set_attr "length_address" "8,0")
1692117404Skan   (set_attr "length_immediate" "0,*")
169390286Sobrien   (set_attr "memory" "store")
169490286Sobrien   (set_attr "mode" "QI")])
169518334Speter
169690286Sobrien(define_insn "*movabsqi_2_rex64"
169790286Sobrien  [(set (match_operand:QI 0 "register_operand" "=a,r")
169890286Sobrien        (mem:QI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1699117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
170090286Sobrien  "@
170190286Sobrien   movabs{b}\t{%P1, %0|%0, %P1}
170290286Sobrien   mov{b}\t{%a1, %0|%0, %a1}"
170390286Sobrien  [(set_attr "type" "imov")
170490286Sobrien   (set_attr "modrm" "0,*")
170590286Sobrien   (set_attr "length_address" "8,0")
170690286Sobrien   (set_attr "length_immediate" "0")
170790286Sobrien   (set_attr "memory" "load")
170890286Sobrien   (set_attr "mode" "QI")])
170918334Speter
1710169699Skan(define_insn "*movdi_extzv_1"
1711169699Skan  [(set (match_operand:DI 0 "register_operand" "=R")
1712169699Skan	(zero_extract:DI (match_operand 1 "ext_register_operand" "Q")
1713169699Skan			 (const_int 8)
1714169699Skan			 (const_int 8)))]
1715169699Skan  "TARGET_64BIT"
1716169699Skan  "movz{bl|x}\t{%h1, %k0|%k0, %h1}"
1717169699Skan  [(set_attr "type" "imovx")
1718169699Skan   (set_attr "mode" "DI")])
1719169699Skan
172090286Sobrien(define_insn "*movsi_extzv_1"
172190286Sobrien  [(set (match_operand:SI 0 "register_operand" "=R")
172290286Sobrien	(zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
172390286Sobrien			 (const_int 8)
172490286Sobrien			 (const_int 8)))]
172590286Sobrien  ""
172690286Sobrien  "movz{bl|x}\t{%h1, %0|%0, %h1}"
172790286Sobrien  [(set_attr "type" "imovx")
172890286Sobrien   (set_attr "mode" "SI")])
172918334Speter
173090286Sobrien(define_insn "*movqi_extzv_2"
173190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?R")
173290286Sobrien        (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
173390286Sobrien				    (const_int 8)
173490286Sobrien				    (const_int 8)) 0))]
173590286Sobrien  "!TARGET_64BIT"
173618334Speter{
173790286Sobrien  switch (get_attr_type (insn))
173818334Speter    {
173990286Sobrien    case TYPE_IMOVX:
174090286Sobrien      return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
174190286Sobrien    default:
174290286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
174318334Speter    }
174490286Sobrien}
174590286Sobrien  [(set (attr "type")
174690286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
174790286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
174890286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
174990286Sobrien				 (const_int 0))))
175090286Sobrien	(const_string "imovx")
175190286Sobrien	(const_string "imov")))
175290286Sobrien   (set (attr "mode")
175390286Sobrien     (if_then_else (eq_attr "type" "imovx")
175490286Sobrien	(const_string "SI")
175590286Sobrien	(const_string "QI")))])
175618334Speter
175790286Sobrien(define_insn "*movqi_extzv_2_rex64"
175890286Sobrien  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
175990286Sobrien        (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
176090286Sobrien				    (const_int 8)
176190286Sobrien				    (const_int 8)) 0))]
176290286Sobrien  "TARGET_64BIT"
176318334Speter{
176490286Sobrien  switch (get_attr_type (insn))
176590286Sobrien    {
176690286Sobrien    case TYPE_IMOVX:
176790286Sobrien      return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
176890286Sobrien    default:
176990286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
177090286Sobrien    }
177190286Sobrien}
177290286Sobrien  [(set (attr "type")
177390286Sobrien     (if_then_else (ior (not (match_operand:QI 0 "q_regs_operand" ""))
177490286Sobrien			(ne (symbol_ref "TARGET_MOVX")
177590286Sobrien			    (const_int 0)))
177690286Sobrien	(const_string "imovx")
177790286Sobrien	(const_string "imov")))
177890286Sobrien   (set (attr "mode")
177990286Sobrien     (if_then_else (eq_attr "type" "imovx")
178090286Sobrien	(const_string "SI")
178190286Sobrien	(const_string "QI")))])
178218334Speter
178390286Sobrien(define_insn "movsi_insv_1"
178490286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
178590286Sobrien			 (const_int 8)
178690286Sobrien			 (const_int 8))
178790286Sobrien	(match_operand:SI 1 "general_operand" "Qmn"))]
178890286Sobrien  "!TARGET_64BIT"
178990286Sobrien  "mov{b}\t{%b1, %h0|%h0, %b1}"
179090286Sobrien  [(set_attr "type" "imov")
179190286Sobrien   (set_attr "mode" "QI")])
179252296Sobrien
1793132727Skan(define_insn "movdi_insv_1_rex64"
1794132727Skan  [(set (zero_extract:DI (match_operand 0 "ext_register_operand" "+Q")
179590286Sobrien			 (const_int 8)
179690286Sobrien			 (const_int 8))
1797132727Skan	(match_operand:DI 1 "nonmemory_operand" "Qn"))]
179890286Sobrien  "TARGET_64BIT"
179990286Sobrien  "mov{b}\t{%b1, %h0|%h0, %b1}"
180090286Sobrien  [(set_attr "type" "imov")
180190286Sobrien   (set_attr "mode" "QI")])
180218334Speter
180390286Sobrien(define_insn "*movqi_insv_2"
180490286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
180590286Sobrien			 (const_int 8)
180690286Sobrien			 (const_int 8))
1807132727Skan	(lshiftrt:SI (match_operand:SI 1 "register_operand" "Q")
1808132727Skan		     (const_int 8)))]
180990286Sobrien  ""
181090286Sobrien  "mov{b}\t{%h1, %h0|%h0, %h1}"
181190286Sobrien  [(set_attr "type" "imov")
181290286Sobrien   (set_attr "mode" "QI")])
181318334Speter
181490286Sobrien(define_expand "movdi"
181590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
181690286Sobrien	(match_operand:DI 1 "general_operand" ""))]
181790286Sobrien  ""
181890286Sobrien  "ix86_expand_move (DImode, operands); DONE;")
181918334Speter
182090286Sobrien(define_insn "*pushdi"
182190286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
182290286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "riF*m"))]
182390286Sobrien  "!TARGET_64BIT"
182490286Sobrien  "#")
182590286Sobrien
1826169699Skan(define_insn "*pushdi2_rex64"
182790286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<,!<")
182890286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "re*m,n"))]
182990286Sobrien  "TARGET_64BIT"
183090286Sobrien  "@
183190286Sobrien   push{q}\t%1
183290286Sobrien   #"
183390286Sobrien  [(set_attr "type" "push,multi")
183490286Sobrien   (set_attr "mode" "DI")])
183590286Sobrien
183690286Sobrien;; Convert impossible pushes of immediate to existing instructions.
183790286Sobrien;; First try to get scratch register and go through it.  In case this
183890286Sobrien;; fails, push sign extended lower part first and then overwrite
183990286Sobrien;; upper part by 32bit move.
184090286Sobrien(define_peephole2
184190286Sobrien  [(match_scratch:DI 2 "r")
184290286Sobrien   (set (match_operand:DI 0 "push_operand" "")
184390286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
184490286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
184590286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
184690286Sobrien  [(set (match_dup 2) (match_dup 1))
184790286Sobrien   (set (match_dup 0) (match_dup 2))]
184890286Sobrien  "")
184990286Sobrien
185090286Sobrien;; We need to define this as both peepholer and splitter for case
185190286Sobrien;; peephole2 pass is not run.
1852169699Skan;; "&& 1" is needed to keep it from matching the previous pattern.
185390286Sobrien(define_peephole2
185490286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
185590286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
185690286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
185790286Sobrien   && !x86_64_immediate_operand (operands[1], DImode) && 1"
185890286Sobrien  [(set (match_dup 0) (match_dup 1))
185990286Sobrien   (set (match_dup 2) (match_dup 3))]
186090286Sobrien  "split_di (operands + 1, 1, operands + 2, operands + 3);
186190286Sobrien   operands[1] = gen_lowpart (DImode, operands[2]);
186290286Sobrien   operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
186390286Sobrien						    GEN_INT (4)));
186490286Sobrien  ")
186590286Sobrien
186690286Sobrien(define_split
186790286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
186890286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
1869161660Skan  "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
1870169699Skan		    ? flow2_completed : reload_completed)
187190286Sobrien   && !symbolic_operand (operands[1], DImode)
187290286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
187390286Sobrien  [(set (match_dup 0) (match_dup 1))
187490286Sobrien   (set (match_dup 2) (match_dup 3))]
187590286Sobrien  "split_di (operands + 1, 1, operands + 2, operands + 3);
187690286Sobrien   operands[1] = gen_lowpart (DImode, operands[2]);
187790286Sobrien   operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
187890286Sobrien						    GEN_INT (4)));
187990286Sobrien  ")
188090286Sobrien
188190286Sobrien(define_insn "*pushdi2_prologue_rex64"
188290286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
188390286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "re*m"))
188490286Sobrien   (clobber (mem:BLK (scratch)))]
188590286Sobrien  "TARGET_64BIT"
188690286Sobrien  "push{q}\t%1"
188790286Sobrien  [(set_attr "type" "push")
188890286Sobrien   (set_attr "mode" "DI")])
188990286Sobrien
189090286Sobrien(define_insn "*popdi1_epilogue_rex64"
189190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
1892169699Skan	(mem:DI (reg:DI SP_REG)))
1893169699Skan   (set (reg:DI SP_REG)
1894169699Skan	(plus:DI (reg:DI SP_REG) (const_int 8)))
189590286Sobrien   (clobber (mem:BLK (scratch)))]
189690286Sobrien  "TARGET_64BIT"
189790286Sobrien  "pop{q}\t%0"
189890286Sobrien  [(set_attr "type" "pop")
189990286Sobrien   (set_attr "mode" "DI")])
190090286Sobrien
190190286Sobrien(define_insn "popdi1"
190290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
1903169699Skan	(mem:DI (reg:DI SP_REG)))
1904169699Skan   (set (reg:DI SP_REG)
1905169699Skan	(plus:DI (reg:DI SP_REG) (const_int 8)))]
190690286Sobrien  "TARGET_64BIT"
190790286Sobrien  "pop{q}\t%0"
190890286Sobrien  [(set_attr "type" "pop")
190990286Sobrien   (set_attr "mode" "DI")])
191090286Sobrien
191190286Sobrien(define_insn "*movdi_xor_rex64"
191290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
191390286Sobrien	(match_operand:DI 1 "const0_operand" "i"))
1914169699Skan   (clobber (reg:CC FLAGS_REG))]
191590286Sobrien  "TARGET_64BIT && (!TARGET_USE_MOV0 || optimize_size)
191690286Sobrien   && reload_completed"
191790286Sobrien  "xor{l}\t{%k0, %k0|%k0, %k0}"
191890286Sobrien  [(set_attr "type" "alu1")
191990286Sobrien   (set_attr "mode" "SI")
192090286Sobrien   (set_attr "length_immediate" "0")])
192190286Sobrien
192290286Sobrien(define_insn "*movdi_or_rex64"
192390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
192490286Sobrien	(match_operand:DI 1 "const_int_operand" "i"))
1925169699Skan   (clobber (reg:CC FLAGS_REG))]
192690286Sobrien  "TARGET_64BIT && (TARGET_PENTIUM || optimize_size)
192790286Sobrien   && reload_completed
1928132727Skan   && operands[1] == constm1_rtx"
192918334Speter{
193090286Sobrien  operands[1] = constm1_rtx;
193190286Sobrien  return "or{q}\t{%1, %0|%0, %1}";
193290286Sobrien}
193390286Sobrien  [(set_attr "type" "alu1")
193490286Sobrien   (set_attr "mode" "DI")
193590286Sobrien   (set_attr "length_immediate" "1")])
193618334Speter
193790286Sobrien(define_insn "*movdi_2"
1938169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand"
1939169699Skan				"=r  ,o  ,*y,m*y,*y,*Y,m ,*Y,*Y,*x,m ,*x,*x")
1940169699Skan	(match_operand:DI 1 "general_operand"
1941169699Skan				"riFo,riF,C ,*y ,m ,C ,*Y,*Y,m ,C ,*x,*x,m "))]
1942169699Skan  "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
194390286Sobrien  "@
194490286Sobrien   #
194590286Sobrien   #
1946169699Skan   pxor\t%0, %0
194790286Sobrien   movq\t{%1, %0|%0, %1}
194890286Sobrien   movq\t{%1, %0|%0, %1}
1949169699Skan   pxor\t%0, %0
195090286Sobrien   movq\t{%1, %0|%0, %1}
195190286Sobrien   movdqa\t{%1, %0|%0, %1}
1952169699Skan   movq\t{%1, %0|%0, %1}
1953169699Skan   xorps\t%0, %0
1954169699Skan   movlps\t{%1, %0|%0, %1}
1955169699Skan   movaps\t{%1, %0|%0, %1}
1956169699Skan   movlps\t{%1, %0|%0, %1}"
1957169699Skan  [(set_attr "type" "*,*,mmx,mmxmov,mmxmov,sselog1,ssemov,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov")
1958169699Skan   (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,TI,DI,V4SF,V2SF,V4SF,V2SF")])
195918334Speter
196090286Sobrien(define_split
196190286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
196290286Sobrien        (match_operand:DI 1 "general_operand" ""))]
196390286Sobrien  "!TARGET_64BIT && reload_completed
196490286Sobrien   && (! MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
196590286Sobrien  [(const_int 0)]
196690286Sobrien  "ix86_split_long_move (operands); DONE;")
196718334Speter
196890286Sobrien;; %%% This multiword shite has got to go.
196990286Sobrien(define_split
197090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
197190286Sobrien        (match_operand:DI 1 "general_operand" ""))]
197290286Sobrien  "!TARGET_64BIT && reload_completed
197390286Sobrien   && (!MMX_REG_P (operands[0]) && !SSE_REG_P (operands[0]))
197490286Sobrien   && (!MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
197590286Sobrien  [(const_int 0)]
197690286Sobrien  "ix86_split_long_move (operands); DONE;")
197718334Speter
197890286Sobrien(define_insn "*movdi_1_rex64"
1979169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand"
1980169699Skan		"=r,r  ,r,m ,!m,*y,*y,?rm,?*y,*x,*x,?rm,?*x,?*x,?*y")
1981169699Skan	(match_operand:DI 1 "general_operand"
1982169699Skan		"Z ,rem,i,re,n ,C ,*y,*y ,rm ,C ,*x,*x ,rm ,*y ,*x"))]
1983169699Skan  "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
198490286Sobrien{
198590286Sobrien  switch (get_attr_type (insn))
198690286Sobrien    {
1987169699Skan    case TYPE_SSECVT:
1988169699Skan      if (which_alternative == 13)
1989169699Skan	return "movq2dq\t{%1, %0|%0, %1}";
1990169699Skan      else
1991169699Skan	return "movdq2q\t{%1, %0|%0, %1}";
1992117404Skan    case TYPE_SSEMOV:
1993132727Skan      if (get_attr_mode (insn) == MODE_TI)
199490286Sobrien	  return "movdqa\t{%1, %0|%0, %1}";
199590286Sobrien      /* FALLTHRU */
1996117404Skan    case TYPE_MMXMOV:
1997132727Skan      /* Moves from and into integer register is done using movd opcode with
1998132727Skan 	 REX prefix.  */
1999132727Skan      if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
2000132727Skan	  return "movd\t{%1, %0|%0, %1}";
200190286Sobrien      return "movq\t{%1, %0|%0, %1}";
2002169699Skan    case TYPE_SSELOG1:
2003169699Skan    case TYPE_MMXADD:
2004169699Skan      return "pxor\t%0, %0";
200590286Sobrien    case TYPE_MULTI:
200690286Sobrien      return "#";
200790286Sobrien    case TYPE_LEA:
200890286Sobrien      return "lea{q}\t{%a1, %0|%0, %a1}";
200990286Sobrien    default:
2010169699Skan      gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
201190286Sobrien      if (get_attr_mode (insn) == MODE_SI)
201290286Sobrien	return "mov{l}\t{%k1, %k0|%k0, %k1}";
201390286Sobrien      else if (which_alternative == 2)
201490286Sobrien	return "movabs{q}\t{%1, %0|%0, %1}";
201518334Speter      else
201690286Sobrien	return "mov{q}\t{%1, %0|%0, %1}";
201718334Speter    }
201890286Sobrien}
201990286Sobrien  [(set (attr "type")
2020169699Skan     (cond [(eq_attr "alternative" "5")
2021169699Skan	      (const_string "mmxadd")
2022169699Skan	    (eq_attr "alternative" "6,7,8")
2023117404Skan	      (const_string "mmxmov")
2024169699Skan	    (eq_attr "alternative" "9")
2025169699Skan	      (const_string "sselog1")
2026169699Skan	    (eq_attr "alternative" "10,11,12")
2027117404Skan	      (const_string "ssemov")
2028169699Skan	    (eq_attr "alternative" "13,14")
2029169699Skan	      (const_string "ssecvt")
203090286Sobrien	    (eq_attr "alternative" "4")
203190286Sobrien	      (const_string "multi")
2032169699Skan 	    (match_operand:DI 1 "pic_32bit_operand" "")
203390286Sobrien	      (const_string "lea")
203490286Sobrien	   ]
203590286Sobrien	   (const_string "imov")))
2036169699Skan   (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*")
2037169699Skan   (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*")
2038169699Skan   (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI")])
203950650Sobrien
2040132727Skan;; Stores and loads of ax to arbitrary constant address.
204190286Sobrien;; We fake an second form of instruction to force reload to load address
204290286Sobrien;; into register when rax is not available
204390286Sobrien(define_insn "*movabsdi_1_rex64"
2044102802Skan  [(set (mem:DI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
2045102802Skan	(match_operand:DI 1 "nonmemory_operand" "a,er"))]
2046117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
204790286Sobrien  "@
204890286Sobrien   movabs{q}\t{%1, %P0|%P0, %1}
2049102802Skan   mov{q}\t{%1, %a0|%a0, %1}"
205090286Sobrien  [(set_attr "type" "imov")
2051102802Skan   (set_attr "modrm" "0,*")
2052102802Skan   (set_attr "length_address" "8,0")
2053102802Skan   (set_attr "length_immediate" "0,*")
205490286Sobrien   (set_attr "memory" "store")
205590286Sobrien   (set_attr "mode" "DI")])
205618334Speter
205790286Sobrien(define_insn "*movabsdi_2_rex64"
205890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a,r")
205990286Sobrien        (mem:DI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
2060117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
206190286Sobrien  "@
206290286Sobrien   movabs{q}\t{%P1, %0|%0, %P1}
206390286Sobrien   mov{q}\t{%a1, %0|%0, %a1}"
206490286Sobrien  [(set_attr "type" "imov")
206590286Sobrien   (set_attr "modrm" "0,*")
206690286Sobrien   (set_attr "length_address" "8,0")
206790286Sobrien   (set_attr "length_immediate" "0")
206890286Sobrien   (set_attr "memory" "load")
206990286Sobrien   (set_attr "mode" "DI")])
207090286Sobrien
207190286Sobrien;; Convert impossible stores of immediate to existing instructions.
207290286Sobrien;; First try to get scratch register and go through it.  In case this
207390286Sobrien;; fails, move by 32bit parts.
207490286Sobrien(define_peephole2
207590286Sobrien  [(match_scratch:DI 2 "r")
207690286Sobrien   (set (match_operand:DI 0 "memory_operand" "")
207790286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
207890286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
207990286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
208090286Sobrien  [(set (match_dup 2) (match_dup 1))
208190286Sobrien   (set (match_dup 0) (match_dup 2))]
208252296Sobrien  "")
208350650Sobrien
208490286Sobrien;; We need to define this as both peepholer and splitter for case
208590286Sobrien;; peephole2 pass is not run.
2086169699Skan;; "&& 1" is needed to keep it from matching the previous pattern.
208790286Sobrien(define_peephole2
208890286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
208990286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
209090286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
209190286Sobrien   && !x86_64_immediate_operand (operands[1], DImode) && 1"
209290286Sobrien  [(set (match_dup 2) (match_dup 3))
209390286Sobrien   (set (match_dup 4) (match_dup 5))]
209490286Sobrien  "split_di (operands, 2, operands + 2, operands + 4);")
209590286Sobrien
209690286Sobrien(define_split
209790286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
209890286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
2099161660Skan  "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
2100169699Skan		    ? flow2_completed : reload_completed)
210190286Sobrien   && !symbolic_operand (operands[1], DImode)
210290286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
210390286Sobrien  [(set (match_dup 2) (match_dup 3))
210490286Sobrien   (set (match_dup 4) (match_dup 5))]
210590286Sobrien  "split_di (operands, 2, operands + 2, operands + 4);")
210690286Sobrien
210790286Sobrien(define_insn "*swapdi_rex64"
210890286Sobrien  [(set (match_operand:DI 0 "register_operand" "+r")
210990286Sobrien	(match_operand:DI 1 "register_operand" "+r"))
211090286Sobrien   (set (match_dup 1)
211190286Sobrien	(match_dup 0))]
211290286Sobrien  "TARGET_64BIT"
211390286Sobrien  "xchg{q}\t%1, %0"
211490286Sobrien  [(set_attr "type" "imov")
2115146906Skan   (set_attr "mode" "DI")
211690286Sobrien   (set_attr "pent_pair" "np")
2117169699Skan   (set_attr "athlon_decode" "vector")])
211890286Sobrien
2119169699Skan(define_expand "movti"
2120169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
2121169699Skan	(match_operand:TI 1 "nonimmediate_operand" ""))]
2122169699Skan  "TARGET_SSE || TARGET_64BIT"
2123169699Skan{
2124169699Skan  if (TARGET_64BIT)
2125169699Skan    ix86_expand_move (TImode, operands);
2126169699Skan  else
2127169699Skan    ix86_expand_vector_move (TImode, operands);
2128169699Skan  DONE;
2129169699Skan})
2130169699Skan
2131169699Skan(define_insn "*movti_internal"
2132169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m")
2133169699Skan	(match_operand:TI 1 "vector_move_operand" "C,xm,x"))]
2134169699Skan  "TARGET_SSE && !TARGET_64BIT
2135169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2136169699Skan{
2137169699Skan  switch (which_alternative)
2138169699Skan    {
2139169699Skan    case 0:
2140169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2141169699Skan	return "xorps\t%0, %0";
2142169699Skan      else
2143169699Skan	return "pxor\t%0, %0";
2144169699Skan    case 1:
2145169699Skan    case 2:
2146169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2147169699Skan	return "movaps\t{%1, %0|%0, %1}";
2148169699Skan      else
2149169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2150169699Skan    default:
2151169699Skan      gcc_unreachable ();
2152169699Skan    }
2153169699Skan}
2154169699Skan  [(set_attr "type" "sselog1,ssemov,ssemov")
2155169699Skan   (set (attr "mode")
2156169699Skan	(cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2157169699Skan		    (ne (symbol_ref "optimize_size") (const_int 0)))
2158169699Skan		 (const_string "V4SF")
2159169699Skan	       (and (eq_attr "alternative" "2")
2160169699Skan		    (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2161169699Skan			(const_int 0)))
2162169699Skan		 (const_string "V4SF")]
2163169699Skan	      (const_string "TI")))])
2164169699Skan
2165169699Skan(define_insn "*movti_rex64"
2166169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,x,xm")
2167169699Skan	(match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))]
2168169699Skan  "TARGET_64BIT
2169169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2170169699Skan{
2171169699Skan  switch (which_alternative)
2172169699Skan    {
2173169699Skan    case 0:
2174169699Skan    case 1:
2175169699Skan      return "#";
2176169699Skan    case 2:
2177169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2178169699Skan	return "xorps\t%0, %0";
2179169699Skan      else
2180169699Skan	return "pxor\t%0, %0";
2181169699Skan    case 3:
2182169699Skan    case 4:
2183169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2184169699Skan	return "movaps\t{%1, %0|%0, %1}";
2185169699Skan      else
2186169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2187169699Skan    default:
2188169699Skan      gcc_unreachable ();
2189169699Skan    }
2190169699Skan}
2191169699Skan  [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
2192169699Skan   (set (attr "mode")
2193169699Skan        (cond [(eq_attr "alternative" "2,3")
2194169699Skan		 (if_then_else
2195169699Skan		   (ne (symbol_ref "optimize_size")
2196169699Skan		       (const_int 0))
2197169699Skan		   (const_string "V4SF")
2198169699Skan		   (const_string "TI"))
2199169699Skan	       (eq_attr "alternative" "4")
2200169699Skan		 (if_then_else
2201169699Skan		   (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2202169699Skan			    (const_int 0))
2203169699Skan			(ne (symbol_ref "optimize_size")
2204169699Skan			    (const_int 0)))
2205169699Skan		   (const_string "V4SF")
2206169699Skan		   (const_string "TI"))]
2207169699Skan	       (const_string "DI")))])
2208169699Skan
2209169699Skan(define_split
2210169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
2211169699Skan        (match_operand:TI 1 "general_operand" ""))]
2212169699Skan  "reload_completed && !SSE_REG_P (operands[0])
2213169699Skan   && !SSE_REG_P (operands[1])"
2214169699Skan  [(const_int 0)]
2215169699Skan  "ix86_split_long_move (operands); DONE;")
2216169699Skan
221750650Sobrien(define_expand "movsf"
221890286Sobrien  [(set (match_operand:SF 0 "nonimmediate_operand" "")
221950650Sobrien	(match_operand:SF 1 "general_operand" ""))]
222018334Speter  ""
222190286Sobrien  "ix86_expand_move (SFmode, operands); DONE;")
222290286Sobrien
222390286Sobrien(define_insn "*pushsf"
222490286Sobrien  [(set (match_operand:SF 0 "push_operand" "=<,<,<")
2225169699Skan	(match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
222690286Sobrien  "!TARGET_64BIT"
222718334Speter{
2228169699Skan  /* Anything else should be already split before reg-stack.  */
2229169699Skan  gcc_assert (which_alternative == 1);
2230169699Skan  return "push{l}\t%1";
223190286Sobrien}
223290286Sobrien  [(set_attr "type" "multi,push,multi")
2233169699Skan   (set_attr "unit" "i387,*,*")
223490286Sobrien   (set_attr "mode" "SF,SI,SF")])
223518334Speter
223690286Sobrien(define_insn "*pushsf_rex64"
223790286Sobrien  [(set (match_operand:SF 0 "push_operand" "=X,X,X")
2238169699Skan	(match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
223990286Sobrien  "TARGET_64BIT"
224018334Speter{
2241169699Skan  /* Anything else should be already split before reg-stack.  */
2242169699Skan  gcc_assert (which_alternative == 1);
2243169699Skan  return "push{q}\t%q1";
224490286Sobrien}
224590286Sobrien  [(set_attr "type" "multi,push,multi")
2246169699Skan   (set_attr "unit" "i387,*,*")
224790286Sobrien   (set_attr "mode" "SF,DI,SF")])
224818334Speter
224990286Sobrien(define_split
225090286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
225190286Sobrien	(match_operand:SF 1 "memory_operand" ""))]
225290286Sobrien  "reload_completed
225390286Sobrien   && GET_CODE (operands[1]) == MEM
2254161660Skan   && constant_pool_reference_p (operands[1])"
225590286Sobrien  [(set (match_dup 0)
225690286Sobrien	(match_dup 1))]
2257161660Skan  "operands[1] = avoid_constant_pool_reference (operands[1]);")
225818334Speter
225990286Sobrien
226090286Sobrien;; %%% Kill this when call knows how to work this out.
226190286Sobrien(define_split
226290286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
2263117404Skan	(match_operand:SF 1 "any_fp_register_operand" ""))]
2264117404Skan  "!TARGET_64BIT"
2265169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
2266169699Skan   (set (mem:SF (reg:SI SP_REG)) (match_dup 1))])
226790286Sobrien
226890286Sobrien(define_split
226990286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
2270117404Skan	(match_operand:SF 1 "any_fp_register_operand" ""))]
2271117404Skan  "TARGET_64BIT"
2272169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
2273169699Skan   (set (mem:SF (reg:DI SP_REG)) (match_dup 1))])
227490286Sobrien
227590286Sobrien(define_insn "*movsf_1"
2276169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"
2277169699Skan	  "=f,m   ,f,r  ,m    ,x,x,x ,m   ,!*y,!rm,!*y")
2278169699Skan	(match_operand:SF 1 "general_operand"
2279169699Skan	  "fm,f,G   ,rmF,Fr,C   ,x   ,xm,x,rm ,*y ,*y"))]
2280169699Skan  "!(MEM_P (operands[0]) && MEM_P (operands[1]))
228190286Sobrien   && (reload_in_progress || reload_completed
228290286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
228390286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
228490286Sobrien       || memory_operand (operands[0], SFmode))" 
228590286Sobrien{
228690286Sobrien  switch (which_alternative)
228718334Speter    {
228890286Sobrien    case 0:
2289169699Skan      return output_387_reg_move (insn, operands);
229018334Speter
229190286Sobrien    case 1:
229290286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
229390286Sobrien        return "fstp%z0\t%y0";
229490286Sobrien      else
229590286Sobrien        return "fst%z0\t%y0";
229618334Speter
229790286Sobrien    case 2:
2298132727Skan      return standard_80387_constant_opcode (operands[1]);
2299132727Skan
2300132727Skan    case 3:
2301132727Skan    case 4:
2302132727Skan      return "mov{l}\t{%1, %0|%0, %1}";
2303132727Skan    case 5:
2304132727Skan      if (get_attr_mode (insn) == MODE_TI)
2305132727Skan	return "pxor\t%0, %0";
2306132727Skan      else
2307132727Skan	return "xorps\t%0, %0";
2308132727Skan    case 6:
2309132727Skan      if (get_attr_mode (insn) == MODE_V4SF)
2310132727Skan	return "movaps\t{%1, %0|%0, %1}";
2311132727Skan      else
2312132727Skan	return "movss\t{%1, %0|%0, %1}";
2313132727Skan    case 7:
2314132727Skan    case 8:
2315132727Skan      return "movss\t{%1, %0|%0, %1}";
2316132727Skan
2317132727Skan    case 9:
2318132727Skan    case 10:
2319132727Skan      return "movd\t{%1, %0|%0, %1}";
2320132727Skan
2321132727Skan    case 11:
2322132727Skan      return "movq\t{%1, %0|%0, %1}";
2323132727Skan
2324132727Skan    default:
2325169699Skan      gcc_unreachable ();
2326132727Skan    }
2327132727Skan}
2328169699Skan  [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov")
2329132727Skan   (set (attr "mode")
2330132727Skan        (cond [(eq_attr "alternative" "3,4,9,10")
2331132727Skan		 (const_string "SI")
2332132727Skan	       (eq_attr "alternative" "5")
2333132727Skan		 (if_then_else
2334132727Skan		   (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2335132727Skan			    	 (const_int 0))
2336132727Skan			     (ne (symbol_ref "TARGET_SSE2")
2337132727Skan				 (const_int 0)))
2338132727Skan			(eq (symbol_ref "optimize_size")
2339132727Skan			    (const_int 0)))
2340132727Skan		   (const_string "TI")
2341132727Skan		   (const_string "V4SF"))
2342132727Skan	       /* For architectures resolving dependencies on
2343132727Skan		  whole SSE registers use APS move to break dependency
2344132727Skan		  chains, otherwise use short move to avoid extra work. 
234518334Speter
2346132727Skan		  Do the same for architectures resolving dependencies on
2347132727Skan		  the parts.  While in DF mode it is better to always handle
2348132727Skan		  just register parts, the SF mode is different due to lack
2349132727Skan		  of instructions to load just part of the register.  It is
2350132727Skan		  better to maintain the whole registers in single format
2351132727Skan		  to avoid problems on using packed logical operations.  */
2352132727Skan	       (eq_attr "alternative" "6")
2353132727Skan		 (if_then_else
2354132727Skan		   (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2355132727Skan			    (const_int 0))
2356169699Skan			(ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2357132727Skan			    (const_int 0)))
2358132727Skan		   (const_string "V4SF")
2359132727Skan		   (const_string "SF"))
2360132727Skan	       (eq_attr "alternative" "11")
2361132727Skan		 (const_string "DI")]
2362132727Skan	       (const_string "SF")))])
2363132727Skan
236490286Sobrien(define_insn "*swapsf"
2365169699Skan  [(set (match_operand:SF 0 "fp_register_operand" "+f")
2366169699Skan	(match_operand:SF 1 "fp_register_operand" "+f"))
236718334Speter   (set (match_dup 1)
236818334Speter	(match_dup 0))]
2369169699Skan  "reload_completed || TARGET_80387"
237018334Speter{
237118334Speter  if (STACK_TOP_P (operands[0]))
237290286Sobrien    return "fxch\t%1";
237318334Speter  else
237490286Sobrien    return "fxch\t%0";
237590286Sobrien}
237690286Sobrien  [(set_attr "type" "fxch")
237790286Sobrien   (set_attr "mode" "SF")])
237818334Speter
237990286Sobrien(define_expand "movdf"
238090286Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
238190286Sobrien	(match_operand:DF 1 "general_operand" ""))]
238290286Sobrien  ""
238390286Sobrien  "ix86_expand_move (DFmode, operands); DONE;")
238452296Sobrien
238590286Sobrien;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
2386132727Skan;; Size of pushdf using integer instructions is 2+2*memory operand size
238790286Sobrien;; On the average, pushdf using integers can be still shorter.  Allow this
238890286Sobrien;; pattern for optimize_size too.
238990286Sobrien
239090286Sobrien(define_insn "*pushdf_nointeger"
239190286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
2392169699Skan	(match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))]
239390286Sobrien  "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
239418334Speter{
2395132727Skan  /* This insn should be already split before reg-stack.  */
2396169699Skan  gcc_unreachable ();
239790286Sobrien}
239890286Sobrien  [(set_attr "type" "multi")
2399169699Skan   (set_attr "unit" "i387,*,*,*")
240090286Sobrien   (set_attr "mode" "DF,SI,SI,DF")])
240118334Speter
240290286Sobrien(define_insn "*pushdf_integer"
240390286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<,<,<")
2404169699Skan	(match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))]
240590286Sobrien  "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
240690286Sobrien{
2407132727Skan  /* This insn should be already split before reg-stack.  */
2408169699Skan  gcc_unreachable ();
240990286Sobrien}
241090286Sobrien  [(set_attr "type" "multi")
2411169699Skan   (set_attr "unit" "i387,*,*")
241290286Sobrien   (set_attr "mode" "DF,SI,DF")])
241318334Speter
241490286Sobrien;; %%% Kill this when call knows how to work this out.
241552296Sobrien(define_split
241652296Sobrien  [(set (match_operand:DF 0 "push_operand" "")
2417117404Skan	(match_operand:DF 1 "any_fp_register_operand" ""))]
2418117404Skan  "!TARGET_64BIT && reload_completed"
2419169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
2420169699Skan   (set (mem:DF (reg:SI SP_REG)) (match_dup 1))]
242152296Sobrien  "")
242250650Sobrien
242390286Sobrien(define_split
242490286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
2425117404Skan	(match_operand:DF 1 "any_fp_register_operand" ""))]
2426117404Skan  "TARGET_64BIT && reload_completed"
2427169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
2428169699Skan   (set (mem:DF (reg:DI SP_REG)) (match_dup 1))]
242990286Sobrien  "")
243090286Sobrien
243190286Sobrien(define_split
243290286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
243350650Sobrien	(match_operand:DF 1 "general_operand" ""))]
243490286Sobrien  "reload_completed"
243590286Sobrien  [(const_int 0)]
243690286Sobrien  "ix86_split_long_move (operands); DONE;")
243790286Sobrien
243890286Sobrien;; Moving is usually shorter when only FP registers are used. This separate
243990286Sobrien;; movdf pattern avoids the use of integer registers for FP operations
244090286Sobrien;; when optimizing for size.
244190286Sobrien
244290286Sobrien(define_insn "*movdf_nointeger"
2443169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"
2444169699Skan			"=f,m,f,*r  ,o  ,Y*x,Y*x,Y*x ,m  ")
2445169699Skan	(match_operand:DF 1 "general_operand"
2446169699Skan			"fm,f,G,*roF,F*r,C  ,Y*x,mY*x,Y*x"))]
244790286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2448132727Skan   && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
244990286Sobrien   && (reload_in_progress || reload_completed
245090286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
245190286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
245290286Sobrien       || memory_operand (operands[0], DFmode))" 
245318334Speter{
245490286Sobrien  switch (which_alternative)
245518334Speter    {
245690286Sobrien    case 0:
2457169699Skan      return output_387_reg_move (insn, operands);
245818334Speter
245990286Sobrien    case 1:
246090286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
246190286Sobrien        return "fstp%z0\t%y0";
246290286Sobrien      else
246390286Sobrien        return "fst%z0\t%y0";
246418334Speter
246590286Sobrien    case 2:
2466132727Skan      return standard_80387_constant_opcode (operands[1]);
246718334Speter
246890286Sobrien    case 3:
246990286Sobrien    case 4:
247090286Sobrien      return "#";
247190286Sobrien    case 5:
2472132727Skan      switch (get_attr_mode (insn))
2473132727Skan	{
2474132727Skan	case MODE_V4SF:
2475132727Skan	  return "xorps\t%0, %0";
2476132727Skan	case MODE_V2DF:
2477132727Skan	  return "xorpd\t%0, %0";
2478132727Skan	case MODE_TI:
2479132727Skan	  return "pxor\t%0, %0";
2480132727Skan	default:
2481169699Skan	  gcc_unreachable ();
2482132727Skan	}
248390286Sobrien    case 6:
2484169699Skan    case 7:
2485169699Skan    case 8:
2486132727Skan      switch (get_attr_mode (insn))
2487132727Skan	{
2488132727Skan	case MODE_V4SF:
2489132727Skan	  return "movaps\t{%1, %0|%0, %1}";
2490132727Skan	case MODE_V2DF:
2491132727Skan	  return "movapd\t{%1, %0|%0, %1}";
2492169699Skan	case MODE_TI:
2493169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
2494169699Skan	case MODE_DI:
2495169699Skan	  return "movq\t{%1, %0|%0, %1}";
2496132727Skan	case MODE_DF:
2497132727Skan	  return "movsd\t{%1, %0|%0, %1}";
2498169699Skan	case MODE_V1DF:
2499169699Skan	  return "movlpd\t{%1, %0|%0, %1}";
2500169699Skan	case MODE_V2SF:
2501169699Skan	  return "movlps\t{%1, %0|%0, %1}";
2502132727Skan	default:
2503169699Skan	  gcc_unreachable ();
2504132727Skan	}
250518334Speter
250690286Sobrien    default:
2507169699Skan      gcc_unreachable ();
250818334Speter    }
250990286Sobrien}
2510169699Skan  [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
2511132727Skan   (set (attr "mode")
2512169699Skan        (cond [(eq_attr "alternative" "0,1,2")
2513169699Skan		 (const_string "DF")
2514169699Skan	       (eq_attr "alternative" "3,4")
2515132727Skan		 (const_string "SI")
2516169699Skan
2517169699Skan	       /* For SSE1, we have many fewer alternatives.  */
2518169699Skan	       (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2519169699Skan		 (cond [(eq_attr "alternative" "5,6")
2520169699Skan			  (const_string "V4SF")
2521169699Skan		       ]
2522169699Skan		   (const_string "V2SF"))
2523169699Skan
2524132727Skan	       /* xorps is one byte shorter.  */
2525132727Skan	       (eq_attr "alternative" "5")
2526132727Skan		 (cond [(ne (symbol_ref "optimize_size")
2527132727Skan			    (const_int 0))
2528132727Skan			  (const_string "V4SF")
2529132727Skan			(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2530132727Skan			    (const_int 0))
2531169699Skan			  (const_string "TI")
2532169699Skan		       ]
2533132727Skan		       (const_string "V2DF"))
2534169699Skan
2535132727Skan	       /* For architectures resolving dependencies on
2536132727Skan		  whole SSE registers use APD move to break dependency
2537132727Skan		  chains, otherwise use short move to avoid extra work.
253818334Speter
2539132727Skan		  movaps encodes one byte shorter.  */
2540132727Skan	       (eq_attr "alternative" "6")
2541132727Skan		 (cond
2542169699Skan		   [(ne (symbol_ref "optimize_size")
2543169699Skan		        (const_int 0))
2544169699Skan		      (const_string "V4SF")
2545169699Skan		    (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2546169699Skan		        (const_int 0))
2547169699Skan		      (const_string "V2DF")
2548169699Skan		   ]
2549132727Skan		   (const_string "DF"))
2550132727Skan	       /* For architectures resolving dependencies on register
2551132727Skan		  parts we may avoid extra work to zero out upper part
2552132727Skan		  of register.  */
2553132727Skan	       (eq_attr "alternative" "7")
2554132727Skan		 (if_then_else
2555169699Skan		   (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2556132727Skan		       (const_int 0))
2557169699Skan		   (const_string "V1DF")
2558169699Skan		   (const_string "DF"))
2559169699Skan	      ]
2560169699Skan	      (const_string "DF")))])
2561132727Skan
256290286Sobrien(define_insn "*movdf_integer"
2563169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"
2564169699Skan		"=f,m,f,r  ,o ,Y*x,Y*x,Y*x,m  ")
2565169699Skan	(match_operand:DF 1 "general_operand"
2566169699Skan		"fm,f,G,roF,Fr,C  ,Y*x,m  ,Y*x"))]
256790286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2568132727Skan   && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
256990286Sobrien   && (reload_in_progress || reload_completed
257090286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
257190286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
257290286Sobrien       || memory_operand (operands[0], DFmode))" 
257390286Sobrien{
257490286Sobrien  switch (which_alternative)
257518334Speter    {
257690286Sobrien    case 0:
2577169699Skan      return output_387_reg_move (insn, operands);
257818334Speter
257990286Sobrien    case 1:
258090286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
258190286Sobrien        return "fstp%z0\t%y0";
258290286Sobrien      else
258390286Sobrien        return "fst%z0\t%y0";
258418334Speter
258590286Sobrien    case 2:
2586132727Skan      return standard_80387_constant_opcode (operands[1]);
258718334Speter
258890286Sobrien    case 3:
258990286Sobrien    case 4:
259090286Sobrien      return "#";
259118334Speter
259290286Sobrien    case 5:
2593132727Skan      switch (get_attr_mode (insn))
2594132727Skan	{
2595132727Skan	case MODE_V4SF:
2596132727Skan	  return "xorps\t%0, %0";
2597132727Skan	case MODE_V2DF:
2598132727Skan	  return "xorpd\t%0, %0";
2599132727Skan	case MODE_TI:
2600132727Skan	  return "pxor\t%0, %0";
2601132727Skan	default:
2602169699Skan	  gcc_unreachable ();
2603132727Skan	}
260490286Sobrien    case 6:
2605169699Skan    case 7:
2606169699Skan    case 8:
2607132727Skan      switch (get_attr_mode (insn))
2608132727Skan	{
2609132727Skan	case MODE_V4SF:
2610132727Skan	  return "movaps\t{%1, %0|%0, %1}";
2611132727Skan	case MODE_V2DF:
2612132727Skan	  return "movapd\t{%1, %0|%0, %1}";
2613169699Skan	case MODE_TI:
2614169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
2615169699Skan	case MODE_DI:
2616169699Skan	  return "movq\t{%1, %0|%0, %1}";
2617132727Skan	case MODE_DF:
2618132727Skan	  return "movsd\t{%1, %0|%0, %1}";
2619169699Skan	case MODE_V1DF:
2620169699Skan	  return "movlpd\t{%1, %0|%0, %1}";
2621169699Skan	case MODE_V2SF:
2622169699Skan	  return "movlps\t{%1, %0|%0, %1}";
2623132727Skan	default:
2624169699Skan	  gcc_unreachable ();
2625132727Skan	}
262618334Speter
262790286Sobrien    default:
2628169699Skan      gcc_unreachable();
262990286Sobrien    }
263090286Sobrien}
2631169699Skan  [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
2632132727Skan   (set (attr "mode")
2633169699Skan        (cond [(eq_attr "alternative" "0,1,2")
2634169699Skan		 (const_string "DF")
2635169699Skan	       (eq_attr "alternative" "3,4")
2636132727Skan		 (const_string "SI")
2637169699Skan
2638169699Skan	       /* For SSE1, we have many fewer alternatives.  */
2639169699Skan	       (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2640169699Skan		 (cond [(eq_attr "alternative" "5,6")
2641169699Skan			  (const_string "V4SF")
2642169699Skan		       ]
2643169699Skan		   (const_string "V2SF"))
2644169699Skan
2645132727Skan	       /* xorps is one byte shorter.  */
2646132727Skan	       (eq_attr "alternative" "5")
2647132727Skan		 (cond [(ne (symbol_ref "optimize_size")
2648132727Skan			    (const_int 0))
2649132727Skan			  (const_string "V4SF")
2650132727Skan			(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2651132727Skan			    (const_int 0))
2652169699Skan			  (const_string "TI")
2653169699Skan		       ]
2654132727Skan		       (const_string "V2DF"))
2655169699Skan
2656132727Skan	       /* For architectures resolving dependencies on
2657132727Skan		  whole SSE registers use APD move to break dependency
2658169699Skan		  chains, otherwise use short move to avoid extra work.
265918334Speter
2660132727Skan		  movaps encodes one byte shorter.  */
2661132727Skan	       (eq_attr "alternative" "6")
2662132727Skan		 (cond
2663169699Skan		   [(ne (symbol_ref "optimize_size")
2664169699Skan		        (const_int 0))
2665169699Skan		      (const_string "V4SF")
2666169699Skan		    (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2667169699Skan		        (const_int 0))
2668169699Skan		      (const_string "V2DF")
2669169699Skan		   ]
2670132727Skan		   (const_string "DF"))
2671132727Skan	       /* For architectures resolving dependencies on register
2672132727Skan		  parts we may avoid extra work to zero out upper part
2673132727Skan		  of register.  */
2674132727Skan	       (eq_attr "alternative" "7")
2675132727Skan		 (if_then_else
2676169699Skan		   (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2677132727Skan		       (const_int 0))
2678169699Skan		   (const_string "V1DF")
2679169699Skan		   (const_string "DF"))
2680169699Skan	      ]
2681169699Skan	      (const_string "DF")))])
2682132727Skan
268390286Sobrien(define_split
268490286Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
268590286Sobrien	(match_operand:DF 1 "general_operand" ""))]
268690286Sobrien  "reload_completed
268790286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
268890286Sobrien   && ! (ANY_FP_REG_P (operands[0]) || 
268990286Sobrien	 (GET_CODE (operands[0]) == SUBREG
269090286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
269190286Sobrien   && ! (ANY_FP_REG_P (operands[1]) || 
269290286Sobrien	 (GET_CODE (operands[1]) == SUBREG
269390286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
269490286Sobrien  [(const_int 0)]
269590286Sobrien  "ix86_split_long_move (operands); DONE;")
269650650Sobrien
269790286Sobrien(define_insn "*swapdf"
2698169699Skan  [(set (match_operand:DF 0 "fp_register_operand" "+f")
2699169699Skan	(match_operand:DF 1 "fp_register_operand" "+f"))
270018334Speter   (set (match_dup 1)
270118334Speter	(match_dup 0))]
2702169699Skan  "reload_completed || TARGET_80387"
270318334Speter{
270418334Speter  if (STACK_TOP_P (operands[0]))
270590286Sobrien    return "fxch\t%1";
270618334Speter  else
270790286Sobrien    return "fxch\t%0";
270890286Sobrien}
270990286Sobrien  [(set_attr "type" "fxch")
271090286Sobrien   (set_attr "mode" "DF")])
271118334Speter
271290286Sobrien(define_expand "movxf"
271390286Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
271490286Sobrien	(match_operand:XF 1 "general_operand" ""))]
2715132727Skan  ""
271690286Sobrien  "ix86_expand_move (XFmode, operands); DONE;")
271790286Sobrien
271890286Sobrien;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
2719132727Skan;; Size of pushdf using integer instructions is 3+3*memory operand size
272090286Sobrien;; Pushing using integer instructions is longer except for constants
272190286Sobrien;; and direct memory references.
272290286Sobrien;; (assuming that any given constant is pushed only once, but this ought to be
272390286Sobrien;;  handled elsewhere).
272490286Sobrien
272590286Sobrien(define_insn "*pushxf_nointeger"
272690286Sobrien  [(set (match_operand:XF 0 "push_operand" "=X,X,X")
272790286Sobrien	(match_operand:XF 1 "general_no_elim_operand" "f,Fo,*r"))]
272890286Sobrien  "optimize_size"
272990286Sobrien{
2730132727Skan  /* This insn should be already split before reg-stack.  */
2731169699Skan  gcc_unreachable ();
273290286Sobrien}
273390286Sobrien  [(set_attr "type" "multi")
2734169699Skan   (set_attr "unit" "i387,*,*")
273590286Sobrien   (set_attr "mode" "XF,SI,SI")])
273650650Sobrien
273790286Sobrien(define_insn "*pushxf_integer"
273890286Sobrien  [(set (match_operand:XF 0 "push_operand" "=<,<")
2739169699Skan	(match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
274090286Sobrien  "!optimize_size"
274190286Sobrien{
2742132727Skan  /* This insn should be already split before reg-stack.  */
2743169699Skan  gcc_unreachable ();
274490286Sobrien}
274590286Sobrien  [(set_attr "type" "multi")
2746169699Skan   (set_attr "unit" "i387,*")
274790286Sobrien   (set_attr "mode" "XF,SI")])
274890286Sobrien
274952296Sobrien(define_split
275090286Sobrien  [(set (match_operand 0 "push_operand" "")
275190286Sobrien	(match_operand 1 "general_operand" ""))]
275290286Sobrien  "reload_completed
275390286Sobrien   && (GET_MODE (operands[0]) == XFmode
275490286Sobrien       || GET_MODE (operands[0]) == DFmode)
2755117404Skan   && !ANY_FP_REG_P (operands[1])"
275690286Sobrien  [(const_int 0)]
275790286Sobrien  "ix86_split_long_move (operands); DONE;")
275890286Sobrien
275990286Sobrien(define_split
276052296Sobrien  [(set (match_operand:XF 0 "push_operand" "")
2761117404Skan	(match_operand:XF 1 "any_fp_register_operand" ""))]
2762117404Skan  "!TARGET_64BIT"
2763169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
2764169699Skan   (set (mem:XF (reg:SI SP_REG)) (match_dup 1))]
2765132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
276650650Sobrien
276790286Sobrien(define_split
2768132727Skan  [(set (match_operand:XF 0 "push_operand" "")
2769132727Skan	(match_operand:XF 1 "any_fp_register_operand" ""))]
2770117404Skan  "TARGET_64BIT"
2771169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
2772169699Skan   (set (mem:XF (reg:DI SP_REG)) (match_dup 1))]
2773132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
277490286Sobrien
277590286Sobrien;; Do not use integer registers when optimizing for size
277690286Sobrien(define_insn "*movxf_nointeger"
277790286Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o")
277890286Sobrien	(match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))]
2779132727Skan  "optimize_size
278090286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
278190286Sobrien   && (reload_in_progress || reload_completed
278290286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
278390286Sobrien       || memory_operand (operands[0], XFmode))" 
278418334Speter{
278590286Sobrien  switch (which_alternative)
278618334Speter    {
278790286Sobrien    case 0:
2788169699Skan      return output_387_reg_move (insn, operands);
278918334Speter
279090286Sobrien    case 1:
279190286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
279290286Sobrien	 we need one, follow the store with a load.  */
279390286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
279490286Sobrien        return "fstp%z0\t%y0\;fld%z0\t%y0";
279590286Sobrien      else
279690286Sobrien        return "fstp%z0\t%y0";
279718334Speter
279890286Sobrien    case 2:
2799132727Skan      return standard_80387_constant_opcode (operands[1]);
280018334Speter
280190286Sobrien    case 3: case 4:
280290286Sobrien      return "#";
2803169699Skan    default:
2804169699Skan      gcc_unreachable ();
280590286Sobrien    }
280690286Sobrien}
280790286Sobrien  [(set_attr "type" "fmov,fmov,fmov,multi,multi")
280890286Sobrien   (set_attr "mode" "XF,XF,XF,SI,SI")])
280918334Speter
281090286Sobrien(define_insn "*movxf_integer"
2811169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
2812169699Skan	(match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
2813132727Skan  "!optimize_size
281490286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
281590286Sobrien   && (reload_in_progress || reload_completed
281690286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
281790286Sobrien       || memory_operand (operands[0], XFmode))" 
281890286Sobrien{
281990286Sobrien  switch (which_alternative)
282018334Speter    {
282190286Sobrien    case 0:
2822169699Skan      return output_387_reg_move (insn, operands);
282318334Speter
282490286Sobrien    case 1:
282590286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
282690286Sobrien	 we need one, follow the store with a load.  */
282790286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
282890286Sobrien        return "fstp%z0\t%y0\;fld%z0\t%y0";
282990286Sobrien      else
283090286Sobrien        return "fstp%z0\t%y0";
283118334Speter
283290286Sobrien    case 2:
2833132727Skan      return standard_80387_constant_opcode (operands[1]);
283418334Speter
283590286Sobrien    case 3: case 4:
283690286Sobrien      return "#";
2837169699Skan
2838169699Skan    default:
2839169699Skan      gcc_unreachable ();
284090286Sobrien    }
284190286Sobrien}
284290286Sobrien  [(set_attr "type" "fmov,fmov,fmov,multi,multi")
284390286Sobrien   (set_attr "mode" "XF,XF,XF,SI,SI")])
284418334Speter
284590286Sobrien(define_split
284690286Sobrien  [(set (match_operand 0 "nonimmediate_operand" "")
284790286Sobrien	(match_operand 1 "general_operand" ""))]
284890286Sobrien  "reload_completed
284990286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2850132727Skan   && GET_MODE (operands[0]) == XFmode
285190286Sobrien   && ! (ANY_FP_REG_P (operands[0]) || 
285290286Sobrien	 (GET_CODE (operands[0]) == SUBREG
285390286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
285490286Sobrien   && ! (ANY_FP_REG_P (operands[1]) || 
285590286Sobrien	 (GET_CODE (operands[1]) == SUBREG
285690286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
285790286Sobrien  [(const_int 0)]
285890286Sobrien  "ix86_split_long_move (operands); DONE;")
285918334Speter
286090286Sobrien(define_split
286190286Sobrien  [(set (match_operand 0 "register_operand" "")
286290286Sobrien	(match_operand 1 "memory_operand" ""))]
286390286Sobrien  "reload_completed
286490286Sobrien   && GET_CODE (operands[1]) == MEM
2865132727Skan   && (GET_MODE (operands[0]) == XFmode
286690286Sobrien       || GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode)
2867161660Skan   && constant_pool_reference_p (operands[1])"
2868132727Skan  [(set (match_dup 0) (match_dup 1))]
2869132727Skan{
2870161660Skan  rtx c = avoid_constant_pool_reference (operands[1]);
2871132727Skan  rtx r = operands[0];
287290286Sobrien
2873132727Skan  if (GET_CODE (r) == SUBREG)
2874132727Skan    r = SUBREG_REG (r);
2875132727Skan
2876132727Skan  if (SSE_REG_P (r))
2877132727Skan    {
2878132727Skan      if (!standard_sse_constant_p (c))
2879132727Skan	FAIL;
2880132727Skan    }
2881132727Skan  else if (FP_REG_P (r))
2882132727Skan    {
2883132727Skan      if (!standard_80387_constant_p (c))
2884132727Skan	FAIL;
2885132727Skan    }
2886132727Skan  else if (MMX_REG_P (r))
2887132727Skan    FAIL;
2888132727Skan
2889132727Skan  operands[1] = c;
2890132727Skan})
2891132727Skan
289290286Sobrien(define_insn "swapxf"
289390286Sobrien  [(set (match_operand:XF 0 "register_operand" "+f")
289490286Sobrien	(match_operand:XF 1 "register_operand" "+f"))
289518334Speter   (set (match_dup 1)
289618334Speter	(match_dup 0))]
2897169699Skan  "TARGET_80387"
289818334Speter{
289918334Speter  if (STACK_TOP_P (operands[0]))
290090286Sobrien    return "fxch\t%1";
290118334Speter  else
290290286Sobrien    return "fxch\t%0";
290390286Sobrien}
290490286Sobrien  [(set_attr "type" "fxch")
290590286Sobrien   (set_attr "mode" "XF")])
2906169699Skan
2907169699Skan(define_expand "movtf"
2908169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "")
2909169699Skan	(match_operand:TF 1 "nonimmediate_operand" ""))]
2910169699Skan  "TARGET_64BIT"
2911169699Skan{
2912169699Skan  ix86_expand_move (TFmode, operands);
2913169699Skan  DONE;
2914169699Skan})
2915169699Skan
2916169699Skan(define_insn "*movtf_internal"
2917169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm")
2918169699Skan	(match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))]
2919169699Skan  "TARGET_64BIT
2920169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2921169699Skan{
2922169699Skan  switch (which_alternative)
2923169699Skan    {
2924169699Skan    case 0:
2925169699Skan    case 1:
2926169699Skan      return "#";
2927169699Skan    case 2:
2928169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2929169699Skan	return "xorps\t%0, %0";
2930169699Skan      else
2931169699Skan	return "pxor\t%0, %0";
2932169699Skan    case 3:
2933169699Skan    case 4:
2934169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2935169699Skan	return "movaps\t{%1, %0|%0, %1}";
2936169699Skan      else
2937169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2938169699Skan    default:
2939169699Skan      gcc_unreachable ();
2940169699Skan    }
2941169699Skan}
2942169699Skan  [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
2943169699Skan   (set (attr "mode")
2944169699Skan        (cond [(eq_attr "alternative" "2,3")
2945169699Skan		 (if_then_else
2946169699Skan		   (ne (symbol_ref "optimize_size")
2947169699Skan		       (const_int 0))
2948169699Skan		   (const_string "V4SF")
2949169699Skan		   (const_string "TI"))
2950169699Skan	       (eq_attr "alternative" "4")
2951169699Skan		 (if_then_else
2952169699Skan		   (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2953169699Skan			    (const_int 0))
2954169699Skan			(ne (symbol_ref "optimize_size")
2955169699Skan			    (const_int 0)))
2956169699Skan		   (const_string "V4SF")
2957169699Skan		   (const_string "TI"))]
2958169699Skan	       (const_string "DI")))])
2959169699Skan
2960169699Skan(define_split
2961169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "")
2962169699Skan        (match_operand:TF 1 "general_operand" ""))]
2963169699Skan  "reload_completed && !SSE_REG_P (operands[0])
2964169699Skan   && !SSE_REG_P (operands[1])"
2965169699Skan  [(const_int 0)]
2966169699Skan  "ix86_split_long_move (operands); DONE;")
296718334Speter
296890286Sobrien;; Zero extension instructions
296918334Speter
297052296Sobrien(define_expand "zero_extendhisi2"
297152296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
297290286Sobrien     (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
297352296Sobrien  ""
297490286Sobrien{
297590286Sobrien  if (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
297618334Speter    {
297790286Sobrien      operands[1] = force_reg (HImode, operands[1]);
297890286Sobrien      emit_insn (gen_zero_extendhisi2_and (operands[0], operands[1]));
297990286Sobrien      DONE;
298018334Speter    }
298190286Sobrien})
298218334Speter
298390286Sobrien(define_insn "zero_extendhisi2_and"
298490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
298590286Sobrien     (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
2986169699Skan   (clobber (reg:CC FLAGS_REG))]
298790286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
298890286Sobrien  "#"
298990286Sobrien  [(set_attr "type" "alu1")
299090286Sobrien   (set_attr "mode" "SI")])
299150650Sobrien
299250650Sobrien(define_split
299350650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
299490286Sobrien	(zero_extend:SI (match_operand:HI 1 "register_operand" "")))
2995169699Skan   (clobber (reg:CC FLAGS_REG))]
299690286Sobrien  "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
299790286Sobrien  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535)))
2998169699Skan	      (clobber (reg:CC FLAGS_REG))])]
299990286Sobrien  "")
300050650Sobrien
300190286Sobrien(define_insn "*zero_extendhisi2_movzwl"
300290286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
300390286Sobrien     (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
300490286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
300590286Sobrien  "movz{wl|x}\t{%1, %0|%0, %1}"
300690286Sobrien  [(set_attr "type" "imovx")
300790286Sobrien   (set_attr "mode" "SI")])
300850650Sobrien
300952296Sobrien(define_expand "zero_extendqihi2"
301090286Sobrien  [(parallel
301190286Sobrien    [(set (match_operand:HI 0 "register_operand" "")
301290286Sobrien       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3013169699Skan     (clobber (reg:CC FLAGS_REG))])]
301452296Sobrien  ""
301552296Sobrien  "")
301652296Sobrien
301790286Sobrien(define_insn "*zero_extendqihi2_and"
301890286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,?&q")
301990286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
3020169699Skan   (clobber (reg:CC FLAGS_REG))]
302190286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
302290286Sobrien  "#"
302390286Sobrien  [(set_attr "type" "alu1")
302490286Sobrien   (set_attr "mode" "HI")])
302552296Sobrien
302690286Sobrien(define_insn "*zero_extendqihi2_movzbw_and"
302790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
302890286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
3029169699Skan   (clobber (reg:CC FLAGS_REG))]
303090286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
303190286Sobrien  "#"
303290286Sobrien  [(set_attr "type" "imovx,alu1")
303390286Sobrien   (set_attr "mode" "HI")])
303452296Sobrien
3035169699Skan; zero extend to SImode here to avoid partial register stalls
3036169699Skan(define_insn "*zero_extendqihi2_movzbl"
303790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r")
303890286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
303990286Sobrien  "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
3040169699Skan  "movz{bl|x}\t{%1, %k0|%k0, %k1}"
304190286Sobrien  [(set_attr "type" "imovx")
3042169699Skan   (set_attr "mode" "SI")])
304350650Sobrien
304490286Sobrien;; For the movzbw case strip only the clobber
304550650Sobrien(define_split
304650650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
304790286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3048169699Skan   (clobber (reg:CC FLAGS_REG))]
304990286Sobrien  "reload_completed 
305090286Sobrien   && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
305190286Sobrien   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
305290286Sobrien  [(set (match_operand:HI 0 "register_operand" "")
305390286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))])
305450650Sobrien
305590286Sobrien;; When source and destination does not overlap, clear destination
305690286Sobrien;; first and then do the movb
305750650Sobrien(define_split
305850650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
305990286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3060169699Skan   (clobber (reg:CC FLAGS_REG))]
306190286Sobrien  "reload_completed
306290286Sobrien   && ANY_QI_REG_P (operands[0])
306390286Sobrien   && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
306490286Sobrien   && !reg_overlap_mentioned_p (operands[0], operands[1])"
306590286Sobrien  [(set (match_dup 0) (const_int 0))
306690286Sobrien   (set (strict_low_part (match_dup 2)) (match_dup 1))]
306790286Sobrien  "operands[2] = gen_lowpart (QImode, operands[0]);")
306850650Sobrien
306990286Sobrien;; Rest is handled by single and.
307050650Sobrien(define_split
307150650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
307290286Sobrien	(zero_extend:HI (match_operand:QI 1 "register_operand" "")))
3073169699Skan   (clobber (reg:CC FLAGS_REG))]
307490286Sobrien  "reload_completed
307590286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
307690286Sobrien  [(parallel [(set (match_dup 0) (and:HI (match_dup 0) (const_int 255)))
3077169699Skan	      (clobber (reg:CC FLAGS_REG))])]
307890286Sobrien  "")
307950650Sobrien
308052296Sobrien(define_expand "zero_extendqisi2"
308190286Sobrien  [(parallel
308290286Sobrien    [(set (match_operand:SI 0 "register_operand" "")
308390286Sobrien       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3084169699Skan     (clobber (reg:CC FLAGS_REG))])]
308552296Sobrien  ""
308652296Sobrien  "")
308752296Sobrien
308890286Sobrien(define_insn "*zero_extendqisi2_and"
308990286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,?&q")
309090286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
3091169699Skan   (clobber (reg:CC FLAGS_REG))]
309290286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
309390286Sobrien  "#"
309490286Sobrien  [(set_attr "type" "alu1")
309590286Sobrien   (set_attr "mode" "SI")])
309652296Sobrien
309790286Sobrien(define_insn "*zero_extendqisi2_movzbw_and"
309890286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
309990286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
3100169699Skan   (clobber (reg:CC FLAGS_REG))]
310190286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
310290286Sobrien  "#"
310390286Sobrien  [(set_attr "type" "imovx,alu1")
310490286Sobrien   (set_attr "mode" "SI")])
310550650Sobrien
310690286Sobrien(define_insn "*zero_extendqisi2_movzbw"
310790286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
310890286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
310990286Sobrien  "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
311090286Sobrien  "movz{bl|x}\t{%1, %0|%0, %1}"
311190286Sobrien  [(set_attr "type" "imovx")
311290286Sobrien   (set_attr "mode" "SI")])
311318334Speter
311490286Sobrien;; For the movzbl case strip only the clobber
311550650Sobrien(define_split
311650650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
311790286Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3118169699Skan   (clobber (reg:CC FLAGS_REG))]
311990286Sobrien  "reload_completed 
312090286Sobrien   && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
312190286Sobrien   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
312290286Sobrien  [(set (match_dup 0)
312390286Sobrien	(zero_extend:SI (match_dup 1)))])
312450650Sobrien
312590286Sobrien;; When source and destination does not overlap, clear destination
312690286Sobrien;; first and then do the movb
312750650Sobrien(define_split
312850650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
312990286Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3130169699Skan   (clobber (reg:CC FLAGS_REG))]
313190286Sobrien  "reload_completed
313290286Sobrien   && ANY_QI_REG_P (operands[0])
313390286Sobrien   && (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)
313490286Sobrien   && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
313590286Sobrien   && !reg_overlap_mentioned_p (operands[0], operands[1])"
313690286Sobrien  [(set (match_dup 0) (const_int 0))
313790286Sobrien   (set (strict_low_part (match_dup 2)) (match_dup 1))]
313890286Sobrien  "operands[2] = gen_lowpart (QImode, operands[0]);")
313950650Sobrien
314090286Sobrien;; Rest is handled by single and.
314150650Sobrien(define_split
314250650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
314390286Sobrien	(zero_extend:SI (match_operand:QI 1 "register_operand" "")))
3144169699Skan   (clobber (reg:CC FLAGS_REG))]
314590286Sobrien  "reload_completed
314690286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
314790286Sobrien  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 255)))
3148169699Skan	      (clobber (reg:CC FLAGS_REG))])]
314990286Sobrien  "")
315050650Sobrien
315190286Sobrien;; %%% Kill me once multi-word ops are sane.
315290286Sobrien(define_expand "zero_extendsidi2"
315390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
315490286Sobrien     (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
315518334Speter  ""
315690286Sobrien  "if (!TARGET_64BIT)
315790286Sobrien     {
315890286Sobrien       emit_insn (gen_zero_extendsidi2_32 (operands[0], operands[1]));
315990286Sobrien       DONE;
316090286Sobrien     }
316190286Sobrien  ")
316250650Sobrien
316390286Sobrien(define_insn "zero_extendsidi2_32"
3164169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,?*y,?*Y")
3165132727Skan	(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,rm,rm")))
3166169699Skan   (clobber (reg:CC FLAGS_REG))]
3167169699Skan  "!TARGET_64BIT"
3168132727Skan  "@
3169132727Skan   #
3170132727Skan   #
3171132727Skan   #
3172132727Skan   movd\t{%1, %0|%0, %1}
3173132727Skan   movd\t{%1, %0|%0, %1}"
3174132727Skan  [(set_attr "mode" "SI,SI,SI,DI,TI")
3175132727Skan   (set_attr "type" "multi,multi,multi,mmxmov,ssemov")])
3176132727Skan
317790286Sobrien(define_insn "zero_extendsidi2_rex64"
3178169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*y,?*Y")
3179132727Skan     (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,rm,rm")))]
3180169699Skan  "TARGET_64BIT"
3181132727Skan  "@
3182132727Skan   mov\t{%k1, %k0|%k0, %k1}
3183132727Skan   #
3184132727Skan   movd\t{%1, %0|%0, %1}
3185132727Skan   movd\t{%1, %0|%0, %1}"
3186132727Skan  [(set_attr "type" "imovx,imov,mmxmov,ssemov")
3187132727Skan   (set_attr "mode" "SI,DI,SI,SI")])
3188132727Skan
318990286Sobrien(define_split
319090286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
319190286Sobrien     (zero_extend:DI (match_dup 0)))]
319290286Sobrien  "TARGET_64BIT"
319390286Sobrien  [(set (match_dup 4) (const_int 0))]
319490286Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
319590286Sobrien
319652296Sobrien(define_split 
319752296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
319890286Sobrien	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
3199169699Skan   (clobber (reg:CC FLAGS_REG))]
320090286Sobrien  "!TARGET_64BIT && reload_completed
320190286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
320252296Sobrien  [(set (match_dup 4) (const_int 0))]
320352296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
320450650Sobrien
320552296Sobrien(define_split 
320652296Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
320790286Sobrien	(zero_extend:DI (match_operand:SI 1 "general_operand" "")))
3208169699Skan   (clobber (reg:CC FLAGS_REG))]
3209132727Skan  "!TARGET_64BIT && reload_completed
3210132727Skan   && !SSE_REG_P (operands[0]) && !MMX_REG_P (operands[0])"
321152296Sobrien  [(set (match_dup 3) (match_dup 1))
321252296Sobrien   (set (match_dup 4) (const_int 0))]
321352296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
321490286Sobrien
321590286Sobrien(define_insn "zero_extendhidi2"
3216169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
3217169699Skan     (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
321890286Sobrien  "TARGET_64BIT"
3219169699Skan  "movz{wl|x}\t{%1, %k0|%k0, %1}"
322090286Sobrien  [(set_attr "type" "imovx")
3221169699Skan   (set_attr "mode" "DI")])
322290286Sobrien
322390286Sobrien(define_insn "zero_extendqidi2"
3224169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
3225169699Skan     (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
322690286Sobrien  "TARGET_64BIT"
3227169699Skan  "movz{bl|x}\t{%1, %k0|%k0, %1}"
322890286Sobrien  [(set_attr "type" "imovx")
3229169699Skan   (set_attr "mode" "DI")])
323018334Speter
323190286Sobrien;; Sign extension instructions
323218334Speter
323390286Sobrien(define_expand "extendsidi2"
323490286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
323590286Sobrien		   (sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3236169699Skan	      (clobber (reg:CC FLAGS_REG))
323790286Sobrien	      (clobber (match_scratch:SI 2 ""))])]
323890286Sobrien  ""
323990286Sobrien{
324090286Sobrien  if (TARGET_64BIT)
324190286Sobrien    {
324290286Sobrien      emit_insn (gen_extendsidi2_rex64 (operands[0], operands[1]));
324390286Sobrien      DONE;
324490286Sobrien    }
324590286Sobrien})
324690286Sobrien
324790286Sobrien(define_insn "*extendsidi2_1"
324890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=*A,r,?r,?*o")
324990286Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,r")))
3250169699Skan   (clobber (reg:CC FLAGS_REG))
325152296Sobrien   (clobber (match_scratch:SI 2 "=X,X,X,&r"))]
325290286Sobrien  "!TARGET_64BIT"
325352296Sobrien  "#")
325452296Sobrien
325590286Sobrien(define_insn "extendsidi2_rex64"
325690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*a,r")
325790286Sobrien	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "*0,rm")))]
325890286Sobrien  "TARGET_64BIT"
325990286Sobrien  "@
326090286Sobrien   {cltq|cdqe}
326190286Sobrien   movs{lq|x}\t{%1,%0|%0, %1}"
326290286Sobrien  [(set_attr "type" "imovx")
326390286Sobrien   (set_attr "mode" "DI")
326490286Sobrien   (set_attr "prefix_0f" "0")
326590286Sobrien   (set_attr "modrm" "0,1")])
326690286Sobrien
326790286Sobrien(define_insn "extendhidi2"
326890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
326990286Sobrien	(sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
327090286Sobrien  "TARGET_64BIT"
327190286Sobrien  "movs{wq|x}\t{%1,%0|%0, %1}"
327290286Sobrien  [(set_attr "type" "imovx")
327390286Sobrien   (set_attr "mode" "DI")])
327490286Sobrien
327590286Sobrien(define_insn "extendqidi2"
327690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
327790286Sobrien	(sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
327890286Sobrien  "TARGET_64BIT"
327990286Sobrien  "movs{bq|x}\t{%1,%0|%0, %1}"
328090286Sobrien   [(set_attr "type" "imovx")
328190286Sobrien    (set_attr "mode" "DI")])
328290286Sobrien
328352296Sobrien;; Extend to memory case when source register does die.
328452296Sobrien(define_split 
328552296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
328652296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3287169699Skan   (clobber (reg:CC FLAGS_REG))
328852296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
328990286Sobrien  "(reload_completed
329052296Sobrien    && dead_or_set_p (insn, operands[1])
329152296Sobrien    && !reg_mentioned_p (operands[1], operands[0]))"
329252296Sobrien  [(set (match_dup 3) (match_dup 1))
329390286Sobrien   (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
3294169699Skan	      (clobber (reg:CC FLAGS_REG))])
329552296Sobrien   (set (match_dup 4) (match_dup 1))]
329652296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
329752296Sobrien
329852296Sobrien;; Extend to memory case when source register does not die.
329952296Sobrien(define_split 
330052296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
330152296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3302169699Skan   (clobber (reg:CC FLAGS_REG))
330352296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
330490286Sobrien  "reload_completed"
330552296Sobrien  [(const_int 0)]
330618334Speter{
330752296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
330852296Sobrien
330952296Sobrien  emit_move_insn (operands[3], operands[1]);
331052296Sobrien
331152296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
331252296Sobrien  if (true_regnum (operands[1]) == 0
331352296Sobrien      && true_regnum (operands[2]) == 1
331490286Sobrien      && (optimize_size || TARGET_USE_CLTD))
331518334Speter    {
331690286Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[1], GEN_INT (31)));
331718334Speter    }
331852296Sobrien  else
331952296Sobrien    {
332052296Sobrien      emit_move_insn (operands[2], operands[1]);
332190286Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[2], GEN_INT (31)));
332252296Sobrien    }
332352296Sobrien  emit_move_insn (operands[4], operands[2]);
332452296Sobrien  DONE;
332590286Sobrien})
332618334Speter
332752296Sobrien;; Extend to register case.  Optimize case where source and destination
332852296Sobrien;; registers match and cases where we can use cltd.
332952296Sobrien(define_split 
333052296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
333152296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3332169699Skan   (clobber (reg:CC FLAGS_REG))
333352296Sobrien   (clobber (match_scratch:SI 2 ""))]
333452296Sobrien  "reload_completed"
333552296Sobrien  [(const_int 0)]
333652296Sobrien{
333752296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
333818334Speter
333952296Sobrien  if (true_regnum (operands[3]) != true_regnum (operands[1]))
334052296Sobrien    emit_move_insn (operands[3], operands[1]);
334152296Sobrien
334252296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
334352296Sobrien  if (true_regnum (operands[3]) == 0
334490286Sobrien      && (optimize_size || TARGET_USE_CLTD))
334552296Sobrien    {
334690286Sobrien      emit_insn (gen_ashrsi3_31 (operands[4], operands[3], GEN_INT (31)));
334752296Sobrien      DONE;
334852296Sobrien    }
334952296Sobrien
335052296Sobrien  if (true_regnum (operands[4]) != true_regnum (operands[1]))
335152296Sobrien    emit_move_insn (operands[4], operands[1]);
335252296Sobrien
335390286Sobrien  emit_insn (gen_ashrsi3_31 (operands[4], operands[4], GEN_INT (31)));
335452296Sobrien  DONE;
335590286Sobrien})
335618334Speter
335718334Speter(define_insn "extendhisi2"
335890286Sobrien  [(set (match_operand:SI 0 "register_operand" "=*a,r")
335990286Sobrien	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm")))]
336018334Speter  ""
336118334Speter{
336290286Sobrien  switch (get_attr_prefix_0f (insn))
336390286Sobrien    {
336490286Sobrien    case 0:
336590286Sobrien      return "{cwtl|cwde}";
336690286Sobrien    default:
336790286Sobrien      return "movs{wl|x}\t{%1,%0|%0, %1}";
336890286Sobrien    }
336990286Sobrien}
337090286Sobrien  [(set_attr "type" "imovx")
337190286Sobrien   (set_attr "mode" "SI")
337290286Sobrien   (set (attr "prefix_0f")
337390286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
337490286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
337590286Sobrien			(eq_attr "alternative" "0"))
337690286Sobrien	(const_string "0")
337790286Sobrien	(const_string "1")))
337890286Sobrien   (set (attr "modrm")
337990286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
338090286Sobrien	(const_string "0")
338190286Sobrien	(const_string "1")))])
338218334Speter
338390286Sobrien(define_insn "*extendhisi2_zext"
338490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*a,r")
338590286Sobrien	(zero_extend:DI
338690286Sobrien	  (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm"))))]
338790286Sobrien  "TARGET_64BIT"
338890286Sobrien{
338990286Sobrien  switch (get_attr_prefix_0f (insn))
339090286Sobrien    {
339190286Sobrien    case 0:
339290286Sobrien      return "{cwtl|cwde}";
339390286Sobrien    default:
339490286Sobrien      return "movs{wl|x}\t{%1,%k0|%k0, %1}";
339590286Sobrien    }
339690286Sobrien}
339790286Sobrien  [(set_attr "type" "imovx")
339890286Sobrien   (set_attr "mode" "SI")
339990286Sobrien   (set (attr "prefix_0f")
340090286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
340190286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
340290286Sobrien			(eq_attr "alternative" "0"))
340390286Sobrien	(const_string "0")
340490286Sobrien	(const_string "1")))
340590286Sobrien   (set (attr "modrm")
340690286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
340790286Sobrien	(const_string "0")
340890286Sobrien	(const_string "1")))])
340918334Speter
341018334Speter(define_insn "extendqihi2"
341190286Sobrien  [(set (match_operand:HI 0 "register_operand" "=*a,r")
341290286Sobrien	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "*0,qm")))]
341318334Speter  ""
341418334Speter{
341590286Sobrien  switch (get_attr_prefix_0f (insn))
341690286Sobrien    {
341790286Sobrien    case 0:
341890286Sobrien      return "{cbtw|cbw}";
341990286Sobrien    default:
342090286Sobrien      return "movs{bw|x}\t{%1,%0|%0, %1}";
342190286Sobrien    }
342290286Sobrien}
342390286Sobrien  [(set_attr "type" "imovx")
342490286Sobrien   (set_attr "mode" "HI")
342590286Sobrien   (set (attr "prefix_0f")
342690286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
342790286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
342890286Sobrien			(eq_attr "alternative" "0"))
342990286Sobrien	(const_string "0")
343090286Sobrien	(const_string "1")))
343190286Sobrien   (set (attr "modrm")
343290286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
343390286Sobrien	(const_string "0")
343490286Sobrien	(const_string "1")))])
343518334Speter
343618334Speter(define_insn "extendqisi2"
343750650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
343850650Sobrien	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
343918334Speter  ""
344090286Sobrien  "movs{bl|x}\t{%1,%0|%0, %1}"
344190286Sobrien   [(set_attr "type" "imovx")
344290286Sobrien    (set_attr "mode" "SI")])
344350650Sobrien
344490286Sobrien(define_insn "*extendqisi2_zext"
344590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
344690286Sobrien	(zero_extend:DI
344790286Sobrien	  (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))))]
344890286Sobrien  "TARGET_64BIT"
344990286Sobrien  "movs{bl|x}\t{%1,%k0|%k0, %1}"
345090286Sobrien   [(set_attr "type" "imovx")
345190286Sobrien    (set_attr "mode" "SI")])
345218334Speter
345390286Sobrien;; Conversions between float and double.
345450650Sobrien
345590286Sobrien;; These are all no-ops in the model used for the 80387.  So just
345690286Sobrien;; emit moves.
345750650Sobrien
345890286Sobrien;; %%% Kill these when call knows how to work out a DFmode push earlier. 
345990286Sobrien(define_insn "*dummy_extendsfdf2"
346090286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<")
346190286Sobrien	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fY")))]
346290286Sobrien  "0"
346390286Sobrien  "#")
346450650Sobrien
346590286Sobrien(define_split
346690286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
3467117404Skan	(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
3468117404Skan  "!TARGET_64BIT"
3469169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
3470169699Skan   (set (mem:DF (reg:SI SP_REG)) (float_extend:DF (match_dup 1)))])
347150650Sobrien
347290286Sobrien(define_split
347390286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
3474117404Skan	(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
3475117404Skan  "TARGET_64BIT"
3476169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
3477169699Skan   (set (mem:DF (reg:DI SP_REG)) (float_extend:DF (match_dup 1)))])
347850650Sobrien
347990286Sobrien(define_insn "*dummy_extendsfxf2"
348090286Sobrien  [(set (match_operand:XF 0 "push_operand" "=<")
348190286Sobrien	(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "f")))]
348290286Sobrien  "0"
348390286Sobrien  "#")
348450650Sobrien
348590286Sobrien(define_split
348690286Sobrien  [(set (match_operand:XF 0 "push_operand" "")
3487117404Skan	(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
3488132727Skan  ""
3489169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
3490169699Skan   (set (mem:XF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
3491132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
349250650Sobrien
349390286Sobrien(define_split
3494132727Skan  [(set (match_operand:XF 0 "push_operand" "")
3495132727Skan	(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
3496117404Skan  "TARGET_64BIT"
3497169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
3498169699Skan   (set (mem:DF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
3499132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
350018334Speter
350190286Sobrien(define_split
350290286Sobrien  [(set (match_operand:XF 0 "push_operand" "")
3503117404Skan	(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
3504132727Skan  ""
3505169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
3506169699Skan   (set (mem:DF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
3507132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
350852296Sobrien
350952296Sobrien(define_split
3510132727Skan  [(set (match_operand:XF 0 "push_operand" "")
3511132727Skan	(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
3512117404Skan  "TARGET_64BIT"
3513169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
3514169699Skan   (set (mem:XF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
3515132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
351618334Speter
351790286Sobrien(define_expand "extendsfdf2"
351852296Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
3519117404Skan        (float_extend:DF (match_operand:SF 1 "general_operand" "")))]
3520169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
352152296Sobrien{
3522117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3523117404Skan     are LEGITIMATE_CONSTANT_P.  */
3524117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3525169699Skan    {
3526169699Skan      if ((!TARGET_SSE2 || TARGET_MIX_SSE_I387)
3527169699Skan	  && standard_80387_constant_p (operands[1]) > 0)
3528169699Skan	{
3529169699Skan	  operands[1] = simplify_const_unary_operation
3530169699Skan	    (FLOAT_EXTEND, DFmode, operands[1], SFmode);
3531169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3532169699Skan	  DONE;
3533169699Skan	}
3534169699Skan      operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
3535169699Skan    }
353690286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
353790286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
353890286Sobrien})
353918334Speter
3540169699Skan(define_insn "*extendsfdf2_mixed"
3541169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y")
3542169699Skan        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))]
3543169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387
354490286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
354552296Sobrien{
354690286Sobrien  switch (which_alternative)
354790286Sobrien    {
354890286Sobrien    case 0:
3549169699Skan      return output_387_reg_move (insn, operands);
355052296Sobrien
355190286Sobrien    case 1:
355290286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
355390286Sobrien        return "fstp%z0\t%y0";
355490286Sobrien      else
355590286Sobrien        return "fst%z0\t%y0";
3556169699Skan
355790286Sobrien    case 2:
355890286Sobrien      return "cvtss2sd\t{%1, %0|%0, %1}";
355918334Speter
356090286Sobrien    default:
3561169699Skan      gcc_unreachable ();
356290286Sobrien    }
356390286Sobrien}
3564117404Skan  [(set_attr "type" "fmov,fmov,ssecvt")
356590286Sobrien   (set_attr "mode" "SF,XF,DF")])
356618334Speter
3567169699Skan(define_insn "*extendsfdf2_sse"
3568169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y")
356990286Sobrien        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "mY")))]
3570169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
357190286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
357290286Sobrien  "cvtss2sd\t{%1, %0|%0, %1}"
3573117404Skan  [(set_attr "type" "ssecvt")
357490286Sobrien   (set_attr "mode" "DF")])
357518334Speter
3576169699Skan(define_insn "*extendsfdf2_i387"
3577169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
3578169699Skan        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
3579169699Skan  "TARGET_80387
3580169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
3581169699Skan{
3582169699Skan  switch (which_alternative)
3583169699Skan    {
3584169699Skan    case 0:
3585169699Skan      return output_387_reg_move (insn, operands);
3586169699Skan
3587169699Skan    case 1:
3588169699Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3589169699Skan        return "fstp%z0\t%y0";
3590169699Skan      else
3591169699Skan        return "fst%z0\t%y0";
3592169699Skan
3593169699Skan    default:
3594169699Skan      gcc_unreachable ();
3595169699Skan    }
3596169699Skan}
3597169699Skan  [(set_attr "type" "fmov")
3598169699Skan   (set_attr "mode" "SF,XF")])
3599169699Skan
360090286Sobrien(define_expand "extendsfxf2"
360152296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
3602117404Skan        (float_extend:XF (match_operand:SF 1 "general_operand" "")))]
3603132727Skan  "TARGET_80387"
360490286Sobrien{
3605117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3606117404Skan     are LEGITIMATE_CONSTANT_P.  */
3607117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3608169699Skan    {
3609169699Skan      if (standard_80387_constant_p (operands[1]) > 0)
3610169699Skan	{
3611169699Skan	  operands[1] = simplify_const_unary_operation
3612169699Skan	    (FLOAT_EXTEND, XFmode, operands[1], SFmode);
3613169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3614169699Skan	  DONE;
3615169699Skan	}
3616169699Skan      operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
3617169699Skan    }
361890286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
361990286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
362090286Sobrien})
362118334Speter
3622169699Skan(define_insn "*extendsfxf2_i387"
362352296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
362490286Sobrien        (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
362590286Sobrien  "TARGET_80387
362690286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
362718334Speter{
362890286Sobrien  switch (which_alternative)
362990286Sobrien    {
363090286Sobrien    case 0:
3631169699Skan      return output_387_reg_move (insn, operands);
363218334Speter
363390286Sobrien    case 1:
363490286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
363590286Sobrien	 we need one, follow the store with a load.  */
3636169699Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3637169699Skan        return "fstp%z0\t%y0";
3638169699Skan      else
363990286Sobrien        return "fstp%z0\t%y0\n\tfld%z0\t%y0";
364018334Speter
364190286Sobrien    default:
3642169699Skan      gcc_unreachable ();
364390286Sobrien    }
364490286Sobrien}
364590286Sobrien  [(set_attr "type" "fmov")
364690286Sobrien   (set_attr "mode" "SF,XF")])
364718334Speter
364890286Sobrien(define_expand "extenddfxf2"
364952296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
3650117404Skan        (float_extend:XF (match_operand:DF 1 "general_operand" "")))]
3651132727Skan  "TARGET_80387"
365290286Sobrien{
3653117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3654117404Skan     are LEGITIMATE_CONSTANT_P.  */
3655117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3656169699Skan    {
3657169699Skan      if (standard_80387_constant_p (operands[1]) > 0)
3658169699Skan	{
3659169699Skan	  operands[1] = simplify_const_unary_operation
3660169699Skan	    (FLOAT_EXTEND, XFmode, operands[1], DFmode);
3661169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3662169699Skan	  DONE;
3663169699Skan	}
3664169699Skan      operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
3665169699Skan    }
366690286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
366790286Sobrien    operands[1] = force_reg (DFmode, operands[1]);
366890286Sobrien})
366918334Speter
3670169699Skan(define_insn "*extenddfxf2_i387"
367152296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
367290286Sobrien        (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
367390286Sobrien  "TARGET_80387
367490286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
367590286Sobrien{
367690286Sobrien  switch (which_alternative)
367790286Sobrien    {
367890286Sobrien    case 0:
3679169699Skan      return output_387_reg_move (insn, operands);
368090286Sobrien
368190286Sobrien    case 1:
368290286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
368390286Sobrien	 we need one, follow the store with a load.  */
368490286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
368590286Sobrien        return "fstp%z0\t%y0\n\tfld%z0\t%y0";
368690286Sobrien      else
368790286Sobrien        return "fstp%z0\t%y0";
368890286Sobrien
368990286Sobrien    default:
3690169699Skan      gcc_unreachable ();
369190286Sobrien    }
369290286Sobrien}
369390286Sobrien  [(set_attr "type" "fmov")
369490286Sobrien   (set_attr "mode" "DF,XF")])
369590286Sobrien
369690286Sobrien;; %%% This seems bad bad news.
369790286Sobrien;; This cannot output into an f-reg because there is no way to be sure
369890286Sobrien;; of truncating in that case.  Otherwise this is just like a simple move
369990286Sobrien;; insn.  So we pretend we can output to a reg in order to get better
370090286Sobrien;; register preferencing, but we really use a stack slot.
370190286Sobrien
3702169699Skan;; Conversion from DFmode to SFmode.
3703169699Skan
370418334Speter(define_expand "truncdfsf2"
3705169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
370690286Sobrien	(float_truncate:SF
3707169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "")))]
3708169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
370918334Speter{
3710169699Skan  if (MEM_P (operands[0]) && MEM_P (operands[1]))
3711169699Skan    operands[1] = force_reg (DFmode, operands[1]);
3712169699Skan
3713169699Skan  if (TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_MIX_SSE_I387)
3714169699Skan    ;
3715169699Skan  else if (flag_unsafe_math_optimizations)
3716169699Skan    ;
3717169699Skan  else
371890286Sobrien    {
3719171835Skan      rtx temp = assign_386_stack_local (SFmode, SLOT_VIRTUAL);
3720169699Skan      emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
3721169699Skan      DONE;
372290286Sobrien    }
3723169699Skan})
372418334Speter
3725169699Skan(define_expand "truncdfsf2_with_temp"
3726169699Skan  [(parallel [(set (match_operand:SF 0 "" "")
3727169699Skan		   (float_truncate:SF (match_operand:DF 1 "" "")))
3728169699Skan	      (clobber (match_operand:SF 2 "" ""))])]
3729169699Skan  "")
3730169699Skan
3731169699Skan(define_insn "*truncdfsf_fast_mixed"
3732169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,f,Y")
3733169699Skan        (float_truncate:SF
3734169699Skan          (match_operand:DF 1 "nonimmediate_operand" "f ,f,Ym")))]
3735169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387 && flag_unsafe_math_optimizations"
373618334Speter{
373790286Sobrien  switch (which_alternative)
373890286Sobrien    {
373990286Sobrien    case 0:
374090286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
374190286Sobrien	return "fstp%z0\t%y0";
374290286Sobrien      else
374390286Sobrien	return "fst%z0\t%y0";
3744169699Skan    case 1:
3745169699Skan      return output_387_reg_move (insn, operands);
3746169699Skan    case 2:
3747169699Skan      return "cvtsd2ss\t{%1, %0|%0, %1}";
374890286Sobrien    default:
3749169699Skan      gcc_unreachable ();
375090286Sobrien    }
375190286Sobrien}
3752169699Skan  [(set_attr "type" "fmov,fmov,ssecvt")
3753169699Skan   (set_attr "mode" "SF")])
375418334Speter
3755169699Skan;; Yes, this one doesn't depend on flag_unsafe_math_optimizations,
3756169699Skan;; because nothing we do here is unsafe.
3757169699Skan(define_insn "*truncdfsf_fast_sse"
3758169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=Y")
3759169699Skan        (float_truncate:SF
3760169699Skan          (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
3761169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
3762169699Skan  "cvtsd2ss\t{%1, %0|%0, %1}"
3763169699Skan  [(set_attr "type" "ssecvt")
3764169699Skan   (set_attr "mode" "SF")])
3765169699Skan
3766169699Skan(define_insn "*truncdfsf_fast_i387"
3767169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=fm")
3768169699Skan        (float_truncate:SF
3769169699Skan          (match_operand:DF 1 "nonimmediate_operand" "f")))]
3770169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3771169699Skan  "* return output_387_reg_move (insn, operands);"
3772169699Skan  [(set_attr "type" "fmov")
3773169699Skan   (set_attr "mode" "SF")])
3774169699Skan
3775169699Skan(define_insn "*truncdfsf_mixed"
3776169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,?fx*r,Y")
3777132727Skan	(float_truncate:SF
3778169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "f ,f    ,Ym")))
3779169699Skan   (clobber (match_operand:SF 2 "memory_operand"     "=X,m    ,X"))]
3780169699Skan  "TARGET_MIX_SSE_I387"
3781132727Skan{
3782132727Skan  switch (which_alternative)
3783132727Skan    {
3784132727Skan    case 0:
3785132727Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3786132727Skan	return "fstp%z0\t%y0";
3787132727Skan      else
3788132727Skan	return "fst%z0\t%y0";
3789169699Skan    case 1:
3790132727Skan      return "#";
3791169699Skan    case 2:
3792169699Skan      return "cvtsd2ss\t{%1, %0|%0, %1}";
3793132727Skan    default:
3794169699Skan      gcc_unreachable ();
3795132727Skan    }
3796132727Skan}
3797169699Skan  [(set_attr "type" "fmov,multi,ssecvt")
3798169699Skan   (set_attr "unit" "*,i387,*")
3799169699Skan   (set_attr "mode" "SF")])
3800132727Skan
3801169699Skan(define_insn "*truncdfsf_i387"
3802169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r")
380390286Sobrien	(float_truncate:SF
3804169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "f,f")))
3805169699Skan   (clobber (match_operand:SF 2 "memory_operand" "=X,m"))]
3806169699Skan  "TARGET_80387"
3807132727Skan{
3808132727Skan  switch (which_alternative)
3809132727Skan    {
3810132727Skan    case 0:
3811132727Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3812132727Skan	return "fstp%z0\t%y0";
3813132727Skan      else
3814132727Skan	return "fst%z0\t%y0";
3815169699Skan    case 1:
3816132727Skan      return "#";
381790286Sobrien    default:
3818169699Skan      gcc_unreachable ();
381990286Sobrien    }
382090286Sobrien}
3821169699Skan  [(set_attr "type" "fmov,multi")
3822169699Skan   (set_attr "unit" "*,i387")
3823169699Skan   (set_attr "mode" "SF")])
382452296Sobrien
3825169699Skan(define_insn "*truncdfsf2_i387_1"
382690286Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
382790286Sobrien	(float_truncate:SF
3828169699Skan	  (match_operand:DF 1 "register_operand" "f")))]
3829169699Skan  "TARGET_80387
3830169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)
3831169699Skan   && !TARGET_MIX_SSE_I387"
383290286Sobrien{
383390286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
383490286Sobrien    return "fstp%z0\t%y0";
383518334Speter  else
383690286Sobrien    return "fst%z0\t%y0";
383790286Sobrien}
383890286Sobrien  [(set_attr "type" "fmov")
383990286Sobrien   (set_attr "mode" "SF")])
384018334Speter
384152296Sobrien(define_split
3842132727Skan  [(set (match_operand:SF 0 "register_operand" "")
384390286Sobrien	(float_truncate:SF
3844169699Skan	 (match_operand:DF 1 "fp_register_operand" "")))
384590286Sobrien   (clobber (match_operand 2 "" ""))]
3846169699Skan  "reload_completed"
3847169699Skan  [(set (match_dup 2) (match_dup 1))
3848169699Skan   (set (match_dup 0) (match_dup 2))]
3849132727Skan{
3850169699Skan  operands[1] = gen_rtx_REG (SFmode, true_regnum (operands[1]));
3851132727Skan})
385290286Sobrien
3853169699Skan;; Conversion from XFmode to SFmode.
3854132727Skan
385590286Sobrien(define_expand "truncxfsf2"
385690286Sobrien  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
385790286Sobrien		   (float_truncate:SF
385890286Sobrien		    (match_operand:XF 1 "register_operand" "")))
385990286Sobrien	      (clobber (match_dup 2))])]
3860132727Skan  "TARGET_80387"
3861169699Skan{
3862169699Skan  if (flag_unsafe_math_optimizations)
3863169699Skan    {
3864169699Skan      rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SFmode);
3865169699Skan      emit_insn (gen_truncxfsf2_i387_noop (reg, operands[1]));
3866169699Skan      if (reg != operands[0])
3867169699Skan	emit_move_insn (operands[0], reg);
3868169699Skan      DONE;
3869169699Skan    }
3870169699Skan  else
3871171835Skan    operands[2] = assign_386_stack_local (SFmode, SLOT_VIRTUAL);
3872169699Skan})
387352296Sobrien
3874169699Skan(define_insn "*truncxfsf2_mixed"
3875169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x")
387690286Sobrien	(float_truncate:SF
387790286Sobrien	 (match_operand:XF 1 "register_operand" "f,f,f,f")))
387890286Sobrien   (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
3879169699Skan  "TARGET_MIX_SSE_I387"
388090286Sobrien{
3881169699Skan  gcc_assert (!which_alternative);
3882169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3883169699Skan    return "fstp%z0\t%y0";
3884169699Skan  else
3885169699Skan    return "fst%z0\t%y0";
388690286Sobrien}
388790286Sobrien  [(set_attr "type" "fmov,multi,multi,multi")
3888169699Skan   (set_attr "unit" "*,i387,i387,i387")
388990286Sobrien   (set_attr "mode" "SF")])
389090286Sobrien
3891169699Skan(define_insn "truncxfsf2_i387_noop"
3892169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
3893169699Skan	(float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
3894169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3895169699Skan{
3896169699Skan  return output_387_reg_move (insn, operands);
3897169699Skan}
3898169699Skan  [(set_attr "type" "fmov")
3899169699Skan   (set_attr "mode" "SF")])
3900169699Skan
3901169699Skan(define_insn "*truncxfsf2_i387"
3902169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r")
3903169699Skan	(float_truncate:SF
3904169699Skan	 (match_operand:XF 1 "register_operand" "f,f,f")))
3905169699Skan   (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
3906169699Skan  "TARGET_80387"
3907169699Skan{
3908169699Skan  gcc_assert (!which_alternative);
3909169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3910169699Skan    return "fstp%z0\t%y0";
3911169699Skan   else
3912169699Skan     return "fst%z0\t%y0";
3913169699Skan}
3914169699Skan  [(set_attr "type" "fmov,multi,multi")
3915169699Skan   (set_attr "unit" "*,i387,i387")
3916169699Skan   (set_attr "mode" "SF")])
3917169699Skan
3918169699Skan(define_insn "*truncxfsf2_i387_1"
391952296Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
392090286Sobrien	(float_truncate:SF
392190286Sobrien	 (match_operand:XF 1 "register_operand" "f")))]
3922132727Skan  "TARGET_80387"
392318334Speter{
392490286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
392590286Sobrien    return "fstp%z0\t%y0";
392618334Speter  else
392790286Sobrien    return "fst%z0\t%y0";
392890286Sobrien}
392990286Sobrien  [(set_attr "type" "fmov")
393090286Sobrien   (set_attr "mode" "SF")])
393152296Sobrien
393290286Sobrien(define_split
3933169699Skan  [(set (match_operand:SF 0 "register_operand" "")
393490286Sobrien	(float_truncate:SF
393590286Sobrien	 (match_operand:XF 1 "register_operand" "")))
393690286Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
3937169699Skan  "TARGET_80387 && reload_completed"
3938169699Skan  [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
3939169699Skan   (set (match_dup 0) (match_dup 2))]
394090286Sobrien  "")
394190286Sobrien
394290286Sobrien(define_split
3943169699Skan  [(set (match_operand:SF 0 "memory_operand" "")
394490286Sobrien	(float_truncate:SF
394590286Sobrien	 (match_operand:XF 1 "register_operand" "")))
394690286Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
3947169699Skan  "TARGET_80387"
3948169699Skan  [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
394990286Sobrien  "")
395090286Sobrien
3951169699Skan;; Conversion from XFmode to DFmode.
3952169699Skan
395352296Sobrien(define_expand "truncxfdf2"
395452296Sobrien  [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
395552296Sobrien		   (float_truncate:DF
395652296Sobrien		    (match_operand:XF 1 "register_operand" "")))
395752296Sobrien	      (clobber (match_dup 2))])]
3958132727Skan  "TARGET_80387"
3959169699Skan{
3960169699Skan  if (flag_unsafe_math_optimizations)
3961169699Skan    {
3962169699Skan      rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DFmode);
3963169699Skan      emit_insn (gen_truncxfdf2_i387_noop (reg, operands[1]));
3964169699Skan      if (reg != operands[0])
3965169699Skan	emit_move_insn (operands[0], reg);
3966169699Skan      DONE;
3967169699Skan    }
3968169699Skan  else
3969171835Skan    operands[2] = assign_386_stack_local (DFmode, SLOT_VIRTUAL);
3970169699Skan})
397118334Speter
3972169699Skan(define_insn "*truncxfdf2_mixed"
3973169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y")
397452296Sobrien	(float_truncate:DF
397590286Sobrien	 (match_operand:XF 1 "register_operand" "f,f,f,f")))
397690286Sobrien   (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
3977169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387"
397818334Speter{
3979169699Skan  gcc_assert (!which_alternative);
3980169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3981169699Skan    return "fstp%z0\t%y0";
3982169699Skan  else
3983169699Skan    return "fst%z0\t%y0";
398490286Sobrien}
398590286Sobrien  [(set_attr "type" "fmov,multi,multi,multi")
3986169699Skan   (set_attr "unit" "*,i387,i387,i387")
398790286Sobrien   (set_attr "mode" "DF")])
398852296Sobrien
3989169699Skan(define_insn "truncxfdf2_i387_noop"
3990169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
3991169699Skan	(float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
3992169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3993169699Skan{
3994169699Skan  return output_387_reg_move (insn, operands);
3995169699Skan}
3996169699Skan  [(set_attr "type" "fmov")
3997169699Skan   (set_attr "mode" "DF")])
3998169699Skan
3999169699Skan(define_insn "*truncxfdf2_i387"
4000169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r")
4001169699Skan	(float_truncate:DF
4002169699Skan	 (match_operand:XF 1 "register_operand" "f,f,f")))
4003169699Skan   (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
4004169699Skan  "TARGET_80387"
4005169699Skan{
4006169699Skan  gcc_assert (!which_alternative);
4007169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
4008169699Skan    return "fstp%z0\t%y0";
4009169699Skan  else
4010169699Skan    return "fst%z0\t%y0";
4011169699Skan}
4012169699Skan  [(set_attr "type" "fmov,multi,multi")
4013169699Skan   (set_attr "unit" "*,i387,i387")
4014169699Skan   (set_attr "mode" "DF")])
4015169699Skan
4016169699Skan(define_insn "*truncxfdf2_i387_1"
401790286Sobrien  [(set (match_operand:DF 0 "memory_operand" "=m")
401890286Sobrien	(float_truncate:DF
401990286Sobrien	  (match_operand:XF 1 "register_operand" "f")))]
4020132727Skan  "TARGET_80387"
402190286Sobrien{
402290286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
402390286Sobrien    return "fstp%z0\t%y0";
402490286Sobrien  else
402590286Sobrien    return "fst%z0\t%y0";
402690286Sobrien}
402790286Sobrien  [(set_attr "type" "fmov")
402890286Sobrien   (set_attr "mode" "DF")])
402952296Sobrien
403052296Sobrien(define_split
4031169699Skan  [(set (match_operand:DF 0 "register_operand" "")
403290286Sobrien	(float_truncate:DF
403390286Sobrien	 (match_operand:XF 1 "register_operand" "")))
403452296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
4035169699Skan  "TARGET_80387 && reload_completed"
4036169699Skan  [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
4037169699Skan   (set (match_dup 0) (match_dup 2))]
403852296Sobrien  "")
403952296Sobrien
404052296Sobrien(define_split
4041169699Skan  [(set (match_operand:DF 0 "memory_operand" "")
404290286Sobrien	(float_truncate:DF
404390286Sobrien	 (match_operand:XF 1 "register_operand" "")))
404452296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
4045169699Skan  "TARGET_80387"
4046169699Skan  [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
404752296Sobrien  "")
404890286Sobrien
404990286Sobrien;; Signed conversion to DImode.
405090286Sobrien
405190286Sobrien(define_expand "fix_truncxfdi2"
4052169699Skan  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4053169699Skan                   (fix:DI (match_operand:XF 1 "register_operand" "")))
4054169699Skan	      (clobber (reg:CC FLAGS_REG))])]
405518334Speter  "TARGET_80387"
405618334Speter{
4057169699Skan  if (TARGET_FISTTP)
405890286Sobrien   {
4059169699Skan     emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
406090286Sobrien     DONE;
406190286Sobrien   }
406290286Sobrien})
406318334Speter
4064169699Skan(define_expand "fix_trunc<mode>di2"
4065169699Skan  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4066169699Skan                   (fix:DI (match_operand:SSEMODEF 1 "register_operand" "")))
4067169699Skan              (clobber (reg:CC FLAGS_REG))])]
4068169699Skan  "TARGET_80387 || (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))"
406990286Sobrien{
4070169699Skan  if (TARGET_FISTTP
4071169699Skan      && !(TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
407290286Sobrien   {
4073169699Skan     emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
4074169699Skan     DONE;
4075169699Skan   }
4076169699Skan  if (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))
4077169699Skan   {
407890286Sobrien     rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
4079169699Skan     emit_insn (gen_fix_trunc<mode>di_sse (out, operands[1]));
408090286Sobrien     if (out != operands[0])
408190286Sobrien	emit_move_insn (operands[0], out);
408290286Sobrien     DONE;
408390286Sobrien   }
408490286Sobrien})
408552296Sobrien
408690286Sobrien;; Signed conversion to SImode.
408790286Sobrien
408852296Sobrien(define_expand "fix_truncxfsi2"
4089169699Skan  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
4090169699Skan                   (fix:SI (match_operand:XF 1 "register_operand" "")))
4091169699Skan	      (clobber (reg:CC FLAGS_REG))])]
409218334Speter  "TARGET_80387"
409318334Speter{
4094169699Skan  if (TARGET_FISTTP)
409590286Sobrien   {
4096169699Skan     emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
409790286Sobrien     DONE;
409890286Sobrien   }
409990286Sobrien})
410018334Speter
4101169699Skan(define_expand "fix_trunc<mode>si2"
4102169699Skan  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
4103169699Skan	           (fix:SI (match_operand:SSEMODEF 1 "register_operand" "")))
4104169699Skan	      (clobber (reg:CC FLAGS_REG))])]
4105169699Skan  "TARGET_80387 || SSE_FLOAT_MODE_P (<MODE>mode)"
410690286Sobrien{
4107169699Skan  if (TARGET_FISTTP
4108169699Skan      && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
410990286Sobrien   {
4110169699Skan     emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
4111169699Skan     DONE;
4112169699Skan   }
4113169699Skan  if (SSE_FLOAT_MODE_P (<MODE>mode))
4114169699Skan   {
411590286Sobrien     rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
4116169699Skan     emit_insn (gen_fix_trunc<mode>si_sse (out, operands[1]));
411790286Sobrien     if (out != operands[0])
411890286Sobrien	emit_move_insn (operands[0], out);
411990286Sobrien     DONE;
412090286Sobrien   }
412190286Sobrien})
412252296Sobrien
4123169699Skan;; Signed conversion to HImode.
4124169699Skan
4125169699Skan(define_expand "fix_trunc<mode>hi2"
4126169699Skan  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
4127169699Skan	           (fix:HI (match_operand:X87MODEF 1 "register_operand" "")))
4128169699Skan              (clobber (reg:CC FLAGS_REG))])]
4129169699Skan  "TARGET_80387
4130169699Skan   && !(SSE_FLOAT_MODE_P (<MODE>mode) && (!TARGET_FISTTP || TARGET_SSE_MATH))"
413118334Speter{
4132169699Skan  if (TARGET_FISTTP)
4133169699Skan   {
4134169699Skan     emit_insn (gen_fix_trunchi_fisttp_i387_1 (operands[0], operands[1]));
4135169699Skan     DONE;
4136169699Skan   }
4137169699Skan})
413818334Speter
4139169699Skan;; When SSE is available, it is always faster to use it!
4140169699Skan(define_insn "fix_truncsfdi_sse"
4141169699Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
4142169699Skan	(fix:DI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
4143169699Skan  "TARGET_64BIT && TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
4144169699Skan  "cvttss2si{q}\t{%1, %0|%0, %1}"
4145169699Skan  [(set_attr "type" "sseicvt")
4146169699Skan   (set_attr "mode" "SF")
4147169699Skan   (set_attr "athlon_decode" "double,vector")])
414890286Sobrien
4149169699Skan(define_insn "fix_truncdfdi_sse"
4150169699Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
4151169699Skan	(fix:DI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
4152169699Skan  "TARGET_64BIT && TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
4153169699Skan  "cvttsd2si{q}\t{%1, %0|%0, %1}"
4154169699Skan  [(set_attr "type" "sseicvt")
4155169699Skan   (set_attr "mode" "DF")
4156169699Skan   (set_attr "athlon_decode" "double,vector")])
415718334Speter
415890286Sobrien(define_insn "fix_truncsfsi_sse"
4159132727Skan  [(set (match_operand:SI 0 "register_operand" "=r,r")
4160132727Skan	(fix:SI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
4161169699Skan  "TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
416290286Sobrien  "cvttss2si\t{%1, %0|%0, %1}"
4163132727Skan  [(set_attr "type" "sseicvt")
4164132727Skan   (set_attr "mode" "DF")
4165132727Skan   (set_attr "athlon_decode" "double,vector")])
416652296Sobrien
416790286Sobrien(define_insn "fix_truncdfsi_sse"
4168132727Skan  [(set (match_operand:SI 0 "register_operand" "=r,r")
4169132727Skan	(fix:SI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
4170169699Skan  "TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
417190286Sobrien  "cvttsd2si\t{%1, %0|%0, %1}"
4172132727Skan  [(set_attr "type" "sseicvt")
4173132727Skan   (set_attr "mode" "DF")
4174132727Skan   (set_attr "athlon_decode" "double,vector")])
417552296Sobrien
4176169699Skan;; Avoid vector decoded forms of the instruction.
4177132727Skan(define_peephole2
4178132727Skan  [(match_scratch:DF 2 "Y")
4179169699Skan   (set (match_operand:SSEMODEI24 0 "register_operand" "")
4180169699Skan	(fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))]
4181169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
4182132727Skan  [(set (match_dup 2) (match_dup 1))
4183169699Skan   (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
4184132727Skan  "")
4185132727Skan
4186169699Skan(define_peephole2
4187169699Skan  [(match_scratch:SF 2 "x")
4188169699Skan   (set (match_operand:SSEMODEI24 0 "register_operand" "")
4189169699Skan	(fix:SSEMODEI24 (match_operand:SF 1 "memory_operand" "")))]
4190169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
4191169699Skan  [(set (match_dup 2) (match_dup 1))
4192169699Skan   (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
419390286Sobrien  "")
419418334Speter
4195169699Skan(define_insn_and_split "fix_trunc<mode>_fisttp_i387_1"
4196169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4197169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))]
4198169699Skan  "TARGET_FISTTP
4199169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4200169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4201169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4202169699Skan	&& TARGET_SSE_MATH)
4203169699Skan   && !(reload_completed || reload_in_progress)"
4204169699Skan  "#"
4205169699Skan  "&& 1"
4206169699Skan  [(const_int 0)]
4207169699Skan{
4208169699Skan  if (memory_operand (operands[0], VOIDmode))
4209169699Skan    emit_insn (gen_fix_trunc<mode>_i387_fisttp (operands[0], operands[1]));
4210169699Skan  else
4211169699Skan    {
4212169699Skan      operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
4213169699Skan      emit_insn (gen_fix_trunc<mode>_i387_fisttp_with_temp (operands[0],
4214169699Skan							    operands[1],
4215169699Skan							    operands[2]));
4216169699Skan    }
4217169699Skan  DONE;
4218169699Skan}
4219169699Skan  [(set_attr "type" "fisttp")
4220169699Skan   (set_attr "mode" "<MODE>")])
422152296Sobrien
4222169699Skan(define_insn "fix_trunc<mode>_i387_fisttp"
4223169699Skan  [(set (match_operand:X87MODEI 0 "memory_operand" "=m")
4224169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f")))
4225169699Skan   (clobber (match_scratch:XF 2 "=&1f"))]
4226169699Skan  "TARGET_FISTTP
4227169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4228169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4229169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4230169699Skan	&& TARGET_SSE_MATH)"
4231169699Skan  "* return output_fix_trunc (insn, operands, 1);"
4232169699Skan  [(set_attr "type" "fisttp")
4233169699Skan   (set_attr "mode" "<MODE>")])
423490286Sobrien
4235169699Skan(define_insn "fix_trunc<mode>_i387_fisttp_with_temp"
4236169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4237169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
4238169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" "=m,m"))
4239169699Skan   (clobber (match_scratch:XF 3 "=&1f,&1f"))]
4240169699Skan  "TARGET_FISTTP
4241169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4242169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4243169699Skan	&& (TARGET_64BIT || <MODE>mode != DImode))
4244169699Skan	&& TARGET_SSE_MATH)"
4245169699Skan  "#"
4246169699Skan  [(set_attr "type" "fisttp")
4247169699Skan   (set_attr "mode" "<MODE>")])
424818334Speter
4249169699Skan(define_split
4250169699Skan  [(set (match_operand:X87MODEI 0 "register_operand" "")
4251169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "")))
4252169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
4253169699Skan   (clobber (match_scratch 3 ""))]
4254169699Skan  "reload_completed"
4255169699Skan  [(parallel [(set (match_dup 2) (fix:X87MODEI (match_dup 1)))
4256169699Skan	      (clobber (match_dup 3))])
4257169699Skan   (set (match_dup 0) (match_dup 2))]
425890286Sobrien  "")
425918334Speter
4260169699Skan(define_split
4261169699Skan  [(set (match_operand:X87MODEI 0 "memory_operand" "")
4262169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "")))
4263169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
4264169699Skan   (clobber (match_scratch 3 ""))]
4265169699Skan  "reload_completed"
4266169699Skan  [(parallel [(set (match_dup 0) (fix:X87MODEI (match_dup 1)))
4267169699Skan	      (clobber (match_dup 3))])]
426890286Sobrien  "")
426952296Sobrien
427090286Sobrien;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
4271169699Skan;; of the machinery. Please note the clobber of FLAGS_REG. In i387 control
4272169699Skan;; word calculation (inserted by LCM in mode switching pass) a FLAGS_REG
4273169699Skan;; clobbering insns can be used. Look at emit_i387_cw_initialization ()
4274169699Skan;; function in i386.c.
4275169699Skan(define_insn_and_split "*fix_trunc<mode>_i387_1"
4276169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4277169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
4278169699Skan   (clobber (reg:CC FLAGS_REG))]
4279169699Skan  "TARGET_80387 && !TARGET_FISTTP
4280169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4281169699Skan   && !(SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4282169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4283169699Skan   && !(reload_completed || reload_in_progress)"
428490286Sobrien  "#"
4285169699Skan  "&& 1"
428690286Sobrien  [(const_int 0)]
428790286Sobrien{
4288169699Skan  ix86_optimize_mode_switching[I387_TRUNC] = 1;
4289169699Skan
4290169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
4291169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
429290286Sobrien  if (memory_operand (operands[0], VOIDmode))
4293169699Skan    emit_insn (gen_fix_trunc<mode>_i387 (operands[0], operands[1],
4294169699Skan					 operands[2], operands[3]));
429590286Sobrien  else
429690286Sobrien    {
4297169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
4298169699Skan      emit_insn (gen_fix_trunc<mode>_i387_with_temp (operands[0], operands[1],
4299169699Skan						     operands[2], operands[3],
4300169699Skan						     operands[4]));
430190286Sobrien    }
430290286Sobrien  DONE;
430390286Sobrien}
4304132727Skan  [(set_attr "type" "fistp")
4305169699Skan   (set_attr "i387_cw" "trunc")
4306169699Skan   (set_attr "mode" "<MODE>")])
430790286Sobrien
4308169699Skan(define_insn "fix_truncdi_i387"
4309169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
4310169699Skan	(fix:DI (match_operand 1 "register_operand" "f")))
4311169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
4312169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
4313169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
4314169699Skan  "TARGET_80387 && !TARGET_FISTTP
4315169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4316169699Skan   && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
4317169699Skan  "* return output_fix_trunc (insn, operands, 0);"
4318169699Skan  [(set_attr "type" "fistp")
4319169699Skan   (set_attr "i387_cw" "trunc")
4320169699Skan   (set_attr "mode" "DI")])
4321169699Skan
4322169699Skan(define_insn "fix_truncdi_i387_with_temp"
4323169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
4324169699Skan	(fix:DI (match_operand 1 "register_operand" "f,f")))
432590286Sobrien   (use (match_operand:HI 2 "memory_operand" "m,m"))
432690286Sobrien   (use (match_operand:HI 3 "memory_operand" "m,m"))
4327169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
4328169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
4329169699Skan  "TARGET_80387 && !TARGET_FISTTP
4330169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4331169699Skan   && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
433290286Sobrien  "#"
4333132727Skan  [(set_attr "type" "fistp")
4334169699Skan   (set_attr "i387_cw" "trunc")
4335169699Skan   (set_attr "mode" "DI")])
433690286Sobrien
4337169699Skan(define_split 
4338169699Skan  [(set (match_operand:DI 0 "register_operand" "")
4339169699Skan	(fix:DI (match_operand 1 "register_operand" "")))
4340169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
4341169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
4342169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
4343169699Skan   (clobber (match_scratch 5 ""))]
4344169699Skan  "reload_completed"
4345169699Skan  [(parallel [(set (match_dup 4) (fix:DI (match_dup 1)))
4346169699Skan	      (use (match_dup 2))
4347169699Skan	      (use (match_dup 3))
4348169699Skan	      (clobber (match_dup 5))])
4349169699Skan   (set (match_dup 0) (match_dup 4))]
4350169699Skan  "")
4351169699Skan
4352169699Skan(define_split 
4353169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
4354169699Skan	(fix:DI (match_operand 1 "register_operand" "")))
4355169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
4356169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
4357169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
4358169699Skan   (clobber (match_scratch 5 ""))]
4359169699Skan  "reload_completed"
4360169699Skan  [(parallel [(set (match_dup 0) (fix:DI (match_dup 1)))
4361169699Skan	      (use (match_dup 2))
4362169699Skan	      (use (match_dup 3))
4363169699Skan	      (clobber (match_dup 5))])]
4364169699Skan  "")
4365169699Skan
4366169699Skan(define_insn "fix_trunc<mode>_i387"
4367169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
4368169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "f")))
436990286Sobrien   (use (match_operand:HI 2 "memory_operand" "m"))
437090286Sobrien   (use (match_operand:HI 3 "memory_operand" "m"))]
4371169699Skan  "TARGET_80387 && !TARGET_FISTTP
4372169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
437390286Sobrien   && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
4374169699Skan  "* return output_fix_trunc (insn, operands, 0);"
4375132727Skan  [(set_attr "type" "fistp")
4376169699Skan   (set_attr "i387_cw" "trunc")
4377169699Skan   (set_attr "mode" "<MODE>")])
437890286Sobrien
4379169699Skan(define_insn "fix_trunc<mode>_i387_with_temp"
4380169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
4381169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "f,f")))
4382169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
4383169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
4384169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
4385169699Skan  "TARGET_80387 && !TARGET_FISTTP
4386169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4387169699Skan   && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
4388169699Skan  "#"
4389169699Skan  [(set_attr "type" "fistp")
4390169699Skan   (set_attr "i387_cw" "trunc")
4391169699Skan   (set_attr "mode" "<MODE>")])
4392169699Skan
439390286Sobrien(define_split 
4394169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
4395169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
439690286Sobrien   (use (match_operand:HI 2 "memory_operand" ""))
439790286Sobrien   (use (match_operand:HI 3 "memory_operand" ""))
4398169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
439990286Sobrien  "reload_completed"
4400169699Skan  [(parallel [(set (match_dup 4) (fix:X87MODEI12 (match_dup 1)))
440190286Sobrien	      (use (match_dup 2))
4402169699Skan	      (use (match_dup 3))])
4403169699Skan   (set (match_dup 0) (match_dup 4))]
440418334Speter  "")
440518334Speter
440690286Sobrien(define_split 
4407169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
4408169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
440990286Sobrien   (use (match_operand:HI 2 "memory_operand" ""))
441090286Sobrien   (use (match_operand:HI 3 "memory_operand" ""))
4411169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
441290286Sobrien  "reload_completed"
4413169699Skan  [(parallel [(set (match_dup 0) (fix:X87MODEI12 (match_dup 1)))
441490286Sobrien	      (use (match_dup 2))
4415169699Skan	      (use (match_dup 3))])]
441652296Sobrien  "")
441752296Sobrien
441890286Sobrien(define_insn "x86_fnstcw_1"
441990286Sobrien  [(set (match_operand:HI 0 "memory_operand" "=m")
4420169699Skan	(unspec:HI [(reg:HI FPSR_REG)] UNSPEC_FSTCW))]
442152296Sobrien  "TARGET_80387"
442290286Sobrien  "fnstcw\t%0"
442390286Sobrien  [(set_attr "length" "2")
442490286Sobrien   (set_attr "mode" "HI")
4425169699Skan   (set_attr "unit" "i387")])
442652296Sobrien
442790286Sobrien(define_insn "x86_fldcw_1"
4428169699Skan  [(set (reg:HI FPSR_REG)
4429117404Skan	(unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))]
443052296Sobrien  "TARGET_80387"
443190286Sobrien  "fldcw\t%0"
443290286Sobrien  [(set_attr "length" "2")
443390286Sobrien   (set_attr "mode" "HI")
4434117404Skan   (set_attr "unit" "i387")
4435169699Skan   (set_attr "athlon_decode" "vector")])
443690286Sobrien
443790286Sobrien;; Conversion between fixed point and floating point.
443852296Sobrien
443990286Sobrien;; Even though we only accept memory inputs, the backend _really_
444090286Sobrien;; wants to be able to do this between registers.
444190286Sobrien
4442132727Skan(define_expand "floathisf2"
4443132727Skan  [(set (match_operand:SF 0 "register_operand" "")
4444132727Skan	(float:SF (match_operand:HI 1 "nonimmediate_operand" "")))]
4445169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
4446132727Skan{
4447169699Skan  if (TARGET_SSE_MATH)
4448132727Skan    {
4449132727Skan      emit_insn (gen_floatsisf2 (operands[0],
4450132727Skan				 convert_to_mode (SImode, operands[1], 0)));
4451132727Skan      DONE;
4452132727Skan    }
4453132727Skan})
4454132727Skan
4455169699Skan(define_insn "*floathisf2_i387"
445652296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
4457169699Skan	(float:SF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
4458169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
445990286Sobrien  "@
446090286Sobrien   fild%z1\t%1
446190286Sobrien   #"
446290286Sobrien  [(set_attr "type" "fmov,multi")
446390286Sobrien   (set_attr "mode" "SF")
4464169699Skan   (set_attr "unit" "*,i387")
446590286Sobrien   (set_attr "fp_int_src" "true")])
446652296Sobrien
446790286Sobrien(define_expand "floatsisf2"
446818334Speter  [(set (match_operand:SF 0 "register_operand" "")
446990286Sobrien	(float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
4470169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
447118334Speter  "")
447218334Speter
4473169699Skan(define_insn "*floatsisf2_mixed"
4474169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
4475132727Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
4476169699Skan  "TARGET_MIX_SSE_I387"
447790286Sobrien  "@
447890286Sobrien   fild%z1\t%1
447990286Sobrien   #
4480132727Skan   cvtsi2ss\t{%1, %0|%0, %1}
448190286Sobrien   cvtsi2ss\t{%1, %0|%0, %1}"
4482132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
448390286Sobrien   (set_attr "mode" "SF")
4484169699Skan   (set_attr "unit" "*,i387,*,*")
4485132727Skan   (set_attr "athlon_decode" "*,*,vector,double")
448690286Sobrien   (set_attr "fp_int_src" "true")])
448790286Sobrien
448890286Sobrien(define_insn "*floatsisf2_sse"
4489132727Skan  [(set (match_operand:SF 0 "register_operand" "=x,x")
4490132727Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
4491169699Skan  "TARGET_SSE_MATH"
449290286Sobrien  "cvtsi2ss\t{%1, %0|%0, %1}"
4493132727Skan  [(set_attr "type" "sseicvt")
449490286Sobrien   (set_attr "mode" "SF")
4495132727Skan   (set_attr "athlon_decode" "vector,double")
449690286Sobrien   (set_attr "fp_int_src" "true")])
449790286Sobrien
4498169699Skan(define_insn "*floatsisf2_i387"
4499169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
4500169699Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
4501169699Skan  "TARGET_80387"
450290286Sobrien  "@
450390286Sobrien   fild%z1\t%1
450490286Sobrien   #"
450590286Sobrien  [(set_attr "type" "fmov,multi")
450690286Sobrien   (set_attr "mode" "SF")
4507169699Skan   (set_attr "unit" "*,i387")
450890286Sobrien   (set_attr "fp_int_src" "true")])
450952296Sobrien
4510169699Skan(define_expand "floatdisf2"
4511169699Skan  [(set (match_operand:SF 0 "register_operand" "")
4512169699Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
4513169699Skan  "TARGET_80387 || (TARGET_64BIT && TARGET_SSE_MATH)"
4514169699Skan  "")
4515169699Skan
4516169699Skan(define_insn "*floatdisf2_mixed"
4517169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
4518132727Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
4519169699Skan  "TARGET_64BIT && TARGET_MIX_SSE_I387"
452090286Sobrien  "@
452190286Sobrien   fild%z1\t%1
452290286Sobrien   #
4523132727Skan   cvtsi2ss{q}\t{%1, %0|%0, %1}
452490286Sobrien   cvtsi2ss{q}\t{%1, %0|%0, %1}"
4525132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
452690286Sobrien   (set_attr "mode" "SF")
4527169699Skan   (set_attr "unit" "*,i387,*,*")
4528132727Skan   (set_attr "athlon_decode" "*,*,vector,double")
452990286Sobrien   (set_attr "fp_int_src" "true")])
453052296Sobrien
453190286Sobrien(define_insn "*floatdisf2_sse"
4532132727Skan  [(set (match_operand:SF 0 "register_operand" "=x,x")
4533132727Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
4534169699Skan  "TARGET_64BIT && TARGET_SSE_MATH"
453590286Sobrien  "cvtsi2ss{q}\t{%1, %0|%0, %1}"
4536132727Skan  [(set_attr "type" "sseicvt")
453790286Sobrien   (set_attr "mode" "SF")
4538132727Skan   (set_attr "athlon_decode" "vector,double")
453990286Sobrien   (set_attr "fp_int_src" "true")])
454090286Sobrien
4541169699Skan(define_insn "*floatdisf2_i387"
4542169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
4543169699Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
4544169699Skan  "TARGET_80387"
4545169699Skan  "@
4546169699Skan   fild%z1\t%1
4547169699Skan   #"
4548169699Skan  [(set_attr "type" "fmov,multi")
4549169699Skan   (set_attr "mode" "SF")
4550169699Skan   (set_attr "unit" "*,i387")
4551169699Skan   (set_attr "fp_int_src" "true")])
4552132727Skan
4553132727Skan(define_expand "floathidf2"
4554132727Skan  [(set (match_operand:DF 0 "register_operand" "")
4555132727Skan	(float:DF (match_operand:HI 1 "nonimmediate_operand" "")))]
4556169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
4557132727Skan{
4558169699Skan  if (TARGET_SSE2 && TARGET_SSE_MATH)
4559132727Skan    {
4560132727Skan      emit_insn (gen_floatsidf2 (operands[0],
4561132727Skan				 convert_to_mode (SImode, operands[1], 0)));
4562132727Skan      DONE;
4563132727Skan    }
4564132727Skan})
4565132727Skan
4566169699Skan(define_insn "*floathidf2_i387"
456752296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
4568169699Skan	(float:DF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
4569169699Skan  "TARGET_80387 && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
457090286Sobrien  "@
457190286Sobrien   fild%z1\t%1
457290286Sobrien   #"
457390286Sobrien  [(set_attr "type" "fmov,multi")
457490286Sobrien   (set_attr "mode" "DF")
4575169699Skan   (set_attr "unit" "*,i387")
457690286Sobrien   (set_attr "fp_int_src" "true")])
457752296Sobrien
457890286Sobrien(define_expand "floatsidf2"
457918334Speter  [(set (match_operand:DF 0 "register_operand" "")
458090286Sobrien	(float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
4581169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
458252296Sobrien  "")
458352296Sobrien
4584169699Skan(define_insn "*floatsidf2_mixed"
4585169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
4586132727Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
4587169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387"
458890286Sobrien  "@
458990286Sobrien   fild%z1\t%1
459090286Sobrien   #
4591132727Skan   cvtsi2sd\t{%1, %0|%0, %1}
459290286Sobrien   cvtsi2sd\t{%1, %0|%0, %1}"
4593132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
459490286Sobrien   (set_attr "mode" "DF")
4595169699Skan   (set_attr "unit" "*,i387,*,*")
4596132727Skan   (set_attr "athlon_decode" "*,*,double,direct")
459790286Sobrien   (set_attr "fp_int_src" "true")])
459890286Sobrien
459990286Sobrien(define_insn "*floatsidf2_sse"
4600132727Skan  [(set (match_operand:DF 0 "register_operand" "=Y,Y")
4601132727Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
4602169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
460390286Sobrien  "cvtsi2sd\t{%1, %0|%0, %1}"
4604132727Skan  [(set_attr "type" "sseicvt")
460590286Sobrien   (set_attr "mode" "DF")
4606132727Skan   (set_attr "athlon_decode" "double,direct")
460790286Sobrien   (set_attr "fp_int_src" "true")])
460890286Sobrien
4609169699Skan(define_insn "*floatsidf2_i387"
4610169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
4611169699Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
4612169699Skan  "TARGET_80387"
461390286Sobrien  "@
461490286Sobrien   fild%z1\t%1
461590286Sobrien   #"
461690286Sobrien  [(set_attr "type" "fmov,multi")
461790286Sobrien   (set_attr "mode" "DF")
4618169699Skan   (set_attr "unit" "*,i387")
461990286Sobrien   (set_attr "fp_int_src" "true")])
462090286Sobrien
4621169699Skan(define_expand "floatdidf2"
4622169699Skan  [(set (match_operand:DF 0 "register_operand" "")
4623169699Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
4624169699Skan  "TARGET_80387 || (TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH)"
4625169699Skan  "")
4626169699Skan
4627169699Skan(define_insn "*floatdidf2_mixed"
4628169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
4629132727Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
4630169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
463190286Sobrien  "@
463290286Sobrien   fild%z1\t%1
463390286Sobrien   #
4634132727Skan   cvtsi2sd{q}\t{%1, %0|%0, %1}
463590286Sobrien   cvtsi2sd{q}\t{%1, %0|%0, %1}"
4636132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
463790286Sobrien   (set_attr "mode" "DF")
4638169699Skan   (set_attr "unit" "*,i387,*,*")
4639132727Skan   (set_attr "athlon_decode" "*,*,double,direct")
464090286Sobrien   (set_attr "fp_int_src" "true")])
464190286Sobrien
464290286Sobrien(define_insn "*floatdidf2_sse"
4643132727Skan  [(set (match_operand:DF 0 "register_operand" "=Y,Y")
4644132727Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
4645169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
464690286Sobrien  "cvtsi2sd{q}\t{%1, %0|%0, %1}"
4647132727Skan  [(set_attr "type" "sseicvt")
464890286Sobrien   (set_attr "mode" "DF")
4649132727Skan   (set_attr "athlon_decode" "double,direct")
465090286Sobrien   (set_attr "fp_int_src" "true")])
465190286Sobrien
4652169699Skan(define_insn "*floatdidf2_i387"
4653169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
4654169699Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
4655169699Skan  "TARGET_80387"
4656169699Skan  "@
4657169699Skan   fild%z1\t%1
4658169699Skan   #"
4659169699Skan  [(set_attr "type" "fmov,multi")
4660169699Skan   (set_attr "mode" "DF")
4661169699Skan   (set_attr "unit" "*,i387")
4662169699Skan   (set_attr "fp_int_src" "true")])
4663169699Skan
466490286Sobrien(define_insn "floathixf2"
466590286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4666169699Skan	(float:XF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
466718334Speter  "TARGET_80387"
466890286Sobrien  "@
466990286Sobrien   fild%z1\t%1
467090286Sobrien   #"
467190286Sobrien  [(set_attr "type" "fmov,multi")
467290286Sobrien   (set_attr "mode" "XF")
4673169699Skan   (set_attr "unit" "*,i387")
467490286Sobrien   (set_attr "fp_int_src" "true")])
467552296Sobrien
467690286Sobrien(define_insn "floatsixf2"
467790286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4678169699Skan	(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
467952296Sobrien  "TARGET_80387"
468090286Sobrien  "@
468190286Sobrien   fild%z1\t%1
468290286Sobrien   #"
468390286Sobrien  [(set_attr "type" "fmov,multi")
468490286Sobrien   (set_attr "mode" "XF")
4685169699Skan   (set_attr "unit" "*,i387")
468690286Sobrien   (set_attr "fp_int_src" "true")])
468752296Sobrien
468890286Sobrien(define_insn "floatdixf2"
468990286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4690169699Skan	(float:XF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
469152296Sobrien  "TARGET_80387"
469290286Sobrien  "@
469390286Sobrien   fild%z1\t%1
469490286Sobrien   #"
469590286Sobrien  [(set_attr "type" "fmov,multi")
469690286Sobrien   (set_attr "mode" "XF")
4697169699Skan   (set_attr "unit" "*,i387")
469890286Sobrien   (set_attr "fp_int_src" "true")])
469952296Sobrien
470090286Sobrien;; %%% Kill these when reload knows how to do it.
470152296Sobrien(define_split
4702117404Skan  [(set (match_operand 0 "fp_register_operand" "")
470390286Sobrien	(float (match_operand 1 "register_operand" "")))]
4704169699Skan  "reload_completed
4705169699Skan   && TARGET_80387
4706169699Skan   && FLOAT_MODE_P (GET_MODE (operands[0]))"
470790286Sobrien  [(const_int 0)]
470890286Sobrien{
470990286Sobrien  operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
471090286Sobrien  operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]);
471190286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[2]));
471290286Sobrien  ix86_free_from_memory (GET_MODE (operands[1]));
471390286Sobrien  DONE;
471490286Sobrien})
4715132727Skan
4716132727Skan(define_expand "floatunssisf2"
4717132727Skan  [(use (match_operand:SF 0 "register_operand" ""))
4718132727Skan   (use (match_operand:SI 1 "register_operand" ""))]
4719169699Skan  "!TARGET_64BIT && TARGET_SSE_MATH"
4720132727Skan  "x86_emit_floatuns (operands); DONE;")
4721132727Skan
4722132727Skan(define_expand "floatunsdisf2"
4723132727Skan  [(use (match_operand:SF 0 "register_operand" ""))
4724132727Skan   (use (match_operand:DI 1 "register_operand" ""))]
4725169699Skan  "TARGET_64BIT && TARGET_SSE_MATH"
4726132727Skan  "x86_emit_floatuns (operands); DONE;")
4727132727Skan
4728132727Skan(define_expand "floatunsdidf2"
4729132727Skan  [(use (match_operand:DF 0 "register_operand" ""))
4730132727Skan   (use (match_operand:DI 1 "register_operand" ""))]
4731169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
4732132727Skan  "x86_emit_floatuns (operands); DONE;")
473390286Sobrien
4734132727Skan;; SSE extract/set expanders
4735132727Skan
4736169699Skan
4737169699Skan;; Add instructions
4738132727Skan
4739169699Skan;; %%% splits for addditi3
4740132727Skan
4741169699Skan(define_expand "addti3"
4742169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
4743169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
4744169699Skan		 (match_operand:TI 2 "x86_64_general_operand" "")))
4745169699Skan   (clobber (reg:CC FLAGS_REG))]
4746169699Skan  "TARGET_64BIT"
4747169699Skan  "ix86_expand_binary_operator (PLUS, TImode, operands); DONE;")
4748132727Skan
4749169699Skan(define_insn "*addti3_1"
4750169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
4751169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0")
4752171835Skan		 (match_operand:TI 2 "x86_64_general_operand" "roe,re")))
4753169699Skan   (clobber (reg:CC FLAGS_REG))]
4754169699Skan  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)"
4755169699Skan  "#")
4756132727Skan
4757169699Skan(define_split
4758169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
4759169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
4760171835Skan		 (match_operand:TI 2 "x86_64_general_operand" "")))
4761169699Skan   (clobber (reg:CC FLAGS_REG))]
4762169699Skan  "TARGET_64BIT && reload_completed"
4763169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
4764169699Skan					  UNSPEC_ADD_CARRY))
4765169699Skan	      (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))])
4766169699Skan   (parallel [(set (match_dup 3)
4767169699Skan		   (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
4768169699Skan				     (match_dup 4))
4769169699Skan			    (match_dup 5)))
4770169699Skan	      (clobber (reg:CC FLAGS_REG))])]
4771169699Skan  "split_ti (operands+0, 1, operands+0, operands+3);
4772169699Skan   split_ti (operands+1, 1, operands+1, operands+4);
4773169699Skan   split_ti (operands+2, 1, operands+2, operands+5);")
4774132727Skan
477590286Sobrien;; %%% splits for addsidi3
477690286Sobrien;  [(set (match_operand:DI 0 "nonimmediate_operand" "")
477790286Sobrien;	(plus:DI (match_operand:DI 1 "general_operand" "")
477890286Sobrien;		 (zero_extend:DI (match_operand:SI 2 "general_operand" ""))))]
477952296Sobrien
478090286Sobrien(define_expand "adddi3"
478190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
478290286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
478390286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "")))
4784169699Skan   (clobber (reg:CC FLAGS_REG))]
478590286Sobrien  ""
478690286Sobrien  "ix86_expand_binary_operator (PLUS, DImode, operands); DONE;")
478752296Sobrien
478890286Sobrien(define_insn "*adddi3_1"
478990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
479090286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
479190286Sobrien		 (match_operand:DI 2 "general_operand" "roiF,riF")))
4792169699Skan   (clobber (reg:CC FLAGS_REG))]
4793107605Sobrien  "!TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
479452296Sobrien  "#")
479552296Sobrien
479652296Sobrien(define_split
479790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
479890286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
479990286Sobrien		 (match_operand:DI 2 "general_operand" "")))
4800169699Skan   (clobber (reg:CC FLAGS_REG))]
480190286Sobrien  "!TARGET_64BIT && reload_completed"
4802169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
4803117404Skan					  UNSPEC_ADD_CARRY))
480490286Sobrien	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
480590286Sobrien   (parallel [(set (match_dup 3)
4806169699Skan		   (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
480790286Sobrien				     (match_dup 4))
480890286Sobrien			    (match_dup 5)))
4809169699Skan	      (clobber (reg:CC FLAGS_REG))])]
481090286Sobrien  "split_di (operands+0, 1, operands+0, operands+3);
481190286Sobrien   split_di (operands+1, 1, operands+1, operands+4);
481290286Sobrien   split_di (operands+2, 1, operands+2, operands+5);")
481318334Speter
4814132727Skan(define_insn "adddi3_carry_rex64"
481590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
4816132727Skan	  (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
481790286Sobrien			    (match_operand:DI 1 "nonimmediate_operand" "%0,0"))
481890286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
4819169699Skan   (clobber (reg:CC FLAGS_REG))]
482090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
482190286Sobrien  "adc{q}\t{%2, %0|%0, %2}"
482290286Sobrien  [(set_attr "type" "alu")
482390286Sobrien   (set_attr "pent_pair" "pu")
4824169699Skan   (set_attr "mode" "DI")])
482552296Sobrien
482690286Sobrien(define_insn "*adddi3_cc_rex64"
4827169699Skan  [(set (reg:CC FLAGS_REG)
4828117404Skan	(unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0")
4829117404Skan		    (match_operand:DI 2 "x86_64_general_operand" "re,rm")]
4830117404Skan		   UNSPEC_ADD_CARRY))
483190286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
483290286Sobrien	(plus:DI (match_dup 1) (match_dup 2)))]
483390286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
483490286Sobrien  "add{q}\t{%2, %0|%0, %2}"
483590286Sobrien  [(set_attr "type" "alu")
483690286Sobrien   (set_attr "mode" "DI")])
483752296Sobrien
4838132727Skan(define_insn "addqi3_carry"
4839132727Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
4840132727Skan	  (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
4841132727Skan			    (match_operand:QI 1 "nonimmediate_operand" "%0,0"))
4842132727Skan		   (match_operand:QI 2 "general_operand" "qi,qm")))
4843169699Skan   (clobber (reg:CC FLAGS_REG))]
4844132727Skan  "ix86_binary_operator_ok (PLUS, QImode, operands)"
4845132727Skan  "adc{b}\t{%2, %0|%0, %2}"
4846132727Skan  [(set_attr "type" "alu")
4847132727Skan   (set_attr "pent_pair" "pu")
4848169699Skan   (set_attr "mode" "QI")])
4849132727Skan
4850132727Skan(define_insn "addhi3_carry"
4851132727Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
4852132727Skan	  (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
4853132727Skan			    (match_operand:HI 1 "nonimmediate_operand" "%0,0"))
4854132727Skan		   (match_operand:HI 2 "general_operand" "ri,rm")))
4855169699Skan   (clobber (reg:CC FLAGS_REG))]
4856132727Skan  "ix86_binary_operator_ok (PLUS, HImode, operands)"
4857132727Skan  "adc{w}\t{%2, %0|%0, %2}"
4858132727Skan  [(set_attr "type" "alu")
4859132727Skan   (set_attr "pent_pair" "pu")
4860169699Skan   (set_attr "mode" "HI")])
4861132727Skan
4862132727Skan(define_insn "addsi3_carry"
486390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
4864132727Skan	  (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
486590286Sobrien			    (match_operand:SI 1 "nonimmediate_operand" "%0,0"))
486690286Sobrien		   (match_operand:SI 2 "general_operand" "ri,rm")))
4867169699Skan   (clobber (reg:CC FLAGS_REG))]
486890286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
486990286Sobrien  "adc{l}\t{%2, %0|%0, %2}"
487090286Sobrien  [(set_attr "type" "alu")
487190286Sobrien   (set_attr "pent_pair" "pu")
4872169699Skan   (set_attr "mode" "SI")])
487352296Sobrien
487490286Sobrien(define_insn "*addsi3_carry_zext"
487590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
487690286Sobrien	  (zero_extend:DI 
4877132727Skan	    (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
487890286Sobrien			      (match_operand:SI 1 "nonimmediate_operand" "%0"))
487990286Sobrien		     (match_operand:SI 2 "general_operand" "rim"))))
4880169699Skan   (clobber (reg:CC FLAGS_REG))]
488190286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
488290286Sobrien  "adc{l}\t{%2, %k0|%k0, %2}"
488390286Sobrien  [(set_attr "type" "alu")
488490286Sobrien   (set_attr "pent_pair" "pu")
4885169699Skan   (set_attr "mode" "SI")])
488652296Sobrien
488790286Sobrien(define_insn "*addsi3_cc"
4888169699Skan  [(set (reg:CC FLAGS_REG)
4889117404Skan	(unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0")
4890117404Skan		    (match_operand:SI 2 "general_operand" "ri,rm")]
4891117404Skan		   UNSPEC_ADD_CARRY))
489290286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
489390286Sobrien	(plus:SI (match_dup 1) (match_dup 2)))]
489490286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
489590286Sobrien  "add{l}\t{%2, %0|%0, %2}"
489690286Sobrien  [(set_attr "type" "alu")
489790286Sobrien   (set_attr "mode" "SI")])
489818334Speter
489990286Sobrien(define_insn "addqi3_cc"
4900169699Skan  [(set (reg:CC FLAGS_REG)
4901117404Skan	(unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0")
4902117404Skan		    (match_operand:QI 2 "general_operand" "qi,qm")]
4903117404Skan		   UNSPEC_ADD_CARRY))
490490286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
490590286Sobrien	(plus:QI (match_dup 1) (match_dup 2)))]
490690286Sobrien  "ix86_binary_operator_ok (PLUS, QImode, operands)"
490790286Sobrien  "add{b}\t{%2, %0|%0, %2}"
490890286Sobrien  [(set_attr "type" "alu")
490990286Sobrien   (set_attr "mode" "QI")])
491018334Speter
491190286Sobrien(define_expand "addsi3"
491290286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
491390286Sobrien		   (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
491490286Sobrien			    (match_operand:SI 2 "general_operand" "")))
4915169699Skan	      (clobber (reg:CC FLAGS_REG))])]
491690286Sobrien  ""
491790286Sobrien  "ix86_expand_binary_operator (PLUS, SImode, operands); DONE;")
491818334Speter
491990286Sobrien(define_insn "*lea_1"
492090286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
4921132727Skan	(match_operand:SI 1 "no_seg_address_operand" "p"))]
492290286Sobrien  "!TARGET_64BIT"
492390286Sobrien  "lea{l}\t{%a1, %0|%0, %a1}"
492490286Sobrien  [(set_attr "type" "lea")
492590286Sobrien   (set_attr "mode" "SI")])
492618334Speter
492790286Sobrien(define_insn "*lea_1_rex64"
492890286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
4929132727Skan	(subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))]
493090286Sobrien  "TARGET_64BIT"
493190286Sobrien  "lea{l}\t{%a1, %0|%0, %a1}"
493290286Sobrien  [(set_attr "type" "lea")
493390286Sobrien   (set_attr "mode" "SI")])
493418334Speter
493590286Sobrien(define_insn "*lea_1_zext"
493690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
4937132727Skan	(zero_extend:DI
4938132727Skan	 (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))]
493990286Sobrien  "TARGET_64BIT"
494090286Sobrien  "lea{l}\t{%a1, %k0|%k0, %a1}"
494190286Sobrien  [(set_attr "type" "lea")
494290286Sobrien   (set_attr "mode" "SI")])
494390286Sobrien
494490286Sobrien(define_insn "*lea_2_rex64"
494590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
4946132727Skan	(match_operand:DI 1 "no_seg_address_operand" "p"))]
494790286Sobrien  "TARGET_64BIT"
494890286Sobrien  "lea{q}\t{%a1, %0|%0, %a1}"
494990286Sobrien  [(set_attr "type" "lea")
495090286Sobrien   (set_attr "mode" "DI")])
495190286Sobrien
495290286Sobrien;; The lea patterns for non-Pmodes needs to be matched by several
495390286Sobrien;; insns converted to real lea by splitters.
495490286Sobrien
495590286Sobrien(define_insn_and_split "*lea_general_1"
495690286Sobrien  [(set (match_operand 0 "register_operand" "=r")
4957169699Skan	(plus (plus (match_operand 1 "index_register_operand" "l")
495890286Sobrien		    (match_operand 2 "register_operand" "r"))
495990286Sobrien	      (match_operand 3 "immediate_operand" "i")))]
496090286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
496190286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
496290286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
496390286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
496490286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[2])
496590286Sobrien   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
496690286Sobrien       || GET_MODE (operands[3]) == VOIDmode)"
496790286Sobrien  "#"
496890286Sobrien  "&& reload_completed"
496990286Sobrien  [(const_int 0)]
497090286Sobrien{
497190286Sobrien  rtx pat;
497290286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
497390286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
497490286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
497590286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
497690286Sobrien  pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]),
497790286Sobrien  		      operands[3]);
497890286Sobrien  if (Pmode != SImode)
497990286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
498090286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
498190286Sobrien  DONE;
498290286Sobrien}
498390286Sobrien  [(set_attr "type" "lea")
498490286Sobrien   (set_attr "mode" "SI")])
498590286Sobrien
498690286Sobrien(define_insn_and_split "*lea_general_1_zext"
498790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
498890286Sobrien	(zero_extend:DI
4989169699Skan	  (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "l")
499090286Sobrien			    (match_operand:SI 2 "register_operand" "r"))
499190286Sobrien		   (match_operand:SI 3 "immediate_operand" "i"))))]
499290286Sobrien  "TARGET_64BIT"
499390286Sobrien  "#"
499490286Sobrien  "&& reload_completed"
499552296Sobrien  [(set (match_dup 0)
499690286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1)
499790286Sobrien						     (match_dup 2))
499890286Sobrien					    (match_dup 3)) 0)))]
499990286Sobrien{
500090286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
500190286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
500290286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
500390286Sobrien}
500490286Sobrien  [(set_attr "type" "lea")
500590286Sobrien   (set_attr "mode" "SI")])
500652296Sobrien
500790286Sobrien(define_insn_and_split "*lea_general_2"
500890286Sobrien  [(set (match_operand 0 "register_operand" "=r")
5009169699Skan	(plus (mult (match_operand 1 "index_register_operand" "l")
501090286Sobrien		    (match_operand 2 "const248_operand" "i"))
501190286Sobrien	      (match_operand 3 "nonmemory_operand" "ri")))]
501290286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
501390286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
501490286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
501590286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
501690286Sobrien   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
501790286Sobrien       || GET_MODE (operands[3]) == VOIDmode)"
501890286Sobrien  "#"
501990286Sobrien  "&& reload_completed"
502090286Sobrien  [(const_int 0)]
502190286Sobrien{
502290286Sobrien  rtx pat;
502390286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
502490286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
502590286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
502690286Sobrien  pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]),
502790286Sobrien  		      operands[3]);
502890286Sobrien  if (Pmode != SImode)
502990286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
503090286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
503190286Sobrien  DONE;
503290286Sobrien}
503390286Sobrien  [(set_attr "type" "lea")
503490286Sobrien   (set_attr "mode" "SI")])
503552296Sobrien
503690286Sobrien(define_insn_and_split "*lea_general_2_zext"
503790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
503890286Sobrien	(zero_extend:DI
5039169699Skan	  (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "l")
504090286Sobrien			    (match_operand:SI 2 "const248_operand" "n"))
504190286Sobrien		   (match_operand:SI 3 "nonmemory_operand" "ri"))))]
504290286Sobrien  "TARGET_64BIT"
504390286Sobrien  "#"
504490286Sobrien  "&& reload_completed"
504590286Sobrien  [(set (match_dup 0)
504690286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1)
504790286Sobrien						     (match_dup 2))
504890286Sobrien					    (match_dup 3)) 0)))]
504990286Sobrien{
505090286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
505190286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
505290286Sobrien}
505390286Sobrien  [(set_attr "type" "lea")
505490286Sobrien   (set_attr "mode" "SI")])
505518334Speter
505690286Sobrien(define_insn_and_split "*lea_general_3"
505790286Sobrien  [(set (match_operand 0 "register_operand" "=r")
5058169699Skan	(plus (plus (mult (match_operand 1 "index_register_operand" "l")
505990286Sobrien			  (match_operand 2 "const248_operand" "i"))
506090286Sobrien		    (match_operand 3 "register_operand" "r"))
506190286Sobrien	      (match_operand 4 "immediate_operand" "i")))]
506290286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
506390286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
506490286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
506590286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
506690286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[3])"
506790286Sobrien  "#"
506890286Sobrien  "&& reload_completed"
506990286Sobrien  [(const_int 0)]
507090286Sobrien{
507190286Sobrien  rtx pat;
507290286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
507390286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
507490286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
507590286Sobrien  operands[4] = gen_lowpart (Pmode, operands[4]);
507690286Sobrien  pat = gen_rtx_PLUS (Pmode,
507790286Sobrien  		      gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1],
507890286Sobrien		      					 operands[2]),
507990286Sobrien				    operands[3]),
508090286Sobrien  		      operands[4]);
508190286Sobrien  if (Pmode != SImode)
508290286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
508390286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
508490286Sobrien  DONE;
508590286Sobrien}
508690286Sobrien  [(set_attr "type" "lea")
508790286Sobrien   (set_attr "mode" "SI")])
508852296Sobrien
508990286Sobrien(define_insn_and_split "*lea_general_3_zext"
509090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
509190286Sobrien	(zero_extend:DI
5092169699Skan	  (plus:SI (plus:SI (mult:SI
5093169699Skan			      (match_operand:SI 1 "index_register_operand" "l")
5094169699Skan			      (match_operand:SI 2 "const248_operand" "n"))
509590286Sobrien			    (match_operand:SI 3 "register_operand" "r"))
509690286Sobrien		   (match_operand:SI 4 "immediate_operand" "i"))))]
509790286Sobrien  "TARGET_64BIT"
509890286Sobrien  "#"
509990286Sobrien  "&& reload_completed"
510090286Sobrien  [(set (match_dup 0)
510190286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1)
510290286Sobrien							      (match_dup 2))
510390286Sobrien						     (match_dup 3))
510490286Sobrien					    (match_dup 4)) 0)))]
510590286Sobrien{
510690286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
510790286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
510890286Sobrien  operands[4] = gen_lowpart (Pmode, operands[4]);
510990286Sobrien}
511090286Sobrien  [(set_attr "type" "lea")
511190286Sobrien   (set_attr "mode" "SI")])
511218334Speter
511390286Sobrien(define_insn "*adddi_1_rex64"
511490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
511590286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r")
5116169699Skan		 (match_operand:DI 2 "x86_64_general_operand" "rme,re,le")))
5117169699Skan   (clobber (reg:CC FLAGS_REG))]
511890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
511990286Sobrien{
512090286Sobrien  switch (get_attr_type (insn))
512190286Sobrien    {
512290286Sobrien    case TYPE_LEA:
512390286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
512490286Sobrien      return "lea{q}\t{%a2, %0|%0, %a2}";
512590286Sobrien
512690286Sobrien    case TYPE_INCDEC:
5127169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
512890286Sobrien      if (operands[2] == const1_rtx)
512990286Sobrien        return "inc{q}\t%0";
513090286Sobrien      else
5131169699Skan        {
5132169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5133169699Skan          return "dec{q}\t%0";
5134169699Skan	}
513590286Sobrien
513690286Sobrien    default:
5137169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
513890286Sobrien
513990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
514090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
514190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
514290286Sobrien	  /* Avoid overflows.  */
514390286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
514490286Sobrien          && (INTVAL (operands[2]) == 128
514590286Sobrien	      || (INTVAL (operands[2]) < 0
514690286Sobrien		  && INTVAL (operands[2]) != -128)))
514790286Sobrien        {
514890286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
514990286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
515090286Sobrien        }
515190286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
515290286Sobrien    }
515390286Sobrien}
515490286Sobrien  [(set (attr "type")
515590286Sobrien     (cond [(eq_attr "alternative" "2")
515690286Sobrien	      (const_string "lea")
515790286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
515890286Sobrien	    ; ought but a memory context.
515990286Sobrien	    (match_operand:DI 2 "pic_symbolic_operand" "")
516090286Sobrien	      (const_string "lea")
516190286Sobrien	    (match_operand:DI 2 "incdec_operand" "")
516290286Sobrien	      (const_string "incdec")
516390286Sobrien	   ]
516490286Sobrien	   (const_string "alu")))
516590286Sobrien   (set_attr "mode" "DI")])
516690286Sobrien
516790286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
516852296Sobrien(define_split
516990286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
517090286Sobrien	(plus:DI (match_operand:DI 1 "register_operand" "")
517190286Sobrien		 (match_operand:DI 2 "x86_64_nonmemory_operand" "")))
5172169699Skan   (clobber (reg:CC FLAGS_REG))]
517390286Sobrien  "TARGET_64BIT && reload_completed
517490286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
517552296Sobrien  [(set (match_dup 0)
517690286Sobrien	(plus:DI (match_dup 1)
517790286Sobrien		 (match_dup 2)))]
517852296Sobrien  "")
517952296Sobrien
518090286Sobrien(define_insn "*adddi_2_rex64"
5181169699Skan  [(set (reg FLAGS_REG)
518290286Sobrien	(compare
518390286Sobrien	  (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
518490286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "rme,re"))
518590286Sobrien	  (const_int 0)))			
518690286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
518790286Sobrien	(plus:DI (match_dup 1) (match_dup 2)))]
518890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
518990286Sobrien   && ix86_binary_operator_ok (PLUS, DImode, operands)
519090286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
519190286Sobrien      ought but a memory context.  */
519290286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
519390286Sobrien{
519490286Sobrien  switch (get_attr_type (insn))
519590286Sobrien    {
519690286Sobrien    case TYPE_INCDEC:
5197169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
519890286Sobrien      if (operands[2] == const1_rtx)
519990286Sobrien        return "inc{q}\t%0";
520090286Sobrien      else
5201169699Skan        {
5202169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5203169699Skan          return "dec{q}\t%0";
5204169699Skan	}
520552296Sobrien
520690286Sobrien    default:
5207169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
520890286Sobrien      /* ???? We ought to handle there the 32bit case too
5209132727Skan	 - do we need new constraint?  */
521090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
521190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
521290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
521390286Sobrien	  /* Avoid overflows.  */
521490286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
521590286Sobrien          && (INTVAL (operands[2]) == 128
521690286Sobrien	      || (INTVAL (operands[2]) < 0
521790286Sobrien		  && INTVAL (operands[2]) != -128)))
521890286Sobrien        {
521990286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
522090286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
522190286Sobrien        }
522290286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
522390286Sobrien    }
522490286Sobrien}
522590286Sobrien  [(set (attr "type")
522690286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
522790286Sobrien	(const_string "incdec")
522890286Sobrien	(const_string "alu")))
522990286Sobrien   (set_attr "mode" "DI")])
523018334Speter
523190286Sobrien(define_insn "*adddi_3_rex64"
5232169699Skan  [(set (reg FLAGS_REG)
523390286Sobrien	(compare (neg:DI (match_operand:DI 2 "x86_64_general_operand" "rme"))
523490286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "%0")))
523590286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
523690286Sobrien  "TARGET_64BIT
523790286Sobrien   && ix86_match_ccmode (insn, CCZmode)
523890286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
523990286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
524090286Sobrien      ought but a memory context.  */
524190286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
524250650Sobrien{
524390286Sobrien  switch (get_attr_type (insn))
524490286Sobrien    {
524590286Sobrien    case TYPE_INCDEC:
5246169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
524790286Sobrien      if (operands[2] == const1_rtx)
524890286Sobrien        return "inc{q}\t%0";
524990286Sobrien      else
5250169699Skan        {
5251169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5252169699Skan          return "dec{q}\t%0";
5253169699Skan	}
525450650Sobrien
525590286Sobrien    default:
5256169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
525790286Sobrien      /* ???? We ought to handle there the 32bit case too
5258132727Skan	 - do we need new constraint?  */
525990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
526090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
526190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
526290286Sobrien	  /* Avoid overflows.  */
526390286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
526490286Sobrien          && (INTVAL (operands[2]) == 128
526590286Sobrien	      || (INTVAL (operands[2]) < 0
526690286Sobrien		  && INTVAL (operands[2]) != -128)))
526790286Sobrien        {
526890286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
526990286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
527090286Sobrien        }
527190286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
527290286Sobrien    }
527390286Sobrien}
527490286Sobrien  [(set (attr "type")
527590286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
527690286Sobrien	(const_string "incdec")
527790286Sobrien	(const_string "alu")))
527890286Sobrien   (set_attr "mode" "DI")])
527950650Sobrien
528090286Sobrien; For comparisons against 1, -1 and 128, we may generate better code
528190286Sobrien; by converting cmp to add, inc or dec as done by peephole2.  This pattern
528290286Sobrien; is matched then.  We can't accept general immediate, because for
528390286Sobrien; case of overflows,  the result is messed up.
528490286Sobrien; This pattern also don't hold of 0x8000000000000000, since the value overflows
528590286Sobrien; when negated.
528690286Sobrien; Also carry flag is reversed compared to cmp, so this conversion is valid
528790286Sobrien; only for comparisons not depending on it.
528890286Sobrien(define_insn "*adddi_4_rex64"
5289169699Skan  [(set (reg FLAGS_REG)
529090286Sobrien	(compare (match_operand:DI 1 "nonimmediate_operand" "0")
529190286Sobrien		 (match_operand:DI 2 "x86_64_immediate_operand" "e")))
529290286Sobrien   (clobber (match_scratch:DI 0 "=rm"))]
529390286Sobrien  "TARGET_64BIT
529490286Sobrien   &&  ix86_match_ccmode (insn, CCGCmode)"
529590286Sobrien{
529690286Sobrien  switch (get_attr_type (insn))
529790286Sobrien    {
529890286Sobrien    case TYPE_INCDEC:
529990286Sobrien      if (operands[2] == constm1_rtx)
530090286Sobrien        return "inc{q}\t%0";
530190286Sobrien      else
5302169699Skan        {
5303169699Skan	  gcc_assert (operands[2] == const1_rtx);
5304169699Skan          return "dec{q}\t%0";
5305169699Skan	}
530650650Sobrien
530790286Sobrien    default:
5308169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
530990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
531090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
531190286Sobrien      if ((INTVAL (operands[2]) == -128
531290286Sobrien	   || (INTVAL (operands[2]) > 0
531390286Sobrien	       && INTVAL (operands[2]) != 128))
531490286Sobrien	  /* Avoid overflows.  */
531590286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))))
531690286Sobrien	return "sub{q}\t{%2, %0|%0, %2}";
531790286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
531890286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
531990286Sobrien    }
532090286Sobrien}
532190286Sobrien  [(set (attr "type")
532290286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
532390286Sobrien	(const_string "incdec")
532490286Sobrien	(const_string "alu")))
532590286Sobrien   (set_attr "mode" "DI")])
532690286Sobrien
532790286Sobrien(define_insn "*adddi_5_rex64"
5328169699Skan  [(set (reg FLAGS_REG)
532990286Sobrien	(compare
533090286Sobrien	  (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
533190286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "rme"))
533290286Sobrien	  (const_int 0)))			
533390286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
533490286Sobrien  "TARGET_64BIT
533590286Sobrien   && ix86_match_ccmode (insn, CCGOCmode)
533690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
533790286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
533890286Sobrien      ought but a memory context.  */
533990286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
534090286Sobrien{
534190286Sobrien  switch (get_attr_type (insn))
534250650Sobrien    {
534390286Sobrien    case TYPE_INCDEC:
5344169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
534590286Sobrien      if (operands[2] == const1_rtx)
534690286Sobrien        return "inc{q}\t%0";
534790286Sobrien      else
5348169699Skan        {
5349169699Skan          gcc_assert (operands[2] == constm1_rtx);
5350169699Skan          return "dec{q}\t%0";
5351169699Skan	}
535250650Sobrien
535390286Sobrien    default:
5354169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
535590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
535690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
535790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
535890286Sobrien	  /* Avoid overflows.  */
535990286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
536090286Sobrien          && (INTVAL (operands[2]) == 128
536190286Sobrien	      || (INTVAL (operands[2]) < 0
536290286Sobrien		  && INTVAL (operands[2]) != -128)))
536390286Sobrien        {
536490286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
536590286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
536690286Sobrien        }
536790286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
536850650Sobrien    }
536990286Sobrien}
537090286Sobrien  [(set (attr "type")
537190286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
537290286Sobrien	(const_string "incdec")
537390286Sobrien	(const_string "alu")))
537490286Sobrien   (set_attr "mode" "DI")])
537550650Sobrien
537650650Sobrien
537790286Sobrien(define_insn "*addsi_1"
537890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
537990286Sobrien	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
5380169699Skan		 (match_operand:SI 2 "general_operand" "rmni,rni,lni")))
5381169699Skan   (clobber (reg:CC FLAGS_REG))]
538290286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
538350650Sobrien{
538490286Sobrien  switch (get_attr_type (insn))
538590286Sobrien    {
538690286Sobrien    case TYPE_LEA:
538790286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
538890286Sobrien      return "lea{l}\t{%a2, %0|%0, %a2}";
538950650Sobrien
539090286Sobrien    case TYPE_INCDEC:
5391169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
539290286Sobrien      if (operands[2] == const1_rtx)
539390286Sobrien        return "inc{l}\t%0";
539490286Sobrien      else
5395169699Skan	{
5396169699Skan  	  gcc_assert (operands[2] == constm1_rtx);
5397169699Skan          return "dec{l}\t%0";
5398169699Skan	}
539950650Sobrien
540090286Sobrien    default:
5401169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
540250650Sobrien
540390286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
540490286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
540590286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
540690286Sobrien          && (INTVAL (operands[2]) == 128
540790286Sobrien	      || (INTVAL (operands[2]) < 0
540890286Sobrien		  && INTVAL (operands[2]) != -128)))
540990286Sobrien        {
541090286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
541190286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
541290286Sobrien        }
541390286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
541490286Sobrien    }
541590286Sobrien}
541690286Sobrien  [(set (attr "type")
541790286Sobrien     (cond [(eq_attr "alternative" "2")
541890286Sobrien	      (const_string "lea")
541990286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
542090286Sobrien	    ; ought but a memory context.
542190286Sobrien	    (match_operand:SI 2 "pic_symbolic_operand" "")
542290286Sobrien	      (const_string "lea")
542390286Sobrien	    (match_operand:SI 2 "incdec_operand" "")
542490286Sobrien	      (const_string "incdec")
542590286Sobrien	   ]
542690286Sobrien	   (const_string "alu")))
542790286Sobrien   (set_attr "mode" "SI")])
542890286Sobrien
542990286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
543090286Sobrien(define_split
543190286Sobrien  [(set (match_operand 0 "register_operand" "")
543290286Sobrien	(plus (match_operand 1 "register_operand" "")
543390286Sobrien              (match_operand 2 "nonmemory_operand" "")))
5434169699Skan   (clobber (reg:CC FLAGS_REG))]
543590286Sobrien  "reload_completed
543690286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
543790286Sobrien  [(const_int 0)]
543890286Sobrien{
543990286Sobrien  rtx pat;
544090286Sobrien  /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
544190286Sobrien     may confuse gen_lowpart.  */
544290286Sobrien  if (GET_MODE (operands[0]) != Pmode)
544350650Sobrien    {
544490286Sobrien      operands[1] = gen_lowpart (Pmode, operands[1]);
544590286Sobrien      operands[2] = gen_lowpart (Pmode, operands[2]);
544690286Sobrien    }
544790286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
544890286Sobrien  pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
544990286Sobrien  if (Pmode != SImode)
545090286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
545190286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
545290286Sobrien  DONE;
545390286Sobrien})
545450650Sobrien
545590286Sobrien;; It may seem that nonimmediate operand is proper one for operand 1.
545690286Sobrien;; The addsi_1 pattern allows nonimmediate operand at that place and
545790286Sobrien;; we take care in ix86_binary_operator_ok to not allow two memory
545890286Sobrien;; operands so proper swapping will be done in reload.  This allow
545990286Sobrien;; patterns constructed from addsi_1 to match.
546090286Sobrien(define_insn "addsi_1_zext"
546190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
546290286Sobrien	(zero_extend:DI
546390286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r")
5464169699Skan		   (match_operand:SI 2 "general_operand" "rmni,lni"))))
5465169699Skan   (clobber (reg:CC FLAGS_REG))]
546690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
546790286Sobrien{
546890286Sobrien  switch (get_attr_type (insn))
546990286Sobrien    {
547090286Sobrien    case TYPE_LEA:
547190286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
547290286Sobrien      return "lea{l}\t{%a2, %k0|%k0, %a2}";
547390286Sobrien
547490286Sobrien    case TYPE_INCDEC:
547590286Sobrien      if (operands[2] == const1_rtx)
547690286Sobrien        return "inc{l}\t%k0";
547750650Sobrien      else
5478169699Skan        {
5479169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5480169699Skan          return "dec{l}\t%k0";
5481169699Skan	}
548290286Sobrien
548390286Sobrien    default:
548490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
548590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
548690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
548790286Sobrien          && (INTVAL (operands[2]) == 128
548890286Sobrien	      || (INTVAL (operands[2]) < 0
548990286Sobrien		  && INTVAL (operands[2]) != -128)))
549090286Sobrien        {
549190286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
549290286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
549390286Sobrien        }
549490286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
549550650Sobrien    }
549690286Sobrien}
549790286Sobrien  [(set (attr "type")
549890286Sobrien     (cond [(eq_attr "alternative" "1")
549990286Sobrien	      (const_string "lea")
550090286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
550190286Sobrien	    ; ought but a memory context.
550290286Sobrien	    (match_operand:SI 2 "pic_symbolic_operand" "")
550390286Sobrien	      (const_string "lea")
550490286Sobrien	    (match_operand:SI 2 "incdec_operand" "")
550590286Sobrien	      (const_string "incdec")
550690286Sobrien	   ]
550790286Sobrien	   (const_string "alu")))
550890286Sobrien   (set_attr "mode" "SI")])
550950650Sobrien
551090286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
551190286Sobrien(define_split
551290286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
551390286Sobrien	(zero_extend:DI
551490286Sobrien	  (plus:SI (match_operand:SI 1 "register_operand" "")
551590286Sobrien		   (match_operand:SI 2 "nonmemory_operand" ""))))
5516169699Skan   (clobber (reg:CC FLAGS_REG))]
5517132727Skan  "TARGET_64BIT && reload_completed
551890286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
551990286Sobrien  [(set (match_dup 0)
552090286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))]
552190286Sobrien{
552290286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
552390286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
552490286Sobrien})
552550650Sobrien
552690286Sobrien(define_insn "*addsi_2"
5527169699Skan  [(set (reg FLAGS_REG)
552890286Sobrien	(compare
552990286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
553090286Sobrien		   (match_operand:SI 2 "general_operand" "rmni,rni"))
553190286Sobrien	  (const_int 0)))			
553290286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
553390286Sobrien	(plus:SI (match_dup 1) (match_dup 2)))]
553490286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
553590286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
553690286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
553790286Sobrien      ought but a memory context.  */
553890286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
553918334Speter{
554090286Sobrien  switch (get_attr_type (insn))
554190286Sobrien    {
554290286Sobrien    case TYPE_INCDEC:
5543169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
554490286Sobrien      if (operands[2] == const1_rtx)
554590286Sobrien        return "inc{l}\t%0";
554690286Sobrien      else
5547169699Skan        {
5548169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5549169699Skan          return "dec{l}\t%0";
5550169699Skan	}
555118334Speter
555290286Sobrien    default:
5553169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
555490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
555590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
555690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
555790286Sobrien          && (INTVAL (operands[2]) == 128
555890286Sobrien	      || (INTVAL (operands[2]) < 0
555990286Sobrien		  && INTVAL (operands[2]) != -128)))
556090286Sobrien        {
556190286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
556290286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
556390286Sobrien        }
556490286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
556590286Sobrien    }
556690286Sobrien}
556790286Sobrien  [(set (attr "type")
556890286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
556990286Sobrien	(const_string "incdec")
557090286Sobrien	(const_string "alu")))
557190286Sobrien   (set_attr "mode" "SI")])
557218334Speter
557390286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
557490286Sobrien(define_insn "*addsi_2_zext"
5575169699Skan  [(set (reg FLAGS_REG)
557690286Sobrien	(compare
557790286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
557890286Sobrien		   (match_operand:SI 2 "general_operand" "rmni"))
557990286Sobrien	  (const_int 0)))			
558090286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
558190286Sobrien	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
558290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
558390286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
558490286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
558590286Sobrien      ought but a memory context.  */
558690286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
558790286Sobrien{
558890286Sobrien  switch (get_attr_type (insn))
558918334Speter    {
559090286Sobrien    case TYPE_INCDEC:
559190286Sobrien      if (operands[2] == const1_rtx)
559290286Sobrien        return "inc{l}\t%k0";
559390286Sobrien      else
5594169699Skan	{
5595169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5596169699Skan          return "dec{l}\t%k0";
5597169699Skan	}
559890286Sobrien
559990286Sobrien    default:
560090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
560190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
560290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
560390286Sobrien          && (INTVAL (operands[2]) == 128
560490286Sobrien	      || (INTVAL (operands[2]) < 0
560590286Sobrien		  && INTVAL (operands[2]) != -128)))
560690286Sobrien        {
560790286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
560890286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
560990286Sobrien        }
561090286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
561118334Speter    }
561290286Sobrien}
561390286Sobrien  [(set (attr "type")
561490286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
561590286Sobrien	(const_string "incdec")
561690286Sobrien	(const_string "alu")))
561790286Sobrien   (set_attr "mode" "SI")])
561818334Speter
561990286Sobrien(define_insn "*addsi_3"
5620169699Skan  [(set (reg FLAGS_REG)
562190286Sobrien	(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
562290286Sobrien		 (match_operand:SI 1 "nonimmediate_operand" "%0")))
562390286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
562490286Sobrien  "ix86_match_ccmode (insn, CCZmode)
562590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
562690286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
562790286Sobrien      ought but a memory context.  */
562890286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
562990286Sobrien{
563090286Sobrien  switch (get_attr_type (insn))
563118334Speter    {
563290286Sobrien    case TYPE_INCDEC:
5633169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
563490286Sobrien      if (operands[2] == const1_rtx)
563590286Sobrien        return "inc{l}\t%0";
563690286Sobrien      else
5637169699Skan        {
5638169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5639169699Skan          return "dec{l}\t%0";
5640169699Skan	}
564118334Speter
564290286Sobrien    default:
5643169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
564490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
564590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
564690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
564790286Sobrien          && (INTVAL (operands[2]) == 128
564890286Sobrien	      || (INTVAL (operands[2]) < 0
564990286Sobrien		  && INTVAL (operands[2]) != -128)))
565090286Sobrien        {
565190286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
565290286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
565390286Sobrien        }
565490286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
565590286Sobrien    }
565690286Sobrien}
565790286Sobrien  [(set (attr "type")
565890286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
565990286Sobrien	(const_string "incdec")
566090286Sobrien	(const_string "alu")))
566190286Sobrien   (set_attr "mode" "SI")])
566290286Sobrien
566390286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
566490286Sobrien(define_insn "*addsi_3_zext"
5665169699Skan  [(set (reg FLAGS_REG)
566690286Sobrien	(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
566790286Sobrien		 (match_operand:SI 1 "nonimmediate_operand" "%0")))
566890286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
566990286Sobrien	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
567090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCZmode)
567190286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
567290286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
567390286Sobrien      ought but a memory context.  */
567490286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
567590286Sobrien{
567690286Sobrien  switch (get_attr_type (insn))
567790286Sobrien    {
567890286Sobrien    case TYPE_INCDEC:
567990286Sobrien      if (operands[2] == const1_rtx)
568090286Sobrien        return "inc{l}\t%k0";
568118334Speter      else
5682169699Skan        {
5683169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5684169699Skan          return "dec{l}\t%k0";
5685169699Skan	}
568690286Sobrien
568790286Sobrien    default:
568890286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
568990286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
569090286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
569190286Sobrien          && (INTVAL (operands[2]) == 128
569290286Sobrien	      || (INTVAL (operands[2]) < 0
569390286Sobrien		  && INTVAL (operands[2]) != -128)))
569490286Sobrien        {
569590286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
569690286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
569790286Sobrien        }
569890286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
569918334Speter    }
570090286Sobrien}
570190286Sobrien  [(set (attr "type")
570290286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
570390286Sobrien	(const_string "incdec")
570490286Sobrien	(const_string "alu")))
570590286Sobrien   (set_attr "mode" "SI")])
570618334Speter
5707132727Skan; For comparisons against 1, -1 and 128, we may generate better code
570890286Sobrien; by converting cmp to add, inc or dec as done by peephole2.  This pattern
570990286Sobrien; is matched then.  We can't accept general immediate, because for
571090286Sobrien; case of overflows,  the result is messed up.
571190286Sobrien; This pattern also don't hold of 0x80000000, since the value overflows
571290286Sobrien; when negated.
571390286Sobrien; Also carry flag is reversed compared to cmp, so this conversion is valid
571490286Sobrien; only for comparisons not depending on it.
571590286Sobrien(define_insn "*addsi_4"
5716169699Skan  [(set (reg FLAGS_REG)
571790286Sobrien	(compare (match_operand:SI 1 "nonimmediate_operand" "0")
571890286Sobrien		 (match_operand:SI 2 "const_int_operand" "n")))
571990286Sobrien   (clobber (match_scratch:SI 0 "=rm"))]
572090286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
572190286Sobrien   && (INTVAL (operands[2]) & 0xffffffff) != 0x80000000"
572290286Sobrien{
572390286Sobrien  switch (get_attr_type (insn))
572418334Speter    {
572590286Sobrien    case TYPE_INCDEC:
572690286Sobrien      if (operands[2] == constm1_rtx)
572790286Sobrien        return "inc{l}\t%0";
572890286Sobrien      else
5729169699Skan        {
5730169699Skan	  gcc_assert (operands[2] == const1_rtx);
5731169699Skan          return "dec{l}\t%0";
5732169699Skan	}
573318334Speter
573490286Sobrien    default:
5735169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
573690286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
573790286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
573890286Sobrien      if ((INTVAL (operands[2]) == -128
573990286Sobrien	   || (INTVAL (operands[2]) > 0
574090286Sobrien	       && INTVAL (operands[2]) != 128)))
574190286Sobrien	return "sub{l}\t{%2, %0|%0, %2}";
574290286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
574390286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
574418334Speter    }
574590286Sobrien}
574690286Sobrien  [(set (attr "type")
574790286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
574890286Sobrien	(const_string "incdec")
574990286Sobrien	(const_string "alu")))
575090286Sobrien   (set_attr "mode" "SI")])
575118334Speter
575290286Sobrien(define_insn "*addsi_5"
5753169699Skan  [(set (reg FLAGS_REG)
575490286Sobrien	(compare
575590286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
575690286Sobrien		   (match_operand:SI 2 "general_operand" "rmni"))
575790286Sobrien	  (const_int 0)))			
575890286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
575990286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
576090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
576190286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
576290286Sobrien      ought but a memory context.  */
576390286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
576490286Sobrien{
576590286Sobrien  switch (get_attr_type (insn))
576618334Speter    {
576790286Sobrien    case TYPE_INCDEC:
5768169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
576990286Sobrien      if (operands[2] == const1_rtx)
577090286Sobrien        return "inc{l}\t%0";
577190286Sobrien      else
5772169699Skan        {
5773169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5774169699Skan          return "dec{l}\t%0";
5775169699Skan	}
577690286Sobrien
577790286Sobrien    default:
5778169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
577990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
578090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
578190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
578290286Sobrien          && (INTVAL (operands[2]) == 128
578390286Sobrien	      || (INTVAL (operands[2]) < 0
578490286Sobrien		  && INTVAL (operands[2]) != -128)))
578590286Sobrien        {
578690286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
578790286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
578890286Sobrien        }
578990286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
579018334Speter    }
579190286Sobrien}
579290286Sobrien  [(set (attr "type")
579390286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
579490286Sobrien	(const_string "incdec")
579590286Sobrien	(const_string "alu")))
579690286Sobrien   (set_attr "mode" "SI")])
579718334Speter
579890286Sobrien(define_expand "addhi3"
579990286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
580090286Sobrien		   (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
580190286Sobrien			    (match_operand:HI 2 "general_operand" "")))
5802169699Skan	      (clobber (reg:CC FLAGS_REG))])]
580390286Sobrien  "TARGET_HIMODE_MATH"
580490286Sobrien  "ix86_expand_binary_operator (PLUS, HImode, operands); DONE;")
580518334Speter
580690286Sobrien;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah
580790286Sobrien;; type optimizations enabled by define-splits.  This is not important
580890286Sobrien;; for PII, and in fact harmful because of partial register stalls.
580918334Speter
581090286Sobrien(define_insn "*addhi_1_lea"
581190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
581290286Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
5813169699Skan		 (match_operand:HI 2 "general_operand" "ri,rm,lni")))
5814169699Skan   (clobber (reg:CC FLAGS_REG))]
581590286Sobrien  "!TARGET_PARTIAL_REG_STALL
581690286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
581790286Sobrien{
581890286Sobrien  switch (get_attr_type (insn))
581990286Sobrien    {
582090286Sobrien    case TYPE_LEA:
582190286Sobrien      return "#";
582290286Sobrien    case TYPE_INCDEC:
582390286Sobrien      if (operands[2] == const1_rtx)
582490286Sobrien	return "inc{w}\t%0";
5825169699Skan      else
5826169699Skan	{
5827169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5828169699Skan	  return "dec{w}\t%0";
5829169699Skan	}
583018334Speter
583190286Sobrien    default:
583290286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
583390286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
583490286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
583590286Sobrien          && (INTVAL (operands[2]) == 128
583690286Sobrien	      || (INTVAL (operands[2]) < 0
583790286Sobrien		  && INTVAL (operands[2]) != -128)))
583890286Sobrien	{
583990286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
584090286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
584190286Sobrien	}
584290286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
584390286Sobrien    }
584490286Sobrien}
584590286Sobrien  [(set (attr "type")
584690286Sobrien     (if_then_else (eq_attr "alternative" "2")
584790286Sobrien	(const_string "lea")
584890286Sobrien	(if_then_else (match_operand:HI 2 "incdec_operand" "")
584990286Sobrien	   (const_string "incdec")
585090286Sobrien	   (const_string "alu"))))
585190286Sobrien   (set_attr "mode" "HI,HI,SI")])
585250650Sobrien
585390286Sobrien(define_insn "*addhi_1"
585490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
585590286Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
585690286Sobrien		 (match_operand:HI 2 "general_operand" "ri,rm")))
5857169699Skan   (clobber (reg:CC FLAGS_REG))]
585890286Sobrien  "TARGET_PARTIAL_REG_STALL
585990286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
586018334Speter{
586190286Sobrien  switch (get_attr_type (insn))
586218334Speter    {
586390286Sobrien    case TYPE_INCDEC:
586490286Sobrien      if (operands[2] == const1_rtx)
586590286Sobrien	return "inc{w}\t%0";
5866169699Skan      else
5867169699Skan        {
5868169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5869169699Skan	  return "dec{w}\t%0";
5870169699Skan	}
587118334Speter
587290286Sobrien    default:
587390286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
587490286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
587590286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
587690286Sobrien          && (INTVAL (operands[2]) == 128
587790286Sobrien	      || (INTVAL (operands[2]) < 0
587890286Sobrien		  && INTVAL (operands[2]) != -128)))
587918334Speter	{
588090286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
588190286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
588218334Speter	}
588390286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
588490286Sobrien    }
588590286Sobrien}
588690286Sobrien  [(set (attr "type")
588790286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
588890286Sobrien	(const_string "incdec")
588990286Sobrien	(const_string "alu")))
589090286Sobrien   (set_attr "mode" "HI")])
589118334Speter
589290286Sobrien(define_insn "*addhi_2"
5893169699Skan  [(set (reg FLAGS_REG)
589490286Sobrien	(compare
589590286Sobrien	  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
589690286Sobrien		   (match_operand:HI 2 "general_operand" "rmni,rni"))
589790286Sobrien	  (const_int 0)))			
589890286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
589990286Sobrien	(plus:HI (match_dup 1) (match_dup 2)))]
590090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
590190286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
590290286Sobrien{
590390286Sobrien  switch (get_attr_type (insn))
590490286Sobrien    {
590590286Sobrien    case TYPE_INCDEC:
590690286Sobrien      if (operands[2] == const1_rtx)
590790286Sobrien	return "inc{w}\t%0";
5908169699Skan      else
5909169699Skan        {
5910169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5911169699Skan	  return "dec{w}\t%0";
5912169699Skan	}
591390286Sobrien
591490286Sobrien    default:
591590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
591690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
591790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
591890286Sobrien          && (INTVAL (operands[2]) == 128
591990286Sobrien	      || (INTVAL (operands[2]) < 0
592090286Sobrien		  && INTVAL (operands[2]) != -128)))
592118334Speter	{
592290286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
592390286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
592418334Speter	}
592590286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
592618334Speter    }
592790286Sobrien}
592890286Sobrien  [(set (attr "type")
592990286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
593090286Sobrien	(const_string "incdec")
593190286Sobrien	(const_string "alu")))
593290286Sobrien   (set_attr "mode" "HI")])
593318334Speter
593490286Sobrien(define_insn "*addhi_3"
5935169699Skan  [(set (reg FLAGS_REG)
593690286Sobrien	(compare (neg:HI (match_operand:HI 2 "general_operand" "rmni"))
593790286Sobrien		 (match_operand:HI 1 "nonimmediate_operand" "%0")))
593890286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
593990286Sobrien  "ix86_match_ccmode (insn, CCZmode)
594090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
594190286Sobrien{
594290286Sobrien  switch (get_attr_type (insn))
594390286Sobrien    {
594490286Sobrien    case TYPE_INCDEC:
594590286Sobrien      if (operands[2] == const1_rtx)
594690286Sobrien	return "inc{w}\t%0";
5947169699Skan      else
5948169699Skan        {
5949169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5950169699Skan	  return "dec{w}\t%0";
5951169699Skan	}
595250650Sobrien
595390286Sobrien    default:
595490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
595590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
595690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
595790286Sobrien          && (INTVAL (operands[2]) == 128
595890286Sobrien	      || (INTVAL (operands[2]) < 0
595990286Sobrien		  && INTVAL (operands[2]) != -128)))
596090286Sobrien	{
596190286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
596290286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
596390286Sobrien	}
596490286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
596590286Sobrien    }
596690286Sobrien}
596790286Sobrien  [(set (attr "type")
596890286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
596990286Sobrien	(const_string "incdec")
597090286Sobrien	(const_string "alu")))
597190286Sobrien   (set_attr "mode" "HI")])
597218334Speter
5973169699Skan; See comments above addsi_4 for details.
597490286Sobrien(define_insn "*addhi_4"
5975169699Skan  [(set (reg FLAGS_REG)
597690286Sobrien	(compare (match_operand:HI 1 "nonimmediate_operand" "0")
597790286Sobrien		 (match_operand:HI 2 "const_int_operand" "n")))
597890286Sobrien   (clobber (match_scratch:HI 0 "=rm"))]
597990286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
598090286Sobrien   && (INTVAL (operands[2]) & 0xffff) != 0x8000"
598190286Sobrien{
598290286Sobrien  switch (get_attr_type (insn))
598390286Sobrien    {
598490286Sobrien    case TYPE_INCDEC:
5985117404Skan      if (operands[2] == constm1_rtx)
598690286Sobrien        return "inc{w}\t%0";
598790286Sobrien      else
5988169699Skan	{
5989169699Skan	  gcc_assert (operands[2] == const1_rtx);
5990169699Skan          return "dec{w}\t%0";
5991169699Skan	}
599218334Speter
599390286Sobrien    default:
5994169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
599590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
599690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
599790286Sobrien      if ((INTVAL (operands[2]) == -128
599890286Sobrien	   || (INTVAL (operands[2]) > 0
599990286Sobrien	       && INTVAL (operands[2]) != 128)))
600090286Sobrien	return "sub{w}\t{%2, %0|%0, %2}";
600190286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
600290286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
600350650Sobrien    }
600490286Sobrien}
600590286Sobrien  [(set (attr "type")
600690286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
600790286Sobrien	(const_string "incdec")
600890286Sobrien	(const_string "alu")))
600990286Sobrien   (set_attr "mode" "SI")])
601050650Sobrien
601118334Speter
601290286Sobrien(define_insn "*addhi_5"
6013169699Skan  [(set (reg FLAGS_REG)
601490286Sobrien	(compare
601590286Sobrien	  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
601690286Sobrien		   (match_operand:HI 2 "general_operand" "rmni"))
601790286Sobrien	  (const_int 0)))			
601890286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
601990286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
602090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
602150650Sobrien{
602290286Sobrien  switch (get_attr_type (insn))
602350650Sobrien    {
602490286Sobrien    case TYPE_INCDEC:
602590286Sobrien      if (operands[2] == const1_rtx)
602690286Sobrien	return "inc{w}\t%0";
6027169699Skan      else
6028169699Skan	{
6029169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6030169699Skan	  return "dec{w}\t%0";
6031169699Skan	}
603250650Sobrien
603390286Sobrien    default:
603490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
603590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
603690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
603790286Sobrien          && (INTVAL (operands[2]) == 128
603890286Sobrien	      || (INTVAL (operands[2]) < 0
603990286Sobrien		  && INTVAL (operands[2]) != -128)))
604090286Sobrien	{
604190286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
604290286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
604390286Sobrien	}
604490286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
604550650Sobrien    }
604690286Sobrien}
604790286Sobrien  [(set (attr "type")
604890286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
604990286Sobrien	(const_string "incdec")
605090286Sobrien	(const_string "alu")))
605190286Sobrien   (set_attr "mode" "HI")])
605250650Sobrien
605390286Sobrien(define_expand "addqi3"
605490286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
605590286Sobrien		   (plus:QI (match_operand:QI 1 "nonimmediate_operand" "")
605690286Sobrien			    (match_operand:QI 2 "general_operand" "")))
6057169699Skan	      (clobber (reg:CC FLAGS_REG))])]
605890286Sobrien  "TARGET_QIMODE_MATH"
605990286Sobrien  "ix86_expand_binary_operator (PLUS, QImode, operands); DONE;")
606050650Sobrien
606190286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
606290286Sobrien(define_insn "*addqi_1_lea"
606390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r")
606490286Sobrien	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r")
6065169699Skan		 (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln")))
6066169699Skan   (clobber (reg:CC FLAGS_REG))]
606790286Sobrien  "!TARGET_PARTIAL_REG_STALL
606890286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
606990286Sobrien{
607090286Sobrien  int widen = (which_alternative == 2);
607190286Sobrien  switch (get_attr_type (insn))
607290286Sobrien    {
607390286Sobrien    case TYPE_LEA:
607490286Sobrien      return "#";
607590286Sobrien    case TYPE_INCDEC:
607690286Sobrien      if (operands[2] == const1_rtx)
607790286Sobrien	return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
6078169699Skan      else
6079169699Skan	{
6080169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6081169699Skan	  return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
6082169699Skan	}
608318334Speter
608490286Sobrien    default:
608590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
608690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
608790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
608890286Sobrien          && (INTVAL (operands[2]) == 128
608990286Sobrien	      || (INTVAL (operands[2]) < 0
609090286Sobrien		  && INTVAL (operands[2]) != -128)))
609190286Sobrien	{
609290286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
609390286Sobrien	  if (widen)
609490286Sobrien	    return "sub{l}\t{%2, %k0|%k0, %2}";
609590286Sobrien	  else
609690286Sobrien	    return "sub{b}\t{%2, %0|%0, %2}";
609790286Sobrien	}
609890286Sobrien      if (widen)
609990286Sobrien        return "add{l}\t{%k2, %k0|%k0, %k2}";
610090286Sobrien      else
610190286Sobrien        return "add{b}\t{%2, %0|%0, %2}";
610290286Sobrien    }
610390286Sobrien}
610490286Sobrien  [(set (attr "type")
610590286Sobrien     (if_then_else (eq_attr "alternative" "3")
610690286Sobrien	(const_string "lea")
610790286Sobrien	(if_then_else (match_operand:QI 2 "incdec_operand" "")
610890286Sobrien	   (const_string "incdec")
610990286Sobrien	   (const_string "alu"))))
611090286Sobrien   (set_attr "mode" "QI,QI,SI,SI")])
611150650Sobrien
611290286Sobrien(define_insn "*addqi_1"
611390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
611490286Sobrien	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
611590286Sobrien		 (match_operand:QI 2 "general_operand" "qn,qmn,rn")))
6116169699Skan   (clobber (reg:CC FLAGS_REG))]
611790286Sobrien  "TARGET_PARTIAL_REG_STALL
611890286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
611918334Speter{
612090286Sobrien  int widen = (which_alternative == 2);
612190286Sobrien  switch (get_attr_type (insn))
612252296Sobrien    {
612390286Sobrien    case TYPE_INCDEC:
612490286Sobrien      if (operands[2] == const1_rtx)
612590286Sobrien	return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
6126169699Skan      else
6127169699Skan	{
6128169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6129169699Skan	  return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
6130169699Skan	}
613152296Sobrien
613290286Sobrien    default:
613390286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
613490286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
613590286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
613690286Sobrien          && (INTVAL (operands[2]) == 128
613790286Sobrien	      || (INTVAL (operands[2]) < 0
613890286Sobrien		  && INTVAL (operands[2]) != -128)))
613990286Sobrien	{
614090286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
614190286Sobrien	  if (widen)
614290286Sobrien	    return "sub{l}\t{%2, %k0|%k0, %2}";
614390286Sobrien	  else
614490286Sobrien	    return "sub{b}\t{%2, %0|%0, %2}";
614590286Sobrien	}
614690286Sobrien      if (widen)
614790286Sobrien        return "add{l}\t{%k2, %k0|%k0, %k2}";
614890286Sobrien      else
614990286Sobrien        return "add{b}\t{%2, %0|%0, %2}";
615052296Sobrien    }
615190286Sobrien}
615290286Sobrien  [(set (attr "type")
615390286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
615490286Sobrien	(const_string "incdec")
615590286Sobrien	(const_string "alu")))
615690286Sobrien   (set_attr "mode" "QI,QI,SI")])
615752296Sobrien
6158117404Skan(define_insn "*addqi_1_slp"
6159117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
6160117404Skan	(plus:QI (match_dup 0)
6161117404Skan		 (match_operand:QI 1 "general_operand" "qn,qnm")))
6162169699Skan   (clobber (reg:CC FLAGS_REG))]
6163117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
6164117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
6165117404Skan{
6166117404Skan  switch (get_attr_type (insn))
6167117404Skan    {
6168117404Skan    case TYPE_INCDEC:
6169117404Skan      if (operands[1] == const1_rtx)
6170117404Skan	return "inc{b}\t%0";
6171169699Skan      else
6172169699Skan	{
6173169699Skan	  gcc_assert (operands[1] == constm1_rtx);
6174169699Skan	  return "dec{b}\t%0";
6175169699Skan	}
6176117404Skan
6177117404Skan    default:
6178117404Skan      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.  */
6179117404Skan      if (GET_CODE (operands[1]) == CONST_INT
6180117404Skan	  && INTVAL (operands[1]) < 0)
6181117404Skan	{
6182132727Skan	  operands[1] = GEN_INT (-INTVAL (operands[1]));
6183117404Skan	  return "sub{b}\t{%1, %0|%0, %1}";
6184117404Skan	}
6185117404Skan      return "add{b}\t{%1, %0|%0, %1}";
6186117404Skan    }
6187117404Skan}
6188117404Skan  [(set (attr "type")
6189146906Skan     (if_then_else (match_operand:QI 1 "incdec_operand" "")
6190117404Skan	(const_string "incdec")
6191117404Skan	(const_string "alu1")))
6192146906Skan   (set (attr "memory")
6193146906Skan     (if_then_else (match_operand 1 "memory_operand" "")
6194146906Skan        (const_string "load")
6195146906Skan        (const_string "none")))
6196117404Skan   (set_attr "mode" "QI")])
6197117404Skan
619890286Sobrien(define_insn "*addqi_2"
6199169699Skan  [(set (reg FLAGS_REG)
620090286Sobrien	(compare
620190286Sobrien	  (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
620290286Sobrien		   (match_operand:QI 2 "general_operand" "qmni,qni"))
620390286Sobrien	  (const_int 0)))
620490286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
620590286Sobrien	(plus:QI (match_dup 1) (match_dup 2)))]
620690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
620790286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
620890286Sobrien{
620990286Sobrien  switch (get_attr_type (insn))
621018334Speter    {
621190286Sobrien    case TYPE_INCDEC:
621290286Sobrien      if (operands[2] == const1_rtx)
621390286Sobrien	return "inc{b}\t%0";
6214169699Skan      else
6215169699Skan        {
6216169699Skan	  gcc_assert (operands[2] == constm1_rtx
6217169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6218169699Skan		          && INTVAL (operands[2]) == 255));
6219169699Skan	  return "dec{b}\t%0";
6220169699Skan	}
622118334Speter
622290286Sobrien    default:
622390286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
622490286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
622590286Sobrien          && INTVAL (operands[2]) < 0)
622690286Sobrien	{
622790286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
622890286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
622990286Sobrien	}
623090286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
623118334Speter    }
623290286Sobrien}
623390286Sobrien  [(set (attr "type")
623490286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
623590286Sobrien	(const_string "incdec")
623690286Sobrien	(const_string "alu")))
623790286Sobrien   (set_attr "mode" "QI")])
623818334Speter
623990286Sobrien(define_insn "*addqi_3"
6240169699Skan  [(set (reg FLAGS_REG)
624190286Sobrien	(compare (neg:QI (match_operand:QI 2 "general_operand" "qmni"))
624290286Sobrien		 (match_operand:QI 1 "nonimmediate_operand" "%0")))
624390286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
624490286Sobrien  "ix86_match_ccmode (insn, CCZmode)
624590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
624690286Sobrien{
624790286Sobrien  switch (get_attr_type (insn))
624850650Sobrien    {
624990286Sobrien    case TYPE_INCDEC:
625090286Sobrien      if (operands[2] == const1_rtx)
625190286Sobrien	return "inc{b}\t%0";
6252169699Skan      else
6253169699Skan        {
6254169699Skan	  gcc_assert (operands[2] == constm1_rtx
6255169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6256169699Skan			  && INTVAL (operands[2]) == 255));
6257169699Skan	  return "dec{b}\t%0";
6258169699Skan	}
625950650Sobrien
626090286Sobrien    default:
626190286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
626290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
626390286Sobrien          && INTVAL (operands[2]) < 0)
626450650Sobrien	{
626590286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
626690286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
626790286Sobrien	}
626890286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
626990286Sobrien    }
627090286Sobrien}
627190286Sobrien  [(set (attr "type")
627290286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
627390286Sobrien	(const_string "incdec")
627490286Sobrien	(const_string "alu")))
627590286Sobrien   (set_attr "mode" "QI")])
627650650Sobrien
6277169699Skan; See comments above addsi_4 for details.
627890286Sobrien(define_insn "*addqi_4"
6279169699Skan  [(set (reg FLAGS_REG)
628090286Sobrien	(compare (match_operand:QI 1 "nonimmediate_operand" "0")
628190286Sobrien		 (match_operand:QI 2 "const_int_operand" "n")))
628290286Sobrien   (clobber (match_scratch:QI 0 "=qm"))]
628390286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
628490286Sobrien   && (INTVAL (operands[2]) & 0xff) != 0x80"
628590286Sobrien{
628690286Sobrien  switch (get_attr_type (insn))
628790286Sobrien    {
628890286Sobrien    case TYPE_INCDEC:
628990286Sobrien      if (operands[2] == constm1_rtx
629090286Sobrien	  || (GET_CODE (operands[2]) == CONST_INT
629190286Sobrien	      && INTVAL (operands[2]) == 255))
629290286Sobrien        return "inc{b}\t%0";
629390286Sobrien      else
6294169699Skan	{
6295169699Skan	  gcc_assert (operands[2] == const1_rtx);
6296169699Skan          return "dec{b}\t%0";
6297169699Skan	}
629850650Sobrien
629990286Sobrien    default:
6300169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
630190286Sobrien      if (INTVAL (operands[2]) < 0)
630290286Sobrien        {
630390286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
630490286Sobrien          return "add{b}\t{%2, %0|%0, %2}";
630590286Sobrien        }
630690286Sobrien      return "sub{b}\t{%2, %0|%0, %2}";
630750650Sobrien    }
630890286Sobrien}
630990286Sobrien  [(set (attr "type")
631090286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
631190286Sobrien	(const_string "incdec")
631290286Sobrien	(const_string "alu")))
631390286Sobrien   (set_attr "mode" "QI")])
631450650Sobrien
631518334Speter
631690286Sobrien(define_insn "*addqi_5"
6317169699Skan  [(set (reg FLAGS_REG)
631890286Sobrien	(compare
631990286Sobrien	  (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
632090286Sobrien		   (match_operand:QI 2 "general_operand" "qmni"))
632190286Sobrien	  (const_int 0)))
632290286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
632390286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
632490286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
632590286Sobrien{
632690286Sobrien  switch (get_attr_type (insn))
632790286Sobrien    {
632890286Sobrien    case TYPE_INCDEC:
632990286Sobrien      if (operands[2] == const1_rtx)
633090286Sobrien	return "inc{b}\t%0";
6331169699Skan      else
6332169699Skan        {
6333169699Skan	  gcc_assert (operands[2] == constm1_rtx
6334169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6335169699Skan			  && INTVAL (operands[2]) == 255));
6336169699Skan	  return "dec{b}\t%0";
6337169699Skan	}
633818334Speter
633990286Sobrien    default:
634090286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
634190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
634290286Sobrien          && INTVAL (operands[2]) < 0)
634390286Sobrien	{
634490286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
634590286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
634690286Sobrien	}
634790286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
634890286Sobrien    }
634990286Sobrien}
635090286Sobrien  [(set (attr "type")
635190286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
635290286Sobrien	(const_string "incdec")
635390286Sobrien	(const_string "alu")))
635490286Sobrien   (set_attr "mode" "QI")])
635518334Speter
635650650Sobrien
635790286Sobrien(define_insn "addqi_ext_1"
635890286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
635990286Sobrien			 (const_int 8)
636090286Sobrien			 (const_int 8))
636190286Sobrien	(plus:SI
636290286Sobrien	  (zero_extract:SI
636390286Sobrien	    (match_operand 1 "ext_register_operand" "0")
636490286Sobrien	    (const_int 8)
636590286Sobrien	    (const_int 8))
636690286Sobrien	  (match_operand:QI 2 "general_operand" "Qmn")))
6367169699Skan   (clobber (reg:CC FLAGS_REG))]
636890286Sobrien  "!TARGET_64BIT"
636918334Speter{
637090286Sobrien  switch (get_attr_type (insn))
637152296Sobrien    {
637290286Sobrien    case TYPE_INCDEC:
637390286Sobrien      if (operands[2] == const1_rtx)
637490286Sobrien	return "inc{b}\t%h0";
6375169699Skan      else
6376169699Skan        {
6377169699Skan	  gcc_assert (operands[2] == constm1_rtx
6378169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6379169699Skan			  && INTVAL (operands[2]) == 255));
6380169699Skan          return "dec{b}\t%h0";
6381169699Skan	}
638252296Sobrien
638390286Sobrien    default:
638490286Sobrien      return "add{b}\t{%2, %h0|%h0, %2}";
638552296Sobrien    }
638690286Sobrien}
638790286Sobrien  [(set (attr "type")
638890286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
638990286Sobrien	(const_string "incdec")
639090286Sobrien	(const_string "alu")))
639190286Sobrien   (set_attr "mode" "QI")])
639218334Speter
639390286Sobrien(define_insn "*addqi_ext_1_rex64"
639490286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
639590286Sobrien			 (const_int 8)
639690286Sobrien			 (const_int 8))
639790286Sobrien	(plus:SI
639890286Sobrien	  (zero_extract:SI
639990286Sobrien	    (match_operand 1 "ext_register_operand" "0")
640090286Sobrien	    (const_int 8)
640190286Sobrien	    (const_int 8))
640290286Sobrien	  (match_operand:QI 2 "nonmemory_operand" "Qn")))
6403169699Skan   (clobber (reg:CC FLAGS_REG))]
640490286Sobrien  "TARGET_64BIT"
640590286Sobrien{
640690286Sobrien  switch (get_attr_type (insn))
640790286Sobrien    {
640890286Sobrien    case TYPE_INCDEC:
640990286Sobrien      if (operands[2] == const1_rtx)
641090286Sobrien	return "inc{b}\t%h0";
6411169699Skan      else
6412169699Skan        {
6413169699Skan	  gcc_assert (operands[2] == constm1_rtx
6414169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6415169699Skan			  && INTVAL (operands[2]) == 255));
6416169699Skan          return "dec{b}\t%h0";
6417169699Skan        }
641818334Speter
641990286Sobrien    default:
642090286Sobrien      return "add{b}\t{%2, %h0|%h0, %2}";
642190286Sobrien    }
642290286Sobrien}
642390286Sobrien  [(set (attr "type")
642490286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
642590286Sobrien	(const_string "incdec")
642690286Sobrien	(const_string "alu")))
642790286Sobrien   (set_attr "mode" "QI")])
642818334Speter
642990286Sobrien(define_insn "*addqi_ext_2"
643090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
643190286Sobrien			 (const_int 8)
643290286Sobrien			 (const_int 8))
643390286Sobrien	(plus:SI
643490286Sobrien	  (zero_extract:SI
643590286Sobrien	    (match_operand 1 "ext_register_operand" "%0")
643690286Sobrien	    (const_int 8)
643790286Sobrien	    (const_int 8))
643890286Sobrien	  (zero_extract:SI
643990286Sobrien	    (match_operand 2 "ext_register_operand" "Q")
644090286Sobrien	    (const_int 8)
644190286Sobrien	    (const_int 8))))
6442169699Skan   (clobber (reg:CC FLAGS_REG))]
644390286Sobrien  ""
644490286Sobrien  "add{b}\t{%h2, %h0|%h0, %h2}"
644590286Sobrien  [(set_attr "type" "alu")
644690286Sobrien   (set_attr "mode" "QI")])
644718334Speter
644818334Speter;; The patterns that match these are at the end of this file.
644918334Speter
645018334Speter(define_expand "addxf3"
645118334Speter  [(set (match_operand:XF 0 "register_operand" "")
645250650Sobrien	(plus:XF (match_operand:XF 1 "register_operand" "")
645350650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
645418334Speter  "TARGET_80387"
645518334Speter  "")
645618334Speter
645718334Speter(define_expand "adddf3"
645818334Speter  [(set (match_operand:DF 0 "register_operand" "")
645990286Sobrien	(plus:DF (match_operand:DF 1 "register_operand" "")
646018334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
646190286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
646218334Speter  "")
646318334Speter
646418334Speter(define_expand "addsf3"
646518334Speter  [(set (match_operand:SF 0 "register_operand" "")
646690286Sobrien	(plus:SF (match_operand:SF 1 "register_operand" "")
646718334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
646890286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
646918334Speter  "")
647018334Speter
647190286Sobrien;; Subtract instructions
647218334Speter
6473169699Skan;; %%% splits for subditi3
6474169699Skan
6475169699Skan(define_expand "subti3"
6476169699Skan  [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
6477169699Skan		   (minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
6478169699Skan			     (match_operand:TI 2 "x86_64_general_operand" "")))
6479169699Skan	      (clobber (reg:CC FLAGS_REG))])]
6480169699Skan  "TARGET_64BIT"
6481169699Skan  "ix86_expand_binary_operator (MINUS, TImode, operands); DONE;")
6482169699Skan
6483169699Skan(define_insn "*subti3_1"
6484169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
6485169699Skan	(minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0")
6486171835Skan		  (match_operand:TI 2 "x86_64_general_operand" "roe,re")))
6487169699Skan   (clobber (reg:CC FLAGS_REG))]
6488169699Skan  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)"
6489169699Skan  "#")
6490169699Skan
6491169699Skan(define_split
6492169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
6493169699Skan	(minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
6494171835Skan		  (match_operand:TI 2 "x86_64_general_operand" "")))
6495169699Skan   (clobber (reg:CC FLAGS_REG))]
6496169699Skan  "TARGET_64BIT && reload_completed"
6497169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
6498169699Skan	      (set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))])
6499169699Skan   (parallel [(set (match_dup 3)
6500169699Skan		   (minus:DI (match_dup 4)
6501169699Skan			     (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
6502169699Skan				      (match_dup 5))))
6503169699Skan	      (clobber (reg:CC FLAGS_REG))])]
6504169699Skan  "split_ti (operands+0, 1, operands+0, operands+3);
6505169699Skan   split_ti (operands+1, 1, operands+1, operands+4);
6506169699Skan   split_ti (operands+2, 1, operands+2, operands+5);")
6507169699Skan
650890286Sobrien;; %%% splits for subsidi3
650950650Sobrien
651090286Sobrien(define_expand "subdi3"
651190286Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
651290286Sobrien		   (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
651390286Sobrien			     (match_operand:DI 2 "x86_64_general_operand" "")))
6514169699Skan	      (clobber (reg:CC FLAGS_REG))])]
651518334Speter  ""
651690286Sobrien  "ix86_expand_binary_operator (MINUS, DImode, operands); DONE;")
651718334Speter
651890286Sobrien(define_insn "*subdi3_1"
651990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
652090286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
652190286Sobrien		  (match_operand:DI 2 "general_operand" "roiF,riF")))
6522169699Skan   (clobber (reg:CC FLAGS_REG))]
6523107605Sobrien  "!TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
652490286Sobrien  "#")
652518334Speter
652690286Sobrien(define_split
652790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
652890286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
652990286Sobrien		  (match_operand:DI 2 "general_operand" "")))
6530169699Skan   (clobber (reg:CC FLAGS_REG))]
653190286Sobrien  "!TARGET_64BIT && reload_completed"
6532169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
653390286Sobrien	      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
653490286Sobrien   (parallel [(set (match_dup 3)
653590286Sobrien		   (minus:SI (match_dup 4)
6536169699Skan			     (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
653790286Sobrien				      (match_dup 5))))
6538169699Skan	      (clobber (reg:CC FLAGS_REG))])]
653990286Sobrien  "split_di (operands+0, 1, operands+0, operands+3);
654090286Sobrien   split_di (operands+1, 1, operands+1, operands+4);
654190286Sobrien   split_di (operands+2, 1, operands+2, operands+5);")
654218334Speter
654390286Sobrien(define_insn "subdi3_carry_rex64"
654490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
654590286Sobrien	  (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
6546132727Skan	    (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
654790286Sobrien	       (match_operand:DI 2 "x86_64_general_operand" "re,rm"))))
6548169699Skan   (clobber (reg:CC FLAGS_REG))]
654990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
655090286Sobrien  "sbb{q}\t{%2, %0|%0, %2}"
655190286Sobrien  [(set_attr "type" "alu")
655290286Sobrien   (set_attr "pent_pair" "pu")
655390286Sobrien   (set_attr "mode" "DI")])
655418334Speter
655590286Sobrien(define_insn "*subdi_1_rex64"
655690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
655790286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
655890286Sobrien		  (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
6559169699Skan   (clobber (reg:CC FLAGS_REG))]
656090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
656190286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
656290286Sobrien  [(set_attr "type" "alu")
656390286Sobrien   (set_attr "mode" "DI")])
656418334Speter
656590286Sobrien(define_insn "*subdi_2_rex64"
6566169699Skan  [(set (reg FLAGS_REG)
656790286Sobrien	(compare
656890286Sobrien	  (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
656990286Sobrien		    (match_operand:DI 2 "x86_64_general_operand" "re,rm"))
657090286Sobrien	  (const_int 0)))
657190286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
657290286Sobrien	(minus:DI (match_dup 1) (match_dup 2)))]
657390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
657490286Sobrien   && ix86_binary_operator_ok (MINUS, DImode, operands)"
657590286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
657690286Sobrien  [(set_attr "type" "alu")
657790286Sobrien   (set_attr "mode" "DI")])
657852296Sobrien
657990286Sobrien(define_insn "*subdi_3_rex63"
6580169699Skan  [(set (reg FLAGS_REG)
658190286Sobrien	(compare (match_operand:DI 1 "nonimmediate_operand" "0,0")
658290286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
658390286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
658490286Sobrien	(minus:DI (match_dup 1) (match_dup 2)))]
658590286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
658690286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
658790286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
658890286Sobrien  [(set_attr "type" "alu")
658990286Sobrien   (set_attr "mode" "DI")])
659018334Speter
6591132727Skan(define_insn "subqi3_carry"
6592132727Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
6593132727Skan	  (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
6594132727Skan	    (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
6595132727Skan	       (match_operand:QI 2 "general_operand" "qi,qm"))))
6596169699Skan   (clobber (reg:CC FLAGS_REG))]
6597132727Skan  "ix86_binary_operator_ok (MINUS, QImode, operands)"
6598132727Skan  "sbb{b}\t{%2, %0|%0, %2}"
6599132727Skan  [(set_attr "type" "alu")
6600132727Skan   (set_attr "pent_pair" "pu")
6601132727Skan   (set_attr "mode" "QI")])
660218334Speter
6603132727Skan(define_insn "subhi3_carry"
6604132727Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
6605132727Skan	  (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
6606132727Skan	    (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
6607132727Skan	       (match_operand:HI 2 "general_operand" "ri,rm"))))
6608169699Skan   (clobber (reg:CC FLAGS_REG))]
6609132727Skan  "ix86_binary_operator_ok (MINUS, HImode, operands)"
6610132727Skan  "sbb{w}\t{%2, %0|%0, %2}"
6611132727Skan  [(set_attr "type" "alu")
6612132727Skan   (set_attr "pent_pair" "pu")
6613132727Skan   (set_attr "mode" "HI")])
6614132727Skan
661590286Sobrien(define_insn "subsi3_carry"
661690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
661790286Sobrien	  (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6618132727Skan	    (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
661990286Sobrien	       (match_operand:SI 2 "general_operand" "ri,rm"))))
6620169699Skan   (clobber (reg:CC FLAGS_REG))]
662190286Sobrien  "ix86_binary_operator_ok (MINUS, SImode, operands)"
662290286Sobrien  "sbb{l}\t{%2, %0|%0, %2}"
662390286Sobrien  [(set_attr "type" "alu")
662490286Sobrien   (set_attr "pent_pair" "pu")
662590286Sobrien   (set_attr "mode" "SI")])
662618334Speter
662790286Sobrien(define_insn "subsi3_carry_zext"
662890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm,r")
662990286Sobrien	  (zero_extend:DI
663090286Sobrien	    (minus:SI (match_operand:SI 1 "register_operand" "0,0")
6631132727Skan	      (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
663290286Sobrien		 (match_operand:SI 2 "general_operand" "ri,rm")))))
6633169699Skan   (clobber (reg:CC FLAGS_REG))]
663490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
663590286Sobrien  "sbb{l}\t{%2, %k0|%k0, %2}"
663690286Sobrien  [(set_attr "type" "alu")
663790286Sobrien   (set_attr "pent_pair" "pu")
663890286Sobrien   (set_attr "mode" "SI")])
663918334Speter
664050650Sobrien(define_expand "subsi3"
664190286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
664290286Sobrien		   (minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
664390286Sobrien			     (match_operand:SI 2 "general_operand" "")))
6644169699Skan	      (clobber (reg:CC FLAGS_REG))])]
664550650Sobrien  ""
664690286Sobrien  "ix86_expand_binary_operator (MINUS, SImode, operands); DONE;")
664750650Sobrien
664890286Sobrien(define_insn "*subsi_1"
664950650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
665050650Sobrien	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
665190286Sobrien		  (match_operand:SI 2 "general_operand" "ri,rm")))
6652169699Skan   (clobber (reg:CC FLAGS_REG))]
665350650Sobrien  "ix86_binary_operator_ok (MINUS, SImode, operands)"
665490286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
665590286Sobrien  [(set_attr "type" "alu")
665690286Sobrien   (set_attr "mode" "SI")])
665718334Speter
665890286Sobrien(define_insn "*subsi_1_zext"
665990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
666090286Sobrien	(zero_extend:DI
666190286Sobrien	  (minus:SI (match_operand:SI 1 "register_operand" "0")
666290286Sobrien		    (match_operand:SI 2 "general_operand" "rim"))))
6663169699Skan   (clobber (reg:CC FLAGS_REG))]
666490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
666590286Sobrien  "sub{l}\t{%2, %k0|%k0, %2}"
666690286Sobrien  [(set_attr "type" "alu")
666790286Sobrien   (set_attr "mode" "SI")])
666890286Sobrien
666990286Sobrien(define_insn "*subsi_2"
6670169699Skan  [(set (reg FLAGS_REG)
667190286Sobrien	(compare
667290286Sobrien	  (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
667390286Sobrien		    (match_operand:SI 2 "general_operand" "ri,rm"))
667490286Sobrien	  (const_int 0)))
667590286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
667690286Sobrien	(minus:SI (match_dup 1) (match_dup 2)))]
667790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
667890286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
667990286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
668090286Sobrien  [(set_attr "type" "alu")
668190286Sobrien   (set_attr "mode" "SI")])
668290286Sobrien
668390286Sobrien(define_insn "*subsi_2_zext"
6684169699Skan  [(set (reg FLAGS_REG)
668590286Sobrien	(compare
668690286Sobrien	  (minus:SI (match_operand:SI 1 "register_operand" "0")
668790286Sobrien		    (match_operand:SI 2 "general_operand" "rim"))
668890286Sobrien	  (const_int 0)))
668990286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
669090286Sobrien	(zero_extend:DI
669190286Sobrien	  (minus:SI (match_dup 1)
669290286Sobrien		    (match_dup 2))))]
669390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
669490286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
669590286Sobrien  "sub{l}\t{%2, %k0|%k0, %2}"
669690286Sobrien  [(set_attr "type" "alu")
669790286Sobrien   (set_attr "mode" "SI")])
669890286Sobrien
669990286Sobrien(define_insn "*subsi_3"
6700169699Skan  [(set (reg FLAGS_REG)
670190286Sobrien	(compare (match_operand:SI 1 "nonimmediate_operand" "0,0")
670290286Sobrien		 (match_operand:SI 2 "general_operand" "ri,rm")))
670390286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
670490286Sobrien	(minus:SI (match_dup 1) (match_dup 2)))]
670590286Sobrien  "ix86_match_ccmode (insn, CCmode)
670690286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
670790286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
670890286Sobrien  [(set_attr "type" "alu")
670990286Sobrien   (set_attr "mode" "SI")])
671090286Sobrien
671190286Sobrien(define_insn "*subsi_3_zext"
6712169699Skan  [(set (reg FLAGS_REG)
6713132727Skan	(compare (match_operand:SI 1 "register_operand" "0")
671490286Sobrien		 (match_operand:SI 2 "general_operand" "rim")))
671590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
671690286Sobrien	(zero_extend:DI
671790286Sobrien	  (minus:SI (match_dup 1)
671890286Sobrien		    (match_dup 2))))]
671990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
672090286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
6721169699Skan  "sub{l}\t{%2, %1|%1, %2}"
672290286Sobrien  [(set_attr "type" "alu")
672390286Sobrien   (set_attr "mode" "DI")])
672490286Sobrien
672550650Sobrien(define_expand "subhi3"
672690286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
672790286Sobrien		   (minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
672890286Sobrien			     (match_operand:HI 2 "general_operand" "")))
6729169699Skan	      (clobber (reg:CC FLAGS_REG))])]
673090286Sobrien  "TARGET_HIMODE_MATH"
673190286Sobrien  "ix86_expand_binary_operator (MINUS, HImode, operands); DONE;")
673250650Sobrien
673390286Sobrien(define_insn "*subhi_1"
673450650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
673550650Sobrien	(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
673690286Sobrien		  (match_operand:HI 2 "general_operand" "ri,rm")))
6737169699Skan   (clobber (reg:CC FLAGS_REG))]
673850650Sobrien  "ix86_binary_operator_ok (MINUS, HImode, operands)"
673990286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
674090286Sobrien  [(set_attr "type" "alu")
674190286Sobrien   (set_attr "mode" "HI")])
674250650Sobrien
674390286Sobrien(define_insn "*subhi_2"
6744169699Skan  [(set (reg FLAGS_REG)
674590286Sobrien	(compare
674690286Sobrien	  (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
674790286Sobrien		    (match_operand:HI 2 "general_operand" "ri,rm"))
674890286Sobrien	  (const_int 0)))
674990286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
675090286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
675190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
675290286Sobrien   && ix86_binary_operator_ok (MINUS, HImode, operands)"
675390286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
675490286Sobrien  [(set_attr "type" "alu")
675590286Sobrien   (set_attr "mode" "HI")])
675690286Sobrien
675790286Sobrien(define_insn "*subhi_3"
6758169699Skan  [(set (reg FLAGS_REG)
675990286Sobrien	(compare (match_operand:HI 1 "nonimmediate_operand" "0,0")
676090286Sobrien		 (match_operand:HI 2 "general_operand" "ri,rm")))
676190286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
676290286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
676390286Sobrien  "ix86_match_ccmode (insn, CCmode)
676490286Sobrien   && ix86_binary_operator_ok (MINUS, HImode, operands)"
676590286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
676690286Sobrien  [(set_attr "type" "alu")
676790286Sobrien   (set_attr "mode" "HI")])
676890286Sobrien
676950650Sobrien(define_expand "subqi3"
677090286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
677190286Sobrien		   (minus:QI (match_operand:QI 1 "nonimmediate_operand" "")
677290286Sobrien			     (match_operand:QI 2 "general_operand" "")))
6773169699Skan	      (clobber (reg:CC FLAGS_REG))])]
677490286Sobrien  "TARGET_QIMODE_MATH"
677590286Sobrien  "ix86_expand_binary_operator (MINUS, QImode, operands); DONE;")
677618334Speter
677790286Sobrien(define_insn "*subqi_1"
677850650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
677950650Sobrien	(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
678090286Sobrien		  (match_operand:QI 2 "general_operand" "qn,qmn")))
6781169699Skan   (clobber (reg:CC FLAGS_REG))]
678250650Sobrien  "ix86_binary_operator_ok (MINUS, QImode, operands)"
678390286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
678490286Sobrien  [(set_attr "type" "alu")
678590286Sobrien   (set_attr "mode" "QI")])
678618334Speter
6787117404Skan(define_insn "*subqi_1_slp"
6788117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
6789117404Skan	(minus:QI (match_dup 0)
6790117404Skan		  (match_operand:QI 1 "general_operand" "qn,qmn")))
6791169699Skan   (clobber (reg:CC FLAGS_REG))]
6792117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
6793117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
6794117404Skan  "sub{b}\t{%1, %0|%0, %1}"
6795117404Skan  [(set_attr "type" "alu1")
6796117404Skan   (set_attr "mode" "QI")])
6797117404Skan
679890286Sobrien(define_insn "*subqi_2"
6799169699Skan  [(set (reg FLAGS_REG)
680090286Sobrien	(compare
680190286Sobrien	  (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
680290286Sobrien		    (match_operand:QI 2 "general_operand" "qi,qm"))
680390286Sobrien	  (const_int 0)))
680490286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
680590286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
680690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
680790286Sobrien   && ix86_binary_operator_ok (MINUS, QImode, operands)"
680890286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
680990286Sobrien  [(set_attr "type" "alu")
681090286Sobrien   (set_attr "mode" "QI")])
681190286Sobrien
681290286Sobrien(define_insn "*subqi_3"
6813169699Skan  [(set (reg FLAGS_REG)
681490286Sobrien	(compare (match_operand:QI 1 "nonimmediate_operand" "0,0")
681590286Sobrien		 (match_operand:QI 2 "general_operand" "qi,qm")))
681690286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
681790286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
681890286Sobrien  "ix86_match_ccmode (insn, CCmode)
681990286Sobrien   && ix86_binary_operator_ok (MINUS, QImode, operands)"
682090286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
682190286Sobrien  [(set_attr "type" "alu")
682290286Sobrien   (set_attr "mode" "QI")])
682390286Sobrien
682418334Speter;; The patterns that match these are at the end of this file.
682518334Speter
682618334Speter(define_expand "subxf3"
682718334Speter  [(set (match_operand:XF 0 "register_operand" "")
682850650Sobrien	(minus:XF (match_operand:XF 1 "register_operand" "")
682950650Sobrien		  (match_operand:XF 2 "register_operand" "")))]
683018334Speter  "TARGET_80387"
683118334Speter  "")
683218334Speter
683318334Speter(define_expand "subdf3"
683418334Speter  [(set (match_operand:DF 0 "register_operand" "")
683590286Sobrien	(minus:DF (match_operand:DF 1 "register_operand" "")
683618334Speter		  (match_operand:DF 2 "nonimmediate_operand" "")))]
683790286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
683818334Speter  "")
683918334Speter
684018334Speter(define_expand "subsf3"
684118334Speter  [(set (match_operand:SF 0 "register_operand" "")
684290286Sobrien	(minus:SF (match_operand:SF 1 "register_operand" "")
684318334Speter		  (match_operand:SF 2 "nonimmediate_operand" "")))]
684490286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
684518334Speter  "")
684618334Speter
684790286Sobrien;; Multiply instructions
684818334Speter
684990286Sobrien(define_expand "muldi3"
685090286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
685190286Sobrien		   (mult:DI (match_operand:DI 1 "register_operand" "")
685290286Sobrien			    (match_operand:DI 2 "x86_64_general_operand" "")))
6853169699Skan	      (clobber (reg:CC FLAGS_REG))])]
685490286Sobrien  "TARGET_64BIT"
685590286Sobrien  "")
685618334Speter
685790286Sobrien(define_insn "*muldi3_1_rex64"
685890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6859132727Skan	(mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,rm,0")
686090286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "K,e,mr")))
6861169699Skan   (clobber (reg:CC FLAGS_REG))]
686290286Sobrien  "TARGET_64BIT
686390286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
686490286Sobrien  "@
686590286Sobrien   imul{q}\t{%2, %1, %0|%0, %1, %2}
686690286Sobrien   imul{q}\t{%2, %1, %0|%0, %1, %2}
686790286Sobrien   imul{q}\t{%2, %0|%0, %2}"
686890286Sobrien  [(set_attr "type" "imul")
686990286Sobrien   (set_attr "prefix_0f" "0,0,1")
6870132727Skan   (set (attr "athlon_decode")
6871132727Skan	(cond [(eq_attr "cpu" "athlon")
6872132727Skan		  (const_string "vector")
6873132727Skan	       (eq_attr "alternative" "1")
6874132727Skan		  (const_string "vector")
6875132727Skan	       (and (eq_attr "alternative" "2")
6876132727Skan		    (match_operand 1 "memory_operand" ""))
6877132727Skan		  (const_string "vector")]
6878132727Skan	      (const_string "direct")))
687990286Sobrien   (set_attr "mode" "DI")])
688018334Speter
688190286Sobrien(define_expand "mulsi3"
688290286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
688390286Sobrien		   (mult:SI (match_operand:SI 1 "register_operand" "")
688490286Sobrien			    (match_operand:SI 2 "general_operand" "")))
6885169699Skan	      (clobber (reg:CC FLAGS_REG))])]
688618334Speter  ""
688790286Sobrien  "")
688818334Speter
688990286Sobrien(define_insn "*mulsi3_1"
689090286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
6891132727Skan	(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
689290286Sobrien		 (match_operand:SI 2 "general_operand" "K,i,mr")))
6893169699Skan   (clobber (reg:CC FLAGS_REG))]
689490286Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
689590286Sobrien  "@
689690286Sobrien   imul{l}\t{%2, %1, %0|%0, %1, %2}
689790286Sobrien   imul{l}\t{%2, %1, %0|%0, %1, %2}
689890286Sobrien   imul{l}\t{%2, %0|%0, %2}"
689990286Sobrien  [(set_attr "type" "imul")
690090286Sobrien   (set_attr "prefix_0f" "0,0,1")
6901132727Skan   (set (attr "athlon_decode")
6902132727Skan	(cond [(eq_attr "cpu" "athlon")
6903132727Skan		  (const_string "vector")
6904132727Skan	       (eq_attr "alternative" "1")
6905132727Skan		  (const_string "vector")
6906132727Skan	       (and (eq_attr "alternative" "2")
6907132727Skan		    (match_operand 1 "memory_operand" ""))
6908132727Skan		  (const_string "vector")]
6909132727Skan	      (const_string "direct")))
691090286Sobrien   (set_attr "mode" "SI")])
691190286Sobrien
691290286Sobrien(define_insn "*mulsi3_1_zext"
691390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
691490286Sobrien	(zero_extend:DI
6915132727Skan	  (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
691690286Sobrien		   (match_operand:SI 2 "general_operand" "K,i,mr"))))
6917169699Skan   (clobber (reg:CC FLAGS_REG))]
691890286Sobrien  "TARGET_64BIT
691990286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
692090286Sobrien  "@
692190286Sobrien   imul{l}\t{%2, %1, %k0|%k0, %1, %2}
692290286Sobrien   imul{l}\t{%2, %1, %k0|%k0, %1, %2}
692390286Sobrien   imul{l}\t{%2, %k0|%k0, %2}"
692490286Sobrien  [(set_attr "type" "imul")
692590286Sobrien   (set_attr "prefix_0f" "0,0,1")
6926132727Skan   (set (attr "athlon_decode")
6927132727Skan	(cond [(eq_attr "cpu" "athlon")
6928132727Skan		  (const_string "vector")
6929132727Skan	       (eq_attr "alternative" "1")
6930132727Skan		  (const_string "vector")
6931132727Skan	       (and (eq_attr "alternative" "2")
6932132727Skan		    (match_operand 1 "memory_operand" ""))
6933132727Skan		  (const_string "vector")]
6934132727Skan	      (const_string "direct")))
693590286Sobrien   (set_attr "mode" "SI")])
693690286Sobrien
693790286Sobrien(define_expand "mulhi3"
693890286Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
693990286Sobrien		   (mult:HI (match_operand:HI 1 "register_operand" "")
694090286Sobrien			    (match_operand:HI 2 "general_operand" "")))
6941169699Skan	      (clobber (reg:CC FLAGS_REG))])]
694290286Sobrien  "TARGET_HIMODE_MATH"
694390286Sobrien  "")
694490286Sobrien
694590286Sobrien(define_insn "*mulhi3_1"
694690286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
6947132727Skan	(mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rm,rm,0")
694890286Sobrien		 (match_operand:HI 2 "general_operand" "K,i,mr")))
6949169699Skan   (clobber (reg:CC FLAGS_REG))]
695090286Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
695190286Sobrien  "@
695290286Sobrien   imul{w}\t{%2, %1, %0|%0, %1, %2}
695390286Sobrien   imul{w}\t{%2, %1, %0|%0, %1, %2}
695490286Sobrien   imul{w}\t{%2, %0|%0, %2}"
695590286Sobrien  [(set_attr "type" "imul")
695690286Sobrien   (set_attr "prefix_0f" "0,0,1")
6957132727Skan   (set (attr "athlon_decode")
6958132727Skan	(cond [(eq_attr "cpu" "athlon")
6959132727Skan		  (const_string "vector")
6960132727Skan	       (eq_attr "alternative" "1,2")
6961132727Skan		  (const_string "vector")]
6962132727Skan	      (const_string "direct")))
696390286Sobrien   (set_attr "mode" "HI")])
696490286Sobrien
696596294Sobrien(define_expand "mulqi3"
696696294Sobrien  [(parallel [(set (match_operand:QI 0 "register_operand" "")
696796294Sobrien		   (mult:QI (match_operand:QI 1 "nonimmediate_operand" "")
696896294Sobrien			    (match_operand:QI 2 "register_operand" "")))
6969169699Skan	      (clobber (reg:CC FLAGS_REG))])]
697096294Sobrien  "TARGET_QIMODE_MATH"
697196294Sobrien  "")
697296294Sobrien
697396294Sobrien(define_insn "*mulqi3_1"
697490286Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
697596294Sobrien	(mult:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
697690286Sobrien		 (match_operand:QI 2 "nonimmediate_operand" "qm")))
6977169699Skan   (clobber (reg:CC FLAGS_REG))]
697896294Sobrien  "TARGET_QIMODE_MATH
697996294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
698090286Sobrien  "mul{b}\t%2"
698190286Sobrien  [(set_attr "type" "imul")
698290286Sobrien   (set_attr "length_immediate" "0")
6983132727Skan   (set (attr "athlon_decode")
6984132727Skan     (if_then_else (eq_attr "cpu" "athlon")
6985132727Skan        (const_string "vector")
6986132727Skan        (const_string "direct")))
698790286Sobrien   (set_attr "mode" "QI")])
698890286Sobrien
698996294Sobrien(define_expand "umulqihi3"
699096294Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
699196294Sobrien		   (mult:HI (zero_extend:HI
699296294Sobrien			      (match_operand:QI 1 "nonimmediate_operand" ""))
699396294Sobrien			    (zero_extend:HI
699496294Sobrien			      (match_operand:QI 2 "register_operand" ""))))
6995169699Skan	      (clobber (reg:CC FLAGS_REG))])]
699696294Sobrien  "TARGET_QIMODE_MATH"
699796294Sobrien  "")
699896294Sobrien
699996294Sobrien(define_insn "*umulqihi3_1"
700050650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
700196294Sobrien	(mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
700290286Sobrien		 (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
7003169699Skan   (clobber (reg:CC FLAGS_REG))]
700496294Sobrien  "TARGET_QIMODE_MATH
700596294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
700690286Sobrien  "mul{b}\t%2"
700790286Sobrien  [(set_attr "type" "imul")
700890286Sobrien   (set_attr "length_immediate" "0")
7009132727Skan   (set (attr "athlon_decode")
7010132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7011132727Skan        (const_string "vector")
7012132727Skan        (const_string "direct")))
701390286Sobrien   (set_attr "mode" "QI")])
701418334Speter
701596294Sobrien(define_expand "mulqihi3"
701696294Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
701796294Sobrien		   (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))
701896294Sobrien			    (sign_extend:HI (match_operand:QI 2 "register_operand" ""))))
7019169699Skan	      (clobber (reg:CC FLAGS_REG))])]
702096294Sobrien  "TARGET_QIMODE_MATH"
702196294Sobrien  "")
702296294Sobrien
702396294Sobrien(define_insn "*mulqihi3_insn"
702450650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
702596294Sobrien	(mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
702690286Sobrien		 (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
7027169699Skan   (clobber (reg:CC FLAGS_REG))]
702896294Sobrien  "TARGET_QIMODE_MATH
702996294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
703090286Sobrien  "imul{b}\t%2"
703190286Sobrien  [(set_attr "type" "imul")
703290286Sobrien   (set_attr "length_immediate" "0")
7033132727Skan   (set (attr "athlon_decode")
7034132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7035132727Skan        (const_string "vector")
7036132727Skan        (const_string "direct")))
703790286Sobrien   (set_attr "mode" "QI")])
703818334Speter
703996294Sobrien(define_expand "umulditi3"
704096294Sobrien  [(parallel [(set (match_operand:TI 0 "register_operand" "")
704196294Sobrien		   (mult:TI (zero_extend:TI
704296294Sobrien			      (match_operand:DI 1 "nonimmediate_operand" ""))
704396294Sobrien			    (zero_extend:TI
704496294Sobrien			      (match_operand:DI 2 "register_operand" ""))))
7045169699Skan	      (clobber (reg:CC FLAGS_REG))])]
704696294Sobrien  "TARGET_64BIT"
704796294Sobrien  "")
704896294Sobrien
704996294Sobrien(define_insn "*umulditi3_insn"
705090286Sobrien  [(set (match_operand:TI 0 "register_operand" "=A")
705196294Sobrien	(mult:TI (zero_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
705290286Sobrien		 (zero_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
7053169699Skan   (clobber (reg:CC FLAGS_REG))]
705496294Sobrien  "TARGET_64BIT
705596294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
705690286Sobrien  "mul{q}\t%2"
705790286Sobrien  [(set_attr "type" "imul")
705890286Sobrien   (set_attr "length_immediate" "0")
7059132727Skan   (set (attr "athlon_decode")
7060132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7061132727Skan        (const_string "vector")
7062132727Skan        (const_string "double")))
706390286Sobrien   (set_attr "mode" "DI")])
706490286Sobrien
706590286Sobrien;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers
706696294Sobrien(define_expand "umulsidi3"
706796294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
706896294Sobrien		   (mult:DI (zero_extend:DI
706996294Sobrien			      (match_operand:SI 1 "nonimmediate_operand" ""))
707096294Sobrien			    (zero_extend:DI
707196294Sobrien			      (match_operand:SI 2 "register_operand" ""))))
7072169699Skan	      (clobber (reg:CC FLAGS_REG))])]
707396294Sobrien  "!TARGET_64BIT"
707496294Sobrien  "")
707596294Sobrien
707696294Sobrien(define_insn "*umulsidi3_insn"
707718334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
707896294Sobrien	(mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
707990286Sobrien		 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
7080169699Skan   (clobber (reg:CC FLAGS_REG))]
708196294Sobrien  "!TARGET_64BIT
708296294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
708390286Sobrien  "mul{l}\t%2"
708490286Sobrien  [(set_attr "type" "imul")
708590286Sobrien   (set_attr "length_immediate" "0")
7086132727Skan   (set (attr "athlon_decode")
7087132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7088132727Skan        (const_string "vector")
7089132727Skan        (const_string "double")))
709090286Sobrien   (set_attr "mode" "SI")])
709118334Speter
709296294Sobrien(define_expand "mulditi3"
709396294Sobrien  [(parallel [(set (match_operand:TI 0 "register_operand" "")
709496294Sobrien		   (mult:TI (sign_extend:TI
709596294Sobrien			      (match_operand:DI 1 "nonimmediate_operand" ""))
709696294Sobrien			    (sign_extend:TI
709796294Sobrien			      (match_operand:DI 2 "register_operand" ""))))
7098169699Skan	      (clobber (reg:CC FLAGS_REG))])]
709996294Sobrien  "TARGET_64BIT"
710096294Sobrien  "")
710196294Sobrien
710296294Sobrien(define_insn "*mulditi3_insn"
710390286Sobrien  [(set (match_operand:TI 0 "register_operand" "=A")
710496294Sobrien	(mult:TI (sign_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
710590286Sobrien		 (sign_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
7106169699Skan   (clobber (reg:CC FLAGS_REG))]
710796294Sobrien  "TARGET_64BIT
710896294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
710990286Sobrien  "imul{q}\t%2"
711090286Sobrien  [(set_attr "type" "imul")
711190286Sobrien   (set_attr "length_immediate" "0")
7112132727Skan   (set (attr "athlon_decode")
7113132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7114132727Skan        (const_string "vector")
7115132727Skan        (const_string "double")))
711690286Sobrien   (set_attr "mode" "DI")])
711790286Sobrien
711896294Sobrien(define_expand "mulsidi3"
711996294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
712096294Sobrien		   (mult:DI (sign_extend:DI
712196294Sobrien			      (match_operand:SI 1 "nonimmediate_operand" ""))
712296294Sobrien			    (sign_extend:DI
712396294Sobrien			      (match_operand:SI 2 "register_operand" ""))))
7124169699Skan	      (clobber (reg:CC FLAGS_REG))])]
712596294Sobrien  "!TARGET_64BIT"
712696294Sobrien  "")
712796294Sobrien
712896294Sobrien(define_insn "*mulsidi3_insn"
712918334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
713096294Sobrien	(mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
713190286Sobrien		 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
7132169699Skan   (clobber (reg:CC FLAGS_REG))]
713396294Sobrien  "!TARGET_64BIT
713496294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
713590286Sobrien  "imul{l}\t%2"
713690286Sobrien  [(set_attr "type" "imul")
713790286Sobrien   (set_attr "length_immediate" "0")
7138132727Skan   (set (attr "athlon_decode")
7139132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7140132727Skan        (const_string "vector")
7141132727Skan        (const_string "double")))
714290286Sobrien   (set_attr "mode" "SI")])
714318334Speter
714496294Sobrien(define_expand "umuldi3_highpart"
714596294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
714696294Sobrien		   (truncate:DI
714796294Sobrien		     (lshiftrt:TI
714896294Sobrien		       (mult:TI (zero_extend:TI
714996294Sobrien				  (match_operand:DI 1 "nonimmediate_operand" ""))
715096294Sobrien				(zero_extend:TI
715196294Sobrien				  (match_operand:DI 2 "register_operand" "")))
715296294Sobrien		       (const_int 64))))
715396294Sobrien	      (clobber (match_scratch:DI 3 ""))
7154169699Skan	      (clobber (reg:CC FLAGS_REG))])]
715596294Sobrien  "TARGET_64BIT"
715696294Sobrien  "")
715796294Sobrien
715890286Sobrien(define_insn "*umuldi3_highpart_rex64"
715990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
716090286Sobrien	(truncate:DI
716190286Sobrien	  (lshiftrt:TI
716290286Sobrien	    (mult:TI (zero_extend:TI
716396294Sobrien		       (match_operand:DI 1 "nonimmediate_operand" "%a"))
716490286Sobrien		     (zero_extend:TI
716590286Sobrien		       (match_operand:DI 2 "nonimmediate_operand" "rm")))
716690286Sobrien	    (const_int 64))))
716796294Sobrien   (clobber (match_scratch:DI 3 "=1"))
7168169699Skan   (clobber (reg:CC FLAGS_REG))]
716996294Sobrien  "TARGET_64BIT
717096294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
717190286Sobrien  "mul{q}\t%2"
717290286Sobrien  [(set_attr "type" "imul")
717390286Sobrien   (set_attr "length_immediate" "0")
7174132727Skan   (set (attr "athlon_decode")
7175132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7176132727Skan        (const_string "vector")
7177132727Skan        (const_string "double")))
717890286Sobrien   (set_attr "mode" "DI")])
717990286Sobrien
718096294Sobrien(define_expand "umulsi3_highpart"
718196294Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
718296294Sobrien		   (truncate:SI
718396294Sobrien		     (lshiftrt:DI
718496294Sobrien		       (mult:DI (zero_extend:DI
718596294Sobrien				  (match_operand:SI 1 "nonimmediate_operand" ""))
718696294Sobrien				(zero_extend:DI
718796294Sobrien				  (match_operand:SI 2 "register_operand" "")))
718896294Sobrien		       (const_int 32))))
718996294Sobrien	      (clobber (match_scratch:SI 3 ""))
7190169699Skan	      (clobber (reg:CC FLAGS_REG))])]
719196294Sobrien  ""
719296294Sobrien  "")
719396294Sobrien
719496294Sobrien(define_insn "*umulsi3_highpart_insn"
719518334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
719690286Sobrien	(truncate:SI
719790286Sobrien	  (lshiftrt:DI
719890286Sobrien	    (mult:DI (zero_extend:DI
719996294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
720090286Sobrien		     (zero_extend:DI
720190286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
720290286Sobrien	    (const_int 32))))
720396294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7204169699Skan   (clobber (reg:CC FLAGS_REG))]
720596294Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
720690286Sobrien  "mul{l}\t%2"
720790286Sobrien  [(set_attr "type" "imul")
720890286Sobrien   (set_attr "length_immediate" "0")
7209132727Skan   (set (attr "athlon_decode")
7210132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7211132727Skan        (const_string "vector")
7212132727Skan        (const_string "double")))
721390286Sobrien   (set_attr "mode" "SI")])
721418334Speter
721590286Sobrien(define_insn "*umulsi3_highpart_zext"
721690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
721790286Sobrien	(zero_extend:DI (truncate:SI
721890286Sobrien	  (lshiftrt:DI
721990286Sobrien	    (mult:DI (zero_extend:DI
722096294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
722190286Sobrien		     (zero_extend:DI
722290286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
722390286Sobrien	    (const_int 32)))))
722496294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7225169699Skan   (clobber (reg:CC FLAGS_REG))]
722696294Sobrien  "TARGET_64BIT
722796294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
722890286Sobrien  "mul{l}\t%2"
722990286Sobrien  [(set_attr "type" "imul")
723090286Sobrien   (set_attr "length_immediate" "0")
7231132727Skan   (set (attr "athlon_decode")
7232132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7233132727Skan        (const_string "vector")
7234132727Skan        (const_string "double")))
723590286Sobrien   (set_attr "mode" "SI")])
723690286Sobrien
723796294Sobrien(define_expand "smuldi3_highpart"
723896294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "=d")
723996294Sobrien		   (truncate:DI
724096294Sobrien		     (lshiftrt:TI
724196294Sobrien		       (mult:TI (sign_extend:TI
724296294Sobrien				  (match_operand:DI 1 "nonimmediate_operand" ""))
724396294Sobrien				(sign_extend:TI
724496294Sobrien				  (match_operand:DI 2 "register_operand" "")))
724596294Sobrien		       (const_int 64))))
724696294Sobrien	      (clobber (match_scratch:DI 3 ""))
7247169699Skan	      (clobber (reg:CC FLAGS_REG))])]
724896294Sobrien  "TARGET_64BIT"
724996294Sobrien  "")
725096294Sobrien
725190286Sobrien(define_insn "*smuldi3_highpart_rex64"
725290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
725390286Sobrien	(truncate:DI
725490286Sobrien	  (lshiftrt:TI
725590286Sobrien	    (mult:TI (sign_extend:TI
725696294Sobrien		       (match_operand:DI 1 "nonimmediate_operand" "%a"))
725790286Sobrien		     (sign_extend:TI
725890286Sobrien		       (match_operand:DI 2 "nonimmediate_operand" "rm")))
725990286Sobrien	    (const_int 64))))
726096294Sobrien   (clobber (match_scratch:DI 3 "=1"))
7261169699Skan   (clobber (reg:CC FLAGS_REG))]
726296294Sobrien  "TARGET_64BIT
726396294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
726490286Sobrien  "imul{q}\t%2"
726590286Sobrien  [(set_attr "type" "imul")
7266132727Skan   (set (attr "athlon_decode")
7267132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7268132727Skan        (const_string "vector")
7269132727Skan        (const_string "double")))
727090286Sobrien   (set_attr "mode" "DI")])
727190286Sobrien
727296294Sobrien(define_expand "smulsi3_highpart"
727396294Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
727496294Sobrien		   (truncate:SI
727596294Sobrien		     (lshiftrt:DI
727696294Sobrien		       (mult:DI (sign_extend:DI
727796294Sobrien				  (match_operand:SI 1 "nonimmediate_operand" ""))
727896294Sobrien				(sign_extend:DI
727996294Sobrien				  (match_operand:SI 2 "register_operand" "")))
728096294Sobrien		       (const_int 32))))
728196294Sobrien	      (clobber (match_scratch:SI 3 ""))
7282169699Skan	      (clobber (reg:CC FLAGS_REG))])]
728396294Sobrien  ""
728496294Sobrien  "")
728596294Sobrien
728696294Sobrien(define_insn "*smulsi3_highpart_insn"
728718334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
728890286Sobrien	(truncate:SI
728990286Sobrien	  (lshiftrt:DI
729090286Sobrien	    (mult:DI (sign_extend:DI
729196294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
729290286Sobrien		     (sign_extend:DI
729390286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
729490286Sobrien	    (const_int 32))))
729596294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7296169699Skan   (clobber (reg:CC FLAGS_REG))]
729796294Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
729890286Sobrien  "imul{l}\t%2"
729990286Sobrien  [(set_attr "type" "imul")
7300132727Skan   (set (attr "athlon_decode")
7301132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7302132727Skan        (const_string "vector")
7303132727Skan        (const_string "double")))
730490286Sobrien   (set_attr "mode" "SI")])
730518334Speter
730690286Sobrien(define_insn "*smulsi3_highpart_zext"
730790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
730890286Sobrien	(zero_extend:DI (truncate:SI
730990286Sobrien	  (lshiftrt:DI
731090286Sobrien	    (mult:DI (sign_extend:DI
731196294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
731290286Sobrien		     (sign_extend:DI
731390286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
731490286Sobrien	    (const_int 32)))))
731596294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7316169699Skan   (clobber (reg:CC FLAGS_REG))]
731796294Sobrien  "TARGET_64BIT
731896294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
731990286Sobrien  "imul{l}\t%2"
732090286Sobrien  [(set_attr "type" "imul")
7321132727Skan   (set (attr "athlon_decode")
7322132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7323132727Skan        (const_string "vector")
7324132727Skan        (const_string "double")))
732590286Sobrien   (set_attr "mode" "SI")])
732690286Sobrien
732718334Speter;; The patterns that match these are at the end of this file.
732818334Speter
732918334Speter(define_expand "mulxf3"
733018334Speter  [(set (match_operand:XF 0 "register_operand" "")
733150650Sobrien	(mult:XF (match_operand:XF 1 "register_operand" "")
733250650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
733318334Speter  "TARGET_80387"
733418334Speter  "")
733518334Speter
733618334Speter(define_expand "muldf3"
733718334Speter  [(set (match_operand:DF 0 "register_operand" "")
733850650Sobrien	(mult:DF (match_operand:DF 1 "register_operand" "")
733918334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
734090286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
734118334Speter  "")
734218334Speter
734318334Speter(define_expand "mulsf3"
734418334Speter  [(set (match_operand:SF 0 "register_operand" "")
734550650Sobrien	(mult:SF (match_operand:SF 1 "register_operand" "")
734618334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
734790286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
734818334Speter  "")
734918334Speter
735090286Sobrien;; Divide instructions
735118334Speter
735218334Speter(define_insn "divqi3"
735350650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
735450650Sobrien	(div:QI (match_operand:HI 1 "register_operand" "0")
735590286Sobrien		(match_operand:QI 2 "nonimmediate_operand" "qm")))
7356169699Skan   (clobber (reg:CC FLAGS_REG))]
735790286Sobrien  "TARGET_QIMODE_MATH"
735890286Sobrien  "idiv{b}\t%2"
735990286Sobrien  [(set_attr "type" "idiv")
7360169699Skan   (set_attr "mode" "QI")])
736118334Speter
736218334Speter(define_insn "udivqi3"
736350650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
736450650Sobrien	(udiv:QI (match_operand:HI 1 "register_operand" "0")
736590286Sobrien		 (match_operand:QI 2 "nonimmediate_operand" "qm")))
7366169699Skan   (clobber (reg:CC FLAGS_REG))]
736790286Sobrien  "TARGET_QIMODE_MATH"
736890286Sobrien  "div{b}\t%2"
736990286Sobrien  [(set_attr "type" "idiv")
7370169699Skan   (set_attr "mode" "QI")])
737118334Speter
737218334Speter;; The patterns that match these are at the end of this file.
737318334Speter
737418334Speter(define_expand "divxf3"
737518334Speter  [(set (match_operand:XF 0 "register_operand" "")
737650650Sobrien	(div:XF (match_operand:XF 1 "register_operand" "")
737750650Sobrien		(match_operand:XF 2 "register_operand" "")))]
737818334Speter  "TARGET_80387"
737918334Speter  "")
738018334Speter
738118334Speter(define_expand "divdf3"
738218334Speter  [(set (match_operand:DF 0 "register_operand" "")
738350650Sobrien 	(div:DF (match_operand:DF 1 "register_operand" "")
738450650Sobrien 		(match_operand:DF 2 "nonimmediate_operand" "")))]
738590286Sobrien   "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
738650650Sobrien   "")
738750650Sobrien 
738818334Speter(define_expand "divsf3"
738918334Speter  [(set (match_operand:SF 0 "register_operand" "")
739050650Sobrien	(div:SF (match_operand:SF 1 "register_operand" "")
739118334Speter		(match_operand:SF 2 "nonimmediate_operand" "")))]
739290286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
739318334Speter  "")
739418334Speter
739518334Speter;; Remainder instructions.
739618334Speter
739790286Sobrien(define_expand "divmoddi4"
739890286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
739990286Sobrien		   (div:DI (match_operand:DI 1 "register_operand" "")
740090286Sobrien			   (match_operand:DI 2 "nonimmediate_operand" "")))
740190286Sobrien	      (set (match_operand:DI 3 "register_operand" "")
740290286Sobrien		   (mod:DI (match_dup 1) (match_dup 2)))
7403169699Skan	      (clobber (reg:CC FLAGS_REG))])]
740490286Sobrien  "TARGET_64BIT"
740590286Sobrien  "")
740690286Sobrien
740790286Sobrien;; Allow to come the parameter in eax or edx to avoid extra moves.
7408132727Skan;; Penalize eax case slightly because it results in worse scheduling
740990286Sobrien;; of code.
741090286Sobrien(define_insn "*divmoddi4_nocltd_rex64"
741190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=&a,?a")
741290286Sobrien	(div:DI (match_operand:DI 2 "register_operand" "1,0")
741390286Sobrien		(match_operand:DI 3 "nonimmediate_operand" "rm,rm")))
741490286Sobrien   (set (match_operand:DI 1 "register_operand" "=&d,&d")
741590286Sobrien	(mod:DI (match_dup 2) (match_dup 3)))
7416169699Skan   (clobber (reg:CC FLAGS_REG))]
741790286Sobrien  "TARGET_64BIT && !optimize_size && !TARGET_USE_CLTD"
741890286Sobrien  "#"
741990286Sobrien  [(set_attr "type" "multi")])
742090286Sobrien
742190286Sobrien(define_insn "*divmoddi4_cltd_rex64"
742290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
742390286Sobrien	(div:DI (match_operand:DI 2 "register_operand" "a")
742490286Sobrien		(match_operand:DI 3 "nonimmediate_operand" "rm")))
742590286Sobrien   (set (match_operand:DI 1 "register_operand" "=&d")
742690286Sobrien	(mod:DI (match_dup 2) (match_dup 3)))
7427169699Skan   (clobber (reg:CC FLAGS_REG))]
742890286Sobrien  "TARGET_64BIT && (optimize_size || TARGET_USE_CLTD)"
742990286Sobrien  "#"
743090286Sobrien  [(set_attr "type" "multi")])
743190286Sobrien
743290286Sobrien(define_insn "*divmoddi_noext_rex64"
743390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
743490286Sobrien	(div:DI (match_operand:DI 1 "register_operand" "0")
743590286Sobrien		(match_operand:DI 2 "nonimmediate_operand" "rm")))
743690286Sobrien   (set (match_operand:DI 3 "register_operand" "=d")
743790286Sobrien	(mod:DI (match_dup 1) (match_dup 2)))
743890286Sobrien   (use (match_operand:DI 4 "register_operand" "3"))
7439169699Skan   (clobber (reg:CC FLAGS_REG))]
744090286Sobrien  "TARGET_64BIT"
744190286Sobrien  "idiv{q}\t%2"
744290286Sobrien  [(set_attr "type" "idiv")
7443169699Skan   (set_attr "mode" "DI")])
744490286Sobrien
744590286Sobrien(define_split
744690286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
744790286Sobrien	(div:DI (match_operand:DI 1 "register_operand" "")
744890286Sobrien		(match_operand:DI 2 "nonimmediate_operand" "")))
744990286Sobrien   (set (match_operand:DI 3 "register_operand" "")
745090286Sobrien	(mod:DI (match_dup 1) (match_dup 2)))
7451169699Skan   (clobber (reg:CC FLAGS_REG))]
745290286Sobrien  "TARGET_64BIT && reload_completed"
745390286Sobrien  [(parallel [(set (match_dup 3)
745490286Sobrien		   (ashiftrt:DI (match_dup 4) (const_int 63)))
7455169699Skan	      (clobber (reg:CC FLAGS_REG))])
745690286Sobrien   (parallel [(set (match_dup 0)
745790286Sobrien	           (div:DI (reg:DI 0) (match_dup 2)))
745890286Sobrien	      (set (match_dup 3)
745990286Sobrien		   (mod:DI (reg:DI 0) (match_dup 2)))
746090286Sobrien	      (use (match_dup 3))
7461169699Skan	      (clobber (reg:CC FLAGS_REG))])]
746290286Sobrien{
7463117404Skan  /* Avoid use of cltd in favor of a mov+shift.  */
746490286Sobrien  if (!TARGET_USE_CLTD && !optimize_size)
746590286Sobrien    {
746690286Sobrien      if (true_regnum (operands[1]))
746790286Sobrien        emit_move_insn (operands[0], operands[1]);
746890286Sobrien      else
746990286Sobrien	emit_move_insn (operands[3], operands[1]);
747090286Sobrien      operands[4] = operands[3];
747190286Sobrien    }
747290286Sobrien  else
747390286Sobrien    {
7474169699Skan      gcc_assert (!true_regnum (operands[1]));
747590286Sobrien      operands[4] = operands[1];
747690286Sobrien    }
747790286Sobrien})
747890286Sobrien
747990286Sobrien
748090286Sobrien(define_expand "divmodsi4"
748190286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
748290286Sobrien		   (div:SI (match_operand:SI 1 "register_operand" "")
748390286Sobrien			   (match_operand:SI 2 "nonimmediate_operand" "")))
748490286Sobrien	      (set (match_operand:SI 3 "register_operand" "")
748590286Sobrien		   (mod:SI (match_dup 1) (match_dup 2)))
7486169699Skan	      (clobber (reg:CC FLAGS_REG))])]
748790286Sobrien  ""
748890286Sobrien  "")
748990286Sobrien
749090286Sobrien;; Allow to come the parameter in eax or edx to avoid extra moves.
7491132727Skan;; Penalize eax case slightly because it results in worse scheduling
749290286Sobrien;; of code.
749390286Sobrien(define_insn "*divmodsi4_nocltd"
749490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=&a,?a")
749590286Sobrien	(div:SI (match_operand:SI 2 "register_operand" "1,0")
749690286Sobrien		(match_operand:SI 3 "nonimmediate_operand" "rm,rm")))
749790286Sobrien   (set (match_operand:SI 1 "register_operand" "=&d,&d")
749890286Sobrien	(mod:SI (match_dup 2) (match_dup 3)))
7499169699Skan   (clobber (reg:CC FLAGS_REG))]
750090286Sobrien  "!optimize_size && !TARGET_USE_CLTD"
750190286Sobrien  "#"
750290286Sobrien  [(set_attr "type" "multi")])
750390286Sobrien
750490286Sobrien(define_insn "*divmodsi4_cltd"
750518334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
750690286Sobrien	(div:SI (match_operand:SI 2 "register_operand" "a")
750790286Sobrien		(match_operand:SI 3 "nonimmediate_operand" "rm")))
750890286Sobrien   (set (match_operand:SI 1 "register_operand" "=&d")
750990286Sobrien	(mod:SI (match_dup 2) (match_dup 3)))
7510169699Skan   (clobber (reg:CC FLAGS_REG))]
751190286Sobrien  "optimize_size || TARGET_USE_CLTD"
751290286Sobrien  "#"
751390286Sobrien  [(set_attr "type" "multi")])
751490286Sobrien
751590286Sobrien(define_insn "*divmodsi_noext"
751690286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a")
751718334Speter	(div:SI (match_operand:SI 1 "register_operand" "0")
751850650Sobrien		(match_operand:SI 2 "nonimmediate_operand" "rm")))
751990286Sobrien   (set (match_operand:SI 3 "register_operand" "=d")
752090286Sobrien	(mod:SI (match_dup 1) (match_dup 2)))
752190286Sobrien   (use (match_operand:SI 4 "register_operand" "3"))
7522169699Skan   (clobber (reg:CC FLAGS_REG))]
752318334Speter  ""
752490286Sobrien  "idiv{l}\t%2"
752590286Sobrien  [(set_attr "type" "idiv")
7526169699Skan   (set_attr "mode" "SI")])
752790286Sobrien
752890286Sobrien(define_split
752990286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
753090286Sobrien	(div:SI (match_operand:SI 1 "register_operand" "")
753190286Sobrien		(match_operand:SI 2 "nonimmediate_operand" "")))
753290286Sobrien   (set (match_operand:SI 3 "register_operand" "")
753390286Sobrien	(mod:SI (match_dup 1) (match_dup 2)))
7534169699Skan   (clobber (reg:CC FLAGS_REG))]
753590286Sobrien  "reload_completed"
753690286Sobrien  [(parallel [(set (match_dup 3)
753790286Sobrien		   (ashiftrt:SI (match_dup 4) (const_int 31)))
7538169699Skan	      (clobber (reg:CC FLAGS_REG))])
753990286Sobrien   (parallel [(set (match_dup 0)
754090286Sobrien	           (div:SI (reg:SI 0) (match_dup 2)))
754190286Sobrien	      (set (match_dup 3)
754290286Sobrien		   (mod:SI (reg:SI 0) (match_dup 2)))
754390286Sobrien	      (use (match_dup 3))
7544169699Skan	      (clobber (reg:CC FLAGS_REG))])]
754518334Speter{
7546117404Skan  /* Avoid use of cltd in favor of a mov+shift.  */
754790286Sobrien  if (!TARGET_USE_CLTD && !optimize_size)
754890286Sobrien    {
754990286Sobrien      if (true_regnum (operands[1]))
755090286Sobrien        emit_move_insn (operands[0], operands[1]);
755190286Sobrien      else
755290286Sobrien	emit_move_insn (operands[3], operands[1]);
755390286Sobrien      operands[4] = operands[3];
755490286Sobrien    }
755590286Sobrien  else
755690286Sobrien    {
7557169699Skan      gcc_assert (!true_regnum (operands[1]));
755890286Sobrien      operands[4] = operands[1];
755990286Sobrien    }
756090286Sobrien})
756190286Sobrien;; %%% Split me.
756218334Speter(define_insn "divmodhi4"
756318334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
756418334Speter	(div:HI (match_operand:HI 1 "register_operand" "0")
756550650Sobrien		(match_operand:HI 2 "nonimmediate_operand" "rm")))
756618334Speter   (set (match_operand:HI 3 "register_operand" "=&d")
756790286Sobrien	(mod:HI (match_dup 1) (match_dup 2)))
7568169699Skan   (clobber (reg:CC FLAGS_REG))]
756990286Sobrien  "TARGET_HIMODE_MATH"
757090286Sobrien  "cwtd\;idiv{w}\t%2"
757190286Sobrien  [(set_attr "type" "multi")
757290286Sobrien   (set_attr "length_immediate" "0")
757390286Sobrien   (set_attr "mode" "SI")])
757418334Speter
757590286Sobrien(define_insn "udivmoddi4"
757690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
757790286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "0")
757890286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "rm")))
757990286Sobrien   (set (match_operand:DI 3 "register_operand" "=&d")
758090286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
7581169699Skan   (clobber (reg:CC FLAGS_REG))]
758290286Sobrien  "TARGET_64BIT"
758390286Sobrien  "xor{q}\t%3, %3\;div{q}\t%2"
758490286Sobrien  [(set_attr "type" "multi")
758590286Sobrien   (set_attr "length_immediate" "0")
758690286Sobrien   (set_attr "mode" "DI")])
758790286Sobrien
758890286Sobrien(define_insn "*udivmoddi4_noext"
758990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
759090286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "0")
759190286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "rm")))
759290286Sobrien   (set (match_operand:DI 3 "register_operand" "=d")
759390286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
759490286Sobrien   (use (match_dup 3))
7595169699Skan   (clobber (reg:CC FLAGS_REG))]
759690286Sobrien  "TARGET_64BIT"
759790286Sobrien  "div{q}\t%2"
759890286Sobrien  [(set_attr "type" "idiv")
759990286Sobrien   (set_attr "mode" "DI")])
760090286Sobrien
760190286Sobrien(define_split
760290286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
760390286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "")
760490286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "")))
760590286Sobrien   (set (match_operand:DI 3 "register_operand" "")
760690286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
7607169699Skan   (clobber (reg:CC FLAGS_REG))]
760890286Sobrien  "TARGET_64BIT && reload_completed"
760990286Sobrien  [(set (match_dup 3) (const_int 0))
761090286Sobrien   (parallel [(set (match_dup 0)
761190286Sobrien		   (udiv:DI (match_dup 1) (match_dup 2)))
761290286Sobrien	      (set (match_dup 3)
761390286Sobrien		   (umod:DI (match_dup 1) (match_dup 2)))
761490286Sobrien	      (use (match_dup 3))
7615169699Skan	      (clobber (reg:CC FLAGS_REG))])]
761690286Sobrien  "")
761790286Sobrien
761818334Speter(define_insn "udivmodsi4"
761918334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
762018334Speter	(udiv:SI (match_operand:SI 1 "register_operand" "0")
762150650Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
762218334Speter   (set (match_operand:SI 3 "register_operand" "=&d")
762390286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
7624169699Skan   (clobber (reg:CC FLAGS_REG))]
762518334Speter  ""
762690286Sobrien  "xor{l}\t%3, %3\;div{l}\t%2"
762790286Sobrien  [(set_attr "type" "multi")
762890286Sobrien   (set_attr "length_immediate" "0")
762990286Sobrien   (set_attr "mode" "SI")])
763018334Speter
763190286Sobrien(define_insn "*udivmodsi4_noext"
763290286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a")
763390286Sobrien	(udiv:SI (match_operand:SI 1 "register_operand" "0")
763490286Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
763590286Sobrien   (set (match_operand:SI 3 "register_operand" "=d")
763690286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
763790286Sobrien   (use (match_dup 3))
7638169699Skan   (clobber (reg:CC FLAGS_REG))]
763990286Sobrien  ""
764090286Sobrien  "div{l}\t%2"
764190286Sobrien  [(set_attr "type" "idiv")
764290286Sobrien   (set_attr "mode" "SI")])
764390286Sobrien
764490286Sobrien(define_split
764590286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
764690286Sobrien	(udiv:SI (match_operand:SI 1 "register_operand" "")
764790286Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "")))
764890286Sobrien   (set (match_operand:SI 3 "register_operand" "")
764990286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
7650169699Skan   (clobber (reg:CC FLAGS_REG))]
765190286Sobrien  "reload_completed"
765290286Sobrien  [(set (match_dup 3) (const_int 0))
765390286Sobrien   (parallel [(set (match_dup 0)
765490286Sobrien		   (udiv:SI (match_dup 1) (match_dup 2)))
765590286Sobrien	      (set (match_dup 3)
765690286Sobrien		   (umod:SI (match_dup 1) (match_dup 2)))
765790286Sobrien	      (use (match_dup 3))
7658169699Skan	      (clobber (reg:CC FLAGS_REG))])]
765990286Sobrien  "")
766090286Sobrien
766190286Sobrien(define_expand "udivmodhi4"
766290286Sobrien  [(set (match_dup 4) (const_int 0))
766390286Sobrien   (parallel [(set (match_operand:HI 0 "register_operand" "")
766490286Sobrien		   (udiv:HI (match_operand:HI 1 "register_operand" "")
766590286Sobrien		 	    (match_operand:HI 2 "nonimmediate_operand" "")))
766690286Sobrien	      (set (match_operand:HI 3 "register_operand" "")
766790286Sobrien	   	   (umod:HI (match_dup 1) (match_dup 2)))
766890286Sobrien	      (use (match_dup 4))
7669169699Skan	      (clobber (reg:CC FLAGS_REG))])]
767090286Sobrien  "TARGET_HIMODE_MATH"
767190286Sobrien  "operands[4] = gen_reg_rtx (HImode);")
767290286Sobrien
767390286Sobrien(define_insn "*udivmodhi_noext"
767418334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
767518334Speter	(udiv:HI (match_operand:HI 1 "register_operand" "0")
767650650Sobrien		 (match_operand:HI 2 "nonimmediate_operand" "rm")))
767790286Sobrien   (set (match_operand:HI 3 "register_operand" "=d")
767890286Sobrien	(umod:HI (match_dup 1) (match_dup 2)))
767990286Sobrien   (use (match_operand:HI 4 "register_operand" "3"))
7680169699Skan   (clobber (reg:CC FLAGS_REG))]
768118334Speter  ""
768290286Sobrien  "div{w}\t%2"
768390286Sobrien  [(set_attr "type" "idiv")
7684169699Skan   (set_attr "mode" "HI")])
768518334Speter
7686169699Skan;; We cannot use div/idiv for double division, because it causes
768790286Sobrien;; "division by zero" on the overflow and that's not what we expect
768890286Sobrien;; from truncate.  Because true (non truncating) double division is
768990286Sobrien;; never generated, we can't create this insn anyway.
769090286Sobrien;
769190286Sobrien;(define_insn ""
769290286Sobrien;  [(set (match_operand:SI 0 "register_operand" "=a")
769390286Sobrien;	(truncate:SI
769490286Sobrien;	  (udiv:DI (match_operand:DI 1 "register_operand" "A")
769590286Sobrien;		   (zero_extend:DI
769690286Sobrien;		     (match_operand:SI 2 "nonimmediate_operand" "rm")))))
769790286Sobrien;   (set (match_operand:SI 3 "register_operand" "=d")
769890286Sobrien;	(truncate:SI
769990286Sobrien;	  (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))
7700169699Skan;   (clobber (reg:CC FLAGS_REG))]
770190286Sobrien;  ""
770290286Sobrien;  "div{l}\t{%2, %0|%0, %2}"
7703169699Skan;  [(set_attr "type" "idiv")])
770490286Sobrien
770590286Sobrien;;- Logical AND instructions
770618334Speter
770790286Sobrien;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al.
770890286Sobrien;; Note that this excludes ah.
770990286Sobrien
771090286Sobrien(define_insn "*testdi_1_rex64"
7711169699Skan  [(set (reg FLAGS_REG)
771290286Sobrien	(compare
7713132727Skan	  (and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm")
7714132727Skan		  (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re"))
771590286Sobrien	  (const_int 0)))]
7716132727Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
7717132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
771890286Sobrien  "@
7719169699Skan   test{l}\t{%k1, %k0|%k0, %k1}
7720169699Skan   test{l}\t{%k1, %k0|%k0, %k1}
7721169699Skan   test{q}\t{%1, %0|%0, %1}
7722169699Skan   test{q}\t{%1, %0|%0, %1}
772390286Sobrien   test{q}\t{%1, %0|%0, %1}"
772490286Sobrien  [(set_attr "type" "test")
772590286Sobrien   (set_attr "modrm" "0,1,0,1,1")
772690286Sobrien   (set_attr "mode" "SI,SI,DI,DI,DI")
772790286Sobrien   (set_attr "pent_pair" "uv,np,uv,np,uv")])
772890286Sobrien
772990286Sobrien(define_insn "testsi_1"
7730169699Skan  [(set (reg FLAGS_REG)
773190286Sobrien	(compare
7732132727Skan	  (and:SI (match_operand:SI 0 "nonimmediate_operand" "%!*a,r,rm")
7733132727Skan		  (match_operand:SI 1 "general_operand" "in,in,rin"))
773490286Sobrien	  (const_int 0)))]
7735132727Skan  "ix86_match_ccmode (insn, CCNOmode)
7736132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
773790286Sobrien  "test{l}\t{%1, %0|%0, %1}"
773890286Sobrien  [(set_attr "type" "test")
773990286Sobrien   (set_attr "modrm" "0,1,1")
774090286Sobrien   (set_attr "mode" "SI")
774190286Sobrien   (set_attr "pent_pair" "uv,np,uv")])
774290286Sobrien
774390286Sobrien(define_expand "testsi_ccno_1"
7744169699Skan  [(set (reg:CCNO FLAGS_REG)
774590286Sobrien	(compare:CCNO
774690286Sobrien	  (and:SI (match_operand:SI 0 "nonimmediate_operand" "")
774790286Sobrien		  (match_operand:SI 1 "nonmemory_operand" ""))
774890286Sobrien	  (const_int 0)))]
774918334Speter  ""
775090286Sobrien  "")
775118334Speter
775290286Sobrien(define_insn "*testhi_1"
7753169699Skan  [(set (reg FLAGS_REG)
7754132727Skan        (compare (and:HI (match_operand:HI 0 "nonimmediate_operand" "%!*a,r,rm")
7755132727Skan			 (match_operand:HI 1 "general_operand" "n,n,rn"))
775690286Sobrien		 (const_int 0)))]
7757132727Skan  "ix86_match_ccmode (insn, CCNOmode)
7758132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
775990286Sobrien  "test{w}\t{%1, %0|%0, %1}"
776090286Sobrien  [(set_attr "type" "test")
776190286Sobrien   (set_attr "modrm" "0,1,1")
776290286Sobrien   (set_attr "mode" "HI")
776390286Sobrien   (set_attr "pent_pair" "uv,np,uv")])
776418334Speter
776590286Sobrien(define_expand "testqi_ccz_1"
7766169699Skan  [(set (reg:CCZ FLAGS_REG)
776790286Sobrien        (compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand" "")
776890286Sobrien			     (match_operand:QI 1 "nonmemory_operand" ""))
776990286Sobrien		 (const_int 0)))]
777090286Sobrien  ""
777190286Sobrien  "")
777218334Speter
7773146906Skan(define_insn "*testqi_1_maybe_si"
7774169699Skan  [(set (reg FLAGS_REG)
7775146906Skan        (compare
7776146906Skan	  (and:QI
7777146906Skan	    (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm,r")
7778146906Skan	    (match_operand:QI 1 "general_operand" "n,n,qn,n"))
7779146906Skan	  (const_int 0)))]
7780169699Skan   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
7781169699Skan    && ix86_match_ccmode (insn,
7782169699Skan 			 GET_CODE (operands[1]) == CONST_INT
7783169699Skan 			 && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)"
778418334Speter{
778590286Sobrien  if (which_alternative == 3)
778618334Speter    {
7787146906Skan      if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
778890286Sobrien	operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
778990286Sobrien      return "test{l}\t{%1, %k0|%k0, %1}";
779050650Sobrien    }
779190286Sobrien  return "test{b}\t{%1, %0|%0, %1}";
779290286Sobrien}
779390286Sobrien  [(set_attr "type" "test")
779490286Sobrien   (set_attr "modrm" "0,1,1,1")
779590286Sobrien   (set_attr "mode" "QI,QI,QI,SI")
779690286Sobrien   (set_attr "pent_pair" "uv,np,uv,np")])
779718334Speter
7798146906Skan(define_insn "*testqi_1"
7799169699Skan  [(set (reg FLAGS_REG)
7800146906Skan        (compare
7801146906Skan	  (and:QI
7802146906Skan	    (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm")
7803146906Skan	    (match_operand:QI 1 "general_operand" "n,n,qn"))
7804146906Skan	  (const_int 0)))]
7805146906Skan  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
7806146906Skan   && ix86_match_ccmode (insn, CCNOmode)"
7807146906Skan  "test{b}\t{%1, %0|%0, %1}"
7808146906Skan  [(set_attr "type" "test")
7809146906Skan   (set_attr "modrm" "0,1,1")
7810146906Skan   (set_attr "mode" "QI")
7811146906Skan   (set_attr "pent_pair" "uv,np,uv")])
7812146906Skan
781390286Sobrien(define_expand "testqi_ext_ccno_0"
7814169699Skan  [(set (reg:CCNO FLAGS_REG)
781590286Sobrien	(compare:CCNO
781690286Sobrien	  (and:SI
781790286Sobrien	    (zero_extract:SI
781890286Sobrien	      (match_operand 0 "ext_register_operand" "")
781990286Sobrien	      (const_int 8)
782090286Sobrien	      (const_int 8))
782190286Sobrien	    (match_operand 1 "const_int_operand" ""))
782290286Sobrien	  (const_int 0)))]
782390286Sobrien  ""
782490286Sobrien  "")
782518334Speter
782690286Sobrien(define_insn "*testqi_ext_0"
7827169699Skan  [(set (reg FLAGS_REG)
782890286Sobrien	(compare
782990286Sobrien	  (and:SI
783090286Sobrien	    (zero_extract:SI
783190286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
783290286Sobrien	      (const_int 8)
783390286Sobrien	      (const_int 8))
783490286Sobrien	    (match_operand 1 "const_int_operand" "n"))
783590286Sobrien	  (const_int 0)))]
7836117404Skan  "ix86_match_ccmode (insn, CCNOmode)"
783790286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
783890286Sobrien  [(set_attr "type" "test")
783990286Sobrien   (set_attr "mode" "QI")
784090286Sobrien   (set_attr "length_immediate" "1")
784190286Sobrien   (set_attr "pent_pair" "np")])
784250650Sobrien
784390286Sobrien(define_insn "*testqi_ext_1"
7844169699Skan  [(set (reg FLAGS_REG)
784590286Sobrien	(compare
784690286Sobrien	  (and:SI
784790286Sobrien	    (zero_extract:SI
784890286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
784990286Sobrien	      (const_int 8)
785090286Sobrien	      (const_int 8))
785190286Sobrien	    (zero_extend:SI
7852132727Skan	      (match_operand:QI 1 "general_operand" "Qm")))
785390286Sobrien	  (const_int 0)))]
7854132727Skan  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
7855132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
785690286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
785790286Sobrien  [(set_attr "type" "test")
785890286Sobrien   (set_attr "mode" "QI")])
785918334Speter
786090286Sobrien(define_insn "*testqi_ext_1_rex64"
7861169699Skan  [(set (reg FLAGS_REG)
786290286Sobrien	(compare
786390286Sobrien	  (and:SI
786490286Sobrien	    (zero_extract:SI
786590286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
786690286Sobrien	      (const_int 8)
786790286Sobrien	      (const_int 8))
786890286Sobrien	    (zero_extend:SI
786990286Sobrien	      (match_operand:QI 1 "register_operand" "Q")))
787090286Sobrien	  (const_int 0)))]
787190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
787290286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
787390286Sobrien  [(set_attr "type" "test")
787490286Sobrien   (set_attr "mode" "QI")])
787518334Speter
787690286Sobrien(define_insn "*testqi_ext_2"
7877169699Skan  [(set (reg FLAGS_REG)
787890286Sobrien	(compare
787990286Sobrien	  (and:SI
788090286Sobrien	    (zero_extract:SI
788190286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
788290286Sobrien	      (const_int 8)
788390286Sobrien	      (const_int 8))
788490286Sobrien	    (zero_extract:SI
788590286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
788690286Sobrien	      (const_int 8)
788790286Sobrien	      (const_int 8)))
788890286Sobrien	  (const_int 0)))]
788990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
789090286Sobrien  "test{b}\t{%h1, %h0|%h0, %h1}"
789190286Sobrien  [(set_attr "type" "test")
789290286Sobrien   (set_attr "mode" "QI")])
789350650Sobrien
789490286Sobrien;; Combine likes to form bit extractions for some tests.  Humor it.
789590286Sobrien(define_insn "*testqi_ext_3"
7896169699Skan  [(set (reg FLAGS_REG)
789790286Sobrien        (compare (zero_extract:SI
789890286Sobrien		   (match_operand 0 "nonimmediate_operand" "rm")
789990286Sobrien		   (match_operand:SI 1 "const_int_operand" "")
790090286Sobrien		   (match_operand:SI 2 "const_int_operand" ""))
790190286Sobrien		 (const_int 0)))]
790290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
7903169699Skan   && INTVAL (operands[1]) > 0
7904169699Skan   && INTVAL (operands[2]) >= 0
7905169699Skan   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
790690286Sobrien   && (GET_MODE (operands[0]) == SImode
790790286Sobrien       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
790890286Sobrien       || GET_MODE (operands[0]) == HImode
790990286Sobrien       || GET_MODE (operands[0]) == QImode)"
791090286Sobrien  "#")
791150650Sobrien
791290286Sobrien(define_insn "*testqi_ext_3_rex64"
7913169699Skan  [(set (reg FLAGS_REG)
791490286Sobrien        (compare (zero_extract:DI
791590286Sobrien		   (match_operand 0 "nonimmediate_operand" "rm")
791690286Sobrien		   (match_operand:DI 1 "const_int_operand" "")
791790286Sobrien		   (match_operand:DI 2 "const_int_operand" ""))
791890286Sobrien		 (const_int 0)))]
791990286Sobrien  "TARGET_64BIT
792090286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
7921169699Skan   && INTVAL (operands[1]) > 0
7922169699Skan   && INTVAL (operands[2]) >= 0
792390286Sobrien   /* Ensure that resulting mask is zero or sign extended operand.  */
792490286Sobrien   && (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
792590286Sobrien       || (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
792690286Sobrien	   && INTVAL (operands[1]) > 32))
792790286Sobrien   && (GET_MODE (operands[0]) == SImode
792890286Sobrien       || GET_MODE (operands[0]) == DImode
792990286Sobrien       || GET_MODE (operands[0]) == HImode
793090286Sobrien       || GET_MODE (operands[0]) == QImode)"
793190286Sobrien  "#")
793250650Sobrien
793390286Sobrien(define_split
7934146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
7935146906Skan        (match_operator 1 "compare_operator"
7936146906Skan	  [(zero_extract
7937146906Skan	     (match_operand 2 "nonimmediate_operand" "")
7938146906Skan	     (match_operand 3 "const_int_operand" "")
7939146906Skan	     (match_operand 4 "const_int_operand" ""))
7940146906Skan	   (const_int 0)]))]
794190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
7942146906Skan  [(set (match_dup 0) (match_op_dup 1 [(match_dup 2) (const_int 0)]))]
794390286Sobrien{
7944146906Skan  rtx val = operands[2];
7945146906Skan  HOST_WIDE_INT len = INTVAL (operands[3]);
7946146906Skan  HOST_WIDE_INT pos = INTVAL (operands[4]);
794790286Sobrien  HOST_WIDE_INT mask;
794890286Sobrien  enum machine_mode mode, submode;
794918334Speter
7950146906Skan  mode = GET_MODE (val);
7951146906Skan  if (GET_CODE (val) == MEM)
795290286Sobrien    {
795390286Sobrien      /* ??? Combine likes to put non-volatile mem extractions in QImode
795490286Sobrien	 no matter the size of the test.  So find a mode that works.  */
7955146906Skan      if (! MEM_VOLATILE_P (val))
795618334Speter	{
795790286Sobrien	  mode = smallest_mode_for_size (pos + len, MODE_INT);
7958146906Skan	  val = adjust_address (val, mode, 0);
795990286Sobrien	}
796090286Sobrien    }
7961146906Skan  else if (GET_CODE (val) == SUBREG
7962146906Skan	   && (submode = GET_MODE (SUBREG_REG (val)),
796390286Sobrien	       GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (submode))
796490286Sobrien	   && pos + len <= GET_MODE_BITSIZE (submode))
796590286Sobrien    {
796690286Sobrien      /* Narrow a paradoxical subreg to prevent partial register stalls.  */
796790286Sobrien      mode = submode;
7968146906Skan      val = SUBREG_REG (val);
796990286Sobrien    }
797090286Sobrien  else if (mode == HImode && pos + len <= 8)
797190286Sobrien    {
797290286Sobrien      /* Small HImode tests can be converted to QImode.  */
797390286Sobrien      mode = QImode;
7974146906Skan      val = gen_lowpart (QImode, val);
797590286Sobrien    }
797618334Speter
7977169699Skan  if (len == HOST_BITS_PER_WIDE_INT)
7978169699Skan    mask = -1;
7979169699Skan  else
7980169699Skan    mask = ((HOST_WIDE_INT)1 << len) - 1;
7981169699Skan  mask <<= pos;
798218334Speter
7983146906Skan  operands[2] = gen_rtx_AND (mode, val, gen_int_mode (mask, mode));
798490286Sobrien})
798550650Sobrien
7986117404Skan;; Convert HImode/SImode test instructions with immediate to QImode ones.
7987117404Skan;; i386 does not allow to encode test with 8bit sign extended immediate, so
7988117404Skan;; this is relatively important trick.
7989132727Skan;; Do the conversion only post-reload to avoid limiting of the register class
7990117404Skan;; to QI regs.
7991117404Skan(define_split
7992146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
7993146906Skan	(match_operator 1 "compare_operator"
7994146906Skan	  [(and (match_operand 2 "register_operand" "")
7995146906Skan	        (match_operand 3 "const_int_operand" ""))
7996146906Skan	   (const_int 0)]))]
7997117404Skan   "reload_completed
7998146906Skan    && QI_REG_P (operands[2])
7999146906Skan    && GET_MODE (operands[2]) != QImode
8000117404Skan    && ((ix86_match_ccmode (insn, CCZmode)
8001146906Skan    	 && !(INTVAL (operands[3]) & ~(255 << 8)))
8002117404Skan	|| (ix86_match_ccmode (insn, CCNOmode)
8003146906Skan	    && !(INTVAL (operands[3]) & ~(127 << 8))))"
8004146906Skan  [(set (match_dup 0)
8005146906Skan	(match_op_dup 1
8006146906Skan	  [(and:SI (zero_extract:SI (match_dup 2) (const_int 8) (const_int 8))
8007146906Skan		   (match_dup 3))
8008146906Skan	   (const_int 0)]))]
8009146906Skan  "operands[2] = gen_lowpart (SImode, operands[2]);
8010146906Skan   operands[3] = gen_int_mode (INTVAL (operands[3]) >> 8, SImode);")
8011117404Skan
8012117404Skan(define_split
8013146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
8014146906Skan	(match_operator 1 "compare_operator"
8015146906Skan	  [(and (match_operand 2 "nonimmediate_operand" "")
8016146906Skan	        (match_operand 3 "const_int_operand" ""))
8017146906Skan	   (const_int 0)]))]
8018117404Skan   "reload_completed
8019146906Skan    && GET_MODE (operands[2]) != QImode
8020146906Skan    && (!REG_P (operands[2]) || ANY_QI_REG_P (operands[2]))
8021117404Skan    && ((ix86_match_ccmode (insn, CCZmode)
8022146906Skan	 && !(INTVAL (operands[3]) & ~255))
8023117404Skan	|| (ix86_match_ccmode (insn, CCNOmode)
8024146906Skan	    && !(INTVAL (operands[3]) & ~127)))"
8025146906Skan  [(set (match_dup 0)
8026146906Skan	(match_op_dup 1 [(and:QI (match_dup 2) (match_dup 3))
8027146906Skan			 (const_int 0)]))]
8028146906Skan  "operands[2] = gen_lowpart (QImode, operands[2]);
8029146906Skan   operands[3] = gen_lowpart (QImode, operands[3]);")
8030117404Skan
8031117404Skan
803290286Sobrien;; %%% This used to optimize known byte-wide and operations to memory,
803390286Sobrien;; and sometimes to QImode registers.  If this is considered useful,
803490286Sobrien;; it should be done with splitters.
803518334Speter
803690286Sobrien(define_expand "anddi3"
803790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
803890286Sobrien	(and:DI (match_operand:DI 1 "nonimmediate_operand" "")
803990286Sobrien		(match_operand:DI 2 "x86_64_szext_general_operand" "")))
8040169699Skan   (clobber (reg:CC FLAGS_REG))]
804190286Sobrien  "TARGET_64BIT"
804290286Sobrien  "ix86_expand_binary_operator (AND, DImode, operands); DONE;")
804350650Sobrien
804490286Sobrien(define_insn "*anddi_1_rex64"
804590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
804690286Sobrien	(and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm")
804790286Sobrien		(match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L")))
8048169699Skan   (clobber (reg:CC FLAGS_REG))]
804990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)"
805090286Sobrien{
805190286Sobrien  switch (get_attr_type (insn))
805290286Sobrien    {
805390286Sobrien    case TYPE_IMOVX:
805490286Sobrien      {
805590286Sobrien	enum machine_mode mode;
805650650Sobrien
8057169699Skan	gcc_assert (GET_CODE (operands[2]) == CONST_INT);
805890286Sobrien        if (INTVAL (operands[2]) == 0xff)
805990286Sobrien	  mode = QImode;
806090286Sobrien	else
8061169699Skan	  {
8062169699Skan	    gcc_assert (INTVAL (operands[2]) == 0xffff);
8063169699Skan	    mode = HImode;
8064169699Skan	  }
806590286Sobrien	
806690286Sobrien	operands[1] = gen_lowpart (mode, operands[1]);
806790286Sobrien	if (mode == QImode)
806890286Sobrien	  return "movz{bq|x}\t{%1,%0|%0, %1}";
806990286Sobrien	else
807090286Sobrien	  return "movz{wq|x}\t{%1,%0|%0, %1}";
807190286Sobrien      }
807250650Sobrien
807350650Sobrien    default:
8074169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
807590286Sobrien      if (get_attr_mode (insn) == MODE_SI)
807690286Sobrien	return "and{l}\t{%k2, %k0|%k0, %k2}";
807790286Sobrien      else
807890286Sobrien	return "and{q}\t{%2, %0|%0, %2}";
807918334Speter    }
808090286Sobrien}
808190286Sobrien  [(set_attr "type" "alu,alu,alu,imovx")
808290286Sobrien   (set_attr "length_immediate" "*,*,*,0")
808390286Sobrien   (set_attr "mode" "SI,DI,DI,DI")])
808418334Speter
808590286Sobrien(define_insn "*anddi_2"
8086169699Skan  [(set (reg FLAGS_REG)
808790286Sobrien	(compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
808890286Sobrien			 (match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re"))
808990286Sobrien		 (const_int 0)))
809090286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm")
809190286Sobrien	(and:DI (match_dup 1) (match_dup 2)))]
809290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
809390286Sobrien   && ix86_binary_operator_ok (AND, DImode, operands)"
809490286Sobrien  "@
8095169699Skan   and{l}\t{%k2, %k0|%k0, %k2}
8096169699Skan   and{q}\t{%2, %0|%0, %2}
809790286Sobrien   and{q}\t{%2, %0|%0, %2}"
809890286Sobrien  [(set_attr "type" "alu")
809990286Sobrien   (set_attr "mode" "SI,DI,DI")])
810018334Speter
810190286Sobrien(define_expand "andsi3"
810290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
810390286Sobrien	(and:SI (match_operand:SI 1 "nonimmediate_operand" "")
810490286Sobrien		(match_operand:SI 2 "general_operand" "")))
8105169699Skan   (clobber (reg:CC FLAGS_REG))]
810618334Speter  ""
810790286Sobrien  "ix86_expand_binary_operator (AND, SImode, operands); DONE;")
810890286Sobrien
810990286Sobrien(define_insn "*andsi_1"
811090286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r")
811190286Sobrien	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm")
811290286Sobrien		(match_operand:SI 2 "general_operand" "ri,rm,L")))
8113169699Skan   (clobber (reg:CC FLAGS_REG))]
811490286Sobrien  "ix86_binary_operator_ok (AND, SImode, operands)"
811518334Speter{
811690286Sobrien  switch (get_attr_type (insn))
811718334Speter    {
811890286Sobrien    case TYPE_IMOVX:
811990286Sobrien      {
812090286Sobrien	enum machine_mode mode;
812118334Speter
8122169699Skan	gcc_assert (GET_CODE (operands[2]) == CONST_INT);
812390286Sobrien        if (INTVAL (operands[2]) == 0xff)
812490286Sobrien	  mode = QImode;
812590286Sobrien	else
8126169699Skan	  {
8127169699Skan	    gcc_assert (INTVAL (operands[2]) == 0xffff);
8128169699Skan	    mode = HImode;
8129169699Skan	  }
813090286Sobrien	
813190286Sobrien	operands[1] = gen_lowpart (mode, operands[1]);
813290286Sobrien	if (mode == QImode)
813390286Sobrien	  return "movz{bl|x}\t{%1,%0|%0, %1}";
813490286Sobrien	else
813590286Sobrien	  return "movz{wl|x}\t{%1,%0|%0, %1}";
813690286Sobrien      }
813718334Speter
813890286Sobrien    default:
8139169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
814090286Sobrien      return "and{l}\t{%2, %0|%0, %2}";
814190286Sobrien    }
814290286Sobrien}
814390286Sobrien  [(set_attr "type" "alu,alu,imovx")
814490286Sobrien   (set_attr "length_immediate" "*,*,0")
814590286Sobrien   (set_attr "mode" "SI")])
814618334Speter
814790286Sobrien(define_split
814890286Sobrien  [(set (match_operand 0 "register_operand" "")
814990286Sobrien	(and (match_dup 0)
815090286Sobrien	     (const_int -65536)))
8151169699Skan   (clobber (reg:CC FLAGS_REG))]
8152117404Skan  "optimize_size || (TARGET_FAST_PREFIX && !TARGET_PARTIAL_REG_STALL)"
815390286Sobrien  [(set (strict_low_part (match_dup 1)) (const_int 0))]
815490286Sobrien  "operands[1] = gen_lowpart (HImode, operands[0]);")
815518334Speter
815690286Sobrien(define_split
815790286Sobrien  [(set (match_operand 0 "ext_register_operand" "")
815890286Sobrien	(and (match_dup 0)
815990286Sobrien	     (const_int -256)))
8160169699Skan   (clobber (reg:CC FLAGS_REG))]
816190286Sobrien  "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
816290286Sobrien  [(set (strict_low_part (match_dup 1)) (const_int 0))]
816390286Sobrien  "operands[1] = gen_lowpart (QImode, operands[0]);")
816418334Speter
816590286Sobrien(define_split
816690286Sobrien  [(set (match_operand 0 "ext_register_operand" "")
816790286Sobrien	(and (match_dup 0)
816890286Sobrien	     (const_int -65281)))
8169169699Skan   (clobber (reg:CC FLAGS_REG))]
817090286Sobrien  "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
817190286Sobrien  [(parallel [(set (zero_extract:SI (match_dup 0)
817290286Sobrien				    (const_int 8)
817390286Sobrien				    (const_int 8))
817490286Sobrien		   (xor:SI 
817590286Sobrien		     (zero_extract:SI (match_dup 0)
817690286Sobrien				      (const_int 8)
817790286Sobrien				      (const_int 8))
817890286Sobrien		     (zero_extract:SI (match_dup 0)
817990286Sobrien				      (const_int 8)
818090286Sobrien				      (const_int 8))))
8181169699Skan	      (clobber (reg:CC FLAGS_REG))])]
818290286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);")
818350650Sobrien
818490286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
818590286Sobrien(define_insn "*andsi_1_zext"
818690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
818790286Sobrien	(zero_extend:DI
818890286Sobrien	  (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
818990286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8190169699Skan   (clobber (reg:CC FLAGS_REG))]
819190286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
819290286Sobrien  "and{l}\t{%2, %k0|%k0, %2}"
819390286Sobrien  [(set_attr "type" "alu")
819490286Sobrien   (set_attr "mode" "SI")])
819518334Speter
819690286Sobrien(define_insn "*andsi_2"
8197169699Skan  [(set (reg FLAGS_REG)
819890286Sobrien	(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
819990286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
820090286Sobrien		 (const_int 0)))
820190286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
820290286Sobrien	(and:SI (match_dup 1) (match_dup 2)))]
820390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
820490286Sobrien   && ix86_binary_operator_ok (AND, SImode, operands)"
820590286Sobrien  "and{l}\t{%2, %0|%0, %2}"
820690286Sobrien  [(set_attr "type" "alu")
820790286Sobrien   (set_attr "mode" "SI")])
820890286Sobrien
820990286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
821090286Sobrien(define_insn "*andsi_2_zext"
8211169699Skan  [(set (reg FLAGS_REG)
821290286Sobrien	(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
821390286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
821490286Sobrien		 (const_int 0)))
821590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
821690286Sobrien	(zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
821790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
821890286Sobrien   && ix86_binary_operator_ok (AND, SImode, operands)"
821990286Sobrien  "and{l}\t{%2, %k0|%k0, %2}"
822090286Sobrien  [(set_attr "type" "alu")
822190286Sobrien   (set_attr "mode" "SI")])
822290286Sobrien
822390286Sobrien(define_expand "andhi3"
822490286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
822590286Sobrien	(and:HI (match_operand:HI 1 "nonimmediate_operand" "")
822690286Sobrien		(match_operand:HI 2 "general_operand" "")))
8227169699Skan   (clobber (reg:CC FLAGS_REG))]
822890286Sobrien  "TARGET_HIMODE_MATH"
822990286Sobrien  "ix86_expand_binary_operator (AND, HImode, operands); DONE;")
823090286Sobrien
823190286Sobrien(define_insn "*andhi_1"
823290286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
823390286Sobrien	(and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,qm")
823490286Sobrien		(match_operand:HI 2 "general_operand" "ri,rm,L")))
8235169699Skan   (clobber (reg:CC FLAGS_REG))]
823690286Sobrien  "ix86_binary_operator_ok (AND, HImode, operands)"
823790286Sobrien{
823890286Sobrien  switch (get_attr_type (insn))
823950650Sobrien    {
824090286Sobrien    case TYPE_IMOVX:
8241169699Skan      gcc_assert (GET_CODE (operands[2]) == CONST_INT);
8242169699Skan      gcc_assert (INTVAL (operands[2]) == 0xff);
8243169699Skan      return "movz{bl|x}\t{%b1, %k0|%k0, %b1}";
824490286Sobrien
824590286Sobrien    default:
8246169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
824790286Sobrien
824890286Sobrien      return "and{w}\t{%2, %0|%0, %2}";
824950650Sobrien    }
825090286Sobrien}
825190286Sobrien  [(set_attr "type" "alu,alu,imovx")
825290286Sobrien   (set_attr "length_immediate" "*,*,0")
825390286Sobrien   (set_attr "mode" "HI,HI,SI")])
825450650Sobrien
825590286Sobrien(define_insn "*andhi_2"
8256169699Skan  [(set (reg FLAGS_REG)
825790286Sobrien	(compare (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
825890286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
825990286Sobrien		 (const_int 0)))
826090286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
826190286Sobrien	(and:HI (match_dup 1) (match_dup 2)))]
826290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
826390286Sobrien   && ix86_binary_operator_ok (AND, HImode, operands)"
826490286Sobrien  "and{w}\t{%2, %0|%0, %2}"
826590286Sobrien  [(set_attr "type" "alu")
826690286Sobrien   (set_attr "mode" "HI")])
826790286Sobrien
826890286Sobrien(define_expand "andqi3"
826990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
827090286Sobrien	(and:QI (match_operand:QI 1 "nonimmediate_operand" "")
827190286Sobrien		(match_operand:QI 2 "general_operand" "")))
8272169699Skan   (clobber (reg:CC FLAGS_REG))]
827390286Sobrien  "TARGET_QIMODE_MATH"
827490286Sobrien  "ix86_expand_binary_operator (AND, QImode, operands); DONE;")
827590286Sobrien
827690286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
827790286Sobrien(define_insn "*andqi_1"
827890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
827990286Sobrien	(and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
828090286Sobrien		(match_operand:QI 2 "general_operand" "qi,qmi,ri")))
8281169699Skan   (clobber (reg:CC FLAGS_REG))]
828290286Sobrien  "ix86_binary_operator_ok (AND, QImode, operands)"
828390286Sobrien  "@
828490286Sobrien   and{b}\t{%2, %0|%0, %2}
828590286Sobrien   and{b}\t{%2, %0|%0, %2}
828690286Sobrien   and{l}\t{%k2, %k0|%k0, %k2}"
828790286Sobrien  [(set_attr "type" "alu")
828890286Sobrien   (set_attr "mode" "QI,QI,SI")])
828990286Sobrien
829090286Sobrien(define_insn "*andqi_1_slp"
829190286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
829290286Sobrien	(and:QI (match_dup 0)
829390286Sobrien		(match_operand:QI 1 "general_operand" "qi,qmi")))
8294169699Skan   (clobber (reg:CC FLAGS_REG))]
8295117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8296117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
829790286Sobrien  "and{b}\t{%1, %0|%0, %1}"
829890286Sobrien  [(set_attr "type" "alu1")
829990286Sobrien   (set_attr "mode" "QI")])
830090286Sobrien
8301146906Skan(define_insn "*andqi_2_maybe_si"
8302169699Skan  [(set (reg FLAGS_REG)
830390286Sobrien	(compare (and:QI
8304146906Skan		      (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
8305146906Skan		      (match_operand:QI 2 "general_operand" "qim,qi,i"))
830690286Sobrien		 (const_int 0)))
830790286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,*r")
830890286Sobrien	(and:QI (match_dup 1) (match_dup 2)))]
8309146906Skan  "ix86_binary_operator_ok (AND, QImode, operands)
8310146906Skan   && ix86_match_ccmode (insn,
8311146906Skan			 GET_CODE (operands[2]) == CONST_INT
8312146906Skan			 && INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode)"
831390286Sobrien{
831490286Sobrien  if (which_alternative == 2)
831550650Sobrien    {
8316146906Skan      if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
831790286Sobrien        operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
831890286Sobrien      return "and{l}\t{%2, %k0|%k0, %2}";
831950650Sobrien    }
832090286Sobrien  return "and{b}\t{%2, %0|%0, %2}";
832190286Sobrien}
832290286Sobrien  [(set_attr "type" "alu")
832390286Sobrien   (set_attr "mode" "QI,QI,SI")])
832450650Sobrien
8325146906Skan(define_insn "*andqi_2"
8326169699Skan  [(set (reg FLAGS_REG)
8327146906Skan	(compare (and:QI
8328146906Skan		   (match_operand:QI 1 "nonimmediate_operand" "%0,0")
8329146906Skan		   (match_operand:QI 2 "general_operand" "qim,qi"))
8330146906Skan		 (const_int 0)))
8331146906Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
8332146906Skan	(and:QI (match_dup 1) (match_dup 2)))]
8333146906Skan  "ix86_match_ccmode (insn, CCNOmode)
8334146906Skan   && ix86_binary_operator_ok (AND, QImode, operands)"
8335146906Skan  "and{b}\t{%2, %0|%0, %2}"
8336146906Skan  [(set_attr "type" "alu")
8337146906Skan   (set_attr "mode" "QI")])
8338146906Skan
833990286Sobrien(define_insn "*andqi_2_slp"
8340169699Skan  [(set (reg FLAGS_REG)
834190286Sobrien	(compare (and:QI
834290286Sobrien		   (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
834390286Sobrien		   (match_operand:QI 1 "nonimmediate_operand" "qmi,qi"))
834490286Sobrien		 (const_int 0)))
834590286Sobrien   (set (strict_low_part (match_dup 0))
834690286Sobrien	(and:QI (match_dup 0) (match_dup 1)))]
8347117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8348117404Skan   && ix86_match_ccmode (insn, CCNOmode)
8349117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
835090286Sobrien  "and{b}\t{%1, %0|%0, %1}"
835190286Sobrien  [(set_attr "type" "alu1")
835290286Sobrien   (set_attr "mode" "QI")])
835318334Speter
835490286Sobrien;; ??? A bug in recog prevents it from recognizing a const_int as an
835590286Sobrien;; operand to zero_extend in andqi_ext_1.  It was checking explicitly
835690286Sobrien;; for a QImode operand, which of course failed.
835718334Speter
835890286Sobrien(define_insn "andqi_ext_0"
835990286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
836090286Sobrien			 (const_int 8)
836190286Sobrien			 (const_int 8))
836290286Sobrien	(and:SI 
836390286Sobrien	  (zero_extract:SI
836490286Sobrien	    (match_operand 1 "ext_register_operand" "0")
836590286Sobrien	    (const_int 8)
836690286Sobrien	    (const_int 8))
836790286Sobrien	  (match_operand 2 "const_int_operand" "n")))
8368169699Skan   (clobber (reg:CC FLAGS_REG))]
8369117404Skan  ""
837090286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
837190286Sobrien  [(set_attr "type" "alu")
837290286Sobrien   (set_attr "length_immediate" "1")
837390286Sobrien   (set_attr "mode" "QI")])
837418334Speter
837590286Sobrien;; Generated by peephole translating test to and.  This shows up
837690286Sobrien;; often in fp comparisons.
837790286Sobrien
837890286Sobrien(define_insn "*andqi_ext_0_cc"
8379169699Skan  [(set (reg FLAGS_REG)
838090286Sobrien	(compare
838190286Sobrien	  (and:SI
838290286Sobrien	    (zero_extract:SI
838390286Sobrien	      (match_operand 1 "ext_register_operand" "0")
838490286Sobrien	      (const_int 8)
838590286Sobrien	      (const_int 8))
838690286Sobrien	    (match_operand 2 "const_int_operand" "n"))
838790286Sobrien	  (const_int 0)))
838890286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
838990286Sobrien			 (const_int 8)
839090286Sobrien			 (const_int 8))
839190286Sobrien	(and:SI 
839290286Sobrien	  (zero_extract:SI
839390286Sobrien	    (match_dup 1)
839490286Sobrien	    (const_int 8)
839590286Sobrien	    (const_int 8))
839690286Sobrien	  (match_dup 2)))]
8397117404Skan  "ix86_match_ccmode (insn, CCNOmode)"
839890286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
839990286Sobrien  [(set_attr "type" "alu")
840090286Sobrien   (set_attr "length_immediate" "1")
840190286Sobrien   (set_attr "mode" "QI")])
840290286Sobrien
840390286Sobrien(define_insn "*andqi_ext_1"
840490286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
840590286Sobrien			 (const_int 8)
840690286Sobrien			 (const_int 8))
840790286Sobrien	(and:SI 
840890286Sobrien	  (zero_extract:SI
840990286Sobrien	    (match_operand 1 "ext_register_operand" "0")
841090286Sobrien	    (const_int 8)
841190286Sobrien	    (const_int 8))
841290286Sobrien	  (zero_extend:SI
841390286Sobrien	    (match_operand:QI 2 "general_operand" "Qm"))))
8414169699Skan   (clobber (reg:CC FLAGS_REG))]
841590286Sobrien  "!TARGET_64BIT"
841690286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
841790286Sobrien  [(set_attr "type" "alu")
841890286Sobrien   (set_attr "length_immediate" "0")
841990286Sobrien   (set_attr "mode" "QI")])
842090286Sobrien
842190286Sobrien(define_insn "*andqi_ext_1_rex64"
842290286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
842390286Sobrien			 (const_int 8)
842490286Sobrien			 (const_int 8))
842590286Sobrien	(and:SI 
842690286Sobrien	  (zero_extract:SI
842790286Sobrien	    (match_operand 1 "ext_register_operand" "0")
842890286Sobrien	    (const_int 8)
842990286Sobrien	    (const_int 8))
843090286Sobrien	  (zero_extend:SI
843190286Sobrien	    (match_operand 2 "ext_register_operand" "Q"))))
8432169699Skan   (clobber (reg:CC FLAGS_REG))]
843390286Sobrien  "TARGET_64BIT"
843490286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
843590286Sobrien  [(set_attr "type" "alu")
843690286Sobrien   (set_attr "length_immediate" "0")
843790286Sobrien   (set_attr "mode" "QI")])
843890286Sobrien
843990286Sobrien(define_insn "*andqi_ext_2"
844090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
844190286Sobrien			 (const_int 8)
844290286Sobrien			 (const_int 8))
844318334Speter	(and:SI
844490286Sobrien	  (zero_extract:SI
844590286Sobrien	    (match_operand 1 "ext_register_operand" "%0")
844690286Sobrien	    (const_int 8)
844790286Sobrien	    (const_int 8))
844890286Sobrien	  (zero_extract:SI
844990286Sobrien	    (match_operand 2 "ext_register_operand" "Q")
845090286Sobrien	    (const_int 8)
845190286Sobrien	    (const_int 8))))
8452169699Skan   (clobber (reg:CC FLAGS_REG))]
845390286Sobrien  ""
845490286Sobrien  "and{b}\t{%h2, %h0|%h0, %h2}"
845590286Sobrien  [(set_attr "type" "alu")
845690286Sobrien   (set_attr "length_immediate" "0")
845790286Sobrien   (set_attr "mode" "QI")])
8458117404Skan
8459117404Skan;; Convert wide AND instructions with immediate operand to shorter QImode
8460117404Skan;; equivalents when possible.
8461132727Skan;; Don't do the splitting with memory operands, since it introduces risk
8462117404Skan;; of memory mismatch stalls.  We may want to do the splitting for optimizing
8463117404Skan;; for size, but that can (should?) be handled by generic code instead.
8464117404Skan(define_split
8465117404Skan  [(set (match_operand 0 "register_operand" "")
8466117404Skan	(and (match_operand 1 "register_operand" "")
8467117404Skan	     (match_operand 2 "const_int_operand" "")))
8468169699Skan   (clobber (reg:CC FLAGS_REG))]
8469117404Skan   "reload_completed
8470117404Skan    && QI_REG_P (operands[0])
8471117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8472117404Skan    && !(~INTVAL (operands[2]) & ~(255 << 8))
8473117404Skan    && GET_MODE (operands[0]) != QImode"
8474117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
8475117404Skan		   (and:SI (zero_extract:SI (match_dup 1)
8476117404Skan					    (const_int 8) (const_int 8))
8477117404Skan			   (match_dup 2)))
8478169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8479117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
8480117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
8481117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
8482117404Skan
8483117404Skan;; Since AND can be encoded with sign extended immediate, this is only
8484117404Skan;; profitable when 7th bit is not set.
8485117404Skan(define_split
8486117404Skan  [(set (match_operand 0 "register_operand" "")
8487117404Skan	(and (match_operand 1 "general_operand" "")
8488117404Skan	     (match_operand 2 "const_int_operand" "")))
8489169699Skan   (clobber (reg:CC FLAGS_REG))]
8490117404Skan   "reload_completed
8491117404Skan    && ANY_QI_REG_P (operands[0])
8492117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8493117404Skan    && !(~INTVAL (operands[2]) & ~255)
8494117404Skan    && !(INTVAL (operands[2]) & 128)
8495117404Skan    && GET_MODE (operands[0]) != QImode"
8496117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
8497117404Skan		   (and:QI (match_dup 1)
8498117404Skan			   (match_dup 2)))
8499169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8500117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
8501117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
8502117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
850318334Speter
850490286Sobrien;; Logical inclusive OR instructions
850518334Speter
850690286Sobrien;; %%% This used to optimize known byte-wide and operations to memory.
850790286Sobrien;; If this is considered useful, it should be done with splitters.
850890286Sobrien
850990286Sobrien(define_expand "iordi3"
851090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
851190286Sobrien	(ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
851290286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "")))
8513169699Skan   (clobber (reg:CC FLAGS_REG))]
851490286Sobrien  "TARGET_64BIT"
851590286Sobrien  "ix86_expand_binary_operator (IOR, DImode, operands); DONE;")
851690286Sobrien
851790286Sobrien(define_insn "*iordi_1_rex64"
851890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
851990286Sobrien	(ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
852090286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "re,rme")))
8521169699Skan   (clobber (reg:CC FLAGS_REG))]
852290286Sobrien  "TARGET_64BIT
852390286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
852490286Sobrien  "or{q}\t{%2, %0|%0, %2}"
852590286Sobrien  [(set_attr "type" "alu")
852690286Sobrien   (set_attr "mode" "DI")])
852790286Sobrien
852890286Sobrien(define_insn "*iordi_2_rex64"
8529169699Skan  [(set (reg FLAGS_REG)
853090286Sobrien	(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
853190286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
853290286Sobrien		 (const_int 0)))
853390286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
853490286Sobrien	(ior:DI (match_dup 1) (match_dup 2)))]
853590286Sobrien  "TARGET_64BIT
853690286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
853790286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
853890286Sobrien  "or{q}\t{%2, %0|%0, %2}"
853990286Sobrien  [(set_attr "type" "alu")
854090286Sobrien   (set_attr "mode" "DI")])
854190286Sobrien
854290286Sobrien(define_insn "*iordi_3_rex64"
8543169699Skan  [(set (reg FLAGS_REG)
854490286Sobrien	(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
854590286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem"))
854690286Sobrien		 (const_int 0)))
854790286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
854890286Sobrien  "TARGET_64BIT
854990286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
855090286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
855190286Sobrien  "or{q}\t{%2, %0|%0, %2}"
855290286Sobrien  [(set_attr "type" "alu")
855390286Sobrien   (set_attr "mode" "DI")])
855490286Sobrien
855590286Sobrien
855690286Sobrien(define_expand "iorsi3"
855790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
855890286Sobrien	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
855990286Sobrien		(match_operand:SI 2 "general_operand" "")))
8560169699Skan   (clobber (reg:CC FLAGS_REG))]
856190286Sobrien  ""
856290286Sobrien  "ix86_expand_binary_operator (IOR, SImode, operands); DONE;")
856390286Sobrien
856490286Sobrien(define_insn "*iorsi_1"
856550650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
856650650Sobrien	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
856790286Sobrien		(match_operand:SI 2 "general_operand" "ri,rmi")))
8568169699Skan   (clobber (reg:CC FLAGS_REG))]
856990286Sobrien  "ix86_binary_operator_ok (IOR, SImode, operands)"
857090286Sobrien  "or{l}\t{%2, %0|%0, %2}"
857190286Sobrien  [(set_attr "type" "alu")
857290286Sobrien   (set_attr "mode" "SI")])
857350650Sobrien
857490286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
857590286Sobrien(define_insn "*iorsi_1_zext"
857690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm")
857790286Sobrien	(zero_extend:DI
857890286Sobrien	  (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
857990286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8580169699Skan   (clobber (reg:CC FLAGS_REG))]
858190286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)"
858290286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
858390286Sobrien  [(set_attr "type" "alu")
858490286Sobrien   (set_attr "mode" "SI")])
858550650Sobrien
858690286Sobrien(define_insn "*iorsi_1_zext_imm"
858790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm")
858890286Sobrien	(ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
858990286Sobrien		(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
8590169699Skan   (clobber (reg:CC FLAGS_REG))]
859190286Sobrien  "TARGET_64BIT"
859290286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
859390286Sobrien  [(set_attr "type" "alu")
859490286Sobrien   (set_attr "mode" "SI")])
859550650Sobrien
859690286Sobrien(define_insn "*iorsi_2"
8597169699Skan  [(set (reg FLAGS_REG)
859890286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
859990286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
860090286Sobrien		 (const_int 0)))
860190286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
860290286Sobrien	(ior:SI (match_dup 1) (match_dup 2)))]
860390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
860490286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
860590286Sobrien  "or{l}\t{%2, %0|%0, %2}"
860690286Sobrien  [(set_attr "type" "alu")
860790286Sobrien   (set_attr "mode" "SI")])
860850650Sobrien
860990286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
861090286Sobrien;; ??? Special case for immediate operand is missing - it is tricky.
861190286Sobrien(define_insn "*iorsi_2_zext"
8612169699Skan  [(set (reg FLAGS_REG)
861390286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
861490286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
861590286Sobrien		 (const_int 0)))
861690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
861790286Sobrien	(zero_extend:DI (ior:SI (match_dup 1) (match_dup 2))))]
861890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
861990286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
862090286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
862190286Sobrien  [(set_attr "type" "alu")
862290286Sobrien   (set_attr "mode" "SI")])
862350650Sobrien
862490286Sobrien(define_insn "*iorsi_2_zext_imm"
8625169699Skan  [(set (reg FLAGS_REG)
862690286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
862790286Sobrien			 (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
862890286Sobrien		 (const_int 0)))
862990286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
863090286Sobrien	(ior:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
863190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
863290286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
863390286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
863490286Sobrien  [(set_attr "type" "alu")
863590286Sobrien   (set_attr "mode" "SI")])
863650650Sobrien
863790286Sobrien(define_insn "*iorsi_3"
8638169699Skan  [(set (reg FLAGS_REG)
863990286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
864090286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
864190286Sobrien		 (const_int 0)))
864290286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
864390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
864490286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
864590286Sobrien  "or{l}\t{%2, %0|%0, %2}"
864690286Sobrien  [(set_attr "type" "alu")
864790286Sobrien   (set_attr "mode" "SI")])
864850650Sobrien
864990286Sobrien(define_expand "iorhi3"
865090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
865190286Sobrien	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "")
865290286Sobrien		(match_operand:HI 2 "general_operand" "")))
8653169699Skan   (clobber (reg:CC FLAGS_REG))]
865490286Sobrien  "TARGET_HIMODE_MATH"
865590286Sobrien  "ix86_expand_binary_operator (IOR, HImode, operands); DONE;")
865650650Sobrien
865790286Sobrien(define_insn "*iorhi_1"
865890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
865990286Sobrien	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
866090286Sobrien		(match_operand:HI 2 "general_operand" "rmi,ri")))
8661169699Skan   (clobber (reg:CC FLAGS_REG))]
866290286Sobrien  "ix86_binary_operator_ok (IOR, HImode, operands)"
866390286Sobrien  "or{w}\t{%2, %0|%0, %2}"
866490286Sobrien  [(set_attr "type" "alu")
866590286Sobrien   (set_attr "mode" "HI")])
866618334Speter
866790286Sobrien(define_insn "*iorhi_2"
8668169699Skan  [(set (reg FLAGS_REG)
866990286Sobrien	(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
867090286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
867190286Sobrien		 (const_int 0)))
867290286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
867390286Sobrien	(ior:HI (match_dup 1) (match_dup 2)))]
867490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
867590286Sobrien   && ix86_binary_operator_ok (IOR, HImode, operands)"
867690286Sobrien  "or{w}\t{%2, %0|%0, %2}"
867790286Sobrien  [(set_attr "type" "alu")
867890286Sobrien   (set_attr "mode" "HI")])
867918334Speter
868090286Sobrien(define_insn "*iorhi_3"
8681169699Skan  [(set (reg FLAGS_REG)
868290286Sobrien	(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
868390286Sobrien			 (match_operand:HI 2 "general_operand" "rim"))
868490286Sobrien		 (const_int 0)))
868590286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
868690286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
868790286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
868890286Sobrien  "or{w}\t{%2, %0|%0, %2}"
868990286Sobrien  [(set_attr "type" "alu")
869090286Sobrien   (set_attr "mode" "HI")])
869150650Sobrien
869290286Sobrien(define_expand "iorqi3"
869390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
869490286Sobrien	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "")
869590286Sobrien		(match_operand:QI 2 "general_operand" "")))
8696169699Skan   (clobber (reg:CC FLAGS_REG))]
869790286Sobrien  "TARGET_QIMODE_MATH"
869890286Sobrien  "ix86_expand_binary_operator (IOR, QImode, operands); DONE;")
869918334Speter
870090286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
870190286Sobrien(define_insn "*iorqi_1"
870290286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
870390286Sobrien	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
870490286Sobrien		(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
8705169699Skan   (clobber (reg:CC FLAGS_REG))]
870690286Sobrien  "ix86_binary_operator_ok (IOR, QImode, operands)"
870790286Sobrien  "@
870890286Sobrien   or{b}\t{%2, %0|%0, %2}
870990286Sobrien   or{b}\t{%2, %0|%0, %2}
871090286Sobrien   or{l}\t{%k2, %k0|%k0, %k2}"
871190286Sobrien  [(set_attr "type" "alu")
871290286Sobrien   (set_attr "mode" "QI,QI,SI")])
871350650Sobrien
871490286Sobrien(define_insn "*iorqi_1_slp"
871590286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m"))
871690286Sobrien	(ior:QI (match_dup 0)
871790286Sobrien		(match_operand:QI 1 "general_operand" "qmi,qi")))
8718169699Skan   (clobber (reg:CC FLAGS_REG))]
8719117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8720117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
872190286Sobrien  "or{b}\t{%1, %0|%0, %1}"
872290286Sobrien  [(set_attr "type" "alu1")
872390286Sobrien   (set_attr "mode" "QI")])
872418334Speter
872590286Sobrien(define_insn "*iorqi_2"
8726169699Skan  [(set (reg FLAGS_REG)
872790286Sobrien	(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
872890286Sobrien			 (match_operand:QI 2 "general_operand" "qim,qi"))
872990286Sobrien		 (const_int 0)))
873090286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
873190286Sobrien	(ior:QI (match_dup 1) (match_dup 2)))]
873290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
873390286Sobrien   && ix86_binary_operator_ok (IOR, QImode, operands)"
873490286Sobrien  "or{b}\t{%2, %0|%0, %2}"
873590286Sobrien  [(set_attr "type" "alu")
873690286Sobrien   (set_attr "mode" "QI")])
873718334Speter
873890286Sobrien(define_insn "*iorqi_2_slp"
8739169699Skan  [(set (reg FLAGS_REG)
874090286Sobrien	(compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
874190286Sobrien			 (match_operand:QI 1 "general_operand" "qim,qi"))
874290286Sobrien		 (const_int 0)))
874390286Sobrien   (set (strict_low_part (match_dup 0))
874490286Sobrien	(ior:QI (match_dup 0) (match_dup 1)))]
8745117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8746117404Skan   && ix86_match_ccmode (insn, CCNOmode)
8747117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
874890286Sobrien  "or{b}\t{%1, %0|%0, %1}"
874990286Sobrien  [(set_attr "type" "alu1")
875090286Sobrien   (set_attr "mode" "QI")])
875118334Speter
875290286Sobrien(define_insn "*iorqi_3"
8753169699Skan  [(set (reg FLAGS_REG)
875490286Sobrien	(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
875590286Sobrien			 (match_operand:QI 2 "general_operand" "qim"))
875690286Sobrien		 (const_int 0)))
875790286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
875890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
875990286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
876090286Sobrien  "or{b}\t{%2, %0|%0, %2}"
876190286Sobrien  [(set_attr "type" "alu")
876290286Sobrien   (set_attr "mode" "QI")])
876318334Speter
8764117404Skan(define_insn "iorqi_ext_0"
8765117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8766117404Skan			 (const_int 8)
8767117404Skan			 (const_int 8))
8768117404Skan	(ior:SI 
8769117404Skan	  (zero_extract:SI
8770117404Skan	    (match_operand 1 "ext_register_operand" "0")
8771117404Skan	    (const_int 8)
8772117404Skan	    (const_int 8))
8773117404Skan	  (match_operand 2 "const_int_operand" "n")))
8774169699Skan   (clobber (reg:CC FLAGS_REG))]
8775117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
8776117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8777117404Skan  [(set_attr "type" "alu")
8778117404Skan   (set_attr "length_immediate" "1")
8779117404Skan   (set_attr "mode" "QI")])
8780117404Skan
8781117404Skan(define_insn "*iorqi_ext_1"
8782117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8783117404Skan			 (const_int 8)
8784117404Skan			 (const_int 8))
8785117404Skan	(ior:SI 
8786117404Skan	  (zero_extract:SI
8787117404Skan	    (match_operand 1 "ext_register_operand" "0")
8788117404Skan	    (const_int 8)
8789117404Skan	    (const_int 8))
8790117404Skan	  (zero_extend:SI
8791117404Skan	    (match_operand:QI 2 "general_operand" "Qm"))))
8792169699Skan   (clobber (reg:CC FLAGS_REG))]
8793117404Skan  "!TARGET_64BIT
8794117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
8795117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8796117404Skan  [(set_attr "type" "alu")
8797117404Skan   (set_attr "length_immediate" "0")
8798117404Skan   (set_attr "mode" "QI")])
8799117404Skan
8800117404Skan(define_insn "*iorqi_ext_1_rex64"
8801117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8802117404Skan			 (const_int 8)
8803117404Skan			 (const_int 8))
8804117404Skan	(ior:SI 
8805117404Skan	  (zero_extract:SI
8806117404Skan	    (match_operand 1 "ext_register_operand" "0")
8807117404Skan	    (const_int 8)
8808117404Skan	    (const_int 8))
8809117404Skan	  (zero_extend:SI
8810117404Skan	    (match_operand 2 "ext_register_operand" "Q"))))
8811169699Skan   (clobber (reg:CC FLAGS_REG))]
8812117404Skan  "TARGET_64BIT
8813117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
8814117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8815117404Skan  [(set_attr "type" "alu")
8816117404Skan   (set_attr "length_immediate" "0")
8817117404Skan   (set_attr "mode" "QI")])
8818117404Skan
8819117404Skan(define_insn "*iorqi_ext_2"
8820117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8821117404Skan			 (const_int 8)
8822117404Skan			 (const_int 8))
8823117404Skan	(ior:SI 
8824117404Skan	  (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
8825117404Skan	  		   (const_int 8)
8826117404Skan			   (const_int 8))
8827117404Skan	  (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
8828117404Skan	  		   (const_int 8)
8829117404Skan			   (const_int 8))))
8830169699Skan   (clobber (reg:CC FLAGS_REG))]
8831117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
8832117404Skan  "ior{b}\t{%h2, %h0|%h0, %h2}"
8833117404Skan  [(set_attr "type" "alu")
8834117404Skan   (set_attr "length_immediate" "0")
8835117404Skan   (set_attr "mode" "QI")])
8836117404Skan
8837117404Skan(define_split
8838117404Skan  [(set (match_operand 0 "register_operand" "")
8839117404Skan	(ior (match_operand 1 "register_operand" "")
8840117404Skan	     (match_operand 2 "const_int_operand" "")))
8841169699Skan   (clobber (reg:CC FLAGS_REG))]
8842117404Skan   "reload_completed
8843117404Skan    && QI_REG_P (operands[0])
8844117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8845117404Skan    && !(INTVAL (operands[2]) & ~(255 << 8))
8846117404Skan    && GET_MODE (operands[0]) != QImode"
8847117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
8848117404Skan		   (ior:SI (zero_extract:SI (match_dup 1)
8849117404Skan					    (const_int 8) (const_int 8))
8850117404Skan			   (match_dup 2)))
8851169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8852117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
8853117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
8854117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
8855117404Skan
8856117404Skan;; Since OR can be encoded with sign extended immediate, this is only
8857117404Skan;; profitable when 7th bit is set.
8858117404Skan(define_split
8859117404Skan  [(set (match_operand 0 "register_operand" "")
8860117404Skan	(ior (match_operand 1 "general_operand" "")
8861117404Skan	     (match_operand 2 "const_int_operand" "")))
8862169699Skan   (clobber (reg:CC FLAGS_REG))]
8863117404Skan   "reload_completed
8864117404Skan    && ANY_QI_REG_P (operands[0])
8865117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8866117404Skan    && !(INTVAL (operands[2]) & ~255)
8867117404Skan    && (INTVAL (operands[2]) & 128)
8868117404Skan    && GET_MODE (operands[0]) != QImode"
8869117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
8870117404Skan		   (ior:QI (match_dup 1)
8871117404Skan			   (match_dup 2)))
8872169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8873117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
8874117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
8875117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
887690286Sobrien
887790286Sobrien;; Logical XOR instructions
887890286Sobrien
887990286Sobrien;; %%% This used to optimize known byte-wide and operations to memory.
888090286Sobrien;; If this is considered useful, it should be done with splitters.
888190286Sobrien
888290286Sobrien(define_expand "xordi3"
888390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
888490286Sobrien	(xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
888590286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "")))
8886169699Skan   (clobber (reg:CC FLAGS_REG))]
888790286Sobrien  "TARGET_64BIT"
888890286Sobrien  "ix86_expand_binary_operator (XOR, DImode, operands); DONE;")
888990286Sobrien
889090286Sobrien(define_insn "*xordi_1_rex64"
889190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
889290286Sobrien	(xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
889390286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
8894169699Skan   (clobber (reg:CC FLAGS_REG))]
889590286Sobrien  "TARGET_64BIT
889690286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
889790286Sobrien  "@
8898169699Skan   xor{q}\t{%2, %0|%0, %2}
889990286Sobrien   xor{q}\t{%2, %0|%0, %2}"
890090286Sobrien  [(set_attr "type" "alu")
890190286Sobrien   (set_attr "mode" "DI,DI")])
890290286Sobrien
890390286Sobrien(define_insn "*xordi_2_rex64"
8904169699Skan  [(set (reg FLAGS_REG)
890590286Sobrien	(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
890690286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
890790286Sobrien		 (const_int 0)))
890890286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
890990286Sobrien	(xor:DI (match_dup 1) (match_dup 2)))]
891090286Sobrien  "TARGET_64BIT
891190286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
891290286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
891390286Sobrien  "@
8914169699Skan   xor{q}\t{%2, %0|%0, %2}
891590286Sobrien   xor{q}\t{%2, %0|%0, %2}"
891690286Sobrien  [(set_attr "type" "alu")
891790286Sobrien   (set_attr "mode" "DI,DI")])
891890286Sobrien
891990286Sobrien(define_insn "*xordi_3_rex64"
8920169699Skan  [(set (reg FLAGS_REG)
892190286Sobrien	(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
892290286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem"))
892390286Sobrien		 (const_int 0)))
892490286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
892590286Sobrien  "TARGET_64BIT
892690286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
892790286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
892890286Sobrien  "xor{q}\t{%2, %0|%0, %2}"
892990286Sobrien  [(set_attr "type" "alu")
893090286Sobrien   (set_attr "mode" "DI")])
893190286Sobrien
893290286Sobrien(define_expand "xorsi3"
893390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
893490286Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "")
893590286Sobrien		(match_operand:SI 2 "general_operand" "")))
8936169699Skan   (clobber (reg:CC FLAGS_REG))]
893718334Speter  ""
893890286Sobrien  "ix86_expand_binary_operator (XOR, SImode, operands); DONE;")
893918334Speter
894090286Sobrien(define_insn "*xorsi_1"
894190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
894290286Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
894390286Sobrien		(match_operand:SI 2 "general_operand" "ri,rm")))
8944169699Skan   (clobber (reg:CC FLAGS_REG))]
894590286Sobrien  "ix86_binary_operator_ok (XOR, SImode, operands)"
894690286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
894790286Sobrien  [(set_attr "type" "alu")
894890286Sobrien   (set_attr "mode" "SI")])
894918334Speter
895090286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
895190286Sobrien;; Add speccase for immediates
895290286Sobrien(define_insn "*xorsi_1_zext"
895390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
895490286Sobrien	(zero_extend:DI
895590286Sobrien	  (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
895690286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8957169699Skan   (clobber (reg:CC FLAGS_REG))]
895890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
895990286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
896090286Sobrien  [(set_attr "type" "alu")
896190286Sobrien   (set_attr "mode" "SI")])
896250650Sobrien
896390286Sobrien(define_insn "*xorsi_1_zext_imm"
896490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
896590286Sobrien	(xor:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
896690286Sobrien		(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
8967169699Skan   (clobber (reg:CC FLAGS_REG))]
896890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
896990286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
897090286Sobrien  [(set_attr "type" "alu")
897190286Sobrien   (set_attr "mode" "SI")])
897250650Sobrien
897390286Sobrien(define_insn "*xorsi_2"
8974169699Skan  [(set (reg FLAGS_REG)
897590286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
897690286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
897790286Sobrien		 (const_int 0)))
897890286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
897990286Sobrien	(xor:SI (match_dup 1) (match_dup 2)))]
898090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
898190286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
898290286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
898390286Sobrien  [(set_attr "type" "alu")
898490286Sobrien   (set_attr "mode" "SI")])
898550650Sobrien
898690286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
898790286Sobrien;; ??? Special case for immediate operand is missing - it is tricky.
898890286Sobrien(define_insn "*xorsi_2_zext"
8989169699Skan  [(set (reg FLAGS_REG)
899090286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
899190286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
899290286Sobrien		 (const_int 0)))
899390286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
899490286Sobrien	(zero_extend:DI (xor:SI (match_dup 1) (match_dup 2))))]
899590286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
899690286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
899790286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
899890286Sobrien  [(set_attr "type" "alu")
899990286Sobrien   (set_attr "mode" "SI")])
900050650Sobrien
900190286Sobrien(define_insn "*xorsi_2_zext_imm"
9002169699Skan  [(set (reg FLAGS_REG)
900390286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
900490286Sobrien			 (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
900590286Sobrien		 (const_int 0)))
900690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
900790286Sobrien	(xor:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
900890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
900990286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
901090286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
901190286Sobrien  [(set_attr "type" "alu")
901290286Sobrien   (set_attr "mode" "SI")])
901350650Sobrien
901490286Sobrien(define_insn "*xorsi_3"
9015169699Skan  [(set (reg FLAGS_REG)
901690286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
901790286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
901890286Sobrien		 (const_int 0)))
901990286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
902090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
902190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
902290286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
902390286Sobrien  [(set_attr "type" "alu")
902490286Sobrien   (set_attr "mode" "SI")])
902518334Speter
902690286Sobrien(define_expand "xorhi3"
902790286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
902890286Sobrien	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "")
902990286Sobrien		(match_operand:HI 2 "general_operand" "")))
9030169699Skan   (clobber (reg:CC FLAGS_REG))]
903190286Sobrien  "TARGET_HIMODE_MATH"
903290286Sobrien  "ix86_expand_binary_operator (XOR, HImode, operands); DONE;")
903318334Speter
903490286Sobrien(define_insn "*xorhi_1"
903590286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
903690286Sobrien	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
903790286Sobrien		(match_operand:HI 2 "general_operand" "rmi,ri")))
9038169699Skan   (clobber (reg:CC FLAGS_REG))]
903990286Sobrien  "ix86_binary_operator_ok (XOR, HImode, operands)"
904090286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
904190286Sobrien  [(set_attr "type" "alu")
904290286Sobrien   (set_attr "mode" "HI")])
904318334Speter
904490286Sobrien(define_insn "*xorhi_2"
9045169699Skan  [(set (reg FLAGS_REG)
904690286Sobrien	(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
904790286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
904890286Sobrien		 (const_int 0)))
904990286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
905090286Sobrien	(xor:HI (match_dup 1) (match_dup 2)))]
905190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
905290286Sobrien   && ix86_binary_operator_ok (XOR, HImode, operands)"
905390286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
905490286Sobrien  [(set_attr "type" "alu")
905590286Sobrien   (set_attr "mode" "HI")])
905650650Sobrien
905790286Sobrien(define_insn "*xorhi_3"
9058169699Skan  [(set (reg FLAGS_REG)
905990286Sobrien	(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
906090286Sobrien			 (match_operand:HI 2 "general_operand" "rim"))
906190286Sobrien		 (const_int 0)))
906290286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
906390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
906490286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
906590286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
906690286Sobrien  [(set_attr "type" "alu")
906790286Sobrien   (set_attr "mode" "HI")])
906850650Sobrien
906990286Sobrien(define_expand "xorqi3"
907090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
907190286Sobrien	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "")
907290286Sobrien		(match_operand:QI 2 "general_operand" "")))
9073169699Skan   (clobber (reg:CC FLAGS_REG))]
907490286Sobrien  "TARGET_QIMODE_MATH"
907590286Sobrien  "ix86_expand_binary_operator (XOR, QImode, operands); DONE;")
907650650Sobrien
907790286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
907890286Sobrien(define_insn "*xorqi_1"
907990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
908090286Sobrien	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
908190286Sobrien		(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
9082169699Skan   (clobber (reg:CC FLAGS_REG))]
908390286Sobrien  "ix86_binary_operator_ok (XOR, QImode, operands)"
908490286Sobrien  "@
908590286Sobrien   xor{b}\t{%2, %0|%0, %2}
908690286Sobrien   xor{b}\t{%2, %0|%0, %2}
908790286Sobrien   xor{l}\t{%k2, %k0|%k0, %k2}"
908890286Sobrien  [(set_attr "type" "alu")
908990286Sobrien   (set_attr "mode" "QI,QI,SI")])
909018334Speter
9091117404Skan(define_insn "*xorqi_1_slp"
9092117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
9093117404Skan	(xor:QI (match_dup 0)
9094117404Skan		(match_operand:QI 1 "general_operand" "qi,qmi")))
9095169699Skan   (clobber (reg:CC FLAGS_REG))]
9096117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
9097117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
9098117404Skan  "xor{b}\t{%1, %0|%0, %1}"
9099117404Skan  [(set_attr "type" "alu1")
9100117404Skan   (set_attr "mode" "QI")])
9101117404Skan
9102117404Skan(define_insn "xorqi_ext_0"
9103117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9104117404Skan			 (const_int 8)
9105117404Skan			 (const_int 8))
9106117404Skan	(xor:SI 
9107117404Skan	  (zero_extract:SI
9108117404Skan	    (match_operand 1 "ext_register_operand" "0")
9109117404Skan	    (const_int 8)
9110117404Skan	    (const_int 8))
9111117404Skan	  (match_operand 2 "const_int_operand" "n")))
9112169699Skan   (clobber (reg:CC FLAGS_REG))]
9113117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
9114117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9115117404Skan  [(set_attr "type" "alu")
9116117404Skan   (set_attr "length_immediate" "1")
9117117404Skan   (set_attr "mode" "QI")])
9118117404Skan
911990286Sobrien(define_insn "*xorqi_ext_1"
912090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
912190286Sobrien			 (const_int 8)
912290286Sobrien			 (const_int 8))
912390286Sobrien	(xor:SI 
9124117404Skan	  (zero_extract:SI
9125117404Skan	    (match_operand 1 "ext_register_operand" "0")
9126117404Skan	    (const_int 8)
9127117404Skan	    (const_int 8))
9128117404Skan	  (zero_extend:SI
9129117404Skan	    (match_operand:QI 2 "general_operand" "Qm"))))
9130169699Skan   (clobber (reg:CC FLAGS_REG))]
9131117404Skan  "!TARGET_64BIT
9132117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
9133117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9134117404Skan  [(set_attr "type" "alu")
9135117404Skan   (set_attr "length_immediate" "0")
9136117404Skan   (set_attr "mode" "QI")])
9137117404Skan
9138117404Skan(define_insn "*xorqi_ext_1_rex64"
9139117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9140117404Skan			 (const_int 8)
9141117404Skan			 (const_int 8))
9142117404Skan	(xor:SI 
9143117404Skan	  (zero_extract:SI
9144117404Skan	    (match_operand 1 "ext_register_operand" "0")
9145117404Skan	    (const_int 8)
9146117404Skan	    (const_int 8))
9147117404Skan	  (zero_extend:SI
9148117404Skan	    (match_operand 2 "ext_register_operand" "Q"))))
9149169699Skan   (clobber (reg:CC FLAGS_REG))]
9150117404Skan  "TARGET_64BIT
9151117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
9152117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9153117404Skan  [(set_attr "type" "alu")
9154117404Skan   (set_attr "length_immediate" "0")
9155117404Skan   (set_attr "mode" "QI")])
9156117404Skan
9157117404Skan(define_insn "*xorqi_ext_2"
9158117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9159117404Skan			 (const_int 8)
9160117404Skan			 (const_int 8))
9161117404Skan	(xor:SI 
916290286Sobrien	  (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
916390286Sobrien	  		   (const_int 8)
916490286Sobrien			   (const_int 8))
916590286Sobrien	  (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
916690286Sobrien	  		   (const_int 8)
916790286Sobrien			   (const_int 8))))
9168169699Skan   (clobber (reg:CC FLAGS_REG))]
9169117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
917090286Sobrien  "xor{b}\t{%h2, %h0|%h0, %h2}"
917190286Sobrien  [(set_attr "type" "alu")
917290286Sobrien   (set_attr "length_immediate" "0")
917390286Sobrien   (set_attr "mode" "QI")])
917450650Sobrien
917590286Sobrien(define_insn "*xorqi_cc_1"
9176169699Skan  [(set (reg FLAGS_REG)
917790286Sobrien	(compare
917890286Sobrien	  (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
917990286Sobrien		  (match_operand:QI 2 "general_operand" "qim,qi"))
918090286Sobrien	  (const_int 0)))
918190286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
918290286Sobrien	(xor:QI (match_dup 1) (match_dup 2)))]
918390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
918490286Sobrien   && ix86_binary_operator_ok (XOR, QImode, operands)"
918590286Sobrien  "xor{b}\t{%2, %0|%0, %2}"
918690286Sobrien  [(set_attr "type" "alu")
918790286Sobrien   (set_attr "mode" "QI")])
918850650Sobrien
9189117404Skan(define_insn "*xorqi_2_slp"
9190169699Skan  [(set (reg FLAGS_REG)
9191117404Skan	(compare (xor:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
9192117404Skan			 (match_operand:QI 1 "general_operand" "qim,qi"))
9193117404Skan		 (const_int 0)))
9194117404Skan   (set (strict_low_part (match_dup 0))
9195117404Skan	(xor:QI (match_dup 0) (match_dup 1)))]
9196117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
9197117404Skan   && ix86_match_ccmode (insn, CCNOmode)
9198117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
9199117404Skan  "xor{b}\t{%1, %0|%0, %1}"
9200117404Skan  [(set_attr "type" "alu1")
9201117404Skan   (set_attr "mode" "QI")])
9202117404Skan
920390286Sobrien(define_insn "*xorqi_cc_2"
9204169699Skan  [(set (reg FLAGS_REG)
920590286Sobrien	(compare
920690286Sobrien	  (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
920790286Sobrien		  (match_operand:QI 2 "general_operand" "qim"))
920890286Sobrien	  (const_int 0)))
920990286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
921090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
921190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
921290286Sobrien  "xor{b}\t{%2, %0|%0, %2}"
921390286Sobrien  [(set_attr "type" "alu")
921490286Sobrien   (set_attr "mode" "QI")])
921518334Speter
921690286Sobrien(define_insn "*xorqi_cc_ext_1"
9217169699Skan  [(set (reg FLAGS_REG)
921890286Sobrien	(compare
921990286Sobrien	  (xor:SI
922090286Sobrien	    (zero_extract:SI
922190286Sobrien	      (match_operand 1 "ext_register_operand" "0")
922290286Sobrien	      (const_int 8)
922390286Sobrien	      (const_int 8))
922490286Sobrien	    (match_operand:QI 2 "general_operand" "qmn"))
922590286Sobrien	  (const_int 0)))
922690286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=q")
922790286Sobrien			 (const_int 8)
922890286Sobrien			 (const_int 8))
922990286Sobrien	(xor:SI 
923090286Sobrien	  (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
923190286Sobrien	  (match_dup 2)))]
923290286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
923390286Sobrien  "xor{b}\t{%2, %h0|%h0, %2}"
923490286Sobrien  [(set_attr "type" "alu")
923590286Sobrien   (set_attr "mode" "QI")])
923690286Sobrien
923790286Sobrien(define_insn "*xorqi_cc_ext_1_rex64"
9238169699Skan  [(set (reg FLAGS_REG)
923990286Sobrien	(compare
924090286Sobrien	  (xor:SI
924190286Sobrien	    (zero_extract:SI
924290286Sobrien	      (match_operand 1 "ext_register_operand" "0")
924390286Sobrien	      (const_int 8)
924490286Sobrien	      (const_int 8))
924590286Sobrien	    (match_operand:QI 2 "nonmemory_operand" "Qn"))
924690286Sobrien	  (const_int 0)))
924790286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
924890286Sobrien			 (const_int 8)
924990286Sobrien			 (const_int 8))
925090286Sobrien	(xor:SI 
925190286Sobrien	  (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
925290286Sobrien	  (match_dup 2)))]
925390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
925490286Sobrien  "xor{b}\t{%2, %h0|%h0, %2}"
925590286Sobrien  [(set_attr "type" "alu")
925690286Sobrien   (set_attr "mode" "QI")])
925790286Sobrien
925890286Sobrien(define_expand "xorqi_cc_ext_1"
925990286Sobrien  [(parallel [
9260169699Skan     (set (reg:CCNO FLAGS_REG)
926190286Sobrien	  (compare:CCNO
926290286Sobrien	    (xor:SI
926390286Sobrien	      (zero_extract:SI
926490286Sobrien		(match_operand 1 "ext_register_operand" "")
926590286Sobrien		(const_int 8)
926690286Sobrien		(const_int 8))
926790286Sobrien	      (match_operand:QI 2 "general_operand" ""))
926890286Sobrien	    (const_int 0)))
926990286Sobrien     (set (zero_extract:SI (match_operand 0 "ext_register_operand" "")
927090286Sobrien			   (const_int 8)
927190286Sobrien			   (const_int 8))
927290286Sobrien	  (xor:SI 
927390286Sobrien	    (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
927490286Sobrien	    (match_dup 2)))])]
927518334Speter  ""
927690286Sobrien  "")
9277117404Skan
9278117404Skan(define_split
9279117404Skan  [(set (match_operand 0 "register_operand" "")
9280117404Skan	(xor (match_operand 1 "register_operand" "")
9281117404Skan	     (match_operand 2 "const_int_operand" "")))
9282169699Skan   (clobber (reg:CC FLAGS_REG))]
9283117404Skan   "reload_completed
9284117404Skan    && QI_REG_P (operands[0])
9285117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
9286117404Skan    && !(INTVAL (operands[2]) & ~(255 << 8))
9287117404Skan    && GET_MODE (operands[0]) != QImode"
9288117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
9289117404Skan		   (xor:SI (zero_extract:SI (match_dup 1)
9290117404Skan					    (const_int 8) (const_int 8))
9291117404Skan			   (match_dup 2)))
9292169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9293117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
9294117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
9295117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
9296117404Skan
9297117404Skan;; Since XOR can be encoded with sign extended immediate, this is only
9298117404Skan;; profitable when 7th bit is set.
9299117404Skan(define_split
9300117404Skan  [(set (match_operand 0 "register_operand" "")
9301117404Skan	(xor (match_operand 1 "general_operand" "")
9302117404Skan	     (match_operand 2 "const_int_operand" "")))
9303169699Skan   (clobber (reg:CC FLAGS_REG))]
9304117404Skan   "reload_completed
9305117404Skan    && ANY_QI_REG_P (operands[0])
9306117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
9307117404Skan    && !(INTVAL (operands[2]) & ~255)
9308117404Skan    && (INTVAL (operands[2]) & 128)
9309117404Skan    && GET_MODE (operands[0]) != QImode"
9310117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
9311117404Skan		   (xor:QI (match_dup 1)
9312117404Skan			   (match_dup 2)))
9313169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9314117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
9315117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
9316117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
931718334Speter
931890286Sobrien;; Negation instructions
931918334Speter
9320169699Skan(define_expand "negti2"
9321169699Skan  [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
9322169699Skan		   (neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
9323169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9324169699Skan  "TARGET_64BIT"
9325169699Skan  "ix86_expand_unary_operator (NEG, TImode, operands); DONE;")
9326169699Skan
9327169699Skan(define_insn "*negti2_1"
9328169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=ro")
9329171835Skan	(neg:TI (match_operand:TI 1 "nonimmediate_operand" "0")))
9330169699Skan   (clobber (reg:CC FLAGS_REG))]
9331169699Skan  "TARGET_64BIT
9332169699Skan   && ix86_unary_operator_ok (NEG, TImode, operands)"
9333169699Skan  "#")
9334169699Skan
9335169699Skan(define_split
9336169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
9337171835Skan	(neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
9338169699Skan   (clobber (reg:CC FLAGS_REG))]
9339169699Skan  "TARGET_64BIT && reload_completed"
9340169699Skan  [(parallel
9341169699Skan    [(set (reg:CCZ FLAGS_REG)
9342169699Skan	  (compare:CCZ (neg:DI (match_dup 2)) (const_int 0)))
9343169699Skan     (set (match_dup 0) (neg:DI (match_dup 2)))])
9344169699Skan   (parallel
9345169699Skan    [(set (match_dup 1)
9346169699Skan	  (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
9347169699Skan			    (match_dup 3))
9348169699Skan		   (const_int 0)))
9349169699Skan     (clobber (reg:CC FLAGS_REG))])
9350169699Skan   (parallel
9351169699Skan    [(set (match_dup 1)
9352169699Skan	  (neg:DI (match_dup 1)))
9353169699Skan     (clobber (reg:CC FLAGS_REG))])]
9354169699Skan  "split_ti (operands+1, 1, operands+2, operands+3);
9355169699Skan   split_ti (operands+0, 1, operands+0, operands+1);")
9356169699Skan
935790286Sobrien(define_expand "negdi2"
935890286Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
935990286Sobrien		   (neg:DI (match_operand:DI 1 "nonimmediate_operand" "")))
9360169699Skan	      (clobber (reg:CC FLAGS_REG))])]
936118334Speter  ""
936290286Sobrien  "ix86_expand_unary_operator (NEG, DImode, operands); DONE;")
936350650Sobrien
936490286Sobrien(define_insn "*negdi2_1"
936590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=ro")
936690286Sobrien	(neg:DI (match_operand:DI 1 "general_operand" "0")))
9367169699Skan   (clobber (reg:CC FLAGS_REG))]
936890286Sobrien  "!TARGET_64BIT
936990286Sobrien   && ix86_unary_operator_ok (NEG, DImode, operands)"
937090286Sobrien  "#")
937150650Sobrien
937290286Sobrien(define_split
937390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
937490286Sobrien	(neg:DI (match_operand:DI 1 "general_operand" "")))
9375169699Skan   (clobber (reg:CC FLAGS_REG))]
937690286Sobrien  "!TARGET_64BIT && reload_completed"
937790286Sobrien  [(parallel
9378169699Skan    [(set (reg:CCZ FLAGS_REG)
937990286Sobrien	  (compare:CCZ (neg:SI (match_dup 2)) (const_int 0)))
938090286Sobrien     (set (match_dup 0) (neg:SI (match_dup 2)))])
938190286Sobrien   (parallel
938290286Sobrien    [(set (match_dup 1)
9383169699Skan	  (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
938490286Sobrien			    (match_dup 3))
938590286Sobrien		   (const_int 0)))
9386169699Skan     (clobber (reg:CC FLAGS_REG))])
938790286Sobrien   (parallel
938890286Sobrien    [(set (match_dup 1)
938990286Sobrien	  (neg:SI (match_dup 1)))
9390169699Skan     (clobber (reg:CC FLAGS_REG))])]
939190286Sobrien  "split_di (operands+1, 1, operands+2, operands+3);
939290286Sobrien   split_di (operands+0, 1, operands+0, operands+1);")
939350650Sobrien
939490286Sobrien(define_insn "*negdi2_1_rex64"
939590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
939690286Sobrien	(neg:DI (match_operand:DI 1 "nonimmediate_operand" "0")))
9397169699Skan   (clobber (reg:CC FLAGS_REG))]
939890286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
939990286Sobrien  "neg{q}\t%0"
940090286Sobrien  [(set_attr "type" "negnot")
940190286Sobrien   (set_attr "mode" "DI")])
940250650Sobrien
940390286Sobrien;; The problem with neg is that it does not perform (compare x 0),
940490286Sobrien;; it really performs (compare 0 x), which leaves us with the zero
940590286Sobrien;; flag being the only useful item.
940650650Sobrien
940790286Sobrien(define_insn "*negdi2_cmpz_rex64"
9408169699Skan  [(set (reg:CCZ FLAGS_REG)
940990286Sobrien	(compare:CCZ (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
941090286Sobrien		     (const_int 0)))
941190286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
941290286Sobrien	(neg:DI (match_dup 1)))]
941390286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
941490286Sobrien  "neg{q}\t%0"
941590286Sobrien  [(set_attr "type" "negnot")
941690286Sobrien   (set_attr "mode" "DI")])
941750650Sobrien
941818334Speter
941990286Sobrien(define_expand "negsi2"
942090286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
942190286Sobrien		   (neg:SI (match_operand:SI 1 "nonimmediate_operand" "")))
9422169699Skan	      (clobber (reg:CC FLAGS_REG))])]
942390286Sobrien  ""
942490286Sobrien  "ix86_expand_unary_operator (NEG, SImode, operands); DONE;")
942518334Speter
942690286Sobrien(define_insn "*negsi2_1"
942790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
942890286Sobrien	(neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))
9429169699Skan   (clobber (reg:CC FLAGS_REG))]
943090286Sobrien  "ix86_unary_operator_ok (NEG, SImode, operands)"
943190286Sobrien  "neg{l}\t%0"
943290286Sobrien  [(set_attr "type" "negnot")
943390286Sobrien   (set_attr "mode" "SI")])
943450650Sobrien
943590286Sobrien;; Combine is quite creative about this pattern.
943690286Sobrien(define_insn "*negsi2_1_zext"
943790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
943890286Sobrien	(lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0")
943990286Sobrien					(const_int 32)))
944090286Sobrien		     (const_int 32)))
9441169699Skan   (clobber (reg:CC FLAGS_REG))]
944290286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
944390286Sobrien  "neg{l}\t%k0"
944490286Sobrien  [(set_attr "type" "negnot")
944590286Sobrien   (set_attr "mode" "SI")])
944650650Sobrien
944790286Sobrien;; The problem with neg is that it does not perform (compare x 0),
944890286Sobrien;; it really performs (compare 0 x), which leaves us with the zero
944990286Sobrien;; flag being the only useful item.
945018334Speter
945190286Sobrien(define_insn "*negsi2_cmpz"
9452169699Skan  [(set (reg:CCZ FLAGS_REG)
945390286Sobrien	(compare:CCZ (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
945490286Sobrien		     (const_int 0)))
945590286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
945690286Sobrien	(neg:SI (match_dup 1)))]
945790286Sobrien  "ix86_unary_operator_ok (NEG, SImode, operands)"
945890286Sobrien  "neg{l}\t%0"
945990286Sobrien  [(set_attr "type" "negnot")
946090286Sobrien   (set_attr "mode" "SI")])
946150650Sobrien
946290286Sobrien(define_insn "*negsi2_cmpz_zext"
9463169699Skan  [(set (reg:CCZ FLAGS_REG)
946490286Sobrien	(compare:CCZ (lshiftrt:DI
946590286Sobrien		       (neg:DI (ashift:DI
946690286Sobrien				 (match_operand:DI 1 "register_operand" "0")
946790286Sobrien				 (const_int 32)))
946890286Sobrien		       (const_int 32))
946990286Sobrien		     (const_int 0)))
947090286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
947190286Sobrien	(lshiftrt:DI (neg:DI (ashift:DI (match_dup 1)
947290286Sobrien					(const_int 32)))
947390286Sobrien		     (const_int 32)))]
947490286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
947590286Sobrien  "neg{l}\t%k0"
947690286Sobrien  [(set_attr "type" "negnot")
947790286Sobrien   (set_attr "mode" "SI")])
947890286Sobrien
947990286Sobrien(define_expand "neghi2"
948090286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
948190286Sobrien		   (neg:HI (match_operand:HI 1 "nonimmediate_operand" "")))
9482169699Skan	      (clobber (reg:CC FLAGS_REG))])]
948390286Sobrien  "TARGET_HIMODE_MATH"
948490286Sobrien  "ix86_expand_unary_operator (NEG, HImode, operands); DONE;")
948590286Sobrien
948690286Sobrien(define_insn "*neghi2_1"
948790286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
948890286Sobrien	(neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))
9489169699Skan   (clobber (reg:CC FLAGS_REG))]
949090286Sobrien  "ix86_unary_operator_ok (NEG, HImode, operands)"
949190286Sobrien  "neg{w}\t%0"
949290286Sobrien  [(set_attr "type" "negnot")
949390286Sobrien   (set_attr "mode" "HI")])
949490286Sobrien
949590286Sobrien(define_insn "*neghi2_cmpz"
9496169699Skan  [(set (reg:CCZ FLAGS_REG)
949790286Sobrien	(compare:CCZ (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
949890286Sobrien		     (const_int 0)))
949990286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
950090286Sobrien	(neg:HI (match_dup 1)))]
950190286Sobrien  "ix86_unary_operator_ok (NEG, HImode, operands)"
950290286Sobrien  "neg{w}\t%0"
950390286Sobrien  [(set_attr "type" "negnot")
950490286Sobrien   (set_attr "mode" "HI")])
950590286Sobrien
950690286Sobrien(define_expand "negqi2"
950790286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
950890286Sobrien		   (neg:QI (match_operand:QI 1 "nonimmediate_operand" "")))
9509169699Skan	      (clobber (reg:CC FLAGS_REG))])]
951090286Sobrien  "TARGET_QIMODE_MATH"
951190286Sobrien  "ix86_expand_unary_operator (NEG, QImode, operands); DONE;")
951290286Sobrien
951390286Sobrien(define_insn "*negqi2_1"
951490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
951590286Sobrien	(neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))
9516169699Skan   (clobber (reg:CC FLAGS_REG))]
951790286Sobrien  "ix86_unary_operator_ok (NEG, QImode, operands)"
951890286Sobrien  "neg{b}\t%0"
951990286Sobrien  [(set_attr "type" "negnot")
952090286Sobrien   (set_attr "mode" "QI")])
952190286Sobrien
952290286Sobrien(define_insn "*negqi2_cmpz"
9523169699Skan  [(set (reg:CCZ FLAGS_REG)
952490286Sobrien	(compare:CCZ (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
952590286Sobrien		     (const_int 0)))
952690286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
952790286Sobrien	(neg:QI (match_dup 1)))]
952890286Sobrien  "ix86_unary_operator_ok (NEG, QImode, operands)"
952990286Sobrien  "neg{b}\t%0"
953090286Sobrien  [(set_attr "type" "negnot")
953190286Sobrien   (set_attr "mode" "QI")])
953290286Sobrien
953390286Sobrien;; Changing of sign for FP values is doable using integer unit too.
953490286Sobrien
953590286Sobrien(define_expand "negsf2"
9536169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
9537169699Skan	(neg:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
9538146906Skan  "TARGET_80387 || TARGET_SSE_MATH"
9539169699Skan  "ix86_expand_fp_absneg_operator (NEG, SFmode, operands); DONE;")
954018334Speter
9541169699Skan(define_expand "abssf2"
9542169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
9543169699Skan	(abs:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
9544169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
9545169699Skan  "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
954618334Speter
9547169699Skan(define_insn "*absnegsf2_mixed"
9548169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x  ,x,f,rm")
9549169699Skan	(match_operator:SF 3 "absneg_operator"
9550169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0   ,x,0,0 ")]))
9551169699Skan   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm  ,0,X,X "))
9552169699Skan   (clobber (reg:CC FLAGS_REG))]
9553169699Skan  "TARGET_SSE_MATH && TARGET_MIX_SSE_I387
9554169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
955590286Sobrien  "#")
955618334Speter
9557169699Skan(define_insn "*absnegsf2_sse"
9558169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x,x,rm")
9559169699Skan	(match_operator:SF 3 "absneg_operator"
9560169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0")]))
9561169699Skan   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm,0,X"))
9562169699Skan   (clobber (reg:CC FLAGS_REG))]
9563169699Skan  "TARGET_SSE_MATH
9564169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
956590286Sobrien  "#")
956618334Speter
9567169699Skan(define_insn "*absnegsf2_i387"
9568169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,rm")
9569169699Skan	(match_operator:SF 3 "absneg_operator"
9570169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0,0")]))
9571169699Skan   (use (match_operand 2 "" ""))
9572169699Skan   (clobber (reg:CC FLAGS_REG))]
9573169699Skan  "TARGET_80387 && !TARGET_SSE_MATH
9574169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
9575169699Skan  "#")
957690286Sobrien
9577169699Skan(define_expand "copysignsf3"
9578169699Skan  [(match_operand:SF 0 "register_operand" "")
9579169699Skan   (match_operand:SF 1 "nonmemory_operand" "")
9580169699Skan   (match_operand:SF 2 "register_operand" "")]
9581169699Skan  "TARGET_SSE_MATH"
9582169699Skan{
9583169699Skan  ix86_expand_copysign (operands);
9584169699Skan  DONE;
9585169699Skan})
958690286Sobrien
9587169699Skan(define_insn_and_split "copysignsf3_const"
9588169699Skan  [(set (match_operand:SF 0 "register_operand"          "=x")
9589169699Skan	(unspec:SF
9590169699Skan	  [(match_operand:V4SF 1 "vector_move_operand"  "xmC")
9591169699Skan	   (match_operand:SF 2 "register_operand"       "0")
9592169699Skan	   (match_operand:V4SF 3 "nonimmediate_operand" "xm")]
9593169699Skan	  UNSPEC_COPYSIGN))]
9594169699Skan  "TARGET_SSE_MATH"
9595169699Skan  "#"
9596169699Skan  "&& reload_completed"
9597169699Skan  [(const_int 0)]
959818334Speter{
9599169699Skan  ix86_split_copysign_const (operands);
9600169699Skan  DONE;
960190286Sobrien})
960218334Speter
9603169699Skan(define_insn "copysignsf3_var"
9604169699Skan  [(set (match_operand:SF 0 "register_operand"          "=x, x, x, x,x")
9605169699Skan	(unspec:SF
9606169699Skan	  [(match_operand:SF 2 "register_operand"       " x, 0, 0, x,x")
9607169699Skan	   (match_operand:SF 3 "register_operand"       " 1, 1, x, 1,x")
9608169699Skan	   (match_operand:V4SF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
9609169699Skan	   (match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
9610169699Skan	  UNSPEC_COPYSIGN))
9611169699Skan   (clobber (match_scratch:V4SF 1			"=x, x, x, x,x"))]
9612169699Skan  "TARGET_SSE_MATH"
961390286Sobrien  "#")
961418334Speter
961590286Sobrien(define_split
9616169699Skan  [(set (match_operand:SF 0 "register_operand" "")
9617169699Skan	(unspec:SF
9618169699Skan	  [(match_operand:SF 2 "register_operand" "")
9619169699Skan	   (match_operand:SF 3 "register_operand" "")
9620169699Skan	   (match_operand:V4SF 4 "" "")
9621169699Skan	   (match_operand:V4SF 5 "" "")]
9622169699Skan	  UNSPEC_COPYSIGN))
9623169699Skan   (clobber (match_scratch:V4SF 1 ""))]
9624169699Skan  "TARGET_SSE_MATH && reload_completed"
9625169699Skan  [(const_int 0)]
962690286Sobrien{
9627169699Skan  ix86_split_copysign_var (operands);
9628169699Skan  DONE;
962990286Sobrien})
963090286Sobrien
963190286Sobrien(define_expand "negdf2"
9632169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "")
9633169699Skan	(neg:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
9634146906Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
9635169699Skan  "ix86_expand_fp_absneg_operator (NEG, DFmode, operands); DONE;")
963618334Speter
9637169699Skan(define_expand "absdf2"
9638169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "")
9639169699Skan	(abs:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
9640169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
9641169699Skan  "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
964218334Speter
9643169699Skan(define_insn "*absnegdf2_mixed"
9644169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,f,rm")
9645169699Skan	(match_operator:DF 3 "absneg_operator"
9646169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0,0")]))
9647169699Skan   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X,X"))
9648169699Skan   (clobber (reg:CC FLAGS_REG))]
9649169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
9650169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
965190286Sobrien  "#")
965250650Sobrien
9653169699Skan(define_insn "*absnegdf2_sse"
9654169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,rm")
9655169699Skan	(match_operator:DF 3 "absneg_operator"
9656169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0 ")]))
9657169699Skan   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X "))
9658169699Skan   (clobber (reg:CC FLAGS_REG))]
9659169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
9660169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
966190286Sobrien  "#")
966250650Sobrien
9663169699Skan(define_insn "*absnegdf2_i387"
9664169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,rm")
9665169699Skan	(match_operator:DF 3 "absneg_operator"
9666169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0,0")]))
9667169699Skan   (use (match_operand 2 "" ""))
9668169699Skan   (clobber (reg:CC FLAGS_REG))]
9669169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
9670169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
967190286Sobrien  "#")
967218334Speter
9673169699Skan(define_expand "copysigndf3"
9674169699Skan  [(match_operand:DF 0 "register_operand" "")
9675169699Skan   (match_operand:DF 1 "nonmemory_operand" "")
9676169699Skan   (match_operand:DF 2 "register_operand" "")]
9677169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9678169699Skan{
9679169699Skan  ix86_expand_copysign (operands);
9680169699Skan  DONE;
9681169699Skan})
968250650Sobrien
9683169699Skan(define_insn_and_split "copysigndf3_const"
9684169699Skan  [(set (match_operand:DF 0 "register_operand"          "=x")
9685169699Skan	(unspec:DF
9686169699Skan	  [(match_operand:V2DF 1 "vector_move_operand"  "xmC")
9687169699Skan	   (match_operand:DF 2 "register_operand"       "0")
9688169699Skan	   (match_operand:V2DF 3 "nonimmediate_operand" "xm")]
9689169699Skan	  UNSPEC_COPYSIGN))]
9690169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9691169699Skan  "#"
9692169699Skan  "&& reload_completed"
9693169699Skan  [(const_int 0)]
9694169699Skan{
9695169699Skan  ix86_split_copysign_const (operands);
9696169699Skan  DONE;
9697169699Skan})
969850650Sobrien
9699169699Skan(define_insn "copysigndf3_var"
9700169699Skan  [(set (match_operand:DF 0 "register_operand"          "=x, x, x, x,x")
9701169699Skan	(unspec:DF
9702169699Skan	  [(match_operand:DF 2 "register_operand"       " x, 0, 0, x,x")
9703169699Skan	   (match_operand:DF 3 "register_operand"       " 1, 1, x, 1,x")
9704169699Skan	   (match_operand:V2DF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
9705169699Skan	   (match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
9706169699Skan	  UNSPEC_COPYSIGN))
9707169699Skan   (clobber (match_scratch:V2DF 1			"=x, x, x, x,x"))]
9708169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9709169699Skan  "#")
971052296Sobrien
971190286Sobrien(define_split
971290286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
9713169699Skan	(unspec:DF
9714169699Skan	  [(match_operand:DF 2 "register_operand" "")
9715169699Skan	   (match_operand:DF 3 "register_operand" "")
9716169699Skan	   (match_operand:V2DF 4 "" "")
9717169699Skan	   (match_operand:V2DF 5 "" "")]
9718169699Skan	  UNSPEC_COPYSIGN))
9719169699Skan   (clobber (match_scratch:V2DF 1 ""))]
9720169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
9721169699Skan  [(const_int 0)]
972290286Sobrien{
9723169699Skan  ix86_split_copysign_var (operands);
9724169699Skan  DONE;
972590286Sobrien})
972652296Sobrien
972790286Sobrien(define_expand "negxf2"
9728169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "")
9729169699Skan	(neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
9730132727Skan  "TARGET_80387"
9731169699Skan  "ix86_expand_fp_absneg_operator (NEG, XFmode, operands); DONE;")
973218334Speter
9733169699Skan(define_expand "absxf2"
9734169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "")
9735169699Skan	(abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
973618334Speter  "TARGET_80387"
9737169699Skan  "ix86_expand_fp_absneg_operator (ABS, XFmode, operands); DONE;")
973818334Speter
9739169699Skan(define_insn "*absnegxf2_i387"
9740169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,?rm")
9741169699Skan	(match_operator:XF 3 "absneg_operator"
9742169699Skan	  [(match_operand:XF 1 "nonimmediate_operand" "0,0")]))
9743169699Skan   (use (match_operand 2 "" ""))
9744169699Skan   (clobber (reg:CC FLAGS_REG))]
9745169699Skan  "TARGET_80387
9746169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), XFmode, operands)"
974790286Sobrien  "#")
974890286Sobrien
9749169699Skan;; Splitters for fp abs and neg.
975090286Sobrien
975190286Sobrien(define_split
9752169699Skan  [(set (match_operand 0 "fp_register_operand" "")
9753169699Skan	(match_operator 1 "absneg_operator" [(match_dup 0)]))
9754169699Skan   (use (match_operand 2 "" ""))
9755169699Skan   (clobber (reg:CC FLAGS_REG))]
9756169699Skan  "reload_completed"
9757169699Skan  [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))])
975890286Sobrien
975990286Sobrien(define_split
9760169699Skan  [(set (match_operand 0 "register_operand" "")
9761169699Skan	(match_operator 3 "absneg_operator"
9762169699Skan	  [(match_operand 1 "register_operand" "")]))
9763169699Skan   (use (match_operand 2 "nonimmediate_operand" ""))
9764169699Skan   (clobber (reg:CC FLAGS_REG))]
976590286Sobrien  "reload_completed && SSE_REG_P (operands[0])"
9766169699Skan  [(set (match_dup 0) (match_dup 3))]
9767132727Skan{
9768169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
9769169699Skan  enum machine_mode vmode = GET_MODE (operands[2]);
9770169699Skan  rtx tmp;
9771169699Skan  
9772169699Skan  operands[0] = simplify_gen_subreg (vmode, operands[0], mode, 0);
9773169699Skan  operands[1] = simplify_gen_subreg (vmode, operands[1], mode, 0);
9774132727Skan  if (operands_match_p (operands[0], operands[2]))
9775132727Skan    {
9776132727Skan      tmp = operands[1];
9777132727Skan      operands[1] = operands[2];
9778132727Skan      operands[2] = tmp;
9779132727Skan    }
9780169699Skan  if (GET_CODE (operands[3]) == ABS)
9781169699Skan    tmp = gen_rtx_AND (vmode, operands[1], operands[2]);
9782169699Skan  else
9783169699Skan    tmp = gen_rtx_XOR (vmode, operands[1], operands[2]);
9784169699Skan  operands[3] = tmp;
9785132727Skan})
978690286Sobrien
978790286Sobrien(define_split
9788169699Skan  [(set (match_operand:SF 0 "register_operand" "")
9789169699Skan	(match_operator:SF 1 "absneg_operator" [(match_dup 0)]))
9790169699Skan   (use (match_operand:V4SF 2 "" ""))
9791169699Skan   (clobber (reg:CC FLAGS_REG))]
9792169699Skan  "reload_completed"
9793169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9794169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9795169699Skan{ 
9796169699Skan  rtx tmp;
9797169699Skan  operands[0] = gen_lowpart (SImode, operands[0]);
9798169699Skan  if (GET_CODE (operands[1]) == ABS)
9799169699Skan    {
9800169699Skan      tmp = gen_int_mode (0x7fffffff, SImode);
9801169699Skan      tmp = gen_rtx_AND (SImode, operands[0], tmp);
9802169699Skan    }
9803169699Skan  else
9804169699Skan    {
9805169699Skan      tmp = gen_int_mode (0x80000000, SImode);
9806169699Skan      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9807169699Skan    }
9808169699Skan  operands[1] = tmp;
9809169699Skan})
981090286Sobrien
981190286Sobrien(define_split
9812169699Skan  [(set (match_operand:DF 0 "register_operand" "")
9813169699Skan	(match_operator:DF 1 "absneg_operator" [(match_dup 0)]))
9814169699Skan   (use (match_operand 2 "" ""))
9815169699Skan   (clobber (reg:CC FLAGS_REG))]
9816169699Skan  "reload_completed"
9817169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9818169699Skan	      (clobber (reg:CC FLAGS_REG))])]
981990286Sobrien{
9820169699Skan  rtx tmp;
9821169699Skan  if (TARGET_64BIT)
9822169699Skan    {
9823169699Skan      tmp = gen_lowpart (DImode, operands[0]);
9824169699Skan      tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63));
9825169699Skan      operands[0] = tmp;
982690286Sobrien
9827169699Skan      if (GET_CODE (operands[1]) == ABS)
9828169699Skan	tmp = const0_rtx;
9829169699Skan      else
9830169699Skan	tmp = gen_rtx_NOT (DImode, tmp);
9831169699Skan    }
9832169699Skan  else
9833169699Skan    {
9834169699Skan      operands[0] = gen_highpart (SImode, operands[0]);
9835169699Skan      if (GET_CODE (operands[1]) == ABS)
983690286Sobrien	{
9837169699Skan	  tmp = gen_int_mode (0x7fffffff, SImode);
9838169699Skan	  tmp = gen_rtx_AND (SImode, operands[0], tmp);
983990286Sobrien	}
9840169699Skan      else
9841169699Skan	{
9842169699Skan	  tmp = gen_int_mode (0x80000000, SImode);
9843169699Skan	  tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9844169699Skan	}
9845169699Skan    }
9846169699Skan  operands[1] = tmp;
9847169699Skan})
984890286Sobrien
984990286Sobrien(define_split
9850169699Skan  [(set (match_operand:XF 0 "register_operand" "")
9851169699Skan	(match_operator:XF 1 "absneg_operator" [(match_dup 0)]))
9852169699Skan   (use (match_operand 2 "" ""))
9853169699Skan   (clobber (reg:CC FLAGS_REG))]
9854169699Skan  "reload_completed"
9855169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9856169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9857169699Skan{
9858169699Skan  rtx tmp;
9859169699Skan  operands[0] = gen_rtx_REG (SImode,
9860169699Skan			     true_regnum (operands[0])
9861169699Skan			     + (TARGET_64BIT ? 1 : 2));
9862169699Skan  if (GET_CODE (operands[1]) == ABS)
9863169699Skan    {
9864169699Skan      tmp = GEN_INT (0x7fff);
9865169699Skan      tmp = gen_rtx_AND (SImode, operands[0], tmp);
9866169699Skan    }
9867169699Skan  else
9868169699Skan    {
9869169699Skan      tmp = GEN_INT (0x8000);
9870169699Skan      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9871169699Skan    }
9872169699Skan  operands[1] = tmp;
9873169699Skan})
987490286Sobrien
987590286Sobrien(define_split
9876169699Skan  [(set (match_operand 0 "memory_operand" "")
9877169699Skan	(match_operator 1 "absneg_operator" [(match_dup 0)]))
9878169699Skan   (use (match_operand 2 "" ""))
9879169699Skan   (clobber (reg:CC FLAGS_REG))]
9880169699Skan  "reload_completed"
9881169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9882169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9883169699Skan{
9884169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
9885169699Skan  int size = mode == XFmode ? 10 : GET_MODE_SIZE (mode);
9886169699Skan  rtx tmp;
988790286Sobrien
9888169699Skan  operands[0] = adjust_address (operands[0], QImode, size - 1);
9889169699Skan  if (GET_CODE (operands[1]) == ABS)
9890132727Skan    {
9891169699Skan      tmp = gen_int_mode (0x7f, QImode);
9892169699Skan      tmp = gen_rtx_AND (QImode, operands[0], tmp);
9893132727Skan    }
9894169699Skan  else
9895169699Skan    {
9896169699Skan      tmp = gen_int_mode (0x80, QImode);
9897169699Skan      tmp = gen_rtx_XOR (QImode, operands[0], tmp);
9898169699Skan    }
9899169699Skan  operands[1] = tmp;
9900132727Skan})
990190286Sobrien
9902169699Skan;; Conditionalize these after reload. If they match before reload, we 
9903169699Skan;; lose the clobber and ability to use integer instructions.
990490286Sobrien
9905169699Skan(define_insn "*negsf2_1"
9906169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
9907169699Skan	(neg:SF (match_operand:SF 1 "register_operand" "0")))]
9908169699Skan  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
9909169699Skan  "fchs"
9910169699Skan  [(set_attr "type" "fsgn")
9911169699Skan   (set_attr "mode" "SF")])
991290286Sobrien
9913169699Skan(define_insn "*negdf2_1"
9914169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
9915169699Skan	(neg:DF (match_operand:DF 1 "register_operand" "0")))]
9916169699Skan  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
9917169699Skan  "fchs"
9918169699Skan  [(set_attr "type" "fsgn")
9919169699Skan   (set_attr "mode" "DF")])
992090286Sobrien
9921169699Skan(define_insn "*negxf2_1"
9922169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
9923169699Skan	(neg:XF (match_operand:XF 1 "register_operand" "0")))]
9924132727Skan  "TARGET_80387"
9925169699Skan  "fchs"
9926169699Skan  [(set_attr "type" "fsgn")
9927169699Skan   (set_attr "mode" "XF")])
992890286Sobrien
992990286Sobrien(define_insn "*abssf2_1"
993018334Speter  [(set (match_operand:SF 0 "register_operand" "=f")
993150650Sobrien	(abs:SF (match_operand:SF 1 "register_operand" "0")))]
9932169699Skan  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
993350650Sobrien  "fabs"
993490286Sobrien  [(set_attr "type" "fsgn")
993590286Sobrien   (set_attr "mode" "SF")])
993618334Speter
993790286Sobrien(define_insn "*absdf2_1"
993818334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
993950650Sobrien	(abs:DF (match_operand:DF 1 "register_operand" "0")))]
9940169699Skan  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
994150650Sobrien  "fabs"
994290286Sobrien  [(set_attr "type" "fsgn")
994390286Sobrien   (set_attr "mode" "DF")])
994418334Speter
9945169699Skan(define_insn "*absxf2_1"
9946169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
9947169699Skan	(abs:XF (match_operand:XF 1 "register_operand" "0")))]
994818334Speter  "TARGET_80387"
994950650Sobrien  "fabs"
995090286Sobrien  [(set_attr "type" "fsgn")
995190286Sobrien   (set_attr "mode" "DF")])
995218334Speter
9953169699Skan(define_insn "*negextendsfdf2"
9954169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
9955169699Skan	(neg:DF (float_extend:DF
9956169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
9957169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
9958169699Skan  "fchs"
9959169699Skan  [(set_attr "type" "fsgn")
9960169699Skan   (set_attr "mode" "DF")])
9961169699Skan
9962169699Skan(define_insn "*negextenddfxf2"
996318334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
9964169699Skan	(neg:XF (float_extend:XF
9965169699Skan		  (match_operand:DF 1 "register_operand" "0"))))]
9966169699Skan  "TARGET_80387"
9967169699Skan  "fchs"
9968169699Skan  [(set_attr "type" "fsgn")
9969169699Skan   (set_attr "mode" "XF")])
9970169699Skan
9971169699Skan(define_insn "*negextendsfxf2"
9972169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
9973169699Skan	(neg:XF (float_extend:XF
9974169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
9975169699Skan  "TARGET_80387"
9976169699Skan  "fchs"
9977169699Skan  [(set_attr "type" "fsgn")
9978169699Skan   (set_attr "mode" "XF")])
9979169699Skan
9980169699Skan(define_insn "*absextendsfdf2"
9981169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
9982169699Skan	(abs:DF (float_extend:DF
9983169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
9984169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
998550650Sobrien  "fabs"
998690286Sobrien  [(set_attr "type" "fsgn")
998790286Sobrien   (set_attr "mode" "DF")])
998818334Speter
998990286Sobrien(define_insn "*absextenddfxf2"
999018334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
999190286Sobrien	(abs:XF (float_extend:XF
999290286Sobrien	  (match_operand:DF 1 "register_operand" "0"))))]
9993132727Skan  "TARGET_80387"
999450650Sobrien  "fabs"
999590286Sobrien  [(set_attr "type" "fsgn")
999690286Sobrien   (set_attr "mode" "XF")])
999718334Speter
999890286Sobrien(define_insn "*absextendsfxf2"
999990286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1000090286Sobrien	(abs:XF (float_extend:XF
1000190286Sobrien	  (match_operand:SF 1 "register_operand" "0"))))]
1000290286Sobrien  "TARGET_80387"
1000390286Sobrien  "fabs"
1000490286Sobrien  [(set_attr "type" "fsgn")
1000590286Sobrien   (set_attr "mode" "XF")])
1000690286Sobrien
1000790286Sobrien;; One complement instructions
1000818334Speter
1000990286Sobrien(define_expand "one_cmpldi2"
1001090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
1001190286Sobrien	(not:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
1001290286Sobrien  "TARGET_64BIT"
1001390286Sobrien  "ix86_expand_unary_operator (NOT, DImode, operands); DONE;")
1001418334Speter
1001590286Sobrien(define_insn "*one_cmpldi2_1_rex64"
1001690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1001790286Sobrien	(not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
1001890286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NOT, DImode, operands)"
1001990286Sobrien  "not{q}\t%0"
1002090286Sobrien  [(set_attr "type" "negnot")
1002190286Sobrien   (set_attr "mode" "DI")])
1002218334Speter
1002390286Sobrien(define_insn "*one_cmpldi2_2_rex64"
10024169699Skan  [(set (reg FLAGS_REG)
1002590286Sobrien	(compare (not:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
1002690286Sobrien		 (const_int 0)))
1002790286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1002890286Sobrien	(not:DI (match_dup 1)))]
1002990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
1003090286Sobrien   && ix86_unary_operator_ok (NOT, DImode, operands)"
1003190286Sobrien  "#"
1003290286Sobrien  [(set_attr "type" "alu1")
1003390286Sobrien   (set_attr "mode" "DI")])
1003418334Speter
1003590286Sobrien(define_split
10036146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10037146906Skan	(match_operator 2 "compare_operator"
10038146906Skan	  [(not:DI (match_operand:DI 3 "nonimmediate_operand" ""))
10039146906Skan	   (const_int 0)]))
10040146906Skan   (set (match_operand:DI 1 "nonimmediate_operand" "")
10041146906Skan	(not:DI (match_dup 3)))]
1004290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
10043146906Skan  [(parallel [(set (match_dup 0)
10044146906Skan		   (match_op_dup 2
10045146906Skan		     [(xor:DI (match_dup 3) (const_int -1))
10046146906Skan		      (const_int 0)]))
10047146906Skan	      (set (match_dup 1)
10048146906Skan		   (xor:DI (match_dup 3) (const_int -1)))])]
1004990286Sobrien  "")
1005018334Speter
1005190286Sobrien(define_expand "one_cmplsi2"
1005290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1005390286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
1005490286Sobrien  ""
1005590286Sobrien  "ix86_expand_unary_operator (NOT, SImode, operands); DONE;")
1005618334Speter
1005790286Sobrien(define_insn "*one_cmplsi2_1"
1005890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1005990286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
1006090286Sobrien  "ix86_unary_operator_ok (NOT, SImode, operands)"
1006190286Sobrien  "not{l}\t%0"
1006290286Sobrien  [(set_attr "type" "negnot")
1006390286Sobrien   (set_attr "mode" "SI")])
1006418334Speter
1006590286Sobrien;; ??? Currently never generated - xor is used instead.
1006690286Sobrien(define_insn "*one_cmplsi2_1_zext"
1006790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1006890286Sobrien	(zero_extend:DI (not:SI (match_operand:SI 1 "register_operand" "0"))))]
1006990286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NOT, SImode, operands)"
1007090286Sobrien  "not{l}\t%k0"
1007190286Sobrien  [(set_attr "type" "negnot")
1007290286Sobrien   (set_attr "mode" "SI")])
1007318334Speter
1007490286Sobrien(define_insn "*one_cmplsi2_2"
10075169699Skan  [(set (reg FLAGS_REG)
1007690286Sobrien	(compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
1007790286Sobrien		 (const_int 0)))
1007890286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1007990286Sobrien	(not:SI (match_dup 1)))]
1008090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1008190286Sobrien   && ix86_unary_operator_ok (NOT, SImode, operands)"
1008290286Sobrien  "#"
1008390286Sobrien  [(set_attr "type" "alu1")
1008490286Sobrien   (set_attr "mode" "SI")])
1008518334Speter
1008690286Sobrien(define_split
10087146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10088146906Skan	(match_operator 2 "compare_operator"
10089146906Skan	  [(not:SI (match_operand:SI 3 "nonimmediate_operand" ""))
10090146906Skan	   (const_int 0)]))
10091146906Skan   (set (match_operand:SI 1 "nonimmediate_operand" "")
10092146906Skan	(not:SI (match_dup 3)))]
1009390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10094146906Skan  [(parallel [(set (match_dup 0)
10095146906Skan		   (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
10096146906Skan				    (const_int 0)]))
10097146906Skan	      (set (match_dup 1)
10098146906Skan		   (xor:SI (match_dup 3) (const_int -1)))])]
1009990286Sobrien  "")
1010018334Speter
1010190286Sobrien;; ??? Currently never generated - xor is used instead.
1010290286Sobrien(define_insn "*one_cmplsi2_2_zext"
10103169699Skan  [(set (reg FLAGS_REG)
1010490286Sobrien	(compare (not:SI (match_operand:SI 1 "register_operand" "0"))
1010590286Sobrien		 (const_int 0)))
1010690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1010790286Sobrien	(zero_extend:DI (not:SI (match_dup 1))))]
1010890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
1010990286Sobrien   && ix86_unary_operator_ok (NOT, SImode, operands)"
1011090286Sobrien  "#"
1011190286Sobrien  [(set_attr "type" "alu1")
1011290286Sobrien   (set_attr "mode" "SI")])
1011318334Speter
1011490286Sobrien(define_split
10115146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10116146906Skan	(match_operator 2 "compare_operator"
10117146906Skan	  [(not:SI (match_operand:SI 3 "register_operand" ""))
10118146906Skan	   (const_int 0)]))
10119146906Skan   (set (match_operand:DI 1 "register_operand" "")
10120146906Skan	(zero_extend:DI (not:SI (match_dup 3))))]
1012190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10122146906Skan  [(parallel [(set (match_dup 0)
10123146906Skan		   (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
10124146906Skan				    (const_int 0)]))
10125146906Skan	      (set (match_dup 1)
10126146906Skan		   (zero_extend:DI (xor:SI (match_dup 3) (const_int -1))))])]
1012790286Sobrien  "")
1012818334Speter
1012990286Sobrien(define_expand "one_cmplhi2"
1013090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1013190286Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
1013290286Sobrien  "TARGET_HIMODE_MATH"
1013390286Sobrien  "ix86_expand_unary_operator (NOT, HImode, operands); DONE;")
1013452296Sobrien
1013590286Sobrien(define_insn "*one_cmplhi2_1"
1013650650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1013750650Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
1013890286Sobrien  "ix86_unary_operator_ok (NOT, HImode, operands)"
1013990286Sobrien  "not{w}\t%0"
1014090286Sobrien  [(set_attr "type" "negnot")
1014190286Sobrien   (set_attr "mode" "HI")])
1014218334Speter
1014390286Sobrien(define_insn "*one_cmplhi2_2"
10144169699Skan  [(set (reg FLAGS_REG)
1014590286Sobrien	(compare (not:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
1014690286Sobrien		 (const_int 0)))
1014790286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1014890286Sobrien	(not:HI (match_dup 1)))]
1014990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1015090286Sobrien   && ix86_unary_operator_ok (NEG, HImode, operands)"
1015190286Sobrien  "#"
1015290286Sobrien  [(set_attr "type" "alu1")
1015390286Sobrien   (set_attr "mode" "HI")])
1015452296Sobrien
1015590286Sobrien(define_split
10156146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10157146906Skan	(match_operator 2 "compare_operator"
10158146906Skan	  [(not:HI (match_operand:HI 3 "nonimmediate_operand" ""))
10159146906Skan	   (const_int 0)]))
10160146906Skan   (set (match_operand:HI 1 "nonimmediate_operand" "")
10161146906Skan	(not:HI (match_dup 3)))]
1016290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10163146906Skan  [(parallel [(set (match_dup 0)
10164146906Skan		   (match_op_dup 2 [(xor:HI (match_dup 3) (const_int -1))
10165146906Skan		      		    (const_int 0)]))
10166146906Skan	      (set (match_dup 1)
10167146906Skan		   (xor:HI (match_dup 3) (const_int -1)))])]
1016890286Sobrien  "")
1016952296Sobrien
1017090286Sobrien;; %%% Potential partial reg stall on alternative 1.  What to do?
1017190286Sobrien(define_expand "one_cmplqi2"
1017290286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1017390286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
1017490286Sobrien  "TARGET_QIMODE_MATH"
1017590286Sobrien  "ix86_expand_unary_operator (NOT, QImode, operands); DONE;")
1017690286Sobrien
1017790286Sobrien(define_insn "*one_cmplqi2_1"
1017890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
1017990286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))]
1018090286Sobrien  "ix86_unary_operator_ok (NOT, QImode, operands)"
1018190286Sobrien  "@
1018290286Sobrien   not{b}\t%0
1018390286Sobrien   not{l}\t%k0"
1018490286Sobrien  [(set_attr "type" "negnot")
1018590286Sobrien   (set_attr "mode" "QI,SI")])
1018690286Sobrien
1018790286Sobrien(define_insn "*one_cmplqi2_2"
10188169699Skan  [(set (reg FLAGS_REG)
1018990286Sobrien	(compare (not:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
1019090286Sobrien		 (const_int 0)))
1019190286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1019290286Sobrien	(not:QI (match_dup 1)))]
1019390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1019490286Sobrien   && ix86_unary_operator_ok (NOT, QImode, operands)"
1019590286Sobrien  "#"
1019690286Sobrien  [(set_attr "type" "alu1")
1019790286Sobrien   (set_attr "mode" "QI")])
1019890286Sobrien
1019990286Sobrien(define_split
10200146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10201146906Skan	(match_operator 2 "compare_operator"
10202146906Skan	  [(not:QI (match_operand:QI 3 "nonimmediate_operand" ""))
10203146906Skan	   (const_int 0)]))
10204146906Skan   (set (match_operand:QI 1 "nonimmediate_operand" "")
10205146906Skan	(not:QI (match_dup 3)))]
1020690286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10207146906Skan  [(parallel [(set (match_dup 0)
10208146906Skan		   (match_op_dup 2 [(xor:QI (match_dup 3) (const_int -1))
10209146906Skan		      		    (const_int 0)]))
10210146906Skan	      (set (match_dup 1)
10211146906Skan		   (xor:QI (match_dup 3) (const_int -1)))])]
1021290286Sobrien  "")
1021318334Speter
1021490286Sobrien;; Arithmetic shift instructions
1021518334Speter
1021618334Speter;; DImode shifts are implemented using the i386 "shift double" opcode,
1021718334Speter;; which is written as "sh[lr]d[lw] imm,reg,reg/mem".  If the shift count
1021818334Speter;; is variable, then the count is in %cl and the "imm" operand is dropped
1021918334Speter;; from the assembler input.
1022090286Sobrien;;
1022118334Speter;; This instruction shifts the target reg/mem as usual, but instead of
1022218334Speter;; shifting in zeros, bits are shifted in from reg operand.  If the insn
1022318334Speter;; is a left shift double, bits are taken from the high order bits of
1022418334Speter;; reg, else if the insn is a shift right double, bits are taken from the
1022518334Speter;; low order bits of reg.  So if %eax is "1234" and %edx is "5678",
1022618334Speter;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
1022790286Sobrien;;
1022818334Speter;; Since sh[lr]d does not change the `reg' operand, that is done
1022918334Speter;; separately, making all shifts emit pairs of shift double and normal
1023018334Speter;; shift.  Since sh[lr]d does not shift more than 31 bits, and we wish to
1023118334Speter;; support a 63 bit shift, each shift where the count is in a reg expands
1023250650Sobrien;; to a pair of shifts, a branch, a shift by 32 and a label.
1023390286Sobrien;;
1023418334Speter;; If the shift count is a constant, we need never emit more than one
1023518334Speter;; shift pair, instead using moves and sign extension for counts greater
1023618334Speter;; than 31.
1023718334Speter
10238169699Skan(define_expand "ashlti3"
10239169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
10240169699Skan		   (ashift:TI (match_operand:TI 1 "register_operand" "")
1024190286Sobrien			      (match_operand:QI 2 "nonmemory_operand" "")))
10242169699Skan	      (clobber (reg:CC FLAGS_REG))])]
10243169699Skan  "TARGET_64BIT"
1024418334Speter{
10245169699Skan  if (! immediate_operand (operands[2], QImode))
1024618334Speter    {
10247169699Skan      emit_insn (gen_ashlti3_1 (operands[0], operands[1], operands[2]));
1024890286Sobrien      DONE;
1024918334Speter    }
10250169699Skan  ix86_expand_binary_operator (ASHIFT, TImode, operands);
1025118334Speter  DONE;
1025290286Sobrien})
1025318334Speter
10254169699Skan(define_insn "ashlti3_1"
10255169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
10256169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "0")
10257169699Skan		   (match_operand:QI 2 "register_operand" "c")))
10258169699Skan   (clobber (match_scratch:DI 3 "=&r"))
10259169699Skan   (clobber (reg:CC FLAGS_REG))]
10260169699Skan  "TARGET_64BIT"
10261169699Skan  "#"
10262169699Skan  [(set_attr "type" "multi")])
10263169699Skan
10264169699Skan(define_insn "*ashlti3_2"
10265169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
10266169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "0")
10267169699Skan		   (match_operand:QI 2 "immediate_operand" "O")))
10268169699Skan   (clobber (reg:CC FLAGS_REG))]
10269169699Skan  "TARGET_64BIT"
10270169699Skan  "#"
10271169699Skan  [(set_attr "type" "multi")])
10272169699Skan
10273169699Skan(define_split
10274169699Skan  [(set (match_operand:TI 0 "register_operand" "")
10275169699Skan	(ashift:TI (match_operand:TI 1 "nonmemory_operand" "")
10276169699Skan		   (match_operand:QI 2 "register_operand" "")))
10277169699Skan   (clobber (match_scratch:DI 3 ""))
10278169699Skan   (clobber (reg:CC FLAGS_REG))]
10279169699Skan  "TARGET_64BIT && reload_completed"
10280169699Skan  [(const_int 0)]
10281169699Skan  "ix86_split_ashl (operands, operands[3], TImode); DONE;")
10282169699Skan
10283169699Skan(define_split
10284169699Skan  [(set (match_operand:TI 0 "register_operand" "")
10285169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "")
10286169699Skan		   (match_operand:QI 2 "immediate_operand" "")))
10287169699Skan   (clobber (reg:CC FLAGS_REG))]
10288169699Skan  "TARGET_64BIT && reload_completed"
10289169699Skan  [(const_int 0)]
10290169699Skan  "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;")
10291169699Skan
10292169699Skan(define_insn "x86_64_shld"
10293169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
10294169699Skan        (ior:DI (ashift:DI (match_dup 0)
10295169699Skan		  (match_operand:QI 2 "nonmemory_operand" "J,c"))
10296169699Skan		(lshiftrt:DI (match_operand:DI 1 "register_operand" "r,r")
10297169699Skan		  (minus:QI (const_int 64) (match_dup 2)))))
10298169699Skan   (clobber (reg:CC FLAGS_REG))]
10299169699Skan  "TARGET_64BIT"
10300169699Skan  "@
10301169699Skan   shld{q}\t{%2, %1, %0|%0, %1, %2}
10302169699Skan   shld{q}\t{%s2%1, %0|%0, %1, %2}"
10303169699Skan  [(set_attr "type" "ishift")
10304169699Skan   (set_attr "prefix_0f" "1")
10305169699Skan   (set_attr "mode" "DI")
10306169699Skan   (set_attr "athlon_decode" "vector")])
10307169699Skan
10308169699Skan(define_expand "x86_64_shift_adj"
10309169699Skan  [(set (reg:CCZ FLAGS_REG)
10310169699Skan	(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
10311169699Skan			     (const_int 64))
10312169699Skan		     (const_int 0)))
10313169699Skan   (set (match_operand:DI 0 "register_operand" "")
10314169699Skan        (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
10315169699Skan			 (match_operand:DI 1 "register_operand" "")
10316169699Skan			 (match_dup 0)))
10317169699Skan   (set (match_dup 1)
10318169699Skan	(if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
10319169699Skan			 (match_operand:DI 3 "register_operand" "r")
10320169699Skan			 (match_dup 1)))]
10321169699Skan  "TARGET_64BIT"
10322169699Skan  "")
10323169699Skan
10324169699Skan(define_expand "ashldi3"
10325169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
10326169699Skan	(ashift:DI (match_operand:DI 1 "ashldi_input_operand" "")
10327169699Skan		   (match_operand:QI 2 "nonmemory_operand" "")))]
10328169699Skan  ""
10329169699Skan  "ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;")
10330169699Skan
1033190286Sobrien(define_insn "*ashldi3_1_rex64"
1033290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
10333169699Skan	(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,l")
1033490286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cJ,M")))
10335169699Skan   (clobber (reg:CC FLAGS_REG))]
1033690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
1033718334Speter{
1033890286Sobrien  switch (get_attr_type (insn))
1033990286Sobrien    {
1034090286Sobrien    case TYPE_ALU:
10341169699Skan      gcc_assert (operands[2] == const1_rtx);
10342169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
1034390286Sobrien      return "add{q}\t{%0, %0|%0, %0}";
1034418334Speter
1034590286Sobrien    case TYPE_LEA:
10346169699Skan      gcc_assert (GET_CODE (operands[2]) == CONST_INT);
10347169699Skan      gcc_assert ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) <= 3);
1034890286Sobrien      operands[1] = gen_rtx_MULT (DImode, operands[1],
1034990286Sobrien				  GEN_INT (1 << INTVAL (operands[2])));
1035090286Sobrien      return "lea{q}\t{%a1, %0|%0, %a1}";
1035118334Speter
1035290286Sobrien    default:
1035390286Sobrien      if (REG_P (operands[2]))
1035490286Sobrien	return "sal{q}\t{%b2, %0|%0, %b2}";
10355169699Skan      else if (operands[2] == const1_rtx
10356117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1035790286Sobrien	return "sal{q}\t%0";
1035890286Sobrien      else
1035990286Sobrien	return "sal{q}\t{%2, %0|%0, %2}";
1036090286Sobrien    }
1036190286Sobrien}
1036290286Sobrien  [(set (attr "type")
1036390286Sobrien     (cond [(eq_attr "alternative" "1")
1036490286Sobrien	      (const_string "lea")
1036590286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1036690286Sobrien		          (const_int 0))
1036790286Sobrien		      (match_operand 0 "register_operand" ""))
1036890286Sobrien		 (match_operand 2 "const1_operand" ""))
1036990286Sobrien	      (const_string "alu")
1037090286Sobrien	   ]
1037190286Sobrien	   (const_string "ishift")))
1037290286Sobrien   (set_attr "mode" "DI")])
1037318334Speter
1037490286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1037590286Sobrien(define_split
1037690286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
10377169699Skan	(ashift:DI (match_operand:DI 1 "index_register_operand" "")
1037890286Sobrien		   (match_operand:QI 2 "immediate_operand" "")))
10379169699Skan   (clobber (reg:CC FLAGS_REG))]
1038090286Sobrien  "TARGET_64BIT && reload_completed
1038190286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
1038290286Sobrien  [(set (match_dup 0)
1038390286Sobrien	(mult:DI (match_dup 1)
1038490286Sobrien		 (match_dup 2)))]
10385117404Skan  "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);")
1038690286Sobrien
1038790286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1038890286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1038990286Sobrien;; zero are optimized away.
1039090286Sobrien(define_insn "*ashldi3_cmp_rex64"
10391169699Skan  [(set (reg FLAGS_REG)
1039290286Sobrien	(compare
1039390286Sobrien	  (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1039490286Sobrien		     (match_operand:QI 2 "immediate_operand" "e"))
1039590286Sobrien	  (const_int 0)))
1039690286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1039790286Sobrien	(ashift:DI (match_dup 1) (match_dup 2)))]
1039890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10399169699Skan   && ix86_binary_operator_ok (ASHIFT, DImode, operands)
10400169699Skan   && (optimize_size
10401169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10402169699Skan       || (operands[2] == const1_rtx
10403169699Skan	   && (TARGET_SHIFT1
10404169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1040590286Sobrien{
1040690286Sobrien  switch (get_attr_type (insn))
1040718334Speter    {
1040890286Sobrien    case TYPE_ALU:
10409169699Skan      gcc_assert (operands[2] == const1_rtx);
1041090286Sobrien      return "add{q}\t{%0, %0|%0, %0}";
1041118334Speter
1041290286Sobrien    default:
1041390286Sobrien      if (REG_P (operands[2]))
1041490286Sobrien	return "sal{q}\t{%b2, %0|%0, %b2}";
10415169699Skan      else if (operands[2] == const1_rtx
10416117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1041790286Sobrien	return "sal{q}\t%0";
1041890286Sobrien      else
1041990286Sobrien	return "sal{q}\t{%2, %0|%0, %2}";
1042018334Speter    }
1042190286Sobrien}
1042290286Sobrien  [(set (attr "type")
1042390286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1042490286Sobrien		          (const_int 0))
1042590286Sobrien		      (match_operand 0 "register_operand" ""))
1042690286Sobrien		 (match_operand 2 "const1_operand" ""))
1042790286Sobrien	      (const_string "alu")
1042890286Sobrien	   ]
1042990286Sobrien	   (const_string "ishift")))
1043090286Sobrien   (set_attr "mode" "DI")])
1043118334Speter
10432169699Skan(define_insn "*ashldi3_cconly_rex64"
10433169699Skan  [(set (reg FLAGS_REG)
10434169699Skan	(compare
10435169699Skan	  (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
10436169699Skan		     (match_operand:QI 2 "immediate_operand" "e"))
10437169699Skan	  (const_int 0)))
10438169699Skan   (clobber (match_scratch:DI 0 "=r"))]
10439169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10440169699Skan   && ix86_binary_operator_ok (ASHIFT, DImode, operands)
10441169699Skan   && (optimize_size
10442169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10443169699Skan       || (operands[2] == const1_rtx
10444169699Skan	   && (TARGET_SHIFT1
10445169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10446169699Skan{
10447169699Skan  switch (get_attr_type (insn))
10448169699Skan    {
10449169699Skan    case TYPE_ALU:
10450169699Skan      gcc_assert (operands[2] == const1_rtx);
10451169699Skan      return "add{q}\t{%0, %0|%0, %0}";
1045290286Sobrien
10453169699Skan    default:
10454169699Skan      if (REG_P (operands[2]))
10455169699Skan	return "sal{q}\t{%b2, %0|%0, %b2}";
10456169699Skan      else if (operands[2] == const1_rtx
10457169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10458169699Skan	return "sal{q}\t%0";
10459169699Skan      else
10460169699Skan	return "sal{q}\t{%2, %0|%0, %2}";
10461169699Skan    }
10462169699Skan}
10463169699Skan  [(set (attr "type")
10464169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
10465169699Skan		          (const_int 0))
10466169699Skan		      (match_operand 0 "register_operand" ""))
10467169699Skan		 (match_operand 2 "const1_operand" ""))
10468169699Skan	      (const_string "alu")
10469169699Skan	   ]
10470169699Skan	   (const_string "ishift")))
10471169699Skan   (set_attr "mode" "DI")])
10472169699Skan
10473169699Skan(define_insn "*ashldi3_1"
10474169699Skan  [(set (match_operand:DI 0 "register_operand" "=&r,r")
10475169699Skan	(ashift:DI (match_operand:DI 1 "reg_or_pm1_operand" "n,0")
10476169699Skan		   (match_operand:QI 2 "nonmemory_operand" "Jc,Jc")))
10477169699Skan   (clobber (reg:CC FLAGS_REG))]
1047890286Sobrien  "!TARGET_64BIT"
1047990286Sobrien  "#"
1048090286Sobrien  [(set_attr "type" "multi")])
1048190286Sobrien
10482169699Skan;; By default we don't ask for a scratch register, because when DImode
10483169699Skan;; values are manipulated, registers are already at a premium.  But if
10484169699Skan;; we have one handy, we won't turn it away.
10485169699Skan(define_peephole2
10486169699Skan  [(match_scratch:SI 3 "r")
10487169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
10488169699Skan		   (ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
10489169699Skan			      (match_operand:QI 2 "nonmemory_operand" "")))
10490169699Skan	      (clobber (reg:CC FLAGS_REG))])
10491169699Skan   (match_dup 3)]
10492169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1049390286Sobrien  [(const_int 0)]
10494169699Skan  "ix86_split_ashl (operands, operands[3], DImode); DONE;")
1049590286Sobrien
1049690286Sobrien(define_split
1049790286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
10498169699Skan	(ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
1049990286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10500169699Skan   (clobber (reg:CC FLAGS_REG))]
10501169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
10502169699Skan		     ? flow2_completed : reload_completed)"
1050390286Sobrien  [(const_int 0)]
10504169699Skan  "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;")
1050590286Sobrien
1050690286Sobrien(define_insn "x86_shld_1"
1050790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
1050890286Sobrien        (ior:SI (ashift:SI (match_dup 0)
1050990286Sobrien		  (match_operand:QI 2 "nonmemory_operand" "I,c"))
1051090286Sobrien		(lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
1051190286Sobrien		  (minus:QI (const_int 32) (match_dup 2)))))
10512169699Skan   (clobber (reg:CC FLAGS_REG))]
1051318334Speter  ""
1051490286Sobrien  "@
1051590286Sobrien   shld{l}\t{%2, %1, %0|%0, %1, %2}
1051690286Sobrien   shld{l}\t{%s2%1, %0|%0, %1, %2}"
1051790286Sobrien  [(set_attr "type" "ishift")
1051890286Sobrien   (set_attr "prefix_0f" "1")
1051990286Sobrien   (set_attr "mode" "SI")
1052090286Sobrien   (set_attr "pent_pair" "np")
10521169699Skan   (set_attr "athlon_decode" "vector")])
1052290286Sobrien
1052390286Sobrien(define_expand "x86_shift_adj_1"
10524169699Skan  [(set (reg:CCZ FLAGS_REG)
1052590286Sobrien	(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
1052690286Sobrien			     (const_int 32))
1052790286Sobrien		     (const_int 0)))
1052890286Sobrien   (set (match_operand:SI 0 "register_operand" "")
10529169699Skan        (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
1053090286Sobrien			 (match_operand:SI 1 "register_operand" "")
1053190286Sobrien			 (match_dup 0)))
1053290286Sobrien   (set (match_dup 1)
10533169699Skan	(if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
1053490286Sobrien			 (match_operand:SI 3 "register_operand" "r")
1053590286Sobrien			 (match_dup 1)))]
1053690286Sobrien  "TARGET_CMOVE"
1053790286Sobrien  "")
1053890286Sobrien
1053990286Sobrien(define_expand "x86_shift_adj_2"
1054090286Sobrien  [(use (match_operand:SI 0 "register_operand" ""))
1054190286Sobrien   (use (match_operand:SI 1 "register_operand" ""))
1054290286Sobrien   (use (match_operand:QI 2 "register_operand" ""))]
1054390286Sobrien  ""
1054418334Speter{
1054590286Sobrien  rtx label = gen_label_rtx ();
1054690286Sobrien  rtx tmp;
1054718334Speter
1054890286Sobrien  emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
1054918334Speter
1055090286Sobrien  tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
1055190286Sobrien  tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1055290286Sobrien  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
1055390286Sobrien			      gen_rtx_LABEL_REF (VOIDmode, label),
1055490286Sobrien			      pc_rtx);
1055590286Sobrien  tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
1055690286Sobrien  JUMP_LABEL (tmp) = label;
1055718334Speter
1055890286Sobrien  emit_move_insn (operands[0], operands[1]);
10559169699Skan  ix86_expand_clear (operands[1]);
1056018334Speter
1056190286Sobrien  emit_label (label);
1056290286Sobrien  LABEL_NUSES (label) = 1;
1056390286Sobrien
1056490286Sobrien  DONE;
1056590286Sobrien})
1056690286Sobrien
1056752296Sobrien(define_expand "ashlsi3"
1056852296Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1056952296Sobrien	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
1057090286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10571169699Skan   (clobber (reg:CC FLAGS_REG))]
1057252296Sobrien  ""
1057390286Sobrien  "ix86_expand_binary_operator (ASHIFT, SImode, operands); DONE;")
1057418334Speter
1057590286Sobrien(define_insn "*ashlsi3_1"
1057690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
10577169699Skan	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,l")
1057890286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,M")))
10579169699Skan   (clobber (reg:CC FLAGS_REG))]
1058090286Sobrien  "ix86_binary_operator_ok (ASHIFT, SImode, operands)"
1058190286Sobrien{
1058290286Sobrien  switch (get_attr_type (insn))
1058390286Sobrien    {
1058490286Sobrien    case TYPE_ALU:
10585169699Skan      gcc_assert (operands[2] == const1_rtx);
10586169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
1058790286Sobrien      return "add{l}\t{%0, %0|%0, %0}";
1058890286Sobrien
1058990286Sobrien    case TYPE_LEA:
1059090286Sobrien      return "#";
1059190286Sobrien
1059290286Sobrien    default:
1059390286Sobrien      if (REG_P (operands[2]))
1059490286Sobrien	return "sal{l}\t{%b2, %0|%0, %b2}";
10595169699Skan      else if (operands[2] == const1_rtx
10596117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1059790286Sobrien	return "sal{l}\t%0";
1059890286Sobrien      else
1059990286Sobrien	return "sal{l}\t{%2, %0|%0, %2}";
1060090286Sobrien    }
1060190286Sobrien}
1060290286Sobrien  [(set (attr "type")
1060390286Sobrien     (cond [(eq_attr "alternative" "1")
1060490286Sobrien	      (const_string "lea")
1060590286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1060690286Sobrien		          (const_int 0))
1060790286Sobrien		      (match_operand 0 "register_operand" ""))
1060890286Sobrien		 (match_operand 2 "const1_operand" ""))
1060990286Sobrien	      (const_string "alu")
1061090286Sobrien	   ]
1061190286Sobrien	   (const_string "ishift")))
1061290286Sobrien   (set_attr "mode" "SI")])
1061390286Sobrien
1061490286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1061590286Sobrien(define_split
1061690286Sobrien  [(set (match_operand 0 "register_operand" "")
10617117404Skan	(ashift (match_operand 1 "index_register_operand" "")
1061890286Sobrien                (match_operand:QI 2 "const_int_operand" "")))
10619169699Skan   (clobber (reg:CC FLAGS_REG))]
1062090286Sobrien  "reload_completed
10621169699Skan   && true_regnum (operands[0]) != true_regnum (operands[1])
10622169699Skan   && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4"
1062390286Sobrien  [(const_int 0)]
1062490286Sobrien{
1062590286Sobrien  rtx pat;
10626169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
10627169699Skan
10628169699Skan  if (GET_MODE_SIZE (mode) < 4)
10629169699Skan    operands[0] = gen_lowpart (SImode, operands[0]);
10630169699Skan  if (mode != Pmode)
10631169699Skan    operands[1] = gen_lowpart (Pmode, operands[1]);
10632117404Skan  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
10633169699Skan
1063490286Sobrien  pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
1063590286Sobrien  if (Pmode != SImode)
1063690286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
1063790286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
1063890286Sobrien  DONE;
1063990286Sobrien})
1064090286Sobrien
10641117404Skan;; Rare case of shifting RSP is handled by generating move and shift
10642117404Skan(define_split
10643117404Skan  [(set (match_operand 0 "register_operand" "")
10644117404Skan	(ashift (match_operand 1 "register_operand" "")
10645117404Skan                (match_operand:QI 2 "const_int_operand" "")))
10646169699Skan   (clobber (reg:CC FLAGS_REG))]
10647117404Skan  "reload_completed
10648117404Skan   && true_regnum (operands[0]) != true_regnum (operands[1])"
10649117404Skan  [(const_int 0)]
10650117404Skan{
10651117404Skan  rtx pat, clob;
10652169699Skan  emit_move_insn (operands[0], operands[1]);
10653117404Skan  pat = gen_rtx_SET (VOIDmode, operands[0],
10654117404Skan		     gen_rtx_ASHIFT (GET_MODE (operands[0]),
10655117404Skan				     operands[0], operands[2]));
10656117404Skan  clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
10657117404Skan  emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob)));
10658117404Skan  DONE;
10659117404Skan})
10660117404Skan
1066190286Sobrien(define_insn "*ashlsi3_1_zext"
1066290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
10663169699Skan	(zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l")
1066490286Sobrien			(match_operand:QI 2 "nonmemory_operand" "cI,M"))))
10665169699Skan   (clobber (reg:CC FLAGS_REG))]
1066690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
1066790286Sobrien{
1066890286Sobrien  switch (get_attr_type (insn))
1066990286Sobrien    {
1067090286Sobrien    case TYPE_ALU:
10671169699Skan      gcc_assert (operands[2] == const1_rtx);
1067290286Sobrien      return "add{l}\t{%k0, %k0|%k0, %k0}";
1067390286Sobrien
1067490286Sobrien    case TYPE_LEA:
1067590286Sobrien      return "#";
1067690286Sobrien
1067790286Sobrien    default:
1067890286Sobrien      if (REG_P (operands[2]))
1067990286Sobrien	return "sal{l}\t{%b2, %k0|%k0, %b2}";
10680169699Skan      else if (operands[2] == const1_rtx
10681117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1068290286Sobrien	return "sal{l}\t%k0";
1068390286Sobrien      else
1068490286Sobrien	return "sal{l}\t{%2, %k0|%k0, %2}";
1068590286Sobrien    }
1068690286Sobrien}
1068790286Sobrien  [(set (attr "type")
1068890286Sobrien     (cond [(eq_attr "alternative" "1")
1068990286Sobrien	      (const_string "lea")
1069090286Sobrien            (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1069190286Sobrien		     (const_int 0))
1069290286Sobrien		 (match_operand 2 "const1_operand" ""))
1069390286Sobrien	      (const_string "alu")
1069490286Sobrien	   ]
1069590286Sobrien	   (const_string "ishift")))
1069690286Sobrien   (set_attr "mode" "SI")])
1069790286Sobrien
1069890286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1069990286Sobrien(define_split
1070090286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1070190286Sobrien	(zero_extend:DI (ashift (match_operand 1 "register_operand" "")
1070290286Sobrien				(match_operand:QI 2 "const_int_operand" ""))))
10703169699Skan   (clobber (reg:CC FLAGS_REG))]
10704132727Skan  "TARGET_64BIT && reload_completed
1070590286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
10706132727Skan  [(set (match_dup 0) (zero_extend:DI
10707132727Skan			(subreg:SI (mult:SI (match_dup 1)
10708132727Skan					    (match_dup 2)) 0)))]
1070990286Sobrien{
1071090286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
10711117404Skan  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
1071290286Sobrien})
1071390286Sobrien
1071490286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1071590286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1071690286Sobrien;; zero are optimized away.
1071790286Sobrien(define_insn "*ashlsi3_cmp"
10718169699Skan  [(set (reg FLAGS_REG)
1071990286Sobrien	(compare
1072090286Sobrien	  (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
10721169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1072290286Sobrien	  (const_int 0)))
1072390286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1072490286Sobrien	(ashift:SI (match_dup 1) (match_dup 2)))]
1072590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
10726169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10727169699Skan   && (optimize_size
10728169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10729169699Skan       || (operands[2] == const1_rtx
10730169699Skan	   && (TARGET_SHIFT1
10731169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1073290286Sobrien{
1073390286Sobrien  switch (get_attr_type (insn))
1073490286Sobrien    {
1073590286Sobrien    case TYPE_ALU:
10736169699Skan      gcc_assert (operands[2] == const1_rtx);
1073790286Sobrien      return "add{l}\t{%0, %0|%0, %0}";
1073890286Sobrien
1073990286Sobrien    default:
1074090286Sobrien      if (REG_P (operands[2]))
1074190286Sobrien	return "sal{l}\t{%b2, %0|%0, %b2}";
10742169699Skan      else if (operands[2] == const1_rtx
10743117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1074490286Sobrien	return "sal{l}\t%0";
1074590286Sobrien      else
1074690286Sobrien	return "sal{l}\t{%2, %0|%0, %2}";
1074790286Sobrien    }
1074890286Sobrien}
1074990286Sobrien  [(set (attr "type")
1075090286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1075190286Sobrien		          (const_int 0))
1075290286Sobrien		      (match_operand 0 "register_operand" ""))
1075390286Sobrien		 (match_operand 2 "const1_operand" ""))
1075490286Sobrien	      (const_string "alu")
1075590286Sobrien	   ]
1075690286Sobrien	   (const_string "ishift")))
1075790286Sobrien   (set_attr "mode" "SI")])
1075890286Sobrien
10759169699Skan(define_insn "*ashlsi3_cconly"
10760169699Skan  [(set (reg FLAGS_REG)
10761169699Skan	(compare
10762169699Skan	  (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
10763169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
10764169699Skan	  (const_int 0)))
10765169699Skan   (clobber (match_scratch:SI 0 "=r"))]
10766169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
10767169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10768169699Skan   && (optimize_size
10769169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10770169699Skan       || (operands[2] == const1_rtx
10771169699Skan	   && (TARGET_SHIFT1
10772169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10773169699Skan{
10774169699Skan  switch (get_attr_type (insn))
10775169699Skan    {
10776169699Skan    case TYPE_ALU:
10777169699Skan      gcc_assert (operands[2] == const1_rtx);
10778169699Skan      return "add{l}\t{%0, %0|%0, %0}";
10779169699Skan
10780169699Skan    default:
10781169699Skan      if (REG_P (operands[2]))
10782169699Skan	return "sal{l}\t{%b2, %0|%0, %b2}";
10783169699Skan      else if (operands[2] == const1_rtx
10784169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10785169699Skan	return "sal{l}\t%0";
10786169699Skan      else
10787169699Skan	return "sal{l}\t{%2, %0|%0, %2}";
10788169699Skan    }
10789169699Skan}
10790169699Skan  [(set (attr "type")
10791169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
10792169699Skan		          (const_int 0))
10793169699Skan		      (match_operand 0 "register_operand" ""))
10794169699Skan		 (match_operand 2 "const1_operand" ""))
10795169699Skan	      (const_string "alu")
10796169699Skan	   ]
10797169699Skan	   (const_string "ishift")))
10798169699Skan   (set_attr "mode" "SI")])
10799169699Skan
1080090286Sobrien(define_insn "*ashlsi3_cmp_zext"
10801169699Skan  [(set (reg FLAGS_REG)
1080290286Sobrien	(compare
1080390286Sobrien	  (ashift:SI (match_operand:SI 1 "register_operand" "0")
10804169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1080590286Sobrien	  (const_int 0)))
1080690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1080790286Sobrien	(zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
1080890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10809169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10810169699Skan   && (optimize_size
10811169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10812169699Skan       || (operands[2] == const1_rtx
10813169699Skan	   && (TARGET_SHIFT1
10814169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
1081590286Sobrien{
1081690286Sobrien  switch (get_attr_type (insn))
1081790286Sobrien    {
1081890286Sobrien    case TYPE_ALU:
10819169699Skan      gcc_assert (operands[2] == const1_rtx);
1082090286Sobrien      return "add{l}\t{%k0, %k0|%k0, %k0}";
1082190286Sobrien
1082290286Sobrien    default:
1082390286Sobrien      if (REG_P (operands[2]))
1082490286Sobrien	return "sal{l}\t{%b2, %k0|%k0, %b2}";
10825169699Skan      else if (operands[2] == const1_rtx
10826117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1082790286Sobrien	return "sal{l}\t%k0";
1082890286Sobrien      else
1082990286Sobrien	return "sal{l}\t{%2, %k0|%k0, %2}";
1083090286Sobrien    }
1083190286Sobrien}
1083290286Sobrien  [(set (attr "type")
1083390286Sobrien     (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1083490286Sobrien		     (const_int 0))
1083590286Sobrien		 (match_operand 2 "const1_operand" ""))
1083690286Sobrien	      (const_string "alu")
1083790286Sobrien	   ]
1083890286Sobrien	   (const_string "ishift")))
1083990286Sobrien   (set_attr "mode" "SI")])
1084090286Sobrien
1084152296Sobrien(define_expand "ashlhi3"
1084252296Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1084352296Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
1084490286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10845169699Skan   (clobber (reg:CC FLAGS_REG))]
1084690286Sobrien  "TARGET_HIMODE_MATH"
1084790286Sobrien  "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;")
1084818334Speter
1084990286Sobrien(define_insn "*ashlhi3_1_lea"
1085090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
10851169699Skan	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l")
1085290286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,M")))
10853169699Skan   (clobber (reg:CC FLAGS_REG))]
1085490286Sobrien  "!TARGET_PARTIAL_REG_STALL
1085590286Sobrien   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
1085690286Sobrien{
1085790286Sobrien  switch (get_attr_type (insn))
1085890286Sobrien    {
1085990286Sobrien    case TYPE_LEA:
1086090286Sobrien      return "#";
1086190286Sobrien    case TYPE_ALU:
10862169699Skan      gcc_assert (operands[2] == const1_rtx);
1086390286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1086490286Sobrien
1086590286Sobrien    default:
1086690286Sobrien      if (REG_P (operands[2]))
1086790286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10868169699Skan      else if (operands[2] == const1_rtx
10869117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1087090286Sobrien	return "sal{w}\t%0";
1087190286Sobrien      else
1087290286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1087390286Sobrien    }
1087490286Sobrien}
1087590286Sobrien  [(set (attr "type")
1087690286Sobrien     (cond [(eq_attr "alternative" "1")
1087790286Sobrien	      (const_string "lea")
1087890286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1087990286Sobrien		          (const_int 0))
1088090286Sobrien		      (match_operand 0 "register_operand" ""))
1088190286Sobrien		 (match_operand 2 "const1_operand" ""))
1088290286Sobrien	      (const_string "alu")
1088390286Sobrien	   ]
1088490286Sobrien	   (const_string "ishift")))
1088590286Sobrien   (set_attr "mode" "HI,SI")])
1088690286Sobrien
1088790286Sobrien(define_insn "*ashlhi3_1"
1088890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1088990286Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
1089090286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI")))
10891169699Skan   (clobber (reg:CC FLAGS_REG))]
1089290286Sobrien  "TARGET_PARTIAL_REG_STALL
1089390286Sobrien   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
1089490286Sobrien{
1089590286Sobrien  switch (get_attr_type (insn))
1089690286Sobrien    {
1089790286Sobrien    case TYPE_ALU:
10898169699Skan      gcc_assert (operands[2] == const1_rtx);
1089990286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1090090286Sobrien
1090190286Sobrien    default:
1090290286Sobrien      if (REG_P (operands[2]))
1090390286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10904169699Skan      else if (operands[2] == const1_rtx
10905117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1090690286Sobrien	return "sal{w}\t%0";
1090790286Sobrien      else
1090890286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1090990286Sobrien    }
1091090286Sobrien}
1091190286Sobrien  [(set (attr "type")
1091290286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1091390286Sobrien		          (const_int 0))
1091490286Sobrien		      (match_operand 0 "register_operand" ""))
1091590286Sobrien		 (match_operand 2 "const1_operand" ""))
1091690286Sobrien	      (const_string "alu")
1091790286Sobrien	   ]
1091890286Sobrien	   (const_string "ishift")))
1091990286Sobrien   (set_attr "mode" "HI")])
1092090286Sobrien
1092190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1092290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1092390286Sobrien;; zero are optimized away.
1092490286Sobrien(define_insn "*ashlhi3_cmp"
10925169699Skan  [(set (reg FLAGS_REG)
1092690286Sobrien	(compare
1092790286Sobrien	  (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
10928169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1092990286Sobrien	  (const_int 0)))
1093090286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1093190286Sobrien	(ashift:HI (match_dup 1) (match_dup 2)))]
1093290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
10933169699Skan   && ix86_binary_operator_ok (ASHIFT, HImode, operands)
10934169699Skan   && (optimize_size
10935169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10936169699Skan       || (operands[2] == const1_rtx
10937169699Skan	   && (TARGET_SHIFT1
10938169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1093990286Sobrien{
1094090286Sobrien  switch (get_attr_type (insn))
1094190286Sobrien    {
1094290286Sobrien    case TYPE_ALU:
10943169699Skan      gcc_assert (operands[2] == const1_rtx);
1094490286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1094590286Sobrien
1094690286Sobrien    default:
1094790286Sobrien      if (REG_P (operands[2]))
1094890286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10949169699Skan      else if (operands[2] == const1_rtx
10950117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1095190286Sobrien	return "sal{w}\t%0";
1095290286Sobrien      else
1095390286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1095490286Sobrien    }
1095590286Sobrien}
1095690286Sobrien  [(set (attr "type")
1095790286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1095890286Sobrien		          (const_int 0))
1095990286Sobrien		      (match_operand 0 "register_operand" ""))
1096090286Sobrien		 (match_operand 2 "const1_operand" ""))
1096190286Sobrien	      (const_string "alu")
1096290286Sobrien	   ]
1096390286Sobrien	   (const_string "ishift")))
1096490286Sobrien   (set_attr "mode" "HI")])
1096590286Sobrien
10966169699Skan(define_insn "*ashlhi3_cconly"
10967169699Skan  [(set (reg FLAGS_REG)
10968169699Skan	(compare
10969169699Skan	  (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
10970169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
10971169699Skan	  (const_int 0)))
10972169699Skan   (clobber (match_scratch:HI 0 "=r"))]
10973169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
10974169699Skan   && ix86_binary_operator_ok (ASHIFT, HImode, operands)
10975169699Skan   && (optimize_size
10976169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10977169699Skan       || (operands[2] == const1_rtx
10978169699Skan	   && (TARGET_SHIFT1
10979169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10980169699Skan{
10981169699Skan  switch (get_attr_type (insn))
10982169699Skan    {
10983169699Skan    case TYPE_ALU:
10984169699Skan      gcc_assert (operands[2] == const1_rtx);
10985169699Skan      return "add{w}\t{%0, %0|%0, %0}";
10986169699Skan
10987169699Skan    default:
10988169699Skan      if (REG_P (operands[2]))
10989169699Skan	return "sal{w}\t{%b2, %0|%0, %b2}";
10990169699Skan      else if (operands[2] == const1_rtx
10991169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10992169699Skan	return "sal{w}\t%0";
10993169699Skan      else
10994169699Skan	return "sal{w}\t{%2, %0|%0, %2}";
10995169699Skan    }
10996169699Skan}
10997169699Skan  [(set (attr "type")
10998169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
10999169699Skan		          (const_int 0))
11000169699Skan		      (match_operand 0 "register_operand" ""))
11001169699Skan		 (match_operand 2 "const1_operand" ""))
11002169699Skan	      (const_string "alu")
11003169699Skan	   ]
11004169699Skan	   (const_string "ishift")))
11005169699Skan   (set_attr "mode" "HI")])
11006169699Skan
1100752296Sobrien(define_expand "ashlqi3"
1100852296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1100952296Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
1101090286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
11011169699Skan   (clobber (reg:CC FLAGS_REG))]
1101290286Sobrien  "TARGET_QIMODE_MATH"
1101390286Sobrien  "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;")
1101418334Speter
1101590286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
1101618334Speter
1101790286Sobrien(define_insn "*ashlqi3_1_lea"
1101890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r")
11019169699Skan	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l")
1102090286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,cI,M")))
11021169699Skan   (clobber (reg:CC FLAGS_REG))]
1102290286Sobrien  "!TARGET_PARTIAL_REG_STALL
1102390286Sobrien   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
1102490286Sobrien{
1102590286Sobrien  switch (get_attr_type (insn))
1102690286Sobrien    {
1102790286Sobrien    case TYPE_LEA:
1102890286Sobrien      return "#";
1102990286Sobrien    case TYPE_ALU:
11030169699Skan      gcc_assert (operands[2] == const1_rtx);
1103190286Sobrien      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
1103290286Sobrien        return "add{l}\t{%k0, %k0|%k0, %k0}";
1103390286Sobrien      else
1103490286Sobrien        return "add{b}\t{%0, %0|%0, %0}";
1103518334Speter
1103690286Sobrien    default:
1103790286Sobrien      if (REG_P (operands[2]))
1103890286Sobrien	{
1103990286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1104090286Sobrien	    return "sal{l}\t{%b2, %k0|%k0, %b2}";
1104190286Sobrien	  else
1104290286Sobrien	    return "sal{b}\t{%b2, %0|%0, %b2}";
1104390286Sobrien	}
11044169699Skan      else if (operands[2] == const1_rtx
11045117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1104690286Sobrien	{
1104790286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1104890286Sobrien	    return "sal{l}\t%0";
1104990286Sobrien	  else
1105090286Sobrien	    return "sal{b}\t%0";
1105190286Sobrien	}
1105290286Sobrien      else
1105390286Sobrien	{
1105490286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1105590286Sobrien	    return "sal{l}\t{%2, %k0|%k0, %2}";
1105690286Sobrien	  else
1105790286Sobrien	    return "sal{b}\t{%2, %0|%0, %2}";
1105890286Sobrien	}
1105990286Sobrien    }
1106090286Sobrien}
1106190286Sobrien  [(set (attr "type")
1106290286Sobrien     (cond [(eq_attr "alternative" "2")
1106390286Sobrien	      (const_string "lea")
1106490286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1106590286Sobrien		          (const_int 0))
1106690286Sobrien		      (match_operand 0 "register_operand" ""))
1106790286Sobrien		 (match_operand 2 "const1_operand" ""))
1106890286Sobrien	      (const_string "alu")
1106990286Sobrien	   ]
1107090286Sobrien	   (const_string "ishift")))
1107190286Sobrien   (set_attr "mode" "QI,SI,SI")])
1107218334Speter
1107390286Sobrien(define_insn "*ashlqi3_1"
1107490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
1107590286Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1107690286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
11077169699Skan   (clobber (reg:CC FLAGS_REG))]
1107890286Sobrien  "TARGET_PARTIAL_REG_STALL
1107990286Sobrien   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
1108090286Sobrien{
1108190286Sobrien  switch (get_attr_type (insn))
1108290286Sobrien    {
1108390286Sobrien    case TYPE_ALU:
11084169699Skan      gcc_assert (operands[2] == const1_rtx);
1108590286Sobrien      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
1108690286Sobrien        return "add{l}\t{%k0, %k0|%k0, %k0}";
1108790286Sobrien      else
1108890286Sobrien        return "add{b}\t{%0, %0|%0, %0}";
1108952296Sobrien
1109090286Sobrien    default:
1109190286Sobrien      if (REG_P (operands[2]))
1109290286Sobrien	{
1109390286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1109490286Sobrien	    return "sal{l}\t{%b2, %k0|%k0, %b2}";
1109590286Sobrien	  else
1109690286Sobrien	    return "sal{b}\t{%b2, %0|%0, %b2}";
1109790286Sobrien	}
11098169699Skan      else if (operands[2] == const1_rtx
11099117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1110090286Sobrien	{
1110190286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1110290286Sobrien	    return "sal{l}\t%0";
1110390286Sobrien	  else
1110490286Sobrien	    return "sal{b}\t%0";
1110590286Sobrien	}
1110690286Sobrien      else
1110790286Sobrien	{
1110890286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1110990286Sobrien	    return "sal{l}\t{%2, %k0|%k0, %2}";
1111090286Sobrien	  else
1111190286Sobrien	    return "sal{b}\t{%2, %0|%0, %2}";
1111290286Sobrien	}
1111390286Sobrien    }
1111490286Sobrien}
1111590286Sobrien  [(set (attr "type")
1111690286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1111790286Sobrien		          (const_int 0))
1111890286Sobrien		      (match_operand 0 "register_operand" ""))
1111990286Sobrien		 (match_operand 2 "const1_operand" ""))
1112090286Sobrien	      (const_string "alu")
1112190286Sobrien	   ]
1112290286Sobrien	   (const_string "ishift")))
1112390286Sobrien   (set_attr "mode" "QI,SI")])
1112418334Speter
1112590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1112690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1112790286Sobrien;; zero are optimized away.
1112890286Sobrien(define_insn "*ashlqi3_cmp"
11129169699Skan  [(set (reg FLAGS_REG)
1113090286Sobrien	(compare
1113190286Sobrien	  (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11132169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1113390286Sobrien	  (const_int 0)))
1113490286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1113590286Sobrien	(ashift:QI (match_dup 1) (match_dup 2)))]
1113690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11137169699Skan   && ix86_binary_operator_ok (ASHIFT, QImode, operands)
11138169699Skan   && (optimize_size
11139169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11140169699Skan       || (operands[2] == const1_rtx
11141169699Skan	   && (TARGET_SHIFT1
11142169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1114390286Sobrien{
1114490286Sobrien  switch (get_attr_type (insn))
1114590286Sobrien    {
1114690286Sobrien    case TYPE_ALU:
11147169699Skan      gcc_assert (operands[2] == const1_rtx);
1114890286Sobrien      return "add{b}\t{%0, %0|%0, %0}";
1114918334Speter
1115090286Sobrien    default:
1115190286Sobrien      if (REG_P (operands[2]))
1115290286Sobrien	return "sal{b}\t{%b2, %0|%0, %b2}";
11153169699Skan      else if (operands[2] == const1_rtx
11154117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1115590286Sobrien	return "sal{b}\t%0";
1115690286Sobrien      else
1115790286Sobrien	return "sal{b}\t{%2, %0|%0, %2}";
1115890286Sobrien    }
1115990286Sobrien}
1116090286Sobrien  [(set (attr "type")
1116190286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1116290286Sobrien		          (const_int 0))
1116390286Sobrien		      (match_operand 0 "register_operand" ""))
1116490286Sobrien		 (match_operand 2 "const1_operand" ""))
1116590286Sobrien	      (const_string "alu")
1116690286Sobrien	   ]
1116790286Sobrien	   (const_string "ishift")))
1116890286Sobrien   (set_attr "mode" "QI")])
1116918334Speter
11170169699Skan(define_insn "*ashlqi3_cconly"
11171169699Skan  [(set (reg FLAGS_REG)
11172169699Skan	(compare
11173169699Skan	  (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11174169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
11175169699Skan	  (const_int 0)))
11176169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11177169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11178169699Skan   && ix86_binary_operator_ok (ASHIFT, QImode, operands)
11179169699Skan   && (optimize_size
11180169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11181169699Skan       || (operands[2] == const1_rtx
11182169699Skan	   && (TARGET_SHIFT1
11183169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
11184169699Skan{
11185169699Skan  switch (get_attr_type (insn))
11186169699Skan    {
11187169699Skan    case TYPE_ALU:
11188169699Skan      gcc_assert (operands[2] == const1_rtx);
11189169699Skan      return "add{b}\t{%0, %0|%0, %0}";
11190169699Skan
11191169699Skan    default:
11192169699Skan      if (REG_P (operands[2]))
11193169699Skan	return "sal{b}\t{%b2, %0|%0, %b2}";
11194169699Skan      else if (operands[2] == const1_rtx
11195169699Skan	       && (TARGET_SHIFT1 || optimize_size))
11196169699Skan	return "sal{b}\t%0";
11197169699Skan      else
11198169699Skan	return "sal{b}\t{%2, %0|%0, %2}";
11199169699Skan    }
11200169699Skan}
11201169699Skan  [(set (attr "type")
11202169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
11203169699Skan		          (const_int 0))
11204169699Skan		      (match_operand 0 "register_operand" ""))
11205169699Skan		 (match_operand 2 "const1_operand" ""))
11206169699Skan	      (const_string "alu")
11207169699Skan	   ]
11208169699Skan	   (const_string "ishift")))
11209169699Skan   (set_attr "mode" "QI")])
11210169699Skan
1121118334Speter;; See comment above `ashldi3' about how this works.
1121218334Speter
11213169699Skan(define_expand "ashrti3"
11214169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
11215169699Skan		   (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
1121690286Sobrien				(match_operand:QI 2 "nonmemory_operand" "")))
11217169699Skan	      (clobber (reg:CC FLAGS_REG))])]
11218169699Skan  "TARGET_64BIT"
1121918334Speter{
11220169699Skan  if (! immediate_operand (operands[2], QImode))
1122118334Speter    {
11222169699Skan      emit_insn (gen_ashrti3_1 (operands[0], operands[1], operands[2]));
1122390286Sobrien      DONE;
1122418334Speter    }
11225169699Skan  ix86_expand_binary_operator (ASHIFTRT, TImode, operands);
1122618334Speter  DONE;
1122790286Sobrien})
1122818334Speter
11229169699Skan(define_insn "ashrti3_1"
11230169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11231169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
11232169699Skan		     (match_operand:QI 2 "register_operand" "c")))
11233169699Skan   (clobber (match_scratch:DI 3 "=&r"))
11234169699Skan   (clobber (reg:CC FLAGS_REG))]
11235169699Skan  "TARGET_64BIT"
11236169699Skan  "#"
11237169699Skan  [(set_attr "type" "multi")])
11238169699Skan
11239169699Skan(define_insn "*ashrti3_2"
11240169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11241169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
11242169699Skan		     (match_operand:QI 2 "immediate_operand" "O")))
11243169699Skan   (clobber (reg:CC FLAGS_REG))]
11244169699Skan  "TARGET_64BIT"
11245169699Skan  "#"
11246169699Skan  [(set_attr "type" "multi")])
11247169699Skan
11248169699Skan(define_split
11249169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11250169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "")
11251169699Skan		     (match_operand:QI 2 "register_operand" "")))
11252169699Skan   (clobber (match_scratch:DI 3 ""))
11253169699Skan   (clobber (reg:CC FLAGS_REG))]
11254169699Skan  "TARGET_64BIT && reload_completed"
11255169699Skan  [(const_int 0)]
11256169699Skan  "ix86_split_ashr (operands, operands[3], TImode); DONE;")
11257169699Skan
11258169699Skan(define_split
11259169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11260169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "")
11261169699Skan		     (match_operand:QI 2 "immediate_operand" "")))
11262169699Skan   (clobber (reg:CC FLAGS_REG))]
11263169699Skan  "TARGET_64BIT && reload_completed"
11264169699Skan  [(const_int 0)]
11265169699Skan  "ix86_split_ashr (operands, NULL_RTX, TImode); DONE;")
11266169699Skan
11267169699Skan(define_insn "x86_64_shrd"
11268169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
11269169699Skan        (ior:DI (ashiftrt:DI (match_dup 0)
11270169699Skan		  (match_operand:QI 2 "nonmemory_operand" "J,c"))
11271169699Skan		(ashift:DI (match_operand:DI 1 "register_operand" "r,r")
11272169699Skan		  (minus:QI (const_int 64) (match_dup 2)))))
11273169699Skan   (clobber (reg:CC FLAGS_REG))]
11274169699Skan  "TARGET_64BIT"
11275169699Skan  "@
11276169699Skan   shrd{q}\t{%2, %1, %0|%0, %1, %2}
11277169699Skan   shrd{q}\t{%s2%1, %0|%0, %1, %2}"
11278169699Skan  [(set_attr "type" "ishift")
11279169699Skan   (set_attr "prefix_0f" "1")
11280169699Skan   (set_attr "mode" "DI")
11281169699Skan   (set_attr "athlon_decode" "vector")])
11282169699Skan
11283169699Skan(define_expand "ashrdi3"
11284169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
11285169699Skan	(ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
11286169699Skan		     (match_operand:QI 2 "nonmemory_operand" "")))]
11287169699Skan  ""
11288169699Skan  "ix86_expand_binary_operator (ASHIFTRT, DImode, operands); DONE;")
11289169699Skan
11290169699Skan(define_insn "*ashrdi3_63_rex64"
1129190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=*d,rm")
1129290286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "*a,0")
1129390286Sobrien		     (match_operand:DI 2 "const_int_operand" "i,i")))
11294169699Skan   (clobber (reg:CC FLAGS_REG))]
11295169699Skan  "TARGET_64BIT && INTVAL (operands[2]) == 63
11296169699Skan   && (TARGET_USE_CLTD || optimize_size)
1129790286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1129890286Sobrien  "@
1129990286Sobrien   {cqto|cqo}
1130090286Sobrien   sar{q}\t{%2, %0|%0, %2}"
1130190286Sobrien  [(set_attr "type" "imovx,ishift")
1130290286Sobrien   (set_attr "prefix_0f" "0,*")
1130390286Sobrien   (set_attr "length_immediate" "0,*")
1130490286Sobrien   (set_attr "modrm" "0,1")
1130590286Sobrien   (set_attr "mode" "DI")])
1130650650Sobrien
1130790286Sobrien(define_insn "*ashrdi3_1_one_bit_rex64"
1130890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1130990286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11310132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11311169699Skan   (clobber (reg:CC FLAGS_REG))]
1131290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11313117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1131490286Sobrien  "sar{q}\t%0"
1131590286Sobrien  [(set_attr "type" "ishift")
1131690286Sobrien   (set (attr "length") 
1131790286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1131890286Sobrien	(const_string "2")
1131990286Sobrien	(const_string "*")))])
1132050650Sobrien
1132190286Sobrien(define_insn "*ashrdi3_1_rex64"
1132290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1132390286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1132490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
11325169699Skan   (clobber (reg:CC FLAGS_REG))]
1132690286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1132790286Sobrien  "@
1132890286Sobrien   sar{q}\t{%2, %0|%0, %2}
1132990286Sobrien   sar{q}\t{%b2, %0|%0, %b2}"
1133090286Sobrien  [(set_attr "type" "ishift")
1133190286Sobrien   (set_attr "mode" "DI")])
1133250650Sobrien
1133390286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1133490286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1133590286Sobrien;; zero are optimized away.
1133690286Sobrien(define_insn "*ashrdi3_one_bit_cmp_rex64"
11337169699Skan  [(set (reg FLAGS_REG)
1133890286Sobrien	(compare
1133990286Sobrien	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11340132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1134190286Sobrien	  (const_int 0)))
1134290286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1134390286Sobrien	(ashiftrt:DI (match_dup 1) (match_dup 2)))]
1134490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11345117404Skan   && (TARGET_SHIFT1 || optimize_size)
1134690286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1134790286Sobrien  "sar{q}\t%0"
1134890286Sobrien  [(set_attr "type" "ishift")
1134990286Sobrien   (set (attr "length") 
1135090286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1135190286Sobrien	(const_string "2")
1135290286Sobrien	(const_string "*")))])
1135350650Sobrien
11354169699Skan(define_insn "*ashrdi3_one_bit_cconly_rex64"
11355169699Skan  [(set (reg FLAGS_REG)
11356169699Skan	(compare
11357169699Skan	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11358169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11359169699Skan	  (const_int 0)))
11360169699Skan   (clobber (match_scratch:DI 0 "=r"))]
11361169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11362169699Skan   && (TARGET_SHIFT1 || optimize_size)
11363169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
11364169699Skan  "sar{q}\t%0"
11365169699Skan  [(set_attr "type" "ishift")
11366169699Skan   (set_attr "length" "2")])
11367169699Skan
1136890286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1136990286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1137090286Sobrien;; zero are optimized away.
1137190286Sobrien(define_insn "*ashrdi3_cmp_rex64"
11372169699Skan  [(set (reg FLAGS_REG)
1137390286Sobrien	(compare
1137490286Sobrien	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1137590286Sobrien		       (match_operand:QI 2 "const_int_operand" "n"))
1137690286Sobrien	  (const_int 0)))
1137790286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1137890286Sobrien	(ashiftrt:DI (match_dup 1) (match_dup 2)))]
1137990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11380169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11381169699Skan   && (optimize_size
11382169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1138390286Sobrien  "sar{q}\t{%2, %0|%0, %2}"
1138490286Sobrien  [(set_attr "type" "ishift")
1138590286Sobrien   (set_attr "mode" "DI")])
1138618334Speter
11387169699Skan(define_insn "*ashrdi3_cconly_rex64"
11388169699Skan  [(set (reg FLAGS_REG)
11389169699Skan	(compare
11390169699Skan	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11391169699Skan		       (match_operand:QI 2 "const_int_operand" "n"))
11392169699Skan	  (const_int 0)))
11393169699Skan   (clobber (match_scratch:DI 0 "=r"))]
11394169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11395169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11396169699Skan   && (optimize_size
11397169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11398169699Skan  "sar{q}\t{%2, %0|%0, %2}"
11399169699Skan  [(set_attr "type" "ishift")
11400169699Skan   (set_attr "mode" "DI")])
1140118334Speter
11402169699Skan(define_insn "*ashrdi3_1"
1140390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1140490286Sobrien	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
1140590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "Jc")))
11406169699Skan   (clobber (reg:CC FLAGS_REG))]
1140790286Sobrien  "!TARGET_64BIT"
1140890286Sobrien  "#"
1140990286Sobrien  [(set_attr "type" "multi")])
1141018334Speter
11411169699Skan;; By default we don't ask for a scratch register, because when DImode
11412169699Skan;; values are manipulated, registers are already at a premium.  But if
11413169699Skan;; we have one handy, we won't turn it away.
11414169699Skan(define_peephole2
11415169699Skan  [(match_scratch:SI 3 "r")
11416169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
11417169699Skan		   (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
11418169699Skan			        (match_operand:QI 2 "nonmemory_operand" "")))
11419169699Skan	      (clobber (reg:CC FLAGS_REG))])
11420169699Skan   (match_dup 3)]
11421169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1142290286Sobrien  [(const_int 0)]
11423169699Skan  "ix86_split_ashr (operands, operands[3], DImode); DONE;")
1142418334Speter
1142590286Sobrien(define_split
1142690286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1142790286Sobrien	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
1142890286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11429169699Skan   (clobber (reg:CC FLAGS_REG))]
11430169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
11431169699Skan		     ? flow2_completed : reload_completed)"
1143290286Sobrien  [(const_int 0)]
11433169699Skan  "ix86_split_ashr (operands, NULL_RTX, DImode); DONE;")
1143418334Speter
1143590286Sobrien(define_insn "x86_shrd_1"
1143690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
1143790286Sobrien        (ior:SI (ashiftrt:SI (match_dup 0)
1143890286Sobrien		  (match_operand:QI 2 "nonmemory_operand" "I,c"))
1143990286Sobrien		(ashift:SI (match_operand:SI 1 "register_operand" "r,r")
1144090286Sobrien		  (minus:QI (const_int 32) (match_dup 2)))))
11441169699Skan   (clobber (reg:CC FLAGS_REG))]
1144218334Speter  ""
1144390286Sobrien  "@
1144490286Sobrien   shrd{l}\t{%2, %1, %0|%0, %1, %2}
1144590286Sobrien   shrd{l}\t{%s2%1, %0|%0, %1, %2}"
1144690286Sobrien  [(set_attr "type" "ishift")
1144790286Sobrien   (set_attr "prefix_0f" "1")
1144890286Sobrien   (set_attr "pent_pair" "np")
1144990286Sobrien   (set_attr "mode" "SI")])
1145090286Sobrien
1145190286Sobrien(define_expand "x86_shift_adj_3"
1145290286Sobrien  [(use (match_operand:SI 0 "register_operand" ""))
1145390286Sobrien   (use (match_operand:SI 1 "register_operand" ""))
1145490286Sobrien   (use (match_operand:QI 2 "register_operand" ""))]
1145590286Sobrien  ""
1145618334Speter{
1145790286Sobrien  rtx label = gen_label_rtx ();
1145890286Sobrien  rtx tmp;
1145918334Speter
1146090286Sobrien  emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
1146118334Speter
1146290286Sobrien  tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
1146390286Sobrien  tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1146490286Sobrien  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
1146590286Sobrien			      gen_rtx_LABEL_REF (VOIDmode, label),
1146690286Sobrien			      pc_rtx);
1146790286Sobrien  tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
1146890286Sobrien  JUMP_LABEL (tmp) = label;
1146918334Speter
1147090286Sobrien  emit_move_insn (operands[0], operands[1]);
1147190286Sobrien  emit_insn (gen_ashrsi3_31 (operands[1], operands[1], GEN_INT (31)));
1147218334Speter
1147390286Sobrien  emit_label (label);
1147490286Sobrien  LABEL_NUSES (label) = 1;
1147590286Sobrien
1147690286Sobrien  DONE;
1147790286Sobrien})
1147890286Sobrien
1147952296Sobrien(define_insn "ashrsi3_31"
1148090286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm")
1148190286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0")
1148290286Sobrien		     (match_operand:SI 2 "const_int_operand" "i,i")))
11483169699Skan   (clobber (reg:CC FLAGS_REG))]
1148490286Sobrien  "INTVAL (operands[2]) == 31 && (TARGET_USE_CLTD || optimize_size)
1148590286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1148652296Sobrien  "@
1148790286Sobrien   {cltd|cdq}
1148890286Sobrien   sar{l}\t{%2, %0|%0, %2}"
1148990286Sobrien  [(set_attr "type" "imovx,ishift")
1149090286Sobrien   (set_attr "prefix_0f" "0,*")
1149190286Sobrien   (set_attr "length_immediate" "0,*")
1149290286Sobrien   (set_attr "modrm" "0,1")
1149390286Sobrien   (set_attr "mode" "SI")])
1149452296Sobrien
1149590286Sobrien(define_insn "*ashrsi3_31_zext"
1149690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*d,r")
1149790286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "*a,0")
1149890286Sobrien				     (match_operand:SI 2 "const_int_operand" "i,i"))))
11499169699Skan   (clobber (reg:CC FLAGS_REG))]
1150090286Sobrien  "TARGET_64BIT && (TARGET_USE_CLTD || optimize_size)
1150190286Sobrien   && INTVAL (operands[2]) == 31
1150290286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1150390286Sobrien  "@
1150490286Sobrien   {cltd|cdq}
1150590286Sobrien   sar{l}\t{%2, %k0|%k0, %2}"
1150690286Sobrien  [(set_attr "type" "imovx,ishift")
1150790286Sobrien   (set_attr "prefix_0f" "0,*")
1150890286Sobrien   (set_attr "length_immediate" "0,*")
1150990286Sobrien   (set_attr "modrm" "0,1")
1151090286Sobrien   (set_attr "mode" "SI")])
1151190286Sobrien
1151290286Sobrien(define_expand "ashrsi3"
1151390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1151490286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
1151590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11516169699Skan   (clobber (reg:CC FLAGS_REG))]
1151790286Sobrien  ""
1151890286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, SImode, operands); DONE;")
1151990286Sobrien
1152090286Sobrien(define_insn "*ashrsi3_1_one_bit"
1152150650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1152250650Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11523132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11524169699Skan   (clobber (reg:CC FLAGS_REG))]
1152590286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11526117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1152790286Sobrien  "sar{l}\t%0"
1152890286Sobrien  [(set_attr "type" "ishift")
1152990286Sobrien   (set (attr "length") 
1153090286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1153190286Sobrien	(const_string "2")
1153290286Sobrien	(const_string "*")))])
1153318334Speter
1153490286Sobrien(define_insn "*ashrsi3_1_one_bit_zext"
1153590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1153690286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11537132727Skan				     (match_operand:QI 2 "const1_operand" ""))))
11538169699Skan   (clobber (reg:CC FLAGS_REG))]
1153990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11540117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1154190286Sobrien  "sar{l}\t%k0"
1154290286Sobrien  [(set_attr "type" "ishift")
1154390286Sobrien   (set_attr "length" "2")])
1154490286Sobrien
1154590286Sobrien(define_insn "*ashrsi3_1"
1154690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1154790286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1154890286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11549169699Skan   (clobber (reg:CC FLAGS_REG))]
1155090286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1155190286Sobrien  "@
1155290286Sobrien   sar{l}\t{%2, %0|%0, %2}
1155390286Sobrien   sar{l}\t{%b2, %0|%0, %b2}"
1155490286Sobrien  [(set_attr "type" "ishift")
1155590286Sobrien   (set_attr "mode" "SI")])
1155690286Sobrien
1155790286Sobrien(define_insn "*ashrsi3_1_zext"
1155890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1155990286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
1156090286Sobrien				     (match_operand:QI 2 "nonmemory_operand" "I,c"))))
11561169699Skan   (clobber (reg:CC FLAGS_REG))]
1156290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1156390286Sobrien  "@
1156490286Sobrien   sar{l}\t{%2, %k0|%k0, %2}
1156590286Sobrien   sar{l}\t{%b2, %k0|%k0, %b2}"
1156690286Sobrien  [(set_attr "type" "ishift")
1156790286Sobrien   (set_attr "mode" "SI")])
1156890286Sobrien
1156990286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1157090286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1157190286Sobrien;; zero are optimized away.
1157290286Sobrien(define_insn "*ashrsi3_one_bit_cmp"
11573169699Skan  [(set (reg FLAGS_REG)
1157490286Sobrien	(compare
1157590286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11576132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1157790286Sobrien	  (const_int 0)))
1157890286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1157990286Sobrien	(ashiftrt:SI (match_dup 1) (match_dup 2)))]
1158090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11581117404Skan   && (TARGET_SHIFT1 || optimize_size)
1158290286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1158390286Sobrien  "sar{l}\t%0"
1158490286Sobrien  [(set_attr "type" "ishift")
1158590286Sobrien   (set (attr "length") 
1158690286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1158790286Sobrien	(const_string "2")
1158890286Sobrien	(const_string "*")))])
1158990286Sobrien
11590169699Skan(define_insn "*ashrsi3_one_bit_cconly"
11591169699Skan  [(set (reg FLAGS_REG)
11592169699Skan	(compare
11593169699Skan	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11594169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11595169699Skan	  (const_int 0)))
11596169699Skan   (clobber (match_scratch:SI 0 "=r"))]
11597169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11598169699Skan   && (TARGET_SHIFT1 || optimize_size)
11599169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
11600169699Skan  "sar{l}\t%0"
11601169699Skan  [(set_attr "type" "ishift")
11602169699Skan   (set_attr "length" "2")])
11603169699Skan
1160490286Sobrien(define_insn "*ashrsi3_one_bit_cmp_zext"
11605169699Skan  [(set (reg FLAGS_REG)
1160690286Sobrien	(compare
1160790286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11608132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1160990286Sobrien	  (const_int 0)))
1161090286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1161190286Sobrien	(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
1161290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
11613117404Skan   && (TARGET_SHIFT1 || optimize_size)
1161490286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1161590286Sobrien  "sar{l}\t%k0"
1161690286Sobrien  [(set_attr "type" "ishift")
1161790286Sobrien   (set_attr "length" "2")])
1161890286Sobrien
1161990286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1162090286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1162190286Sobrien;; zero are optimized away.
1162290286Sobrien(define_insn "*ashrsi3_cmp"
11623169699Skan  [(set (reg FLAGS_REG)
1162490286Sobrien	(compare
1162590286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11626169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1162790286Sobrien	  (const_int 0)))
1162890286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1162990286Sobrien	(ashiftrt:SI (match_dup 1) (match_dup 2)))]
1163090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11631169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11632169699Skan   && (optimize_size
11633169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1163490286Sobrien  "sar{l}\t{%2, %0|%0, %2}"
1163590286Sobrien  [(set_attr "type" "ishift")
1163690286Sobrien   (set_attr "mode" "SI")])
1163790286Sobrien
11638169699Skan(define_insn "*ashrsi3_cconly"
11639169699Skan  [(set (reg FLAGS_REG)
11640169699Skan	(compare
11641169699Skan	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11642169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11643169699Skan	  (const_int 0)))
11644169699Skan   (clobber (match_scratch:SI 0 "=r"))]
11645169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11646169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11647169699Skan   && (optimize_size
11648169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11649169699Skan  "sar{l}\t{%2, %0|%0, %2}"
11650169699Skan  [(set_attr "type" "ishift")
11651169699Skan   (set_attr "mode" "SI")])
11652169699Skan
1165390286Sobrien(define_insn "*ashrsi3_cmp_zext"
11654169699Skan  [(set (reg FLAGS_REG)
1165590286Sobrien	(compare
1165690286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11657169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1165890286Sobrien	  (const_int 0)))
1165990286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1166090286Sobrien	(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
1166190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11662169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11663169699Skan   && (optimize_size
11664169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1166590286Sobrien  "sar{l}\t{%2, %k0|%k0, %2}"
1166690286Sobrien  [(set_attr "type" "ishift")
1166790286Sobrien   (set_attr "mode" "SI")])
1166890286Sobrien
1166990286Sobrien(define_expand "ashrhi3"
1167090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1167190286Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
1167290286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11673169699Skan   (clobber (reg:CC FLAGS_REG))]
1167490286Sobrien  "TARGET_HIMODE_MATH"
1167590286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, HImode, operands); DONE;")
1167690286Sobrien
1167790286Sobrien(define_insn "*ashrhi3_1_one_bit"
1167850650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1167950650Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11680132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11681169699Skan   (clobber (reg:CC FLAGS_REG))]
1168290286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11683117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1168490286Sobrien  "sar{w}\t%0"
1168590286Sobrien  [(set_attr "type" "ishift")
1168690286Sobrien   (set (attr "length") 
1168790286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1168890286Sobrien	(const_string "2")
1168990286Sobrien	(const_string "*")))])
1169018334Speter
1169190286Sobrien(define_insn "*ashrhi3_1"
1169290286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1169390286Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1169490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11695169699Skan   (clobber (reg:CC FLAGS_REG))]
1169690286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
1169790286Sobrien  "@
1169890286Sobrien   sar{w}\t{%2, %0|%0, %2}
1169990286Sobrien   sar{w}\t{%b2, %0|%0, %b2}"
1170090286Sobrien  [(set_attr "type" "ishift")
1170190286Sobrien   (set_attr "mode" "HI")])
1170290286Sobrien
1170390286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1170490286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1170590286Sobrien;; zero are optimized away.
1170690286Sobrien(define_insn "*ashrhi3_one_bit_cmp"
11707169699Skan  [(set (reg FLAGS_REG)
1170890286Sobrien	(compare
1170990286Sobrien	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11710132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1171190286Sobrien	  (const_int 0)))
1171290286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1171390286Sobrien	(ashiftrt:HI (match_dup 1) (match_dup 2)))]
1171490286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11715117404Skan   && (TARGET_SHIFT1 || optimize_size)
1171690286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
1171790286Sobrien  "sar{w}\t%0"
1171890286Sobrien  [(set_attr "type" "ishift")
1171990286Sobrien   (set (attr "length") 
1172090286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1172190286Sobrien	(const_string "2")
1172290286Sobrien	(const_string "*")))])
1172390286Sobrien
11724169699Skan(define_insn "*ashrhi3_one_bit_cconly"
11725169699Skan  [(set (reg FLAGS_REG)
11726169699Skan	(compare
11727169699Skan	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11728169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11729169699Skan	  (const_int 0)))
11730169699Skan   (clobber (match_scratch:HI 0 "=r"))]
11731169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11732169699Skan   && (TARGET_SHIFT1 || optimize_size)
11733169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
11734169699Skan  "sar{w}\t%0"
11735169699Skan  [(set_attr "type" "ishift")
11736169699Skan   (set_attr "length" "2")])
11737169699Skan
1173890286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1173990286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1174090286Sobrien;; zero are optimized away.
1174190286Sobrien(define_insn "*ashrhi3_cmp"
11742169699Skan  [(set (reg FLAGS_REG)
1174390286Sobrien	(compare
1174490286Sobrien	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11745169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1174690286Sobrien	  (const_int 0)))
1174790286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1174890286Sobrien	(ashiftrt:HI (match_dup 1) (match_dup 2)))]
1174990286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11750169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11751169699Skan   && (optimize_size
11752169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1175390286Sobrien  "sar{w}\t{%2, %0|%0, %2}"
1175490286Sobrien  [(set_attr "type" "ishift")
1175590286Sobrien   (set_attr "mode" "HI")])
1175690286Sobrien
11757169699Skan(define_insn "*ashrhi3_cconly"
11758169699Skan  [(set (reg FLAGS_REG)
11759169699Skan	(compare
11760169699Skan	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11761169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11762169699Skan	  (const_int 0)))
11763169699Skan   (clobber (match_scratch:HI 0 "=r"))]
11764169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11765169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11766169699Skan   && (optimize_size
11767169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11768169699Skan  "sar{w}\t{%2, %0|%0, %2}"
11769169699Skan  [(set_attr "type" "ishift")
11770169699Skan   (set_attr "mode" "HI")])
11771169699Skan
1177290286Sobrien(define_expand "ashrqi3"
1177390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1177490286Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
1177590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11776169699Skan   (clobber (reg:CC FLAGS_REG))]
1177790286Sobrien  "TARGET_QIMODE_MATH"
1177890286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, QImode, operands); DONE;")
1177990286Sobrien
1178090286Sobrien(define_insn "*ashrqi3_1_one_bit"
1178150650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1178250650Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11783132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11784169699Skan   (clobber (reg:CC FLAGS_REG))]
1178590286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11786117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1178790286Sobrien  "sar{b}\t%0"
1178890286Sobrien  [(set_attr "type" "ishift")
1178990286Sobrien   (set (attr "length") 
1179090286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1179190286Sobrien	(const_string "2")
1179290286Sobrien	(const_string "*")))])
1179390286Sobrien
11794117404Skan(define_insn "*ashrqi3_1_one_bit_slp"
11795117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
11796117404Skan	(ashiftrt:QI (match_dup 0)
11797132727Skan		     (match_operand:QI 1 "const1_operand" "")))
11798169699Skan   (clobber (reg:CC FLAGS_REG))]
11799117404Skan  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11800117404Skan   && (! TARGET_PARTIAL_REG_STALL || optimize_size)
11801117404Skan   && (TARGET_SHIFT1 || optimize_size)"
11802117404Skan  "sar{b}\t%0"
11803117404Skan  [(set_attr "type" "ishift1")
11804117404Skan   (set (attr "length") 
11805117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
11806117404Skan	(const_string "2")
11807117404Skan	(const_string "*")))])
11808117404Skan
1180990286Sobrien(define_insn "*ashrqi3_1"
1181090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1181190286Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1181290286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11813169699Skan   (clobber (reg:CC FLAGS_REG))]
1181490286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
1181590286Sobrien  "@
1181690286Sobrien   sar{b}\t{%2, %0|%0, %2}
1181790286Sobrien   sar{b}\t{%b2, %0|%0, %b2}"
1181890286Sobrien  [(set_attr "type" "ishift")
1181990286Sobrien   (set_attr "mode" "QI")])
1182090286Sobrien
11821117404Skan(define_insn "*ashrqi3_1_slp"
11822117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
11823117404Skan	(ashiftrt:QI (match_dup 0)
11824117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
11825169699Skan   (clobber (reg:CC FLAGS_REG))]
11826117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
11827117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
11828117404Skan  "@
11829117404Skan   sar{b}\t{%1, %0|%0, %1}
11830117404Skan   sar{b}\t{%b1, %0|%0, %b1}"
11831117404Skan  [(set_attr "type" "ishift1")
11832117404Skan   (set_attr "mode" "QI")])
11833117404Skan
1183490286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1183590286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1183690286Sobrien;; zero are optimized away.
1183790286Sobrien(define_insn "*ashrqi3_one_bit_cmp"
11838169699Skan  [(set (reg FLAGS_REG)
1183990286Sobrien	(compare
1184090286Sobrien	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11841132727Skan		       (match_operand:QI 2 "const1_operand" "I"))
1184290286Sobrien	  (const_int 0)))
11843102802Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1184490286Sobrien	(ashiftrt:QI (match_dup 1) (match_dup 2)))]
1184590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11846117404Skan   && (TARGET_SHIFT1 || optimize_size)
1184790286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
1184890286Sobrien  "sar{b}\t%0"
1184990286Sobrien  [(set_attr "type" "ishift")
1185090286Sobrien   (set (attr "length") 
1185190286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1185290286Sobrien	(const_string "2")
1185390286Sobrien	(const_string "*")))])
1185490286Sobrien
11855169699Skan(define_insn "*ashrqi3_one_bit_cconly"
11856169699Skan  [(set (reg FLAGS_REG)
11857169699Skan	(compare
11858169699Skan	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11859169699Skan		       (match_operand:QI 2 "const1_operand" "I"))
11860169699Skan	  (const_int 0)))
11861169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11862169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11863169699Skan   && (TARGET_SHIFT1 || optimize_size)
11864169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
11865169699Skan  "sar{b}\t%0"
11866169699Skan  [(set_attr "type" "ishift")
11867169699Skan   (set_attr "length" "2")])
11868169699Skan
1186990286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1187090286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1187190286Sobrien;; zero are optimized away.
1187290286Sobrien(define_insn "*ashrqi3_cmp"
11873169699Skan  [(set (reg FLAGS_REG)
1187490286Sobrien	(compare
1187590286Sobrien	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11876169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1187790286Sobrien	  (const_int 0)))
11878102802Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1187990286Sobrien	(ashiftrt:QI (match_dup 1) (match_dup 2)))]
1188090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11881169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11882169699Skan   && (optimize_size
11883169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1188490286Sobrien  "sar{b}\t{%2, %0|%0, %2}"
1188590286Sobrien  [(set_attr "type" "ishift")
1188690286Sobrien   (set_attr "mode" "QI")])
11887169699Skan
11888169699Skan(define_insn "*ashrqi3_cconly"
11889169699Skan  [(set (reg FLAGS_REG)
11890169699Skan	(compare
11891169699Skan	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11892169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11893169699Skan	  (const_int 0)))
11894169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11895169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11896169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11897169699Skan   && (optimize_size
11898169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11899169699Skan  "sar{b}\t{%2, %0|%0, %2}"
11900169699Skan  [(set_attr "type" "ishift")
11901169699Skan   (set_attr "mode" "QI")])
11902169699Skan
1190318334Speter
1190490286Sobrien;; Logical shift instructions
1190518334Speter
1190618334Speter;; See comment above `ashldi3' about how this works.
1190718334Speter
11908169699Skan(define_expand "lshrti3"
11909169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
11910169699Skan		   (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
1191190286Sobrien			        (match_operand:QI 2 "nonmemory_operand" "")))
11912169699Skan	      (clobber (reg:CC FLAGS_REG))])]
11913169699Skan  "TARGET_64BIT"
1191418334Speter{
11915169699Skan  if (! immediate_operand (operands[2], QImode))
1191618334Speter    {
11917169699Skan      emit_insn (gen_lshrti3_1 (operands[0], operands[1], operands[2]));
1191890286Sobrien      DONE;
1191918334Speter    }
11920169699Skan  ix86_expand_binary_operator (LSHIFTRT, TImode, operands);
1192118334Speter  DONE;
1192290286Sobrien})
1192318334Speter
11924169699Skan(define_insn "lshrti3_1"
11925169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11926169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
11927169699Skan		     (match_operand:QI 2 "register_operand" "c")))
11928169699Skan   (clobber (match_scratch:DI 3 "=&r"))
11929169699Skan   (clobber (reg:CC FLAGS_REG))]
11930169699Skan  "TARGET_64BIT"
11931169699Skan  "#"
11932169699Skan  [(set_attr "type" "multi")])
11933169699Skan
11934169699Skan(define_insn "*lshrti3_2"
11935169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11936169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
11937169699Skan		     (match_operand:QI 2 "immediate_operand" "O")))
11938169699Skan   (clobber (reg:CC FLAGS_REG))]
11939169699Skan  "TARGET_64BIT"
11940169699Skan  "#"
11941169699Skan  [(set_attr "type" "multi")])
11942169699Skan
11943169699Skan(define_split 
11944169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11945169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "")
11946169699Skan		     (match_operand:QI 2 "register_operand" "")))
11947169699Skan   (clobber (match_scratch:DI 3 ""))
11948169699Skan   (clobber (reg:CC FLAGS_REG))]
11949169699Skan  "TARGET_64BIT && reload_completed"
11950169699Skan  [(const_int 0)]
11951169699Skan  "ix86_split_lshr (operands, operands[3], TImode); DONE;")
11952169699Skan
11953169699Skan(define_split 
11954169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11955169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "")
11956169699Skan		     (match_operand:QI 2 "immediate_operand" "")))
11957169699Skan   (clobber (reg:CC FLAGS_REG))]
11958169699Skan  "TARGET_64BIT && reload_completed"
11959169699Skan  [(const_int 0)]
11960169699Skan  "ix86_split_lshr (operands, NULL_RTX, TImode); DONE;")
11961169699Skan
11962169699Skan(define_expand "lshrdi3"
11963169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
11964169699Skan	(lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
11965169699Skan		     (match_operand:QI 2 "nonmemory_operand" "")))]
11966169699Skan  ""
11967169699Skan  "ix86_expand_binary_operator (LSHIFTRT, DImode, operands); DONE;")
11968169699Skan
1196990286Sobrien(define_insn "*lshrdi3_1_one_bit_rex64"
1197090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1197190286Sobrien	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11972132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11973169699Skan   (clobber (reg:CC FLAGS_REG))]
1197490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
11975117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1197690286Sobrien  "shr{q}\t%0"
1197790286Sobrien  [(set_attr "type" "ishift")
1197890286Sobrien   (set (attr "length") 
1197990286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1198090286Sobrien	(const_string "2")
1198190286Sobrien	(const_string "*")))])
1198250650Sobrien
1198390286Sobrien(define_insn "*lshrdi3_1_rex64"
1198490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1198590286Sobrien	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1198690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
11987169699Skan   (clobber (reg:CC FLAGS_REG))]
1198890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1198990286Sobrien  "@
1199090286Sobrien   shr{q}\t{%2, %0|%0, %2}
1199190286Sobrien   shr{q}\t{%b2, %0|%0, %b2}"
1199290286Sobrien  [(set_attr "type" "ishift")
1199390286Sobrien   (set_attr "mode" "DI")])
1199450650Sobrien
1199590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1199690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1199790286Sobrien;; zero are optimized away.
1199890286Sobrien(define_insn "*lshrdi3_cmp_one_bit_rex64"
11999169699Skan  [(set (reg FLAGS_REG)
1200090286Sobrien	(compare
1200190286Sobrien	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12002132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1200390286Sobrien	  (const_int 0)))
1200490286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1200590286Sobrien	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
1200690286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12007117404Skan   && (TARGET_SHIFT1 || optimize_size)
1200890286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1200990286Sobrien  "shr{q}\t%0"
1201090286Sobrien  [(set_attr "type" "ishift")
1201190286Sobrien   (set (attr "length") 
1201290286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1201390286Sobrien	(const_string "2")
1201490286Sobrien	(const_string "*")))])
1201550650Sobrien
12016169699Skan(define_insn "*lshrdi3_cconly_one_bit_rex64"
12017169699Skan  [(set (reg FLAGS_REG)
12018169699Skan	(compare
12019169699Skan	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12020169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12021169699Skan	  (const_int 0)))
12022169699Skan   (clobber (match_scratch:DI 0 "=r"))]
12023169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12024169699Skan   && (TARGET_SHIFT1 || optimize_size)
12025169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12026169699Skan  "shr{q}\t%0"
12027169699Skan  [(set_attr "type" "ishift")
12028169699Skan   (set_attr "length" "2")])
12029169699Skan
1203090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1203190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1203290286Sobrien;; zero are optimized away.
1203390286Sobrien(define_insn "*lshrdi3_cmp_rex64"
12034169699Skan  [(set (reg FLAGS_REG)
1203590286Sobrien	(compare
1203690286Sobrien	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1203790286Sobrien		       (match_operand:QI 2 "const_int_operand" "e"))
1203890286Sobrien	  (const_int 0)))
1203990286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1204090286Sobrien	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
1204190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12042169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12043169699Skan   && (optimize_size
12044169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1204590286Sobrien  "shr{q}\t{%2, %0|%0, %2}"
1204690286Sobrien  [(set_attr "type" "ishift")
1204790286Sobrien   (set_attr "mode" "DI")])
1204850650Sobrien
12049169699Skan(define_insn "*lshrdi3_cconly_rex64"
12050169699Skan  [(set (reg FLAGS_REG)
12051169699Skan	(compare
12052169699Skan	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12053169699Skan		       (match_operand:QI 2 "const_int_operand" "e"))
12054169699Skan	  (const_int 0)))
12055169699Skan   (clobber (match_scratch:DI 0 "=r"))]
12056169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12057169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12058169699Skan   && (optimize_size
12059169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12060169699Skan  "shr{q}\t{%2, %0|%0, %2}"
12061169699Skan  [(set_attr "type" "ishift")
12062169699Skan   (set_attr "mode" "DI")])
1206318334Speter
12064169699Skan(define_insn "*lshrdi3_1"
1206590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1206690286Sobrien	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
1206790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "Jc")))
12068169699Skan   (clobber (reg:CC FLAGS_REG))]
1206990286Sobrien  "!TARGET_64BIT"
1207090286Sobrien  "#"
1207190286Sobrien  [(set_attr "type" "multi")])
1207218334Speter
12073169699Skan;; By default we don't ask for a scratch register, because when DImode
12074169699Skan;; values are manipulated, registers are already at a premium.  But if
12075169699Skan;; we have one handy, we won't turn it away.
12076169699Skan(define_peephole2
12077169699Skan  [(match_scratch:SI 3 "r")
12078169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
12079169699Skan		   (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
12080169699Skan			        (match_operand:QI 2 "nonmemory_operand" "")))
12081169699Skan	      (clobber (reg:CC FLAGS_REG))])
12082169699Skan   (match_dup 3)]
12083169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1208490286Sobrien  [(const_int 0)]
12085169699Skan  "ix86_split_lshr (operands, operands[3], DImode); DONE;")
1208618334Speter
1208790286Sobrien(define_split 
1208890286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1208990286Sobrien	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
1209090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12091169699Skan   (clobber (reg:CC FLAGS_REG))]
12092169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
12093169699Skan		     ? flow2_completed : reload_completed)"
1209490286Sobrien  [(const_int 0)]
12095169699Skan  "ix86_split_lshr (operands, NULL_RTX, DImode); DONE;")
1209618334Speter
1209790286Sobrien(define_expand "lshrsi3"
1209890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1209990286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
1210090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12101169699Skan   (clobber (reg:CC FLAGS_REG))]
1210290286Sobrien  ""
1210390286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, SImode, operands); DONE;")
1210418334Speter
1210590286Sobrien(define_insn "*lshrsi3_1_one_bit"
1210690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1210790286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12108132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12109169699Skan   (clobber (reg:CC FLAGS_REG))]
1211090286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12111117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1211290286Sobrien  "shr{l}\t%0"
1211390286Sobrien  [(set_attr "type" "ishift")
1211490286Sobrien   (set (attr "length") 
1211590286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1211690286Sobrien	(const_string "2")
1211790286Sobrien	(const_string "*")))])
1211818334Speter
1211990286Sobrien(define_insn "*lshrsi3_1_one_bit_zext"
1212090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1212190286Sobrien	(lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0"))
12122132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12123169699Skan   (clobber (reg:CC FLAGS_REG))]
1212490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12125117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1212690286Sobrien  "shr{l}\t%k0"
1212790286Sobrien  [(set_attr "type" "ishift")
1212890286Sobrien   (set_attr "length" "2")])
1212918334Speter
1213090286Sobrien(define_insn "*lshrsi3_1"
1213190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1213290286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1213390286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12134169699Skan   (clobber (reg:CC FLAGS_REG))]
1213590286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1213690286Sobrien  "@
1213790286Sobrien   shr{l}\t{%2, %0|%0, %2}
1213890286Sobrien   shr{l}\t{%b2, %0|%0, %b2}"
1213990286Sobrien  [(set_attr "type" "ishift")
1214090286Sobrien   (set_attr "mode" "SI")])
1214118334Speter
1214290286Sobrien(define_insn "*lshrsi3_1_zext"
1214390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1214490286Sobrien	(zero_extend:DI
1214590286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1214690286Sobrien		       (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12147169699Skan   (clobber (reg:CC FLAGS_REG))]
1214890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1214990286Sobrien  "@
1215090286Sobrien   shr{l}\t{%2, %k0|%k0, %2}
1215190286Sobrien   shr{l}\t{%b2, %k0|%k0, %b2}"
1215290286Sobrien  [(set_attr "type" "ishift")
1215390286Sobrien   (set_attr "mode" "SI")])
1215418334Speter
1215590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1215690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1215790286Sobrien;; zero are optimized away.
1215890286Sobrien(define_insn "*lshrsi3_one_bit_cmp"
12159169699Skan  [(set (reg FLAGS_REG)
1216090286Sobrien	(compare
1216190286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12162132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1216390286Sobrien	  (const_int 0)))
1216490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1216590286Sobrien	(lshiftrt:SI (match_dup 1) (match_dup 2)))]
1216690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12167117404Skan   && (TARGET_SHIFT1 || optimize_size)
1216890286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1216990286Sobrien  "shr{l}\t%0"
1217090286Sobrien  [(set_attr "type" "ishift")
1217190286Sobrien   (set (attr "length") 
1217290286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1217390286Sobrien	(const_string "2")
1217490286Sobrien	(const_string "*")))])
1217518334Speter
12176169699Skan(define_insn "*lshrsi3_one_bit_cconly"
12177169699Skan  [(set (reg FLAGS_REG)
12178169699Skan	(compare
12179169699Skan	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12180169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12181169699Skan	  (const_int 0)))
12182169699Skan   (clobber (match_scratch:SI 0 "=r"))]
12183169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12184169699Skan   && (TARGET_SHIFT1 || optimize_size)
12185169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12186169699Skan  "shr{l}\t%0"
12187169699Skan  [(set_attr "type" "ishift")
12188169699Skan   (set_attr "length" "2")])
12189169699Skan
1219090286Sobrien(define_insn "*lshrsi3_cmp_one_bit_zext"
12191169699Skan  [(set (reg FLAGS_REG)
1219290286Sobrien	(compare
1219390286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
12194132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1219590286Sobrien	  (const_int 0)))
1219690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1219790286Sobrien	(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
1219890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12199117404Skan   && (TARGET_SHIFT1 || optimize_size)
1220090286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1220190286Sobrien  "shr{l}\t%k0"
1220290286Sobrien  [(set_attr "type" "ishift")
1220390286Sobrien   (set_attr "length" "2")])
1220418334Speter
1220590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1220690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1220790286Sobrien;; zero are optimized away.
1220890286Sobrien(define_insn "*lshrsi3_cmp"
12209169699Skan  [(set (reg FLAGS_REG)
1221090286Sobrien	(compare
1221190286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12212169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1221390286Sobrien	  (const_int 0)))
1221490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1221590286Sobrien	(lshiftrt:SI (match_dup 1) (match_dup 2)))]
1221690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12217169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12218169699Skan   && (optimize_size
12219169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1222090286Sobrien  "shr{l}\t{%2, %0|%0, %2}"
1222190286Sobrien  [(set_attr "type" "ishift")
1222290286Sobrien   (set_attr "mode" "SI")])
1222390286Sobrien
12224169699Skan(define_insn "*lshrsi3_cconly"
12225169699Skan  [(set (reg FLAGS_REG)
12226169699Skan      (compare
12227169699Skan	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12228169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
12229169699Skan        (const_int 0)))
12230169699Skan   (clobber (match_scratch:SI 0 "=r"))]
12231169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12232169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12233169699Skan   && (optimize_size
12234169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12235169699Skan  "shr{l}\t{%2, %0|%0, %2}"
12236169699Skan  [(set_attr "type" "ishift")
12237169699Skan   (set_attr "mode" "SI")])
12238169699Skan
1223990286Sobrien(define_insn "*lshrsi3_cmp_zext"
12240169699Skan  [(set (reg FLAGS_REG)
1224190286Sobrien	(compare
1224290286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
12243169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1224490286Sobrien	  (const_int 0)))
1224590286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1224690286Sobrien	(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
1224790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12248169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12249169699Skan   && (optimize_size
12250169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1225190286Sobrien  "shr{l}\t{%2, %k0|%k0, %2}"
1225290286Sobrien  [(set_attr "type" "ishift")
1225390286Sobrien   (set_attr "mode" "SI")])
1225490286Sobrien
1225590286Sobrien(define_expand "lshrhi3"
1225690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1225790286Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
1225890286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12259169699Skan   (clobber (reg:CC FLAGS_REG))]
1226090286Sobrien  "TARGET_HIMODE_MATH"
1226190286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, HImode, operands); DONE;")
1226290286Sobrien
1226390286Sobrien(define_insn "*lshrhi3_1_one_bit"
1226450650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1226550650Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12266132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12267169699Skan   (clobber (reg:CC FLAGS_REG))]
1226890286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12269117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1227090286Sobrien  "shr{w}\t%0"
1227190286Sobrien  [(set_attr "type" "ishift")
1227290286Sobrien   (set (attr "length") 
1227390286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1227490286Sobrien	(const_string "2")
1227590286Sobrien	(const_string "*")))])
1227618334Speter
1227790286Sobrien(define_insn "*lshrhi3_1"
1227890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1227990286Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1228090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12281169699Skan   (clobber (reg:CC FLAGS_REG))]
1228290286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1228390286Sobrien  "@
1228490286Sobrien   shr{w}\t{%2, %0|%0, %2}
1228590286Sobrien   shr{w}\t{%b2, %0|%0, %b2}"
1228690286Sobrien  [(set_attr "type" "ishift")
1228790286Sobrien   (set_attr "mode" "HI")])
1228890286Sobrien
1228990286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1229090286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1229190286Sobrien;; zero are optimized away.
1229290286Sobrien(define_insn "*lshrhi3_one_bit_cmp"
12293169699Skan  [(set (reg FLAGS_REG)
1229490286Sobrien	(compare
1229590286Sobrien	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12296132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1229790286Sobrien	  (const_int 0)))
1229890286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1229990286Sobrien	(lshiftrt:HI (match_dup 1) (match_dup 2)))]
1230090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12301117404Skan   && (TARGET_SHIFT1 || optimize_size)
1230290286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1230390286Sobrien  "shr{w}\t%0"
1230490286Sobrien  [(set_attr "type" "ishift")
1230590286Sobrien   (set (attr "length") 
1230690286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1230790286Sobrien	(const_string "2")
1230890286Sobrien	(const_string "*")))])
1230990286Sobrien
12310169699Skan(define_insn "*lshrhi3_one_bit_cconly"
12311169699Skan  [(set (reg FLAGS_REG)
12312169699Skan	(compare
12313169699Skan	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12314169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12315169699Skan	  (const_int 0)))
12316169699Skan   (clobber (match_scratch:HI 0 "=r"))]
12317169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12318169699Skan   && (TARGET_SHIFT1 || optimize_size)
12319169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12320169699Skan  "shr{w}\t%0"
12321169699Skan  [(set_attr "type" "ishift")
12322169699Skan   (set_attr "length" "2")])
12323169699Skan
1232490286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1232590286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1232690286Sobrien;; zero are optimized away.
1232790286Sobrien(define_insn "*lshrhi3_cmp"
12328169699Skan  [(set (reg FLAGS_REG)
1232990286Sobrien	(compare
1233090286Sobrien	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12331169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1233290286Sobrien	  (const_int 0)))
1233390286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1233490286Sobrien	(lshiftrt:HI (match_dup 1) (match_dup 2)))]
1233590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12336169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12337169699Skan   && (optimize_size
12338169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1233990286Sobrien  "shr{w}\t{%2, %0|%0, %2}"
1234090286Sobrien  [(set_attr "type" "ishift")
1234190286Sobrien   (set_attr "mode" "HI")])
1234290286Sobrien
12343169699Skan(define_insn "*lshrhi3_cconly"
12344169699Skan  [(set (reg FLAGS_REG)
12345169699Skan	(compare
12346169699Skan	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12347169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
12348169699Skan	  (const_int 0)))
12349169699Skan   (clobber (match_scratch:HI 0 "=r"))]
12350169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12351169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12352169699Skan   && (optimize_size
12353169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12354169699Skan  "shr{w}\t{%2, %0|%0, %2}"
12355169699Skan  [(set_attr "type" "ishift")
12356169699Skan   (set_attr "mode" "HI")])
12357169699Skan
1235890286Sobrien(define_expand "lshrqi3"
1235990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1236090286Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
1236190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12362169699Skan   (clobber (reg:CC FLAGS_REG))]
1236390286Sobrien  "TARGET_QIMODE_MATH"
1236490286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, QImode, operands); DONE;")
1236590286Sobrien
1236690286Sobrien(define_insn "*lshrqi3_1_one_bit"
1236750650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1236850650Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12369132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12370169699Skan   (clobber (reg:CC FLAGS_REG))]
1237190286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12372117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1237390286Sobrien  "shr{b}\t%0"
1237490286Sobrien  [(set_attr "type" "ishift")
1237590286Sobrien   (set (attr "length") 
1237690286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1237790286Sobrien	(const_string "2")
1237890286Sobrien	(const_string "*")))])
1237990286Sobrien
12380117404Skan(define_insn "*lshrqi3_1_one_bit_slp"
12381117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12382117404Skan	(lshiftrt:QI (match_dup 0)
12383132727Skan		     (match_operand:QI 1 "const1_operand" "")))
12384169699Skan   (clobber (reg:CC FLAGS_REG))]
12385117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12386117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12387117404Skan  "shr{b}\t%0"
12388117404Skan  [(set_attr "type" "ishift1")
12389117404Skan   (set (attr "length") 
12390117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
12391117404Skan	(const_string "2")
12392117404Skan	(const_string "*")))])
12393117404Skan
1239490286Sobrien(define_insn "*lshrqi3_1"
1239590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1239690286Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1239790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12398169699Skan   (clobber (reg:CC FLAGS_REG))]
1239990286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
1240090286Sobrien  "@
1240190286Sobrien   shr{b}\t{%2, %0|%0, %2}
1240290286Sobrien   shr{b}\t{%b2, %0|%0, %b2}"
1240390286Sobrien  [(set_attr "type" "ishift")
1240490286Sobrien   (set_attr "mode" "QI")])
1240590286Sobrien
12406117404Skan(define_insn "*lshrqi3_1_slp"
12407117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12408117404Skan	(lshiftrt:QI (match_dup 0)
12409117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
12410169699Skan   (clobber (reg:CC FLAGS_REG))]
12411117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12412117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12413117404Skan  "@
12414117404Skan   shr{b}\t{%1, %0|%0, %1}
12415117404Skan   shr{b}\t{%b1, %0|%0, %b1}"
12416117404Skan  [(set_attr "type" "ishift1")
12417117404Skan   (set_attr "mode" "QI")])
12418117404Skan
1241990286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1242090286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1242190286Sobrien;; zero are optimized away.
1242290286Sobrien(define_insn "*lshrqi2_one_bit_cmp"
12423169699Skan  [(set (reg FLAGS_REG)
1242490286Sobrien	(compare
1242590286Sobrien	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12426132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1242790286Sobrien	  (const_int 0)))
1242890286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1242990286Sobrien	(lshiftrt:QI (match_dup 1) (match_dup 2)))]
1243090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12431117404Skan   && (TARGET_SHIFT1 || optimize_size)
1243290286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
1243390286Sobrien  "shr{b}\t%0"
1243490286Sobrien  [(set_attr "type" "ishift")
1243590286Sobrien   (set (attr "length") 
1243690286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1243790286Sobrien	(const_string "2")
1243890286Sobrien	(const_string "*")))])
1243990286Sobrien
12440169699Skan(define_insn "*lshrqi2_one_bit_cconly"
12441169699Skan  [(set (reg FLAGS_REG)
12442169699Skan	(compare
12443169699Skan	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12444169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12445169699Skan	  (const_int 0)))
12446169699Skan   (clobber (match_scratch:QI 0 "=q"))]
12447169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12448169699Skan   && (TARGET_SHIFT1 || optimize_size)
12449169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
12450169699Skan  "shr{b}\t%0"
12451169699Skan  [(set_attr "type" "ishift")
12452169699Skan   (set_attr "length" "2")])
12453169699Skan
1245490286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1245590286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1245690286Sobrien;; zero are optimized away.
1245790286Sobrien(define_insn "*lshrqi2_cmp"
12458169699Skan  [(set (reg FLAGS_REG)
1245990286Sobrien	(compare
1246090286Sobrien	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12461169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1246290286Sobrien	  (const_int 0)))
1246390286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1246490286Sobrien	(lshiftrt:QI (match_dup 1) (match_dup 2)))]
1246590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12466169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12467169699Skan   && (optimize_size
12468169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1246990286Sobrien  "shr{b}\t{%2, %0|%0, %2}"
1247090286Sobrien  [(set_attr "type" "ishift")
1247190286Sobrien   (set_attr "mode" "QI")])
12472169699Skan
12473169699Skan(define_insn "*lshrqi2_cconly"
12474169699Skan  [(set (reg FLAGS_REG)
12475169699Skan	(compare
12476169699Skan	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12477169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
12478169699Skan	  (const_int 0)))
12479169699Skan   (clobber (match_scratch:QI 0 "=q"))]
12480169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12481169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12482169699Skan   && (optimize_size
12483169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12484169699Skan  "shr{b}\t{%2, %0|%0, %2}"
12485169699Skan  [(set_attr "type" "ishift")
12486169699Skan   (set_attr "mode" "QI")])
1248718334Speter
1248890286Sobrien;; Rotate instructions
1248918334Speter
1249090286Sobrien(define_expand "rotldi3"
12491169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
12492169699Skan	(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
1249390286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12494169699Skan   (clobber (reg:CC FLAGS_REG))]
12495169699Skan ""
12496169699Skan{
12497169699Skan  if (TARGET_64BIT)
12498169699Skan    {
12499169699Skan      ix86_expand_binary_operator (ROTATE, DImode, operands);
12500169699Skan      DONE;
12501169699Skan    }
12502169699Skan  if (!const_1_to_31_operand (operands[2], VOIDmode))
12503169699Skan    FAIL;
12504169699Skan  emit_insn (gen_ix86_rotldi3 (operands[0], operands[1], operands[2]));
12505169699Skan  DONE;
12506169699Skan})
1250718334Speter
12508169699Skan;; Implement rotation using two double-precision shift instructions
12509169699Skan;; and a scratch register.   
12510169699Skan(define_insn_and_split "ix86_rotldi3"
12511169699Skan [(set (match_operand:DI 0 "register_operand" "=r")
12512169699Skan       (rotate:DI (match_operand:DI 1 "register_operand" "0")
12513169699Skan                  (match_operand:QI 2 "const_1_to_31_operand" "I")))
12514169699Skan  (clobber (reg:CC FLAGS_REG))
12515169699Skan  (clobber (match_scratch:SI 3 "=&r"))]
12516169699Skan "!TARGET_64BIT"
12517169699Skan "" 
12518169699Skan "&& reload_completed"
12519169699Skan [(set (match_dup 3) (match_dup 4))
12520169699Skan  (parallel
12521169699Skan   [(set (match_dup 4)
12522169699Skan         (ior:SI (ashift:SI (match_dup 4) (match_dup 2))
12523169699Skan                 (lshiftrt:SI (match_dup 5)
12524169699Skan                              (minus:QI (const_int 32) (match_dup 2)))))
12525169699Skan    (clobber (reg:CC FLAGS_REG))])
12526169699Skan  (parallel
12527169699Skan   [(set (match_dup 5)
12528169699Skan         (ior:SI (ashift:SI (match_dup 5) (match_dup 2))
12529169699Skan                 (lshiftrt:SI (match_dup 3)
12530169699Skan                              (minus:QI (const_int 32) (match_dup 2)))))
12531169699Skan    (clobber (reg:CC FLAGS_REG))])]
12532169699Skan "split_di (operands, 1, operands + 4, operands + 5);")
12533169699Skan 
1253490286Sobrien(define_insn "*rotlsi3_1_one_bit_rex64"
1253590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1253690286Sobrien	(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12537132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12538169699Skan   (clobber (reg:CC FLAGS_REG))]
1253990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)
12540117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1254190286Sobrien  "rol{q}\t%0"
12542117404Skan  [(set_attr "type" "rotate")
1254390286Sobrien   (set (attr "length") 
1254490286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1254590286Sobrien	(const_string "2")
1254690286Sobrien	(const_string "*")))])
1254718334Speter
1254890286Sobrien(define_insn "*rotldi3_1_rex64"
1254990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1255090286Sobrien	(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1255190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "e,c")))
12552169699Skan   (clobber (reg:CC FLAGS_REG))]
1255390286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)"
1255490286Sobrien  "@
1255590286Sobrien   rol{q}\t{%2, %0|%0, %2}
1255690286Sobrien   rol{q}\t{%b2, %0|%0, %b2}"
12557117404Skan  [(set_attr "type" "rotate")
1255890286Sobrien   (set_attr "mode" "DI")])
1255990286Sobrien
1256090286Sobrien(define_expand "rotlsi3"
1256190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1256290286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "")
1256390286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12564169699Skan   (clobber (reg:CC FLAGS_REG))]
1256518334Speter  ""
1256690286Sobrien  "ix86_expand_binary_operator (ROTATE, SImode, operands); DONE;")
1256718334Speter
1256890286Sobrien(define_insn "*rotlsi3_1_one_bit"
1256950650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1257090286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12571132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12572169699Skan   (clobber (reg:CC FLAGS_REG))]
1257390286Sobrien  "ix86_binary_operator_ok (ROTATE, SImode, operands)
12574117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1257590286Sobrien  "rol{l}\t%0"
12576117404Skan  [(set_attr "type" "rotate")
1257790286Sobrien   (set (attr "length") 
1257890286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1257990286Sobrien	(const_string "2")
1258090286Sobrien	(const_string "*")))])
1258118334Speter
1258290286Sobrien(define_insn "*rotlsi3_1_one_bit_zext"
1258390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1258490286Sobrien	(zero_extend:DI
1258590286Sobrien	  (rotate:SI (match_operand:SI 1 "register_operand" "0")
12586132727Skan		     (match_operand:QI 2 "const1_operand" ""))))
12587169699Skan   (clobber (reg:CC FLAGS_REG))]
1258890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)
12589117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1259090286Sobrien  "rol{l}\t%k0"
12591117404Skan  [(set_attr "type" "rotate")
1259290286Sobrien   (set_attr "length" "2")])
1259318334Speter
1259490286Sobrien(define_insn "*rotlsi3_1"
1259590286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1259690286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1259790286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12598169699Skan   (clobber (reg:CC FLAGS_REG))]
1259990286Sobrien  "ix86_binary_operator_ok (ROTATE, SImode, operands)"
1260090286Sobrien  "@
1260190286Sobrien   rol{l}\t{%2, %0|%0, %2}
1260290286Sobrien   rol{l}\t{%b2, %0|%0, %b2}"
12603117404Skan  [(set_attr "type" "rotate")
1260490286Sobrien   (set_attr "mode" "SI")])
1260518334Speter
1260690286Sobrien(define_insn "*rotlsi3_1_zext"
1260790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1260890286Sobrien	(zero_extend:DI
1260990286Sobrien	  (rotate:SI (match_operand:SI 1 "register_operand" "0,0")
1261090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12611169699Skan   (clobber (reg:CC FLAGS_REG))]
1261290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)"
1261390286Sobrien  "@
1261490286Sobrien   rol{l}\t{%2, %k0|%k0, %2}
1261590286Sobrien   rol{l}\t{%b2, %k0|%k0, %b2}"
12616117404Skan  [(set_attr "type" "rotate")
1261790286Sobrien   (set_attr "mode" "SI")])
1261818334Speter
1261990286Sobrien(define_expand "rotlhi3"
1262090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1262190286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "")
1262290286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12623169699Skan   (clobber (reg:CC FLAGS_REG))]
1262490286Sobrien  "TARGET_HIMODE_MATH"
1262590286Sobrien  "ix86_expand_binary_operator (ROTATE, HImode, operands); DONE;")
1262618334Speter
1262790286Sobrien(define_insn "*rotlhi3_1_one_bit"
1262890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1262990286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12630132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12631169699Skan   (clobber (reg:CC FLAGS_REG))]
1263290286Sobrien  "ix86_binary_operator_ok (ROTATE, HImode, operands)
12633117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1263490286Sobrien  "rol{w}\t%0"
12635117404Skan  [(set_attr "type" "rotate")
1263690286Sobrien   (set (attr "length") 
1263790286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1263890286Sobrien	(const_string "2")
1263990286Sobrien	(const_string "*")))])
1264018334Speter
1264190286Sobrien(define_insn "*rotlhi3_1"
1264290286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1264390286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1264490286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12645169699Skan   (clobber (reg:CC FLAGS_REG))]
1264690286Sobrien  "ix86_binary_operator_ok (ROTATE, HImode, operands)"
1264790286Sobrien  "@
1264890286Sobrien   rol{w}\t{%2, %0|%0, %2}
1264990286Sobrien   rol{w}\t{%b2, %0|%0, %b2}"
12650117404Skan  [(set_attr "type" "rotate")
1265190286Sobrien   (set_attr "mode" "HI")])
1265218334Speter
1265390286Sobrien(define_expand "rotlqi3"
1265490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1265590286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "")
1265690286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12657169699Skan   (clobber (reg:CC FLAGS_REG))]
1265890286Sobrien  "TARGET_QIMODE_MATH"
1265990286Sobrien  "ix86_expand_binary_operator (ROTATE, QImode, operands); DONE;")
1266018334Speter
12661117404Skan(define_insn "*rotlqi3_1_one_bit_slp"
12662117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12663117404Skan	(rotate:QI (match_dup 0)
12664132727Skan		   (match_operand:QI 1 "const1_operand" "")))
12665169699Skan   (clobber (reg:CC FLAGS_REG))]
12666117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12667117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12668117404Skan  "rol{b}\t%0"
12669117404Skan  [(set_attr "type" "rotate1")
12670117404Skan   (set (attr "length") 
12671117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
12672117404Skan	(const_string "2")
12673117404Skan	(const_string "*")))])
12674117404Skan
1267590286Sobrien(define_insn "*rotlqi3_1_one_bit"
1267690286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1267790286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12678132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12679169699Skan   (clobber (reg:CC FLAGS_REG))]
1268090286Sobrien  "ix86_binary_operator_ok (ROTATE, QImode, operands)
12681117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1268290286Sobrien  "rol{b}\t%0"
12683117404Skan  [(set_attr "type" "rotate")
1268490286Sobrien   (set (attr "length") 
1268590286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1268690286Sobrien	(const_string "2")
1268790286Sobrien	(const_string "*")))])
1268818334Speter
12689117404Skan(define_insn "*rotlqi3_1_slp"
12690117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12691117404Skan	(rotate:QI (match_dup 0)
12692117404Skan		   (match_operand:QI 1 "nonmemory_operand" "I,c")))
12693169699Skan   (clobber (reg:CC FLAGS_REG))]
12694117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12695117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12696117404Skan  "@
12697117404Skan   rol{b}\t{%1, %0|%0, %1}
12698117404Skan   rol{b}\t{%b1, %0|%0, %b1}"
12699117404Skan  [(set_attr "type" "rotate1")
12700117404Skan   (set_attr "mode" "QI")])
12701117404Skan
1270290286Sobrien(define_insn "*rotlqi3_1"
1270390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1270490286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1270590286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12706169699Skan   (clobber (reg:CC FLAGS_REG))]
1270790286Sobrien  "ix86_binary_operator_ok (ROTATE, QImode, operands)"
1270890286Sobrien  "@
1270990286Sobrien   rol{b}\t{%2, %0|%0, %2}
1271090286Sobrien   rol{b}\t{%b2, %0|%0, %b2}"
12711117404Skan  [(set_attr "type" "rotate")
1271290286Sobrien   (set_attr "mode" "QI")])
1271318334Speter
1271490286Sobrien(define_expand "rotrdi3"
12715169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
12716169699Skan	(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
12717169699Skan		   (match_operand:QI 2 "nonmemory_operand" "")))
12718169699Skan   (clobber (reg:CC FLAGS_REG))]
12719169699Skan ""
12720169699Skan{
12721169699Skan  if (TARGET_64BIT)
12722169699Skan    {
12723169699Skan      ix86_expand_binary_operator (ROTATERT, DImode, operands);
12724169699Skan      DONE;
12725169699Skan    }
12726169699Skan  if (!const_1_to_31_operand (operands[2], VOIDmode))
12727169699Skan    FAIL;
12728169699Skan  emit_insn (gen_ix86_rotrdi3 (operands[0], operands[1], operands[2]));
12729169699Skan  DONE;
12730169699Skan})
12731169699Skan  
12732169699Skan;; Implement rotation using two double-precision shift instructions
12733169699Skan;; and a scratch register.   
12734169699Skan(define_insn_and_split "ix86_rotrdi3"
12735169699Skan [(set (match_operand:DI 0 "register_operand" "=r")
12736169699Skan       (rotatert:DI (match_operand:DI 1 "register_operand" "0")
12737169699Skan                    (match_operand:QI 2 "const_1_to_31_operand" "I")))
12738169699Skan  (clobber (reg:CC FLAGS_REG))
12739169699Skan  (clobber (match_scratch:SI 3 "=&r"))]
12740169699Skan "!TARGET_64BIT"
12741169699Skan ""
12742169699Skan "&& reload_completed"
12743169699Skan [(set (match_dup 3) (match_dup 4))
12744169699Skan  (parallel
12745169699Skan   [(set (match_dup 4)
12746169699Skan         (ior:SI (ashiftrt:SI (match_dup 4) (match_dup 2))
12747169699Skan                 (ashift:SI (match_dup 5)
12748169699Skan                            (minus:QI (const_int 32) (match_dup 2)))))
12749169699Skan    (clobber (reg:CC FLAGS_REG))])
12750169699Skan  (parallel
12751169699Skan   [(set (match_dup 5)
12752169699Skan         (ior:SI (ashiftrt:SI (match_dup 5) (match_dup 2))
12753169699Skan                 (ashift:SI (match_dup 3)
12754169699Skan                            (minus:QI (const_int 32) (match_dup 2)))))
12755169699Skan    (clobber (reg:CC FLAGS_REG))])]
12756169699Skan "split_di (operands, 1, operands + 4, operands + 5);")
1275718334Speter
1275890286Sobrien(define_insn "*rotrdi3_1_one_bit_rex64"
1275990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1276090286Sobrien	(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12761132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12762169699Skan   (clobber (reg:CC FLAGS_REG))]
1276390286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)
12764117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1276590286Sobrien  "ror{q}\t%0"
12766117404Skan  [(set_attr "type" "rotate")
1276790286Sobrien   (set (attr "length") 
1276890286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1276990286Sobrien	(const_string "2")
1277090286Sobrien	(const_string "*")))])
1277118334Speter
1277290286Sobrien(define_insn "*rotrdi3_1_rex64"
1277390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1277490286Sobrien	(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1277590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
12776169699Skan   (clobber (reg:CC FLAGS_REG))]
1277790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)"
1277890286Sobrien  "@
1277990286Sobrien   ror{q}\t{%2, %0|%0, %2}
1278090286Sobrien   ror{q}\t{%b2, %0|%0, %b2}"
12781117404Skan  [(set_attr "type" "rotate")
1278290286Sobrien   (set_attr "mode" "DI")])
1278390286Sobrien
1278490286Sobrien(define_expand "rotrsi3"
1278590286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1278690286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "")
1278790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12788169699Skan   (clobber (reg:CC FLAGS_REG))]
1278990286Sobrien  ""
1279090286Sobrien  "ix86_expand_binary_operator (ROTATERT, SImode, operands); DONE;")
1279190286Sobrien
1279290286Sobrien(define_insn "*rotrsi3_1_one_bit"
1279350650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1279490286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12795132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12796169699Skan   (clobber (reg:CC FLAGS_REG))]
1279790286Sobrien  "ix86_binary_operator_ok (ROTATERT, SImode, operands)
12798117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1279990286Sobrien  "ror{l}\t%0"
12800117404Skan  [(set_attr "type" "rotate")
1280190286Sobrien   (set (attr "length") 
1280290286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1280390286Sobrien	(const_string "2")
1280490286Sobrien	(const_string "*")))])
1280518334Speter
1280690286Sobrien(define_insn "*rotrsi3_1_one_bit_zext"
1280790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1280890286Sobrien	(zero_extend:DI
1280990286Sobrien	  (rotatert:SI (match_operand:SI 1 "register_operand" "0")
12810132727Skan		       (match_operand:QI 2 "const1_operand" ""))))
12811169699Skan   (clobber (reg:CC FLAGS_REG))]
1281290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)
12813117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1281490286Sobrien  "ror{l}\t%k0"
12815117404Skan  [(set_attr "type" "rotate")
1281690286Sobrien   (set (attr "length") 
1281790286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1281890286Sobrien	(const_string "2")
1281990286Sobrien	(const_string "*")))])
1282018334Speter
1282190286Sobrien(define_insn "*rotrsi3_1"
1282290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1282390286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1282490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12825169699Skan   (clobber (reg:CC FLAGS_REG))]
1282690286Sobrien  "ix86_binary_operator_ok (ROTATERT, SImode, operands)"
1282790286Sobrien  "@
1282890286Sobrien   ror{l}\t{%2, %0|%0, %2}
1282990286Sobrien   ror{l}\t{%b2, %0|%0, %b2}"
12830117404Skan  [(set_attr "type" "rotate")
1283190286Sobrien   (set_attr "mode" "SI")])
1283218334Speter
1283390286Sobrien(define_insn "*rotrsi3_1_zext"
1283490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1283590286Sobrien	(zero_extend:DI
1283690286Sobrien	  (rotatert:SI (match_operand:SI 1 "register_operand" "0,0")
1283790286Sobrien		       (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12838169699Skan   (clobber (reg:CC FLAGS_REG))]
1283990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)"
1284090286Sobrien  "@
1284190286Sobrien   ror{l}\t{%2, %k0|%k0, %2}
1284290286Sobrien   ror{l}\t{%b2, %k0|%k0, %b2}"
12843117404Skan  [(set_attr "type" "rotate")
1284490286Sobrien   (set_attr "mode" "SI")])
1284518334Speter
1284690286Sobrien(define_expand "rotrhi3"
1284790286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1284890286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "")
1284990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12850169699Skan   (clobber (reg:CC FLAGS_REG))]
1285190286Sobrien  "TARGET_HIMODE_MATH"
1285290286Sobrien  "ix86_expand_binary_operator (ROTATERT, HImode, operands); DONE;")
1285318334Speter
1285490286Sobrien(define_insn "*rotrhi3_one_bit"
1285590286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1285690286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12857132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12858169699Skan   (clobber (reg:CC FLAGS_REG))]
1285990286Sobrien  "ix86_binary_operator_ok (ROTATERT, HImode, operands)
12860117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1286190286Sobrien  "ror{w}\t%0"
12862117404Skan  [(set_attr "type" "rotate")
1286390286Sobrien   (set (attr "length") 
1286490286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1286590286Sobrien	(const_string "2")
1286690286Sobrien	(const_string "*")))])
1286718334Speter
1286890286Sobrien(define_insn "*rotrhi3"
1286990286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1287090286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1287190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12872169699Skan   (clobber (reg:CC FLAGS_REG))]
1287390286Sobrien  "ix86_binary_operator_ok (ROTATERT, HImode, operands)"
1287490286Sobrien  "@
1287590286Sobrien   ror{w}\t{%2, %0|%0, %2}
1287690286Sobrien   ror{w}\t{%b2, %0|%0, %b2}"
12877117404Skan  [(set_attr "type" "rotate")
1287890286Sobrien   (set_attr "mode" "HI")])
1287918334Speter
1288090286Sobrien(define_expand "rotrqi3"
1288190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1288290286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "")
1288390286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12884169699Skan   (clobber (reg:CC FLAGS_REG))]
1288590286Sobrien  "TARGET_QIMODE_MATH"
1288690286Sobrien  "ix86_expand_binary_operator (ROTATERT, QImode, operands); DONE;")
1288718334Speter
1288890286Sobrien(define_insn "*rotrqi3_1_one_bit"
1288990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1289090286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12891132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12892169699Skan   (clobber (reg:CC FLAGS_REG))]
1289390286Sobrien  "ix86_binary_operator_ok (ROTATERT, QImode, operands)
12894117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1289590286Sobrien  "ror{b}\t%0"
12896117404Skan  [(set_attr "type" "rotate")
1289790286Sobrien   (set (attr "length") 
1289890286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1289990286Sobrien	(const_string "2")
1290090286Sobrien	(const_string "*")))])
1290118334Speter
12902117404Skan(define_insn "*rotrqi3_1_one_bit_slp"
12903117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12904117404Skan	(rotatert:QI (match_dup 0)
12905132727Skan		     (match_operand:QI 1 "const1_operand" "")))
12906169699Skan   (clobber (reg:CC FLAGS_REG))]
12907117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12908117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12909117404Skan  "ror{b}\t%0"
12910117404Skan  [(set_attr "type" "rotate1")
12911117404Skan   (set (attr "length") 
12912117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
12913117404Skan	(const_string "2")
12914117404Skan	(const_string "*")))])
12915117404Skan
1291690286Sobrien(define_insn "*rotrqi3_1"
1291790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1291890286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1291990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12920169699Skan   (clobber (reg:CC FLAGS_REG))]
1292190286Sobrien  "ix86_binary_operator_ok (ROTATERT, QImode, operands)"
1292290286Sobrien  "@
1292390286Sobrien   ror{b}\t{%2, %0|%0, %2}
1292490286Sobrien   ror{b}\t{%b2, %0|%0, %b2}"
12925117404Skan  [(set_attr "type" "rotate")
1292690286Sobrien   (set_attr "mode" "QI")])
12927117404Skan
12928117404Skan(define_insn "*rotrqi3_1_slp"
12929117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12930117404Skan	(rotatert:QI (match_dup 0)
12931117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
12932169699Skan   (clobber (reg:CC FLAGS_REG))]
12933117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12934117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12935117404Skan  "@
12936117404Skan   ror{b}\t{%1, %0|%0, %1}
12937117404Skan   ror{b}\t{%b1, %0|%0, %b1}"
12938117404Skan  [(set_attr "type" "rotate1")
12939117404Skan   (set_attr "mode" "QI")])
1294090286Sobrien
1294190286Sobrien;; Bit set / bit test instructions
1294218334Speter
1294390286Sobrien(define_expand "extv"
1294490286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1294590286Sobrien	(sign_extract:SI (match_operand:SI 1 "register_operand" "")
12946169699Skan			 (match_operand:SI 2 "const8_operand" "")
12947169699Skan			 (match_operand:SI 3 "const8_operand" "")))]
1294890286Sobrien  ""
1294918334Speter{
1295090286Sobrien  /* Handle extractions from %ah et al.  */
1295190286Sobrien  if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8)
1295290286Sobrien    FAIL;
1295318334Speter
1295490286Sobrien  /* From mips.md: extract_bit_field doesn't verify that our source
1295590286Sobrien     matches the predicate, so check it again here.  */
12956169699Skan  if (! ext_register_operand (operands[1], VOIDmode))
1295790286Sobrien    FAIL;
1295890286Sobrien})
1295918334Speter
1296090286Sobrien(define_expand "extzv"
1296190286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1296290286Sobrien	(zero_extract:SI (match_operand 1 "ext_register_operand" "")
12963169699Skan			 (match_operand:SI 2 "const8_operand" "")
12964169699Skan			 (match_operand:SI 3 "const8_operand" "")))]
1296590286Sobrien  ""
1296690286Sobrien{
1296790286Sobrien  /* Handle extractions from %ah et al.  */
1296890286Sobrien  if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8)
1296990286Sobrien    FAIL;
1297018334Speter
1297190286Sobrien  /* From mips.md: extract_bit_field doesn't verify that our source
1297290286Sobrien     matches the predicate, so check it again here.  */
12973169699Skan  if (! ext_register_operand (operands[1], VOIDmode))
1297490286Sobrien    FAIL;
1297590286Sobrien})
1297618334Speter
1297790286Sobrien(define_expand "insv"
12978132727Skan  [(set (zero_extract (match_operand 0 "ext_register_operand" "")
12979169699Skan		      (match_operand 1 "const8_operand" "")
12980169699Skan		      (match_operand 2 "const8_operand" ""))
12981132727Skan        (match_operand 3 "register_operand" ""))]
1298290286Sobrien  ""
1298390286Sobrien{
12984169699Skan  /* Handle insertions to %ah et al.  */
1298590286Sobrien  if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8)
1298690286Sobrien    FAIL;
1298718334Speter
1298890286Sobrien  /* From mips.md: insert_bit_field doesn't verify that our source
1298990286Sobrien     matches the predicate, so check it again here.  */
12990169699Skan  if (! ext_register_operand (operands[0], VOIDmode))
1299190286Sobrien    FAIL;
12992132727Skan
12993132727Skan  if (TARGET_64BIT)
12994132727Skan    emit_insn (gen_movdi_insv_1_rex64 (operands[0], operands[3]));
12995132727Skan  else
12996132727Skan    emit_insn (gen_movsi_insv_1 (operands[0], operands[3]));
12997132727Skan
12998132727Skan  DONE;
1299990286Sobrien})
1300018334Speter
1300190286Sobrien;; %%% bts, btr, btc, bt.
13002169699Skan;; In general these instructions are *slow* when applied to memory,
13003169699Skan;; since they enforce atomic operation.  When applied to registers,
13004169699Skan;; it depends on the cpu implementation.  They're never faster than
13005169699Skan;; the corresponding and/ior/xor operations, so with 32-bit there's
13006169699Skan;; no point.  But in 64-bit, we can't hold the relevant immediates
13007169699Skan;; within the instruction itself, so operating on bits in the high
13008169699Skan;; 32-bits of a register becomes easier.
13009169699Skan;;
13010169699Skan;; These are slow on Nocona, but fast on Athlon64.  We do require the use
13011169699Skan;; of btrq and btcq for corner cases of post-reload expansion of absdf and
13012169699Skan;; negdf respectively, so they can never be disabled entirely.
13013169699Skan
13014169699Skan(define_insn "*btsq"
13015169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13016169699Skan			 (const_int 1)
13017169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13018169699Skan	(const_int 1))
13019169699Skan   (clobber (reg:CC FLAGS_REG))]
13020169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13021169699Skan  "bts{q} %1,%0"
13022169699Skan  [(set_attr "type" "alu1")])
13023169699Skan
13024169699Skan(define_insn "*btrq"
13025169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13026169699Skan			 (const_int 1)
13027169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13028169699Skan	(const_int 0))
13029169699Skan   (clobber (reg:CC FLAGS_REG))]
13030169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13031169699Skan  "btr{q} %1,%0"
13032169699Skan  [(set_attr "type" "alu1")])
13033169699Skan
13034169699Skan(define_insn "*btcq"
13035169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13036169699Skan			 (const_int 1)
13037169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13038169699Skan	(not:DI (zero_extract:DI (match_dup 0) (const_int 1) (match_dup 1))))
13039169699Skan   (clobber (reg:CC FLAGS_REG))]
13040169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13041169699Skan  "btc{q} %1,%0"
13042169699Skan  [(set_attr "type" "alu1")])
13043169699Skan
13044169699Skan;; Allow Nocona to avoid these instructions if a register is available.
13045169699Skan
13046169699Skan(define_peephole2
13047169699Skan  [(match_scratch:DI 2 "r")
13048169699Skan   (parallel [(set (zero_extract:DI
13049169699Skan		     (match_operand:DI 0 "register_operand" "")
13050169699Skan		     (const_int 1)
13051169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13052169699Skan		   (const_int 1))
13053169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13054169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13055169699Skan  [(const_int 0)]
13056169699Skan{
13057169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13058169699Skan  rtx op1;
13059169699Skan
13060169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13061169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13062169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13063169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13064169699Skan  else
13065169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13066169699Skan
13067169699Skan  op1 = immed_double_const (lo, hi, DImode);
13068169699Skan  if (i >= 31)
13069169699Skan    {
13070169699Skan      emit_move_insn (operands[2], op1);
13071169699Skan      op1 = operands[2];
13072169699Skan    }
13073169699Skan
13074169699Skan  emit_insn (gen_iordi3 (operands[0], operands[0], op1));
13075169699Skan  DONE;
13076169699Skan})
13077169699Skan
13078169699Skan(define_peephole2
13079169699Skan  [(match_scratch:DI 2 "r")
13080169699Skan   (parallel [(set (zero_extract:DI
13081169699Skan		     (match_operand:DI 0 "register_operand" "")
13082169699Skan		     (const_int 1)
13083169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13084169699Skan		   (const_int 0))
13085169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13086169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13087169699Skan  [(const_int 0)]
13088169699Skan{
13089169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13090169699Skan  rtx op1;
13091169699Skan
13092169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13093169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13094169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13095169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13096169699Skan  else
13097169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13098169699Skan
13099169699Skan  op1 = immed_double_const (~lo, ~hi, DImode);
13100169699Skan  if (i >= 32)
13101169699Skan    {
13102169699Skan      emit_move_insn (operands[2], op1);
13103169699Skan      op1 = operands[2];
13104169699Skan    }
13105169699Skan
13106169699Skan  emit_insn (gen_anddi3 (operands[0], operands[0], op1));
13107169699Skan  DONE;
13108169699Skan})
13109169699Skan
13110169699Skan(define_peephole2
13111169699Skan  [(match_scratch:DI 2 "r")
13112169699Skan   (parallel [(set (zero_extract:DI
13113169699Skan		     (match_operand:DI 0 "register_operand" "")
13114169699Skan		     (const_int 1)
13115169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13116169699Skan	      (not:DI (zero_extract:DI
13117169699Skan			(match_dup 0) (const_int 1) (match_dup 1))))
13118169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13119169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13120169699Skan  [(const_int 0)]
13121169699Skan{
13122169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13123169699Skan  rtx op1;
13124169699Skan
13125169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13126169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13127169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13128169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13129169699Skan  else
13130169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13131169699Skan
13132169699Skan  op1 = immed_double_const (lo, hi, DImode);
13133169699Skan  if (i >= 31)
13134169699Skan    {
13135169699Skan      emit_move_insn (operands[2], op1);
13136169699Skan      op1 = operands[2];
13137169699Skan    }
13138169699Skan
13139169699Skan  emit_insn (gen_xordi3 (operands[0], operands[0], op1));
13140169699Skan  DONE;
13141169699Skan})
1314218334Speter
1314318334Speter;; Store-flag instructions.
1314418334Speter
1314518334Speter;; For all sCOND expanders, also expand the compare or test insn that
1314618334Speter;; generates cc0.  Generate an equality comparison if `seq' or `sne'.
1314718334Speter
1314890286Sobrien;; %%% Do the expansion to SImode.  If PII, do things the xor+setcc way
1314990286Sobrien;; to avoid partial register stalls.  Otherwise do things the setcc+movzx
1315090286Sobrien;; way, which can later delete the movzx if only QImode is needed.
1315190286Sobrien
1315218334Speter(define_expand "seq"
1315390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13154169699Skan        (eq:QI (reg:CC FLAGS_REG) (const_int 0)))]
1315518334Speter  ""
1315690286Sobrien  "if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;")
1315718334Speter
1315818334Speter(define_expand "sne"
1315990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13160169699Skan        (ne:QI (reg:CC FLAGS_REG) (const_int 0)))]
1316118334Speter  ""
1316290286Sobrien  "if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;")
1316318334Speter
1316418334Speter(define_expand "sgt"
1316590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13166169699Skan        (gt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1316718334Speter  ""
1316890286Sobrien  "if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;")
1316918334Speter
1317018334Speter(define_expand "sgtu"
1317190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13172169699Skan        (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1317318334Speter  ""
1317490286Sobrien  "if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;")
1317518334Speter
1317618334Speter(define_expand "slt"
1317790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13178169699Skan        (lt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1317918334Speter  ""
1318090286Sobrien  "if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;")
1318118334Speter
1318218334Speter(define_expand "sltu"
1318390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13184169699Skan        (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1318518334Speter  ""
1318690286Sobrien  "if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;")
1318718334Speter
1318818334Speter(define_expand "sge"
1318990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13190169699Skan        (ge:QI (reg:CC FLAGS_REG) (const_int 0)))]
1319118334Speter  ""
1319290286Sobrien  "if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;")
1319318334Speter
1319418334Speter(define_expand "sgeu"
1319590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13196169699Skan        (geu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1319718334Speter  ""
1319890286Sobrien  "if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;")
1319918334Speter
1320018334Speter(define_expand "sle"
1320190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13202169699Skan        (le:QI (reg:CC FLAGS_REG) (const_int 0)))]
1320318334Speter  ""
1320490286Sobrien  "if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;")
1320518334Speter
1320618334Speter(define_expand "sleu"
1320790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13208169699Skan        (leu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1320918334Speter  ""
1321090286Sobrien  "if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;")
1321118334Speter
1321290286Sobrien(define_expand "sunordered"
1321390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13214169699Skan        (unordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
1321590286Sobrien  "TARGET_80387 || TARGET_SSE"
1321690286Sobrien  "if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;")
1321752296Sobrien
1321890286Sobrien(define_expand "sordered"
1321990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13220169699Skan        (ordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
1322190286Sobrien  "TARGET_80387"
1322290286Sobrien  "if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;")
1322390286Sobrien
1322490286Sobrien(define_expand "suneq"
1322590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13226169699Skan        (uneq:QI (reg:CC FLAGS_REG) (const_int 0)))]
1322790286Sobrien  "TARGET_80387 || TARGET_SSE"
1322890286Sobrien  "if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;")
1322990286Sobrien
1323090286Sobrien(define_expand "sunge"
1323190286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13232169699Skan        (unge:QI (reg:CC FLAGS_REG) (const_int 0)))]
1323390286Sobrien  "TARGET_80387 || TARGET_SSE"
1323490286Sobrien  "if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;")
1323590286Sobrien
1323690286Sobrien(define_expand "sungt"
1323790286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13238169699Skan        (ungt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1323990286Sobrien  "TARGET_80387 || TARGET_SSE"
1324090286Sobrien  "if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;")
1324190286Sobrien
1324290286Sobrien(define_expand "sunle"
1324390286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13244169699Skan        (unle:QI (reg:CC FLAGS_REG) (const_int 0)))]
1324590286Sobrien  "TARGET_80387 || TARGET_SSE"
1324690286Sobrien  "if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;")
1324790286Sobrien
1324890286Sobrien(define_expand "sunlt"
1324990286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13250169699Skan        (unlt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1325190286Sobrien  "TARGET_80387 || TARGET_SSE"
1325290286Sobrien  "if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;")
1325390286Sobrien
1325490286Sobrien(define_expand "sltgt"
1325590286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13256169699Skan        (ltgt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1325790286Sobrien  "TARGET_80387 || TARGET_SSE"
1325890286Sobrien  "if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;")
1325990286Sobrien
1326090286Sobrien(define_insn "*setcc_1"
1326152296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1326290286Sobrien	(match_operator:QI 1 "ix86_comparison_operator"
13263169699Skan	  [(reg FLAGS_REG) (const_int 0)]))]
1326490286Sobrien  ""
1326590286Sobrien  "set%C1\t%0"
1326690286Sobrien  [(set_attr "type" "setcc")
1326790286Sobrien   (set_attr "mode" "QI")])
1326890286Sobrien
13269169699Skan(define_insn "*setcc_2"
1327090286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
1327190286Sobrien	(match_operator:QI 1 "ix86_comparison_operator"
13272169699Skan	  [(reg FLAGS_REG) (const_int 0)]))]
1327390286Sobrien  ""
1327490286Sobrien  "set%C1\t%0"
1327590286Sobrien  [(set_attr "type" "setcc")
1327690286Sobrien   (set_attr "mode" "QI")])
1327790286Sobrien
1327890286Sobrien;; In general it is not safe to assume too much about CCmode registers,
1327990286Sobrien;; so simplify-rtx stops when it sees a second one.  Under certain 
1328090286Sobrien;; conditions this is safe on x86, so help combine not create
1328190286Sobrien;;
1328290286Sobrien;;	seta	%al
1328390286Sobrien;;	testb	%al, %al
1328490286Sobrien;;	sete	%al
1328590286Sobrien
1328690286Sobrien(define_split 
1328790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1328890286Sobrien	(ne:QI (match_operator 1 "ix86_comparison_operator"
13289169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1329090286Sobrien	    (const_int 0)))]
1329190286Sobrien  ""
1329290286Sobrien  [(set (match_dup 0) (match_dup 1))]
1329352296Sobrien{
1329490286Sobrien  PUT_MODE (operands[1], QImode);
1329590286Sobrien})
1329652296Sobrien
1329790286Sobrien(define_split 
1329890286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
1329990286Sobrien	(ne:QI (match_operator 1 "ix86_comparison_operator"
13300169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1330190286Sobrien	    (const_int 0)))]
1330290286Sobrien  ""
1330390286Sobrien  [(set (match_dup 0) (match_dup 1))]
1330490286Sobrien{
1330590286Sobrien  PUT_MODE (operands[1], QImode);
1330690286Sobrien})
1330752296Sobrien
1330890286Sobrien(define_split 
1330990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1331090286Sobrien	(eq:QI (match_operator 1 "ix86_comparison_operator"
13311169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1331290286Sobrien	    (const_int 0)))]
1331390286Sobrien  ""
1331490286Sobrien  [(set (match_dup 0) (match_dup 1))]
1331590286Sobrien{
1331690286Sobrien  rtx new_op1 = copy_rtx (operands[1]);
1331790286Sobrien  operands[1] = new_op1;
1331890286Sobrien  PUT_MODE (new_op1, QImode);
13319169699Skan  PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
13320169699Skan					     GET_MODE (XEXP (new_op1, 0))));
1332190286Sobrien
1332290286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1332390286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1332490286Sobrien  if (! ix86_comparison_operator (new_op1, VOIDmode))
1332590286Sobrien    FAIL;
1332690286Sobrien})
1332790286Sobrien
1332890286Sobrien(define_split 
1332990286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
1333090286Sobrien	(eq:QI (match_operator 1 "ix86_comparison_operator"
13331169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1333290286Sobrien	    (const_int 0)))]
1333390286Sobrien  ""
1333490286Sobrien  [(set (match_dup 0) (match_dup 1))]
1333590286Sobrien{
1333690286Sobrien  rtx new_op1 = copy_rtx (operands[1]);
1333790286Sobrien  operands[1] = new_op1;
1333890286Sobrien  PUT_MODE (new_op1, QImode);
13339169699Skan  PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
13340169699Skan					     GET_MODE (XEXP (new_op1, 0))));
1334190286Sobrien
1334290286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1334390286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1334490286Sobrien  if (! ix86_comparison_operator (new_op1, VOIDmode))
1334590286Sobrien    FAIL;
1334690286Sobrien})
1334790286Sobrien
1334890286Sobrien;; The SSE store flag instructions saves 0 or 0xffffffff to the result.
1334990286Sobrien;; subsequent logical operations are used to imitate conditional moves.
1335090286Sobrien;; 0xffffffff is NaN, but not in normalized form, so we can't represent
13351169699Skan;; it directly.
1335290286Sobrien
1335390286Sobrien(define_insn "*sse_setccsf"
1335490286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1335590286Sobrien	(match_operator:SF 1 "sse_comparison_operator"
1335690286Sobrien	  [(match_operand:SF 2 "register_operand" "0")
1335790286Sobrien	   (match_operand:SF 3 "nonimmediate_operand" "xm")]))]
13358169699Skan  "TARGET_SSE"
1335990286Sobrien  "cmp%D1ss\t{%3, %0|%0, %3}"
13360117404Skan  [(set_attr "type" "ssecmp")
1336190286Sobrien   (set_attr "mode" "SF")])
1336290286Sobrien
1336390286Sobrien(define_insn "*sse_setccdf"
1336490286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1336590286Sobrien	(match_operator:DF 1 "sse_comparison_operator"
1336690286Sobrien	  [(match_operand:DF 2 "register_operand" "0")
1336790286Sobrien	   (match_operand:DF 3 "nonimmediate_operand" "Ym")]))]
13368169699Skan  "TARGET_SSE2"
1336990286Sobrien  "cmp%D1sd\t{%3, %0|%0, %3}"
13370117404Skan  [(set_attr "type" "ssecmp")
1337190286Sobrien   (set_attr "mode" "DF")])
1337218334Speter
1337318334Speter;; Basic conditional jump instructions.
1337418334Speter;; We ignore the overflow flag for signed branch instructions.
1337518334Speter
1337618334Speter;; For all bCOND expanders, also expand the compare or test insn that
13377169699Skan;; generates reg FLAGS_REG.  Generate an equality comparison if `beq' or `bne'.
1337818334Speter
1337918334Speter(define_expand "beq"
1338090286Sobrien  [(set (pc)
1338190286Sobrien	(if_then_else (match_dup 1)
1338218334Speter		      (label_ref (match_operand 0 "" ""))
1338318334Speter		      (pc)))]
1338418334Speter  ""
1338590286Sobrien  "ix86_expand_branch (EQ, operands[0]); DONE;")
1338618334Speter
1338718334Speter(define_expand "bne"
1338890286Sobrien  [(set (pc)
1338990286Sobrien	(if_then_else (match_dup 1)
1339018334Speter		      (label_ref (match_operand 0 "" ""))
1339118334Speter		      (pc)))]
1339218334Speter  ""
1339390286Sobrien  "ix86_expand_branch (NE, operands[0]); DONE;")
1339418334Speter
1339518334Speter(define_expand "bgt"
1339690286Sobrien  [(set (pc)
1339790286Sobrien	(if_then_else (match_dup 1)
1339818334Speter		      (label_ref (match_operand 0 "" ""))
1339918334Speter		      (pc)))]
1340018334Speter  ""
1340190286Sobrien  "ix86_expand_branch (GT, operands[0]); DONE;")
1340218334Speter
1340318334Speter(define_expand "bgtu"
1340490286Sobrien  [(set (pc)
1340590286Sobrien	(if_then_else (match_dup 1)
1340618334Speter		      (label_ref (match_operand 0 "" ""))
1340718334Speter		      (pc)))]
1340818334Speter  ""
1340990286Sobrien  "ix86_expand_branch (GTU, operands[0]); DONE;")
1341018334Speter
1341118334Speter(define_expand "blt"
1341290286Sobrien  [(set (pc)
1341390286Sobrien	(if_then_else (match_dup 1)
1341418334Speter		      (label_ref (match_operand 0 "" ""))
1341518334Speter		      (pc)))]
1341618334Speter  ""
1341790286Sobrien  "ix86_expand_branch (LT, operands[0]); DONE;")
1341818334Speter
1341918334Speter(define_expand "bltu"
1342090286Sobrien  [(set (pc)
1342190286Sobrien	(if_then_else (match_dup 1)
1342218334Speter		      (label_ref (match_operand 0 "" ""))
1342318334Speter		      (pc)))]
1342418334Speter  ""
1342590286Sobrien  "ix86_expand_branch (LTU, operands[0]); DONE;")
1342618334Speter
1342718334Speter(define_expand "bge"
1342890286Sobrien  [(set (pc)
1342990286Sobrien	(if_then_else (match_dup 1)
1343018334Speter		      (label_ref (match_operand 0 "" ""))
1343118334Speter		      (pc)))]
1343218334Speter  ""
1343390286Sobrien  "ix86_expand_branch (GE, operands[0]); DONE;")
1343418334Speter
1343518334Speter(define_expand "bgeu"
1343690286Sobrien  [(set (pc)
1343790286Sobrien	(if_then_else (match_dup 1)
1343818334Speter		      (label_ref (match_operand 0 "" ""))
1343918334Speter		      (pc)))]
1344018334Speter  ""
1344190286Sobrien  "ix86_expand_branch (GEU, operands[0]); DONE;")
1344218334Speter
1344318334Speter(define_expand "ble"
1344490286Sobrien  [(set (pc)
1344590286Sobrien	(if_then_else (match_dup 1)
1344618334Speter		      (label_ref (match_operand 0 "" ""))
1344718334Speter		      (pc)))]
1344818334Speter  ""
1344990286Sobrien  "ix86_expand_branch (LE, operands[0]); DONE;")
1345018334Speter
1345118334Speter(define_expand "bleu"
1345290286Sobrien  [(set (pc)
1345390286Sobrien	(if_then_else (match_dup 1)
1345418334Speter		      (label_ref (match_operand 0 "" ""))
1345518334Speter		      (pc)))]
1345618334Speter  ""
1345790286Sobrien  "ix86_expand_branch (LEU, operands[0]); DONE;")
1345818334Speter
1345990286Sobrien(define_expand "bunordered"
1346018334Speter  [(set (pc)
1346190286Sobrien	(if_then_else (match_dup 1)
1346290286Sobrien		      (label_ref (match_operand 0 "" ""))
1346318334Speter		      (pc)))]
13464169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1346590286Sobrien  "ix86_expand_branch (UNORDERED, operands[0]); DONE;")
1346618334Speter
1346790286Sobrien(define_expand "bordered"
1346890286Sobrien  [(set (pc)
1346990286Sobrien	(if_then_else (match_dup 1)
1347090286Sobrien		      (label_ref (match_operand 0 "" ""))
1347190286Sobrien		      (pc)))]
13472169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1347390286Sobrien  "ix86_expand_branch (ORDERED, operands[0]); DONE;")
1347418334Speter
1347590286Sobrien(define_expand "buneq"
1347618334Speter  [(set (pc)
1347790286Sobrien	(if_then_else (match_dup 1)
1347890286Sobrien		      (label_ref (match_operand 0 "" ""))
1347990286Sobrien		      (pc)))]
13480169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1348190286Sobrien  "ix86_expand_branch (UNEQ, operands[0]); DONE;")
1348218334Speter
1348390286Sobrien(define_expand "bunge"
1348490286Sobrien  [(set (pc)
1348590286Sobrien	(if_then_else (match_dup 1)
1348690286Sobrien		      (label_ref (match_operand 0 "" ""))
1348790286Sobrien		      (pc)))]
13488169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1348990286Sobrien  "ix86_expand_branch (UNGE, operands[0]); DONE;")
1349018334Speter
1349190286Sobrien(define_expand "bungt"
1349218334Speter  [(set (pc)
1349390286Sobrien	(if_then_else (match_dup 1)
1349490286Sobrien		      (label_ref (match_operand 0 "" ""))
1349590286Sobrien		      (pc)))]
13496169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1349790286Sobrien  "ix86_expand_branch (UNGT, operands[0]); DONE;")
1349818334Speter
1349990286Sobrien(define_expand "bunle"
1350090286Sobrien  [(set (pc)
1350190286Sobrien	(if_then_else (match_dup 1)
1350290286Sobrien		      (label_ref (match_operand 0 "" ""))
1350390286Sobrien		      (pc)))]
13504169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1350590286Sobrien  "ix86_expand_branch (UNLE, operands[0]); DONE;")
1350618334Speter
1350790286Sobrien(define_expand "bunlt"
1350890286Sobrien  [(set (pc)
1350990286Sobrien	(if_then_else (match_dup 1)
1351090286Sobrien		      (label_ref (match_operand 0 "" ""))
1351190286Sobrien		      (pc)))]
13512169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1351390286Sobrien  "ix86_expand_branch (UNLT, operands[0]); DONE;")
1351418334Speter
1351590286Sobrien(define_expand "bltgt"
1351690286Sobrien  [(set (pc)
1351790286Sobrien	(if_then_else (match_dup 1)
1351890286Sobrien		      (label_ref (match_operand 0 "" ""))
1351990286Sobrien		      (pc)))]
13520169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1352190286Sobrien  "ix86_expand_branch (LTGT, operands[0]); DONE;")
1352218334Speter
1352390286Sobrien(define_insn "*jcc_1"
1352490286Sobrien  [(set (pc)
1352590286Sobrien	(if_then_else (match_operator 1 "ix86_comparison_operator"
13526169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1352790286Sobrien		      (label_ref (match_operand 0 "" ""))
1352890286Sobrien		      (pc)))]
1352918334Speter  ""
1353090286Sobrien  "%+j%C1\t%l0"
1353190286Sobrien  [(set_attr "type" "ibr")
13532117404Skan   (set_attr "modrm" "0")
13533117404Skan   (set (attr "length")
1353490286Sobrien	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13535117404Skan				  (const_int -126))
1353690286Sobrien			      (lt (minus (match_dup 0) (pc))
13537117404Skan				  (const_int 128)))
13538117404Skan	     (const_int 2)
13539117404Skan	     (const_int 6)))])
1354018334Speter
1354190286Sobrien(define_insn "*jcc_2"
1354218334Speter  [(set (pc)
1354390286Sobrien	(if_then_else (match_operator 1 "ix86_comparison_operator"
13544169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1354590286Sobrien		      (pc)
1354690286Sobrien		      (label_ref (match_operand 0 "" ""))))]
1354718334Speter  ""
1354890286Sobrien  "%+j%c1\t%l0"
1354990286Sobrien  [(set_attr "type" "ibr")
13550117404Skan   (set_attr "modrm" "0")
13551117404Skan   (set (attr "length")
1355290286Sobrien	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13553117404Skan				  (const_int -126))
1355490286Sobrien			      (lt (minus (match_dup 0) (pc))
13555117404Skan				  (const_int 128)))
13556117404Skan	     (const_int 2)
13557117404Skan	     (const_int 6)))])
1355890286Sobrien
1355990286Sobrien;; In general it is not safe to assume too much about CCmode registers,
1356090286Sobrien;; so simplify-rtx stops when it sees a second one.  Under certain 
1356190286Sobrien;; conditions this is safe on x86, so help combine not create
1356290286Sobrien;;
1356390286Sobrien;;	seta	%al
1356490286Sobrien;;	testb	%al, %al
1356590286Sobrien;;	je	Lfoo
1356690286Sobrien
1356790286Sobrien(define_split 
1356890286Sobrien  [(set (pc)
1356990286Sobrien	(if_then_else (ne (match_operator 0 "ix86_comparison_operator"
13570169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1357190286Sobrien			  (const_int 0))
1357290286Sobrien		      (label_ref (match_operand 1 "" ""))
1357390286Sobrien		      (pc)))]
1357490286Sobrien  ""
1357590286Sobrien  [(set (pc)
1357690286Sobrien	(if_then_else (match_dup 0)
1357790286Sobrien		      (label_ref (match_dup 1))
1357890286Sobrien		      (pc)))]
1357918334Speter{
1358090286Sobrien  PUT_MODE (operands[0], VOIDmode);
1358190286Sobrien})
1358290286Sobrien  
1358390286Sobrien(define_split 
1358490286Sobrien  [(set (pc)
1358590286Sobrien	(if_then_else (eq (match_operator 0 "ix86_comparison_operator"
13586169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1358790286Sobrien			  (const_int 0))
1358890286Sobrien		      (label_ref (match_operand 1 "" ""))
1358990286Sobrien		      (pc)))]
1359090286Sobrien  ""
1359190286Sobrien  [(set (pc)
1359290286Sobrien	(if_then_else (match_dup 0)
1359390286Sobrien		      (label_ref (match_dup 1))
1359490286Sobrien		      (pc)))]
1359590286Sobrien{
1359690286Sobrien  rtx new_op0 = copy_rtx (operands[0]);
1359790286Sobrien  operands[0] = new_op0;
1359890286Sobrien  PUT_MODE (new_op0, VOIDmode);
13599169699Skan  PUT_CODE (new_op0, ix86_reverse_condition (GET_CODE (new_op0),
13600169699Skan					     GET_MODE (XEXP (new_op0, 0))));
1360152296Sobrien
1360290286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1360390286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1360490286Sobrien  if (! ix86_comparison_operator (new_op0, VOIDmode))
1360590286Sobrien    FAIL;
1360690286Sobrien})
1360752296Sobrien
1360890286Sobrien;; Define combination compare-and-branch fp compare instructions to use
1360990286Sobrien;; during early optimization.  Splitting the operation apart early makes
1361090286Sobrien;; for bad code when we want to reverse the operation.
1361118334Speter
13612169699Skan(define_insn "*fp_jcc_1_mixed"
1361390286Sobrien  [(set (pc)
1361490286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13615169699Skan			[(match_operand 1 "register_operand" "f,x")
13616169699Skan			 (match_operand 2 "nonimmediate_operand" "f,xm")])
1361790286Sobrien	  (label_ref (match_operand 3 "" ""))
1361890286Sobrien	  (pc)))
13619169699Skan   (clobber (reg:CCFP FPSR_REG))
13620169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13621169699Skan  "TARGET_MIX_SSE_I387
13622169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1362390286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1362490286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1362590286Sobrien  "#")
1362618334Speter
1362790286Sobrien(define_insn "*fp_jcc_1_sse"
1362890286Sobrien  [(set (pc)
1362990286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13630169699Skan			[(match_operand 1 "register_operand" "x")
13631169699Skan			 (match_operand 2 "nonimmediate_operand" "xm")])
1363290286Sobrien	  (label_ref (match_operand 3 "" ""))
1363390286Sobrien	  (pc)))
13634169699Skan   (clobber (reg:CCFP FPSR_REG))
13635169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13636169699Skan  "TARGET_SSE_MATH
1363790286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1363890286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1363990286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1364090286Sobrien  "#")
1364118334Speter
13642169699Skan(define_insn "*fp_jcc_1_387"
1364390286Sobrien  [(set (pc)
1364490286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13645169699Skan			[(match_operand 1 "register_operand" "f")
13646169699Skan			 (match_operand 2 "register_operand" "f")])
1364790286Sobrien	  (label_ref (match_operand 3 "" ""))
1364890286Sobrien	  (pc)))
13649169699Skan   (clobber (reg:CCFP FPSR_REG))
13650169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13651169699Skan  "TARGET_CMOVE && TARGET_80387
13652169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
1365390286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1365490286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1365590286Sobrien  "#")
1365618334Speter
13657169699Skan(define_insn "*fp_jcc_2_mixed"
1365818334Speter  [(set (pc)
1365990286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13660169699Skan			[(match_operand 1 "register_operand" "f,x")
13661169699Skan			 (match_operand 2 "nonimmediate_operand" "f,xm")])
1366290286Sobrien	  (pc)
1366390286Sobrien	  (label_ref (match_operand 3 "" ""))))
13664169699Skan   (clobber (reg:CCFP FPSR_REG))
13665169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13666169699Skan  "TARGET_MIX_SSE_I387
13667169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1366890286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1366990286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1367090286Sobrien  "#")
1367118334Speter
1367290286Sobrien(define_insn "*fp_jcc_2_sse"
1367390286Sobrien  [(set (pc)
1367490286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13675169699Skan			[(match_operand 1 "register_operand" "x")
13676169699Skan			 (match_operand 2 "nonimmediate_operand" "xm")])
1367790286Sobrien	  (pc)
1367890286Sobrien	  (label_ref (match_operand 3 "" ""))))
13679169699Skan   (clobber (reg:CCFP FPSR_REG))
13680169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13681169699Skan  "TARGET_SSE_MATH
1368290286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1368390286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1368490286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1368590286Sobrien  "#")
1368618334Speter
13687169699Skan(define_insn "*fp_jcc_2_387"
1368890286Sobrien  [(set (pc)
1368990286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13690169699Skan			[(match_operand 1 "register_operand" "f")
13691169699Skan			 (match_operand 2 "register_operand" "f")])
1369290286Sobrien	  (pc)
1369390286Sobrien	  (label_ref (match_operand 3 "" ""))))
13694169699Skan   (clobber (reg:CCFP FPSR_REG))
13695169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13696169699Skan  "TARGET_CMOVE && TARGET_80387
13697169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
1369890286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1369990286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1370090286Sobrien  "#")
1370118334Speter
13702169699Skan(define_insn "*fp_jcc_3_387"
1370390286Sobrien  [(set (pc)
1370490286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1370590286Sobrien			[(match_operand 1 "register_operand" "f")
1370690286Sobrien			 (match_operand 2 "nonimmediate_operand" "fm")])
1370790286Sobrien	  (label_ref (match_operand 3 "" ""))
1370890286Sobrien	  (pc)))
13709169699Skan   (clobber (reg:CCFP FPSR_REG))
13710169699Skan   (clobber (reg:CCFP FLAGS_REG))
1371190286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1371290286Sobrien  "TARGET_80387
1371390286Sobrien   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
1371490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1371590286Sobrien   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
1371690286Sobrien   && SELECT_CC_MODE (GET_CODE (operands[0]),
1371790286Sobrien		      operands[1], operands[2]) == CCFPmode
1371890286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1371990286Sobrien  "#")
1372018334Speter
13721169699Skan(define_insn "*fp_jcc_4_387"
1372250650Sobrien  [(set (pc)
1372390286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1372490286Sobrien			[(match_operand 1 "register_operand" "f")
1372590286Sobrien			 (match_operand 2 "nonimmediate_operand" "fm")])
1372690286Sobrien	  (pc)
1372790286Sobrien	  (label_ref (match_operand 3 "" ""))))
13728169699Skan   (clobber (reg:CCFP FPSR_REG))
13729169699Skan   (clobber (reg:CCFP FLAGS_REG))
1373090286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1373190286Sobrien  "TARGET_80387
1373290286Sobrien   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
1373390286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1373490286Sobrien   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
1373590286Sobrien   && SELECT_CC_MODE (GET_CODE (operands[0]),
1373690286Sobrien		      operands[1], operands[2]) == CCFPmode
1373790286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1373890286Sobrien  "#")
1373950650Sobrien
13740169699Skan(define_insn "*fp_jcc_5_387"
1374150650Sobrien  [(set (pc)
1374290286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1374390286Sobrien			[(match_operand 1 "register_operand" "f")
1374490286Sobrien			 (match_operand 2 "register_operand" "f")])
1374590286Sobrien	  (label_ref (match_operand 3 "" ""))
1374690286Sobrien	  (pc)))
13747169699Skan   (clobber (reg:CCFP FPSR_REG))
13748169699Skan   (clobber (reg:CCFP FLAGS_REG))
1374990286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1375090286Sobrien  "TARGET_80387
1375190286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
1375290286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1375390286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1375490286Sobrien  "#")
1375550650Sobrien
13756169699Skan(define_insn "*fp_jcc_6_387"
1375750650Sobrien  [(set (pc)
1375890286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1375990286Sobrien			[(match_operand 1 "register_operand" "f")
1376090286Sobrien			 (match_operand 2 "register_operand" "f")])
1376190286Sobrien	  (pc)
1376290286Sobrien	  (label_ref (match_operand 3 "" ""))))
13763169699Skan   (clobber (reg:CCFP FPSR_REG))
13764169699Skan   (clobber (reg:CCFP FLAGS_REG))
1376590286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1376690286Sobrien  "TARGET_80387
1376790286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
1376890286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1376990286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1377090286Sobrien  "#")
1377150650Sobrien
13772169699Skan(define_insn "*fp_jcc_7_387"
13773169699Skan  [(set (pc)
13774169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13775169699Skan			[(match_operand 1 "register_operand" "f")
13776169699Skan			 (match_operand 2 "const0_operand" "X")])
13777169699Skan	  (label_ref (match_operand 3 "" ""))
13778169699Skan	  (pc)))
13779169699Skan   (clobber (reg:CCFP FPSR_REG))
13780169699Skan   (clobber (reg:CCFP FLAGS_REG))
13781169699Skan   (clobber (match_scratch:HI 4 "=a"))]
13782169699Skan  "TARGET_80387
13783169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
13784169699Skan   && GET_MODE (operands[1]) == GET_MODE (operands[2])
13785169699Skan   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
13786169699Skan   && SELECT_CC_MODE (GET_CODE (operands[0]),
13787169699Skan		      operands[1], operands[2]) == CCFPmode
13788169699Skan   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
13789169699Skan  "#")
13790169699Skan
13791169699Skan;; The order of operands in *fp_jcc_8_387 is forced by combine in
13792169699Skan;; simplify_comparison () function. Float operator is treated as RTX_OBJ
13793169699Skan;; with a precedence over other operators and is always put in the first
13794169699Skan;; place. Swap condition and operands to match ficom instruction.
13795169699Skan
13796169699Skan(define_insn "*fp_jcc_8<mode>_387"
13797169699Skan  [(set (pc)
13798169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13799169699Skan			[(match_operator 1 "float_operator"
13800169699Skan			   [(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")])
13801169699Skan			   (match_operand 3 "register_operand" "f,f")])
13802169699Skan	  (label_ref (match_operand 4 "" ""))
13803169699Skan	  (pc)))
13804169699Skan   (clobber (reg:CCFP FPSR_REG))
13805169699Skan   (clobber (reg:CCFP FLAGS_REG))
13806169699Skan   (clobber (match_scratch:HI 5 "=a,a"))]
13807169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
13808169699Skan   && FLOAT_MODE_P (GET_MODE (operands[3]))
13809169699Skan   && GET_MODE (operands[1]) == GET_MODE (operands[3])
13810169699Skan   && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0])))
13811169699Skan   && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
13812169699Skan   && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))"
13813169699Skan  "#")
13814169699Skan
1381590286Sobrien(define_split
1381650650Sobrien  [(set (pc)
1381790286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1381890286Sobrien			[(match_operand 1 "register_operand" "")
1381990286Sobrien			 (match_operand 2 "nonimmediate_operand" "")])
1382090286Sobrien	  (match_operand 3 "" "")
1382190286Sobrien	  (match_operand 4 "" "")))
13822169699Skan   (clobber (reg:CCFP FPSR_REG))
13823169699Skan   (clobber (reg:CCFP FLAGS_REG))]
1382490286Sobrien  "reload_completed"
1382590286Sobrien  [(const_int 0)]
1382650650Sobrien{
1382790286Sobrien  ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
13828169699Skan	                operands[3], operands[4], NULL_RTX, NULL_RTX);
1382990286Sobrien  DONE;
1383090286Sobrien})
1383150650Sobrien
1383290286Sobrien(define_split
1383350650Sobrien  [(set (pc)
1383490286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1383590286Sobrien			[(match_operand 1 "register_operand" "")
13836169699Skan			 (match_operand 2 "general_operand" "")])
1383790286Sobrien	  (match_operand 3 "" "")
1383890286Sobrien	  (match_operand 4 "" "")))
13839169699Skan   (clobber (reg:CCFP FPSR_REG))
13840169699Skan   (clobber (reg:CCFP FLAGS_REG))
1384190286Sobrien   (clobber (match_scratch:HI 5 "=a"))]
1384290286Sobrien  "reload_completed"
13843169699Skan  [(const_int 0)]
1384450650Sobrien{
1384590286Sobrien  ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
13846169699Skan	     		operands[3], operands[4], operands[5], NULL_RTX);
1384790286Sobrien  DONE;
1384890286Sobrien})
13849169699Skan
13850169699Skan(define_split
13851169699Skan  [(set (pc)
13852169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13853169699Skan			[(match_operator 1 "float_operator"
13854169699Skan			   [(match_operand:X87MODEI12 2 "memory_operand" "")])
13855169699Skan			   (match_operand 3 "register_operand" "")])
13856169699Skan	  (match_operand 4 "" "")
13857169699Skan	  (match_operand 5 "" "")))
13858169699Skan   (clobber (reg:CCFP FPSR_REG))
13859169699Skan   (clobber (reg:CCFP FLAGS_REG))
13860169699Skan   (clobber (match_scratch:HI 6 "=a"))]
13861169699Skan  "reload_completed"
13862169699Skan  [(const_int 0)]
13863169699Skan{
13864169699Skan  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[2]);
13865169699Skan  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
13866169699Skan			operands[3], operands[7],
13867169699Skan			operands[4], operands[5], operands[6], NULL_RTX);
13868169699Skan  DONE;
13869169699Skan})
13870169699Skan
13871169699Skan;; %%% Kill this when reload knows how to do it.
13872169699Skan(define_split
13873169699Skan  [(set (pc)
13874169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13875169699Skan			[(match_operator 1 "float_operator"
13876169699Skan			   [(match_operand:X87MODEI12 2 "register_operand" "")])
13877169699Skan			   (match_operand 3 "register_operand" "")])
13878169699Skan	  (match_operand 4 "" "")
13879169699Skan	  (match_operand 5 "" "")))
13880169699Skan   (clobber (reg:CCFP FPSR_REG))
13881169699Skan   (clobber (reg:CCFP FLAGS_REG))
13882169699Skan   (clobber (match_scratch:HI 6 "=a"))]
13883169699Skan  "reload_completed"
13884169699Skan  [(const_int 0)]
13885169699Skan{
13886169699Skan  operands[7] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
13887169699Skan  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[7]);
13888169699Skan  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
13889169699Skan			operands[3], operands[7],
13890169699Skan			operands[4], operands[5], operands[6], operands[2]);
13891169699Skan  DONE;
13892169699Skan})
1389390286Sobrien
1389490286Sobrien;; Unconditional and other jump instructions
1389550650Sobrien
1389690286Sobrien(define_insn "jump"
1389750650Sobrien  [(set (pc)
1389890286Sobrien	(label_ref (match_operand 0 "" "")))]
1389950650Sobrien  ""
1390090286Sobrien  "jmp\t%l0"
13901117404Skan  [(set_attr "type" "ibr")
13902117404Skan   (set (attr "length")
13903117404Skan	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13904117404Skan				  (const_int -126))
13905117404Skan			      (lt (minus (match_dup 0) (pc))
13906117404Skan				  (const_int 128)))
13907117404Skan	     (const_int 2)
13908117404Skan	     (const_int 5)))
13909117404Skan   (set_attr "modrm" "0")])
1391090286Sobrien
1391190286Sobrien(define_expand "indirect_jump"
1391290286Sobrien  [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))]
1391390286Sobrien  ""
1391490286Sobrien  "")
1391590286Sobrien
1391690286Sobrien(define_insn "*indirect_jump"
1391790286Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
1391890286Sobrien  "!TARGET_64BIT"
1391990286Sobrien  "jmp\t%A0"
1392090286Sobrien  [(set_attr "type" "ibr")
1392190286Sobrien   (set_attr "length_immediate" "0")])
1392290286Sobrien
1392390286Sobrien(define_insn "*indirect_jump_rtx64"
1392490286Sobrien  [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm"))]
1392590286Sobrien  "TARGET_64BIT"
1392690286Sobrien  "jmp\t%A0"
1392790286Sobrien  [(set_attr "type" "ibr")
1392890286Sobrien   (set_attr "length_immediate" "0")])
1392990286Sobrien
1393090286Sobrien(define_expand "tablejump"
1393190286Sobrien  [(parallel [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))
1393290286Sobrien	      (use (label_ref (match_operand 1 "" "")))])]
1393390286Sobrien  ""
1393450650Sobrien{
13935117404Skan  /* In PIC mode, the table entries are stored GOT (32-bit) or PC (64-bit)
13936117404Skan     relative.  Convert the relative address to an absolute address.  */
1393790286Sobrien  if (flag_pic)
1393890286Sobrien    {
13939117404Skan      rtx op0, op1;
13940117404Skan      enum rtx_code code;
13941117404Skan
1394290286Sobrien      if (TARGET_64BIT)
1394390286Sobrien	{
13944117404Skan	  code = PLUS;
13945117404Skan	  op0 = operands[0];
13946117404Skan	  op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);
1394790286Sobrien	}
13948117404Skan      else if (TARGET_MACHO || HAVE_AS_GOTOFF_IN_DATA)
13949117404Skan	{
13950117404Skan	  code = PLUS;
13951117404Skan	  op0 = operands[0];
13952117404Skan	  op1 = pic_offset_table_rtx;
13953117404Skan	}
1395490286Sobrien      else
1395590286Sobrien	{
13956117404Skan	  code = MINUS;
13957117404Skan	  op0 = pic_offset_table_rtx;
13958117404Skan	  op1 = operands[0];
1395990286Sobrien	}
13960117404Skan
13961117404Skan      operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0,
13962117404Skan					 OPTAB_DIRECT);
1396390286Sobrien    }
1396490286Sobrien})
1396550650Sobrien
1396690286Sobrien(define_insn "*tablejump_1"
1396790286Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
1396890286Sobrien   (use (label_ref (match_operand 1 "" "")))]
1396990286Sobrien  "!TARGET_64BIT"
1397090286Sobrien  "jmp\t%A0"
1397190286Sobrien  [(set_attr "type" "ibr")
1397290286Sobrien   (set_attr "length_immediate" "0")])
1397318334Speter
1397490286Sobrien(define_insn "*tablejump_1_rtx64"
1397590286Sobrien  [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm"))
1397690286Sobrien   (use (label_ref (match_operand 1 "" "")))]
1397790286Sobrien  "TARGET_64BIT"
1397890286Sobrien  "jmp\t%A0"
1397990286Sobrien  [(set_attr "type" "ibr")
1398090286Sobrien   (set_attr "length_immediate" "0")])
1398190286Sobrien
1398290286Sobrien;; Convert setcc + movzbl to xor + setcc if operands don't overlap.
1398318334Speter
1398490286Sobrien(define_peephole2
13985169699Skan  [(set (reg FLAGS_REG) (match_operand 0 "" ""))
1398690286Sobrien   (set (match_operand:QI 1 "register_operand" "")
1398790286Sobrien	(match_operator:QI 2 "ix86_comparison_operator"
13988169699Skan	  [(reg FLAGS_REG) (const_int 0)]))
1398990286Sobrien   (set (match_operand 3 "q_regs_operand" "")
1399090286Sobrien	(zero_extend (match_dup 1)))]
1399190286Sobrien  "(peep2_reg_dead_p (3, operands[1])
1399290286Sobrien    || operands_match_p (operands[1], operands[3]))
1399390286Sobrien   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
1399490286Sobrien  [(set (match_dup 4) (match_dup 0))
1399590286Sobrien   (set (strict_low_part (match_dup 5))
1399690286Sobrien	(match_dup 2))]
1399718334Speter{
13998169699Skan  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
13999132727Skan  operands[5] = gen_lowpart (QImode, operands[3]);
1400090286Sobrien  ix86_expand_clear (operands[3]);
1400190286Sobrien})
1400218334Speter
1400390286Sobrien;; Similar, but match zero_extendhisi2_and, which adds a clobber.
1400418334Speter
1400590286Sobrien(define_peephole2
14006169699Skan  [(set (reg FLAGS_REG) (match_operand 0 "" ""))
1400790286Sobrien   (set (match_operand:QI 1 "register_operand" "")
1400890286Sobrien	(match_operator:QI 2 "ix86_comparison_operator"
14009169699Skan	  [(reg FLAGS_REG) (const_int 0)]))
1401090286Sobrien   (parallel [(set (match_operand 3 "q_regs_operand" "")
1401190286Sobrien		   (zero_extend (match_dup 1)))
14012169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1401390286Sobrien  "(peep2_reg_dead_p (3, operands[1])
1401490286Sobrien    || operands_match_p (operands[1], operands[3]))
1401590286Sobrien   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
1401690286Sobrien  [(set (match_dup 4) (match_dup 0))
1401790286Sobrien   (set (strict_low_part (match_dup 5))
1401890286Sobrien	(match_dup 2))]
1401990286Sobrien{
14020169699Skan  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
14021132727Skan  operands[5] = gen_lowpart (QImode, operands[3]);
1402290286Sobrien  ix86_expand_clear (operands[3]);
1402390286Sobrien})
1402490286Sobrien
1402590286Sobrien;; Call instructions.
1402618334Speter
1402790286Sobrien;; The predicates normally associated with named expanders are not properly
1402890286Sobrien;; checked for calls.  This is a bug in the generic code, but it isn't that
1402990286Sobrien;; easy to fix.  Ignore it for now and be prepared to fix things up.
1403018334Speter
1403118334Speter;; Call subroutine returning no value.
1403218334Speter
1403318334Speter(define_expand "call_pop"
1403490286Sobrien  [(parallel [(call (match_operand:QI 0 "" "")
1403590286Sobrien		    (match_operand:SI 1 "" ""))
14036169699Skan	      (set (reg:SI SP_REG)
14037169699Skan		   (plus:SI (reg:SI SP_REG)
1403890286Sobrien			    (match_operand:SI 3 "" "")))])]
1403990286Sobrien  "!TARGET_64BIT"
1404018334Speter{
14041132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3], 0);
14042117404Skan  DONE;
1404390286Sobrien})
1404418334Speter
1404590286Sobrien(define_insn "*call_pop_0"
1404690286Sobrien  [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" ""))
1404790286Sobrien	 (match_operand:SI 1 "" ""))
14048169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
1404990286Sobrien			    (match_operand:SI 2 "immediate_operand" "")))]
1405090286Sobrien  "!TARGET_64BIT"
1405118334Speter{
1405290286Sobrien  if (SIBLING_CALL_P (insn))
1405390286Sobrien    return "jmp\t%P0";
1405490286Sobrien  else
1405590286Sobrien    return "call\t%P0";
1405690286Sobrien}
1405790286Sobrien  [(set_attr "type" "call")])
1405890286Sobrien  
1405990286Sobrien(define_insn "*call_pop_1"
1406090286Sobrien  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
1406190286Sobrien	 (match_operand:SI 1 "" ""))
14062169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
1406390286Sobrien			    (match_operand:SI 2 "immediate_operand" "i")))]
1406490286Sobrien  "!TARGET_64BIT"
1406590286Sobrien{
1406690286Sobrien  if (constant_call_address_operand (operands[0], Pmode))
1406718334Speter    {
1406890286Sobrien      if (SIBLING_CALL_P (insn))
1406990286Sobrien	return "jmp\t%P0";
1407090286Sobrien      else
1407190286Sobrien	return "call\t%P0";
1407218334Speter    }
1407390286Sobrien  if (SIBLING_CALL_P (insn))
1407490286Sobrien    return "jmp\t%A0";
1407518334Speter  else
1407690286Sobrien    return "call\t%A0";
1407790286Sobrien}
1407890286Sobrien  [(set_attr "type" "call")])
1407918334Speter
1408018334Speter(define_expand "call"
1408190286Sobrien  [(call (match_operand:QI 0 "" "")
1408290286Sobrien	 (match_operand 1 "" ""))
1408390286Sobrien   (use (match_operand 2 "" ""))]
1408418334Speter  ""
1408518334Speter{
14086132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 0);
14087117404Skan  DONE;
1408890286Sobrien})
1408918334Speter
14090132727Skan(define_expand "sibcall"
14091132727Skan  [(call (match_operand:QI 0 "" "")
14092132727Skan	 (match_operand 1 "" ""))
14093132727Skan   (use (match_operand 2 "" ""))]
14094132727Skan  ""
14095132727Skan{
14096132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 1);
14097132727Skan  DONE;
14098132727Skan})
14099132727Skan
1410090286Sobrien(define_insn "*call_0"
1410190286Sobrien  [(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
1410290286Sobrien	 (match_operand 1 "" ""))]
1410318334Speter  ""
1410418334Speter{
1410590286Sobrien  if (SIBLING_CALL_P (insn))
1410690286Sobrien    return "jmp\t%P0";
1410790286Sobrien  else
1410890286Sobrien    return "call\t%P0";
1410990286Sobrien}
1411090286Sobrien  [(set_attr "type" "call")])
1411190286Sobrien
1411290286Sobrien(define_insn "*call_1"
1411390286Sobrien  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
1411490286Sobrien	 (match_operand 1 "" ""))]
14115132727Skan  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
1411690286Sobrien{
14117169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14118132727Skan    return "call\t%P0";
14119132727Skan  return "call\t%A0";
1412090286Sobrien}
1412190286Sobrien  [(set_attr "type" "call")])
1412218334Speter
14123132727Skan(define_insn "*sibcall_1"
14124132727Skan  [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,c,d,a"))
14125132727Skan	 (match_operand 1 "" ""))]
14126132727Skan  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
14127132727Skan{
14128169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14129132727Skan    return "jmp\t%P0";
14130132727Skan  return "jmp\t%A0";
14131132727Skan}
14132132727Skan  [(set_attr "type" "call")])
14133132727Skan
1413490286Sobrien(define_insn "*call_1_rex64"
1413590286Sobrien  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
1413690286Sobrien	 (match_operand 1 "" ""))]
14137132727Skan  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
1413890286Sobrien{
14139169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14140132727Skan    return "call\t%P0";
14141132727Skan  return "call\t%A0";
1414290286Sobrien}
1414390286Sobrien  [(set_attr "type" "call")])
1414418334Speter
14145132727Skan(define_insn "*sibcall_1_rex64"
14146132727Skan  [(call (mem:QI (match_operand:DI 0 "constant_call_address_operand" ""))
14147132727Skan	 (match_operand 1 "" ""))]
14148132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
14149132727Skan  "jmp\t%P0"
14150132727Skan  [(set_attr "type" "call")])
14151132727Skan
14152132727Skan(define_insn "*sibcall_1_rex64_v"
14153132727Skan  [(call (mem:QI (reg:DI 40))
14154132727Skan	 (match_operand 0 "" ""))]
14155132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
14156132727Skan  "jmp\t*%%r11"
14157132727Skan  [(set_attr "type" "call")])
14158132727Skan
14159132727Skan
1416018334Speter;; Call subroutine, returning value in operand 0
1416118334Speter
1416218334Speter(define_expand "call_value_pop"
1416318334Speter  [(parallel [(set (match_operand 0 "" "")
1416490286Sobrien		   (call (match_operand:QI 1 "" "")
1416590286Sobrien			 (match_operand:SI 2 "" "")))
14166169699Skan	      (set (reg:SI SP_REG)
14167169699Skan		   (plus:SI (reg:SI SP_REG)
1416890286Sobrien			    (match_operand:SI 4 "" "")))])]
1416990286Sobrien  "!TARGET_64BIT"
1417018334Speter{
14171117404Skan  ix86_expand_call (operands[0], operands[1], operands[2],
14172132727Skan		    operands[3], operands[4], 0);
14173117404Skan  DONE;
1417490286Sobrien})
1417518334Speter
1417618334Speter(define_expand "call_value"
1417718334Speter  [(set (match_operand 0 "" "")
1417890286Sobrien	(call (match_operand:QI 1 "" "")
1417990286Sobrien	      (match_operand:SI 2 "" "")))
1418090286Sobrien   (use (match_operand:SI 3 "" ""))]
1418118334Speter  ;; Operand 2 not used on the i386.
1418218334Speter  ""
1418318334Speter{
14184132727Skan  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 0);
1418590286Sobrien  DONE;
1418690286Sobrien})
1418718334Speter
14188132727Skan(define_expand "sibcall_value"
14189132727Skan  [(set (match_operand 0 "" "")
14190132727Skan	(call (match_operand:QI 1 "" "")
14191132727Skan	      (match_operand:SI 2 "" "")))
14192132727Skan   (use (match_operand:SI 3 "" ""))]
14193132727Skan  ;; Operand 2 not used on the i386.
14194132727Skan  ""
14195132727Skan{
14196132727Skan  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 1);
14197132727Skan  DONE;
14198132727Skan})
14199132727Skan
1420018334Speter;; Call subroutine returning any type.
1420118334Speter
1420218334Speter(define_expand "untyped_call"
1420318334Speter  [(parallel [(call (match_operand 0 "" "")
1420418334Speter		    (const_int 0))
1420518334Speter	      (match_operand 1 "" "")
1420618334Speter	      (match_operand 2 "" "")])]
1420718334Speter  ""
1420818334Speter{
1420918334Speter  int i;
1421018334Speter
1421118334Speter  /* In order to give reg-stack an easier job in validating two
1421218334Speter     coprocessor registers as containing a possible return value,
1421318334Speter     simply pretend the untyped call returns a complex long double
1421418334Speter     value.  */
1421550650Sobrien
14216117404Skan  ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387
14217117404Skan		     ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL),
14218117404Skan		    operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1),
14219132727Skan		    NULL, 0);
1422018334Speter
1422118334Speter  for (i = 0; i < XVECLEN (operands[2], 0); i++)
1422218334Speter    {
1422318334Speter      rtx set = XVECEXP (operands[2], 0, i);
1422418334Speter      emit_move_insn (SET_DEST (set), SET_SRC (set));
1422518334Speter    }
1422618334Speter
1422718334Speter  /* The optimizer does not know that the call sets the function value
1422818334Speter     registers we stored in the result block.  We avoid problems by
1422918334Speter     claiming that all hard registers are used and clobbered at this
1423018334Speter     point.  */
14231117404Skan  emit_insn (gen_blockage (const0_rtx));
1423218334Speter
1423318334Speter  DONE;
1423490286Sobrien})
1423590286Sobrien
1423690286Sobrien;; Prologue and epilogue instructions
1423718334Speter
1423818334Speter;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
1423918334Speter;; all of memory.  This blocks insns from being moved across this point.
1424018334Speter
1424118334Speter(define_insn "blockage"
14242117404Skan  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_BLOCKAGE)]
1424318334Speter  ""
1424452296Sobrien  ""
1424590286Sobrien  [(set_attr "length" "0")])
1424618334Speter
1424718334Speter;; Insn emitted into the body of a function to return from a function.
1424818334Speter;; This is only done if the function's epilogue is known to be simple.
1424990286Sobrien;; See comments for ix86_can_use_return_insn_p in i386.c.
1425018334Speter
1425150650Sobrien(define_expand "return"
1425218334Speter  [(return)]
1425350650Sobrien  "ix86_can_use_return_insn_p ()"
1425490286Sobrien{
1425590286Sobrien  if (current_function_pops_args)
1425690286Sobrien    {
1425790286Sobrien      rtx popc = GEN_INT (current_function_pops_args);
1425890286Sobrien      emit_jump_insn (gen_return_pop_internal (popc));
1425990286Sobrien      DONE;
1426090286Sobrien    }
1426190286Sobrien})
1426250650Sobrien
1426350650Sobrien(define_insn "return_internal"
1426450650Sobrien  [(return)]
1426550650Sobrien  "reload_completed"
1426652296Sobrien  "ret"
1426790286Sobrien  [(set_attr "length" "1")
1426890286Sobrien   (set_attr "length_immediate" "0")
1426990286Sobrien   (set_attr "modrm" "0")])
1427050650Sobrien
14271132727Skan;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
14272132727Skan;; instruction Athlon and K8 have.
14273132727Skan
14274132727Skan(define_insn "return_internal_long"
14275132727Skan  [(return)
14276132727Skan   (unspec [(const_int 0)] UNSPEC_REP)]
14277132727Skan  "reload_completed"
14278132727Skan  "rep {;} ret"
14279132727Skan  [(set_attr "length" "1")
14280132727Skan   (set_attr "length_immediate" "0")
14281132727Skan   (set_attr "prefix_rep" "1")
14282132727Skan   (set_attr "modrm" "0")])
14283132727Skan
1428450650Sobrien(define_insn "return_pop_internal"
1428550650Sobrien  [(return)
1428650650Sobrien   (use (match_operand:SI 0 "const_int_operand" ""))]
1428750650Sobrien  "reload_completed"
1428890286Sobrien  "ret\t%0"
1428990286Sobrien  [(set_attr "length" "3")
1429090286Sobrien   (set_attr "length_immediate" "2")
1429190286Sobrien   (set_attr "modrm" "0")])
1429250650Sobrien
1429390286Sobrien(define_insn "return_indirect_internal"
1429490286Sobrien  [(return)
1429590286Sobrien   (use (match_operand:SI 0 "register_operand" "r"))]
1429690286Sobrien  "reload_completed"
1429790286Sobrien  "jmp\t%A0"
1429890286Sobrien  [(set_attr "type" "ibr")
1429990286Sobrien   (set_attr "length_immediate" "0")])
1430090286Sobrien
1430150650Sobrien(define_insn "nop"
1430250650Sobrien  [(const_int 0)]
1430350650Sobrien  ""
1430452296Sobrien  "nop"
1430590286Sobrien  [(set_attr "length" "1")
1430690286Sobrien   (set_attr "length_immediate" "0")
14307169699Skan   (set_attr "modrm" "0")])
1430850650Sobrien
14309132727Skan;; Align to 16-byte boundary, max skip in op0.  Used to avoid
14310132727Skan;; branch prediction penalty for the third jump in a 16-byte
14311132727Skan;; block on K8.
14312132727Skan
14313132727Skan(define_insn "align"
14314132727Skan  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_ALIGN)]
14315132727Skan  ""
14316132727Skan{
14317132727Skan#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
14318132727Skan  ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 4, (int)INTVAL (operands[0]));
14319132727Skan#else
14320132727Skan  /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that.
14321132727Skan     The align insn is used to avoid 3 jump instructions in the row to improve
14322169699Skan     branch prediction and the benefits hardly outweigh the cost of extra 8
14323132727Skan     nops on the average inserted by full alignment pseudo operation.  */
14324132727Skan#endif
14325132727Skan  return "";
14326132727Skan}
14327132727Skan  [(set_attr "length" "16")])
14328132727Skan
1432950650Sobrien(define_expand "prologue"
1433050650Sobrien  [(const_int 1)]
1433150650Sobrien  ""
1433290286Sobrien  "ix86_expand_prologue (); DONE;")
1433350650Sobrien
14334117404Skan(define_insn "set_got"
1433590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
14336117404Skan	(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
14337169699Skan   (clobber (reg:CC FLAGS_REG))]
1433890286Sobrien  "!TARGET_64BIT"
14339169699Skan  { return output_set_got (operands[0], NULL_RTX); }
14340117404Skan  [(set_attr "type" "multi")
14341117404Skan   (set_attr "length" "12")])
1434250650Sobrien
14343169699Skan(define_insn "set_got_labelled"
14344169699Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14345169699Skan	(unspec:SI [(label_ref (match_operand 1 "" ""))]
14346169699Skan	 UNSPEC_SET_GOT))
14347169699Skan   (clobber (reg:CC FLAGS_REG))]
14348169699Skan  "!TARGET_64BIT"
14349169699Skan  { return output_set_got (operands[0], operands[1]); }
14350169699Skan  [(set_attr "type" "multi")
14351169699Skan   (set_attr "length" "12")])
14352169699Skan
14353169699Skan(define_insn "set_got_rex64"
14354169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14355169699Skan	(unspec:DI [(const_int 0)] UNSPEC_SET_GOT))]
14356169699Skan  "TARGET_64BIT"
14357169699Skan  "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
14358169699Skan  [(set_attr "type" "lea")
14359169699Skan   (set_attr "length" "6")])
14360169699Skan
1436150650Sobrien(define_expand "epilogue"
1436250650Sobrien  [(const_int 1)]
1436350650Sobrien  ""
1436490286Sobrien  "ix86_expand_epilogue (1); DONE;")
1436550650Sobrien
1436690286Sobrien(define_expand "sibcall_epilogue"
1436790286Sobrien  [(const_int 1)]
1436850650Sobrien  ""
1436990286Sobrien  "ix86_expand_epilogue (0); DONE;")
1437050650Sobrien
1437190286Sobrien(define_expand "eh_return"
14372117404Skan  [(use (match_operand 0 "register_operand" ""))]
1437350650Sobrien  ""
1437450650Sobrien{
14375117404Skan  rtx tmp, sa = EH_RETURN_STACKADJ_RTX, ra = operands[0];
1437650650Sobrien
1437790286Sobrien  /* Tricky bit: we write the address of the handler to which we will
1437890286Sobrien     be returning into someone else's stack frame, one word below the
1437990286Sobrien     stack address we wish to restore.  */
1438090286Sobrien  tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa);
1438190286Sobrien  tmp = plus_constant (tmp, -UNITS_PER_WORD);
1438290286Sobrien  tmp = gen_rtx_MEM (Pmode, tmp);
1438390286Sobrien  emit_move_insn (tmp, ra);
1438418334Speter
1438590286Sobrien  if (Pmode == SImode)
14386169699Skan    emit_jump_insn (gen_eh_return_si (sa));
1438790286Sobrien  else
14388169699Skan    emit_jump_insn (gen_eh_return_di (sa));
1438990286Sobrien  emit_barrier ();
1439090286Sobrien  DONE;
1439190286Sobrien})
1439218334Speter
1439390286Sobrien(define_insn_and_split "eh_return_si"
14394169699Skan  [(set (pc) 
14395169699Skan        (unspec [(match_operand:SI 0 "register_operand" "c")]
14396169699Skan	         UNSPEC_EH_RETURN))]
1439790286Sobrien  "!TARGET_64BIT"
1439890286Sobrien  "#"
1439990286Sobrien  "reload_completed"
1440090286Sobrien  [(const_int 1)]
1440190286Sobrien  "ix86_expand_epilogue (2); DONE;")
1440218334Speter
1440390286Sobrien(define_insn_and_split "eh_return_di"
14404169699Skan  [(set (pc) 
14405169699Skan        (unspec [(match_operand:DI 0 "register_operand" "c")]
14406169699Skan	         UNSPEC_EH_RETURN))]
1440790286Sobrien  "TARGET_64BIT"
1440890286Sobrien  "#"
1440990286Sobrien  "reload_completed"
1441090286Sobrien  [(const_int 1)]
1441190286Sobrien  "ix86_expand_epilogue (2); DONE;")
1441218334Speter
1441390286Sobrien(define_insn "leave"
14414169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI BP_REG) (const_int 4)))
14415169699Skan   (set (reg:SI BP_REG) (mem:SI (reg:SI BP_REG)))
1441690286Sobrien   (clobber (mem:BLK (scratch)))]
1441790286Sobrien  "!TARGET_64BIT"
1441890286Sobrien  "leave"
14419132727Skan  [(set_attr "type" "leave")])
1442018334Speter
1442190286Sobrien(define_insn "leave_rex64"
14422169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI BP_REG) (const_int 8)))
14423169699Skan   (set (reg:DI BP_REG) (mem:DI (reg:DI BP_REG)))
1442490286Sobrien   (clobber (mem:BLK (scratch)))]
1442590286Sobrien  "TARGET_64BIT"
1442690286Sobrien  "leave"
14427132727Skan  [(set_attr "type" "leave")])
1442890286Sobrien
1442990286Sobrien(define_expand "ffssi2"
14430132727Skan  [(parallel
14431132727Skan     [(set (match_operand:SI 0 "register_operand" "") 
14432132727Skan	   (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "")))
14433132727Skan      (clobber (match_scratch:SI 2 ""))
14434169699Skan      (clobber (reg:CC FLAGS_REG))])]
1443518334Speter  ""
14436132727Skan  "")
1443718334Speter
14438132727Skan(define_insn_and_split "*ffs_cmove"
14439132727Skan  [(set (match_operand:SI 0 "register_operand" "=r") 
14440132727Skan	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14441132727Skan   (clobber (match_scratch:SI 2 "=&r"))
14442169699Skan   (clobber (reg:CC FLAGS_REG))]
14443132727Skan  "TARGET_CMOVE"
14444132727Skan  "#"
14445132727Skan  "&& reload_completed"
14446132727Skan  [(set (match_dup 2) (const_int -1))
14447169699Skan   (parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
14448132727Skan	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
14449132727Skan   (set (match_dup 0) (if_then_else:SI
14450169699Skan			(eq (reg:CCZ FLAGS_REG) (const_int 0))
14451132727Skan			(match_dup 2)
14452132727Skan			(match_dup 0)))
14453132727Skan   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
14454169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14455132727Skan  "")
1445618334Speter
14457132727Skan(define_insn_and_split "*ffs_no_cmove"
14458132727Skan  [(set (match_operand:SI 0 "nonimmediate_operand" "=r") 
14459132727Skan	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14460132727Skan   (clobber (match_scratch:SI 2 "=&q"))
14461169699Skan   (clobber (reg:CC FLAGS_REG))]
14462132727Skan  ""
14463132727Skan  "#"
14464132727Skan  "reload_completed"
14465169699Skan  [(parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
14466132727Skan	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
14467132727Skan   (set (strict_low_part (match_dup 3))
14468169699Skan	(eq:QI (reg:CCZ FLAGS_REG) (const_int 0)))
14469132727Skan   (parallel [(set (match_dup 2) (neg:SI (match_dup 2)))
14470169699Skan	      (clobber (reg:CC FLAGS_REG))])
14471132727Skan   (parallel [(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 2)))
14472169699Skan	      (clobber (reg:CC FLAGS_REG))])
14473132727Skan   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
14474169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14475132727Skan{
14476132727Skan  operands[3] = gen_lowpart (QImode, operands[2]);
14477132727Skan  ix86_expand_clear (operands[2]);
1447890286Sobrien})
1447950650Sobrien
14480132727Skan(define_insn "*ffssi_1"
14481169699Skan  [(set (reg:CCZ FLAGS_REG)
14482132727Skan	(compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm")
1448390286Sobrien		     (const_int 0)))
1448490286Sobrien   (set (match_operand:SI 0 "register_operand" "=r")
14485132727Skan	(ctz:SI (match_dup 1)))]
1448618334Speter  ""
1448790286Sobrien  "bsf{l}\t{%1, %0|%0, %1}"
14488169699Skan  [(set_attr "prefix_0f" "1")])
1448918334Speter
14490169699Skan(define_expand "ffsdi2"
14491169699Skan  [(parallel
14492169699Skan     [(set (match_operand:DI 0 "register_operand" "") 
14493169699Skan	   (ffs:DI (match_operand:DI 1 "nonimmediate_operand" "")))
14494169699Skan      (clobber (match_scratch:DI 2 ""))
14495169699Skan      (clobber (reg:CC FLAGS_REG))])]
14496169699Skan  "TARGET_64BIT && TARGET_CMOVE"
14497169699Skan  "")
14498169699Skan
14499169699Skan(define_insn_and_split "*ffs_rex64"
14500169699Skan  [(set (match_operand:DI 0 "register_operand" "=r") 
14501169699Skan	(ffs:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
14502169699Skan   (clobber (match_scratch:DI 2 "=&r"))
14503169699Skan   (clobber (reg:CC FLAGS_REG))]
14504169699Skan  "TARGET_64BIT && TARGET_CMOVE"
14505169699Skan  "#"
14506169699Skan  "&& reload_completed"
14507169699Skan  [(set (match_dup 2) (const_int -1))
14508169699Skan   (parallel [(set (reg:CCZ FLAGS_REG)
14509169699Skan		   (compare:CCZ (match_dup 1) (const_int 0)))
14510169699Skan	      (set (match_dup 0) (ctz:DI (match_dup 1)))])
14511169699Skan   (set (match_dup 0) (if_then_else:DI
14512169699Skan			(eq (reg:CCZ FLAGS_REG) (const_int 0))
14513169699Skan			(match_dup 2)
14514169699Skan			(match_dup 0)))
14515169699Skan   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1)))
14516169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14517169699Skan  "")
14518169699Skan
14519169699Skan(define_insn "*ffsdi_1"
14520169699Skan  [(set (reg:CCZ FLAGS_REG)
14521169699Skan	(compare:CCZ (match_operand:DI 1 "nonimmediate_operand" "rm")
14522169699Skan		     (const_int 0)))
14523169699Skan   (set (match_operand:DI 0 "register_operand" "=r")
14524169699Skan	(ctz:DI (match_dup 1)))]
14525169699Skan  "TARGET_64BIT"
14526169699Skan  "bsf{q}\t{%1, %0|%0, %1}"
14527169699Skan  [(set_attr "prefix_0f" "1")])
14528169699Skan
14529132727Skan(define_insn "ctzsi2"
14530132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14531132727Skan	(ctz:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14532169699Skan   (clobber (reg:CC FLAGS_REG))]
14533132727Skan  ""
14534132727Skan  "bsf{l}\t{%1, %0|%0, %1}"
14535169699Skan  [(set_attr "prefix_0f" "1")])
14536132727Skan
14537169699Skan(define_insn "ctzdi2"
14538169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14539169699Skan	(ctz:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
14540169699Skan   (clobber (reg:CC FLAGS_REG))]
14541169699Skan  "TARGET_64BIT"
14542169699Skan  "bsf{q}\t{%1, %0|%0, %1}"
14543169699Skan  [(set_attr "prefix_0f" "1")])
14544169699Skan
14545132727Skan(define_expand "clzsi2"
14546132727Skan  [(parallel
14547132727Skan     [(set (match_operand:SI 0 "register_operand" "")
14548132727Skan	   (minus:SI (const_int 31)
14549132727Skan		     (clz:SI (match_operand:SI 1 "nonimmediate_operand" ""))))
14550169699Skan      (clobber (reg:CC FLAGS_REG))])
14551132727Skan   (parallel
14552132727Skan     [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 31)))
14553169699Skan      (clobber (reg:CC FLAGS_REG))])]
14554132727Skan  ""
14555132727Skan  "")
14556132727Skan
14557132727Skan(define_insn "*bsr"
14558132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14559132727Skan	(minus:SI (const_int 31)
14560132727Skan		  (clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))))
14561169699Skan   (clobber (reg:CC FLAGS_REG))]
14562132727Skan  ""
14563132727Skan  "bsr{l}\t{%1, %0|%0, %1}"
14564169699Skan  [(set_attr "prefix_0f" "1")])
14565169699Skan
14566169699Skan(define_expand "clzdi2"
14567169699Skan  [(parallel
14568169699Skan     [(set (match_operand:DI 0 "register_operand" "")
14569169699Skan	   (minus:DI (const_int 63)
14570169699Skan		     (clz:DI (match_operand:DI 1 "nonimmediate_operand" ""))))
14571169699Skan      (clobber (reg:CC FLAGS_REG))])
14572169699Skan   (parallel
14573169699Skan     [(set (match_dup 0) (xor:DI (match_dup 0) (const_int 63)))
14574169699Skan      (clobber (reg:CC FLAGS_REG))])]
14575169699Skan  "TARGET_64BIT"
14576169699Skan  "")
14577169699Skan
14578169699Skan(define_insn "*bsr_rex64"
14579169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14580169699Skan	(minus:DI (const_int 63)
14581169699Skan		  (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))))
14582169699Skan   (clobber (reg:CC FLAGS_REG))]
14583169699Skan  "TARGET_64BIT"
14584169699Skan  "bsr{q}\t{%1, %0|%0, %1}"
14585169699Skan  [(set_attr "prefix_0f" "1")])
1458690286Sobrien
14587117404Skan;; Thread-local storage patterns for ELF.
14588117404Skan;;
14589117404Skan;; Note that these code sequences must appear exactly as shown
14590117404Skan;; in order to allow linker relaxation.
14591117404Skan
14592117404Skan(define_insn "*tls_global_dynamic_32_gnu"
14593117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14594117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14595117404Skan		    (match_operand:SI 2 "tls_symbolic_operand" "")
14596117404Skan		    (match_operand:SI 3 "call_insn_operand" "")]
14597117404Skan		    UNSPEC_TLS_GD))
14598117404Skan   (clobber (match_scratch:SI 4 "=d"))
14599117404Skan   (clobber (match_scratch:SI 5 "=c"))
14600169699Skan   (clobber (reg:CC FLAGS_REG))]
14601117404Skan  "!TARGET_64BIT && TARGET_GNU_TLS"
14602117404Skan  "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
14603117404Skan  [(set_attr "type" "multi")
14604117404Skan   (set_attr "length" "12")])
14605117404Skan
14606117404Skan(define_insn "*tls_global_dynamic_32_sun"
14607117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14608117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14609117404Skan		    (match_operand:SI 2 "tls_symbolic_operand" "")
14610117404Skan		    (match_operand:SI 3 "call_insn_operand" "")]
14611117404Skan		    UNSPEC_TLS_GD))
14612117404Skan   (clobber (match_scratch:SI 4 "=d"))
14613117404Skan   (clobber (match_scratch:SI 5 "=c"))
14614169699Skan   (clobber (reg:CC FLAGS_REG))]
14615117404Skan  "!TARGET_64BIT && TARGET_SUN_TLS"
14616117404Skan  "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
14617117404Skan	push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
14618117404Skan  [(set_attr "type" "multi")
14619117404Skan   (set_attr "length" "14")])
14620117404Skan
14621117404Skan(define_expand "tls_global_dynamic_32"
14622117404Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
14623117404Skan		   (unspec:SI
14624117404Skan		    [(match_dup 2)
14625117404Skan		     (match_operand:SI 1 "tls_symbolic_operand" "")
14626117404Skan		     (match_dup 3)]
14627117404Skan		    UNSPEC_TLS_GD))
14628117404Skan	      (clobber (match_scratch:SI 4 ""))
14629117404Skan	      (clobber (match_scratch:SI 5 ""))
14630169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14631117404Skan  ""
14632117404Skan{
14633117404Skan  if (flag_pic)
14634117404Skan    operands[2] = pic_offset_table_rtx;
14635117404Skan  else
14636117404Skan    {
14637117404Skan      operands[2] = gen_reg_rtx (Pmode);
14638117404Skan      emit_insn (gen_set_got (operands[2]));
14639117404Skan    }
14640169699Skan  if (TARGET_GNU2_TLS)
14641169699Skan    {
14642169699Skan       emit_insn (gen_tls_dynamic_gnu2_32
14643169699Skan		  (operands[0], operands[1], operands[2]));
14644169699Skan       DONE;
14645169699Skan    }
14646117404Skan  operands[3] = ix86_tls_get_addr ();
14647117404Skan})
14648117404Skan
14649117404Skan(define_insn "*tls_global_dynamic_64"
14650117404Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14651169699Skan	(call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
14652169699Skan		 (match_operand:DI 3 "" "")))
14653117404Skan   (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14654117404Skan	      UNSPEC_TLS_GD)]
14655117404Skan  "TARGET_64BIT"
14656117404Skan  ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%P2"
14657117404Skan  [(set_attr "type" "multi")
14658117404Skan   (set_attr "length" "16")])
14659117404Skan
14660117404Skan(define_expand "tls_global_dynamic_64"
14661117404Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
14662169699Skan		   (call:DI (mem:QI (match_dup 2)) (const_int 0)))
14663117404Skan	      (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14664117404Skan			 UNSPEC_TLS_GD)])]
14665117404Skan  ""
14666117404Skan{
14667169699Skan  if (TARGET_GNU2_TLS)
14668169699Skan    {
14669169699Skan       emit_insn (gen_tls_dynamic_gnu2_64
14670169699Skan		  (operands[0], operands[1]));
14671169699Skan       DONE;
14672169699Skan    }
14673117404Skan  operands[2] = ix86_tls_get_addr ();
14674117404Skan})
14675117404Skan
14676117404Skan(define_insn "*tls_local_dynamic_base_32_gnu"
14677117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14678117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14679117404Skan                    (match_operand:SI 2 "call_insn_operand" "")]
14680117404Skan		   UNSPEC_TLS_LD_BASE))
14681117404Skan   (clobber (match_scratch:SI 3 "=d"))
14682117404Skan   (clobber (match_scratch:SI 4 "=c"))
14683169699Skan   (clobber (reg:CC FLAGS_REG))]
14684117404Skan  "!TARGET_64BIT && TARGET_GNU_TLS"
14685117404Skan  "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
14686117404Skan  [(set_attr "type" "multi")
14687117404Skan   (set_attr "length" "11")])
14688117404Skan
14689117404Skan(define_insn "*tls_local_dynamic_base_32_sun"
14690117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14691117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14692117404Skan                    (match_operand:SI 2 "call_insn_operand" "")]
14693117404Skan		   UNSPEC_TLS_LD_BASE))
14694117404Skan   (clobber (match_scratch:SI 3 "=d"))
14695117404Skan   (clobber (match_scratch:SI 4 "=c"))
14696169699Skan   (clobber (reg:CC FLAGS_REG))]
14697117404Skan  "!TARGET_64BIT && TARGET_SUN_TLS"
14698117404Skan  "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
14699117404Skan	push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
14700117404Skan  [(set_attr "type" "multi")
14701117404Skan   (set_attr "length" "13")])
14702117404Skan
14703117404Skan(define_expand "tls_local_dynamic_base_32"
14704117404Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
14705117404Skan		   (unspec:SI [(match_dup 1) (match_dup 2)]
14706117404Skan			      UNSPEC_TLS_LD_BASE))
14707117404Skan	      (clobber (match_scratch:SI 3 ""))
14708117404Skan	      (clobber (match_scratch:SI 4 ""))
14709169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14710117404Skan  ""
14711117404Skan{
14712117404Skan  if (flag_pic)
14713117404Skan    operands[1] = pic_offset_table_rtx;
14714117404Skan  else
14715117404Skan    {
14716117404Skan      operands[1] = gen_reg_rtx (Pmode);
14717117404Skan      emit_insn (gen_set_got (operands[1]));
14718117404Skan    }
14719169699Skan  if (TARGET_GNU2_TLS)
14720169699Skan    {
14721169699Skan       emit_insn (gen_tls_dynamic_gnu2_32
14722169699Skan		  (operands[0], ix86_tls_module_base (), operands[1]));
14723169699Skan       DONE;
14724169699Skan    }
14725117404Skan  operands[2] = ix86_tls_get_addr ();
14726117404Skan})
14727117404Skan
14728117404Skan(define_insn "*tls_local_dynamic_base_64"
14729117404Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14730169699Skan	(call:DI (mem:QI (match_operand:DI 1 "call_insn_operand" ""))
14731169699Skan		 (match_operand:DI 2 "" "")))
14732117404Skan   (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
14733117404Skan  "TARGET_64BIT"
14734117404Skan  "lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1"
14735117404Skan  [(set_attr "type" "multi")
14736117404Skan   (set_attr "length" "12")])
14737117404Skan
14738117404Skan(define_expand "tls_local_dynamic_base_64"
14739117404Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
14740169699Skan		   (call:DI (mem:QI (match_dup 1)) (const_int 0)))
14741117404Skan	      (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
14742117404Skan  ""
14743117404Skan{
14744169699Skan  if (TARGET_GNU2_TLS)
14745169699Skan    {
14746169699Skan       emit_insn (gen_tls_dynamic_gnu2_64
14747169699Skan		  (operands[0], ix86_tls_module_base ()));
14748169699Skan       DONE;
14749169699Skan    }
14750117404Skan  operands[1] = ix86_tls_get_addr ();
14751117404Skan})
14752117404Skan
14753117404Skan;; Local dynamic of a single variable is a lose.  Show combine how
14754117404Skan;; to convert that back to global dynamic.
14755117404Skan
14756117404Skan(define_insn_and_split "*tls_local_dynamic_32_once"
14757117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14758117404Skan	(plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b")
14759117404Skan			     (match_operand:SI 2 "call_insn_operand" "")]
14760117404Skan			    UNSPEC_TLS_LD_BASE)
14761117404Skan		 (const:SI (unspec:SI
14762117404Skan			    [(match_operand:SI 3 "tls_symbolic_operand" "")]
14763117404Skan			    UNSPEC_DTPOFF))))
14764117404Skan   (clobber (match_scratch:SI 4 "=d"))
14765117404Skan   (clobber (match_scratch:SI 5 "=c"))
14766169699Skan   (clobber (reg:CC FLAGS_REG))]
14767117404Skan  ""
14768117404Skan  "#"
14769117404Skan  ""
14770117404Skan  [(parallel [(set (match_dup 0)
14771117404Skan		   (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)]
14772117404Skan			      UNSPEC_TLS_GD))
14773117404Skan	      (clobber (match_dup 4))
14774117404Skan	      (clobber (match_dup 5))
14775169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14776117404Skan  "")
14777132727Skan
14778132727Skan;; Load and add the thread base pointer from %gs:0.
14779132727Skan
14780132727Skan(define_insn "*load_tp_si"
14781132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14782132727Skan	(unspec:SI [(const_int 0)] UNSPEC_TP))]
14783132727Skan  "!TARGET_64BIT"
14784132727Skan  "mov{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
14785132727Skan  [(set_attr "type" "imov")
14786132727Skan   (set_attr "modrm" "0")
14787132727Skan   (set_attr "length" "7")
14788132727Skan   (set_attr "memory" "load")
14789132727Skan   (set_attr "imm_disp" "false")])
14790132727Skan
14791132727Skan(define_insn "*add_tp_si"
14792132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14793132727Skan	(plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
14794132727Skan		 (match_operand:SI 1 "register_operand" "0")))
14795169699Skan   (clobber (reg:CC FLAGS_REG))]
14796132727Skan  "!TARGET_64BIT"
14797132727Skan  "add{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
14798132727Skan  [(set_attr "type" "alu")
14799132727Skan   (set_attr "modrm" "0")
14800132727Skan   (set_attr "length" "7")
14801132727Skan   (set_attr "memory" "load")
14802132727Skan   (set_attr "imm_disp" "false")])
14803132727Skan
14804132727Skan(define_insn "*load_tp_di"
14805132727Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14806132727Skan	(unspec:DI [(const_int 0)] UNSPEC_TP))]
14807132727Skan  "TARGET_64BIT"
14808132727Skan  "mov{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
14809132727Skan  [(set_attr "type" "imov")
14810132727Skan   (set_attr "modrm" "0")
14811132727Skan   (set_attr "length" "7")
14812132727Skan   (set_attr "memory" "load")
14813132727Skan   (set_attr "imm_disp" "false")])
14814132727Skan
14815132727Skan(define_insn "*add_tp_di"
14816132727Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14817132727Skan	(plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP)
14818132727Skan		 (match_operand:DI 1 "register_operand" "0")))
14819169699Skan   (clobber (reg:CC FLAGS_REG))]
14820132727Skan  "TARGET_64BIT"
14821132727Skan  "add{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
14822132727Skan  [(set_attr "type" "alu")
14823132727Skan   (set_attr "modrm" "0")
14824132727Skan   (set_attr "length" "7")
14825132727Skan   (set_attr "memory" "load")
14826132727Skan   (set_attr "imm_disp" "false")])
14827169699Skan
14828169699Skan;; GNU2 TLS patterns can be split.
14829169699Skan
14830169699Skan(define_expand "tls_dynamic_gnu2_32"
14831169699Skan  [(set (match_dup 3)
14832169699Skan	(plus:SI (match_operand:SI 2 "register_operand" "")
14833169699Skan		 (const:SI
14834169699Skan		  (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")]
14835169699Skan			     UNSPEC_TLSDESC))))
14836169699Skan   (parallel
14837169699Skan    [(set (match_operand:SI 0 "register_operand" "")
14838169699Skan	  (unspec:SI [(match_dup 1) (match_dup 3)
14839169699Skan		      (match_dup 2) (reg:SI SP_REG)]
14840169699Skan		      UNSPEC_TLSDESC))
14841169699Skan     (clobber (reg:CC FLAGS_REG))])]
14842169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14843169699Skan{
14844169699Skan  operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14845169699Skan  ix86_tls_descriptor_calls_expanded_in_cfun = true;
14846169699Skan})
14847169699Skan
14848169699Skan(define_insn "*tls_dynamic_lea_32"
14849169699Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14850169699Skan	(plus:SI (match_operand:SI 1 "register_operand" "b")
14851169699Skan		 (const:SI
14852169699Skan		  (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")]
14853169699Skan			      UNSPEC_TLSDESC))))]
14854169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14855169699Skan  "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}"
14856169699Skan  [(set_attr "type" "lea")
14857169699Skan   (set_attr "mode" "SI")
14858169699Skan   (set_attr "length" "6")
14859169699Skan   (set_attr "length_address" "4")])
14860169699Skan
14861169699Skan(define_insn "*tls_dynamic_call_32"
14862169699Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14863169699Skan	(unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")
14864169699Skan		    (match_operand:SI 2 "register_operand" "0")
14865169699Skan		    ;; we have to make sure %ebx still points to the GOT
14866169699Skan		    (match_operand:SI 3 "register_operand" "b")
14867169699Skan		    (reg:SI SP_REG)]
14868169699Skan		   UNSPEC_TLSDESC))
14869169699Skan   (clobber (reg:CC FLAGS_REG))]
14870169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14871169699Skan  "call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}"
14872169699Skan  [(set_attr "type" "call")
14873169699Skan   (set_attr "length" "2")
14874169699Skan   (set_attr "length_address" "0")])
14875169699Skan
14876169699Skan(define_insn_and_split "*tls_dynamic_gnu2_combine_32"
14877169699Skan  [(set (match_operand:SI 0 "register_operand" "=&a")
14878169699Skan	(plus:SI
14879169699Skan	 (unspec:SI [(match_operand:SI 3 "tls_modbase_operand" "")
14880169699Skan		     (match_operand:SI 4 "" "")
14881169699Skan		     (match_operand:SI 2 "register_operand" "b")
14882169699Skan		     (reg:SI SP_REG)]
14883169699Skan		    UNSPEC_TLSDESC)
14884169699Skan	 (const:SI (unspec:SI
14885169699Skan		    [(match_operand:SI 1 "tls_symbolic_operand" "")]
14886169699Skan		    UNSPEC_DTPOFF))))
14887169699Skan   (clobber (reg:CC FLAGS_REG))]
14888169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14889169699Skan  "#"
14890169699Skan  ""
14891169699Skan  [(set (match_dup 0) (match_dup 5))]
14892169699Skan{
14893169699Skan  operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14894169699Skan  emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2]));
14895169699Skan})
14896169699Skan
14897169699Skan(define_expand "tls_dynamic_gnu2_64"
14898169699Skan  [(set (match_dup 2)
14899169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14900169699Skan		   UNSPEC_TLSDESC))
14901169699Skan   (parallel
14902169699Skan    [(set (match_operand:DI 0 "register_operand" "")
14903169699Skan	  (unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)]
14904169699Skan		     UNSPEC_TLSDESC))
14905169699Skan     (clobber (reg:CC FLAGS_REG))])]
14906169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14907169699Skan{
14908169699Skan  operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14909169699Skan  ix86_tls_descriptor_calls_expanded_in_cfun = true;
14910169699Skan})
14911169699Skan
14912169699Skan(define_insn "*tls_dynamic_lea_64"
14913169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14914169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14915169699Skan		   UNSPEC_TLSDESC))]
14916169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14917169699Skan  "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}"
14918169699Skan  [(set_attr "type" "lea")
14919169699Skan   (set_attr "mode" "DI")
14920169699Skan   (set_attr "length" "7")
14921169699Skan   (set_attr "length_address" "4")])
14922169699Skan
14923169699Skan(define_insn "*tls_dynamic_call_64"
14924169699Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14925169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
14926169699Skan		    (match_operand:DI 2 "register_operand" "0")
14927169699Skan		    (reg:DI SP_REG)]
14928169699Skan		   UNSPEC_TLSDESC))
14929169699Skan   (clobber (reg:CC FLAGS_REG))]
14930169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14931169699Skan  "call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}"
14932169699Skan  [(set_attr "type" "call")
14933169699Skan   (set_attr "length" "2")
14934169699Skan   (set_attr "length_address" "0")])
14935169699Skan
14936169699Skan(define_insn_and_split "*tls_dynamic_gnu2_combine_64"
14937169699Skan  [(set (match_operand:DI 0 "register_operand" "=&a")
14938169699Skan	(plus:DI
14939169699Skan	 (unspec:DI [(match_operand:DI 2 "tls_modbase_operand" "")
14940169699Skan		     (match_operand:DI 3 "" "")
14941169699Skan		     (reg:DI SP_REG)]
14942169699Skan		    UNSPEC_TLSDESC)
14943169699Skan	 (const:DI (unspec:DI
14944169699Skan		    [(match_operand:DI 1 "tls_symbolic_operand" "")]
14945169699Skan		    UNSPEC_DTPOFF))))
14946169699Skan   (clobber (reg:CC FLAGS_REG))]
14947169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14948169699Skan  "#"
14949169699Skan  ""
14950169699Skan  [(set (match_dup 0) (match_dup 4))]
14951169699Skan{
14952169699Skan  operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14953169699Skan  emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
14954169699Skan})
14955169699Skan
14956169699Skan;;
14957117404Skan
1495890286Sobrien;; These patterns match the binary 387 instructions for addM3, subM3,
1495990286Sobrien;; mulM3 and divM3.  There are three patterns for each of DFmode and
1496090286Sobrien;; SFmode.  The first is the normal insn, the second the same insn but
1496190286Sobrien;; with one operand a conversion, and the third the same insn but with
1496290286Sobrien;; the other operand a conversion.  The conversion may be SFmode or
1496390286Sobrien;; SImode if the target mode DFmode, but only SImode if the target mode
1496490286Sobrien;; is SFmode.
1496518334Speter
1496690286Sobrien;; Gcc is slightly more smart about handling normal two address instructions
1496790286Sobrien;; so use special patterns for add and mull.
1496818334Speter
14969169699Skan(define_insn "*fop_sf_comm_mixed"
14970169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,x")
1497190286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1497296294Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "%0,0")
14973169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))]
14974169699Skan  "TARGET_MIX_SSE_I387
14975169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1497696294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1497790286Sobrien  "* return output_387_binary_op (insn, operands);"
1497890286Sobrien  [(set (attr "type") 
1497990286Sobrien	(if_then_else (eq_attr "alternative" "1")
1498090286Sobrien	   (if_then_else (match_operand:SF 3 "mult_operator" "") 
14981117404Skan	      (const_string "ssemul")
14982117404Skan	      (const_string "sseadd"))
14983117404Skan	   (if_then_else (match_operand:SF 3 "mult_operator" "") 
1498490286Sobrien	      (const_string "fmul")
1498590286Sobrien	      (const_string "fop"))))
1498690286Sobrien   (set_attr "mode" "SF")])
1498718334Speter
1498890286Sobrien(define_insn "*fop_sf_comm_sse"
1498990286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1499090286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1499196294Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "%0")
1499290286Sobrien			 (match_operand:SF 2 "nonimmediate_operand" "xm")]))]
14993169699Skan  "TARGET_SSE_MATH
14994169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1499596294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1499690286Sobrien  "* return output_387_binary_op (insn, operands);"
14997117404Skan  [(set (attr "type") 
14998117404Skan        (if_then_else (match_operand:SF 3 "mult_operator" "") 
14999117404Skan	   (const_string "ssemul")
15000117404Skan	   (const_string "sseadd")))
1500190286Sobrien   (set_attr "mode" "SF")])
1500218334Speter
15003169699Skan(define_insn "*fop_sf_comm_i387"
15004169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
15005169699Skan	(match_operator:SF 3 "binary_fp_operator"
15006169699Skan			[(match_operand:SF 1 "nonimmediate_operand" "%0")
15007169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm")]))]
15008169699Skan  "TARGET_80387
15009169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1501096294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1501190286Sobrien  "* return output_387_binary_op (insn, operands);"
1501290286Sobrien  [(set (attr "type") 
1501390286Sobrien	(if_then_else (match_operand:SF 3 "mult_operator" "") 
1501490286Sobrien	   (const_string "fmul")
1501590286Sobrien	   (const_string "fop")))
1501690286Sobrien   (set_attr "mode" "SF")])
1501718334Speter
15018169699Skan(define_insn "*fop_sf_1_mixed"
1501990286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f,x")
1502090286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1502190286Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
15022169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))]
15023169699Skan  "TARGET_MIX_SSE_I387
15024169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
1502590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1502690286Sobrien  "* return output_387_binary_op (insn, operands);"
1502790286Sobrien  [(set (attr "type") 
15028117404Skan        (cond [(and (eq_attr "alternative" "2")
15029117404Skan	            (match_operand:SF 3 "mult_operator" ""))
15030117404Skan                 (const_string "ssemul")
15031117404Skan	       (and (eq_attr "alternative" "2")
15032117404Skan	            (match_operand:SF 3 "div_operator" ""))
15033117404Skan                 (const_string "ssediv")
15034117404Skan	       (eq_attr "alternative" "2")
15035117404Skan                 (const_string "sseadd")
1503690286Sobrien	       (match_operand:SF 3 "mult_operator" "") 
1503790286Sobrien                 (const_string "fmul")
1503890286Sobrien               (match_operand:SF 3 "div_operator" "") 
1503990286Sobrien                 (const_string "fdiv")
1504090286Sobrien              ]
1504190286Sobrien              (const_string "fop")))
1504290286Sobrien   (set_attr "mode" "SF")])
1504318334Speter
1504490286Sobrien(define_insn "*fop_sf_1_sse"
1504590286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1504690286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1504790286Sobrien			[(match_operand:SF 1 "register_operand" "0")
1504890286Sobrien			 (match_operand:SF 2 "nonimmediate_operand" "xm")]))]
1504990286Sobrien  "TARGET_SSE_MATH
15050169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1505190286Sobrien  "* return output_387_binary_op (insn, operands);"
15052117404Skan  [(set (attr "type") 
15053117404Skan        (cond [(match_operand:SF 3 "mult_operator" "")
15054117404Skan                 (const_string "ssemul")
15055117404Skan	       (match_operand:SF 3 "div_operator" "")
15056117404Skan                 (const_string "ssediv")
15057117404Skan              ]
15058117404Skan              (const_string "sseadd")))
1505990286Sobrien   (set_attr "mode" "SF")])
1506018334Speter
15061169699Skan;; This pattern is not fully shadowed by the pattern above.
15062169699Skan(define_insn "*fop_sf_1_i387"
15063169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
15064169699Skan	(match_operator:SF 3 "binary_fp_operator"
15065169699Skan			[(match_operand:SF 1 "nonimmediate_operand" "0,fm")
15066169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
15067169699Skan  "TARGET_80387 && !TARGET_SSE_MATH
15068169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
15069169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15070169699Skan  "* return output_387_binary_op (insn, operands);"
15071169699Skan  [(set (attr "type") 
15072169699Skan        (cond [(match_operand:SF 3 "mult_operator" "") 
15073169699Skan                 (const_string "fmul")
15074169699Skan               (match_operand:SF 3 "div_operator" "") 
15075169699Skan                 (const_string "fdiv")
15076169699Skan              ]
15077169699Skan              (const_string "fop")))
15078169699Skan   (set_attr "mode" "SF")])
15079169699Skan
1508090286Sobrien;; ??? Add SSE splitters for these!
15081169699Skan(define_insn "*fop_sf_2<mode>_i387"
1508290286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
1508390286Sobrien	(match_operator:SF 3 "binary_fp_operator"
15084169699Skan	  [(float:SF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1508590286Sobrien	   (match_operand:SF 2 "register_operand" "0,0")]))]
15086169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
1508790286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1508890286Sobrien  [(set (attr "type") 
1508990286Sobrien        (cond [(match_operand:SF 3 "mult_operator" "") 
1509090286Sobrien                 (const_string "fmul")
1509190286Sobrien               (match_operand:SF 3 "div_operator" "") 
1509290286Sobrien                 (const_string "fdiv")
1509390286Sobrien              ]
1509490286Sobrien              (const_string "fop")))
1509590286Sobrien   (set_attr "fp_int_src" "true")
15096169699Skan   (set_attr "mode" "<MODE>")])
1509718334Speter
15098169699Skan(define_insn "*fop_sf_3<mode>_i387"
1509990286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
1510090286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1510190286Sobrien	  [(match_operand:SF 1 "register_operand" "0,0")
15102169699Skan	   (float:SF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15103169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
1510490286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1510590286Sobrien  [(set (attr "type") 
1510690286Sobrien        (cond [(match_operand:SF 3 "mult_operator" "") 
1510790286Sobrien                 (const_string "fmul")
1510890286Sobrien               (match_operand:SF 3 "div_operator" "") 
1510990286Sobrien                 (const_string "fdiv")
1511090286Sobrien              ]
1511190286Sobrien              (const_string "fop")))
1511290286Sobrien   (set_attr "fp_int_src" "true")
15113169699Skan   (set_attr "mode" "<MODE>")])
1511418334Speter
15115169699Skan(define_insn "*fop_df_comm_mixed"
15116169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,Y")
1511790286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15118169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0,0")
15119169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))]
15120169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387
15121169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1512290286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1512390286Sobrien  "* return output_387_binary_op (insn, operands);"
1512490286Sobrien  [(set (attr "type") 
15125169699Skan	(if_then_else (eq_attr "alternative" "1")
15126169699Skan	   (if_then_else (match_operand:DF 3 "mult_operator" "") 
15127169699Skan	      (const_string "ssemul")
15128169699Skan	      (const_string "sseadd"))
15129169699Skan	   (if_then_else (match_operand:DF 3 "mult_operator" "") 
15130169699Skan	      (const_string "fmul")
15131169699Skan	      (const_string "fop"))))
1513290286Sobrien   (set_attr "mode" "DF")])
1513318334Speter
15134169699Skan(define_insn "*fop_df_comm_sse"
15135169699Skan  [(set (match_operand:DF 0 "register_operand" "=Y")
15136169699Skan	(match_operator:DF 3 "binary_fp_operator"
15137169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0")
15138169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
15139169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
15140169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
15141169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15142169699Skan  "* return output_387_binary_op (insn, operands);"
15143169699Skan  [(set (attr "type") 
15144169699Skan        (if_then_else (match_operand:DF 3 "mult_operator" "") 
15145169699Skan	   (const_string "ssemul")
15146169699Skan	   (const_string "sseadd")))
15147169699Skan   (set_attr "mode" "DF")])
1514818334Speter
15149169699Skan(define_insn "*fop_df_comm_i387"
15150169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
1515190286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15152169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0")
15153169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm")]))]
15154169699Skan  "TARGET_80387
15155169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
15156169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15157169699Skan  "* return output_387_binary_op (insn, operands);"
15158169699Skan  [(set (attr "type") 
15159169699Skan	(if_then_else (match_operand:DF 3 "mult_operator" "") 
15160169699Skan	   (const_string "fmul")
15161169699Skan	   (const_string "fop")))
15162169699Skan   (set_attr "mode" "DF")])
15163169699Skan
15164169699Skan(define_insn "*fop_df_1_mixed"
15165169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,Y")
15166169699Skan	(match_operator:DF 3 "binary_fp_operator"
1516790286Sobrien			[(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
15168169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))]
15169169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
15170169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
1517190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1517290286Sobrien  "* return output_387_binary_op (insn, operands);"
1517390286Sobrien  [(set (attr "type") 
15174117404Skan        (cond [(and (eq_attr "alternative" "2")
15175169699Skan	            (match_operand:DF 3 "mult_operator" ""))
15176117404Skan                 (const_string "ssemul")
15177117404Skan	       (and (eq_attr "alternative" "2")
15178169699Skan	            (match_operand:DF 3 "div_operator" ""))
15179117404Skan                 (const_string "ssediv")
15180117404Skan	       (eq_attr "alternative" "2")
15181117404Skan                 (const_string "sseadd")
1518290286Sobrien	       (match_operand:DF 3 "mult_operator" "") 
1518390286Sobrien                 (const_string "fmul")
1518490286Sobrien               (match_operand:DF 3 "div_operator" "") 
1518590286Sobrien                 (const_string "fdiv")
1518690286Sobrien              ]
1518790286Sobrien              (const_string "fop")))
1518890286Sobrien   (set_attr "mode" "DF")])
1518918334Speter
1519090286Sobrien(define_insn "*fop_df_1_sse"
1519190286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1519290286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1519390286Sobrien			[(match_operand:DF 1 "register_operand" "0")
1519490286Sobrien			 (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
1519590286Sobrien  "TARGET_SSE2 && TARGET_SSE_MATH
15196169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1519790286Sobrien  "* return output_387_binary_op (insn, operands);"
15198117404Skan  [(set_attr "mode" "DF")
15199117404Skan   (set (attr "type") 
15200169699Skan        (cond [(match_operand:DF 3 "mult_operator" "")
15201117404Skan                 (const_string "ssemul")
15202169699Skan	       (match_operand:DF 3 "div_operator" "")
15203117404Skan                 (const_string "ssediv")
15204117404Skan              ]
15205117404Skan              (const_string "sseadd")))])
1520618334Speter
15207169699Skan;; This pattern is not fully shadowed by the pattern above.
15208169699Skan(define_insn "*fop_df_1_i387"
15209169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
15210169699Skan	(match_operator:DF 3 "binary_fp_operator"
15211169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "0,fm")
15212169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
15213169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
15214169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
15215169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15216169699Skan  "* return output_387_binary_op (insn, operands);"
15217169699Skan  [(set (attr "type") 
15218169699Skan        (cond [(match_operand:DF 3 "mult_operator" "") 
15219169699Skan                 (const_string "fmul")
15220169699Skan               (match_operand:DF 3 "div_operator" "")
15221169699Skan                 (const_string "fdiv")
15222169699Skan              ]
15223169699Skan              (const_string "fop")))
15224169699Skan   (set_attr "mode" "DF")])
15225169699Skan
1522690286Sobrien;; ??? Add SSE splitters for these!
15227169699Skan(define_insn "*fop_df_2<mode>_i387"
1522890286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1522990286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15230169699Skan	   [(float:DF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1523190286Sobrien	    (match_operand:DF 2 "register_operand" "0,0")]))]
15232169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
15233169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1523490286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1523590286Sobrien  [(set (attr "type") 
1523690286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1523790286Sobrien                 (const_string "fmul")
1523890286Sobrien               (match_operand:DF 3 "div_operator" "") 
1523990286Sobrien                 (const_string "fdiv")
1524090286Sobrien              ]
1524190286Sobrien              (const_string "fop")))
1524290286Sobrien   (set_attr "fp_int_src" "true")
15243169699Skan   (set_attr "mode" "<MODE>")])
1524418334Speter
15245169699Skan(define_insn "*fop_df_3<mode>_i387"
1524690286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1524790286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1524890286Sobrien	   [(match_operand:DF 1 "register_operand" "0,0")
15249169699Skan	    (float:DF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15250169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
15251169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1525290286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1525390286Sobrien  [(set (attr "type") 
1525490286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1525590286Sobrien                 (const_string "fmul")
1525690286Sobrien               (match_operand:DF 3 "div_operator" "") 
1525790286Sobrien                 (const_string "fdiv")
1525890286Sobrien              ]
1525990286Sobrien              (const_string "fop")))
1526090286Sobrien   (set_attr "fp_int_src" "true")
15261169699Skan   (set_attr "mode" "<MODE>")])
1526218334Speter
15263169699Skan(define_insn "*fop_df_4_i387"
1526490286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1526590286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1526690286Sobrien	   [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
1526790286Sobrien	    (match_operand:DF 2 "register_operand" "0,f")]))]
15268169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
1526990286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1527090286Sobrien  "* return output_387_binary_op (insn, operands);"
1527190286Sobrien  [(set (attr "type") 
1527290286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1527390286Sobrien                 (const_string "fmul")
1527490286Sobrien               (match_operand:DF 3 "div_operator" "") 
1527590286Sobrien                 (const_string "fdiv")
1527690286Sobrien              ]
1527790286Sobrien              (const_string "fop")))
1527890286Sobrien   (set_attr "mode" "SF")])
1527918334Speter
15280169699Skan(define_insn "*fop_df_5_i387"
1528118334Speter  [(set (match_operand:DF 0 "register_operand" "=f,f")
1528290286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1528390286Sobrien	  [(match_operand:DF 1 "register_operand" "0,f")
1528490286Sobrien	   (float_extend:DF
1528590286Sobrien	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
1528690286Sobrien  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1528750650Sobrien  "* return output_387_binary_op (insn, operands);"
1528850650Sobrien  [(set (attr "type") 
1528990286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1529090286Sobrien                 (const_string "fmul")
1529190286Sobrien               (match_operand:DF 3 "div_operator" "") 
1529290286Sobrien                 (const_string "fdiv")
1529350650Sobrien              ]
1529490286Sobrien              (const_string "fop")))
1529590286Sobrien   (set_attr "mode" "SF")])
1529618334Speter
15297169699Skan(define_insn "*fop_df_6_i387"
15298132727Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
15299132727Skan	(match_operator:DF 3 "binary_fp_operator"
15300132727Skan	  [(float_extend:DF
15301132727Skan	    (match_operand:SF 1 "register_operand" "0,f"))
15302132727Skan	   (float_extend:DF
15303132727Skan	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
15304132727Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1530550650Sobrien  "* return output_387_binary_op (insn, operands);"
1530650650Sobrien  [(set (attr "type") 
15307132727Skan        (cond [(match_operand:DF 3 "mult_operator" "") 
1530890286Sobrien                 (const_string "fmul")
15309132727Skan               (match_operand:DF 3 "div_operator" "") 
1531090286Sobrien                 (const_string "fdiv")
1531150650Sobrien              ]
1531290286Sobrien              (const_string "fop")))
15313132727Skan   (set_attr "mode" "SF")])
1531418334Speter
15315169699Skan(define_insn "*fop_xf_comm_i387"
15316169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15317169699Skan	(match_operator:XF 3 "binary_fp_operator"
15318169699Skan			[(match_operand:XF 1 "register_operand" "%0")
15319169699Skan			 (match_operand:XF 2 "register_operand" "f")]))]
15320169699Skan  "TARGET_80387
15321169699Skan   && COMMUTATIVE_ARITH_P (operands[3])"
15322169699Skan  "* return output_387_binary_op (insn, operands);"
15323169699Skan  [(set (attr "type") 
15324169699Skan        (if_then_else (match_operand:XF 3 "mult_operator" "") 
15325169699Skan           (const_string "fmul")
15326169699Skan           (const_string "fop")))
15327169699Skan   (set_attr "mode" "XF")])
15328169699Skan
15329169699Skan(define_insn "*fop_xf_1_i387"
15330132727Skan  [(set (match_operand:XF 0 "register_operand" "=f,f")
15331132727Skan	(match_operator:XF 3 "binary_fp_operator"
15332132727Skan			[(match_operand:XF 1 "register_operand" "0,f")
15333132727Skan			 (match_operand:XF 2 "register_operand" "f,0")]))]
1533490286Sobrien  "TARGET_80387
15335169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1533690286Sobrien  "* return output_387_binary_op (insn, operands);"
1533790286Sobrien  [(set (attr "type") 
15338132727Skan        (cond [(match_operand:XF 3 "mult_operator" "") 
1533990286Sobrien                 (const_string "fmul")
15340132727Skan               (match_operand:XF 3 "div_operator" "") 
1534190286Sobrien                 (const_string "fdiv")
1534290286Sobrien              ]
1534390286Sobrien              (const_string "fop")))
1534490286Sobrien   (set_attr "mode" "XF")])
1534590286Sobrien
15346169699Skan(define_insn "*fop_xf_2<mode>_i387"
1534718334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
1534890286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15349169699Skan	   [(float:XF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1535090286Sobrien	    (match_operand:XF 2 "register_operand" "0,0")]))]
15351169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
1535290286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1535390286Sobrien  [(set (attr "type") 
1535490286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1535590286Sobrien                 (const_string "fmul")
1535690286Sobrien               (match_operand:XF 3 "div_operator" "") 
1535790286Sobrien                 (const_string "fdiv")
1535890286Sobrien              ]
1535990286Sobrien              (const_string "fop")))
1536090286Sobrien   (set_attr "fp_int_src" "true")
15361169699Skan   (set_attr "mode" "<MODE>")])
1536290286Sobrien
15363169699Skan(define_insn "*fop_xf_3<mode>_i387"
1536490286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1536590286Sobrien	(match_operator:XF 3 "binary_fp_operator"
1536690286Sobrien	  [(match_operand:XF 1 "register_operand" "0,0")
15367169699Skan	   (float:XF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15368169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
1536990286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1537090286Sobrien  [(set (attr "type") 
1537190286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1537290286Sobrien                 (const_string "fmul")
1537390286Sobrien               (match_operand:XF 3 "div_operator" "") 
1537490286Sobrien                 (const_string "fdiv")
1537590286Sobrien              ]
1537690286Sobrien              (const_string "fop")))
1537790286Sobrien   (set_attr "fp_int_src" "true")
15378169699Skan   (set_attr "mode" "<MODE>")])
1537990286Sobrien
15380169699Skan(define_insn "*fop_xf_4_i387"
1538190286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1538290286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15383132727Skan	   [(float_extend:XF (match_operand 1 "nonimmediate_operand" "fm,0"))
1538450650Sobrien	    (match_operand:XF 2 "register_operand" "0,f")]))]
15385132727Skan  "TARGET_80387"
1538690286Sobrien  "* return output_387_binary_op (insn, operands);"
1538790286Sobrien  [(set (attr "type") 
1538890286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1538990286Sobrien                 (const_string "fmul")
1539090286Sobrien               (match_operand:XF 3 "div_operator" "") 
1539190286Sobrien                 (const_string "fdiv")
1539290286Sobrien              ]
1539390286Sobrien              (const_string "fop")))
1539490286Sobrien   (set_attr "mode" "SF")])
1539590286Sobrien
15396169699Skan(define_insn "*fop_xf_5_i387"
1539718334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
1539890286Sobrien	(match_operator:XF 3 "binary_fp_operator"
1539950650Sobrien	  [(match_operand:XF 1 "register_operand" "0,f")
1540018334Speter	   (float_extend:XF
15401132727Skan	    (match_operand 2 "nonimmediate_operand" "fm,0"))]))]
15402132727Skan  "TARGET_80387"
1540350650Sobrien  "* return output_387_binary_op (insn, operands);"
1540450650Sobrien  [(set (attr "type") 
1540590286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1540690286Sobrien                 (const_string "fmul")
1540790286Sobrien               (match_operand:XF 3 "div_operator" "") 
1540890286Sobrien                 (const_string "fdiv")
1540950650Sobrien              ]
1541090286Sobrien              (const_string "fop")))
1541190286Sobrien   (set_attr "mode" "SF")])
1541218334Speter
15413169699Skan(define_insn "*fop_xf_6_i387"
1541490286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1541590286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15416132727Skan	  [(float_extend:XF
15417132727Skan	    (match_operand 1 "register_operand" "0,f"))
15418132727Skan	   (float_extend:XF
15419132727Skan	    (match_operand 2 "nonimmediate_operand" "fm,0"))]))]
1542018334Speter  "TARGET_80387"
1542150650Sobrien  "* return output_387_binary_op (insn, operands);"
1542250650Sobrien  [(set (attr "type") 
1542390286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1542490286Sobrien                 (const_string "fmul")
1542590286Sobrien               (match_operand:XF 3 "div_operator" "") 
1542690286Sobrien                 (const_string "fdiv")
1542790286Sobrien              ]
1542890286Sobrien              (const_string "fop")))
15429132727Skan   (set_attr "mode" "SF")])
1543090286Sobrien
1543190286Sobrien(define_split
1543290286Sobrien  [(set (match_operand 0 "register_operand" "")
1543390286Sobrien	(match_operator 3 "binary_fp_operator"
15434169699Skan	   [(float (match_operand:X87MODEI12 1 "register_operand" ""))
1543590286Sobrien	    (match_operand 2 "register_operand" "")]))]
1543690286Sobrien  "TARGET_80387 && reload_completed
1543790286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))"
1543890286Sobrien  [(const_int 0)]
1543990286Sobrien{ 
1544090286Sobrien  operands[4] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
1544190286Sobrien  operands[4] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[4]);
1544290286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1544390286Sobrien			  gen_rtx_fmt_ee (GET_CODE (operands[3]),
1544490286Sobrien					  GET_MODE (operands[3]),
1544590286Sobrien					  operands[4],
1544690286Sobrien					  operands[2])));
1544790286Sobrien  ix86_free_from_memory (GET_MODE (operands[1]));
1544890286Sobrien  DONE;
1544990286Sobrien})
1545090286Sobrien
1545190286Sobrien(define_split
1545290286Sobrien  [(set (match_operand 0 "register_operand" "")
1545390286Sobrien	(match_operator 3 "binary_fp_operator"
1545490286Sobrien	   [(match_operand 1 "register_operand" "")
15455169699Skan	    (float (match_operand:X87MODEI12 2 "register_operand" ""))]))]
1545690286Sobrien  "TARGET_80387 && reload_completed
1545790286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))"
1545890286Sobrien  [(const_int 0)]
1545990286Sobrien{
1546090286Sobrien  operands[4] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
1546190286Sobrien  operands[4] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[4]);
1546290286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1546390286Sobrien			  gen_rtx_fmt_ee (GET_CODE (operands[3]),
1546490286Sobrien					  GET_MODE (operands[3]),
1546590286Sobrien					  operands[1],
1546690286Sobrien					  operands[4])));
1546790286Sobrien  ix86_free_from_memory (GET_MODE (operands[2]));
1546890286Sobrien  DONE;
1546990286Sobrien})
1547018334Speter
1547190286Sobrien;; FPU special functions.
1547290286Sobrien
1547390286Sobrien(define_expand "sqrtsf2"
1547490286Sobrien  [(set (match_operand:SF 0 "register_operand" "")
1547590286Sobrien	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
15476169699Skan  "TARGET_USE_FANCY_MATH_387 || TARGET_SSE_MATH"
1547790286Sobrien{
1547890286Sobrien  if (!TARGET_SSE_MATH)
1547990286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
1548090286Sobrien})
1548190286Sobrien
15482169699Skan(define_insn "*sqrtsf2_mixed"
15483169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,x")
15484169699Skan	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))]
15485169699Skan  "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387"
1548690286Sobrien  "@
1548790286Sobrien   fsqrt
1548890286Sobrien   sqrtss\t{%1, %0|%0, %1}"
1548990286Sobrien  [(set_attr "type" "fpspc,sse")
1549090286Sobrien   (set_attr "mode" "SF,SF")
1549190286Sobrien   (set_attr "athlon_decode" "direct,*")])
1549290286Sobrien
15493169699Skan(define_insn "*sqrtsf2_sse"
1549490286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1549590286Sobrien	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "xm")))]
15496169699Skan  "TARGET_SSE_MATH"
1549790286Sobrien  "sqrtss\t{%1, %0|%0, %1}"
1549890286Sobrien  [(set_attr "type" "sse")
1549990286Sobrien   (set_attr "mode" "SF")
1550090286Sobrien   (set_attr "athlon_decode" "*")])
1550190286Sobrien
15502169699Skan(define_insn "*sqrtsf2_i387"
1550390286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
1550490286Sobrien	(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
15505169699Skan  "TARGET_USE_FANCY_MATH_387"
1550690286Sobrien  "fsqrt"
1550790286Sobrien  [(set_attr "type" "fpspc")
1550890286Sobrien   (set_attr "mode" "SF")
1550990286Sobrien   (set_attr "athlon_decode" "direct")])
1551090286Sobrien
1551190286Sobrien(define_expand "sqrtdf2"
1551290286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
1551390286Sobrien	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
15514169699Skan  "TARGET_USE_FANCY_MATH_387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
1551590286Sobrien{
15516169699Skan  if (!(TARGET_SSE2 && TARGET_SSE_MATH))
1551790286Sobrien    operands[1] = force_reg (DFmode, operands[1]);
1551890286Sobrien})
1551990286Sobrien
15520169699Skan(define_insn "*sqrtdf2_mixed"
15521169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,Y")
15522169699Skan	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))]
15523169699Skan  "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387"
1552490286Sobrien  "@
1552590286Sobrien   fsqrt
1552690286Sobrien   sqrtsd\t{%1, %0|%0, %1}"
1552790286Sobrien  [(set_attr "type" "fpspc,sse")
1552890286Sobrien   (set_attr "mode" "DF,DF")
1552990286Sobrien   (set_attr "athlon_decode" "direct,*")])
1553090286Sobrien
15531169699Skan(define_insn "*sqrtdf2_sse"
1553290286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1553390286Sobrien	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
15534169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
1553590286Sobrien  "sqrtsd\t{%1, %0|%0, %1}"
1553690286Sobrien  [(set_attr "type" "sse")
1553790286Sobrien   (set_attr "mode" "DF")
1553890286Sobrien   (set_attr "athlon_decode" "*")])
1553990286Sobrien
15540169699Skan(define_insn "*sqrtdf2_i387"
1554190286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1554290286Sobrien	(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
15543169699Skan  "TARGET_USE_FANCY_MATH_387"
1554490286Sobrien  "fsqrt"
1554590286Sobrien  [(set_attr "type" "fpspc")
1554690286Sobrien   (set_attr "mode" "DF")
1554790286Sobrien   (set_attr "athlon_decode" "direct")])
1554890286Sobrien
15549169699Skan(define_insn "*sqrtextendsfdf2_i387"
1555090286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1555190286Sobrien	(sqrt:DF (float_extend:DF
1555290286Sobrien		  (match_operand:SF 1 "register_operand" "0"))))]
15553169699Skan  "TARGET_USE_FANCY_MATH_387
15554169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
1555590286Sobrien  "fsqrt"
1555690286Sobrien  [(set_attr "type" "fpspc")
1555790286Sobrien   (set_attr "mode" "DF")
1555890286Sobrien   (set_attr "athlon_decode" "direct")])
1555990286Sobrien
1556090286Sobrien(define_insn "sqrtxf2"
1556190286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1556290286Sobrien	(sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
15563169699Skan  "TARGET_USE_FANCY_MATH_387"
1556490286Sobrien  "fsqrt"
1556590286Sobrien  [(set_attr "type" "fpspc")
1556690286Sobrien   (set_attr "mode" "XF")
1556790286Sobrien   (set_attr "athlon_decode" "direct")])
1556890286Sobrien
15569169699Skan(define_insn "*sqrtextendsfxf2_i387"
1557090286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1557190286Sobrien	(sqrt:XF (float_extend:XF
15572169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
15573169699Skan  "TARGET_USE_FANCY_MATH_387"
1557490286Sobrien  "fsqrt"
1557590286Sobrien  [(set_attr "type" "fpspc")
1557690286Sobrien   (set_attr "mode" "XF")
1557790286Sobrien   (set_attr "athlon_decode" "direct")])
1557890286Sobrien
15579169699Skan(define_insn "*sqrtextenddfxf2_i387"
1558090286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1558190286Sobrien	(sqrt:XF (float_extend:XF
15582169699Skan		  (match_operand:DF 1 "register_operand" "0"))))]
15583169699Skan  "TARGET_USE_FANCY_MATH_387"
1558490286Sobrien  "fsqrt"
1558590286Sobrien  [(set_attr "type" "fpspc")
1558690286Sobrien   (set_attr "mode" "XF")
1558790286Sobrien   (set_attr "athlon_decode" "direct")])
1558890286Sobrien
15589169699Skan(define_insn "fpremxf4"
15590169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15591169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
15592169699Skan		    (match_operand:XF 3 "register_operand" "1")]
15593169699Skan		   UNSPEC_FPREM_F))
15594169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15595169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
15596169699Skan		   UNSPEC_FPREM_U))
15597169699Skan   (set (reg:CCFP FPSR_REG)
15598169699Skan	(unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
15599169699Skan  "TARGET_USE_FANCY_MATH_387
15600169699Skan   && flag_unsafe_math_optimizations"
15601169699Skan  "fprem"
15602169699Skan  [(set_attr "type" "fpspc")
15603169699Skan   (set_attr "mode" "XF")])
15604169699Skan
15605169699Skan(define_expand "fmodsf3"
15606169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
15607169699Skan   (use (match_operand:SF 1 "register_operand" ""))
15608169699Skan   (use (match_operand:SF 2 "register_operand" ""))]
15609169699Skan  "TARGET_USE_FANCY_MATH_387
15610169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15611169699Skan   && flag_unsafe_math_optimizations"
15612169699Skan{
15613169699Skan  rtx label = gen_label_rtx ();
15614169699Skan
15615169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15616169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15617169699Skan
15618169699Skan  emit_insn(gen_extendsfxf2 (op1, operands[1]));
15619169699Skan  emit_insn(gen_extendsfxf2 (op2, operands[2]));
15620169699Skan
15621169699Skan  emit_label (label);
15622169699Skan
15623169699Skan  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
15624169699Skan  ix86_emit_fp_unordered_jump (label);
15625169699Skan
15626169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
15627169699Skan  DONE;
15628169699Skan})
15629169699Skan
15630169699Skan(define_expand "fmoddf3"
15631169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
15632169699Skan   (use (match_operand:DF 1 "register_operand" ""))
15633169699Skan   (use (match_operand:DF 2 "register_operand" ""))]
15634169699Skan  "TARGET_USE_FANCY_MATH_387
15635169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15636169699Skan   && flag_unsafe_math_optimizations"
15637169699Skan{
15638169699Skan  rtx label = gen_label_rtx ();
15639169699Skan
15640169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15641169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15642169699Skan
15643169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
15644169699Skan  emit_insn (gen_extenddfxf2 (op2, operands[2]));
15645169699Skan
15646169699Skan  emit_label (label);
15647169699Skan
15648169699Skan  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
15649169699Skan  ix86_emit_fp_unordered_jump (label);
15650169699Skan
15651169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
15652169699Skan  DONE;
15653169699Skan})
15654169699Skan
15655169699Skan(define_expand "fmodxf3"
15656169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
15657169699Skan   (use (match_operand:XF 1 "register_operand" ""))
15658169699Skan   (use (match_operand:XF 2 "register_operand" ""))]
15659169699Skan  "TARGET_USE_FANCY_MATH_387
15660169699Skan   && flag_unsafe_math_optimizations"
15661169699Skan{
15662169699Skan  rtx label = gen_label_rtx ();
15663169699Skan
15664169699Skan  emit_label (label);
15665169699Skan
15666169699Skan  emit_insn (gen_fpremxf4 (operands[1], operands[2],
15667169699Skan			   operands[1], operands[2]));
15668169699Skan  ix86_emit_fp_unordered_jump (label);
15669169699Skan
15670169699Skan  emit_move_insn (operands[0], operands[1]);
15671169699Skan  DONE;
15672169699Skan})
15673169699Skan
15674169699Skan(define_insn "fprem1xf4"
15675169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15676169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
15677169699Skan		    (match_operand:XF 3 "register_operand" "1")]
15678169699Skan		   UNSPEC_FPREM1_F))
15679169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15680169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
15681169699Skan		   UNSPEC_FPREM1_U))
15682169699Skan   (set (reg:CCFP FPSR_REG)
15683169699Skan	(unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
15684169699Skan  "TARGET_USE_FANCY_MATH_387
15685169699Skan   && flag_unsafe_math_optimizations"
15686169699Skan  "fprem1"
15687169699Skan  [(set_attr "type" "fpspc")
15688169699Skan   (set_attr "mode" "XF")])
15689169699Skan
15690169699Skan(define_expand "dremsf3"
15691169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
15692169699Skan   (use (match_operand:SF 1 "register_operand" ""))
15693169699Skan   (use (match_operand:SF 2 "register_operand" ""))]
15694169699Skan  "TARGET_USE_FANCY_MATH_387
15695169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15696169699Skan   && flag_unsafe_math_optimizations"
15697169699Skan{
15698169699Skan  rtx label = gen_label_rtx ();
15699169699Skan
15700169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15701169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15702169699Skan
15703169699Skan  emit_insn(gen_extendsfxf2 (op1, operands[1]));
15704169699Skan  emit_insn(gen_extendsfxf2 (op2, operands[2]));
15705169699Skan
15706169699Skan  emit_label (label);
15707169699Skan
15708169699Skan  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
15709169699Skan  ix86_emit_fp_unordered_jump (label);
15710169699Skan
15711169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
15712169699Skan  DONE;
15713169699Skan})
15714169699Skan
15715169699Skan(define_expand "dremdf3"
15716169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
15717169699Skan   (use (match_operand:DF 1 "register_operand" ""))
15718169699Skan   (use (match_operand:DF 2 "register_operand" ""))]
15719169699Skan  "TARGET_USE_FANCY_MATH_387
15720169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15721169699Skan   && flag_unsafe_math_optimizations"
15722169699Skan{
15723169699Skan  rtx label = gen_label_rtx ();
15724169699Skan
15725169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15726169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15727169699Skan
15728169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
15729169699Skan  emit_insn (gen_extenddfxf2 (op2, operands[2]));
15730169699Skan
15731169699Skan  emit_label (label);
15732169699Skan
15733169699Skan  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
15734169699Skan  ix86_emit_fp_unordered_jump (label);
15735169699Skan
15736169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
15737169699Skan  DONE;
15738169699Skan})
15739169699Skan
15740169699Skan(define_expand "dremxf3"
15741169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
15742169699Skan   (use (match_operand:XF 1 "register_operand" ""))
15743169699Skan   (use (match_operand:XF 2 "register_operand" ""))]
15744169699Skan  "TARGET_USE_FANCY_MATH_387
15745169699Skan   && flag_unsafe_math_optimizations"
15746169699Skan{
15747169699Skan  rtx label = gen_label_rtx ();
15748169699Skan
15749169699Skan  emit_label (label);
15750169699Skan
15751169699Skan  emit_insn (gen_fprem1xf4 (operands[1], operands[2],
15752169699Skan			    operands[1], operands[2]));
15753169699Skan  ix86_emit_fp_unordered_jump (label);
15754169699Skan
15755169699Skan  emit_move_insn (operands[0], operands[1]);
15756169699Skan  DONE;
15757169699Skan})
15758169699Skan
15759169699Skan(define_insn "*sindf2"
1576090286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
15761117404Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_SIN))]
15762169699Skan  "TARGET_USE_FANCY_MATH_387
15763169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1576490286Sobrien   && flag_unsafe_math_optimizations"
1576590286Sobrien  "fsin"
1576690286Sobrien  [(set_attr "type" "fpspc")
1576790286Sobrien   (set_attr "mode" "DF")])
1576890286Sobrien
15769169699Skan(define_insn "*sinsf2"
1577090286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
15771117404Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_SIN))]
15772169699Skan  "TARGET_USE_FANCY_MATH_387
15773169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
1577490286Sobrien   && flag_unsafe_math_optimizations"
1577590286Sobrien  "fsin"
1577690286Sobrien  [(set_attr "type" "fpspc")
1577790286Sobrien   (set_attr "mode" "SF")])
1577890286Sobrien
1577990286Sobrien(define_insn "*sinextendsfdf2"
1578090286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1578190286Sobrien	(unspec:DF [(float_extend:DF
15782117404Skan		     (match_operand:SF 1 "register_operand" "0"))]
15783117404Skan		   UNSPEC_SIN))]
15784169699Skan  "TARGET_USE_FANCY_MATH_387
15785169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1578690286Sobrien   && flag_unsafe_math_optimizations"
1578790286Sobrien  "fsin"
1578890286Sobrien  [(set_attr "type" "fpspc")
1578990286Sobrien   (set_attr "mode" "DF")])
1579090286Sobrien
15791169699Skan(define_insn "*sinxf2"
1579290286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
15793117404Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_SIN))]
15794169699Skan  "TARGET_USE_FANCY_MATH_387
1579590286Sobrien   && flag_unsafe_math_optimizations"
1579690286Sobrien  "fsin"
1579790286Sobrien  [(set_attr "type" "fpspc")
1579890286Sobrien   (set_attr "mode" "XF")])
1579990286Sobrien
15800169699Skan(define_insn "*cosdf2"
1580190286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
15802117404Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_COS))]
15803169699Skan  "TARGET_USE_FANCY_MATH_387
15804169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1580590286Sobrien   && flag_unsafe_math_optimizations"
1580690286Sobrien  "fcos"
1580790286Sobrien  [(set_attr "type" "fpspc")
1580890286Sobrien   (set_attr "mode" "DF")])
1580990286Sobrien
15810169699Skan(define_insn "*cossf2"
1581190286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
15812117404Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_COS))]
15813169699Skan  "TARGET_USE_FANCY_MATH_387
15814169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
1581590286Sobrien   && flag_unsafe_math_optimizations"
1581690286Sobrien  "fcos"
1581790286Sobrien  [(set_attr "type" "fpspc")
1581890286Sobrien   (set_attr "mode" "SF")])
1581990286Sobrien
1582090286Sobrien(define_insn "*cosextendsfdf2"
1582190286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1582290286Sobrien	(unspec:DF [(float_extend:DF
15823117404Skan		     (match_operand:SF 1 "register_operand" "0"))]
15824117404Skan		   UNSPEC_COS))]
15825169699Skan  "TARGET_USE_FANCY_MATH_387
15826169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1582790286Sobrien   && flag_unsafe_math_optimizations"
1582890286Sobrien  "fcos"
1582990286Sobrien  [(set_attr "type" "fpspc")
1583090286Sobrien   (set_attr "mode" "DF")])
1583190286Sobrien
15832169699Skan(define_insn "*cosxf2"
1583390286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
15834117404Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_COS))]
15835169699Skan  "TARGET_USE_FANCY_MATH_387
1583690286Sobrien   && flag_unsafe_math_optimizations"
1583790286Sobrien  "fcos"
1583890286Sobrien  [(set_attr "type" "fpspc")
1583990286Sobrien   (set_attr "mode" "XF")])
1584090286Sobrien
15841169699Skan;; With sincos pattern defined, sin and cos builtin function will be
15842169699Skan;; expanded to sincos pattern with one of its outputs left unused. 
15843169699Skan;; Cse pass  will detected, if two sincos patterns can be combined,
15844169699Skan;; otherwise sincos pattern will be split back to sin or cos pattern,
15845169699Skan;; depending on the unused output.
15846169699Skan
15847169699Skan(define_insn "sincosdf3"
15848169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
15849169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")]
15850169699Skan		   UNSPEC_SINCOS_COS))
15851169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
15852169699Skan        (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15853169699Skan  "TARGET_USE_FANCY_MATH_387
15854169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15855169699Skan   && flag_unsafe_math_optimizations"
15856169699Skan  "fsincos"
15857169699Skan  [(set_attr "type" "fpspc")
15858169699Skan   (set_attr "mode" "DF")])
15859169699Skan
15860169699Skan(define_split
15861169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15862169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "")]
15863169699Skan		   UNSPEC_SINCOS_COS))
15864169699Skan   (set (match_operand:DF 1 "register_operand" "")
15865169699Skan	(unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15866169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15867169699Skan   && !reload_completed && !reload_in_progress"
15868169699Skan  [(set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_SIN))]
15869169699Skan  "")
15870169699Skan
15871169699Skan(define_split
15872169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15873169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "")]
15874169699Skan		   UNSPEC_SINCOS_COS))
15875169699Skan   (set (match_operand:DF 1 "register_operand" "")
15876169699Skan	(unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15877169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15878169699Skan   && !reload_completed && !reload_in_progress"
15879169699Skan  [(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_COS))]
15880169699Skan  "")
15881169699Skan
15882169699Skan(define_insn "sincossf3"
15883169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
15884169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "0")]
15885169699Skan		   UNSPEC_SINCOS_COS))
15886169699Skan   (set (match_operand:SF 1 "register_operand" "=u")
15887169699Skan        (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15888169699Skan  "TARGET_USE_FANCY_MATH_387
15889169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15890169699Skan   && flag_unsafe_math_optimizations"
15891169699Skan  "fsincos"
15892169699Skan  [(set_attr "type" "fpspc")
15893169699Skan   (set_attr "mode" "SF")])
15894169699Skan
15895169699Skan(define_split
15896169699Skan  [(set (match_operand:SF 0 "register_operand" "")
15897169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "")]
15898169699Skan		   UNSPEC_SINCOS_COS))
15899169699Skan   (set (match_operand:SF 1 "register_operand" "")
15900169699Skan	(unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15901169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15902169699Skan   && !reload_completed && !reload_in_progress"
15903169699Skan  [(set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_SIN))]
15904169699Skan  "")
15905169699Skan
15906169699Skan(define_split
15907169699Skan  [(set (match_operand:SF 0 "register_operand" "")
15908169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "")]
15909169699Skan		   UNSPEC_SINCOS_COS))
15910169699Skan   (set (match_operand:SF 1 "register_operand" "")
15911169699Skan	(unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15912169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15913169699Skan   && !reload_completed && !reload_in_progress"
15914169699Skan  [(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_COS))]
15915169699Skan  "")
15916169699Skan
15917169699Skan(define_insn "*sincosextendsfdf3"
15918169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
15919169699Skan	(unspec:DF [(float_extend:DF
15920169699Skan		     (match_operand:SF 2 "register_operand" "0"))]
15921169699Skan		   UNSPEC_SINCOS_COS))
15922169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
15923169699Skan        (unspec:DF [(float_extend:DF
15924169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
15925169699Skan  "TARGET_USE_FANCY_MATH_387
15926169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15927169699Skan   && flag_unsafe_math_optimizations"
15928169699Skan  "fsincos"
15929169699Skan  [(set_attr "type" "fpspc")
15930169699Skan   (set_attr "mode" "DF")])
15931169699Skan
15932169699Skan(define_split
15933169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15934169699Skan	(unspec:DF [(float_extend:DF
15935169699Skan		     (match_operand:SF 2 "register_operand" ""))]
15936169699Skan		   UNSPEC_SINCOS_COS))
15937169699Skan   (set (match_operand:DF 1 "register_operand" "")
15938169699Skan        (unspec:DF [(float_extend:DF
15939169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
15940169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15941169699Skan   && !reload_completed && !reload_in_progress"
15942169699Skan  [(set (match_dup 1) (unspec:DF [(float_extend:DF
15943169699Skan				   (match_dup 2))] UNSPEC_SIN))]
15944169699Skan  "")
15945169699Skan
15946169699Skan(define_split
15947169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15948169699Skan	(unspec:DF [(float_extend:DF
15949169699Skan		     (match_operand:SF 2 "register_operand" ""))]
15950169699Skan		   UNSPEC_SINCOS_COS))
15951169699Skan   (set (match_operand:DF 1 "register_operand" "")
15952169699Skan        (unspec:DF [(float_extend:DF
15953169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
15954169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15955169699Skan   && !reload_completed && !reload_in_progress"
15956169699Skan  [(set (match_dup 0) (unspec:DF [(float_extend:DF
15957169699Skan				   (match_dup 2))] UNSPEC_COS))]
15958169699Skan  "")
15959169699Skan
15960169699Skan(define_insn "sincosxf3"
15961169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15962169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
15963169699Skan		   UNSPEC_SINCOS_COS))
15964169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15965169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15966169699Skan  "TARGET_USE_FANCY_MATH_387
15967169699Skan   && flag_unsafe_math_optimizations"
15968169699Skan  "fsincos"
15969169699Skan  [(set_attr "type" "fpspc")
15970169699Skan   (set_attr "mode" "XF")])
15971169699Skan
15972169699Skan(define_split
15973169699Skan  [(set (match_operand:XF 0 "register_operand" "")
15974169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "")]
15975169699Skan		   UNSPEC_SINCOS_COS))
15976169699Skan   (set (match_operand:XF 1 "register_operand" "")
15977169699Skan	(unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15978169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15979169699Skan   && !reload_completed && !reload_in_progress"
15980169699Skan  [(set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_SIN))]
15981169699Skan  "")
15982169699Skan
15983169699Skan(define_split
15984169699Skan  [(set (match_operand:XF 0 "register_operand" "")
15985169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "")]
15986169699Skan		   UNSPEC_SINCOS_COS))
15987169699Skan   (set (match_operand:XF 1 "register_operand" "")
15988169699Skan	(unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15989169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15990169699Skan   && !reload_completed && !reload_in_progress"
15991169699Skan  [(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_COS))]
15992169699Skan  "")
15993169699Skan
15994169699Skan(define_insn "*tandf3_1"
15995169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
15996169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")]
15997169699Skan		   UNSPEC_TAN_ONE))
15998169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
15999169699Skan        (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))]
16000169699Skan  "TARGET_USE_FANCY_MATH_387
16001169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16002169699Skan   && flag_unsafe_math_optimizations"
16003169699Skan  "fptan"
16004169699Skan  [(set_attr "type" "fpspc")
16005169699Skan   (set_attr "mode" "DF")])
16006169699Skan
16007169699Skan;; optimize sequence: fptan
16008169699Skan;;		      fstp    %st(0)
16009169699Skan;;		      fld1
16010169699Skan;; into fptan insn.
16011169699Skan
16012169699Skan(define_peephole2
16013169699Skan  [(parallel[(set (match_operand:DF 0 "register_operand" "")
16014169699Skan		  (unspec:DF [(match_operand:DF 2 "register_operand" "")]
16015169699Skan			     UNSPEC_TAN_ONE))
16016169699Skan	     (set (match_operand:DF 1 "register_operand" "")
16017169699Skan		  (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])
16018169699Skan   (set (match_dup 0)
16019169699Skan        (match_operand:DF 3 "immediate_operand" ""))]
16020169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16021169699Skan  [(parallel[(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_TAN_ONE))
16022169699Skan   	     (set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16023169699Skan  "")
16024169699Skan
16025169699Skan(define_expand "tandf2"
16026169699Skan  [(parallel [(set (match_dup 2)
16027169699Skan		   (unspec:DF [(match_operand:DF 1 "register_operand" "")]
16028169699Skan			      UNSPEC_TAN_ONE))
16029169699Skan	      (set (match_operand:DF 0 "register_operand" "")
16030169699Skan		   (unspec:DF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16031169699Skan  "TARGET_USE_FANCY_MATH_387
16032169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16033169699Skan   && flag_unsafe_math_optimizations"
16034169699Skan{
16035169699Skan  operands[2] = gen_reg_rtx (DFmode);
16036169699Skan})
16037169699Skan
16038169699Skan(define_insn "*tansf3_1"
16039169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
16040169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "0")]
16041169699Skan		   UNSPEC_TAN_ONE))
16042169699Skan   (set (match_operand:SF 1 "register_operand" "=u")
16043169699Skan        (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))]
16044169699Skan  "TARGET_USE_FANCY_MATH_387
16045169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16046169699Skan   && flag_unsafe_math_optimizations"
16047169699Skan  "fptan"
16048169699Skan  [(set_attr "type" "fpspc")
16049169699Skan   (set_attr "mode" "SF")])
16050169699Skan
16051169699Skan;; optimize sequence: fptan
16052169699Skan;;		      fstp    %st(0)
16053169699Skan;;		      fld1
16054169699Skan;; into fptan insn.
16055169699Skan
16056169699Skan(define_peephole2
16057169699Skan  [(parallel[(set (match_operand:SF 0 "register_operand" "")
16058169699Skan		  (unspec:SF [(match_operand:SF 2 "register_operand" "")]
16059169699Skan			     UNSPEC_TAN_ONE))
16060169699Skan	     (set (match_operand:SF 1 "register_operand" "")
16061169699Skan		  (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])
16062169699Skan   (set (match_dup 0)
16063169699Skan        (match_operand:SF 3 "immediate_operand" ""))]
16064169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16065169699Skan  [(parallel[(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_TAN_ONE))
16066169699Skan   	     (set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16067169699Skan  "")
16068169699Skan
16069169699Skan(define_expand "tansf2"
16070169699Skan  [(parallel [(set (match_dup 2)
16071169699Skan		   (unspec:SF [(match_operand:SF 1 "register_operand" "")]
16072169699Skan			      UNSPEC_TAN_ONE))
16073169699Skan	      (set (match_operand:SF 0 "register_operand" "")
16074169699Skan		   (unspec:SF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16075169699Skan  "TARGET_USE_FANCY_MATH_387
16076169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16077169699Skan   && flag_unsafe_math_optimizations"
16078169699Skan{
16079169699Skan  operands[2] = gen_reg_rtx (SFmode);
16080169699Skan})
16081169699Skan
16082169699Skan(define_insn "*tanxf3_1"
16083169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16084169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
16085169699Skan		   UNSPEC_TAN_ONE))
16086169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16087169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))]
16088169699Skan  "TARGET_USE_FANCY_MATH_387
16089169699Skan   && flag_unsafe_math_optimizations"
16090169699Skan  "fptan"
16091169699Skan  [(set_attr "type" "fpspc")
16092169699Skan   (set_attr "mode" "XF")])
16093169699Skan
16094169699Skan;; optimize sequence: fptan
16095169699Skan;;		      fstp    %st(0)
16096169699Skan;;		      fld1
16097169699Skan;; into fptan insn.
16098169699Skan
16099169699Skan(define_peephole2
16100169699Skan  [(parallel[(set (match_operand:XF 0 "register_operand" "")
16101169699Skan		  (unspec:XF [(match_operand:XF 2 "register_operand" "")]
16102169699Skan			     UNSPEC_TAN_ONE))
16103169699Skan	     (set (match_operand:XF 1 "register_operand" "")
16104169699Skan		  (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])
16105169699Skan   (set (match_dup 0)
16106169699Skan        (match_operand:XF 3 "immediate_operand" ""))]
16107169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16108169699Skan  [(parallel[(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_TAN_ONE))
16109169699Skan   	     (set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16110169699Skan  "")
16111169699Skan
16112169699Skan(define_expand "tanxf2"
16113169699Skan  [(parallel [(set (match_dup 2)
16114169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16115169699Skan			      UNSPEC_TAN_ONE))
16116169699Skan	      (set (match_operand:XF 0 "register_operand" "")
16117169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16118169699Skan  "TARGET_USE_FANCY_MATH_387
16119169699Skan   && flag_unsafe_math_optimizations"
16120169699Skan{
16121169699Skan  operands[2] = gen_reg_rtx (XFmode);
16122169699Skan})
16123169699Skan
16124132727Skan(define_insn "atan2df3_1"
16125132727Skan  [(set (match_operand:DF 0 "register_operand" "=f")
16126132727Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")
16127132727Skan		    (match_operand:DF 1 "register_operand" "u")]
16128132727Skan		   UNSPEC_FPATAN))
16129132727Skan   (clobber (match_scratch:DF 3 "=1"))]
16130169699Skan  "TARGET_USE_FANCY_MATH_387
16131169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1613290286Sobrien   && flag_unsafe_math_optimizations"
16133132727Skan  "fpatan"
1613490286Sobrien  [(set_attr "type" "fpspc")
16135132727Skan   (set_attr "mode" "DF")])
16136132727Skan
16137132727Skan(define_expand "atan2df3"
16138169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
16139169699Skan   (use (match_operand:DF 2 "register_operand" ""))
16140169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
16141169699Skan  "TARGET_USE_FANCY_MATH_387
16142169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16143132727Skan   && flag_unsafe_math_optimizations"
16144132727Skan{
16145132727Skan  rtx copy = gen_reg_rtx (DFmode);
16146132727Skan  emit_move_insn (copy, operands[1]);
16147132727Skan  emit_insn (gen_atan2df3_1 (operands[0], copy, operands[2]));
16148132727Skan  DONE;
16149132727Skan})
16150132727Skan
16151169699Skan(define_expand "atandf2"
16152169699Skan  [(parallel [(set (match_operand:DF 0 "register_operand" "")
16153169699Skan		   (unspec:DF [(match_dup 2)
16154169699Skan			       (match_operand:DF 1 "register_operand" "")]
16155169699Skan		    UNSPEC_FPATAN))
16156169699Skan	      (clobber (match_scratch:DF 3 ""))])]
16157169699Skan  "TARGET_USE_FANCY_MATH_387
16158169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16159169699Skan   && flag_unsafe_math_optimizations"
16160169699Skan{
16161169699Skan  operands[2] = gen_reg_rtx (DFmode);
16162169699Skan  emit_move_insn (operands[2], CONST1_RTX (DFmode));  /* fld1 */
16163169699Skan})
16164169699Skan
16165132727Skan(define_insn "atan2sf3_1"
16166132727Skan  [(set (match_operand:SF 0 "register_operand" "=f")
16167132727Skan        (unspec:SF [(match_operand:SF 2 "register_operand" "0")
16168132727Skan		    (match_operand:SF 1 "register_operand" "u")]
16169132727Skan		   UNSPEC_FPATAN))
16170132727Skan   (clobber (match_scratch:SF 3 "=1"))]
16171169699Skan  "TARGET_USE_FANCY_MATH_387
16172169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16173132727Skan   && flag_unsafe_math_optimizations"
16174132727Skan  "fpatan"
16175132727Skan  [(set_attr "type" "fpspc")
16176132727Skan   (set_attr "mode" "SF")])
16177132727Skan
16178132727Skan(define_expand "atan2sf3"
16179169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
16180169699Skan   (use (match_operand:SF 2 "register_operand" ""))
16181169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
16182169699Skan  "TARGET_USE_FANCY_MATH_387
16183169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16184132727Skan   && flag_unsafe_math_optimizations"
16185132727Skan{
16186132727Skan  rtx copy = gen_reg_rtx (SFmode);
16187132727Skan  emit_move_insn (copy, operands[1]);
16188132727Skan  emit_insn (gen_atan2sf3_1 (operands[0], copy, operands[2]));
16189132727Skan  DONE;
16190132727Skan})
16191132727Skan
16192169699Skan(define_expand "atansf2"
16193169699Skan  [(parallel [(set (match_operand:SF 0 "register_operand" "")
16194169699Skan		   (unspec:SF [(match_dup 2)
16195169699Skan			       (match_operand:SF 1 "register_operand" "")]
16196169699Skan		    UNSPEC_FPATAN))
16197169699Skan	      (clobber (match_scratch:SF 3 ""))])]
16198169699Skan  "TARGET_USE_FANCY_MATH_387
16199169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16200169699Skan   && flag_unsafe_math_optimizations"
16201169699Skan{
16202169699Skan  operands[2] = gen_reg_rtx (SFmode);
16203169699Skan  emit_move_insn (operands[2], CONST1_RTX (SFmode));  /* fld1 */
16204169699Skan})
16205169699Skan
16206132727Skan(define_insn "atan2xf3_1"
16207132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16208132727Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16209132727Skan	            (match_operand:XF 1 "register_operand" "u")]
16210132727Skan	           UNSPEC_FPATAN))
16211132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16212169699Skan  "TARGET_USE_FANCY_MATH_387
16213132727Skan   && flag_unsafe_math_optimizations"
16214132727Skan  "fpatan"
16215132727Skan  [(set_attr "type" "fpspc")
1621690286Sobrien   (set_attr "mode" "XF")])
16217132727Skan
16218132727Skan(define_expand "atan2xf3"
16219169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
16220169699Skan   (use (match_operand:XF 2 "register_operand" ""))
16221169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
16222169699Skan  "TARGET_USE_FANCY_MATH_387
16223132727Skan   && flag_unsafe_math_optimizations"
16224132727Skan{
16225132727Skan  rtx copy = gen_reg_rtx (XFmode);
16226132727Skan  emit_move_insn (copy, operands[1]);
16227132727Skan  emit_insn (gen_atan2xf3_1 (operands[0], copy, operands[2]));
16228132727Skan  DONE;
16229132727Skan})
16230132727Skan
16231169699Skan(define_expand "atanxf2"
16232169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16233169699Skan		   (unspec:XF [(match_dup 2)
16234169699Skan			       (match_operand:XF 1 "register_operand" "")]
16235169699Skan		    UNSPEC_FPATAN))
16236169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16237169699Skan  "TARGET_USE_FANCY_MATH_387
16238132727Skan   && flag_unsafe_math_optimizations"
16239169699Skan{
16240169699Skan  operands[2] = gen_reg_rtx (XFmode);
16241169699Skan  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
16242169699Skan})
16243132727Skan
16244169699Skan(define_expand "asindf2"
16245169699Skan  [(set (match_dup 2)
16246169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16247169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16248169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16249169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16250169699Skan   (parallel [(set (match_dup 7)
16251169699Skan        	   (unspec:XF [(match_dup 6) (match_dup 2)]
16252169699Skan			      UNSPEC_FPATAN))
16253169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16254169699Skan   (set (match_operand:DF 0 "register_operand" "")
16255169699Skan	(float_truncate:DF (match_dup 7)))]
16256169699Skan  "TARGET_USE_FANCY_MATH_387
16257169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16258132727Skan   && flag_unsafe_math_optimizations"
16259169699Skan{
16260169699Skan  int i;
16261132727Skan
16262169699Skan  for (i=2; i<8; i++)
16263169699Skan    operands[i] = gen_reg_rtx (XFmode);
16264169699Skan
16265169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16266169699Skan})
16267169699Skan
16268169699Skan(define_expand "asinsf2"
16269169699Skan  [(set (match_dup 2)
16270169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16271169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16272169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16273169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16274169699Skan   (parallel [(set (match_dup 7)
16275169699Skan        	   (unspec:XF [(match_dup 6) (match_dup 2)]
16276169699Skan			      UNSPEC_FPATAN))
16277169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16278169699Skan   (set (match_operand:SF 0 "register_operand" "")
16279169699Skan	(float_truncate:SF (match_dup 7)))]
16280169699Skan  "TARGET_USE_FANCY_MATH_387
16281169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16282169699Skan   && flag_unsafe_math_optimizations"
16283169699Skan{
16284169699Skan  int i;
16285169699Skan
16286169699Skan  for (i=2; i<8; i++)
16287169699Skan    operands[i] = gen_reg_rtx (XFmode);
16288169699Skan
16289169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16290169699Skan})
16291169699Skan
16292169699Skan(define_expand "asinxf2"
16293169699Skan  [(set (match_dup 2)
16294169699Skan	(mult:XF (match_operand:XF 1 "register_operand" "")
16295169699Skan		 (match_dup 1)))
16296169699Skan   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
16297169699Skan   (set (match_dup 5) (sqrt:XF (match_dup 4)))
16298169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16299169699Skan        	   (unspec:XF [(match_dup 5) (match_dup 1)]
16300169699Skan			      UNSPEC_FPATAN))
16301169699Skan   	      (clobber (match_scratch:XF 6 ""))])]
16302169699Skan  "TARGET_USE_FANCY_MATH_387
16303169699Skan   && flag_unsafe_math_optimizations"
16304169699Skan{
16305169699Skan  int i;
16306169699Skan
16307169699Skan  for (i=2; i<6; i++)
16308169699Skan    operands[i] = gen_reg_rtx (XFmode);
16309169699Skan
16310169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16311169699Skan})
16312169699Skan
16313169699Skan(define_expand "acosdf2"
16314169699Skan  [(set (match_dup 2)
16315169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16316169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16317169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16318169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16319169699Skan   (parallel [(set (match_dup 7)
16320169699Skan        	   (unspec:XF [(match_dup 2) (match_dup 6)]
16321169699Skan			      UNSPEC_FPATAN))
16322169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16323169699Skan   (set (match_operand:DF 0 "register_operand" "")
16324169699Skan	(float_truncate:DF (match_dup 7)))]
16325169699Skan  "TARGET_USE_FANCY_MATH_387
16326169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16327169699Skan   && flag_unsafe_math_optimizations"
16328169699Skan{
16329169699Skan  int i;
16330169699Skan
16331169699Skan  for (i=2; i<8; i++)
16332169699Skan    operands[i] = gen_reg_rtx (XFmode);
16333169699Skan
16334169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16335169699Skan})
16336169699Skan
16337169699Skan(define_expand "acossf2"
16338169699Skan  [(set (match_dup 2)
16339169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16340169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16341169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16342169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16343169699Skan   (parallel [(set (match_dup 7)
16344169699Skan        	   (unspec:XF [(match_dup 2) (match_dup 6)]
16345169699Skan			      UNSPEC_FPATAN))
16346169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16347169699Skan   (set (match_operand:SF 0 "register_operand" "")
16348169699Skan	(float_truncate:SF (match_dup 7)))]
16349169699Skan  "TARGET_USE_FANCY_MATH_387
16350169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16351169699Skan   && flag_unsafe_math_optimizations"
16352169699Skan{
16353169699Skan  int i;
16354169699Skan
16355169699Skan  for (i=2; i<8; i++)
16356169699Skan    operands[i] = gen_reg_rtx (XFmode);
16357169699Skan
16358169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16359169699Skan})
16360169699Skan
16361169699Skan(define_expand "acosxf2"
16362169699Skan  [(set (match_dup 2)
16363169699Skan	(mult:XF (match_operand:XF 1 "register_operand" "")
16364169699Skan		 (match_dup 1)))
16365169699Skan   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
16366169699Skan   (set (match_dup 5) (sqrt:XF (match_dup 4)))
16367169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16368169699Skan        	   (unspec:XF [(match_dup 1) (match_dup 5)]
16369169699Skan			      UNSPEC_FPATAN))
16370169699Skan   	      (clobber (match_scratch:XF 6 ""))])]
16371169699Skan  "TARGET_USE_FANCY_MATH_387
16372169699Skan   && flag_unsafe_math_optimizations"
16373169699Skan{
16374169699Skan  int i;
16375169699Skan
16376169699Skan  for (i=2; i<6; i++)
16377169699Skan    operands[i] = gen_reg_rtx (XFmode);
16378169699Skan
16379169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16380169699Skan})
16381169699Skan
16382169699Skan(define_insn "fyl2x_xf3"
16383132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16384132727Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16385132727Skan		    (match_operand:XF 1 "register_operand" "u")]
16386132727Skan	           UNSPEC_FYL2X))
16387132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16388169699Skan  "TARGET_USE_FANCY_MATH_387
16389132727Skan   && flag_unsafe_math_optimizations"
16390132727Skan  "fyl2x"
16391132727Skan  [(set_attr "type" "fpspc")
16392132727Skan   (set_attr "mode" "XF")])
16393132727Skan
16394132727Skan(define_expand "logsf2"
16395169699Skan  [(set (match_dup 2)
16396169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16397169699Skan   (parallel [(set (match_dup 4)
16398169699Skan		   (unspec:XF [(match_dup 2)
16399169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16400169699Skan	      (clobber (match_scratch:XF 5 ""))])
16401169699Skan   (set (match_operand:SF 0 "register_operand" "")
16402169699Skan	(float_truncate:SF (match_dup 4)))]
16403169699Skan  "TARGET_USE_FANCY_MATH_387
16404169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16405132727Skan   && flag_unsafe_math_optimizations"
16406132727Skan{
16407132727Skan  rtx temp;
16408132727Skan
16409132727Skan  operands[2] = gen_reg_rtx (XFmode);
16410169699Skan  operands[3] = gen_reg_rtx (XFmode);
16411169699Skan  operands[4] = gen_reg_rtx (XFmode);
16412169699Skan
16413132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16414169699Skan  emit_move_insn (operands[3], temp);
16415132727Skan})
16416132727Skan
16417132727Skan(define_expand "logdf2"
16418169699Skan  [(set (match_dup 2)
16419169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16420169699Skan   (parallel [(set (match_dup 4)
16421169699Skan		   (unspec:XF [(match_dup 2)
16422169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16423169699Skan	      (clobber (match_scratch:XF 5 ""))])
16424169699Skan   (set (match_operand:DF 0 "register_operand" "")
16425169699Skan	(float_truncate:DF (match_dup 4)))]
16426169699Skan  "TARGET_USE_FANCY_MATH_387
16427169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16428132727Skan   && flag_unsafe_math_optimizations"
16429132727Skan{
16430132727Skan  rtx temp;
16431132727Skan
16432132727Skan  operands[2] = gen_reg_rtx (XFmode);
16433169699Skan  operands[3] = gen_reg_rtx (XFmode);
16434169699Skan  operands[4] = gen_reg_rtx (XFmode);
16435169699Skan
16436132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16437169699Skan  emit_move_insn (operands[3], temp);
16438132727Skan})
16439132727Skan
16440132727Skan(define_expand "logxf2"
16441132727Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16442132727Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16443132727Skan			       (match_dup 2)] UNSPEC_FYL2X))
16444132727Skan	      (clobber (match_scratch:XF 3 ""))])]
16445169699Skan  "TARGET_USE_FANCY_MATH_387
16446132727Skan   && flag_unsafe_math_optimizations"
16447132727Skan{
16448132727Skan  rtx temp;
16449132727Skan
16450132727Skan  operands[2] = gen_reg_rtx (XFmode);
16451132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16452132727Skan  emit_move_insn (operands[2], temp);
16453132727Skan})
16454132727Skan
16455169699Skan(define_expand "log10sf2"
16456169699Skan  [(set (match_dup 2)
16457169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16458169699Skan   (parallel [(set (match_dup 4)
16459169699Skan		   (unspec:XF [(match_dup 2)
16460169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16461169699Skan	      (clobber (match_scratch:XF 5 ""))])
16462169699Skan   (set (match_operand:SF 0 "register_operand" "")
16463169699Skan	(float_truncate:SF (match_dup 4)))]
16464169699Skan  "TARGET_USE_FANCY_MATH_387
16465169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16466132727Skan   && flag_unsafe_math_optimizations"
16467169699Skan{
16468169699Skan  rtx temp;
16469132727Skan
16470169699Skan  operands[2] = gen_reg_rtx (XFmode);
16471169699Skan  operands[3] = gen_reg_rtx (XFmode);
16472169699Skan  operands[4] = gen_reg_rtx (XFmode);
16473169699Skan
16474169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16475169699Skan  emit_move_insn (operands[3], temp);
16476169699Skan})
16477169699Skan
16478169699Skan(define_expand "log10df2"
16479169699Skan  [(set (match_dup 2)
16480169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16481169699Skan   (parallel [(set (match_dup 4)
16482169699Skan		   (unspec:XF [(match_dup 2)
16483169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16484169699Skan	      (clobber (match_scratch:XF 5 ""))])
16485169699Skan   (set (match_operand:DF 0 "register_operand" "")
16486169699Skan	(float_truncate:DF (match_dup 4)))]
16487169699Skan  "TARGET_USE_FANCY_MATH_387
16488169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16489132727Skan   && flag_unsafe_math_optimizations"
16490169699Skan{
16491169699Skan  rtx temp;
16492132727Skan
16493169699Skan  operands[2] = gen_reg_rtx (XFmode);
16494169699Skan  operands[3] = gen_reg_rtx (XFmode);
16495169699Skan  operands[4] = gen_reg_rtx (XFmode);
16496169699Skan
16497169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16498169699Skan  emit_move_insn (operands[3], temp);
16499169699Skan})
16500169699Skan
16501169699Skan(define_expand "log10xf2"
16502169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16503169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16504169699Skan			       (match_dup 2)] UNSPEC_FYL2X))
16505169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16506169699Skan  "TARGET_USE_FANCY_MATH_387
16507169699Skan   && flag_unsafe_math_optimizations"
16508169699Skan{
16509169699Skan  rtx temp;
16510169699Skan
16511169699Skan  operands[2] = gen_reg_rtx (XFmode);
16512169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16513169699Skan  emit_move_insn (operands[2], temp);
16514169699Skan})
16515169699Skan
16516169699Skan(define_expand "log2sf2"
16517169699Skan  [(set (match_dup 2)
16518169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16519169699Skan   (parallel [(set (match_dup 4)
16520169699Skan		   (unspec:XF [(match_dup 2)
16521169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16522169699Skan	      (clobber (match_scratch:XF 5 ""))])
16523169699Skan   (set (match_operand:SF 0 "register_operand" "")
16524169699Skan	(float_truncate:SF (match_dup 4)))]
16525169699Skan  "TARGET_USE_FANCY_MATH_387
16526169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16527169699Skan   && flag_unsafe_math_optimizations"
16528169699Skan{
16529169699Skan  operands[2] = gen_reg_rtx (XFmode);
16530169699Skan  operands[3] = gen_reg_rtx (XFmode);
16531169699Skan  operands[4] = gen_reg_rtx (XFmode);
16532169699Skan
16533169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16534169699Skan})
16535169699Skan
16536169699Skan(define_expand "log2df2"
16537169699Skan  [(set (match_dup 2)
16538169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16539169699Skan   (parallel [(set (match_dup 4)
16540169699Skan		   (unspec:XF [(match_dup 2)
16541169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16542169699Skan	      (clobber (match_scratch:XF 5 ""))])
16543169699Skan   (set (match_operand:DF 0 "register_operand" "")
16544169699Skan	(float_truncate:DF (match_dup 4)))]
16545169699Skan  "TARGET_USE_FANCY_MATH_387
16546169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16547169699Skan   && flag_unsafe_math_optimizations"
16548169699Skan{
16549169699Skan  operands[2] = gen_reg_rtx (XFmode);
16550169699Skan  operands[3] = gen_reg_rtx (XFmode);
16551169699Skan  operands[4] = gen_reg_rtx (XFmode);
16552169699Skan
16553169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16554169699Skan})
16555169699Skan
16556169699Skan(define_expand "log2xf2"
16557169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16558169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16559169699Skan			       (match_dup 2)] UNSPEC_FYL2X))
16560169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16561169699Skan  "TARGET_USE_FANCY_MATH_387
16562169699Skan   && flag_unsafe_math_optimizations"
16563169699Skan{
16564169699Skan  operands[2] = gen_reg_rtx (XFmode);
16565169699Skan  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
16566169699Skan})
16567169699Skan
16568169699Skan(define_insn "fyl2xp1_xf3"
16569132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16570169699Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16571132727Skan		    (match_operand:XF 1 "register_operand" "u")]
16572169699Skan	           UNSPEC_FYL2XP1))
16573132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16574169699Skan  "TARGET_USE_FANCY_MATH_387
16575132727Skan   && flag_unsafe_math_optimizations"
16576169699Skan  "fyl2xp1"
16577132727Skan  [(set_attr "type" "fpspc")
16578132727Skan   (set_attr "mode" "XF")])
16579132727Skan
16580169699Skan(define_expand "log1psf2"
16581169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
16582169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
16583169699Skan  "TARGET_USE_FANCY_MATH_387
16584169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16585169699Skan   && flag_unsafe_math_optimizations"
16586169699Skan{
16587169699Skan  rtx op0 = gen_reg_rtx (XFmode);
16588169699Skan  rtx op1 = gen_reg_rtx (XFmode);
16589169699Skan
16590169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
16591169699Skan  ix86_emit_i387_log1p (op0, op1);
16592169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
16593169699Skan  DONE;
16594169699Skan})
16595169699Skan
16596169699Skan(define_expand "log1pdf2"
16597169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
16598169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
16599169699Skan  "TARGET_USE_FANCY_MATH_387
16600169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16601169699Skan   && flag_unsafe_math_optimizations"
16602169699Skan{
16603169699Skan  rtx op0 = gen_reg_rtx (XFmode);
16604169699Skan  rtx op1 = gen_reg_rtx (XFmode);
16605169699Skan
16606169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
16607169699Skan  ix86_emit_i387_log1p (op0, op1);
16608169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
16609169699Skan  DONE;
16610169699Skan})
16611169699Skan
16612169699Skan(define_expand "log1pxf2"
16613169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
16614169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
16615169699Skan  "TARGET_USE_FANCY_MATH_387
16616169699Skan   && flag_unsafe_math_optimizations"
16617169699Skan{
16618169699Skan  ix86_emit_i387_log1p (operands[0], operands[1]);
16619169699Skan  DONE;
16620169699Skan})
16621169699Skan
16622169699Skan(define_insn "*fxtractxf3"
16623132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16624169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
16625169699Skan		   UNSPEC_XTRACT_FRACT))
16626169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16627169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))]
16628169699Skan  "TARGET_USE_FANCY_MATH_387
16629132727Skan   && flag_unsafe_math_optimizations"
16630169699Skan  "fxtract"
16631132727Skan  [(set_attr "type" "fpspc")
16632132727Skan   (set_attr "mode" "XF")])
16633132727Skan
16634169699Skan(define_expand "logbsf2"
16635169699Skan  [(set (match_dup 2)
16636169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16637169699Skan   (parallel [(set (match_dup 3)
16638169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
16639169699Skan	      (set (match_dup 4)
16640169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
16641169699Skan   (set (match_operand:SF 0 "register_operand" "")
16642169699Skan	(float_truncate:SF (match_dup 4)))]
16643169699Skan  "TARGET_USE_FANCY_MATH_387
16644169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16645169699Skan   && flag_unsafe_math_optimizations"
16646169699Skan{
16647169699Skan  operands[2] = gen_reg_rtx (XFmode);
16648169699Skan  operands[3] = gen_reg_rtx (XFmode);
16649169699Skan  operands[4] = gen_reg_rtx (XFmode);
16650169699Skan})
16651169699Skan
16652169699Skan(define_expand "logbdf2"
16653169699Skan  [(set (match_dup 2)
16654169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16655169699Skan   (parallel [(set (match_dup 3)
16656169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
16657169699Skan	      (set (match_dup 4)
16658169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
16659169699Skan   (set (match_operand:DF 0 "register_operand" "")
16660169699Skan	(float_truncate:DF (match_dup 4)))]
16661169699Skan  "TARGET_USE_FANCY_MATH_387
16662169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16663169699Skan   && flag_unsafe_math_optimizations"
16664169699Skan{
16665169699Skan  operands[2] = gen_reg_rtx (XFmode);
16666169699Skan  operands[3] = gen_reg_rtx (XFmode);
16667169699Skan  operands[4] = gen_reg_rtx (XFmode);
16668169699Skan})
16669169699Skan
16670169699Skan(define_expand "logbxf2"
16671169699Skan  [(parallel [(set (match_dup 2)
16672169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16673169699Skan			      UNSPEC_XTRACT_FRACT))
16674169699Skan	      (set (match_operand:XF 0 "register_operand" "")
16675169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])]
16676169699Skan  "TARGET_USE_FANCY_MATH_387
16677169699Skan   && flag_unsafe_math_optimizations"
16678169699Skan{
16679169699Skan  operands[2] = gen_reg_rtx (XFmode);
16680169699Skan})
16681169699Skan
16682169699Skan(define_expand "ilogbsi2"
16683169699Skan  [(parallel [(set (match_dup 2)
16684169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16685169699Skan			      UNSPEC_XTRACT_FRACT))
16686169699Skan	      (set (match_operand:XF 3 "register_operand" "")
16687169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])
16688169699Skan   (parallel [(set (match_operand:SI 0 "register_operand" "")
16689169699Skan	           (fix:SI (match_dup 3)))
16690169699Skan	      (clobber (reg:CC FLAGS_REG))])]
16691169699Skan  "TARGET_USE_FANCY_MATH_387
16692169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16693169699Skan   && flag_unsafe_math_optimizations"
16694169699Skan{
16695169699Skan  operands[2] = gen_reg_rtx (XFmode);
16696169699Skan  operands[3] = gen_reg_rtx (XFmode);
16697169699Skan})
16698169699Skan
16699132727Skan(define_insn "*f2xm1xf2"
16700132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16701132727Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
16702132727Skan	 UNSPEC_F2XM1))]
16703169699Skan  "TARGET_USE_FANCY_MATH_387
16704132727Skan   && flag_unsafe_math_optimizations"
16705132727Skan  "f2xm1"
16706132727Skan  [(set_attr "type" "fpspc")
16707132727Skan   (set_attr "mode" "XF")])
16708132727Skan
16709169699Skan(define_insn "*fscalexf4"
16710169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16711169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
16712169699Skan		    (match_operand:XF 3 "register_operand" "1")]
16713169699Skan		   UNSPEC_FSCALE_FRACT))
16714169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16715169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
16716169699Skan		   UNSPEC_FSCALE_EXP))]
16717169699Skan  "TARGET_USE_FANCY_MATH_387
16718169699Skan   && flag_unsafe_math_optimizations"
16719169699Skan  "fscale"
16720169699Skan  [(set_attr "type" "fpspc")
16721169699Skan   (set_attr "mode" "XF")])
16722169699Skan
16723132727Skan(define_expand "expsf2"
16724132727Skan  [(set (match_dup 2)
16725132727Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16726132727Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16727132727Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16728132727Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16729132727Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16730132727Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16731169699Skan   (parallel [(set (match_dup 10)
16732169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16733169699Skan			      UNSPEC_FSCALE_FRACT))
16734169699Skan	      (set (match_dup 11)
16735169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16736169699Skan			      UNSPEC_FSCALE_EXP))])
16737169699Skan   (set (match_operand:SF 0 "register_operand" "")
16738169699Skan	(float_truncate:SF (match_dup 10)))]
16739169699Skan  "TARGET_USE_FANCY_MATH_387
16740169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16741132727Skan   && flag_unsafe_math_optimizations"
16742132727Skan{
16743132727Skan  rtx temp;
16744132727Skan  int i;
16745132727Skan
16746169699Skan  for (i=2; i<12; i++)
16747132727Skan    operands[i] = gen_reg_rtx (XFmode);
16748132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
16749132727Skan  emit_move_insn (operands[3], temp);
16750132727Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16751132727Skan})
16752132727Skan
16753132727Skan(define_expand "expdf2"
16754132727Skan  [(set (match_dup 2)
16755132727Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16756132727Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16757132727Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16758132727Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16759132727Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16760132727Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16761169699Skan   (parallel [(set (match_dup 10)
16762169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16763169699Skan			      UNSPEC_FSCALE_FRACT))
16764169699Skan	      (set (match_dup 11)
16765169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16766169699Skan			      UNSPEC_FSCALE_EXP))])
16767169699Skan   (set (match_operand:DF 0 "register_operand" "")
16768169699Skan	(float_truncate:DF (match_dup 10)))]
16769169699Skan  "TARGET_USE_FANCY_MATH_387
16770169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16771132727Skan   && flag_unsafe_math_optimizations"
16772132727Skan{
16773132727Skan  rtx temp;
16774132727Skan  int i;
16775132727Skan
16776169699Skan  for (i=2; i<12; i++)
16777132727Skan    operands[i] = gen_reg_rtx (XFmode);
16778132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
16779132727Skan  emit_move_insn (operands[3], temp);
16780132727Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16781132727Skan})
16782132727Skan
16783132727Skan(define_expand "expxf2"
16784132727Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
16785132727Skan			       (match_dup 2)))
16786132727Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
16787132727Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
16788132727Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
16789132727Skan   (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
16790132727Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16791169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16792169699Skan			      UNSPEC_FSCALE_FRACT))
16793169699Skan	      (set (match_dup 9)
16794169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16795169699Skan			      UNSPEC_FSCALE_EXP))])]
16796169699Skan  "TARGET_USE_FANCY_MATH_387
16797132727Skan   && flag_unsafe_math_optimizations"
16798132727Skan{
16799132727Skan  rtx temp;
16800132727Skan  int i;
16801132727Skan
16802169699Skan  for (i=2; i<10; i++)
16803132727Skan    operands[i] = gen_reg_rtx (XFmode);
16804132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
16805132727Skan  emit_move_insn (operands[2], temp);
16806132727Skan  emit_move_insn (operands[7], CONST1_RTX (XFmode));  /* fld1 */
16807132727Skan})
16808132727Skan
16809169699Skan(define_expand "exp10sf2"
16810169699Skan  [(set (match_dup 2)
16811169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16812169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16813169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16814169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16815169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16816169699Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16817169699Skan   (parallel [(set (match_dup 10)
16818169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16819169699Skan			      UNSPEC_FSCALE_FRACT))
16820169699Skan	      (set (match_dup 11)
16821169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16822169699Skan			      UNSPEC_FSCALE_EXP))])
16823169699Skan   (set (match_operand:SF 0 "register_operand" "")
16824169699Skan	(float_truncate:SF (match_dup 10)))]
16825169699Skan  "TARGET_USE_FANCY_MATH_387
16826169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16827132727Skan   && flag_unsafe_math_optimizations"
16828132727Skan{
16829169699Skan  rtx temp;
16830169699Skan  int i;
16831169699Skan
16832169699Skan  for (i=2; i<12; i++)
16833169699Skan    operands[i] = gen_reg_rtx (XFmode);
16834169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
16835169699Skan  emit_move_insn (operands[3], temp);
16836169699Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16837132727Skan})
16838132727Skan
16839169699Skan(define_expand "exp10df2"
16840169699Skan  [(set (match_dup 2)
16841169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16842169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16843169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16844169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16845169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16846169699Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16847169699Skan   (parallel [(set (match_dup 10)
16848169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16849169699Skan			      UNSPEC_FSCALE_FRACT))
16850169699Skan	      (set (match_dup 11)
16851169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16852169699Skan			      UNSPEC_FSCALE_EXP))])
16853169699Skan   (set (match_operand:DF 0 "register_operand" "")
16854169699Skan	(float_truncate:DF (match_dup 10)))]
16855169699Skan  "TARGET_USE_FANCY_MATH_387
16856169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16857132727Skan   && flag_unsafe_math_optimizations"
16858132727Skan{
16859169699Skan  rtx temp;
16860169699Skan  int i;
16861169699Skan
16862169699Skan  for (i=2; i<12; i++)
16863169699Skan    operands[i] = gen_reg_rtx (XFmode);
16864169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
16865169699Skan  emit_move_insn (operands[3], temp);
16866169699Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16867132727Skan})
16868132727Skan
16869169699Skan(define_expand "exp10xf2"
16870169699Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
16871169699Skan			       (match_dup 2)))
16872169699Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
16873169699Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
16874169699Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
16875169699Skan   (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
16876169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16877169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16878169699Skan			      UNSPEC_FSCALE_FRACT))
16879169699Skan	      (set (match_dup 9)
16880169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16881169699Skan			      UNSPEC_FSCALE_EXP))])]
16882169699Skan  "TARGET_USE_FANCY_MATH_387
16883132727Skan   && flag_unsafe_math_optimizations"
16884132727Skan{
16885169699Skan  rtx temp;
16886169699Skan  int i;
16887169699Skan
16888169699Skan  for (i=2; i<10; i++)
16889169699Skan    operands[i] = gen_reg_rtx (XFmode);
16890169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
16891169699Skan  emit_move_insn (operands[2], temp);
16892169699Skan  emit_move_insn (operands[7], CONST1_RTX (XFmode));  /* fld1 */
16893132727Skan})
16894169699Skan
16895169699Skan(define_expand "exp2sf2"
16896169699Skan  [(set (match_dup 2)
16897169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16898169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
16899169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
16900169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
16901169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
16902169699Skan   (parallel [(set (match_dup 8)
16903169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16904169699Skan			      UNSPEC_FSCALE_FRACT))
16905169699Skan	      (set (match_dup 9)
16906169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16907169699Skan			      UNSPEC_FSCALE_EXP))])
16908169699Skan   (set (match_operand:SF 0 "register_operand" "")
16909169699Skan	(float_truncate:SF (match_dup 8)))]
16910169699Skan  "TARGET_USE_FANCY_MATH_387
16911169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16912169699Skan   && flag_unsafe_math_optimizations"
16913169699Skan{
16914169699Skan  int i;
16915169699Skan
16916169699Skan  for (i=2; i<10; i++)
16917169699Skan    operands[i] = gen_reg_rtx (XFmode);
16918169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
16919169699Skan})
16920169699Skan
16921169699Skan(define_expand "exp2df2"
16922169699Skan  [(set (match_dup 2)
16923169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16924169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
16925169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
16926169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
16927169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
16928169699Skan   (parallel [(set (match_dup 8)
16929169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16930169699Skan			      UNSPEC_FSCALE_FRACT))
16931169699Skan	      (set (match_dup 9)
16932169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16933169699Skan			      UNSPEC_FSCALE_EXP))])
16934169699Skan   (set (match_operand:DF 0 "register_operand" "")
16935169699Skan	(float_truncate:DF (match_dup 8)))]
16936169699Skan  "TARGET_USE_FANCY_MATH_387
16937169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16938169699Skan   && flag_unsafe_math_optimizations"
16939169699Skan{
16940169699Skan  int i;
16941169699Skan
16942169699Skan  for (i=2; i<10; i++)
16943169699Skan    operands[i] = gen_reg_rtx (XFmode);
16944169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
16945169699Skan})
16946169699Skan
16947169699Skan(define_expand "exp2xf2"
16948169699Skan  [(set (match_dup 2) (match_operand:XF 1 "register_operand" ""))
16949169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
16950169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
16951169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
16952169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
16953169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16954169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16955169699Skan			      UNSPEC_FSCALE_FRACT))
16956169699Skan	      (set (match_dup 8)
16957169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16958169699Skan			      UNSPEC_FSCALE_EXP))])]
16959169699Skan  "TARGET_USE_FANCY_MATH_387
16960169699Skan   && flag_unsafe_math_optimizations"
16961169699Skan{
16962169699Skan  int i;
16963169699Skan
16964169699Skan  for (i=2; i<9; i++)
16965169699Skan    operands[i] = gen_reg_rtx (XFmode);
16966169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
16967169699Skan})
16968169699Skan
16969169699Skan(define_expand "expm1df2"
16970169699Skan  [(set (match_dup 2)
16971169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16972169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16973169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16974169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16975169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16976169699Skan   (parallel [(set (match_dup 8)
16977169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
16978169699Skan			      UNSPEC_FSCALE_FRACT))
16979169699Skan		   (set (match_dup 9)
16980169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
16981169699Skan			      UNSPEC_FSCALE_EXP))])
16982169699Skan   (parallel [(set (match_dup 11)
16983169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
16984169699Skan			      UNSPEC_FSCALE_FRACT))
16985169699Skan	      (set (match_dup 12)
16986169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
16987169699Skan			      UNSPEC_FSCALE_EXP))])
16988169699Skan   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
16989169699Skan   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
16990169699Skan   (set (match_operand:DF 0 "register_operand" "")
16991169699Skan	(float_truncate:DF (match_dup 14)))]
16992169699Skan  "TARGET_USE_FANCY_MATH_387
16993169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16994169699Skan   && flag_unsafe_math_optimizations"
16995169699Skan{
16996169699Skan  rtx temp;
16997169699Skan  int i;
16998169699Skan
16999169699Skan  for (i=2; i<15; i++)
17000169699Skan    operands[i] = gen_reg_rtx (XFmode);
17001169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17002169699Skan  emit_move_insn (operands[3], temp);
17003169699Skan  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
17004169699Skan})
17005169699Skan
17006169699Skan(define_expand "expm1sf2"
17007169699Skan  [(set (match_dup 2)
17008169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17009169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
17010169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
17011169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
17012169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
17013169699Skan   (parallel [(set (match_dup 8)
17014169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17015169699Skan			      UNSPEC_FSCALE_FRACT))
17016169699Skan		   (set (match_dup 9)
17017169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17018169699Skan			      UNSPEC_FSCALE_EXP))])
17019169699Skan   (parallel [(set (match_dup 11)
17020169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17021169699Skan			      UNSPEC_FSCALE_FRACT))
17022169699Skan	      (set (match_dup 12)
17023169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17024169699Skan			      UNSPEC_FSCALE_EXP))])
17025169699Skan   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
17026169699Skan   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
17027169699Skan   (set (match_operand:SF 0 "register_operand" "")
17028169699Skan	(float_truncate:SF (match_dup 14)))]
17029169699Skan  "TARGET_USE_FANCY_MATH_387
17030169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17031169699Skan   && flag_unsafe_math_optimizations"
17032169699Skan{
17033169699Skan  rtx temp;
17034169699Skan  int i;
17035169699Skan
17036169699Skan  for (i=2; i<15; i++)
17037169699Skan    operands[i] = gen_reg_rtx (XFmode);
17038169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17039169699Skan  emit_move_insn (operands[3], temp);
17040169699Skan  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
17041169699Skan})
17042169699Skan
17043169699Skan(define_expand "expm1xf2"
17044169699Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
17045169699Skan			       (match_dup 2)))
17046169699Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
17047169699Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
17048169699Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
17049169699Skan   (parallel [(set (match_dup 7)
17050169699Skan		   (unspec:XF [(match_dup 6) (match_dup 4)]
17051169699Skan			      UNSPEC_FSCALE_FRACT))
17052169699Skan		   (set (match_dup 8)
17053169699Skan		   (unspec:XF [(match_dup 6) (match_dup 4)]
17054169699Skan			      UNSPEC_FSCALE_EXP))])
17055169699Skan   (parallel [(set (match_dup 10)
17056169699Skan		   (unspec:XF [(match_dup 9) (match_dup 8)]
17057169699Skan			      UNSPEC_FSCALE_FRACT))
17058169699Skan	      (set (match_dup 11)
17059169699Skan		   (unspec:XF [(match_dup 9) (match_dup 8)]
17060169699Skan			      UNSPEC_FSCALE_EXP))])
17061169699Skan   (set (match_dup 12) (minus:XF (match_dup 10) (match_dup 9)))
17062169699Skan   (set (match_operand:XF 0 "register_operand" "")
17063169699Skan	(plus:XF (match_dup 12) (match_dup 7)))]
17064169699Skan  "TARGET_USE_FANCY_MATH_387
17065169699Skan   && flag_unsafe_math_optimizations"
17066169699Skan{
17067169699Skan  rtx temp;
17068169699Skan  int i;
17069169699Skan
17070169699Skan  for (i=2; i<13; i++)
17071169699Skan    operands[i] = gen_reg_rtx (XFmode);
17072169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17073169699Skan  emit_move_insn (operands[2], temp);
17074169699Skan  emit_move_insn (operands[9], CONST1_RTX (XFmode));  /* fld1 */
17075169699Skan})
17076169699Skan
17077169699Skan(define_expand "ldexpdf3"
17078169699Skan  [(set (match_dup 3)
17079169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
17080169699Skan   (set (match_dup 4)
17081169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17082169699Skan   (parallel [(set (match_dup 5)
17083169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17084169699Skan			      UNSPEC_FSCALE_FRACT))
17085169699Skan	      (set (match_dup 6)
17086169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17087169699Skan			      UNSPEC_FSCALE_EXP))])
17088169699Skan   (set (match_operand:DF 0 "register_operand" "")
17089169699Skan	(float_truncate:DF (match_dup 5)))]
17090169699Skan  "TARGET_USE_FANCY_MATH_387
17091169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17092169699Skan   && flag_unsafe_math_optimizations"
17093169699Skan{
17094169699Skan  int i;
17095169699Skan
17096169699Skan  for (i=3; i<7; i++)
17097169699Skan    operands[i] = gen_reg_rtx (XFmode);
17098169699Skan})
17099169699Skan
17100169699Skan(define_expand "ldexpsf3"
17101169699Skan  [(set (match_dup 3)
17102169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17103169699Skan   (set (match_dup 4)
17104169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17105169699Skan   (parallel [(set (match_dup 5)
17106169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17107169699Skan			      UNSPEC_FSCALE_FRACT))
17108169699Skan	      (set (match_dup 6)
17109169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17110169699Skan			      UNSPEC_FSCALE_EXP))])
17111169699Skan   (set (match_operand:SF 0 "register_operand" "")
17112169699Skan	(float_truncate:SF (match_dup 5)))]
17113169699Skan  "TARGET_USE_FANCY_MATH_387
17114169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17115169699Skan   && flag_unsafe_math_optimizations"
17116169699Skan{
17117169699Skan  int i;
17118169699Skan
17119169699Skan  for (i=3; i<7; i++)
17120169699Skan    operands[i] = gen_reg_rtx (XFmode);
17121169699Skan})
17122169699Skan
17123169699Skan(define_expand "ldexpxf3"
17124169699Skan  [(set (match_dup 3)
17125169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17126169699Skan   (parallel [(set (match_operand:XF 0 " register_operand" "")
17127169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
17128169699Skan			       (match_dup 3)]
17129169699Skan			      UNSPEC_FSCALE_FRACT))
17130169699Skan	      (set (match_dup 4)
17131169699Skan		   (unspec:XF [(match_dup 1) (match_dup 3)]
17132169699Skan			      UNSPEC_FSCALE_EXP))])]
17133169699Skan  "TARGET_USE_FANCY_MATH_387
17134169699Skan   && flag_unsafe_math_optimizations"
17135169699Skan{
17136169699Skan  int i;
17137169699Skan
17138169699Skan  for (i=3; i<5; i++)
17139169699Skan    operands[i] = gen_reg_rtx (XFmode);
17140169699Skan})
1714190286Sobrien
17142169699Skan
17143169699Skan(define_insn "frndintxf2"
17144169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17145169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17146169699Skan	 UNSPEC_FRNDINT))]
17147169699Skan  "TARGET_USE_FANCY_MATH_387
17148169699Skan   && flag_unsafe_math_optimizations"
17149169699Skan  "frndint"
17150169699Skan  [(set_attr "type" "fpspc")
17151169699Skan   (set_attr "mode" "XF")])
17152169699Skan
17153169699Skan(define_expand "rintdf2"
17154169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17155169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17156169699Skan  "TARGET_USE_FANCY_MATH_387
17157169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17158169699Skan   && flag_unsafe_math_optimizations"
17159169699Skan{
17160169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17161169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17162169699Skan
17163169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17164169699Skan  emit_insn (gen_frndintxf2 (op0, op1));
17165169699Skan
17166169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17167169699Skan  DONE;
17168169699Skan})
17169169699Skan
17170169699Skan(define_expand "rintsf2"
17171169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17172169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17173169699Skan  "TARGET_USE_FANCY_MATH_387
17174169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17175169699Skan   && flag_unsafe_math_optimizations"
17176169699Skan{
17177169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17178169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17179169699Skan
17180169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17181169699Skan  emit_insn (gen_frndintxf2 (op0, op1));
17182169699Skan
17183169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17184169699Skan  DONE;
17185169699Skan})
17186169699Skan
17187169699Skan(define_expand "rintxf2"
17188169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17189169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17190169699Skan  "TARGET_USE_FANCY_MATH_387
17191169699Skan   && flag_unsafe_math_optimizations"
17192169699Skan{
17193169699Skan  emit_insn (gen_frndintxf2 (operands[0], operands[1]));
17194169699Skan  DONE;
17195169699Skan})
17196169699Skan
17197169699Skan(define_insn_and_split "*fistdi2_1"
17198169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17199169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17200169699Skan	 UNSPEC_FIST))]
17201169699Skan  "TARGET_USE_FANCY_MATH_387
17202169699Skan   && flag_unsafe_math_optimizations
17203169699Skan   && !(reload_completed || reload_in_progress)"
17204169699Skan  "#"
17205169699Skan  "&& 1"
17206169699Skan  [(const_int 0)]
17207169699Skan{
17208169699Skan  if (memory_operand (operands[0], VOIDmode))
17209169699Skan    emit_insn (gen_fistdi2 (operands[0], operands[1]));
17210169699Skan  else
17211169699Skan    {
17212169699Skan      operands[2] = assign_386_stack_local (DImode, SLOT_TEMP);
17213169699Skan      emit_insn (gen_fistdi2_with_temp (operands[0], operands[1],
17214169699Skan					 operands[2]));
17215169699Skan    }
17216169699Skan  DONE;
17217169699Skan}
17218169699Skan  [(set_attr "type" "fpspc")
17219169699Skan   (set_attr "mode" "DI")])
17220169699Skan
17221169699Skan(define_insn "fistdi2"
17222169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17223169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17224169699Skan	 UNSPEC_FIST))
17225169699Skan   (clobber (match_scratch:XF 2 "=&1f"))]
17226169699Skan  "TARGET_USE_FANCY_MATH_387
17227169699Skan   && flag_unsafe_math_optimizations"
17228169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17229169699Skan  [(set_attr "type" "fpspc")
17230169699Skan   (set_attr "mode" "DI")])
17231169699Skan
17232169699Skan(define_insn "fistdi2_with_temp"
17233169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17234169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17235169699Skan	 UNSPEC_FIST))
17236169699Skan   (clobber (match_operand:DI 2 "memory_operand" "=m,m"))
17237169699Skan   (clobber (match_scratch:XF 3 "=&1f,&1f"))]
17238169699Skan  "TARGET_USE_FANCY_MATH_387
17239169699Skan   && flag_unsafe_math_optimizations"
17240169699Skan  "#"
17241169699Skan  [(set_attr "type" "fpspc")
17242169699Skan   (set_attr "mode" "DI")])
17243169699Skan
17244169699Skan(define_split 
17245169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17246169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17247169699Skan	 UNSPEC_FIST))
17248169699Skan   (clobber (match_operand:DI 2 "memory_operand" ""))
17249169699Skan   (clobber (match_scratch 3 ""))]
17250169699Skan  "reload_completed"
17251169699Skan  [(parallel [(set (match_dup 2) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
17252169699Skan	      (clobber (match_dup 3))])
17253169699Skan   (set (match_dup 0) (match_dup 2))]
17254169699Skan  "")
17255169699Skan
17256169699Skan(define_split 
17257169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17258169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17259169699Skan	 UNSPEC_FIST))
17260169699Skan   (clobber (match_operand:DI 2 "memory_operand" ""))
17261169699Skan   (clobber (match_scratch 3 ""))]
17262169699Skan  "reload_completed"
17263169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
17264169699Skan	      (clobber (match_dup 3))])]
17265169699Skan  "")
17266169699Skan
17267169699Skan(define_insn_and_split "*fist<mode>2_1"
17268169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
17269169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17270169699Skan	 UNSPEC_FIST))]
17271169699Skan  "TARGET_USE_FANCY_MATH_387
17272169699Skan   && flag_unsafe_math_optimizations
17273169699Skan   && !(reload_completed || reload_in_progress)"
17274169699Skan  "#"
17275169699Skan  "&& 1"
17276169699Skan  [(const_int 0)]
17277169699Skan{
17278169699Skan  operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17279169699Skan  emit_insn (gen_fist<mode>2_with_temp (operands[0], operands[1],
17280169699Skan					operands[2]));
17281169699Skan  DONE;
17282169699Skan}
17283169699Skan  [(set_attr "type" "fpspc")
17284169699Skan   (set_attr "mode" "<MODE>")])
17285169699Skan
17286169699Skan(define_insn "fist<mode>2"
17287169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17288169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17289169699Skan	 UNSPEC_FIST))]
17290169699Skan  "TARGET_USE_FANCY_MATH_387
17291169699Skan   && flag_unsafe_math_optimizations"
17292169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17293169699Skan  [(set_attr "type" "fpspc")
17294169699Skan   (set_attr "mode" "<MODE>")])
17295169699Skan
17296169699Skan(define_insn "fist<mode>2_with_temp"
17297169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
17298169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17299169699Skan	 UNSPEC_FIST))
17300169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" "=m"))]
17301169699Skan  "TARGET_USE_FANCY_MATH_387
17302169699Skan   && flag_unsafe_math_optimizations"
17303169699Skan  "#"
17304169699Skan  [(set_attr "type" "fpspc")
17305169699Skan   (set_attr "mode" "<MODE>")])
17306169699Skan
17307169699Skan(define_split 
17308169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17309169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17310169699Skan	 UNSPEC_FIST))
17311169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
17312169699Skan  "reload_completed"
17313169699Skan  [(set (match_dup 2) (unspec:X87MODEI12 [(match_dup 1)]
17314169699Skan		       UNSPEC_FIST))
17315169699Skan   (set (match_dup 0) (match_dup 2))]
17316169699Skan  "")
17317169699Skan
17318169699Skan(define_split 
17319169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17320169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17321169699Skan	 UNSPEC_FIST))
17322169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
17323169699Skan  "reload_completed"
17324169699Skan  [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17325169699Skan		       UNSPEC_FIST))]
17326169699Skan  "")
17327169699Skan
17328169699Skan(define_expand "lrint<mode>2"
17329169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17330169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17331169699Skan	 UNSPEC_FIST))]
17332169699Skan  "TARGET_USE_FANCY_MATH_387
17333169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17334169699Skan   && flag_unsafe_math_optimizations"
17335169699Skan  "")
17336169699Skan
17337169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17338169699Skan(define_insn_and_split "frndintxf2_floor"
17339169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17340169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17341169699Skan	 UNSPEC_FRNDINT_FLOOR))
17342169699Skan   (clobber (reg:CC FLAGS_REG))]
17343169699Skan  "TARGET_USE_FANCY_MATH_387
17344169699Skan   && flag_unsafe_math_optimizations
17345169699Skan   && !(reload_completed || reload_in_progress)"
17346169699Skan  "#"
17347169699Skan  "&& 1"
17348169699Skan  [(const_int 0)]
17349169699Skan{
17350169699Skan  ix86_optimize_mode_switching[I387_FLOOR] = 1;
17351169699Skan
17352169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17353169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
17354169699Skan
17355169699Skan  emit_insn (gen_frndintxf2_floor_i387 (operands[0], operands[1],
17356169699Skan					operands[2], operands[3]));
17357169699Skan  DONE;
17358169699Skan}
17359169699Skan  [(set_attr "type" "frndint")
17360169699Skan   (set_attr "i387_cw" "floor")
17361169699Skan   (set_attr "mode" "XF")])
17362169699Skan
17363169699Skan(define_insn "frndintxf2_floor_i387"
17364169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17365169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17366169699Skan	 UNSPEC_FRNDINT_FLOOR))
17367169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17368169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17369169699Skan  "TARGET_USE_FANCY_MATH_387
17370169699Skan   && flag_unsafe_math_optimizations"
17371169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17372169699Skan  [(set_attr "type" "frndint")
17373169699Skan   (set_attr "i387_cw" "floor")
17374169699Skan   (set_attr "mode" "XF")])
17375169699Skan
17376169699Skan(define_expand "floorxf2"
17377169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17378169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17379169699Skan  "TARGET_USE_FANCY_MATH_387
17380169699Skan   && flag_unsafe_math_optimizations"
17381169699Skan{
17382169699Skan  emit_insn (gen_frndintxf2_floor (operands[0], operands[1]));
17383169699Skan  DONE;
17384169699Skan})
17385169699Skan
17386169699Skan(define_expand "floordf2"
17387169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17388169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17389169699Skan  "TARGET_USE_FANCY_MATH_387
17390169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17391169699Skan   && flag_unsafe_math_optimizations"
17392169699Skan{
17393169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17394169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17395169699Skan
17396169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17397169699Skan  emit_insn (gen_frndintxf2_floor (op0, op1));
17398169699Skan
17399169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17400169699Skan  DONE;
17401169699Skan})
17402169699Skan
17403169699Skan(define_expand "floorsf2"
17404169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17405169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17406169699Skan  "TARGET_USE_FANCY_MATH_387
17407169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17408169699Skan   && flag_unsafe_math_optimizations"
17409169699Skan{
17410169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17411169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17412169699Skan
17413169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17414169699Skan  emit_insn (gen_frndintxf2_floor (op0, op1));
17415169699Skan
17416169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17417169699Skan  DONE;
17418169699Skan})
17419169699Skan
17420169699Skan(define_insn_and_split "*fist<mode>2_floor_1"
17421169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
17422169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
17423169699Skan	 UNSPEC_FIST_FLOOR))
17424169699Skan   (clobber (reg:CC FLAGS_REG))]
17425169699Skan  "TARGET_USE_FANCY_MATH_387
17426169699Skan   && flag_unsafe_math_optimizations
17427169699Skan   && !(reload_completed || reload_in_progress)"
17428169699Skan  "#"
17429169699Skan  "&& 1"
17430169699Skan  [(const_int 0)]
17431169699Skan{
17432169699Skan  ix86_optimize_mode_switching[I387_FLOOR] = 1;
17433169699Skan
17434169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17435169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
17436169699Skan  if (memory_operand (operands[0], VOIDmode))
17437169699Skan    emit_insn (gen_fist<mode>2_floor (operands[0], operands[1],
17438169699Skan				      operands[2], operands[3]));
17439169699Skan  else
17440169699Skan    {
17441169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17442169699Skan      emit_insn (gen_fist<mode>2_floor_with_temp (operands[0], operands[1],
17443169699Skan						  operands[2], operands[3],
17444169699Skan						  operands[4]));
17445169699Skan    }
17446169699Skan  DONE;
17447169699Skan}
17448169699Skan  [(set_attr "type" "fistp")
17449169699Skan   (set_attr "i387_cw" "floor")
17450169699Skan   (set_attr "mode" "<MODE>")])
17451169699Skan
17452169699Skan(define_insn "fistdi2_floor"
17453169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17454169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17455169699Skan	 UNSPEC_FIST_FLOOR))
17456169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17457169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
17458169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
17459169699Skan  "TARGET_USE_FANCY_MATH_387
17460169699Skan   && flag_unsafe_math_optimizations"
17461169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17462169699Skan  [(set_attr "type" "fistp")
17463169699Skan   (set_attr "i387_cw" "floor")
17464169699Skan   (set_attr "mode" "DI")])
17465169699Skan
17466169699Skan(define_insn "fistdi2_floor_with_temp"
17467169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17468169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17469169699Skan	 UNSPEC_FIST_FLOOR))
17470169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17471169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17472169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
17473169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
17474169699Skan  "TARGET_USE_FANCY_MATH_387
17475169699Skan   && flag_unsafe_math_optimizations"
17476169699Skan  "#"
17477169699Skan  [(set_attr "type" "fistp")
17478169699Skan   (set_attr "i387_cw" "floor")
17479169699Skan   (set_attr "mode" "DI")])
17480169699Skan
17481169699Skan(define_split 
17482169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17483169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17484169699Skan	 UNSPEC_FIST_FLOOR))
17485169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17486169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17487169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17488169699Skan   (clobber (match_scratch 5 ""))]
17489169699Skan  "reload_completed"
17490169699Skan  [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
17491169699Skan	      (use (match_dup 2))
17492169699Skan	      (use (match_dup 3))
17493169699Skan	      (clobber (match_dup 5))])
17494169699Skan   (set (match_dup 0) (match_dup 4))]
17495169699Skan  "")
17496169699Skan
17497169699Skan(define_split 
17498169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17499169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17500169699Skan	 UNSPEC_FIST_FLOOR))
17501169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17502169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17503169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17504169699Skan   (clobber (match_scratch 5 ""))]
17505169699Skan  "reload_completed"
17506169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
17507169699Skan	      (use (match_dup 2))
17508169699Skan	      (use (match_dup 3))
17509169699Skan	      (clobber (match_dup 5))])]
17510169699Skan  "")
17511169699Skan
17512169699Skan(define_insn "fist<mode>2_floor"
17513169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17514169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17515169699Skan	 UNSPEC_FIST_FLOOR))
17516169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17517169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17518169699Skan  "TARGET_USE_FANCY_MATH_387
17519169699Skan   && flag_unsafe_math_optimizations"
17520169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17521169699Skan  [(set_attr "type" "fistp")
17522169699Skan   (set_attr "i387_cw" "floor")
17523169699Skan   (set_attr "mode" "<MODE>")])
17524169699Skan
17525169699Skan(define_insn "fist<mode>2_floor_with_temp"
17526169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
17527169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
17528169699Skan	 UNSPEC_FIST_FLOOR))
17529169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17530169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17531169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
17532169699Skan  "TARGET_USE_FANCY_MATH_387
17533169699Skan   && flag_unsafe_math_optimizations"
17534169699Skan  "#"
17535169699Skan  [(set_attr "type" "fistp")
17536169699Skan   (set_attr "i387_cw" "floor")
17537169699Skan   (set_attr "mode" "<MODE>")])
17538169699Skan
17539169699Skan(define_split 
17540169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17541169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17542169699Skan	 UNSPEC_FIST_FLOOR))
17543169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17544169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17545169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17546169699Skan  "reload_completed"
17547169699Skan  [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
17548169699Skan				  UNSPEC_FIST_FLOOR))
17549169699Skan	      (use (match_dup 2))
17550169699Skan	      (use (match_dup 3))])
17551169699Skan   (set (match_dup 0) (match_dup 4))]
17552169699Skan  "")
17553169699Skan
17554169699Skan(define_split 
17555169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17556169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17557169699Skan	 UNSPEC_FIST_FLOOR))
17558169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17559169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17560169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17561169699Skan  "reload_completed"
17562169699Skan  [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17563169699Skan				  UNSPEC_FIST_FLOOR))
17564169699Skan	      (use (match_dup 2))
17565169699Skan	      (use (match_dup 3))])]
17566169699Skan  "")
17567169699Skan
17568169699Skan(define_expand "lfloor<mode>2"
17569169699Skan  [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17570169699Skan		   (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17571169699Skan		    UNSPEC_FIST_FLOOR))
17572169699Skan	      (clobber (reg:CC FLAGS_REG))])]
17573169699Skan  "TARGET_USE_FANCY_MATH_387
17574169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17575169699Skan   && flag_unsafe_math_optimizations"
17576169699Skan  "")
17577169699Skan
17578169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17579169699Skan(define_insn_and_split "frndintxf2_ceil"
17580169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17581169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17582169699Skan	 UNSPEC_FRNDINT_CEIL))
17583169699Skan   (clobber (reg:CC FLAGS_REG))]
17584169699Skan  "TARGET_USE_FANCY_MATH_387
17585169699Skan   && flag_unsafe_math_optimizations
17586169699Skan   && !(reload_completed || reload_in_progress)"
17587169699Skan  "#"
17588169699Skan  "&& 1"
17589169699Skan  [(const_int 0)]
17590169699Skan{
17591169699Skan  ix86_optimize_mode_switching[I387_CEIL] = 1;
17592169699Skan
17593169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17594169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
17595169699Skan
17596169699Skan  emit_insn (gen_frndintxf2_ceil_i387 (operands[0], operands[1],
17597169699Skan				       operands[2], operands[3]));
17598169699Skan  DONE;
17599169699Skan}
17600169699Skan  [(set_attr "type" "frndint")
17601169699Skan   (set_attr "i387_cw" "ceil")
17602169699Skan   (set_attr "mode" "XF")])
17603169699Skan
17604169699Skan(define_insn "frndintxf2_ceil_i387"
17605169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17606169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17607169699Skan	 UNSPEC_FRNDINT_CEIL))
17608169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17609169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17610169699Skan  "TARGET_USE_FANCY_MATH_387
17611169699Skan   && flag_unsafe_math_optimizations"
17612169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17613169699Skan  [(set_attr "type" "frndint")
17614169699Skan   (set_attr "i387_cw" "ceil")
17615169699Skan   (set_attr "mode" "XF")])
17616169699Skan
17617169699Skan(define_expand "ceilxf2"
17618169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17619169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17620169699Skan  "TARGET_USE_FANCY_MATH_387
17621169699Skan   && flag_unsafe_math_optimizations"
17622169699Skan{
17623169699Skan  emit_insn (gen_frndintxf2_ceil (operands[0], operands[1]));
17624169699Skan  DONE;
17625169699Skan})
17626169699Skan
17627169699Skan(define_expand "ceildf2"
17628169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17629169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17630169699Skan  "TARGET_USE_FANCY_MATH_387
17631169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17632169699Skan   && flag_unsafe_math_optimizations"
17633169699Skan{
17634169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17635169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17636169699Skan
17637169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17638169699Skan  emit_insn (gen_frndintxf2_ceil (op0, op1));
17639169699Skan
17640169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17641169699Skan  DONE;
17642169699Skan})
17643169699Skan
17644169699Skan(define_expand "ceilsf2"
17645169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17646169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17647169699Skan  "TARGET_USE_FANCY_MATH_387
17648169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17649169699Skan   && flag_unsafe_math_optimizations"
17650169699Skan{
17651169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17652169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17653169699Skan
17654169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17655169699Skan  emit_insn (gen_frndintxf2_ceil (op0, op1));
17656169699Skan
17657169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17658169699Skan  DONE;
17659169699Skan})
17660169699Skan
17661169699Skan(define_insn_and_split "*fist<mode>2_ceil_1"
17662169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
17663169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
17664169699Skan	 UNSPEC_FIST_CEIL))
17665169699Skan   (clobber (reg:CC FLAGS_REG))]
17666169699Skan  "TARGET_USE_FANCY_MATH_387
17667169699Skan   && flag_unsafe_math_optimizations
17668169699Skan   && !(reload_completed || reload_in_progress)"
17669169699Skan  "#"
17670169699Skan  "&& 1"
17671169699Skan  [(const_int 0)]
17672169699Skan{
17673169699Skan  ix86_optimize_mode_switching[I387_CEIL] = 1;
17674169699Skan
17675169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17676169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
17677169699Skan  if (memory_operand (operands[0], VOIDmode))
17678169699Skan    emit_insn (gen_fist<mode>2_ceil (operands[0], operands[1],
17679169699Skan				     operands[2], operands[3]));
17680169699Skan  else
17681169699Skan    {
17682169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17683169699Skan      emit_insn (gen_fist<mode>2_ceil_with_temp (operands[0], operands[1],
17684169699Skan						 operands[2], operands[3],
17685169699Skan						 operands[4]));
17686169699Skan    }
17687169699Skan  DONE;
17688169699Skan}
17689169699Skan  [(set_attr "type" "fistp")
17690169699Skan   (set_attr "i387_cw" "ceil")
17691169699Skan   (set_attr "mode" "<MODE>")])
17692169699Skan
17693169699Skan(define_insn "fistdi2_ceil"
17694169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17695169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17696169699Skan	 UNSPEC_FIST_CEIL))
17697169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17698169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
17699169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
17700169699Skan  "TARGET_USE_FANCY_MATH_387
17701169699Skan   && flag_unsafe_math_optimizations"
17702169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17703169699Skan  [(set_attr "type" "fistp")
17704169699Skan   (set_attr "i387_cw" "ceil")
17705169699Skan   (set_attr "mode" "DI")])
17706169699Skan
17707169699Skan(define_insn "fistdi2_ceil_with_temp"
17708169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17709169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17710169699Skan	 UNSPEC_FIST_CEIL))
17711169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17712169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17713169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
17714169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
17715169699Skan  "TARGET_USE_FANCY_MATH_387
17716169699Skan   && flag_unsafe_math_optimizations"
17717169699Skan  "#"
17718169699Skan  [(set_attr "type" "fistp")
17719169699Skan   (set_attr "i387_cw" "ceil")
17720169699Skan   (set_attr "mode" "DI")])
17721169699Skan
17722169699Skan(define_split 
17723169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17724169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17725169699Skan	 UNSPEC_FIST_CEIL))
17726169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17727169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17728169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17729169699Skan   (clobber (match_scratch 5 ""))]
17730169699Skan  "reload_completed"
17731169699Skan  [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
17732169699Skan	      (use (match_dup 2))
17733169699Skan	      (use (match_dup 3))
17734169699Skan	      (clobber (match_dup 5))])
17735169699Skan   (set (match_dup 0) (match_dup 4))]
17736169699Skan  "")
17737169699Skan
17738169699Skan(define_split 
17739169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17740169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17741169699Skan	 UNSPEC_FIST_CEIL))
17742169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17743169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17744169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17745169699Skan   (clobber (match_scratch 5 ""))]
17746169699Skan  "reload_completed"
17747169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
17748169699Skan	      (use (match_dup 2))
17749169699Skan	      (use (match_dup 3))
17750169699Skan	      (clobber (match_dup 5))])]
17751169699Skan  "")
17752169699Skan
17753169699Skan(define_insn "fist<mode>2_ceil"
17754169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17755169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17756169699Skan	 UNSPEC_FIST_CEIL))
17757169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17758169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17759169699Skan  "TARGET_USE_FANCY_MATH_387
17760169699Skan   && flag_unsafe_math_optimizations"
17761169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17762169699Skan  [(set_attr "type" "fistp")
17763169699Skan   (set_attr "i387_cw" "ceil")
17764169699Skan   (set_attr "mode" "<MODE>")])
17765169699Skan
17766169699Skan(define_insn "fist<mode>2_ceil_with_temp"
17767169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
17768169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
17769169699Skan	 UNSPEC_FIST_CEIL))
17770169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17771169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17772169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
17773169699Skan  "TARGET_USE_FANCY_MATH_387
17774169699Skan   && flag_unsafe_math_optimizations"
17775169699Skan  "#"
17776169699Skan  [(set_attr "type" "fistp")
17777169699Skan   (set_attr "i387_cw" "ceil")
17778169699Skan   (set_attr "mode" "<MODE>")])
17779169699Skan
17780169699Skan(define_split 
17781169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17782169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17783169699Skan	 UNSPEC_FIST_CEIL))
17784169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17785169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17786169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17787169699Skan  "reload_completed"
17788169699Skan  [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
17789169699Skan				  UNSPEC_FIST_CEIL))
17790169699Skan	      (use (match_dup 2))
17791169699Skan	      (use (match_dup 3))])
17792169699Skan   (set (match_dup 0) (match_dup 4))]
17793169699Skan  "")
17794169699Skan
17795169699Skan(define_split 
17796169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17797169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17798169699Skan	 UNSPEC_FIST_CEIL))
17799169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17800169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17801169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17802169699Skan  "reload_completed"
17803169699Skan  [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17804169699Skan				  UNSPEC_FIST_CEIL))
17805169699Skan	      (use (match_dup 2))
17806169699Skan	      (use (match_dup 3))])]
17807169699Skan  "")
17808169699Skan
17809169699Skan(define_expand "lceil<mode>2"
17810169699Skan  [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17811169699Skan		   (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17812169699Skan		    UNSPEC_FIST_CEIL))
17813169699Skan	      (clobber (reg:CC FLAGS_REG))])]
17814169699Skan  "TARGET_USE_FANCY_MATH_387
17815169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17816169699Skan   && flag_unsafe_math_optimizations"
17817169699Skan  "")
17818169699Skan
17819169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17820169699Skan(define_insn_and_split "frndintxf2_trunc"
17821169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17822169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17823169699Skan	 UNSPEC_FRNDINT_TRUNC))
17824169699Skan   (clobber (reg:CC FLAGS_REG))]
17825169699Skan  "TARGET_USE_FANCY_MATH_387
17826169699Skan   && flag_unsafe_math_optimizations
17827169699Skan   && !(reload_completed || reload_in_progress)"
17828169699Skan  "#"
17829169699Skan  "&& 1"
17830169699Skan  [(const_int 0)]
17831169699Skan{
17832169699Skan  ix86_optimize_mode_switching[I387_TRUNC] = 1;
17833169699Skan
17834169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17835169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
17836169699Skan
17837169699Skan  emit_insn (gen_frndintxf2_trunc_i387 (operands[0], operands[1],
17838169699Skan					operands[2], operands[3]));
17839169699Skan  DONE;
17840169699Skan}
17841169699Skan  [(set_attr "type" "frndint")
17842169699Skan   (set_attr "i387_cw" "trunc")
17843169699Skan   (set_attr "mode" "XF")])
17844169699Skan
17845169699Skan(define_insn "frndintxf2_trunc_i387"
17846169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17847169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17848169699Skan	 UNSPEC_FRNDINT_TRUNC))
17849169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17850169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17851169699Skan  "TARGET_USE_FANCY_MATH_387
17852169699Skan   && flag_unsafe_math_optimizations"
17853169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17854169699Skan  [(set_attr "type" "frndint")
17855169699Skan   (set_attr "i387_cw" "trunc")
17856169699Skan   (set_attr "mode" "XF")])
17857169699Skan
17858169699Skan(define_expand "btruncxf2"
17859169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17860169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17861169699Skan  "TARGET_USE_FANCY_MATH_387
17862169699Skan   && flag_unsafe_math_optimizations"
17863169699Skan{
17864169699Skan  emit_insn (gen_frndintxf2_trunc (operands[0], operands[1]));
17865169699Skan  DONE;
17866169699Skan})
17867169699Skan
17868169699Skan(define_expand "btruncdf2"
17869169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17870169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17871169699Skan  "TARGET_USE_FANCY_MATH_387
17872169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17873169699Skan   && flag_unsafe_math_optimizations"
17874169699Skan{
17875169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17876169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17877169699Skan
17878169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17879169699Skan  emit_insn (gen_frndintxf2_trunc (op0, op1));
17880169699Skan
17881169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17882169699Skan  DONE;
17883169699Skan})
17884169699Skan
17885169699Skan(define_expand "btruncsf2"
17886169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17887169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17888169699Skan  "TARGET_USE_FANCY_MATH_387
17889169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17890169699Skan   && flag_unsafe_math_optimizations"
17891169699Skan{
17892169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17893169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17894169699Skan
17895169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17896169699Skan  emit_insn (gen_frndintxf2_trunc (op0, op1));
17897169699Skan
17898169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17899169699Skan  DONE;
17900169699Skan})
17901169699Skan
17902169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17903169699Skan(define_insn_and_split "frndintxf2_mask_pm"
17904169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17905169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17906169699Skan	 UNSPEC_FRNDINT_MASK_PM))
17907169699Skan   (clobber (reg:CC FLAGS_REG))]
17908169699Skan  "TARGET_USE_FANCY_MATH_387
17909169699Skan   && flag_unsafe_math_optimizations
17910169699Skan   && !(reload_completed || reload_in_progress)"
17911169699Skan  "#"
17912169699Skan  "&& 1"
17913169699Skan  [(const_int 0)]
17914169699Skan{
17915169699Skan  ix86_optimize_mode_switching[I387_MASK_PM] = 1;
17916169699Skan
17917169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17918169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_MASK_PM);
17919169699Skan
17920169699Skan  emit_insn (gen_frndintxf2_mask_pm_i387 (operands[0], operands[1],
17921169699Skan					  operands[2], operands[3]));
17922169699Skan  DONE;
17923169699Skan}
17924169699Skan  [(set_attr "type" "frndint")
17925169699Skan   (set_attr "i387_cw" "mask_pm")
17926169699Skan   (set_attr "mode" "XF")])
17927169699Skan
17928169699Skan(define_insn "frndintxf2_mask_pm_i387"
17929169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17930169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17931169699Skan	 UNSPEC_FRNDINT_MASK_PM))
17932169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17933169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17934169699Skan  "TARGET_USE_FANCY_MATH_387
17935169699Skan   && flag_unsafe_math_optimizations"
17936169699Skan  "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2"
17937169699Skan  [(set_attr "type" "frndint")
17938169699Skan   (set_attr "i387_cw" "mask_pm")
17939169699Skan   (set_attr "mode" "XF")])
17940169699Skan
17941169699Skan(define_expand "nearbyintxf2"
17942169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17943169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17944169699Skan  "TARGET_USE_FANCY_MATH_387
17945169699Skan   && flag_unsafe_math_optimizations"
17946169699Skan{
17947169699Skan  emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1]));
17948169699Skan
17949169699Skan  DONE;
17950169699Skan})
17951169699Skan
17952169699Skan(define_expand "nearbyintdf2"
17953169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17954169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17955169699Skan  "TARGET_USE_FANCY_MATH_387
17956169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17957169699Skan   && flag_unsafe_math_optimizations"
17958169699Skan{
17959169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17960169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17961169699Skan
17962169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17963169699Skan  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
17964169699Skan
17965169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17966169699Skan  DONE;
17967169699Skan})
17968169699Skan
17969169699Skan(define_expand "nearbyintsf2"
17970169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17971169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17972169699Skan  "TARGET_USE_FANCY_MATH_387
17973169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17974169699Skan   && flag_unsafe_math_optimizations"
17975169699Skan{
17976169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17977169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17978169699Skan
17979169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17980169699Skan  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
17981169699Skan
17982169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17983169699Skan  DONE;
17984169699Skan})
17985169699Skan
17986169699Skan
1798790286Sobrien;; Block operation instructions
1798890286Sobrien
1798990286Sobrien(define_insn "cld"
17990169699Skan [(set (reg:SI DIRFLAG_REG) (const_int 0))]
1799190286Sobrien ""
1799290286Sobrien "cld"
1799390286Sobrien  [(set_attr "type" "cld")])
1799490286Sobrien
17995169699Skan(define_expand "movmemsi"
1799690286Sobrien  [(use (match_operand:BLK 0 "memory_operand" ""))
1799790286Sobrien   (use (match_operand:BLK 1 "memory_operand" ""))
1799890286Sobrien   (use (match_operand:SI 2 "nonmemory_operand" ""))
1799990286Sobrien   (use (match_operand:SI 3 "const_int_operand" ""))]
18000169699Skan  "! optimize_size || TARGET_INLINE_ALL_STRINGOPS"
1800118334Speter{
18002169699Skan if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
1800390286Sobrien   DONE;
1800490286Sobrien else
1800590286Sobrien   FAIL;
1800690286Sobrien})
1800790286Sobrien
18008169699Skan(define_expand "movmemdi"
1800990286Sobrien  [(use (match_operand:BLK 0 "memory_operand" ""))
1801090286Sobrien   (use (match_operand:BLK 1 "memory_operand" ""))
1801190286Sobrien   (use (match_operand:DI 2 "nonmemory_operand" ""))
1801290286Sobrien   (use (match_operand:DI 3 "const_int_operand" ""))]
1801390286Sobrien  "TARGET_64BIT"
1801490286Sobrien{
18015169699Skan if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
1801690286Sobrien   DONE;
1801790286Sobrien else
1801890286Sobrien   FAIL;
1801990286Sobrien})
1802090286Sobrien
1802190286Sobrien;; Most CPUs don't like single string operations
1802290286Sobrien;; Handle this case here to simplify previous expander.
1802390286Sobrien
18024132727Skan(define_expand "strmov"
18025132727Skan  [(set (match_dup 4) (match_operand 3 "memory_operand" ""))
18026132727Skan   (set (match_operand 1 "memory_operand" "") (match_dup 4))
18027132727Skan   (parallel [(set (match_operand 0 "register_operand" "") (match_dup 5))
18028169699Skan	      (clobber (reg:CC FLAGS_REG))])
18029132727Skan   (parallel [(set (match_operand 2 "register_operand" "") (match_dup 6))
18030169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1803190286Sobrien  ""
1803290286Sobrien{
18033132727Skan  rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])));
1803450650Sobrien
18035132727Skan  /* If .md ever supports :P for Pmode, these can be directly
18036132727Skan     in the pattern above.  */
18037132727Skan  operands[5] = gen_rtx_PLUS (Pmode, operands[0], adjust);
18038132727Skan  operands[6] = gen_rtx_PLUS (Pmode, operands[2], adjust);
1803950650Sobrien
1804090286Sobrien  if (TARGET_SINGLE_STRINGOP || optimize_size)
1804190286Sobrien    {
18042132727Skan      emit_insn (gen_strmov_singleop (operands[0], operands[1],
18043132727Skan				      operands[2], operands[3],
18044132727Skan				      operands[5], operands[6]));
1804590286Sobrien      DONE;
1804690286Sobrien    }
1804750650Sobrien
18048132727Skan  operands[4] = gen_reg_rtx (GET_MODE (operands[1]));
1804990286Sobrien})
1805050650Sobrien
18051132727Skan(define_expand "strmov_singleop"
18052132727Skan  [(parallel [(set (match_operand 1 "memory_operand" "")
18053132727Skan		   (match_operand 3 "memory_operand" ""))
18054132727Skan	      (set (match_operand 0 "register_operand" "")
18055132727Skan		   (match_operand 4 "" ""))
18056132727Skan	      (set (match_operand 2 "register_operand" "")
18057132727Skan		   (match_operand 5 "" ""))
18058169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18059132727Skan  "TARGET_SINGLE_STRINGOP || optimize_size"
18060132727Skan  "")
1806118334Speter
18062132727Skan(define_insn "*strmovdi_rex_1"
1806390286Sobrien  [(set (mem:DI (match_operand:DI 2 "register_operand" "0"))
1806490286Sobrien	(mem:DI (match_operand:DI 3 "register_operand" "1")))
1806590286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1806690286Sobrien	(plus:DI (match_dup 2)
1806790286Sobrien		 (const_int 8)))
1806890286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1806990286Sobrien	(plus:DI (match_dup 3)
1807090286Sobrien		 (const_int 8)))
18071169699Skan   (use (reg:SI DIRFLAG_REG))]
1807290286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1807390286Sobrien  "movsq"
1807490286Sobrien  [(set_attr "type" "str")
1807590286Sobrien   (set_attr "mode" "DI")
1807690286Sobrien   (set_attr "memory" "both")])
1807790286Sobrien
18078132727Skan(define_insn "*strmovsi_1"
1807990286Sobrien  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
1808090286Sobrien	(mem:SI (match_operand:SI 3 "register_operand" "1")))
1808190286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1808290286Sobrien	(plus:SI (match_dup 2)
1808390286Sobrien		 (const_int 4)))
1808490286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1808590286Sobrien	(plus:SI (match_dup 3)
1808690286Sobrien		 (const_int 4)))
18087169699Skan   (use (reg:SI DIRFLAG_REG))]
1808890286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1808990286Sobrien  "{movsl|movsd}"
1809090286Sobrien  [(set_attr "type" "str")
1809190286Sobrien   (set_attr "mode" "SI")
1809290286Sobrien   (set_attr "memory" "both")])
1809390286Sobrien
18094132727Skan(define_insn "*strmovsi_rex_1"
1809590286Sobrien  [(set (mem:SI (match_operand:DI 2 "register_operand" "0"))
1809690286Sobrien	(mem:SI (match_operand:DI 3 "register_operand" "1")))
1809790286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1809890286Sobrien	(plus:DI (match_dup 2)
1809990286Sobrien		 (const_int 4)))
1810090286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1810190286Sobrien	(plus:DI (match_dup 3)
1810290286Sobrien		 (const_int 4)))
18103169699Skan   (use (reg:SI DIRFLAG_REG))]
1810490286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1810590286Sobrien  "{movsl|movsd}"
1810690286Sobrien  [(set_attr "type" "str")
1810790286Sobrien   (set_attr "mode" "SI")
1810890286Sobrien   (set_attr "memory" "both")])
1810990286Sobrien
18110132727Skan(define_insn "*strmovhi_1"
1811190286Sobrien  [(set (mem:HI (match_operand:SI 2 "register_operand" "0"))
1811290286Sobrien	(mem:HI (match_operand:SI 3 "register_operand" "1")))
1811390286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1811490286Sobrien	(plus:SI (match_dup 2)
1811590286Sobrien		 (const_int 2)))
1811690286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1811790286Sobrien	(plus:SI (match_dup 3)
1811890286Sobrien		 (const_int 2)))
18119169699Skan   (use (reg:SI DIRFLAG_REG))]
1812090286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1812190286Sobrien  "movsw"
1812290286Sobrien  [(set_attr "type" "str")
1812390286Sobrien   (set_attr "memory" "both")
1812490286Sobrien   (set_attr "mode" "HI")])
1812590286Sobrien
18126132727Skan(define_insn "*strmovhi_rex_1"
1812790286Sobrien  [(set (mem:HI (match_operand:DI 2 "register_operand" "0"))
1812890286Sobrien	(mem:HI (match_operand:DI 3 "register_operand" "1")))
1812990286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1813090286Sobrien	(plus:DI (match_dup 2)
1813190286Sobrien		 (const_int 2)))
1813290286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1813390286Sobrien	(plus:DI (match_dup 3)
1813490286Sobrien		 (const_int 2)))
18135169699Skan   (use (reg:SI DIRFLAG_REG))]
1813690286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1813790286Sobrien  "movsw"
1813890286Sobrien  [(set_attr "type" "str")
1813990286Sobrien   (set_attr "memory" "both")
1814090286Sobrien   (set_attr "mode" "HI")])
1814190286Sobrien
18142132727Skan(define_insn "*strmovqi_1"
1814390286Sobrien  [(set (mem:QI (match_operand:SI 2 "register_operand" "0"))
1814490286Sobrien	(mem:QI (match_operand:SI 3 "register_operand" "1")))
1814590286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1814690286Sobrien	(plus:SI (match_dup 2)
1814790286Sobrien		 (const_int 1)))
1814890286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1814990286Sobrien	(plus:SI (match_dup 3)
1815090286Sobrien		 (const_int 1)))
18151169699Skan   (use (reg:SI DIRFLAG_REG))]
1815290286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1815390286Sobrien  "movsb"
1815490286Sobrien  [(set_attr "type" "str")
1815590286Sobrien   (set_attr "memory" "both")
1815690286Sobrien   (set_attr "mode" "QI")])
1815790286Sobrien
18158132727Skan(define_insn "*strmovqi_rex_1"
1815990286Sobrien  [(set (mem:QI (match_operand:DI 2 "register_operand" "0"))
1816090286Sobrien	(mem:QI (match_operand:DI 3 "register_operand" "1")))
1816190286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1816290286Sobrien	(plus:DI (match_dup 2)
1816390286Sobrien		 (const_int 1)))
1816490286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1816590286Sobrien	(plus:DI (match_dup 3)
1816690286Sobrien		 (const_int 1)))
18167169699Skan   (use (reg:SI DIRFLAG_REG))]
1816890286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1816990286Sobrien  "movsb"
1817090286Sobrien  [(set_attr "type" "str")
1817190286Sobrien   (set_attr "memory" "both")
1817290286Sobrien   (set_attr "mode" "QI")])
1817390286Sobrien
18174132727Skan(define_expand "rep_mov"
18175132727Skan  [(parallel [(set (match_operand 4 "register_operand" "") (const_int 0))
18176132727Skan	      (set (match_operand 0 "register_operand" "")
18177132727Skan		   (match_operand 5 "" ""))
18178132727Skan	      (set (match_operand 2 "register_operand" "")
18179132727Skan		   (match_operand 6 "" ""))
18180132727Skan	      (set (match_operand 1 "memory_operand" "")
18181132727Skan		   (match_operand 3 "memory_operand" ""))
18182132727Skan	      (use (match_dup 4))
18183169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18184132727Skan  ""
18185132727Skan  "")
18186132727Skan
18187132727Skan(define_insn "*rep_movdi_rex64"
1818890286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
1818990286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1819090286Sobrien        (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
1819190286Sobrien			    (const_int 3))
1819290286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1819390286Sobrien   (set (match_operand:DI 1 "register_operand" "=S") 
1819490286Sobrien        (plus:DI (ashift:DI (match_dup 5) (const_int 3))
1819590286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1819690286Sobrien   (set (mem:BLK (match_dup 3))
1819790286Sobrien	(mem:BLK (match_dup 4)))
1819890286Sobrien   (use (match_dup 5))
18199169699Skan   (use (reg:SI DIRFLAG_REG))]
1820090286Sobrien  "TARGET_64BIT"
1820190286Sobrien  "{rep\;movsq|rep movsq}"
1820290286Sobrien  [(set_attr "type" "str")
1820390286Sobrien   (set_attr "prefix_rep" "1")
1820490286Sobrien   (set_attr "memory" "both")
1820590286Sobrien   (set_attr "mode" "DI")])
1820690286Sobrien
18207132727Skan(define_insn "*rep_movsi"
1820890286Sobrien  [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
1820990286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1821090286Sobrien        (plus:SI (ashift:SI (match_operand:SI 5 "register_operand" "2")
1821190286Sobrien			    (const_int 2))
1821290286Sobrien		 (match_operand:SI 3 "register_operand" "0")))
1821390286Sobrien   (set (match_operand:SI 1 "register_operand" "=S") 
1821490286Sobrien        (plus:SI (ashift:SI (match_dup 5) (const_int 2))
1821590286Sobrien		 (match_operand:SI 4 "register_operand" "1")))
1821690286Sobrien   (set (mem:BLK (match_dup 3))
1821790286Sobrien	(mem:BLK (match_dup 4)))
1821890286Sobrien   (use (match_dup 5))
18219169699Skan   (use (reg:SI DIRFLAG_REG))]
1822090286Sobrien  "!TARGET_64BIT"
1822190286Sobrien  "{rep\;movsl|rep movsd}"
1822290286Sobrien  [(set_attr "type" "str")
1822390286Sobrien   (set_attr "prefix_rep" "1")
1822490286Sobrien   (set_attr "memory" "both")
1822590286Sobrien   (set_attr "mode" "SI")])
1822690286Sobrien
18227132727Skan(define_insn "*rep_movsi_rex64"
1822890286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
1822990286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1823090286Sobrien        (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
1823190286Sobrien			    (const_int 2))
1823290286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1823390286Sobrien   (set (match_operand:DI 1 "register_operand" "=S") 
1823490286Sobrien        (plus:DI (ashift:DI (match_dup 5) (const_int 2))
1823590286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1823690286Sobrien   (set (mem:BLK (match_dup 3))
1823790286Sobrien	(mem:BLK (match_dup 4)))
1823890286Sobrien   (use (match_dup 5))
18239169699Skan   (use (reg:SI DIRFLAG_REG))]
1824090286Sobrien  "TARGET_64BIT"
1824190286Sobrien  "{rep\;movsl|rep movsd}"
1824290286Sobrien  [(set_attr "type" "str")
1824390286Sobrien   (set_attr "prefix_rep" "1")
1824490286Sobrien   (set_attr "memory" "both")
1824590286Sobrien   (set_attr "mode" "SI")])
1824690286Sobrien
18247132727Skan(define_insn "*rep_movqi"
1824890286Sobrien  [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
1824990286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1825090286Sobrien        (plus:SI (match_operand:SI 3 "register_operand" "0")
1825190286Sobrien		 (match_operand:SI 5 "register_operand" "2")))
1825290286Sobrien   (set (match_operand:SI 1 "register_operand" "=S") 
1825390286Sobrien        (plus:SI (match_operand:SI 4 "register_operand" "1") (match_dup 5)))
1825490286Sobrien   (set (mem:BLK (match_dup 3))
1825590286Sobrien	(mem:BLK (match_dup 4)))
1825690286Sobrien   (use (match_dup 5))
18257169699Skan   (use (reg:SI DIRFLAG_REG))]
1825890286Sobrien  "!TARGET_64BIT"
1825990286Sobrien  "{rep\;movsb|rep movsb}"
1826090286Sobrien  [(set_attr "type" "str")
1826190286Sobrien   (set_attr "prefix_rep" "1")
1826290286Sobrien   (set_attr "memory" "both")
1826390286Sobrien   (set_attr "mode" "SI")])
1826490286Sobrien
18265132727Skan(define_insn "*rep_movqi_rex64"
1826690286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
1826790286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1826890286Sobrien        (plus:DI (match_operand:DI 3 "register_operand" "0")
1826990286Sobrien		 (match_operand:DI 5 "register_operand" "2")))
1827090286Sobrien   (set (match_operand:DI 1 "register_operand" "=S") 
1827190286Sobrien        (plus:DI (match_operand:DI 4 "register_operand" "1") (match_dup 5)))
1827290286Sobrien   (set (mem:BLK (match_dup 3))
1827390286Sobrien	(mem:BLK (match_dup 4)))
1827490286Sobrien   (use (match_dup 5))
18275169699Skan   (use (reg:SI DIRFLAG_REG))]
1827690286Sobrien  "TARGET_64BIT"
1827790286Sobrien  "{rep\;movsb|rep movsb}"
1827890286Sobrien  [(set_attr "type" "str")
1827990286Sobrien   (set_attr "prefix_rep" "1")
1828090286Sobrien   (set_attr "memory" "both")
1828190286Sobrien   (set_attr "mode" "SI")])
1828290286Sobrien
18283169699Skan(define_expand "setmemsi"
1828490286Sobrien   [(use (match_operand:BLK 0 "memory_operand" ""))
1828590286Sobrien    (use (match_operand:SI 1 "nonmemory_operand" ""))
18286169699Skan    (use (match_operand 2 "const_int_operand" ""))
18287169699Skan    (use (match_operand 3 "const_int_operand" ""))]
1828818334Speter  ""
1828918334Speter{
18290169699Skan /* If value to set is not zero, use the library routine.  */
18291169699Skan if (operands[2] != const0_rtx)
18292169699Skan   FAIL;
18293169699Skan
18294169699Skan if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
1829590286Sobrien   DONE;
1829690286Sobrien else
1829790286Sobrien   FAIL;
1829890286Sobrien})
1829918334Speter
18300169699Skan(define_expand "setmemdi"
1830190286Sobrien   [(use (match_operand:BLK 0 "memory_operand" ""))
1830290286Sobrien    (use (match_operand:DI 1 "nonmemory_operand" ""))
18303169699Skan    (use (match_operand 2 "const_int_operand" ""))
18304169699Skan    (use (match_operand 3 "const_int_operand" ""))]
1830590286Sobrien  "TARGET_64BIT"
1830690286Sobrien{
18307169699Skan /* If value to set is not zero, use the library routine.  */
18308169699Skan if (operands[2] != const0_rtx)
18309169699Skan   FAIL;
18310169699Skan
18311169699Skan if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
1831290286Sobrien   DONE;
1831390286Sobrien else
1831490286Sobrien   FAIL;
1831590286Sobrien})
1831650650Sobrien
1831790286Sobrien;; Most CPUs don't like single string operations
1831890286Sobrien;; Handle this case here to simplify previous expander.
1831950650Sobrien
18320132727Skan(define_expand "strset"
18321132727Skan  [(set (match_operand 1 "memory_operand" "")
18322132727Skan	(match_operand 2 "register_operand" ""))
18323132727Skan   (parallel [(set (match_operand 0 "register_operand" "")
18324132727Skan		   (match_dup 3))
18325169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1832690286Sobrien  ""
1832790286Sobrien{
18328132727Skan  if (GET_MODE (operands[1]) != GET_MODE (operands[2]))
18329132727Skan    operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0);
1833090286Sobrien
18331132727Skan  /* If .md ever supports :P for Pmode, this can be directly
18332132727Skan     in the pattern above.  */
18333132727Skan  operands[3] = gen_rtx_PLUS (Pmode, operands[0],
18334132727Skan			      GEN_INT (GET_MODE_SIZE (GET_MODE
18335132727Skan						      (operands[2]))));
1833690286Sobrien  if (TARGET_SINGLE_STRINGOP || optimize_size)
1833790286Sobrien    {
18338132727Skan      emit_insn (gen_strset_singleop (operands[0], operands[1], operands[2],
18339132727Skan				      operands[3]));
1834090286Sobrien      DONE;
1834190286Sobrien    }
1834290286Sobrien})
1834390286Sobrien
18344132727Skan(define_expand "strset_singleop"
18345132727Skan  [(parallel [(set (match_operand 1 "memory_operand" "")
18346132727Skan		   (match_operand 2 "register_operand" ""))
18347132727Skan	      (set (match_operand 0 "register_operand" "")
18348132727Skan		   (match_operand 3 "" ""))
18349169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18350132727Skan  "TARGET_SINGLE_STRINGOP || optimize_size"
18351132727Skan  "")
1835290286Sobrien
18353132727Skan(define_insn "*strsetdi_rex_1"
18354169699Skan  [(set (mem:DI (match_operand:DI 1 "register_operand" "0"))
18355169699Skan	(match_operand:DI 2 "register_operand" "a"))
1835690286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1835790286Sobrien	(plus:DI (match_dup 1)
1835890286Sobrien		 (const_int 8)))
18359169699Skan   (use (reg:SI DIRFLAG_REG))]
1836090286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1836190286Sobrien  "stosq"
1836290286Sobrien  [(set_attr "type" "str")
1836390286Sobrien   (set_attr "memory" "store")
1836490286Sobrien   (set_attr "mode" "DI")])
1836590286Sobrien
18366132727Skan(define_insn "*strsetsi_1"
1836790286Sobrien  [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
1836890286Sobrien	(match_operand:SI 2 "register_operand" "a"))
1836990286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1837090286Sobrien	(plus:SI (match_dup 1)
1837190286Sobrien		 (const_int 4)))
18372169699Skan   (use (reg:SI DIRFLAG_REG))]
1837390286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1837490286Sobrien  "{stosl|stosd}"
1837590286Sobrien  [(set_attr "type" "str")
1837690286Sobrien   (set_attr "memory" "store")
1837790286Sobrien   (set_attr "mode" "SI")])
1837890286Sobrien
18379132727Skan(define_insn "*strsetsi_rex_1"
1838090286Sobrien  [(set (mem:SI (match_operand:DI 1 "register_operand" "0"))
1838190286Sobrien	(match_operand:SI 2 "register_operand" "a"))
1838290286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1838390286Sobrien	(plus:DI (match_dup 1)
1838490286Sobrien		 (const_int 4)))
18385169699Skan   (use (reg:SI DIRFLAG_REG))]
1838690286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1838790286Sobrien  "{stosl|stosd}"
1838890286Sobrien  [(set_attr "type" "str")
1838990286Sobrien   (set_attr "memory" "store")
1839090286Sobrien   (set_attr "mode" "SI")])
1839190286Sobrien
18392132727Skan(define_insn "*strsethi_1"
1839390286Sobrien  [(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
1839490286Sobrien	(match_operand:HI 2 "register_operand" "a"))
1839590286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1839690286Sobrien	(plus:SI (match_dup 1)
1839790286Sobrien		 (const_int 2)))
18398169699Skan   (use (reg:SI DIRFLAG_REG))]
1839990286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1840090286Sobrien  "stosw"
1840190286Sobrien  [(set_attr "type" "str")
1840290286Sobrien   (set_attr "memory" "store")
1840390286Sobrien   (set_attr "mode" "HI")])
1840490286Sobrien
18405132727Skan(define_insn "*strsethi_rex_1"
1840690286Sobrien  [(set (mem:HI (match_operand:DI 1 "register_operand" "0"))
1840790286Sobrien	(match_operand:HI 2 "register_operand" "a"))
1840890286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1840990286Sobrien	(plus:DI (match_dup 1)
1841090286Sobrien		 (const_int 2)))
18411169699Skan   (use (reg:SI DIRFLAG_REG))]
1841290286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1841390286Sobrien  "stosw"
1841490286Sobrien  [(set_attr "type" "str")
1841590286Sobrien   (set_attr "memory" "store")
1841690286Sobrien   (set_attr "mode" "HI")])
1841790286Sobrien
18418132727Skan(define_insn "*strsetqi_1"
1841990286Sobrien  [(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
1842090286Sobrien	(match_operand:QI 2 "register_operand" "a"))
1842190286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1842290286Sobrien	(plus:SI (match_dup 1)
1842390286Sobrien		 (const_int 1)))
18424169699Skan   (use (reg:SI DIRFLAG_REG))]
1842590286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1842690286Sobrien  "stosb"
1842790286Sobrien  [(set_attr "type" "str")
1842890286Sobrien   (set_attr "memory" "store")
1842990286Sobrien   (set_attr "mode" "QI")])
1843090286Sobrien
18431132727Skan(define_insn "*strsetqi_rex_1"
1843290286Sobrien  [(set (mem:QI (match_operand:DI 1 "register_operand" "0"))
1843390286Sobrien	(match_operand:QI 2 "register_operand" "a"))
1843490286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1843590286Sobrien	(plus:DI (match_dup 1)
1843690286Sobrien		 (const_int 1)))
18437169699Skan   (use (reg:SI DIRFLAG_REG))]
1843890286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1843990286Sobrien  "stosb"
1844090286Sobrien  [(set_attr "type" "str")
1844190286Sobrien   (set_attr "memory" "store")
1844290286Sobrien   (set_attr "mode" "QI")])
1844390286Sobrien
18444132727Skan(define_expand "rep_stos"
18445132727Skan  [(parallel [(set (match_operand 1 "register_operand" "") (const_int 0))
18446132727Skan	      (set (match_operand 0 "register_operand" "")
18447132727Skan		   (match_operand 4 "" ""))
18448132727Skan	      (set (match_operand 2 "memory_operand" "") (const_int 0))
18449132727Skan	      (use (match_operand 3 "register_operand" ""))
18450132727Skan	      (use (match_dup 1))
18451169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18452132727Skan  ""
18453132727Skan  "")
18454132727Skan
18455132727Skan(define_insn "*rep_stosdi_rex64"
1845690286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
1845790286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1845890286Sobrien        (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
1845990286Sobrien			    (const_int 3))
1846090286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1846190286Sobrien   (set (mem:BLK (match_dup 3))
1846290286Sobrien	(const_int 0))
1846390286Sobrien   (use (match_operand:DI 2 "register_operand" "a"))
1846490286Sobrien   (use (match_dup 4))
18465169699Skan   (use (reg:SI DIRFLAG_REG))]
1846690286Sobrien  "TARGET_64BIT"
1846790286Sobrien  "{rep\;stosq|rep stosq}"
1846890286Sobrien  [(set_attr "type" "str")
1846990286Sobrien   (set_attr "prefix_rep" "1")
1847090286Sobrien   (set_attr "memory" "store")
1847190286Sobrien   (set_attr "mode" "DI")])
1847290286Sobrien
18473132727Skan(define_insn "*rep_stossi"
1847490286Sobrien  [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
1847590286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1847690286Sobrien        (plus:SI (ashift:SI (match_operand:SI 4 "register_operand" "1")
1847790286Sobrien			    (const_int 2))
1847890286Sobrien		 (match_operand:SI 3 "register_operand" "0")))
1847990286Sobrien   (set (mem:BLK (match_dup 3))
1848090286Sobrien	(const_int 0))
1848190286Sobrien   (use (match_operand:SI 2 "register_operand" "a"))
1848290286Sobrien   (use (match_dup 4))
18483169699Skan   (use (reg:SI DIRFLAG_REG))]
1848490286Sobrien  "!TARGET_64BIT"
1848590286Sobrien  "{rep\;stosl|rep stosd}"
1848690286Sobrien  [(set_attr "type" "str")
1848790286Sobrien   (set_attr "prefix_rep" "1")
1848890286Sobrien   (set_attr "memory" "store")
1848990286Sobrien   (set_attr "mode" "SI")])
1849090286Sobrien
18491132727Skan(define_insn "*rep_stossi_rex64"
1849290286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
1849390286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1849490286Sobrien        (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
1849590286Sobrien			    (const_int 2))
1849690286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1849790286Sobrien   (set (mem:BLK (match_dup 3))
1849890286Sobrien	(const_int 0))
1849990286Sobrien   (use (match_operand:SI 2 "register_operand" "a"))
1850090286Sobrien   (use (match_dup 4))
18501169699Skan   (use (reg:SI DIRFLAG_REG))]
1850290286Sobrien  "TARGET_64BIT"
1850390286Sobrien  "{rep\;stosl|rep stosd}"
1850490286Sobrien  [(set_attr "type" "str")
1850590286Sobrien   (set_attr "prefix_rep" "1")
1850690286Sobrien   (set_attr "memory" "store")
1850790286Sobrien   (set_attr "mode" "SI")])
1850890286Sobrien
18509132727Skan(define_insn "*rep_stosqi"
1851090286Sobrien  [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
1851190286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1851290286Sobrien        (plus:SI (match_operand:SI 3 "register_operand" "0")
1851390286Sobrien		 (match_operand:SI 4 "register_operand" "1")))
1851490286Sobrien   (set (mem:BLK (match_dup 3))
1851590286Sobrien	(const_int 0))
1851690286Sobrien   (use (match_operand:QI 2 "register_operand" "a"))
1851790286Sobrien   (use (match_dup 4))
18518169699Skan   (use (reg:SI DIRFLAG_REG))]
1851990286Sobrien  "!TARGET_64BIT"
1852090286Sobrien  "{rep\;stosb|rep stosb}"
1852190286Sobrien  [(set_attr "type" "str")
1852290286Sobrien   (set_attr "prefix_rep" "1")
1852390286Sobrien   (set_attr "memory" "store")
1852490286Sobrien   (set_attr "mode" "QI")])
1852590286Sobrien
18526132727Skan(define_insn "*rep_stosqi_rex64"
1852790286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
1852890286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1852990286Sobrien        (plus:DI (match_operand:DI 3 "register_operand" "0")
1853090286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1853190286Sobrien   (set (mem:BLK (match_dup 3))
1853290286Sobrien	(const_int 0))
1853390286Sobrien   (use (match_operand:QI 2 "register_operand" "a"))
1853490286Sobrien   (use (match_dup 4))
18535169699Skan   (use (reg:SI DIRFLAG_REG))]
1853690286Sobrien  "TARGET_64BIT"
1853790286Sobrien  "{rep\;stosb|rep stosb}"
1853890286Sobrien  [(set_attr "type" "str")
1853990286Sobrien   (set_attr "prefix_rep" "1")
1854090286Sobrien   (set_attr "memory" "store")
1854190286Sobrien   (set_attr "mode" "QI")])
1854290286Sobrien
18543169699Skan(define_expand "cmpstrnsi"
1854450650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1854590286Sobrien	(compare:SI (match_operand:BLK 1 "general_operand" "")
1854690286Sobrien		    (match_operand:BLK 2 "general_operand" "")))
1854790286Sobrien   (use (match_operand 3 "general_operand" ""))
1854890286Sobrien   (use (match_operand 4 "immediate_operand" ""))]
18549132727Skan  "! optimize_size || TARGET_INLINE_ALL_STRINGOPS"
1855050650Sobrien{
1855190286Sobrien  rtx addr1, addr2, out, outlow, count, countreg, align;
1855250650Sobrien
18553132727Skan  /* Can't use this if the user has appropriated esi or edi.  */
18554132727Skan  if (global_regs[4] || global_regs[5])
18555132727Skan    FAIL;
18556132727Skan
1855790286Sobrien  out = operands[0];
1855890286Sobrien  if (GET_CODE (out) != REG)
1855990286Sobrien    out = gen_reg_rtx (SImode);
1856050650Sobrien
1856190286Sobrien  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1856290286Sobrien  addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
18563132727Skan  if (addr1 != XEXP (operands[1], 0))
18564132727Skan    operands[1] = replace_equiv_address_nv (operands[1], addr1);
18565132727Skan  if (addr2 != XEXP (operands[2], 0))
18566132727Skan    operands[2] = replace_equiv_address_nv (operands[2], addr2);
18567132727Skan
1856890286Sobrien  count = operands[3];
1856990286Sobrien  countreg = ix86_zero_extend_to_Pmode (count);
1857050650Sobrien
1857190286Sobrien  /* %%% Iff we are testing strict equality, we can use known alignment
1857290286Sobrien     to good advantage.  This may be possible with combine, particularly
1857390286Sobrien     once cc0 is dead.  */
1857490286Sobrien  align = operands[4];
1857550650Sobrien
1857690286Sobrien  emit_insn (gen_cld ());
1857790286Sobrien  if (GET_CODE (count) == CONST_INT)
1857890286Sobrien    {
1857990286Sobrien      if (INTVAL (count) == 0)
1858090286Sobrien	{
1858190286Sobrien	  emit_move_insn (operands[0], const0_rtx);
1858290286Sobrien	  DONE;
1858390286Sobrien	}
18584169699Skan      emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, countreg, align,
18585169699Skan				     operands[1], operands[2]));
1858690286Sobrien    }
1858790286Sobrien  else
1858890286Sobrien    {
1858990286Sobrien      if (TARGET_64BIT)
18590132727Skan	emit_insn (gen_cmpdi_1_rex64 (countreg, countreg));
1859190286Sobrien      else
18592132727Skan	emit_insn (gen_cmpsi_1 (countreg, countreg));
18593169699Skan      emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
18594169699Skan				  operands[1], operands[2]));
1859590286Sobrien    }
1859690286Sobrien
1859790286Sobrien  outlow = gen_lowpart (QImode, out);
1859890286Sobrien  emit_insn (gen_cmpintqi (outlow));
1859990286Sobrien  emit_move_insn (out, gen_rtx_SIGN_EXTEND (SImode, outlow));
1860090286Sobrien
1860190286Sobrien  if (operands[0] != out)
1860290286Sobrien    emit_move_insn (operands[0], out);
1860390286Sobrien
1860490286Sobrien  DONE;
1860590286Sobrien})
1860690286Sobrien
1860790286Sobrien;; Produce a tri-state integer (-1, 0, 1) from condition codes.
1860890286Sobrien
1860990286Sobrien(define_expand "cmpintqi"
1861090286Sobrien  [(set (match_dup 1)
18611169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1861290286Sobrien   (set (match_dup 2)
18613169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
1861490286Sobrien   (parallel [(set (match_operand:QI 0 "register_operand" "")
1861590286Sobrien		   (minus:QI (match_dup 1)
1861690286Sobrien			     (match_dup 2)))
18617169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1861890286Sobrien  ""
1861990286Sobrien  "operands[1] = gen_reg_rtx (QImode);
1862090286Sobrien   operands[2] = gen_reg_rtx (QImode);")
1862190286Sobrien
1862290286Sobrien;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
1862390286Sobrien;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
1862490286Sobrien
18625169699Skan(define_expand "cmpstrnqi_nz_1"
18626169699Skan  [(parallel [(set (reg:CC FLAGS_REG)
18627132727Skan		   (compare:CC (match_operand 4 "memory_operand" "")
18628132727Skan			       (match_operand 5 "memory_operand" "")))
18629132727Skan	      (use (match_operand 2 "register_operand" ""))
18630132727Skan	      (use (match_operand:SI 3 "immediate_operand" ""))
18631169699Skan	      (use (reg:SI DIRFLAG_REG))
18632132727Skan	      (clobber (match_operand 0 "register_operand" ""))
18633132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18634132727Skan	      (clobber (match_dup 2))])]
18635132727Skan  ""
18636132727Skan  "")
18637132727Skan
18638169699Skan(define_insn "*cmpstrnqi_nz_1"
18639169699Skan  [(set (reg:CC FLAGS_REG)
1864090286Sobrien	(compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
1864190286Sobrien		    (mem:BLK (match_operand:SI 5 "register_operand" "1"))))
1864290286Sobrien   (use (match_operand:SI 6 "register_operand" "2"))
1864390286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18644169699Skan   (use (reg:SI DIRFLAG_REG))
1864590286Sobrien   (clobber (match_operand:SI 0 "register_operand" "=S"))
1864690286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
1864790286Sobrien   (clobber (match_operand:SI 2 "register_operand" "=c"))]
1864890286Sobrien  "!TARGET_64BIT"
1864990286Sobrien  "repz{\;| }cmpsb"
1865090286Sobrien  [(set_attr "type" "str")
1865190286Sobrien   (set_attr "mode" "QI")
1865290286Sobrien   (set_attr "prefix_rep" "1")])
1865390286Sobrien
18654169699Skan(define_insn "*cmpstrnqi_nz_rex_1"
18655169699Skan  [(set (reg:CC FLAGS_REG)
1865690286Sobrien	(compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
1865790286Sobrien		    (mem:BLK (match_operand:DI 5 "register_operand" "1"))))
1865890286Sobrien   (use (match_operand:DI 6 "register_operand" "2"))
1865990286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18660169699Skan   (use (reg:SI DIRFLAG_REG))
1866190286Sobrien   (clobber (match_operand:DI 0 "register_operand" "=S"))
1866290286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
1866390286Sobrien   (clobber (match_operand:DI 2 "register_operand" "=c"))]
1866490286Sobrien  "TARGET_64BIT"
1866590286Sobrien  "repz{\;| }cmpsb"
1866690286Sobrien  [(set_attr "type" "str")
1866790286Sobrien   (set_attr "mode" "QI")
1866890286Sobrien   (set_attr "prefix_rep" "1")])
1866990286Sobrien
1867090286Sobrien;; The same, but the count is not known to not be zero.
1867190286Sobrien
18672169699Skan(define_expand "cmpstrnqi_1"
18673169699Skan  [(parallel [(set (reg:CC FLAGS_REG)
18674132727Skan		(if_then_else:CC (ne (match_operand 2 "register_operand" "")
18675132727Skan				     (const_int 0))
18676132727Skan		  (compare:CC (match_operand 4 "memory_operand" "")
18677132727Skan			      (match_operand 5 "memory_operand" ""))
18678132727Skan		  (const_int 0)))
18679132727Skan	      (use (match_operand:SI 3 "immediate_operand" ""))
18680169699Skan	      (use (reg:CC FLAGS_REG))
18681169699Skan	      (use (reg:SI DIRFLAG_REG))
18682132727Skan	      (clobber (match_operand 0 "register_operand" ""))
18683132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18684132727Skan	      (clobber (match_dup 2))])]
18685132727Skan  ""
18686132727Skan  "")
18687132727Skan
18688169699Skan(define_insn "*cmpstrnqi_1"
18689169699Skan  [(set (reg:CC FLAGS_REG)
1869090286Sobrien	(if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
1869190286Sobrien			     (const_int 0))
1869290286Sobrien	  (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
1869390286Sobrien		      (mem:BLK (match_operand:SI 5 "register_operand" "1")))
1869490286Sobrien	  (const_int 0)))
1869590286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18696169699Skan   (use (reg:CC FLAGS_REG))
18697169699Skan   (use (reg:SI DIRFLAG_REG))
1869890286Sobrien   (clobber (match_operand:SI 0 "register_operand" "=S"))
1869990286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
1870090286Sobrien   (clobber (match_operand:SI 2 "register_operand" "=c"))]
1870190286Sobrien  "!TARGET_64BIT"
1870290286Sobrien  "repz{\;| }cmpsb"
1870390286Sobrien  [(set_attr "type" "str")
1870490286Sobrien   (set_attr "mode" "QI")
1870590286Sobrien   (set_attr "prefix_rep" "1")])
1870690286Sobrien
18707169699Skan(define_insn "*cmpstrnqi_rex_1"
18708169699Skan  [(set (reg:CC FLAGS_REG)
1870990286Sobrien	(if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2")
1871090286Sobrien			     (const_int 0))
1871190286Sobrien	  (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
1871290286Sobrien		      (mem:BLK (match_operand:DI 5 "register_operand" "1")))
1871390286Sobrien	  (const_int 0)))
1871490286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18715169699Skan   (use (reg:CC FLAGS_REG))
18716169699Skan   (use (reg:SI DIRFLAG_REG))
1871790286Sobrien   (clobber (match_operand:DI 0 "register_operand" "=S"))
1871890286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
1871990286Sobrien   (clobber (match_operand:DI 2 "register_operand" "=c"))]
1872090286Sobrien  "TARGET_64BIT"
1872190286Sobrien  "repz{\;| }cmpsb"
1872290286Sobrien  [(set_attr "type" "str")
1872390286Sobrien   (set_attr "mode" "QI")
1872490286Sobrien   (set_attr "prefix_rep" "1")])
1872590286Sobrien
1872690286Sobrien(define_expand "strlensi"
1872752296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1872890286Sobrien	(unspec:SI [(match_operand:BLK 1 "general_operand" "")
1872990286Sobrien		    (match_operand:QI 2 "immediate_operand" "")
18730117404Skan		    (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
1873190286Sobrien  ""
1873290286Sobrien{
1873390286Sobrien if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
1873490286Sobrien   DONE;
1873590286Sobrien else
1873690286Sobrien   FAIL;
1873790286Sobrien})
1873890286Sobrien
1873990286Sobrien(define_expand "strlendi"
1874090286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1874190286Sobrien	(unspec:DI [(match_operand:BLK 1 "general_operand" "")
1874290286Sobrien		    (match_operand:QI 2 "immediate_operand" "")
18743117404Skan		    (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
1874490286Sobrien  ""
1874590286Sobrien{
1874690286Sobrien if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
1874790286Sobrien   DONE;
1874890286Sobrien else
1874990286Sobrien   FAIL;
1875090286Sobrien})
1875190286Sobrien
18752132727Skan(define_expand "strlenqi_1"
18753132727Skan  [(parallel [(set (match_operand 0 "register_operand" "") (match_operand 2 "" ""))
18754169699Skan	      (use (reg:SI DIRFLAG_REG))
18755132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18756169699Skan	      (clobber (reg:CC FLAGS_REG))])]
18757132727Skan  ""
18758132727Skan  "")
18759132727Skan
18760132727Skan(define_insn "*strlenqi_1"
1876190286Sobrien  [(set (match_operand:SI 0 "register_operand" "=&c")
1876290286Sobrien	(unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1"))
1876390286Sobrien		    (match_operand:QI 2 "register_operand" "a")
1876490286Sobrien		    (match_operand:SI 3 "immediate_operand" "i")
18765117404Skan		    (match_operand:SI 4 "register_operand" "0")] UNSPEC_SCAS))
18766169699Skan   (use (reg:SI DIRFLAG_REG))
1876790286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
18768169699Skan   (clobber (reg:CC FLAGS_REG))]
1876990286Sobrien  "!TARGET_64BIT"
1877090286Sobrien  "repnz{\;| }scasb"
1877190286Sobrien  [(set_attr "type" "str")
1877290286Sobrien   (set_attr "mode" "QI")
1877390286Sobrien   (set_attr "prefix_rep" "1")])
1877490286Sobrien
18775132727Skan(define_insn "*strlenqi_rex_1"
1877690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=&c")
1877790286Sobrien	(unspec:DI [(mem:BLK (match_operand:DI 5 "register_operand" "1"))
1877890286Sobrien		    (match_operand:QI 2 "register_operand" "a")
1877990286Sobrien		    (match_operand:DI 3 "immediate_operand" "i")
18780117404Skan		    (match_operand:DI 4 "register_operand" "0")] UNSPEC_SCAS))
18781169699Skan   (use (reg:SI DIRFLAG_REG))
1878290286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
18783169699Skan   (clobber (reg:CC FLAGS_REG))]
1878490286Sobrien  "TARGET_64BIT"
1878590286Sobrien  "repnz{\;| }scasb"
1878690286Sobrien  [(set_attr "type" "str")
1878790286Sobrien   (set_attr "mode" "QI")
1878890286Sobrien   (set_attr "prefix_rep" "1")])
1878990286Sobrien
18790169699Skan;; Peephole optimizations to clean up after cmpstrn*.  This should be
1879190286Sobrien;; handled in combine, but it is not currently up to the task.
18792169699Skan;; When used for their truth value, the cmpstrn* expanders generate
1879390286Sobrien;; code like this:
1879490286Sobrien;;
1879590286Sobrien;;   repz cmpsb
1879690286Sobrien;;   seta 	%al
1879790286Sobrien;;   setb 	%dl
1879890286Sobrien;;   cmpb 	%al, %dl
1879990286Sobrien;;   jcc	label
1880090286Sobrien;;
1880190286Sobrien;; The intermediate three instructions are unnecessary.
1880290286Sobrien
18803169699Skan;; This one handles cmpstrn*_nz_1...
1880490286Sobrien(define_peephole2
1880590286Sobrien  [(parallel[
18806169699Skan     (set (reg:CC FLAGS_REG)
1880790286Sobrien	  (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
1880890286Sobrien		      (mem:BLK (match_operand 5 "register_operand" ""))))
1880990286Sobrien     (use (match_operand 6 "register_operand" ""))
1881090286Sobrien     (use (match_operand:SI 3 "immediate_operand" ""))
18811169699Skan     (use (reg:SI DIRFLAG_REG))
1881290286Sobrien     (clobber (match_operand 0 "register_operand" ""))
1881390286Sobrien     (clobber (match_operand 1 "register_operand" ""))
1881490286Sobrien     (clobber (match_operand 2 "register_operand" ""))])
1881590286Sobrien   (set (match_operand:QI 7 "register_operand" "")
18816169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1881790286Sobrien   (set (match_operand:QI 8 "register_operand" "")
18818169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
18819169699Skan   (set (reg FLAGS_REG)
1882090286Sobrien	(compare (match_dup 7) (match_dup 8)))
1882190286Sobrien  ]
1882290286Sobrien  "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
1882390286Sobrien  [(parallel[
18824169699Skan     (set (reg:CC FLAGS_REG)
1882590286Sobrien	  (compare:CC (mem:BLK (match_dup 4))
1882690286Sobrien		      (mem:BLK (match_dup 5))))
1882790286Sobrien     (use (match_dup 6))
1882890286Sobrien     (use (match_dup 3))
18829169699Skan     (use (reg:SI DIRFLAG_REG))
1883090286Sobrien     (clobber (match_dup 0))
1883190286Sobrien     (clobber (match_dup 1))
1883290286Sobrien     (clobber (match_dup 2))])]
1883350650Sobrien  "")
1883450650Sobrien
18835169699Skan;; ...and this one handles cmpstrn*_1.
1883690286Sobrien(define_peephole2
1883790286Sobrien  [(parallel[
18838169699Skan     (set (reg:CC FLAGS_REG)
1883990286Sobrien	  (if_then_else:CC (ne (match_operand 6 "register_operand" "")
1884090286Sobrien			       (const_int 0))
1884190286Sobrien	    (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
1884290286Sobrien		        (mem:BLK (match_operand 5 "register_operand" "")))
1884390286Sobrien	    (const_int 0)))
1884490286Sobrien     (use (match_operand:SI 3 "immediate_operand" ""))
18845169699Skan     (use (reg:CC FLAGS_REG))
18846169699Skan     (use (reg:SI DIRFLAG_REG))
1884790286Sobrien     (clobber (match_operand 0 "register_operand" ""))
1884890286Sobrien     (clobber (match_operand 1 "register_operand" ""))
1884990286Sobrien     (clobber (match_operand 2 "register_operand" ""))])
1885090286Sobrien   (set (match_operand:QI 7 "register_operand" "")
18851169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1885290286Sobrien   (set (match_operand:QI 8 "register_operand" "")
18853169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
18854169699Skan   (set (reg FLAGS_REG)
1885590286Sobrien	(compare (match_dup 7) (match_dup 8)))
1885690286Sobrien  ]
1885790286Sobrien  "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
1885890286Sobrien  [(parallel[
18859169699Skan     (set (reg:CC FLAGS_REG)
1886090286Sobrien	  (if_then_else:CC (ne (match_dup 6)
1886190286Sobrien			       (const_int 0))
1886290286Sobrien	    (compare:CC (mem:BLK (match_dup 4))
1886390286Sobrien			(mem:BLK (match_dup 5)))
1886490286Sobrien	    (const_int 0)))
1886590286Sobrien     (use (match_dup 3))
18866169699Skan     (use (reg:CC FLAGS_REG))
18867169699Skan     (use (reg:SI DIRFLAG_REG))
1886890286Sobrien     (clobber (match_dup 0))
1886990286Sobrien     (clobber (match_dup 1))
1887090286Sobrien     (clobber (match_dup 2))])]
1887150650Sobrien  "")
1887250650Sobrien
1887390286Sobrien
1887490286Sobrien
1887590286Sobrien;; Conditional move instructions.
1887690286Sobrien
1887790286Sobrien(define_expand "movdicc"
1887890286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1887990286Sobrien	(if_then_else:DI (match_operand 1 "comparison_operator" "")
1888090286Sobrien			 (match_operand:DI 2 "general_operand" "")
1888190286Sobrien			 (match_operand:DI 3 "general_operand" "")))]
1888290286Sobrien  "TARGET_64BIT"
1888390286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1888490286Sobrien
1888590286Sobrien(define_insn "x86_movdicc_0_m1_rex64"
1888690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
18887132727Skan	(if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "")
1888890286Sobrien	  (const_int -1)
1888990286Sobrien	  (const_int 0)))
18890169699Skan   (clobber (reg:CC FLAGS_REG))]
1889190286Sobrien  "TARGET_64BIT"
1889290286Sobrien  "sbb{q}\t%0, %0"
1889390286Sobrien  ; Since we don't have the proper number of operands for an alu insn,
1889490286Sobrien  ; fill in all the blanks.
1889590286Sobrien  [(set_attr "type" "alu")
18896117404Skan   (set_attr "pent_pair" "pu")
1889790286Sobrien   (set_attr "memory" "none")
1889890286Sobrien   (set_attr "imm_disp" "false")
1889990286Sobrien   (set_attr "mode" "DI")
1890090286Sobrien   (set_attr "length_immediate" "0")])
1890190286Sobrien
18902169699Skan(define_insn "*movdicc_c_rex64"
1890390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1890490286Sobrien	(if_then_else:DI (match_operator 1 "ix86_comparison_operator" 
18905169699Skan				[(reg FLAGS_REG) (const_int 0)])
1890690286Sobrien		      (match_operand:DI 2 "nonimmediate_operand" "rm,0")
1890790286Sobrien		      (match_operand:DI 3 "nonimmediate_operand" "0,rm")))]
1890890286Sobrien  "TARGET_64BIT && TARGET_CMOVE
1890990286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1891090286Sobrien  "@
1891196294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1891296294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1891390286Sobrien  [(set_attr "type" "icmov")
1891490286Sobrien   (set_attr "mode" "DI")])
1891590286Sobrien
1891690286Sobrien(define_expand "movsicc"
1891790286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1891890286Sobrien	(if_then_else:SI (match_operand 1 "comparison_operator" "")
1891990286Sobrien			 (match_operand:SI 2 "general_operand" "")
1892090286Sobrien			 (match_operand:SI 3 "general_operand" "")))]
1892190286Sobrien  ""
1892290286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1892390286Sobrien
1892490286Sobrien;; Data flow gets confused by our desire for `sbbl reg,reg', and clearing
1892590286Sobrien;; the register first winds up with `sbbl $0,reg', which is also weird.
1892690286Sobrien;; So just document what we're doing explicitly.
1892790286Sobrien
1892890286Sobrien(define_insn "x86_movsicc_0_m1"
1892990286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
18930132727Skan	(if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "")
1893190286Sobrien	  (const_int -1)
1893290286Sobrien	  (const_int 0)))
18933169699Skan   (clobber (reg:CC FLAGS_REG))]
1893490286Sobrien  ""
1893590286Sobrien  "sbb{l}\t%0, %0"
1893690286Sobrien  ; Since we don't have the proper number of operands for an alu insn,
1893790286Sobrien  ; fill in all the blanks.
1893890286Sobrien  [(set_attr "type" "alu")
18939117404Skan   (set_attr "pent_pair" "pu")
1894090286Sobrien   (set_attr "memory" "none")
1894190286Sobrien   (set_attr "imm_disp" "false")
1894290286Sobrien   (set_attr "mode" "SI")
1894390286Sobrien   (set_attr "length_immediate" "0")])
1894490286Sobrien
1894590286Sobrien(define_insn "*movsicc_noc"
1894650650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
1894790286Sobrien	(if_then_else:SI (match_operator 1 "ix86_comparison_operator" 
18948169699Skan				[(reg FLAGS_REG) (const_int 0)])
1894950650Sobrien		      (match_operand:SI 2 "nonimmediate_operand" "rm,0")
1895050650Sobrien		      (match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
1895190286Sobrien  "TARGET_CMOVE
1895290286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1895390286Sobrien  "@
1895496294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1895596294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1895690286Sobrien  [(set_attr "type" "icmov")
1895790286Sobrien   (set_attr "mode" "SI")])
1895850650Sobrien
1895950650Sobrien(define_expand "movhicc"
1896050650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
1896150650Sobrien	(if_then_else:HI (match_operand 1 "comparison_operator" "")
18962132727Skan			 (match_operand:HI 2 "general_operand" "")
18963132727Skan			 (match_operand:HI 3 "general_operand" "")))]
18964132727Skan  "TARGET_HIMODE_MATH"
1896590286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1896650650Sobrien
1896790286Sobrien(define_insn "*movhicc_noc"
1896850650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
1896990286Sobrien	(if_then_else:HI (match_operator 1 "ix86_comparison_operator" 
18970169699Skan				[(reg FLAGS_REG) (const_int 0)])
1897150650Sobrien		      (match_operand:HI 2 "nonimmediate_operand" "rm,0")
1897250650Sobrien		      (match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
1897390286Sobrien  "TARGET_CMOVE
1897490286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1897590286Sobrien  "@
1897696294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1897796294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1897890286Sobrien  [(set_attr "type" "icmov")
1897990286Sobrien   (set_attr "mode" "HI")])
1898050650Sobrien
18981132727Skan(define_expand "movqicc"
18982132727Skan  [(set (match_operand:QI 0 "register_operand" "")
18983132727Skan	(if_then_else:QI (match_operand 1 "comparison_operator" "")
18984132727Skan			 (match_operand:QI 2 "general_operand" "")
18985132727Skan			 (match_operand:QI 3 "general_operand" "")))]
18986132727Skan  "TARGET_QIMODE_MATH"
18987132727Skan  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
18988132727Skan
18989132727Skan(define_insn_and_split "*movqicc_noc"
18990132727Skan  [(set (match_operand:QI 0 "register_operand" "=r,r")
18991132727Skan	(if_then_else:QI (match_operator 1 "ix86_comparison_operator" 
18992169699Skan				[(match_operand 4 "flags_reg_operand" "")
18993169699Skan				 (const_int 0)])
18994132727Skan		      (match_operand:QI 2 "register_operand" "r,0")
18995132727Skan		      (match_operand:QI 3 "register_operand" "0,r")))]
18996132727Skan  "TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL"
18997132727Skan  "#"
18998132727Skan  "&& reload_completed"
18999132727Skan  [(set (match_dup 0)
19000132727Skan	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
19001132727Skan		      (match_dup 2)
19002132727Skan		      (match_dup 3)))]
19003132727Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
19004132727Skan   operands[2] = gen_lowpart (SImode, operands[2]);
19005132727Skan   operands[3] = gen_lowpart (SImode, operands[3]);"
19006132727Skan  [(set_attr "type" "icmov")
19007132727Skan   (set_attr "mode" "SI")])
19008132727Skan
1900950650Sobrien(define_expand "movsfcc"
1901050650Sobrien  [(set (match_operand:SF 0 "register_operand" "")
1901150650Sobrien	(if_then_else:SF (match_operand 1 "comparison_operator" "")
1901250650Sobrien			 (match_operand:SF 2 "register_operand" "")
1901350650Sobrien			 (match_operand:SF 3 "register_operand" "")))]
19014169699Skan  "(TARGET_80387 && TARGET_CMOVE) || TARGET_SSE_MATH"
1901590286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1901650650Sobrien
19017169699Skan(define_insn "*movsfcc_1_387"
19018169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f,r,r")
1901990286Sobrien	(if_then_else:SF (match_operator 1 "fcmov_comparison_operator" 
19020169699Skan				[(reg FLAGS_REG) (const_int 0)])
19021169699Skan		      (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0")
19022169699Skan		      (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))]
19023169699Skan  "TARGET_80387 && TARGET_CMOVE
1902490286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1902590286Sobrien  "@
1902690286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1902790286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1902896294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1902996294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1903090286Sobrien  [(set_attr "type" "fcmov,fcmov,icmov,icmov")
1903190286Sobrien   (set_attr "mode" "SF,SF,SI,SI")])
1903250650Sobrien
1903390286Sobrien(define_expand "movdfcc"
1903490286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
1903590286Sobrien	(if_then_else:DF (match_operand 1 "comparison_operator" "")
1903690286Sobrien			 (match_operand:DF 2 "register_operand" "")
1903790286Sobrien			 (match_operand:DF 3 "register_operand" "")))]
19038169699Skan  "(TARGET_80387 && TARGET_CMOVE) || (TARGET_SSE2 && TARGET_SSE_MATH)"
1903990286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1904050650Sobrien
1904190286Sobrien(define_insn "*movdfcc_1"
19042169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r")
1904390286Sobrien	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
19044169699Skan				[(reg FLAGS_REG) (const_int 0)])
19045169699Skan		      (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
19046169699Skan		      (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
19047169699Skan  "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
1904890286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1904990286Sobrien  "@
1905090286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1905190286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1905290286Sobrien   #
1905390286Sobrien   #"
1905490286Sobrien  [(set_attr "type" "fcmov,fcmov,multi,multi")
1905590286Sobrien   (set_attr "mode" "DF")])
1905650650Sobrien
1905790286Sobrien(define_insn "*movdfcc_1_rex64"
19058169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,r,r")
1905990286Sobrien	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
19060169699Skan				[(reg FLAGS_REG) (const_int 0)])
19061169699Skan		      (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
19062169699Skan		      (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
19063169699Skan  "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
1906490286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1906590286Sobrien  "@
1906690286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1906790286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1906896294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1906996294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1907090286Sobrien  [(set_attr "type" "fcmov,fcmov,icmov,icmov")
1907190286Sobrien   (set_attr "mode" "DF")])
1907250650Sobrien
1907390286Sobrien(define_split
19074117404Skan  [(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "")
1907590286Sobrien	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
19076169699Skan				[(match_operand 4 "flags_reg_operand" "")
19077169699Skan				 (const_int 0)])
1907890286Sobrien		      (match_operand:DF 2 "nonimmediate_operand" "")
1907990286Sobrien		      (match_operand:DF 3 "nonimmediate_operand" "")))]
19080117404Skan  "!TARGET_64BIT && reload_completed"
1908190286Sobrien  [(set (match_dup 2)
1908290286Sobrien	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
1908390286Sobrien		      (match_dup 5)
1908490286Sobrien		      (match_dup 7)))
1908590286Sobrien   (set (match_dup 3)
1908690286Sobrien	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
1908790286Sobrien		      (match_dup 6)
1908890286Sobrien		      (match_dup 8)))]
1908990286Sobrien  "split_di (operands+2, 1, operands+5, operands+6);
1909090286Sobrien   split_di (operands+3, 1, operands+7, operands+8);
1909190286Sobrien   split_di (operands, 1, operands+2, operands+3);")
1909250650Sobrien
1909390286Sobrien(define_expand "movxfcc"
1909490286Sobrien  [(set (match_operand:XF 0 "register_operand" "")
1909590286Sobrien	(if_then_else:XF (match_operand 1 "comparison_operator" "")
1909690286Sobrien			 (match_operand:XF 2 "register_operand" "")
1909790286Sobrien			 (match_operand:XF 3 "register_operand" "")))]
19098169699Skan  "TARGET_80387 && TARGET_CMOVE"
1909990286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1910090286Sobrien
1910190286Sobrien(define_insn "*movxfcc_1"
1910290286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1910390286Sobrien	(if_then_else:XF (match_operator 1 "fcmov_comparison_operator" 
19104169699Skan				[(reg FLAGS_REG) (const_int 0)])
1910590286Sobrien		      (match_operand:XF 2 "register_operand" "f,0")
1910690286Sobrien		      (match_operand:XF 3 "register_operand" "0,f")))]
19107169699Skan  "TARGET_80387 && TARGET_CMOVE"
1910890286Sobrien  "@
1910990286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1911090286Sobrien   fcmov%f1\t{%3, %0|%0, %3}"
1911190286Sobrien  [(set_attr "type" "fcmov")
1911290286Sobrien   (set_attr "mode" "XF")])
1911390286Sobrien
19114169699Skan;; These versions of the min/max patterns are intentionally ignorant of
19115169699Skan;; their behavior wrt -0.0 and NaN (via the commutative operand mark).
19116169699Skan;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
19117169699Skan;; are undefined in this condition, we're certain this is correct.
1911890286Sobrien
19119169699Skan(define_insn "sminsf3"
19120169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19121169699Skan	(smin:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
19122169699Skan		 (match_operand:SF 2 "nonimmediate_operand" "xm")))]
19123169699Skan  "TARGET_SSE_MATH"
19124169699Skan  "minss\t{%2, %0|%0, %2}"
19125169699Skan  [(set_attr "type" "sseadd")
19126169699Skan   (set_attr "mode" "SF")])
1912750650Sobrien
19128169699Skan(define_insn "smaxsf3"
19129169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19130169699Skan	(smax:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
19131169699Skan		 (match_operand:SF 2 "nonimmediate_operand" "xm")))]
19132169699Skan  "TARGET_SSE_MATH"
19133169699Skan  "maxss\t{%2, %0|%0, %2}"
19134169699Skan  [(set_attr "type" "sseadd")
19135169699Skan   (set_attr "mode" "SF")])
1913650650Sobrien
19137169699Skan(define_insn "smindf3"
19138169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19139169699Skan	(smin:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
19140169699Skan		 (match_operand:DF 2 "nonimmediate_operand" "xm")))]
19141169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19142169699Skan  "minsd\t{%2, %0|%0, %2}"
19143169699Skan  [(set_attr "type" "sseadd")
19144169699Skan   (set_attr "mode" "DF")])
1914550650Sobrien
19146169699Skan(define_insn "smaxdf3"
19147169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19148169699Skan	(smax:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
19149169699Skan		 (match_operand:DF 2 "nonimmediate_operand" "xm")))]
19150169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19151169699Skan  "maxsd\t{%2, %0|%0, %2}"
19152169699Skan  [(set_attr "type" "sseadd")
19153169699Skan   (set_attr "mode" "DF")])
19154169699Skan
19155169699Skan;; These versions of the min/max patterns implement exactly the operations
19156169699Skan;;   min = (op1 < op2 ? op1 : op2)
19157169699Skan;;   max = (!(op1 < op2) ? op1 : op2)
19158169699Skan;; Their operands are not commutative, and thus they may be used in the
19159169699Skan;; presence of -0.0 and NaN.
19160169699Skan
19161169699Skan(define_insn "*ieee_sminsf3"
19162169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19163169699Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")
19164169699Skan		    (match_operand:SF 2 "nonimmediate_operand" "xm")]
19165169699Skan		   UNSPEC_IEEE_MIN))]
19166169699Skan  "TARGET_SSE_MATH"
19167169699Skan  "minss\t{%2, %0|%0, %2}"
19168169699Skan  [(set_attr "type" "sseadd")
19169169699Skan   (set_attr "mode" "SF")])
19170169699Skan
19171169699Skan(define_insn "*ieee_smaxsf3"
19172169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19173169699Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")
19174169699Skan		    (match_operand:SF 2 "nonimmediate_operand" "xm")]
19175169699Skan		   UNSPEC_IEEE_MAX))]
19176169699Skan  "TARGET_SSE_MATH"
19177169699Skan  "maxss\t{%2, %0|%0, %2}"
19178169699Skan  [(set_attr "type" "sseadd")
19179169699Skan   (set_attr "mode" "SF")])
19180169699Skan
19181169699Skan(define_insn "*ieee_smindf3"
19182169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19183169699Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")
19184169699Skan		    (match_operand:DF 2 "nonimmediate_operand" "xm")]
19185169699Skan		   UNSPEC_IEEE_MIN))]
19186169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19187169699Skan  "minsd\t{%2, %0|%0, %2}"
19188169699Skan  [(set_attr "type" "sseadd")
19189169699Skan   (set_attr "mode" "DF")])
19190169699Skan
19191169699Skan(define_insn "*ieee_smaxdf3"
19192169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19193169699Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")
19194169699Skan		    (match_operand:DF 2 "nonimmediate_operand" "xm")]
19195169699Skan		   UNSPEC_IEEE_MAX))]
19196169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19197169699Skan  "maxsd\t{%2, %0|%0, %2}"
19198169699Skan  [(set_attr "type" "sseadd")
19199169699Skan   (set_attr "mode" "DF")])
19200169699Skan
19201169699Skan;; Make two stack loads independent:
19202169699Skan;;   fld aa              fld aa
19203169699Skan;;   fld %st(0)     ->   fld bb
19204169699Skan;;   fmul bb             fmul %st(1), %st
19205169699Skan;;
19206169699Skan;; Actually we only match the last two instructions for simplicity.
19207169699Skan(define_peephole2
19208169699Skan  [(set (match_operand 0 "fp_register_operand" "")
19209169699Skan	(match_operand 1 "fp_register_operand" ""))
19210169699Skan   (set (match_dup 0)
19211169699Skan	(match_operator 2 "binary_fp_operator"
19212169699Skan	   [(match_dup 0)
19213169699Skan	    (match_operand 3 "memory_operand" "")]))]
19214169699Skan  "REGNO (operands[0]) != REGNO (operands[1])"
19215169699Skan  [(set (match_dup 0) (match_dup 3))
19216169699Skan   (set (match_dup 0) (match_dup 4))]
19217169699Skan
19218169699Skan  ;; The % modifier is not operational anymore in peephole2's, so we have to
19219169699Skan  ;; swap the operands manually in the case of addition and multiplication.
19220169699Skan  "if (COMMUTATIVE_ARITH_P (operands[2]))
19221169699Skan     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
19222169699Skan				 operands[0], operands[1]);
19223169699Skan   else
19224169699Skan     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
19225169699Skan				 operands[1], operands[0]);")
19226169699Skan
19227132727Skan;; Conditional addition patterns
19228132727Skan(define_expand "addqicc"
19229132727Skan  [(match_operand:QI 0 "register_operand" "")
19230132727Skan   (match_operand 1 "comparison_operator" "")
19231132727Skan   (match_operand:QI 2 "register_operand" "")
19232132727Skan   (match_operand:QI 3 "const_int_operand" "")]
19233132727Skan  ""
19234132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19235132727Skan
19236132727Skan(define_expand "addhicc"
19237132727Skan  [(match_operand:HI 0 "register_operand" "")
19238132727Skan   (match_operand 1 "comparison_operator" "")
19239132727Skan   (match_operand:HI 2 "register_operand" "")
19240132727Skan   (match_operand:HI 3 "const_int_operand" "")]
19241132727Skan  ""
19242132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19243132727Skan
19244132727Skan(define_expand "addsicc"
19245132727Skan  [(match_operand:SI 0 "register_operand" "")
19246132727Skan   (match_operand 1 "comparison_operator" "")
19247132727Skan   (match_operand:SI 2 "register_operand" "")
19248132727Skan   (match_operand:SI 3 "const_int_operand" "")]
19249132727Skan  ""
19250132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19251132727Skan
19252132727Skan(define_expand "adddicc"
19253132727Skan  [(match_operand:DI 0 "register_operand" "")
19254132727Skan   (match_operand 1 "comparison_operator" "")
19255132727Skan   (match_operand:DI 2 "register_operand" "")
19256132727Skan   (match_operand:DI 3 "const_int_operand" "")]
19257132727Skan  "TARGET_64BIT"
19258132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19259132727Skan
1926090286Sobrien
1926190286Sobrien;; Misc patterns (?)
1926250650Sobrien
1926390286Sobrien;; This pattern exists to put a dependency on all ebp-based memory accesses.
1926490286Sobrien;; Otherwise there will be nothing to keep
1926590286Sobrien;; 
1926690286Sobrien;; [(set (reg ebp) (reg esp))]
1926790286Sobrien;; [(set (reg esp) (plus (reg esp) (const_int -160000)))
1926890286Sobrien;;  (clobber (eflags)]
1926990286Sobrien;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))]
1927090286Sobrien;;
1927190286Sobrien;; in proper program order.
19272132727Skan(define_insn "pro_epilogue_adjust_stack_1"
1927390286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
1927490286Sobrien	(plus:SI (match_operand:SI 1 "register_operand" "0,r")
1927590286Sobrien	         (match_operand:SI 2 "immediate_operand" "i,i")))
19276169699Skan   (clobber (reg:CC FLAGS_REG))
1927790286Sobrien   (clobber (mem:BLK (scratch)))]
1927890286Sobrien  "!TARGET_64BIT"
1927990286Sobrien{
1928090286Sobrien  switch (get_attr_type (insn))
1928190286Sobrien    {
1928290286Sobrien    case TYPE_IMOV:
1928390286Sobrien      return "mov{l}\t{%1, %0|%0, %1}";
1928450650Sobrien
1928590286Sobrien    case TYPE_ALU:
1928690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
1928790286Sobrien          && (INTVAL (operands[2]) == 128
1928890286Sobrien	      || (INTVAL (operands[2]) < 0
1928990286Sobrien	          && INTVAL (operands[2]) != -128)))
1929090286Sobrien	{
1929190286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
1929290286Sobrien	  return "sub{l}\t{%2, %0|%0, %2}";
1929390286Sobrien	}
1929490286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
1929550650Sobrien
1929690286Sobrien    case TYPE_LEA:
1929790286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
1929890286Sobrien      return "lea{l}\t{%a2, %0|%0, %a2}";
1929990286Sobrien
1930090286Sobrien    default:
19301169699Skan      gcc_unreachable ();
1930290286Sobrien    }
1930390286Sobrien}
1930490286Sobrien  [(set (attr "type")
1930590286Sobrien	(cond [(eq_attr "alternative" "0")
1930690286Sobrien		 (const_string "alu")
1930790286Sobrien	       (match_operand:SI 2 "const0_operand" "")
1930890286Sobrien		 (const_string "imov")
1930990286Sobrien	      ]
1931090286Sobrien	      (const_string "lea")))
1931190286Sobrien   (set_attr "mode" "SI")])
1931290286Sobrien
1931390286Sobrien(define_insn "pro_epilogue_adjust_stack_rex64"
1931490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1931590286Sobrien	(plus:DI (match_operand:DI 1 "register_operand" "0,r")
1931690286Sobrien		 (match_operand:DI 2 "x86_64_immediate_operand" "e,e")))
19317169699Skan   (clobber (reg:CC FLAGS_REG))
1931890286Sobrien   (clobber (mem:BLK (scratch)))]
1931990286Sobrien  "TARGET_64BIT"
1932090286Sobrien{
1932190286Sobrien  switch (get_attr_type (insn))
1932250650Sobrien    {
1932390286Sobrien    case TYPE_IMOV:
1932490286Sobrien      return "mov{q}\t{%1, %0|%0, %1}";
1932550650Sobrien
1932690286Sobrien    case TYPE_ALU:
1932790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
19328132727Skan	  /* Avoid overflows.  */
19329132727Skan	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
1933090286Sobrien          && (INTVAL (operands[2]) == 128
1933190286Sobrien	      || (INTVAL (operands[2]) < 0
1933290286Sobrien	          && INTVAL (operands[2]) != -128)))
1933390286Sobrien	{
1933490286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
1933590286Sobrien	  return "sub{q}\t{%2, %0|%0, %2}";
1933690286Sobrien	}
1933790286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
1933850650Sobrien
1933990286Sobrien    case TYPE_LEA:
1934090286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
1934190286Sobrien      return "lea{q}\t{%a2, %0|%0, %a2}";
1934250650Sobrien
1934350650Sobrien    default:
19344169699Skan      gcc_unreachable ();
1934550650Sobrien    }
1934690286Sobrien}
1934790286Sobrien  [(set (attr "type")
1934890286Sobrien	(cond [(eq_attr "alternative" "0")
1934990286Sobrien		 (const_string "alu")
1935090286Sobrien	       (match_operand:DI 2 "const0_operand" "")
1935190286Sobrien		 (const_string "imov")
1935290286Sobrien	      ]
1935390286Sobrien	      (const_string "lea")))
1935490286Sobrien   (set_attr "mode" "DI")])
1935550650Sobrien
19356132727Skan(define_insn "pro_epilogue_adjust_stack_rex64_2"
19357132727Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
19358132727Skan	(plus:DI (match_operand:DI 1 "register_operand" "0,r")
19359132727Skan		 (match_operand:DI 3 "immediate_operand" "i,i")))
19360132727Skan   (use (match_operand:DI 2 "register_operand" "r,r"))
19361169699Skan   (clobber (reg:CC FLAGS_REG))
19362132727Skan   (clobber (mem:BLK (scratch)))]
19363132727Skan  "TARGET_64BIT"
19364132727Skan{
19365132727Skan  switch (get_attr_type (insn))
19366132727Skan    {
19367132727Skan    case TYPE_ALU:
19368132727Skan      return "add{q}\t{%2, %0|%0, %2}";
1936990286Sobrien
19370132727Skan    case TYPE_LEA:
19371132727Skan      operands[2] = gen_rtx_PLUS (DImode, operands[1], operands[2]);
19372132727Skan      return "lea{q}\t{%a2, %0|%0, %a2}";
19373132727Skan
19374132727Skan    default:
19375169699Skan      gcc_unreachable ();
19376132727Skan    }
19377132727Skan}
19378132727Skan  [(set_attr "type" "alu,lea")
19379132727Skan   (set_attr "mode" "DI")])
19380132727Skan
1938190286Sobrien(define_expand "allocate_stack_worker"
1938290286Sobrien  [(match_operand:SI 0 "register_operand" "")]
1938390286Sobrien  "TARGET_STACK_PROBE"
1938490286Sobrien{
19385132727Skan  if (reload_completed)
19386132727Skan    {
19387132727Skan      if (TARGET_64BIT)
19388132727Skan	emit_insn (gen_allocate_stack_worker_rex64_postreload (operands[0]));
19389132727Skan      else
19390132727Skan	emit_insn (gen_allocate_stack_worker_postreload (operands[0]));
19391132727Skan    }
1939290286Sobrien  else
19393132727Skan    {
19394132727Skan      if (TARGET_64BIT)
19395132727Skan	emit_insn (gen_allocate_stack_worker_rex64 (operands[0]));
19396132727Skan      else
19397132727Skan	emit_insn (gen_allocate_stack_worker_1 (operands[0]));
19398132727Skan    }
1939990286Sobrien  DONE;
1940090286Sobrien})
1940150650Sobrien
1940290286Sobrien(define_insn "allocate_stack_worker_1"
19403132727Skan  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
19404132727Skan    UNSPECV_STACK_PROBE)
19405169699Skan   (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
19406132727Skan   (clobber (match_scratch:SI 1 "=0"))
19407169699Skan   (clobber (reg:CC FLAGS_REG))]
1940890286Sobrien  "!TARGET_64BIT && TARGET_STACK_PROBE"
1940990286Sobrien  "call\t__alloca"
1941090286Sobrien  [(set_attr "type" "multi")
1941190286Sobrien   (set_attr "length" "5")])
1941250650Sobrien
19413132727Skan(define_expand "allocate_stack_worker_postreload"
19414132727Skan  [(parallel [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
19415132727Skan				    UNSPECV_STACK_PROBE)
19416169699Skan	      (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
19417132727Skan	      (clobber (match_dup 0))
19418169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19419132727Skan  ""
19420132727Skan  "")
19421132727Skan
1942290286Sobrien(define_insn "allocate_stack_worker_rex64"
19423132727Skan  [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
19424132727Skan    UNSPECV_STACK_PROBE)
19425169699Skan   (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
19426132727Skan   (clobber (match_scratch:DI 1 "=0"))
19427169699Skan   (clobber (reg:CC FLAGS_REG))]
1942890286Sobrien  "TARGET_64BIT && TARGET_STACK_PROBE"
1942990286Sobrien  "call\t__alloca"
1943090286Sobrien  [(set_attr "type" "multi")
1943190286Sobrien   (set_attr "length" "5")])
1943290286Sobrien
19433132727Skan(define_expand "allocate_stack_worker_rex64_postreload"
19434132727Skan  [(parallel [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
19435132727Skan				    UNSPECV_STACK_PROBE)
19436169699Skan	      (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
19437132727Skan	      (clobber (match_dup 0))
19438169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19439132727Skan  ""
19440132727Skan  "")
19441132727Skan
1944250650Sobrien(define_expand "allocate_stack"
1944390286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
19444169699Skan		   (minus:SI (reg:SI SP_REG)
1944590286Sobrien			     (match_operand:SI 1 "general_operand" "")))
19446169699Skan	      (clobber (reg:CC FLAGS_REG))])
19447169699Skan   (parallel [(set (reg:SI SP_REG)
19448169699Skan		   (minus:SI (reg:SI SP_REG) (match_dup 1)))
19449169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1945090286Sobrien  "TARGET_STACK_PROBE"
1945150650Sobrien{
1945250650Sobrien#ifdef CHECK_STACK_LIMIT
1945350650Sobrien  if (GET_CODE (operands[1]) == CONST_INT
1945450650Sobrien      && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
1945550650Sobrien    emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
1945650650Sobrien			   operands[1]));
1945750650Sobrien  else 
1945850650Sobrien#endif
1945950650Sobrien    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
1946050650Sobrien							    operands[1])));
1946150650Sobrien
1946250650Sobrien  emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
1946350650Sobrien  DONE;
1946490286Sobrien})
1946550650Sobrien
1946690286Sobrien(define_expand "builtin_setjmp_receiver"
1946790286Sobrien  [(label_ref (match_operand 0 "" ""))]
1946890286Sobrien  "!TARGET_64BIT && flag_pic"
1946950650Sobrien{
19470169699Skan  if (TARGET_MACHO)
19471169699Skan    {
19472169699Skan      rtx xops[3];
19473169699Skan      rtx picreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
19474169699Skan      rtx label_rtx = gen_label_rtx ();
19475169699Skan      emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx));
19476169699Skan      xops[0] = xops[1] = picreg;
19477169699Skan      xops[2] = gen_rtx_CONST (SImode,
19478169699Skan	          gen_rtx_MINUS (SImode,
19479169699Skan		    gen_rtx_LABEL_REF (SImode, label_rtx),
19480169699Skan		    gen_rtx_SYMBOL_REF (SImode, GOT_SYMBOL_NAME)));
19481169699Skan      ix86_expand_binary_operator (MINUS, SImode, xops);
19482169699Skan    }
19483169699Skan  else
19484169699Skan    emit_insn (gen_set_got (pic_offset_table_rtx));
1948556391Sobrien  DONE;
1948690286Sobrien})
1948790286Sobrien
1948890286Sobrien;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
1948956391Sobrien
1949090286Sobrien(define_split
1949190286Sobrien  [(set (match_operand 0 "register_operand" "")
1949290286Sobrien	(match_operator 3 "promotable_binary_operator"
1949390286Sobrien	   [(match_operand 1 "register_operand" "")
1949490286Sobrien	    (match_operand 2 "aligned_operand" "")]))
19495169699Skan   (clobber (reg:CC FLAGS_REG))]
1949690286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1949790286Sobrien   && ((GET_MODE (operands[0]) == HImode 
19498117404Skan	&& ((!optimize_size && !TARGET_FAST_PREFIX)
19499169699Skan            /* ??? next two lines just !satisfies_constraint_K (...) */
19500117404Skan	    || GET_CODE (operands[2]) != CONST_INT
19501169699Skan	    || satisfies_constraint_K (operands[2])))
1950290286Sobrien       || (GET_MODE (operands[0]) == QImode 
1950390286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1950490286Sobrien  [(parallel [(set (match_dup 0)
1950590286Sobrien		   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
19506169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1950790286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1950890286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);
1950990286Sobrien   if (GET_CODE (operands[3]) != ASHIFT)
1951090286Sobrien     operands[2] = gen_lowpart (SImode, operands[2]);
1951190286Sobrien   PUT_MODE (operands[3], SImode);")
1951290286Sobrien
19513117404Skan; Promote the QImode tests, as i386 has encoding of the AND
19514117404Skan; instruction with 32-bit sign-extended immediate and thus the
19515117404Skan; instruction size is unchanged, except in the %eax case for
19516117404Skan; which it is increased by one byte, hence the ! optimize_size.
1951790286Sobrien(define_split
19518146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19519146906Skan	(match_operator 2 "compare_operator"
19520146906Skan	  [(and (match_operand 3 "aligned_operand" "")
19521146906Skan		(match_operand 4 "const_int_operand" ""))
19522146906Skan	   (const_int 0)]))
19523146906Skan   (set (match_operand 1 "register_operand" "")
19524146906Skan	(and (match_dup 3) (match_dup 4)))]
1952590286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
19526117404Skan   /* Ensure that the operand will remain sign-extended immediate.  */
19527146906Skan   && ix86_match_ccmode (insn, INTVAL (operands[4]) >= 0 ? CCNOmode : CCZmode)
19528117404Skan   && ! optimize_size
19529146906Skan   && ((GET_MODE (operands[1]) == HImode && ! TARGET_FAST_PREFIX)
19530146906Skan       || (GET_MODE (operands[1]) == QImode && TARGET_PROMOTE_QImode))"
19531146906Skan  [(parallel [(set (match_dup 0)
19532146906Skan		   (match_op_dup 2 [(and:SI (match_dup 3) (match_dup 4))
19533146906Skan			            (const_int 0)]))
19534146906Skan	      (set (match_dup 1)
19535146906Skan		   (and:SI (match_dup 3) (match_dup 4)))])]
19536146906Skan{
19537146906Skan  operands[4]
19538146906Skan    = gen_int_mode (INTVAL (operands[4])
19539146906Skan		    & GET_MODE_MASK (GET_MODE (operands[1])), SImode);
19540146906Skan  operands[1] = gen_lowpart (SImode, operands[1]);
19541146906Skan  operands[3] = gen_lowpart (SImode, operands[3]);
19542146906Skan})
1954390286Sobrien
19544117404Skan; Don't promote the QImode tests, as i386 doesn't have encoding of
19545117404Skan; the TEST instruction with 32-bit sign-extended immediate and thus
19546117404Skan; the instruction size would at least double, which is not what we
19547117404Skan; want even with ! optimize_size.
1954890286Sobrien(define_split
19549146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19550146906Skan	(match_operator 1 "compare_operator"
19551146906Skan	  [(and (match_operand:HI 2 "aligned_operand" "")
19552146906Skan		(match_operand:HI 3 "const_int_operand" ""))
19553146906Skan	   (const_int 0)]))]
1955490286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
19555117404Skan   /* Ensure that the operand will remain sign-extended immediate.  */
19556146906Skan   && ix86_match_ccmode (insn, INTVAL (operands[3]) >= 0 ? CCNOmode : CCZmode)
19557117404Skan   && ! TARGET_FAST_PREFIX
19558117404Skan   && ! optimize_size"
19559146906Skan  [(set (match_dup 0)
19560146906Skan	(match_op_dup 1 [(and:SI (match_dup 2) (match_dup 3))
19561146906Skan		         (const_int 0)]))]
19562146906Skan{
19563146906Skan  operands[3]
19564146906Skan    = gen_int_mode (INTVAL (operands[3])
19565146906Skan		    & GET_MODE_MASK (GET_MODE (operands[2])), SImode);
19566146906Skan  operands[2] = gen_lowpart (SImode, operands[2]);
19567146906Skan})
1956890286Sobrien
1956990286Sobrien(define_split
1957090286Sobrien  [(set (match_operand 0 "register_operand" "")
1957190286Sobrien	(neg (match_operand 1 "register_operand" "")))
19572169699Skan   (clobber (reg:CC FLAGS_REG))]
1957390286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1957490286Sobrien   && (GET_MODE (operands[0]) == HImode
1957590286Sobrien       || (GET_MODE (operands[0]) == QImode 
1957690286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1957790286Sobrien  [(parallel [(set (match_dup 0)
1957890286Sobrien		   (neg:SI (match_dup 1)))
19579169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1958090286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1958190286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);")
1958290286Sobrien
1958390286Sobrien(define_split
1958490286Sobrien  [(set (match_operand 0 "register_operand" "")
1958590286Sobrien	(not (match_operand 1 "register_operand" "")))]
1958690286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1958790286Sobrien   && (GET_MODE (operands[0]) == HImode
1958890286Sobrien       || (GET_MODE (operands[0]) == QImode 
1958990286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1959090286Sobrien  [(set (match_dup 0)
1959190286Sobrien	(not:SI (match_dup 1)))]
1959290286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1959390286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);")
1959490286Sobrien
1959590286Sobrien(define_split 
1959690286Sobrien  [(set (match_operand 0 "register_operand" "")
1959790286Sobrien	(if_then_else (match_operator 1 "comparison_operator" 
19598169699Skan				[(reg FLAGS_REG) (const_int 0)])
1959990286Sobrien		      (match_operand 2 "register_operand" "")
1960090286Sobrien		      (match_operand 3 "register_operand" "")))]
1960190286Sobrien  "! TARGET_PARTIAL_REG_STALL && TARGET_CMOVE
1960290286Sobrien   && (GET_MODE (operands[0]) == HImode
1960390286Sobrien       || (GET_MODE (operands[0]) == QImode 
1960490286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1960590286Sobrien  [(set (match_dup 0)
1960690286Sobrien	(if_then_else:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
1960790286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1960890286Sobrien   operands[2] = gen_lowpart (SImode, operands[2]);
1960990286Sobrien   operands[3] = gen_lowpart (SImode, operands[3]);")
1961090286Sobrien			
1961190286Sobrien
1961290286Sobrien;; RTL Peephole optimizations, run before sched2.  These primarily look to
1961390286Sobrien;; transform a complex memory operation into two memory to register operations.
1961490286Sobrien
1961590286Sobrien;; Don't push memory operands
1961690286Sobrien(define_peephole2
1961790286Sobrien  [(set (match_operand:SI 0 "push_operand" "")
1961890286Sobrien	(match_operand:SI 1 "memory_operand" ""))
1961990286Sobrien   (match_scratch:SI 2 "r")]
19620169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19621169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1962290286Sobrien  [(set (match_dup 2) (match_dup 1))
1962390286Sobrien   (set (match_dup 0) (match_dup 2))]
1962490286Sobrien  "")
1962590286Sobrien
1962690286Sobrien(define_peephole2
1962790286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
1962890286Sobrien	(match_operand:DI 1 "memory_operand" ""))
1962990286Sobrien   (match_scratch:DI 2 "r")]
19630169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19631169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1963290286Sobrien  [(set (match_dup 2) (match_dup 1))
1963390286Sobrien   (set (match_dup 0) (match_dup 2))]
1963490286Sobrien  "")
1963590286Sobrien
1963690286Sobrien;; We need to handle SFmode only, because DFmode and XFmode is split to
1963790286Sobrien;; SImode pushes.
1963890286Sobrien(define_peephole2
1963990286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
1964090286Sobrien	(match_operand:SF 1 "memory_operand" ""))
1964190286Sobrien   (match_scratch:SF 2 "r")]
19642169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19643169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1964490286Sobrien  [(set (match_dup 2) (match_dup 1))
1964590286Sobrien   (set (match_dup 0) (match_dup 2))]
1964690286Sobrien  "")
1964790286Sobrien
1964890286Sobrien(define_peephole2
1964990286Sobrien  [(set (match_operand:HI 0 "push_operand" "")
1965090286Sobrien	(match_operand:HI 1 "memory_operand" ""))
1965190286Sobrien   (match_scratch:HI 2 "r")]
19652169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19653169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1965490286Sobrien  [(set (match_dup 2) (match_dup 1))
1965590286Sobrien   (set (match_dup 0) (match_dup 2))]
1965690286Sobrien  "")
1965790286Sobrien
1965890286Sobrien(define_peephole2
1965990286Sobrien  [(set (match_operand:QI 0 "push_operand" "")
1966090286Sobrien	(match_operand:QI 1 "memory_operand" ""))
1966190286Sobrien   (match_scratch:QI 2 "q")]
19662169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19663169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1966490286Sobrien  [(set (match_dup 2) (match_dup 1))
1966590286Sobrien   (set (match_dup 0) (match_dup 2))]
1966690286Sobrien  "")
1966790286Sobrien
1966890286Sobrien;; Don't move an immediate directly to memory when the instruction
1966990286Sobrien;; gets too big.
1967090286Sobrien(define_peephole2
1967190286Sobrien  [(match_scratch:SI 1 "r")
1967290286Sobrien   (set (match_operand:SI 0 "memory_operand" "")
1967390286Sobrien        (const_int 0))]
1967490286Sobrien  "! optimize_size
1967590286Sobrien   && ! TARGET_USE_MOV0
1967690286Sobrien   && TARGET_SPLIT_LONG_MOVES
1967790286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1967890286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1967990286Sobrien  [(parallel [(set (match_dup 1) (const_int 0))
19680169699Skan	      (clobber (reg:CC FLAGS_REG))])
1968190286Sobrien   (set (match_dup 0) (match_dup 1))]
1968290286Sobrien  "")
1968390286Sobrien
1968490286Sobrien(define_peephole2
1968590286Sobrien  [(match_scratch:HI 1 "r")
1968690286Sobrien   (set (match_operand:HI 0 "memory_operand" "")
1968790286Sobrien        (const_int 0))]
1968890286Sobrien  "! optimize_size
1968990286Sobrien   && ! TARGET_USE_MOV0
1969090286Sobrien   && TARGET_SPLIT_LONG_MOVES
1969190286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1969290286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1969390286Sobrien  [(parallel [(set (match_dup 2) (const_int 0))
19694169699Skan	      (clobber (reg:CC FLAGS_REG))])
1969590286Sobrien   (set (match_dup 0) (match_dup 1))]
19696132727Skan  "operands[2] = gen_lowpart (SImode, operands[1]);")
1969790286Sobrien
1969890286Sobrien(define_peephole2
1969990286Sobrien  [(match_scratch:QI 1 "q")
1970090286Sobrien   (set (match_operand:QI 0 "memory_operand" "")
1970190286Sobrien        (const_int 0))]
1970290286Sobrien  "! optimize_size
1970390286Sobrien   && ! TARGET_USE_MOV0
1970490286Sobrien   && TARGET_SPLIT_LONG_MOVES
1970590286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1970690286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1970790286Sobrien  [(parallel [(set (match_dup 2) (const_int 0))
19708169699Skan	      (clobber (reg:CC FLAGS_REG))])
1970990286Sobrien   (set (match_dup 0) (match_dup 1))]
19710132727Skan  "operands[2] = gen_lowpart (SImode, operands[1]);")
1971190286Sobrien
1971290286Sobrien(define_peephole2
1971390286Sobrien  [(match_scratch:SI 2 "r")
1971490286Sobrien   (set (match_operand:SI 0 "memory_operand" "")
1971590286Sobrien        (match_operand:SI 1 "immediate_operand" ""))]
1971690286Sobrien  "! optimize_size
1971790286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1971890286Sobrien   && TARGET_SPLIT_LONG_MOVES"
1971990286Sobrien  [(set (match_dup 2) (match_dup 1))
1972090286Sobrien   (set (match_dup 0) (match_dup 2))]
1972190286Sobrien  "")
1972290286Sobrien
1972390286Sobrien(define_peephole2
1972490286Sobrien  [(match_scratch:HI 2 "r")
1972590286Sobrien   (set (match_operand:HI 0 "memory_operand" "")
1972690286Sobrien        (match_operand:HI 1 "immediate_operand" ""))]
1972790286Sobrien  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
1972890286Sobrien  && TARGET_SPLIT_LONG_MOVES"
1972990286Sobrien  [(set (match_dup 2) (match_dup 1))
1973090286Sobrien   (set (match_dup 0) (match_dup 2))]
1973190286Sobrien  "")
1973290286Sobrien
1973390286Sobrien(define_peephole2
1973490286Sobrien  [(match_scratch:QI 2 "q")
1973590286Sobrien   (set (match_operand:QI 0 "memory_operand" "")
1973690286Sobrien        (match_operand:QI 1 "immediate_operand" ""))]
1973790286Sobrien  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
1973890286Sobrien  && TARGET_SPLIT_LONG_MOVES"
1973990286Sobrien  [(set (match_dup 2) (match_dup 1))
1974090286Sobrien   (set (match_dup 0) (match_dup 2))]
1974190286Sobrien  "")
1974290286Sobrien
1974390286Sobrien;; Don't compare memory with zero, load and use a test instead.
1974490286Sobrien(define_peephole2
19745146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19746146906Skan 	(match_operator 1 "compare_operator"
19747146906Skan	  [(match_operand:SI 2 "memory_operand" "")
19748146906Skan	   (const_int 0)]))
1974990286Sobrien   (match_scratch:SI 3 "r")]
1975090286Sobrien  "ix86_match_ccmode (insn, CCNOmode) && ! optimize_size"
19751146906Skan  [(set (match_dup 3) (match_dup 2))
19752146906Skan   (set (match_dup 0) (match_op_dup 1 [(match_dup 3) (const_int 0)]))]
1975390286Sobrien  "")
1975490286Sobrien
1975590286Sobrien;; NOT is not pairable on Pentium, while XOR is, but one byte longer. 
1975690286Sobrien;; Don't split NOTs with a displacement operand, because resulting XOR
19757132727Skan;; will not be pairable anyway.
1975890286Sobrien;;
19759169699Skan;; On AMD K6, NOT is vector decoded with memory operand that cannot be
1976090286Sobrien;; represented using a modRM byte.  The XOR replacement is long decoded,
1976190286Sobrien;; so this split helps here as well.
1976290286Sobrien;;
1976390286Sobrien;; Note: Can't do this as a regular split because we can't get proper
1976490286Sobrien;; lifetime information then.
1976590286Sobrien
1976690286Sobrien(define_peephole2
1976790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1976890286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
1976990286Sobrien  "!optimize_size
1977090286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
1977190286Sobrien   && ((TARGET_PENTIUM 
1977290286Sobrien        && (GET_CODE (operands[0]) != MEM
1977390286Sobrien            || !memory_displacement_operand (operands[0], SImode)))
1977490286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], SImode)))"
1977590286Sobrien  [(parallel [(set (match_dup 0)
1977690286Sobrien		   (xor:SI (match_dup 1) (const_int -1)))
19777169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1977890286Sobrien  "")
1977990286Sobrien
1978090286Sobrien(define_peephole2
1978190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1978290286Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
1978390286Sobrien  "!optimize_size
1978490286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
1978590286Sobrien   && ((TARGET_PENTIUM 
1978690286Sobrien        && (GET_CODE (operands[0]) != MEM
1978790286Sobrien            || !memory_displacement_operand (operands[0], HImode)))
1978890286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], HImode)))"
1978990286Sobrien  [(parallel [(set (match_dup 0)
1979090286Sobrien		   (xor:HI (match_dup 1) (const_int -1)))
19791169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1979290286Sobrien  "")
1979390286Sobrien
1979490286Sobrien(define_peephole2
1979590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1979690286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
1979790286Sobrien  "!optimize_size
1979890286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
1979990286Sobrien   && ((TARGET_PENTIUM 
1980090286Sobrien        && (GET_CODE (operands[0]) != MEM
1980190286Sobrien            || !memory_displacement_operand (operands[0], QImode)))
1980290286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], QImode)))"
1980390286Sobrien  [(parallel [(set (match_dup 0)
1980490286Sobrien		   (xor:QI (match_dup 1) (const_int -1)))
19805169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1980690286Sobrien  "")
1980790286Sobrien
1980890286Sobrien;; Non pairable "test imm, reg" instructions can be translated to
1980990286Sobrien;; "and imm, reg" if reg dies.  The "and" form is also shorter (one
1981090286Sobrien;; byte opcode instead of two, have a short form for byte operands),
1981190286Sobrien;; so do it for other CPUs as well.  Given that the value was dead,
1981290286Sobrien;; this should not create any new dependencies.  Pass on the sub-word
1981390286Sobrien;; versions if we're concerned about partial register stalls.
1981490286Sobrien
1981590286Sobrien(define_peephole2
19816146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19817146906Skan	(match_operator 1 "compare_operator"
19818146906Skan	  [(and:SI (match_operand:SI 2 "register_operand" "")
19819146906Skan		   (match_operand:SI 3 "immediate_operand" ""))
19820146906Skan	   (const_int 0)]))]
1982190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
19822146906Skan   && (true_regnum (operands[2]) != 0
19823169699Skan       || satisfies_constraint_K (operands[3]))
19824146906Skan   && peep2_reg_dead_p (1, operands[2])"
1982590286Sobrien  [(parallel
19826146906Skan     [(set (match_dup 0)
19827146906Skan	   (match_op_dup 1 [(and:SI (match_dup 2) (match_dup 3))
19828146906Skan		            (const_int 0)]))
19829146906Skan      (set (match_dup 2)
19830146906Skan	   (and:SI (match_dup 2) (match_dup 3)))])]
1983190286Sobrien  "")
1983290286Sobrien
1983390286Sobrien;; We don't need to handle HImode case, because it will be promoted to SImode
1983490286Sobrien;; on ! TARGET_PARTIAL_REG_STALL
1983590286Sobrien
1983690286Sobrien(define_peephole2
19837146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19838146906Skan	(match_operator 1 "compare_operator"
19839146906Skan	  [(and:QI (match_operand:QI 2 "register_operand" "")
19840146906Skan		   (match_operand:QI 3 "immediate_operand" ""))
19841146906Skan	   (const_int 0)]))]
1984290286Sobrien  "! TARGET_PARTIAL_REG_STALL
1984390286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
19844146906Skan   && true_regnum (operands[2]) != 0
19845146906Skan   && peep2_reg_dead_p (1, operands[2])"
1984690286Sobrien  [(parallel
19847146906Skan     [(set (match_dup 0)
19848146906Skan	   (match_op_dup 1 [(and:QI (match_dup 2) (match_dup 3))
19849146906Skan		            (const_int 0)]))
19850146906Skan      (set (match_dup 2)
19851146906Skan	   (and:QI (match_dup 2) (match_dup 3)))])]
1985290286Sobrien  "")
1985390286Sobrien
1985490286Sobrien(define_peephole2
19855146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19856146906Skan	(match_operator 1 "compare_operator"
19857146906Skan	  [(and:SI
19858146906Skan	     (zero_extract:SI
19859146906Skan	       (match_operand 2 "ext_register_operand" "")
19860146906Skan	       (const_int 8)
19861146906Skan	       (const_int 8))
19862146906Skan	     (match_operand 3 "const_int_operand" ""))
19863146906Skan	   (const_int 0)]))]
1986490286Sobrien  "! TARGET_PARTIAL_REG_STALL
1986590286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
19866146906Skan   && true_regnum (operands[2]) != 0
19867146906Skan   && peep2_reg_dead_p (1, operands[2])"
19868146906Skan  [(parallel [(set (match_dup 0)
19869146906Skan		   (match_op_dup 1
19870146906Skan		     [(and:SI
19871146906Skan			(zero_extract:SI
19872146906Skan			  (match_dup 2)
19873146906Skan			  (const_int 8)
19874146906Skan			  (const_int 8))
19875146906Skan			(match_dup 3))
19876146906Skan		      (const_int 0)]))
19877146906Skan	      (set (zero_extract:SI (match_dup 2)
1987890286Sobrien				    (const_int 8)
1987990286Sobrien				    (const_int 8))
1988090286Sobrien		   (and:SI 
1988190286Sobrien		     (zero_extract:SI
19882146906Skan		       (match_dup 2)
1988390286Sobrien		       (const_int 8)
1988490286Sobrien		       (const_int 8))
19885146906Skan		     (match_dup 3)))])]
1988690286Sobrien  "")
1988790286Sobrien
1988890286Sobrien;; Don't do logical operations with memory inputs.
1988990286Sobrien(define_peephole2
1989090286Sobrien  [(match_scratch:SI 2 "r")
1989190286Sobrien   (parallel [(set (match_operand:SI 0 "register_operand" "")
1989290286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1989390286Sobrien                     [(match_dup 0)
1989490286Sobrien                      (match_operand:SI 1 "memory_operand" "")]))
19895169699Skan              (clobber (reg:CC FLAGS_REG))])]
1989690286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY"
1989790286Sobrien  [(set (match_dup 2) (match_dup 1))
1989890286Sobrien   (parallel [(set (match_dup 0)
1989990286Sobrien                   (match_op_dup 3 [(match_dup 0) (match_dup 2)]))
19900169699Skan              (clobber (reg:CC FLAGS_REG))])]
1990190286Sobrien  "")
1990290286Sobrien
1990390286Sobrien(define_peephole2
1990490286Sobrien  [(match_scratch:SI 2 "r")
1990590286Sobrien   (parallel [(set (match_operand:SI 0 "register_operand" "")
1990690286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1990790286Sobrien                     [(match_operand:SI 1 "memory_operand" "")
1990890286Sobrien                      (match_dup 0)]))
19909169699Skan              (clobber (reg:CC FLAGS_REG))])]
1991090286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY"
1991190286Sobrien  [(set (match_dup 2) (match_dup 1))
1991290286Sobrien   (parallel [(set (match_dup 0)
1991390286Sobrien                   (match_op_dup 3 [(match_dup 2) (match_dup 0)]))
19914169699Skan              (clobber (reg:CC FLAGS_REG))])]
1991590286Sobrien  "")
1991690286Sobrien
1991790286Sobrien; Don't do logical operations with memory outputs
1991890286Sobrien;
1991990286Sobrien; These two don't make sense for PPro/PII -- we're expanding a 4-uop
1992090286Sobrien; instruction into two 1-uop insns plus a 2-uop insn.  That last has
1992190286Sobrien; the same decoder scheduling characteristics as the original.
1992290286Sobrien
1992390286Sobrien(define_peephole2
1992490286Sobrien  [(match_scratch:SI 2 "r")
1992590286Sobrien   (parallel [(set (match_operand:SI 0 "memory_operand" "")
1992690286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1992790286Sobrien                     [(match_dup 0)
1992890286Sobrien                      (match_operand:SI 1 "nonmemory_operand" "")]))
19929169699Skan              (clobber (reg:CC FLAGS_REG))])]
1993090286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY_WRITE"
1993190286Sobrien  [(set (match_dup 2) (match_dup 0))
1993290286Sobrien   (parallel [(set (match_dup 2)
1993390286Sobrien                   (match_op_dup 3 [(match_dup 2) (match_dup 1)]))
19934169699Skan              (clobber (reg:CC FLAGS_REG))])
1993590286Sobrien   (set (match_dup 0) (match_dup 2))]
1993690286Sobrien  "")
1993790286Sobrien
1993890286Sobrien(define_peephole2
1993990286Sobrien  [(match_scratch:SI 2 "r")
1994090286Sobrien   (parallel [(set (match_operand:SI 0 "memory_operand" "")
1994190286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1994290286Sobrien                     [(match_operand:SI 1 "nonmemory_operand" "")
1994390286Sobrien                      (match_dup 0)]))
19944169699Skan              (clobber (reg:CC FLAGS_REG))])]
1994590286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY_WRITE"
1994690286Sobrien  [(set (match_dup 2) (match_dup 0))
1994790286Sobrien   (parallel [(set (match_dup 2)
1994890286Sobrien                   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
19949169699Skan              (clobber (reg:CC FLAGS_REG))])
1995090286Sobrien   (set (match_dup 0) (match_dup 2))]
1995190286Sobrien  "")
1995290286Sobrien
1995390286Sobrien;; Attempt to always use XOR for zeroing registers.
1995490286Sobrien(define_peephole2
1995590286Sobrien  [(set (match_operand 0 "register_operand" "")
19956169699Skan	(match_operand 1 "const0_operand" ""))]
19957169699Skan  "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
1995890286Sobrien   && (! TARGET_USE_MOV0 || optimize_size)
19959169699Skan   && GENERAL_REG_P (operands[0])
1996090286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1996190286Sobrien  [(parallel [(set (match_dup 0) (const_int 0))
19962169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19963169699Skan{
19964169699Skan  operands[0] = gen_lowpart (word_mode, operands[0]);
19965169699Skan})
1996690286Sobrien
1996790286Sobrien(define_peephole2
1996890286Sobrien  [(set (strict_low_part (match_operand 0 "register_operand" ""))
1996990286Sobrien	(const_int 0))]
1997090286Sobrien  "(GET_MODE (operands[0]) == QImode
1997190286Sobrien    || GET_MODE (operands[0]) == HImode)
1997290286Sobrien   && (! TARGET_USE_MOV0 || optimize_size)
1997390286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1997490286Sobrien  [(parallel [(set (strict_low_part (match_dup 0)) (const_int 0))
19975169699Skan	      (clobber (reg:CC FLAGS_REG))])])
1997690286Sobrien
1997790286Sobrien;; For HI and SI modes, or $-1,reg is smaller than mov $-1,reg.
1997890286Sobrien(define_peephole2
1997990286Sobrien  [(set (match_operand 0 "register_operand" "")
1998090286Sobrien	(const_int -1))]
1998190286Sobrien  "(GET_MODE (operands[0]) == HImode
1998290286Sobrien    || GET_MODE (operands[0]) == SImode 
1998390286Sobrien    || (GET_MODE (operands[0]) == DImode && TARGET_64BIT))
1998490286Sobrien   && (optimize_size || TARGET_PENTIUM)
1998590286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1998690286Sobrien  [(parallel [(set (match_dup 0) (const_int -1))
19987169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19988132727Skan  "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode,
19989132727Skan			      operands[0]);")
1999090286Sobrien
1999190286Sobrien;; Attempt to convert simple leas to adds. These can be created by
1999290286Sobrien;; move expanders.
1999390286Sobrien(define_peephole2
1999490286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1999590286Sobrien  	(plus:SI (match_dup 0)
1999690286Sobrien		 (match_operand:SI 1 "nonmemory_operand" "")))]
1999790286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG)"
1999890286Sobrien  [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
19999169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2000090286Sobrien  "")
2000190286Sobrien
2000290286Sobrien(define_peephole2
2000390286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2000490286Sobrien  	(subreg:SI (plus:DI (match_operand:DI 1 "register_operand" "")
2000590286Sobrien			    (match_operand:DI 2 "nonmemory_operand" "")) 0))]
2000690286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG) && REGNO (operands[0]) == REGNO (operands[1])"
2000790286Sobrien  [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
20008169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2000990286Sobrien  "operands[2] = gen_lowpart (SImode, operands[2]);")
2001090286Sobrien
2001190286Sobrien(define_peephole2
2001290286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
2001390286Sobrien  	(plus:DI (match_dup 0)
2001490286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "")))]
2001590286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG)"
2001690286Sobrien  [(parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
20017169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2001890286Sobrien  "")
2001990286Sobrien
2002090286Sobrien(define_peephole2
2002190286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2002290286Sobrien  	(mult:SI (match_dup 0)
2002390286Sobrien		 (match_operand:SI 1 "const_int_operand" "")))]
2002490286Sobrien  "exact_log2 (INTVAL (operands[1])) >= 0
2002590286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2002690286Sobrien  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
20027169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2002890286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
2002990286Sobrien
2003090286Sobrien(define_peephole2
2003190286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
2003290286Sobrien  	(mult:DI (match_dup 0)
2003390286Sobrien		 (match_operand:DI 1 "const_int_operand" "")))]
2003490286Sobrien  "exact_log2 (INTVAL (operands[1])) >= 0
2003590286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2003690286Sobrien  [(parallel [(set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))
20037169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2003890286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
2003990286Sobrien
2004090286Sobrien(define_peephole2
2004190286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2004290286Sobrien  	(subreg:SI (mult:DI (match_operand:DI 1 "register_operand" "")
2004390286Sobrien		   (match_operand:DI 2 "const_int_operand" "")) 0))]
20044117404Skan  "exact_log2 (INTVAL (operands[2])) >= 0
2004590286Sobrien   && REGNO (operands[0]) == REGNO (operands[1])
2004690286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2004790286Sobrien  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
20048169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2004990286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));")
2005090286Sobrien
2005190286Sobrien;; The ESP adjustments can be done by the push and pop instructions.  Resulting
2005290286Sobrien;; code is shorter, since push is only 1 byte, while add imm, %esp 3 bytes.  On
2005390286Sobrien;; many CPUs it is also faster, since special hardware to avoid esp
2005490286Sobrien;; dependencies is present.
2005590286Sobrien
2005690286Sobrien;; While some of these conversions may be done using splitters, we use peepholes
2005790286Sobrien;; in order to allow combine_stack_adjustments pass to see nonobfuscated RTL.
2005890286Sobrien
2005990286Sobrien;; Convert prologue esp subtractions to push.
2006090286Sobrien;; We need register to push.  In order to keep verify_flow_info happy we have
2006190286Sobrien;; two choices
2006290286Sobrien;; - use scratch and clobber it in order to avoid dependencies
2006390286Sobrien;; - use already live register
2006490286Sobrien;; We can't use the second way right now, since there is no reliable way how to
2006590286Sobrien;; verify that given register is live.  First choice will also most likely in
2006690286Sobrien;; fewer dependencies.  On the place of esp adjustments it is very likely that
2006790286Sobrien;; call clobbered registers are dead.  We may want to use base pointer as an
2006890286Sobrien;; alternative when no register is available later.
2006990286Sobrien
2007090286Sobrien(define_peephole2
2007190286Sobrien  [(match_scratch:SI 0 "r")
20072169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
20073169699Skan	      (clobber (reg:CC FLAGS_REG))
2007490286Sobrien	      (clobber (mem:BLK (scratch)))])]
2007590286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2007690286Sobrien  [(clobber (match_dup 0))
20077169699Skan   (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
2007890286Sobrien	      (clobber (mem:BLK (scratch)))])])
2007990286Sobrien
2008090286Sobrien(define_peephole2
2008190286Sobrien  [(match_scratch:SI 0 "r")
20082169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
20083169699Skan	      (clobber (reg:CC FLAGS_REG))
2008490286Sobrien	      (clobber (mem:BLK (scratch)))])]
2008590286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2008690286Sobrien  [(clobber (match_dup 0))
20087169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
20088169699Skan   (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
2008990286Sobrien	      (clobber (mem:BLK (scratch)))])])
2009090286Sobrien
2009190286Sobrien;; Convert esp subtractions to push.
2009290286Sobrien(define_peephole2
2009390286Sobrien  [(match_scratch:SI 0 "r")
20094169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
20095169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2009690286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2009790286Sobrien  [(clobber (match_dup 0))
20098169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
2009990286Sobrien
2010090286Sobrien(define_peephole2
2010190286Sobrien  [(match_scratch:SI 0 "r")
20102169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
20103169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2010490286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2010590286Sobrien  [(clobber (match_dup 0))
20106169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
20107169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
2010890286Sobrien
2010990286Sobrien;; Convert epilogue deallocator to pop.
2011090286Sobrien(define_peephole2
2011190286Sobrien  [(match_scratch:SI 0 "r")
20112169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
20113169699Skan	      (clobber (reg:CC FLAGS_REG))
2011490286Sobrien	      (clobber (mem:BLK (scratch)))])]
2011590286Sobrien  "optimize_size || !TARGET_ADD_ESP_4"
20116169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20117169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2011890286Sobrien	      (clobber (mem:BLK (scratch)))])]
2011990286Sobrien  "")
2012090286Sobrien
2012190286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2012290286Sobrien;; We use two registers if available.
2012390286Sobrien(define_peephole2
2012490286Sobrien  [(match_scratch:SI 0 "r")
2012590286Sobrien   (match_scratch:SI 1 "r")
20126169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20127169699Skan	      (clobber (reg:CC FLAGS_REG))
2012890286Sobrien	      (clobber (mem:BLK (scratch)))])]
2012990286Sobrien  "optimize_size || !TARGET_ADD_ESP_8"
20130169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20131169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2013290286Sobrien	      (clobber (mem:BLK (scratch)))])
20133169699Skan   (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
20134169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2013590286Sobrien  "")
2013690286Sobrien
2013790286Sobrien(define_peephole2
2013890286Sobrien  [(match_scratch:SI 0 "r")
20139169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20140169699Skan	      (clobber (reg:CC FLAGS_REG))
2014190286Sobrien	      (clobber (mem:BLK (scratch)))])]
2014290286Sobrien  "optimize_size"
20143169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20144169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2014590286Sobrien	      (clobber (mem:BLK (scratch)))])
20146169699Skan   (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20147169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2014890286Sobrien  "")
2014990286Sobrien
2015090286Sobrien;; Convert esp additions to pop.
2015190286Sobrien(define_peephole2
2015290286Sobrien  [(match_scratch:SI 0 "r")
20153169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
20154169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2015590286Sobrien  ""
20156169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20157169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2015890286Sobrien  "")
2015990286Sobrien
2016090286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2016190286Sobrien;; We use two registers if available.
2016290286Sobrien(define_peephole2
2016390286Sobrien  [(match_scratch:SI 0 "r")
2016490286Sobrien   (match_scratch:SI 1 "r")
20165169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20166169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2016790286Sobrien  ""
20168169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20169169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
20170169699Skan   (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
20171169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2017290286Sobrien  "")
2017390286Sobrien
2017490286Sobrien(define_peephole2
2017590286Sobrien  [(match_scratch:SI 0 "r")
20176169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20177169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2017890286Sobrien  "optimize_size"
20179169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20180169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
20181169699Skan   (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20182169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2018390286Sobrien  "")
2018490286Sobrien
2018590286Sobrien;; Convert compares with 1 to shorter inc/dec operations when CF is not
20186146906Skan;; required and register dies.  Similarly for 128 to plus -128.
2018790286Sobrien(define_peephole2
20188146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
20189146906Skan	(match_operator 1 "compare_operator"
20190146906Skan	  [(match_operand 2 "register_operand" "")
20191146906Skan	   (match_operand 3 "const_int_operand" "")]))]
20192146906Skan  "(INTVAL (operands[3]) == -1
20193146906Skan    || INTVAL (operands[3]) == 1
20194146906Skan    || INTVAL (operands[3]) == 128)
20195146906Skan   && ix86_match_ccmode (insn, CCGCmode)
20196146906Skan   && peep2_reg_dead_p (1, operands[2])"
20197146906Skan  [(parallel [(set (match_dup 0)
20198146906Skan		   (match_op_dup 1 [(match_dup 2) (match_dup 3)]))
20199146906Skan	      (clobber (match_dup 2))])]
2020090286Sobrien  "")
2020190286Sobrien
2020290286Sobrien(define_peephole2
2020390286Sobrien  [(match_scratch:DI 0 "r")
20204169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
20205169699Skan	      (clobber (reg:CC FLAGS_REG))
2020690286Sobrien	      (clobber (mem:BLK (scratch)))])]
2020790286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2020890286Sobrien  [(clobber (match_dup 0))
20209169699Skan   (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
2021090286Sobrien	      (clobber (mem:BLK (scratch)))])])
2021190286Sobrien
2021290286Sobrien(define_peephole2
2021390286Sobrien  [(match_scratch:DI 0 "r")
20214169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
20215169699Skan	      (clobber (reg:CC FLAGS_REG))
2021690286Sobrien	      (clobber (mem:BLK (scratch)))])]
2021790286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2021890286Sobrien  [(clobber (match_dup 0))
20219169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
20220169699Skan   (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
2022190286Sobrien	      (clobber (mem:BLK (scratch)))])])
2022290286Sobrien
2022390286Sobrien;; Convert esp subtractions to push.
2022490286Sobrien(define_peephole2
2022590286Sobrien  [(match_scratch:DI 0 "r")
20226169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
20227169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2022890286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2022990286Sobrien  [(clobber (match_dup 0))
20230169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
2023190286Sobrien
2023290286Sobrien(define_peephole2
2023390286Sobrien  [(match_scratch:DI 0 "r")
20234169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
20235169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2023690286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2023790286Sobrien  [(clobber (match_dup 0))
20238169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
20239169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
2024090286Sobrien
2024190286Sobrien;; Convert epilogue deallocator to pop.
2024290286Sobrien(define_peephole2
2024390286Sobrien  [(match_scratch:DI 0 "r")
20244169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
20245169699Skan	      (clobber (reg:CC FLAGS_REG))
2024690286Sobrien	      (clobber (mem:BLK (scratch)))])]
2024790286Sobrien  "optimize_size || !TARGET_ADD_ESP_4"
20248169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20249169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2025090286Sobrien	      (clobber (mem:BLK (scratch)))])]
2025190286Sobrien  "")
2025290286Sobrien
2025390286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2025490286Sobrien;; We use two registers if available.
2025590286Sobrien(define_peephole2
2025690286Sobrien  [(match_scratch:DI 0 "r")
2025790286Sobrien   (match_scratch:DI 1 "r")
20258169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20259169699Skan	      (clobber (reg:CC FLAGS_REG))
2026090286Sobrien	      (clobber (mem:BLK (scratch)))])]
2026190286Sobrien  "optimize_size || !TARGET_ADD_ESP_8"
20262169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20263169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2026490286Sobrien	      (clobber (mem:BLK (scratch)))])
20265169699Skan   (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
20266169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2026790286Sobrien  "")
2026890286Sobrien
2026990286Sobrien(define_peephole2
2027090286Sobrien  [(match_scratch:DI 0 "r")
20271169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20272169699Skan	      (clobber (reg:CC FLAGS_REG))
2027390286Sobrien	      (clobber (mem:BLK (scratch)))])]
2027490286Sobrien  "optimize_size"
20275169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20276169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2027790286Sobrien	      (clobber (mem:BLK (scratch)))])
20278169699Skan   (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20279169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2028090286Sobrien  "")
2028190286Sobrien
2028290286Sobrien;; Convert esp additions to pop.
2028390286Sobrien(define_peephole2
2028490286Sobrien  [(match_scratch:DI 0 "r")
20285169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
20286169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2028790286Sobrien  ""
20288169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20289169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2029090286Sobrien  "")
2029190286Sobrien
2029290286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2029390286Sobrien;; We use two registers if available.
2029490286Sobrien(define_peephole2
2029590286Sobrien  [(match_scratch:DI 0 "r")
2029690286Sobrien   (match_scratch:DI 1 "r")
20297169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20298169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2029990286Sobrien  ""
20300169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20301169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
20302169699Skan   (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
20303169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2030490286Sobrien  "")
2030590286Sobrien
2030690286Sobrien(define_peephole2
2030790286Sobrien  [(match_scratch:DI 0 "r")
20308169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20309169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2031090286Sobrien  "optimize_size"
20311169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20312169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
20313169699Skan   (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20314169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2031590286Sobrien  "")
2031690286Sobrien
20317169699Skan;; Convert imul by three, five and nine into lea
20318169699Skan(define_peephole2
20319169699Skan  [(parallel
20320169699Skan    [(set (match_operand:SI 0 "register_operand" "")
20321169699Skan	  (mult:SI (match_operand:SI 1 "register_operand" "")
20322169699Skan		   (match_operand:SI 2 "const_int_operand" "")))
20323169699Skan     (clobber (reg:CC FLAGS_REG))])]
20324169699Skan  "INTVAL (operands[2]) == 3
20325169699Skan   || INTVAL (operands[2]) == 5
20326169699Skan   || INTVAL (operands[2]) == 9"
20327169699Skan  [(set (match_dup 0)
20328169699Skan        (plus:SI (mult:SI (match_dup 1) (match_dup 2))
20329169699Skan                 (match_dup 1)))]
20330169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20331169699Skan
20332169699Skan(define_peephole2
20333169699Skan  [(parallel
20334169699Skan    [(set (match_operand:SI 0 "register_operand" "")
20335169699Skan          (mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
20336169699Skan                   (match_operand:SI 2 "const_int_operand" "")))
20337169699Skan     (clobber (reg:CC FLAGS_REG))])]
20338169699Skan  "!optimize_size 
20339169699Skan   && (INTVAL (operands[2]) == 3
20340169699Skan       || INTVAL (operands[2]) == 5
20341169699Skan       || INTVAL (operands[2]) == 9)"
20342169699Skan  [(set (match_dup 0) (match_dup 1))
20343169699Skan   (set (match_dup 0)
20344169699Skan        (plus:SI (mult:SI (match_dup 0) (match_dup 2))
20345169699Skan                 (match_dup 0)))]
20346169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20347169699Skan
20348169699Skan(define_peephole2
20349169699Skan  [(parallel
20350169699Skan    [(set (match_operand:DI 0 "register_operand" "")
20351169699Skan	  (mult:DI (match_operand:DI 1 "register_operand" "")
20352169699Skan		   (match_operand:DI 2 "const_int_operand" "")))
20353169699Skan     (clobber (reg:CC FLAGS_REG))])]
20354169699Skan  "TARGET_64BIT
20355169699Skan   && (INTVAL (operands[2]) == 3
20356169699Skan       || INTVAL (operands[2]) == 5
20357169699Skan       || INTVAL (operands[2]) == 9)"
20358169699Skan  [(set (match_dup 0)
20359169699Skan        (plus:DI (mult:DI (match_dup 1) (match_dup 2))
20360169699Skan                 (match_dup 1)))]
20361169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20362169699Skan
20363169699Skan(define_peephole2
20364169699Skan  [(parallel
20365169699Skan    [(set (match_operand:DI 0 "register_operand" "")
20366169699Skan          (mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
20367169699Skan                   (match_operand:DI 2 "const_int_operand" "")))
20368169699Skan     (clobber (reg:CC FLAGS_REG))])]
20369169699Skan  "TARGET_64BIT
20370169699Skan   && !optimize_size 
20371169699Skan   && (INTVAL (operands[2]) == 3
20372169699Skan       || INTVAL (operands[2]) == 5
20373169699Skan       || INTVAL (operands[2]) == 9)"
20374169699Skan  [(set (match_dup 0) (match_dup 1))
20375169699Skan   (set (match_dup 0)
20376169699Skan        (plus:DI (mult:DI (match_dup 0) (match_dup 2))
20377169699Skan                 (match_dup 0)))]
20378169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20379169699Skan
20380132727Skan;; Imul $32bit_imm, mem, reg is vector decoded, while
20381132727Skan;; imul $32bit_imm, reg, reg is direct decoded.
20382132727Skan(define_peephole2
20383132727Skan  [(match_scratch:DI 3 "r")
20384132727Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
20385132727Skan		   (mult:DI (match_operand:DI 1 "memory_operand" "")
20386132727Skan			    (match_operand:DI 2 "immediate_operand" "")))
20387169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20388169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20389169699Skan   && !satisfies_constraint_K (operands[2])"
20390132727Skan  [(set (match_dup 3) (match_dup 1))
20391132727Skan   (parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2)))
20392169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20393132727Skan"")
20394132727Skan
20395132727Skan(define_peephole2
20396132727Skan  [(match_scratch:SI 3 "r")
20397132727Skan   (parallel [(set (match_operand:SI 0 "register_operand" "")
20398132727Skan		   (mult:SI (match_operand:SI 1 "memory_operand" "")
20399132727Skan			    (match_operand:SI 2 "immediate_operand" "")))
20400169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20401169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20402169699Skan   && !satisfies_constraint_K (operands[2])"
20403132727Skan  [(set (match_dup 3) (match_dup 1))
20404132727Skan   (parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2)))
20405169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20406132727Skan"")
20407132727Skan
20408132727Skan(define_peephole2
20409132727Skan  [(match_scratch:SI 3 "r")
20410132727Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
20411132727Skan		   (zero_extend:DI
20412132727Skan		     (mult:SI (match_operand:SI 1 "memory_operand" "")
20413132727Skan			      (match_operand:SI 2 "immediate_operand" ""))))
20414169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20415169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20416169699Skan   && !satisfies_constraint_K (operands[2])"
20417132727Skan  [(set (match_dup 3) (match_dup 1))
20418132727Skan   (parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2))))
20419169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20420132727Skan"")
20421132727Skan
20422132727Skan;; imul $8/16bit_imm, regmem, reg is vector decoded.
20423132727Skan;; Convert it into imul reg, reg
20424132727Skan;; It would be better to force assembler to encode instruction using long
20425132727Skan;; immediate, but there is apparently no way to do so.
20426132727Skan(define_peephole2
20427132727Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
20428132727Skan		   (mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
20429132727Skan			    (match_operand:DI 2 "const_int_operand" "")))
20430169699Skan	      (clobber (reg:CC FLAGS_REG))])
20431132727Skan   (match_scratch:DI 3 "r")]
20432169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20433169699Skan   && satisfies_constraint_K (operands[2])"
20434132727Skan  [(set (match_dup 3) (match_dup 2))
20435132727Skan   (parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3)))
20436169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20437132727Skan{
20438132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20439132727Skan    emit_move_insn (operands[0], operands[1]);
20440132727Skan})
20441132727Skan
20442132727Skan(define_peephole2
20443132727Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
20444132727Skan		   (mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
20445132727Skan			    (match_operand:SI 2 "const_int_operand" "")))
20446169699Skan	      (clobber (reg:CC FLAGS_REG))])
20447132727Skan   (match_scratch:SI 3 "r")]
20448169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20449169699Skan   && satisfies_constraint_K (operands[2])"
20450132727Skan  [(set (match_dup 3) (match_dup 2))
20451132727Skan   (parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3)))
20452169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20453132727Skan{
20454132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20455132727Skan    emit_move_insn (operands[0], operands[1]);
20456132727Skan})
20457132727Skan
20458132727Skan(define_peephole2
20459132727Skan  [(parallel [(set (match_operand:HI 0 "register_operand" "")
20460132727Skan		   (mult:HI (match_operand:HI 1 "nonimmediate_operand" "")
20461132727Skan			    (match_operand:HI 2 "immediate_operand" "")))
20462169699Skan	      (clobber (reg:CC FLAGS_REG))])
20463132727Skan   (match_scratch:HI 3 "r")]
20464169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
20465132727Skan  [(set (match_dup 3) (match_dup 2))
20466132727Skan   (parallel [(set (match_dup 0) (mult:HI (match_dup 0) (match_dup 3)))
20467169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20468132727Skan{
20469132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20470132727Skan    emit_move_insn (operands[0], operands[1]);
20471132727Skan})
20472169699Skan
20473169699Skan;; After splitting up read-modify operations, array accesses with memory
20474169699Skan;; operands might end up in form:
20475169699Skan;;  sall    $2, %eax
20476169699Skan;;  movl    4(%esp), %edx
20477169699Skan;;  addl    %edx, %eax
20478169699Skan;; instead of pre-splitting:
20479169699Skan;;  sall    $2, %eax
20480169699Skan;;  addl    4(%esp), %eax
20481169699Skan;; Turn it into:
20482169699Skan;;  movl    4(%esp), %edx
20483169699Skan;;  leal    (%edx,%eax,4), %eax
20484169699Skan
20485169699Skan(define_peephole2
20486169699Skan  [(parallel [(set (match_operand 0 "register_operand" "")
20487169699Skan		   (ashift (match_operand 1 "register_operand" "")
20488169699Skan			   (match_operand 2 "const_int_operand" "")))
20489169699Skan	       (clobber (reg:CC FLAGS_REG))])
20490169699Skan   (set (match_operand 3 "register_operand")
20491169699Skan        (match_operand 4 "x86_64_general_operand" ""))
20492169699Skan   (parallel [(set (match_operand 5 "register_operand" "")
20493169699Skan		   (plus (match_operand 6 "register_operand" "")
20494169699Skan			 (match_operand 7 "register_operand" "")))
20495169699Skan		   (clobber (reg:CC FLAGS_REG))])]
20496169699Skan  "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
20497169699Skan   /* Validate MODE for lea.  */
20498169699Skan   && ((!TARGET_PARTIAL_REG_STALL
20499169699Skan	&& (GET_MODE (operands[0]) == QImode
20500169699Skan	    || GET_MODE (operands[0]) == HImode))
20501169699Skan       || GET_MODE (operands[0]) == SImode 
20502169699Skan       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
20503169699Skan   /* We reorder load and the shift.  */
20504169699Skan   && !rtx_equal_p (operands[1], operands[3])
20505169699Skan   && !reg_overlap_mentioned_p (operands[0], operands[4])
20506169699Skan   /* Last PLUS must consist of operand 0 and 3.  */
20507169699Skan   && !rtx_equal_p (operands[0], operands[3])
20508169699Skan   && (rtx_equal_p (operands[3], operands[6])
20509169699Skan       || rtx_equal_p (operands[3], operands[7]))
20510169699Skan   && (rtx_equal_p (operands[0], operands[6])
20511169699Skan       || rtx_equal_p (operands[0], operands[7]))
20512169699Skan   /* The intermediate operand 0 must die or be same as output.  */
20513169699Skan   && (rtx_equal_p (operands[0], operands[5])
20514169699Skan       || peep2_reg_dead_p (3, operands[0]))"
20515169699Skan  [(set (match_dup 3) (match_dup 4))
20516169699Skan   (set (match_dup 0) (match_dup 1))]
20517169699Skan{
20518169699Skan  enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
20519169699Skan  int scale = 1 << INTVAL (operands[2]);
20520169699Skan  rtx index = gen_lowpart (Pmode, operands[1]);
20521169699Skan  rtx base = gen_lowpart (Pmode, operands[3]);
20522169699Skan  rtx dest = gen_lowpart (mode, operands[5]);
20523169699Skan
20524169699Skan  operands[1] = gen_rtx_PLUS (Pmode, base,
20525169699Skan  			      gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
20526169699Skan  if (mode != Pmode)
20527169699Skan    operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
20528169699Skan  operands[0] = dest;
20529169699Skan})
20530132727Skan
2053190286Sobrien;; Call-value patterns last so that the wildcard operand does not
2053290286Sobrien;; disrupt insn-recog's switch tables.
2053390286Sobrien
2053490286Sobrien(define_insn "*call_value_pop_0"
2053590286Sobrien  [(set (match_operand 0 "" "")
2053690286Sobrien	(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
2053790286Sobrien	      (match_operand:SI 2 "" "")))
20538169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
2053990286Sobrien			    (match_operand:SI 3 "immediate_operand" "")))]
2054090286Sobrien  "!TARGET_64BIT"
2054190286Sobrien{
2054290286Sobrien  if (SIBLING_CALL_P (insn))
2054390286Sobrien    return "jmp\t%P1";
2054490286Sobrien  else
2054590286Sobrien    return "call\t%P1";
2054690286Sobrien}
2054790286Sobrien  [(set_attr "type" "callv")])
2054890286Sobrien
2054990286Sobrien(define_insn "*call_value_pop_1"
2055090286Sobrien  [(set (match_operand 0 "" "")
2055190286Sobrien	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
2055290286Sobrien	      (match_operand:SI 2 "" "")))
20553169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
2055490286Sobrien			    (match_operand:SI 3 "immediate_operand" "i")))]
2055590286Sobrien  "!TARGET_64BIT"
2055690286Sobrien{
20557169699Skan  if (constant_call_address_operand (operands[1], Pmode))
2055890286Sobrien    {
2055990286Sobrien      if (SIBLING_CALL_P (insn))
2056090286Sobrien	return "jmp\t%P1";
2056190286Sobrien      else
2056290286Sobrien	return "call\t%P1";
2056390286Sobrien    }
2056490286Sobrien  if (SIBLING_CALL_P (insn))
2056590286Sobrien    return "jmp\t%A1";
2056690286Sobrien  else
2056790286Sobrien    return "call\t%A1";
2056890286Sobrien}
2056990286Sobrien  [(set_attr "type" "callv")])
2057090286Sobrien
2057190286Sobrien(define_insn "*call_value_0"
2057290286Sobrien  [(set (match_operand 0 "" "")
2057390286Sobrien	(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
2057490286Sobrien	      (match_operand:SI 2 "" "")))]
2057590286Sobrien  "!TARGET_64BIT"
2057690286Sobrien{
2057790286Sobrien  if (SIBLING_CALL_P (insn))
2057890286Sobrien    return "jmp\t%P1";
2057990286Sobrien  else
2058090286Sobrien    return "call\t%P1";
2058190286Sobrien}
2058290286Sobrien  [(set_attr "type" "callv")])
2058390286Sobrien
2058490286Sobrien(define_insn "*call_value_0_rex64"
2058590286Sobrien  [(set (match_operand 0 "" "")
2058690286Sobrien	(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
2058790286Sobrien	      (match_operand:DI 2 "const_int_operand" "")))]
2058890286Sobrien  "TARGET_64BIT"
2058990286Sobrien{
2059090286Sobrien  if (SIBLING_CALL_P (insn))
2059190286Sobrien    return "jmp\t%P1";
2059290286Sobrien  else
2059390286Sobrien    return "call\t%P1";
2059490286Sobrien}
2059590286Sobrien  [(set_attr "type" "callv")])
2059690286Sobrien
2059790286Sobrien(define_insn "*call_value_1"
2059890286Sobrien  [(set (match_operand 0 "" "")
2059990286Sobrien	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
2060090286Sobrien	      (match_operand:SI 2 "" "")))]
20601132727Skan  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
2060290286Sobrien{
20603169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20604132727Skan    return "call\t%P1";
20605146906Skan  return "call\t%A1";
2060690286Sobrien}
2060790286Sobrien  [(set_attr "type" "callv")])
2060890286Sobrien
20609132727Skan(define_insn "*sibcall_value_1"
20610132727Skan  [(set (match_operand 0 "" "")
20611132727Skan	(call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,c,d,a"))
20612132727Skan	      (match_operand:SI 2 "" "")))]
20613132727Skan  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
20614132727Skan{
20615169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20616132727Skan    return "jmp\t%P1";
20617146906Skan  return "jmp\t%A1";
20618132727Skan}
20619132727Skan  [(set_attr "type" "callv")])
20620132727Skan
2062190286Sobrien(define_insn "*call_value_1_rex64"
2062290286Sobrien  [(set (match_operand 0 "" "")
2062390286Sobrien	(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
2062490286Sobrien	      (match_operand:DI 2 "" "")))]
20625132727Skan  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
2062690286Sobrien{
20627169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20628132727Skan    return "call\t%P1";
20629132727Skan  return "call\t%A1";
2063090286Sobrien}
2063190286Sobrien  [(set_attr "type" "callv")])
20632132727Skan
20633132727Skan(define_insn "*sibcall_value_1_rex64"
20634132727Skan  [(set (match_operand 0 "" "")
20635132727Skan	(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
20636132727Skan	      (match_operand:DI 2 "" "")))]
20637132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
20638132727Skan  "jmp\t%P1"
20639132727Skan  [(set_attr "type" "callv")])
20640132727Skan
20641132727Skan(define_insn "*sibcall_value_1_rex64_v"
20642132727Skan  [(set (match_operand 0 "" "")
20643132727Skan	(call (mem:QI (reg:DI 40))
20644132727Skan	      (match_operand:DI 1 "" "")))]
20645132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
20646132727Skan  "jmp\t*%%r11"
20647132727Skan  [(set_attr "type" "callv")])
2064890286Sobrien
20649169699Skan;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5.
20650169699Skan;; That, however, is usually mapped by the OS to SIGSEGV, which is often 
20651169699Skan;; caught for use by garbage collectors and the like.  Using an insn that
20652169699Skan;; maps to SIGILL makes it more likely the program will rightfully die.
20653169699Skan;; Keeping with tradition, "6" is in honor of #UD.
2065490286Sobrien(define_insn "trap"
20655169699Skan  [(trap_if (const_int 1) (const_int 6))]
2065690286Sobrien  ""
20657169699Skan  { return ASM_SHORT "0x0b0f"; }
20658169699Skan  [(set_attr "length" "2")])
2065990286Sobrien
2066090286Sobrien(define_expand "sse_prologue_save"
2066190286Sobrien  [(parallel [(set (match_operand:BLK 0 "" "")
2066290286Sobrien		   (unspec:BLK [(reg:DI 21)
2066390286Sobrien				(reg:DI 22)
2066490286Sobrien				(reg:DI 23)
2066590286Sobrien				(reg:DI 24)
2066690286Sobrien				(reg:DI 25)
2066790286Sobrien				(reg:DI 26)
2066890286Sobrien				(reg:DI 27)
20669117404Skan				(reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
2067090286Sobrien	      (use (match_operand:DI 1 "register_operand" ""))
2067190286Sobrien	      (use (match_operand:DI 2 "immediate_operand" ""))
2067290286Sobrien	      (use (label_ref:DI (match_operand 3 "" "")))])]
2067390286Sobrien  "TARGET_64BIT"
2067490286Sobrien  "")
2067590286Sobrien
2067690286Sobrien(define_insn "*sse_prologue_save_insn"
2067790286Sobrien  [(set (mem:BLK (plus:DI (match_operand:DI 0 "register_operand" "R")
2067890286Sobrien			  (match_operand:DI 4 "const_int_operand" "n")))
2067990286Sobrien	(unspec:BLK [(reg:DI 21)
2068090286Sobrien		     (reg:DI 22)
2068190286Sobrien		     (reg:DI 23)
2068290286Sobrien		     (reg:DI 24)
2068390286Sobrien		     (reg:DI 25)
2068490286Sobrien		     (reg:DI 26)
2068590286Sobrien		     (reg:DI 27)
20686117404Skan		     (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
2068790286Sobrien   (use (match_operand:DI 1 "register_operand" "r"))
2068890286Sobrien   (use (match_operand:DI 2 "const_int_operand" "i"))
2068990286Sobrien   (use (label_ref:DI (match_operand 3 "" "X")))]
2069090286Sobrien  "TARGET_64BIT
2069190286Sobrien   && INTVAL (operands[4]) + SSE_REGPARM_MAX * 16 - 16 < 128
2069290286Sobrien   && INTVAL (operands[4]) + INTVAL (operands[2]) * 16 >= -128"
2069390286Sobrien  "*
2069490286Sobrien{
2069590286Sobrien  int i;
2069690286Sobrien  operands[0] = gen_rtx_MEM (Pmode,
2069790286Sobrien			     gen_rtx_PLUS (Pmode, operands[0], operands[4]));
2069890286Sobrien  output_asm_insn (\"jmp\\t%A1\", operands);
2069990286Sobrien  for (i = SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--)
2070090286Sobrien    {
2070190286Sobrien      operands[4] = adjust_address (operands[0], DImode, i*16);
2070290286Sobrien      operands[5] = gen_rtx_REG (TImode, SSE_REGNO (i));
2070390286Sobrien      PUT_MODE (operands[4], TImode);
2070490286Sobrien      if (GET_CODE (XEXP (operands[0], 0)) != PLUS)
2070590286Sobrien        output_asm_insn (\"rex\", operands);
2070690286Sobrien      output_asm_insn (\"movaps\\t{%5, %4|%4, %5}\", operands);
2070790286Sobrien    }
20708132727Skan  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
2070990286Sobrien			     CODE_LABEL_NUMBER (operands[3]));
2071090286Sobrien  RET;
2071190286Sobrien}
2071256391Sobrien  "
2071390286Sobrien  [(set_attr "type" "other")
2071490286Sobrien   (set_attr "length_immediate" "0")
2071590286Sobrien   (set_attr "length_address" "0")
2071690286Sobrien   (set_attr "length" "135")
2071790286Sobrien   (set_attr "memory" "store")
2071890286Sobrien   (set_attr "modrm" "0")
2071990286Sobrien   (set_attr "mode" "DI")])
2072090286Sobrien
2072190286Sobrien(define_expand "prefetch"
20722102802Skan  [(prefetch (match_operand 0 "address_operand" "")
2072390286Sobrien	     (match_operand:SI 1 "const_int_operand" "")
2072490286Sobrien	     (match_operand:SI 2 "const_int_operand" ""))]
2072590286Sobrien  "TARGET_PREFETCH_SSE || TARGET_3DNOW"
2072656391Sobrien{
2072790286Sobrien  int rw = INTVAL (operands[1]);
2072890286Sobrien  int locality = INTVAL (operands[2]);
2072990286Sobrien
20730169699Skan  gcc_assert (rw == 0 || rw == 1);
20731169699Skan  gcc_assert (locality >= 0 && locality <= 3);
20732169699Skan  gcc_assert (GET_MODE (operands[0]) == Pmode
20733169699Skan	      || GET_MODE (operands[0]) == VOIDmode);
2073490286Sobrien
2073590286Sobrien  /* Use 3dNOW prefetch in case we are asking for write prefetch not
20736169699Skan     supported by SSE counterpart or the SSE prefetch is not available
2073790286Sobrien     (K6 machines).  Otherwise use SSE prefetch as it allows specifying
2073890286Sobrien     of locality.  */
2073990286Sobrien  if (TARGET_3DNOW && (!TARGET_PREFETCH_SSE || rw))
2074090286Sobrien    operands[2] = GEN_INT (3);
2074190286Sobrien  else
2074290286Sobrien    operands[1] = const0_rtx;
2074390286Sobrien})
2074490286Sobrien
2074590286Sobrien(define_insn "*prefetch_sse"
2074690286Sobrien  [(prefetch (match_operand:SI 0 "address_operand" "p")
2074790286Sobrien	     (const_int 0)
2074890286Sobrien	     (match_operand:SI 1 "const_int_operand" ""))]
20749102802Skan  "TARGET_PREFETCH_SSE && !TARGET_64BIT"
2075090286Sobrien{
2075190286Sobrien  static const char * const patterns[4] = {
2075290286Sobrien   "prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
2075390286Sobrien  };
2075490286Sobrien
2075590286Sobrien  int locality = INTVAL (operands[1]);
20756169699Skan  gcc_assert (locality >= 0 && locality <= 3);
2075790286Sobrien
2075890286Sobrien  return patterns[locality];  
2075990286Sobrien}
20760102802Skan  [(set_attr "type" "sse")
20761102802Skan   (set_attr "memory" "none")])
20762102802Skan
20763102802Skan(define_insn "*prefetch_sse_rex"
20764102802Skan  [(prefetch (match_operand:DI 0 "address_operand" "p")
20765102802Skan	     (const_int 0)
20766102802Skan	     (match_operand:SI 1 "const_int_operand" ""))]
20767102802Skan  "TARGET_PREFETCH_SSE && TARGET_64BIT"
20768102802Skan{
20769102802Skan  static const char * const patterns[4] = {
20770102802Skan   "prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
20771102802Skan  };
20772102802Skan
20773102802Skan  int locality = INTVAL (operands[1]);
20774169699Skan  gcc_assert (locality >= 0 && locality <= 3);
20775102802Skan
20776102802Skan  return patterns[locality];  
20777102802Skan}
20778117404Skan  [(set_attr "type" "sse")
20779117404Skan   (set_attr "memory" "none")])
2078090286Sobrien
2078190286Sobrien(define_insn "*prefetch_3dnow"
2078290286Sobrien  [(prefetch (match_operand:SI 0 "address_operand" "p")
2078390286Sobrien	     (match_operand:SI 1 "const_int_operand" "n")
2078490286Sobrien	     (const_int 3))]
20785102802Skan  "TARGET_3DNOW && !TARGET_64BIT"
2078690286Sobrien{
2078790286Sobrien  if (INTVAL (operands[1]) == 0)
2078890286Sobrien    return "prefetch\t%a0";
2078990286Sobrien  else
2079090286Sobrien    return "prefetchw\t%a0";
2079190286Sobrien}
20792102802Skan  [(set_attr "type" "mmx")
20793102802Skan   (set_attr "memory" "none")])
20794102802Skan
20795102802Skan(define_insn "*prefetch_3dnow_rex"
20796102802Skan  [(prefetch (match_operand:DI 0 "address_operand" "p")
20797102802Skan	     (match_operand:SI 1 "const_int_operand" "n")
20798102802Skan	     (const_int 3))]
20799102802Skan  "TARGET_3DNOW && TARGET_64BIT"
20800102802Skan{
20801102802Skan  if (INTVAL (operands[1]) == 0)
20802102802Skan    return "prefetch\t%a0";
20803102802Skan  else
20804102802Skan    return "prefetchw\t%a0";
20805102802Skan}
20806117404Skan  [(set_attr "type" "mmx")
20807117404Skan   (set_attr "memory" "none")])
20808117404Skan
20809169699Skan(define_expand "stack_protect_set"
20810169699Skan  [(match_operand 0 "memory_operand" "")
20811169699Skan   (match_operand 1 "memory_operand" "")]
20812169699Skan  ""
20813117404Skan{
20814169699Skan#ifdef TARGET_THREAD_SSP_OFFSET
20815169699Skan  if (TARGET_64BIT)
20816169699Skan    emit_insn (gen_stack_tls_protect_set_di (operands[0],
20817169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20818117404Skan  else
20819169699Skan    emit_insn (gen_stack_tls_protect_set_si (operands[0],
20820169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20821169699Skan#else
20822169699Skan  if (TARGET_64BIT)
20823169699Skan    emit_insn (gen_stack_protect_set_di (operands[0], operands[1]));
20824117404Skan  else
20825169699Skan    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
20826169699Skan#endif
20827169699Skan  DONE;
20828169699Skan})
20829117404Skan
20830169699Skan(define_insn "stack_protect_set_si"
20831169699Skan  [(set (match_operand:SI 0 "memory_operand" "=m")
20832169699Skan	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
20833169699Skan   (set (match_scratch:SI 2 "=&r") (const_int 0))
20834169699Skan   (clobber (reg:CC FLAGS_REG))]
20835169699Skan  ""
20836169699Skan  "mov{l}\t{%1, %2|%2, %1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
20837169699Skan  [(set_attr "type" "multi")])
20838117404Skan
20839169699Skan(define_insn "stack_protect_set_di"
20840169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
20841169699Skan	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
20842169699Skan   (set (match_scratch:DI 2 "=&r") (const_int 0))
20843169699Skan   (clobber (reg:CC FLAGS_REG))]
20844169699Skan  "TARGET_64BIT"
20845169699Skan  "mov{q}\t{%1, %2|%2, %1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
20846169699Skan  [(set_attr "type" "multi")])
20847117404Skan
20848169699Skan(define_insn "stack_tls_protect_set_si"
20849117404Skan  [(set (match_operand:SI 0 "memory_operand" "=m")
20850169699Skan	(unspec:SI [(match_operand:SI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
20851169699Skan   (set (match_scratch:SI 2 "=&r") (const_int 0))
20852169699Skan   (clobber (reg:CC FLAGS_REG))]
20853169699Skan  ""
20854169699Skan  "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR %%gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
20855169699Skan  [(set_attr "type" "multi")])
20856117404Skan
20857169699Skan(define_insn "stack_tls_protect_set_di"
20858169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
20859169699Skan	(unspec:DI [(match_operand:DI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
20860169699Skan   (set (match_scratch:DI 2 "=&r") (const_int 0))
20861169699Skan   (clobber (reg:CC FLAGS_REG))]
20862169699Skan  "TARGET_64BIT"
20863169699Skan  {
20864169699Skan     /* The kernel uses a different segment register for performance reasons; a
20865169699Skan        system call would not have to trash the userspace segment register,
20866169699Skan        which would be expensive */
20867169699Skan     if (ix86_cmodel != CM_KERNEL)
20868169699Skan        return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
20869169699Skan     else
20870169699Skan        return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR %%gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
20871169699Skan  }
20872169699Skan  [(set_attr "type" "multi")])
20873117404Skan
20874169699Skan(define_expand "stack_protect_test"
20875169699Skan  [(match_operand 0 "memory_operand" "")
20876169699Skan   (match_operand 1 "memory_operand" "")
20877169699Skan   (match_operand 2 "" "")]
20878169699Skan  ""
20879169699Skan{
20880169699Skan  rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG);
20881169699Skan  ix86_compare_op0 = operands[0];
20882169699Skan  ix86_compare_op1 = operands[1];
20883169699Skan  ix86_compare_emitted = flags;
20884117404Skan
20885169699Skan#ifdef TARGET_THREAD_SSP_OFFSET
20886169699Skan  if (TARGET_64BIT)
20887169699Skan    emit_insn (gen_stack_tls_protect_test_di (flags, operands[0],
20888169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20889132727Skan  else
20890169699Skan    emit_insn (gen_stack_tls_protect_test_si (flags, operands[0],
20891169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20892169699Skan#else
20893169699Skan  if (TARGET_64BIT)
20894169699Skan    emit_insn (gen_stack_protect_test_di (flags, operands[0], operands[1]));
20895169699Skan  else
20896169699Skan    emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1]));
20897169699Skan#endif
20898169699Skan  emit_jump_insn (gen_beq (operands[2]));
20899117404Skan  DONE;
20900117404Skan})
20901117404Skan
20902169699Skan(define_insn "stack_protect_test_si"
20903169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20904169699Skan	(unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
20905169699Skan		     (match_operand:SI 2 "memory_operand" "m")]
20906169699Skan		    UNSPEC_SP_TEST))
20907169699Skan   (clobber (match_scratch:SI 3 "=&r"))]
20908169699Skan  ""
20909169699Skan  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%2, %3|%3, %2}"
20910169699Skan  [(set_attr "type" "multi")])
20911117404Skan
20912169699Skan(define_insn "stack_protect_test_di"
20913169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20914169699Skan	(unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
20915169699Skan		     (match_operand:DI 2 "memory_operand" "m")]
20916169699Skan		    UNSPEC_SP_TEST))
20917169699Skan   (clobber (match_scratch:DI 3 "=&r"))]
20918169699Skan  "TARGET_64BIT"
20919169699Skan  "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%2, %3|%3, %2}"
20920169699Skan  [(set_attr "type" "multi")])
20921117404Skan
20922169699Skan(define_insn "stack_tls_protect_test_si"
20923169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20924169699Skan	(unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
20925169699Skan		     (match_operand:SI 2 "const_int_operand" "i")]
20926169699Skan		    UNSPEC_SP_TLS_TEST))
20927169699Skan   (clobber (match_scratch:SI 3 "=r"))]
20928169699Skan  ""
20929169699Skan  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR %%gs:%P2}"
20930169699Skan  [(set_attr "type" "multi")])
20931117404Skan
20932169699Skan(define_insn "stack_tls_protect_test_di"
20933169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20934169699Skan	(unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
20935169699Skan		     (match_operand:DI 2 "const_int_operand" "i")]
20936169699Skan		    UNSPEC_SP_TLS_TEST))
20937169699Skan   (clobber (match_scratch:DI 3 "=r"))]
20938169699Skan  "TARGET_64BIT"
20939169699Skan  {
20940169699Skan     /* The kernel uses a different segment register for performance reasons; a
20941169699Skan        system call would not have to trash the userspace segment register,
20942169699Skan        which would be expensive */
20943169699Skan     if (ix86_cmodel != CM_KERNEL)
20944169699Skan        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}";
20945169699Skan     else
20946169699Skan        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR %%gs:%P2}";
20947169699Skan  }
20948169699Skan  [(set_attr "type" "multi")])
20949117404Skan
20950169699Skan(include "sse.md")
20951169699Skan(include "mmx.md")
20952169699Skan(include "sync.md")
20953