i386.md revision 219374
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.
190219374Smm(define_attr "cpu" "i386,i486,pentium,pentiumpro,geode,k6,athlon,pentium4,k8,nocona,core2,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")
476219374Smm(include "geode.md")
477169699Skan
47890286Sobrien
479169699Skan;; Operand and operator predicates and constraints
480169699Skan
481169699Skan(include "predicates.md")
482169699Skan(include "constraints.md")
483169699Skan
484169699Skan
48590286Sobrien;; Compare instructions.
48690286Sobrien
48790286Sobrien;; All compare insns have expanders that save the operands away without
48890286Sobrien;; actually generating RTL.  The bCOND or sCOND (emitted immediately
48990286Sobrien;; after the cmp) will actually emit the cmpM.
49090286Sobrien
491169699Skan(define_expand "cmpti"
492169699Skan  [(set (reg:CC FLAGS_REG)
493169699Skan	(compare:CC (match_operand:TI 0 "nonimmediate_operand" "")
494169699Skan		    (match_operand:TI 1 "x86_64_general_operand" "")))]
495169699Skan  "TARGET_64BIT"
496169699Skan{
497169699Skan  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
498169699Skan    operands[0] = force_reg (TImode, operands[0]);
499169699Skan  ix86_compare_op0 = operands[0];
500169699Skan  ix86_compare_op1 = operands[1];
501169699Skan  DONE;
502169699Skan})
503169699Skan
50490286Sobrien(define_expand "cmpdi"
505169699Skan  [(set (reg:CC FLAGS_REG)
50690286Sobrien	(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
50790286Sobrien		    (match_operand:DI 1 "x86_64_general_operand" "")))]
50890286Sobrien  ""
50918334Speter{
51090286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
51190286Sobrien    operands[0] = force_reg (DImode, operands[0]);
51290286Sobrien  ix86_compare_op0 = operands[0];
51390286Sobrien  ix86_compare_op1 = operands[1];
51418334Speter  DONE;
51590286Sobrien})
51618334Speter
51718334Speter(define_expand "cmpsi"
518169699Skan  [(set (reg:CC FLAGS_REG)
51990286Sobrien	(compare:CC (match_operand:SI 0 "cmpsi_operand" "")
52090286Sobrien		    (match_operand:SI 1 "general_operand" "")))]
52118334Speter  ""
52218334Speter{
52318334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
52418334Speter    operands[0] = force_reg (SImode, operands[0]);
52590286Sobrien  ix86_compare_op0 = operands[0];
52690286Sobrien  ix86_compare_op1 = operands[1];
52718334Speter  DONE;
52890286Sobrien})
52918334Speter
53018334Speter(define_expand "cmphi"
531169699Skan  [(set (reg:CC FLAGS_REG)
53290286Sobrien	(compare:CC (match_operand:HI 0 "nonimmediate_operand" "")
53390286Sobrien		    (match_operand:HI 1 "general_operand" "")))]
53418334Speter  ""
53518334Speter{
53618334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
53718334Speter    operands[0] = force_reg (HImode, operands[0]);
53890286Sobrien  ix86_compare_op0 = operands[0];
53990286Sobrien  ix86_compare_op1 = operands[1];
54018334Speter  DONE;
54190286Sobrien})
54218334Speter
54318334Speter(define_expand "cmpqi"
544169699Skan  [(set (reg:CC FLAGS_REG)
54590286Sobrien	(compare:CC (match_operand:QI 0 "nonimmediate_operand" "")
54690286Sobrien		    (match_operand:QI 1 "general_operand" "")))]
54790286Sobrien  "TARGET_QIMODE_MATH"
54818334Speter{
54918334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
55018334Speter    operands[0] = force_reg (QImode, operands[0]);
55190286Sobrien  ix86_compare_op0 = operands[0];
55290286Sobrien  ix86_compare_op1 = operands[1];
55318334Speter  DONE;
55490286Sobrien})
55518334Speter
55690286Sobrien(define_insn "cmpdi_ccno_1_rex64"
557169699Skan  [(set (reg FLAGS_REG)
55890286Sobrien	(compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")
55990286Sobrien		 (match_operand:DI 1 "const0_operand" "n,n")))]
56090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
56190286Sobrien  "@
56290286Sobrien   test{q}\t{%0, %0|%0, %0}
56390286Sobrien   cmp{q}\t{%1, %0|%0, %1}"
56490286Sobrien  [(set_attr "type" "test,icmp")
56590286Sobrien   (set_attr "length_immediate" "0,1")
56690286Sobrien   (set_attr "mode" "DI")])
56718334Speter
56890286Sobrien(define_insn "*cmpdi_minus_1_rex64"
569169699Skan  [(set (reg FLAGS_REG)
57090286Sobrien	(compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r")
57190286Sobrien			   (match_operand:DI 1 "x86_64_general_operand" "re,mr"))
57290286Sobrien		 (const_int 0)))]
57390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)"
57490286Sobrien  "cmp{q}\t{%1, %0|%0, %1}"
57590286Sobrien  [(set_attr "type" "icmp")
57690286Sobrien   (set_attr "mode" "DI")])
57718334Speter
57890286Sobrien(define_expand "cmpdi_1_rex64"
579169699Skan  [(set (reg:CC FLAGS_REG)
58090286Sobrien	(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
58190286Sobrien		    (match_operand:DI 1 "general_operand" "")))]
58290286Sobrien  "TARGET_64BIT"
58390286Sobrien  "")
58418334Speter
58590286Sobrien(define_insn "cmpdi_1_insn_rex64"
586169699Skan  [(set (reg FLAGS_REG)
58790286Sobrien	(compare (match_operand:DI 0 "nonimmediate_operand" "mr,r")
58890286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "re,mr")))]
58990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
59090286Sobrien  "cmp{q}\t{%1, %0|%0, %1}"
59190286Sobrien  [(set_attr "type" "icmp")
59290286Sobrien   (set_attr "mode" "DI")])
59350650Sobrien
59418334Speter
59590286Sobrien(define_insn "*cmpsi_ccno_1"
596169699Skan  [(set (reg FLAGS_REG)
59790286Sobrien	(compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
59890286Sobrien		 (match_operand:SI 1 "const0_operand" "n,n")))]
59990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
60090286Sobrien  "@
60190286Sobrien   test{l}\t{%0, %0|%0, %0}
60290286Sobrien   cmp{l}\t{%1, %0|%0, %1}"
60390286Sobrien  [(set_attr "type" "test,icmp")
60490286Sobrien   (set_attr "length_immediate" "0,1")
60590286Sobrien   (set_attr "mode" "SI")])
60650650Sobrien
60790286Sobrien(define_insn "*cmpsi_minus_1"
608169699Skan  [(set (reg FLAGS_REG)
60990286Sobrien	(compare (minus:SI (match_operand:SI 0 "nonimmediate_operand" "rm,r")
61090286Sobrien			   (match_operand:SI 1 "general_operand" "ri,mr"))
61190286Sobrien		 (const_int 0)))]
61290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
61390286Sobrien  "cmp{l}\t{%1, %0|%0, %1}"
61490286Sobrien  [(set_attr "type" "icmp")
61590286Sobrien   (set_attr "mode" "SI")])
61618334Speter
61790286Sobrien(define_expand "cmpsi_1"
618169699Skan  [(set (reg:CC FLAGS_REG)
61990286Sobrien	(compare:CC (match_operand:SI 0 "nonimmediate_operand" "rm,r")
62090286Sobrien		    (match_operand:SI 1 "general_operand" "ri,mr")))]
62190286Sobrien  ""
62290286Sobrien  "")
62318334Speter
62490286Sobrien(define_insn "*cmpsi_1_insn"
625169699Skan  [(set (reg FLAGS_REG)
62690286Sobrien	(compare (match_operand:SI 0 "nonimmediate_operand" "rm,r")
62790286Sobrien		 (match_operand:SI 1 "general_operand" "ri,mr")))]
62890286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
62990286Sobrien    && ix86_match_ccmode (insn, CCmode)"
63090286Sobrien  "cmp{l}\t{%1, %0|%0, %1}"
63190286Sobrien  [(set_attr "type" "icmp")
63290286Sobrien   (set_attr "mode" "SI")])
63318334Speter
63490286Sobrien(define_insn "*cmphi_ccno_1"
635169699Skan  [(set (reg FLAGS_REG)
63690286Sobrien	(compare (match_operand:HI 0 "nonimmediate_operand" "r,?mr")
63790286Sobrien		 (match_operand:HI 1 "const0_operand" "n,n")))]
63890286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
63990286Sobrien  "@
64090286Sobrien   test{w}\t{%0, %0|%0, %0}
64190286Sobrien   cmp{w}\t{%1, %0|%0, %1}"
64290286Sobrien  [(set_attr "type" "test,icmp")
64390286Sobrien   (set_attr "length_immediate" "0,1")
64490286Sobrien   (set_attr "mode" "HI")])
64518334Speter
64690286Sobrien(define_insn "*cmphi_minus_1"
647169699Skan  [(set (reg FLAGS_REG)
64890286Sobrien	(compare (minus:HI (match_operand:HI 0 "nonimmediate_operand" "rm,r")
64990286Sobrien			   (match_operand:HI 1 "general_operand" "ri,mr"))
65090286Sobrien		 (const_int 0)))]
65190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
65290286Sobrien  "cmp{w}\t{%1, %0|%0, %1}"
65390286Sobrien  [(set_attr "type" "icmp")
65490286Sobrien   (set_attr "mode" "HI")])
65550650Sobrien
65690286Sobrien(define_insn "*cmphi_1"
657169699Skan  [(set (reg FLAGS_REG)
65890286Sobrien	(compare (match_operand:HI 0 "nonimmediate_operand" "rm,r")
65990286Sobrien		 (match_operand:HI 1 "general_operand" "ri,mr")))]
66090286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
66190286Sobrien   && ix86_match_ccmode (insn, CCmode)"
66290286Sobrien  "cmp{w}\t{%1, %0|%0, %1}"
66390286Sobrien  [(set_attr "type" "icmp")
66490286Sobrien   (set_attr "mode" "HI")])
66518334Speter
66690286Sobrien(define_insn "*cmpqi_ccno_1"
667169699Skan  [(set (reg FLAGS_REG)
66890286Sobrien	(compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq")
66990286Sobrien		 (match_operand:QI 1 "const0_operand" "n,n")))]
67090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
67190286Sobrien  "@
67290286Sobrien   test{b}\t{%0, %0|%0, %0}
67390286Sobrien   cmp{b}\t{$0, %0|%0, 0}"
67490286Sobrien  [(set_attr "type" "test,icmp")
67590286Sobrien   (set_attr "length_immediate" "0,1")
67690286Sobrien   (set_attr "mode" "QI")])
67718334Speter
67890286Sobrien(define_insn "*cmpqi_1"
679169699Skan  [(set (reg FLAGS_REG)
68090286Sobrien	(compare (match_operand:QI 0 "nonimmediate_operand" "qm,q")
68190286Sobrien		 (match_operand:QI 1 "general_operand" "qi,mq")))]
68290286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
68390286Sobrien    && ix86_match_ccmode (insn, CCmode)"
68490286Sobrien  "cmp{b}\t{%1, %0|%0, %1}"
68590286Sobrien  [(set_attr "type" "icmp")
68690286Sobrien   (set_attr "mode" "QI")])
68718334Speter
68890286Sobrien(define_insn "*cmpqi_minus_1"
689169699Skan  [(set (reg FLAGS_REG)
69090286Sobrien	(compare (minus:QI (match_operand:QI 0 "nonimmediate_operand" "qm,q")
69190286Sobrien			   (match_operand:QI 1 "general_operand" "qi,mq"))
69290286Sobrien		 (const_int 0)))]
69390286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)"
69490286Sobrien  "cmp{b}\t{%1, %0|%0, %1}"
69590286Sobrien  [(set_attr "type" "icmp")
69690286Sobrien   (set_attr "mode" "QI")])
69718334Speter
69890286Sobrien(define_insn "*cmpqi_ext_1"
699169699Skan  [(set (reg FLAGS_REG)
70090286Sobrien	(compare
70190286Sobrien	  (match_operand:QI 0 "general_operand" "Qm")
70290286Sobrien	  (subreg:QI
70390286Sobrien	    (zero_extract:SI
70490286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
70590286Sobrien	      (const_int 8)
70690286Sobrien	      (const_int 8)) 0)))]
70790286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
70890286Sobrien  "cmp{b}\t{%h1, %0|%0, %h1}"
70990286Sobrien  [(set_attr "type" "icmp")
71090286Sobrien   (set_attr "mode" "QI")])
71190286Sobrien
71290286Sobrien(define_insn "*cmpqi_ext_1_rex64"
713169699Skan  [(set (reg FLAGS_REG)
71490286Sobrien	(compare
71590286Sobrien	  (match_operand:QI 0 "register_operand" "Q")
71690286Sobrien	  (subreg:QI
71790286Sobrien	    (zero_extract:SI
71890286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
71990286Sobrien	      (const_int 8)
72090286Sobrien	      (const_int 8)) 0)))]
72190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
72290286Sobrien  "cmp{b}\t{%h1, %0|%0, %h1}"
72390286Sobrien  [(set_attr "type" "icmp")
72490286Sobrien   (set_attr "mode" "QI")])
72590286Sobrien
72690286Sobrien(define_insn "*cmpqi_ext_2"
727169699Skan  [(set (reg FLAGS_REG)
72890286Sobrien	(compare
72990286Sobrien	  (subreg:QI
73090286Sobrien	    (zero_extract:SI
73190286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
73290286Sobrien	      (const_int 8)
73390286Sobrien	      (const_int 8)) 0)
73490286Sobrien	  (match_operand:QI 1 "const0_operand" "n")))]
73590286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
73690286Sobrien  "test{b}\t%h0, %h0"
73790286Sobrien  [(set_attr "type" "test")
73890286Sobrien   (set_attr "length_immediate" "0")
73990286Sobrien   (set_attr "mode" "QI")])
74090286Sobrien
74190286Sobrien(define_expand "cmpqi_ext_3"
742169699Skan  [(set (reg:CC FLAGS_REG)
74390286Sobrien	(compare:CC
74490286Sobrien	  (subreg:QI
74590286Sobrien	    (zero_extract:SI
74690286Sobrien	      (match_operand 0 "ext_register_operand" "")
74790286Sobrien	      (const_int 8)
74890286Sobrien	      (const_int 8)) 0)
74990286Sobrien	  (match_operand:QI 1 "general_operand" "")))]
75090286Sobrien  ""
75190286Sobrien  "")
75290286Sobrien
75390286Sobrien(define_insn "cmpqi_ext_3_insn"
754169699Skan  [(set (reg FLAGS_REG)
75590286Sobrien	(compare
75690286Sobrien	  (subreg:QI
75790286Sobrien	    (zero_extract:SI
75890286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
75990286Sobrien	      (const_int 8)
76090286Sobrien	      (const_int 8)) 0)
76190286Sobrien	  (match_operand:QI 1 "general_operand" "Qmn")))]
76290286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
76390286Sobrien  "cmp{b}\t{%1, %h0|%h0, %1}"
76490286Sobrien  [(set_attr "type" "icmp")
76590286Sobrien   (set_attr "mode" "QI")])
76690286Sobrien
76790286Sobrien(define_insn "cmpqi_ext_3_insn_rex64"
768169699Skan  [(set (reg FLAGS_REG)
76990286Sobrien	(compare
77090286Sobrien	  (subreg:QI
77190286Sobrien	    (zero_extract:SI
77290286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
77390286Sobrien	      (const_int 8)
77490286Sobrien	      (const_int 8)) 0)
77590286Sobrien	  (match_operand:QI 1 "nonmemory_operand" "Qn")))]
77690286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
77790286Sobrien  "cmp{b}\t{%1, %h0|%h0, %1}"
77890286Sobrien  [(set_attr "type" "icmp")
77990286Sobrien   (set_attr "mode" "QI")])
78090286Sobrien
78190286Sobrien(define_insn "*cmpqi_ext_4"
782169699Skan  [(set (reg FLAGS_REG)
78390286Sobrien	(compare
78490286Sobrien	  (subreg:QI
78590286Sobrien	    (zero_extract:SI
78690286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
78790286Sobrien	      (const_int 8)
78890286Sobrien	      (const_int 8)) 0)
78990286Sobrien	  (subreg:QI
79090286Sobrien	    (zero_extract:SI
79190286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
79290286Sobrien	      (const_int 8)
79390286Sobrien	      (const_int 8)) 0)))]
79490286Sobrien  "ix86_match_ccmode (insn, CCmode)"
79590286Sobrien  "cmp{b}\t{%h1, %h0|%h0, %h1}"
79690286Sobrien  [(set_attr "type" "icmp")
79790286Sobrien   (set_attr "mode" "QI")])
79890286Sobrien
79990286Sobrien;; These implement float point compares.
80090286Sobrien;; %%% See if we can get away with VOIDmode operands on the actual insns,
80190286Sobrien;; which would allow mix and match FP modes on the compares.  Which is what
80290286Sobrien;; the old patterns did, but with many more of them.
80390286Sobrien
80418334Speter(define_expand "cmpxf"
805169699Skan  [(set (reg:CC FLAGS_REG)
806169699Skan	(compare:CC (match_operand:XF 0 "nonmemory_operand" "")
807169699Skan		    (match_operand:XF 1 "nonmemory_operand" "")))]
80818334Speter  "TARGET_80387"
80918334Speter{
81090286Sobrien  ix86_compare_op0 = operands[0];
81190286Sobrien  ix86_compare_op1 = operands[1];
81218334Speter  DONE;
81390286Sobrien})
81418334Speter
81518334Speter(define_expand "cmpdf"
816169699Skan  [(set (reg:CC FLAGS_REG)
81790286Sobrien	(compare:CC (match_operand:DF 0 "cmp_fp_expander_operand" "")
81890286Sobrien		    (match_operand:DF 1 "cmp_fp_expander_operand" "")))]
819169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
82018334Speter{
82190286Sobrien  ix86_compare_op0 = operands[0];
82290286Sobrien  ix86_compare_op1 = operands[1];
82318334Speter  DONE;
82490286Sobrien})
82518334Speter
82618334Speter(define_expand "cmpsf"
827169699Skan  [(set (reg:CC FLAGS_REG)
82890286Sobrien	(compare:CC (match_operand:SF 0 "cmp_fp_expander_operand" "")
82990286Sobrien		    (match_operand:SF 1 "cmp_fp_expander_operand" "")))]
830169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
83118334Speter{
83290286Sobrien  ix86_compare_op0 = operands[0];
83390286Sobrien  ix86_compare_op1 = operands[1];
83418334Speter  DONE;
83590286Sobrien})
83618334Speter
83790286Sobrien;; FP compares, step 1:
83890286Sobrien;; Set the FP condition codes.
83990286Sobrien;;
84090286Sobrien;; CCFPmode	compare with exceptions
84190286Sobrien;; CCFPUmode	compare with no exceptions
84218334Speter
843169699Skan;; We may not use "#" to split and emit these, since the REG_DEAD notes
844169699Skan;; used to manage the reg stack popping would not be preserved.
84518334Speter
84690286Sobrien(define_insn "*cmpfp_0"
84790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
84890286Sobrien	(unspec:HI
849169699Skan	  [(compare:CCFP
850169699Skan	     (match_operand 1 "register_operand" "f")
851169699Skan	     (match_operand 2 "const0_operand" "X"))]
852169699Skan	UNSPEC_FNSTSW))]
85390286Sobrien  "TARGET_80387
85490286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
85590286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
856169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
85790286Sobrien  [(set_attr "type" "multi")
858169699Skan   (set_attr "unit" "i387")
859132727Skan   (set (attr "mode")
860132727Skan     (cond [(match_operand:SF 1 "" "")
861132727Skan	      (const_string "SF")
862132727Skan	    (match_operand:DF 1 "" "")
863132727Skan	      (const_string "DF")
864132727Skan	   ]
865132727Skan	   (const_string "XF")))])
86690286Sobrien
867169699Skan(define_insn "*cmpfp_sf"
86890286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
86990286Sobrien	(unspec:HI
87090286Sobrien	  [(compare:CCFP
87190286Sobrien	     (match_operand:SF 1 "register_operand" "f")
872117404Skan	     (match_operand:SF 2 "nonimmediate_operand" "fm"))]
873117404Skan	  UNSPEC_FNSTSW))]
87418334Speter  "TARGET_80387"
875169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
876169699Skan  [(set_attr "type" "multi")
877169699Skan   (set_attr "unit" "i387")
87890286Sobrien   (set_attr "mode" "SF")])
87918334Speter
880169699Skan(define_insn "*cmpfp_df"
88190286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
88290286Sobrien	(unspec:HI
88390286Sobrien	  [(compare:CCFP
88490286Sobrien	     (match_operand:DF 1 "register_operand" "f")
885117404Skan	     (match_operand:DF 2 "nonimmediate_operand" "fm"))]
886117404Skan	  UNSPEC_FNSTSW))]
88718334Speter  "TARGET_80387"
888169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
88990286Sobrien  [(set_attr "type" "multi")
890169699Skan   (set_attr "unit" "i387")
89190286Sobrien   (set_attr "mode" "DF")])
89218334Speter
893169699Skan(define_insn "*cmpfp_xf"
89490286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
89590286Sobrien	(unspec:HI
89690286Sobrien	  [(compare:CCFP
89790286Sobrien	     (match_operand:XF 1 "register_operand" "f")
898117404Skan	     (match_operand:XF 2 "register_operand" "f"))]
899117404Skan	  UNSPEC_FNSTSW))]
90090286Sobrien  "TARGET_80387"
901169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
90290286Sobrien  [(set_attr "type" "multi")
903169699Skan   (set_attr "unit" "i387")
90490286Sobrien   (set_attr "mode" "XF")])
90518334Speter
906169699Skan(define_insn "*cmpfp_u"
90790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
90890286Sobrien	(unspec:HI
90990286Sobrien	  [(compare:CCFPU
91090286Sobrien	     (match_operand 1 "register_operand" "f")
911117404Skan	     (match_operand 2 "register_operand" "f"))]
912117404Skan	  UNSPEC_FNSTSW))]
91390286Sobrien  "TARGET_80387
91490286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
91590286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
916169699Skan  "* return output_fp_compare (insn, operands, 0, 1);"
91790286Sobrien  [(set_attr "type" "multi")
918169699Skan   (set_attr "unit" "i387")
919132727Skan   (set (attr "mode")
920132727Skan     (cond [(match_operand:SF 1 "" "")
921132727Skan	      (const_string "SF")
922132727Skan	    (match_operand:DF 1 "" "")
923132727Skan	      (const_string "DF")
924132727Skan	   ]
925132727Skan	   (const_string "XF")))])
92618334Speter
927169699Skan(define_insn "*cmpfp_<mode>"
928169699Skan  [(set (match_operand:HI 0 "register_operand" "=a")
929169699Skan	(unspec:HI
930169699Skan	  [(compare:CCFP
931169699Skan	     (match_operand 1 "register_operand" "f")
932169699Skan	     (match_operator 3 "float_operator"
933169699Skan	       [(match_operand:X87MODEI12 2 "memory_operand" "m")]))]
934169699Skan	  UNSPEC_FNSTSW))]
935169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
936169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
937169699Skan   && (GET_MODE (operands [3]) == GET_MODE (operands[1]))"
938169699Skan  "* return output_fp_compare (insn, operands, 0, 0);"
939169699Skan  [(set_attr "type" "multi")
940169699Skan   (set_attr "unit" "i387")
941169699Skan   (set_attr "fp_int_src" "true")
942169699Skan   (set_attr "mode" "<MODE>")])
94318334Speter
94490286Sobrien;; FP compares, step 2
94590286Sobrien;; Move the fpsw to ax.
94618334Speter
947169699Skan(define_insn "x86_fnstsw_1"
94890286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
949169699Skan	(unspec:HI [(reg:CCFP FPSR_REG)] UNSPEC_FNSTSW))]
95090286Sobrien  "TARGET_80387"
95190286Sobrien  "fnstsw\t%0"
95290286Sobrien  [(set_attr "length" "2")
95390286Sobrien   (set_attr "mode" "SI")
954169699Skan   (set_attr "unit" "i387")])
95518334Speter
95690286Sobrien;; FP compares, step 3
95790286Sobrien;; Get ax into flags, general case.
95850650Sobrien
95990286Sobrien(define_insn "x86_sahf_1"
960169699Skan  [(set (reg:CC FLAGS_REG)
961117404Skan	(unspec:CC [(match_operand:HI 0 "register_operand" "a")] UNSPEC_SAHF))]
96290286Sobrien  "!TARGET_64BIT"
96390286Sobrien  "sahf"
96490286Sobrien  [(set_attr "length" "1")
96590286Sobrien   (set_attr "athlon_decode" "vector")
966169699Skan   (set_attr "mode" "SI")])
96718334Speter
96890286Sobrien;; Pentium Pro can do steps 1 through 3 in one go.
96918334Speter
970169699Skan(define_insn "*cmpfp_i_mixed"
971169699Skan  [(set (reg:CCFP FLAGS_REG)
972169699Skan	(compare:CCFP (match_operand 0 "register_operand" "f,x")
973169699Skan		      (match_operand 1 "nonimmediate_operand" "f,xm")))]
974169699Skan  "TARGET_MIX_SSE_I387
97590286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
976169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
97790286Sobrien  "* return output_fp_compare (insn, operands, 1, 0);"
978132727Skan  [(set_attr "type" "fcmp,ssecomi")
979132727Skan   (set (attr "mode")
980132727Skan     (if_then_else (match_operand:SF 1 "" "")
981132727Skan        (const_string "SF")
982132727Skan        (const_string "DF")))
98390286Sobrien   (set_attr "athlon_decode" "vector")])
98418334Speter
985169699Skan(define_insn "*cmpfp_i_sse"
986169699Skan  [(set (reg:CCFP FLAGS_REG)
98790286Sobrien	(compare:CCFP (match_operand 0 "register_operand" "x")
98890286Sobrien		      (match_operand 1 "nonimmediate_operand" "xm")))]
989169699Skan  "TARGET_SSE_MATH
990169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
991169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
99290286Sobrien  "* return output_fp_compare (insn, operands, 1, 0);"
993132727Skan  [(set_attr "type" "ssecomi")
994132727Skan   (set (attr "mode")
995132727Skan     (if_then_else (match_operand:SF 1 "" "")
996132727Skan        (const_string "SF")
997132727Skan        (const_string "DF")))
99890286Sobrien   (set_attr "athlon_decode" "vector")])
99918334Speter
1000169699Skan(define_insn "*cmpfp_i_i387"
1001169699Skan  [(set (reg:CCFP FLAGS_REG)
1002169699Skan	(compare:CCFP (match_operand 0 "register_operand" "f")
1003169699Skan		      (match_operand 1 "register_operand" "f")))]
100490286Sobrien  "TARGET_80387 && TARGET_CMOVE
1005169699Skan   && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
100690286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))
100790286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
1008169699Skan  "* return output_fp_compare (insn, operands, 1, 0);"
100990286Sobrien  [(set_attr "type" "fcmp")
1010132727Skan   (set (attr "mode")
1011132727Skan     (cond [(match_operand:SF 1 "" "")
1012132727Skan	      (const_string "SF")
1013132727Skan	    (match_operand:DF 1 "" "")
1014132727Skan	      (const_string "DF")
1015132727Skan	   ]
1016132727Skan	   (const_string "XF")))
101790286Sobrien   (set_attr "athlon_decode" "vector")])
101818334Speter
1019169699Skan(define_insn "*cmpfp_iu_mixed"
1020169699Skan  [(set (reg:CCFPU FLAGS_REG)
1021169699Skan	(compare:CCFPU (match_operand 0 "register_operand" "f,x")
1022169699Skan		       (match_operand 1 "nonimmediate_operand" "f,xm")))]
1023169699Skan  "TARGET_MIX_SSE_I387
102490286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
102590286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
102690286Sobrien  "* return output_fp_compare (insn, operands, 1, 1);"
1027132727Skan  [(set_attr "type" "fcmp,ssecomi")
1028132727Skan   (set (attr "mode")
1029132727Skan     (if_then_else (match_operand:SF 1 "" "")
1030132727Skan        (const_string "SF")
1031132727Skan        (const_string "DF")))
103290286Sobrien   (set_attr "athlon_decode" "vector")])
103350650Sobrien
1034169699Skan(define_insn "*cmpfp_iu_sse"
1035169699Skan  [(set (reg:CCFPU FLAGS_REG)
103690286Sobrien	(compare:CCFPU (match_operand 0 "register_operand" "x")
103790286Sobrien		       (match_operand 1 "nonimmediate_operand" "xm")))]
1038169699Skan  "TARGET_SSE_MATH
1039169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
104090286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
104190286Sobrien  "* return output_fp_compare (insn, operands, 1, 1);"
1042132727Skan  [(set_attr "type" "ssecomi")
1043132727Skan   (set (attr "mode")
1044132727Skan     (if_then_else (match_operand:SF 1 "" "")
1045132727Skan        (const_string "SF")
1046132727Skan        (const_string "DF")))
104790286Sobrien   (set_attr "athlon_decode" "vector")])
1048169699Skan
1049169699Skan(define_insn "*cmpfp_iu_387"
1050169699Skan  [(set (reg:CCFPU FLAGS_REG)
1051169699Skan	(compare:CCFPU (match_operand 0 "register_operand" "f")
1052169699Skan		       (match_operand 1 "register_operand" "f")))]
1053169699Skan  "TARGET_80387 && TARGET_CMOVE
1054169699Skan   && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
1055169699Skan   && FLOAT_MODE_P (GET_MODE (operands[0]))
1056169699Skan   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
1057169699Skan  "* return output_fp_compare (insn, operands, 1, 1);"
1058169699Skan  [(set_attr "type" "fcmp")
1059169699Skan   (set (attr "mode")
1060169699Skan     (cond [(match_operand:SF 1 "" "")
1061169699Skan	      (const_string "SF")
1062169699Skan	    (match_operand:DF 1 "" "")
1063169699Skan	      (const_string "DF")
1064169699Skan	   ]
1065169699Skan	   (const_string "XF")))
1066169699Skan   (set_attr "athlon_decode" "vector")])
106790286Sobrien
106890286Sobrien;; Move instructions.
106918334Speter
107018334Speter;; General case of fullword move.
107118334Speter
107218334Speter(define_expand "movsi"
107390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
107418334Speter	(match_operand:SI 1 "general_operand" ""))]
107518334Speter  ""
107690286Sobrien  "ix86_expand_move (SImode, operands); DONE;")
107718334Speter
107890286Sobrien;; Push/pop instructions.  They are separate since autoinc/dec is not a
107990286Sobrien;; general_operand.
108090286Sobrien;;
108190286Sobrien;; %%% We don't use a post-inc memory reference because x86 is not a 
108290286Sobrien;; general AUTO_INC_DEC host, which impacts how it is treated in flow.
108390286Sobrien;; Changing this impacts compiler performance on other non-AUTO_INC_DEC
108490286Sobrien;; targets without our curiosities, and it is just as easy to represent
108590286Sobrien;; this differently.
108618334Speter
108790286Sobrien(define_insn "*pushsi2"
108890286Sobrien  [(set (match_operand:SI 0 "push_operand" "=<")
108990286Sobrien	(match_operand:SI 1 "general_no_elim_operand" "ri*m"))]
109090286Sobrien  "!TARGET_64BIT"
109190286Sobrien  "push{l}\t%1"
109290286Sobrien  [(set_attr "type" "push")
109390286Sobrien   (set_attr "mode" "SI")])
109418334Speter
109590286Sobrien;; For 64BIT abi we always round up to 8 bytes.
109690286Sobrien(define_insn "*pushsi2_rex64"
109790286Sobrien  [(set (match_operand:SI 0 "push_operand" "=X")
109890286Sobrien	(match_operand:SI 1 "nonmemory_no_elim_operand" "ri"))]
109990286Sobrien  "TARGET_64BIT"
110090286Sobrien  "push{q}\t%q1"
110190286Sobrien  [(set_attr "type" "push")
110290286Sobrien   (set_attr "mode" "SI")])
110318334Speter
110490286Sobrien(define_insn "*pushsi2_prologue"
110590286Sobrien  [(set (match_operand:SI 0 "push_operand" "=<")
110690286Sobrien	(match_operand:SI 1 "general_no_elim_operand" "ri*m"))
110790286Sobrien   (clobber (mem:BLK (scratch)))]
110890286Sobrien  "!TARGET_64BIT"
110990286Sobrien  "push{l}\t%1"
111090286Sobrien  [(set_attr "type" "push")
111190286Sobrien   (set_attr "mode" "SI")])
111252296Sobrien
111390286Sobrien(define_insn "*popsi1_epilogue"
111490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
1115169699Skan	(mem:SI (reg:SI SP_REG)))
1116169699Skan   (set (reg:SI SP_REG)
1117169699Skan	(plus:SI (reg:SI SP_REG) (const_int 4)))
111890286Sobrien   (clobber (mem:BLK (scratch)))]
111990286Sobrien  "!TARGET_64BIT"
112090286Sobrien  "pop{l}\t%0"
112190286Sobrien  [(set_attr "type" "pop")
112290286Sobrien   (set_attr "mode" "SI")])
112318334Speter
112490286Sobrien(define_insn "popsi1"
112590286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
1126169699Skan	(mem:SI (reg:SI SP_REG)))
1127169699Skan   (set (reg:SI SP_REG)
1128169699Skan	(plus:SI (reg:SI SP_REG) (const_int 4)))]
112990286Sobrien  "!TARGET_64BIT"
113090286Sobrien  "pop{l}\t%0"
113190286Sobrien  [(set_attr "type" "pop")
113290286Sobrien   (set_attr "mode" "SI")])
113318334Speter
113490286Sobrien(define_insn "*movsi_xor"
113590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
113690286Sobrien	(match_operand:SI 1 "const0_operand" "i"))
1137169699Skan   (clobber (reg:CC FLAGS_REG))]
113890286Sobrien  "reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
113990286Sobrien  "xor{l}\t{%0, %0|%0, %0}"
114090286Sobrien  [(set_attr "type" "alu1")
114190286Sobrien   (set_attr "mode" "SI")
114290286Sobrien   (set_attr "length_immediate" "0")])
1143132727Skan 
114490286Sobrien(define_insn "*movsi_or"
114590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
114690286Sobrien	(match_operand:SI 1 "immediate_operand" "i"))
1147169699Skan   (clobber (reg:CC FLAGS_REG))]
1148132727Skan  "reload_completed
1149132727Skan   && operands[1] == constm1_rtx
115090286Sobrien   && (TARGET_PENTIUM || optimize_size)"
115190286Sobrien{
115290286Sobrien  operands[1] = constm1_rtx;
115390286Sobrien  return "or{l}\t{%1, %0|%0, %1}";
115490286Sobrien}
115590286Sobrien  [(set_attr "type" "alu1")
115690286Sobrien   (set_attr "mode" "SI")
115790286Sobrien   (set_attr "length_immediate" "1")])
115818334Speter
115990286Sobrien(define_insn "*movsi_1"
1160169699Skan  [(set (match_operand:SI 0 "nonimmediate_operand"
1161169699Skan			"=r  ,m  ,*y,*y,?rm,?*y,*x,*x,?r,m ,?*Y,*x")
1162169699Skan	(match_operand:SI 1 "general_operand"
1163169699Skan			"rinm,rin,C ,*y,*y ,rm ,C ,*x,*Y,*x,r  ,m "))]
1164169699Skan  "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
116550650Sobrien{
116690286Sobrien  switch (get_attr_type (insn))
116790286Sobrien    {
1168169699Skan    case TYPE_SSELOG1:
1169117404Skan      if (get_attr_mode (insn) == MODE_TI)
1170169699Skan        return "pxor\t%0, %0";
1171169699Skan      return "xorps\t%0, %0";
117252296Sobrien
1173169699Skan    case TYPE_SSEMOV:
1174169699Skan      switch (get_attr_mode (insn))
1175169699Skan	{
1176169699Skan	case MODE_TI:
1177169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
1178169699Skan	case MODE_V4SF:
1179169699Skan	  return "movaps\t{%1, %0|%0, %1}";
1180169699Skan	case MODE_SI:
1181169699Skan          return "movd\t{%1, %0|%0, %1}";
1182169699Skan	case MODE_SF:
1183169699Skan          return "movss\t{%1, %0|%0, %1}";
1184169699Skan	default:
1185169699Skan	  gcc_unreachable ();
1186169699Skan	}
118752296Sobrien
1188169699Skan    case TYPE_MMXADD:
1189169699Skan      return "pxor\t%0, %0";
119018334Speter
1191132727Skan    case TYPE_MMXMOV:
1192132727Skan      if (get_attr_mode (insn) == MODE_DI)
1193132727Skan	return "movq\t{%1, %0|%0, %1}";
1194132727Skan      return "movd\t{%1, %0|%0, %1}";
1195132727Skan
1196132727Skan    case TYPE_LEA:
1197132727Skan      return "lea{l}\t{%1, %0|%0, %1}";
1198132727Skan
1199132727Skan    default:
1200169699Skan      gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
1201132727Skan      return "mov{l}\t{%1, %0|%0, %1}";
1202132727Skan    }
1203132727Skan}
1204132727Skan  [(set (attr "type")
1205169699Skan     (cond [(eq_attr "alternative" "2")
1206169699Skan	      (const_string "mmxadd")
1207169699Skan	    (eq_attr "alternative" "3,4,5")
1208132727Skan	      (const_string "mmxmov")
1209169699Skan	    (eq_attr "alternative" "6")
1210169699Skan	      (const_string "sselog1")
1211169699Skan	    (eq_attr "alternative" "7,8,9,10,11")
1212132727Skan	      (const_string "ssemov")
1213169699Skan 	    (match_operand:DI 1 "pic_32bit_operand" "")
1214132727Skan	      (const_string "lea")
1215132727Skan	   ]
1216132727Skan	   (const_string "imov")))
1217169699Skan   (set (attr "mode")
1218169699Skan     (cond [(eq_attr "alternative" "2,3")
1219169699Skan	      (const_string "DI")
1220169699Skan	    (eq_attr "alternative" "6,7")
1221169699Skan	      (if_then_else
1222169699Skan	        (eq (symbol_ref "TARGET_SSE2") (const_int 0))
1223169699Skan	        (const_string "V4SF")
1224169699Skan	        (const_string "TI"))
1225169699Skan	    (and (eq_attr "alternative" "8,9,10,11")
1226169699Skan	         (eq (symbol_ref "TARGET_SSE2") (const_int 0)))
1227169699Skan	      (const_string "SF")
1228169699Skan	   ]
1229169699Skan	   (const_string "SI")))])
1230132727Skan
1231132727Skan;; Stores and loads of ax to arbitrary constant address.
123290286Sobrien;; We fake an second form of instruction to force reload to load address
123390286Sobrien;; into register when rax is not available
123490286Sobrien(define_insn "*movabssi_1_rex64"
1235117404Skan  [(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1236117404Skan	(match_operand:SI 1 "nonmemory_operand" "a,er"))]
1237117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
123890286Sobrien  "@
123990286Sobrien   movabs{l}\t{%1, %P0|%P0, %1}
1240117404Skan   mov{l}\t{%1, %a0|%a0, %1}"
124190286Sobrien  [(set_attr "type" "imov")
1242117404Skan   (set_attr "modrm" "0,*")
1243117404Skan   (set_attr "length_address" "8,0")
1244117404Skan   (set_attr "length_immediate" "0,*")
124590286Sobrien   (set_attr "memory" "store")
124690286Sobrien   (set_attr "mode" "SI")])
124750650Sobrien
124890286Sobrien(define_insn "*movabssi_2_rex64"
124990286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a,r")
125090286Sobrien        (mem:SI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1251117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
125290286Sobrien  "@
125390286Sobrien   movabs{l}\t{%P1, %0|%0, %P1}
125490286Sobrien   mov{l}\t{%a1, %0|%0, %a1}"
125590286Sobrien  [(set_attr "type" "imov")
125690286Sobrien   (set_attr "modrm" "0,*")
125790286Sobrien   (set_attr "length_address" "8,0")
125890286Sobrien   (set_attr "length_immediate" "0")
125990286Sobrien   (set_attr "memory" "load")
126090286Sobrien   (set_attr "mode" "SI")])
126190286Sobrien
126290286Sobrien(define_insn "*swapsi"
126390286Sobrien  [(set (match_operand:SI 0 "register_operand" "+r")
126490286Sobrien	(match_operand:SI 1 "register_operand" "+r"))
126590286Sobrien   (set (match_dup 1)
126690286Sobrien	(match_dup 0))]
126750650Sobrien  ""
126890286Sobrien  "xchg{l}\t%1, %0"
126990286Sobrien  [(set_attr "type" "imov")
1270146906Skan   (set_attr "mode" "SI")
127190286Sobrien   (set_attr "pent_pair" "np")
1272169699Skan   (set_attr "athlon_decode" "vector")])
127318334Speter
127490286Sobrien(define_expand "movhi"
127590286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
127690286Sobrien        (match_operand:HI 1 "general_operand" ""))]
127790286Sobrien  ""
127890286Sobrien  "ix86_expand_move (HImode, operands); DONE;")
127918334Speter
128090286Sobrien(define_insn "*pushhi2"
1281169699Skan  [(set (match_operand:HI 0 "push_operand" "=X")
1282169699Skan	(match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
128390286Sobrien  "!TARGET_64BIT"
1284169699Skan  "push{l}\t%k1"
128590286Sobrien  [(set_attr "type" "push")
1286169699Skan   (set_attr "mode" "SI")])
128718334Speter
128890286Sobrien;; For 64BIT abi we always round up to 8 bytes.
128990286Sobrien(define_insn "*pushhi2_rex64"
129090286Sobrien  [(set (match_operand:HI 0 "push_operand" "=X")
129190286Sobrien	(match_operand:HI 1 "nonmemory_no_elim_operand" "ri"))]
129290286Sobrien  "TARGET_64BIT"
129390286Sobrien  "push{q}\t%q1"
129490286Sobrien  [(set_attr "type" "push")
1295169699Skan   (set_attr "mode" "DI")])
129690286Sobrien
129790286Sobrien(define_insn "*movhi_1"
1298117404Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
1299117404Skan	(match_operand:HI 1 "general_operand" "r,rn,rm,rn"))]
130090286Sobrien  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
130118334Speter{
130290286Sobrien  switch (get_attr_type (insn))
130318334Speter    {
130490286Sobrien    case TYPE_IMOVX:
130590286Sobrien      /* movzwl is faster than movw on p2 due to partial word stalls,
130690286Sobrien	 though not as fast as an aligned movl.  */
130790286Sobrien      return "movz{wl|x}\t{%1, %k0|%k0, %1}";
130890286Sobrien    default:
130990286Sobrien      if (get_attr_mode (insn) == MODE_SI)
131090286Sobrien        return "mov{l}\t{%k1, %k0|%k0, %k1}";
131190286Sobrien      else
131290286Sobrien        return "mov{w}\t{%1, %0|%0, %1}";
131318334Speter    }
131490286Sobrien}
131590286Sobrien  [(set (attr "type")
1316169699Skan     (cond [(ne (symbol_ref "optimize_size") (const_int 0))
1317169699Skan	      (const_string "imov")
1318169699Skan	    (and (eq_attr "alternative" "0")
131990286Sobrien		 (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
132090286Sobrien			  (const_int 0))
132190286Sobrien		      (eq (symbol_ref "TARGET_HIMODE_MATH")
132290286Sobrien			  (const_int 0))))
132390286Sobrien	      (const_string "imov")
1324117404Skan	    (and (eq_attr "alternative" "1,2")
132590286Sobrien		 (match_operand:HI 1 "aligned_operand" ""))
132690286Sobrien	      (const_string "imov")
132790286Sobrien	    (and (ne (symbol_ref "TARGET_MOVX")
132890286Sobrien		     (const_int 0))
1329117404Skan		 (eq_attr "alternative" "0,2"))
133090286Sobrien	      (const_string "imovx")
133190286Sobrien	   ]
133290286Sobrien	   (const_string "imov")))
133390286Sobrien    (set (attr "mode")
133490286Sobrien      (cond [(eq_attr "type" "imovx")
133590286Sobrien	       (const_string "SI")
1336117404Skan	     (and (eq_attr "alternative" "1,2")
133790286Sobrien		  (match_operand:HI 1 "aligned_operand" ""))
133890286Sobrien	       (const_string "SI")
1339117404Skan	     (and (eq_attr "alternative" "0")
134090286Sobrien		  (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
134190286Sobrien			   (const_int 0))
134290286Sobrien		       (eq (symbol_ref "TARGET_HIMODE_MATH")
134390286Sobrien			   (const_int 0))))
134490286Sobrien	       (const_string "SI")
134590286Sobrien	    ]
1346117404Skan	    (const_string "HI")))])
134718334Speter
1348132727Skan;; Stores and loads of ax to arbitrary constant address.
134990286Sobrien;; We fake an second form of instruction to force reload to load address
135090286Sobrien;; into register when rax is not available
135190286Sobrien(define_insn "*movabshi_1_rex64"
1352117404Skan  [(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1353117404Skan	(match_operand:HI 1 "nonmemory_operand" "a,er"))]
1354117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
135590286Sobrien  "@
135690286Sobrien   movabs{w}\t{%1, %P0|%P0, %1}
1357117404Skan   mov{w}\t{%1, %a0|%a0, %1}"
135890286Sobrien  [(set_attr "type" "imov")
1359117404Skan   (set_attr "modrm" "0,*")
1360117404Skan   (set_attr "length_address" "8,0")
1361117404Skan   (set_attr "length_immediate" "0,*")
136290286Sobrien   (set_attr "memory" "store")
136390286Sobrien   (set_attr "mode" "HI")])
136418334Speter
136590286Sobrien(define_insn "*movabshi_2_rex64"
136690286Sobrien  [(set (match_operand:HI 0 "register_operand" "=a,r")
136790286Sobrien        (mem:HI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1368117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
136990286Sobrien  "@
137090286Sobrien   movabs{w}\t{%P1, %0|%0, %P1}
137190286Sobrien   mov{w}\t{%a1, %0|%0, %a1}"
137290286Sobrien  [(set_attr "type" "imov")
137390286Sobrien   (set_attr "modrm" "0,*")
137490286Sobrien   (set_attr "length_address" "8,0")
137590286Sobrien   (set_attr "length_immediate" "0")
137690286Sobrien   (set_attr "memory" "load")
137790286Sobrien   (set_attr "mode" "HI")])
137818334Speter
137990286Sobrien(define_insn "*swaphi_1"
138090286Sobrien  [(set (match_operand:HI 0 "register_operand" "+r")
138190286Sobrien	(match_operand:HI 1 "register_operand" "+r"))
138290286Sobrien   (set (match_dup 1)
138390286Sobrien	(match_dup 0))]
1384146906Skan  "!TARGET_PARTIAL_REG_STALL || optimize_size"
1385146906Skan  "xchg{l}\t%k1, %k0"
138690286Sobrien  [(set_attr "type" "imov")
1387146906Skan   (set_attr "mode" "SI")
138890286Sobrien   (set_attr "pent_pair" "np")
1389169699Skan   (set_attr "athlon_decode" "vector")])
139018334Speter
139190286Sobrien(define_insn "*swaphi_2"
139290286Sobrien  [(set (match_operand:HI 0 "register_operand" "+r")
139390286Sobrien	(match_operand:HI 1 "register_operand" "+r"))
139490286Sobrien   (set (match_dup 1)
139590286Sobrien	(match_dup 0))]
1396146906Skan  "TARGET_PARTIAL_REG_STALL"
1397146906Skan  "xchg{w}\t%1, %0"
139890286Sobrien  [(set_attr "type" "imov")
1399146906Skan   (set_attr "mode" "HI")
140090286Sobrien   (set_attr "pent_pair" "np")
1401169699Skan   (set_attr "athlon_decode" "vector")])
140218334Speter
140318334Speter(define_expand "movstricthi"
140490286Sobrien  [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
140518334Speter	(match_operand:HI 1 "general_operand" ""))]
140690286Sobrien  "! TARGET_PARTIAL_REG_STALL || optimize_size"
140718334Speter{
140818334Speter  /* Don't generate memory->memory moves, go through a register */
140990286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
141090286Sobrien    operands[1] = force_reg (HImode, operands[1]);
141190286Sobrien})
141218334Speter
141390286Sobrien(define_insn "*movstricthi_1"
141490286Sobrien  [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+rm,r"))
141590286Sobrien	(match_operand:HI 1 "general_operand" "rn,m"))]
141690286Sobrien  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
141790286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
141890286Sobrien  "mov{w}\t{%1, %0|%0, %1}"
141990286Sobrien  [(set_attr "type" "imov")
142090286Sobrien   (set_attr "mode" "HI")])
142152296Sobrien
142290286Sobrien(define_insn "*movstricthi_xor"
142390286Sobrien  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
142490286Sobrien	(match_operand:HI 1 "const0_operand" "i"))
1425169699Skan   (clobber (reg:CC FLAGS_REG))]
142690286Sobrien  "reload_completed
142790286Sobrien   && ((!TARGET_USE_MOV0 && !TARGET_PARTIAL_REG_STALL) || optimize_size)"
142890286Sobrien  "xor{w}\t{%0, %0|%0, %0}"
142990286Sobrien  [(set_attr "type" "alu1")
143090286Sobrien   (set_attr "mode" "HI")
143190286Sobrien   (set_attr "length_immediate" "0")])
143252296Sobrien
143390286Sobrien(define_expand "movqi"
143490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
143590286Sobrien	(match_operand:QI 1 "general_operand" ""))]
143690286Sobrien  ""
143790286Sobrien  "ix86_expand_move (QImode, operands); DONE;")
143818334Speter
143990286Sobrien;; emit_push_insn when it calls move_by_pieces requires an insn to
1440169699Skan;; "push a byte".  But actually we use pushl, which has the effect
1441169699Skan;; of rounding the amount pushed up to a word.
144218334Speter
144390286Sobrien(define_insn "*pushqi2"
1444169699Skan  [(set (match_operand:QI 0 "push_operand" "=X")
1445169699Skan	(match_operand:QI 1 "nonmemory_no_elim_operand" "rn"))]
144690286Sobrien  "!TARGET_64BIT"
1447169699Skan  "push{l}\t%k1"
144890286Sobrien  [(set_attr "type" "push")
1449169699Skan   (set_attr "mode" "SI")])
145018334Speter
145190286Sobrien;; For 64BIT abi we always round up to 8 bytes.
145290286Sobrien(define_insn "*pushqi2_rex64"
145390286Sobrien  [(set (match_operand:QI 0 "push_operand" "=X")
1454102802Skan	(match_operand:QI 1 "nonmemory_no_elim_operand" "qi"))]
145590286Sobrien  "TARGET_64BIT"
145690286Sobrien  "push{q}\t%q1"
145790286Sobrien  [(set_attr "type" "push")
1458169699Skan   (set_attr "mode" "DI")])
145990286Sobrien
146090286Sobrien;; Situation is quite tricky about when to choose full sized (SImode) move
146190286Sobrien;; over QImode moves.  For Q_REG -> Q_REG move we use full size only for
146290286Sobrien;; partial register dependency machines (such as AMD Athlon), where QImode
146390286Sobrien;; moves issue extra dependency and for partial register stalls machines
146490286Sobrien;; that don't use QImode patterns (and QImode move cause stall on the next
146590286Sobrien;; instruction).
146690286Sobrien;;
146790286Sobrien;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial
146890286Sobrien;; register stall machines with, where we use QImode instructions, since
146990286Sobrien;; partial register stall can be caused there.  Then we use movzx.
147090286Sobrien(define_insn "*movqi_1"
147190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m")
147290286Sobrien	(match_operand:QI 1 "general_operand"      " q,qn,qm,q,rn,qm,qn"))]
147390286Sobrien  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
147490286Sobrien{
147590286Sobrien  switch (get_attr_type (insn))
147690286Sobrien    {
147790286Sobrien    case TYPE_IMOVX:
1478169699Skan      gcc_assert (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM);
147990286Sobrien      return "movz{bl|x}\t{%1, %k0|%k0, %1}";
148090286Sobrien    default:
148190286Sobrien      if (get_attr_mode (insn) == MODE_SI)
148290286Sobrien        return "mov{l}\t{%k1, %k0|%k0, %k1}";
148390286Sobrien      else
148490286Sobrien        return "mov{b}\t{%1, %0|%0, %1}";
148590286Sobrien    }
148690286Sobrien}
148790286Sobrien  [(set (attr "type")
1488169699Skan     (cond [(and (eq_attr "alternative" "5")
1489169699Skan		 (not (match_operand:QI 1 "aligned_operand" "")))
1490169699Skan	      (const_string "imovx")
1491169699Skan	    (ne (symbol_ref "optimize_size") (const_int 0))
1492169699Skan	      (const_string "imov")
1493169699Skan	    (and (eq_attr "alternative" "3")
149490286Sobrien		 (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
149590286Sobrien			  (const_int 0))
149690286Sobrien		      (eq (symbol_ref "TARGET_QIMODE_MATH")
149790286Sobrien			  (const_int 0))))
149890286Sobrien	      (const_string "imov")
149990286Sobrien	    (eq_attr "alternative" "3,5")
150090286Sobrien	      (const_string "imovx")
150190286Sobrien	    (and (ne (symbol_ref "TARGET_MOVX")
150290286Sobrien		     (const_int 0))
150390286Sobrien		 (eq_attr "alternative" "2"))
150490286Sobrien	      (const_string "imovx")
150590286Sobrien	   ]
150690286Sobrien	   (const_string "imov")))
150790286Sobrien   (set (attr "mode")
150890286Sobrien      (cond [(eq_attr "alternative" "3,4,5")
150990286Sobrien	       (const_string "SI")
151090286Sobrien	     (eq_attr "alternative" "6")
151190286Sobrien	       (const_string "QI")
151290286Sobrien	     (eq_attr "type" "imovx")
151390286Sobrien	       (const_string "SI")
151490286Sobrien	     (and (eq_attr "type" "imov")
1515169699Skan		  (and (eq_attr "alternative" "0,1")
1516169699Skan		       (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
1517169699Skan				(const_int 0))
1518169699Skan			    (and (eq (symbol_ref "optimize_size")
1519169699Skan				     (const_int 0))
1520169699Skan			    	 (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
1521169699Skan				     (const_int 0))))))
152290286Sobrien	       (const_string "SI")
152390286Sobrien	     ;; Avoid partial register stalls when not using QImode arithmetic
152490286Sobrien	     (and (eq_attr "type" "imov")
1525169699Skan		  (and (eq_attr "alternative" "0,1")
152690286Sobrien		       (and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL")
152790286Sobrien				(const_int 0))
152890286Sobrien			    (eq (symbol_ref "TARGET_QIMODE_MATH")
152990286Sobrien				(const_int 0)))))
153090286Sobrien	       (const_string "SI")
153190286Sobrien	   ]
153290286Sobrien	   (const_string "QI")))])
153390286Sobrien
153490286Sobrien(define_expand "reload_outqi"
153590286Sobrien  [(parallel [(match_operand:QI 0 "" "=m")
153690286Sobrien              (match_operand:QI 1 "register_operand" "r")
153790286Sobrien              (match_operand:QI 2 "register_operand" "=&q")])]
153818334Speter  ""
153990286Sobrien{
154090286Sobrien  rtx op0, op1, op2;
154190286Sobrien  op0 = operands[0]; op1 = operands[1]; op2 = operands[2];
154218334Speter
1543169699Skan  gcc_assert (!reg_overlap_mentioned_p (op2, op0));
154490286Sobrien  if (! q_regs_operand (op1, QImode))
154590286Sobrien    {
154690286Sobrien      emit_insn (gen_movqi (op2, op1));
154790286Sobrien      op1 = op2;
154890286Sobrien    }
154990286Sobrien  emit_insn (gen_movqi (op0, op1));
155090286Sobrien  DONE;
155190286Sobrien})
155290286Sobrien
1553146906Skan(define_insn "*swapqi_1"
155490286Sobrien  [(set (match_operand:QI 0 "register_operand" "+r")
155590286Sobrien	(match_operand:QI 1 "register_operand" "+r"))
155690286Sobrien   (set (match_dup 1)
155790286Sobrien	(match_dup 0))]
1558146906Skan  "!TARGET_PARTIAL_REG_STALL || optimize_size"
1559146906Skan  "xchg{l}\t%k1, %k0"
1560146906Skan  [(set_attr "type" "imov")
1561146906Skan   (set_attr "mode" "SI")
1562146906Skan   (set_attr "pent_pair" "np")
1563169699Skan   (set_attr "athlon_decode" "vector")])
1564146906Skan
1565146906Skan(define_insn "*swapqi_2"
1566146906Skan  [(set (match_operand:QI 0 "register_operand" "+q")
1567146906Skan	(match_operand:QI 1 "register_operand" "+q"))
1568146906Skan   (set (match_dup 1)
1569146906Skan	(match_dup 0))]
1570146906Skan  "TARGET_PARTIAL_REG_STALL"
157190286Sobrien  "xchg{b}\t%1, %0"
157290286Sobrien  [(set_attr "type" "imov")
1573146906Skan   (set_attr "mode" "QI")
157490286Sobrien   (set_attr "pent_pair" "np")
1575169699Skan   (set_attr "athlon_decode" "vector")])
157690286Sobrien
157790286Sobrien(define_expand "movstrictqi"
157890286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
157990286Sobrien	(match_operand:QI 1 "general_operand" ""))]
1580117404Skan  "! TARGET_PARTIAL_REG_STALL || optimize_size"
158118334Speter{
158290286Sobrien  /* Don't generate memory->memory moves, go through a register.  */
158390286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
158490286Sobrien    operands[1] = force_reg (QImode, operands[1]);
158590286Sobrien})
158618334Speter
158790286Sobrien(define_insn "*movstrictqi_1"
158890286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
158990286Sobrien	(match_operand:QI 1 "general_operand" "*qn,m"))]
1590117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
159190286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
159290286Sobrien  "mov{b}\t{%1, %0|%0, %1}"
159390286Sobrien  [(set_attr "type" "imov")
159490286Sobrien   (set_attr "mode" "QI")])
159518334Speter
159690286Sobrien(define_insn "*movstrictqi_xor"
159790286Sobrien  [(set (strict_low_part (match_operand:QI 0 "q_regs_operand" "+q"))
159890286Sobrien	(match_operand:QI 1 "const0_operand" "i"))
1599169699Skan   (clobber (reg:CC FLAGS_REG))]
160090286Sobrien  "reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
160190286Sobrien  "xor{b}\t{%0, %0|%0, %0}"
160290286Sobrien  [(set_attr "type" "alu1")
160390286Sobrien   (set_attr "mode" "QI")
160490286Sobrien   (set_attr "length_immediate" "0")])
160518334Speter
160690286Sobrien(define_insn "*movsi_extv_1"
160790286Sobrien  [(set (match_operand:SI 0 "register_operand" "=R")
160890286Sobrien	(sign_extract:SI (match_operand 1 "ext_register_operand" "Q")
160990286Sobrien			 (const_int 8)
161090286Sobrien			 (const_int 8)))]
161118334Speter  ""
161290286Sobrien  "movs{bl|x}\t{%h1, %0|%0, %h1}"
161390286Sobrien  [(set_attr "type" "imovx")
161490286Sobrien   (set_attr "mode" "SI")])
161590286Sobrien
161690286Sobrien(define_insn "*movhi_extv_1"
161790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=R")
161890286Sobrien	(sign_extract:HI (match_operand 1 "ext_register_operand" "Q")
161990286Sobrien			 (const_int 8)
162090286Sobrien			 (const_int 8)))]
162190286Sobrien  ""
162290286Sobrien  "movs{bl|x}\t{%h1, %k0|%k0, %h1}"
162390286Sobrien  [(set_attr "type" "imovx")
162490286Sobrien   (set_attr "mode" "SI")])
162590286Sobrien
162690286Sobrien(define_insn "*movqi_extv_1"
162790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?r")
162890286Sobrien        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
162990286Sobrien                         (const_int 8)
163090286Sobrien                         (const_int 8)))]
163190286Sobrien  "!TARGET_64BIT"
163218334Speter{
163390286Sobrien  switch (get_attr_type (insn))
163418334Speter    {
163590286Sobrien    case TYPE_IMOVX:
163690286Sobrien      return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
163790286Sobrien    default:
163890286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
163918334Speter    }
164090286Sobrien}
164190286Sobrien  [(set (attr "type")
164290286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
164390286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
164490286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
164590286Sobrien				 (const_int 0))))
164690286Sobrien	(const_string "imovx")
164790286Sobrien	(const_string "imov")))
164890286Sobrien   (set (attr "mode")
164990286Sobrien     (if_then_else (eq_attr "type" "imovx")
165090286Sobrien	(const_string "SI")
165190286Sobrien	(const_string "QI")))])
165218334Speter
165390286Sobrien(define_insn "*movqi_extv_1_rex64"
165490286Sobrien  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
165590286Sobrien        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
165690286Sobrien                         (const_int 8)
165790286Sobrien                         (const_int 8)))]
165890286Sobrien  "TARGET_64BIT"
165918334Speter{
166090286Sobrien  switch (get_attr_type (insn))
166150650Sobrien    {
166290286Sobrien    case TYPE_IMOVX:
166390286Sobrien      return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
166490286Sobrien    default:
166590286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
166650650Sobrien    }
166790286Sobrien}
166890286Sobrien  [(set (attr "type")
166990286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
167090286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
167190286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
167290286Sobrien				 (const_int 0))))
167390286Sobrien	(const_string "imovx")
167490286Sobrien	(const_string "imov")))
167590286Sobrien   (set (attr "mode")
167690286Sobrien     (if_then_else (eq_attr "type" "imovx")
167790286Sobrien	(const_string "SI")
167890286Sobrien	(const_string "QI")))])
167918334Speter
1680132727Skan;; Stores and loads of ax to arbitrary constant address.
168190286Sobrien;; We fake an second form of instruction to force reload to load address
168290286Sobrien;; into register when rax is not available
168390286Sobrien(define_insn "*movabsqi_1_rex64"
1684117404Skan  [(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
1685117404Skan	(match_operand:QI 1 "nonmemory_operand" "a,er"))]
1686117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
168790286Sobrien  "@
168890286Sobrien   movabs{b}\t{%1, %P0|%P0, %1}
1689117404Skan   mov{b}\t{%1, %a0|%a0, %1}"
169090286Sobrien  [(set_attr "type" "imov")
1691117404Skan   (set_attr "modrm" "0,*")
1692117404Skan   (set_attr "length_address" "8,0")
1693117404Skan   (set_attr "length_immediate" "0,*")
169490286Sobrien   (set_attr "memory" "store")
169590286Sobrien   (set_attr "mode" "QI")])
169618334Speter
169790286Sobrien(define_insn "*movabsqi_2_rex64"
169890286Sobrien  [(set (match_operand:QI 0 "register_operand" "=a,r")
169990286Sobrien        (mem:QI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
1700117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
170190286Sobrien  "@
170290286Sobrien   movabs{b}\t{%P1, %0|%0, %P1}
170390286Sobrien   mov{b}\t{%a1, %0|%0, %a1}"
170490286Sobrien  [(set_attr "type" "imov")
170590286Sobrien   (set_attr "modrm" "0,*")
170690286Sobrien   (set_attr "length_address" "8,0")
170790286Sobrien   (set_attr "length_immediate" "0")
170890286Sobrien   (set_attr "memory" "load")
170990286Sobrien   (set_attr "mode" "QI")])
171018334Speter
1711169699Skan(define_insn "*movdi_extzv_1"
1712169699Skan  [(set (match_operand:DI 0 "register_operand" "=R")
1713169699Skan	(zero_extract:DI (match_operand 1 "ext_register_operand" "Q")
1714169699Skan			 (const_int 8)
1715169699Skan			 (const_int 8)))]
1716169699Skan  "TARGET_64BIT"
1717169699Skan  "movz{bl|x}\t{%h1, %k0|%k0, %h1}"
1718169699Skan  [(set_attr "type" "imovx")
1719169699Skan   (set_attr "mode" "DI")])
1720169699Skan
172190286Sobrien(define_insn "*movsi_extzv_1"
172290286Sobrien  [(set (match_operand:SI 0 "register_operand" "=R")
172390286Sobrien	(zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
172490286Sobrien			 (const_int 8)
172590286Sobrien			 (const_int 8)))]
172690286Sobrien  ""
172790286Sobrien  "movz{bl|x}\t{%h1, %0|%0, %h1}"
172890286Sobrien  [(set_attr "type" "imovx")
172990286Sobrien   (set_attr "mode" "SI")])
173018334Speter
173190286Sobrien(define_insn "*movqi_extzv_2"
173290286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?R")
173390286Sobrien        (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
173490286Sobrien				    (const_int 8)
173590286Sobrien				    (const_int 8)) 0))]
173690286Sobrien  "!TARGET_64BIT"
173718334Speter{
173890286Sobrien  switch (get_attr_type (insn))
173918334Speter    {
174090286Sobrien    case TYPE_IMOVX:
174190286Sobrien      return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
174290286Sobrien    default:
174390286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
174418334Speter    }
174590286Sobrien}
174690286Sobrien  [(set (attr "type")
174790286Sobrien     (if_then_else (and (match_operand:QI 0 "register_operand" "")
174890286Sobrien			(ior (not (match_operand:QI 0 "q_regs_operand" ""))
174990286Sobrien			     (ne (symbol_ref "TARGET_MOVX")
175090286Sobrien				 (const_int 0))))
175190286Sobrien	(const_string "imovx")
175290286Sobrien	(const_string "imov")))
175390286Sobrien   (set (attr "mode")
175490286Sobrien     (if_then_else (eq_attr "type" "imovx")
175590286Sobrien	(const_string "SI")
175690286Sobrien	(const_string "QI")))])
175718334Speter
175890286Sobrien(define_insn "*movqi_extzv_2_rex64"
175990286Sobrien  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
176090286Sobrien        (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
176190286Sobrien				    (const_int 8)
176290286Sobrien				    (const_int 8)) 0))]
176390286Sobrien  "TARGET_64BIT"
176418334Speter{
176590286Sobrien  switch (get_attr_type (insn))
176690286Sobrien    {
176790286Sobrien    case TYPE_IMOVX:
176890286Sobrien      return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
176990286Sobrien    default:
177090286Sobrien      return "mov{b}\t{%h1, %0|%0, %h1}";
177190286Sobrien    }
177290286Sobrien}
177390286Sobrien  [(set (attr "type")
177490286Sobrien     (if_then_else (ior (not (match_operand:QI 0 "q_regs_operand" ""))
177590286Sobrien			(ne (symbol_ref "TARGET_MOVX")
177690286Sobrien			    (const_int 0)))
177790286Sobrien	(const_string "imovx")
177890286Sobrien	(const_string "imov")))
177990286Sobrien   (set (attr "mode")
178090286Sobrien     (if_then_else (eq_attr "type" "imovx")
178190286Sobrien	(const_string "SI")
178290286Sobrien	(const_string "QI")))])
178318334Speter
178490286Sobrien(define_insn "movsi_insv_1"
178590286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
178690286Sobrien			 (const_int 8)
178790286Sobrien			 (const_int 8))
178890286Sobrien	(match_operand:SI 1 "general_operand" "Qmn"))]
178990286Sobrien  "!TARGET_64BIT"
179090286Sobrien  "mov{b}\t{%b1, %h0|%h0, %b1}"
179190286Sobrien  [(set_attr "type" "imov")
179290286Sobrien   (set_attr "mode" "QI")])
179352296Sobrien
1794132727Skan(define_insn "movdi_insv_1_rex64"
1795132727Skan  [(set (zero_extract:DI (match_operand 0 "ext_register_operand" "+Q")
179690286Sobrien			 (const_int 8)
179790286Sobrien			 (const_int 8))
1798132727Skan	(match_operand:DI 1 "nonmemory_operand" "Qn"))]
179990286Sobrien  "TARGET_64BIT"
180090286Sobrien  "mov{b}\t{%b1, %h0|%h0, %b1}"
180190286Sobrien  [(set_attr "type" "imov")
180290286Sobrien   (set_attr "mode" "QI")])
180318334Speter
180490286Sobrien(define_insn "*movqi_insv_2"
180590286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
180690286Sobrien			 (const_int 8)
180790286Sobrien			 (const_int 8))
1808132727Skan	(lshiftrt:SI (match_operand:SI 1 "register_operand" "Q")
1809132727Skan		     (const_int 8)))]
181090286Sobrien  ""
181190286Sobrien  "mov{b}\t{%h1, %h0|%h0, %h1}"
181290286Sobrien  [(set_attr "type" "imov")
181390286Sobrien   (set_attr "mode" "QI")])
181418334Speter
181590286Sobrien(define_expand "movdi"
181690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
181790286Sobrien	(match_operand:DI 1 "general_operand" ""))]
181890286Sobrien  ""
181990286Sobrien  "ix86_expand_move (DImode, operands); DONE;")
182018334Speter
182190286Sobrien(define_insn "*pushdi"
182290286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
182390286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "riF*m"))]
182490286Sobrien  "!TARGET_64BIT"
182590286Sobrien  "#")
182690286Sobrien
1827169699Skan(define_insn "*pushdi2_rex64"
182890286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<,!<")
182990286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "re*m,n"))]
183090286Sobrien  "TARGET_64BIT"
183190286Sobrien  "@
183290286Sobrien   push{q}\t%1
183390286Sobrien   #"
183490286Sobrien  [(set_attr "type" "push,multi")
183590286Sobrien   (set_attr "mode" "DI")])
183690286Sobrien
183790286Sobrien;; Convert impossible pushes of immediate to existing instructions.
183890286Sobrien;; First try to get scratch register and go through it.  In case this
183990286Sobrien;; fails, push sign extended lower part first and then overwrite
184090286Sobrien;; upper part by 32bit move.
184190286Sobrien(define_peephole2
184290286Sobrien  [(match_scratch:DI 2 "r")
184390286Sobrien   (set (match_operand:DI 0 "push_operand" "")
184490286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
184590286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
184690286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
184790286Sobrien  [(set (match_dup 2) (match_dup 1))
184890286Sobrien   (set (match_dup 0) (match_dup 2))]
184990286Sobrien  "")
185090286Sobrien
185190286Sobrien;; We need to define this as both peepholer and splitter for case
185290286Sobrien;; peephole2 pass is not run.
1853169699Skan;; "&& 1" is needed to keep it from matching the previous pattern.
185490286Sobrien(define_peephole2
185590286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
185690286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
185790286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
185890286Sobrien   && !x86_64_immediate_operand (operands[1], DImode) && 1"
185990286Sobrien  [(set (match_dup 0) (match_dup 1))
186090286Sobrien   (set (match_dup 2) (match_dup 3))]
186190286Sobrien  "split_di (operands + 1, 1, operands + 2, operands + 3);
186290286Sobrien   operands[1] = gen_lowpart (DImode, operands[2]);
186390286Sobrien   operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
186490286Sobrien						    GEN_INT (4)));
186590286Sobrien  ")
186690286Sobrien
186790286Sobrien(define_split
186890286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
186990286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
1870161660Skan  "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
1871169699Skan		    ? flow2_completed : reload_completed)
187290286Sobrien   && !symbolic_operand (operands[1], DImode)
187390286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
187490286Sobrien  [(set (match_dup 0) (match_dup 1))
187590286Sobrien   (set (match_dup 2) (match_dup 3))]
187690286Sobrien  "split_di (operands + 1, 1, operands + 2, operands + 3);
187790286Sobrien   operands[1] = gen_lowpart (DImode, operands[2]);
187890286Sobrien   operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
187990286Sobrien						    GEN_INT (4)));
188090286Sobrien  ")
188190286Sobrien
188290286Sobrien(define_insn "*pushdi2_prologue_rex64"
188390286Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
188490286Sobrien	(match_operand:DI 1 "general_no_elim_operand" "re*m"))
188590286Sobrien   (clobber (mem:BLK (scratch)))]
188690286Sobrien  "TARGET_64BIT"
188790286Sobrien  "push{q}\t%1"
188890286Sobrien  [(set_attr "type" "push")
188990286Sobrien   (set_attr "mode" "DI")])
189090286Sobrien
189190286Sobrien(define_insn "*popdi1_epilogue_rex64"
189290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
1893169699Skan	(mem:DI (reg:DI SP_REG)))
1894169699Skan   (set (reg:DI SP_REG)
1895169699Skan	(plus:DI (reg:DI SP_REG) (const_int 8)))
189690286Sobrien   (clobber (mem:BLK (scratch)))]
189790286Sobrien  "TARGET_64BIT"
189890286Sobrien  "pop{q}\t%0"
189990286Sobrien  [(set_attr "type" "pop")
190090286Sobrien   (set_attr "mode" "DI")])
190190286Sobrien
190290286Sobrien(define_insn "popdi1"
190390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
1904169699Skan	(mem:DI (reg:DI SP_REG)))
1905169699Skan   (set (reg:DI SP_REG)
1906169699Skan	(plus:DI (reg:DI SP_REG) (const_int 8)))]
190790286Sobrien  "TARGET_64BIT"
190890286Sobrien  "pop{q}\t%0"
190990286Sobrien  [(set_attr "type" "pop")
191090286Sobrien   (set_attr "mode" "DI")])
191190286Sobrien
191290286Sobrien(define_insn "*movdi_xor_rex64"
191390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
191490286Sobrien	(match_operand:DI 1 "const0_operand" "i"))
1915169699Skan   (clobber (reg:CC FLAGS_REG))]
191690286Sobrien  "TARGET_64BIT && (!TARGET_USE_MOV0 || optimize_size)
191790286Sobrien   && reload_completed"
191890286Sobrien  "xor{l}\t{%k0, %k0|%k0, %k0}"
191990286Sobrien  [(set_attr "type" "alu1")
192090286Sobrien   (set_attr "mode" "SI")
192190286Sobrien   (set_attr "length_immediate" "0")])
192290286Sobrien
192390286Sobrien(define_insn "*movdi_or_rex64"
192490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
192590286Sobrien	(match_operand:DI 1 "const_int_operand" "i"))
1926169699Skan   (clobber (reg:CC FLAGS_REG))]
192790286Sobrien  "TARGET_64BIT && (TARGET_PENTIUM || optimize_size)
192890286Sobrien   && reload_completed
1929132727Skan   && operands[1] == constm1_rtx"
193018334Speter{
193190286Sobrien  operands[1] = constm1_rtx;
193290286Sobrien  return "or{q}\t{%1, %0|%0, %1}";
193390286Sobrien}
193490286Sobrien  [(set_attr "type" "alu1")
193590286Sobrien   (set_attr "mode" "DI")
193690286Sobrien   (set_attr "length_immediate" "1")])
193718334Speter
193890286Sobrien(define_insn "*movdi_2"
1939169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand"
1940169699Skan				"=r  ,o  ,*y,m*y,*y,*Y,m ,*Y,*Y,*x,m ,*x,*x")
1941169699Skan	(match_operand:DI 1 "general_operand"
1942169699Skan				"riFo,riF,C ,*y ,m ,C ,*Y,*Y,m ,C ,*x,*x,m "))]
1943169699Skan  "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
194490286Sobrien  "@
194590286Sobrien   #
194690286Sobrien   #
1947169699Skan   pxor\t%0, %0
194890286Sobrien   movq\t{%1, %0|%0, %1}
194990286Sobrien   movq\t{%1, %0|%0, %1}
1950169699Skan   pxor\t%0, %0
195190286Sobrien   movq\t{%1, %0|%0, %1}
195290286Sobrien   movdqa\t{%1, %0|%0, %1}
1953169699Skan   movq\t{%1, %0|%0, %1}
1954169699Skan   xorps\t%0, %0
1955169699Skan   movlps\t{%1, %0|%0, %1}
1956169699Skan   movaps\t{%1, %0|%0, %1}
1957169699Skan   movlps\t{%1, %0|%0, %1}"
1958169699Skan  [(set_attr "type" "*,*,mmx,mmxmov,mmxmov,sselog1,ssemov,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov")
1959169699Skan   (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,TI,DI,V4SF,V2SF,V4SF,V2SF")])
196018334Speter
196190286Sobrien(define_split
196290286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
196390286Sobrien        (match_operand:DI 1 "general_operand" ""))]
196490286Sobrien  "!TARGET_64BIT && reload_completed
196590286Sobrien   && (! MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
196690286Sobrien  [(const_int 0)]
196790286Sobrien  "ix86_split_long_move (operands); DONE;")
196818334Speter
196990286Sobrien;; %%% This multiword shite has got to go.
197090286Sobrien(define_split
197190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
197290286Sobrien        (match_operand:DI 1 "general_operand" ""))]
197390286Sobrien  "!TARGET_64BIT && reload_completed
197490286Sobrien   && (!MMX_REG_P (operands[0]) && !SSE_REG_P (operands[0]))
197590286Sobrien   && (!MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
197690286Sobrien  [(const_int 0)]
197790286Sobrien  "ix86_split_long_move (operands); DONE;")
197818334Speter
197990286Sobrien(define_insn "*movdi_1_rex64"
1980169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand"
1981169699Skan		"=r,r  ,r,m ,!m,*y,*y,?rm,?*y,*x,*x,?rm,?*x,?*x,?*y")
1982169699Skan	(match_operand:DI 1 "general_operand"
1983169699Skan		"Z ,rem,i,re,n ,C ,*y,*y ,rm ,C ,*x,*x ,rm ,*y ,*x"))]
1984169699Skan  "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
198590286Sobrien{
198690286Sobrien  switch (get_attr_type (insn))
198790286Sobrien    {
1988169699Skan    case TYPE_SSECVT:
1989169699Skan      if (which_alternative == 13)
1990169699Skan	return "movq2dq\t{%1, %0|%0, %1}";
1991169699Skan      else
1992169699Skan	return "movdq2q\t{%1, %0|%0, %1}";
1993117404Skan    case TYPE_SSEMOV:
1994132727Skan      if (get_attr_mode (insn) == MODE_TI)
199590286Sobrien	  return "movdqa\t{%1, %0|%0, %1}";
199690286Sobrien      /* FALLTHRU */
1997117404Skan    case TYPE_MMXMOV:
1998132727Skan      /* Moves from and into integer register is done using movd opcode with
1999132727Skan 	 REX prefix.  */
2000132727Skan      if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
2001132727Skan	  return "movd\t{%1, %0|%0, %1}";
200290286Sobrien      return "movq\t{%1, %0|%0, %1}";
2003169699Skan    case TYPE_SSELOG1:
2004169699Skan    case TYPE_MMXADD:
2005169699Skan      return "pxor\t%0, %0";
200690286Sobrien    case TYPE_MULTI:
200790286Sobrien      return "#";
200890286Sobrien    case TYPE_LEA:
200990286Sobrien      return "lea{q}\t{%a1, %0|%0, %a1}";
201090286Sobrien    default:
2011169699Skan      gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
201290286Sobrien      if (get_attr_mode (insn) == MODE_SI)
201390286Sobrien	return "mov{l}\t{%k1, %k0|%k0, %k1}";
201490286Sobrien      else if (which_alternative == 2)
201590286Sobrien	return "movabs{q}\t{%1, %0|%0, %1}";
201618334Speter      else
201790286Sobrien	return "mov{q}\t{%1, %0|%0, %1}";
201818334Speter    }
201990286Sobrien}
202090286Sobrien  [(set (attr "type")
2021169699Skan     (cond [(eq_attr "alternative" "5")
2022169699Skan	      (const_string "mmxadd")
2023169699Skan	    (eq_attr "alternative" "6,7,8")
2024117404Skan	      (const_string "mmxmov")
2025169699Skan	    (eq_attr "alternative" "9")
2026169699Skan	      (const_string "sselog1")
2027169699Skan	    (eq_attr "alternative" "10,11,12")
2028117404Skan	      (const_string "ssemov")
2029169699Skan	    (eq_attr "alternative" "13,14")
2030169699Skan	      (const_string "ssecvt")
203190286Sobrien	    (eq_attr "alternative" "4")
203290286Sobrien	      (const_string "multi")
2033169699Skan 	    (match_operand:DI 1 "pic_32bit_operand" "")
203490286Sobrien	      (const_string "lea")
203590286Sobrien	   ]
203690286Sobrien	   (const_string "imov")))
2037169699Skan   (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*")
2038169699Skan   (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*")
2039169699Skan   (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI")])
204050650Sobrien
2041132727Skan;; Stores and loads of ax to arbitrary constant address.
204290286Sobrien;; We fake an second form of instruction to force reload to load address
204390286Sobrien;; into register when rax is not available
204490286Sobrien(define_insn "*movabsdi_1_rex64"
2045102802Skan  [(set (mem:DI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
2046102802Skan	(match_operand:DI 1 "nonmemory_operand" "a,er"))]
2047117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 0)"
204890286Sobrien  "@
204990286Sobrien   movabs{q}\t{%1, %P0|%P0, %1}
2050102802Skan   mov{q}\t{%1, %a0|%a0, %1}"
205190286Sobrien  [(set_attr "type" "imov")
2052102802Skan   (set_attr "modrm" "0,*")
2053102802Skan   (set_attr "length_address" "8,0")
2054102802Skan   (set_attr "length_immediate" "0,*")
205590286Sobrien   (set_attr "memory" "store")
205690286Sobrien   (set_attr "mode" "DI")])
205718334Speter
205890286Sobrien(define_insn "*movabsdi_2_rex64"
205990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a,r")
206090286Sobrien        (mem:DI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
2061117404Skan  "TARGET_64BIT && ix86_check_movabs (insn, 1)"
206290286Sobrien  "@
206390286Sobrien   movabs{q}\t{%P1, %0|%0, %P1}
206490286Sobrien   mov{q}\t{%a1, %0|%0, %a1}"
206590286Sobrien  [(set_attr "type" "imov")
206690286Sobrien   (set_attr "modrm" "0,*")
206790286Sobrien   (set_attr "length_address" "8,0")
206890286Sobrien   (set_attr "length_immediate" "0")
206990286Sobrien   (set_attr "memory" "load")
207090286Sobrien   (set_attr "mode" "DI")])
207190286Sobrien
207290286Sobrien;; Convert impossible stores of immediate to existing instructions.
207390286Sobrien;; First try to get scratch register and go through it.  In case this
207490286Sobrien;; fails, move by 32bit parts.
207590286Sobrien(define_peephole2
207690286Sobrien  [(match_scratch:DI 2 "r")
207790286Sobrien   (set (match_operand:DI 0 "memory_operand" "")
207890286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
207990286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
208090286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
208190286Sobrien  [(set (match_dup 2) (match_dup 1))
208290286Sobrien   (set (match_dup 0) (match_dup 2))]
208352296Sobrien  "")
208450650Sobrien
208590286Sobrien;; We need to define this as both peepholer and splitter for case
208690286Sobrien;; peephole2 pass is not run.
2087169699Skan;; "&& 1" is needed to keep it from matching the previous pattern.
208890286Sobrien(define_peephole2
208990286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
209090286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
209190286Sobrien  "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
209290286Sobrien   && !x86_64_immediate_operand (operands[1], DImode) && 1"
209390286Sobrien  [(set (match_dup 2) (match_dup 3))
209490286Sobrien   (set (match_dup 4) (match_dup 5))]
209590286Sobrien  "split_di (operands, 2, operands + 2, operands + 4);")
209690286Sobrien
209790286Sobrien(define_split
209890286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
209990286Sobrien        (match_operand:DI 1 "immediate_operand" ""))]
2100161660Skan  "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
2101169699Skan		    ? flow2_completed : reload_completed)
210290286Sobrien   && !symbolic_operand (operands[1], DImode)
210390286Sobrien   && !x86_64_immediate_operand (operands[1], DImode)"
210490286Sobrien  [(set (match_dup 2) (match_dup 3))
210590286Sobrien   (set (match_dup 4) (match_dup 5))]
210690286Sobrien  "split_di (operands, 2, operands + 2, operands + 4);")
210790286Sobrien
210890286Sobrien(define_insn "*swapdi_rex64"
210990286Sobrien  [(set (match_operand:DI 0 "register_operand" "+r")
211090286Sobrien	(match_operand:DI 1 "register_operand" "+r"))
211190286Sobrien   (set (match_dup 1)
211290286Sobrien	(match_dup 0))]
211390286Sobrien  "TARGET_64BIT"
211490286Sobrien  "xchg{q}\t%1, %0"
211590286Sobrien  [(set_attr "type" "imov")
2116146906Skan   (set_attr "mode" "DI")
211790286Sobrien   (set_attr "pent_pair" "np")
2118169699Skan   (set_attr "athlon_decode" "vector")])
211990286Sobrien
2120169699Skan(define_expand "movti"
2121169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
2122169699Skan	(match_operand:TI 1 "nonimmediate_operand" ""))]
2123169699Skan  "TARGET_SSE || TARGET_64BIT"
2124169699Skan{
2125169699Skan  if (TARGET_64BIT)
2126169699Skan    ix86_expand_move (TImode, operands);
2127169699Skan  else
2128169699Skan    ix86_expand_vector_move (TImode, operands);
2129169699Skan  DONE;
2130169699Skan})
2131169699Skan
2132169699Skan(define_insn "*movti_internal"
2133169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m")
2134169699Skan	(match_operand:TI 1 "vector_move_operand" "C,xm,x"))]
2135169699Skan  "TARGET_SSE && !TARGET_64BIT
2136169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2137169699Skan{
2138169699Skan  switch (which_alternative)
2139169699Skan    {
2140169699Skan    case 0:
2141169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2142169699Skan	return "xorps\t%0, %0";
2143169699Skan      else
2144169699Skan	return "pxor\t%0, %0";
2145169699Skan    case 1:
2146169699Skan    case 2:
2147169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2148169699Skan	return "movaps\t{%1, %0|%0, %1}";
2149169699Skan      else
2150169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2151169699Skan    default:
2152169699Skan      gcc_unreachable ();
2153169699Skan    }
2154169699Skan}
2155169699Skan  [(set_attr "type" "sselog1,ssemov,ssemov")
2156169699Skan   (set (attr "mode")
2157169699Skan	(cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2158169699Skan		    (ne (symbol_ref "optimize_size") (const_int 0)))
2159169699Skan		 (const_string "V4SF")
2160169699Skan	       (and (eq_attr "alternative" "2")
2161169699Skan		    (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2162169699Skan			(const_int 0)))
2163169699Skan		 (const_string "V4SF")]
2164169699Skan	      (const_string "TI")))])
2165169699Skan
2166169699Skan(define_insn "*movti_rex64"
2167169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,x,xm")
2168169699Skan	(match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))]
2169169699Skan  "TARGET_64BIT
2170169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2171169699Skan{
2172169699Skan  switch (which_alternative)
2173169699Skan    {
2174169699Skan    case 0:
2175169699Skan    case 1:
2176169699Skan      return "#";
2177169699Skan    case 2:
2178169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2179169699Skan	return "xorps\t%0, %0";
2180169699Skan      else
2181169699Skan	return "pxor\t%0, %0";
2182169699Skan    case 3:
2183169699Skan    case 4:
2184169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2185169699Skan	return "movaps\t{%1, %0|%0, %1}";
2186169699Skan      else
2187169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2188169699Skan    default:
2189169699Skan      gcc_unreachable ();
2190169699Skan    }
2191169699Skan}
2192169699Skan  [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
2193169699Skan   (set (attr "mode")
2194169699Skan        (cond [(eq_attr "alternative" "2,3")
2195169699Skan		 (if_then_else
2196169699Skan		   (ne (symbol_ref "optimize_size")
2197169699Skan		       (const_int 0))
2198169699Skan		   (const_string "V4SF")
2199169699Skan		   (const_string "TI"))
2200169699Skan	       (eq_attr "alternative" "4")
2201169699Skan		 (if_then_else
2202169699Skan		   (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2203169699Skan			    (const_int 0))
2204169699Skan			(ne (symbol_ref "optimize_size")
2205169699Skan			    (const_int 0)))
2206169699Skan		   (const_string "V4SF")
2207169699Skan		   (const_string "TI"))]
2208169699Skan	       (const_string "DI")))])
2209169699Skan
2210169699Skan(define_split
2211169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
2212169699Skan        (match_operand:TI 1 "general_operand" ""))]
2213169699Skan  "reload_completed && !SSE_REG_P (operands[0])
2214169699Skan   && !SSE_REG_P (operands[1])"
2215169699Skan  [(const_int 0)]
2216169699Skan  "ix86_split_long_move (operands); DONE;")
2217169699Skan
221850650Sobrien(define_expand "movsf"
221990286Sobrien  [(set (match_operand:SF 0 "nonimmediate_operand" "")
222050650Sobrien	(match_operand:SF 1 "general_operand" ""))]
222118334Speter  ""
222290286Sobrien  "ix86_expand_move (SFmode, operands); DONE;")
222390286Sobrien
222490286Sobrien(define_insn "*pushsf"
222590286Sobrien  [(set (match_operand:SF 0 "push_operand" "=<,<,<")
2226169699Skan	(match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
222790286Sobrien  "!TARGET_64BIT"
222818334Speter{
2229169699Skan  /* Anything else should be already split before reg-stack.  */
2230169699Skan  gcc_assert (which_alternative == 1);
2231169699Skan  return "push{l}\t%1";
223290286Sobrien}
223390286Sobrien  [(set_attr "type" "multi,push,multi")
2234169699Skan   (set_attr "unit" "i387,*,*")
223590286Sobrien   (set_attr "mode" "SF,SI,SF")])
223618334Speter
223790286Sobrien(define_insn "*pushsf_rex64"
223890286Sobrien  [(set (match_operand:SF 0 "push_operand" "=X,X,X")
2239169699Skan	(match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
224090286Sobrien  "TARGET_64BIT"
224118334Speter{
2242169699Skan  /* Anything else should be already split before reg-stack.  */
2243169699Skan  gcc_assert (which_alternative == 1);
2244169699Skan  return "push{q}\t%q1";
224590286Sobrien}
224690286Sobrien  [(set_attr "type" "multi,push,multi")
2247169699Skan   (set_attr "unit" "i387,*,*")
224890286Sobrien   (set_attr "mode" "SF,DI,SF")])
224918334Speter
225090286Sobrien(define_split
225190286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
225290286Sobrien	(match_operand:SF 1 "memory_operand" ""))]
225390286Sobrien  "reload_completed
225490286Sobrien   && GET_CODE (operands[1]) == MEM
2255161660Skan   && constant_pool_reference_p (operands[1])"
225690286Sobrien  [(set (match_dup 0)
225790286Sobrien	(match_dup 1))]
2258161660Skan  "operands[1] = avoid_constant_pool_reference (operands[1]);")
225918334Speter
226090286Sobrien
226190286Sobrien;; %%% Kill this when call knows how to work this out.
226290286Sobrien(define_split
226390286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
2264117404Skan	(match_operand:SF 1 "any_fp_register_operand" ""))]
2265117404Skan  "!TARGET_64BIT"
2266169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
2267169699Skan   (set (mem:SF (reg:SI SP_REG)) (match_dup 1))])
226890286Sobrien
226990286Sobrien(define_split
227090286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
2271117404Skan	(match_operand:SF 1 "any_fp_register_operand" ""))]
2272117404Skan  "TARGET_64BIT"
2273169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
2274169699Skan   (set (mem:SF (reg:DI SP_REG)) (match_dup 1))])
227590286Sobrien
227690286Sobrien(define_insn "*movsf_1"
2277169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"
2278169699Skan	  "=f,m   ,f,r  ,m    ,x,x,x ,m   ,!*y,!rm,!*y")
2279169699Skan	(match_operand:SF 1 "general_operand"
2280169699Skan	  "fm,f,G   ,rmF,Fr,C   ,x   ,xm,x,rm ,*y ,*y"))]
2281169699Skan  "!(MEM_P (operands[0]) && MEM_P (operands[1]))
228290286Sobrien   && (reload_in_progress || reload_completed
228390286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
228490286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
228590286Sobrien       || memory_operand (operands[0], SFmode))" 
228690286Sobrien{
228790286Sobrien  switch (which_alternative)
228818334Speter    {
228990286Sobrien    case 0:
2290169699Skan      return output_387_reg_move (insn, operands);
229118334Speter
229290286Sobrien    case 1:
229390286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
229490286Sobrien        return "fstp%z0\t%y0";
229590286Sobrien      else
229690286Sobrien        return "fst%z0\t%y0";
229718334Speter
229890286Sobrien    case 2:
2299132727Skan      return standard_80387_constant_opcode (operands[1]);
2300132727Skan
2301132727Skan    case 3:
2302132727Skan    case 4:
2303132727Skan      return "mov{l}\t{%1, %0|%0, %1}";
2304132727Skan    case 5:
2305132727Skan      if (get_attr_mode (insn) == MODE_TI)
2306132727Skan	return "pxor\t%0, %0";
2307132727Skan      else
2308132727Skan	return "xorps\t%0, %0";
2309132727Skan    case 6:
2310132727Skan      if (get_attr_mode (insn) == MODE_V4SF)
2311132727Skan	return "movaps\t{%1, %0|%0, %1}";
2312132727Skan      else
2313132727Skan	return "movss\t{%1, %0|%0, %1}";
2314132727Skan    case 7:
2315132727Skan    case 8:
2316132727Skan      return "movss\t{%1, %0|%0, %1}";
2317132727Skan
2318132727Skan    case 9:
2319132727Skan    case 10:
2320132727Skan      return "movd\t{%1, %0|%0, %1}";
2321132727Skan
2322132727Skan    case 11:
2323132727Skan      return "movq\t{%1, %0|%0, %1}";
2324132727Skan
2325132727Skan    default:
2326169699Skan      gcc_unreachable ();
2327132727Skan    }
2328132727Skan}
2329169699Skan  [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov")
2330132727Skan   (set (attr "mode")
2331132727Skan        (cond [(eq_attr "alternative" "3,4,9,10")
2332132727Skan		 (const_string "SI")
2333132727Skan	       (eq_attr "alternative" "5")
2334132727Skan		 (if_then_else
2335132727Skan		   (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2336132727Skan			    	 (const_int 0))
2337132727Skan			     (ne (symbol_ref "TARGET_SSE2")
2338132727Skan				 (const_int 0)))
2339132727Skan			(eq (symbol_ref "optimize_size")
2340132727Skan			    (const_int 0)))
2341132727Skan		   (const_string "TI")
2342132727Skan		   (const_string "V4SF"))
2343132727Skan	       /* For architectures resolving dependencies on
2344132727Skan		  whole SSE registers use APS move to break dependency
2345132727Skan		  chains, otherwise use short move to avoid extra work. 
234618334Speter
2347132727Skan		  Do the same for architectures resolving dependencies on
2348132727Skan		  the parts.  While in DF mode it is better to always handle
2349132727Skan		  just register parts, the SF mode is different due to lack
2350132727Skan		  of instructions to load just part of the register.  It is
2351132727Skan		  better to maintain the whole registers in single format
2352132727Skan		  to avoid problems on using packed logical operations.  */
2353132727Skan	       (eq_attr "alternative" "6")
2354132727Skan		 (if_then_else
2355132727Skan		   (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2356132727Skan			    (const_int 0))
2357169699Skan			(ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2358132727Skan			    (const_int 0)))
2359132727Skan		   (const_string "V4SF")
2360132727Skan		   (const_string "SF"))
2361132727Skan	       (eq_attr "alternative" "11")
2362132727Skan		 (const_string "DI")]
2363132727Skan	       (const_string "SF")))])
2364132727Skan
236590286Sobrien(define_insn "*swapsf"
2366169699Skan  [(set (match_operand:SF 0 "fp_register_operand" "+f")
2367169699Skan	(match_operand:SF 1 "fp_register_operand" "+f"))
236818334Speter   (set (match_dup 1)
236918334Speter	(match_dup 0))]
2370169699Skan  "reload_completed || TARGET_80387"
237118334Speter{
237218334Speter  if (STACK_TOP_P (operands[0]))
237390286Sobrien    return "fxch\t%1";
237418334Speter  else
237590286Sobrien    return "fxch\t%0";
237690286Sobrien}
237790286Sobrien  [(set_attr "type" "fxch")
237890286Sobrien   (set_attr "mode" "SF")])
237918334Speter
238090286Sobrien(define_expand "movdf"
238190286Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
238290286Sobrien	(match_operand:DF 1 "general_operand" ""))]
238390286Sobrien  ""
238490286Sobrien  "ix86_expand_move (DFmode, operands); DONE;")
238552296Sobrien
238690286Sobrien;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
2387132727Skan;; Size of pushdf using integer instructions is 2+2*memory operand size
238890286Sobrien;; On the average, pushdf using integers can be still shorter.  Allow this
238990286Sobrien;; pattern for optimize_size too.
239090286Sobrien
239190286Sobrien(define_insn "*pushdf_nointeger"
239290286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
2393169699Skan	(match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))]
239490286Sobrien  "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
239518334Speter{
2396132727Skan  /* This insn should be already split before reg-stack.  */
2397169699Skan  gcc_unreachable ();
239890286Sobrien}
239990286Sobrien  [(set_attr "type" "multi")
2400169699Skan   (set_attr "unit" "i387,*,*,*")
240190286Sobrien   (set_attr "mode" "DF,SI,SI,DF")])
240218334Speter
240390286Sobrien(define_insn "*pushdf_integer"
240490286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<,<,<")
2405169699Skan	(match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))]
240690286Sobrien  "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
240790286Sobrien{
2408132727Skan  /* This insn should be already split before reg-stack.  */
2409169699Skan  gcc_unreachable ();
241090286Sobrien}
241190286Sobrien  [(set_attr "type" "multi")
2412169699Skan   (set_attr "unit" "i387,*,*")
241390286Sobrien   (set_attr "mode" "DF,SI,DF")])
241418334Speter
241590286Sobrien;; %%% Kill this when call knows how to work this out.
241652296Sobrien(define_split
241752296Sobrien  [(set (match_operand:DF 0 "push_operand" "")
2418117404Skan	(match_operand:DF 1 "any_fp_register_operand" ""))]
2419117404Skan  "!TARGET_64BIT && reload_completed"
2420169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
2421169699Skan   (set (mem:DF (reg:SI SP_REG)) (match_dup 1))]
242252296Sobrien  "")
242350650Sobrien
242490286Sobrien(define_split
242590286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
2426117404Skan	(match_operand:DF 1 "any_fp_register_operand" ""))]
2427117404Skan  "TARGET_64BIT && reload_completed"
2428169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
2429169699Skan   (set (mem:DF (reg:DI SP_REG)) (match_dup 1))]
243090286Sobrien  "")
243190286Sobrien
243290286Sobrien(define_split
243390286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
243450650Sobrien	(match_operand:DF 1 "general_operand" ""))]
243590286Sobrien  "reload_completed"
243690286Sobrien  [(const_int 0)]
243790286Sobrien  "ix86_split_long_move (operands); DONE;")
243890286Sobrien
243990286Sobrien;; Moving is usually shorter when only FP registers are used. This separate
244090286Sobrien;; movdf pattern avoids the use of integer registers for FP operations
244190286Sobrien;; when optimizing for size.
244290286Sobrien
244390286Sobrien(define_insn "*movdf_nointeger"
2444169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"
2445169699Skan			"=f,m,f,*r  ,o  ,Y*x,Y*x,Y*x ,m  ")
2446169699Skan	(match_operand:DF 1 "general_operand"
2447169699Skan			"fm,f,G,*roF,F*r,C  ,Y*x,mY*x,Y*x"))]
244890286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2449132727Skan   && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
245090286Sobrien   && (reload_in_progress || reload_completed
245190286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
245290286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
245390286Sobrien       || memory_operand (operands[0], DFmode))" 
245418334Speter{
245590286Sobrien  switch (which_alternative)
245618334Speter    {
245790286Sobrien    case 0:
2458169699Skan      return output_387_reg_move (insn, operands);
245918334Speter
246090286Sobrien    case 1:
246190286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
246290286Sobrien        return "fstp%z0\t%y0";
246390286Sobrien      else
246490286Sobrien        return "fst%z0\t%y0";
246518334Speter
246690286Sobrien    case 2:
2467132727Skan      return standard_80387_constant_opcode (operands[1]);
246818334Speter
246990286Sobrien    case 3:
247090286Sobrien    case 4:
247190286Sobrien      return "#";
247290286Sobrien    case 5:
2473132727Skan      switch (get_attr_mode (insn))
2474132727Skan	{
2475132727Skan	case MODE_V4SF:
2476132727Skan	  return "xorps\t%0, %0";
2477132727Skan	case MODE_V2DF:
2478132727Skan	  return "xorpd\t%0, %0";
2479132727Skan	case MODE_TI:
2480132727Skan	  return "pxor\t%0, %0";
2481132727Skan	default:
2482169699Skan	  gcc_unreachable ();
2483132727Skan	}
248490286Sobrien    case 6:
2485169699Skan    case 7:
2486169699Skan    case 8:
2487132727Skan      switch (get_attr_mode (insn))
2488132727Skan	{
2489132727Skan	case MODE_V4SF:
2490132727Skan	  return "movaps\t{%1, %0|%0, %1}";
2491132727Skan	case MODE_V2DF:
2492132727Skan	  return "movapd\t{%1, %0|%0, %1}";
2493169699Skan	case MODE_TI:
2494169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
2495169699Skan	case MODE_DI:
2496169699Skan	  return "movq\t{%1, %0|%0, %1}";
2497132727Skan	case MODE_DF:
2498132727Skan	  return "movsd\t{%1, %0|%0, %1}";
2499169699Skan	case MODE_V1DF:
2500169699Skan	  return "movlpd\t{%1, %0|%0, %1}";
2501169699Skan	case MODE_V2SF:
2502169699Skan	  return "movlps\t{%1, %0|%0, %1}";
2503132727Skan	default:
2504169699Skan	  gcc_unreachable ();
2505132727Skan	}
250618334Speter
250790286Sobrien    default:
2508169699Skan      gcc_unreachable ();
250918334Speter    }
251090286Sobrien}
2511169699Skan  [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
2512132727Skan   (set (attr "mode")
2513169699Skan        (cond [(eq_attr "alternative" "0,1,2")
2514169699Skan		 (const_string "DF")
2515169699Skan	       (eq_attr "alternative" "3,4")
2516132727Skan		 (const_string "SI")
2517169699Skan
2518169699Skan	       /* For SSE1, we have many fewer alternatives.  */
2519169699Skan	       (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2520169699Skan		 (cond [(eq_attr "alternative" "5,6")
2521169699Skan			  (const_string "V4SF")
2522169699Skan		       ]
2523169699Skan		   (const_string "V2SF"))
2524169699Skan
2525132727Skan	       /* xorps is one byte shorter.  */
2526132727Skan	       (eq_attr "alternative" "5")
2527132727Skan		 (cond [(ne (symbol_ref "optimize_size")
2528132727Skan			    (const_int 0))
2529132727Skan			  (const_string "V4SF")
2530132727Skan			(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2531132727Skan			    (const_int 0))
2532169699Skan			  (const_string "TI")
2533169699Skan		       ]
2534132727Skan		       (const_string "V2DF"))
2535169699Skan
2536132727Skan	       /* For architectures resolving dependencies on
2537132727Skan		  whole SSE registers use APD move to break dependency
2538132727Skan		  chains, otherwise use short move to avoid extra work.
253918334Speter
2540132727Skan		  movaps encodes one byte shorter.  */
2541132727Skan	       (eq_attr "alternative" "6")
2542132727Skan		 (cond
2543169699Skan		   [(ne (symbol_ref "optimize_size")
2544169699Skan		        (const_int 0))
2545169699Skan		      (const_string "V4SF")
2546169699Skan		    (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2547169699Skan		        (const_int 0))
2548169699Skan		      (const_string "V2DF")
2549169699Skan		   ]
2550132727Skan		   (const_string "DF"))
2551132727Skan	       /* For architectures resolving dependencies on register
2552132727Skan		  parts we may avoid extra work to zero out upper part
2553132727Skan		  of register.  */
2554132727Skan	       (eq_attr "alternative" "7")
2555132727Skan		 (if_then_else
2556169699Skan		   (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2557132727Skan		       (const_int 0))
2558169699Skan		   (const_string "V1DF")
2559169699Skan		   (const_string "DF"))
2560169699Skan	      ]
2561169699Skan	      (const_string "DF")))])
2562132727Skan
256390286Sobrien(define_insn "*movdf_integer"
2564169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"
2565169699Skan		"=f,m,f,r  ,o ,Y*x,Y*x,Y*x,m  ")
2566169699Skan	(match_operand:DF 1 "general_operand"
2567169699Skan		"fm,f,G,roF,Fr,C  ,Y*x,m  ,Y*x"))]
256890286Sobrien  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2569132727Skan   && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
257090286Sobrien   && (reload_in_progress || reload_completed
257190286Sobrien       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
257290286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
257390286Sobrien       || memory_operand (operands[0], DFmode))" 
257490286Sobrien{
257590286Sobrien  switch (which_alternative)
257618334Speter    {
257790286Sobrien    case 0:
2578169699Skan      return output_387_reg_move (insn, operands);
257918334Speter
258090286Sobrien    case 1:
258190286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
258290286Sobrien        return "fstp%z0\t%y0";
258390286Sobrien      else
258490286Sobrien        return "fst%z0\t%y0";
258518334Speter
258690286Sobrien    case 2:
2587132727Skan      return standard_80387_constant_opcode (operands[1]);
258818334Speter
258990286Sobrien    case 3:
259090286Sobrien    case 4:
259190286Sobrien      return "#";
259218334Speter
259390286Sobrien    case 5:
2594132727Skan      switch (get_attr_mode (insn))
2595132727Skan	{
2596132727Skan	case MODE_V4SF:
2597132727Skan	  return "xorps\t%0, %0";
2598132727Skan	case MODE_V2DF:
2599132727Skan	  return "xorpd\t%0, %0";
2600132727Skan	case MODE_TI:
2601132727Skan	  return "pxor\t%0, %0";
2602132727Skan	default:
2603169699Skan	  gcc_unreachable ();
2604132727Skan	}
260590286Sobrien    case 6:
2606169699Skan    case 7:
2607169699Skan    case 8:
2608132727Skan      switch (get_attr_mode (insn))
2609132727Skan	{
2610132727Skan	case MODE_V4SF:
2611132727Skan	  return "movaps\t{%1, %0|%0, %1}";
2612132727Skan	case MODE_V2DF:
2613132727Skan	  return "movapd\t{%1, %0|%0, %1}";
2614169699Skan	case MODE_TI:
2615169699Skan	  return "movdqa\t{%1, %0|%0, %1}";
2616169699Skan	case MODE_DI:
2617169699Skan	  return "movq\t{%1, %0|%0, %1}";
2618132727Skan	case MODE_DF:
2619132727Skan	  return "movsd\t{%1, %0|%0, %1}";
2620169699Skan	case MODE_V1DF:
2621169699Skan	  return "movlpd\t{%1, %0|%0, %1}";
2622169699Skan	case MODE_V2SF:
2623169699Skan	  return "movlps\t{%1, %0|%0, %1}";
2624132727Skan	default:
2625169699Skan	  gcc_unreachable ();
2626132727Skan	}
262718334Speter
262890286Sobrien    default:
2629169699Skan      gcc_unreachable();
263090286Sobrien    }
263190286Sobrien}
2632169699Skan  [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
2633132727Skan   (set (attr "mode")
2634169699Skan        (cond [(eq_attr "alternative" "0,1,2")
2635169699Skan		 (const_string "DF")
2636169699Skan	       (eq_attr "alternative" "3,4")
2637132727Skan		 (const_string "SI")
2638169699Skan
2639169699Skan	       /* For SSE1, we have many fewer alternatives.  */
2640169699Skan	       (eq (symbol_ref "TARGET_SSE2") (const_int 0))
2641169699Skan		 (cond [(eq_attr "alternative" "5,6")
2642169699Skan			  (const_string "V4SF")
2643169699Skan		       ]
2644169699Skan		   (const_string "V2SF"))
2645169699Skan
2646132727Skan	       /* xorps is one byte shorter.  */
2647132727Skan	       (eq_attr "alternative" "5")
2648132727Skan		 (cond [(ne (symbol_ref "optimize_size")
2649132727Skan			    (const_int 0))
2650132727Skan			  (const_string "V4SF")
2651132727Skan			(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
2652132727Skan			    (const_int 0))
2653169699Skan			  (const_string "TI")
2654169699Skan		       ]
2655132727Skan		       (const_string "V2DF"))
2656169699Skan
2657132727Skan	       /* For architectures resolving dependencies on
2658132727Skan		  whole SSE registers use APD move to break dependency
2659169699Skan		  chains, otherwise use short move to avoid extra work.
266018334Speter
2661132727Skan		  movaps encodes one byte shorter.  */
2662132727Skan	       (eq_attr "alternative" "6")
2663132727Skan		 (cond
2664169699Skan		   [(ne (symbol_ref "optimize_size")
2665169699Skan		        (const_int 0))
2666169699Skan		      (const_string "V4SF")
2667169699Skan		    (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
2668169699Skan		        (const_int 0))
2669169699Skan		      (const_string "V2DF")
2670169699Skan		   ]
2671132727Skan		   (const_string "DF"))
2672132727Skan	       /* For architectures resolving dependencies on register
2673132727Skan		  parts we may avoid extra work to zero out upper part
2674132727Skan		  of register.  */
2675132727Skan	       (eq_attr "alternative" "7")
2676132727Skan		 (if_then_else
2677169699Skan		   (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
2678132727Skan		       (const_int 0))
2679169699Skan		   (const_string "V1DF")
2680169699Skan		   (const_string "DF"))
2681169699Skan	      ]
2682169699Skan	      (const_string "DF")))])
2683132727Skan
268490286Sobrien(define_split
268590286Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
268690286Sobrien	(match_operand:DF 1 "general_operand" ""))]
268790286Sobrien  "reload_completed
268890286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
268990286Sobrien   && ! (ANY_FP_REG_P (operands[0]) || 
269090286Sobrien	 (GET_CODE (operands[0]) == SUBREG
269190286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
269290286Sobrien   && ! (ANY_FP_REG_P (operands[1]) || 
269390286Sobrien	 (GET_CODE (operands[1]) == SUBREG
269490286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
269590286Sobrien  [(const_int 0)]
269690286Sobrien  "ix86_split_long_move (operands); DONE;")
269750650Sobrien
269890286Sobrien(define_insn "*swapdf"
2699169699Skan  [(set (match_operand:DF 0 "fp_register_operand" "+f")
2700169699Skan	(match_operand:DF 1 "fp_register_operand" "+f"))
270118334Speter   (set (match_dup 1)
270218334Speter	(match_dup 0))]
2703169699Skan  "reload_completed || TARGET_80387"
270418334Speter{
270518334Speter  if (STACK_TOP_P (operands[0]))
270690286Sobrien    return "fxch\t%1";
270718334Speter  else
270890286Sobrien    return "fxch\t%0";
270990286Sobrien}
271090286Sobrien  [(set_attr "type" "fxch")
271190286Sobrien   (set_attr "mode" "DF")])
271218334Speter
271390286Sobrien(define_expand "movxf"
271490286Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
271590286Sobrien	(match_operand:XF 1 "general_operand" ""))]
2716132727Skan  ""
271790286Sobrien  "ix86_expand_move (XFmode, operands); DONE;")
271890286Sobrien
271990286Sobrien;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
2720132727Skan;; Size of pushdf using integer instructions is 3+3*memory operand size
272190286Sobrien;; Pushing using integer instructions is longer except for constants
272290286Sobrien;; and direct memory references.
272390286Sobrien;; (assuming that any given constant is pushed only once, but this ought to be
272490286Sobrien;;  handled elsewhere).
272590286Sobrien
272690286Sobrien(define_insn "*pushxf_nointeger"
272790286Sobrien  [(set (match_operand:XF 0 "push_operand" "=X,X,X")
272890286Sobrien	(match_operand:XF 1 "general_no_elim_operand" "f,Fo,*r"))]
272990286Sobrien  "optimize_size"
273090286Sobrien{
2731132727Skan  /* This insn should be already split before reg-stack.  */
2732169699Skan  gcc_unreachable ();
273390286Sobrien}
273490286Sobrien  [(set_attr "type" "multi")
2735169699Skan   (set_attr "unit" "i387,*,*")
273690286Sobrien   (set_attr "mode" "XF,SI,SI")])
273750650Sobrien
273890286Sobrien(define_insn "*pushxf_integer"
273990286Sobrien  [(set (match_operand:XF 0 "push_operand" "=<,<")
2740169699Skan	(match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
274190286Sobrien  "!optimize_size"
274290286Sobrien{
2743132727Skan  /* This insn should be already split before reg-stack.  */
2744169699Skan  gcc_unreachable ();
274590286Sobrien}
274690286Sobrien  [(set_attr "type" "multi")
2747169699Skan   (set_attr "unit" "i387,*")
274890286Sobrien   (set_attr "mode" "XF,SI")])
274990286Sobrien
275052296Sobrien(define_split
275190286Sobrien  [(set (match_operand 0 "push_operand" "")
275290286Sobrien	(match_operand 1 "general_operand" ""))]
275390286Sobrien  "reload_completed
275490286Sobrien   && (GET_MODE (operands[0]) == XFmode
275590286Sobrien       || GET_MODE (operands[0]) == DFmode)
2756117404Skan   && !ANY_FP_REG_P (operands[1])"
275790286Sobrien  [(const_int 0)]
275890286Sobrien  "ix86_split_long_move (operands); DONE;")
275990286Sobrien
276090286Sobrien(define_split
276152296Sobrien  [(set (match_operand:XF 0 "push_operand" "")
2762117404Skan	(match_operand:XF 1 "any_fp_register_operand" ""))]
2763117404Skan  "!TARGET_64BIT"
2764169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
2765169699Skan   (set (mem:XF (reg:SI SP_REG)) (match_dup 1))]
2766132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
276750650Sobrien
276890286Sobrien(define_split
2769132727Skan  [(set (match_operand:XF 0 "push_operand" "")
2770132727Skan	(match_operand:XF 1 "any_fp_register_operand" ""))]
2771117404Skan  "TARGET_64BIT"
2772169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
2773169699Skan   (set (mem:XF (reg:DI SP_REG)) (match_dup 1))]
2774132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
277590286Sobrien
277690286Sobrien;; Do not use integer registers when optimizing for size
277790286Sobrien(define_insn "*movxf_nointeger"
277890286Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o")
277990286Sobrien	(match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))]
2780132727Skan  "optimize_size
278190286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
278290286Sobrien   && (reload_in_progress || reload_completed
278390286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
278490286Sobrien       || memory_operand (operands[0], XFmode))" 
278518334Speter{
278690286Sobrien  switch (which_alternative)
278718334Speter    {
278890286Sobrien    case 0:
2789169699Skan      return output_387_reg_move (insn, operands);
279018334Speter
279190286Sobrien    case 1:
279290286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
279390286Sobrien	 we need one, follow the store with a load.  */
279490286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
279590286Sobrien        return "fstp%z0\t%y0\;fld%z0\t%y0";
279690286Sobrien      else
279790286Sobrien        return "fstp%z0\t%y0";
279818334Speter
279990286Sobrien    case 2:
2800132727Skan      return standard_80387_constant_opcode (operands[1]);
280118334Speter
280290286Sobrien    case 3: case 4:
280390286Sobrien      return "#";
2804169699Skan    default:
2805169699Skan      gcc_unreachable ();
280690286Sobrien    }
280790286Sobrien}
280890286Sobrien  [(set_attr "type" "fmov,fmov,fmov,multi,multi")
280990286Sobrien   (set_attr "mode" "XF,XF,XF,SI,SI")])
281018334Speter
281190286Sobrien(define_insn "*movxf_integer"
2812169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
2813169699Skan	(match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
2814132727Skan  "!optimize_size
281590286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
281690286Sobrien   && (reload_in_progress || reload_completed
281790286Sobrien       || GET_CODE (operands[1]) != CONST_DOUBLE
281890286Sobrien       || memory_operand (operands[0], XFmode))" 
281990286Sobrien{
282090286Sobrien  switch (which_alternative)
282118334Speter    {
282290286Sobrien    case 0:
2823169699Skan      return output_387_reg_move (insn, operands);
282418334Speter
282590286Sobrien    case 1:
282690286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
282790286Sobrien	 we need one, follow the store with a load.  */
282890286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
282990286Sobrien        return "fstp%z0\t%y0\;fld%z0\t%y0";
283090286Sobrien      else
283190286Sobrien        return "fstp%z0\t%y0";
283218334Speter
283390286Sobrien    case 2:
2834132727Skan      return standard_80387_constant_opcode (operands[1]);
283518334Speter
283690286Sobrien    case 3: case 4:
283790286Sobrien      return "#";
2838169699Skan
2839169699Skan    default:
2840169699Skan      gcc_unreachable ();
284190286Sobrien    }
284290286Sobrien}
284390286Sobrien  [(set_attr "type" "fmov,fmov,fmov,multi,multi")
284490286Sobrien   (set_attr "mode" "XF,XF,XF,SI,SI")])
284518334Speter
284690286Sobrien(define_split
284790286Sobrien  [(set (match_operand 0 "nonimmediate_operand" "")
284890286Sobrien	(match_operand 1 "general_operand" ""))]
284990286Sobrien  "reload_completed
285090286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2851132727Skan   && GET_MODE (operands[0]) == XFmode
285290286Sobrien   && ! (ANY_FP_REG_P (operands[0]) || 
285390286Sobrien	 (GET_CODE (operands[0]) == SUBREG
285490286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
285590286Sobrien   && ! (ANY_FP_REG_P (operands[1]) || 
285690286Sobrien	 (GET_CODE (operands[1]) == SUBREG
285790286Sobrien	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
285890286Sobrien  [(const_int 0)]
285990286Sobrien  "ix86_split_long_move (operands); DONE;")
286018334Speter
286190286Sobrien(define_split
286290286Sobrien  [(set (match_operand 0 "register_operand" "")
286390286Sobrien	(match_operand 1 "memory_operand" ""))]
286490286Sobrien  "reload_completed
286590286Sobrien   && GET_CODE (operands[1]) == MEM
2866132727Skan   && (GET_MODE (operands[0]) == XFmode
286790286Sobrien       || GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode)
2868161660Skan   && constant_pool_reference_p (operands[1])"
2869132727Skan  [(set (match_dup 0) (match_dup 1))]
2870132727Skan{
2871161660Skan  rtx c = avoid_constant_pool_reference (operands[1]);
2872132727Skan  rtx r = operands[0];
287390286Sobrien
2874132727Skan  if (GET_CODE (r) == SUBREG)
2875132727Skan    r = SUBREG_REG (r);
2876132727Skan
2877132727Skan  if (SSE_REG_P (r))
2878132727Skan    {
2879132727Skan      if (!standard_sse_constant_p (c))
2880132727Skan	FAIL;
2881132727Skan    }
2882132727Skan  else if (FP_REG_P (r))
2883132727Skan    {
2884132727Skan      if (!standard_80387_constant_p (c))
2885132727Skan	FAIL;
2886132727Skan    }
2887132727Skan  else if (MMX_REG_P (r))
2888132727Skan    FAIL;
2889132727Skan
2890132727Skan  operands[1] = c;
2891132727Skan})
2892132727Skan
289390286Sobrien(define_insn "swapxf"
289490286Sobrien  [(set (match_operand:XF 0 "register_operand" "+f")
289590286Sobrien	(match_operand:XF 1 "register_operand" "+f"))
289618334Speter   (set (match_dup 1)
289718334Speter	(match_dup 0))]
2898169699Skan  "TARGET_80387"
289918334Speter{
290018334Speter  if (STACK_TOP_P (operands[0]))
290190286Sobrien    return "fxch\t%1";
290218334Speter  else
290390286Sobrien    return "fxch\t%0";
290490286Sobrien}
290590286Sobrien  [(set_attr "type" "fxch")
290690286Sobrien   (set_attr "mode" "XF")])
2907169699Skan
2908169699Skan(define_expand "movtf"
2909169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "")
2910169699Skan	(match_operand:TF 1 "nonimmediate_operand" ""))]
2911169699Skan  "TARGET_64BIT"
2912169699Skan{
2913169699Skan  ix86_expand_move (TFmode, operands);
2914169699Skan  DONE;
2915169699Skan})
2916169699Skan
2917169699Skan(define_insn "*movtf_internal"
2918169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm")
2919169699Skan	(match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))]
2920169699Skan  "TARGET_64BIT
2921169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2922169699Skan{
2923169699Skan  switch (which_alternative)
2924169699Skan    {
2925169699Skan    case 0:
2926169699Skan    case 1:
2927169699Skan      return "#";
2928169699Skan    case 2:
2929169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2930169699Skan	return "xorps\t%0, %0";
2931169699Skan      else
2932169699Skan	return "pxor\t%0, %0";
2933169699Skan    case 3:
2934169699Skan    case 4:
2935169699Skan      if (get_attr_mode (insn) == MODE_V4SF)
2936169699Skan	return "movaps\t{%1, %0|%0, %1}";
2937169699Skan      else
2938169699Skan	return "movdqa\t{%1, %0|%0, %1}";
2939169699Skan    default:
2940169699Skan      gcc_unreachable ();
2941169699Skan    }
2942169699Skan}
2943169699Skan  [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
2944169699Skan   (set (attr "mode")
2945169699Skan        (cond [(eq_attr "alternative" "2,3")
2946169699Skan		 (if_then_else
2947169699Skan		   (ne (symbol_ref "optimize_size")
2948169699Skan		       (const_int 0))
2949169699Skan		   (const_string "V4SF")
2950169699Skan		   (const_string "TI"))
2951169699Skan	       (eq_attr "alternative" "4")
2952169699Skan		 (if_then_else
2953169699Skan		   (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
2954169699Skan			    (const_int 0))
2955169699Skan			(ne (symbol_ref "optimize_size")
2956169699Skan			    (const_int 0)))
2957169699Skan		   (const_string "V4SF")
2958169699Skan		   (const_string "TI"))]
2959169699Skan	       (const_string "DI")))])
2960169699Skan
2961169699Skan(define_split
2962169699Skan  [(set (match_operand:TF 0 "nonimmediate_operand" "")
2963169699Skan        (match_operand:TF 1 "general_operand" ""))]
2964169699Skan  "reload_completed && !SSE_REG_P (operands[0])
2965169699Skan   && !SSE_REG_P (operands[1])"
2966169699Skan  [(const_int 0)]
2967169699Skan  "ix86_split_long_move (operands); DONE;")
296818334Speter
296990286Sobrien;; Zero extension instructions
297018334Speter
297152296Sobrien(define_expand "zero_extendhisi2"
297252296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
297390286Sobrien     (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
297452296Sobrien  ""
297590286Sobrien{
297690286Sobrien  if (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
297718334Speter    {
297890286Sobrien      operands[1] = force_reg (HImode, operands[1]);
297990286Sobrien      emit_insn (gen_zero_extendhisi2_and (operands[0], operands[1]));
298090286Sobrien      DONE;
298118334Speter    }
298290286Sobrien})
298318334Speter
298490286Sobrien(define_insn "zero_extendhisi2_and"
298590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
298690286Sobrien     (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
2987169699Skan   (clobber (reg:CC FLAGS_REG))]
298890286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
298990286Sobrien  "#"
299090286Sobrien  [(set_attr "type" "alu1")
299190286Sobrien   (set_attr "mode" "SI")])
299250650Sobrien
299350650Sobrien(define_split
299450650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
299590286Sobrien	(zero_extend:SI (match_operand:HI 1 "register_operand" "")))
2996169699Skan   (clobber (reg:CC FLAGS_REG))]
299790286Sobrien  "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
299890286Sobrien  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535)))
2999169699Skan	      (clobber (reg:CC FLAGS_REG))])]
300090286Sobrien  "")
300150650Sobrien
300290286Sobrien(define_insn "*zero_extendhisi2_movzwl"
300390286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
300490286Sobrien     (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
300590286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
300690286Sobrien  "movz{wl|x}\t{%1, %0|%0, %1}"
300790286Sobrien  [(set_attr "type" "imovx")
300890286Sobrien   (set_attr "mode" "SI")])
300950650Sobrien
301052296Sobrien(define_expand "zero_extendqihi2"
301190286Sobrien  [(parallel
301290286Sobrien    [(set (match_operand:HI 0 "register_operand" "")
301390286Sobrien       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3014169699Skan     (clobber (reg:CC FLAGS_REG))])]
301552296Sobrien  ""
301652296Sobrien  "")
301752296Sobrien
301890286Sobrien(define_insn "*zero_extendqihi2_and"
301990286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,?&q")
302090286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
3021169699Skan   (clobber (reg:CC FLAGS_REG))]
302290286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
302390286Sobrien  "#"
302490286Sobrien  [(set_attr "type" "alu1")
302590286Sobrien   (set_attr "mode" "HI")])
302652296Sobrien
302790286Sobrien(define_insn "*zero_extendqihi2_movzbw_and"
302890286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
302990286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
3030169699Skan   (clobber (reg:CC FLAGS_REG))]
303190286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
303290286Sobrien  "#"
303390286Sobrien  [(set_attr "type" "imovx,alu1")
303490286Sobrien   (set_attr "mode" "HI")])
303552296Sobrien
3036169699Skan; zero extend to SImode here to avoid partial register stalls
3037169699Skan(define_insn "*zero_extendqihi2_movzbl"
303890286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r")
303990286Sobrien     (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
304090286Sobrien  "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
3041169699Skan  "movz{bl|x}\t{%1, %k0|%k0, %k1}"
304290286Sobrien  [(set_attr "type" "imovx")
3043169699Skan   (set_attr "mode" "SI")])
304450650Sobrien
304590286Sobrien;; For the movzbw case strip only the clobber
304650650Sobrien(define_split
304750650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
304890286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3049169699Skan   (clobber (reg:CC FLAGS_REG))]
305090286Sobrien  "reload_completed 
305190286Sobrien   && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
305290286Sobrien   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
305390286Sobrien  [(set (match_operand:HI 0 "register_operand" "")
305490286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))])
305550650Sobrien
305690286Sobrien;; When source and destination does not overlap, clear destination
305790286Sobrien;; first and then do the movb
305850650Sobrien(define_split
305950650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
306090286Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
3061169699Skan   (clobber (reg:CC FLAGS_REG))]
306290286Sobrien  "reload_completed
306390286Sobrien   && ANY_QI_REG_P (operands[0])
306490286Sobrien   && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
306590286Sobrien   && !reg_overlap_mentioned_p (operands[0], operands[1])"
306690286Sobrien  [(set (match_dup 0) (const_int 0))
306790286Sobrien   (set (strict_low_part (match_dup 2)) (match_dup 1))]
306890286Sobrien  "operands[2] = gen_lowpart (QImode, operands[0]);")
306950650Sobrien
307090286Sobrien;; Rest is handled by single and.
307150650Sobrien(define_split
307250650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
307390286Sobrien	(zero_extend:HI (match_operand:QI 1 "register_operand" "")))
3074169699Skan   (clobber (reg:CC FLAGS_REG))]
307590286Sobrien  "reload_completed
307690286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
307790286Sobrien  [(parallel [(set (match_dup 0) (and:HI (match_dup 0) (const_int 255)))
3078169699Skan	      (clobber (reg:CC FLAGS_REG))])]
307990286Sobrien  "")
308050650Sobrien
308152296Sobrien(define_expand "zero_extendqisi2"
308290286Sobrien  [(parallel
308390286Sobrien    [(set (match_operand:SI 0 "register_operand" "")
308490286Sobrien       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3085169699Skan     (clobber (reg:CC FLAGS_REG))])]
308652296Sobrien  ""
308752296Sobrien  "")
308852296Sobrien
308990286Sobrien(define_insn "*zero_extendqisi2_and"
309090286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,?&q")
309190286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
3092169699Skan   (clobber (reg:CC FLAGS_REG))]
309390286Sobrien  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
309490286Sobrien  "#"
309590286Sobrien  [(set_attr "type" "alu1")
309690286Sobrien   (set_attr "mode" "SI")])
309752296Sobrien
309890286Sobrien(define_insn "*zero_extendqisi2_movzbw_and"
309990286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
310090286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
3101169699Skan   (clobber (reg:CC FLAGS_REG))]
310290286Sobrien  "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
310390286Sobrien  "#"
310490286Sobrien  [(set_attr "type" "imovx,alu1")
310590286Sobrien   (set_attr "mode" "SI")])
310650650Sobrien
310790286Sobrien(define_insn "*zero_extendqisi2_movzbw"
310890286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
310990286Sobrien     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
311090286Sobrien  "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
311190286Sobrien  "movz{bl|x}\t{%1, %0|%0, %1}"
311290286Sobrien  [(set_attr "type" "imovx")
311390286Sobrien   (set_attr "mode" "SI")])
311418334Speter
311590286Sobrien;; For the movzbl case strip only the clobber
311650650Sobrien(define_split
311750650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
311890286Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3119169699Skan   (clobber (reg:CC FLAGS_REG))]
312090286Sobrien  "reload_completed 
312190286Sobrien   && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
312290286Sobrien   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
312390286Sobrien  [(set (match_dup 0)
312490286Sobrien	(zero_extend:SI (match_dup 1)))])
312550650Sobrien
312690286Sobrien;; When source and destination does not overlap, clear destination
312790286Sobrien;; first and then do the movb
312850650Sobrien(define_split
312950650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
313090286Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
3131169699Skan   (clobber (reg:CC FLAGS_REG))]
313290286Sobrien  "reload_completed
313390286Sobrien   && ANY_QI_REG_P (operands[0])
313490286Sobrien   && (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)
313590286Sobrien   && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
313690286Sobrien   && !reg_overlap_mentioned_p (operands[0], operands[1])"
313790286Sobrien  [(set (match_dup 0) (const_int 0))
313890286Sobrien   (set (strict_low_part (match_dup 2)) (match_dup 1))]
313990286Sobrien  "operands[2] = gen_lowpart (QImode, operands[0]);")
314050650Sobrien
314190286Sobrien;; Rest is handled by single and.
314250650Sobrien(define_split
314350650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
314490286Sobrien	(zero_extend:SI (match_operand:QI 1 "register_operand" "")))
3145169699Skan   (clobber (reg:CC FLAGS_REG))]
314690286Sobrien  "reload_completed
314790286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
314890286Sobrien  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 255)))
3149169699Skan	      (clobber (reg:CC FLAGS_REG))])]
315090286Sobrien  "")
315150650Sobrien
315290286Sobrien;; %%% Kill me once multi-word ops are sane.
315390286Sobrien(define_expand "zero_extendsidi2"
315490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
315590286Sobrien     (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
315618334Speter  ""
315790286Sobrien  "if (!TARGET_64BIT)
315890286Sobrien     {
315990286Sobrien       emit_insn (gen_zero_extendsidi2_32 (operands[0], operands[1]));
316090286Sobrien       DONE;
316190286Sobrien     }
316290286Sobrien  ")
316350650Sobrien
316490286Sobrien(define_insn "zero_extendsidi2_32"
3165169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,?*y,?*Y")
3166132727Skan	(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,rm,rm")))
3167169699Skan   (clobber (reg:CC FLAGS_REG))]
3168169699Skan  "!TARGET_64BIT"
3169132727Skan  "@
3170132727Skan   #
3171132727Skan   #
3172132727Skan   #
3173132727Skan   movd\t{%1, %0|%0, %1}
3174132727Skan   movd\t{%1, %0|%0, %1}"
3175132727Skan  [(set_attr "mode" "SI,SI,SI,DI,TI")
3176132727Skan   (set_attr "type" "multi,multi,multi,mmxmov,ssemov")])
3177132727Skan
317890286Sobrien(define_insn "zero_extendsidi2_rex64"
3179169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*y,?*Y")
3180132727Skan     (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,rm,rm")))]
3181169699Skan  "TARGET_64BIT"
3182132727Skan  "@
3183132727Skan   mov\t{%k1, %k0|%k0, %k1}
3184132727Skan   #
3185132727Skan   movd\t{%1, %0|%0, %1}
3186132727Skan   movd\t{%1, %0|%0, %1}"
3187132727Skan  [(set_attr "type" "imovx,imov,mmxmov,ssemov")
3188132727Skan   (set_attr "mode" "SI,DI,SI,SI")])
3189132727Skan
319090286Sobrien(define_split
319190286Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
319290286Sobrien     (zero_extend:DI (match_dup 0)))]
319390286Sobrien  "TARGET_64BIT"
319490286Sobrien  [(set (match_dup 4) (const_int 0))]
319590286Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
319690286Sobrien
319752296Sobrien(define_split 
319852296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
319990286Sobrien	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
3200169699Skan   (clobber (reg:CC FLAGS_REG))]
320190286Sobrien  "!TARGET_64BIT && reload_completed
320290286Sobrien   && true_regnum (operands[0]) == true_regnum (operands[1])"
320352296Sobrien  [(set (match_dup 4) (const_int 0))]
320452296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
320550650Sobrien
320652296Sobrien(define_split 
320752296Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
320890286Sobrien	(zero_extend:DI (match_operand:SI 1 "general_operand" "")))
3209169699Skan   (clobber (reg:CC FLAGS_REG))]
3210132727Skan  "!TARGET_64BIT && reload_completed
3211132727Skan   && !SSE_REG_P (operands[0]) && !MMX_REG_P (operands[0])"
321252296Sobrien  [(set (match_dup 3) (match_dup 1))
321352296Sobrien   (set (match_dup 4) (const_int 0))]
321452296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
321590286Sobrien
321690286Sobrien(define_insn "zero_extendhidi2"
3217169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
3218169699Skan     (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
321990286Sobrien  "TARGET_64BIT"
3220169699Skan  "movz{wl|x}\t{%1, %k0|%k0, %1}"
322190286Sobrien  [(set_attr "type" "imovx")
3222169699Skan   (set_attr "mode" "DI")])
322390286Sobrien
322490286Sobrien(define_insn "zero_extendqidi2"
3225169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
3226169699Skan     (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
322790286Sobrien  "TARGET_64BIT"
3228169699Skan  "movz{bl|x}\t{%1, %k0|%k0, %1}"
322990286Sobrien  [(set_attr "type" "imovx")
3230169699Skan   (set_attr "mode" "DI")])
323118334Speter
323290286Sobrien;; Sign extension instructions
323318334Speter
323490286Sobrien(define_expand "extendsidi2"
323590286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
323690286Sobrien		   (sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3237169699Skan	      (clobber (reg:CC FLAGS_REG))
323890286Sobrien	      (clobber (match_scratch:SI 2 ""))])]
323990286Sobrien  ""
324090286Sobrien{
324190286Sobrien  if (TARGET_64BIT)
324290286Sobrien    {
324390286Sobrien      emit_insn (gen_extendsidi2_rex64 (operands[0], operands[1]));
324490286Sobrien      DONE;
324590286Sobrien    }
324690286Sobrien})
324790286Sobrien
324890286Sobrien(define_insn "*extendsidi2_1"
324990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=*A,r,?r,?*o")
325090286Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,r")))
3251169699Skan   (clobber (reg:CC FLAGS_REG))
325252296Sobrien   (clobber (match_scratch:SI 2 "=X,X,X,&r"))]
325390286Sobrien  "!TARGET_64BIT"
325452296Sobrien  "#")
325552296Sobrien
325690286Sobrien(define_insn "extendsidi2_rex64"
325790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*a,r")
325890286Sobrien	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "*0,rm")))]
325990286Sobrien  "TARGET_64BIT"
326090286Sobrien  "@
326190286Sobrien   {cltq|cdqe}
326290286Sobrien   movs{lq|x}\t{%1,%0|%0, %1}"
326390286Sobrien  [(set_attr "type" "imovx")
326490286Sobrien   (set_attr "mode" "DI")
326590286Sobrien   (set_attr "prefix_0f" "0")
326690286Sobrien   (set_attr "modrm" "0,1")])
326790286Sobrien
326890286Sobrien(define_insn "extendhidi2"
326990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
327090286Sobrien	(sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
327190286Sobrien  "TARGET_64BIT"
327290286Sobrien  "movs{wq|x}\t{%1,%0|%0, %1}"
327390286Sobrien  [(set_attr "type" "imovx")
327490286Sobrien   (set_attr "mode" "DI")])
327590286Sobrien
327690286Sobrien(define_insn "extendqidi2"
327790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
327890286Sobrien	(sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
327990286Sobrien  "TARGET_64BIT"
328090286Sobrien  "movs{bq|x}\t{%1,%0|%0, %1}"
328190286Sobrien   [(set_attr "type" "imovx")
328290286Sobrien    (set_attr "mode" "DI")])
328390286Sobrien
328452296Sobrien;; Extend to memory case when source register does die.
328552296Sobrien(define_split 
328652296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
328752296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3288169699Skan   (clobber (reg:CC FLAGS_REG))
328952296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
329090286Sobrien  "(reload_completed
329152296Sobrien    && dead_or_set_p (insn, operands[1])
329252296Sobrien    && !reg_mentioned_p (operands[1], operands[0]))"
329352296Sobrien  [(set (match_dup 3) (match_dup 1))
329490286Sobrien   (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
3295169699Skan	      (clobber (reg:CC FLAGS_REG))])
329652296Sobrien   (set (match_dup 4) (match_dup 1))]
329752296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
329852296Sobrien
329952296Sobrien;; Extend to memory case when source register does not die.
330052296Sobrien(define_split 
330152296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
330252296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3303169699Skan   (clobber (reg:CC FLAGS_REG))
330452296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
330590286Sobrien  "reload_completed"
330652296Sobrien  [(const_int 0)]
330718334Speter{
330852296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
330952296Sobrien
331052296Sobrien  emit_move_insn (operands[3], operands[1]);
331152296Sobrien
331252296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
331352296Sobrien  if (true_regnum (operands[1]) == 0
331452296Sobrien      && true_regnum (operands[2]) == 1
331590286Sobrien      && (optimize_size || TARGET_USE_CLTD))
331618334Speter    {
331790286Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[1], GEN_INT (31)));
331818334Speter    }
331952296Sobrien  else
332052296Sobrien    {
332152296Sobrien      emit_move_insn (operands[2], operands[1]);
332290286Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[2], GEN_INT (31)));
332352296Sobrien    }
332452296Sobrien  emit_move_insn (operands[4], operands[2]);
332552296Sobrien  DONE;
332690286Sobrien})
332718334Speter
332852296Sobrien;; Extend to register case.  Optimize case where source and destination
332952296Sobrien;; registers match and cases where we can use cltd.
333052296Sobrien(define_split 
333152296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
333252296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3333169699Skan   (clobber (reg:CC FLAGS_REG))
333452296Sobrien   (clobber (match_scratch:SI 2 ""))]
333552296Sobrien  "reload_completed"
333652296Sobrien  [(const_int 0)]
333752296Sobrien{
333852296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
333918334Speter
334052296Sobrien  if (true_regnum (operands[3]) != true_regnum (operands[1]))
334152296Sobrien    emit_move_insn (operands[3], operands[1]);
334252296Sobrien
334352296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
334452296Sobrien  if (true_regnum (operands[3]) == 0
334590286Sobrien      && (optimize_size || TARGET_USE_CLTD))
334652296Sobrien    {
334790286Sobrien      emit_insn (gen_ashrsi3_31 (operands[4], operands[3], GEN_INT (31)));
334852296Sobrien      DONE;
334952296Sobrien    }
335052296Sobrien
335152296Sobrien  if (true_regnum (operands[4]) != true_regnum (operands[1]))
335252296Sobrien    emit_move_insn (operands[4], operands[1]);
335352296Sobrien
335490286Sobrien  emit_insn (gen_ashrsi3_31 (operands[4], operands[4], GEN_INT (31)));
335552296Sobrien  DONE;
335690286Sobrien})
335718334Speter
335818334Speter(define_insn "extendhisi2"
335990286Sobrien  [(set (match_operand:SI 0 "register_operand" "=*a,r")
336090286Sobrien	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm")))]
336118334Speter  ""
336218334Speter{
336390286Sobrien  switch (get_attr_prefix_0f (insn))
336490286Sobrien    {
336590286Sobrien    case 0:
336690286Sobrien      return "{cwtl|cwde}";
336790286Sobrien    default:
336890286Sobrien      return "movs{wl|x}\t{%1,%0|%0, %1}";
336990286Sobrien    }
337090286Sobrien}
337190286Sobrien  [(set_attr "type" "imovx")
337290286Sobrien   (set_attr "mode" "SI")
337390286Sobrien   (set (attr "prefix_0f")
337490286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
337590286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
337690286Sobrien			(eq_attr "alternative" "0"))
337790286Sobrien	(const_string "0")
337890286Sobrien	(const_string "1")))
337990286Sobrien   (set (attr "modrm")
338090286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
338190286Sobrien	(const_string "0")
338290286Sobrien	(const_string "1")))])
338318334Speter
338490286Sobrien(define_insn "*extendhisi2_zext"
338590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*a,r")
338690286Sobrien	(zero_extend:DI
338790286Sobrien	  (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm"))))]
338890286Sobrien  "TARGET_64BIT"
338990286Sobrien{
339090286Sobrien  switch (get_attr_prefix_0f (insn))
339190286Sobrien    {
339290286Sobrien    case 0:
339390286Sobrien      return "{cwtl|cwde}";
339490286Sobrien    default:
339590286Sobrien      return "movs{wl|x}\t{%1,%k0|%k0, %1}";
339690286Sobrien    }
339790286Sobrien}
339890286Sobrien  [(set_attr "type" "imovx")
339990286Sobrien   (set_attr "mode" "SI")
340090286Sobrien   (set (attr "prefix_0f")
340190286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
340290286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
340390286Sobrien			(eq_attr "alternative" "0"))
340490286Sobrien	(const_string "0")
340590286Sobrien	(const_string "1")))
340690286Sobrien   (set (attr "modrm")
340790286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
340890286Sobrien	(const_string "0")
340990286Sobrien	(const_string "1")))])
341018334Speter
341118334Speter(define_insn "extendqihi2"
341290286Sobrien  [(set (match_operand:HI 0 "register_operand" "=*a,r")
341390286Sobrien	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "*0,qm")))]
341418334Speter  ""
341518334Speter{
341690286Sobrien  switch (get_attr_prefix_0f (insn))
341790286Sobrien    {
341890286Sobrien    case 0:
341990286Sobrien      return "{cbtw|cbw}";
342090286Sobrien    default:
342190286Sobrien      return "movs{bw|x}\t{%1,%0|%0, %1}";
342290286Sobrien    }
342390286Sobrien}
342490286Sobrien  [(set_attr "type" "imovx")
342590286Sobrien   (set_attr "mode" "HI")
342690286Sobrien   (set (attr "prefix_0f")
342790286Sobrien     ;; movsx is short decodable while cwtl is vector decoded.
342890286Sobrien     (if_then_else (and (eq_attr "cpu" "!k6")
342990286Sobrien			(eq_attr "alternative" "0"))
343090286Sobrien	(const_string "0")
343190286Sobrien	(const_string "1")))
343290286Sobrien   (set (attr "modrm")
343390286Sobrien     (if_then_else (eq_attr "prefix_0f" "0")
343490286Sobrien	(const_string "0")
343590286Sobrien	(const_string "1")))])
343618334Speter
343718334Speter(define_insn "extendqisi2"
343850650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
343950650Sobrien	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
344018334Speter  ""
344190286Sobrien  "movs{bl|x}\t{%1,%0|%0, %1}"
344290286Sobrien   [(set_attr "type" "imovx")
344390286Sobrien    (set_attr "mode" "SI")])
344450650Sobrien
344590286Sobrien(define_insn "*extendqisi2_zext"
344690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
344790286Sobrien	(zero_extend:DI
344890286Sobrien	  (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))))]
344990286Sobrien  "TARGET_64BIT"
345090286Sobrien  "movs{bl|x}\t{%1,%k0|%k0, %1}"
345190286Sobrien   [(set_attr "type" "imovx")
345290286Sobrien    (set_attr "mode" "SI")])
345318334Speter
345490286Sobrien;; Conversions between float and double.
345550650Sobrien
345690286Sobrien;; These are all no-ops in the model used for the 80387.  So just
345790286Sobrien;; emit moves.
345850650Sobrien
345990286Sobrien;; %%% Kill these when call knows how to work out a DFmode push earlier. 
346090286Sobrien(define_insn "*dummy_extendsfdf2"
346190286Sobrien  [(set (match_operand:DF 0 "push_operand" "=<")
346290286Sobrien	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fY")))]
346390286Sobrien  "0"
346490286Sobrien  "#")
346550650Sobrien
346690286Sobrien(define_split
346790286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
3468117404Skan	(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
3469117404Skan  "!TARGET_64BIT"
3470169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
3471169699Skan   (set (mem:DF (reg:SI SP_REG)) (float_extend:DF (match_dup 1)))])
347250650Sobrien
347390286Sobrien(define_split
347490286Sobrien  [(set (match_operand:DF 0 "push_operand" "")
3475117404Skan	(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
3476117404Skan  "TARGET_64BIT"
3477169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
3478169699Skan   (set (mem:DF (reg:DI SP_REG)) (float_extend:DF (match_dup 1)))])
347950650Sobrien
348090286Sobrien(define_insn "*dummy_extendsfxf2"
348190286Sobrien  [(set (match_operand:XF 0 "push_operand" "=<")
348290286Sobrien	(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "f")))]
348390286Sobrien  "0"
348490286Sobrien  "#")
348550650Sobrien
348690286Sobrien(define_split
348790286Sobrien  [(set (match_operand:XF 0 "push_operand" "")
3488117404Skan	(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
3489132727Skan  ""
3490169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
3491169699Skan   (set (mem:XF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
3492132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
349350650Sobrien
349490286Sobrien(define_split
3495132727Skan  [(set (match_operand:XF 0 "push_operand" "")
3496132727Skan	(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
3497117404Skan  "TARGET_64BIT"
3498169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
3499169699Skan   (set (mem:DF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
3500132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
350118334Speter
350290286Sobrien(define_split
350390286Sobrien  [(set (match_operand:XF 0 "push_operand" "")
3504117404Skan	(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
3505132727Skan  ""
3506169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
3507169699Skan   (set (mem:DF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
3508132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
350952296Sobrien
351052296Sobrien(define_split
3511132727Skan  [(set (match_operand:XF 0 "push_operand" "")
3512132727Skan	(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
3513117404Skan  "TARGET_64BIT"
3514169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
3515169699Skan   (set (mem:XF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
3516132727Skan  "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
351718334Speter
351890286Sobrien(define_expand "extendsfdf2"
351952296Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
3520117404Skan        (float_extend:DF (match_operand:SF 1 "general_operand" "")))]
3521169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
352252296Sobrien{
3523117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3524117404Skan     are LEGITIMATE_CONSTANT_P.  */
3525117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3526169699Skan    {
3527169699Skan      if ((!TARGET_SSE2 || TARGET_MIX_SSE_I387)
3528169699Skan	  && standard_80387_constant_p (operands[1]) > 0)
3529169699Skan	{
3530169699Skan	  operands[1] = simplify_const_unary_operation
3531169699Skan	    (FLOAT_EXTEND, DFmode, operands[1], SFmode);
3532169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3533169699Skan	  DONE;
3534169699Skan	}
3535169699Skan      operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
3536169699Skan    }
353790286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
353890286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
353990286Sobrien})
354018334Speter
3541169699Skan(define_insn "*extendsfdf2_mixed"
3542169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y")
3543169699Skan        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))]
3544169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387
354590286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
354652296Sobrien{
354790286Sobrien  switch (which_alternative)
354890286Sobrien    {
354990286Sobrien    case 0:
3550169699Skan      return output_387_reg_move (insn, operands);
355152296Sobrien
355290286Sobrien    case 1:
355390286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
355490286Sobrien        return "fstp%z0\t%y0";
355590286Sobrien      else
355690286Sobrien        return "fst%z0\t%y0";
3557169699Skan
355890286Sobrien    case 2:
355990286Sobrien      return "cvtss2sd\t{%1, %0|%0, %1}";
356018334Speter
356190286Sobrien    default:
3562169699Skan      gcc_unreachable ();
356390286Sobrien    }
356490286Sobrien}
3565117404Skan  [(set_attr "type" "fmov,fmov,ssecvt")
356690286Sobrien   (set_attr "mode" "SF,XF,DF")])
356718334Speter
3568169699Skan(define_insn "*extendsfdf2_sse"
3569169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y")
357090286Sobrien        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "mY")))]
3571169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
357290286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
357390286Sobrien  "cvtss2sd\t{%1, %0|%0, %1}"
3574117404Skan  [(set_attr "type" "ssecvt")
357590286Sobrien   (set_attr "mode" "DF")])
357618334Speter
3577169699Skan(define_insn "*extendsfdf2_i387"
3578169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
3579169699Skan        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
3580169699Skan  "TARGET_80387
3581169699Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
3582169699Skan{
3583169699Skan  switch (which_alternative)
3584169699Skan    {
3585169699Skan    case 0:
3586169699Skan      return output_387_reg_move (insn, operands);
3587169699Skan
3588169699Skan    case 1:
3589169699Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3590169699Skan        return "fstp%z0\t%y0";
3591169699Skan      else
3592169699Skan        return "fst%z0\t%y0";
3593169699Skan
3594169699Skan    default:
3595169699Skan      gcc_unreachable ();
3596169699Skan    }
3597169699Skan}
3598169699Skan  [(set_attr "type" "fmov")
3599169699Skan   (set_attr "mode" "SF,XF")])
3600169699Skan
360190286Sobrien(define_expand "extendsfxf2"
360252296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
3603117404Skan        (float_extend:XF (match_operand:SF 1 "general_operand" "")))]
3604132727Skan  "TARGET_80387"
360590286Sobrien{
3606117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3607117404Skan     are LEGITIMATE_CONSTANT_P.  */
3608117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3609169699Skan    {
3610169699Skan      if (standard_80387_constant_p (operands[1]) > 0)
3611169699Skan	{
3612169699Skan	  operands[1] = simplify_const_unary_operation
3613169699Skan	    (FLOAT_EXTEND, XFmode, operands[1], SFmode);
3614169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3615169699Skan	  DONE;
3616169699Skan	}
3617169699Skan      operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
3618169699Skan    }
361990286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
362090286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
362190286Sobrien})
362218334Speter
3623169699Skan(define_insn "*extendsfxf2_i387"
362452296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
362590286Sobrien        (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
362690286Sobrien  "TARGET_80387
362790286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
362818334Speter{
362990286Sobrien  switch (which_alternative)
363090286Sobrien    {
363190286Sobrien    case 0:
3632169699Skan      return output_387_reg_move (insn, operands);
363318334Speter
363490286Sobrien    case 1:
363590286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
363690286Sobrien	 we need one, follow the store with a load.  */
3637169699Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3638169699Skan        return "fstp%z0\t%y0";
3639169699Skan      else
364090286Sobrien        return "fstp%z0\t%y0\n\tfld%z0\t%y0";
364118334Speter
364290286Sobrien    default:
3643169699Skan      gcc_unreachable ();
364490286Sobrien    }
364590286Sobrien}
364690286Sobrien  [(set_attr "type" "fmov")
364790286Sobrien   (set_attr "mode" "SF,XF")])
364818334Speter
364990286Sobrien(define_expand "extenddfxf2"
365052296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
3651117404Skan        (float_extend:XF (match_operand:DF 1 "general_operand" "")))]
3652132727Skan  "TARGET_80387"
365390286Sobrien{
3654117404Skan  /* ??? Needed for compress_float_constant since all fp constants
3655117404Skan     are LEGITIMATE_CONSTANT_P.  */
3656117404Skan  if (GET_CODE (operands[1]) == CONST_DOUBLE)
3657169699Skan    {
3658169699Skan      if (standard_80387_constant_p (operands[1]) > 0)
3659169699Skan	{
3660169699Skan	  operands[1] = simplify_const_unary_operation
3661169699Skan	    (FLOAT_EXTEND, XFmode, operands[1], DFmode);
3662169699Skan	  emit_move_insn_1 (operands[0], operands[1]);
3663169699Skan	  DONE;
3664169699Skan	}
3665169699Skan      operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
3666169699Skan    }
366790286Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
366890286Sobrien    operands[1] = force_reg (DFmode, operands[1]);
366990286Sobrien})
367018334Speter
3671169699Skan(define_insn "*extenddfxf2_i387"
367252296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
367390286Sobrien        (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
367490286Sobrien  "TARGET_80387
367590286Sobrien   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
367690286Sobrien{
367790286Sobrien  switch (which_alternative)
367890286Sobrien    {
367990286Sobrien    case 0:
3680169699Skan      return output_387_reg_move (insn, operands);
368190286Sobrien
368290286Sobrien    case 1:
368390286Sobrien      /* There is no non-popping store to memory for XFmode.  So if
368490286Sobrien	 we need one, follow the store with a load.  */
368590286Sobrien      if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
368690286Sobrien        return "fstp%z0\t%y0\n\tfld%z0\t%y0";
368790286Sobrien      else
368890286Sobrien        return "fstp%z0\t%y0";
368990286Sobrien
369090286Sobrien    default:
3691169699Skan      gcc_unreachable ();
369290286Sobrien    }
369390286Sobrien}
369490286Sobrien  [(set_attr "type" "fmov")
369590286Sobrien   (set_attr "mode" "DF,XF")])
369690286Sobrien
369790286Sobrien;; %%% This seems bad bad news.
369890286Sobrien;; This cannot output into an f-reg because there is no way to be sure
369990286Sobrien;; of truncating in that case.  Otherwise this is just like a simple move
370090286Sobrien;; insn.  So we pretend we can output to a reg in order to get better
370190286Sobrien;; register preferencing, but we really use a stack slot.
370290286Sobrien
3703169699Skan;; Conversion from DFmode to SFmode.
3704169699Skan
370518334Speter(define_expand "truncdfsf2"
3706169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
370790286Sobrien	(float_truncate:SF
3708169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "")))]
3709169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
371018334Speter{
3711169699Skan  if (MEM_P (operands[0]) && MEM_P (operands[1]))
3712169699Skan    operands[1] = force_reg (DFmode, operands[1]);
3713169699Skan
3714169699Skan  if (TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_MIX_SSE_I387)
3715169699Skan    ;
3716169699Skan  else if (flag_unsafe_math_optimizations)
3717169699Skan    ;
3718169699Skan  else
371990286Sobrien    {
3720171835Skan      rtx temp = assign_386_stack_local (SFmode, SLOT_VIRTUAL);
3721169699Skan      emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
3722169699Skan      DONE;
372390286Sobrien    }
3724169699Skan})
372518334Speter
3726169699Skan(define_expand "truncdfsf2_with_temp"
3727169699Skan  [(parallel [(set (match_operand:SF 0 "" "")
3728169699Skan		   (float_truncate:SF (match_operand:DF 1 "" "")))
3729169699Skan	      (clobber (match_operand:SF 2 "" ""))])]
3730169699Skan  "")
3731169699Skan
3732169699Skan(define_insn "*truncdfsf_fast_mixed"
3733169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,f,Y")
3734169699Skan        (float_truncate:SF
3735169699Skan          (match_operand:DF 1 "nonimmediate_operand" "f ,f,Ym")))]
3736169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387 && flag_unsafe_math_optimizations"
373718334Speter{
373890286Sobrien  switch (which_alternative)
373990286Sobrien    {
374090286Sobrien    case 0:
374190286Sobrien      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
374290286Sobrien	return "fstp%z0\t%y0";
374390286Sobrien      else
374490286Sobrien	return "fst%z0\t%y0";
3745169699Skan    case 1:
3746169699Skan      return output_387_reg_move (insn, operands);
3747169699Skan    case 2:
3748169699Skan      return "cvtsd2ss\t{%1, %0|%0, %1}";
374990286Sobrien    default:
3750169699Skan      gcc_unreachable ();
375190286Sobrien    }
375290286Sobrien}
3753169699Skan  [(set_attr "type" "fmov,fmov,ssecvt")
3754169699Skan   (set_attr "mode" "SF")])
375518334Speter
3756169699Skan;; Yes, this one doesn't depend on flag_unsafe_math_optimizations,
3757169699Skan;; because nothing we do here is unsafe.
3758169699Skan(define_insn "*truncdfsf_fast_sse"
3759169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=Y")
3760169699Skan        (float_truncate:SF
3761169699Skan          (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
3762169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
3763169699Skan  "cvtsd2ss\t{%1, %0|%0, %1}"
3764169699Skan  [(set_attr "type" "ssecvt")
3765169699Skan   (set_attr "mode" "SF")])
3766169699Skan
3767169699Skan(define_insn "*truncdfsf_fast_i387"
3768169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=fm")
3769169699Skan        (float_truncate:SF
3770169699Skan          (match_operand:DF 1 "nonimmediate_operand" "f")))]
3771169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3772169699Skan  "* return output_387_reg_move (insn, operands);"
3773169699Skan  [(set_attr "type" "fmov")
3774169699Skan   (set_attr "mode" "SF")])
3775169699Skan
3776169699Skan(define_insn "*truncdfsf_mixed"
3777169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,?fx*r,Y")
3778132727Skan	(float_truncate:SF
3779169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "f ,f    ,Ym")))
3780169699Skan   (clobber (match_operand:SF 2 "memory_operand"     "=X,m    ,X"))]
3781169699Skan  "TARGET_MIX_SSE_I387"
3782132727Skan{
3783132727Skan  switch (which_alternative)
3784132727Skan    {
3785132727Skan    case 0:
3786132727Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3787132727Skan	return "fstp%z0\t%y0";
3788132727Skan      else
3789132727Skan	return "fst%z0\t%y0";
3790169699Skan    case 1:
3791132727Skan      return "#";
3792169699Skan    case 2:
3793169699Skan      return "cvtsd2ss\t{%1, %0|%0, %1}";
3794132727Skan    default:
3795169699Skan      gcc_unreachable ();
3796132727Skan    }
3797132727Skan}
3798169699Skan  [(set_attr "type" "fmov,multi,ssecvt")
3799169699Skan   (set_attr "unit" "*,i387,*")
3800169699Skan   (set_attr "mode" "SF")])
3801132727Skan
3802169699Skan(define_insn "*truncdfsf_i387"
3803169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r")
380490286Sobrien	(float_truncate:SF
3805169699Skan	  (match_operand:DF 1 "nonimmediate_operand" "f,f")))
3806169699Skan   (clobber (match_operand:SF 2 "memory_operand" "=X,m"))]
3807169699Skan  "TARGET_80387"
3808132727Skan{
3809132727Skan  switch (which_alternative)
3810132727Skan    {
3811132727Skan    case 0:
3812132727Skan      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3813132727Skan	return "fstp%z0\t%y0";
3814132727Skan      else
3815132727Skan	return "fst%z0\t%y0";
3816169699Skan    case 1:
3817132727Skan      return "#";
381890286Sobrien    default:
3819169699Skan      gcc_unreachable ();
382090286Sobrien    }
382190286Sobrien}
3822169699Skan  [(set_attr "type" "fmov,multi")
3823169699Skan   (set_attr "unit" "*,i387")
3824169699Skan   (set_attr "mode" "SF")])
382552296Sobrien
3826169699Skan(define_insn "*truncdfsf2_i387_1"
382790286Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
382890286Sobrien	(float_truncate:SF
3829169699Skan	  (match_operand:DF 1 "register_operand" "f")))]
3830169699Skan  "TARGET_80387
3831169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)
3832169699Skan   && !TARGET_MIX_SSE_I387"
383390286Sobrien{
383490286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
383590286Sobrien    return "fstp%z0\t%y0";
383618334Speter  else
383790286Sobrien    return "fst%z0\t%y0";
383890286Sobrien}
383990286Sobrien  [(set_attr "type" "fmov")
384090286Sobrien   (set_attr "mode" "SF")])
384118334Speter
384252296Sobrien(define_split
3843132727Skan  [(set (match_operand:SF 0 "register_operand" "")
384490286Sobrien	(float_truncate:SF
3845169699Skan	 (match_operand:DF 1 "fp_register_operand" "")))
384690286Sobrien   (clobber (match_operand 2 "" ""))]
3847169699Skan  "reload_completed"
3848169699Skan  [(set (match_dup 2) (match_dup 1))
3849169699Skan   (set (match_dup 0) (match_dup 2))]
3850132727Skan{
3851169699Skan  operands[1] = gen_rtx_REG (SFmode, true_regnum (operands[1]));
3852132727Skan})
385390286Sobrien
3854169699Skan;; Conversion from XFmode to SFmode.
3855132727Skan
385690286Sobrien(define_expand "truncxfsf2"
385790286Sobrien  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
385890286Sobrien		   (float_truncate:SF
385990286Sobrien		    (match_operand:XF 1 "register_operand" "")))
386090286Sobrien	      (clobber (match_dup 2))])]
3861132727Skan  "TARGET_80387"
3862169699Skan{
3863169699Skan  if (flag_unsafe_math_optimizations)
3864169699Skan    {
3865169699Skan      rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SFmode);
3866169699Skan      emit_insn (gen_truncxfsf2_i387_noop (reg, operands[1]));
3867169699Skan      if (reg != operands[0])
3868169699Skan	emit_move_insn (operands[0], reg);
3869169699Skan      DONE;
3870169699Skan    }
3871169699Skan  else
3872171835Skan    operands[2] = assign_386_stack_local (SFmode, SLOT_VIRTUAL);
3873169699Skan})
387452296Sobrien
3875169699Skan(define_insn "*truncxfsf2_mixed"
3876169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x")
387790286Sobrien	(float_truncate:SF
387890286Sobrien	 (match_operand:XF 1 "register_operand" "f,f,f,f")))
387990286Sobrien   (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
3880169699Skan  "TARGET_MIX_SSE_I387"
388190286Sobrien{
3882169699Skan  gcc_assert (!which_alternative);
3883169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3884169699Skan    return "fstp%z0\t%y0";
3885169699Skan  else
3886169699Skan    return "fst%z0\t%y0";
388790286Sobrien}
388890286Sobrien  [(set_attr "type" "fmov,multi,multi,multi")
3889169699Skan   (set_attr "unit" "*,i387,i387,i387")
389090286Sobrien   (set_attr "mode" "SF")])
389190286Sobrien
3892169699Skan(define_insn "truncxfsf2_i387_noop"
3893169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
3894169699Skan	(float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
3895169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3896169699Skan{
3897169699Skan  return output_387_reg_move (insn, operands);
3898169699Skan}
3899169699Skan  [(set_attr "type" "fmov")
3900169699Skan   (set_attr "mode" "SF")])
3901169699Skan
3902169699Skan(define_insn "*truncxfsf2_i387"
3903169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r")
3904169699Skan	(float_truncate:SF
3905169699Skan	 (match_operand:XF 1 "register_operand" "f,f,f")))
3906169699Skan   (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
3907169699Skan  "TARGET_80387"
3908169699Skan{
3909169699Skan  gcc_assert (!which_alternative);
3910169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3911169699Skan    return "fstp%z0\t%y0";
3912169699Skan   else
3913169699Skan     return "fst%z0\t%y0";
3914169699Skan}
3915169699Skan  [(set_attr "type" "fmov,multi,multi")
3916169699Skan   (set_attr "unit" "*,i387,i387")
3917169699Skan   (set_attr "mode" "SF")])
3918169699Skan
3919169699Skan(define_insn "*truncxfsf2_i387_1"
392052296Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
392190286Sobrien	(float_truncate:SF
392290286Sobrien	 (match_operand:XF 1 "register_operand" "f")))]
3923132727Skan  "TARGET_80387"
392418334Speter{
392590286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
392690286Sobrien    return "fstp%z0\t%y0";
392718334Speter  else
392890286Sobrien    return "fst%z0\t%y0";
392990286Sobrien}
393090286Sobrien  [(set_attr "type" "fmov")
393190286Sobrien   (set_attr "mode" "SF")])
393252296Sobrien
393390286Sobrien(define_split
3934169699Skan  [(set (match_operand:SF 0 "register_operand" "")
393590286Sobrien	(float_truncate:SF
393690286Sobrien	 (match_operand:XF 1 "register_operand" "")))
393790286Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
3938169699Skan  "TARGET_80387 && reload_completed"
3939169699Skan  [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
3940169699Skan   (set (match_dup 0) (match_dup 2))]
394190286Sobrien  "")
394290286Sobrien
394390286Sobrien(define_split
3944169699Skan  [(set (match_operand:SF 0 "memory_operand" "")
394590286Sobrien	(float_truncate:SF
394690286Sobrien	 (match_operand:XF 1 "register_operand" "")))
394790286Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
3948169699Skan  "TARGET_80387"
3949169699Skan  [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
395090286Sobrien  "")
395190286Sobrien
3952169699Skan;; Conversion from XFmode to DFmode.
3953169699Skan
395452296Sobrien(define_expand "truncxfdf2"
395552296Sobrien  [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
395652296Sobrien		   (float_truncate:DF
395752296Sobrien		    (match_operand:XF 1 "register_operand" "")))
395852296Sobrien	      (clobber (match_dup 2))])]
3959132727Skan  "TARGET_80387"
3960169699Skan{
3961169699Skan  if (flag_unsafe_math_optimizations)
3962169699Skan    {
3963169699Skan      rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DFmode);
3964169699Skan      emit_insn (gen_truncxfdf2_i387_noop (reg, operands[1]));
3965169699Skan      if (reg != operands[0])
3966169699Skan	emit_move_insn (operands[0], reg);
3967169699Skan      DONE;
3968169699Skan    }
3969169699Skan  else
3970171835Skan    operands[2] = assign_386_stack_local (DFmode, SLOT_VIRTUAL);
3971169699Skan})
397218334Speter
3973169699Skan(define_insn "*truncxfdf2_mixed"
3974169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y")
397552296Sobrien	(float_truncate:DF
397690286Sobrien	 (match_operand:XF 1 "register_operand" "f,f,f,f")))
397790286Sobrien   (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
3978169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387"
397918334Speter{
3980169699Skan  gcc_assert (!which_alternative);
3981169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3982169699Skan    return "fstp%z0\t%y0";
3983169699Skan  else
3984169699Skan    return "fst%z0\t%y0";
398590286Sobrien}
398690286Sobrien  [(set_attr "type" "fmov,multi,multi,multi")
3987169699Skan   (set_attr "unit" "*,i387,i387,i387")
398890286Sobrien   (set_attr "mode" "DF")])
398952296Sobrien
3990169699Skan(define_insn "truncxfdf2_i387_noop"
3991169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
3992169699Skan	(float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
3993169699Skan  "TARGET_80387 && flag_unsafe_math_optimizations"
3994169699Skan{
3995169699Skan  return output_387_reg_move (insn, operands);
3996169699Skan}
3997169699Skan  [(set_attr "type" "fmov")
3998169699Skan   (set_attr "mode" "DF")])
3999169699Skan
4000169699Skan(define_insn "*truncxfdf2_i387"
4001169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r")
4002169699Skan	(float_truncate:DF
4003169699Skan	 (match_operand:XF 1 "register_operand" "f,f,f")))
4004169699Skan   (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
4005169699Skan  "TARGET_80387"
4006169699Skan{
4007169699Skan  gcc_assert (!which_alternative);
4008169699Skan  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
4009169699Skan    return "fstp%z0\t%y0";
4010169699Skan  else
4011169699Skan    return "fst%z0\t%y0";
4012169699Skan}
4013169699Skan  [(set_attr "type" "fmov,multi,multi")
4014169699Skan   (set_attr "unit" "*,i387,i387")
4015169699Skan   (set_attr "mode" "DF")])
4016169699Skan
4017169699Skan(define_insn "*truncxfdf2_i387_1"
401890286Sobrien  [(set (match_operand:DF 0 "memory_operand" "=m")
401990286Sobrien	(float_truncate:DF
402090286Sobrien	  (match_operand:XF 1 "register_operand" "f")))]
4021132727Skan  "TARGET_80387"
402290286Sobrien{
402390286Sobrien  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
402490286Sobrien    return "fstp%z0\t%y0";
402590286Sobrien  else
402690286Sobrien    return "fst%z0\t%y0";
402790286Sobrien}
402890286Sobrien  [(set_attr "type" "fmov")
402990286Sobrien   (set_attr "mode" "DF")])
403052296Sobrien
403152296Sobrien(define_split
4032169699Skan  [(set (match_operand:DF 0 "register_operand" "")
403390286Sobrien	(float_truncate:DF
403490286Sobrien	 (match_operand:XF 1 "register_operand" "")))
403552296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
4036169699Skan  "TARGET_80387 && reload_completed"
4037169699Skan  [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
4038169699Skan   (set (match_dup 0) (match_dup 2))]
403952296Sobrien  "")
404052296Sobrien
404152296Sobrien(define_split
4042169699Skan  [(set (match_operand:DF 0 "memory_operand" "")
404390286Sobrien	(float_truncate:DF
404490286Sobrien	 (match_operand:XF 1 "register_operand" "")))
404552296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
4046169699Skan  "TARGET_80387"
4047169699Skan  [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
404852296Sobrien  "")
404990286Sobrien
405090286Sobrien;; Signed conversion to DImode.
405190286Sobrien
405290286Sobrien(define_expand "fix_truncxfdi2"
4053169699Skan  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4054169699Skan                   (fix:DI (match_operand:XF 1 "register_operand" "")))
4055169699Skan	      (clobber (reg:CC FLAGS_REG))])]
405618334Speter  "TARGET_80387"
405718334Speter{
4058169699Skan  if (TARGET_FISTTP)
405990286Sobrien   {
4060169699Skan     emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
406190286Sobrien     DONE;
406290286Sobrien   }
406390286Sobrien})
406418334Speter
4065169699Skan(define_expand "fix_trunc<mode>di2"
4066169699Skan  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4067169699Skan                   (fix:DI (match_operand:SSEMODEF 1 "register_operand" "")))
4068169699Skan              (clobber (reg:CC FLAGS_REG))])]
4069169699Skan  "TARGET_80387 || (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))"
407090286Sobrien{
4071169699Skan  if (TARGET_FISTTP
4072169699Skan      && !(TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
407390286Sobrien   {
4074169699Skan     emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
4075169699Skan     DONE;
4076169699Skan   }
4077169699Skan  if (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))
4078169699Skan   {
407990286Sobrien     rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
4080169699Skan     emit_insn (gen_fix_trunc<mode>di_sse (out, operands[1]));
408190286Sobrien     if (out != operands[0])
408290286Sobrien	emit_move_insn (operands[0], out);
408390286Sobrien     DONE;
408490286Sobrien   }
408590286Sobrien})
408652296Sobrien
408790286Sobrien;; Signed conversion to SImode.
408890286Sobrien
408952296Sobrien(define_expand "fix_truncxfsi2"
4090169699Skan  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
4091169699Skan                   (fix:SI (match_operand:XF 1 "register_operand" "")))
4092169699Skan	      (clobber (reg:CC FLAGS_REG))])]
409318334Speter  "TARGET_80387"
409418334Speter{
4095169699Skan  if (TARGET_FISTTP)
409690286Sobrien   {
4097169699Skan     emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
409890286Sobrien     DONE;
409990286Sobrien   }
410090286Sobrien})
410118334Speter
4102169699Skan(define_expand "fix_trunc<mode>si2"
4103169699Skan  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
4104169699Skan	           (fix:SI (match_operand:SSEMODEF 1 "register_operand" "")))
4105169699Skan	      (clobber (reg:CC FLAGS_REG))])]
4106169699Skan  "TARGET_80387 || SSE_FLOAT_MODE_P (<MODE>mode)"
410790286Sobrien{
4108169699Skan  if (TARGET_FISTTP
4109169699Skan      && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
411090286Sobrien   {
4111169699Skan     emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
4112169699Skan     DONE;
4113169699Skan   }
4114169699Skan  if (SSE_FLOAT_MODE_P (<MODE>mode))
4115169699Skan   {
411690286Sobrien     rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
4117169699Skan     emit_insn (gen_fix_trunc<mode>si_sse (out, operands[1]));
411890286Sobrien     if (out != operands[0])
411990286Sobrien	emit_move_insn (operands[0], out);
412090286Sobrien     DONE;
412190286Sobrien   }
412290286Sobrien})
412352296Sobrien
4124169699Skan;; Signed conversion to HImode.
4125169699Skan
4126169699Skan(define_expand "fix_trunc<mode>hi2"
4127169699Skan  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
4128169699Skan	           (fix:HI (match_operand:X87MODEF 1 "register_operand" "")))
4129169699Skan              (clobber (reg:CC FLAGS_REG))])]
4130169699Skan  "TARGET_80387
4131169699Skan   && !(SSE_FLOAT_MODE_P (<MODE>mode) && (!TARGET_FISTTP || TARGET_SSE_MATH))"
413218334Speter{
4133169699Skan  if (TARGET_FISTTP)
4134169699Skan   {
4135169699Skan     emit_insn (gen_fix_trunchi_fisttp_i387_1 (operands[0], operands[1]));
4136169699Skan     DONE;
4137169699Skan   }
4138169699Skan})
413918334Speter
4140169699Skan;; When SSE is available, it is always faster to use it!
4141169699Skan(define_insn "fix_truncsfdi_sse"
4142169699Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
4143169699Skan	(fix:DI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
4144169699Skan  "TARGET_64BIT && TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
4145169699Skan  "cvttss2si{q}\t{%1, %0|%0, %1}"
4146169699Skan  [(set_attr "type" "sseicvt")
4147169699Skan   (set_attr "mode" "SF")
4148169699Skan   (set_attr "athlon_decode" "double,vector")])
414990286Sobrien
4150169699Skan(define_insn "fix_truncdfdi_sse"
4151169699Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
4152169699Skan	(fix:DI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
4153169699Skan  "TARGET_64BIT && TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
4154169699Skan  "cvttsd2si{q}\t{%1, %0|%0, %1}"
4155169699Skan  [(set_attr "type" "sseicvt")
4156169699Skan   (set_attr "mode" "DF")
4157169699Skan   (set_attr "athlon_decode" "double,vector")])
415818334Speter
415990286Sobrien(define_insn "fix_truncsfsi_sse"
4160132727Skan  [(set (match_operand:SI 0 "register_operand" "=r,r")
4161132727Skan	(fix:SI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
4162169699Skan  "TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
416390286Sobrien  "cvttss2si\t{%1, %0|%0, %1}"
4164132727Skan  [(set_attr "type" "sseicvt")
4165132727Skan   (set_attr "mode" "DF")
4166132727Skan   (set_attr "athlon_decode" "double,vector")])
416752296Sobrien
416890286Sobrien(define_insn "fix_truncdfsi_sse"
4169132727Skan  [(set (match_operand:SI 0 "register_operand" "=r,r")
4170132727Skan	(fix:SI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
4171169699Skan  "TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
417290286Sobrien  "cvttsd2si\t{%1, %0|%0, %1}"
4173132727Skan  [(set_attr "type" "sseicvt")
4174132727Skan   (set_attr "mode" "DF")
4175132727Skan   (set_attr "athlon_decode" "double,vector")])
417652296Sobrien
4177169699Skan;; Avoid vector decoded forms of the instruction.
4178132727Skan(define_peephole2
4179132727Skan  [(match_scratch:DF 2 "Y")
4180169699Skan   (set (match_operand:SSEMODEI24 0 "register_operand" "")
4181169699Skan	(fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))]
4182169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
4183132727Skan  [(set (match_dup 2) (match_dup 1))
4184169699Skan   (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
4185132727Skan  "")
4186132727Skan
4187169699Skan(define_peephole2
4188169699Skan  [(match_scratch:SF 2 "x")
4189169699Skan   (set (match_operand:SSEMODEI24 0 "register_operand" "")
4190169699Skan	(fix:SSEMODEI24 (match_operand:SF 1 "memory_operand" "")))]
4191169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
4192169699Skan  [(set (match_dup 2) (match_dup 1))
4193169699Skan   (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
419490286Sobrien  "")
419518334Speter
4196169699Skan(define_insn_and_split "fix_trunc<mode>_fisttp_i387_1"
4197169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4198169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))]
4199169699Skan  "TARGET_FISTTP
4200169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4201169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4202169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4203169699Skan	&& TARGET_SSE_MATH)
4204169699Skan   && !(reload_completed || reload_in_progress)"
4205169699Skan  "#"
4206169699Skan  "&& 1"
4207169699Skan  [(const_int 0)]
4208169699Skan{
4209169699Skan  if (memory_operand (operands[0], VOIDmode))
4210169699Skan    emit_insn (gen_fix_trunc<mode>_i387_fisttp (operands[0], operands[1]));
4211169699Skan  else
4212169699Skan    {
4213169699Skan      operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
4214169699Skan      emit_insn (gen_fix_trunc<mode>_i387_fisttp_with_temp (operands[0],
4215169699Skan							    operands[1],
4216169699Skan							    operands[2]));
4217169699Skan    }
4218169699Skan  DONE;
4219169699Skan}
4220169699Skan  [(set_attr "type" "fisttp")
4221169699Skan   (set_attr "mode" "<MODE>")])
422252296Sobrien
4223169699Skan(define_insn "fix_trunc<mode>_i387_fisttp"
4224169699Skan  [(set (match_operand:X87MODEI 0 "memory_operand" "=m")
4225169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f")))
4226169699Skan   (clobber (match_scratch:XF 2 "=&1f"))]
4227169699Skan  "TARGET_FISTTP
4228169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4229169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4230169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4231169699Skan	&& TARGET_SSE_MATH)"
4232169699Skan  "* return output_fix_trunc (insn, operands, 1);"
4233169699Skan  [(set_attr "type" "fisttp")
4234169699Skan   (set_attr "mode" "<MODE>")])
423590286Sobrien
4236169699Skan(define_insn "fix_trunc<mode>_i387_fisttp_with_temp"
4237169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4238169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
4239169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" "=m,m"))
4240169699Skan   (clobber (match_scratch:XF 3 "=&1f,&1f"))]
4241169699Skan  "TARGET_FISTTP
4242169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4243169699Skan   && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4244169699Skan	&& (TARGET_64BIT || <MODE>mode != DImode))
4245169699Skan	&& TARGET_SSE_MATH)"
4246169699Skan  "#"
4247169699Skan  [(set_attr "type" "fisttp")
4248169699Skan   (set_attr "mode" "<MODE>")])
424918334Speter
4250169699Skan(define_split
4251169699Skan  [(set (match_operand:X87MODEI 0 "register_operand" "")
4252169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "")))
4253169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
4254169699Skan   (clobber (match_scratch 3 ""))]
4255169699Skan  "reload_completed"
4256169699Skan  [(parallel [(set (match_dup 2) (fix:X87MODEI (match_dup 1)))
4257169699Skan	      (clobber (match_dup 3))])
4258169699Skan   (set (match_dup 0) (match_dup 2))]
425990286Sobrien  "")
426018334Speter
4261169699Skan(define_split
4262169699Skan  [(set (match_operand:X87MODEI 0 "memory_operand" "")
4263169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "")))
4264169699Skan   (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
4265169699Skan   (clobber (match_scratch 3 ""))]
4266169699Skan  "reload_completed"
4267169699Skan  [(parallel [(set (match_dup 0) (fix:X87MODEI (match_dup 1)))
4268169699Skan	      (clobber (match_dup 3))])]
426990286Sobrien  "")
427052296Sobrien
427190286Sobrien;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
4272169699Skan;; of the machinery. Please note the clobber of FLAGS_REG. In i387 control
4273169699Skan;; word calculation (inserted by LCM in mode switching pass) a FLAGS_REG
4274169699Skan;; clobbering insns can be used. Look at emit_i387_cw_initialization ()
4275169699Skan;; function in i386.c.
4276169699Skan(define_insn_and_split "*fix_trunc<mode>_i387_1"
4277169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
4278169699Skan	(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
4279169699Skan   (clobber (reg:CC FLAGS_REG))]
4280169699Skan  "TARGET_80387 && !TARGET_FISTTP
4281169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4282169699Skan   && !(SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
4283169699Skan	 && (TARGET_64BIT || <MODE>mode != DImode))
4284169699Skan   && !(reload_completed || reload_in_progress)"
428590286Sobrien  "#"
4286169699Skan  "&& 1"
428790286Sobrien  [(const_int 0)]
428890286Sobrien{
4289169699Skan  ix86_optimize_mode_switching[I387_TRUNC] = 1;
4290169699Skan
4291169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
4292169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
429390286Sobrien  if (memory_operand (operands[0], VOIDmode))
4294169699Skan    emit_insn (gen_fix_trunc<mode>_i387 (operands[0], operands[1],
4295169699Skan					 operands[2], operands[3]));
429690286Sobrien  else
429790286Sobrien    {
4298169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
4299169699Skan      emit_insn (gen_fix_trunc<mode>_i387_with_temp (operands[0], operands[1],
4300169699Skan						     operands[2], operands[3],
4301169699Skan						     operands[4]));
430290286Sobrien    }
430390286Sobrien  DONE;
430490286Sobrien}
4305132727Skan  [(set_attr "type" "fistp")
4306169699Skan   (set_attr "i387_cw" "trunc")
4307169699Skan   (set_attr "mode" "<MODE>")])
430890286Sobrien
4309169699Skan(define_insn "fix_truncdi_i387"
4310169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
4311169699Skan	(fix:DI (match_operand 1 "register_operand" "f")))
4312169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
4313169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
4314169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
4315169699Skan  "TARGET_80387 && !TARGET_FISTTP
4316169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4317169699Skan   && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
4318169699Skan  "* return output_fix_trunc (insn, operands, 0);"
4319169699Skan  [(set_attr "type" "fistp")
4320169699Skan   (set_attr "i387_cw" "trunc")
4321169699Skan   (set_attr "mode" "DI")])
4322169699Skan
4323169699Skan(define_insn "fix_truncdi_i387_with_temp"
4324169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
4325169699Skan	(fix:DI (match_operand 1 "register_operand" "f,f")))
432690286Sobrien   (use (match_operand:HI 2 "memory_operand" "m,m"))
432790286Sobrien   (use (match_operand:HI 3 "memory_operand" "m,m"))
4328169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
4329169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
4330169699Skan  "TARGET_80387 && !TARGET_FISTTP
4331169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4332169699Skan   && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
433390286Sobrien  "#"
4334132727Skan  [(set_attr "type" "fistp")
4335169699Skan   (set_attr "i387_cw" "trunc")
4336169699Skan   (set_attr "mode" "DI")])
433790286Sobrien
4338169699Skan(define_split 
4339169699Skan  [(set (match_operand:DI 0 "register_operand" "")
4340169699Skan	(fix:DI (match_operand 1 "register_operand" "")))
4341169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
4342169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
4343169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
4344169699Skan   (clobber (match_scratch 5 ""))]
4345169699Skan  "reload_completed"
4346169699Skan  [(parallel [(set (match_dup 4) (fix:DI (match_dup 1)))
4347169699Skan	      (use (match_dup 2))
4348169699Skan	      (use (match_dup 3))
4349169699Skan	      (clobber (match_dup 5))])
4350169699Skan   (set (match_dup 0) (match_dup 4))]
4351169699Skan  "")
4352169699Skan
4353169699Skan(define_split 
4354169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
4355169699Skan	(fix:DI (match_operand 1 "register_operand" "")))
4356169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
4357169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
4358169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
4359169699Skan   (clobber (match_scratch 5 ""))]
4360169699Skan  "reload_completed"
4361169699Skan  [(parallel [(set (match_dup 0) (fix:DI (match_dup 1)))
4362169699Skan	      (use (match_dup 2))
4363169699Skan	      (use (match_dup 3))
4364169699Skan	      (clobber (match_dup 5))])]
4365169699Skan  "")
4366169699Skan
4367169699Skan(define_insn "fix_trunc<mode>_i387"
4368169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
4369169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "f")))
437090286Sobrien   (use (match_operand:HI 2 "memory_operand" "m"))
437190286Sobrien   (use (match_operand:HI 3 "memory_operand" "m"))]
4372169699Skan  "TARGET_80387 && !TARGET_FISTTP
4373169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
437490286Sobrien   && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
4375169699Skan  "* return output_fix_trunc (insn, operands, 0);"
4376132727Skan  [(set_attr "type" "fistp")
4377169699Skan   (set_attr "i387_cw" "trunc")
4378169699Skan   (set_attr "mode" "<MODE>")])
437990286Sobrien
4380169699Skan(define_insn "fix_trunc<mode>_i387_with_temp"
4381169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
4382169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "f,f")))
4383169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
4384169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
4385169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
4386169699Skan  "TARGET_80387 && !TARGET_FISTTP
4387169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
4388169699Skan   && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
4389169699Skan  "#"
4390169699Skan  [(set_attr "type" "fistp")
4391169699Skan   (set_attr "i387_cw" "trunc")
4392169699Skan   (set_attr "mode" "<MODE>")])
4393169699Skan
439490286Sobrien(define_split 
4395169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
4396169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
439790286Sobrien   (use (match_operand:HI 2 "memory_operand" ""))
439890286Sobrien   (use (match_operand:HI 3 "memory_operand" ""))
4399169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
440090286Sobrien  "reload_completed"
4401169699Skan  [(parallel [(set (match_dup 4) (fix:X87MODEI12 (match_dup 1)))
440290286Sobrien	      (use (match_dup 2))
4403169699Skan	      (use (match_dup 3))])
4404169699Skan   (set (match_dup 0) (match_dup 4))]
440518334Speter  "")
440618334Speter
440790286Sobrien(define_split 
4408169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
4409169699Skan	(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
441090286Sobrien   (use (match_operand:HI 2 "memory_operand" ""))
441190286Sobrien   (use (match_operand:HI 3 "memory_operand" ""))
4412169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
441390286Sobrien  "reload_completed"
4414169699Skan  [(parallel [(set (match_dup 0) (fix:X87MODEI12 (match_dup 1)))
441590286Sobrien	      (use (match_dup 2))
4416169699Skan	      (use (match_dup 3))])]
441752296Sobrien  "")
441852296Sobrien
441990286Sobrien(define_insn "x86_fnstcw_1"
442090286Sobrien  [(set (match_operand:HI 0 "memory_operand" "=m")
4421169699Skan	(unspec:HI [(reg:HI FPSR_REG)] UNSPEC_FSTCW))]
442252296Sobrien  "TARGET_80387"
442390286Sobrien  "fnstcw\t%0"
442490286Sobrien  [(set_attr "length" "2")
442590286Sobrien   (set_attr "mode" "HI")
4426169699Skan   (set_attr "unit" "i387")])
442752296Sobrien
442890286Sobrien(define_insn "x86_fldcw_1"
4429169699Skan  [(set (reg:HI FPSR_REG)
4430117404Skan	(unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))]
443152296Sobrien  "TARGET_80387"
443290286Sobrien  "fldcw\t%0"
443390286Sobrien  [(set_attr "length" "2")
443490286Sobrien   (set_attr "mode" "HI")
4435117404Skan   (set_attr "unit" "i387")
4436169699Skan   (set_attr "athlon_decode" "vector")])
443790286Sobrien
443890286Sobrien;; Conversion between fixed point and floating point.
443952296Sobrien
444090286Sobrien;; Even though we only accept memory inputs, the backend _really_
444190286Sobrien;; wants to be able to do this between registers.
444290286Sobrien
4443132727Skan(define_expand "floathisf2"
4444132727Skan  [(set (match_operand:SF 0 "register_operand" "")
4445132727Skan	(float:SF (match_operand:HI 1 "nonimmediate_operand" "")))]
4446169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
4447132727Skan{
4448169699Skan  if (TARGET_SSE_MATH)
4449132727Skan    {
4450132727Skan      emit_insn (gen_floatsisf2 (operands[0],
4451132727Skan				 convert_to_mode (SImode, operands[1], 0)));
4452132727Skan      DONE;
4453132727Skan    }
4454132727Skan})
4455132727Skan
4456169699Skan(define_insn "*floathisf2_i387"
445752296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
4458169699Skan	(float:SF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
4459169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
446090286Sobrien  "@
446190286Sobrien   fild%z1\t%1
446290286Sobrien   #"
446390286Sobrien  [(set_attr "type" "fmov,multi")
446490286Sobrien   (set_attr "mode" "SF")
4465169699Skan   (set_attr "unit" "*,i387")
446690286Sobrien   (set_attr "fp_int_src" "true")])
446752296Sobrien
446890286Sobrien(define_expand "floatsisf2"
446918334Speter  [(set (match_operand:SF 0 "register_operand" "")
447090286Sobrien	(float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
4471169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
447218334Speter  "")
447318334Speter
4474169699Skan(define_insn "*floatsisf2_mixed"
4475169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
4476132727Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
4477169699Skan  "TARGET_MIX_SSE_I387"
447890286Sobrien  "@
447990286Sobrien   fild%z1\t%1
448090286Sobrien   #
4481132727Skan   cvtsi2ss\t{%1, %0|%0, %1}
448290286Sobrien   cvtsi2ss\t{%1, %0|%0, %1}"
4483132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
448490286Sobrien   (set_attr "mode" "SF")
4485169699Skan   (set_attr "unit" "*,i387,*,*")
4486132727Skan   (set_attr "athlon_decode" "*,*,vector,double")
448790286Sobrien   (set_attr "fp_int_src" "true")])
448890286Sobrien
448990286Sobrien(define_insn "*floatsisf2_sse"
4490132727Skan  [(set (match_operand:SF 0 "register_operand" "=x,x")
4491132727Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
4492169699Skan  "TARGET_SSE_MATH"
449390286Sobrien  "cvtsi2ss\t{%1, %0|%0, %1}"
4494132727Skan  [(set_attr "type" "sseicvt")
449590286Sobrien   (set_attr "mode" "SF")
4496132727Skan   (set_attr "athlon_decode" "vector,double")
449790286Sobrien   (set_attr "fp_int_src" "true")])
449890286Sobrien
4499169699Skan(define_insn "*floatsisf2_i387"
4500169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
4501169699Skan	(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
4502169699Skan  "TARGET_80387"
450390286Sobrien  "@
450490286Sobrien   fild%z1\t%1
450590286Sobrien   #"
450690286Sobrien  [(set_attr "type" "fmov,multi")
450790286Sobrien   (set_attr "mode" "SF")
4508169699Skan   (set_attr "unit" "*,i387")
450990286Sobrien   (set_attr "fp_int_src" "true")])
451052296Sobrien
4511169699Skan(define_expand "floatdisf2"
4512169699Skan  [(set (match_operand:SF 0 "register_operand" "")
4513169699Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
4514169699Skan  "TARGET_80387 || (TARGET_64BIT && TARGET_SSE_MATH)"
4515169699Skan  "")
4516169699Skan
4517169699Skan(define_insn "*floatdisf2_mixed"
4518169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
4519132727Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
4520169699Skan  "TARGET_64BIT && TARGET_MIX_SSE_I387"
452190286Sobrien  "@
452290286Sobrien   fild%z1\t%1
452390286Sobrien   #
4524132727Skan   cvtsi2ss{q}\t{%1, %0|%0, %1}
452590286Sobrien   cvtsi2ss{q}\t{%1, %0|%0, %1}"
4526132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
452790286Sobrien   (set_attr "mode" "SF")
4528169699Skan   (set_attr "unit" "*,i387,*,*")
4529132727Skan   (set_attr "athlon_decode" "*,*,vector,double")
453090286Sobrien   (set_attr "fp_int_src" "true")])
453152296Sobrien
453290286Sobrien(define_insn "*floatdisf2_sse"
4533132727Skan  [(set (match_operand:SF 0 "register_operand" "=x,x")
4534132727Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
4535169699Skan  "TARGET_64BIT && TARGET_SSE_MATH"
453690286Sobrien  "cvtsi2ss{q}\t{%1, %0|%0, %1}"
4537132727Skan  [(set_attr "type" "sseicvt")
453890286Sobrien   (set_attr "mode" "SF")
4539132727Skan   (set_attr "athlon_decode" "vector,double")
454090286Sobrien   (set_attr "fp_int_src" "true")])
454190286Sobrien
4542169699Skan(define_insn "*floatdisf2_i387"
4543169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
4544169699Skan	(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
4545169699Skan  "TARGET_80387"
4546169699Skan  "@
4547169699Skan   fild%z1\t%1
4548169699Skan   #"
4549169699Skan  [(set_attr "type" "fmov,multi")
4550169699Skan   (set_attr "mode" "SF")
4551169699Skan   (set_attr "unit" "*,i387")
4552169699Skan   (set_attr "fp_int_src" "true")])
4553132727Skan
4554132727Skan(define_expand "floathidf2"
4555132727Skan  [(set (match_operand:DF 0 "register_operand" "")
4556132727Skan	(float:DF (match_operand:HI 1 "nonimmediate_operand" "")))]
4557169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
4558132727Skan{
4559169699Skan  if (TARGET_SSE2 && TARGET_SSE_MATH)
4560132727Skan    {
4561132727Skan      emit_insn (gen_floatsidf2 (operands[0],
4562132727Skan				 convert_to_mode (SImode, operands[1], 0)));
4563132727Skan      DONE;
4564132727Skan    }
4565132727Skan})
4566132727Skan
4567169699Skan(define_insn "*floathidf2_i387"
456852296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
4569169699Skan	(float:DF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
4570169699Skan  "TARGET_80387 && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
457190286Sobrien  "@
457290286Sobrien   fild%z1\t%1
457390286Sobrien   #"
457490286Sobrien  [(set_attr "type" "fmov,multi")
457590286Sobrien   (set_attr "mode" "DF")
4576169699Skan   (set_attr "unit" "*,i387")
457790286Sobrien   (set_attr "fp_int_src" "true")])
457852296Sobrien
457990286Sobrien(define_expand "floatsidf2"
458018334Speter  [(set (match_operand:DF 0 "register_operand" "")
458190286Sobrien	(float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
4582169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
458352296Sobrien  "")
458452296Sobrien
4585169699Skan(define_insn "*floatsidf2_mixed"
4586169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
4587132727Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
4588169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387"
458990286Sobrien  "@
459090286Sobrien   fild%z1\t%1
459190286Sobrien   #
4592132727Skan   cvtsi2sd\t{%1, %0|%0, %1}
459390286Sobrien   cvtsi2sd\t{%1, %0|%0, %1}"
4594132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
459590286Sobrien   (set_attr "mode" "DF")
4596169699Skan   (set_attr "unit" "*,i387,*,*")
4597132727Skan   (set_attr "athlon_decode" "*,*,double,direct")
459890286Sobrien   (set_attr "fp_int_src" "true")])
459990286Sobrien
460090286Sobrien(define_insn "*floatsidf2_sse"
4601132727Skan  [(set (match_operand:DF 0 "register_operand" "=Y,Y")
4602132727Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
4603169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
460490286Sobrien  "cvtsi2sd\t{%1, %0|%0, %1}"
4605132727Skan  [(set_attr "type" "sseicvt")
460690286Sobrien   (set_attr "mode" "DF")
4607132727Skan   (set_attr "athlon_decode" "double,direct")
460890286Sobrien   (set_attr "fp_int_src" "true")])
460990286Sobrien
4610169699Skan(define_insn "*floatsidf2_i387"
4611169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
4612169699Skan	(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
4613169699Skan  "TARGET_80387"
461490286Sobrien  "@
461590286Sobrien   fild%z1\t%1
461690286Sobrien   #"
461790286Sobrien  [(set_attr "type" "fmov,multi")
461890286Sobrien   (set_attr "mode" "DF")
4619169699Skan   (set_attr "unit" "*,i387")
462090286Sobrien   (set_attr "fp_int_src" "true")])
462190286Sobrien
4622169699Skan(define_expand "floatdidf2"
4623169699Skan  [(set (match_operand:DF 0 "register_operand" "")
4624169699Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
4625169699Skan  "TARGET_80387 || (TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH)"
4626169699Skan  "")
4627169699Skan
4628169699Skan(define_insn "*floatdidf2_mixed"
4629169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
4630132727Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
4631169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
463290286Sobrien  "@
463390286Sobrien   fild%z1\t%1
463490286Sobrien   #
4635132727Skan   cvtsi2sd{q}\t{%1, %0|%0, %1}
463690286Sobrien   cvtsi2sd{q}\t{%1, %0|%0, %1}"
4637132727Skan  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
463890286Sobrien   (set_attr "mode" "DF")
4639169699Skan   (set_attr "unit" "*,i387,*,*")
4640132727Skan   (set_attr "athlon_decode" "*,*,double,direct")
464190286Sobrien   (set_attr "fp_int_src" "true")])
464290286Sobrien
464390286Sobrien(define_insn "*floatdidf2_sse"
4644132727Skan  [(set (match_operand:DF 0 "register_operand" "=Y,Y")
4645132727Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
4646169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
464790286Sobrien  "cvtsi2sd{q}\t{%1, %0|%0, %1}"
4648132727Skan  [(set_attr "type" "sseicvt")
464990286Sobrien   (set_attr "mode" "DF")
4650132727Skan   (set_attr "athlon_decode" "double,direct")
465190286Sobrien   (set_attr "fp_int_src" "true")])
465290286Sobrien
4653169699Skan(define_insn "*floatdidf2_i387"
4654169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
4655169699Skan	(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
4656169699Skan  "TARGET_80387"
4657169699Skan  "@
4658169699Skan   fild%z1\t%1
4659169699Skan   #"
4660169699Skan  [(set_attr "type" "fmov,multi")
4661169699Skan   (set_attr "mode" "DF")
4662169699Skan   (set_attr "unit" "*,i387")
4663169699Skan   (set_attr "fp_int_src" "true")])
4664169699Skan
466590286Sobrien(define_insn "floathixf2"
466690286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4667169699Skan	(float:XF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
466818334Speter  "TARGET_80387"
466990286Sobrien  "@
467090286Sobrien   fild%z1\t%1
467190286Sobrien   #"
467290286Sobrien  [(set_attr "type" "fmov,multi")
467390286Sobrien   (set_attr "mode" "XF")
4674169699Skan   (set_attr "unit" "*,i387")
467590286Sobrien   (set_attr "fp_int_src" "true")])
467652296Sobrien
467790286Sobrien(define_insn "floatsixf2"
467890286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4679169699Skan	(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
468052296Sobrien  "TARGET_80387"
468190286Sobrien  "@
468290286Sobrien   fild%z1\t%1
468390286Sobrien   #"
468490286Sobrien  [(set_attr "type" "fmov,multi")
468590286Sobrien   (set_attr "mode" "XF")
4686169699Skan   (set_attr "unit" "*,i387")
468790286Sobrien   (set_attr "fp_int_src" "true")])
468852296Sobrien
468990286Sobrien(define_insn "floatdixf2"
469090286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
4691169699Skan	(float:XF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
469252296Sobrien  "TARGET_80387"
469390286Sobrien  "@
469490286Sobrien   fild%z1\t%1
469590286Sobrien   #"
469690286Sobrien  [(set_attr "type" "fmov,multi")
469790286Sobrien   (set_attr "mode" "XF")
4698169699Skan   (set_attr "unit" "*,i387")
469990286Sobrien   (set_attr "fp_int_src" "true")])
470052296Sobrien
470190286Sobrien;; %%% Kill these when reload knows how to do it.
470252296Sobrien(define_split
4703117404Skan  [(set (match_operand 0 "fp_register_operand" "")
470490286Sobrien	(float (match_operand 1 "register_operand" "")))]
4705169699Skan  "reload_completed
4706169699Skan   && TARGET_80387
4707169699Skan   && FLOAT_MODE_P (GET_MODE (operands[0]))"
470890286Sobrien  [(const_int 0)]
470990286Sobrien{
471090286Sobrien  operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
471190286Sobrien  operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]);
471290286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[2]));
471390286Sobrien  ix86_free_from_memory (GET_MODE (operands[1]));
471490286Sobrien  DONE;
471590286Sobrien})
4716132727Skan
4717132727Skan(define_expand "floatunssisf2"
4718132727Skan  [(use (match_operand:SF 0 "register_operand" ""))
4719132727Skan   (use (match_operand:SI 1 "register_operand" ""))]
4720169699Skan  "!TARGET_64BIT && TARGET_SSE_MATH"
4721132727Skan  "x86_emit_floatuns (operands); DONE;")
4722132727Skan
4723132727Skan(define_expand "floatunsdisf2"
4724132727Skan  [(use (match_operand:SF 0 "register_operand" ""))
4725132727Skan   (use (match_operand:DI 1 "register_operand" ""))]
4726169699Skan  "TARGET_64BIT && TARGET_SSE_MATH"
4727132727Skan  "x86_emit_floatuns (operands); DONE;")
4728132727Skan
4729132727Skan(define_expand "floatunsdidf2"
4730132727Skan  [(use (match_operand:DF 0 "register_operand" ""))
4731132727Skan   (use (match_operand:DI 1 "register_operand" ""))]
4732169699Skan  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
4733132727Skan  "x86_emit_floatuns (operands); DONE;")
473490286Sobrien
4735132727Skan;; SSE extract/set expanders
4736132727Skan
4737169699Skan
4738169699Skan;; Add instructions
4739132727Skan
4740169699Skan;; %%% splits for addditi3
4741132727Skan
4742169699Skan(define_expand "addti3"
4743169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
4744169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
4745169699Skan		 (match_operand:TI 2 "x86_64_general_operand" "")))
4746169699Skan   (clobber (reg:CC FLAGS_REG))]
4747169699Skan  "TARGET_64BIT"
4748169699Skan  "ix86_expand_binary_operator (PLUS, TImode, operands); DONE;")
4749132727Skan
4750169699Skan(define_insn "*addti3_1"
4751169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
4752169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0")
4753171835Skan		 (match_operand:TI 2 "x86_64_general_operand" "roe,re")))
4754169699Skan   (clobber (reg:CC FLAGS_REG))]
4755169699Skan  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)"
4756169699Skan  "#")
4757132727Skan
4758169699Skan(define_split
4759169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
4760169699Skan	(plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
4761171835Skan		 (match_operand:TI 2 "x86_64_general_operand" "")))
4762169699Skan   (clobber (reg:CC FLAGS_REG))]
4763169699Skan  "TARGET_64BIT && reload_completed"
4764169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
4765169699Skan					  UNSPEC_ADD_CARRY))
4766169699Skan	      (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))])
4767169699Skan   (parallel [(set (match_dup 3)
4768169699Skan		   (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
4769169699Skan				     (match_dup 4))
4770169699Skan			    (match_dup 5)))
4771169699Skan	      (clobber (reg:CC FLAGS_REG))])]
4772169699Skan  "split_ti (operands+0, 1, operands+0, operands+3);
4773169699Skan   split_ti (operands+1, 1, operands+1, operands+4);
4774169699Skan   split_ti (operands+2, 1, operands+2, operands+5);")
4775132727Skan
477690286Sobrien;; %%% splits for addsidi3
477790286Sobrien;  [(set (match_operand:DI 0 "nonimmediate_operand" "")
477890286Sobrien;	(plus:DI (match_operand:DI 1 "general_operand" "")
477990286Sobrien;		 (zero_extend:DI (match_operand:SI 2 "general_operand" ""))))]
478052296Sobrien
478190286Sobrien(define_expand "adddi3"
478290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
478390286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
478490286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "")))
4785169699Skan   (clobber (reg:CC FLAGS_REG))]
478690286Sobrien  ""
478790286Sobrien  "ix86_expand_binary_operator (PLUS, DImode, operands); DONE;")
478852296Sobrien
478990286Sobrien(define_insn "*adddi3_1"
479090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
479190286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
479290286Sobrien		 (match_operand:DI 2 "general_operand" "roiF,riF")))
4793169699Skan   (clobber (reg:CC FLAGS_REG))]
4794107605Sobrien  "!TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
479552296Sobrien  "#")
479652296Sobrien
479752296Sobrien(define_split
479890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
479990286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
480090286Sobrien		 (match_operand:DI 2 "general_operand" "")))
4801169699Skan   (clobber (reg:CC FLAGS_REG))]
480290286Sobrien  "!TARGET_64BIT && reload_completed"
4803169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
4804117404Skan					  UNSPEC_ADD_CARRY))
480590286Sobrien	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
480690286Sobrien   (parallel [(set (match_dup 3)
4807169699Skan		   (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
480890286Sobrien				     (match_dup 4))
480990286Sobrien			    (match_dup 5)))
4810169699Skan	      (clobber (reg:CC FLAGS_REG))])]
481190286Sobrien  "split_di (operands+0, 1, operands+0, operands+3);
481290286Sobrien   split_di (operands+1, 1, operands+1, operands+4);
481390286Sobrien   split_di (operands+2, 1, operands+2, operands+5);")
481418334Speter
4815132727Skan(define_insn "adddi3_carry_rex64"
481690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
4817132727Skan	  (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
481890286Sobrien			    (match_operand:DI 1 "nonimmediate_operand" "%0,0"))
481990286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
4820169699Skan   (clobber (reg:CC FLAGS_REG))]
482190286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
482290286Sobrien  "adc{q}\t{%2, %0|%0, %2}"
482390286Sobrien  [(set_attr "type" "alu")
482490286Sobrien   (set_attr "pent_pair" "pu")
4825169699Skan   (set_attr "mode" "DI")])
482652296Sobrien
482790286Sobrien(define_insn "*adddi3_cc_rex64"
4828169699Skan  [(set (reg:CC FLAGS_REG)
4829117404Skan	(unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0")
4830117404Skan		    (match_operand:DI 2 "x86_64_general_operand" "re,rm")]
4831117404Skan		   UNSPEC_ADD_CARRY))
483290286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
483390286Sobrien	(plus:DI (match_dup 1) (match_dup 2)))]
483490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
483590286Sobrien  "add{q}\t{%2, %0|%0, %2}"
483690286Sobrien  [(set_attr "type" "alu")
483790286Sobrien   (set_attr "mode" "DI")])
483852296Sobrien
4839132727Skan(define_insn "addqi3_carry"
4840132727Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
4841132727Skan	  (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
4842132727Skan			    (match_operand:QI 1 "nonimmediate_operand" "%0,0"))
4843132727Skan		   (match_operand:QI 2 "general_operand" "qi,qm")))
4844169699Skan   (clobber (reg:CC FLAGS_REG))]
4845132727Skan  "ix86_binary_operator_ok (PLUS, QImode, operands)"
4846132727Skan  "adc{b}\t{%2, %0|%0, %2}"
4847132727Skan  [(set_attr "type" "alu")
4848132727Skan   (set_attr "pent_pair" "pu")
4849169699Skan   (set_attr "mode" "QI")])
4850132727Skan
4851132727Skan(define_insn "addhi3_carry"
4852132727Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
4853132727Skan	  (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
4854132727Skan			    (match_operand:HI 1 "nonimmediate_operand" "%0,0"))
4855132727Skan		   (match_operand:HI 2 "general_operand" "ri,rm")))
4856169699Skan   (clobber (reg:CC FLAGS_REG))]
4857132727Skan  "ix86_binary_operator_ok (PLUS, HImode, operands)"
4858132727Skan  "adc{w}\t{%2, %0|%0, %2}"
4859132727Skan  [(set_attr "type" "alu")
4860132727Skan   (set_attr "pent_pair" "pu")
4861169699Skan   (set_attr "mode" "HI")])
4862132727Skan
4863132727Skan(define_insn "addsi3_carry"
486490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
4865132727Skan	  (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
486690286Sobrien			    (match_operand:SI 1 "nonimmediate_operand" "%0,0"))
486790286Sobrien		   (match_operand:SI 2 "general_operand" "ri,rm")))
4868169699Skan   (clobber (reg:CC FLAGS_REG))]
486990286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
487090286Sobrien  "adc{l}\t{%2, %0|%0, %2}"
487190286Sobrien  [(set_attr "type" "alu")
487290286Sobrien   (set_attr "pent_pair" "pu")
4873169699Skan   (set_attr "mode" "SI")])
487452296Sobrien
487590286Sobrien(define_insn "*addsi3_carry_zext"
487690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
487790286Sobrien	  (zero_extend:DI 
4878132727Skan	    (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
487990286Sobrien			      (match_operand:SI 1 "nonimmediate_operand" "%0"))
488090286Sobrien		     (match_operand:SI 2 "general_operand" "rim"))))
4881169699Skan   (clobber (reg:CC FLAGS_REG))]
488290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
488390286Sobrien  "adc{l}\t{%2, %k0|%k0, %2}"
488490286Sobrien  [(set_attr "type" "alu")
488590286Sobrien   (set_attr "pent_pair" "pu")
4886169699Skan   (set_attr "mode" "SI")])
488752296Sobrien
488890286Sobrien(define_insn "*addsi3_cc"
4889169699Skan  [(set (reg:CC FLAGS_REG)
4890117404Skan	(unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0")
4891117404Skan		    (match_operand:SI 2 "general_operand" "ri,rm")]
4892117404Skan		   UNSPEC_ADD_CARRY))
489390286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
489490286Sobrien	(plus:SI (match_dup 1) (match_dup 2)))]
489590286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
489690286Sobrien  "add{l}\t{%2, %0|%0, %2}"
489790286Sobrien  [(set_attr "type" "alu")
489890286Sobrien   (set_attr "mode" "SI")])
489918334Speter
490090286Sobrien(define_insn "addqi3_cc"
4901169699Skan  [(set (reg:CC FLAGS_REG)
4902117404Skan	(unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0")
4903117404Skan		    (match_operand:QI 2 "general_operand" "qi,qm")]
4904117404Skan		   UNSPEC_ADD_CARRY))
490590286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
490690286Sobrien	(plus:QI (match_dup 1) (match_dup 2)))]
490790286Sobrien  "ix86_binary_operator_ok (PLUS, QImode, operands)"
490890286Sobrien  "add{b}\t{%2, %0|%0, %2}"
490990286Sobrien  [(set_attr "type" "alu")
491090286Sobrien   (set_attr "mode" "QI")])
491118334Speter
491290286Sobrien(define_expand "addsi3"
491390286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
491490286Sobrien		   (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
491590286Sobrien			    (match_operand:SI 2 "general_operand" "")))
4916169699Skan	      (clobber (reg:CC FLAGS_REG))])]
491790286Sobrien  ""
491890286Sobrien  "ix86_expand_binary_operator (PLUS, SImode, operands); DONE;")
491918334Speter
492090286Sobrien(define_insn "*lea_1"
492190286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
4922132727Skan	(match_operand:SI 1 "no_seg_address_operand" "p"))]
492390286Sobrien  "!TARGET_64BIT"
492490286Sobrien  "lea{l}\t{%a1, %0|%0, %a1}"
492590286Sobrien  [(set_attr "type" "lea")
492690286Sobrien   (set_attr "mode" "SI")])
492718334Speter
492890286Sobrien(define_insn "*lea_1_rex64"
492990286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
4930132727Skan	(subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))]
493190286Sobrien  "TARGET_64BIT"
493290286Sobrien  "lea{l}\t{%a1, %0|%0, %a1}"
493390286Sobrien  [(set_attr "type" "lea")
493490286Sobrien   (set_attr "mode" "SI")])
493518334Speter
493690286Sobrien(define_insn "*lea_1_zext"
493790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
4938132727Skan	(zero_extend:DI
4939132727Skan	 (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))]
494090286Sobrien  "TARGET_64BIT"
494190286Sobrien  "lea{l}\t{%a1, %k0|%k0, %a1}"
494290286Sobrien  [(set_attr "type" "lea")
494390286Sobrien   (set_attr "mode" "SI")])
494490286Sobrien
494590286Sobrien(define_insn "*lea_2_rex64"
494690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
4947132727Skan	(match_operand:DI 1 "no_seg_address_operand" "p"))]
494890286Sobrien  "TARGET_64BIT"
494990286Sobrien  "lea{q}\t{%a1, %0|%0, %a1}"
495090286Sobrien  [(set_attr "type" "lea")
495190286Sobrien   (set_attr "mode" "DI")])
495290286Sobrien
495390286Sobrien;; The lea patterns for non-Pmodes needs to be matched by several
495490286Sobrien;; insns converted to real lea by splitters.
495590286Sobrien
495690286Sobrien(define_insn_and_split "*lea_general_1"
495790286Sobrien  [(set (match_operand 0 "register_operand" "=r")
4958169699Skan	(plus (plus (match_operand 1 "index_register_operand" "l")
495990286Sobrien		    (match_operand 2 "register_operand" "r"))
496090286Sobrien	      (match_operand 3 "immediate_operand" "i")))]
496190286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
496290286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
496390286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
496490286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
496590286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[2])
496690286Sobrien   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
496790286Sobrien       || GET_MODE (operands[3]) == VOIDmode)"
496890286Sobrien  "#"
496990286Sobrien  "&& reload_completed"
497090286Sobrien  [(const_int 0)]
497190286Sobrien{
497290286Sobrien  rtx pat;
497390286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
497490286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
497590286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
497690286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
497790286Sobrien  pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]),
497890286Sobrien  		      operands[3]);
497990286Sobrien  if (Pmode != SImode)
498090286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
498190286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
498290286Sobrien  DONE;
498390286Sobrien}
498490286Sobrien  [(set_attr "type" "lea")
498590286Sobrien   (set_attr "mode" "SI")])
498690286Sobrien
498790286Sobrien(define_insn_and_split "*lea_general_1_zext"
498890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
498990286Sobrien	(zero_extend:DI
4990169699Skan	  (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "l")
499190286Sobrien			    (match_operand:SI 2 "register_operand" "r"))
499290286Sobrien		   (match_operand:SI 3 "immediate_operand" "i"))))]
499390286Sobrien  "TARGET_64BIT"
499490286Sobrien  "#"
499590286Sobrien  "&& reload_completed"
499652296Sobrien  [(set (match_dup 0)
499790286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1)
499890286Sobrien						     (match_dup 2))
499990286Sobrien					    (match_dup 3)) 0)))]
500090286Sobrien{
500190286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
500290286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
500390286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
500490286Sobrien}
500590286Sobrien  [(set_attr "type" "lea")
500690286Sobrien   (set_attr "mode" "SI")])
500752296Sobrien
500890286Sobrien(define_insn_and_split "*lea_general_2"
500990286Sobrien  [(set (match_operand 0 "register_operand" "=r")
5010169699Skan	(plus (mult (match_operand 1 "index_register_operand" "l")
501190286Sobrien		    (match_operand 2 "const248_operand" "i"))
501290286Sobrien	      (match_operand 3 "nonmemory_operand" "ri")))]
501390286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
501490286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
501590286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
501690286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
501790286Sobrien   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
501890286Sobrien       || GET_MODE (operands[3]) == VOIDmode)"
501990286Sobrien  "#"
502090286Sobrien  "&& reload_completed"
502190286Sobrien  [(const_int 0)]
502290286Sobrien{
502390286Sobrien  rtx pat;
502490286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
502590286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
502690286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
502790286Sobrien  pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]),
502890286Sobrien  		      operands[3]);
502990286Sobrien  if (Pmode != SImode)
503090286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
503190286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
503290286Sobrien  DONE;
503390286Sobrien}
503490286Sobrien  [(set_attr "type" "lea")
503590286Sobrien   (set_attr "mode" "SI")])
503652296Sobrien
503790286Sobrien(define_insn_and_split "*lea_general_2_zext"
503890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
503990286Sobrien	(zero_extend:DI
5040169699Skan	  (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "l")
504190286Sobrien			    (match_operand:SI 2 "const248_operand" "n"))
504290286Sobrien		   (match_operand:SI 3 "nonmemory_operand" "ri"))))]
504390286Sobrien  "TARGET_64BIT"
504490286Sobrien  "#"
504590286Sobrien  "&& reload_completed"
504690286Sobrien  [(set (match_dup 0)
504790286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1)
504890286Sobrien						     (match_dup 2))
504990286Sobrien					    (match_dup 3)) 0)))]
505090286Sobrien{
505190286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
505290286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
505390286Sobrien}
505490286Sobrien  [(set_attr "type" "lea")
505590286Sobrien   (set_attr "mode" "SI")])
505618334Speter
505790286Sobrien(define_insn_and_split "*lea_general_3"
505890286Sobrien  [(set (match_operand 0 "register_operand" "=r")
5059169699Skan	(plus (plus (mult (match_operand 1 "index_register_operand" "l")
506090286Sobrien			  (match_operand 2 "const248_operand" "i"))
506190286Sobrien		    (match_operand 3 "register_operand" "r"))
506290286Sobrien	      (match_operand 4 "immediate_operand" "i")))]
506390286Sobrien  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
506490286Sobrien    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
506590286Sobrien   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
506690286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[1])
506790286Sobrien   && GET_MODE (operands[0]) == GET_MODE (operands[3])"
506890286Sobrien  "#"
506990286Sobrien  "&& reload_completed"
507090286Sobrien  [(const_int 0)]
507190286Sobrien{
507290286Sobrien  rtx pat;
507390286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
507490286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
507590286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
507690286Sobrien  operands[4] = gen_lowpart (Pmode, operands[4]);
507790286Sobrien  pat = gen_rtx_PLUS (Pmode,
507890286Sobrien  		      gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1],
507990286Sobrien		      					 operands[2]),
508090286Sobrien				    operands[3]),
508190286Sobrien  		      operands[4]);
508290286Sobrien  if (Pmode != SImode)
508390286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
508490286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
508590286Sobrien  DONE;
508690286Sobrien}
508790286Sobrien  [(set_attr "type" "lea")
508890286Sobrien   (set_attr "mode" "SI")])
508952296Sobrien
509090286Sobrien(define_insn_and_split "*lea_general_3_zext"
509190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
509290286Sobrien	(zero_extend:DI
5093169699Skan	  (plus:SI (plus:SI (mult:SI
5094169699Skan			      (match_operand:SI 1 "index_register_operand" "l")
5095169699Skan			      (match_operand:SI 2 "const248_operand" "n"))
509690286Sobrien			    (match_operand:SI 3 "register_operand" "r"))
509790286Sobrien		   (match_operand:SI 4 "immediate_operand" "i"))))]
509890286Sobrien  "TARGET_64BIT"
509990286Sobrien  "#"
510090286Sobrien  "&& reload_completed"
510190286Sobrien  [(set (match_dup 0)
510290286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1)
510390286Sobrien							      (match_dup 2))
510490286Sobrien						     (match_dup 3))
510590286Sobrien					    (match_dup 4)) 0)))]
510690286Sobrien{
510790286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
510890286Sobrien  operands[3] = gen_lowpart (Pmode, operands[3]);
510990286Sobrien  operands[4] = gen_lowpart (Pmode, operands[4]);
511090286Sobrien}
511190286Sobrien  [(set_attr "type" "lea")
511290286Sobrien   (set_attr "mode" "SI")])
511318334Speter
511490286Sobrien(define_insn "*adddi_1_rex64"
511590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
511690286Sobrien	(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r")
5117169699Skan		 (match_operand:DI 2 "x86_64_general_operand" "rme,re,le")))
5118169699Skan   (clobber (reg:CC FLAGS_REG))]
511990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
512090286Sobrien{
512190286Sobrien  switch (get_attr_type (insn))
512290286Sobrien    {
512390286Sobrien    case TYPE_LEA:
512490286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
512590286Sobrien      return "lea{q}\t{%a2, %0|%0, %a2}";
512690286Sobrien
512790286Sobrien    case TYPE_INCDEC:
5128169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
512990286Sobrien      if (operands[2] == const1_rtx)
513090286Sobrien        return "inc{q}\t%0";
513190286Sobrien      else
5132169699Skan        {
5133169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5134169699Skan          return "dec{q}\t%0";
5135169699Skan	}
513690286Sobrien
513790286Sobrien    default:
5138169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
513990286Sobrien
514090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
514190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
514290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
514390286Sobrien	  /* Avoid overflows.  */
514490286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
514590286Sobrien          && (INTVAL (operands[2]) == 128
514690286Sobrien	      || (INTVAL (operands[2]) < 0
514790286Sobrien		  && INTVAL (operands[2]) != -128)))
514890286Sobrien        {
514990286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
515090286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
515190286Sobrien        }
515290286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
515390286Sobrien    }
515490286Sobrien}
515590286Sobrien  [(set (attr "type")
515690286Sobrien     (cond [(eq_attr "alternative" "2")
515790286Sobrien	      (const_string "lea")
515890286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
515990286Sobrien	    ; ought but a memory context.
516090286Sobrien	    (match_operand:DI 2 "pic_symbolic_operand" "")
516190286Sobrien	      (const_string "lea")
516290286Sobrien	    (match_operand:DI 2 "incdec_operand" "")
516390286Sobrien	      (const_string "incdec")
516490286Sobrien	   ]
516590286Sobrien	   (const_string "alu")))
516690286Sobrien   (set_attr "mode" "DI")])
516790286Sobrien
516890286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
516952296Sobrien(define_split
517090286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
517190286Sobrien	(plus:DI (match_operand:DI 1 "register_operand" "")
517290286Sobrien		 (match_operand:DI 2 "x86_64_nonmemory_operand" "")))
5173169699Skan   (clobber (reg:CC FLAGS_REG))]
517490286Sobrien  "TARGET_64BIT && reload_completed
517590286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
517652296Sobrien  [(set (match_dup 0)
517790286Sobrien	(plus:DI (match_dup 1)
517890286Sobrien		 (match_dup 2)))]
517952296Sobrien  "")
518052296Sobrien
518190286Sobrien(define_insn "*adddi_2_rex64"
5182169699Skan  [(set (reg FLAGS_REG)
518390286Sobrien	(compare
518490286Sobrien	  (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
518590286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "rme,re"))
518690286Sobrien	  (const_int 0)))			
518790286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
518890286Sobrien	(plus:DI (match_dup 1) (match_dup 2)))]
518990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
519090286Sobrien   && ix86_binary_operator_ok (PLUS, DImode, operands)
519190286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
519290286Sobrien      ought but a memory context.  */
519390286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
519490286Sobrien{
519590286Sobrien  switch (get_attr_type (insn))
519690286Sobrien    {
519790286Sobrien    case TYPE_INCDEC:
5198169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
519990286Sobrien      if (operands[2] == const1_rtx)
520090286Sobrien        return "inc{q}\t%0";
520190286Sobrien      else
5202169699Skan        {
5203169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5204169699Skan          return "dec{q}\t%0";
5205169699Skan	}
520652296Sobrien
520790286Sobrien    default:
5208169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
520990286Sobrien      /* ???? We ought to handle there the 32bit case too
5210132727Skan	 - do we need new constraint?  */
521190286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
521290286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
521390286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
521490286Sobrien	  /* Avoid overflows.  */
521590286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
521690286Sobrien          && (INTVAL (operands[2]) == 128
521790286Sobrien	      || (INTVAL (operands[2]) < 0
521890286Sobrien		  && INTVAL (operands[2]) != -128)))
521990286Sobrien        {
522090286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
522190286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
522290286Sobrien        }
522390286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
522490286Sobrien    }
522590286Sobrien}
522690286Sobrien  [(set (attr "type")
522790286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
522890286Sobrien	(const_string "incdec")
522990286Sobrien	(const_string "alu")))
523090286Sobrien   (set_attr "mode" "DI")])
523118334Speter
523290286Sobrien(define_insn "*adddi_3_rex64"
5233169699Skan  [(set (reg FLAGS_REG)
523490286Sobrien	(compare (neg:DI (match_operand:DI 2 "x86_64_general_operand" "rme"))
523590286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "%0")))
523690286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
523790286Sobrien  "TARGET_64BIT
523890286Sobrien   && ix86_match_ccmode (insn, CCZmode)
523990286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
524090286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
524190286Sobrien      ought but a memory context.  */
524290286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
524350650Sobrien{
524490286Sobrien  switch (get_attr_type (insn))
524590286Sobrien    {
524690286Sobrien    case TYPE_INCDEC:
5247169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
524890286Sobrien      if (operands[2] == const1_rtx)
524990286Sobrien        return "inc{q}\t%0";
525090286Sobrien      else
5251169699Skan        {
5252169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5253169699Skan          return "dec{q}\t%0";
5254169699Skan	}
525550650Sobrien
525690286Sobrien    default:
5257169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
525890286Sobrien      /* ???? We ought to handle there the 32bit case too
5259132727Skan	 - do we need new constraint?  */
526090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
526190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
526290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
526390286Sobrien	  /* Avoid overflows.  */
526490286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
526590286Sobrien          && (INTVAL (operands[2]) == 128
526690286Sobrien	      || (INTVAL (operands[2]) < 0
526790286Sobrien		  && INTVAL (operands[2]) != -128)))
526890286Sobrien        {
526990286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
527090286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
527190286Sobrien        }
527290286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
527390286Sobrien    }
527490286Sobrien}
527590286Sobrien  [(set (attr "type")
527690286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
527790286Sobrien	(const_string "incdec")
527890286Sobrien	(const_string "alu")))
527990286Sobrien   (set_attr "mode" "DI")])
528050650Sobrien
528190286Sobrien; For comparisons against 1, -1 and 128, we may generate better code
528290286Sobrien; by converting cmp to add, inc or dec as done by peephole2.  This pattern
528390286Sobrien; is matched then.  We can't accept general immediate, because for
528490286Sobrien; case of overflows,  the result is messed up.
528590286Sobrien; This pattern also don't hold of 0x8000000000000000, since the value overflows
528690286Sobrien; when negated.
528790286Sobrien; Also carry flag is reversed compared to cmp, so this conversion is valid
528890286Sobrien; only for comparisons not depending on it.
528990286Sobrien(define_insn "*adddi_4_rex64"
5290169699Skan  [(set (reg FLAGS_REG)
529190286Sobrien	(compare (match_operand:DI 1 "nonimmediate_operand" "0")
529290286Sobrien		 (match_operand:DI 2 "x86_64_immediate_operand" "e")))
529390286Sobrien   (clobber (match_scratch:DI 0 "=rm"))]
529490286Sobrien  "TARGET_64BIT
529590286Sobrien   &&  ix86_match_ccmode (insn, CCGCmode)"
529690286Sobrien{
529790286Sobrien  switch (get_attr_type (insn))
529890286Sobrien    {
529990286Sobrien    case TYPE_INCDEC:
530090286Sobrien      if (operands[2] == constm1_rtx)
530190286Sobrien        return "inc{q}\t%0";
530290286Sobrien      else
5303169699Skan        {
5304169699Skan	  gcc_assert (operands[2] == const1_rtx);
5305169699Skan          return "dec{q}\t%0";
5306169699Skan	}
530750650Sobrien
530890286Sobrien    default:
5309169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
531090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
531190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
531290286Sobrien      if ((INTVAL (operands[2]) == -128
531390286Sobrien	   || (INTVAL (operands[2]) > 0
531490286Sobrien	       && INTVAL (operands[2]) != 128))
531590286Sobrien	  /* Avoid overflows.  */
531690286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))))
531790286Sobrien	return "sub{q}\t{%2, %0|%0, %2}";
531890286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
531990286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
532090286Sobrien    }
532190286Sobrien}
532290286Sobrien  [(set (attr "type")
532390286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
532490286Sobrien	(const_string "incdec")
532590286Sobrien	(const_string "alu")))
532690286Sobrien   (set_attr "mode" "DI")])
532790286Sobrien
532890286Sobrien(define_insn "*adddi_5_rex64"
5329169699Skan  [(set (reg FLAGS_REG)
533090286Sobrien	(compare
533190286Sobrien	  (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
533290286Sobrien		   (match_operand:DI 2 "x86_64_general_operand" "rme"))
533390286Sobrien	  (const_int 0)))			
533490286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
533590286Sobrien  "TARGET_64BIT
533690286Sobrien   && ix86_match_ccmode (insn, CCGOCmode)
533790286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
533890286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
533990286Sobrien      ought but a memory context.  */
534090286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
534190286Sobrien{
534290286Sobrien  switch (get_attr_type (insn))
534350650Sobrien    {
534490286Sobrien    case TYPE_INCDEC:
5345169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
534690286Sobrien      if (operands[2] == const1_rtx)
534790286Sobrien        return "inc{q}\t%0";
534890286Sobrien      else
5349169699Skan        {
5350169699Skan          gcc_assert (operands[2] == constm1_rtx);
5351169699Skan          return "dec{q}\t%0";
5352169699Skan	}
535350650Sobrien
535490286Sobrien    default:
5355169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
535690286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
535790286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
535890286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
535990286Sobrien	  /* Avoid overflows.  */
536090286Sobrien	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
536190286Sobrien          && (INTVAL (operands[2]) == 128
536290286Sobrien	      || (INTVAL (operands[2]) < 0
536390286Sobrien		  && INTVAL (operands[2]) != -128)))
536490286Sobrien        {
536590286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
536690286Sobrien          return "sub{q}\t{%2, %0|%0, %2}";
536790286Sobrien        }
536890286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
536950650Sobrien    }
537090286Sobrien}
537190286Sobrien  [(set (attr "type")
537290286Sobrien     (if_then_else (match_operand:DI 2 "incdec_operand" "")
537390286Sobrien	(const_string "incdec")
537490286Sobrien	(const_string "alu")))
537590286Sobrien   (set_attr "mode" "DI")])
537650650Sobrien
537750650Sobrien
537890286Sobrien(define_insn "*addsi_1"
537990286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
538090286Sobrien	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
5381169699Skan		 (match_operand:SI 2 "general_operand" "rmni,rni,lni")))
5382169699Skan   (clobber (reg:CC FLAGS_REG))]
538390286Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
538450650Sobrien{
538590286Sobrien  switch (get_attr_type (insn))
538690286Sobrien    {
538790286Sobrien    case TYPE_LEA:
538890286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
538990286Sobrien      return "lea{l}\t{%a2, %0|%0, %a2}";
539050650Sobrien
539190286Sobrien    case TYPE_INCDEC:
5392169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
539390286Sobrien      if (operands[2] == const1_rtx)
539490286Sobrien        return "inc{l}\t%0";
539590286Sobrien      else
5396169699Skan	{
5397169699Skan  	  gcc_assert (operands[2] == constm1_rtx);
5398169699Skan          return "dec{l}\t%0";
5399169699Skan	}
540050650Sobrien
540190286Sobrien    default:
5402169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
540350650Sobrien
540490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
540590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
540690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
540790286Sobrien          && (INTVAL (operands[2]) == 128
540890286Sobrien	      || (INTVAL (operands[2]) < 0
540990286Sobrien		  && INTVAL (operands[2]) != -128)))
541090286Sobrien        {
541190286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
541290286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
541390286Sobrien        }
541490286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
541590286Sobrien    }
541690286Sobrien}
541790286Sobrien  [(set (attr "type")
541890286Sobrien     (cond [(eq_attr "alternative" "2")
541990286Sobrien	      (const_string "lea")
542090286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
542190286Sobrien	    ; ought but a memory context.
542290286Sobrien	    (match_operand:SI 2 "pic_symbolic_operand" "")
542390286Sobrien	      (const_string "lea")
542490286Sobrien	    (match_operand:SI 2 "incdec_operand" "")
542590286Sobrien	      (const_string "incdec")
542690286Sobrien	   ]
542790286Sobrien	   (const_string "alu")))
542890286Sobrien   (set_attr "mode" "SI")])
542990286Sobrien
543090286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
543190286Sobrien(define_split
543290286Sobrien  [(set (match_operand 0 "register_operand" "")
543390286Sobrien	(plus (match_operand 1 "register_operand" "")
543490286Sobrien              (match_operand 2 "nonmemory_operand" "")))
5435169699Skan   (clobber (reg:CC FLAGS_REG))]
543690286Sobrien  "reload_completed
543790286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
543890286Sobrien  [(const_int 0)]
543990286Sobrien{
544090286Sobrien  rtx pat;
544190286Sobrien  /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
544290286Sobrien     may confuse gen_lowpart.  */
544390286Sobrien  if (GET_MODE (operands[0]) != Pmode)
544450650Sobrien    {
544590286Sobrien      operands[1] = gen_lowpart (Pmode, operands[1]);
544690286Sobrien      operands[2] = gen_lowpart (Pmode, operands[2]);
544790286Sobrien    }
544890286Sobrien  operands[0] = gen_lowpart (SImode, operands[0]);
544990286Sobrien  pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
545090286Sobrien  if (Pmode != SImode)
545190286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
545290286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
545390286Sobrien  DONE;
545490286Sobrien})
545550650Sobrien
545690286Sobrien;; It may seem that nonimmediate operand is proper one for operand 1.
545790286Sobrien;; The addsi_1 pattern allows nonimmediate operand at that place and
545890286Sobrien;; we take care in ix86_binary_operator_ok to not allow two memory
545990286Sobrien;; operands so proper swapping will be done in reload.  This allow
546090286Sobrien;; patterns constructed from addsi_1 to match.
546190286Sobrien(define_insn "addsi_1_zext"
546290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
546390286Sobrien	(zero_extend:DI
546490286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r")
5465169699Skan		   (match_operand:SI 2 "general_operand" "rmni,lni"))))
5466169699Skan   (clobber (reg:CC FLAGS_REG))]
546790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
546890286Sobrien{
546990286Sobrien  switch (get_attr_type (insn))
547090286Sobrien    {
547190286Sobrien    case TYPE_LEA:
547290286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
547390286Sobrien      return "lea{l}\t{%a2, %k0|%k0, %a2}";
547490286Sobrien
547590286Sobrien    case TYPE_INCDEC:
547690286Sobrien      if (operands[2] == const1_rtx)
547790286Sobrien        return "inc{l}\t%k0";
547850650Sobrien      else
5479169699Skan        {
5480169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5481169699Skan          return "dec{l}\t%k0";
5482169699Skan	}
548390286Sobrien
548490286Sobrien    default:
548590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
548690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
548790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
548890286Sobrien          && (INTVAL (operands[2]) == 128
548990286Sobrien	      || (INTVAL (operands[2]) < 0
549090286Sobrien		  && INTVAL (operands[2]) != -128)))
549190286Sobrien        {
549290286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
549390286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
549490286Sobrien        }
549590286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
549650650Sobrien    }
549790286Sobrien}
549890286Sobrien  [(set (attr "type")
549990286Sobrien     (cond [(eq_attr "alternative" "1")
550090286Sobrien	      (const_string "lea")
550190286Sobrien	    ; Current assemblers are broken and do not allow @GOTOFF in
550290286Sobrien	    ; ought but a memory context.
550390286Sobrien	    (match_operand:SI 2 "pic_symbolic_operand" "")
550490286Sobrien	      (const_string "lea")
550590286Sobrien	    (match_operand:SI 2 "incdec_operand" "")
550690286Sobrien	      (const_string "incdec")
550790286Sobrien	   ]
550890286Sobrien	   (const_string "alu")))
550990286Sobrien   (set_attr "mode" "SI")])
551050650Sobrien
551190286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
551290286Sobrien(define_split
551390286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
551490286Sobrien	(zero_extend:DI
551590286Sobrien	  (plus:SI (match_operand:SI 1 "register_operand" "")
551690286Sobrien		   (match_operand:SI 2 "nonmemory_operand" ""))))
5517169699Skan   (clobber (reg:CC FLAGS_REG))]
5518132727Skan  "TARGET_64BIT && reload_completed
551990286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
552090286Sobrien  [(set (match_dup 0)
552190286Sobrien	(zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))]
552290286Sobrien{
552390286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
552490286Sobrien  operands[2] = gen_lowpart (Pmode, operands[2]);
552590286Sobrien})
552650650Sobrien
552790286Sobrien(define_insn "*addsi_2"
5528169699Skan  [(set (reg FLAGS_REG)
552990286Sobrien	(compare
553090286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
553190286Sobrien		   (match_operand:SI 2 "general_operand" "rmni,rni"))
553290286Sobrien	  (const_int 0)))			
553390286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
553490286Sobrien	(plus:SI (match_dup 1) (match_dup 2)))]
553590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
553690286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
553790286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
553890286Sobrien      ought but a memory context.  */
553990286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
554018334Speter{
554190286Sobrien  switch (get_attr_type (insn))
554290286Sobrien    {
554390286Sobrien    case TYPE_INCDEC:
5544169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
554590286Sobrien      if (operands[2] == const1_rtx)
554690286Sobrien        return "inc{l}\t%0";
554790286Sobrien      else
5548169699Skan        {
5549169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5550169699Skan          return "dec{l}\t%0";
5551169699Skan	}
555218334Speter
555390286Sobrien    default:
5554169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
555590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
555690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
555790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
555890286Sobrien          && (INTVAL (operands[2]) == 128
555990286Sobrien	      || (INTVAL (operands[2]) < 0
556090286Sobrien		  && INTVAL (operands[2]) != -128)))
556190286Sobrien        {
556290286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
556390286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
556490286Sobrien        }
556590286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
556690286Sobrien    }
556790286Sobrien}
556890286Sobrien  [(set (attr "type")
556990286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
557090286Sobrien	(const_string "incdec")
557190286Sobrien	(const_string "alu")))
557290286Sobrien   (set_attr "mode" "SI")])
557318334Speter
557490286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
557590286Sobrien(define_insn "*addsi_2_zext"
5576169699Skan  [(set (reg FLAGS_REG)
557790286Sobrien	(compare
557890286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
557990286Sobrien		   (match_operand:SI 2 "general_operand" "rmni"))
558090286Sobrien	  (const_int 0)))			
558190286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
558290286Sobrien	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
558390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
558490286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
558590286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
558690286Sobrien      ought but a memory context.  */
558790286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
558890286Sobrien{
558990286Sobrien  switch (get_attr_type (insn))
559018334Speter    {
559190286Sobrien    case TYPE_INCDEC:
559290286Sobrien      if (operands[2] == const1_rtx)
559390286Sobrien        return "inc{l}\t%k0";
559490286Sobrien      else
5595169699Skan	{
5596169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5597169699Skan          return "dec{l}\t%k0";
5598169699Skan	}
559990286Sobrien
560090286Sobrien    default:
560190286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
560290286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
560390286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
560490286Sobrien          && (INTVAL (operands[2]) == 128
560590286Sobrien	      || (INTVAL (operands[2]) < 0
560690286Sobrien		  && INTVAL (operands[2]) != -128)))
560790286Sobrien        {
560890286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
560990286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
561090286Sobrien        }
561190286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
561218334Speter    }
561390286Sobrien}
561490286Sobrien  [(set (attr "type")
561590286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
561690286Sobrien	(const_string "incdec")
561790286Sobrien	(const_string "alu")))
561890286Sobrien   (set_attr "mode" "SI")])
561918334Speter
562090286Sobrien(define_insn "*addsi_3"
5621169699Skan  [(set (reg FLAGS_REG)
562290286Sobrien	(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
562390286Sobrien		 (match_operand:SI 1 "nonimmediate_operand" "%0")))
562490286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
562590286Sobrien  "ix86_match_ccmode (insn, CCZmode)
562690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
562790286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
562890286Sobrien      ought but a memory context.  */
562990286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
563090286Sobrien{
563190286Sobrien  switch (get_attr_type (insn))
563218334Speter    {
563390286Sobrien    case TYPE_INCDEC:
5634169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
563590286Sobrien      if (operands[2] == const1_rtx)
563690286Sobrien        return "inc{l}\t%0";
563790286Sobrien      else
5638169699Skan        {
5639169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5640169699Skan          return "dec{l}\t%0";
5641169699Skan	}
564218334Speter
564390286Sobrien    default:
5644169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
564590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
564690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
564790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
564890286Sobrien          && (INTVAL (operands[2]) == 128
564990286Sobrien	      || (INTVAL (operands[2]) < 0
565090286Sobrien		  && INTVAL (operands[2]) != -128)))
565190286Sobrien        {
565290286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
565390286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
565490286Sobrien        }
565590286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
565690286Sobrien    }
565790286Sobrien}
565890286Sobrien  [(set (attr "type")
565990286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
566090286Sobrien	(const_string "incdec")
566190286Sobrien	(const_string "alu")))
566290286Sobrien   (set_attr "mode" "SI")])
566390286Sobrien
566490286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
566590286Sobrien(define_insn "*addsi_3_zext"
5666169699Skan  [(set (reg FLAGS_REG)
566790286Sobrien	(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
566890286Sobrien		 (match_operand:SI 1 "nonimmediate_operand" "%0")))
566990286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
567090286Sobrien	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
567190286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCZmode)
567290286Sobrien   && ix86_binary_operator_ok (PLUS, SImode, operands)
567390286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
567490286Sobrien      ought but a memory context.  */
567590286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
567690286Sobrien{
567790286Sobrien  switch (get_attr_type (insn))
567890286Sobrien    {
567990286Sobrien    case TYPE_INCDEC:
568090286Sobrien      if (operands[2] == const1_rtx)
568190286Sobrien        return "inc{l}\t%k0";
568218334Speter      else
5683169699Skan        {
5684169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5685169699Skan          return "dec{l}\t%k0";
5686169699Skan	}
568790286Sobrien
568890286Sobrien    default:
568990286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
569090286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
569190286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
569290286Sobrien          && (INTVAL (operands[2]) == 128
569390286Sobrien	      || (INTVAL (operands[2]) < 0
569490286Sobrien		  && INTVAL (operands[2]) != -128)))
569590286Sobrien        {
569690286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
569790286Sobrien          return "sub{l}\t{%2, %k0|%k0, %2}";
569890286Sobrien        }
569990286Sobrien      return "add{l}\t{%2, %k0|%k0, %2}";
570018334Speter    }
570190286Sobrien}
570290286Sobrien  [(set (attr "type")
570390286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
570490286Sobrien	(const_string "incdec")
570590286Sobrien	(const_string "alu")))
570690286Sobrien   (set_attr "mode" "SI")])
570718334Speter
5708132727Skan; For comparisons against 1, -1 and 128, we may generate better code
570990286Sobrien; by converting cmp to add, inc or dec as done by peephole2.  This pattern
571090286Sobrien; is matched then.  We can't accept general immediate, because for
571190286Sobrien; case of overflows,  the result is messed up.
571290286Sobrien; This pattern also don't hold of 0x80000000, since the value overflows
571390286Sobrien; when negated.
571490286Sobrien; Also carry flag is reversed compared to cmp, so this conversion is valid
571590286Sobrien; only for comparisons not depending on it.
571690286Sobrien(define_insn "*addsi_4"
5717169699Skan  [(set (reg FLAGS_REG)
571890286Sobrien	(compare (match_operand:SI 1 "nonimmediate_operand" "0")
571990286Sobrien		 (match_operand:SI 2 "const_int_operand" "n")))
572090286Sobrien   (clobber (match_scratch:SI 0 "=rm"))]
572190286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
572290286Sobrien   && (INTVAL (operands[2]) & 0xffffffff) != 0x80000000"
572390286Sobrien{
572490286Sobrien  switch (get_attr_type (insn))
572518334Speter    {
572690286Sobrien    case TYPE_INCDEC:
572790286Sobrien      if (operands[2] == constm1_rtx)
572890286Sobrien        return "inc{l}\t%0";
572990286Sobrien      else
5730169699Skan        {
5731169699Skan	  gcc_assert (operands[2] == const1_rtx);
5732169699Skan          return "dec{l}\t%0";
5733169699Skan	}
573418334Speter
573590286Sobrien    default:
5736169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
573790286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
573890286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
573990286Sobrien      if ((INTVAL (operands[2]) == -128
574090286Sobrien	   || (INTVAL (operands[2]) > 0
574190286Sobrien	       && INTVAL (operands[2]) != 128)))
574290286Sobrien	return "sub{l}\t{%2, %0|%0, %2}";
574390286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
574490286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
574518334Speter    }
574690286Sobrien}
574790286Sobrien  [(set (attr "type")
574890286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
574990286Sobrien	(const_string "incdec")
575090286Sobrien	(const_string "alu")))
575190286Sobrien   (set_attr "mode" "SI")])
575218334Speter
575390286Sobrien(define_insn "*addsi_5"
5754169699Skan  [(set (reg FLAGS_REG)
575590286Sobrien	(compare
575690286Sobrien	  (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
575790286Sobrien		   (match_operand:SI 2 "general_operand" "rmni"))
575890286Sobrien	  (const_int 0)))			
575990286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
576090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
576190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
576290286Sobrien   /* Current assemblers are broken and do not allow @GOTOFF in
576390286Sobrien      ought but a memory context.  */
576490286Sobrien   && ! pic_symbolic_operand (operands[2], VOIDmode)"
576590286Sobrien{
576690286Sobrien  switch (get_attr_type (insn))
576718334Speter    {
576890286Sobrien    case TYPE_INCDEC:
5769169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
577090286Sobrien      if (operands[2] == const1_rtx)
577190286Sobrien        return "inc{l}\t%0";
577290286Sobrien      else
5773169699Skan        {
5774169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5775169699Skan          return "dec{l}\t%0";
5776169699Skan	}
577790286Sobrien
577890286Sobrien    default:
5779169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
578090286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
578190286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
578290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
578390286Sobrien          && (INTVAL (operands[2]) == 128
578490286Sobrien	      || (INTVAL (operands[2]) < 0
578590286Sobrien		  && INTVAL (operands[2]) != -128)))
578690286Sobrien        {
578790286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
578890286Sobrien          return "sub{l}\t{%2, %0|%0, %2}";
578990286Sobrien        }
579090286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
579118334Speter    }
579290286Sobrien}
579390286Sobrien  [(set (attr "type")
579490286Sobrien     (if_then_else (match_operand:SI 2 "incdec_operand" "")
579590286Sobrien	(const_string "incdec")
579690286Sobrien	(const_string "alu")))
579790286Sobrien   (set_attr "mode" "SI")])
579818334Speter
579990286Sobrien(define_expand "addhi3"
580090286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
580190286Sobrien		   (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
580290286Sobrien			    (match_operand:HI 2 "general_operand" "")))
5803169699Skan	      (clobber (reg:CC FLAGS_REG))])]
580490286Sobrien  "TARGET_HIMODE_MATH"
580590286Sobrien  "ix86_expand_binary_operator (PLUS, HImode, operands); DONE;")
580618334Speter
580790286Sobrien;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah
580890286Sobrien;; type optimizations enabled by define-splits.  This is not important
580990286Sobrien;; for PII, and in fact harmful because of partial register stalls.
581018334Speter
581190286Sobrien(define_insn "*addhi_1_lea"
581290286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
581390286Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
5814169699Skan		 (match_operand:HI 2 "general_operand" "ri,rm,lni")))
5815169699Skan   (clobber (reg:CC FLAGS_REG))]
581690286Sobrien  "!TARGET_PARTIAL_REG_STALL
581790286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
581890286Sobrien{
581990286Sobrien  switch (get_attr_type (insn))
582090286Sobrien    {
582190286Sobrien    case TYPE_LEA:
582290286Sobrien      return "#";
582390286Sobrien    case TYPE_INCDEC:
582490286Sobrien      if (operands[2] == const1_rtx)
582590286Sobrien	return "inc{w}\t%0";
5826169699Skan      else
5827169699Skan	{
5828169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5829169699Skan	  return "dec{w}\t%0";
5830169699Skan	}
583118334Speter
583290286Sobrien    default:
583390286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
583490286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
583590286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
583690286Sobrien          && (INTVAL (operands[2]) == 128
583790286Sobrien	      || (INTVAL (operands[2]) < 0
583890286Sobrien		  && INTVAL (operands[2]) != -128)))
583990286Sobrien	{
584090286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
584190286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
584290286Sobrien	}
584390286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
584490286Sobrien    }
584590286Sobrien}
584690286Sobrien  [(set (attr "type")
584790286Sobrien     (if_then_else (eq_attr "alternative" "2")
584890286Sobrien	(const_string "lea")
584990286Sobrien	(if_then_else (match_operand:HI 2 "incdec_operand" "")
585090286Sobrien	   (const_string "incdec")
585190286Sobrien	   (const_string "alu"))))
585290286Sobrien   (set_attr "mode" "HI,HI,SI")])
585350650Sobrien
585490286Sobrien(define_insn "*addhi_1"
585590286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
585690286Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
585790286Sobrien		 (match_operand:HI 2 "general_operand" "ri,rm")))
5858169699Skan   (clobber (reg:CC FLAGS_REG))]
585990286Sobrien  "TARGET_PARTIAL_REG_STALL
586090286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
586118334Speter{
586290286Sobrien  switch (get_attr_type (insn))
586318334Speter    {
586490286Sobrien    case TYPE_INCDEC:
586590286Sobrien      if (operands[2] == const1_rtx)
586690286Sobrien	return "inc{w}\t%0";
5867169699Skan      else
5868169699Skan        {
5869169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5870169699Skan	  return "dec{w}\t%0";
5871169699Skan	}
587218334Speter
587390286Sobrien    default:
587490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
587590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
587690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
587790286Sobrien          && (INTVAL (operands[2]) == 128
587890286Sobrien	      || (INTVAL (operands[2]) < 0
587990286Sobrien		  && INTVAL (operands[2]) != -128)))
588018334Speter	{
588190286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
588290286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
588318334Speter	}
588490286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
588590286Sobrien    }
588690286Sobrien}
588790286Sobrien  [(set (attr "type")
588890286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
588990286Sobrien	(const_string "incdec")
589090286Sobrien	(const_string "alu")))
589190286Sobrien   (set_attr "mode" "HI")])
589218334Speter
589390286Sobrien(define_insn "*addhi_2"
5894169699Skan  [(set (reg FLAGS_REG)
589590286Sobrien	(compare
589690286Sobrien	  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
589790286Sobrien		   (match_operand:HI 2 "general_operand" "rmni,rni"))
589890286Sobrien	  (const_int 0)))			
589990286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
590090286Sobrien	(plus:HI (match_dup 1) (match_dup 2)))]
590190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
590290286Sobrien   && ix86_binary_operator_ok (PLUS, HImode, operands)"
590390286Sobrien{
590490286Sobrien  switch (get_attr_type (insn))
590590286Sobrien    {
590690286Sobrien    case TYPE_INCDEC:
590790286Sobrien      if (operands[2] == const1_rtx)
590890286Sobrien	return "inc{w}\t%0";
5909169699Skan      else
5910169699Skan        {
5911169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5912169699Skan	  return "dec{w}\t%0";
5913169699Skan	}
591490286Sobrien
591590286Sobrien    default:
591690286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
591790286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
591890286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
591990286Sobrien          && (INTVAL (operands[2]) == 128
592090286Sobrien	      || (INTVAL (operands[2]) < 0
592190286Sobrien		  && INTVAL (operands[2]) != -128)))
592218334Speter	{
592390286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
592490286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
592518334Speter	}
592690286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
592718334Speter    }
592890286Sobrien}
592990286Sobrien  [(set (attr "type")
593090286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
593190286Sobrien	(const_string "incdec")
593290286Sobrien	(const_string "alu")))
593390286Sobrien   (set_attr "mode" "HI")])
593418334Speter
593590286Sobrien(define_insn "*addhi_3"
5936169699Skan  [(set (reg FLAGS_REG)
593790286Sobrien	(compare (neg:HI (match_operand:HI 2 "general_operand" "rmni"))
593890286Sobrien		 (match_operand:HI 1 "nonimmediate_operand" "%0")))
593990286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
594090286Sobrien  "ix86_match_ccmode (insn, CCZmode)
594190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
594290286Sobrien{
594390286Sobrien  switch (get_attr_type (insn))
594490286Sobrien    {
594590286Sobrien    case TYPE_INCDEC:
594690286Sobrien      if (operands[2] == const1_rtx)
594790286Sobrien	return "inc{w}\t%0";
5948169699Skan      else
5949169699Skan        {
5950169699Skan	  gcc_assert (operands[2] == constm1_rtx);
5951169699Skan	  return "dec{w}\t%0";
5952169699Skan	}
595350650Sobrien
595490286Sobrien    default:
595590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
595690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
595790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
595890286Sobrien          && (INTVAL (operands[2]) == 128
595990286Sobrien	      || (INTVAL (operands[2]) < 0
596090286Sobrien		  && INTVAL (operands[2]) != -128)))
596190286Sobrien	{
596290286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
596390286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
596490286Sobrien	}
596590286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
596690286Sobrien    }
596790286Sobrien}
596890286Sobrien  [(set (attr "type")
596990286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
597090286Sobrien	(const_string "incdec")
597190286Sobrien	(const_string "alu")))
597290286Sobrien   (set_attr "mode" "HI")])
597318334Speter
5974169699Skan; See comments above addsi_4 for details.
597590286Sobrien(define_insn "*addhi_4"
5976169699Skan  [(set (reg FLAGS_REG)
597790286Sobrien	(compare (match_operand:HI 1 "nonimmediate_operand" "0")
597890286Sobrien		 (match_operand:HI 2 "const_int_operand" "n")))
597990286Sobrien   (clobber (match_scratch:HI 0 "=rm"))]
598090286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
598190286Sobrien   && (INTVAL (operands[2]) & 0xffff) != 0x8000"
598290286Sobrien{
598390286Sobrien  switch (get_attr_type (insn))
598490286Sobrien    {
598590286Sobrien    case TYPE_INCDEC:
5986117404Skan      if (operands[2] == constm1_rtx)
598790286Sobrien        return "inc{w}\t%0";
598890286Sobrien      else
5989169699Skan	{
5990169699Skan	  gcc_assert (operands[2] == const1_rtx);
5991169699Skan          return "dec{w}\t%0";
5992169699Skan	}
599318334Speter
599490286Sobrien    default:
5995169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
599690286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
599790286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
599890286Sobrien      if ((INTVAL (operands[2]) == -128
599990286Sobrien	   || (INTVAL (operands[2]) > 0
600090286Sobrien	       && INTVAL (operands[2]) != 128)))
600190286Sobrien	return "sub{w}\t{%2, %0|%0, %2}";
600290286Sobrien      operands[2] = GEN_INT (-INTVAL (operands[2]));
600390286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
600450650Sobrien    }
600590286Sobrien}
600690286Sobrien  [(set (attr "type")
600790286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
600890286Sobrien	(const_string "incdec")
600990286Sobrien	(const_string "alu")))
601090286Sobrien   (set_attr "mode" "SI")])
601150650Sobrien
601218334Speter
601390286Sobrien(define_insn "*addhi_5"
6014169699Skan  [(set (reg FLAGS_REG)
601590286Sobrien	(compare
601690286Sobrien	  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
601790286Sobrien		   (match_operand:HI 2 "general_operand" "rmni"))
601890286Sobrien	  (const_int 0)))			
601990286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
602090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
602190286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
602250650Sobrien{
602390286Sobrien  switch (get_attr_type (insn))
602450650Sobrien    {
602590286Sobrien    case TYPE_INCDEC:
602690286Sobrien      if (operands[2] == const1_rtx)
602790286Sobrien	return "inc{w}\t%0";
6028169699Skan      else
6029169699Skan	{
6030169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6031169699Skan	  return "dec{w}\t%0";
6032169699Skan	}
603350650Sobrien
603490286Sobrien    default:
603590286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
603690286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
603790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
603890286Sobrien          && (INTVAL (operands[2]) == 128
603990286Sobrien	      || (INTVAL (operands[2]) < 0
604090286Sobrien		  && INTVAL (operands[2]) != -128)))
604190286Sobrien	{
604290286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
604390286Sobrien	  return "sub{w}\t{%2, %0|%0, %2}";
604490286Sobrien	}
604590286Sobrien      return "add{w}\t{%2, %0|%0, %2}";
604650650Sobrien    }
604790286Sobrien}
604890286Sobrien  [(set (attr "type")
604990286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
605090286Sobrien	(const_string "incdec")
605190286Sobrien	(const_string "alu")))
605290286Sobrien   (set_attr "mode" "HI")])
605350650Sobrien
605490286Sobrien(define_expand "addqi3"
605590286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
605690286Sobrien		   (plus:QI (match_operand:QI 1 "nonimmediate_operand" "")
605790286Sobrien			    (match_operand:QI 2 "general_operand" "")))
6058169699Skan	      (clobber (reg:CC FLAGS_REG))])]
605990286Sobrien  "TARGET_QIMODE_MATH"
606090286Sobrien  "ix86_expand_binary_operator (PLUS, QImode, operands); DONE;")
606150650Sobrien
606290286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
606390286Sobrien(define_insn "*addqi_1_lea"
606490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r")
606590286Sobrien	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r")
6066169699Skan		 (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln")))
6067169699Skan   (clobber (reg:CC FLAGS_REG))]
606890286Sobrien  "!TARGET_PARTIAL_REG_STALL
606990286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
607090286Sobrien{
607190286Sobrien  int widen = (which_alternative == 2);
607290286Sobrien  switch (get_attr_type (insn))
607390286Sobrien    {
607490286Sobrien    case TYPE_LEA:
607590286Sobrien      return "#";
607690286Sobrien    case TYPE_INCDEC:
607790286Sobrien      if (operands[2] == const1_rtx)
607890286Sobrien	return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
6079169699Skan      else
6080169699Skan	{
6081169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6082169699Skan	  return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
6083169699Skan	}
608418334Speter
608590286Sobrien    default:
608690286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
608790286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
608890286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
608990286Sobrien          && (INTVAL (operands[2]) == 128
609090286Sobrien	      || (INTVAL (operands[2]) < 0
609190286Sobrien		  && INTVAL (operands[2]) != -128)))
609290286Sobrien	{
609390286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
609490286Sobrien	  if (widen)
609590286Sobrien	    return "sub{l}\t{%2, %k0|%k0, %2}";
609690286Sobrien	  else
609790286Sobrien	    return "sub{b}\t{%2, %0|%0, %2}";
609890286Sobrien	}
609990286Sobrien      if (widen)
610090286Sobrien        return "add{l}\t{%k2, %k0|%k0, %k2}";
610190286Sobrien      else
610290286Sobrien        return "add{b}\t{%2, %0|%0, %2}";
610390286Sobrien    }
610490286Sobrien}
610590286Sobrien  [(set (attr "type")
610690286Sobrien     (if_then_else (eq_attr "alternative" "3")
610790286Sobrien	(const_string "lea")
610890286Sobrien	(if_then_else (match_operand:QI 2 "incdec_operand" "")
610990286Sobrien	   (const_string "incdec")
611090286Sobrien	   (const_string "alu"))))
611190286Sobrien   (set_attr "mode" "QI,QI,SI,SI")])
611250650Sobrien
611390286Sobrien(define_insn "*addqi_1"
611490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
611590286Sobrien	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
611690286Sobrien		 (match_operand:QI 2 "general_operand" "qn,qmn,rn")))
6117169699Skan   (clobber (reg:CC FLAGS_REG))]
611890286Sobrien  "TARGET_PARTIAL_REG_STALL
611990286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
612018334Speter{
612190286Sobrien  int widen = (which_alternative == 2);
612290286Sobrien  switch (get_attr_type (insn))
612352296Sobrien    {
612490286Sobrien    case TYPE_INCDEC:
612590286Sobrien      if (operands[2] == const1_rtx)
612690286Sobrien	return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
6127169699Skan      else
6128169699Skan	{
6129169699Skan	  gcc_assert (operands[2] == constm1_rtx);
6130169699Skan	  return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
6131169699Skan	}
613252296Sobrien
613390286Sobrien    default:
613490286Sobrien      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
613590286Sobrien	 Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
613690286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
613790286Sobrien          && (INTVAL (operands[2]) == 128
613890286Sobrien	      || (INTVAL (operands[2]) < 0
613990286Sobrien		  && INTVAL (operands[2]) != -128)))
614090286Sobrien	{
614190286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
614290286Sobrien	  if (widen)
614390286Sobrien	    return "sub{l}\t{%2, %k0|%k0, %2}";
614490286Sobrien	  else
614590286Sobrien	    return "sub{b}\t{%2, %0|%0, %2}";
614690286Sobrien	}
614790286Sobrien      if (widen)
614890286Sobrien        return "add{l}\t{%k2, %k0|%k0, %k2}";
614990286Sobrien      else
615090286Sobrien        return "add{b}\t{%2, %0|%0, %2}";
615152296Sobrien    }
615290286Sobrien}
615390286Sobrien  [(set (attr "type")
615490286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
615590286Sobrien	(const_string "incdec")
615690286Sobrien	(const_string "alu")))
615790286Sobrien   (set_attr "mode" "QI,QI,SI")])
615852296Sobrien
6159117404Skan(define_insn "*addqi_1_slp"
6160117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
6161117404Skan	(plus:QI (match_dup 0)
6162117404Skan		 (match_operand:QI 1 "general_operand" "qn,qnm")))
6163169699Skan   (clobber (reg:CC FLAGS_REG))]
6164117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
6165117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
6166117404Skan{
6167117404Skan  switch (get_attr_type (insn))
6168117404Skan    {
6169117404Skan    case TYPE_INCDEC:
6170117404Skan      if (operands[1] == const1_rtx)
6171117404Skan	return "inc{b}\t%0";
6172169699Skan      else
6173169699Skan	{
6174169699Skan	  gcc_assert (operands[1] == constm1_rtx);
6175169699Skan	  return "dec{b}\t%0";
6176169699Skan	}
6177117404Skan
6178117404Skan    default:
6179117404Skan      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.  */
6180117404Skan      if (GET_CODE (operands[1]) == CONST_INT
6181117404Skan	  && INTVAL (operands[1]) < 0)
6182117404Skan	{
6183132727Skan	  operands[1] = GEN_INT (-INTVAL (operands[1]));
6184117404Skan	  return "sub{b}\t{%1, %0|%0, %1}";
6185117404Skan	}
6186117404Skan      return "add{b}\t{%1, %0|%0, %1}";
6187117404Skan    }
6188117404Skan}
6189117404Skan  [(set (attr "type")
6190146906Skan     (if_then_else (match_operand:QI 1 "incdec_operand" "")
6191117404Skan	(const_string "incdec")
6192117404Skan	(const_string "alu1")))
6193146906Skan   (set (attr "memory")
6194146906Skan     (if_then_else (match_operand 1 "memory_operand" "")
6195146906Skan        (const_string "load")
6196146906Skan        (const_string "none")))
6197117404Skan   (set_attr "mode" "QI")])
6198117404Skan
619990286Sobrien(define_insn "*addqi_2"
6200169699Skan  [(set (reg FLAGS_REG)
620190286Sobrien	(compare
620290286Sobrien	  (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
620390286Sobrien		   (match_operand:QI 2 "general_operand" "qmni,qni"))
620490286Sobrien	  (const_int 0)))
620590286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
620690286Sobrien	(plus:QI (match_dup 1) (match_dup 2)))]
620790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
620890286Sobrien   && ix86_binary_operator_ok (PLUS, QImode, operands)"
620990286Sobrien{
621090286Sobrien  switch (get_attr_type (insn))
621118334Speter    {
621290286Sobrien    case TYPE_INCDEC:
621390286Sobrien      if (operands[2] == const1_rtx)
621490286Sobrien	return "inc{b}\t%0";
6215169699Skan      else
6216169699Skan        {
6217169699Skan	  gcc_assert (operands[2] == constm1_rtx
6218169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6219169699Skan		          && INTVAL (operands[2]) == 255));
6220169699Skan	  return "dec{b}\t%0";
6221169699Skan	}
622218334Speter
622390286Sobrien    default:
622490286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
622590286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
622690286Sobrien          && INTVAL (operands[2]) < 0)
622790286Sobrien	{
622890286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
622990286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
623090286Sobrien	}
623190286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
623218334Speter    }
623390286Sobrien}
623490286Sobrien  [(set (attr "type")
623590286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
623690286Sobrien	(const_string "incdec")
623790286Sobrien	(const_string "alu")))
623890286Sobrien   (set_attr "mode" "QI")])
623918334Speter
624090286Sobrien(define_insn "*addqi_3"
6241169699Skan  [(set (reg FLAGS_REG)
624290286Sobrien	(compare (neg:QI (match_operand:QI 2 "general_operand" "qmni"))
624390286Sobrien		 (match_operand:QI 1 "nonimmediate_operand" "%0")))
624490286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
624590286Sobrien  "ix86_match_ccmode (insn, CCZmode)
624690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
624790286Sobrien{
624890286Sobrien  switch (get_attr_type (insn))
624950650Sobrien    {
625090286Sobrien    case TYPE_INCDEC:
625190286Sobrien      if (operands[2] == const1_rtx)
625290286Sobrien	return "inc{b}\t%0";
6253169699Skan      else
6254169699Skan        {
6255169699Skan	  gcc_assert (operands[2] == constm1_rtx
6256169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6257169699Skan			  && INTVAL (operands[2]) == 255));
6258169699Skan	  return "dec{b}\t%0";
6259169699Skan	}
626050650Sobrien
626190286Sobrien    default:
626290286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
626390286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
626490286Sobrien          && INTVAL (operands[2]) < 0)
626550650Sobrien	{
626690286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
626790286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
626890286Sobrien	}
626990286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
627090286Sobrien    }
627190286Sobrien}
627290286Sobrien  [(set (attr "type")
627390286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
627490286Sobrien	(const_string "incdec")
627590286Sobrien	(const_string "alu")))
627690286Sobrien   (set_attr "mode" "QI")])
627750650Sobrien
6278169699Skan; See comments above addsi_4 for details.
627990286Sobrien(define_insn "*addqi_4"
6280169699Skan  [(set (reg FLAGS_REG)
628190286Sobrien	(compare (match_operand:QI 1 "nonimmediate_operand" "0")
628290286Sobrien		 (match_operand:QI 2 "const_int_operand" "n")))
628390286Sobrien   (clobber (match_scratch:QI 0 "=qm"))]
628490286Sobrien  "ix86_match_ccmode (insn, CCGCmode)
628590286Sobrien   && (INTVAL (operands[2]) & 0xff) != 0x80"
628690286Sobrien{
628790286Sobrien  switch (get_attr_type (insn))
628890286Sobrien    {
628990286Sobrien    case TYPE_INCDEC:
629090286Sobrien      if (operands[2] == constm1_rtx
629190286Sobrien	  || (GET_CODE (operands[2]) == CONST_INT
629290286Sobrien	      && INTVAL (operands[2]) == 255))
629390286Sobrien        return "inc{b}\t%0";
629490286Sobrien      else
6295169699Skan	{
6296169699Skan	  gcc_assert (operands[2] == const1_rtx);
6297169699Skan          return "dec{b}\t%0";
6298169699Skan	}
629950650Sobrien
630090286Sobrien    default:
6301169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
630290286Sobrien      if (INTVAL (operands[2]) < 0)
630390286Sobrien        {
630490286Sobrien          operands[2] = GEN_INT (-INTVAL (operands[2]));
630590286Sobrien          return "add{b}\t{%2, %0|%0, %2}";
630690286Sobrien        }
630790286Sobrien      return "sub{b}\t{%2, %0|%0, %2}";
630850650Sobrien    }
630990286Sobrien}
631090286Sobrien  [(set (attr "type")
631190286Sobrien     (if_then_else (match_operand:HI 2 "incdec_operand" "")
631290286Sobrien	(const_string "incdec")
631390286Sobrien	(const_string "alu")))
631490286Sobrien   (set_attr "mode" "QI")])
631550650Sobrien
631618334Speter
631790286Sobrien(define_insn "*addqi_5"
6318169699Skan  [(set (reg FLAGS_REG)
631990286Sobrien	(compare
632090286Sobrien	  (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
632190286Sobrien		   (match_operand:QI 2 "general_operand" "qmni"))
632290286Sobrien	  (const_int 0)))
632390286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
632490286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
632590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
632690286Sobrien{
632790286Sobrien  switch (get_attr_type (insn))
632890286Sobrien    {
632990286Sobrien    case TYPE_INCDEC:
633090286Sobrien      if (operands[2] == const1_rtx)
633190286Sobrien	return "inc{b}\t%0";
6332169699Skan      else
6333169699Skan        {
6334169699Skan	  gcc_assert (operands[2] == constm1_rtx
6335169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6336169699Skan			  && INTVAL (operands[2]) == 255));
6337169699Skan	  return "dec{b}\t%0";
6338169699Skan	}
633918334Speter
634090286Sobrien    default:
634190286Sobrien      /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'.  */
634290286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
634390286Sobrien          && INTVAL (operands[2]) < 0)
634490286Sobrien	{
634590286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
634690286Sobrien	  return "sub{b}\t{%2, %0|%0, %2}";
634790286Sobrien	}
634890286Sobrien      return "add{b}\t{%2, %0|%0, %2}";
634990286Sobrien    }
635090286Sobrien}
635190286Sobrien  [(set (attr "type")
635290286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
635390286Sobrien	(const_string "incdec")
635490286Sobrien	(const_string "alu")))
635590286Sobrien   (set_attr "mode" "QI")])
635618334Speter
635750650Sobrien
635890286Sobrien(define_insn "addqi_ext_1"
635990286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
636090286Sobrien			 (const_int 8)
636190286Sobrien			 (const_int 8))
636290286Sobrien	(plus:SI
636390286Sobrien	  (zero_extract:SI
636490286Sobrien	    (match_operand 1 "ext_register_operand" "0")
636590286Sobrien	    (const_int 8)
636690286Sobrien	    (const_int 8))
636790286Sobrien	  (match_operand:QI 2 "general_operand" "Qmn")))
6368169699Skan   (clobber (reg:CC FLAGS_REG))]
636990286Sobrien  "!TARGET_64BIT"
637018334Speter{
637190286Sobrien  switch (get_attr_type (insn))
637252296Sobrien    {
637390286Sobrien    case TYPE_INCDEC:
637490286Sobrien      if (operands[2] == const1_rtx)
637590286Sobrien	return "inc{b}\t%h0";
6376169699Skan      else
6377169699Skan        {
6378169699Skan	  gcc_assert (operands[2] == constm1_rtx
6379169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6380169699Skan			  && INTVAL (operands[2]) == 255));
6381169699Skan          return "dec{b}\t%h0";
6382169699Skan	}
638352296Sobrien
638490286Sobrien    default:
638590286Sobrien      return "add{b}\t{%2, %h0|%h0, %2}";
638652296Sobrien    }
638790286Sobrien}
638890286Sobrien  [(set (attr "type")
638990286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
639090286Sobrien	(const_string "incdec")
639190286Sobrien	(const_string "alu")))
639290286Sobrien   (set_attr "mode" "QI")])
639318334Speter
639490286Sobrien(define_insn "*addqi_ext_1_rex64"
639590286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
639690286Sobrien			 (const_int 8)
639790286Sobrien			 (const_int 8))
639890286Sobrien	(plus:SI
639990286Sobrien	  (zero_extract:SI
640090286Sobrien	    (match_operand 1 "ext_register_operand" "0")
640190286Sobrien	    (const_int 8)
640290286Sobrien	    (const_int 8))
640390286Sobrien	  (match_operand:QI 2 "nonmemory_operand" "Qn")))
6404169699Skan   (clobber (reg:CC FLAGS_REG))]
640590286Sobrien  "TARGET_64BIT"
640690286Sobrien{
640790286Sobrien  switch (get_attr_type (insn))
640890286Sobrien    {
640990286Sobrien    case TYPE_INCDEC:
641090286Sobrien      if (operands[2] == const1_rtx)
641190286Sobrien	return "inc{b}\t%h0";
6412169699Skan      else
6413169699Skan        {
6414169699Skan	  gcc_assert (operands[2] == constm1_rtx
6415169699Skan		      || (GET_CODE (operands[2]) == CONST_INT
6416169699Skan			  && INTVAL (operands[2]) == 255));
6417169699Skan          return "dec{b}\t%h0";
6418169699Skan        }
641918334Speter
642090286Sobrien    default:
642190286Sobrien      return "add{b}\t{%2, %h0|%h0, %2}";
642290286Sobrien    }
642390286Sobrien}
642490286Sobrien  [(set (attr "type")
642590286Sobrien     (if_then_else (match_operand:QI 2 "incdec_operand" "")
642690286Sobrien	(const_string "incdec")
642790286Sobrien	(const_string "alu")))
642890286Sobrien   (set_attr "mode" "QI")])
642918334Speter
643090286Sobrien(define_insn "*addqi_ext_2"
643190286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
643290286Sobrien			 (const_int 8)
643390286Sobrien			 (const_int 8))
643490286Sobrien	(plus:SI
643590286Sobrien	  (zero_extract:SI
643690286Sobrien	    (match_operand 1 "ext_register_operand" "%0")
643790286Sobrien	    (const_int 8)
643890286Sobrien	    (const_int 8))
643990286Sobrien	  (zero_extract:SI
644090286Sobrien	    (match_operand 2 "ext_register_operand" "Q")
644190286Sobrien	    (const_int 8)
644290286Sobrien	    (const_int 8))))
6443169699Skan   (clobber (reg:CC FLAGS_REG))]
644490286Sobrien  ""
644590286Sobrien  "add{b}\t{%h2, %h0|%h0, %h2}"
644690286Sobrien  [(set_attr "type" "alu")
644790286Sobrien   (set_attr "mode" "QI")])
644818334Speter
644918334Speter;; The patterns that match these are at the end of this file.
645018334Speter
645118334Speter(define_expand "addxf3"
645218334Speter  [(set (match_operand:XF 0 "register_operand" "")
645350650Sobrien	(plus:XF (match_operand:XF 1 "register_operand" "")
645450650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
645518334Speter  "TARGET_80387"
645618334Speter  "")
645718334Speter
645818334Speter(define_expand "adddf3"
645918334Speter  [(set (match_operand:DF 0 "register_operand" "")
646090286Sobrien	(plus:DF (match_operand:DF 1 "register_operand" "")
646118334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
646290286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
646318334Speter  "")
646418334Speter
646518334Speter(define_expand "addsf3"
646618334Speter  [(set (match_operand:SF 0 "register_operand" "")
646790286Sobrien	(plus:SF (match_operand:SF 1 "register_operand" "")
646818334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
646990286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
647018334Speter  "")
647118334Speter
647290286Sobrien;; Subtract instructions
647318334Speter
6474169699Skan;; %%% splits for subditi3
6475169699Skan
6476169699Skan(define_expand "subti3"
6477169699Skan  [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
6478169699Skan		   (minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
6479169699Skan			     (match_operand:TI 2 "x86_64_general_operand" "")))
6480169699Skan	      (clobber (reg:CC FLAGS_REG))])]
6481169699Skan  "TARGET_64BIT"
6482169699Skan  "ix86_expand_binary_operator (MINUS, TImode, operands); DONE;")
6483169699Skan
6484169699Skan(define_insn "*subti3_1"
6485169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
6486169699Skan	(minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0")
6487171835Skan		  (match_operand:TI 2 "x86_64_general_operand" "roe,re")))
6488169699Skan   (clobber (reg:CC FLAGS_REG))]
6489169699Skan  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)"
6490169699Skan  "#")
6491169699Skan
6492169699Skan(define_split
6493169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
6494169699Skan	(minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
6495171835Skan		  (match_operand:TI 2 "x86_64_general_operand" "")))
6496169699Skan   (clobber (reg:CC FLAGS_REG))]
6497169699Skan  "TARGET_64BIT && reload_completed"
6498169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
6499169699Skan	      (set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))])
6500169699Skan   (parallel [(set (match_dup 3)
6501169699Skan		   (minus:DI (match_dup 4)
6502169699Skan			     (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
6503169699Skan				      (match_dup 5))))
6504169699Skan	      (clobber (reg:CC FLAGS_REG))])]
6505169699Skan  "split_ti (operands+0, 1, operands+0, operands+3);
6506169699Skan   split_ti (operands+1, 1, operands+1, operands+4);
6507169699Skan   split_ti (operands+2, 1, operands+2, operands+5);")
6508169699Skan
650990286Sobrien;; %%% splits for subsidi3
651050650Sobrien
651190286Sobrien(define_expand "subdi3"
651290286Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
651390286Sobrien		   (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
651490286Sobrien			     (match_operand:DI 2 "x86_64_general_operand" "")))
6515169699Skan	      (clobber (reg:CC FLAGS_REG))])]
651618334Speter  ""
651790286Sobrien  "ix86_expand_binary_operator (MINUS, DImode, operands); DONE;")
651818334Speter
651990286Sobrien(define_insn "*subdi3_1"
652090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
652190286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
652290286Sobrien		  (match_operand:DI 2 "general_operand" "roiF,riF")))
6523169699Skan   (clobber (reg:CC FLAGS_REG))]
6524107605Sobrien  "!TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
652590286Sobrien  "#")
652618334Speter
652790286Sobrien(define_split
652890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
652990286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
653090286Sobrien		  (match_operand:DI 2 "general_operand" "")))
6531169699Skan   (clobber (reg:CC FLAGS_REG))]
653290286Sobrien  "!TARGET_64BIT && reload_completed"
6533169699Skan  [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
653490286Sobrien	      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
653590286Sobrien   (parallel [(set (match_dup 3)
653690286Sobrien		   (minus:SI (match_dup 4)
6537169699Skan			     (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
653890286Sobrien				      (match_dup 5))))
6539169699Skan	      (clobber (reg:CC FLAGS_REG))])]
654090286Sobrien  "split_di (operands+0, 1, operands+0, operands+3);
654190286Sobrien   split_di (operands+1, 1, operands+1, operands+4);
654290286Sobrien   split_di (operands+2, 1, operands+2, operands+5);")
654318334Speter
654490286Sobrien(define_insn "subdi3_carry_rex64"
654590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
654690286Sobrien	  (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
6547132727Skan	    (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
654890286Sobrien	       (match_operand:DI 2 "x86_64_general_operand" "re,rm"))))
6549169699Skan   (clobber (reg:CC FLAGS_REG))]
655090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
655190286Sobrien  "sbb{q}\t{%2, %0|%0, %2}"
655290286Sobrien  [(set_attr "type" "alu")
655390286Sobrien   (set_attr "pent_pair" "pu")
655490286Sobrien   (set_attr "mode" "DI")])
655518334Speter
655690286Sobrien(define_insn "*subdi_1_rex64"
655790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
655890286Sobrien	(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
655990286Sobrien		  (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
6560169699Skan   (clobber (reg:CC FLAGS_REG))]
656190286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
656290286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
656390286Sobrien  [(set_attr "type" "alu")
656490286Sobrien   (set_attr "mode" "DI")])
656518334Speter
656690286Sobrien(define_insn "*subdi_2_rex64"
6567169699Skan  [(set (reg FLAGS_REG)
656890286Sobrien	(compare
656990286Sobrien	  (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
657090286Sobrien		    (match_operand:DI 2 "x86_64_general_operand" "re,rm"))
657190286Sobrien	  (const_int 0)))
657290286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
657390286Sobrien	(minus:DI (match_dup 1) (match_dup 2)))]
657490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
657590286Sobrien   && ix86_binary_operator_ok (MINUS, DImode, operands)"
657690286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
657790286Sobrien  [(set_attr "type" "alu")
657890286Sobrien   (set_attr "mode" "DI")])
657952296Sobrien
658090286Sobrien(define_insn "*subdi_3_rex63"
6581169699Skan  [(set (reg FLAGS_REG)
658290286Sobrien	(compare (match_operand:DI 1 "nonimmediate_operand" "0,0")
658390286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
658490286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
658590286Sobrien	(minus:DI (match_dup 1) (match_dup 2)))]
658690286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
658790286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
658890286Sobrien  "sub{q}\t{%2, %0|%0, %2}"
658990286Sobrien  [(set_attr "type" "alu")
659090286Sobrien   (set_attr "mode" "DI")])
659118334Speter
6592132727Skan(define_insn "subqi3_carry"
6593132727Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
6594132727Skan	  (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
6595132727Skan	    (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
6596132727Skan	       (match_operand:QI 2 "general_operand" "qi,qm"))))
6597169699Skan   (clobber (reg:CC FLAGS_REG))]
6598132727Skan  "ix86_binary_operator_ok (MINUS, QImode, operands)"
6599132727Skan  "sbb{b}\t{%2, %0|%0, %2}"
6600132727Skan  [(set_attr "type" "alu")
6601132727Skan   (set_attr "pent_pair" "pu")
6602132727Skan   (set_attr "mode" "QI")])
660318334Speter
6604132727Skan(define_insn "subhi3_carry"
6605132727Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
6606132727Skan	  (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
6607132727Skan	    (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
6608132727Skan	       (match_operand:HI 2 "general_operand" "ri,rm"))))
6609169699Skan   (clobber (reg:CC FLAGS_REG))]
6610132727Skan  "ix86_binary_operator_ok (MINUS, HImode, operands)"
6611132727Skan  "sbb{w}\t{%2, %0|%0, %2}"
6612132727Skan  [(set_attr "type" "alu")
6613132727Skan   (set_attr "pent_pair" "pu")
6614132727Skan   (set_attr "mode" "HI")])
6615132727Skan
661690286Sobrien(define_insn "subsi3_carry"
661790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
661890286Sobrien	  (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6619132727Skan	    (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
662090286Sobrien	       (match_operand:SI 2 "general_operand" "ri,rm"))))
6621169699Skan   (clobber (reg:CC FLAGS_REG))]
662290286Sobrien  "ix86_binary_operator_ok (MINUS, SImode, operands)"
662390286Sobrien  "sbb{l}\t{%2, %0|%0, %2}"
662490286Sobrien  [(set_attr "type" "alu")
662590286Sobrien   (set_attr "pent_pair" "pu")
662690286Sobrien   (set_attr "mode" "SI")])
662718334Speter
662890286Sobrien(define_insn "subsi3_carry_zext"
662990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm,r")
663090286Sobrien	  (zero_extend:DI
663190286Sobrien	    (minus:SI (match_operand:SI 1 "register_operand" "0,0")
6632132727Skan	      (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
663390286Sobrien		 (match_operand:SI 2 "general_operand" "ri,rm")))))
6634169699Skan   (clobber (reg:CC FLAGS_REG))]
663590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
663690286Sobrien  "sbb{l}\t{%2, %k0|%k0, %2}"
663790286Sobrien  [(set_attr "type" "alu")
663890286Sobrien   (set_attr "pent_pair" "pu")
663990286Sobrien   (set_attr "mode" "SI")])
664018334Speter
664150650Sobrien(define_expand "subsi3"
664290286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
664390286Sobrien		   (minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
664490286Sobrien			     (match_operand:SI 2 "general_operand" "")))
6645169699Skan	      (clobber (reg:CC FLAGS_REG))])]
664650650Sobrien  ""
664790286Sobrien  "ix86_expand_binary_operator (MINUS, SImode, operands); DONE;")
664850650Sobrien
664990286Sobrien(define_insn "*subsi_1"
665050650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
665150650Sobrien	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
665290286Sobrien		  (match_operand:SI 2 "general_operand" "ri,rm")))
6653169699Skan   (clobber (reg:CC FLAGS_REG))]
665450650Sobrien  "ix86_binary_operator_ok (MINUS, SImode, operands)"
665590286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
665690286Sobrien  [(set_attr "type" "alu")
665790286Sobrien   (set_attr "mode" "SI")])
665818334Speter
665990286Sobrien(define_insn "*subsi_1_zext"
666090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
666190286Sobrien	(zero_extend:DI
666290286Sobrien	  (minus:SI (match_operand:SI 1 "register_operand" "0")
666390286Sobrien		    (match_operand:SI 2 "general_operand" "rim"))))
6664169699Skan   (clobber (reg:CC FLAGS_REG))]
666590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
666690286Sobrien  "sub{l}\t{%2, %k0|%k0, %2}"
666790286Sobrien  [(set_attr "type" "alu")
666890286Sobrien   (set_attr "mode" "SI")])
666990286Sobrien
667090286Sobrien(define_insn "*subsi_2"
6671169699Skan  [(set (reg FLAGS_REG)
667290286Sobrien	(compare
667390286Sobrien	  (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
667490286Sobrien		    (match_operand:SI 2 "general_operand" "ri,rm"))
667590286Sobrien	  (const_int 0)))
667690286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
667790286Sobrien	(minus:SI (match_dup 1) (match_dup 2)))]
667890286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
667990286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
668090286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
668190286Sobrien  [(set_attr "type" "alu")
668290286Sobrien   (set_attr "mode" "SI")])
668390286Sobrien
668490286Sobrien(define_insn "*subsi_2_zext"
6685169699Skan  [(set (reg FLAGS_REG)
668690286Sobrien	(compare
668790286Sobrien	  (minus:SI (match_operand:SI 1 "register_operand" "0")
668890286Sobrien		    (match_operand:SI 2 "general_operand" "rim"))
668990286Sobrien	  (const_int 0)))
669090286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
669190286Sobrien	(zero_extend:DI
669290286Sobrien	  (minus:SI (match_dup 1)
669390286Sobrien		    (match_dup 2))))]
669490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
669590286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
669690286Sobrien  "sub{l}\t{%2, %k0|%k0, %2}"
669790286Sobrien  [(set_attr "type" "alu")
669890286Sobrien   (set_attr "mode" "SI")])
669990286Sobrien
670090286Sobrien(define_insn "*subsi_3"
6701169699Skan  [(set (reg FLAGS_REG)
670290286Sobrien	(compare (match_operand:SI 1 "nonimmediate_operand" "0,0")
670390286Sobrien		 (match_operand:SI 2 "general_operand" "ri,rm")))
670490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
670590286Sobrien	(minus:SI (match_dup 1) (match_dup 2)))]
670690286Sobrien  "ix86_match_ccmode (insn, CCmode)
670790286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
670890286Sobrien  "sub{l}\t{%2, %0|%0, %2}"
670990286Sobrien  [(set_attr "type" "alu")
671090286Sobrien   (set_attr "mode" "SI")])
671190286Sobrien
671290286Sobrien(define_insn "*subsi_3_zext"
6713169699Skan  [(set (reg FLAGS_REG)
6714132727Skan	(compare (match_operand:SI 1 "register_operand" "0")
671590286Sobrien		 (match_operand:SI 2 "general_operand" "rim")))
671690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
671790286Sobrien	(zero_extend:DI
671890286Sobrien	  (minus:SI (match_dup 1)
671990286Sobrien		    (match_dup 2))))]
672090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
672190286Sobrien   && ix86_binary_operator_ok (MINUS, SImode, operands)"
6722169699Skan  "sub{l}\t{%2, %1|%1, %2}"
672390286Sobrien  [(set_attr "type" "alu")
672490286Sobrien   (set_attr "mode" "DI")])
672590286Sobrien
672650650Sobrien(define_expand "subhi3"
672790286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
672890286Sobrien		   (minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
672990286Sobrien			     (match_operand:HI 2 "general_operand" "")))
6730169699Skan	      (clobber (reg:CC FLAGS_REG))])]
673190286Sobrien  "TARGET_HIMODE_MATH"
673290286Sobrien  "ix86_expand_binary_operator (MINUS, HImode, operands); DONE;")
673350650Sobrien
673490286Sobrien(define_insn "*subhi_1"
673550650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
673650650Sobrien	(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
673790286Sobrien		  (match_operand:HI 2 "general_operand" "ri,rm")))
6738169699Skan   (clobber (reg:CC FLAGS_REG))]
673950650Sobrien  "ix86_binary_operator_ok (MINUS, HImode, operands)"
674090286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
674190286Sobrien  [(set_attr "type" "alu")
674290286Sobrien   (set_attr "mode" "HI")])
674350650Sobrien
674490286Sobrien(define_insn "*subhi_2"
6745169699Skan  [(set (reg FLAGS_REG)
674690286Sobrien	(compare
674790286Sobrien	  (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
674890286Sobrien		    (match_operand:HI 2 "general_operand" "ri,rm"))
674990286Sobrien	  (const_int 0)))
675090286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
675190286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
675290286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
675390286Sobrien   && ix86_binary_operator_ok (MINUS, HImode, operands)"
675490286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
675590286Sobrien  [(set_attr "type" "alu")
675690286Sobrien   (set_attr "mode" "HI")])
675790286Sobrien
675890286Sobrien(define_insn "*subhi_3"
6759169699Skan  [(set (reg FLAGS_REG)
676090286Sobrien	(compare (match_operand:HI 1 "nonimmediate_operand" "0,0")
676190286Sobrien		 (match_operand:HI 2 "general_operand" "ri,rm")))
676290286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
676390286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
676490286Sobrien  "ix86_match_ccmode (insn, CCmode)
676590286Sobrien   && ix86_binary_operator_ok (MINUS, HImode, operands)"
676690286Sobrien  "sub{w}\t{%2, %0|%0, %2}"
676790286Sobrien  [(set_attr "type" "alu")
676890286Sobrien   (set_attr "mode" "HI")])
676990286Sobrien
677050650Sobrien(define_expand "subqi3"
677190286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
677290286Sobrien		   (minus:QI (match_operand:QI 1 "nonimmediate_operand" "")
677390286Sobrien			     (match_operand:QI 2 "general_operand" "")))
6774169699Skan	      (clobber (reg:CC FLAGS_REG))])]
677590286Sobrien  "TARGET_QIMODE_MATH"
677690286Sobrien  "ix86_expand_binary_operator (MINUS, QImode, operands); DONE;")
677718334Speter
677890286Sobrien(define_insn "*subqi_1"
677950650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
678050650Sobrien	(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
678190286Sobrien		  (match_operand:QI 2 "general_operand" "qn,qmn")))
6782169699Skan   (clobber (reg:CC FLAGS_REG))]
678350650Sobrien  "ix86_binary_operator_ok (MINUS, QImode, operands)"
678490286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
678590286Sobrien  [(set_attr "type" "alu")
678690286Sobrien   (set_attr "mode" "QI")])
678718334Speter
6788117404Skan(define_insn "*subqi_1_slp"
6789117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
6790117404Skan	(minus:QI (match_dup 0)
6791117404Skan		  (match_operand:QI 1 "general_operand" "qn,qmn")))
6792169699Skan   (clobber (reg:CC FLAGS_REG))]
6793117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
6794117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
6795117404Skan  "sub{b}\t{%1, %0|%0, %1}"
6796117404Skan  [(set_attr "type" "alu1")
6797117404Skan   (set_attr "mode" "QI")])
6798117404Skan
679990286Sobrien(define_insn "*subqi_2"
6800169699Skan  [(set (reg FLAGS_REG)
680190286Sobrien	(compare
680290286Sobrien	  (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
680390286Sobrien		    (match_operand:QI 2 "general_operand" "qi,qm"))
680490286Sobrien	  (const_int 0)))
680590286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
680690286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
680790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
680890286Sobrien   && ix86_binary_operator_ok (MINUS, QImode, operands)"
680990286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
681090286Sobrien  [(set_attr "type" "alu")
681190286Sobrien   (set_attr "mode" "QI")])
681290286Sobrien
681390286Sobrien(define_insn "*subqi_3"
6814169699Skan  [(set (reg FLAGS_REG)
681590286Sobrien	(compare (match_operand:QI 1 "nonimmediate_operand" "0,0")
681690286Sobrien		 (match_operand:QI 2 "general_operand" "qi,qm")))
681790286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
681890286Sobrien	(minus:HI (match_dup 1) (match_dup 2)))]
681990286Sobrien  "ix86_match_ccmode (insn, CCmode)
682090286Sobrien   && ix86_binary_operator_ok (MINUS, QImode, operands)"
682190286Sobrien  "sub{b}\t{%2, %0|%0, %2}"
682290286Sobrien  [(set_attr "type" "alu")
682390286Sobrien   (set_attr "mode" "QI")])
682490286Sobrien
682518334Speter;; The patterns that match these are at the end of this file.
682618334Speter
682718334Speter(define_expand "subxf3"
682818334Speter  [(set (match_operand:XF 0 "register_operand" "")
682950650Sobrien	(minus:XF (match_operand:XF 1 "register_operand" "")
683050650Sobrien		  (match_operand:XF 2 "register_operand" "")))]
683118334Speter  "TARGET_80387"
683218334Speter  "")
683318334Speter
683418334Speter(define_expand "subdf3"
683518334Speter  [(set (match_operand:DF 0 "register_operand" "")
683690286Sobrien	(minus:DF (match_operand:DF 1 "register_operand" "")
683718334Speter		  (match_operand:DF 2 "nonimmediate_operand" "")))]
683890286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
683918334Speter  "")
684018334Speter
684118334Speter(define_expand "subsf3"
684218334Speter  [(set (match_operand:SF 0 "register_operand" "")
684390286Sobrien	(minus:SF (match_operand:SF 1 "register_operand" "")
684418334Speter		  (match_operand:SF 2 "nonimmediate_operand" "")))]
684590286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
684618334Speter  "")
684718334Speter
684890286Sobrien;; Multiply instructions
684918334Speter
685090286Sobrien(define_expand "muldi3"
685190286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
685290286Sobrien		   (mult:DI (match_operand:DI 1 "register_operand" "")
685390286Sobrien			    (match_operand:DI 2 "x86_64_general_operand" "")))
6854169699Skan	      (clobber (reg:CC FLAGS_REG))])]
685590286Sobrien  "TARGET_64BIT"
685690286Sobrien  "")
685718334Speter
685890286Sobrien(define_insn "*muldi3_1_rex64"
685990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6860132727Skan	(mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,rm,0")
686190286Sobrien		 (match_operand:DI 2 "x86_64_general_operand" "K,e,mr")))
6862169699Skan   (clobber (reg:CC FLAGS_REG))]
686390286Sobrien  "TARGET_64BIT
686490286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
686590286Sobrien  "@
686690286Sobrien   imul{q}\t{%2, %1, %0|%0, %1, %2}
686790286Sobrien   imul{q}\t{%2, %1, %0|%0, %1, %2}
686890286Sobrien   imul{q}\t{%2, %0|%0, %2}"
686990286Sobrien  [(set_attr "type" "imul")
687090286Sobrien   (set_attr "prefix_0f" "0,0,1")
6871132727Skan   (set (attr "athlon_decode")
6872132727Skan	(cond [(eq_attr "cpu" "athlon")
6873132727Skan		  (const_string "vector")
6874132727Skan	       (eq_attr "alternative" "1")
6875132727Skan		  (const_string "vector")
6876132727Skan	       (and (eq_attr "alternative" "2")
6877132727Skan		    (match_operand 1 "memory_operand" ""))
6878132727Skan		  (const_string "vector")]
6879132727Skan	      (const_string "direct")))
688090286Sobrien   (set_attr "mode" "DI")])
688118334Speter
688290286Sobrien(define_expand "mulsi3"
688390286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
688490286Sobrien		   (mult:SI (match_operand:SI 1 "register_operand" "")
688590286Sobrien			    (match_operand:SI 2 "general_operand" "")))
6886169699Skan	      (clobber (reg:CC FLAGS_REG))])]
688718334Speter  ""
688890286Sobrien  "")
688918334Speter
689090286Sobrien(define_insn "*mulsi3_1"
689190286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
6892132727Skan	(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
689390286Sobrien		 (match_operand:SI 2 "general_operand" "K,i,mr")))
6894169699Skan   (clobber (reg:CC FLAGS_REG))]
689590286Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
689690286Sobrien  "@
689790286Sobrien   imul{l}\t{%2, %1, %0|%0, %1, %2}
689890286Sobrien   imul{l}\t{%2, %1, %0|%0, %1, %2}
689990286Sobrien   imul{l}\t{%2, %0|%0, %2}"
690090286Sobrien  [(set_attr "type" "imul")
690190286Sobrien   (set_attr "prefix_0f" "0,0,1")
6902132727Skan   (set (attr "athlon_decode")
6903132727Skan	(cond [(eq_attr "cpu" "athlon")
6904132727Skan		  (const_string "vector")
6905132727Skan	       (eq_attr "alternative" "1")
6906132727Skan		  (const_string "vector")
6907132727Skan	       (and (eq_attr "alternative" "2")
6908132727Skan		    (match_operand 1 "memory_operand" ""))
6909132727Skan		  (const_string "vector")]
6910132727Skan	      (const_string "direct")))
691190286Sobrien   (set_attr "mode" "SI")])
691290286Sobrien
691390286Sobrien(define_insn "*mulsi3_1_zext"
691490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
691590286Sobrien	(zero_extend:DI
6916132727Skan	  (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
691790286Sobrien		   (match_operand:SI 2 "general_operand" "K,i,mr"))))
6918169699Skan   (clobber (reg:CC FLAGS_REG))]
691990286Sobrien  "TARGET_64BIT
692090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
692190286Sobrien  "@
692290286Sobrien   imul{l}\t{%2, %1, %k0|%k0, %1, %2}
692390286Sobrien   imul{l}\t{%2, %1, %k0|%k0, %1, %2}
692490286Sobrien   imul{l}\t{%2, %k0|%k0, %2}"
692590286Sobrien  [(set_attr "type" "imul")
692690286Sobrien   (set_attr "prefix_0f" "0,0,1")
6927132727Skan   (set (attr "athlon_decode")
6928132727Skan	(cond [(eq_attr "cpu" "athlon")
6929132727Skan		  (const_string "vector")
6930132727Skan	       (eq_attr "alternative" "1")
6931132727Skan		  (const_string "vector")
6932132727Skan	       (and (eq_attr "alternative" "2")
6933132727Skan		    (match_operand 1 "memory_operand" ""))
6934132727Skan		  (const_string "vector")]
6935132727Skan	      (const_string "direct")))
693690286Sobrien   (set_attr "mode" "SI")])
693790286Sobrien
693890286Sobrien(define_expand "mulhi3"
693990286Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
694090286Sobrien		   (mult:HI (match_operand:HI 1 "register_operand" "")
694190286Sobrien			    (match_operand:HI 2 "general_operand" "")))
6942169699Skan	      (clobber (reg:CC FLAGS_REG))])]
694390286Sobrien  "TARGET_HIMODE_MATH"
694490286Sobrien  "")
694590286Sobrien
694690286Sobrien(define_insn "*mulhi3_1"
694790286Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
6948132727Skan	(mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rm,rm,0")
694990286Sobrien		 (match_operand:HI 2 "general_operand" "K,i,mr")))
6950169699Skan   (clobber (reg:CC FLAGS_REG))]
695190286Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
695290286Sobrien  "@
695390286Sobrien   imul{w}\t{%2, %1, %0|%0, %1, %2}
695490286Sobrien   imul{w}\t{%2, %1, %0|%0, %1, %2}
695590286Sobrien   imul{w}\t{%2, %0|%0, %2}"
695690286Sobrien  [(set_attr "type" "imul")
695790286Sobrien   (set_attr "prefix_0f" "0,0,1")
6958132727Skan   (set (attr "athlon_decode")
6959132727Skan	(cond [(eq_attr "cpu" "athlon")
6960132727Skan		  (const_string "vector")
6961132727Skan	       (eq_attr "alternative" "1,2")
6962132727Skan		  (const_string "vector")]
6963132727Skan	      (const_string "direct")))
696490286Sobrien   (set_attr "mode" "HI")])
696590286Sobrien
696696294Sobrien(define_expand "mulqi3"
696796294Sobrien  [(parallel [(set (match_operand:QI 0 "register_operand" "")
696896294Sobrien		   (mult:QI (match_operand:QI 1 "nonimmediate_operand" "")
696996294Sobrien			    (match_operand:QI 2 "register_operand" "")))
6970169699Skan	      (clobber (reg:CC FLAGS_REG))])]
697196294Sobrien  "TARGET_QIMODE_MATH"
697296294Sobrien  "")
697396294Sobrien
697496294Sobrien(define_insn "*mulqi3_1"
697590286Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
697696294Sobrien	(mult:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
697790286Sobrien		 (match_operand:QI 2 "nonimmediate_operand" "qm")))
6978169699Skan   (clobber (reg:CC FLAGS_REG))]
697996294Sobrien  "TARGET_QIMODE_MATH
698096294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
698190286Sobrien  "mul{b}\t%2"
698290286Sobrien  [(set_attr "type" "imul")
698390286Sobrien   (set_attr "length_immediate" "0")
6984132727Skan   (set (attr "athlon_decode")
6985132727Skan     (if_then_else (eq_attr "cpu" "athlon")
6986132727Skan        (const_string "vector")
6987132727Skan        (const_string "direct")))
698890286Sobrien   (set_attr "mode" "QI")])
698990286Sobrien
699096294Sobrien(define_expand "umulqihi3"
699196294Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
699296294Sobrien		   (mult:HI (zero_extend:HI
699396294Sobrien			      (match_operand:QI 1 "nonimmediate_operand" ""))
699496294Sobrien			    (zero_extend:HI
699596294Sobrien			      (match_operand:QI 2 "register_operand" ""))))
6996169699Skan	      (clobber (reg:CC FLAGS_REG))])]
699796294Sobrien  "TARGET_QIMODE_MATH"
699896294Sobrien  "")
699996294Sobrien
700096294Sobrien(define_insn "*umulqihi3_1"
700150650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
700296294Sobrien	(mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
700390286Sobrien		 (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
7004169699Skan   (clobber (reg:CC FLAGS_REG))]
700596294Sobrien  "TARGET_QIMODE_MATH
700696294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
700790286Sobrien  "mul{b}\t%2"
700890286Sobrien  [(set_attr "type" "imul")
700990286Sobrien   (set_attr "length_immediate" "0")
7010132727Skan   (set (attr "athlon_decode")
7011132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7012132727Skan        (const_string "vector")
7013132727Skan        (const_string "direct")))
701490286Sobrien   (set_attr "mode" "QI")])
701518334Speter
701696294Sobrien(define_expand "mulqihi3"
701796294Sobrien  [(parallel [(set (match_operand:HI 0 "register_operand" "")
701896294Sobrien		   (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))
701996294Sobrien			    (sign_extend:HI (match_operand:QI 2 "register_operand" ""))))
7020169699Skan	      (clobber (reg:CC FLAGS_REG))])]
702196294Sobrien  "TARGET_QIMODE_MATH"
702296294Sobrien  "")
702396294Sobrien
702496294Sobrien(define_insn "*mulqihi3_insn"
702550650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
702696294Sobrien	(mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
702790286Sobrien		 (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
7028169699Skan   (clobber (reg:CC FLAGS_REG))]
702996294Sobrien  "TARGET_QIMODE_MATH
703096294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
703190286Sobrien  "imul{b}\t%2"
703290286Sobrien  [(set_attr "type" "imul")
703390286Sobrien   (set_attr "length_immediate" "0")
7034132727Skan   (set (attr "athlon_decode")
7035132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7036132727Skan        (const_string "vector")
7037132727Skan        (const_string "direct")))
703890286Sobrien   (set_attr "mode" "QI")])
703918334Speter
704096294Sobrien(define_expand "umulditi3"
704196294Sobrien  [(parallel [(set (match_operand:TI 0 "register_operand" "")
704296294Sobrien		   (mult:TI (zero_extend:TI
704396294Sobrien			      (match_operand:DI 1 "nonimmediate_operand" ""))
704496294Sobrien			    (zero_extend:TI
704596294Sobrien			      (match_operand:DI 2 "register_operand" ""))))
7046169699Skan	      (clobber (reg:CC FLAGS_REG))])]
704796294Sobrien  "TARGET_64BIT"
704896294Sobrien  "")
704996294Sobrien
705096294Sobrien(define_insn "*umulditi3_insn"
705190286Sobrien  [(set (match_operand:TI 0 "register_operand" "=A")
705296294Sobrien	(mult:TI (zero_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
705390286Sobrien		 (zero_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
7054169699Skan   (clobber (reg:CC FLAGS_REG))]
705596294Sobrien  "TARGET_64BIT
705696294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
705790286Sobrien  "mul{q}\t%2"
705890286Sobrien  [(set_attr "type" "imul")
705990286Sobrien   (set_attr "length_immediate" "0")
7060132727Skan   (set (attr "athlon_decode")
7061132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7062132727Skan        (const_string "vector")
7063132727Skan        (const_string "double")))
706490286Sobrien   (set_attr "mode" "DI")])
706590286Sobrien
706690286Sobrien;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers
706796294Sobrien(define_expand "umulsidi3"
706896294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
706996294Sobrien		   (mult:DI (zero_extend:DI
707096294Sobrien			      (match_operand:SI 1 "nonimmediate_operand" ""))
707196294Sobrien			    (zero_extend:DI
707296294Sobrien			      (match_operand:SI 2 "register_operand" ""))))
7073169699Skan	      (clobber (reg:CC FLAGS_REG))])]
707496294Sobrien  "!TARGET_64BIT"
707596294Sobrien  "")
707696294Sobrien
707796294Sobrien(define_insn "*umulsidi3_insn"
707818334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
707996294Sobrien	(mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
708090286Sobrien		 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
7081169699Skan   (clobber (reg:CC FLAGS_REG))]
708296294Sobrien  "!TARGET_64BIT
708396294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
708490286Sobrien  "mul{l}\t%2"
708590286Sobrien  [(set_attr "type" "imul")
708690286Sobrien   (set_attr "length_immediate" "0")
7087132727Skan   (set (attr "athlon_decode")
7088132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7089132727Skan        (const_string "vector")
7090132727Skan        (const_string "double")))
709190286Sobrien   (set_attr "mode" "SI")])
709218334Speter
709396294Sobrien(define_expand "mulditi3"
709496294Sobrien  [(parallel [(set (match_operand:TI 0 "register_operand" "")
709596294Sobrien		   (mult:TI (sign_extend:TI
709696294Sobrien			      (match_operand:DI 1 "nonimmediate_operand" ""))
709796294Sobrien			    (sign_extend:TI
709896294Sobrien			      (match_operand:DI 2 "register_operand" ""))))
7099169699Skan	      (clobber (reg:CC FLAGS_REG))])]
710096294Sobrien  "TARGET_64BIT"
710196294Sobrien  "")
710296294Sobrien
710396294Sobrien(define_insn "*mulditi3_insn"
710490286Sobrien  [(set (match_operand:TI 0 "register_operand" "=A")
710596294Sobrien	(mult:TI (sign_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
710690286Sobrien		 (sign_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
7107169699Skan   (clobber (reg:CC FLAGS_REG))]
710896294Sobrien  "TARGET_64BIT
710996294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
711090286Sobrien  "imul{q}\t%2"
711190286Sobrien  [(set_attr "type" "imul")
711290286Sobrien   (set_attr "length_immediate" "0")
7113132727Skan   (set (attr "athlon_decode")
7114132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7115132727Skan        (const_string "vector")
7116132727Skan        (const_string "double")))
711790286Sobrien   (set_attr "mode" "DI")])
711890286Sobrien
711996294Sobrien(define_expand "mulsidi3"
712096294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
712196294Sobrien		   (mult:DI (sign_extend:DI
712296294Sobrien			      (match_operand:SI 1 "nonimmediate_operand" ""))
712396294Sobrien			    (sign_extend:DI
712496294Sobrien			      (match_operand:SI 2 "register_operand" ""))))
7125169699Skan	      (clobber (reg:CC FLAGS_REG))])]
712696294Sobrien  "!TARGET_64BIT"
712796294Sobrien  "")
712896294Sobrien
712996294Sobrien(define_insn "*mulsidi3_insn"
713018334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
713196294Sobrien	(mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
713290286Sobrien		 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
7133169699Skan   (clobber (reg:CC FLAGS_REG))]
713496294Sobrien  "!TARGET_64BIT
713596294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
713690286Sobrien  "imul{l}\t%2"
713790286Sobrien  [(set_attr "type" "imul")
713890286Sobrien   (set_attr "length_immediate" "0")
7139132727Skan   (set (attr "athlon_decode")
7140132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7141132727Skan        (const_string "vector")
7142132727Skan        (const_string "double")))
714390286Sobrien   (set_attr "mode" "SI")])
714418334Speter
714596294Sobrien(define_expand "umuldi3_highpart"
714696294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
714796294Sobrien		   (truncate:DI
714896294Sobrien		     (lshiftrt:TI
714996294Sobrien		       (mult:TI (zero_extend:TI
715096294Sobrien				  (match_operand:DI 1 "nonimmediate_operand" ""))
715196294Sobrien				(zero_extend:TI
715296294Sobrien				  (match_operand:DI 2 "register_operand" "")))
715396294Sobrien		       (const_int 64))))
715496294Sobrien	      (clobber (match_scratch:DI 3 ""))
7155169699Skan	      (clobber (reg:CC FLAGS_REG))])]
715696294Sobrien  "TARGET_64BIT"
715796294Sobrien  "")
715896294Sobrien
715990286Sobrien(define_insn "*umuldi3_highpart_rex64"
716090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
716190286Sobrien	(truncate:DI
716290286Sobrien	  (lshiftrt:TI
716390286Sobrien	    (mult:TI (zero_extend:TI
716496294Sobrien		       (match_operand:DI 1 "nonimmediate_operand" "%a"))
716590286Sobrien		     (zero_extend:TI
716690286Sobrien		       (match_operand:DI 2 "nonimmediate_operand" "rm")))
716790286Sobrien	    (const_int 64))))
716896294Sobrien   (clobber (match_scratch:DI 3 "=1"))
7169169699Skan   (clobber (reg:CC FLAGS_REG))]
717096294Sobrien  "TARGET_64BIT
717196294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
717290286Sobrien  "mul{q}\t%2"
717390286Sobrien  [(set_attr "type" "imul")
717490286Sobrien   (set_attr "length_immediate" "0")
7175132727Skan   (set (attr "athlon_decode")
7176132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7177132727Skan        (const_string "vector")
7178132727Skan        (const_string "double")))
717990286Sobrien   (set_attr "mode" "DI")])
718090286Sobrien
718196294Sobrien(define_expand "umulsi3_highpart"
718296294Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
718396294Sobrien		   (truncate:SI
718496294Sobrien		     (lshiftrt:DI
718596294Sobrien		       (mult:DI (zero_extend:DI
718696294Sobrien				  (match_operand:SI 1 "nonimmediate_operand" ""))
718796294Sobrien				(zero_extend:DI
718896294Sobrien				  (match_operand:SI 2 "register_operand" "")))
718996294Sobrien		       (const_int 32))))
719096294Sobrien	      (clobber (match_scratch:SI 3 ""))
7191169699Skan	      (clobber (reg:CC FLAGS_REG))])]
719296294Sobrien  ""
719396294Sobrien  "")
719496294Sobrien
719596294Sobrien(define_insn "*umulsi3_highpart_insn"
719618334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
719790286Sobrien	(truncate:SI
719890286Sobrien	  (lshiftrt:DI
719990286Sobrien	    (mult:DI (zero_extend:DI
720096294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
720190286Sobrien		     (zero_extend:DI
720290286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
720390286Sobrien	    (const_int 32))))
720496294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7205169699Skan   (clobber (reg:CC FLAGS_REG))]
720696294Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
720790286Sobrien  "mul{l}\t%2"
720890286Sobrien  [(set_attr "type" "imul")
720990286Sobrien   (set_attr "length_immediate" "0")
7210132727Skan   (set (attr "athlon_decode")
7211132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7212132727Skan        (const_string "vector")
7213132727Skan        (const_string "double")))
721490286Sobrien   (set_attr "mode" "SI")])
721518334Speter
721690286Sobrien(define_insn "*umulsi3_highpart_zext"
721790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
721890286Sobrien	(zero_extend:DI (truncate:SI
721990286Sobrien	  (lshiftrt:DI
722090286Sobrien	    (mult:DI (zero_extend:DI
722196294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
722290286Sobrien		     (zero_extend:DI
722390286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
722490286Sobrien	    (const_int 32)))))
722596294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7226169699Skan   (clobber (reg:CC FLAGS_REG))]
722796294Sobrien  "TARGET_64BIT
722896294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
722990286Sobrien  "mul{l}\t%2"
723090286Sobrien  [(set_attr "type" "imul")
723190286Sobrien   (set_attr "length_immediate" "0")
7232132727Skan   (set (attr "athlon_decode")
7233132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7234132727Skan        (const_string "vector")
7235132727Skan        (const_string "double")))
723690286Sobrien   (set_attr "mode" "SI")])
723790286Sobrien
723896294Sobrien(define_expand "smuldi3_highpart"
723996294Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "=d")
724096294Sobrien		   (truncate:DI
724196294Sobrien		     (lshiftrt:TI
724296294Sobrien		       (mult:TI (sign_extend:TI
724396294Sobrien				  (match_operand:DI 1 "nonimmediate_operand" ""))
724496294Sobrien				(sign_extend:TI
724596294Sobrien				  (match_operand:DI 2 "register_operand" "")))
724696294Sobrien		       (const_int 64))))
724796294Sobrien	      (clobber (match_scratch:DI 3 ""))
7248169699Skan	      (clobber (reg:CC FLAGS_REG))])]
724996294Sobrien  "TARGET_64BIT"
725096294Sobrien  "")
725196294Sobrien
725290286Sobrien(define_insn "*smuldi3_highpart_rex64"
725390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
725490286Sobrien	(truncate:DI
725590286Sobrien	  (lshiftrt:TI
725690286Sobrien	    (mult:TI (sign_extend:TI
725796294Sobrien		       (match_operand:DI 1 "nonimmediate_operand" "%a"))
725890286Sobrien		     (sign_extend:TI
725990286Sobrien		       (match_operand:DI 2 "nonimmediate_operand" "rm")))
726090286Sobrien	    (const_int 64))))
726196294Sobrien   (clobber (match_scratch:DI 3 "=1"))
7262169699Skan   (clobber (reg:CC FLAGS_REG))]
726396294Sobrien  "TARGET_64BIT
726496294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
726590286Sobrien  "imul{q}\t%2"
726690286Sobrien  [(set_attr "type" "imul")
7267132727Skan   (set (attr "athlon_decode")
7268132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7269132727Skan        (const_string "vector")
7270132727Skan        (const_string "double")))
727190286Sobrien   (set_attr "mode" "DI")])
727290286Sobrien
727396294Sobrien(define_expand "smulsi3_highpart"
727496294Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
727596294Sobrien		   (truncate:SI
727696294Sobrien		     (lshiftrt:DI
727796294Sobrien		       (mult:DI (sign_extend:DI
727896294Sobrien				  (match_operand:SI 1 "nonimmediate_operand" ""))
727996294Sobrien				(sign_extend:DI
728096294Sobrien				  (match_operand:SI 2 "register_operand" "")))
728196294Sobrien		       (const_int 32))))
728296294Sobrien	      (clobber (match_scratch:SI 3 ""))
7283169699Skan	      (clobber (reg:CC FLAGS_REG))])]
728496294Sobrien  ""
728596294Sobrien  "")
728696294Sobrien
728796294Sobrien(define_insn "*smulsi3_highpart_insn"
728818334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
728990286Sobrien	(truncate:SI
729090286Sobrien	  (lshiftrt:DI
729190286Sobrien	    (mult:DI (sign_extend:DI
729296294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
729390286Sobrien		     (sign_extend:DI
729490286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
729590286Sobrien	    (const_int 32))))
729696294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7297169699Skan   (clobber (reg:CC FLAGS_REG))]
729896294Sobrien  "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
729990286Sobrien  "imul{l}\t%2"
730090286Sobrien  [(set_attr "type" "imul")
7301132727Skan   (set (attr "athlon_decode")
7302132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7303132727Skan        (const_string "vector")
7304132727Skan        (const_string "double")))
730590286Sobrien   (set_attr "mode" "SI")])
730618334Speter
730790286Sobrien(define_insn "*smulsi3_highpart_zext"
730890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=d")
730990286Sobrien	(zero_extend:DI (truncate:SI
731090286Sobrien	  (lshiftrt:DI
731190286Sobrien	    (mult:DI (sign_extend:DI
731296294Sobrien		       (match_operand:SI 1 "nonimmediate_operand" "%a"))
731390286Sobrien		     (sign_extend:DI
731490286Sobrien		       (match_operand:SI 2 "nonimmediate_operand" "rm")))
731590286Sobrien	    (const_int 32)))))
731696294Sobrien   (clobber (match_scratch:SI 3 "=1"))
7317169699Skan   (clobber (reg:CC FLAGS_REG))]
731896294Sobrien  "TARGET_64BIT
731996294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
732090286Sobrien  "imul{l}\t%2"
732190286Sobrien  [(set_attr "type" "imul")
7322132727Skan   (set (attr "athlon_decode")
7323132727Skan     (if_then_else (eq_attr "cpu" "athlon")
7324132727Skan        (const_string "vector")
7325132727Skan        (const_string "double")))
732690286Sobrien   (set_attr "mode" "SI")])
732790286Sobrien
732818334Speter;; The patterns that match these are at the end of this file.
732918334Speter
733018334Speter(define_expand "mulxf3"
733118334Speter  [(set (match_operand:XF 0 "register_operand" "")
733250650Sobrien	(mult:XF (match_operand:XF 1 "register_operand" "")
733350650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
733418334Speter  "TARGET_80387"
733518334Speter  "")
733618334Speter
733718334Speter(define_expand "muldf3"
733818334Speter  [(set (match_operand:DF 0 "register_operand" "")
733950650Sobrien	(mult:DF (match_operand:DF 1 "register_operand" "")
734018334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
734190286Sobrien  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
734218334Speter  "")
734318334Speter
734418334Speter(define_expand "mulsf3"
734518334Speter  [(set (match_operand:SF 0 "register_operand" "")
734650650Sobrien	(mult:SF (match_operand:SF 1 "register_operand" "")
734718334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
734890286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
734918334Speter  "")
735018334Speter
735190286Sobrien;; Divide instructions
735218334Speter
735318334Speter(define_insn "divqi3"
735450650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
735550650Sobrien	(div:QI (match_operand:HI 1 "register_operand" "0")
735690286Sobrien		(match_operand:QI 2 "nonimmediate_operand" "qm")))
7357169699Skan   (clobber (reg:CC FLAGS_REG))]
735890286Sobrien  "TARGET_QIMODE_MATH"
735990286Sobrien  "idiv{b}\t%2"
736090286Sobrien  [(set_attr "type" "idiv")
7361169699Skan   (set_attr "mode" "QI")])
736218334Speter
736318334Speter(define_insn "udivqi3"
736450650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
736550650Sobrien	(udiv:QI (match_operand:HI 1 "register_operand" "0")
736690286Sobrien		 (match_operand:QI 2 "nonimmediate_operand" "qm")))
7367169699Skan   (clobber (reg:CC FLAGS_REG))]
736890286Sobrien  "TARGET_QIMODE_MATH"
736990286Sobrien  "div{b}\t%2"
737090286Sobrien  [(set_attr "type" "idiv")
7371169699Skan   (set_attr "mode" "QI")])
737218334Speter
737318334Speter;; The patterns that match these are at the end of this file.
737418334Speter
737518334Speter(define_expand "divxf3"
737618334Speter  [(set (match_operand:XF 0 "register_operand" "")
737750650Sobrien	(div:XF (match_operand:XF 1 "register_operand" "")
737850650Sobrien		(match_operand:XF 2 "register_operand" "")))]
737918334Speter  "TARGET_80387"
738018334Speter  "")
738118334Speter
738218334Speter(define_expand "divdf3"
738318334Speter  [(set (match_operand:DF 0 "register_operand" "")
738450650Sobrien 	(div:DF (match_operand:DF 1 "register_operand" "")
738550650Sobrien 		(match_operand:DF 2 "nonimmediate_operand" "")))]
738690286Sobrien   "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
738750650Sobrien   "")
738850650Sobrien 
738918334Speter(define_expand "divsf3"
739018334Speter  [(set (match_operand:SF 0 "register_operand" "")
739150650Sobrien	(div:SF (match_operand:SF 1 "register_operand" "")
739218334Speter		(match_operand:SF 2 "nonimmediate_operand" "")))]
739390286Sobrien  "TARGET_80387 || TARGET_SSE_MATH"
739418334Speter  "")
739518334Speter
739618334Speter;; Remainder instructions.
739718334Speter
739890286Sobrien(define_expand "divmoddi4"
739990286Sobrien  [(parallel [(set (match_operand:DI 0 "register_operand" "")
740090286Sobrien		   (div:DI (match_operand:DI 1 "register_operand" "")
740190286Sobrien			   (match_operand:DI 2 "nonimmediate_operand" "")))
740290286Sobrien	      (set (match_operand:DI 3 "register_operand" "")
740390286Sobrien		   (mod:DI (match_dup 1) (match_dup 2)))
7404169699Skan	      (clobber (reg:CC FLAGS_REG))])]
740590286Sobrien  "TARGET_64BIT"
740690286Sobrien  "")
740790286Sobrien
740890286Sobrien;; Allow to come the parameter in eax or edx to avoid extra moves.
7409132727Skan;; Penalize eax case slightly because it results in worse scheduling
741090286Sobrien;; of code.
741190286Sobrien(define_insn "*divmoddi4_nocltd_rex64"
741290286Sobrien  [(set (match_operand:DI 0 "register_operand" "=&a,?a")
741390286Sobrien	(div:DI (match_operand:DI 2 "register_operand" "1,0")
741490286Sobrien		(match_operand:DI 3 "nonimmediate_operand" "rm,rm")))
741590286Sobrien   (set (match_operand:DI 1 "register_operand" "=&d,&d")
741690286Sobrien	(mod:DI (match_dup 2) (match_dup 3)))
7417169699Skan   (clobber (reg:CC FLAGS_REG))]
741890286Sobrien  "TARGET_64BIT && !optimize_size && !TARGET_USE_CLTD"
741990286Sobrien  "#"
742090286Sobrien  [(set_attr "type" "multi")])
742190286Sobrien
742290286Sobrien(define_insn "*divmoddi4_cltd_rex64"
742390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
742490286Sobrien	(div:DI (match_operand:DI 2 "register_operand" "a")
742590286Sobrien		(match_operand:DI 3 "nonimmediate_operand" "rm")))
742690286Sobrien   (set (match_operand:DI 1 "register_operand" "=&d")
742790286Sobrien	(mod:DI (match_dup 2) (match_dup 3)))
7428169699Skan   (clobber (reg:CC FLAGS_REG))]
742990286Sobrien  "TARGET_64BIT && (optimize_size || TARGET_USE_CLTD)"
743090286Sobrien  "#"
743190286Sobrien  [(set_attr "type" "multi")])
743290286Sobrien
743390286Sobrien(define_insn "*divmoddi_noext_rex64"
743490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
743590286Sobrien	(div:DI (match_operand:DI 1 "register_operand" "0")
743690286Sobrien		(match_operand:DI 2 "nonimmediate_operand" "rm")))
743790286Sobrien   (set (match_operand:DI 3 "register_operand" "=d")
743890286Sobrien	(mod:DI (match_dup 1) (match_dup 2)))
743990286Sobrien   (use (match_operand:DI 4 "register_operand" "3"))
7440169699Skan   (clobber (reg:CC FLAGS_REG))]
744190286Sobrien  "TARGET_64BIT"
744290286Sobrien  "idiv{q}\t%2"
744390286Sobrien  [(set_attr "type" "idiv")
7444169699Skan   (set_attr "mode" "DI")])
744590286Sobrien
744690286Sobrien(define_split
744790286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
744890286Sobrien	(div:DI (match_operand:DI 1 "register_operand" "")
744990286Sobrien		(match_operand:DI 2 "nonimmediate_operand" "")))
745090286Sobrien   (set (match_operand:DI 3 "register_operand" "")
745190286Sobrien	(mod:DI (match_dup 1) (match_dup 2)))
7452169699Skan   (clobber (reg:CC FLAGS_REG))]
745390286Sobrien  "TARGET_64BIT && reload_completed"
745490286Sobrien  [(parallel [(set (match_dup 3)
745590286Sobrien		   (ashiftrt:DI (match_dup 4) (const_int 63)))
7456169699Skan	      (clobber (reg:CC FLAGS_REG))])
745790286Sobrien   (parallel [(set (match_dup 0)
745890286Sobrien	           (div:DI (reg:DI 0) (match_dup 2)))
745990286Sobrien	      (set (match_dup 3)
746090286Sobrien		   (mod:DI (reg:DI 0) (match_dup 2)))
746190286Sobrien	      (use (match_dup 3))
7462169699Skan	      (clobber (reg:CC FLAGS_REG))])]
746390286Sobrien{
7464117404Skan  /* Avoid use of cltd in favor of a mov+shift.  */
746590286Sobrien  if (!TARGET_USE_CLTD && !optimize_size)
746690286Sobrien    {
746790286Sobrien      if (true_regnum (operands[1]))
746890286Sobrien        emit_move_insn (operands[0], operands[1]);
746990286Sobrien      else
747090286Sobrien	emit_move_insn (operands[3], operands[1]);
747190286Sobrien      operands[4] = operands[3];
747290286Sobrien    }
747390286Sobrien  else
747490286Sobrien    {
7475169699Skan      gcc_assert (!true_regnum (operands[1]));
747690286Sobrien      operands[4] = operands[1];
747790286Sobrien    }
747890286Sobrien})
747990286Sobrien
748090286Sobrien
748190286Sobrien(define_expand "divmodsi4"
748290286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "")
748390286Sobrien		   (div:SI (match_operand:SI 1 "register_operand" "")
748490286Sobrien			   (match_operand:SI 2 "nonimmediate_operand" "")))
748590286Sobrien	      (set (match_operand:SI 3 "register_operand" "")
748690286Sobrien		   (mod:SI (match_dup 1) (match_dup 2)))
7487169699Skan	      (clobber (reg:CC FLAGS_REG))])]
748890286Sobrien  ""
748990286Sobrien  "")
749090286Sobrien
749190286Sobrien;; Allow to come the parameter in eax or edx to avoid extra moves.
7492132727Skan;; Penalize eax case slightly because it results in worse scheduling
749390286Sobrien;; of code.
749490286Sobrien(define_insn "*divmodsi4_nocltd"
749590286Sobrien  [(set (match_operand:SI 0 "register_operand" "=&a,?a")
749690286Sobrien	(div:SI (match_operand:SI 2 "register_operand" "1,0")
749790286Sobrien		(match_operand:SI 3 "nonimmediate_operand" "rm,rm")))
749890286Sobrien   (set (match_operand:SI 1 "register_operand" "=&d,&d")
749990286Sobrien	(mod:SI (match_dup 2) (match_dup 3)))
7500169699Skan   (clobber (reg:CC FLAGS_REG))]
750190286Sobrien  "!optimize_size && !TARGET_USE_CLTD"
750290286Sobrien  "#"
750390286Sobrien  [(set_attr "type" "multi")])
750490286Sobrien
750590286Sobrien(define_insn "*divmodsi4_cltd"
750618334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
750790286Sobrien	(div:SI (match_operand:SI 2 "register_operand" "a")
750890286Sobrien		(match_operand:SI 3 "nonimmediate_operand" "rm")))
750990286Sobrien   (set (match_operand:SI 1 "register_operand" "=&d")
751090286Sobrien	(mod:SI (match_dup 2) (match_dup 3)))
7511169699Skan   (clobber (reg:CC FLAGS_REG))]
751290286Sobrien  "optimize_size || TARGET_USE_CLTD"
751390286Sobrien  "#"
751490286Sobrien  [(set_attr "type" "multi")])
751590286Sobrien
751690286Sobrien(define_insn "*divmodsi_noext"
751790286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a")
751818334Speter	(div:SI (match_operand:SI 1 "register_operand" "0")
751950650Sobrien		(match_operand:SI 2 "nonimmediate_operand" "rm")))
752090286Sobrien   (set (match_operand:SI 3 "register_operand" "=d")
752190286Sobrien	(mod:SI (match_dup 1) (match_dup 2)))
752290286Sobrien   (use (match_operand:SI 4 "register_operand" "3"))
7523169699Skan   (clobber (reg:CC FLAGS_REG))]
752418334Speter  ""
752590286Sobrien  "idiv{l}\t%2"
752690286Sobrien  [(set_attr "type" "idiv")
7527169699Skan   (set_attr "mode" "SI")])
752890286Sobrien
752990286Sobrien(define_split
753090286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
753190286Sobrien	(div:SI (match_operand:SI 1 "register_operand" "")
753290286Sobrien		(match_operand:SI 2 "nonimmediate_operand" "")))
753390286Sobrien   (set (match_operand:SI 3 "register_operand" "")
753490286Sobrien	(mod:SI (match_dup 1) (match_dup 2)))
7535169699Skan   (clobber (reg:CC FLAGS_REG))]
753690286Sobrien  "reload_completed"
753790286Sobrien  [(parallel [(set (match_dup 3)
753890286Sobrien		   (ashiftrt:SI (match_dup 4) (const_int 31)))
7539169699Skan	      (clobber (reg:CC FLAGS_REG))])
754090286Sobrien   (parallel [(set (match_dup 0)
754190286Sobrien	           (div:SI (reg:SI 0) (match_dup 2)))
754290286Sobrien	      (set (match_dup 3)
754390286Sobrien		   (mod:SI (reg:SI 0) (match_dup 2)))
754490286Sobrien	      (use (match_dup 3))
7545169699Skan	      (clobber (reg:CC FLAGS_REG))])]
754618334Speter{
7547117404Skan  /* Avoid use of cltd in favor of a mov+shift.  */
754890286Sobrien  if (!TARGET_USE_CLTD && !optimize_size)
754990286Sobrien    {
755090286Sobrien      if (true_regnum (operands[1]))
755190286Sobrien        emit_move_insn (operands[0], operands[1]);
755290286Sobrien      else
755390286Sobrien	emit_move_insn (operands[3], operands[1]);
755490286Sobrien      operands[4] = operands[3];
755590286Sobrien    }
755690286Sobrien  else
755790286Sobrien    {
7558169699Skan      gcc_assert (!true_regnum (operands[1]));
755990286Sobrien      operands[4] = operands[1];
756090286Sobrien    }
756190286Sobrien})
756290286Sobrien;; %%% Split me.
756318334Speter(define_insn "divmodhi4"
756418334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
756518334Speter	(div:HI (match_operand:HI 1 "register_operand" "0")
756650650Sobrien		(match_operand:HI 2 "nonimmediate_operand" "rm")))
756718334Speter   (set (match_operand:HI 3 "register_operand" "=&d")
756890286Sobrien	(mod:HI (match_dup 1) (match_dup 2)))
7569169699Skan   (clobber (reg:CC FLAGS_REG))]
757090286Sobrien  "TARGET_HIMODE_MATH"
757190286Sobrien  "cwtd\;idiv{w}\t%2"
757290286Sobrien  [(set_attr "type" "multi")
757390286Sobrien   (set_attr "length_immediate" "0")
757490286Sobrien   (set_attr "mode" "SI")])
757518334Speter
757690286Sobrien(define_insn "udivmoddi4"
757790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
757890286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "0")
757990286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "rm")))
758090286Sobrien   (set (match_operand:DI 3 "register_operand" "=&d")
758190286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
7582169699Skan   (clobber (reg:CC FLAGS_REG))]
758390286Sobrien  "TARGET_64BIT"
758490286Sobrien  "xor{q}\t%3, %3\;div{q}\t%2"
758590286Sobrien  [(set_attr "type" "multi")
758690286Sobrien   (set_attr "length_immediate" "0")
758790286Sobrien   (set_attr "mode" "DI")])
758890286Sobrien
758990286Sobrien(define_insn "*udivmoddi4_noext"
759090286Sobrien  [(set (match_operand:DI 0 "register_operand" "=a")
759190286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "0")
759290286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "rm")))
759390286Sobrien   (set (match_operand:DI 3 "register_operand" "=d")
759490286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
759590286Sobrien   (use (match_dup 3))
7596169699Skan   (clobber (reg:CC FLAGS_REG))]
759790286Sobrien  "TARGET_64BIT"
759890286Sobrien  "div{q}\t%2"
759990286Sobrien  [(set_attr "type" "idiv")
760090286Sobrien   (set_attr "mode" "DI")])
760190286Sobrien
760290286Sobrien(define_split
760390286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
760490286Sobrien	(udiv:DI (match_operand:DI 1 "register_operand" "")
760590286Sobrien		 (match_operand:DI 2 "nonimmediate_operand" "")))
760690286Sobrien   (set (match_operand:DI 3 "register_operand" "")
760790286Sobrien	(umod:DI (match_dup 1) (match_dup 2)))
7608169699Skan   (clobber (reg:CC FLAGS_REG))]
760990286Sobrien  "TARGET_64BIT && reload_completed"
761090286Sobrien  [(set (match_dup 3) (const_int 0))
761190286Sobrien   (parallel [(set (match_dup 0)
761290286Sobrien		   (udiv:DI (match_dup 1) (match_dup 2)))
761390286Sobrien	      (set (match_dup 3)
761490286Sobrien		   (umod:DI (match_dup 1) (match_dup 2)))
761590286Sobrien	      (use (match_dup 3))
7616169699Skan	      (clobber (reg:CC FLAGS_REG))])]
761790286Sobrien  "")
761890286Sobrien
761918334Speter(define_insn "udivmodsi4"
762018334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
762118334Speter	(udiv:SI (match_operand:SI 1 "register_operand" "0")
762250650Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
762318334Speter   (set (match_operand:SI 3 "register_operand" "=&d")
762490286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
7625169699Skan   (clobber (reg:CC FLAGS_REG))]
762618334Speter  ""
762790286Sobrien  "xor{l}\t%3, %3\;div{l}\t%2"
762890286Sobrien  [(set_attr "type" "multi")
762990286Sobrien   (set_attr "length_immediate" "0")
763090286Sobrien   (set_attr "mode" "SI")])
763118334Speter
763290286Sobrien(define_insn "*udivmodsi4_noext"
763390286Sobrien  [(set (match_operand:SI 0 "register_operand" "=a")
763490286Sobrien	(udiv:SI (match_operand:SI 1 "register_operand" "0")
763590286Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
763690286Sobrien   (set (match_operand:SI 3 "register_operand" "=d")
763790286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
763890286Sobrien   (use (match_dup 3))
7639169699Skan   (clobber (reg:CC FLAGS_REG))]
764090286Sobrien  ""
764190286Sobrien  "div{l}\t%2"
764290286Sobrien  [(set_attr "type" "idiv")
764390286Sobrien   (set_attr "mode" "SI")])
764490286Sobrien
764590286Sobrien(define_split
764690286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
764790286Sobrien	(udiv:SI (match_operand:SI 1 "register_operand" "")
764890286Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "")))
764990286Sobrien   (set (match_operand:SI 3 "register_operand" "")
765090286Sobrien	(umod:SI (match_dup 1) (match_dup 2)))
7651169699Skan   (clobber (reg:CC FLAGS_REG))]
765290286Sobrien  "reload_completed"
765390286Sobrien  [(set (match_dup 3) (const_int 0))
765490286Sobrien   (parallel [(set (match_dup 0)
765590286Sobrien		   (udiv:SI (match_dup 1) (match_dup 2)))
765690286Sobrien	      (set (match_dup 3)
765790286Sobrien		   (umod:SI (match_dup 1) (match_dup 2)))
765890286Sobrien	      (use (match_dup 3))
7659169699Skan	      (clobber (reg:CC FLAGS_REG))])]
766090286Sobrien  "")
766190286Sobrien
766290286Sobrien(define_expand "udivmodhi4"
766390286Sobrien  [(set (match_dup 4) (const_int 0))
766490286Sobrien   (parallel [(set (match_operand:HI 0 "register_operand" "")
766590286Sobrien		   (udiv:HI (match_operand:HI 1 "register_operand" "")
766690286Sobrien		 	    (match_operand:HI 2 "nonimmediate_operand" "")))
766790286Sobrien	      (set (match_operand:HI 3 "register_operand" "")
766890286Sobrien	   	   (umod:HI (match_dup 1) (match_dup 2)))
766990286Sobrien	      (use (match_dup 4))
7670169699Skan	      (clobber (reg:CC FLAGS_REG))])]
767190286Sobrien  "TARGET_HIMODE_MATH"
767290286Sobrien  "operands[4] = gen_reg_rtx (HImode);")
767390286Sobrien
767490286Sobrien(define_insn "*udivmodhi_noext"
767518334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
767618334Speter	(udiv:HI (match_operand:HI 1 "register_operand" "0")
767750650Sobrien		 (match_operand:HI 2 "nonimmediate_operand" "rm")))
767890286Sobrien   (set (match_operand:HI 3 "register_operand" "=d")
767990286Sobrien	(umod:HI (match_dup 1) (match_dup 2)))
768090286Sobrien   (use (match_operand:HI 4 "register_operand" "3"))
7681169699Skan   (clobber (reg:CC FLAGS_REG))]
768218334Speter  ""
768390286Sobrien  "div{w}\t%2"
768490286Sobrien  [(set_attr "type" "idiv")
7685169699Skan   (set_attr "mode" "HI")])
768618334Speter
7687169699Skan;; We cannot use div/idiv for double division, because it causes
768890286Sobrien;; "division by zero" on the overflow and that's not what we expect
768990286Sobrien;; from truncate.  Because true (non truncating) double division is
769090286Sobrien;; never generated, we can't create this insn anyway.
769190286Sobrien;
769290286Sobrien;(define_insn ""
769390286Sobrien;  [(set (match_operand:SI 0 "register_operand" "=a")
769490286Sobrien;	(truncate:SI
769590286Sobrien;	  (udiv:DI (match_operand:DI 1 "register_operand" "A")
769690286Sobrien;		   (zero_extend:DI
769790286Sobrien;		     (match_operand:SI 2 "nonimmediate_operand" "rm")))))
769890286Sobrien;   (set (match_operand:SI 3 "register_operand" "=d")
769990286Sobrien;	(truncate:SI
770090286Sobrien;	  (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))
7701169699Skan;   (clobber (reg:CC FLAGS_REG))]
770290286Sobrien;  ""
770390286Sobrien;  "div{l}\t{%2, %0|%0, %2}"
7704169699Skan;  [(set_attr "type" "idiv")])
770590286Sobrien
770690286Sobrien;;- Logical AND instructions
770718334Speter
770890286Sobrien;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al.
770990286Sobrien;; Note that this excludes ah.
771090286Sobrien
771190286Sobrien(define_insn "*testdi_1_rex64"
7712169699Skan  [(set (reg FLAGS_REG)
771390286Sobrien	(compare
7714132727Skan	  (and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm")
7715132727Skan		  (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re"))
771690286Sobrien	  (const_int 0)))]
7717132727Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
7718132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
771990286Sobrien  "@
7720169699Skan   test{l}\t{%k1, %k0|%k0, %k1}
7721169699Skan   test{l}\t{%k1, %k0|%k0, %k1}
7722169699Skan   test{q}\t{%1, %0|%0, %1}
7723169699Skan   test{q}\t{%1, %0|%0, %1}
772490286Sobrien   test{q}\t{%1, %0|%0, %1}"
772590286Sobrien  [(set_attr "type" "test")
772690286Sobrien   (set_attr "modrm" "0,1,0,1,1")
772790286Sobrien   (set_attr "mode" "SI,SI,DI,DI,DI")
772890286Sobrien   (set_attr "pent_pair" "uv,np,uv,np,uv")])
772990286Sobrien
773090286Sobrien(define_insn "testsi_1"
7731169699Skan  [(set (reg FLAGS_REG)
773290286Sobrien	(compare
7733132727Skan	  (and:SI (match_operand:SI 0 "nonimmediate_operand" "%!*a,r,rm")
7734132727Skan		  (match_operand:SI 1 "general_operand" "in,in,rin"))
773590286Sobrien	  (const_int 0)))]
7736132727Skan  "ix86_match_ccmode (insn, CCNOmode)
7737132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
773890286Sobrien  "test{l}\t{%1, %0|%0, %1}"
773990286Sobrien  [(set_attr "type" "test")
774090286Sobrien   (set_attr "modrm" "0,1,1")
774190286Sobrien   (set_attr "mode" "SI")
774290286Sobrien   (set_attr "pent_pair" "uv,np,uv")])
774390286Sobrien
774490286Sobrien(define_expand "testsi_ccno_1"
7745169699Skan  [(set (reg:CCNO FLAGS_REG)
774690286Sobrien	(compare:CCNO
774790286Sobrien	  (and:SI (match_operand:SI 0 "nonimmediate_operand" "")
774890286Sobrien		  (match_operand:SI 1 "nonmemory_operand" ""))
774990286Sobrien	  (const_int 0)))]
775018334Speter  ""
775190286Sobrien  "")
775218334Speter
775390286Sobrien(define_insn "*testhi_1"
7754169699Skan  [(set (reg FLAGS_REG)
7755132727Skan        (compare (and:HI (match_operand:HI 0 "nonimmediate_operand" "%!*a,r,rm")
7756132727Skan			 (match_operand:HI 1 "general_operand" "n,n,rn"))
775790286Sobrien		 (const_int 0)))]
7758132727Skan  "ix86_match_ccmode (insn, CCNOmode)
7759132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
776090286Sobrien  "test{w}\t{%1, %0|%0, %1}"
776190286Sobrien  [(set_attr "type" "test")
776290286Sobrien   (set_attr "modrm" "0,1,1")
776390286Sobrien   (set_attr "mode" "HI")
776490286Sobrien   (set_attr "pent_pair" "uv,np,uv")])
776518334Speter
776690286Sobrien(define_expand "testqi_ccz_1"
7767169699Skan  [(set (reg:CCZ FLAGS_REG)
776890286Sobrien        (compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand" "")
776990286Sobrien			     (match_operand:QI 1 "nonmemory_operand" ""))
777090286Sobrien		 (const_int 0)))]
777190286Sobrien  ""
777290286Sobrien  "")
777318334Speter
7774146906Skan(define_insn "*testqi_1_maybe_si"
7775169699Skan  [(set (reg FLAGS_REG)
7776146906Skan        (compare
7777146906Skan	  (and:QI
7778146906Skan	    (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm,r")
7779146906Skan	    (match_operand:QI 1 "general_operand" "n,n,qn,n"))
7780146906Skan	  (const_int 0)))]
7781169699Skan   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
7782169699Skan    && ix86_match_ccmode (insn,
7783169699Skan 			 GET_CODE (operands[1]) == CONST_INT
7784169699Skan 			 && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)"
778518334Speter{
778690286Sobrien  if (which_alternative == 3)
778718334Speter    {
7788146906Skan      if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
778990286Sobrien	operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
779090286Sobrien      return "test{l}\t{%1, %k0|%k0, %1}";
779150650Sobrien    }
779290286Sobrien  return "test{b}\t{%1, %0|%0, %1}";
779390286Sobrien}
779490286Sobrien  [(set_attr "type" "test")
779590286Sobrien   (set_attr "modrm" "0,1,1,1")
779690286Sobrien   (set_attr "mode" "QI,QI,QI,SI")
779790286Sobrien   (set_attr "pent_pair" "uv,np,uv,np")])
779818334Speter
7799146906Skan(define_insn "*testqi_1"
7800169699Skan  [(set (reg FLAGS_REG)
7801146906Skan        (compare
7802146906Skan	  (and:QI
7803146906Skan	    (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm")
7804146906Skan	    (match_operand:QI 1 "general_operand" "n,n,qn"))
7805146906Skan	  (const_int 0)))]
7806146906Skan  "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
7807146906Skan   && ix86_match_ccmode (insn, CCNOmode)"
7808146906Skan  "test{b}\t{%1, %0|%0, %1}"
7809146906Skan  [(set_attr "type" "test")
7810146906Skan   (set_attr "modrm" "0,1,1")
7811146906Skan   (set_attr "mode" "QI")
7812146906Skan   (set_attr "pent_pair" "uv,np,uv")])
7813146906Skan
781490286Sobrien(define_expand "testqi_ext_ccno_0"
7815169699Skan  [(set (reg:CCNO FLAGS_REG)
781690286Sobrien	(compare:CCNO
781790286Sobrien	  (and:SI
781890286Sobrien	    (zero_extract:SI
781990286Sobrien	      (match_operand 0 "ext_register_operand" "")
782090286Sobrien	      (const_int 8)
782190286Sobrien	      (const_int 8))
782290286Sobrien	    (match_operand 1 "const_int_operand" ""))
782390286Sobrien	  (const_int 0)))]
782490286Sobrien  ""
782590286Sobrien  "")
782618334Speter
782790286Sobrien(define_insn "*testqi_ext_0"
7828169699Skan  [(set (reg FLAGS_REG)
782990286Sobrien	(compare
783090286Sobrien	  (and:SI
783190286Sobrien	    (zero_extract:SI
783290286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
783390286Sobrien	      (const_int 8)
783490286Sobrien	      (const_int 8))
783590286Sobrien	    (match_operand 1 "const_int_operand" "n"))
783690286Sobrien	  (const_int 0)))]
7837117404Skan  "ix86_match_ccmode (insn, CCNOmode)"
783890286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
783990286Sobrien  [(set_attr "type" "test")
784090286Sobrien   (set_attr "mode" "QI")
784190286Sobrien   (set_attr "length_immediate" "1")
784290286Sobrien   (set_attr "pent_pair" "np")])
784350650Sobrien
784490286Sobrien(define_insn "*testqi_ext_1"
7845169699Skan  [(set (reg FLAGS_REG)
784690286Sobrien	(compare
784790286Sobrien	  (and:SI
784890286Sobrien	    (zero_extract:SI
784990286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
785090286Sobrien	      (const_int 8)
785190286Sobrien	      (const_int 8))
785290286Sobrien	    (zero_extend:SI
7853132727Skan	      (match_operand:QI 1 "general_operand" "Qm")))
785490286Sobrien	  (const_int 0)))]
7855132727Skan  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
7856132727Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
785790286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
785890286Sobrien  [(set_attr "type" "test")
785990286Sobrien   (set_attr "mode" "QI")])
786018334Speter
786190286Sobrien(define_insn "*testqi_ext_1_rex64"
7862169699Skan  [(set (reg FLAGS_REG)
786390286Sobrien	(compare
786490286Sobrien	  (and:SI
786590286Sobrien	    (zero_extract:SI
786690286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
786790286Sobrien	      (const_int 8)
786890286Sobrien	      (const_int 8))
786990286Sobrien	    (zero_extend:SI
787090286Sobrien	      (match_operand:QI 1 "register_operand" "Q")))
787190286Sobrien	  (const_int 0)))]
787290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
787390286Sobrien  "test{b}\t{%1, %h0|%h0, %1}"
787490286Sobrien  [(set_attr "type" "test")
787590286Sobrien   (set_attr "mode" "QI")])
787618334Speter
787790286Sobrien(define_insn "*testqi_ext_2"
7878169699Skan  [(set (reg FLAGS_REG)
787990286Sobrien	(compare
788090286Sobrien	  (and:SI
788190286Sobrien	    (zero_extract:SI
788290286Sobrien	      (match_operand 0 "ext_register_operand" "Q")
788390286Sobrien	      (const_int 8)
788490286Sobrien	      (const_int 8))
788590286Sobrien	    (zero_extract:SI
788690286Sobrien	      (match_operand 1 "ext_register_operand" "Q")
788790286Sobrien	      (const_int 8)
788890286Sobrien	      (const_int 8)))
788990286Sobrien	  (const_int 0)))]
789090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
789190286Sobrien  "test{b}\t{%h1, %h0|%h0, %h1}"
789290286Sobrien  [(set_attr "type" "test")
789390286Sobrien   (set_attr "mode" "QI")])
789450650Sobrien
789590286Sobrien;; Combine likes to form bit extractions for some tests.  Humor it.
789690286Sobrien(define_insn "*testqi_ext_3"
7897169699Skan  [(set (reg FLAGS_REG)
789890286Sobrien        (compare (zero_extract:SI
789990286Sobrien		   (match_operand 0 "nonimmediate_operand" "rm")
790090286Sobrien		   (match_operand:SI 1 "const_int_operand" "")
790190286Sobrien		   (match_operand:SI 2 "const_int_operand" ""))
790290286Sobrien		 (const_int 0)))]
790390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
7904169699Skan   && INTVAL (operands[1]) > 0
7905169699Skan   && INTVAL (operands[2]) >= 0
7906169699Skan   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
790790286Sobrien   && (GET_MODE (operands[0]) == SImode
790890286Sobrien       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
790990286Sobrien       || GET_MODE (operands[0]) == HImode
791090286Sobrien       || GET_MODE (operands[0]) == QImode)"
791190286Sobrien  "#")
791250650Sobrien
791390286Sobrien(define_insn "*testqi_ext_3_rex64"
7914169699Skan  [(set (reg FLAGS_REG)
791590286Sobrien        (compare (zero_extract:DI
791690286Sobrien		   (match_operand 0 "nonimmediate_operand" "rm")
791790286Sobrien		   (match_operand:DI 1 "const_int_operand" "")
791890286Sobrien		   (match_operand:DI 2 "const_int_operand" ""))
791990286Sobrien		 (const_int 0)))]
792090286Sobrien  "TARGET_64BIT
792190286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
7922169699Skan   && INTVAL (operands[1]) > 0
7923169699Skan   && INTVAL (operands[2]) >= 0
792490286Sobrien   /* Ensure that resulting mask is zero or sign extended operand.  */
792590286Sobrien   && (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
792690286Sobrien       || (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
792790286Sobrien	   && INTVAL (operands[1]) > 32))
792890286Sobrien   && (GET_MODE (operands[0]) == SImode
792990286Sobrien       || GET_MODE (operands[0]) == DImode
793090286Sobrien       || GET_MODE (operands[0]) == HImode
793190286Sobrien       || GET_MODE (operands[0]) == QImode)"
793290286Sobrien  "#")
793350650Sobrien
793490286Sobrien(define_split
7935146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
7936146906Skan        (match_operator 1 "compare_operator"
7937146906Skan	  [(zero_extract
7938146906Skan	     (match_operand 2 "nonimmediate_operand" "")
7939146906Skan	     (match_operand 3 "const_int_operand" "")
7940146906Skan	     (match_operand 4 "const_int_operand" ""))
7941146906Skan	   (const_int 0)]))]
794290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
7943146906Skan  [(set (match_dup 0) (match_op_dup 1 [(match_dup 2) (const_int 0)]))]
794490286Sobrien{
7945146906Skan  rtx val = operands[2];
7946146906Skan  HOST_WIDE_INT len = INTVAL (operands[3]);
7947146906Skan  HOST_WIDE_INT pos = INTVAL (operands[4]);
794890286Sobrien  HOST_WIDE_INT mask;
794990286Sobrien  enum machine_mode mode, submode;
795018334Speter
7951146906Skan  mode = GET_MODE (val);
7952146906Skan  if (GET_CODE (val) == MEM)
795390286Sobrien    {
795490286Sobrien      /* ??? Combine likes to put non-volatile mem extractions in QImode
795590286Sobrien	 no matter the size of the test.  So find a mode that works.  */
7956146906Skan      if (! MEM_VOLATILE_P (val))
795718334Speter	{
795890286Sobrien	  mode = smallest_mode_for_size (pos + len, MODE_INT);
7959146906Skan	  val = adjust_address (val, mode, 0);
796090286Sobrien	}
796190286Sobrien    }
7962146906Skan  else if (GET_CODE (val) == SUBREG
7963146906Skan	   && (submode = GET_MODE (SUBREG_REG (val)),
796490286Sobrien	       GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (submode))
796590286Sobrien	   && pos + len <= GET_MODE_BITSIZE (submode))
796690286Sobrien    {
796790286Sobrien      /* Narrow a paradoxical subreg to prevent partial register stalls.  */
796890286Sobrien      mode = submode;
7969146906Skan      val = SUBREG_REG (val);
797090286Sobrien    }
797190286Sobrien  else if (mode == HImode && pos + len <= 8)
797290286Sobrien    {
797390286Sobrien      /* Small HImode tests can be converted to QImode.  */
797490286Sobrien      mode = QImode;
7975146906Skan      val = gen_lowpart (QImode, val);
797690286Sobrien    }
797718334Speter
7978169699Skan  if (len == HOST_BITS_PER_WIDE_INT)
7979169699Skan    mask = -1;
7980169699Skan  else
7981169699Skan    mask = ((HOST_WIDE_INT)1 << len) - 1;
7982169699Skan  mask <<= pos;
798318334Speter
7984146906Skan  operands[2] = gen_rtx_AND (mode, val, gen_int_mode (mask, mode));
798590286Sobrien})
798650650Sobrien
7987117404Skan;; Convert HImode/SImode test instructions with immediate to QImode ones.
7988117404Skan;; i386 does not allow to encode test with 8bit sign extended immediate, so
7989117404Skan;; this is relatively important trick.
7990132727Skan;; Do the conversion only post-reload to avoid limiting of the register class
7991117404Skan;; to QI regs.
7992117404Skan(define_split
7993146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
7994146906Skan	(match_operator 1 "compare_operator"
7995146906Skan	  [(and (match_operand 2 "register_operand" "")
7996146906Skan	        (match_operand 3 "const_int_operand" ""))
7997146906Skan	   (const_int 0)]))]
7998117404Skan   "reload_completed
7999146906Skan    && QI_REG_P (operands[2])
8000146906Skan    && GET_MODE (operands[2]) != QImode
8001117404Skan    && ((ix86_match_ccmode (insn, CCZmode)
8002146906Skan    	 && !(INTVAL (operands[3]) & ~(255 << 8)))
8003117404Skan	|| (ix86_match_ccmode (insn, CCNOmode)
8004146906Skan	    && !(INTVAL (operands[3]) & ~(127 << 8))))"
8005146906Skan  [(set (match_dup 0)
8006146906Skan	(match_op_dup 1
8007146906Skan	  [(and:SI (zero_extract:SI (match_dup 2) (const_int 8) (const_int 8))
8008146906Skan		   (match_dup 3))
8009146906Skan	   (const_int 0)]))]
8010146906Skan  "operands[2] = gen_lowpart (SImode, operands[2]);
8011146906Skan   operands[3] = gen_int_mode (INTVAL (operands[3]) >> 8, SImode);")
8012117404Skan
8013117404Skan(define_split
8014146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
8015146906Skan	(match_operator 1 "compare_operator"
8016146906Skan	  [(and (match_operand 2 "nonimmediate_operand" "")
8017146906Skan	        (match_operand 3 "const_int_operand" ""))
8018146906Skan	   (const_int 0)]))]
8019117404Skan   "reload_completed
8020146906Skan    && GET_MODE (operands[2]) != QImode
8021146906Skan    && (!REG_P (operands[2]) || ANY_QI_REG_P (operands[2]))
8022117404Skan    && ((ix86_match_ccmode (insn, CCZmode)
8023146906Skan	 && !(INTVAL (operands[3]) & ~255))
8024117404Skan	|| (ix86_match_ccmode (insn, CCNOmode)
8025146906Skan	    && !(INTVAL (operands[3]) & ~127)))"
8026146906Skan  [(set (match_dup 0)
8027146906Skan	(match_op_dup 1 [(and:QI (match_dup 2) (match_dup 3))
8028146906Skan			 (const_int 0)]))]
8029146906Skan  "operands[2] = gen_lowpart (QImode, operands[2]);
8030146906Skan   operands[3] = gen_lowpart (QImode, operands[3]);")
8031117404Skan
8032117404Skan
803390286Sobrien;; %%% This used to optimize known byte-wide and operations to memory,
803490286Sobrien;; and sometimes to QImode registers.  If this is considered useful,
803590286Sobrien;; it should be done with splitters.
803618334Speter
803790286Sobrien(define_expand "anddi3"
803890286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
803990286Sobrien	(and:DI (match_operand:DI 1 "nonimmediate_operand" "")
804090286Sobrien		(match_operand:DI 2 "x86_64_szext_general_operand" "")))
8041169699Skan   (clobber (reg:CC FLAGS_REG))]
804290286Sobrien  "TARGET_64BIT"
804390286Sobrien  "ix86_expand_binary_operator (AND, DImode, operands); DONE;")
804450650Sobrien
804590286Sobrien(define_insn "*anddi_1_rex64"
804690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
804790286Sobrien	(and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm")
804890286Sobrien		(match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L")))
8049169699Skan   (clobber (reg:CC FLAGS_REG))]
805090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)"
805190286Sobrien{
805290286Sobrien  switch (get_attr_type (insn))
805390286Sobrien    {
805490286Sobrien    case TYPE_IMOVX:
805590286Sobrien      {
805690286Sobrien	enum machine_mode mode;
805750650Sobrien
8058169699Skan	gcc_assert (GET_CODE (operands[2]) == CONST_INT);
805990286Sobrien        if (INTVAL (operands[2]) == 0xff)
806090286Sobrien	  mode = QImode;
806190286Sobrien	else
8062169699Skan	  {
8063169699Skan	    gcc_assert (INTVAL (operands[2]) == 0xffff);
8064169699Skan	    mode = HImode;
8065169699Skan	  }
806690286Sobrien	
806790286Sobrien	operands[1] = gen_lowpart (mode, operands[1]);
806890286Sobrien	if (mode == QImode)
806990286Sobrien	  return "movz{bq|x}\t{%1,%0|%0, %1}";
807090286Sobrien	else
807190286Sobrien	  return "movz{wq|x}\t{%1,%0|%0, %1}";
807290286Sobrien      }
807350650Sobrien
807450650Sobrien    default:
8075169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
807690286Sobrien      if (get_attr_mode (insn) == MODE_SI)
807790286Sobrien	return "and{l}\t{%k2, %k0|%k0, %k2}";
807890286Sobrien      else
807990286Sobrien	return "and{q}\t{%2, %0|%0, %2}";
808018334Speter    }
808190286Sobrien}
808290286Sobrien  [(set_attr "type" "alu,alu,alu,imovx")
808390286Sobrien   (set_attr "length_immediate" "*,*,*,0")
808490286Sobrien   (set_attr "mode" "SI,DI,DI,DI")])
808518334Speter
808690286Sobrien(define_insn "*anddi_2"
8087169699Skan  [(set (reg FLAGS_REG)
808890286Sobrien	(compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
808990286Sobrien			 (match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re"))
809090286Sobrien		 (const_int 0)))
809190286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm")
809290286Sobrien	(and:DI (match_dup 1) (match_dup 2)))]
809390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
809490286Sobrien   && ix86_binary_operator_ok (AND, DImode, operands)"
809590286Sobrien  "@
8096169699Skan   and{l}\t{%k2, %k0|%k0, %k2}
8097169699Skan   and{q}\t{%2, %0|%0, %2}
809890286Sobrien   and{q}\t{%2, %0|%0, %2}"
809990286Sobrien  [(set_attr "type" "alu")
810090286Sobrien   (set_attr "mode" "SI,DI,DI")])
810118334Speter
810290286Sobrien(define_expand "andsi3"
810390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
810490286Sobrien	(and:SI (match_operand:SI 1 "nonimmediate_operand" "")
810590286Sobrien		(match_operand:SI 2 "general_operand" "")))
8106169699Skan   (clobber (reg:CC FLAGS_REG))]
810718334Speter  ""
810890286Sobrien  "ix86_expand_binary_operator (AND, SImode, operands); DONE;")
810990286Sobrien
811090286Sobrien(define_insn "*andsi_1"
811190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r")
811290286Sobrien	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm")
811390286Sobrien		(match_operand:SI 2 "general_operand" "ri,rm,L")))
8114169699Skan   (clobber (reg:CC FLAGS_REG))]
811590286Sobrien  "ix86_binary_operator_ok (AND, SImode, operands)"
811618334Speter{
811790286Sobrien  switch (get_attr_type (insn))
811818334Speter    {
811990286Sobrien    case TYPE_IMOVX:
812090286Sobrien      {
812190286Sobrien	enum machine_mode mode;
812218334Speter
8123169699Skan	gcc_assert (GET_CODE (operands[2]) == CONST_INT);
812490286Sobrien        if (INTVAL (operands[2]) == 0xff)
812590286Sobrien	  mode = QImode;
812690286Sobrien	else
8127169699Skan	  {
8128169699Skan	    gcc_assert (INTVAL (operands[2]) == 0xffff);
8129169699Skan	    mode = HImode;
8130169699Skan	  }
813190286Sobrien	
813290286Sobrien	operands[1] = gen_lowpart (mode, operands[1]);
813390286Sobrien	if (mode == QImode)
813490286Sobrien	  return "movz{bl|x}\t{%1,%0|%0, %1}";
813590286Sobrien	else
813690286Sobrien	  return "movz{wl|x}\t{%1,%0|%0, %1}";
813790286Sobrien      }
813818334Speter
813990286Sobrien    default:
8140169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
814190286Sobrien      return "and{l}\t{%2, %0|%0, %2}";
814290286Sobrien    }
814390286Sobrien}
814490286Sobrien  [(set_attr "type" "alu,alu,imovx")
814590286Sobrien   (set_attr "length_immediate" "*,*,0")
814690286Sobrien   (set_attr "mode" "SI")])
814718334Speter
814890286Sobrien(define_split
814990286Sobrien  [(set (match_operand 0 "register_operand" "")
815090286Sobrien	(and (match_dup 0)
815190286Sobrien	     (const_int -65536)))
8152169699Skan   (clobber (reg:CC FLAGS_REG))]
8153117404Skan  "optimize_size || (TARGET_FAST_PREFIX && !TARGET_PARTIAL_REG_STALL)"
815490286Sobrien  [(set (strict_low_part (match_dup 1)) (const_int 0))]
815590286Sobrien  "operands[1] = gen_lowpart (HImode, operands[0]);")
815618334Speter
815790286Sobrien(define_split
815890286Sobrien  [(set (match_operand 0 "ext_register_operand" "")
815990286Sobrien	(and (match_dup 0)
816090286Sobrien	     (const_int -256)))
8161169699Skan   (clobber (reg:CC FLAGS_REG))]
816290286Sobrien  "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
816390286Sobrien  [(set (strict_low_part (match_dup 1)) (const_int 0))]
816490286Sobrien  "operands[1] = gen_lowpart (QImode, operands[0]);")
816518334Speter
816690286Sobrien(define_split
816790286Sobrien  [(set (match_operand 0 "ext_register_operand" "")
816890286Sobrien	(and (match_dup 0)
816990286Sobrien	     (const_int -65281)))
8170169699Skan   (clobber (reg:CC FLAGS_REG))]
817190286Sobrien  "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
817290286Sobrien  [(parallel [(set (zero_extract:SI (match_dup 0)
817390286Sobrien				    (const_int 8)
817490286Sobrien				    (const_int 8))
817590286Sobrien		   (xor:SI 
817690286Sobrien		     (zero_extract:SI (match_dup 0)
817790286Sobrien				      (const_int 8)
817890286Sobrien				      (const_int 8))
817990286Sobrien		     (zero_extract:SI (match_dup 0)
818090286Sobrien				      (const_int 8)
818190286Sobrien				      (const_int 8))))
8182169699Skan	      (clobber (reg:CC FLAGS_REG))])]
818390286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);")
818450650Sobrien
818590286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
818690286Sobrien(define_insn "*andsi_1_zext"
818790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
818890286Sobrien	(zero_extend:DI
818990286Sobrien	  (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
819090286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8191169699Skan   (clobber (reg:CC FLAGS_REG))]
819290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
819390286Sobrien  "and{l}\t{%2, %k0|%k0, %2}"
819490286Sobrien  [(set_attr "type" "alu")
819590286Sobrien   (set_attr "mode" "SI")])
819618334Speter
819790286Sobrien(define_insn "*andsi_2"
8198169699Skan  [(set (reg FLAGS_REG)
819990286Sobrien	(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
820090286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
820190286Sobrien		 (const_int 0)))
820290286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
820390286Sobrien	(and:SI (match_dup 1) (match_dup 2)))]
820490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
820590286Sobrien   && ix86_binary_operator_ok (AND, SImode, operands)"
820690286Sobrien  "and{l}\t{%2, %0|%0, %2}"
820790286Sobrien  [(set_attr "type" "alu")
820890286Sobrien   (set_attr "mode" "SI")])
820990286Sobrien
821090286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
821190286Sobrien(define_insn "*andsi_2_zext"
8212169699Skan  [(set (reg FLAGS_REG)
821390286Sobrien	(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
821490286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
821590286Sobrien		 (const_int 0)))
821690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
821790286Sobrien	(zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
821890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
821990286Sobrien   && ix86_binary_operator_ok (AND, SImode, operands)"
822090286Sobrien  "and{l}\t{%2, %k0|%k0, %2}"
822190286Sobrien  [(set_attr "type" "alu")
822290286Sobrien   (set_attr "mode" "SI")])
822390286Sobrien
822490286Sobrien(define_expand "andhi3"
822590286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
822690286Sobrien	(and:HI (match_operand:HI 1 "nonimmediate_operand" "")
822790286Sobrien		(match_operand:HI 2 "general_operand" "")))
8228169699Skan   (clobber (reg:CC FLAGS_REG))]
822990286Sobrien  "TARGET_HIMODE_MATH"
823090286Sobrien  "ix86_expand_binary_operator (AND, HImode, operands); DONE;")
823190286Sobrien
823290286Sobrien(define_insn "*andhi_1"
823390286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
823490286Sobrien	(and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,qm")
823590286Sobrien		(match_operand:HI 2 "general_operand" "ri,rm,L")))
8236169699Skan   (clobber (reg:CC FLAGS_REG))]
823790286Sobrien  "ix86_binary_operator_ok (AND, HImode, operands)"
823890286Sobrien{
823990286Sobrien  switch (get_attr_type (insn))
824050650Sobrien    {
824190286Sobrien    case TYPE_IMOVX:
8242169699Skan      gcc_assert (GET_CODE (operands[2]) == CONST_INT);
8243169699Skan      gcc_assert (INTVAL (operands[2]) == 0xff);
8244169699Skan      return "movz{bl|x}\t{%b1, %k0|%k0, %b1}";
824590286Sobrien
824690286Sobrien    default:
8247169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
824890286Sobrien
824990286Sobrien      return "and{w}\t{%2, %0|%0, %2}";
825050650Sobrien    }
825190286Sobrien}
825290286Sobrien  [(set_attr "type" "alu,alu,imovx")
825390286Sobrien   (set_attr "length_immediate" "*,*,0")
825490286Sobrien   (set_attr "mode" "HI,HI,SI")])
825550650Sobrien
825690286Sobrien(define_insn "*andhi_2"
8257169699Skan  [(set (reg FLAGS_REG)
825890286Sobrien	(compare (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
825990286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
826090286Sobrien		 (const_int 0)))
826190286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
826290286Sobrien	(and:HI (match_dup 1) (match_dup 2)))]
826390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
826490286Sobrien   && ix86_binary_operator_ok (AND, HImode, operands)"
826590286Sobrien  "and{w}\t{%2, %0|%0, %2}"
826690286Sobrien  [(set_attr "type" "alu")
826790286Sobrien   (set_attr "mode" "HI")])
826890286Sobrien
826990286Sobrien(define_expand "andqi3"
827090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
827190286Sobrien	(and:QI (match_operand:QI 1 "nonimmediate_operand" "")
827290286Sobrien		(match_operand:QI 2 "general_operand" "")))
8273169699Skan   (clobber (reg:CC FLAGS_REG))]
827490286Sobrien  "TARGET_QIMODE_MATH"
827590286Sobrien  "ix86_expand_binary_operator (AND, QImode, operands); DONE;")
827690286Sobrien
827790286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
827890286Sobrien(define_insn "*andqi_1"
827990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
828090286Sobrien	(and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
828190286Sobrien		(match_operand:QI 2 "general_operand" "qi,qmi,ri")))
8282169699Skan   (clobber (reg:CC FLAGS_REG))]
828390286Sobrien  "ix86_binary_operator_ok (AND, QImode, operands)"
828490286Sobrien  "@
828590286Sobrien   and{b}\t{%2, %0|%0, %2}
828690286Sobrien   and{b}\t{%2, %0|%0, %2}
828790286Sobrien   and{l}\t{%k2, %k0|%k0, %k2}"
828890286Sobrien  [(set_attr "type" "alu")
828990286Sobrien   (set_attr "mode" "QI,QI,SI")])
829090286Sobrien
829190286Sobrien(define_insn "*andqi_1_slp"
829290286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
829390286Sobrien	(and:QI (match_dup 0)
829490286Sobrien		(match_operand:QI 1 "general_operand" "qi,qmi")))
8295169699Skan   (clobber (reg:CC FLAGS_REG))]
8296117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8297117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
829890286Sobrien  "and{b}\t{%1, %0|%0, %1}"
829990286Sobrien  [(set_attr "type" "alu1")
830090286Sobrien   (set_attr "mode" "QI")])
830190286Sobrien
8302146906Skan(define_insn "*andqi_2_maybe_si"
8303169699Skan  [(set (reg FLAGS_REG)
830490286Sobrien	(compare (and:QI
8305146906Skan		      (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
8306146906Skan		      (match_operand:QI 2 "general_operand" "qim,qi,i"))
830790286Sobrien		 (const_int 0)))
830890286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,*r")
830990286Sobrien	(and:QI (match_dup 1) (match_dup 2)))]
8310146906Skan  "ix86_binary_operator_ok (AND, QImode, operands)
8311146906Skan   && ix86_match_ccmode (insn,
8312146906Skan			 GET_CODE (operands[2]) == CONST_INT
8313146906Skan			 && INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode)"
831490286Sobrien{
831590286Sobrien  if (which_alternative == 2)
831650650Sobrien    {
8317146906Skan      if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
831890286Sobrien        operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
831990286Sobrien      return "and{l}\t{%2, %k0|%k0, %2}";
832050650Sobrien    }
832190286Sobrien  return "and{b}\t{%2, %0|%0, %2}";
832290286Sobrien}
832390286Sobrien  [(set_attr "type" "alu")
832490286Sobrien   (set_attr "mode" "QI,QI,SI")])
832550650Sobrien
8326146906Skan(define_insn "*andqi_2"
8327169699Skan  [(set (reg FLAGS_REG)
8328146906Skan	(compare (and:QI
8329146906Skan		   (match_operand:QI 1 "nonimmediate_operand" "%0,0")
8330146906Skan		   (match_operand:QI 2 "general_operand" "qim,qi"))
8331146906Skan		 (const_int 0)))
8332146906Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
8333146906Skan	(and:QI (match_dup 1) (match_dup 2)))]
8334146906Skan  "ix86_match_ccmode (insn, CCNOmode)
8335146906Skan   && ix86_binary_operator_ok (AND, QImode, operands)"
8336146906Skan  "and{b}\t{%2, %0|%0, %2}"
8337146906Skan  [(set_attr "type" "alu")
8338146906Skan   (set_attr "mode" "QI")])
8339146906Skan
834090286Sobrien(define_insn "*andqi_2_slp"
8341169699Skan  [(set (reg FLAGS_REG)
834290286Sobrien	(compare (and:QI
834390286Sobrien		   (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
834490286Sobrien		   (match_operand:QI 1 "nonimmediate_operand" "qmi,qi"))
834590286Sobrien		 (const_int 0)))
834690286Sobrien   (set (strict_low_part (match_dup 0))
834790286Sobrien	(and:QI (match_dup 0) (match_dup 1)))]
8348117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8349117404Skan   && ix86_match_ccmode (insn, CCNOmode)
8350117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
835190286Sobrien  "and{b}\t{%1, %0|%0, %1}"
835290286Sobrien  [(set_attr "type" "alu1")
835390286Sobrien   (set_attr "mode" "QI")])
835418334Speter
835590286Sobrien;; ??? A bug in recog prevents it from recognizing a const_int as an
835690286Sobrien;; operand to zero_extend in andqi_ext_1.  It was checking explicitly
835790286Sobrien;; for a QImode operand, which of course failed.
835818334Speter
835990286Sobrien(define_insn "andqi_ext_0"
836090286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
836190286Sobrien			 (const_int 8)
836290286Sobrien			 (const_int 8))
836390286Sobrien	(and:SI 
836490286Sobrien	  (zero_extract:SI
836590286Sobrien	    (match_operand 1 "ext_register_operand" "0")
836690286Sobrien	    (const_int 8)
836790286Sobrien	    (const_int 8))
836890286Sobrien	  (match_operand 2 "const_int_operand" "n")))
8369169699Skan   (clobber (reg:CC FLAGS_REG))]
8370117404Skan  ""
837190286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
837290286Sobrien  [(set_attr "type" "alu")
837390286Sobrien   (set_attr "length_immediate" "1")
837490286Sobrien   (set_attr "mode" "QI")])
837518334Speter
837690286Sobrien;; Generated by peephole translating test to and.  This shows up
837790286Sobrien;; often in fp comparisons.
837890286Sobrien
837990286Sobrien(define_insn "*andqi_ext_0_cc"
8380169699Skan  [(set (reg FLAGS_REG)
838190286Sobrien	(compare
838290286Sobrien	  (and:SI
838390286Sobrien	    (zero_extract:SI
838490286Sobrien	      (match_operand 1 "ext_register_operand" "0")
838590286Sobrien	      (const_int 8)
838690286Sobrien	      (const_int 8))
838790286Sobrien	    (match_operand 2 "const_int_operand" "n"))
838890286Sobrien	  (const_int 0)))
838990286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
839090286Sobrien			 (const_int 8)
839190286Sobrien			 (const_int 8))
839290286Sobrien	(and:SI 
839390286Sobrien	  (zero_extract:SI
839490286Sobrien	    (match_dup 1)
839590286Sobrien	    (const_int 8)
839690286Sobrien	    (const_int 8))
839790286Sobrien	  (match_dup 2)))]
8398117404Skan  "ix86_match_ccmode (insn, CCNOmode)"
839990286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
840090286Sobrien  [(set_attr "type" "alu")
840190286Sobrien   (set_attr "length_immediate" "1")
840290286Sobrien   (set_attr "mode" "QI")])
840390286Sobrien
840490286Sobrien(define_insn "*andqi_ext_1"
840590286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
840690286Sobrien			 (const_int 8)
840790286Sobrien			 (const_int 8))
840890286Sobrien	(and:SI 
840990286Sobrien	  (zero_extract:SI
841090286Sobrien	    (match_operand 1 "ext_register_operand" "0")
841190286Sobrien	    (const_int 8)
841290286Sobrien	    (const_int 8))
841390286Sobrien	  (zero_extend:SI
841490286Sobrien	    (match_operand:QI 2 "general_operand" "Qm"))))
8415169699Skan   (clobber (reg:CC FLAGS_REG))]
841690286Sobrien  "!TARGET_64BIT"
841790286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
841890286Sobrien  [(set_attr "type" "alu")
841990286Sobrien   (set_attr "length_immediate" "0")
842090286Sobrien   (set_attr "mode" "QI")])
842190286Sobrien
842290286Sobrien(define_insn "*andqi_ext_1_rex64"
842390286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
842490286Sobrien			 (const_int 8)
842590286Sobrien			 (const_int 8))
842690286Sobrien	(and:SI 
842790286Sobrien	  (zero_extract:SI
842890286Sobrien	    (match_operand 1 "ext_register_operand" "0")
842990286Sobrien	    (const_int 8)
843090286Sobrien	    (const_int 8))
843190286Sobrien	  (zero_extend:SI
843290286Sobrien	    (match_operand 2 "ext_register_operand" "Q"))))
8433169699Skan   (clobber (reg:CC FLAGS_REG))]
843490286Sobrien  "TARGET_64BIT"
843590286Sobrien  "and{b}\t{%2, %h0|%h0, %2}"
843690286Sobrien  [(set_attr "type" "alu")
843790286Sobrien   (set_attr "length_immediate" "0")
843890286Sobrien   (set_attr "mode" "QI")])
843990286Sobrien
844090286Sobrien(define_insn "*andqi_ext_2"
844190286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
844290286Sobrien			 (const_int 8)
844390286Sobrien			 (const_int 8))
844418334Speter	(and:SI
844590286Sobrien	  (zero_extract:SI
844690286Sobrien	    (match_operand 1 "ext_register_operand" "%0")
844790286Sobrien	    (const_int 8)
844890286Sobrien	    (const_int 8))
844990286Sobrien	  (zero_extract:SI
845090286Sobrien	    (match_operand 2 "ext_register_operand" "Q")
845190286Sobrien	    (const_int 8)
845290286Sobrien	    (const_int 8))))
8453169699Skan   (clobber (reg:CC FLAGS_REG))]
845490286Sobrien  ""
845590286Sobrien  "and{b}\t{%h2, %h0|%h0, %h2}"
845690286Sobrien  [(set_attr "type" "alu")
845790286Sobrien   (set_attr "length_immediate" "0")
845890286Sobrien   (set_attr "mode" "QI")])
8459117404Skan
8460117404Skan;; Convert wide AND instructions with immediate operand to shorter QImode
8461117404Skan;; equivalents when possible.
8462132727Skan;; Don't do the splitting with memory operands, since it introduces risk
8463117404Skan;; of memory mismatch stalls.  We may want to do the splitting for optimizing
8464117404Skan;; for size, but that can (should?) be handled by generic code instead.
8465117404Skan(define_split
8466117404Skan  [(set (match_operand 0 "register_operand" "")
8467117404Skan	(and (match_operand 1 "register_operand" "")
8468117404Skan	     (match_operand 2 "const_int_operand" "")))
8469169699Skan   (clobber (reg:CC FLAGS_REG))]
8470117404Skan   "reload_completed
8471117404Skan    && QI_REG_P (operands[0])
8472117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8473117404Skan    && !(~INTVAL (operands[2]) & ~(255 << 8))
8474117404Skan    && GET_MODE (operands[0]) != QImode"
8475117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
8476117404Skan		   (and:SI (zero_extract:SI (match_dup 1)
8477117404Skan					    (const_int 8) (const_int 8))
8478117404Skan			   (match_dup 2)))
8479169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8480117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
8481117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
8482117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
8483117404Skan
8484117404Skan;; Since AND can be encoded with sign extended immediate, this is only
8485117404Skan;; profitable when 7th bit is not set.
8486117404Skan(define_split
8487117404Skan  [(set (match_operand 0 "register_operand" "")
8488117404Skan	(and (match_operand 1 "general_operand" "")
8489117404Skan	     (match_operand 2 "const_int_operand" "")))
8490169699Skan   (clobber (reg:CC FLAGS_REG))]
8491117404Skan   "reload_completed
8492117404Skan    && ANY_QI_REG_P (operands[0])
8493117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8494117404Skan    && !(~INTVAL (operands[2]) & ~255)
8495117404Skan    && !(INTVAL (operands[2]) & 128)
8496117404Skan    && GET_MODE (operands[0]) != QImode"
8497117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
8498117404Skan		   (and:QI (match_dup 1)
8499117404Skan			   (match_dup 2)))
8500169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8501117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
8502117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
8503117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
850418334Speter
850590286Sobrien;; Logical inclusive OR instructions
850618334Speter
850790286Sobrien;; %%% This used to optimize known byte-wide and operations to memory.
850890286Sobrien;; If this is considered useful, it should be done with splitters.
850990286Sobrien
851090286Sobrien(define_expand "iordi3"
851190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
851290286Sobrien	(ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
851390286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "")))
8514169699Skan   (clobber (reg:CC FLAGS_REG))]
851590286Sobrien  "TARGET_64BIT"
851690286Sobrien  "ix86_expand_binary_operator (IOR, DImode, operands); DONE;")
851790286Sobrien
851890286Sobrien(define_insn "*iordi_1_rex64"
851990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
852090286Sobrien	(ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
852190286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "re,rme")))
8522169699Skan   (clobber (reg:CC FLAGS_REG))]
852390286Sobrien  "TARGET_64BIT
852490286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
852590286Sobrien  "or{q}\t{%2, %0|%0, %2}"
852690286Sobrien  [(set_attr "type" "alu")
852790286Sobrien   (set_attr "mode" "DI")])
852890286Sobrien
852990286Sobrien(define_insn "*iordi_2_rex64"
8530169699Skan  [(set (reg FLAGS_REG)
853190286Sobrien	(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
853290286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
853390286Sobrien		 (const_int 0)))
853490286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
853590286Sobrien	(ior:DI (match_dup 1) (match_dup 2)))]
853690286Sobrien  "TARGET_64BIT
853790286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
853890286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
853990286Sobrien  "or{q}\t{%2, %0|%0, %2}"
854090286Sobrien  [(set_attr "type" "alu")
854190286Sobrien   (set_attr "mode" "DI")])
854290286Sobrien
854390286Sobrien(define_insn "*iordi_3_rex64"
8544169699Skan  [(set (reg FLAGS_REG)
854590286Sobrien	(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
854690286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem"))
854790286Sobrien		 (const_int 0)))
854890286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
854990286Sobrien  "TARGET_64BIT
855090286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
855190286Sobrien   && ix86_binary_operator_ok (IOR, DImode, operands)"
855290286Sobrien  "or{q}\t{%2, %0|%0, %2}"
855390286Sobrien  [(set_attr "type" "alu")
855490286Sobrien   (set_attr "mode" "DI")])
855590286Sobrien
855690286Sobrien
855790286Sobrien(define_expand "iorsi3"
855890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
855990286Sobrien	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
856090286Sobrien		(match_operand:SI 2 "general_operand" "")))
8561169699Skan   (clobber (reg:CC FLAGS_REG))]
856290286Sobrien  ""
856390286Sobrien  "ix86_expand_binary_operator (IOR, SImode, operands); DONE;")
856490286Sobrien
856590286Sobrien(define_insn "*iorsi_1"
856650650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
856750650Sobrien	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
856890286Sobrien		(match_operand:SI 2 "general_operand" "ri,rmi")))
8569169699Skan   (clobber (reg:CC FLAGS_REG))]
857090286Sobrien  "ix86_binary_operator_ok (IOR, SImode, operands)"
857190286Sobrien  "or{l}\t{%2, %0|%0, %2}"
857290286Sobrien  [(set_attr "type" "alu")
857390286Sobrien   (set_attr "mode" "SI")])
857450650Sobrien
857590286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
857690286Sobrien(define_insn "*iorsi_1_zext"
857790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm")
857890286Sobrien	(zero_extend:DI
857990286Sobrien	  (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
858090286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8581169699Skan   (clobber (reg:CC FLAGS_REG))]
858290286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)"
858390286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
858490286Sobrien  [(set_attr "type" "alu")
858590286Sobrien   (set_attr "mode" "SI")])
858650650Sobrien
858790286Sobrien(define_insn "*iorsi_1_zext_imm"
858890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=rm")
858990286Sobrien	(ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
859090286Sobrien		(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
8591169699Skan   (clobber (reg:CC FLAGS_REG))]
859290286Sobrien  "TARGET_64BIT"
859390286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
859490286Sobrien  [(set_attr "type" "alu")
859590286Sobrien   (set_attr "mode" "SI")])
859650650Sobrien
859790286Sobrien(define_insn "*iorsi_2"
8598169699Skan  [(set (reg FLAGS_REG)
859990286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
860090286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
860190286Sobrien		 (const_int 0)))
860290286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
860390286Sobrien	(ior:SI (match_dup 1) (match_dup 2)))]
860490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
860590286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
860690286Sobrien  "or{l}\t{%2, %0|%0, %2}"
860790286Sobrien  [(set_attr "type" "alu")
860890286Sobrien   (set_attr "mode" "SI")])
860950650Sobrien
861090286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
861190286Sobrien;; ??? Special case for immediate operand is missing - it is tricky.
861290286Sobrien(define_insn "*iorsi_2_zext"
8613169699Skan  [(set (reg FLAGS_REG)
861490286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
861590286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
861690286Sobrien		 (const_int 0)))
861790286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
861890286Sobrien	(zero_extend:DI (ior:SI (match_dup 1) (match_dup 2))))]
861990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
862090286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
862190286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
862290286Sobrien  [(set_attr "type" "alu")
862390286Sobrien   (set_attr "mode" "SI")])
862450650Sobrien
862590286Sobrien(define_insn "*iorsi_2_zext_imm"
8626169699Skan  [(set (reg FLAGS_REG)
862790286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
862890286Sobrien			 (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
862990286Sobrien		 (const_int 0)))
863090286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
863190286Sobrien	(ior:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
863290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
863390286Sobrien   && ix86_binary_operator_ok (IOR, SImode, operands)"
863490286Sobrien  "or{l}\t{%2, %k0|%k0, %2}"
863590286Sobrien  [(set_attr "type" "alu")
863690286Sobrien   (set_attr "mode" "SI")])
863750650Sobrien
863890286Sobrien(define_insn "*iorsi_3"
8639169699Skan  [(set (reg FLAGS_REG)
864090286Sobrien	(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
864190286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
864290286Sobrien		 (const_int 0)))
864390286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
864490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
864590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
864690286Sobrien  "or{l}\t{%2, %0|%0, %2}"
864790286Sobrien  [(set_attr "type" "alu")
864890286Sobrien   (set_attr "mode" "SI")])
864950650Sobrien
865090286Sobrien(define_expand "iorhi3"
865190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
865290286Sobrien	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "")
865390286Sobrien		(match_operand:HI 2 "general_operand" "")))
8654169699Skan   (clobber (reg:CC FLAGS_REG))]
865590286Sobrien  "TARGET_HIMODE_MATH"
865690286Sobrien  "ix86_expand_binary_operator (IOR, HImode, operands); DONE;")
865750650Sobrien
865890286Sobrien(define_insn "*iorhi_1"
865990286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
866090286Sobrien	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
866190286Sobrien		(match_operand:HI 2 "general_operand" "rmi,ri")))
8662169699Skan   (clobber (reg:CC FLAGS_REG))]
866390286Sobrien  "ix86_binary_operator_ok (IOR, HImode, operands)"
866490286Sobrien  "or{w}\t{%2, %0|%0, %2}"
866590286Sobrien  [(set_attr "type" "alu")
866690286Sobrien   (set_attr "mode" "HI")])
866718334Speter
866890286Sobrien(define_insn "*iorhi_2"
8669169699Skan  [(set (reg FLAGS_REG)
867090286Sobrien	(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
867190286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
867290286Sobrien		 (const_int 0)))
867390286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
867490286Sobrien	(ior:HI (match_dup 1) (match_dup 2)))]
867590286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
867690286Sobrien   && ix86_binary_operator_ok (IOR, HImode, operands)"
867790286Sobrien  "or{w}\t{%2, %0|%0, %2}"
867890286Sobrien  [(set_attr "type" "alu")
867990286Sobrien   (set_attr "mode" "HI")])
868018334Speter
868190286Sobrien(define_insn "*iorhi_3"
8682169699Skan  [(set (reg FLAGS_REG)
868390286Sobrien	(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
868490286Sobrien			 (match_operand:HI 2 "general_operand" "rim"))
868590286Sobrien		 (const_int 0)))
868690286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
868790286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
868890286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
868990286Sobrien  "or{w}\t{%2, %0|%0, %2}"
869090286Sobrien  [(set_attr "type" "alu")
869190286Sobrien   (set_attr "mode" "HI")])
869250650Sobrien
869390286Sobrien(define_expand "iorqi3"
869490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
869590286Sobrien	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "")
869690286Sobrien		(match_operand:QI 2 "general_operand" "")))
8697169699Skan   (clobber (reg:CC FLAGS_REG))]
869890286Sobrien  "TARGET_QIMODE_MATH"
869990286Sobrien  "ix86_expand_binary_operator (IOR, QImode, operands); DONE;")
870018334Speter
870190286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
870290286Sobrien(define_insn "*iorqi_1"
870390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
870490286Sobrien	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
870590286Sobrien		(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
8706169699Skan   (clobber (reg:CC FLAGS_REG))]
870790286Sobrien  "ix86_binary_operator_ok (IOR, QImode, operands)"
870890286Sobrien  "@
870990286Sobrien   or{b}\t{%2, %0|%0, %2}
871090286Sobrien   or{b}\t{%2, %0|%0, %2}
871190286Sobrien   or{l}\t{%k2, %k0|%k0, %k2}"
871290286Sobrien  [(set_attr "type" "alu")
871390286Sobrien   (set_attr "mode" "QI,QI,SI")])
871450650Sobrien
871590286Sobrien(define_insn "*iorqi_1_slp"
871690286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m"))
871790286Sobrien	(ior:QI (match_dup 0)
871890286Sobrien		(match_operand:QI 1 "general_operand" "qmi,qi")))
8719169699Skan   (clobber (reg:CC FLAGS_REG))]
8720117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8721117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
872290286Sobrien  "or{b}\t{%1, %0|%0, %1}"
872390286Sobrien  [(set_attr "type" "alu1")
872490286Sobrien   (set_attr "mode" "QI")])
872518334Speter
872690286Sobrien(define_insn "*iorqi_2"
8727169699Skan  [(set (reg FLAGS_REG)
872890286Sobrien	(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
872990286Sobrien			 (match_operand:QI 2 "general_operand" "qim,qi"))
873090286Sobrien		 (const_int 0)))
873190286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
873290286Sobrien	(ior:QI (match_dup 1) (match_dup 2)))]
873390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
873490286Sobrien   && ix86_binary_operator_ok (IOR, QImode, operands)"
873590286Sobrien  "or{b}\t{%2, %0|%0, %2}"
873690286Sobrien  [(set_attr "type" "alu")
873790286Sobrien   (set_attr "mode" "QI")])
873818334Speter
873990286Sobrien(define_insn "*iorqi_2_slp"
8740169699Skan  [(set (reg FLAGS_REG)
874190286Sobrien	(compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
874290286Sobrien			 (match_operand:QI 1 "general_operand" "qim,qi"))
874390286Sobrien		 (const_int 0)))
874490286Sobrien   (set (strict_low_part (match_dup 0))
874590286Sobrien	(ior:QI (match_dup 0) (match_dup 1)))]
8746117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
8747117404Skan   && ix86_match_ccmode (insn, CCNOmode)
8748117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
874990286Sobrien  "or{b}\t{%1, %0|%0, %1}"
875090286Sobrien  [(set_attr "type" "alu1")
875190286Sobrien   (set_attr "mode" "QI")])
875218334Speter
875390286Sobrien(define_insn "*iorqi_3"
8754169699Skan  [(set (reg FLAGS_REG)
875590286Sobrien	(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
875690286Sobrien			 (match_operand:QI 2 "general_operand" "qim"))
875790286Sobrien		 (const_int 0)))
875890286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
875990286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
876090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
876190286Sobrien  "or{b}\t{%2, %0|%0, %2}"
876290286Sobrien  [(set_attr "type" "alu")
876390286Sobrien   (set_attr "mode" "QI")])
876418334Speter
8765117404Skan(define_insn "iorqi_ext_0"
8766117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8767117404Skan			 (const_int 8)
8768117404Skan			 (const_int 8))
8769117404Skan	(ior:SI 
8770117404Skan	  (zero_extract:SI
8771117404Skan	    (match_operand 1 "ext_register_operand" "0")
8772117404Skan	    (const_int 8)
8773117404Skan	    (const_int 8))
8774117404Skan	  (match_operand 2 "const_int_operand" "n")))
8775169699Skan   (clobber (reg:CC FLAGS_REG))]
8776117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
8777117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8778117404Skan  [(set_attr "type" "alu")
8779117404Skan   (set_attr "length_immediate" "1")
8780117404Skan   (set_attr "mode" "QI")])
8781117404Skan
8782117404Skan(define_insn "*iorqi_ext_1"
8783117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8784117404Skan			 (const_int 8)
8785117404Skan			 (const_int 8))
8786117404Skan	(ior:SI 
8787117404Skan	  (zero_extract:SI
8788117404Skan	    (match_operand 1 "ext_register_operand" "0")
8789117404Skan	    (const_int 8)
8790117404Skan	    (const_int 8))
8791117404Skan	  (zero_extend:SI
8792117404Skan	    (match_operand:QI 2 "general_operand" "Qm"))))
8793169699Skan   (clobber (reg:CC FLAGS_REG))]
8794117404Skan  "!TARGET_64BIT
8795117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
8796117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8797117404Skan  [(set_attr "type" "alu")
8798117404Skan   (set_attr "length_immediate" "0")
8799117404Skan   (set_attr "mode" "QI")])
8800117404Skan
8801117404Skan(define_insn "*iorqi_ext_1_rex64"
8802117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8803117404Skan			 (const_int 8)
8804117404Skan			 (const_int 8))
8805117404Skan	(ior:SI 
8806117404Skan	  (zero_extract:SI
8807117404Skan	    (match_operand 1 "ext_register_operand" "0")
8808117404Skan	    (const_int 8)
8809117404Skan	    (const_int 8))
8810117404Skan	  (zero_extend:SI
8811117404Skan	    (match_operand 2 "ext_register_operand" "Q"))))
8812169699Skan   (clobber (reg:CC FLAGS_REG))]
8813117404Skan  "TARGET_64BIT
8814117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
8815117404Skan  "or{b}\t{%2, %h0|%h0, %2}"
8816117404Skan  [(set_attr "type" "alu")
8817117404Skan   (set_attr "length_immediate" "0")
8818117404Skan   (set_attr "mode" "QI")])
8819117404Skan
8820117404Skan(define_insn "*iorqi_ext_2"
8821117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
8822117404Skan			 (const_int 8)
8823117404Skan			 (const_int 8))
8824117404Skan	(ior:SI 
8825117404Skan	  (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
8826117404Skan	  		   (const_int 8)
8827117404Skan			   (const_int 8))
8828117404Skan	  (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
8829117404Skan	  		   (const_int 8)
8830117404Skan			   (const_int 8))))
8831169699Skan   (clobber (reg:CC FLAGS_REG))]
8832117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
8833117404Skan  "ior{b}\t{%h2, %h0|%h0, %h2}"
8834117404Skan  [(set_attr "type" "alu")
8835117404Skan   (set_attr "length_immediate" "0")
8836117404Skan   (set_attr "mode" "QI")])
8837117404Skan
8838117404Skan(define_split
8839117404Skan  [(set (match_operand 0 "register_operand" "")
8840117404Skan	(ior (match_operand 1 "register_operand" "")
8841117404Skan	     (match_operand 2 "const_int_operand" "")))
8842169699Skan   (clobber (reg:CC FLAGS_REG))]
8843117404Skan   "reload_completed
8844117404Skan    && QI_REG_P (operands[0])
8845117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8846117404Skan    && !(INTVAL (operands[2]) & ~(255 << 8))
8847117404Skan    && GET_MODE (operands[0]) != QImode"
8848117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
8849117404Skan		   (ior:SI (zero_extract:SI (match_dup 1)
8850117404Skan					    (const_int 8) (const_int 8))
8851117404Skan			   (match_dup 2)))
8852169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8853117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
8854117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
8855117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
8856117404Skan
8857117404Skan;; Since OR can be encoded with sign extended immediate, this is only
8858117404Skan;; profitable when 7th bit is set.
8859117404Skan(define_split
8860117404Skan  [(set (match_operand 0 "register_operand" "")
8861117404Skan	(ior (match_operand 1 "general_operand" "")
8862117404Skan	     (match_operand 2 "const_int_operand" "")))
8863169699Skan   (clobber (reg:CC FLAGS_REG))]
8864117404Skan   "reload_completed
8865117404Skan    && ANY_QI_REG_P (operands[0])
8866117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
8867117404Skan    && !(INTVAL (operands[2]) & ~255)
8868117404Skan    && (INTVAL (operands[2]) & 128)
8869117404Skan    && GET_MODE (operands[0]) != QImode"
8870117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
8871117404Skan		   (ior:QI (match_dup 1)
8872117404Skan			   (match_dup 2)))
8873169699Skan	      (clobber (reg:CC FLAGS_REG))])]
8874117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
8875117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
8876117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
887790286Sobrien
887890286Sobrien;; Logical XOR instructions
887990286Sobrien
888090286Sobrien;; %%% This used to optimize known byte-wide and operations to memory.
888190286Sobrien;; If this is considered useful, it should be done with splitters.
888290286Sobrien
888390286Sobrien(define_expand "xordi3"
888490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
888590286Sobrien	(xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
888690286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "")))
8887169699Skan   (clobber (reg:CC FLAGS_REG))]
888890286Sobrien  "TARGET_64BIT"
888990286Sobrien  "ix86_expand_binary_operator (XOR, DImode, operands); DONE;")
889090286Sobrien
889190286Sobrien(define_insn "*xordi_1_rex64"
889290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
889390286Sobrien	(xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
889490286Sobrien		(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
8895169699Skan   (clobber (reg:CC FLAGS_REG))]
889690286Sobrien  "TARGET_64BIT
889790286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
889890286Sobrien  "@
8899169699Skan   xor{q}\t{%2, %0|%0, %2}
890090286Sobrien   xor{q}\t{%2, %0|%0, %2}"
890190286Sobrien  [(set_attr "type" "alu")
890290286Sobrien   (set_attr "mode" "DI,DI")])
890390286Sobrien
890490286Sobrien(define_insn "*xordi_2_rex64"
8905169699Skan  [(set (reg FLAGS_REG)
890690286Sobrien	(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
890790286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
890890286Sobrien		 (const_int 0)))
890990286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
891090286Sobrien	(xor:DI (match_dup 1) (match_dup 2)))]
891190286Sobrien  "TARGET_64BIT
891290286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
891390286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
891490286Sobrien  "@
8915169699Skan   xor{q}\t{%2, %0|%0, %2}
891690286Sobrien   xor{q}\t{%2, %0|%0, %2}"
891790286Sobrien  [(set_attr "type" "alu")
891890286Sobrien   (set_attr "mode" "DI,DI")])
891990286Sobrien
892090286Sobrien(define_insn "*xordi_3_rex64"
8921169699Skan  [(set (reg FLAGS_REG)
892290286Sobrien	(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
892390286Sobrien			 (match_operand:DI 2 "x86_64_general_operand" "rem"))
892490286Sobrien		 (const_int 0)))
892590286Sobrien   (clobber (match_scratch:DI 0 "=r"))]
892690286Sobrien  "TARGET_64BIT
892790286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
892890286Sobrien   && ix86_binary_operator_ok (XOR, DImode, operands)"
892990286Sobrien  "xor{q}\t{%2, %0|%0, %2}"
893090286Sobrien  [(set_attr "type" "alu")
893190286Sobrien   (set_attr "mode" "DI")])
893290286Sobrien
893390286Sobrien(define_expand "xorsi3"
893490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
893590286Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "")
893690286Sobrien		(match_operand:SI 2 "general_operand" "")))
8937169699Skan   (clobber (reg:CC FLAGS_REG))]
893818334Speter  ""
893990286Sobrien  "ix86_expand_binary_operator (XOR, SImode, operands); DONE;")
894018334Speter
894190286Sobrien(define_insn "*xorsi_1"
894290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
894390286Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
894490286Sobrien		(match_operand:SI 2 "general_operand" "ri,rm")))
8945169699Skan   (clobber (reg:CC FLAGS_REG))]
894690286Sobrien  "ix86_binary_operator_ok (XOR, SImode, operands)"
894790286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
894890286Sobrien  [(set_attr "type" "alu")
894990286Sobrien   (set_attr "mode" "SI")])
895018334Speter
895190286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
895290286Sobrien;; Add speccase for immediates
895390286Sobrien(define_insn "*xorsi_1_zext"
895490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
895590286Sobrien	(zero_extend:DI
895690286Sobrien	  (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
895790286Sobrien		  (match_operand:SI 2 "general_operand" "rim"))))
8958169699Skan   (clobber (reg:CC FLAGS_REG))]
895990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
896090286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
896190286Sobrien  [(set_attr "type" "alu")
896290286Sobrien   (set_attr "mode" "SI")])
896350650Sobrien
896490286Sobrien(define_insn "*xorsi_1_zext_imm"
896590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
896690286Sobrien	(xor:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
896790286Sobrien		(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
8968169699Skan   (clobber (reg:CC FLAGS_REG))]
896990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
897090286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
897190286Sobrien  [(set_attr "type" "alu")
897290286Sobrien   (set_attr "mode" "SI")])
897350650Sobrien
897490286Sobrien(define_insn "*xorsi_2"
8975169699Skan  [(set (reg FLAGS_REG)
897690286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
897790286Sobrien			 (match_operand:SI 2 "general_operand" "rim,ri"))
897890286Sobrien		 (const_int 0)))
897990286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
898090286Sobrien	(xor:SI (match_dup 1) (match_dup 2)))]
898190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
898290286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
898390286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
898490286Sobrien  [(set_attr "type" "alu")
898590286Sobrien   (set_attr "mode" "SI")])
898650650Sobrien
898790286Sobrien;; See comment for addsi_1_zext why we do use nonimmediate_operand
898890286Sobrien;; ??? Special case for immediate operand is missing - it is tricky.
898990286Sobrien(define_insn "*xorsi_2_zext"
8990169699Skan  [(set (reg FLAGS_REG)
899190286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
899290286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
899390286Sobrien		 (const_int 0)))
899490286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
899590286Sobrien	(zero_extend:DI (xor:SI (match_dup 1) (match_dup 2))))]
899690286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
899790286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
899890286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
899990286Sobrien  [(set_attr "type" "alu")
900090286Sobrien   (set_attr "mode" "SI")])
900150650Sobrien
900290286Sobrien(define_insn "*xorsi_2_zext_imm"
9003169699Skan  [(set (reg FLAGS_REG)
900490286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
900590286Sobrien			 (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
900690286Sobrien		 (const_int 0)))
900790286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
900890286Sobrien	(xor:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
900990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
901090286Sobrien   && ix86_binary_operator_ok (XOR, SImode, operands)"
901190286Sobrien  "xor{l}\t{%2, %k0|%k0, %2}"
901290286Sobrien  [(set_attr "type" "alu")
901390286Sobrien   (set_attr "mode" "SI")])
901450650Sobrien
901590286Sobrien(define_insn "*xorsi_3"
9016169699Skan  [(set (reg FLAGS_REG)
901790286Sobrien	(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
901890286Sobrien			 (match_operand:SI 2 "general_operand" "rim"))
901990286Sobrien		 (const_int 0)))
902090286Sobrien   (clobber (match_scratch:SI 0 "=r"))]
902190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
902290286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
902390286Sobrien  "xor{l}\t{%2, %0|%0, %2}"
902490286Sobrien  [(set_attr "type" "alu")
902590286Sobrien   (set_attr "mode" "SI")])
902618334Speter
902790286Sobrien(define_expand "xorhi3"
902890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
902990286Sobrien	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "")
903090286Sobrien		(match_operand:HI 2 "general_operand" "")))
9031169699Skan   (clobber (reg:CC FLAGS_REG))]
903290286Sobrien  "TARGET_HIMODE_MATH"
903390286Sobrien  "ix86_expand_binary_operator (XOR, HImode, operands); DONE;")
903418334Speter
903590286Sobrien(define_insn "*xorhi_1"
903690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
903790286Sobrien	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
903890286Sobrien		(match_operand:HI 2 "general_operand" "rmi,ri")))
9039169699Skan   (clobber (reg:CC FLAGS_REG))]
904090286Sobrien  "ix86_binary_operator_ok (XOR, HImode, operands)"
904190286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
904290286Sobrien  [(set_attr "type" "alu")
904390286Sobrien   (set_attr "mode" "HI")])
904418334Speter
904590286Sobrien(define_insn "*xorhi_2"
9046169699Skan  [(set (reg FLAGS_REG)
904790286Sobrien	(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
904890286Sobrien			 (match_operand:HI 2 "general_operand" "rim,ri"))
904990286Sobrien		 (const_int 0)))
905090286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
905190286Sobrien	(xor:HI (match_dup 1) (match_dup 2)))]
905290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
905390286Sobrien   && ix86_binary_operator_ok (XOR, HImode, operands)"
905490286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
905590286Sobrien  [(set_attr "type" "alu")
905690286Sobrien   (set_attr "mode" "HI")])
905750650Sobrien
905890286Sobrien(define_insn "*xorhi_3"
9059169699Skan  [(set (reg FLAGS_REG)
906090286Sobrien	(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
906190286Sobrien			 (match_operand:HI 2 "general_operand" "rim"))
906290286Sobrien		 (const_int 0)))
906390286Sobrien   (clobber (match_scratch:HI 0 "=r"))]
906490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
906590286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
906690286Sobrien  "xor{w}\t{%2, %0|%0, %2}"
906790286Sobrien  [(set_attr "type" "alu")
906890286Sobrien   (set_attr "mode" "HI")])
906950650Sobrien
907090286Sobrien(define_expand "xorqi3"
907190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
907290286Sobrien	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "")
907390286Sobrien		(match_operand:QI 2 "general_operand" "")))
9074169699Skan   (clobber (reg:CC FLAGS_REG))]
907590286Sobrien  "TARGET_QIMODE_MATH"
907690286Sobrien  "ix86_expand_binary_operator (XOR, QImode, operands); DONE;")
907750650Sobrien
907890286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
907990286Sobrien(define_insn "*xorqi_1"
908090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
908190286Sobrien	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
908290286Sobrien		(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
9083169699Skan   (clobber (reg:CC FLAGS_REG))]
908490286Sobrien  "ix86_binary_operator_ok (XOR, QImode, operands)"
908590286Sobrien  "@
908690286Sobrien   xor{b}\t{%2, %0|%0, %2}
908790286Sobrien   xor{b}\t{%2, %0|%0, %2}
908890286Sobrien   xor{l}\t{%k2, %k0|%k0, %k2}"
908990286Sobrien  [(set_attr "type" "alu")
909090286Sobrien   (set_attr "mode" "QI,QI,SI")])
909118334Speter
9092117404Skan(define_insn "*xorqi_1_slp"
9093117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
9094117404Skan	(xor:QI (match_dup 0)
9095117404Skan		(match_operand:QI 1 "general_operand" "qi,qmi")))
9096169699Skan   (clobber (reg:CC FLAGS_REG))]
9097117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
9098117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
9099117404Skan  "xor{b}\t{%1, %0|%0, %1}"
9100117404Skan  [(set_attr "type" "alu1")
9101117404Skan   (set_attr "mode" "QI")])
9102117404Skan
9103117404Skan(define_insn "xorqi_ext_0"
9104117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9105117404Skan			 (const_int 8)
9106117404Skan			 (const_int 8))
9107117404Skan	(xor:SI 
9108117404Skan	  (zero_extract:SI
9109117404Skan	    (match_operand 1 "ext_register_operand" "0")
9110117404Skan	    (const_int 8)
9111117404Skan	    (const_int 8))
9112117404Skan	  (match_operand 2 "const_int_operand" "n")))
9113169699Skan   (clobber (reg:CC FLAGS_REG))]
9114117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
9115117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9116117404Skan  [(set_attr "type" "alu")
9117117404Skan   (set_attr "length_immediate" "1")
9118117404Skan   (set_attr "mode" "QI")])
9119117404Skan
912090286Sobrien(define_insn "*xorqi_ext_1"
912190286Sobrien  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
912290286Sobrien			 (const_int 8)
912390286Sobrien			 (const_int 8))
912490286Sobrien	(xor:SI 
9125117404Skan	  (zero_extract:SI
9126117404Skan	    (match_operand 1 "ext_register_operand" "0")
9127117404Skan	    (const_int 8)
9128117404Skan	    (const_int 8))
9129117404Skan	  (zero_extend:SI
9130117404Skan	    (match_operand:QI 2 "general_operand" "Qm"))))
9131169699Skan   (clobber (reg:CC FLAGS_REG))]
9132117404Skan  "!TARGET_64BIT
9133117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
9134117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9135117404Skan  [(set_attr "type" "alu")
9136117404Skan   (set_attr "length_immediate" "0")
9137117404Skan   (set_attr "mode" "QI")])
9138117404Skan
9139117404Skan(define_insn "*xorqi_ext_1_rex64"
9140117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9141117404Skan			 (const_int 8)
9142117404Skan			 (const_int 8))
9143117404Skan	(xor:SI 
9144117404Skan	  (zero_extract:SI
9145117404Skan	    (match_operand 1 "ext_register_operand" "0")
9146117404Skan	    (const_int 8)
9147117404Skan	    (const_int 8))
9148117404Skan	  (zero_extend:SI
9149117404Skan	    (match_operand 2 "ext_register_operand" "Q"))))
9150169699Skan   (clobber (reg:CC FLAGS_REG))]
9151117404Skan  "TARGET_64BIT
9152117404Skan   && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
9153117404Skan  "xor{b}\t{%2, %h0|%h0, %2}"
9154117404Skan  [(set_attr "type" "alu")
9155117404Skan   (set_attr "length_immediate" "0")
9156117404Skan   (set_attr "mode" "QI")])
9157117404Skan
9158117404Skan(define_insn "*xorqi_ext_2"
9159117404Skan  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
9160117404Skan			 (const_int 8)
9161117404Skan			 (const_int 8))
9162117404Skan	(xor:SI 
916390286Sobrien	  (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
916490286Sobrien	  		   (const_int 8)
916590286Sobrien			   (const_int 8))
916690286Sobrien	  (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
916790286Sobrien	  		   (const_int 8)
916890286Sobrien			   (const_int 8))))
9169169699Skan   (clobber (reg:CC FLAGS_REG))]
9170117404Skan  "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
917190286Sobrien  "xor{b}\t{%h2, %h0|%h0, %h2}"
917290286Sobrien  [(set_attr "type" "alu")
917390286Sobrien   (set_attr "length_immediate" "0")
917490286Sobrien   (set_attr "mode" "QI")])
917550650Sobrien
917690286Sobrien(define_insn "*xorqi_cc_1"
9177169699Skan  [(set (reg FLAGS_REG)
917890286Sobrien	(compare
917990286Sobrien	  (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
918090286Sobrien		  (match_operand:QI 2 "general_operand" "qim,qi"))
918190286Sobrien	  (const_int 0)))
918290286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm")
918390286Sobrien	(xor:QI (match_dup 1) (match_dup 2)))]
918490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
918590286Sobrien   && ix86_binary_operator_ok (XOR, QImode, operands)"
918690286Sobrien  "xor{b}\t{%2, %0|%0, %2}"
918790286Sobrien  [(set_attr "type" "alu")
918890286Sobrien   (set_attr "mode" "QI")])
918950650Sobrien
9190117404Skan(define_insn "*xorqi_2_slp"
9191169699Skan  [(set (reg FLAGS_REG)
9192117404Skan	(compare (xor:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
9193117404Skan			 (match_operand:QI 1 "general_operand" "qim,qi"))
9194117404Skan		 (const_int 0)))
9195117404Skan   (set (strict_low_part (match_dup 0))
9196117404Skan	(xor:QI (match_dup 0) (match_dup 1)))]
9197117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
9198117404Skan   && ix86_match_ccmode (insn, CCNOmode)
9199117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
9200117404Skan  "xor{b}\t{%1, %0|%0, %1}"
9201117404Skan  [(set_attr "type" "alu1")
9202117404Skan   (set_attr "mode" "QI")])
9203117404Skan
920490286Sobrien(define_insn "*xorqi_cc_2"
9205169699Skan  [(set (reg FLAGS_REG)
920690286Sobrien	(compare
920790286Sobrien	  (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
920890286Sobrien		  (match_operand:QI 2 "general_operand" "qim"))
920990286Sobrien	  (const_int 0)))
921090286Sobrien   (clobber (match_scratch:QI 0 "=q"))]
921190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
921290286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
921390286Sobrien  "xor{b}\t{%2, %0|%0, %2}"
921490286Sobrien  [(set_attr "type" "alu")
921590286Sobrien   (set_attr "mode" "QI")])
921618334Speter
921790286Sobrien(define_insn "*xorqi_cc_ext_1"
9218169699Skan  [(set (reg FLAGS_REG)
921990286Sobrien	(compare
922090286Sobrien	  (xor:SI
922190286Sobrien	    (zero_extract:SI
922290286Sobrien	      (match_operand 1 "ext_register_operand" "0")
922390286Sobrien	      (const_int 8)
922490286Sobrien	      (const_int 8))
922590286Sobrien	    (match_operand:QI 2 "general_operand" "qmn"))
922690286Sobrien	  (const_int 0)))
922790286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=q")
922890286Sobrien			 (const_int 8)
922990286Sobrien			 (const_int 8))
923090286Sobrien	(xor:SI 
923190286Sobrien	  (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
923290286Sobrien	  (match_dup 2)))]
923390286Sobrien  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
923490286Sobrien  "xor{b}\t{%2, %h0|%h0, %2}"
923590286Sobrien  [(set_attr "type" "alu")
923690286Sobrien   (set_attr "mode" "QI")])
923790286Sobrien
923890286Sobrien(define_insn "*xorqi_cc_ext_1_rex64"
9239169699Skan  [(set (reg FLAGS_REG)
924090286Sobrien	(compare
924190286Sobrien	  (xor:SI
924290286Sobrien	    (zero_extract:SI
924390286Sobrien	      (match_operand 1 "ext_register_operand" "0")
924490286Sobrien	      (const_int 8)
924590286Sobrien	      (const_int 8))
924690286Sobrien	    (match_operand:QI 2 "nonmemory_operand" "Qn"))
924790286Sobrien	  (const_int 0)))
924890286Sobrien   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
924990286Sobrien			 (const_int 8)
925090286Sobrien			 (const_int 8))
925190286Sobrien	(xor:SI 
925290286Sobrien	  (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
925390286Sobrien	  (match_dup 2)))]
925490286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
925590286Sobrien  "xor{b}\t{%2, %h0|%h0, %2}"
925690286Sobrien  [(set_attr "type" "alu")
925790286Sobrien   (set_attr "mode" "QI")])
925890286Sobrien
925990286Sobrien(define_expand "xorqi_cc_ext_1"
926090286Sobrien  [(parallel [
9261169699Skan     (set (reg:CCNO FLAGS_REG)
926290286Sobrien	  (compare:CCNO
926390286Sobrien	    (xor:SI
926490286Sobrien	      (zero_extract:SI
926590286Sobrien		(match_operand 1 "ext_register_operand" "")
926690286Sobrien		(const_int 8)
926790286Sobrien		(const_int 8))
926890286Sobrien	      (match_operand:QI 2 "general_operand" ""))
926990286Sobrien	    (const_int 0)))
927090286Sobrien     (set (zero_extract:SI (match_operand 0 "ext_register_operand" "")
927190286Sobrien			   (const_int 8)
927290286Sobrien			   (const_int 8))
927390286Sobrien	  (xor:SI 
927490286Sobrien	    (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))
927590286Sobrien	    (match_dup 2)))])]
927618334Speter  ""
927790286Sobrien  "")
9278117404Skan
9279117404Skan(define_split
9280117404Skan  [(set (match_operand 0 "register_operand" "")
9281117404Skan	(xor (match_operand 1 "register_operand" "")
9282117404Skan	     (match_operand 2 "const_int_operand" "")))
9283169699Skan   (clobber (reg:CC FLAGS_REG))]
9284117404Skan   "reload_completed
9285117404Skan    && QI_REG_P (operands[0])
9286117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
9287117404Skan    && !(INTVAL (operands[2]) & ~(255 << 8))
9288117404Skan    && GET_MODE (operands[0]) != QImode"
9289117404Skan  [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
9290117404Skan		   (xor:SI (zero_extract:SI (match_dup 1)
9291117404Skan					    (const_int 8) (const_int 8))
9292117404Skan			   (match_dup 2)))
9293169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9294117404Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
9295117404Skan   operands[1] = gen_lowpart (SImode, operands[1]);
9296117404Skan   operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
9297117404Skan
9298117404Skan;; Since XOR can be encoded with sign extended immediate, this is only
9299117404Skan;; profitable when 7th bit is set.
9300117404Skan(define_split
9301117404Skan  [(set (match_operand 0 "register_operand" "")
9302117404Skan	(xor (match_operand 1 "general_operand" "")
9303117404Skan	     (match_operand 2 "const_int_operand" "")))
9304169699Skan   (clobber (reg:CC FLAGS_REG))]
9305117404Skan   "reload_completed
9306117404Skan    && ANY_QI_REG_P (operands[0])
9307117404Skan    && (!TARGET_PARTIAL_REG_STALL || optimize_size)
9308117404Skan    && !(INTVAL (operands[2]) & ~255)
9309117404Skan    && (INTVAL (operands[2]) & 128)
9310117404Skan    && GET_MODE (operands[0]) != QImode"
9311117404Skan  [(parallel [(set (strict_low_part (match_dup 0))
9312117404Skan		   (xor:QI (match_dup 1)
9313117404Skan			   (match_dup 2)))
9314169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9315117404Skan  "operands[0] = gen_lowpart (QImode, operands[0]);
9316117404Skan   operands[1] = gen_lowpart (QImode, operands[1]);
9317117404Skan   operands[2] = gen_lowpart (QImode, operands[2]);")
931818334Speter
931990286Sobrien;; Negation instructions
932018334Speter
9321169699Skan(define_expand "negti2"
9322169699Skan  [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
9323169699Skan		   (neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
9324169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9325169699Skan  "TARGET_64BIT"
9326169699Skan  "ix86_expand_unary_operator (NEG, TImode, operands); DONE;")
9327169699Skan
9328169699Skan(define_insn "*negti2_1"
9329169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "=ro")
9330171835Skan	(neg:TI (match_operand:TI 1 "nonimmediate_operand" "0")))
9331169699Skan   (clobber (reg:CC FLAGS_REG))]
9332169699Skan  "TARGET_64BIT
9333169699Skan   && ix86_unary_operator_ok (NEG, TImode, operands)"
9334169699Skan  "#")
9335169699Skan
9336169699Skan(define_split
9337169699Skan  [(set (match_operand:TI 0 "nonimmediate_operand" "")
9338171835Skan	(neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
9339169699Skan   (clobber (reg:CC FLAGS_REG))]
9340169699Skan  "TARGET_64BIT && reload_completed"
9341169699Skan  [(parallel
9342169699Skan    [(set (reg:CCZ FLAGS_REG)
9343169699Skan	  (compare:CCZ (neg:DI (match_dup 2)) (const_int 0)))
9344169699Skan     (set (match_dup 0) (neg:DI (match_dup 2)))])
9345169699Skan   (parallel
9346169699Skan    [(set (match_dup 1)
9347169699Skan	  (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
9348169699Skan			    (match_dup 3))
9349169699Skan		   (const_int 0)))
9350169699Skan     (clobber (reg:CC FLAGS_REG))])
9351169699Skan   (parallel
9352169699Skan    [(set (match_dup 1)
9353169699Skan	  (neg:DI (match_dup 1)))
9354169699Skan     (clobber (reg:CC FLAGS_REG))])]
9355169699Skan  "split_ti (operands+1, 1, operands+2, operands+3);
9356169699Skan   split_ti (operands+0, 1, operands+0, operands+1);")
9357169699Skan
935890286Sobrien(define_expand "negdi2"
935990286Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
936090286Sobrien		   (neg:DI (match_operand:DI 1 "nonimmediate_operand" "")))
9361169699Skan	      (clobber (reg:CC FLAGS_REG))])]
936218334Speter  ""
936390286Sobrien  "ix86_expand_unary_operator (NEG, DImode, operands); DONE;")
936450650Sobrien
936590286Sobrien(define_insn "*negdi2_1"
936690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=ro")
936790286Sobrien	(neg:DI (match_operand:DI 1 "general_operand" "0")))
9368169699Skan   (clobber (reg:CC FLAGS_REG))]
936990286Sobrien  "!TARGET_64BIT
937090286Sobrien   && ix86_unary_operator_ok (NEG, DImode, operands)"
937190286Sobrien  "#")
937250650Sobrien
937390286Sobrien(define_split
937490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
937590286Sobrien	(neg:DI (match_operand:DI 1 "general_operand" "")))
9376169699Skan   (clobber (reg:CC FLAGS_REG))]
937790286Sobrien  "!TARGET_64BIT && reload_completed"
937890286Sobrien  [(parallel
9379169699Skan    [(set (reg:CCZ FLAGS_REG)
938090286Sobrien	  (compare:CCZ (neg:SI (match_dup 2)) (const_int 0)))
938190286Sobrien     (set (match_dup 0) (neg:SI (match_dup 2)))])
938290286Sobrien   (parallel
938390286Sobrien    [(set (match_dup 1)
9384169699Skan	  (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
938590286Sobrien			    (match_dup 3))
938690286Sobrien		   (const_int 0)))
9387169699Skan     (clobber (reg:CC FLAGS_REG))])
938890286Sobrien   (parallel
938990286Sobrien    [(set (match_dup 1)
939090286Sobrien	  (neg:SI (match_dup 1)))
9391169699Skan     (clobber (reg:CC FLAGS_REG))])]
939290286Sobrien  "split_di (operands+1, 1, operands+2, operands+3);
939390286Sobrien   split_di (operands+0, 1, operands+0, operands+1);")
939450650Sobrien
939590286Sobrien(define_insn "*negdi2_1_rex64"
939690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
939790286Sobrien	(neg:DI (match_operand:DI 1 "nonimmediate_operand" "0")))
9398169699Skan   (clobber (reg:CC FLAGS_REG))]
939990286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
940090286Sobrien  "neg{q}\t%0"
940190286Sobrien  [(set_attr "type" "negnot")
940290286Sobrien   (set_attr "mode" "DI")])
940350650Sobrien
940490286Sobrien;; The problem with neg is that it does not perform (compare x 0),
940590286Sobrien;; it really performs (compare 0 x), which leaves us with the zero
940690286Sobrien;; flag being the only useful item.
940750650Sobrien
940890286Sobrien(define_insn "*negdi2_cmpz_rex64"
9409169699Skan  [(set (reg:CCZ FLAGS_REG)
941090286Sobrien	(compare:CCZ (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
941190286Sobrien		     (const_int 0)))
941290286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
941390286Sobrien	(neg:DI (match_dup 1)))]
941490286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
941590286Sobrien  "neg{q}\t%0"
941690286Sobrien  [(set_attr "type" "negnot")
941790286Sobrien   (set_attr "mode" "DI")])
941850650Sobrien
941918334Speter
942090286Sobrien(define_expand "negsi2"
942190286Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
942290286Sobrien		   (neg:SI (match_operand:SI 1 "nonimmediate_operand" "")))
9423169699Skan	      (clobber (reg:CC FLAGS_REG))])]
942490286Sobrien  ""
942590286Sobrien  "ix86_expand_unary_operator (NEG, SImode, operands); DONE;")
942618334Speter
942790286Sobrien(define_insn "*negsi2_1"
942890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
942990286Sobrien	(neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))
9430169699Skan   (clobber (reg:CC FLAGS_REG))]
943190286Sobrien  "ix86_unary_operator_ok (NEG, SImode, operands)"
943290286Sobrien  "neg{l}\t%0"
943390286Sobrien  [(set_attr "type" "negnot")
943490286Sobrien   (set_attr "mode" "SI")])
943550650Sobrien
943690286Sobrien;; Combine is quite creative about this pattern.
943790286Sobrien(define_insn "*negsi2_1_zext"
943890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
943990286Sobrien	(lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0")
944090286Sobrien					(const_int 32)))
944190286Sobrien		     (const_int 32)))
9442169699Skan   (clobber (reg:CC FLAGS_REG))]
944390286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
944490286Sobrien  "neg{l}\t%k0"
944590286Sobrien  [(set_attr "type" "negnot")
944690286Sobrien   (set_attr "mode" "SI")])
944750650Sobrien
944890286Sobrien;; The problem with neg is that it does not perform (compare x 0),
944990286Sobrien;; it really performs (compare 0 x), which leaves us with the zero
945090286Sobrien;; flag being the only useful item.
945118334Speter
945290286Sobrien(define_insn "*negsi2_cmpz"
9453169699Skan  [(set (reg:CCZ FLAGS_REG)
945490286Sobrien	(compare:CCZ (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
945590286Sobrien		     (const_int 0)))
945690286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
945790286Sobrien	(neg:SI (match_dup 1)))]
945890286Sobrien  "ix86_unary_operator_ok (NEG, SImode, operands)"
945990286Sobrien  "neg{l}\t%0"
946090286Sobrien  [(set_attr "type" "negnot")
946190286Sobrien   (set_attr "mode" "SI")])
946250650Sobrien
946390286Sobrien(define_insn "*negsi2_cmpz_zext"
9464169699Skan  [(set (reg:CCZ FLAGS_REG)
946590286Sobrien	(compare:CCZ (lshiftrt:DI
946690286Sobrien		       (neg:DI (ashift:DI
946790286Sobrien				 (match_operand:DI 1 "register_operand" "0")
946890286Sobrien				 (const_int 32)))
946990286Sobrien		       (const_int 32))
947090286Sobrien		     (const_int 0)))
947190286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
947290286Sobrien	(lshiftrt:DI (neg:DI (ashift:DI (match_dup 1)
947390286Sobrien					(const_int 32)))
947490286Sobrien		     (const_int 32)))]
947590286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
947690286Sobrien  "neg{l}\t%k0"
947790286Sobrien  [(set_attr "type" "negnot")
947890286Sobrien   (set_attr "mode" "SI")])
947990286Sobrien
948090286Sobrien(define_expand "neghi2"
948190286Sobrien  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
948290286Sobrien		   (neg:HI (match_operand:HI 1 "nonimmediate_operand" "")))
9483169699Skan	      (clobber (reg:CC FLAGS_REG))])]
948490286Sobrien  "TARGET_HIMODE_MATH"
948590286Sobrien  "ix86_expand_unary_operator (NEG, HImode, operands); DONE;")
948690286Sobrien
948790286Sobrien(define_insn "*neghi2_1"
948890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
948990286Sobrien	(neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))
9490169699Skan   (clobber (reg:CC FLAGS_REG))]
949190286Sobrien  "ix86_unary_operator_ok (NEG, HImode, operands)"
949290286Sobrien  "neg{w}\t%0"
949390286Sobrien  [(set_attr "type" "negnot")
949490286Sobrien   (set_attr "mode" "HI")])
949590286Sobrien
949690286Sobrien(define_insn "*neghi2_cmpz"
9497169699Skan  [(set (reg:CCZ FLAGS_REG)
949890286Sobrien	(compare:CCZ (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
949990286Sobrien		     (const_int 0)))
950090286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
950190286Sobrien	(neg:HI (match_dup 1)))]
950290286Sobrien  "ix86_unary_operator_ok (NEG, HImode, operands)"
950390286Sobrien  "neg{w}\t%0"
950490286Sobrien  [(set_attr "type" "negnot")
950590286Sobrien   (set_attr "mode" "HI")])
950690286Sobrien
950790286Sobrien(define_expand "negqi2"
950890286Sobrien  [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
950990286Sobrien		   (neg:QI (match_operand:QI 1 "nonimmediate_operand" "")))
9510169699Skan	      (clobber (reg:CC FLAGS_REG))])]
951190286Sobrien  "TARGET_QIMODE_MATH"
951290286Sobrien  "ix86_expand_unary_operator (NEG, QImode, operands); DONE;")
951390286Sobrien
951490286Sobrien(define_insn "*negqi2_1"
951590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
951690286Sobrien	(neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))
9517169699Skan   (clobber (reg:CC FLAGS_REG))]
951890286Sobrien  "ix86_unary_operator_ok (NEG, QImode, operands)"
951990286Sobrien  "neg{b}\t%0"
952090286Sobrien  [(set_attr "type" "negnot")
952190286Sobrien   (set_attr "mode" "QI")])
952290286Sobrien
952390286Sobrien(define_insn "*negqi2_cmpz"
9524169699Skan  [(set (reg:CCZ FLAGS_REG)
952590286Sobrien	(compare:CCZ (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
952690286Sobrien		     (const_int 0)))
952790286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
952890286Sobrien	(neg:QI (match_dup 1)))]
952990286Sobrien  "ix86_unary_operator_ok (NEG, QImode, operands)"
953090286Sobrien  "neg{b}\t%0"
953190286Sobrien  [(set_attr "type" "negnot")
953290286Sobrien   (set_attr "mode" "QI")])
953390286Sobrien
953490286Sobrien;; Changing of sign for FP values is doable using integer unit too.
953590286Sobrien
953690286Sobrien(define_expand "negsf2"
9537169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
9538169699Skan	(neg:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
9539146906Skan  "TARGET_80387 || TARGET_SSE_MATH"
9540169699Skan  "ix86_expand_fp_absneg_operator (NEG, SFmode, operands); DONE;")
954118334Speter
9542169699Skan(define_expand "abssf2"
9543169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "")
9544169699Skan	(abs:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
9545169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
9546169699Skan  "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
954718334Speter
9548169699Skan(define_insn "*absnegsf2_mixed"
9549169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x  ,x,f,rm")
9550169699Skan	(match_operator:SF 3 "absneg_operator"
9551169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0   ,x,0,0 ")]))
9552169699Skan   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm  ,0,X,X "))
9553169699Skan   (clobber (reg:CC FLAGS_REG))]
9554169699Skan  "TARGET_SSE_MATH && TARGET_MIX_SSE_I387
9555169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
955690286Sobrien  "#")
955718334Speter
9558169699Skan(define_insn "*absnegsf2_sse"
9559169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand"    "=x,x,rm")
9560169699Skan	(match_operator:SF 3 "absneg_operator"
9561169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0")]))
9562169699Skan   (use (match_operand:V4SF 2 "nonimmediate_operand"  "xm,0,X"))
9563169699Skan   (clobber (reg:CC FLAGS_REG))]
9564169699Skan  "TARGET_SSE_MATH
9565169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
956690286Sobrien  "#")
956718334Speter
9568169699Skan(define_insn "*absnegsf2_i387"
9569169699Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,rm")
9570169699Skan	(match_operator:SF 3 "absneg_operator"
9571169699Skan	  [(match_operand:SF 1 "nonimmediate_operand" "0,0")]))
9572169699Skan   (use (match_operand 2 "" ""))
9573169699Skan   (clobber (reg:CC FLAGS_REG))]
9574169699Skan  "TARGET_80387 && !TARGET_SSE_MATH
9575169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
9576169699Skan  "#")
957790286Sobrien
9578169699Skan(define_expand "copysignsf3"
9579169699Skan  [(match_operand:SF 0 "register_operand" "")
9580169699Skan   (match_operand:SF 1 "nonmemory_operand" "")
9581169699Skan   (match_operand:SF 2 "register_operand" "")]
9582169699Skan  "TARGET_SSE_MATH"
9583169699Skan{
9584169699Skan  ix86_expand_copysign (operands);
9585169699Skan  DONE;
9586169699Skan})
958790286Sobrien
9588169699Skan(define_insn_and_split "copysignsf3_const"
9589169699Skan  [(set (match_operand:SF 0 "register_operand"          "=x")
9590169699Skan	(unspec:SF
9591169699Skan	  [(match_operand:V4SF 1 "vector_move_operand"  "xmC")
9592169699Skan	   (match_operand:SF 2 "register_operand"       "0")
9593169699Skan	   (match_operand:V4SF 3 "nonimmediate_operand" "xm")]
9594169699Skan	  UNSPEC_COPYSIGN))]
9595169699Skan  "TARGET_SSE_MATH"
9596169699Skan  "#"
9597169699Skan  "&& reload_completed"
9598169699Skan  [(const_int 0)]
959918334Speter{
9600169699Skan  ix86_split_copysign_const (operands);
9601169699Skan  DONE;
960290286Sobrien})
960318334Speter
9604169699Skan(define_insn "copysignsf3_var"
9605169699Skan  [(set (match_operand:SF 0 "register_operand"          "=x, x, x, x,x")
9606169699Skan	(unspec:SF
9607169699Skan	  [(match_operand:SF 2 "register_operand"       " x, 0, 0, x,x")
9608169699Skan	   (match_operand:SF 3 "register_operand"       " 1, 1, x, 1,x")
9609169699Skan	   (match_operand:V4SF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
9610169699Skan	   (match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
9611169699Skan	  UNSPEC_COPYSIGN))
9612169699Skan   (clobber (match_scratch:V4SF 1			"=x, x, x, x,x"))]
9613169699Skan  "TARGET_SSE_MATH"
961490286Sobrien  "#")
961518334Speter
961690286Sobrien(define_split
9617169699Skan  [(set (match_operand:SF 0 "register_operand" "")
9618169699Skan	(unspec:SF
9619169699Skan	  [(match_operand:SF 2 "register_operand" "")
9620169699Skan	   (match_operand:SF 3 "register_operand" "")
9621169699Skan	   (match_operand:V4SF 4 "" "")
9622169699Skan	   (match_operand:V4SF 5 "" "")]
9623169699Skan	  UNSPEC_COPYSIGN))
9624169699Skan   (clobber (match_scratch:V4SF 1 ""))]
9625169699Skan  "TARGET_SSE_MATH && reload_completed"
9626169699Skan  [(const_int 0)]
962790286Sobrien{
9628169699Skan  ix86_split_copysign_var (operands);
9629169699Skan  DONE;
963090286Sobrien})
963190286Sobrien
963290286Sobrien(define_expand "negdf2"
9633169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "")
9634169699Skan	(neg:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
9635146906Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
9636169699Skan  "ix86_expand_fp_absneg_operator (NEG, DFmode, operands); DONE;")
963718334Speter
9638169699Skan(define_expand "absdf2"
9639169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "")
9640169699Skan	(abs:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
9641169699Skan  "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
9642169699Skan  "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
964318334Speter
9644169699Skan(define_insn "*absnegdf2_mixed"
9645169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,f,rm")
9646169699Skan	(match_operator:DF 3 "absneg_operator"
9647169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0,0")]))
9648169699Skan   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X,X"))
9649169699Skan   (clobber (reg:CC FLAGS_REG))]
9650169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
9651169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
965290286Sobrien  "#")
965350650Sobrien
9654169699Skan(define_insn "*absnegdf2_sse"
9655169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand"    "=Y,Y,rm")
9656169699Skan	(match_operator:DF 3 "absneg_operator"
9657169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0 ")]))
9658169699Skan   (use (match_operand:V2DF 2 "nonimmediate_operand"  "Ym,0,X "))
9659169699Skan   (clobber (reg:CC FLAGS_REG))]
9660169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
9661169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
966290286Sobrien  "#")
966350650Sobrien
9664169699Skan(define_insn "*absnegdf2_i387"
9665169699Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,rm")
9666169699Skan	(match_operator:DF 3 "absneg_operator"
9667169699Skan	  [(match_operand:DF 1 "nonimmediate_operand" "0,0")]))
9668169699Skan   (use (match_operand 2 "" ""))
9669169699Skan   (clobber (reg:CC FLAGS_REG))]
9670169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
9671169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
967290286Sobrien  "#")
967318334Speter
9674169699Skan(define_expand "copysigndf3"
9675169699Skan  [(match_operand:DF 0 "register_operand" "")
9676169699Skan   (match_operand:DF 1 "nonmemory_operand" "")
9677169699Skan   (match_operand:DF 2 "register_operand" "")]
9678169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9679169699Skan{
9680169699Skan  ix86_expand_copysign (operands);
9681169699Skan  DONE;
9682169699Skan})
968350650Sobrien
9684169699Skan(define_insn_and_split "copysigndf3_const"
9685169699Skan  [(set (match_operand:DF 0 "register_operand"          "=x")
9686169699Skan	(unspec:DF
9687169699Skan	  [(match_operand:V2DF 1 "vector_move_operand"  "xmC")
9688169699Skan	   (match_operand:DF 2 "register_operand"       "0")
9689169699Skan	   (match_operand:V2DF 3 "nonimmediate_operand" "xm")]
9690169699Skan	  UNSPEC_COPYSIGN))]
9691169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9692169699Skan  "#"
9693169699Skan  "&& reload_completed"
9694169699Skan  [(const_int 0)]
9695169699Skan{
9696169699Skan  ix86_split_copysign_const (operands);
9697169699Skan  DONE;
9698169699Skan})
969950650Sobrien
9700169699Skan(define_insn "copysigndf3_var"
9701169699Skan  [(set (match_operand:DF 0 "register_operand"          "=x, x, x, x,x")
9702169699Skan	(unspec:DF
9703169699Skan	  [(match_operand:DF 2 "register_operand"       " x, 0, 0, x,x")
9704169699Skan	   (match_operand:DF 3 "register_operand"       " 1, 1, x, 1,x")
9705169699Skan	   (match_operand:V2DF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
9706169699Skan	   (match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
9707169699Skan	  UNSPEC_COPYSIGN))
9708169699Skan   (clobber (match_scratch:V2DF 1			"=x, x, x, x,x"))]
9709169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
9710169699Skan  "#")
971152296Sobrien
971290286Sobrien(define_split
971390286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
9714169699Skan	(unspec:DF
9715169699Skan	  [(match_operand:DF 2 "register_operand" "")
9716169699Skan	   (match_operand:DF 3 "register_operand" "")
9717169699Skan	   (match_operand:V2DF 4 "" "")
9718169699Skan	   (match_operand:V2DF 5 "" "")]
9719169699Skan	  UNSPEC_COPYSIGN))
9720169699Skan   (clobber (match_scratch:V2DF 1 ""))]
9721169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
9722169699Skan  [(const_int 0)]
972390286Sobrien{
9724169699Skan  ix86_split_copysign_var (operands);
9725169699Skan  DONE;
972690286Sobrien})
972752296Sobrien
972890286Sobrien(define_expand "negxf2"
9729169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "")
9730169699Skan	(neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
9731132727Skan  "TARGET_80387"
9732169699Skan  "ix86_expand_fp_absneg_operator (NEG, XFmode, operands); DONE;")
973318334Speter
9734169699Skan(define_expand "absxf2"
9735169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "")
9736169699Skan	(abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
973718334Speter  "TARGET_80387"
9738169699Skan  "ix86_expand_fp_absneg_operator (ABS, XFmode, operands); DONE;")
973918334Speter
9740169699Skan(define_insn "*absnegxf2_i387"
9741169699Skan  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,?rm")
9742169699Skan	(match_operator:XF 3 "absneg_operator"
9743169699Skan	  [(match_operand:XF 1 "nonimmediate_operand" "0,0")]))
9744169699Skan   (use (match_operand 2 "" ""))
9745169699Skan   (clobber (reg:CC FLAGS_REG))]
9746169699Skan  "TARGET_80387
9747169699Skan   && ix86_unary_operator_ok (GET_CODE (operands[3]), XFmode, operands)"
974890286Sobrien  "#")
974990286Sobrien
9750169699Skan;; Splitters for fp abs and neg.
975190286Sobrien
975290286Sobrien(define_split
9753169699Skan  [(set (match_operand 0 "fp_register_operand" "")
9754169699Skan	(match_operator 1 "absneg_operator" [(match_dup 0)]))
9755169699Skan   (use (match_operand 2 "" ""))
9756169699Skan   (clobber (reg:CC FLAGS_REG))]
9757169699Skan  "reload_completed"
9758169699Skan  [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))])
975990286Sobrien
976090286Sobrien(define_split
9761169699Skan  [(set (match_operand 0 "register_operand" "")
9762169699Skan	(match_operator 3 "absneg_operator"
9763169699Skan	  [(match_operand 1 "register_operand" "")]))
9764169699Skan   (use (match_operand 2 "nonimmediate_operand" ""))
9765169699Skan   (clobber (reg:CC FLAGS_REG))]
976690286Sobrien  "reload_completed && SSE_REG_P (operands[0])"
9767169699Skan  [(set (match_dup 0) (match_dup 3))]
9768132727Skan{
9769169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
9770169699Skan  enum machine_mode vmode = GET_MODE (operands[2]);
9771169699Skan  rtx tmp;
9772169699Skan  
9773169699Skan  operands[0] = simplify_gen_subreg (vmode, operands[0], mode, 0);
9774169699Skan  operands[1] = simplify_gen_subreg (vmode, operands[1], mode, 0);
9775132727Skan  if (operands_match_p (operands[0], operands[2]))
9776132727Skan    {
9777132727Skan      tmp = operands[1];
9778132727Skan      operands[1] = operands[2];
9779132727Skan      operands[2] = tmp;
9780132727Skan    }
9781169699Skan  if (GET_CODE (operands[3]) == ABS)
9782169699Skan    tmp = gen_rtx_AND (vmode, operands[1], operands[2]);
9783169699Skan  else
9784169699Skan    tmp = gen_rtx_XOR (vmode, operands[1], operands[2]);
9785169699Skan  operands[3] = tmp;
9786132727Skan})
978790286Sobrien
978890286Sobrien(define_split
9789169699Skan  [(set (match_operand:SF 0 "register_operand" "")
9790169699Skan	(match_operator:SF 1 "absneg_operator" [(match_dup 0)]))
9791169699Skan   (use (match_operand:V4SF 2 "" ""))
9792169699Skan   (clobber (reg:CC FLAGS_REG))]
9793169699Skan  "reload_completed"
9794169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9795169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9796169699Skan{ 
9797169699Skan  rtx tmp;
9798169699Skan  operands[0] = gen_lowpart (SImode, operands[0]);
9799169699Skan  if (GET_CODE (operands[1]) == ABS)
9800169699Skan    {
9801169699Skan      tmp = gen_int_mode (0x7fffffff, SImode);
9802169699Skan      tmp = gen_rtx_AND (SImode, operands[0], tmp);
9803169699Skan    }
9804169699Skan  else
9805169699Skan    {
9806169699Skan      tmp = gen_int_mode (0x80000000, SImode);
9807169699Skan      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9808169699Skan    }
9809169699Skan  operands[1] = tmp;
9810169699Skan})
981190286Sobrien
981290286Sobrien(define_split
9813169699Skan  [(set (match_operand:DF 0 "register_operand" "")
9814169699Skan	(match_operator:DF 1 "absneg_operator" [(match_dup 0)]))
9815169699Skan   (use (match_operand 2 "" ""))
9816169699Skan   (clobber (reg:CC FLAGS_REG))]
9817169699Skan  "reload_completed"
9818169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9819169699Skan	      (clobber (reg:CC FLAGS_REG))])]
982090286Sobrien{
9821169699Skan  rtx tmp;
9822169699Skan  if (TARGET_64BIT)
9823169699Skan    {
9824169699Skan      tmp = gen_lowpart (DImode, operands[0]);
9825169699Skan      tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63));
9826169699Skan      operands[0] = tmp;
982790286Sobrien
9828169699Skan      if (GET_CODE (operands[1]) == ABS)
9829169699Skan	tmp = const0_rtx;
9830169699Skan      else
9831169699Skan	tmp = gen_rtx_NOT (DImode, tmp);
9832169699Skan    }
9833169699Skan  else
9834169699Skan    {
9835169699Skan      operands[0] = gen_highpart (SImode, operands[0]);
9836169699Skan      if (GET_CODE (operands[1]) == ABS)
983790286Sobrien	{
9838169699Skan	  tmp = gen_int_mode (0x7fffffff, SImode);
9839169699Skan	  tmp = gen_rtx_AND (SImode, operands[0], tmp);
984090286Sobrien	}
9841169699Skan      else
9842169699Skan	{
9843169699Skan	  tmp = gen_int_mode (0x80000000, SImode);
9844169699Skan	  tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9845169699Skan	}
9846169699Skan    }
9847169699Skan  operands[1] = tmp;
9848169699Skan})
984990286Sobrien
985090286Sobrien(define_split
9851169699Skan  [(set (match_operand:XF 0 "register_operand" "")
9852169699Skan	(match_operator:XF 1 "absneg_operator" [(match_dup 0)]))
9853169699Skan   (use (match_operand 2 "" ""))
9854169699Skan   (clobber (reg:CC FLAGS_REG))]
9855169699Skan  "reload_completed"
9856169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9857169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9858169699Skan{
9859169699Skan  rtx tmp;
9860169699Skan  operands[0] = gen_rtx_REG (SImode,
9861169699Skan			     true_regnum (operands[0])
9862169699Skan			     + (TARGET_64BIT ? 1 : 2));
9863169699Skan  if (GET_CODE (operands[1]) == ABS)
9864169699Skan    {
9865169699Skan      tmp = GEN_INT (0x7fff);
9866169699Skan      tmp = gen_rtx_AND (SImode, operands[0], tmp);
9867169699Skan    }
9868169699Skan  else
9869169699Skan    {
9870169699Skan      tmp = GEN_INT (0x8000);
9871169699Skan      tmp = gen_rtx_XOR (SImode, operands[0], tmp);
9872169699Skan    }
9873169699Skan  operands[1] = tmp;
9874169699Skan})
987590286Sobrien
987690286Sobrien(define_split
9877169699Skan  [(set (match_operand 0 "memory_operand" "")
9878169699Skan	(match_operator 1 "absneg_operator" [(match_dup 0)]))
9879169699Skan   (use (match_operand 2 "" ""))
9880169699Skan   (clobber (reg:CC FLAGS_REG))]
9881169699Skan  "reload_completed"
9882169699Skan  [(parallel [(set (match_dup 0) (match_dup 1))
9883169699Skan	      (clobber (reg:CC FLAGS_REG))])]
9884169699Skan{
9885169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
9886169699Skan  int size = mode == XFmode ? 10 : GET_MODE_SIZE (mode);
9887169699Skan  rtx tmp;
988890286Sobrien
9889169699Skan  operands[0] = adjust_address (operands[0], QImode, size - 1);
9890169699Skan  if (GET_CODE (operands[1]) == ABS)
9891132727Skan    {
9892169699Skan      tmp = gen_int_mode (0x7f, QImode);
9893169699Skan      tmp = gen_rtx_AND (QImode, operands[0], tmp);
9894132727Skan    }
9895169699Skan  else
9896169699Skan    {
9897169699Skan      tmp = gen_int_mode (0x80, QImode);
9898169699Skan      tmp = gen_rtx_XOR (QImode, operands[0], tmp);
9899169699Skan    }
9900169699Skan  operands[1] = tmp;
9901132727Skan})
990290286Sobrien
9903169699Skan;; Conditionalize these after reload. If they match before reload, we 
9904169699Skan;; lose the clobber and ability to use integer instructions.
990590286Sobrien
9906169699Skan(define_insn "*negsf2_1"
9907169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
9908169699Skan	(neg:SF (match_operand:SF 1 "register_operand" "0")))]
9909169699Skan  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
9910169699Skan  "fchs"
9911169699Skan  [(set_attr "type" "fsgn")
9912169699Skan   (set_attr "mode" "SF")])
991390286Sobrien
9914169699Skan(define_insn "*negdf2_1"
9915169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
9916169699Skan	(neg:DF (match_operand:DF 1 "register_operand" "0")))]
9917169699Skan  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
9918169699Skan  "fchs"
9919169699Skan  [(set_attr "type" "fsgn")
9920169699Skan   (set_attr "mode" "DF")])
992190286Sobrien
9922169699Skan(define_insn "*negxf2_1"
9923169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
9924169699Skan	(neg:XF (match_operand:XF 1 "register_operand" "0")))]
9925132727Skan  "TARGET_80387"
9926169699Skan  "fchs"
9927169699Skan  [(set_attr "type" "fsgn")
9928169699Skan   (set_attr "mode" "XF")])
992990286Sobrien
993090286Sobrien(define_insn "*abssf2_1"
993118334Speter  [(set (match_operand:SF 0 "register_operand" "=f")
993250650Sobrien	(abs:SF (match_operand:SF 1 "register_operand" "0")))]
9933169699Skan  "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
993450650Sobrien  "fabs"
993590286Sobrien  [(set_attr "type" "fsgn")
993690286Sobrien   (set_attr "mode" "SF")])
993718334Speter
993890286Sobrien(define_insn "*absdf2_1"
993918334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
994050650Sobrien	(abs:DF (match_operand:DF 1 "register_operand" "0")))]
9941169699Skan  "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
994250650Sobrien  "fabs"
994390286Sobrien  [(set_attr "type" "fsgn")
994490286Sobrien   (set_attr "mode" "DF")])
994518334Speter
9946169699Skan(define_insn "*absxf2_1"
9947169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
9948169699Skan	(abs:XF (match_operand:XF 1 "register_operand" "0")))]
994918334Speter  "TARGET_80387"
995050650Sobrien  "fabs"
995190286Sobrien  [(set_attr "type" "fsgn")
995290286Sobrien   (set_attr "mode" "DF")])
995318334Speter
9954169699Skan(define_insn "*negextendsfdf2"
9955169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
9956169699Skan	(neg:DF (float_extend:DF
9957169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
9958169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
9959169699Skan  "fchs"
9960169699Skan  [(set_attr "type" "fsgn")
9961169699Skan   (set_attr "mode" "DF")])
9962169699Skan
9963169699Skan(define_insn "*negextenddfxf2"
996418334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
9965169699Skan	(neg:XF (float_extend:XF
9966169699Skan		  (match_operand:DF 1 "register_operand" "0"))))]
9967169699Skan  "TARGET_80387"
9968169699Skan  "fchs"
9969169699Skan  [(set_attr "type" "fsgn")
9970169699Skan   (set_attr "mode" "XF")])
9971169699Skan
9972169699Skan(define_insn "*negextendsfxf2"
9973169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
9974169699Skan	(neg:XF (float_extend:XF
9975169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
9976169699Skan  "TARGET_80387"
9977169699Skan  "fchs"
9978169699Skan  [(set_attr "type" "fsgn")
9979169699Skan   (set_attr "mode" "XF")])
9980169699Skan
9981169699Skan(define_insn "*absextendsfdf2"
9982169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
9983169699Skan	(abs:DF (float_extend:DF
9984169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
9985169699Skan  "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
998650650Sobrien  "fabs"
998790286Sobrien  [(set_attr "type" "fsgn")
998890286Sobrien   (set_attr "mode" "DF")])
998918334Speter
999090286Sobrien(define_insn "*absextenddfxf2"
999118334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
999290286Sobrien	(abs:XF (float_extend:XF
999390286Sobrien	  (match_operand:DF 1 "register_operand" "0"))))]
9994132727Skan  "TARGET_80387"
999550650Sobrien  "fabs"
999690286Sobrien  [(set_attr "type" "fsgn")
999790286Sobrien   (set_attr "mode" "XF")])
999818334Speter
999990286Sobrien(define_insn "*absextendsfxf2"
1000090286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1000190286Sobrien	(abs:XF (float_extend:XF
1000290286Sobrien	  (match_operand:SF 1 "register_operand" "0"))))]
1000390286Sobrien  "TARGET_80387"
1000490286Sobrien  "fabs"
1000590286Sobrien  [(set_attr "type" "fsgn")
1000690286Sobrien   (set_attr "mode" "XF")])
1000790286Sobrien
1000890286Sobrien;; One complement instructions
1000918334Speter
1001090286Sobrien(define_expand "one_cmpldi2"
1001190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
1001290286Sobrien	(not:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
1001390286Sobrien  "TARGET_64BIT"
1001490286Sobrien  "ix86_expand_unary_operator (NOT, DImode, operands); DONE;")
1001518334Speter
1001690286Sobrien(define_insn "*one_cmpldi2_1_rex64"
1001790286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1001890286Sobrien	(not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
1001990286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NOT, DImode, operands)"
1002090286Sobrien  "not{q}\t%0"
1002190286Sobrien  [(set_attr "type" "negnot")
1002290286Sobrien   (set_attr "mode" "DI")])
1002318334Speter
1002490286Sobrien(define_insn "*one_cmpldi2_2_rex64"
10025169699Skan  [(set (reg FLAGS_REG)
1002690286Sobrien	(compare (not:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
1002790286Sobrien		 (const_int 0)))
1002890286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1002990286Sobrien	(not:DI (match_dup 1)))]
1003090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
1003190286Sobrien   && ix86_unary_operator_ok (NOT, DImode, operands)"
1003290286Sobrien  "#"
1003390286Sobrien  [(set_attr "type" "alu1")
1003490286Sobrien   (set_attr "mode" "DI")])
1003518334Speter
1003690286Sobrien(define_split
10037146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10038146906Skan	(match_operator 2 "compare_operator"
10039146906Skan	  [(not:DI (match_operand:DI 3 "nonimmediate_operand" ""))
10040146906Skan	   (const_int 0)]))
10041146906Skan   (set (match_operand:DI 1 "nonimmediate_operand" "")
10042146906Skan	(not:DI (match_dup 3)))]
1004390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
10044146906Skan  [(parallel [(set (match_dup 0)
10045146906Skan		   (match_op_dup 2
10046146906Skan		     [(xor:DI (match_dup 3) (const_int -1))
10047146906Skan		      (const_int 0)]))
10048146906Skan	      (set (match_dup 1)
10049146906Skan		   (xor:DI (match_dup 3) (const_int -1)))])]
1005090286Sobrien  "")
1005118334Speter
1005290286Sobrien(define_expand "one_cmplsi2"
1005390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1005490286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
1005590286Sobrien  ""
1005690286Sobrien  "ix86_expand_unary_operator (NOT, SImode, operands); DONE;")
1005718334Speter
1005890286Sobrien(define_insn "*one_cmplsi2_1"
1005990286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1006090286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
1006190286Sobrien  "ix86_unary_operator_ok (NOT, SImode, operands)"
1006290286Sobrien  "not{l}\t%0"
1006390286Sobrien  [(set_attr "type" "negnot")
1006490286Sobrien   (set_attr "mode" "SI")])
1006518334Speter
1006690286Sobrien;; ??? Currently never generated - xor is used instead.
1006790286Sobrien(define_insn "*one_cmplsi2_1_zext"
1006890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1006990286Sobrien	(zero_extend:DI (not:SI (match_operand:SI 1 "register_operand" "0"))))]
1007090286Sobrien  "TARGET_64BIT && ix86_unary_operator_ok (NOT, SImode, operands)"
1007190286Sobrien  "not{l}\t%k0"
1007290286Sobrien  [(set_attr "type" "negnot")
1007390286Sobrien   (set_attr "mode" "SI")])
1007418334Speter
1007590286Sobrien(define_insn "*one_cmplsi2_2"
10076169699Skan  [(set (reg FLAGS_REG)
1007790286Sobrien	(compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
1007890286Sobrien		 (const_int 0)))
1007990286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1008090286Sobrien	(not:SI (match_dup 1)))]
1008190286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1008290286Sobrien   && ix86_unary_operator_ok (NOT, SImode, operands)"
1008390286Sobrien  "#"
1008490286Sobrien  [(set_attr "type" "alu1")
1008590286Sobrien   (set_attr "mode" "SI")])
1008618334Speter
1008790286Sobrien(define_split
10088146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10089146906Skan	(match_operator 2 "compare_operator"
10090146906Skan	  [(not:SI (match_operand:SI 3 "nonimmediate_operand" ""))
10091146906Skan	   (const_int 0)]))
10092146906Skan   (set (match_operand:SI 1 "nonimmediate_operand" "")
10093146906Skan	(not:SI (match_dup 3)))]
1009490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10095146906Skan  [(parallel [(set (match_dup 0)
10096146906Skan		   (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
10097146906Skan				    (const_int 0)]))
10098146906Skan	      (set (match_dup 1)
10099146906Skan		   (xor:SI (match_dup 3) (const_int -1)))])]
1010090286Sobrien  "")
1010118334Speter
1010290286Sobrien;; ??? Currently never generated - xor is used instead.
1010390286Sobrien(define_insn "*one_cmplsi2_2_zext"
10104169699Skan  [(set (reg FLAGS_REG)
1010590286Sobrien	(compare (not:SI (match_operand:SI 1 "register_operand" "0"))
1010690286Sobrien		 (const_int 0)))
1010790286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1010890286Sobrien	(zero_extend:DI (not:SI (match_dup 1))))]
1010990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
1011090286Sobrien   && ix86_unary_operator_ok (NOT, SImode, operands)"
1011190286Sobrien  "#"
1011290286Sobrien  [(set_attr "type" "alu1")
1011390286Sobrien   (set_attr "mode" "SI")])
1011418334Speter
1011590286Sobrien(define_split
10116146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10117146906Skan	(match_operator 2 "compare_operator"
10118146906Skan	  [(not:SI (match_operand:SI 3 "register_operand" ""))
10119146906Skan	   (const_int 0)]))
10120146906Skan   (set (match_operand:DI 1 "register_operand" "")
10121146906Skan	(zero_extend:DI (not:SI (match_dup 3))))]
1012290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10123146906Skan  [(parallel [(set (match_dup 0)
10124146906Skan		   (match_op_dup 2 [(xor:SI (match_dup 3) (const_int -1))
10125146906Skan				    (const_int 0)]))
10126146906Skan	      (set (match_dup 1)
10127146906Skan		   (zero_extend:DI (xor:SI (match_dup 3) (const_int -1))))])]
1012890286Sobrien  "")
1012918334Speter
1013090286Sobrien(define_expand "one_cmplhi2"
1013190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1013290286Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
1013390286Sobrien  "TARGET_HIMODE_MATH"
1013490286Sobrien  "ix86_expand_unary_operator (NOT, HImode, operands); DONE;")
1013552296Sobrien
1013690286Sobrien(define_insn "*one_cmplhi2_1"
1013750650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1013850650Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
1013990286Sobrien  "ix86_unary_operator_ok (NOT, HImode, operands)"
1014090286Sobrien  "not{w}\t%0"
1014190286Sobrien  [(set_attr "type" "negnot")
1014290286Sobrien   (set_attr "mode" "HI")])
1014318334Speter
1014490286Sobrien(define_insn "*one_cmplhi2_2"
10145169699Skan  [(set (reg FLAGS_REG)
1014690286Sobrien	(compare (not:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
1014790286Sobrien		 (const_int 0)))
1014890286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1014990286Sobrien	(not:HI (match_dup 1)))]
1015090286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1015190286Sobrien   && ix86_unary_operator_ok (NEG, HImode, operands)"
1015290286Sobrien  "#"
1015390286Sobrien  [(set_attr "type" "alu1")
1015490286Sobrien   (set_attr "mode" "HI")])
1015552296Sobrien
1015690286Sobrien(define_split
10157146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10158146906Skan	(match_operator 2 "compare_operator"
10159146906Skan	  [(not:HI (match_operand:HI 3 "nonimmediate_operand" ""))
10160146906Skan	   (const_int 0)]))
10161146906Skan   (set (match_operand:HI 1 "nonimmediate_operand" "")
10162146906Skan	(not:HI (match_dup 3)))]
1016390286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10164146906Skan  [(parallel [(set (match_dup 0)
10165146906Skan		   (match_op_dup 2 [(xor:HI (match_dup 3) (const_int -1))
10166146906Skan		      		    (const_int 0)]))
10167146906Skan	      (set (match_dup 1)
10168146906Skan		   (xor:HI (match_dup 3) (const_int -1)))])]
1016990286Sobrien  "")
1017052296Sobrien
1017190286Sobrien;; %%% Potential partial reg stall on alternative 1.  What to do?
1017290286Sobrien(define_expand "one_cmplqi2"
1017390286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1017490286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
1017590286Sobrien  "TARGET_QIMODE_MATH"
1017690286Sobrien  "ix86_expand_unary_operator (NOT, QImode, operands); DONE;")
1017790286Sobrien
1017890286Sobrien(define_insn "*one_cmplqi2_1"
1017990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
1018090286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))]
1018190286Sobrien  "ix86_unary_operator_ok (NOT, QImode, operands)"
1018290286Sobrien  "@
1018390286Sobrien   not{b}\t%0
1018490286Sobrien   not{l}\t%k0"
1018590286Sobrien  [(set_attr "type" "negnot")
1018690286Sobrien   (set_attr "mode" "QI,SI")])
1018790286Sobrien
1018890286Sobrien(define_insn "*one_cmplqi2_2"
10189169699Skan  [(set (reg FLAGS_REG)
1019090286Sobrien	(compare (not:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
1019190286Sobrien		 (const_int 0)))
1019290286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1019390286Sobrien	(not:QI (match_dup 1)))]
1019490286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
1019590286Sobrien   && ix86_unary_operator_ok (NOT, QImode, operands)"
1019690286Sobrien  "#"
1019790286Sobrien  [(set_attr "type" "alu1")
1019890286Sobrien   (set_attr "mode" "QI")])
1019990286Sobrien
1020090286Sobrien(define_split
10201146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
10202146906Skan	(match_operator 2 "compare_operator"
10203146906Skan	  [(not:QI (match_operand:QI 3 "nonimmediate_operand" ""))
10204146906Skan	   (const_int 0)]))
10205146906Skan   (set (match_operand:QI 1 "nonimmediate_operand" "")
10206146906Skan	(not:QI (match_dup 3)))]
1020790286Sobrien  "ix86_match_ccmode (insn, CCNOmode)"
10208146906Skan  [(parallel [(set (match_dup 0)
10209146906Skan		   (match_op_dup 2 [(xor:QI (match_dup 3) (const_int -1))
10210146906Skan		      		    (const_int 0)]))
10211146906Skan	      (set (match_dup 1)
10212146906Skan		   (xor:QI (match_dup 3) (const_int -1)))])]
1021390286Sobrien  "")
1021418334Speter
1021590286Sobrien;; Arithmetic shift instructions
1021618334Speter
1021718334Speter;; DImode shifts are implemented using the i386 "shift double" opcode,
1021818334Speter;; which is written as "sh[lr]d[lw] imm,reg,reg/mem".  If the shift count
1021918334Speter;; is variable, then the count is in %cl and the "imm" operand is dropped
1022018334Speter;; from the assembler input.
1022190286Sobrien;;
1022218334Speter;; This instruction shifts the target reg/mem as usual, but instead of
1022318334Speter;; shifting in zeros, bits are shifted in from reg operand.  If the insn
1022418334Speter;; is a left shift double, bits are taken from the high order bits of
1022518334Speter;; reg, else if the insn is a shift right double, bits are taken from the
1022618334Speter;; low order bits of reg.  So if %eax is "1234" and %edx is "5678",
1022718334Speter;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
1022890286Sobrien;;
1022918334Speter;; Since sh[lr]d does not change the `reg' operand, that is done
1023018334Speter;; separately, making all shifts emit pairs of shift double and normal
1023118334Speter;; shift.  Since sh[lr]d does not shift more than 31 bits, and we wish to
1023218334Speter;; support a 63 bit shift, each shift where the count is in a reg expands
1023350650Sobrien;; to a pair of shifts, a branch, a shift by 32 and a label.
1023490286Sobrien;;
1023518334Speter;; If the shift count is a constant, we need never emit more than one
1023618334Speter;; shift pair, instead using moves and sign extension for counts greater
1023718334Speter;; than 31.
1023818334Speter
10239169699Skan(define_expand "ashlti3"
10240169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
10241169699Skan		   (ashift:TI (match_operand:TI 1 "register_operand" "")
1024290286Sobrien			      (match_operand:QI 2 "nonmemory_operand" "")))
10243169699Skan	      (clobber (reg:CC FLAGS_REG))])]
10244169699Skan  "TARGET_64BIT"
1024518334Speter{
10246169699Skan  if (! immediate_operand (operands[2], QImode))
1024718334Speter    {
10248169699Skan      emit_insn (gen_ashlti3_1 (operands[0], operands[1], operands[2]));
1024990286Sobrien      DONE;
1025018334Speter    }
10251169699Skan  ix86_expand_binary_operator (ASHIFT, TImode, operands);
1025218334Speter  DONE;
1025390286Sobrien})
1025418334Speter
10255169699Skan(define_insn "ashlti3_1"
10256169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
10257169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "0")
10258169699Skan		   (match_operand:QI 2 "register_operand" "c")))
10259169699Skan   (clobber (match_scratch:DI 3 "=&r"))
10260169699Skan   (clobber (reg:CC FLAGS_REG))]
10261169699Skan  "TARGET_64BIT"
10262169699Skan  "#"
10263169699Skan  [(set_attr "type" "multi")])
10264169699Skan
10265169699Skan(define_insn "*ashlti3_2"
10266169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
10267169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "0")
10268169699Skan		   (match_operand:QI 2 "immediate_operand" "O")))
10269169699Skan   (clobber (reg:CC FLAGS_REG))]
10270169699Skan  "TARGET_64BIT"
10271169699Skan  "#"
10272169699Skan  [(set_attr "type" "multi")])
10273169699Skan
10274169699Skan(define_split
10275169699Skan  [(set (match_operand:TI 0 "register_operand" "")
10276169699Skan	(ashift:TI (match_operand:TI 1 "nonmemory_operand" "")
10277169699Skan		   (match_operand:QI 2 "register_operand" "")))
10278169699Skan   (clobber (match_scratch:DI 3 ""))
10279169699Skan   (clobber (reg:CC FLAGS_REG))]
10280169699Skan  "TARGET_64BIT && reload_completed"
10281169699Skan  [(const_int 0)]
10282169699Skan  "ix86_split_ashl (operands, operands[3], TImode); DONE;")
10283169699Skan
10284169699Skan(define_split
10285169699Skan  [(set (match_operand:TI 0 "register_operand" "")
10286169699Skan	(ashift:TI (match_operand:TI 1 "register_operand" "")
10287169699Skan		   (match_operand:QI 2 "immediate_operand" "")))
10288169699Skan   (clobber (reg:CC FLAGS_REG))]
10289169699Skan  "TARGET_64BIT && reload_completed"
10290169699Skan  [(const_int 0)]
10291169699Skan  "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;")
10292169699Skan
10293169699Skan(define_insn "x86_64_shld"
10294169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
10295169699Skan        (ior:DI (ashift:DI (match_dup 0)
10296169699Skan		  (match_operand:QI 2 "nonmemory_operand" "J,c"))
10297169699Skan		(lshiftrt:DI (match_operand:DI 1 "register_operand" "r,r")
10298169699Skan		  (minus:QI (const_int 64) (match_dup 2)))))
10299169699Skan   (clobber (reg:CC FLAGS_REG))]
10300169699Skan  "TARGET_64BIT"
10301169699Skan  "@
10302169699Skan   shld{q}\t{%2, %1, %0|%0, %1, %2}
10303169699Skan   shld{q}\t{%s2%1, %0|%0, %1, %2}"
10304169699Skan  [(set_attr "type" "ishift")
10305169699Skan   (set_attr "prefix_0f" "1")
10306169699Skan   (set_attr "mode" "DI")
10307169699Skan   (set_attr "athlon_decode" "vector")])
10308169699Skan
10309169699Skan(define_expand "x86_64_shift_adj"
10310169699Skan  [(set (reg:CCZ FLAGS_REG)
10311169699Skan	(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
10312169699Skan			     (const_int 64))
10313169699Skan		     (const_int 0)))
10314169699Skan   (set (match_operand:DI 0 "register_operand" "")
10315169699Skan        (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
10316169699Skan			 (match_operand:DI 1 "register_operand" "")
10317169699Skan			 (match_dup 0)))
10318169699Skan   (set (match_dup 1)
10319169699Skan	(if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
10320169699Skan			 (match_operand:DI 3 "register_operand" "r")
10321169699Skan			 (match_dup 1)))]
10322169699Skan  "TARGET_64BIT"
10323169699Skan  "")
10324169699Skan
10325169699Skan(define_expand "ashldi3"
10326169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
10327169699Skan	(ashift:DI (match_operand:DI 1 "ashldi_input_operand" "")
10328169699Skan		   (match_operand:QI 2 "nonmemory_operand" "")))]
10329169699Skan  ""
10330169699Skan  "ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;")
10331169699Skan
1033290286Sobrien(define_insn "*ashldi3_1_rex64"
1033390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
10334169699Skan	(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,l")
1033590286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cJ,M")))
10336169699Skan   (clobber (reg:CC FLAGS_REG))]
1033790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
1033818334Speter{
1033990286Sobrien  switch (get_attr_type (insn))
1034090286Sobrien    {
1034190286Sobrien    case TYPE_ALU:
10342169699Skan      gcc_assert (operands[2] == const1_rtx);
10343169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
1034490286Sobrien      return "add{q}\t{%0, %0|%0, %0}";
1034518334Speter
1034690286Sobrien    case TYPE_LEA:
10347169699Skan      gcc_assert (GET_CODE (operands[2]) == CONST_INT);
10348169699Skan      gcc_assert ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) <= 3);
1034990286Sobrien      operands[1] = gen_rtx_MULT (DImode, operands[1],
1035090286Sobrien				  GEN_INT (1 << INTVAL (operands[2])));
1035190286Sobrien      return "lea{q}\t{%a1, %0|%0, %a1}";
1035218334Speter
1035390286Sobrien    default:
1035490286Sobrien      if (REG_P (operands[2]))
1035590286Sobrien	return "sal{q}\t{%b2, %0|%0, %b2}";
10356169699Skan      else if (operands[2] == const1_rtx
10357117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1035890286Sobrien	return "sal{q}\t%0";
1035990286Sobrien      else
1036090286Sobrien	return "sal{q}\t{%2, %0|%0, %2}";
1036190286Sobrien    }
1036290286Sobrien}
1036390286Sobrien  [(set (attr "type")
1036490286Sobrien     (cond [(eq_attr "alternative" "1")
1036590286Sobrien	      (const_string "lea")
1036690286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1036790286Sobrien		          (const_int 0))
1036890286Sobrien		      (match_operand 0 "register_operand" ""))
1036990286Sobrien		 (match_operand 2 "const1_operand" ""))
1037090286Sobrien	      (const_string "alu")
1037190286Sobrien	   ]
1037290286Sobrien	   (const_string "ishift")))
1037390286Sobrien   (set_attr "mode" "DI")])
1037418334Speter
1037590286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1037690286Sobrien(define_split
1037790286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
10378169699Skan	(ashift:DI (match_operand:DI 1 "index_register_operand" "")
1037990286Sobrien		   (match_operand:QI 2 "immediate_operand" "")))
10380169699Skan   (clobber (reg:CC FLAGS_REG))]
1038190286Sobrien  "TARGET_64BIT && reload_completed
1038290286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
1038390286Sobrien  [(set (match_dup 0)
1038490286Sobrien	(mult:DI (match_dup 1)
1038590286Sobrien		 (match_dup 2)))]
10386117404Skan  "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);")
1038790286Sobrien
1038890286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1038990286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1039090286Sobrien;; zero are optimized away.
1039190286Sobrien(define_insn "*ashldi3_cmp_rex64"
10392169699Skan  [(set (reg FLAGS_REG)
1039390286Sobrien	(compare
1039490286Sobrien	  (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1039590286Sobrien		     (match_operand:QI 2 "immediate_operand" "e"))
1039690286Sobrien	  (const_int 0)))
1039790286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1039890286Sobrien	(ashift:DI (match_dup 1) (match_dup 2)))]
1039990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10400169699Skan   && ix86_binary_operator_ok (ASHIFT, DImode, operands)
10401169699Skan   && (optimize_size
10402169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10403169699Skan       || (operands[2] == const1_rtx
10404169699Skan	   && (TARGET_SHIFT1
10405169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1040690286Sobrien{
1040790286Sobrien  switch (get_attr_type (insn))
1040818334Speter    {
1040990286Sobrien    case TYPE_ALU:
10410169699Skan      gcc_assert (operands[2] == const1_rtx);
1041190286Sobrien      return "add{q}\t{%0, %0|%0, %0}";
1041218334Speter
1041390286Sobrien    default:
1041490286Sobrien      if (REG_P (operands[2]))
1041590286Sobrien	return "sal{q}\t{%b2, %0|%0, %b2}";
10416169699Skan      else if (operands[2] == const1_rtx
10417117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1041890286Sobrien	return "sal{q}\t%0";
1041990286Sobrien      else
1042090286Sobrien	return "sal{q}\t{%2, %0|%0, %2}";
1042118334Speter    }
1042290286Sobrien}
1042390286Sobrien  [(set (attr "type")
1042490286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1042590286Sobrien		          (const_int 0))
1042690286Sobrien		      (match_operand 0 "register_operand" ""))
1042790286Sobrien		 (match_operand 2 "const1_operand" ""))
1042890286Sobrien	      (const_string "alu")
1042990286Sobrien	   ]
1043090286Sobrien	   (const_string "ishift")))
1043190286Sobrien   (set_attr "mode" "DI")])
1043218334Speter
10433169699Skan(define_insn "*ashldi3_cconly_rex64"
10434169699Skan  [(set (reg FLAGS_REG)
10435169699Skan	(compare
10436169699Skan	  (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
10437169699Skan		     (match_operand:QI 2 "immediate_operand" "e"))
10438169699Skan	  (const_int 0)))
10439169699Skan   (clobber (match_scratch:DI 0 "=r"))]
10440169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10441169699Skan   && ix86_binary_operator_ok (ASHIFT, DImode, operands)
10442169699Skan   && (optimize_size
10443169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10444169699Skan       || (operands[2] == const1_rtx
10445169699Skan	   && (TARGET_SHIFT1
10446169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10447169699Skan{
10448169699Skan  switch (get_attr_type (insn))
10449169699Skan    {
10450169699Skan    case TYPE_ALU:
10451169699Skan      gcc_assert (operands[2] == const1_rtx);
10452169699Skan      return "add{q}\t{%0, %0|%0, %0}";
1045390286Sobrien
10454169699Skan    default:
10455169699Skan      if (REG_P (operands[2]))
10456169699Skan	return "sal{q}\t{%b2, %0|%0, %b2}";
10457169699Skan      else if (operands[2] == const1_rtx
10458169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10459169699Skan	return "sal{q}\t%0";
10460169699Skan      else
10461169699Skan	return "sal{q}\t{%2, %0|%0, %2}";
10462169699Skan    }
10463169699Skan}
10464169699Skan  [(set (attr "type")
10465169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
10466169699Skan		          (const_int 0))
10467169699Skan		      (match_operand 0 "register_operand" ""))
10468169699Skan		 (match_operand 2 "const1_operand" ""))
10469169699Skan	      (const_string "alu")
10470169699Skan	   ]
10471169699Skan	   (const_string "ishift")))
10472169699Skan   (set_attr "mode" "DI")])
10473169699Skan
10474169699Skan(define_insn "*ashldi3_1"
10475169699Skan  [(set (match_operand:DI 0 "register_operand" "=&r,r")
10476169699Skan	(ashift:DI (match_operand:DI 1 "reg_or_pm1_operand" "n,0")
10477169699Skan		   (match_operand:QI 2 "nonmemory_operand" "Jc,Jc")))
10478169699Skan   (clobber (reg:CC FLAGS_REG))]
1047990286Sobrien  "!TARGET_64BIT"
1048090286Sobrien  "#"
1048190286Sobrien  [(set_attr "type" "multi")])
1048290286Sobrien
10483169699Skan;; By default we don't ask for a scratch register, because when DImode
10484169699Skan;; values are manipulated, registers are already at a premium.  But if
10485169699Skan;; we have one handy, we won't turn it away.
10486169699Skan(define_peephole2
10487169699Skan  [(match_scratch:SI 3 "r")
10488169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
10489169699Skan		   (ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
10490169699Skan			      (match_operand:QI 2 "nonmemory_operand" "")))
10491169699Skan	      (clobber (reg:CC FLAGS_REG))])
10492169699Skan   (match_dup 3)]
10493169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1049490286Sobrien  [(const_int 0)]
10495169699Skan  "ix86_split_ashl (operands, operands[3], DImode); DONE;")
1049690286Sobrien
1049790286Sobrien(define_split
1049890286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
10499169699Skan	(ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
1050090286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10501169699Skan   (clobber (reg:CC FLAGS_REG))]
10502169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
10503169699Skan		     ? flow2_completed : reload_completed)"
1050490286Sobrien  [(const_int 0)]
10505169699Skan  "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;")
1050690286Sobrien
1050790286Sobrien(define_insn "x86_shld_1"
1050890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
1050990286Sobrien        (ior:SI (ashift:SI (match_dup 0)
1051090286Sobrien		  (match_operand:QI 2 "nonmemory_operand" "I,c"))
1051190286Sobrien		(lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
1051290286Sobrien		  (minus:QI (const_int 32) (match_dup 2)))))
10513169699Skan   (clobber (reg:CC FLAGS_REG))]
1051418334Speter  ""
1051590286Sobrien  "@
1051690286Sobrien   shld{l}\t{%2, %1, %0|%0, %1, %2}
1051790286Sobrien   shld{l}\t{%s2%1, %0|%0, %1, %2}"
1051890286Sobrien  [(set_attr "type" "ishift")
1051990286Sobrien   (set_attr "prefix_0f" "1")
1052090286Sobrien   (set_attr "mode" "SI")
1052190286Sobrien   (set_attr "pent_pair" "np")
10522169699Skan   (set_attr "athlon_decode" "vector")])
1052390286Sobrien
1052490286Sobrien(define_expand "x86_shift_adj_1"
10525169699Skan  [(set (reg:CCZ FLAGS_REG)
1052690286Sobrien	(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
1052790286Sobrien			     (const_int 32))
1052890286Sobrien		     (const_int 0)))
1052990286Sobrien   (set (match_operand:SI 0 "register_operand" "")
10530169699Skan        (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
1053190286Sobrien			 (match_operand:SI 1 "register_operand" "")
1053290286Sobrien			 (match_dup 0)))
1053390286Sobrien   (set (match_dup 1)
10534169699Skan	(if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
1053590286Sobrien			 (match_operand:SI 3 "register_operand" "r")
1053690286Sobrien			 (match_dup 1)))]
1053790286Sobrien  "TARGET_CMOVE"
1053890286Sobrien  "")
1053990286Sobrien
1054090286Sobrien(define_expand "x86_shift_adj_2"
1054190286Sobrien  [(use (match_operand:SI 0 "register_operand" ""))
1054290286Sobrien   (use (match_operand:SI 1 "register_operand" ""))
1054390286Sobrien   (use (match_operand:QI 2 "register_operand" ""))]
1054490286Sobrien  ""
1054518334Speter{
1054690286Sobrien  rtx label = gen_label_rtx ();
1054790286Sobrien  rtx tmp;
1054818334Speter
1054990286Sobrien  emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
1055018334Speter
1055190286Sobrien  tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
1055290286Sobrien  tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1055390286Sobrien  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
1055490286Sobrien			      gen_rtx_LABEL_REF (VOIDmode, label),
1055590286Sobrien			      pc_rtx);
1055690286Sobrien  tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
1055790286Sobrien  JUMP_LABEL (tmp) = label;
1055818334Speter
1055990286Sobrien  emit_move_insn (operands[0], operands[1]);
10560169699Skan  ix86_expand_clear (operands[1]);
1056118334Speter
1056290286Sobrien  emit_label (label);
1056390286Sobrien  LABEL_NUSES (label) = 1;
1056490286Sobrien
1056590286Sobrien  DONE;
1056690286Sobrien})
1056790286Sobrien
1056852296Sobrien(define_expand "ashlsi3"
1056952296Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1057052296Sobrien	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
1057190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10572169699Skan   (clobber (reg:CC FLAGS_REG))]
1057352296Sobrien  ""
1057490286Sobrien  "ix86_expand_binary_operator (ASHIFT, SImode, operands); DONE;")
1057518334Speter
1057690286Sobrien(define_insn "*ashlsi3_1"
1057790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
10578169699Skan	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,l")
1057990286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,M")))
10580169699Skan   (clobber (reg:CC FLAGS_REG))]
1058190286Sobrien  "ix86_binary_operator_ok (ASHIFT, SImode, operands)"
1058290286Sobrien{
1058390286Sobrien  switch (get_attr_type (insn))
1058490286Sobrien    {
1058590286Sobrien    case TYPE_ALU:
10586169699Skan      gcc_assert (operands[2] == const1_rtx);
10587169699Skan      gcc_assert (rtx_equal_p (operands[0], operands[1]));
1058890286Sobrien      return "add{l}\t{%0, %0|%0, %0}";
1058990286Sobrien
1059090286Sobrien    case TYPE_LEA:
1059190286Sobrien      return "#";
1059290286Sobrien
1059390286Sobrien    default:
1059490286Sobrien      if (REG_P (operands[2]))
1059590286Sobrien	return "sal{l}\t{%b2, %0|%0, %b2}";
10596169699Skan      else if (operands[2] == const1_rtx
10597117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1059890286Sobrien	return "sal{l}\t%0";
1059990286Sobrien      else
1060090286Sobrien	return "sal{l}\t{%2, %0|%0, %2}";
1060190286Sobrien    }
1060290286Sobrien}
1060390286Sobrien  [(set (attr "type")
1060490286Sobrien     (cond [(eq_attr "alternative" "1")
1060590286Sobrien	      (const_string "lea")
1060690286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1060790286Sobrien		          (const_int 0))
1060890286Sobrien		      (match_operand 0 "register_operand" ""))
1060990286Sobrien		 (match_operand 2 "const1_operand" ""))
1061090286Sobrien	      (const_string "alu")
1061190286Sobrien	   ]
1061290286Sobrien	   (const_string "ishift")))
1061390286Sobrien   (set_attr "mode" "SI")])
1061490286Sobrien
1061590286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1061690286Sobrien(define_split
1061790286Sobrien  [(set (match_operand 0 "register_operand" "")
10618117404Skan	(ashift (match_operand 1 "index_register_operand" "")
1061990286Sobrien                (match_operand:QI 2 "const_int_operand" "")))
10620169699Skan   (clobber (reg:CC FLAGS_REG))]
1062190286Sobrien  "reload_completed
10622169699Skan   && true_regnum (operands[0]) != true_regnum (operands[1])
10623169699Skan   && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4"
1062490286Sobrien  [(const_int 0)]
1062590286Sobrien{
1062690286Sobrien  rtx pat;
10627169699Skan  enum machine_mode mode = GET_MODE (operands[0]);
10628169699Skan
10629169699Skan  if (GET_MODE_SIZE (mode) < 4)
10630169699Skan    operands[0] = gen_lowpart (SImode, operands[0]);
10631169699Skan  if (mode != Pmode)
10632169699Skan    operands[1] = gen_lowpart (Pmode, operands[1]);
10633117404Skan  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
10634169699Skan
1063590286Sobrien  pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
1063690286Sobrien  if (Pmode != SImode)
1063790286Sobrien    pat = gen_rtx_SUBREG (SImode, pat, 0);
1063890286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
1063990286Sobrien  DONE;
1064090286Sobrien})
1064190286Sobrien
10642117404Skan;; Rare case of shifting RSP is handled by generating move and shift
10643117404Skan(define_split
10644117404Skan  [(set (match_operand 0 "register_operand" "")
10645117404Skan	(ashift (match_operand 1 "register_operand" "")
10646117404Skan                (match_operand:QI 2 "const_int_operand" "")))
10647169699Skan   (clobber (reg:CC FLAGS_REG))]
10648117404Skan  "reload_completed
10649117404Skan   && true_regnum (operands[0]) != true_regnum (operands[1])"
10650117404Skan  [(const_int 0)]
10651117404Skan{
10652117404Skan  rtx pat, clob;
10653169699Skan  emit_move_insn (operands[0], operands[1]);
10654117404Skan  pat = gen_rtx_SET (VOIDmode, operands[0],
10655117404Skan		     gen_rtx_ASHIFT (GET_MODE (operands[0]),
10656117404Skan				     operands[0], operands[2]));
10657117404Skan  clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
10658117404Skan  emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob)));
10659117404Skan  DONE;
10660117404Skan})
10661117404Skan
1066290286Sobrien(define_insn "*ashlsi3_1_zext"
1066390286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
10664169699Skan	(zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l")
1066590286Sobrien			(match_operand:QI 2 "nonmemory_operand" "cI,M"))))
10666169699Skan   (clobber (reg:CC FLAGS_REG))]
1066790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
1066890286Sobrien{
1066990286Sobrien  switch (get_attr_type (insn))
1067090286Sobrien    {
1067190286Sobrien    case TYPE_ALU:
10672169699Skan      gcc_assert (operands[2] == const1_rtx);
1067390286Sobrien      return "add{l}\t{%k0, %k0|%k0, %k0}";
1067490286Sobrien
1067590286Sobrien    case TYPE_LEA:
1067690286Sobrien      return "#";
1067790286Sobrien
1067890286Sobrien    default:
1067990286Sobrien      if (REG_P (operands[2]))
1068090286Sobrien	return "sal{l}\t{%b2, %k0|%k0, %b2}";
10681169699Skan      else if (operands[2] == const1_rtx
10682117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1068390286Sobrien	return "sal{l}\t%k0";
1068490286Sobrien      else
1068590286Sobrien	return "sal{l}\t{%2, %k0|%k0, %2}";
1068690286Sobrien    }
1068790286Sobrien}
1068890286Sobrien  [(set (attr "type")
1068990286Sobrien     (cond [(eq_attr "alternative" "1")
1069090286Sobrien	      (const_string "lea")
1069190286Sobrien            (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1069290286Sobrien		     (const_int 0))
1069390286Sobrien		 (match_operand 2 "const1_operand" ""))
1069490286Sobrien	      (const_string "alu")
1069590286Sobrien	   ]
1069690286Sobrien	   (const_string "ishift")))
1069790286Sobrien   (set_attr "mode" "SI")])
1069890286Sobrien
1069990286Sobrien;; Convert lea to the lea pattern to avoid flags dependency.
1070090286Sobrien(define_split
1070190286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1070290286Sobrien	(zero_extend:DI (ashift (match_operand 1 "register_operand" "")
1070390286Sobrien				(match_operand:QI 2 "const_int_operand" ""))))
10704169699Skan   (clobber (reg:CC FLAGS_REG))]
10705132727Skan  "TARGET_64BIT && reload_completed
1070690286Sobrien   && true_regnum (operands[0]) != true_regnum (operands[1])"
10707132727Skan  [(set (match_dup 0) (zero_extend:DI
10708132727Skan			(subreg:SI (mult:SI (match_dup 1)
10709132727Skan					    (match_dup 2)) 0)))]
1071090286Sobrien{
1071190286Sobrien  operands[1] = gen_lowpart (Pmode, operands[1]);
10712117404Skan  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
1071390286Sobrien})
1071490286Sobrien
1071590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1071690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1071790286Sobrien;; zero are optimized away.
1071890286Sobrien(define_insn "*ashlsi3_cmp"
10719169699Skan  [(set (reg FLAGS_REG)
1072090286Sobrien	(compare
1072190286Sobrien	  (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
10722169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1072390286Sobrien	  (const_int 0)))
1072490286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1072590286Sobrien	(ashift:SI (match_dup 1) (match_dup 2)))]
1072690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
10727169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10728169699Skan   && (optimize_size
10729169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10730169699Skan       || (operands[2] == const1_rtx
10731169699Skan	   && (TARGET_SHIFT1
10732169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1073390286Sobrien{
1073490286Sobrien  switch (get_attr_type (insn))
1073590286Sobrien    {
1073690286Sobrien    case TYPE_ALU:
10737169699Skan      gcc_assert (operands[2] == const1_rtx);
1073890286Sobrien      return "add{l}\t{%0, %0|%0, %0}";
1073990286Sobrien
1074090286Sobrien    default:
1074190286Sobrien      if (REG_P (operands[2]))
1074290286Sobrien	return "sal{l}\t{%b2, %0|%0, %b2}";
10743169699Skan      else if (operands[2] == const1_rtx
10744117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1074590286Sobrien	return "sal{l}\t%0";
1074690286Sobrien      else
1074790286Sobrien	return "sal{l}\t{%2, %0|%0, %2}";
1074890286Sobrien    }
1074990286Sobrien}
1075090286Sobrien  [(set (attr "type")
1075190286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1075290286Sobrien		          (const_int 0))
1075390286Sobrien		      (match_operand 0 "register_operand" ""))
1075490286Sobrien		 (match_operand 2 "const1_operand" ""))
1075590286Sobrien	      (const_string "alu")
1075690286Sobrien	   ]
1075790286Sobrien	   (const_string "ishift")))
1075890286Sobrien   (set_attr "mode" "SI")])
1075990286Sobrien
10760169699Skan(define_insn "*ashlsi3_cconly"
10761169699Skan  [(set (reg FLAGS_REG)
10762169699Skan	(compare
10763169699Skan	  (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
10764169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
10765169699Skan	  (const_int 0)))
10766169699Skan   (clobber (match_scratch:SI 0 "=r"))]
10767169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
10768169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10769169699Skan   && (optimize_size
10770169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10771169699Skan       || (operands[2] == const1_rtx
10772169699Skan	   && (TARGET_SHIFT1
10773169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10774169699Skan{
10775169699Skan  switch (get_attr_type (insn))
10776169699Skan    {
10777169699Skan    case TYPE_ALU:
10778169699Skan      gcc_assert (operands[2] == const1_rtx);
10779169699Skan      return "add{l}\t{%0, %0|%0, %0}";
10780169699Skan
10781169699Skan    default:
10782169699Skan      if (REG_P (operands[2]))
10783169699Skan	return "sal{l}\t{%b2, %0|%0, %b2}";
10784169699Skan      else if (operands[2] == const1_rtx
10785169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10786169699Skan	return "sal{l}\t%0";
10787169699Skan      else
10788169699Skan	return "sal{l}\t{%2, %0|%0, %2}";
10789169699Skan    }
10790169699Skan}
10791169699Skan  [(set (attr "type")
10792169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
10793169699Skan		          (const_int 0))
10794169699Skan		      (match_operand 0 "register_operand" ""))
10795169699Skan		 (match_operand 2 "const1_operand" ""))
10796169699Skan	      (const_string "alu")
10797169699Skan	   ]
10798169699Skan	   (const_string "ishift")))
10799169699Skan   (set_attr "mode" "SI")])
10800169699Skan
1080190286Sobrien(define_insn "*ashlsi3_cmp_zext"
10802169699Skan  [(set (reg FLAGS_REG)
1080390286Sobrien	(compare
1080490286Sobrien	  (ashift:SI (match_operand:SI 1 "register_operand" "0")
10805169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1080690286Sobrien	  (const_int 0)))
1080790286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1080890286Sobrien	(zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
1080990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
10810169699Skan   && ix86_binary_operator_ok (ASHIFT, SImode, operands)
10811169699Skan   && (optimize_size
10812169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10813169699Skan       || (operands[2] == const1_rtx
10814169699Skan	   && (TARGET_SHIFT1
10815169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
1081690286Sobrien{
1081790286Sobrien  switch (get_attr_type (insn))
1081890286Sobrien    {
1081990286Sobrien    case TYPE_ALU:
10820169699Skan      gcc_assert (operands[2] == const1_rtx);
1082190286Sobrien      return "add{l}\t{%k0, %k0|%k0, %k0}";
1082290286Sobrien
1082390286Sobrien    default:
1082490286Sobrien      if (REG_P (operands[2]))
1082590286Sobrien	return "sal{l}\t{%b2, %k0|%k0, %b2}";
10826169699Skan      else if (operands[2] == const1_rtx
10827117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1082890286Sobrien	return "sal{l}\t%k0";
1082990286Sobrien      else
1083090286Sobrien	return "sal{l}\t{%2, %k0|%k0, %2}";
1083190286Sobrien    }
1083290286Sobrien}
1083390286Sobrien  [(set (attr "type")
1083490286Sobrien     (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1083590286Sobrien		     (const_int 0))
1083690286Sobrien		 (match_operand 2 "const1_operand" ""))
1083790286Sobrien	      (const_string "alu")
1083890286Sobrien	   ]
1083990286Sobrien	   (const_string "ishift")))
1084090286Sobrien   (set_attr "mode" "SI")])
1084190286Sobrien
1084252296Sobrien(define_expand "ashlhi3"
1084352296Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1084452296Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
1084590286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
10846169699Skan   (clobber (reg:CC FLAGS_REG))]
1084790286Sobrien  "TARGET_HIMODE_MATH"
1084890286Sobrien  "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;")
1084918334Speter
1085090286Sobrien(define_insn "*ashlhi3_1_lea"
1085190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
10852169699Skan	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l")
1085390286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,M")))
10854169699Skan   (clobber (reg:CC FLAGS_REG))]
1085590286Sobrien  "!TARGET_PARTIAL_REG_STALL
1085690286Sobrien   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
1085790286Sobrien{
1085890286Sobrien  switch (get_attr_type (insn))
1085990286Sobrien    {
1086090286Sobrien    case TYPE_LEA:
1086190286Sobrien      return "#";
1086290286Sobrien    case TYPE_ALU:
10863169699Skan      gcc_assert (operands[2] == const1_rtx);
1086490286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1086590286Sobrien
1086690286Sobrien    default:
1086790286Sobrien      if (REG_P (operands[2]))
1086890286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10869169699Skan      else if (operands[2] == const1_rtx
10870117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1087190286Sobrien	return "sal{w}\t%0";
1087290286Sobrien      else
1087390286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1087490286Sobrien    }
1087590286Sobrien}
1087690286Sobrien  [(set (attr "type")
1087790286Sobrien     (cond [(eq_attr "alternative" "1")
1087890286Sobrien	      (const_string "lea")
1087990286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1088090286Sobrien		          (const_int 0))
1088190286Sobrien		      (match_operand 0 "register_operand" ""))
1088290286Sobrien		 (match_operand 2 "const1_operand" ""))
1088390286Sobrien	      (const_string "alu")
1088490286Sobrien	   ]
1088590286Sobrien	   (const_string "ishift")))
1088690286Sobrien   (set_attr "mode" "HI,SI")])
1088790286Sobrien
1088890286Sobrien(define_insn "*ashlhi3_1"
1088990286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1089090286Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
1089190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI")))
10892169699Skan   (clobber (reg:CC FLAGS_REG))]
1089390286Sobrien  "TARGET_PARTIAL_REG_STALL
1089490286Sobrien   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
1089590286Sobrien{
1089690286Sobrien  switch (get_attr_type (insn))
1089790286Sobrien    {
1089890286Sobrien    case TYPE_ALU:
10899169699Skan      gcc_assert (operands[2] == const1_rtx);
1090090286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1090190286Sobrien
1090290286Sobrien    default:
1090390286Sobrien      if (REG_P (operands[2]))
1090490286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10905169699Skan      else if (operands[2] == const1_rtx
10906117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1090790286Sobrien	return "sal{w}\t%0";
1090890286Sobrien      else
1090990286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1091090286Sobrien    }
1091190286Sobrien}
1091290286Sobrien  [(set (attr "type")
1091390286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1091490286Sobrien		          (const_int 0))
1091590286Sobrien		      (match_operand 0 "register_operand" ""))
1091690286Sobrien		 (match_operand 2 "const1_operand" ""))
1091790286Sobrien	      (const_string "alu")
1091890286Sobrien	   ]
1091990286Sobrien	   (const_string "ishift")))
1092090286Sobrien   (set_attr "mode" "HI")])
1092190286Sobrien
1092290286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1092390286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1092490286Sobrien;; zero are optimized away.
1092590286Sobrien(define_insn "*ashlhi3_cmp"
10926169699Skan  [(set (reg FLAGS_REG)
1092790286Sobrien	(compare
1092890286Sobrien	  (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
10929169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1093090286Sobrien	  (const_int 0)))
1093190286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1093290286Sobrien	(ashift:HI (match_dup 1) (match_dup 2)))]
1093390286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
10934169699Skan   && ix86_binary_operator_ok (ASHIFT, HImode, operands)
10935169699Skan   && (optimize_size
10936169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10937169699Skan       || (operands[2] == const1_rtx
10938169699Skan	   && (TARGET_SHIFT1
10939169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1094090286Sobrien{
1094190286Sobrien  switch (get_attr_type (insn))
1094290286Sobrien    {
1094390286Sobrien    case TYPE_ALU:
10944169699Skan      gcc_assert (operands[2] == const1_rtx);
1094590286Sobrien      return "add{w}\t{%0, %0|%0, %0}";
1094690286Sobrien
1094790286Sobrien    default:
1094890286Sobrien      if (REG_P (operands[2]))
1094990286Sobrien	return "sal{w}\t{%b2, %0|%0, %b2}";
10950169699Skan      else if (operands[2] == const1_rtx
10951117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1095290286Sobrien	return "sal{w}\t%0";
1095390286Sobrien      else
1095490286Sobrien	return "sal{w}\t{%2, %0|%0, %2}";
1095590286Sobrien    }
1095690286Sobrien}
1095790286Sobrien  [(set (attr "type")
1095890286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1095990286Sobrien		          (const_int 0))
1096090286Sobrien		      (match_operand 0 "register_operand" ""))
1096190286Sobrien		 (match_operand 2 "const1_operand" ""))
1096290286Sobrien	      (const_string "alu")
1096390286Sobrien	   ]
1096490286Sobrien	   (const_string "ishift")))
1096590286Sobrien   (set_attr "mode" "HI")])
1096690286Sobrien
10967169699Skan(define_insn "*ashlhi3_cconly"
10968169699Skan  [(set (reg FLAGS_REG)
10969169699Skan	(compare
10970169699Skan	  (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
10971169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
10972169699Skan	  (const_int 0)))
10973169699Skan   (clobber (match_scratch:HI 0 "=r"))]
10974169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
10975169699Skan   && ix86_binary_operator_ok (ASHIFT, HImode, operands)
10976169699Skan   && (optimize_size
10977169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
10978169699Skan       || (operands[2] == const1_rtx
10979169699Skan	   && (TARGET_SHIFT1
10980169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
10981169699Skan{
10982169699Skan  switch (get_attr_type (insn))
10983169699Skan    {
10984169699Skan    case TYPE_ALU:
10985169699Skan      gcc_assert (operands[2] == const1_rtx);
10986169699Skan      return "add{w}\t{%0, %0|%0, %0}";
10987169699Skan
10988169699Skan    default:
10989169699Skan      if (REG_P (operands[2]))
10990169699Skan	return "sal{w}\t{%b2, %0|%0, %b2}";
10991169699Skan      else if (operands[2] == const1_rtx
10992169699Skan	       && (TARGET_SHIFT1 || optimize_size))
10993169699Skan	return "sal{w}\t%0";
10994169699Skan      else
10995169699Skan	return "sal{w}\t{%2, %0|%0, %2}";
10996169699Skan    }
10997169699Skan}
10998169699Skan  [(set (attr "type")
10999169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
11000169699Skan		          (const_int 0))
11001169699Skan		      (match_operand 0 "register_operand" ""))
11002169699Skan		 (match_operand 2 "const1_operand" ""))
11003169699Skan	      (const_string "alu")
11004169699Skan	   ]
11005169699Skan	   (const_string "ishift")))
11006169699Skan   (set_attr "mode" "HI")])
11007169699Skan
1100852296Sobrien(define_expand "ashlqi3"
1100952296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1101052296Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
1101190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
11012169699Skan   (clobber (reg:CC FLAGS_REG))]
1101390286Sobrien  "TARGET_QIMODE_MATH"
1101490286Sobrien  "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;")
1101518334Speter
1101690286Sobrien;; %%% Potential partial reg stall on alternative 2.  What to do?
1101718334Speter
1101890286Sobrien(define_insn "*ashlqi3_1_lea"
1101990286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r")
11020169699Skan	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l")
1102190286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,cI,M")))
11022169699Skan   (clobber (reg:CC FLAGS_REG))]
1102390286Sobrien  "!TARGET_PARTIAL_REG_STALL
1102490286Sobrien   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
1102590286Sobrien{
1102690286Sobrien  switch (get_attr_type (insn))
1102790286Sobrien    {
1102890286Sobrien    case TYPE_LEA:
1102990286Sobrien      return "#";
1103090286Sobrien    case TYPE_ALU:
11031169699Skan      gcc_assert (operands[2] == const1_rtx);
1103290286Sobrien      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
1103390286Sobrien        return "add{l}\t{%k0, %k0|%k0, %k0}";
1103490286Sobrien      else
1103590286Sobrien        return "add{b}\t{%0, %0|%0, %0}";
1103618334Speter
1103790286Sobrien    default:
1103890286Sobrien      if (REG_P (operands[2]))
1103990286Sobrien	{
1104090286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1104190286Sobrien	    return "sal{l}\t{%b2, %k0|%k0, %b2}";
1104290286Sobrien	  else
1104390286Sobrien	    return "sal{b}\t{%b2, %0|%0, %b2}";
1104490286Sobrien	}
11045169699Skan      else if (operands[2] == const1_rtx
11046117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1104790286Sobrien	{
1104890286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1104990286Sobrien	    return "sal{l}\t%0";
1105090286Sobrien	  else
1105190286Sobrien	    return "sal{b}\t%0";
1105290286Sobrien	}
1105390286Sobrien      else
1105490286Sobrien	{
1105590286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1105690286Sobrien	    return "sal{l}\t{%2, %k0|%k0, %2}";
1105790286Sobrien	  else
1105890286Sobrien	    return "sal{b}\t{%2, %0|%0, %2}";
1105990286Sobrien	}
1106090286Sobrien    }
1106190286Sobrien}
1106290286Sobrien  [(set (attr "type")
1106390286Sobrien     (cond [(eq_attr "alternative" "2")
1106490286Sobrien	      (const_string "lea")
1106590286Sobrien            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1106690286Sobrien		          (const_int 0))
1106790286Sobrien		      (match_operand 0 "register_operand" ""))
1106890286Sobrien		 (match_operand 2 "const1_operand" ""))
1106990286Sobrien	      (const_string "alu")
1107090286Sobrien	   ]
1107190286Sobrien	   (const_string "ishift")))
1107290286Sobrien   (set_attr "mode" "QI,SI,SI")])
1107318334Speter
1107490286Sobrien(define_insn "*ashlqi3_1"
1107590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
1107690286Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1107790286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
11078169699Skan   (clobber (reg:CC FLAGS_REG))]
1107990286Sobrien  "TARGET_PARTIAL_REG_STALL
1108090286Sobrien   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
1108190286Sobrien{
1108290286Sobrien  switch (get_attr_type (insn))
1108390286Sobrien    {
1108490286Sobrien    case TYPE_ALU:
11085169699Skan      gcc_assert (operands[2] == const1_rtx);
1108690286Sobrien      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
1108790286Sobrien        return "add{l}\t{%k0, %k0|%k0, %k0}";
1108890286Sobrien      else
1108990286Sobrien        return "add{b}\t{%0, %0|%0, %0}";
1109052296Sobrien
1109190286Sobrien    default:
1109290286Sobrien      if (REG_P (operands[2]))
1109390286Sobrien	{
1109490286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1109590286Sobrien	    return "sal{l}\t{%b2, %k0|%k0, %b2}";
1109690286Sobrien	  else
1109790286Sobrien	    return "sal{b}\t{%b2, %0|%0, %b2}";
1109890286Sobrien	}
11099169699Skan      else if (operands[2] == const1_rtx
11100117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1110190286Sobrien	{
1110290286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1110390286Sobrien	    return "sal{l}\t%0";
1110490286Sobrien	  else
1110590286Sobrien	    return "sal{b}\t%0";
1110690286Sobrien	}
1110790286Sobrien      else
1110890286Sobrien	{
1110990286Sobrien	  if (get_attr_mode (insn) == MODE_SI)
1111090286Sobrien	    return "sal{l}\t{%2, %k0|%k0, %2}";
1111190286Sobrien	  else
1111290286Sobrien	    return "sal{b}\t{%2, %0|%0, %2}";
1111390286Sobrien	}
1111490286Sobrien    }
1111590286Sobrien}
1111690286Sobrien  [(set (attr "type")
1111790286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1111890286Sobrien		          (const_int 0))
1111990286Sobrien		      (match_operand 0 "register_operand" ""))
1112090286Sobrien		 (match_operand 2 "const1_operand" ""))
1112190286Sobrien	      (const_string "alu")
1112290286Sobrien	   ]
1112390286Sobrien	   (const_string "ishift")))
1112490286Sobrien   (set_attr "mode" "QI,SI")])
1112518334Speter
1112690286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1112790286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1112890286Sobrien;; zero are optimized away.
1112990286Sobrien(define_insn "*ashlqi3_cmp"
11130169699Skan  [(set (reg FLAGS_REG)
1113190286Sobrien	(compare
1113290286Sobrien	  (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11133169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
1113490286Sobrien	  (const_int 0)))
1113590286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1113690286Sobrien	(ashift:QI (match_dup 1) (match_dup 2)))]
1113790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11138169699Skan   && ix86_binary_operator_ok (ASHIFT, QImode, operands)
11139169699Skan   && (optimize_size
11140169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11141169699Skan       || (operands[2] == const1_rtx
11142169699Skan	   && (TARGET_SHIFT1
11143169699Skan	       || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
1114490286Sobrien{
1114590286Sobrien  switch (get_attr_type (insn))
1114690286Sobrien    {
1114790286Sobrien    case TYPE_ALU:
11148169699Skan      gcc_assert (operands[2] == const1_rtx);
1114990286Sobrien      return "add{b}\t{%0, %0|%0, %0}";
1115018334Speter
1115190286Sobrien    default:
1115290286Sobrien      if (REG_P (operands[2]))
1115390286Sobrien	return "sal{b}\t{%b2, %0|%0, %b2}";
11154169699Skan      else if (operands[2] == const1_rtx
11155117404Skan	       && (TARGET_SHIFT1 || optimize_size))
1115690286Sobrien	return "sal{b}\t%0";
1115790286Sobrien      else
1115890286Sobrien	return "sal{b}\t{%2, %0|%0, %2}";
1115990286Sobrien    }
1116090286Sobrien}
1116190286Sobrien  [(set (attr "type")
1116290286Sobrien     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
1116390286Sobrien		          (const_int 0))
1116490286Sobrien		      (match_operand 0 "register_operand" ""))
1116590286Sobrien		 (match_operand 2 "const1_operand" ""))
1116690286Sobrien	      (const_string "alu")
1116790286Sobrien	   ]
1116890286Sobrien	   (const_string "ishift")))
1116990286Sobrien   (set_attr "mode" "QI")])
1117018334Speter
11171169699Skan(define_insn "*ashlqi3_cconly"
11172169699Skan  [(set (reg FLAGS_REG)
11173169699Skan	(compare
11174169699Skan	  (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11175169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
11176169699Skan	  (const_int 0)))
11177169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11178169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11179169699Skan   && ix86_binary_operator_ok (ASHIFT, QImode, operands)
11180169699Skan   && (optimize_size
11181169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL
11182169699Skan       || (operands[2] == const1_rtx
11183169699Skan	   && (TARGET_SHIFT1
11184169699Skan	       || TARGET_DOUBLE_WITH_ADD)))"
11185169699Skan{
11186169699Skan  switch (get_attr_type (insn))
11187169699Skan    {
11188169699Skan    case TYPE_ALU:
11189169699Skan      gcc_assert (operands[2] == const1_rtx);
11190169699Skan      return "add{b}\t{%0, %0|%0, %0}";
11191169699Skan
11192169699Skan    default:
11193169699Skan      if (REG_P (operands[2]))
11194169699Skan	return "sal{b}\t{%b2, %0|%0, %b2}";
11195169699Skan      else if (operands[2] == const1_rtx
11196169699Skan	       && (TARGET_SHIFT1 || optimize_size))
11197169699Skan	return "sal{b}\t%0";
11198169699Skan      else
11199169699Skan	return "sal{b}\t{%2, %0|%0, %2}";
11200169699Skan    }
11201169699Skan}
11202169699Skan  [(set (attr "type")
11203169699Skan     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
11204169699Skan		          (const_int 0))
11205169699Skan		      (match_operand 0 "register_operand" ""))
11206169699Skan		 (match_operand 2 "const1_operand" ""))
11207169699Skan	      (const_string "alu")
11208169699Skan	   ]
11209169699Skan	   (const_string "ishift")))
11210169699Skan   (set_attr "mode" "QI")])
11211169699Skan
1121218334Speter;; See comment above `ashldi3' about how this works.
1121318334Speter
11214169699Skan(define_expand "ashrti3"
11215169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
11216169699Skan		   (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
1121790286Sobrien				(match_operand:QI 2 "nonmemory_operand" "")))
11218169699Skan	      (clobber (reg:CC FLAGS_REG))])]
11219169699Skan  "TARGET_64BIT"
1122018334Speter{
11221169699Skan  if (! immediate_operand (operands[2], QImode))
1122218334Speter    {
11223169699Skan      emit_insn (gen_ashrti3_1 (operands[0], operands[1], operands[2]));
1122490286Sobrien      DONE;
1122518334Speter    }
11226169699Skan  ix86_expand_binary_operator (ASHIFTRT, TImode, operands);
1122718334Speter  DONE;
1122890286Sobrien})
1122918334Speter
11230169699Skan(define_insn "ashrti3_1"
11231169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11232169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
11233169699Skan		     (match_operand:QI 2 "register_operand" "c")))
11234169699Skan   (clobber (match_scratch:DI 3 "=&r"))
11235169699Skan   (clobber (reg:CC FLAGS_REG))]
11236169699Skan  "TARGET_64BIT"
11237169699Skan  "#"
11238169699Skan  [(set_attr "type" "multi")])
11239169699Skan
11240169699Skan(define_insn "*ashrti3_2"
11241169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11242169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
11243169699Skan		     (match_operand:QI 2 "immediate_operand" "O")))
11244169699Skan   (clobber (reg:CC FLAGS_REG))]
11245169699Skan  "TARGET_64BIT"
11246169699Skan  "#"
11247169699Skan  [(set_attr "type" "multi")])
11248169699Skan
11249169699Skan(define_split
11250169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11251169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "")
11252169699Skan		     (match_operand:QI 2 "register_operand" "")))
11253169699Skan   (clobber (match_scratch:DI 3 ""))
11254169699Skan   (clobber (reg:CC FLAGS_REG))]
11255169699Skan  "TARGET_64BIT && reload_completed"
11256169699Skan  [(const_int 0)]
11257169699Skan  "ix86_split_ashr (operands, operands[3], TImode); DONE;")
11258169699Skan
11259169699Skan(define_split
11260169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11261169699Skan	(ashiftrt:TI (match_operand:TI 1 "register_operand" "")
11262169699Skan		     (match_operand:QI 2 "immediate_operand" "")))
11263169699Skan   (clobber (reg:CC FLAGS_REG))]
11264169699Skan  "TARGET_64BIT && reload_completed"
11265169699Skan  [(const_int 0)]
11266169699Skan  "ix86_split_ashr (operands, NULL_RTX, TImode); DONE;")
11267169699Skan
11268169699Skan(define_insn "x86_64_shrd"
11269169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
11270169699Skan        (ior:DI (ashiftrt:DI (match_dup 0)
11271169699Skan		  (match_operand:QI 2 "nonmemory_operand" "J,c"))
11272169699Skan		(ashift:DI (match_operand:DI 1 "register_operand" "r,r")
11273169699Skan		  (minus:QI (const_int 64) (match_dup 2)))))
11274169699Skan   (clobber (reg:CC FLAGS_REG))]
11275169699Skan  "TARGET_64BIT"
11276169699Skan  "@
11277169699Skan   shrd{q}\t{%2, %1, %0|%0, %1, %2}
11278169699Skan   shrd{q}\t{%s2%1, %0|%0, %1, %2}"
11279169699Skan  [(set_attr "type" "ishift")
11280169699Skan   (set_attr "prefix_0f" "1")
11281169699Skan   (set_attr "mode" "DI")
11282169699Skan   (set_attr "athlon_decode" "vector")])
11283169699Skan
11284169699Skan(define_expand "ashrdi3"
11285169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
11286169699Skan	(ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
11287169699Skan		     (match_operand:QI 2 "nonmemory_operand" "")))]
11288169699Skan  ""
11289169699Skan  "ix86_expand_binary_operator (ASHIFTRT, DImode, operands); DONE;")
11290169699Skan
11291169699Skan(define_insn "*ashrdi3_63_rex64"
1129290286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=*d,rm")
1129390286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "*a,0")
1129490286Sobrien		     (match_operand:DI 2 "const_int_operand" "i,i")))
11295169699Skan   (clobber (reg:CC FLAGS_REG))]
11296169699Skan  "TARGET_64BIT && INTVAL (operands[2]) == 63
11297169699Skan   && (TARGET_USE_CLTD || optimize_size)
1129890286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1129990286Sobrien  "@
1130090286Sobrien   {cqto|cqo}
1130190286Sobrien   sar{q}\t{%2, %0|%0, %2}"
1130290286Sobrien  [(set_attr "type" "imovx,ishift")
1130390286Sobrien   (set_attr "prefix_0f" "0,*")
1130490286Sobrien   (set_attr "length_immediate" "0,*")
1130590286Sobrien   (set_attr "modrm" "0,1")
1130690286Sobrien   (set_attr "mode" "DI")])
1130750650Sobrien
1130890286Sobrien(define_insn "*ashrdi3_1_one_bit_rex64"
1130990286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1131090286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11311132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11312169699Skan   (clobber (reg:CC FLAGS_REG))]
1131390286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11314117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1131590286Sobrien  "sar{q}\t%0"
1131690286Sobrien  [(set_attr "type" "ishift")
1131790286Sobrien   (set (attr "length") 
1131890286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1131990286Sobrien	(const_string "2")
1132090286Sobrien	(const_string "*")))])
1132150650Sobrien
1132290286Sobrien(define_insn "*ashrdi3_1_rex64"
1132390286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1132490286Sobrien	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1132590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
11326169699Skan   (clobber (reg:CC FLAGS_REG))]
1132790286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1132890286Sobrien  "@
1132990286Sobrien   sar{q}\t{%2, %0|%0, %2}
1133090286Sobrien   sar{q}\t{%b2, %0|%0, %b2}"
1133190286Sobrien  [(set_attr "type" "ishift")
1133290286Sobrien   (set_attr "mode" "DI")])
1133350650Sobrien
1133490286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1133590286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1133690286Sobrien;; zero are optimized away.
1133790286Sobrien(define_insn "*ashrdi3_one_bit_cmp_rex64"
11338169699Skan  [(set (reg FLAGS_REG)
1133990286Sobrien	(compare
1134090286Sobrien	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11341132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1134290286Sobrien	  (const_int 0)))
1134390286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1134490286Sobrien	(ashiftrt:DI (match_dup 1) (match_dup 2)))]
1134590286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11346117404Skan   && (TARGET_SHIFT1 || optimize_size)
1134790286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
1134890286Sobrien  "sar{q}\t%0"
1134990286Sobrien  [(set_attr "type" "ishift")
1135090286Sobrien   (set (attr "length") 
1135190286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1135290286Sobrien	(const_string "2")
1135390286Sobrien	(const_string "*")))])
1135450650Sobrien
11355169699Skan(define_insn "*ashrdi3_one_bit_cconly_rex64"
11356169699Skan  [(set (reg FLAGS_REG)
11357169699Skan	(compare
11358169699Skan	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11359169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11360169699Skan	  (const_int 0)))
11361169699Skan   (clobber (match_scratch:DI 0 "=r"))]
11362169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11363169699Skan   && (TARGET_SHIFT1 || optimize_size)
11364169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
11365169699Skan  "sar{q}\t%0"
11366169699Skan  [(set_attr "type" "ishift")
11367169699Skan   (set_attr "length" "2")])
11368169699Skan
1136990286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1137090286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1137190286Sobrien;; zero are optimized away.
1137290286Sobrien(define_insn "*ashrdi3_cmp_rex64"
11373169699Skan  [(set (reg FLAGS_REG)
1137490286Sobrien	(compare
1137590286Sobrien	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1137690286Sobrien		       (match_operand:QI 2 "const_int_operand" "n"))
1137790286Sobrien	  (const_int 0)))
1137890286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1137990286Sobrien	(ashiftrt:DI (match_dup 1) (match_dup 2)))]
1138090286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11381169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11382169699Skan   && (optimize_size
11383169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1138490286Sobrien  "sar{q}\t{%2, %0|%0, %2}"
1138590286Sobrien  [(set_attr "type" "ishift")
1138690286Sobrien   (set_attr "mode" "DI")])
1138718334Speter
11388169699Skan(define_insn "*ashrdi3_cconly_rex64"
11389169699Skan  [(set (reg FLAGS_REG)
11390169699Skan	(compare
11391169699Skan	  (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11392169699Skan		       (match_operand:QI 2 "const_int_operand" "n"))
11393169699Skan	  (const_int 0)))
11394169699Skan   (clobber (match_scratch:DI 0 "=r"))]
11395169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11396169699Skan   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
11397169699Skan   && (optimize_size
11398169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11399169699Skan  "sar{q}\t{%2, %0|%0, %2}"
11400169699Skan  [(set_attr "type" "ishift")
11401169699Skan   (set_attr "mode" "DI")])
1140218334Speter
11403169699Skan(define_insn "*ashrdi3_1"
1140490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1140590286Sobrien	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
1140690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "Jc")))
11407169699Skan   (clobber (reg:CC FLAGS_REG))]
1140890286Sobrien  "!TARGET_64BIT"
1140990286Sobrien  "#"
1141090286Sobrien  [(set_attr "type" "multi")])
1141118334Speter
11412169699Skan;; By default we don't ask for a scratch register, because when DImode
11413169699Skan;; values are manipulated, registers are already at a premium.  But if
11414169699Skan;; we have one handy, we won't turn it away.
11415169699Skan(define_peephole2
11416169699Skan  [(match_scratch:SI 3 "r")
11417169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
11418169699Skan		   (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
11419169699Skan			        (match_operand:QI 2 "nonmemory_operand" "")))
11420169699Skan	      (clobber (reg:CC FLAGS_REG))])
11421169699Skan   (match_dup 3)]
11422169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1142390286Sobrien  [(const_int 0)]
11424169699Skan  "ix86_split_ashr (operands, operands[3], DImode); DONE;")
1142518334Speter
1142690286Sobrien(define_split
1142790286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1142890286Sobrien	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
1142990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11430169699Skan   (clobber (reg:CC FLAGS_REG))]
11431169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
11432169699Skan		     ? flow2_completed : reload_completed)"
1143390286Sobrien  [(const_int 0)]
11434169699Skan  "ix86_split_ashr (operands, NULL_RTX, DImode); DONE;")
1143518334Speter
1143690286Sobrien(define_insn "x86_shrd_1"
1143790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
1143890286Sobrien        (ior:SI (ashiftrt:SI (match_dup 0)
1143990286Sobrien		  (match_operand:QI 2 "nonmemory_operand" "I,c"))
1144090286Sobrien		(ashift:SI (match_operand:SI 1 "register_operand" "r,r")
1144190286Sobrien		  (minus:QI (const_int 32) (match_dup 2)))))
11442169699Skan   (clobber (reg:CC FLAGS_REG))]
1144318334Speter  ""
1144490286Sobrien  "@
1144590286Sobrien   shrd{l}\t{%2, %1, %0|%0, %1, %2}
1144690286Sobrien   shrd{l}\t{%s2%1, %0|%0, %1, %2}"
1144790286Sobrien  [(set_attr "type" "ishift")
1144890286Sobrien   (set_attr "prefix_0f" "1")
1144990286Sobrien   (set_attr "pent_pair" "np")
1145090286Sobrien   (set_attr "mode" "SI")])
1145190286Sobrien
1145290286Sobrien(define_expand "x86_shift_adj_3"
1145390286Sobrien  [(use (match_operand:SI 0 "register_operand" ""))
1145490286Sobrien   (use (match_operand:SI 1 "register_operand" ""))
1145590286Sobrien   (use (match_operand:QI 2 "register_operand" ""))]
1145690286Sobrien  ""
1145718334Speter{
1145890286Sobrien  rtx label = gen_label_rtx ();
1145990286Sobrien  rtx tmp;
1146018334Speter
1146190286Sobrien  emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32)));
1146218334Speter
1146390286Sobrien  tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
1146490286Sobrien  tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1146590286Sobrien  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
1146690286Sobrien			      gen_rtx_LABEL_REF (VOIDmode, label),
1146790286Sobrien			      pc_rtx);
1146890286Sobrien  tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
1146990286Sobrien  JUMP_LABEL (tmp) = label;
1147018334Speter
1147190286Sobrien  emit_move_insn (operands[0], operands[1]);
1147290286Sobrien  emit_insn (gen_ashrsi3_31 (operands[1], operands[1], GEN_INT (31)));
1147318334Speter
1147490286Sobrien  emit_label (label);
1147590286Sobrien  LABEL_NUSES (label) = 1;
1147690286Sobrien
1147790286Sobrien  DONE;
1147890286Sobrien})
1147990286Sobrien
1148052296Sobrien(define_insn "ashrsi3_31"
1148190286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm")
1148290286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0")
1148390286Sobrien		     (match_operand:SI 2 "const_int_operand" "i,i")))
11484169699Skan   (clobber (reg:CC FLAGS_REG))]
1148590286Sobrien  "INTVAL (operands[2]) == 31 && (TARGET_USE_CLTD || optimize_size)
1148690286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1148752296Sobrien  "@
1148890286Sobrien   {cltd|cdq}
1148990286Sobrien   sar{l}\t{%2, %0|%0, %2}"
1149090286Sobrien  [(set_attr "type" "imovx,ishift")
1149190286Sobrien   (set_attr "prefix_0f" "0,*")
1149290286Sobrien   (set_attr "length_immediate" "0,*")
1149390286Sobrien   (set_attr "modrm" "0,1")
1149490286Sobrien   (set_attr "mode" "SI")])
1149552296Sobrien
1149690286Sobrien(define_insn "*ashrsi3_31_zext"
1149790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=*d,r")
1149890286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "*a,0")
1149990286Sobrien				     (match_operand:SI 2 "const_int_operand" "i,i"))))
11500169699Skan   (clobber (reg:CC FLAGS_REG))]
1150190286Sobrien  "TARGET_64BIT && (TARGET_USE_CLTD || optimize_size)
1150290286Sobrien   && INTVAL (operands[2]) == 31
1150390286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1150490286Sobrien  "@
1150590286Sobrien   {cltd|cdq}
1150690286Sobrien   sar{l}\t{%2, %k0|%k0, %2}"
1150790286Sobrien  [(set_attr "type" "imovx,ishift")
1150890286Sobrien   (set_attr "prefix_0f" "0,*")
1150990286Sobrien   (set_attr "length_immediate" "0,*")
1151090286Sobrien   (set_attr "modrm" "0,1")
1151190286Sobrien   (set_attr "mode" "SI")])
1151290286Sobrien
1151390286Sobrien(define_expand "ashrsi3"
1151490286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1151590286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
1151690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11517169699Skan   (clobber (reg:CC FLAGS_REG))]
1151890286Sobrien  ""
1151990286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, SImode, operands); DONE;")
1152090286Sobrien
1152190286Sobrien(define_insn "*ashrsi3_1_one_bit"
1152250650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1152350650Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11524132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11525169699Skan   (clobber (reg:CC FLAGS_REG))]
1152690286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11527117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1152890286Sobrien  "sar{l}\t%0"
1152990286Sobrien  [(set_attr "type" "ishift")
1153090286Sobrien   (set (attr "length") 
1153190286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1153290286Sobrien	(const_string "2")
1153390286Sobrien	(const_string "*")))])
1153418334Speter
1153590286Sobrien(define_insn "*ashrsi3_1_one_bit_zext"
1153690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1153790286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11538132727Skan				     (match_operand:QI 2 "const1_operand" ""))))
11539169699Skan   (clobber (reg:CC FLAGS_REG))]
1154090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11541117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1154290286Sobrien  "sar{l}\t%k0"
1154390286Sobrien  [(set_attr "type" "ishift")
1154490286Sobrien   (set_attr "length" "2")])
1154590286Sobrien
1154690286Sobrien(define_insn "*ashrsi3_1"
1154790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1154890286Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1154990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11550169699Skan   (clobber (reg:CC FLAGS_REG))]
1155190286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1155290286Sobrien  "@
1155390286Sobrien   sar{l}\t{%2, %0|%0, %2}
1155490286Sobrien   sar{l}\t{%b2, %0|%0, %b2}"
1155590286Sobrien  [(set_attr "type" "ishift")
1155690286Sobrien   (set_attr "mode" "SI")])
1155790286Sobrien
1155890286Sobrien(define_insn "*ashrsi3_1_zext"
1155990286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1156090286Sobrien	(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
1156190286Sobrien				     (match_operand:QI 2 "nonmemory_operand" "I,c"))))
11562169699Skan   (clobber (reg:CC FLAGS_REG))]
1156390286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1156490286Sobrien  "@
1156590286Sobrien   sar{l}\t{%2, %k0|%k0, %2}
1156690286Sobrien   sar{l}\t{%b2, %k0|%k0, %b2}"
1156790286Sobrien  [(set_attr "type" "ishift")
1156890286Sobrien   (set_attr "mode" "SI")])
1156990286Sobrien
1157090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1157190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1157290286Sobrien;; zero are optimized away.
1157390286Sobrien(define_insn "*ashrsi3_one_bit_cmp"
11574169699Skan  [(set (reg FLAGS_REG)
1157590286Sobrien	(compare
1157690286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11577132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1157890286Sobrien	  (const_int 0)))
1157990286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1158090286Sobrien	(ashiftrt:SI (match_dup 1) (match_dup 2)))]
1158190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11582117404Skan   && (TARGET_SHIFT1 || optimize_size)
1158390286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1158490286Sobrien  "sar{l}\t%0"
1158590286Sobrien  [(set_attr "type" "ishift")
1158690286Sobrien   (set (attr "length") 
1158790286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1158890286Sobrien	(const_string "2")
1158990286Sobrien	(const_string "*")))])
1159090286Sobrien
11591169699Skan(define_insn "*ashrsi3_one_bit_cconly"
11592169699Skan  [(set (reg FLAGS_REG)
11593169699Skan	(compare
11594169699Skan	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11595169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11596169699Skan	  (const_int 0)))
11597169699Skan   (clobber (match_scratch:SI 0 "=r"))]
11598169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11599169699Skan   && (TARGET_SHIFT1 || optimize_size)
11600169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
11601169699Skan  "sar{l}\t%0"
11602169699Skan  [(set_attr "type" "ishift")
11603169699Skan   (set_attr "length" "2")])
11604169699Skan
1160590286Sobrien(define_insn "*ashrsi3_one_bit_cmp_zext"
11606169699Skan  [(set (reg FLAGS_REG)
1160790286Sobrien	(compare
1160890286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11609132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1161090286Sobrien	  (const_int 0)))
1161190286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1161290286Sobrien	(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
1161390286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
11614117404Skan   && (TARGET_SHIFT1 || optimize_size)
1161590286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
1161690286Sobrien  "sar{l}\t%k0"
1161790286Sobrien  [(set_attr "type" "ishift")
1161890286Sobrien   (set_attr "length" "2")])
1161990286Sobrien
1162090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1162190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1162290286Sobrien;; zero are optimized away.
1162390286Sobrien(define_insn "*ashrsi3_cmp"
11624169699Skan  [(set (reg FLAGS_REG)
1162590286Sobrien	(compare
1162690286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11627169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1162890286Sobrien	  (const_int 0)))
1162990286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1163090286Sobrien	(ashiftrt:SI (match_dup 1) (match_dup 2)))]
1163190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11632169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11633169699Skan   && (optimize_size
11634169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1163590286Sobrien  "sar{l}\t{%2, %0|%0, %2}"
1163690286Sobrien  [(set_attr "type" "ishift")
1163790286Sobrien   (set_attr "mode" "SI")])
1163890286Sobrien
11639169699Skan(define_insn "*ashrsi3_cconly"
11640169699Skan  [(set (reg FLAGS_REG)
11641169699Skan	(compare
11642169699Skan	  (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
11643169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11644169699Skan	  (const_int 0)))
11645169699Skan   (clobber (match_scratch:SI 0 "=r"))]
11646169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11647169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11648169699Skan   && (optimize_size
11649169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11650169699Skan  "sar{l}\t{%2, %0|%0, %2}"
11651169699Skan  [(set_attr "type" "ishift")
11652169699Skan   (set_attr "mode" "SI")])
11653169699Skan
1165490286Sobrien(define_insn "*ashrsi3_cmp_zext"
11655169699Skan  [(set (reg FLAGS_REG)
1165690286Sobrien	(compare
1165790286Sobrien	  (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
11658169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1165990286Sobrien	  (const_int 0)))
1166090286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1166190286Sobrien	(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
1166290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
11663169699Skan   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
11664169699Skan   && (optimize_size
11665169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1166690286Sobrien  "sar{l}\t{%2, %k0|%k0, %2}"
1166790286Sobrien  [(set_attr "type" "ishift")
1166890286Sobrien   (set_attr "mode" "SI")])
1166990286Sobrien
1167090286Sobrien(define_expand "ashrhi3"
1167190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1167290286Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
1167390286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11674169699Skan   (clobber (reg:CC FLAGS_REG))]
1167590286Sobrien  "TARGET_HIMODE_MATH"
1167690286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, HImode, operands); DONE;")
1167790286Sobrien
1167890286Sobrien(define_insn "*ashrhi3_1_one_bit"
1167950650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1168050650Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11681132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11682169699Skan   (clobber (reg:CC FLAGS_REG))]
1168390286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11684117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1168590286Sobrien  "sar{w}\t%0"
1168690286Sobrien  [(set_attr "type" "ishift")
1168790286Sobrien   (set (attr "length") 
1168890286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1168990286Sobrien	(const_string "2")
1169090286Sobrien	(const_string "*")))])
1169118334Speter
1169290286Sobrien(define_insn "*ashrhi3_1"
1169390286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1169490286Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1169590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11696169699Skan   (clobber (reg:CC FLAGS_REG))]
1169790286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
1169890286Sobrien  "@
1169990286Sobrien   sar{w}\t{%2, %0|%0, %2}
1170090286Sobrien   sar{w}\t{%b2, %0|%0, %b2}"
1170190286Sobrien  [(set_attr "type" "ishift")
1170290286Sobrien   (set_attr "mode" "HI")])
1170390286Sobrien
1170490286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1170590286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1170690286Sobrien;; zero are optimized away.
1170790286Sobrien(define_insn "*ashrhi3_one_bit_cmp"
11708169699Skan  [(set (reg FLAGS_REG)
1170990286Sobrien	(compare
1171090286Sobrien	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11711132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1171290286Sobrien	  (const_int 0)))
1171390286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1171490286Sobrien	(ashiftrt:HI (match_dup 1) (match_dup 2)))]
1171590286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11716117404Skan   && (TARGET_SHIFT1 || optimize_size)
1171790286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
1171890286Sobrien  "sar{w}\t%0"
1171990286Sobrien  [(set_attr "type" "ishift")
1172090286Sobrien   (set (attr "length") 
1172190286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1172290286Sobrien	(const_string "2")
1172390286Sobrien	(const_string "*")))])
1172490286Sobrien
11725169699Skan(define_insn "*ashrhi3_one_bit_cconly"
11726169699Skan  [(set (reg FLAGS_REG)
11727169699Skan	(compare
11728169699Skan	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11729169699Skan		       (match_operand:QI 2 "const1_operand" ""))
11730169699Skan	  (const_int 0)))
11731169699Skan   (clobber (match_scratch:HI 0 "=r"))]
11732169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11733169699Skan   && (TARGET_SHIFT1 || optimize_size)
11734169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
11735169699Skan  "sar{w}\t%0"
11736169699Skan  [(set_attr "type" "ishift")
11737169699Skan   (set_attr "length" "2")])
11738169699Skan
1173990286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1174090286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1174190286Sobrien;; zero are optimized away.
1174290286Sobrien(define_insn "*ashrhi3_cmp"
11743169699Skan  [(set (reg FLAGS_REG)
1174490286Sobrien	(compare
1174590286Sobrien	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11746169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1174790286Sobrien	  (const_int 0)))
1174890286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1174990286Sobrien	(ashiftrt:HI (match_dup 1) (match_dup 2)))]
1175090286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11751169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11752169699Skan   && (optimize_size
11753169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1175490286Sobrien  "sar{w}\t{%2, %0|%0, %2}"
1175590286Sobrien  [(set_attr "type" "ishift")
1175690286Sobrien   (set_attr "mode" "HI")])
1175790286Sobrien
11758169699Skan(define_insn "*ashrhi3_cconly"
11759169699Skan  [(set (reg FLAGS_REG)
11760169699Skan	(compare
11761169699Skan	  (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
11762169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11763169699Skan	  (const_int 0)))
11764169699Skan   (clobber (match_scratch:HI 0 "=r"))]
11765169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11766169699Skan   && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
11767169699Skan   && (optimize_size
11768169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11769169699Skan  "sar{w}\t{%2, %0|%0, %2}"
11770169699Skan  [(set_attr "type" "ishift")
11771169699Skan   (set_attr "mode" "HI")])
11772169699Skan
1177390286Sobrien(define_expand "ashrqi3"
1177490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1177590286Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
1177690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
11777169699Skan   (clobber (reg:CC FLAGS_REG))]
1177890286Sobrien  "TARGET_QIMODE_MATH"
1177990286Sobrien  "ix86_expand_binary_operator (ASHIFTRT, QImode, operands); DONE;")
1178090286Sobrien
1178190286Sobrien(define_insn "*ashrqi3_1_one_bit"
1178250650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1178350650Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11784132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11785169699Skan   (clobber (reg:CC FLAGS_REG))]
1178690286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11787117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1178890286Sobrien  "sar{b}\t%0"
1178990286Sobrien  [(set_attr "type" "ishift")
1179090286Sobrien   (set (attr "length") 
1179190286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1179290286Sobrien	(const_string "2")
1179390286Sobrien	(const_string "*")))])
1179490286Sobrien
11795117404Skan(define_insn "*ashrqi3_1_one_bit_slp"
11796117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
11797117404Skan	(ashiftrt:QI (match_dup 0)
11798132727Skan		     (match_operand:QI 1 "const1_operand" "")))
11799169699Skan   (clobber (reg:CC FLAGS_REG))]
11800117404Skan  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11801117404Skan   && (! TARGET_PARTIAL_REG_STALL || optimize_size)
11802117404Skan   && (TARGET_SHIFT1 || optimize_size)"
11803117404Skan  "sar{b}\t%0"
11804117404Skan  [(set_attr "type" "ishift1")
11805117404Skan   (set (attr "length") 
11806117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
11807117404Skan	(const_string "2")
11808117404Skan	(const_string "*")))])
11809117404Skan
1181090286Sobrien(define_insn "*ashrqi3_1"
1181190286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1181290286Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1181390286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
11814169699Skan   (clobber (reg:CC FLAGS_REG))]
1181590286Sobrien  "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
1181690286Sobrien  "@
1181790286Sobrien   sar{b}\t{%2, %0|%0, %2}
1181890286Sobrien   sar{b}\t{%b2, %0|%0, %b2}"
1181990286Sobrien  [(set_attr "type" "ishift")
1182090286Sobrien   (set_attr "mode" "QI")])
1182190286Sobrien
11822117404Skan(define_insn "*ashrqi3_1_slp"
11823117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
11824117404Skan	(ashiftrt:QI (match_dup 0)
11825117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
11826169699Skan   (clobber (reg:CC FLAGS_REG))]
11827117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
11828117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
11829117404Skan  "@
11830117404Skan   sar{b}\t{%1, %0|%0, %1}
11831117404Skan   sar{b}\t{%b1, %0|%0, %b1}"
11832117404Skan  [(set_attr "type" "ishift1")
11833117404Skan   (set_attr "mode" "QI")])
11834117404Skan
1183590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1183690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1183790286Sobrien;; zero are optimized away.
1183890286Sobrien(define_insn "*ashrqi3_one_bit_cmp"
11839169699Skan  [(set (reg FLAGS_REG)
1184090286Sobrien	(compare
1184190286Sobrien	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11842132727Skan		       (match_operand:QI 2 "const1_operand" "I"))
1184390286Sobrien	  (const_int 0)))
11844102802Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1184590286Sobrien	(ashiftrt:QI (match_dup 1) (match_dup 2)))]
1184690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11847117404Skan   && (TARGET_SHIFT1 || optimize_size)
1184890286Sobrien   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
1184990286Sobrien  "sar{b}\t%0"
1185090286Sobrien  [(set_attr "type" "ishift")
1185190286Sobrien   (set (attr "length") 
1185290286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1185390286Sobrien	(const_string "2")
1185490286Sobrien	(const_string "*")))])
1185590286Sobrien
11856169699Skan(define_insn "*ashrqi3_one_bit_cconly"
11857169699Skan  [(set (reg FLAGS_REG)
11858169699Skan	(compare
11859169699Skan	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11860169699Skan		       (match_operand:QI 2 "const1_operand" "I"))
11861169699Skan	  (const_int 0)))
11862169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11863169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11864169699Skan   && (TARGET_SHIFT1 || optimize_size)
11865169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
11866169699Skan  "sar{b}\t%0"
11867169699Skan  [(set_attr "type" "ishift")
11868169699Skan   (set_attr "length" "2")])
11869169699Skan
1187090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1187190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1187290286Sobrien;; zero are optimized away.
1187390286Sobrien(define_insn "*ashrqi3_cmp"
11874169699Skan  [(set (reg FLAGS_REG)
1187590286Sobrien	(compare
1187690286Sobrien	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11877169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1187890286Sobrien	  (const_int 0)))
11879102802Skan   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1188090286Sobrien	(ashiftrt:QI (match_dup 1) (match_dup 2)))]
1188190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
11882169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11883169699Skan   && (optimize_size
11884169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1188590286Sobrien  "sar{b}\t{%2, %0|%0, %2}"
1188690286Sobrien  [(set_attr "type" "ishift")
1188790286Sobrien   (set_attr "mode" "QI")])
11888169699Skan
11889169699Skan(define_insn "*ashrqi3_cconly"
11890169699Skan  [(set (reg FLAGS_REG)
11891169699Skan	(compare
11892169699Skan	  (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
11893169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
11894169699Skan	  (const_int 0)))
11895169699Skan   (clobber (match_scratch:QI 0 "=q"))]
11896169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
11897169699Skan   && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
11898169699Skan   && (optimize_size
11899169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
11900169699Skan  "sar{b}\t{%2, %0|%0, %2}"
11901169699Skan  [(set_attr "type" "ishift")
11902169699Skan   (set_attr "mode" "QI")])
11903169699Skan
1190418334Speter
1190590286Sobrien;; Logical shift instructions
1190618334Speter
1190718334Speter;; See comment above `ashldi3' about how this works.
1190818334Speter
11909169699Skan(define_expand "lshrti3"
11910169699Skan  [(parallel [(set (match_operand:TI 0 "register_operand" "")
11911169699Skan		   (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
1191290286Sobrien			        (match_operand:QI 2 "nonmemory_operand" "")))
11913169699Skan	      (clobber (reg:CC FLAGS_REG))])]
11914169699Skan  "TARGET_64BIT"
1191518334Speter{
11916169699Skan  if (! immediate_operand (operands[2], QImode))
1191718334Speter    {
11918169699Skan      emit_insn (gen_lshrti3_1 (operands[0], operands[1], operands[2]));
1191990286Sobrien      DONE;
1192018334Speter    }
11921169699Skan  ix86_expand_binary_operator (LSHIFTRT, TImode, operands);
1192218334Speter  DONE;
1192390286Sobrien})
1192418334Speter
11925169699Skan(define_insn "lshrti3_1"
11926169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11927169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
11928169699Skan		     (match_operand:QI 2 "register_operand" "c")))
11929169699Skan   (clobber (match_scratch:DI 3 "=&r"))
11930169699Skan   (clobber (reg:CC FLAGS_REG))]
11931169699Skan  "TARGET_64BIT"
11932169699Skan  "#"
11933169699Skan  [(set_attr "type" "multi")])
11934169699Skan
11935169699Skan(define_insn "*lshrti3_2"
11936169699Skan  [(set (match_operand:TI 0 "register_operand" "=r")
11937169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
11938169699Skan		     (match_operand:QI 2 "immediate_operand" "O")))
11939169699Skan   (clobber (reg:CC FLAGS_REG))]
11940169699Skan  "TARGET_64BIT"
11941169699Skan  "#"
11942169699Skan  [(set_attr "type" "multi")])
11943169699Skan
11944169699Skan(define_split 
11945169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11946169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "")
11947169699Skan		     (match_operand:QI 2 "register_operand" "")))
11948169699Skan   (clobber (match_scratch:DI 3 ""))
11949169699Skan   (clobber (reg:CC FLAGS_REG))]
11950169699Skan  "TARGET_64BIT && reload_completed"
11951169699Skan  [(const_int 0)]
11952169699Skan  "ix86_split_lshr (operands, operands[3], TImode); DONE;")
11953169699Skan
11954169699Skan(define_split 
11955169699Skan  [(set (match_operand:TI 0 "register_operand" "")
11956169699Skan	(lshiftrt:TI (match_operand:TI 1 "register_operand" "")
11957169699Skan		     (match_operand:QI 2 "immediate_operand" "")))
11958169699Skan   (clobber (reg:CC FLAGS_REG))]
11959169699Skan  "TARGET_64BIT && reload_completed"
11960169699Skan  [(const_int 0)]
11961169699Skan  "ix86_split_lshr (operands, NULL_RTX, TImode); DONE;")
11962169699Skan
11963169699Skan(define_expand "lshrdi3"
11964169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
11965169699Skan	(lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
11966169699Skan		     (match_operand:QI 2 "nonmemory_operand" "")))]
11967169699Skan  ""
11968169699Skan  "ix86_expand_binary_operator (LSHIFTRT, DImode, operands); DONE;")
11969169699Skan
1197090286Sobrien(define_insn "*lshrdi3_1_one_bit_rex64"
1197190286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1197290286Sobrien	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
11973132727Skan		     (match_operand:QI 2 "const1_operand" "")))
11974169699Skan   (clobber (reg:CC FLAGS_REG))]
1197590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
11976117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1197790286Sobrien  "shr{q}\t%0"
1197890286Sobrien  [(set_attr "type" "ishift")
1197990286Sobrien   (set (attr "length") 
1198090286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1198190286Sobrien	(const_string "2")
1198290286Sobrien	(const_string "*")))])
1198350650Sobrien
1198490286Sobrien(define_insn "*lshrdi3_1_rex64"
1198590286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1198690286Sobrien	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1198790286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
11988169699Skan   (clobber (reg:CC FLAGS_REG))]
1198990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1199090286Sobrien  "@
1199190286Sobrien   shr{q}\t{%2, %0|%0, %2}
1199290286Sobrien   shr{q}\t{%b2, %0|%0, %b2}"
1199390286Sobrien  [(set_attr "type" "ishift")
1199490286Sobrien   (set_attr "mode" "DI")])
1199550650Sobrien
1199690286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1199790286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1199890286Sobrien;; zero are optimized away.
1199990286Sobrien(define_insn "*lshrdi3_cmp_one_bit_rex64"
12000169699Skan  [(set (reg FLAGS_REG)
1200190286Sobrien	(compare
1200290286Sobrien	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12003132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1200490286Sobrien	  (const_int 0)))
1200590286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1200690286Sobrien	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
1200790286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12008117404Skan   && (TARGET_SHIFT1 || optimize_size)
1200990286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1201090286Sobrien  "shr{q}\t%0"
1201190286Sobrien  [(set_attr "type" "ishift")
1201290286Sobrien   (set (attr "length") 
1201390286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1201490286Sobrien	(const_string "2")
1201590286Sobrien	(const_string "*")))])
1201650650Sobrien
12017169699Skan(define_insn "*lshrdi3_cconly_one_bit_rex64"
12018169699Skan  [(set (reg FLAGS_REG)
12019169699Skan	(compare
12020169699Skan	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12021169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12022169699Skan	  (const_int 0)))
12023169699Skan   (clobber (match_scratch:DI 0 "=r"))]
12024169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12025169699Skan   && (TARGET_SHIFT1 || optimize_size)
12026169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12027169699Skan  "shr{q}\t%0"
12028169699Skan  [(set_attr "type" "ishift")
12029169699Skan   (set_attr "length" "2")])
12030169699Skan
1203190286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1203290286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1203390286Sobrien;; zero are optimized away.
1203490286Sobrien(define_insn "*lshrdi3_cmp_rex64"
12035169699Skan  [(set (reg FLAGS_REG)
1203690286Sobrien	(compare
1203790286Sobrien	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
1203890286Sobrien		       (match_operand:QI 2 "const_int_operand" "e"))
1203990286Sobrien	  (const_int 0)))
1204090286Sobrien   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1204190286Sobrien	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
1204290286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12043169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12044169699Skan   && (optimize_size
12045169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1204690286Sobrien  "shr{q}\t{%2, %0|%0, %2}"
1204790286Sobrien  [(set_attr "type" "ishift")
1204890286Sobrien   (set_attr "mode" "DI")])
1204950650Sobrien
12050169699Skan(define_insn "*lshrdi3_cconly_rex64"
12051169699Skan  [(set (reg FLAGS_REG)
12052169699Skan	(compare
12053169699Skan	  (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12054169699Skan		       (match_operand:QI 2 "const_int_operand" "e"))
12055169699Skan	  (const_int 0)))
12056169699Skan   (clobber (match_scratch:DI 0 "=r"))]
12057169699Skan  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12058169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12059169699Skan   && (optimize_size
12060169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12061169699Skan  "shr{q}\t{%2, %0|%0, %2}"
12062169699Skan  [(set_attr "type" "ishift")
12063169699Skan   (set_attr "mode" "DI")])
1206418334Speter
12065169699Skan(define_insn "*lshrdi3_1"
1206690286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1206790286Sobrien	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
1206890286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "Jc")))
12069169699Skan   (clobber (reg:CC FLAGS_REG))]
1207090286Sobrien  "!TARGET_64BIT"
1207190286Sobrien  "#"
1207290286Sobrien  [(set_attr "type" "multi")])
1207318334Speter
12074169699Skan;; By default we don't ask for a scratch register, because when DImode
12075169699Skan;; values are manipulated, registers are already at a premium.  But if
12076169699Skan;; we have one handy, we won't turn it away.
12077169699Skan(define_peephole2
12078169699Skan  [(match_scratch:SI 3 "r")
12079169699Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
12080169699Skan		   (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
12081169699Skan			        (match_operand:QI 2 "nonmemory_operand" "")))
12082169699Skan	      (clobber (reg:CC FLAGS_REG))])
12083169699Skan   (match_dup 3)]
12084169699Skan  "!TARGET_64BIT && TARGET_CMOVE"
1208590286Sobrien  [(const_int 0)]
12086169699Skan  "ix86_split_lshr (operands, operands[3], DImode); DONE;")
1208718334Speter
1208890286Sobrien(define_split 
1208990286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1209090286Sobrien	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
1209190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12092169699Skan   (clobber (reg:CC FLAGS_REG))]
12093169699Skan  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
12094169699Skan		     ? flow2_completed : reload_completed)"
1209590286Sobrien  [(const_int 0)]
12096169699Skan  "ix86_split_lshr (operands, NULL_RTX, DImode); DONE;")
1209718334Speter
1209890286Sobrien(define_expand "lshrsi3"
1209990286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1210090286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
1210190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12102169699Skan   (clobber (reg:CC FLAGS_REG))]
1210390286Sobrien  ""
1210490286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, SImode, operands); DONE;")
1210518334Speter
1210690286Sobrien(define_insn "*lshrsi3_1_one_bit"
1210790286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1210890286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12109132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12110169699Skan   (clobber (reg:CC FLAGS_REG))]
1211190286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12112117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1211390286Sobrien  "shr{l}\t%0"
1211490286Sobrien  [(set_attr "type" "ishift")
1211590286Sobrien   (set (attr "length") 
1211690286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1211790286Sobrien	(const_string "2")
1211890286Sobrien	(const_string "*")))])
1211918334Speter
1212090286Sobrien(define_insn "*lshrsi3_1_one_bit_zext"
1212190286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1212290286Sobrien	(lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0"))
12123132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12124169699Skan   (clobber (reg:CC FLAGS_REG))]
1212590286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12126117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1212790286Sobrien  "shr{l}\t%k0"
1212890286Sobrien  [(set_attr "type" "ishift")
1212990286Sobrien   (set_attr "length" "2")])
1213018334Speter
1213190286Sobrien(define_insn "*lshrsi3_1"
1213290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1213390286Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1213490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12135169699Skan   (clobber (reg:CC FLAGS_REG))]
1213690286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1213790286Sobrien  "@
1213890286Sobrien   shr{l}\t{%2, %0|%0, %2}
1213990286Sobrien   shr{l}\t{%b2, %0|%0, %b2}"
1214090286Sobrien  [(set_attr "type" "ishift")
1214190286Sobrien   (set_attr "mode" "SI")])
1214218334Speter
1214390286Sobrien(define_insn "*lshrsi3_1_zext"
1214490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1214590286Sobrien	(zero_extend:DI
1214690286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1214790286Sobrien		       (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12148169699Skan   (clobber (reg:CC FLAGS_REG))]
1214990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1215090286Sobrien  "@
1215190286Sobrien   shr{l}\t{%2, %k0|%k0, %2}
1215290286Sobrien   shr{l}\t{%b2, %k0|%k0, %b2}"
1215390286Sobrien  [(set_attr "type" "ishift")
1215490286Sobrien   (set_attr "mode" "SI")])
1215518334Speter
1215690286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1215790286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1215890286Sobrien;; zero are optimized away.
1215990286Sobrien(define_insn "*lshrsi3_one_bit_cmp"
12160169699Skan  [(set (reg FLAGS_REG)
1216190286Sobrien	(compare
1216290286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12163132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1216490286Sobrien	  (const_int 0)))
1216590286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1216690286Sobrien	(lshiftrt:SI (match_dup 1) (match_dup 2)))]
1216790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12168117404Skan   && (TARGET_SHIFT1 || optimize_size)
1216990286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1217090286Sobrien  "shr{l}\t%0"
1217190286Sobrien  [(set_attr "type" "ishift")
1217290286Sobrien   (set (attr "length") 
1217390286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1217490286Sobrien	(const_string "2")
1217590286Sobrien	(const_string "*")))])
1217618334Speter
12177169699Skan(define_insn "*lshrsi3_one_bit_cconly"
12178169699Skan  [(set (reg FLAGS_REG)
12179169699Skan	(compare
12180169699Skan	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12181169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12182169699Skan	  (const_int 0)))
12183169699Skan   (clobber (match_scratch:SI 0 "=r"))]
12184169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12185169699Skan   && (TARGET_SHIFT1 || optimize_size)
12186169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12187169699Skan  "shr{l}\t%0"
12188169699Skan  [(set_attr "type" "ishift")
12189169699Skan   (set_attr "length" "2")])
12190169699Skan
1219190286Sobrien(define_insn "*lshrsi3_cmp_one_bit_zext"
12192169699Skan  [(set (reg FLAGS_REG)
1219390286Sobrien	(compare
1219490286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
12195132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1219690286Sobrien	  (const_int 0)))
1219790286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1219890286Sobrien	(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
1219990286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12200117404Skan   && (TARGET_SHIFT1 || optimize_size)
1220190286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1220290286Sobrien  "shr{l}\t%k0"
1220390286Sobrien  [(set_attr "type" "ishift")
1220490286Sobrien   (set_attr "length" "2")])
1220518334Speter
1220690286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1220790286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1220890286Sobrien;; zero are optimized away.
1220990286Sobrien(define_insn "*lshrsi3_cmp"
12210169699Skan  [(set (reg FLAGS_REG)
1221190286Sobrien	(compare
1221290286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12213169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1221490286Sobrien	  (const_int 0)))
1221590286Sobrien   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1221690286Sobrien	(lshiftrt:SI (match_dup 1) (match_dup 2)))]
1221790286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12218169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12219169699Skan   && (optimize_size
12220169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1222190286Sobrien  "shr{l}\t{%2, %0|%0, %2}"
1222290286Sobrien  [(set_attr "type" "ishift")
1222390286Sobrien   (set_attr "mode" "SI")])
1222490286Sobrien
12225169699Skan(define_insn "*lshrsi3_cconly"
12226169699Skan  [(set (reg FLAGS_REG)
12227169699Skan      (compare
12228169699Skan	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12229169699Skan		     (match_operand:QI 2 "const_1_to_31_operand" "I"))
12230169699Skan        (const_int 0)))
12231169699Skan   (clobber (match_scratch:SI 0 "=r"))]
12232169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12233169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12234169699Skan   && (optimize_size
12235169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12236169699Skan  "shr{l}\t{%2, %0|%0, %2}"
12237169699Skan  [(set_attr "type" "ishift")
12238169699Skan   (set_attr "mode" "SI")])
12239169699Skan
1224090286Sobrien(define_insn "*lshrsi3_cmp_zext"
12241169699Skan  [(set (reg FLAGS_REG)
1224290286Sobrien	(compare
1224390286Sobrien	  (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
12244169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1224590286Sobrien	  (const_int 0)))
1224690286Sobrien   (set (match_operand:DI 0 "register_operand" "=r")
1224790286Sobrien	(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
1224890286Sobrien  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
12249169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12250169699Skan   && (optimize_size
12251169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1225290286Sobrien  "shr{l}\t{%2, %k0|%k0, %2}"
1225390286Sobrien  [(set_attr "type" "ishift")
1225490286Sobrien   (set_attr "mode" "SI")])
1225590286Sobrien
1225690286Sobrien(define_expand "lshrhi3"
1225790286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1225890286Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
1225990286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12260169699Skan   (clobber (reg:CC FLAGS_REG))]
1226190286Sobrien  "TARGET_HIMODE_MATH"
1226290286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, HImode, operands); DONE;")
1226390286Sobrien
1226490286Sobrien(define_insn "*lshrhi3_1_one_bit"
1226550650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1226650650Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12267132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12268169699Skan   (clobber (reg:CC FLAGS_REG))]
1226990286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12270117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1227190286Sobrien  "shr{w}\t%0"
1227290286Sobrien  [(set_attr "type" "ishift")
1227390286Sobrien   (set (attr "length") 
1227490286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1227590286Sobrien	(const_string "2")
1227690286Sobrien	(const_string "*")))])
1227718334Speter
1227890286Sobrien(define_insn "*lshrhi3_1"
1227990286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1228090286Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1228190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12282169699Skan   (clobber (reg:CC FLAGS_REG))]
1228390286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1228490286Sobrien  "@
1228590286Sobrien   shr{w}\t{%2, %0|%0, %2}
1228690286Sobrien   shr{w}\t{%b2, %0|%0, %b2}"
1228790286Sobrien  [(set_attr "type" "ishift")
1228890286Sobrien   (set_attr "mode" "HI")])
1228990286Sobrien
1229090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1229190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1229290286Sobrien;; zero are optimized away.
1229390286Sobrien(define_insn "*lshrhi3_one_bit_cmp"
12294169699Skan  [(set (reg FLAGS_REG)
1229590286Sobrien	(compare
1229690286Sobrien	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12297132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1229890286Sobrien	  (const_int 0)))
1229990286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1230090286Sobrien	(lshiftrt:HI (match_dup 1) (match_dup 2)))]
1230190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12302117404Skan   && (TARGET_SHIFT1 || optimize_size)
1230390286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
1230490286Sobrien  "shr{w}\t%0"
1230590286Sobrien  [(set_attr "type" "ishift")
1230690286Sobrien   (set (attr "length") 
1230790286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1230890286Sobrien	(const_string "2")
1230990286Sobrien	(const_string "*")))])
1231090286Sobrien
12311169699Skan(define_insn "*lshrhi3_one_bit_cconly"
12312169699Skan  [(set (reg FLAGS_REG)
12313169699Skan	(compare
12314169699Skan	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12315169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12316169699Skan	  (const_int 0)))
12317169699Skan   (clobber (match_scratch:HI 0 "=r"))]
12318169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12319169699Skan   && (TARGET_SHIFT1 || optimize_size)
12320169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
12321169699Skan  "shr{w}\t%0"
12322169699Skan  [(set_attr "type" "ishift")
12323169699Skan   (set_attr "length" "2")])
12324169699Skan
1232590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1232690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1232790286Sobrien;; zero are optimized away.
1232890286Sobrien(define_insn "*lshrhi3_cmp"
12329169699Skan  [(set (reg FLAGS_REG)
1233090286Sobrien	(compare
1233190286Sobrien	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12332169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1233390286Sobrien	  (const_int 0)))
1233490286Sobrien   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1233590286Sobrien	(lshiftrt:HI (match_dup 1) (match_dup 2)))]
1233690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12337169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12338169699Skan   && (optimize_size
12339169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1234090286Sobrien  "shr{w}\t{%2, %0|%0, %2}"
1234190286Sobrien  [(set_attr "type" "ishift")
1234290286Sobrien   (set_attr "mode" "HI")])
1234390286Sobrien
12344169699Skan(define_insn "*lshrhi3_cconly"
12345169699Skan  [(set (reg FLAGS_REG)
12346169699Skan	(compare
12347169699Skan	  (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12348169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
12349169699Skan	  (const_int 0)))
12350169699Skan   (clobber (match_scratch:HI 0 "=r"))]
12351169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12352169699Skan   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
12353169699Skan   && (optimize_size
12354169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12355169699Skan  "shr{w}\t{%2, %0|%0, %2}"
12356169699Skan  [(set_attr "type" "ishift")
12357169699Skan   (set_attr "mode" "HI")])
12358169699Skan
1235990286Sobrien(define_expand "lshrqi3"
1236090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1236190286Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
1236290286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12363169699Skan   (clobber (reg:CC FLAGS_REG))]
1236490286Sobrien  "TARGET_QIMODE_MATH"
1236590286Sobrien  "ix86_expand_binary_operator (LSHIFTRT, QImode, operands); DONE;")
1236690286Sobrien
1236790286Sobrien(define_insn "*lshrqi3_1_one_bit"
1236850650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1236950650Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12370132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12371169699Skan   (clobber (reg:CC FLAGS_REG))]
1237290286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12373117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1237490286Sobrien  "shr{b}\t%0"
1237590286Sobrien  [(set_attr "type" "ishift")
1237690286Sobrien   (set (attr "length") 
1237790286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1237890286Sobrien	(const_string "2")
1237990286Sobrien	(const_string "*")))])
1238090286Sobrien
12381117404Skan(define_insn "*lshrqi3_1_one_bit_slp"
12382117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12383117404Skan	(lshiftrt:QI (match_dup 0)
12384132727Skan		     (match_operand:QI 1 "const1_operand" "")))
12385169699Skan   (clobber (reg:CC FLAGS_REG))]
12386117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12387117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12388117404Skan  "shr{b}\t%0"
12389117404Skan  [(set_attr "type" "ishift1")
12390117404Skan   (set (attr "length") 
12391117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
12392117404Skan	(const_string "2")
12393117404Skan	(const_string "*")))])
12394117404Skan
1239590286Sobrien(define_insn "*lshrqi3_1"
1239690286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1239790286Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1239890286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12399169699Skan   (clobber (reg:CC FLAGS_REG))]
1240090286Sobrien  "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
1240190286Sobrien  "@
1240290286Sobrien   shr{b}\t{%2, %0|%0, %2}
1240390286Sobrien   shr{b}\t{%b2, %0|%0, %b2}"
1240490286Sobrien  [(set_attr "type" "ishift")
1240590286Sobrien   (set_attr "mode" "QI")])
1240690286Sobrien
12407117404Skan(define_insn "*lshrqi3_1_slp"
12408117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12409117404Skan	(lshiftrt:QI (match_dup 0)
12410117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
12411169699Skan   (clobber (reg:CC FLAGS_REG))]
12412117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12413117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12414117404Skan  "@
12415117404Skan   shr{b}\t{%1, %0|%0, %1}
12416117404Skan   shr{b}\t{%b1, %0|%0, %b1}"
12417117404Skan  [(set_attr "type" "ishift1")
12418117404Skan   (set_attr "mode" "QI")])
12419117404Skan
1242090286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1242190286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1242290286Sobrien;; zero are optimized away.
1242390286Sobrien(define_insn "*lshrqi2_one_bit_cmp"
12424169699Skan  [(set (reg FLAGS_REG)
1242590286Sobrien	(compare
1242690286Sobrien	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12427132727Skan		       (match_operand:QI 2 "const1_operand" ""))
1242890286Sobrien	  (const_int 0)))
1242990286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1243090286Sobrien	(lshiftrt:QI (match_dup 1) (match_dup 2)))]
1243190286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12432117404Skan   && (TARGET_SHIFT1 || optimize_size)
1243390286Sobrien   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
1243490286Sobrien  "shr{b}\t%0"
1243590286Sobrien  [(set_attr "type" "ishift")
1243690286Sobrien   (set (attr "length") 
1243790286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1243890286Sobrien	(const_string "2")
1243990286Sobrien	(const_string "*")))])
1244090286Sobrien
12441169699Skan(define_insn "*lshrqi2_one_bit_cconly"
12442169699Skan  [(set (reg FLAGS_REG)
12443169699Skan	(compare
12444169699Skan	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12445169699Skan		       (match_operand:QI 2 "const1_operand" ""))
12446169699Skan	  (const_int 0)))
12447169699Skan   (clobber (match_scratch:QI 0 "=q"))]
12448169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12449169699Skan   && (TARGET_SHIFT1 || optimize_size)
12450169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
12451169699Skan  "shr{b}\t%0"
12452169699Skan  [(set_attr "type" "ishift")
12453169699Skan   (set_attr "length" "2")])
12454169699Skan
1245590286Sobrien;; This pattern can't accept a variable shift count, since shifts by
1245690286Sobrien;; zero don't affect the flags.  We assume that shifts by constant
1245790286Sobrien;; zero are optimized away.
1245890286Sobrien(define_insn "*lshrqi2_cmp"
12459169699Skan  [(set (reg FLAGS_REG)
1246090286Sobrien	(compare
1246190286Sobrien	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12462169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
1246390286Sobrien	  (const_int 0)))
1246490286Sobrien   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1246590286Sobrien	(lshiftrt:QI (match_dup 1) (match_dup 2)))]
1246690286Sobrien  "ix86_match_ccmode (insn, CCGOCmode)
12467169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12468169699Skan   && (optimize_size
12469169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
1247090286Sobrien  "shr{b}\t{%2, %0|%0, %2}"
1247190286Sobrien  [(set_attr "type" "ishift")
1247290286Sobrien   (set_attr "mode" "QI")])
12473169699Skan
12474169699Skan(define_insn "*lshrqi2_cconly"
12475169699Skan  [(set (reg FLAGS_REG)
12476169699Skan	(compare
12477169699Skan	  (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12478169699Skan		       (match_operand:QI 2 "const_1_to_31_operand" "I"))
12479169699Skan	  (const_int 0)))
12480169699Skan   (clobber (match_scratch:QI 0 "=q"))]
12481169699Skan  "ix86_match_ccmode (insn, CCGOCmode)
12482169699Skan   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
12483169699Skan   && (optimize_size
12484169699Skan       || !TARGET_PARTIAL_FLAG_REG_STALL)"
12485169699Skan  "shr{b}\t{%2, %0|%0, %2}"
12486169699Skan  [(set_attr "type" "ishift")
12487169699Skan   (set_attr "mode" "QI")])
1248818334Speter
1248990286Sobrien;; Rotate instructions
1249018334Speter
1249190286Sobrien(define_expand "rotldi3"
12492169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
12493169699Skan	(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
1249490286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12495169699Skan   (clobber (reg:CC FLAGS_REG))]
12496169699Skan ""
12497169699Skan{
12498169699Skan  if (TARGET_64BIT)
12499169699Skan    {
12500169699Skan      ix86_expand_binary_operator (ROTATE, DImode, operands);
12501169699Skan      DONE;
12502169699Skan    }
12503169699Skan  if (!const_1_to_31_operand (operands[2], VOIDmode))
12504169699Skan    FAIL;
12505169699Skan  emit_insn (gen_ix86_rotldi3 (operands[0], operands[1], operands[2]));
12506169699Skan  DONE;
12507169699Skan})
1250818334Speter
12509169699Skan;; Implement rotation using two double-precision shift instructions
12510169699Skan;; and a scratch register.   
12511169699Skan(define_insn_and_split "ix86_rotldi3"
12512169699Skan [(set (match_operand:DI 0 "register_operand" "=r")
12513169699Skan       (rotate:DI (match_operand:DI 1 "register_operand" "0")
12514169699Skan                  (match_operand:QI 2 "const_1_to_31_operand" "I")))
12515169699Skan  (clobber (reg:CC FLAGS_REG))
12516169699Skan  (clobber (match_scratch:SI 3 "=&r"))]
12517169699Skan "!TARGET_64BIT"
12518169699Skan "" 
12519169699Skan "&& reload_completed"
12520169699Skan [(set (match_dup 3) (match_dup 4))
12521169699Skan  (parallel
12522169699Skan   [(set (match_dup 4)
12523169699Skan         (ior:SI (ashift:SI (match_dup 4) (match_dup 2))
12524169699Skan                 (lshiftrt:SI (match_dup 5)
12525169699Skan                              (minus:QI (const_int 32) (match_dup 2)))))
12526169699Skan    (clobber (reg:CC FLAGS_REG))])
12527169699Skan  (parallel
12528169699Skan   [(set (match_dup 5)
12529169699Skan         (ior:SI (ashift:SI (match_dup 5) (match_dup 2))
12530169699Skan                 (lshiftrt:SI (match_dup 3)
12531169699Skan                              (minus:QI (const_int 32) (match_dup 2)))))
12532169699Skan    (clobber (reg:CC FLAGS_REG))])]
12533169699Skan "split_di (operands, 1, operands + 4, operands + 5);")
12534169699Skan 
1253590286Sobrien(define_insn "*rotlsi3_1_one_bit_rex64"
1253690286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1253790286Sobrien	(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12538132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12539169699Skan   (clobber (reg:CC FLAGS_REG))]
1254090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)
12541117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1254290286Sobrien  "rol{q}\t%0"
12543117404Skan  [(set_attr "type" "rotate")
1254490286Sobrien   (set (attr "length") 
1254590286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1254690286Sobrien	(const_string "2")
1254790286Sobrien	(const_string "*")))])
1254818334Speter
1254990286Sobrien(define_insn "*rotldi3_1_rex64"
1255090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1255190286Sobrien	(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1255290286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "e,c")))
12553169699Skan   (clobber (reg:CC FLAGS_REG))]
1255490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)"
1255590286Sobrien  "@
1255690286Sobrien   rol{q}\t{%2, %0|%0, %2}
1255790286Sobrien   rol{q}\t{%b2, %0|%0, %b2}"
12558117404Skan  [(set_attr "type" "rotate")
1255990286Sobrien   (set_attr "mode" "DI")])
1256090286Sobrien
1256190286Sobrien(define_expand "rotlsi3"
1256290286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1256390286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "")
1256490286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12565169699Skan   (clobber (reg:CC FLAGS_REG))]
1256618334Speter  ""
1256790286Sobrien  "ix86_expand_binary_operator (ROTATE, SImode, operands); DONE;")
1256818334Speter
1256990286Sobrien(define_insn "*rotlsi3_1_one_bit"
1257050650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1257190286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12572132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12573169699Skan   (clobber (reg:CC FLAGS_REG))]
1257490286Sobrien  "ix86_binary_operator_ok (ROTATE, SImode, operands)
12575117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1257690286Sobrien  "rol{l}\t%0"
12577117404Skan  [(set_attr "type" "rotate")
1257890286Sobrien   (set (attr "length") 
1257990286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1258090286Sobrien	(const_string "2")
1258190286Sobrien	(const_string "*")))])
1258218334Speter
1258390286Sobrien(define_insn "*rotlsi3_1_one_bit_zext"
1258490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1258590286Sobrien	(zero_extend:DI
1258690286Sobrien	  (rotate:SI (match_operand:SI 1 "register_operand" "0")
12587132727Skan		     (match_operand:QI 2 "const1_operand" ""))))
12588169699Skan   (clobber (reg:CC FLAGS_REG))]
1258990286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)
12590117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1259190286Sobrien  "rol{l}\t%k0"
12592117404Skan  [(set_attr "type" "rotate")
1259390286Sobrien   (set_attr "length" "2")])
1259418334Speter
1259590286Sobrien(define_insn "*rotlsi3_1"
1259690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1259790286Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1259890286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12599169699Skan   (clobber (reg:CC FLAGS_REG))]
1260090286Sobrien  "ix86_binary_operator_ok (ROTATE, SImode, operands)"
1260190286Sobrien  "@
1260290286Sobrien   rol{l}\t{%2, %0|%0, %2}
1260390286Sobrien   rol{l}\t{%b2, %0|%0, %b2}"
12604117404Skan  [(set_attr "type" "rotate")
1260590286Sobrien   (set_attr "mode" "SI")])
1260618334Speter
1260790286Sobrien(define_insn "*rotlsi3_1_zext"
1260890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1260990286Sobrien	(zero_extend:DI
1261090286Sobrien	  (rotate:SI (match_operand:SI 1 "register_operand" "0,0")
1261190286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12612169699Skan   (clobber (reg:CC FLAGS_REG))]
1261390286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)"
1261490286Sobrien  "@
1261590286Sobrien   rol{l}\t{%2, %k0|%k0, %2}
1261690286Sobrien   rol{l}\t{%b2, %k0|%k0, %b2}"
12617117404Skan  [(set_attr "type" "rotate")
1261890286Sobrien   (set_attr "mode" "SI")])
1261918334Speter
1262090286Sobrien(define_expand "rotlhi3"
1262190286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1262290286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "")
1262390286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12624169699Skan   (clobber (reg:CC FLAGS_REG))]
1262590286Sobrien  "TARGET_HIMODE_MATH"
1262690286Sobrien  "ix86_expand_binary_operator (ROTATE, HImode, operands); DONE;")
1262718334Speter
1262890286Sobrien(define_insn "*rotlhi3_1_one_bit"
1262990286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1263090286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12631132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12632169699Skan   (clobber (reg:CC FLAGS_REG))]
1263390286Sobrien  "ix86_binary_operator_ok (ROTATE, HImode, operands)
12634117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1263590286Sobrien  "rol{w}\t%0"
12636117404Skan  [(set_attr "type" "rotate")
1263790286Sobrien   (set (attr "length") 
1263890286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1263990286Sobrien	(const_string "2")
1264090286Sobrien	(const_string "*")))])
1264118334Speter
1264290286Sobrien(define_insn "*rotlhi3_1"
1264390286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1264490286Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1264590286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12646169699Skan   (clobber (reg:CC FLAGS_REG))]
1264790286Sobrien  "ix86_binary_operator_ok (ROTATE, HImode, operands)"
1264890286Sobrien  "@
1264990286Sobrien   rol{w}\t{%2, %0|%0, %2}
1265090286Sobrien   rol{w}\t{%b2, %0|%0, %b2}"
12651117404Skan  [(set_attr "type" "rotate")
1265290286Sobrien   (set_attr "mode" "HI")])
1265318334Speter
1265490286Sobrien(define_expand "rotlqi3"
1265590286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1265690286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "")
1265790286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))
12658169699Skan   (clobber (reg:CC FLAGS_REG))]
1265990286Sobrien  "TARGET_QIMODE_MATH"
1266090286Sobrien  "ix86_expand_binary_operator (ROTATE, QImode, operands); DONE;")
1266118334Speter
12662117404Skan(define_insn "*rotlqi3_1_one_bit_slp"
12663117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12664117404Skan	(rotate:QI (match_dup 0)
12665132727Skan		   (match_operand:QI 1 "const1_operand" "")))
12666169699Skan   (clobber (reg:CC FLAGS_REG))]
12667117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12668117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12669117404Skan  "rol{b}\t%0"
12670117404Skan  [(set_attr "type" "rotate1")
12671117404Skan   (set (attr "length") 
12672117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
12673117404Skan	(const_string "2")
12674117404Skan	(const_string "*")))])
12675117404Skan
1267690286Sobrien(define_insn "*rotlqi3_1_one_bit"
1267790286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1267890286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12679132727Skan		   (match_operand:QI 2 "const1_operand" "")))
12680169699Skan   (clobber (reg:CC FLAGS_REG))]
1268190286Sobrien  "ix86_binary_operator_ok (ROTATE, QImode, operands)
12682117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1268390286Sobrien  "rol{b}\t%0"
12684117404Skan  [(set_attr "type" "rotate")
1268590286Sobrien   (set (attr "length") 
1268690286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1268790286Sobrien	(const_string "2")
1268890286Sobrien	(const_string "*")))])
1268918334Speter
12690117404Skan(define_insn "*rotlqi3_1_slp"
12691117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12692117404Skan	(rotate:QI (match_dup 0)
12693117404Skan		   (match_operand:QI 1 "nonmemory_operand" "I,c")))
12694169699Skan   (clobber (reg:CC FLAGS_REG))]
12695117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12696117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12697117404Skan  "@
12698117404Skan   rol{b}\t{%1, %0|%0, %1}
12699117404Skan   rol{b}\t{%b1, %0|%0, %b1}"
12700117404Skan  [(set_attr "type" "rotate1")
12701117404Skan   (set_attr "mode" "QI")])
12702117404Skan
1270390286Sobrien(define_insn "*rotlqi3_1"
1270490286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1270590286Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1270690286Sobrien		   (match_operand:QI 2 "nonmemory_operand" "I,c")))
12707169699Skan   (clobber (reg:CC FLAGS_REG))]
1270890286Sobrien  "ix86_binary_operator_ok (ROTATE, QImode, operands)"
1270990286Sobrien  "@
1271090286Sobrien   rol{b}\t{%2, %0|%0, %2}
1271190286Sobrien   rol{b}\t{%b2, %0|%0, %b2}"
12712117404Skan  [(set_attr "type" "rotate")
1271390286Sobrien   (set_attr "mode" "QI")])
1271418334Speter
1271590286Sobrien(define_expand "rotrdi3"
12716169699Skan  [(set (match_operand:DI 0 "shiftdi_operand" "")
12717169699Skan	(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
12718169699Skan		   (match_operand:QI 2 "nonmemory_operand" "")))
12719169699Skan   (clobber (reg:CC FLAGS_REG))]
12720169699Skan ""
12721169699Skan{
12722169699Skan  if (TARGET_64BIT)
12723169699Skan    {
12724169699Skan      ix86_expand_binary_operator (ROTATERT, DImode, operands);
12725169699Skan      DONE;
12726169699Skan    }
12727169699Skan  if (!const_1_to_31_operand (operands[2], VOIDmode))
12728169699Skan    FAIL;
12729169699Skan  emit_insn (gen_ix86_rotrdi3 (operands[0], operands[1], operands[2]));
12730169699Skan  DONE;
12731169699Skan})
12732169699Skan  
12733169699Skan;; Implement rotation using two double-precision shift instructions
12734169699Skan;; and a scratch register.   
12735169699Skan(define_insn_and_split "ix86_rotrdi3"
12736169699Skan [(set (match_operand:DI 0 "register_operand" "=r")
12737169699Skan       (rotatert:DI (match_operand:DI 1 "register_operand" "0")
12738169699Skan                    (match_operand:QI 2 "const_1_to_31_operand" "I")))
12739169699Skan  (clobber (reg:CC FLAGS_REG))
12740169699Skan  (clobber (match_scratch:SI 3 "=&r"))]
12741169699Skan "!TARGET_64BIT"
12742169699Skan ""
12743169699Skan "&& reload_completed"
12744169699Skan [(set (match_dup 3) (match_dup 4))
12745169699Skan  (parallel
12746169699Skan   [(set (match_dup 4)
12747169699Skan         (ior:SI (ashiftrt:SI (match_dup 4) (match_dup 2))
12748169699Skan                 (ashift:SI (match_dup 5)
12749169699Skan                            (minus:QI (const_int 32) (match_dup 2)))))
12750169699Skan    (clobber (reg:CC FLAGS_REG))])
12751169699Skan  (parallel
12752169699Skan   [(set (match_dup 5)
12753169699Skan         (ior:SI (ashiftrt:SI (match_dup 5) (match_dup 2))
12754169699Skan                 (ashift:SI (match_dup 3)
12755169699Skan                            (minus:QI (const_int 32) (match_dup 2)))))
12756169699Skan    (clobber (reg:CC FLAGS_REG))])]
12757169699Skan "split_di (operands, 1, operands + 4, operands + 5);")
1275818334Speter
1275990286Sobrien(define_insn "*rotrdi3_1_one_bit_rex64"
1276090286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
1276190286Sobrien	(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0")
12762132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12763169699Skan   (clobber (reg:CC FLAGS_REG))]
1276490286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)
12765117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1276690286Sobrien  "ror{q}\t%0"
12767117404Skan  [(set_attr "type" "rotate")
1276890286Sobrien   (set (attr "length") 
1276990286Sobrien     (if_then_else (match_operand:DI 0 "register_operand" "") 
1277090286Sobrien	(const_string "2")
1277190286Sobrien	(const_string "*")))])
1277218334Speter
1277390286Sobrien(define_insn "*rotrdi3_1_rex64"
1277490286Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
1277590286Sobrien	(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
1277690286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "J,c")))
12777169699Skan   (clobber (reg:CC FLAGS_REG))]
1277890286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)"
1277990286Sobrien  "@
1278090286Sobrien   ror{q}\t{%2, %0|%0, %2}
1278190286Sobrien   ror{q}\t{%b2, %0|%0, %b2}"
12782117404Skan  [(set_attr "type" "rotate")
1278390286Sobrien   (set_attr "mode" "DI")])
1278490286Sobrien
1278590286Sobrien(define_expand "rotrsi3"
1278690286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1278790286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "")
1278890286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12789169699Skan   (clobber (reg:CC FLAGS_REG))]
1279090286Sobrien  ""
1279190286Sobrien  "ix86_expand_binary_operator (ROTATERT, SImode, operands); DONE;")
1279290286Sobrien
1279390286Sobrien(define_insn "*rotrsi3_1_one_bit"
1279450650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
1279590286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0")
12796132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12797169699Skan   (clobber (reg:CC FLAGS_REG))]
1279890286Sobrien  "ix86_binary_operator_ok (ROTATERT, SImode, operands)
12799117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1280090286Sobrien  "ror{l}\t%0"
12801117404Skan  [(set_attr "type" "rotate")
1280290286Sobrien   (set (attr "length") 
1280390286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1280490286Sobrien	(const_string "2")
1280590286Sobrien	(const_string "*")))])
1280618334Speter
1280790286Sobrien(define_insn "*rotrsi3_1_one_bit_zext"
1280890286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
1280990286Sobrien	(zero_extend:DI
1281090286Sobrien	  (rotatert:SI (match_operand:SI 1 "register_operand" "0")
12811132727Skan		       (match_operand:QI 2 "const1_operand" ""))))
12812169699Skan   (clobber (reg:CC FLAGS_REG))]
1281390286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)
12814117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1281590286Sobrien  "ror{l}\t%k0"
12816117404Skan  [(set_attr "type" "rotate")
1281790286Sobrien   (set (attr "length") 
1281890286Sobrien     (if_then_else (match_operand:SI 0 "register_operand" "") 
1281990286Sobrien	(const_string "2")
1282090286Sobrien	(const_string "*")))])
1282118334Speter
1282290286Sobrien(define_insn "*rotrsi3_1"
1282390286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
1282490286Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
1282590286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12826169699Skan   (clobber (reg:CC FLAGS_REG))]
1282790286Sobrien  "ix86_binary_operator_ok (ROTATERT, SImode, operands)"
1282890286Sobrien  "@
1282990286Sobrien   ror{l}\t{%2, %0|%0, %2}
1283090286Sobrien   ror{l}\t{%b2, %0|%0, %b2}"
12831117404Skan  [(set_attr "type" "rotate")
1283290286Sobrien   (set_attr "mode" "SI")])
1283318334Speter
1283490286Sobrien(define_insn "*rotrsi3_1_zext"
1283590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1283690286Sobrien	(zero_extend:DI
1283790286Sobrien	  (rotatert:SI (match_operand:SI 1 "register_operand" "0,0")
1283890286Sobrien		       (match_operand:QI 2 "nonmemory_operand" "I,c"))))
12839169699Skan   (clobber (reg:CC FLAGS_REG))]
1284090286Sobrien  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)"
1284190286Sobrien  "@
1284290286Sobrien   ror{l}\t{%2, %k0|%k0, %2}
1284390286Sobrien   ror{l}\t{%b2, %k0|%k0, %b2}"
12844117404Skan  [(set_attr "type" "rotate")
1284590286Sobrien   (set_attr "mode" "SI")])
1284618334Speter
1284790286Sobrien(define_expand "rotrhi3"
1284890286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1284990286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "")
1285090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12851169699Skan   (clobber (reg:CC FLAGS_REG))]
1285290286Sobrien  "TARGET_HIMODE_MATH"
1285390286Sobrien  "ix86_expand_binary_operator (ROTATERT, HImode, operands); DONE;")
1285418334Speter
1285590286Sobrien(define_insn "*rotrhi3_one_bit"
1285690286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
1285790286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0")
12858132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12859169699Skan   (clobber (reg:CC FLAGS_REG))]
1286090286Sobrien  "ix86_binary_operator_ok (ROTATERT, HImode, operands)
12861117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1286290286Sobrien  "ror{w}\t%0"
12863117404Skan  [(set_attr "type" "rotate")
1286490286Sobrien   (set (attr "length") 
1286590286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1286690286Sobrien	(const_string "2")
1286790286Sobrien	(const_string "*")))])
1286818334Speter
1286990286Sobrien(define_insn "*rotrhi3"
1287090286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
1287190286Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
1287290286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12873169699Skan   (clobber (reg:CC FLAGS_REG))]
1287490286Sobrien  "ix86_binary_operator_ok (ROTATERT, HImode, operands)"
1287590286Sobrien  "@
1287690286Sobrien   ror{w}\t{%2, %0|%0, %2}
1287790286Sobrien   ror{w}\t{%b2, %0|%0, %b2}"
12878117404Skan  [(set_attr "type" "rotate")
1287990286Sobrien   (set_attr "mode" "HI")])
1288018334Speter
1288190286Sobrien(define_expand "rotrqi3"
1288290286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1288390286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "")
1288490286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "")))
12885169699Skan   (clobber (reg:CC FLAGS_REG))]
1288690286Sobrien  "TARGET_QIMODE_MATH"
1288790286Sobrien  "ix86_expand_binary_operator (ROTATERT, QImode, operands); DONE;")
1288818334Speter
1288990286Sobrien(define_insn "*rotrqi3_1_one_bit"
1289090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1289190286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0")
12892132727Skan		     (match_operand:QI 2 "const1_operand" "")))
12893169699Skan   (clobber (reg:CC FLAGS_REG))]
1289490286Sobrien  "ix86_binary_operator_ok (ROTATERT, QImode, operands)
12895117404Skan   && (TARGET_SHIFT1 || optimize_size)"
1289690286Sobrien  "ror{b}\t%0"
12897117404Skan  [(set_attr "type" "rotate")
1289890286Sobrien   (set (attr "length") 
1289990286Sobrien     (if_then_else (match_operand 0 "register_operand" "") 
1290090286Sobrien	(const_string "2")
1290190286Sobrien	(const_string "*")))])
1290218334Speter
12903117404Skan(define_insn "*rotrqi3_1_one_bit_slp"
12904117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
12905117404Skan	(rotatert:QI (match_dup 0)
12906132727Skan		     (match_operand:QI 1 "const1_operand" "")))
12907169699Skan   (clobber (reg:CC FLAGS_REG))]
12908117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12909117404Skan   && (TARGET_SHIFT1 || optimize_size)"
12910117404Skan  "ror{b}\t%0"
12911117404Skan  [(set_attr "type" "rotate1")
12912117404Skan   (set (attr "length") 
12913117404Skan     (if_then_else (match_operand 0 "register_operand" "") 
12914117404Skan	(const_string "2")
12915117404Skan	(const_string "*")))])
12916117404Skan
1291790286Sobrien(define_insn "*rotrqi3_1"
1291890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
1291990286Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
1292090286Sobrien		     (match_operand:QI 2 "nonmemory_operand" "I,c")))
12921169699Skan   (clobber (reg:CC FLAGS_REG))]
1292290286Sobrien  "ix86_binary_operator_ok (ROTATERT, QImode, operands)"
1292390286Sobrien  "@
1292490286Sobrien   ror{b}\t{%2, %0|%0, %2}
1292590286Sobrien   ror{b}\t{%b2, %0|%0, %b2}"
12926117404Skan  [(set_attr "type" "rotate")
1292790286Sobrien   (set_attr "mode" "QI")])
12928117404Skan
12929117404Skan(define_insn "*rotrqi3_1_slp"
12930117404Skan  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
12931117404Skan	(rotatert:QI (match_dup 0)
12932117404Skan		     (match_operand:QI 1 "nonmemory_operand" "I,c")))
12933169699Skan   (clobber (reg:CC FLAGS_REG))]
12934117404Skan  "(! TARGET_PARTIAL_REG_STALL || optimize_size)
12935117404Skan   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
12936117404Skan  "@
12937117404Skan   ror{b}\t{%1, %0|%0, %1}
12938117404Skan   ror{b}\t{%b1, %0|%0, %b1}"
12939117404Skan  [(set_attr "type" "rotate1")
12940117404Skan   (set_attr "mode" "QI")])
1294190286Sobrien
1294290286Sobrien;; Bit set / bit test instructions
1294318334Speter
1294490286Sobrien(define_expand "extv"
1294590286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1294690286Sobrien	(sign_extract:SI (match_operand:SI 1 "register_operand" "")
12947169699Skan			 (match_operand:SI 2 "const8_operand" "")
12948169699Skan			 (match_operand:SI 3 "const8_operand" "")))]
1294990286Sobrien  ""
1295018334Speter{
1295190286Sobrien  /* Handle extractions from %ah et al.  */
1295290286Sobrien  if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8)
1295390286Sobrien    FAIL;
1295418334Speter
1295590286Sobrien  /* From mips.md: extract_bit_field doesn't verify that our source
1295690286Sobrien     matches the predicate, so check it again here.  */
12957169699Skan  if (! ext_register_operand (operands[1], VOIDmode))
1295890286Sobrien    FAIL;
1295990286Sobrien})
1296018334Speter
1296190286Sobrien(define_expand "extzv"
1296290286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1296390286Sobrien	(zero_extract:SI (match_operand 1 "ext_register_operand" "")
12964169699Skan			 (match_operand:SI 2 "const8_operand" "")
12965169699Skan			 (match_operand:SI 3 "const8_operand" "")))]
1296690286Sobrien  ""
1296790286Sobrien{
1296890286Sobrien  /* Handle extractions from %ah et al.  */
1296990286Sobrien  if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8)
1297090286Sobrien    FAIL;
1297118334Speter
1297290286Sobrien  /* From mips.md: extract_bit_field doesn't verify that our source
1297390286Sobrien     matches the predicate, so check it again here.  */
12974169699Skan  if (! ext_register_operand (operands[1], VOIDmode))
1297590286Sobrien    FAIL;
1297690286Sobrien})
1297718334Speter
1297890286Sobrien(define_expand "insv"
12979132727Skan  [(set (zero_extract (match_operand 0 "ext_register_operand" "")
12980169699Skan		      (match_operand 1 "const8_operand" "")
12981169699Skan		      (match_operand 2 "const8_operand" ""))
12982132727Skan        (match_operand 3 "register_operand" ""))]
1298390286Sobrien  ""
1298490286Sobrien{
12985169699Skan  /* Handle insertions to %ah et al.  */
1298690286Sobrien  if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8)
1298790286Sobrien    FAIL;
1298818334Speter
1298990286Sobrien  /* From mips.md: insert_bit_field doesn't verify that our source
1299090286Sobrien     matches the predicate, so check it again here.  */
12991169699Skan  if (! ext_register_operand (operands[0], VOIDmode))
1299290286Sobrien    FAIL;
12993132727Skan
12994132727Skan  if (TARGET_64BIT)
12995132727Skan    emit_insn (gen_movdi_insv_1_rex64 (operands[0], operands[3]));
12996132727Skan  else
12997132727Skan    emit_insn (gen_movsi_insv_1 (operands[0], operands[3]));
12998132727Skan
12999132727Skan  DONE;
1300090286Sobrien})
1300118334Speter
1300290286Sobrien;; %%% bts, btr, btc, bt.
13003169699Skan;; In general these instructions are *slow* when applied to memory,
13004169699Skan;; since they enforce atomic operation.  When applied to registers,
13005169699Skan;; it depends on the cpu implementation.  They're never faster than
13006169699Skan;; the corresponding and/ior/xor operations, so with 32-bit there's
13007169699Skan;; no point.  But in 64-bit, we can't hold the relevant immediates
13008169699Skan;; within the instruction itself, so operating on bits in the high
13009169699Skan;; 32-bits of a register becomes easier.
13010169699Skan;;
13011169699Skan;; These are slow on Nocona, but fast on Athlon64.  We do require the use
13012169699Skan;; of btrq and btcq for corner cases of post-reload expansion of absdf and
13013169699Skan;; negdf respectively, so they can never be disabled entirely.
13014169699Skan
13015169699Skan(define_insn "*btsq"
13016169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13017169699Skan			 (const_int 1)
13018169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13019169699Skan	(const_int 1))
13020169699Skan   (clobber (reg:CC FLAGS_REG))]
13021169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13022169699Skan  "bts{q} %1,%0"
13023169699Skan  [(set_attr "type" "alu1")])
13024169699Skan
13025169699Skan(define_insn "*btrq"
13026169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13027169699Skan			 (const_int 1)
13028169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13029169699Skan	(const_int 0))
13030169699Skan   (clobber (reg:CC FLAGS_REG))]
13031169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13032169699Skan  "btr{q} %1,%0"
13033169699Skan  [(set_attr "type" "alu1")])
13034169699Skan
13035169699Skan(define_insn "*btcq"
13036169699Skan  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
13037169699Skan			 (const_int 1)
13038169699Skan			 (match_operand:DI 1 "const_0_to_63_operand" ""))
13039169699Skan	(not:DI (zero_extract:DI (match_dup 0) (const_int 1) (match_dup 1))))
13040169699Skan   (clobber (reg:CC FLAGS_REG))]
13041169699Skan  "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
13042169699Skan  "btc{q} %1,%0"
13043169699Skan  [(set_attr "type" "alu1")])
13044169699Skan
13045169699Skan;; Allow Nocona to avoid these instructions if a register is available.
13046169699Skan
13047169699Skan(define_peephole2
13048169699Skan  [(match_scratch:DI 2 "r")
13049169699Skan   (parallel [(set (zero_extract:DI
13050169699Skan		     (match_operand:DI 0 "register_operand" "")
13051169699Skan		     (const_int 1)
13052169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13053169699Skan		   (const_int 1))
13054169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13055169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13056169699Skan  [(const_int 0)]
13057169699Skan{
13058169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13059169699Skan  rtx op1;
13060169699Skan
13061169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13062169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13063169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13064169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13065169699Skan  else
13066169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13067169699Skan
13068169699Skan  op1 = immed_double_const (lo, hi, DImode);
13069169699Skan  if (i >= 31)
13070169699Skan    {
13071169699Skan      emit_move_insn (operands[2], op1);
13072169699Skan      op1 = operands[2];
13073169699Skan    }
13074169699Skan
13075169699Skan  emit_insn (gen_iordi3 (operands[0], operands[0], op1));
13076169699Skan  DONE;
13077169699Skan})
13078169699Skan
13079169699Skan(define_peephole2
13080169699Skan  [(match_scratch:DI 2 "r")
13081169699Skan   (parallel [(set (zero_extract:DI
13082169699Skan		     (match_operand:DI 0 "register_operand" "")
13083169699Skan		     (const_int 1)
13084169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13085169699Skan		   (const_int 0))
13086169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13087169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13088169699Skan  [(const_int 0)]
13089169699Skan{
13090169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13091169699Skan  rtx op1;
13092169699Skan
13093169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13094169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13095169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13096169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13097169699Skan  else
13098169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13099169699Skan
13100169699Skan  op1 = immed_double_const (~lo, ~hi, DImode);
13101169699Skan  if (i >= 32)
13102169699Skan    {
13103169699Skan      emit_move_insn (operands[2], op1);
13104169699Skan      op1 = operands[2];
13105169699Skan    }
13106169699Skan
13107169699Skan  emit_insn (gen_anddi3 (operands[0], operands[0], op1));
13108169699Skan  DONE;
13109169699Skan})
13110169699Skan
13111169699Skan(define_peephole2
13112169699Skan  [(match_scratch:DI 2 "r")
13113169699Skan   (parallel [(set (zero_extract:DI
13114169699Skan		     (match_operand:DI 0 "register_operand" "")
13115169699Skan		     (const_int 1)
13116169699Skan		     (match_operand:DI 1 "const_0_to_63_operand" ""))
13117169699Skan	      (not:DI (zero_extract:DI
13118169699Skan			(match_dup 0) (const_int 1) (match_dup 1))))
13119169699Skan	      (clobber (reg:CC FLAGS_REG))])]
13120169699Skan  "TARGET_64BIT && !TARGET_USE_BT"
13121169699Skan  [(const_int 0)]
13122169699Skan{
13123169699Skan  HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
13124169699Skan  rtx op1;
13125169699Skan
13126169699Skan  if (HOST_BITS_PER_WIDE_INT >= 64)
13127169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13128169699Skan  else if (i < HOST_BITS_PER_WIDE_INT)
13129169699Skan    lo = (HOST_WIDE_INT)1 << i, hi = 0;
13130169699Skan  else
13131169699Skan    lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
13132169699Skan
13133169699Skan  op1 = immed_double_const (lo, hi, DImode);
13134169699Skan  if (i >= 31)
13135169699Skan    {
13136169699Skan      emit_move_insn (operands[2], op1);
13137169699Skan      op1 = operands[2];
13138169699Skan    }
13139169699Skan
13140169699Skan  emit_insn (gen_xordi3 (operands[0], operands[0], op1));
13141169699Skan  DONE;
13142169699Skan})
1314318334Speter
1314418334Speter;; Store-flag instructions.
1314518334Speter
1314618334Speter;; For all sCOND expanders, also expand the compare or test insn that
1314718334Speter;; generates cc0.  Generate an equality comparison if `seq' or `sne'.
1314818334Speter
1314990286Sobrien;; %%% Do the expansion to SImode.  If PII, do things the xor+setcc way
1315090286Sobrien;; to avoid partial register stalls.  Otherwise do things the setcc+movzx
1315190286Sobrien;; way, which can later delete the movzx if only QImode is needed.
1315290286Sobrien
1315318334Speter(define_expand "seq"
1315490286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13155169699Skan        (eq:QI (reg:CC FLAGS_REG) (const_int 0)))]
1315618334Speter  ""
1315790286Sobrien  "if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;")
1315818334Speter
1315918334Speter(define_expand "sne"
1316090286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13161169699Skan        (ne:QI (reg:CC FLAGS_REG) (const_int 0)))]
1316218334Speter  ""
1316390286Sobrien  "if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;")
1316418334Speter
1316518334Speter(define_expand "sgt"
1316690286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13167169699Skan        (gt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1316818334Speter  ""
1316990286Sobrien  "if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;")
1317018334Speter
1317118334Speter(define_expand "sgtu"
1317290286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13173169699Skan        (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1317418334Speter  ""
1317590286Sobrien  "if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;")
1317618334Speter
1317718334Speter(define_expand "slt"
1317890286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13179169699Skan        (lt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1318018334Speter  ""
1318190286Sobrien  "if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;")
1318218334Speter
1318318334Speter(define_expand "sltu"
1318490286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13185169699Skan        (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1318618334Speter  ""
1318790286Sobrien  "if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;")
1318818334Speter
1318918334Speter(define_expand "sge"
1319090286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13191169699Skan        (ge:QI (reg:CC FLAGS_REG) (const_int 0)))]
1319218334Speter  ""
1319390286Sobrien  "if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;")
1319418334Speter
1319518334Speter(define_expand "sgeu"
1319690286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13197169699Skan        (geu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1319818334Speter  ""
1319990286Sobrien  "if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;")
1320018334Speter
1320118334Speter(define_expand "sle"
1320290286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13203169699Skan        (le:QI (reg:CC FLAGS_REG) (const_int 0)))]
1320418334Speter  ""
1320590286Sobrien  "if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;")
1320618334Speter
1320718334Speter(define_expand "sleu"
1320890286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13209169699Skan        (leu:QI (reg:CC FLAGS_REG) (const_int 0)))]
1321018334Speter  ""
1321190286Sobrien  "if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;")
1321218334Speter
1321390286Sobrien(define_expand "sunordered"
1321490286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13215169699Skan        (unordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
1321690286Sobrien  "TARGET_80387 || TARGET_SSE"
1321790286Sobrien  "if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;")
1321852296Sobrien
1321990286Sobrien(define_expand "sordered"
1322090286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13221169699Skan        (ordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
1322290286Sobrien  "TARGET_80387"
1322390286Sobrien  "if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;")
1322490286Sobrien
1322590286Sobrien(define_expand "suneq"
1322690286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13227169699Skan        (uneq:QI (reg:CC FLAGS_REG) (const_int 0)))]
1322890286Sobrien  "TARGET_80387 || TARGET_SSE"
1322990286Sobrien  "if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;")
1323090286Sobrien
1323190286Sobrien(define_expand "sunge"
1323290286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13233169699Skan        (unge:QI (reg:CC FLAGS_REG) (const_int 0)))]
1323490286Sobrien  "TARGET_80387 || TARGET_SSE"
1323590286Sobrien  "if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;")
1323690286Sobrien
1323790286Sobrien(define_expand "sungt"
1323890286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13239169699Skan        (ungt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1324090286Sobrien  "TARGET_80387 || TARGET_SSE"
1324190286Sobrien  "if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;")
1324290286Sobrien
1324390286Sobrien(define_expand "sunle"
1324490286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13245169699Skan        (unle:QI (reg:CC FLAGS_REG) (const_int 0)))]
1324690286Sobrien  "TARGET_80387 || TARGET_SSE"
1324790286Sobrien  "if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;")
1324890286Sobrien
1324990286Sobrien(define_expand "sunlt"
1325090286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13251169699Skan        (unlt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1325290286Sobrien  "TARGET_80387 || TARGET_SSE"
1325390286Sobrien  "if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;")
1325490286Sobrien
1325590286Sobrien(define_expand "sltgt"
1325690286Sobrien  [(set (match_operand:QI 0 "register_operand" "")
13257169699Skan        (ltgt:QI (reg:CC FLAGS_REG) (const_int 0)))]
1325890286Sobrien  "TARGET_80387 || TARGET_SSE"
1325990286Sobrien  "if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;")
1326090286Sobrien
1326190286Sobrien(define_insn "*setcc_1"
1326252296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
1326390286Sobrien	(match_operator:QI 1 "ix86_comparison_operator"
13264169699Skan	  [(reg FLAGS_REG) (const_int 0)]))]
1326590286Sobrien  ""
1326690286Sobrien  "set%C1\t%0"
1326790286Sobrien  [(set_attr "type" "setcc")
1326890286Sobrien   (set_attr "mode" "QI")])
1326990286Sobrien
13270169699Skan(define_insn "*setcc_2"
1327190286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
1327290286Sobrien	(match_operator:QI 1 "ix86_comparison_operator"
13273169699Skan	  [(reg FLAGS_REG) (const_int 0)]))]
1327490286Sobrien  ""
1327590286Sobrien  "set%C1\t%0"
1327690286Sobrien  [(set_attr "type" "setcc")
1327790286Sobrien   (set_attr "mode" "QI")])
1327890286Sobrien
1327990286Sobrien;; In general it is not safe to assume too much about CCmode registers,
1328090286Sobrien;; so simplify-rtx stops when it sees a second one.  Under certain 
1328190286Sobrien;; conditions this is safe on x86, so help combine not create
1328290286Sobrien;;
1328390286Sobrien;;	seta	%al
1328490286Sobrien;;	testb	%al, %al
1328590286Sobrien;;	sete	%al
1328690286Sobrien
1328790286Sobrien(define_split 
1328890286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1328990286Sobrien	(ne:QI (match_operator 1 "ix86_comparison_operator"
13290169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1329190286Sobrien	    (const_int 0)))]
1329290286Sobrien  ""
1329390286Sobrien  [(set (match_dup 0) (match_dup 1))]
1329452296Sobrien{
1329590286Sobrien  PUT_MODE (operands[1], QImode);
1329690286Sobrien})
1329752296Sobrien
1329890286Sobrien(define_split 
1329990286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
1330090286Sobrien	(ne:QI (match_operator 1 "ix86_comparison_operator"
13301169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1330290286Sobrien	    (const_int 0)))]
1330390286Sobrien  ""
1330490286Sobrien  [(set (match_dup 0) (match_dup 1))]
1330590286Sobrien{
1330690286Sobrien  PUT_MODE (operands[1], QImode);
1330790286Sobrien})
1330852296Sobrien
1330990286Sobrien(define_split 
1331090286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1331190286Sobrien	(eq:QI (match_operator 1 "ix86_comparison_operator"
13312169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1331390286Sobrien	    (const_int 0)))]
1331490286Sobrien  ""
1331590286Sobrien  [(set (match_dup 0) (match_dup 1))]
1331690286Sobrien{
1331790286Sobrien  rtx new_op1 = copy_rtx (operands[1]);
1331890286Sobrien  operands[1] = new_op1;
1331990286Sobrien  PUT_MODE (new_op1, QImode);
13320169699Skan  PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
13321169699Skan					     GET_MODE (XEXP (new_op1, 0))));
1332290286Sobrien
1332390286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1332490286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1332590286Sobrien  if (! ix86_comparison_operator (new_op1, VOIDmode))
1332690286Sobrien    FAIL;
1332790286Sobrien})
1332890286Sobrien
1332990286Sobrien(define_split 
1333090286Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
1333190286Sobrien	(eq:QI (match_operator 1 "ix86_comparison_operator"
13332169699Skan	         [(reg FLAGS_REG) (const_int 0)])
1333390286Sobrien	    (const_int 0)))]
1333490286Sobrien  ""
1333590286Sobrien  [(set (match_dup 0) (match_dup 1))]
1333690286Sobrien{
1333790286Sobrien  rtx new_op1 = copy_rtx (operands[1]);
1333890286Sobrien  operands[1] = new_op1;
1333990286Sobrien  PUT_MODE (new_op1, QImode);
13340169699Skan  PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
13341169699Skan					     GET_MODE (XEXP (new_op1, 0))));
1334290286Sobrien
1334390286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1334490286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1334590286Sobrien  if (! ix86_comparison_operator (new_op1, VOIDmode))
1334690286Sobrien    FAIL;
1334790286Sobrien})
1334890286Sobrien
1334990286Sobrien;; The SSE store flag instructions saves 0 or 0xffffffff to the result.
1335090286Sobrien;; subsequent logical operations are used to imitate conditional moves.
1335190286Sobrien;; 0xffffffff is NaN, but not in normalized form, so we can't represent
13352169699Skan;; it directly.
1335390286Sobrien
1335490286Sobrien(define_insn "*sse_setccsf"
1335590286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1335690286Sobrien	(match_operator:SF 1 "sse_comparison_operator"
1335790286Sobrien	  [(match_operand:SF 2 "register_operand" "0")
1335890286Sobrien	   (match_operand:SF 3 "nonimmediate_operand" "xm")]))]
13359169699Skan  "TARGET_SSE"
1336090286Sobrien  "cmp%D1ss\t{%3, %0|%0, %3}"
13361117404Skan  [(set_attr "type" "ssecmp")
1336290286Sobrien   (set_attr "mode" "SF")])
1336390286Sobrien
1336490286Sobrien(define_insn "*sse_setccdf"
1336590286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1336690286Sobrien	(match_operator:DF 1 "sse_comparison_operator"
1336790286Sobrien	  [(match_operand:DF 2 "register_operand" "0")
1336890286Sobrien	   (match_operand:DF 3 "nonimmediate_operand" "Ym")]))]
13369169699Skan  "TARGET_SSE2"
1337090286Sobrien  "cmp%D1sd\t{%3, %0|%0, %3}"
13371117404Skan  [(set_attr "type" "ssecmp")
1337290286Sobrien   (set_attr "mode" "DF")])
1337318334Speter
1337418334Speter;; Basic conditional jump instructions.
1337518334Speter;; We ignore the overflow flag for signed branch instructions.
1337618334Speter
1337718334Speter;; For all bCOND expanders, also expand the compare or test insn that
13378169699Skan;; generates reg FLAGS_REG.  Generate an equality comparison if `beq' or `bne'.
1337918334Speter
1338018334Speter(define_expand "beq"
1338190286Sobrien  [(set (pc)
1338290286Sobrien	(if_then_else (match_dup 1)
1338318334Speter		      (label_ref (match_operand 0 "" ""))
1338418334Speter		      (pc)))]
1338518334Speter  ""
1338690286Sobrien  "ix86_expand_branch (EQ, operands[0]); DONE;")
1338718334Speter
1338818334Speter(define_expand "bne"
1338990286Sobrien  [(set (pc)
1339090286Sobrien	(if_then_else (match_dup 1)
1339118334Speter		      (label_ref (match_operand 0 "" ""))
1339218334Speter		      (pc)))]
1339318334Speter  ""
1339490286Sobrien  "ix86_expand_branch (NE, operands[0]); DONE;")
1339518334Speter
1339618334Speter(define_expand "bgt"
1339790286Sobrien  [(set (pc)
1339890286Sobrien	(if_then_else (match_dup 1)
1339918334Speter		      (label_ref (match_operand 0 "" ""))
1340018334Speter		      (pc)))]
1340118334Speter  ""
1340290286Sobrien  "ix86_expand_branch (GT, operands[0]); DONE;")
1340318334Speter
1340418334Speter(define_expand "bgtu"
1340590286Sobrien  [(set (pc)
1340690286Sobrien	(if_then_else (match_dup 1)
1340718334Speter		      (label_ref (match_operand 0 "" ""))
1340818334Speter		      (pc)))]
1340918334Speter  ""
1341090286Sobrien  "ix86_expand_branch (GTU, operands[0]); DONE;")
1341118334Speter
1341218334Speter(define_expand "blt"
1341390286Sobrien  [(set (pc)
1341490286Sobrien	(if_then_else (match_dup 1)
1341518334Speter		      (label_ref (match_operand 0 "" ""))
1341618334Speter		      (pc)))]
1341718334Speter  ""
1341890286Sobrien  "ix86_expand_branch (LT, operands[0]); DONE;")
1341918334Speter
1342018334Speter(define_expand "bltu"
1342190286Sobrien  [(set (pc)
1342290286Sobrien	(if_then_else (match_dup 1)
1342318334Speter		      (label_ref (match_operand 0 "" ""))
1342418334Speter		      (pc)))]
1342518334Speter  ""
1342690286Sobrien  "ix86_expand_branch (LTU, operands[0]); DONE;")
1342718334Speter
1342818334Speter(define_expand "bge"
1342990286Sobrien  [(set (pc)
1343090286Sobrien	(if_then_else (match_dup 1)
1343118334Speter		      (label_ref (match_operand 0 "" ""))
1343218334Speter		      (pc)))]
1343318334Speter  ""
1343490286Sobrien  "ix86_expand_branch (GE, operands[0]); DONE;")
1343518334Speter
1343618334Speter(define_expand "bgeu"
1343790286Sobrien  [(set (pc)
1343890286Sobrien	(if_then_else (match_dup 1)
1343918334Speter		      (label_ref (match_operand 0 "" ""))
1344018334Speter		      (pc)))]
1344118334Speter  ""
1344290286Sobrien  "ix86_expand_branch (GEU, operands[0]); DONE;")
1344318334Speter
1344418334Speter(define_expand "ble"
1344590286Sobrien  [(set (pc)
1344690286Sobrien	(if_then_else (match_dup 1)
1344718334Speter		      (label_ref (match_operand 0 "" ""))
1344818334Speter		      (pc)))]
1344918334Speter  ""
1345090286Sobrien  "ix86_expand_branch (LE, operands[0]); DONE;")
1345118334Speter
1345218334Speter(define_expand "bleu"
1345390286Sobrien  [(set (pc)
1345490286Sobrien	(if_then_else (match_dup 1)
1345518334Speter		      (label_ref (match_operand 0 "" ""))
1345618334Speter		      (pc)))]
1345718334Speter  ""
1345890286Sobrien  "ix86_expand_branch (LEU, operands[0]); DONE;")
1345918334Speter
1346090286Sobrien(define_expand "bunordered"
1346118334Speter  [(set (pc)
1346290286Sobrien	(if_then_else (match_dup 1)
1346390286Sobrien		      (label_ref (match_operand 0 "" ""))
1346418334Speter		      (pc)))]
13465169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1346690286Sobrien  "ix86_expand_branch (UNORDERED, operands[0]); DONE;")
1346718334Speter
1346890286Sobrien(define_expand "bordered"
1346990286Sobrien  [(set (pc)
1347090286Sobrien	(if_then_else (match_dup 1)
1347190286Sobrien		      (label_ref (match_operand 0 "" ""))
1347290286Sobrien		      (pc)))]
13473169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1347490286Sobrien  "ix86_expand_branch (ORDERED, operands[0]); DONE;")
1347518334Speter
1347690286Sobrien(define_expand "buneq"
1347718334Speter  [(set (pc)
1347890286Sobrien	(if_then_else (match_dup 1)
1347990286Sobrien		      (label_ref (match_operand 0 "" ""))
1348090286Sobrien		      (pc)))]
13481169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1348290286Sobrien  "ix86_expand_branch (UNEQ, operands[0]); DONE;")
1348318334Speter
1348490286Sobrien(define_expand "bunge"
1348590286Sobrien  [(set (pc)
1348690286Sobrien	(if_then_else (match_dup 1)
1348790286Sobrien		      (label_ref (match_operand 0 "" ""))
1348890286Sobrien		      (pc)))]
13489169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1349090286Sobrien  "ix86_expand_branch (UNGE, operands[0]); DONE;")
1349118334Speter
1349290286Sobrien(define_expand "bungt"
1349318334Speter  [(set (pc)
1349490286Sobrien	(if_then_else (match_dup 1)
1349590286Sobrien		      (label_ref (match_operand 0 "" ""))
1349690286Sobrien		      (pc)))]
13497169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1349890286Sobrien  "ix86_expand_branch (UNGT, operands[0]); DONE;")
1349918334Speter
1350090286Sobrien(define_expand "bunle"
1350190286Sobrien  [(set (pc)
1350290286Sobrien	(if_then_else (match_dup 1)
1350390286Sobrien		      (label_ref (match_operand 0 "" ""))
1350490286Sobrien		      (pc)))]
13505169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1350690286Sobrien  "ix86_expand_branch (UNLE, operands[0]); DONE;")
1350718334Speter
1350890286Sobrien(define_expand "bunlt"
1350990286Sobrien  [(set (pc)
1351090286Sobrien	(if_then_else (match_dup 1)
1351190286Sobrien		      (label_ref (match_operand 0 "" ""))
1351290286Sobrien		      (pc)))]
13513169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1351490286Sobrien  "ix86_expand_branch (UNLT, operands[0]); DONE;")
1351518334Speter
1351690286Sobrien(define_expand "bltgt"
1351790286Sobrien  [(set (pc)
1351890286Sobrien	(if_then_else (match_dup 1)
1351990286Sobrien		      (label_ref (match_operand 0 "" ""))
1352090286Sobrien		      (pc)))]
13521169699Skan  "TARGET_80387 || TARGET_SSE_MATH"
1352290286Sobrien  "ix86_expand_branch (LTGT, operands[0]); DONE;")
1352318334Speter
1352490286Sobrien(define_insn "*jcc_1"
1352590286Sobrien  [(set (pc)
1352690286Sobrien	(if_then_else (match_operator 1 "ix86_comparison_operator"
13527169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1352890286Sobrien		      (label_ref (match_operand 0 "" ""))
1352990286Sobrien		      (pc)))]
1353018334Speter  ""
1353190286Sobrien  "%+j%C1\t%l0"
1353290286Sobrien  [(set_attr "type" "ibr")
13533117404Skan   (set_attr "modrm" "0")
13534117404Skan   (set (attr "length")
1353590286Sobrien	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13536117404Skan				  (const_int -126))
1353790286Sobrien			      (lt (minus (match_dup 0) (pc))
13538117404Skan				  (const_int 128)))
13539117404Skan	     (const_int 2)
13540117404Skan	     (const_int 6)))])
1354118334Speter
1354290286Sobrien(define_insn "*jcc_2"
1354318334Speter  [(set (pc)
1354490286Sobrien	(if_then_else (match_operator 1 "ix86_comparison_operator"
13545169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1354690286Sobrien		      (pc)
1354790286Sobrien		      (label_ref (match_operand 0 "" ""))))]
1354818334Speter  ""
1354990286Sobrien  "%+j%c1\t%l0"
1355090286Sobrien  [(set_attr "type" "ibr")
13551117404Skan   (set_attr "modrm" "0")
13552117404Skan   (set (attr "length")
1355390286Sobrien	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13554117404Skan				  (const_int -126))
1355590286Sobrien			      (lt (minus (match_dup 0) (pc))
13556117404Skan				  (const_int 128)))
13557117404Skan	     (const_int 2)
13558117404Skan	     (const_int 6)))])
1355990286Sobrien
1356090286Sobrien;; In general it is not safe to assume too much about CCmode registers,
1356190286Sobrien;; so simplify-rtx stops when it sees a second one.  Under certain 
1356290286Sobrien;; conditions this is safe on x86, so help combine not create
1356390286Sobrien;;
1356490286Sobrien;;	seta	%al
1356590286Sobrien;;	testb	%al, %al
1356690286Sobrien;;	je	Lfoo
1356790286Sobrien
1356890286Sobrien(define_split 
1356990286Sobrien  [(set (pc)
1357090286Sobrien	(if_then_else (ne (match_operator 0 "ix86_comparison_operator"
13571169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1357290286Sobrien			  (const_int 0))
1357390286Sobrien		      (label_ref (match_operand 1 "" ""))
1357490286Sobrien		      (pc)))]
1357590286Sobrien  ""
1357690286Sobrien  [(set (pc)
1357790286Sobrien	(if_then_else (match_dup 0)
1357890286Sobrien		      (label_ref (match_dup 1))
1357990286Sobrien		      (pc)))]
1358018334Speter{
1358190286Sobrien  PUT_MODE (operands[0], VOIDmode);
1358290286Sobrien})
1358390286Sobrien  
1358490286Sobrien(define_split 
1358590286Sobrien  [(set (pc)
1358690286Sobrien	(if_then_else (eq (match_operator 0 "ix86_comparison_operator"
13587169699Skan				      [(reg FLAGS_REG) (const_int 0)])
1358890286Sobrien			  (const_int 0))
1358990286Sobrien		      (label_ref (match_operand 1 "" ""))
1359090286Sobrien		      (pc)))]
1359190286Sobrien  ""
1359290286Sobrien  [(set (pc)
1359390286Sobrien	(if_then_else (match_dup 0)
1359490286Sobrien		      (label_ref (match_dup 1))
1359590286Sobrien		      (pc)))]
1359690286Sobrien{
1359790286Sobrien  rtx new_op0 = copy_rtx (operands[0]);
1359890286Sobrien  operands[0] = new_op0;
1359990286Sobrien  PUT_MODE (new_op0, VOIDmode);
13600169699Skan  PUT_CODE (new_op0, ix86_reverse_condition (GET_CODE (new_op0),
13601169699Skan					     GET_MODE (XEXP (new_op0, 0))));
1360252296Sobrien
1360390286Sobrien  /* Make sure that (a) the CCmode we have for the flags is strong
1360490286Sobrien     enough for the reversed compare or (b) we have a valid FP compare.  */
1360590286Sobrien  if (! ix86_comparison_operator (new_op0, VOIDmode))
1360690286Sobrien    FAIL;
1360790286Sobrien})
1360852296Sobrien
1360990286Sobrien;; Define combination compare-and-branch fp compare instructions to use
1361090286Sobrien;; during early optimization.  Splitting the operation apart early makes
1361190286Sobrien;; for bad code when we want to reverse the operation.
1361218334Speter
13613169699Skan(define_insn "*fp_jcc_1_mixed"
1361490286Sobrien  [(set (pc)
1361590286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13616169699Skan			[(match_operand 1 "register_operand" "f,x")
13617169699Skan			 (match_operand 2 "nonimmediate_operand" "f,xm")])
1361890286Sobrien	  (label_ref (match_operand 3 "" ""))
1361990286Sobrien	  (pc)))
13620169699Skan   (clobber (reg:CCFP FPSR_REG))
13621169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13622169699Skan  "TARGET_MIX_SSE_I387
13623169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1362490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1362590286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1362690286Sobrien  "#")
1362718334Speter
1362890286Sobrien(define_insn "*fp_jcc_1_sse"
1362990286Sobrien  [(set (pc)
1363090286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13631169699Skan			[(match_operand 1 "register_operand" "x")
13632169699Skan			 (match_operand 2 "nonimmediate_operand" "xm")])
1363390286Sobrien	  (label_ref (match_operand 3 "" ""))
1363490286Sobrien	  (pc)))
13635169699Skan   (clobber (reg:CCFP FPSR_REG))
13636169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13637169699Skan  "TARGET_SSE_MATH
1363890286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1363990286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1364090286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1364190286Sobrien  "#")
1364218334Speter
13643169699Skan(define_insn "*fp_jcc_1_387"
1364490286Sobrien  [(set (pc)
1364590286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13646169699Skan			[(match_operand 1 "register_operand" "f")
13647169699Skan			 (match_operand 2 "register_operand" "f")])
1364890286Sobrien	  (label_ref (match_operand 3 "" ""))
1364990286Sobrien	  (pc)))
13650169699Skan   (clobber (reg:CCFP FPSR_REG))
13651169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13652169699Skan  "TARGET_CMOVE && TARGET_80387
13653169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
1365490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1365590286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1365690286Sobrien  "#")
1365718334Speter
13658169699Skan(define_insn "*fp_jcc_2_mixed"
1365918334Speter  [(set (pc)
1366090286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13661169699Skan			[(match_operand 1 "register_operand" "f,x")
13662169699Skan			 (match_operand 2 "nonimmediate_operand" "f,xm")])
1366390286Sobrien	  (pc)
1366490286Sobrien	  (label_ref (match_operand 3 "" ""))))
13665169699Skan   (clobber (reg:CCFP FPSR_REG))
13666169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13667169699Skan  "TARGET_MIX_SSE_I387
13668169699Skan   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1366990286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1367090286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1367190286Sobrien  "#")
1367218334Speter
1367390286Sobrien(define_insn "*fp_jcc_2_sse"
1367490286Sobrien  [(set (pc)
1367590286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13676169699Skan			[(match_operand 1 "register_operand" "x")
13677169699Skan			 (match_operand 2 "nonimmediate_operand" "xm")])
1367890286Sobrien	  (pc)
1367990286Sobrien	  (label_ref (match_operand 3 "" ""))))
13680169699Skan   (clobber (reg:CCFP FPSR_REG))
13681169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13682169699Skan  "TARGET_SSE_MATH
1368390286Sobrien   && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
1368490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1368590286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1368690286Sobrien  "#")
1368718334Speter
13688169699Skan(define_insn "*fp_jcc_2_387"
1368990286Sobrien  [(set (pc)
1369090286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
13691169699Skan			[(match_operand 1 "register_operand" "f")
13692169699Skan			 (match_operand 2 "register_operand" "f")])
1369390286Sobrien	  (pc)
1369490286Sobrien	  (label_ref (match_operand 3 "" ""))))
13695169699Skan   (clobber (reg:CCFP FPSR_REG))
13696169699Skan   (clobber (reg:CCFP FLAGS_REG))]
13697169699Skan  "TARGET_CMOVE && TARGET_80387
13698169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
1369990286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1370090286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1370190286Sobrien  "#")
1370218334Speter
13703169699Skan(define_insn "*fp_jcc_3_387"
1370490286Sobrien  [(set (pc)
1370590286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1370690286Sobrien			[(match_operand 1 "register_operand" "f")
1370790286Sobrien			 (match_operand 2 "nonimmediate_operand" "fm")])
1370890286Sobrien	  (label_ref (match_operand 3 "" ""))
1370990286Sobrien	  (pc)))
13710169699Skan   (clobber (reg:CCFP FPSR_REG))
13711169699Skan   (clobber (reg:CCFP FLAGS_REG))
1371290286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1371390286Sobrien  "TARGET_80387
1371490286Sobrien   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
1371590286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1371690286Sobrien   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
1371790286Sobrien   && SELECT_CC_MODE (GET_CODE (operands[0]),
1371890286Sobrien		      operands[1], operands[2]) == CCFPmode
1371990286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1372090286Sobrien  "#")
1372118334Speter
13722169699Skan(define_insn "*fp_jcc_4_387"
1372350650Sobrien  [(set (pc)
1372490286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1372590286Sobrien			[(match_operand 1 "register_operand" "f")
1372690286Sobrien			 (match_operand 2 "nonimmediate_operand" "fm")])
1372790286Sobrien	  (pc)
1372890286Sobrien	  (label_ref (match_operand 3 "" ""))))
13729169699Skan   (clobber (reg:CCFP FPSR_REG))
13730169699Skan   (clobber (reg:CCFP FLAGS_REG))
1373190286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1373290286Sobrien  "TARGET_80387
1373390286Sobrien   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
1373490286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1373590286Sobrien   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
1373690286Sobrien   && SELECT_CC_MODE (GET_CODE (operands[0]),
1373790286Sobrien		      operands[1], operands[2]) == CCFPmode
1373890286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1373990286Sobrien  "#")
1374050650Sobrien
13741169699Skan(define_insn "*fp_jcc_5_387"
1374250650Sobrien  [(set (pc)
1374390286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1374490286Sobrien			[(match_operand 1 "register_operand" "f")
1374590286Sobrien			 (match_operand 2 "register_operand" "f")])
1374690286Sobrien	  (label_ref (match_operand 3 "" ""))
1374790286Sobrien	  (pc)))
13748169699Skan   (clobber (reg:CCFP FPSR_REG))
13749169699Skan   (clobber (reg:CCFP FLAGS_REG))
1375090286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1375190286Sobrien  "TARGET_80387
1375290286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
1375390286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1375490286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1375590286Sobrien  "#")
1375650650Sobrien
13757169699Skan(define_insn "*fp_jcc_6_387"
1375850650Sobrien  [(set (pc)
1375990286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1376090286Sobrien			[(match_operand 1 "register_operand" "f")
1376190286Sobrien			 (match_operand 2 "register_operand" "f")])
1376290286Sobrien	  (pc)
1376390286Sobrien	  (label_ref (match_operand 3 "" ""))))
13764169699Skan   (clobber (reg:CCFP FPSR_REG))
13765169699Skan   (clobber (reg:CCFP FLAGS_REG))
1376690286Sobrien   (clobber (match_scratch:HI 4 "=a"))]
1376790286Sobrien  "TARGET_80387
1376890286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[1]))
1376990286Sobrien   && GET_MODE (operands[1]) == GET_MODE (operands[2])
1377090286Sobrien   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
1377190286Sobrien  "#")
1377250650Sobrien
13773169699Skan(define_insn "*fp_jcc_7_387"
13774169699Skan  [(set (pc)
13775169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13776169699Skan			[(match_operand 1 "register_operand" "f")
13777169699Skan			 (match_operand 2 "const0_operand" "X")])
13778169699Skan	  (label_ref (match_operand 3 "" ""))
13779169699Skan	  (pc)))
13780169699Skan   (clobber (reg:CCFP FPSR_REG))
13781169699Skan   (clobber (reg:CCFP FLAGS_REG))
13782169699Skan   (clobber (match_scratch:HI 4 "=a"))]
13783169699Skan  "TARGET_80387
13784169699Skan   && FLOAT_MODE_P (GET_MODE (operands[1]))
13785169699Skan   && GET_MODE (operands[1]) == GET_MODE (operands[2])
13786169699Skan   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
13787169699Skan   && SELECT_CC_MODE (GET_CODE (operands[0]),
13788169699Skan		      operands[1], operands[2]) == CCFPmode
13789169699Skan   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
13790169699Skan  "#")
13791169699Skan
13792169699Skan;; The order of operands in *fp_jcc_8_387 is forced by combine in
13793169699Skan;; simplify_comparison () function. Float operator is treated as RTX_OBJ
13794169699Skan;; with a precedence over other operators and is always put in the first
13795169699Skan;; place. Swap condition and operands to match ficom instruction.
13796169699Skan
13797169699Skan(define_insn "*fp_jcc_8<mode>_387"
13798169699Skan  [(set (pc)
13799169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13800169699Skan			[(match_operator 1 "float_operator"
13801169699Skan			   [(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")])
13802169699Skan			   (match_operand 3 "register_operand" "f,f")])
13803169699Skan	  (label_ref (match_operand 4 "" ""))
13804169699Skan	  (pc)))
13805169699Skan   (clobber (reg:CCFP FPSR_REG))
13806169699Skan   (clobber (reg:CCFP FLAGS_REG))
13807169699Skan   (clobber (match_scratch:HI 5 "=a,a"))]
13808169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
13809169699Skan   && FLOAT_MODE_P (GET_MODE (operands[3]))
13810169699Skan   && GET_MODE (operands[1]) == GET_MODE (operands[3])
13811169699Skan   && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0])))
13812169699Skan   && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
13813169699Skan   && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))"
13814169699Skan  "#")
13815169699Skan
1381690286Sobrien(define_split
1381750650Sobrien  [(set (pc)
1381890286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1381990286Sobrien			[(match_operand 1 "register_operand" "")
1382090286Sobrien			 (match_operand 2 "nonimmediate_operand" "")])
1382190286Sobrien	  (match_operand 3 "" "")
1382290286Sobrien	  (match_operand 4 "" "")))
13823169699Skan   (clobber (reg:CCFP FPSR_REG))
13824169699Skan   (clobber (reg:CCFP FLAGS_REG))]
1382590286Sobrien  "reload_completed"
1382690286Sobrien  [(const_int 0)]
1382750650Sobrien{
1382890286Sobrien  ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
13829169699Skan	                operands[3], operands[4], NULL_RTX, NULL_RTX);
1383090286Sobrien  DONE;
1383190286Sobrien})
1383250650Sobrien
1383390286Sobrien(define_split
1383450650Sobrien  [(set (pc)
1383590286Sobrien	(if_then_else (match_operator 0 "comparison_operator"
1383690286Sobrien			[(match_operand 1 "register_operand" "")
13837169699Skan			 (match_operand 2 "general_operand" "")])
1383890286Sobrien	  (match_operand 3 "" "")
1383990286Sobrien	  (match_operand 4 "" "")))
13840169699Skan   (clobber (reg:CCFP FPSR_REG))
13841169699Skan   (clobber (reg:CCFP FLAGS_REG))
1384290286Sobrien   (clobber (match_scratch:HI 5 "=a"))]
1384390286Sobrien  "reload_completed"
13844169699Skan  [(const_int 0)]
1384550650Sobrien{
1384690286Sobrien  ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
13847169699Skan	     		operands[3], operands[4], operands[5], NULL_RTX);
1384890286Sobrien  DONE;
1384990286Sobrien})
13850169699Skan
13851169699Skan(define_split
13852169699Skan  [(set (pc)
13853169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13854169699Skan			[(match_operator 1 "float_operator"
13855169699Skan			   [(match_operand:X87MODEI12 2 "memory_operand" "")])
13856169699Skan			   (match_operand 3 "register_operand" "")])
13857169699Skan	  (match_operand 4 "" "")
13858169699Skan	  (match_operand 5 "" "")))
13859169699Skan   (clobber (reg:CCFP FPSR_REG))
13860169699Skan   (clobber (reg:CCFP FLAGS_REG))
13861169699Skan   (clobber (match_scratch:HI 6 "=a"))]
13862169699Skan  "reload_completed"
13863169699Skan  [(const_int 0)]
13864169699Skan{
13865169699Skan  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[2]);
13866169699Skan  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
13867169699Skan			operands[3], operands[7],
13868169699Skan			operands[4], operands[5], operands[6], NULL_RTX);
13869169699Skan  DONE;
13870169699Skan})
13871169699Skan
13872169699Skan;; %%% Kill this when reload knows how to do it.
13873169699Skan(define_split
13874169699Skan  [(set (pc)
13875169699Skan	(if_then_else (match_operator 0 "comparison_operator"
13876169699Skan			[(match_operator 1 "float_operator"
13877169699Skan			   [(match_operand:X87MODEI12 2 "register_operand" "")])
13878169699Skan			   (match_operand 3 "register_operand" "")])
13879169699Skan	  (match_operand 4 "" "")
13880169699Skan	  (match_operand 5 "" "")))
13881169699Skan   (clobber (reg:CCFP FPSR_REG))
13882169699Skan   (clobber (reg:CCFP FLAGS_REG))
13883169699Skan   (clobber (match_scratch:HI 6 "=a"))]
13884169699Skan  "reload_completed"
13885169699Skan  [(const_int 0)]
13886169699Skan{
13887169699Skan  operands[7] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
13888169699Skan  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[7]);
13889169699Skan  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
13890169699Skan			operands[3], operands[7],
13891169699Skan			operands[4], operands[5], operands[6], operands[2]);
13892169699Skan  DONE;
13893169699Skan})
1389490286Sobrien
1389590286Sobrien;; Unconditional and other jump instructions
1389650650Sobrien
1389790286Sobrien(define_insn "jump"
1389850650Sobrien  [(set (pc)
1389990286Sobrien	(label_ref (match_operand 0 "" "")))]
1390050650Sobrien  ""
1390190286Sobrien  "jmp\t%l0"
13902117404Skan  [(set_attr "type" "ibr")
13903117404Skan   (set (attr "length")
13904117404Skan	   (if_then_else (and (ge (minus (match_dup 0) (pc))
13905117404Skan				  (const_int -126))
13906117404Skan			      (lt (minus (match_dup 0) (pc))
13907117404Skan				  (const_int 128)))
13908117404Skan	     (const_int 2)
13909117404Skan	     (const_int 5)))
13910117404Skan   (set_attr "modrm" "0")])
1391190286Sobrien
1391290286Sobrien(define_expand "indirect_jump"
1391390286Sobrien  [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))]
1391490286Sobrien  ""
1391590286Sobrien  "")
1391690286Sobrien
1391790286Sobrien(define_insn "*indirect_jump"
1391890286Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
1391990286Sobrien  "!TARGET_64BIT"
1392090286Sobrien  "jmp\t%A0"
1392190286Sobrien  [(set_attr "type" "ibr")
1392290286Sobrien   (set_attr "length_immediate" "0")])
1392390286Sobrien
1392490286Sobrien(define_insn "*indirect_jump_rtx64"
1392590286Sobrien  [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm"))]
1392690286Sobrien  "TARGET_64BIT"
1392790286Sobrien  "jmp\t%A0"
1392890286Sobrien  [(set_attr "type" "ibr")
1392990286Sobrien   (set_attr "length_immediate" "0")])
1393090286Sobrien
1393190286Sobrien(define_expand "tablejump"
1393290286Sobrien  [(parallel [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))
1393390286Sobrien	      (use (label_ref (match_operand 1 "" "")))])]
1393490286Sobrien  ""
1393550650Sobrien{
13936117404Skan  /* In PIC mode, the table entries are stored GOT (32-bit) or PC (64-bit)
13937117404Skan     relative.  Convert the relative address to an absolute address.  */
1393890286Sobrien  if (flag_pic)
1393990286Sobrien    {
13940117404Skan      rtx op0, op1;
13941117404Skan      enum rtx_code code;
13942117404Skan
1394390286Sobrien      if (TARGET_64BIT)
1394490286Sobrien	{
13945117404Skan	  code = PLUS;
13946117404Skan	  op0 = operands[0];
13947117404Skan	  op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);
1394890286Sobrien	}
13949117404Skan      else if (TARGET_MACHO || HAVE_AS_GOTOFF_IN_DATA)
13950117404Skan	{
13951117404Skan	  code = PLUS;
13952117404Skan	  op0 = operands[0];
13953117404Skan	  op1 = pic_offset_table_rtx;
13954117404Skan	}
1395590286Sobrien      else
1395690286Sobrien	{
13957117404Skan	  code = MINUS;
13958117404Skan	  op0 = pic_offset_table_rtx;
13959117404Skan	  op1 = operands[0];
1396090286Sobrien	}
13961117404Skan
13962117404Skan      operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0,
13963117404Skan					 OPTAB_DIRECT);
1396490286Sobrien    }
1396590286Sobrien})
1396650650Sobrien
1396790286Sobrien(define_insn "*tablejump_1"
1396890286Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
1396990286Sobrien   (use (label_ref (match_operand 1 "" "")))]
1397090286Sobrien  "!TARGET_64BIT"
1397190286Sobrien  "jmp\t%A0"
1397290286Sobrien  [(set_attr "type" "ibr")
1397390286Sobrien   (set_attr "length_immediate" "0")])
1397418334Speter
1397590286Sobrien(define_insn "*tablejump_1_rtx64"
1397690286Sobrien  [(set (pc) (match_operand:DI 0 "nonimmediate_operand" "rm"))
1397790286Sobrien   (use (label_ref (match_operand 1 "" "")))]
1397890286Sobrien  "TARGET_64BIT"
1397990286Sobrien  "jmp\t%A0"
1398090286Sobrien  [(set_attr "type" "ibr")
1398190286Sobrien   (set_attr "length_immediate" "0")])
1398290286Sobrien
1398390286Sobrien;; Convert setcc + movzbl to xor + setcc if operands don't overlap.
1398418334Speter
1398590286Sobrien(define_peephole2
13986169699Skan  [(set (reg FLAGS_REG) (match_operand 0 "" ""))
1398790286Sobrien   (set (match_operand:QI 1 "register_operand" "")
1398890286Sobrien	(match_operator:QI 2 "ix86_comparison_operator"
13989169699Skan	  [(reg FLAGS_REG) (const_int 0)]))
1399090286Sobrien   (set (match_operand 3 "q_regs_operand" "")
1399190286Sobrien	(zero_extend (match_dup 1)))]
1399290286Sobrien  "(peep2_reg_dead_p (3, operands[1])
1399390286Sobrien    || operands_match_p (operands[1], operands[3]))
1399490286Sobrien   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
1399590286Sobrien  [(set (match_dup 4) (match_dup 0))
1399690286Sobrien   (set (strict_low_part (match_dup 5))
1399790286Sobrien	(match_dup 2))]
1399818334Speter{
13999169699Skan  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
14000132727Skan  operands[5] = gen_lowpart (QImode, operands[3]);
1400190286Sobrien  ix86_expand_clear (operands[3]);
1400290286Sobrien})
1400318334Speter
1400490286Sobrien;; Similar, but match zero_extendhisi2_and, which adds a clobber.
1400518334Speter
1400690286Sobrien(define_peephole2
14007169699Skan  [(set (reg FLAGS_REG) (match_operand 0 "" ""))
1400890286Sobrien   (set (match_operand:QI 1 "register_operand" "")
1400990286Sobrien	(match_operator:QI 2 "ix86_comparison_operator"
14010169699Skan	  [(reg FLAGS_REG) (const_int 0)]))
1401190286Sobrien   (parallel [(set (match_operand 3 "q_regs_operand" "")
1401290286Sobrien		   (zero_extend (match_dup 1)))
14013169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1401490286Sobrien  "(peep2_reg_dead_p (3, operands[1])
1401590286Sobrien    || operands_match_p (operands[1], operands[3]))
1401690286Sobrien   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
1401790286Sobrien  [(set (match_dup 4) (match_dup 0))
1401890286Sobrien   (set (strict_low_part (match_dup 5))
1401990286Sobrien	(match_dup 2))]
1402090286Sobrien{
14021169699Skan  operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
14022132727Skan  operands[5] = gen_lowpart (QImode, operands[3]);
1402390286Sobrien  ix86_expand_clear (operands[3]);
1402490286Sobrien})
1402590286Sobrien
1402690286Sobrien;; Call instructions.
1402718334Speter
1402890286Sobrien;; The predicates normally associated with named expanders are not properly
1402990286Sobrien;; checked for calls.  This is a bug in the generic code, but it isn't that
1403090286Sobrien;; easy to fix.  Ignore it for now and be prepared to fix things up.
1403118334Speter
1403218334Speter;; Call subroutine returning no value.
1403318334Speter
1403418334Speter(define_expand "call_pop"
1403590286Sobrien  [(parallel [(call (match_operand:QI 0 "" "")
1403690286Sobrien		    (match_operand:SI 1 "" ""))
14037169699Skan	      (set (reg:SI SP_REG)
14038169699Skan		   (plus:SI (reg:SI SP_REG)
1403990286Sobrien			    (match_operand:SI 3 "" "")))])]
1404090286Sobrien  "!TARGET_64BIT"
1404118334Speter{
14042132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3], 0);
14043117404Skan  DONE;
1404490286Sobrien})
1404518334Speter
1404690286Sobrien(define_insn "*call_pop_0"
1404790286Sobrien  [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" ""))
1404890286Sobrien	 (match_operand:SI 1 "" ""))
14049169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
1405090286Sobrien			    (match_operand:SI 2 "immediate_operand" "")))]
1405190286Sobrien  "!TARGET_64BIT"
1405218334Speter{
1405390286Sobrien  if (SIBLING_CALL_P (insn))
1405490286Sobrien    return "jmp\t%P0";
1405590286Sobrien  else
1405690286Sobrien    return "call\t%P0";
1405790286Sobrien}
1405890286Sobrien  [(set_attr "type" "call")])
1405990286Sobrien  
1406090286Sobrien(define_insn "*call_pop_1"
1406190286Sobrien  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
1406290286Sobrien	 (match_operand:SI 1 "" ""))
14063169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
1406490286Sobrien			    (match_operand:SI 2 "immediate_operand" "i")))]
1406590286Sobrien  "!TARGET_64BIT"
1406690286Sobrien{
1406790286Sobrien  if (constant_call_address_operand (operands[0], Pmode))
1406818334Speter    {
1406990286Sobrien      if (SIBLING_CALL_P (insn))
1407090286Sobrien	return "jmp\t%P0";
1407190286Sobrien      else
1407290286Sobrien	return "call\t%P0";
1407318334Speter    }
1407490286Sobrien  if (SIBLING_CALL_P (insn))
1407590286Sobrien    return "jmp\t%A0";
1407618334Speter  else
1407790286Sobrien    return "call\t%A0";
1407890286Sobrien}
1407990286Sobrien  [(set_attr "type" "call")])
1408018334Speter
1408118334Speter(define_expand "call"
1408290286Sobrien  [(call (match_operand:QI 0 "" "")
1408390286Sobrien	 (match_operand 1 "" ""))
1408490286Sobrien   (use (match_operand 2 "" ""))]
1408518334Speter  ""
1408618334Speter{
14087132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 0);
14088117404Skan  DONE;
1408990286Sobrien})
1409018334Speter
14091132727Skan(define_expand "sibcall"
14092132727Skan  [(call (match_operand:QI 0 "" "")
14093132727Skan	 (match_operand 1 "" ""))
14094132727Skan   (use (match_operand 2 "" ""))]
14095132727Skan  ""
14096132727Skan{
14097132727Skan  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 1);
14098132727Skan  DONE;
14099132727Skan})
14100132727Skan
1410190286Sobrien(define_insn "*call_0"
1410290286Sobrien  [(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
1410390286Sobrien	 (match_operand 1 "" ""))]
1410418334Speter  ""
1410518334Speter{
1410690286Sobrien  if (SIBLING_CALL_P (insn))
1410790286Sobrien    return "jmp\t%P0";
1410890286Sobrien  else
1410990286Sobrien    return "call\t%P0";
1411090286Sobrien}
1411190286Sobrien  [(set_attr "type" "call")])
1411290286Sobrien
1411390286Sobrien(define_insn "*call_1"
1411490286Sobrien  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
1411590286Sobrien	 (match_operand 1 "" ""))]
14116132727Skan  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
1411790286Sobrien{
14118169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14119132727Skan    return "call\t%P0";
14120132727Skan  return "call\t%A0";
1412190286Sobrien}
1412290286Sobrien  [(set_attr "type" "call")])
1412318334Speter
14124132727Skan(define_insn "*sibcall_1"
14125132727Skan  [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,c,d,a"))
14126132727Skan	 (match_operand 1 "" ""))]
14127132727Skan  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
14128132727Skan{
14129169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14130132727Skan    return "jmp\t%P0";
14131132727Skan  return "jmp\t%A0";
14132132727Skan}
14133132727Skan  [(set_attr "type" "call")])
14134132727Skan
1413590286Sobrien(define_insn "*call_1_rex64"
1413690286Sobrien  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
1413790286Sobrien	 (match_operand 1 "" ""))]
14138132727Skan  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
1413990286Sobrien{
14140169699Skan  if (constant_call_address_operand (operands[0], Pmode))
14141132727Skan    return "call\t%P0";
14142132727Skan  return "call\t%A0";
1414390286Sobrien}
1414490286Sobrien  [(set_attr "type" "call")])
1414518334Speter
14146132727Skan(define_insn "*sibcall_1_rex64"
14147132727Skan  [(call (mem:QI (match_operand:DI 0 "constant_call_address_operand" ""))
14148132727Skan	 (match_operand 1 "" ""))]
14149132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
14150132727Skan  "jmp\t%P0"
14151132727Skan  [(set_attr "type" "call")])
14152132727Skan
14153132727Skan(define_insn "*sibcall_1_rex64_v"
14154132727Skan  [(call (mem:QI (reg:DI 40))
14155132727Skan	 (match_operand 0 "" ""))]
14156132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
14157132727Skan  "jmp\t*%%r11"
14158132727Skan  [(set_attr "type" "call")])
14159132727Skan
14160132727Skan
1416118334Speter;; Call subroutine, returning value in operand 0
1416218334Speter
1416318334Speter(define_expand "call_value_pop"
1416418334Speter  [(parallel [(set (match_operand 0 "" "")
1416590286Sobrien		   (call (match_operand:QI 1 "" "")
1416690286Sobrien			 (match_operand:SI 2 "" "")))
14167169699Skan	      (set (reg:SI SP_REG)
14168169699Skan		   (plus:SI (reg:SI SP_REG)
1416990286Sobrien			    (match_operand:SI 4 "" "")))])]
1417090286Sobrien  "!TARGET_64BIT"
1417118334Speter{
14172117404Skan  ix86_expand_call (operands[0], operands[1], operands[2],
14173132727Skan		    operands[3], operands[4], 0);
14174117404Skan  DONE;
1417590286Sobrien})
1417618334Speter
1417718334Speter(define_expand "call_value"
1417818334Speter  [(set (match_operand 0 "" "")
1417990286Sobrien	(call (match_operand:QI 1 "" "")
1418090286Sobrien	      (match_operand:SI 2 "" "")))
1418190286Sobrien   (use (match_operand:SI 3 "" ""))]
1418218334Speter  ;; Operand 2 not used on the i386.
1418318334Speter  ""
1418418334Speter{
14185132727Skan  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 0);
1418690286Sobrien  DONE;
1418790286Sobrien})
1418818334Speter
14189132727Skan(define_expand "sibcall_value"
14190132727Skan  [(set (match_operand 0 "" "")
14191132727Skan	(call (match_operand:QI 1 "" "")
14192132727Skan	      (match_operand:SI 2 "" "")))
14193132727Skan   (use (match_operand:SI 3 "" ""))]
14194132727Skan  ;; Operand 2 not used on the i386.
14195132727Skan  ""
14196132727Skan{
14197132727Skan  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 1);
14198132727Skan  DONE;
14199132727Skan})
14200132727Skan
1420118334Speter;; Call subroutine returning any type.
1420218334Speter
1420318334Speter(define_expand "untyped_call"
1420418334Speter  [(parallel [(call (match_operand 0 "" "")
1420518334Speter		    (const_int 0))
1420618334Speter	      (match_operand 1 "" "")
1420718334Speter	      (match_operand 2 "" "")])]
1420818334Speter  ""
1420918334Speter{
1421018334Speter  int i;
1421118334Speter
1421218334Speter  /* In order to give reg-stack an easier job in validating two
1421318334Speter     coprocessor registers as containing a possible return value,
1421418334Speter     simply pretend the untyped call returns a complex long double
1421518334Speter     value.  */
1421650650Sobrien
14217117404Skan  ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387
14218117404Skan		     ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL),
14219117404Skan		    operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1),
14220132727Skan		    NULL, 0);
1422118334Speter
1422218334Speter  for (i = 0; i < XVECLEN (operands[2], 0); i++)
1422318334Speter    {
1422418334Speter      rtx set = XVECEXP (operands[2], 0, i);
1422518334Speter      emit_move_insn (SET_DEST (set), SET_SRC (set));
1422618334Speter    }
1422718334Speter
1422818334Speter  /* The optimizer does not know that the call sets the function value
1422918334Speter     registers we stored in the result block.  We avoid problems by
1423018334Speter     claiming that all hard registers are used and clobbered at this
1423118334Speter     point.  */
14232117404Skan  emit_insn (gen_blockage (const0_rtx));
1423318334Speter
1423418334Speter  DONE;
1423590286Sobrien})
1423690286Sobrien
1423790286Sobrien;; Prologue and epilogue instructions
1423818334Speter
1423918334Speter;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
1424018334Speter;; all of memory.  This blocks insns from being moved across this point.
1424118334Speter
1424218334Speter(define_insn "blockage"
14243117404Skan  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_BLOCKAGE)]
1424418334Speter  ""
1424552296Sobrien  ""
1424690286Sobrien  [(set_attr "length" "0")])
1424718334Speter
1424818334Speter;; Insn emitted into the body of a function to return from a function.
1424918334Speter;; This is only done if the function's epilogue is known to be simple.
1425090286Sobrien;; See comments for ix86_can_use_return_insn_p in i386.c.
1425118334Speter
1425250650Sobrien(define_expand "return"
1425318334Speter  [(return)]
1425450650Sobrien  "ix86_can_use_return_insn_p ()"
1425590286Sobrien{
1425690286Sobrien  if (current_function_pops_args)
1425790286Sobrien    {
1425890286Sobrien      rtx popc = GEN_INT (current_function_pops_args);
1425990286Sobrien      emit_jump_insn (gen_return_pop_internal (popc));
1426090286Sobrien      DONE;
1426190286Sobrien    }
1426290286Sobrien})
1426350650Sobrien
1426450650Sobrien(define_insn "return_internal"
1426550650Sobrien  [(return)]
1426650650Sobrien  "reload_completed"
1426752296Sobrien  "ret"
1426890286Sobrien  [(set_attr "length" "1")
1426990286Sobrien   (set_attr "length_immediate" "0")
1427090286Sobrien   (set_attr "modrm" "0")])
1427150650Sobrien
14272132727Skan;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
14273132727Skan;; instruction Athlon and K8 have.
14274132727Skan
14275132727Skan(define_insn "return_internal_long"
14276132727Skan  [(return)
14277132727Skan   (unspec [(const_int 0)] UNSPEC_REP)]
14278132727Skan  "reload_completed"
14279132727Skan  "rep {;} ret"
14280132727Skan  [(set_attr "length" "1")
14281132727Skan   (set_attr "length_immediate" "0")
14282132727Skan   (set_attr "prefix_rep" "1")
14283132727Skan   (set_attr "modrm" "0")])
14284132727Skan
1428550650Sobrien(define_insn "return_pop_internal"
1428650650Sobrien  [(return)
1428750650Sobrien   (use (match_operand:SI 0 "const_int_operand" ""))]
1428850650Sobrien  "reload_completed"
1428990286Sobrien  "ret\t%0"
1429090286Sobrien  [(set_attr "length" "3")
1429190286Sobrien   (set_attr "length_immediate" "2")
1429290286Sobrien   (set_attr "modrm" "0")])
1429350650Sobrien
1429490286Sobrien(define_insn "return_indirect_internal"
1429590286Sobrien  [(return)
1429690286Sobrien   (use (match_operand:SI 0 "register_operand" "r"))]
1429790286Sobrien  "reload_completed"
1429890286Sobrien  "jmp\t%A0"
1429990286Sobrien  [(set_attr "type" "ibr")
1430090286Sobrien   (set_attr "length_immediate" "0")])
1430190286Sobrien
1430250650Sobrien(define_insn "nop"
1430350650Sobrien  [(const_int 0)]
1430450650Sobrien  ""
1430552296Sobrien  "nop"
1430690286Sobrien  [(set_attr "length" "1")
1430790286Sobrien   (set_attr "length_immediate" "0")
14308169699Skan   (set_attr "modrm" "0")])
1430950650Sobrien
14310132727Skan;; Align to 16-byte boundary, max skip in op0.  Used to avoid
14311132727Skan;; branch prediction penalty for the third jump in a 16-byte
14312132727Skan;; block on K8.
14313132727Skan
14314132727Skan(define_insn "align"
14315132727Skan  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_ALIGN)]
14316132727Skan  ""
14317132727Skan{
14318132727Skan#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
14319132727Skan  ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 4, (int)INTVAL (operands[0]));
14320132727Skan#else
14321132727Skan  /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that.
14322132727Skan     The align insn is used to avoid 3 jump instructions in the row to improve
14323169699Skan     branch prediction and the benefits hardly outweigh the cost of extra 8
14324132727Skan     nops on the average inserted by full alignment pseudo operation.  */
14325132727Skan#endif
14326132727Skan  return "";
14327132727Skan}
14328132727Skan  [(set_attr "length" "16")])
14329132727Skan
1433050650Sobrien(define_expand "prologue"
1433150650Sobrien  [(const_int 1)]
1433250650Sobrien  ""
1433390286Sobrien  "ix86_expand_prologue (); DONE;")
1433450650Sobrien
14335117404Skan(define_insn "set_got"
1433690286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
14337117404Skan	(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
14338169699Skan   (clobber (reg:CC FLAGS_REG))]
1433990286Sobrien  "!TARGET_64BIT"
14340169699Skan  { return output_set_got (operands[0], NULL_RTX); }
14341117404Skan  [(set_attr "type" "multi")
14342117404Skan   (set_attr "length" "12")])
1434350650Sobrien
14344169699Skan(define_insn "set_got_labelled"
14345169699Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14346169699Skan	(unspec:SI [(label_ref (match_operand 1 "" ""))]
14347169699Skan	 UNSPEC_SET_GOT))
14348169699Skan   (clobber (reg:CC FLAGS_REG))]
14349169699Skan  "!TARGET_64BIT"
14350169699Skan  { return output_set_got (operands[0], operands[1]); }
14351169699Skan  [(set_attr "type" "multi")
14352169699Skan   (set_attr "length" "12")])
14353169699Skan
14354169699Skan(define_insn "set_got_rex64"
14355169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14356169699Skan	(unspec:DI [(const_int 0)] UNSPEC_SET_GOT))]
14357169699Skan  "TARGET_64BIT"
14358169699Skan  "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
14359169699Skan  [(set_attr "type" "lea")
14360169699Skan   (set_attr "length" "6")])
14361169699Skan
1436250650Sobrien(define_expand "epilogue"
1436350650Sobrien  [(const_int 1)]
1436450650Sobrien  ""
1436590286Sobrien  "ix86_expand_epilogue (1); DONE;")
1436650650Sobrien
1436790286Sobrien(define_expand "sibcall_epilogue"
1436890286Sobrien  [(const_int 1)]
1436950650Sobrien  ""
1437090286Sobrien  "ix86_expand_epilogue (0); DONE;")
1437150650Sobrien
1437290286Sobrien(define_expand "eh_return"
14373117404Skan  [(use (match_operand 0 "register_operand" ""))]
1437450650Sobrien  ""
1437550650Sobrien{
14376117404Skan  rtx tmp, sa = EH_RETURN_STACKADJ_RTX, ra = operands[0];
1437750650Sobrien
1437890286Sobrien  /* Tricky bit: we write the address of the handler to which we will
1437990286Sobrien     be returning into someone else's stack frame, one word below the
1438090286Sobrien     stack address we wish to restore.  */
1438190286Sobrien  tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa);
1438290286Sobrien  tmp = plus_constant (tmp, -UNITS_PER_WORD);
1438390286Sobrien  tmp = gen_rtx_MEM (Pmode, tmp);
1438490286Sobrien  emit_move_insn (tmp, ra);
1438518334Speter
1438690286Sobrien  if (Pmode == SImode)
14387169699Skan    emit_jump_insn (gen_eh_return_si (sa));
1438890286Sobrien  else
14389169699Skan    emit_jump_insn (gen_eh_return_di (sa));
1439090286Sobrien  emit_barrier ();
1439190286Sobrien  DONE;
1439290286Sobrien})
1439318334Speter
1439490286Sobrien(define_insn_and_split "eh_return_si"
14395169699Skan  [(set (pc) 
14396169699Skan        (unspec [(match_operand:SI 0 "register_operand" "c")]
14397169699Skan	         UNSPEC_EH_RETURN))]
1439890286Sobrien  "!TARGET_64BIT"
1439990286Sobrien  "#"
1440090286Sobrien  "reload_completed"
1440190286Sobrien  [(const_int 1)]
1440290286Sobrien  "ix86_expand_epilogue (2); DONE;")
1440318334Speter
1440490286Sobrien(define_insn_and_split "eh_return_di"
14405169699Skan  [(set (pc) 
14406169699Skan        (unspec [(match_operand:DI 0 "register_operand" "c")]
14407169699Skan	         UNSPEC_EH_RETURN))]
1440890286Sobrien  "TARGET_64BIT"
1440990286Sobrien  "#"
1441090286Sobrien  "reload_completed"
1441190286Sobrien  [(const_int 1)]
1441290286Sobrien  "ix86_expand_epilogue (2); DONE;")
1441318334Speter
1441490286Sobrien(define_insn "leave"
14415169699Skan  [(set (reg:SI SP_REG) (plus:SI (reg:SI BP_REG) (const_int 4)))
14416169699Skan   (set (reg:SI BP_REG) (mem:SI (reg:SI BP_REG)))
1441790286Sobrien   (clobber (mem:BLK (scratch)))]
1441890286Sobrien  "!TARGET_64BIT"
1441990286Sobrien  "leave"
14420132727Skan  [(set_attr "type" "leave")])
1442118334Speter
1442290286Sobrien(define_insn "leave_rex64"
14423169699Skan  [(set (reg:DI SP_REG) (plus:DI (reg:DI BP_REG) (const_int 8)))
14424169699Skan   (set (reg:DI BP_REG) (mem:DI (reg:DI BP_REG)))
1442590286Sobrien   (clobber (mem:BLK (scratch)))]
1442690286Sobrien  "TARGET_64BIT"
1442790286Sobrien  "leave"
14428132727Skan  [(set_attr "type" "leave")])
1442990286Sobrien
1443090286Sobrien(define_expand "ffssi2"
14431132727Skan  [(parallel
14432132727Skan     [(set (match_operand:SI 0 "register_operand" "") 
14433132727Skan	   (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "")))
14434132727Skan      (clobber (match_scratch:SI 2 ""))
14435169699Skan      (clobber (reg:CC FLAGS_REG))])]
1443618334Speter  ""
14437132727Skan  "")
1443818334Speter
14439132727Skan(define_insn_and_split "*ffs_cmove"
14440132727Skan  [(set (match_operand:SI 0 "register_operand" "=r") 
14441132727Skan	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14442132727Skan   (clobber (match_scratch:SI 2 "=&r"))
14443169699Skan   (clobber (reg:CC FLAGS_REG))]
14444132727Skan  "TARGET_CMOVE"
14445132727Skan  "#"
14446132727Skan  "&& reload_completed"
14447132727Skan  [(set (match_dup 2) (const_int -1))
14448169699Skan   (parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
14449132727Skan	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
14450132727Skan   (set (match_dup 0) (if_then_else:SI
14451169699Skan			(eq (reg:CCZ FLAGS_REG) (const_int 0))
14452132727Skan			(match_dup 2)
14453132727Skan			(match_dup 0)))
14454132727Skan   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
14455169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14456132727Skan  "")
1445718334Speter
14458132727Skan(define_insn_and_split "*ffs_no_cmove"
14459132727Skan  [(set (match_operand:SI 0 "nonimmediate_operand" "=r") 
14460132727Skan	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14461132727Skan   (clobber (match_scratch:SI 2 "=&q"))
14462169699Skan   (clobber (reg:CC FLAGS_REG))]
14463132727Skan  ""
14464132727Skan  "#"
14465132727Skan  "reload_completed"
14466169699Skan  [(parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
14467132727Skan	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
14468132727Skan   (set (strict_low_part (match_dup 3))
14469169699Skan	(eq:QI (reg:CCZ FLAGS_REG) (const_int 0)))
14470132727Skan   (parallel [(set (match_dup 2) (neg:SI (match_dup 2)))
14471169699Skan	      (clobber (reg:CC FLAGS_REG))])
14472132727Skan   (parallel [(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 2)))
14473169699Skan	      (clobber (reg:CC FLAGS_REG))])
14474132727Skan   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
14475169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14476132727Skan{
14477132727Skan  operands[3] = gen_lowpart (QImode, operands[2]);
14478132727Skan  ix86_expand_clear (operands[2]);
1447990286Sobrien})
1448050650Sobrien
14481132727Skan(define_insn "*ffssi_1"
14482169699Skan  [(set (reg:CCZ FLAGS_REG)
14483132727Skan	(compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm")
1448490286Sobrien		     (const_int 0)))
1448590286Sobrien   (set (match_operand:SI 0 "register_operand" "=r")
14486132727Skan	(ctz:SI (match_dup 1)))]
1448718334Speter  ""
1448890286Sobrien  "bsf{l}\t{%1, %0|%0, %1}"
14489169699Skan  [(set_attr "prefix_0f" "1")])
1449018334Speter
14491169699Skan(define_expand "ffsdi2"
14492169699Skan  [(parallel
14493169699Skan     [(set (match_operand:DI 0 "register_operand" "") 
14494169699Skan	   (ffs:DI (match_operand:DI 1 "nonimmediate_operand" "")))
14495169699Skan      (clobber (match_scratch:DI 2 ""))
14496169699Skan      (clobber (reg:CC FLAGS_REG))])]
14497169699Skan  "TARGET_64BIT && TARGET_CMOVE"
14498169699Skan  "")
14499169699Skan
14500169699Skan(define_insn_and_split "*ffs_rex64"
14501169699Skan  [(set (match_operand:DI 0 "register_operand" "=r") 
14502169699Skan	(ffs:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
14503169699Skan   (clobber (match_scratch:DI 2 "=&r"))
14504169699Skan   (clobber (reg:CC FLAGS_REG))]
14505169699Skan  "TARGET_64BIT && TARGET_CMOVE"
14506169699Skan  "#"
14507169699Skan  "&& reload_completed"
14508169699Skan  [(set (match_dup 2) (const_int -1))
14509169699Skan   (parallel [(set (reg:CCZ FLAGS_REG)
14510169699Skan		   (compare:CCZ (match_dup 1) (const_int 0)))
14511169699Skan	      (set (match_dup 0) (ctz:DI (match_dup 1)))])
14512169699Skan   (set (match_dup 0) (if_then_else:DI
14513169699Skan			(eq (reg:CCZ FLAGS_REG) (const_int 0))
14514169699Skan			(match_dup 2)
14515169699Skan			(match_dup 0)))
14516169699Skan   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1)))
14517169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14518169699Skan  "")
14519169699Skan
14520169699Skan(define_insn "*ffsdi_1"
14521169699Skan  [(set (reg:CCZ FLAGS_REG)
14522169699Skan	(compare:CCZ (match_operand:DI 1 "nonimmediate_operand" "rm")
14523169699Skan		     (const_int 0)))
14524169699Skan   (set (match_operand:DI 0 "register_operand" "=r")
14525169699Skan	(ctz:DI (match_dup 1)))]
14526169699Skan  "TARGET_64BIT"
14527169699Skan  "bsf{q}\t{%1, %0|%0, %1}"
14528169699Skan  [(set_attr "prefix_0f" "1")])
14529169699Skan
14530132727Skan(define_insn "ctzsi2"
14531132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14532132727Skan	(ctz:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
14533169699Skan   (clobber (reg:CC FLAGS_REG))]
14534132727Skan  ""
14535132727Skan  "bsf{l}\t{%1, %0|%0, %1}"
14536169699Skan  [(set_attr "prefix_0f" "1")])
14537132727Skan
14538169699Skan(define_insn "ctzdi2"
14539169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14540169699Skan	(ctz:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
14541169699Skan   (clobber (reg:CC FLAGS_REG))]
14542169699Skan  "TARGET_64BIT"
14543169699Skan  "bsf{q}\t{%1, %0|%0, %1}"
14544169699Skan  [(set_attr "prefix_0f" "1")])
14545169699Skan
14546132727Skan(define_expand "clzsi2"
14547132727Skan  [(parallel
14548132727Skan     [(set (match_operand:SI 0 "register_operand" "")
14549132727Skan	   (minus:SI (const_int 31)
14550132727Skan		     (clz:SI (match_operand:SI 1 "nonimmediate_operand" ""))))
14551169699Skan      (clobber (reg:CC FLAGS_REG))])
14552132727Skan   (parallel
14553132727Skan     [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 31)))
14554169699Skan      (clobber (reg:CC FLAGS_REG))])]
14555132727Skan  ""
14556132727Skan  "")
14557132727Skan
14558132727Skan(define_insn "*bsr"
14559132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14560132727Skan	(minus:SI (const_int 31)
14561132727Skan		  (clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))))
14562169699Skan   (clobber (reg:CC FLAGS_REG))]
14563132727Skan  ""
14564132727Skan  "bsr{l}\t{%1, %0|%0, %1}"
14565169699Skan  [(set_attr "prefix_0f" "1")])
14566169699Skan
14567169699Skan(define_expand "clzdi2"
14568169699Skan  [(parallel
14569169699Skan     [(set (match_operand:DI 0 "register_operand" "")
14570169699Skan	   (minus:DI (const_int 63)
14571169699Skan		     (clz:DI (match_operand:DI 1 "nonimmediate_operand" ""))))
14572169699Skan      (clobber (reg:CC FLAGS_REG))])
14573169699Skan   (parallel
14574169699Skan     [(set (match_dup 0) (xor:DI (match_dup 0) (const_int 63)))
14575169699Skan      (clobber (reg:CC FLAGS_REG))])]
14576169699Skan  "TARGET_64BIT"
14577169699Skan  "")
14578169699Skan
14579169699Skan(define_insn "*bsr_rex64"
14580169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14581169699Skan	(minus:DI (const_int 63)
14582169699Skan		  (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))))
14583169699Skan   (clobber (reg:CC FLAGS_REG))]
14584169699Skan  "TARGET_64BIT"
14585169699Skan  "bsr{q}\t{%1, %0|%0, %1}"
14586169699Skan  [(set_attr "prefix_0f" "1")])
1458790286Sobrien
14588117404Skan;; Thread-local storage patterns for ELF.
14589117404Skan;;
14590117404Skan;; Note that these code sequences must appear exactly as shown
14591117404Skan;; in order to allow linker relaxation.
14592117404Skan
14593117404Skan(define_insn "*tls_global_dynamic_32_gnu"
14594117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14595117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14596117404Skan		    (match_operand:SI 2 "tls_symbolic_operand" "")
14597117404Skan		    (match_operand:SI 3 "call_insn_operand" "")]
14598117404Skan		    UNSPEC_TLS_GD))
14599117404Skan   (clobber (match_scratch:SI 4 "=d"))
14600117404Skan   (clobber (match_scratch:SI 5 "=c"))
14601169699Skan   (clobber (reg:CC FLAGS_REG))]
14602117404Skan  "!TARGET_64BIT && TARGET_GNU_TLS"
14603117404Skan  "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
14604117404Skan  [(set_attr "type" "multi")
14605117404Skan   (set_attr "length" "12")])
14606117404Skan
14607117404Skan(define_insn "*tls_global_dynamic_32_sun"
14608117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14609117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14610117404Skan		    (match_operand:SI 2 "tls_symbolic_operand" "")
14611117404Skan		    (match_operand:SI 3 "call_insn_operand" "")]
14612117404Skan		    UNSPEC_TLS_GD))
14613117404Skan   (clobber (match_scratch:SI 4 "=d"))
14614117404Skan   (clobber (match_scratch:SI 5 "=c"))
14615169699Skan   (clobber (reg:CC FLAGS_REG))]
14616117404Skan  "!TARGET_64BIT && TARGET_SUN_TLS"
14617117404Skan  "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
14618117404Skan	push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
14619117404Skan  [(set_attr "type" "multi")
14620117404Skan   (set_attr "length" "14")])
14621117404Skan
14622117404Skan(define_expand "tls_global_dynamic_32"
14623117404Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
14624117404Skan		   (unspec:SI
14625117404Skan		    [(match_dup 2)
14626117404Skan		     (match_operand:SI 1 "tls_symbolic_operand" "")
14627117404Skan		     (match_dup 3)]
14628117404Skan		    UNSPEC_TLS_GD))
14629117404Skan	      (clobber (match_scratch:SI 4 ""))
14630117404Skan	      (clobber (match_scratch:SI 5 ""))
14631169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14632117404Skan  ""
14633117404Skan{
14634117404Skan  if (flag_pic)
14635117404Skan    operands[2] = pic_offset_table_rtx;
14636117404Skan  else
14637117404Skan    {
14638117404Skan      operands[2] = gen_reg_rtx (Pmode);
14639117404Skan      emit_insn (gen_set_got (operands[2]));
14640117404Skan    }
14641169699Skan  if (TARGET_GNU2_TLS)
14642169699Skan    {
14643169699Skan       emit_insn (gen_tls_dynamic_gnu2_32
14644169699Skan		  (operands[0], operands[1], operands[2]));
14645169699Skan       DONE;
14646169699Skan    }
14647117404Skan  operands[3] = ix86_tls_get_addr ();
14648117404Skan})
14649117404Skan
14650117404Skan(define_insn "*tls_global_dynamic_64"
14651117404Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14652169699Skan	(call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
14653169699Skan		 (match_operand:DI 3 "" "")))
14654117404Skan   (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14655117404Skan	      UNSPEC_TLS_GD)]
14656117404Skan  "TARGET_64BIT"
14657117404Skan  ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%P2"
14658117404Skan  [(set_attr "type" "multi")
14659117404Skan   (set_attr "length" "16")])
14660117404Skan
14661117404Skan(define_expand "tls_global_dynamic_64"
14662117404Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
14663169699Skan		   (call:DI (mem:QI (match_dup 2)) (const_int 0)))
14664117404Skan	      (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14665117404Skan			 UNSPEC_TLS_GD)])]
14666117404Skan  ""
14667117404Skan{
14668169699Skan  if (TARGET_GNU2_TLS)
14669169699Skan    {
14670169699Skan       emit_insn (gen_tls_dynamic_gnu2_64
14671169699Skan		  (operands[0], operands[1]));
14672169699Skan       DONE;
14673169699Skan    }
14674117404Skan  operands[2] = ix86_tls_get_addr ();
14675117404Skan})
14676117404Skan
14677117404Skan(define_insn "*tls_local_dynamic_base_32_gnu"
14678117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14679117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14680117404Skan                    (match_operand:SI 2 "call_insn_operand" "")]
14681117404Skan		   UNSPEC_TLS_LD_BASE))
14682117404Skan   (clobber (match_scratch:SI 3 "=d"))
14683117404Skan   (clobber (match_scratch:SI 4 "=c"))
14684169699Skan   (clobber (reg:CC FLAGS_REG))]
14685117404Skan  "!TARGET_64BIT && TARGET_GNU_TLS"
14686117404Skan  "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
14687117404Skan  [(set_attr "type" "multi")
14688117404Skan   (set_attr "length" "11")])
14689117404Skan
14690117404Skan(define_insn "*tls_local_dynamic_base_32_sun"
14691117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14692117404Skan	(unspec:SI [(match_operand:SI 1 "register_operand" "b")
14693117404Skan                    (match_operand:SI 2 "call_insn_operand" "")]
14694117404Skan		   UNSPEC_TLS_LD_BASE))
14695117404Skan   (clobber (match_scratch:SI 3 "=d"))
14696117404Skan   (clobber (match_scratch:SI 4 "=c"))
14697169699Skan   (clobber (reg:CC FLAGS_REG))]
14698117404Skan  "!TARGET_64BIT && TARGET_SUN_TLS"
14699117404Skan  "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
14700117404Skan	push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
14701117404Skan  [(set_attr "type" "multi")
14702117404Skan   (set_attr "length" "13")])
14703117404Skan
14704117404Skan(define_expand "tls_local_dynamic_base_32"
14705117404Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
14706117404Skan		   (unspec:SI [(match_dup 1) (match_dup 2)]
14707117404Skan			      UNSPEC_TLS_LD_BASE))
14708117404Skan	      (clobber (match_scratch:SI 3 ""))
14709117404Skan	      (clobber (match_scratch:SI 4 ""))
14710169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14711117404Skan  ""
14712117404Skan{
14713117404Skan  if (flag_pic)
14714117404Skan    operands[1] = pic_offset_table_rtx;
14715117404Skan  else
14716117404Skan    {
14717117404Skan      operands[1] = gen_reg_rtx (Pmode);
14718117404Skan      emit_insn (gen_set_got (operands[1]));
14719117404Skan    }
14720169699Skan  if (TARGET_GNU2_TLS)
14721169699Skan    {
14722169699Skan       emit_insn (gen_tls_dynamic_gnu2_32
14723169699Skan		  (operands[0], ix86_tls_module_base (), operands[1]));
14724169699Skan       DONE;
14725169699Skan    }
14726117404Skan  operands[2] = ix86_tls_get_addr ();
14727117404Skan})
14728117404Skan
14729117404Skan(define_insn "*tls_local_dynamic_base_64"
14730117404Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14731169699Skan	(call:DI (mem:QI (match_operand:DI 1 "call_insn_operand" ""))
14732169699Skan		 (match_operand:DI 2 "" "")))
14733117404Skan   (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
14734117404Skan  "TARGET_64BIT"
14735117404Skan  "lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1"
14736117404Skan  [(set_attr "type" "multi")
14737117404Skan   (set_attr "length" "12")])
14738117404Skan
14739117404Skan(define_expand "tls_local_dynamic_base_64"
14740117404Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
14741169699Skan		   (call:DI (mem:QI (match_dup 1)) (const_int 0)))
14742117404Skan	      (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
14743117404Skan  ""
14744117404Skan{
14745169699Skan  if (TARGET_GNU2_TLS)
14746169699Skan    {
14747169699Skan       emit_insn (gen_tls_dynamic_gnu2_64
14748169699Skan		  (operands[0], ix86_tls_module_base ()));
14749169699Skan       DONE;
14750169699Skan    }
14751117404Skan  operands[1] = ix86_tls_get_addr ();
14752117404Skan})
14753117404Skan
14754117404Skan;; Local dynamic of a single variable is a lose.  Show combine how
14755117404Skan;; to convert that back to global dynamic.
14756117404Skan
14757117404Skan(define_insn_and_split "*tls_local_dynamic_32_once"
14758117404Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14759117404Skan	(plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b")
14760117404Skan			     (match_operand:SI 2 "call_insn_operand" "")]
14761117404Skan			    UNSPEC_TLS_LD_BASE)
14762117404Skan		 (const:SI (unspec:SI
14763117404Skan			    [(match_operand:SI 3 "tls_symbolic_operand" "")]
14764117404Skan			    UNSPEC_DTPOFF))))
14765117404Skan   (clobber (match_scratch:SI 4 "=d"))
14766117404Skan   (clobber (match_scratch:SI 5 "=c"))
14767169699Skan   (clobber (reg:CC FLAGS_REG))]
14768117404Skan  ""
14769117404Skan  "#"
14770117404Skan  ""
14771117404Skan  [(parallel [(set (match_dup 0)
14772117404Skan		   (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)]
14773117404Skan			      UNSPEC_TLS_GD))
14774117404Skan	      (clobber (match_dup 4))
14775117404Skan	      (clobber (match_dup 5))
14776169699Skan	      (clobber (reg:CC FLAGS_REG))])]
14777117404Skan  "")
14778132727Skan
14779132727Skan;; Load and add the thread base pointer from %gs:0.
14780132727Skan
14781132727Skan(define_insn "*load_tp_si"
14782132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14783132727Skan	(unspec:SI [(const_int 0)] UNSPEC_TP))]
14784132727Skan  "!TARGET_64BIT"
14785132727Skan  "mov{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
14786132727Skan  [(set_attr "type" "imov")
14787132727Skan   (set_attr "modrm" "0")
14788132727Skan   (set_attr "length" "7")
14789132727Skan   (set_attr "memory" "load")
14790132727Skan   (set_attr "imm_disp" "false")])
14791132727Skan
14792132727Skan(define_insn "*add_tp_si"
14793132727Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14794132727Skan	(plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
14795132727Skan		 (match_operand:SI 1 "register_operand" "0")))
14796169699Skan   (clobber (reg:CC FLAGS_REG))]
14797132727Skan  "!TARGET_64BIT"
14798132727Skan  "add{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
14799132727Skan  [(set_attr "type" "alu")
14800132727Skan   (set_attr "modrm" "0")
14801132727Skan   (set_attr "length" "7")
14802132727Skan   (set_attr "memory" "load")
14803132727Skan   (set_attr "imm_disp" "false")])
14804132727Skan
14805132727Skan(define_insn "*load_tp_di"
14806132727Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14807132727Skan	(unspec:DI [(const_int 0)] UNSPEC_TP))]
14808132727Skan  "TARGET_64BIT"
14809132727Skan  "mov{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
14810132727Skan  [(set_attr "type" "imov")
14811132727Skan   (set_attr "modrm" "0")
14812132727Skan   (set_attr "length" "7")
14813132727Skan   (set_attr "memory" "load")
14814132727Skan   (set_attr "imm_disp" "false")])
14815132727Skan
14816132727Skan(define_insn "*add_tp_di"
14817132727Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14818132727Skan	(plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP)
14819132727Skan		 (match_operand:DI 1 "register_operand" "0")))
14820169699Skan   (clobber (reg:CC FLAGS_REG))]
14821132727Skan  "TARGET_64BIT"
14822132727Skan  "add{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
14823132727Skan  [(set_attr "type" "alu")
14824132727Skan   (set_attr "modrm" "0")
14825132727Skan   (set_attr "length" "7")
14826132727Skan   (set_attr "memory" "load")
14827132727Skan   (set_attr "imm_disp" "false")])
14828169699Skan
14829169699Skan;; GNU2 TLS patterns can be split.
14830169699Skan
14831169699Skan(define_expand "tls_dynamic_gnu2_32"
14832169699Skan  [(set (match_dup 3)
14833169699Skan	(plus:SI (match_operand:SI 2 "register_operand" "")
14834169699Skan		 (const:SI
14835169699Skan		  (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")]
14836169699Skan			     UNSPEC_TLSDESC))))
14837169699Skan   (parallel
14838169699Skan    [(set (match_operand:SI 0 "register_operand" "")
14839169699Skan	  (unspec:SI [(match_dup 1) (match_dup 3)
14840169699Skan		      (match_dup 2) (reg:SI SP_REG)]
14841169699Skan		      UNSPEC_TLSDESC))
14842169699Skan     (clobber (reg:CC FLAGS_REG))])]
14843169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14844169699Skan{
14845169699Skan  operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14846169699Skan  ix86_tls_descriptor_calls_expanded_in_cfun = true;
14847169699Skan})
14848169699Skan
14849169699Skan(define_insn "*tls_dynamic_lea_32"
14850169699Skan  [(set (match_operand:SI 0 "register_operand" "=r")
14851169699Skan	(plus:SI (match_operand:SI 1 "register_operand" "b")
14852169699Skan		 (const:SI
14853169699Skan		  (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")]
14854169699Skan			      UNSPEC_TLSDESC))))]
14855169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14856169699Skan  "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}"
14857169699Skan  [(set_attr "type" "lea")
14858169699Skan   (set_attr "mode" "SI")
14859169699Skan   (set_attr "length" "6")
14860169699Skan   (set_attr "length_address" "4")])
14861169699Skan
14862169699Skan(define_insn "*tls_dynamic_call_32"
14863169699Skan  [(set (match_operand:SI 0 "register_operand" "=a")
14864169699Skan	(unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")
14865169699Skan		    (match_operand:SI 2 "register_operand" "0")
14866169699Skan		    ;; we have to make sure %ebx still points to the GOT
14867169699Skan		    (match_operand:SI 3 "register_operand" "b")
14868169699Skan		    (reg:SI SP_REG)]
14869169699Skan		   UNSPEC_TLSDESC))
14870169699Skan   (clobber (reg:CC FLAGS_REG))]
14871169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14872169699Skan  "call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}"
14873169699Skan  [(set_attr "type" "call")
14874169699Skan   (set_attr "length" "2")
14875169699Skan   (set_attr "length_address" "0")])
14876169699Skan
14877169699Skan(define_insn_and_split "*tls_dynamic_gnu2_combine_32"
14878169699Skan  [(set (match_operand:SI 0 "register_operand" "=&a")
14879169699Skan	(plus:SI
14880169699Skan	 (unspec:SI [(match_operand:SI 3 "tls_modbase_operand" "")
14881169699Skan		     (match_operand:SI 4 "" "")
14882169699Skan		     (match_operand:SI 2 "register_operand" "b")
14883169699Skan		     (reg:SI SP_REG)]
14884169699Skan		    UNSPEC_TLSDESC)
14885169699Skan	 (const:SI (unspec:SI
14886169699Skan		    [(match_operand:SI 1 "tls_symbolic_operand" "")]
14887169699Skan		    UNSPEC_DTPOFF))))
14888169699Skan   (clobber (reg:CC FLAGS_REG))]
14889169699Skan  "!TARGET_64BIT && TARGET_GNU2_TLS"
14890169699Skan  "#"
14891169699Skan  ""
14892169699Skan  [(set (match_dup 0) (match_dup 5))]
14893169699Skan{
14894169699Skan  operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14895169699Skan  emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2]));
14896169699Skan})
14897169699Skan
14898169699Skan(define_expand "tls_dynamic_gnu2_64"
14899169699Skan  [(set (match_dup 2)
14900169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14901169699Skan		   UNSPEC_TLSDESC))
14902169699Skan   (parallel
14903169699Skan    [(set (match_operand:DI 0 "register_operand" "")
14904169699Skan	  (unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)]
14905169699Skan		     UNSPEC_TLSDESC))
14906169699Skan     (clobber (reg:CC FLAGS_REG))])]
14907169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14908169699Skan{
14909169699Skan  operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14910169699Skan  ix86_tls_descriptor_calls_expanded_in_cfun = true;
14911169699Skan})
14912169699Skan
14913169699Skan(define_insn "*tls_dynamic_lea_64"
14914169699Skan  [(set (match_operand:DI 0 "register_operand" "=r")
14915169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
14916169699Skan		   UNSPEC_TLSDESC))]
14917169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14918169699Skan  "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}"
14919169699Skan  [(set_attr "type" "lea")
14920169699Skan   (set_attr "mode" "DI")
14921169699Skan   (set_attr "length" "7")
14922169699Skan   (set_attr "length_address" "4")])
14923169699Skan
14924169699Skan(define_insn "*tls_dynamic_call_64"
14925169699Skan  [(set (match_operand:DI 0 "register_operand" "=a")
14926169699Skan	(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
14927169699Skan		    (match_operand:DI 2 "register_operand" "0")
14928169699Skan		    (reg:DI SP_REG)]
14929169699Skan		   UNSPEC_TLSDESC))
14930169699Skan   (clobber (reg:CC FLAGS_REG))]
14931169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14932169699Skan  "call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}"
14933169699Skan  [(set_attr "type" "call")
14934169699Skan   (set_attr "length" "2")
14935169699Skan   (set_attr "length_address" "0")])
14936169699Skan
14937169699Skan(define_insn_and_split "*tls_dynamic_gnu2_combine_64"
14938169699Skan  [(set (match_operand:DI 0 "register_operand" "=&a")
14939169699Skan	(plus:DI
14940169699Skan	 (unspec:DI [(match_operand:DI 2 "tls_modbase_operand" "")
14941169699Skan		     (match_operand:DI 3 "" "")
14942169699Skan		     (reg:DI SP_REG)]
14943169699Skan		    UNSPEC_TLSDESC)
14944169699Skan	 (const:DI (unspec:DI
14945169699Skan		    [(match_operand:DI 1 "tls_symbolic_operand" "")]
14946169699Skan		    UNSPEC_DTPOFF))))
14947169699Skan   (clobber (reg:CC FLAGS_REG))]
14948169699Skan  "TARGET_64BIT && TARGET_GNU2_TLS"
14949169699Skan  "#"
14950169699Skan  ""
14951169699Skan  [(set (match_dup 0) (match_dup 4))]
14952169699Skan{
14953169699Skan  operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
14954169699Skan  emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
14955169699Skan})
14956169699Skan
14957169699Skan;;
14958117404Skan
1495990286Sobrien;; These patterns match the binary 387 instructions for addM3, subM3,
1496090286Sobrien;; mulM3 and divM3.  There are three patterns for each of DFmode and
1496190286Sobrien;; SFmode.  The first is the normal insn, the second the same insn but
1496290286Sobrien;; with one operand a conversion, and the third the same insn but with
1496390286Sobrien;; the other operand a conversion.  The conversion may be SFmode or
1496490286Sobrien;; SImode if the target mode DFmode, but only SImode if the target mode
1496590286Sobrien;; is SFmode.
1496618334Speter
1496790286Sobrien;; Gcc is slightly more smart about handling normal two address instructions
1496890286Sobrien;; so use special patterns for add and mull.
1496918334Speter
14970169699Skan(define_insn "*fop_sf_comm_mixed"
14971169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,x")
1497290286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1497396294Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "%0,0")
14974169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))]
14975169699Skan  "TARGET_MIX_SSE_I387
14976169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1497796294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1497890286Sobrien  "* return output_387_binary_op (insn, operands);"
1497990286Sobrien  [(set (attr "type") 
1498090286Sobrien	(if_then_else (eq_attr "alternative" "1")
1498190286Sobrien	   (if_then_else (match_operand:SF 3 "mult_operator" "") 
14982117404Skan	      (const_string "ssemul")
14983117404Skan	      (const_string "sseadd"))
14984117404Skan	   (if_then_else (match_operand:SF 3 "mult_operator" "") 
1498590286Sobrien	      (const_string "fmul")
1498690286Sobrien	      (const_string "fop"))))
1498790286Sobrien   (set_attr "mode" "SF")])
1498818334Speter
1498990286Sobrien(define_insn "*fop_sf_comm_sse"
1499090286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1499190286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1499296294Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "%0")
1499390286Sobrien			 (match_operand:SF 2 "nonimmediate_operand" "xm")]))]
14994169699Skan  "TARGET_SSE_MATH
14995169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1499696294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1499790286Sobrien  "* return output_387_binary_op (insn, operands);"
14998117404Skan  [(set (attr "type") 
14999117404Skan        (if_then_else (match_operand:SF 3 "mult_operator" "") 
15000117404Skan	   (const_string "ssemul")
15001117404Skan	   (const_string "sseadd")))
1500290286Sobrien   (set_attr "mode" "SF")])
1500318334Speter
15004169699Skan(define_insn "*fop_sf_comm_i387"
15005169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
15006169699Skan	(match_operator:SF 3 "binary_fp_operator"
15007169699Skan			[(match_operand:SF 1 "nonimmediate_operand" "%0")
15008169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm")]))]
15009169699Skan  "TARGET_80387
15010169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1501196294Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1501290286Sobrien  "* return output_387_binary_op (insn, operands);"
1501390286Sobrien  [(set (attr "type") 
1501490286Sobrien	(if_then_else (match_operand:SF 3 "mult_operator" "") 
1501590286Sobrien	   (const_string "fmul")
1501690286Sobrien	   (const_string "fop")))
1501790286Sobrien   (set_attr "mode" "SF")])
1501818334Speter
15019169699Skan(define_insn "*fop_sf_1_mixed"
1502090286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f,x")
1502190286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1502290286Sobrien			[(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
15023169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))]
15024169699Skan  "TARGET_MIX_SSE_I387
15025169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
1502690286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1502790286Sobrien  "* return output_387_binary_op (insn, operands);"
1502890286Sobrien  [(set (attr "type") 
15029117404Skan        (cond [(and (eq_attr "alternative" "2")
15030117404Skan	            (match_operand:SF 3 "mult_operator" ""))
15031117404Skan                 (const_string "ssemul")
15032117404Skan	       (and (eq_attr "alternative" "2")
15033117404Skan	            (match_operand:SF 3 "div_operator" ""))
15034117404Skan                 (const_string "ssediv")
15035117404Skan	       (eq_attr "alternative" "2")
15036117404Skan                 (const_string "sseadd")
1503790286Sobrien	       (match_operand:SF 3 "mult_operator" "") 
1503890286Sobrien                 (const_string "fmul")
1503990286Sobrien               (match_operand:SF 3 "div_operator" "") 
1504090286Sobrien                 (const_string "fdiv")
1504190286Sobrien              ]
1504290286Sobrien              (const_string "fop")))
1504390286Sobrien   (set_attr "mode" "SF")])
1504418334Speter
1504590286Sobrien(define_insn "*fop_sf_1_sse"
1504690286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1504790286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1504890286Sobrien			[(match_operand:SF 1 "register_operand" "0")
1504990286Sobrien			 (match_operand:SF 2 "nonimmediate_operand" "xm")]))]
1505090286Sobrien  "TARGET_SSE_MATH
15051169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1505290286Sobrien  "* return output_387_binary_op (insn, operands);"
15053117404Skan  [(set (attr "type") 
15054117404Skan        (cond [(match_operand:SF 3 "mult_operator" "")
15055117404Skan                 (const_string "ssemul")
15056117404Skan	       (match_operand:SF 3 "div_operator" "")
15057117404Skan                 (const_string "ssediv")
15058117404Skan              ]
15059117404Skan              (const_string "sseadd")))
1506090286Sobrien   (set_attr "mode" "SF")])
1506118334Speter
15062169699Skan;; This pattern is not fully shadowed by the pattern above.
15063169699Skan(define_insn "*fop_sf_1_i387"
15064169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f")
15065169699Skan	(match_operator:SF 3 "binary_fp_operator"
15066169699Skan			[(match_operand:SF 1 "nonimmediate_operand" "0,fm")
15067169699Skan			 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
15068169699Skan  "TARGET_80387 && !TARGET_SSE_MATH
15069169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
15070169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15071169699Skan  "* return output_387_binary_op (insn, operands);"
15072169699Skan  [(set (attr "type") 
15073169699Skan        (cond [(match_operand:SF 3 "mult_operator" "") 
15074169699Skan                 (const_string "fmul")
15075169699Skan               (match_operand:SF 3 "div_operator" "") 
15076169699Skan                 (const_string "fdiv")
15077169699Skan              ]
15078169699Skan              (const_string "fop")))
15079169699Skan   (set_attr "mode" "SF")])
15080169699Skan
1508190286Sobrien;; ??? Add SSE splitters for these!
15082169699Skan(define_insn "*fop_sf_2<mode>_i387"
1508390286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
1508490286Sobrien	(match_operator:SF 3 "binary_fp_operator"
15085169699Skan	  [(float:SF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1508690286Sobrien	   (match_operand:SF 2 "register_operand" "0,0")]))]
15087169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
1508890286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1508990286Sobrien  [(set (attr "type") 
1509090286Sobrien        (cond [(match_operand:SF 3 "mult_operator" "") 
1509190286Sobrien                 (const_string "fmul")
1509290286Sobrien               (match_operand:SF 3 "div_operator" "") 
1509390286Sobrien                 (const_string "fdiv")
1509490286Sobrien              ]
1509590286Sobrien              (const_string "fop")))
1509690286Sobrien   (set_attr "fp_int_src" "true")
15097169699Skan   (set_attr "mode" "<MODE>")])
1509818334Speter
15099169699Skan(define_insn "*fop_sf_3<mode>_i387"
1510090286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
1510190286Sobrien	(match_operator:SF 3 "binary_fp_operator"
1510290286Sobrien	  [(match_operand:SF 1 "register_operand" "0,0")
15103169699Skan	   (float:SF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15104169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
1510590286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1510690286Sobrien  [(set (attr "type") 
1510790286Sobrien        (cond [(match_operand:SF 3 "mult_operator" "") 
1510890286Sobrien                 (const_string "fmul")
1510990286Sobrien               (match_operand:SF 3 "div_operator" "") 
1511090286Sobrien                 (const_string "fdiv")
1511190286Sobrien              ]
1511290286Sobrien              (const_string "fop")))
1511390286Sobrien   (set_attr "fp_int_src" "true")
15114169699Skan   (set_attr "mode" "<MODE>")])
1511518334Speter
15116169699Skan(define_insn "*fop_df_comm_mixed"
15117169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,Y")
1511890286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15119169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0,0")
15120169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))]
15121169699Skan  "TARGET_SSE2 && TARGET_MIX_SSE_I387
15122169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
1512390286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1512490286Sobrien  "* return output_387_binary_op (insn, operands);"
1512590286Sobrien  [(set (attr "type") 
15126169699Skan	(if_then_else (eq_attr "alternative" "1")
15127169699Skan	   (if_then_else (match_operand:DF 3 "mult_operator" "") 
15128169699Skan	      (const_string "ssemul")
15129169699Skan	      (const_string "sseadd"))
15130169699Skan	   (if_then_else (match_operand:DF 3 "mult_operator" "") 
15131169699Skan	      (const_string "fmul")
15132169699Skan	      (const_string "fop"))))
1513390286Sobrien   (set_attr "mode" "DF")])
1513418334Speter
15135169699Skan(define_insn "*fop_df_comm_sse"
15136169699Skan  [(set (match_operand:DF 0 "register_operand" "=Y")
15137169699Skan	(match_operator:DF 3 "binary_fp_operator"
15138169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0")
15139169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
15140169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH
15141169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
15142169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15143169699Skan  "* return output_387_binary_op (insn, operands);"
15144169699Skan  [(set (attr "type") 
15145169699Skan        (if_then_else (match_operand:DF 3 "mult_operator" "") 
15146169699Skan	   (const_string "ssemul")
15147169699Skan	   (const_string "sseadd")))
15148169699Skan   (set_attr "mode" "DF")])
1514918334Speter
15150169699Skan(define_insn "*fop_df_comm_i387"
15151169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
1515290286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15153169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "%0")
15154169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm")]))]
15155169699Skan  "TARGET_80387
15156169699Skan   && COMMUTATIVE_ARITH_P (operands[3])
15157169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15158169699Skan  "* return output_387_binary_op (insn, operands);"
15159169699Skan  [(set (attr "type") 
15160169699Skan	(if_then_else (match_operand:DF 3 "mult_operator" "") 
15161169699Skan	   (const_string "fmul")
15162169699Skan	   (const_string "fop")))
15163169699Skan   (set_attr "mode" "DF")])
15164169699Skan
15165169699Skan(define_insn "*fop_df_1_mixed"
15166169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,Y")
15167169699Skan	(match_operator:DF 3 "binary_fp_operator"
1516890286Sobrien			[(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
15169169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))]
15170169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
15171169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
1517290286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1517390286Sobrien  "* return output_387_binary_op (insn, operands);"
1517490286Sobrien  [(set (attr "type") 
15175117404Skan        (cond [(and (eq_attr "alternative" "2")
15176169699Skan	            (match_operand:DF 3 "mult_operator" ""))
15177117404Skan                 (const_string "ssemul")
15178117404Skan	       (and (eq_attr "alternative" "2")
15179169699Skan	            (match_operand:DF 3 "div_operator" ""))
15180117404Skan                 (const_string "ssediv")
15181117404Skan	       (eq_attr "alternative" "2")
15182117404Skan                 (const_string "sseadd")
1518390286Sobrien	       (match_operand:DF 3 "mult_operator" "") 
1518490286Sobrien                 (const_string "fmul")
1518590286Sobrien               (match_operand:DF 3 "div_operator" "") 
1518690286Sobrien                 (const_string "fdiv")
1518790286Sobrien              ]
1518890286Sobrien              (const_string "fop")))
1518990286Sobrien   (set_attr "mode" "DF")])
1519018334Speter
1519190286Sobrien(define_insn "*fop_df_1_sse"
1519290286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1519390286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1519490286Sobrien			[(match_operand:DF 1 "register_operand" "0")
1519590286Sobrien			 (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
1519690286Sobrien  "TARGET_SSE2 && TARGET_SSE_MATH
15197169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1519890286Sobrien  "* return output_387_binary_op (insn, operands);"
15199117404Skan  [(set_attr "mode" "DF")
15200117404Skan   (set (attr "type") 
15201169699Skan        (cond [(match_operand:DF 3 "mult_operator" "")
15202117404Skan                 (const_string "ssemul")
15203169699Skan	       (match_operand:DF 3 "div_operator" "")
15204117404Skan                 (const_string "ssediv")
15205117404Skan              ]
15206117404Skan              (const_string "sseadd")))])
1520718334Speter
15208169699Skan;; This pattern is not fully shadowed by the pattern above.
15209169699Skan(define_insn "*fop_df_1_i387"
15210169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
15211169699Skan	(match_operator:DF 3 "binary_fp_operator"
15212169699Skan			[(match_operand:DF 1 "nonimmediate_operand" "0,fm")
15213169699Skan			 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
15214169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
15215169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])
15216169699Skan   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
15217169699Skan  "* return output_387_binary_op (insn, operands);"
15218169699Skan  [(set (attr "type") 
15219169699Skan        (cond [(match_operand:DF 3 "mult_operator" "") 
15220169699Skan                 (const_string "fmul")
15221169699Skan               (match_operand:DF 3 "div_operator" "")
15222169699Skan                 (const_string "fdiv")
15223169699Skan              ]
15224169699Skan              (const_string "fop")))
15225169699Skan   (set_attr "mode" "DF")])
15226169699Skan
1522790286Sobrien;; ??? Add SSE splitters for these!
15228169699Skan(define_insn "*fop_df_2<mode>_i387"
1522990286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1523090286Sobrien	(match_operator:DF 3 "binary_fp_operator"
15231169699Skan	   [(float:DF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1523290286Sobrien	    (match_operand:DF 2 "register_operand" "0,0")]))]
15233169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
15234169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1523590286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1523690286Sobrien  [(set (attr "type") 
1523790286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1523890286Sobrien                 (const_string "fmul")
1523990286Sobrien               (match_operand:DF 3 "div_operator" "") 
1524090286Sobrien                 (const_string "fdiv")
1524190286Sobrien              ]
1524290286Sobrien              (const_string "fop")))
1524390286Sobrien   (set_attr "fp_int_src" "true")
15244169699Skan   (set_attr "mode" "<MODE>")])
1524518334Speter
15246169699Skan(define_insn "*fop_df_3<mode>_i387"
1524790286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1524890286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1524990286Sobrien	   [(match_operand:DF 1 "register_operand" "0,0")
15250169699Skan	    (float:DF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15251169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
15252169699Skan   && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1525390286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1525490286Sobrien  [(set (attr "type") 
1525590286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1525690286Sobrien                 (const_string "fmul")
1525790286Sobrien               (match_operand:DF 3 "div_operator" "") 
1525890286Sobrien                 (const_string "fdiv")
1525990286Sobrien              ]
1526090286Sobrien              (const_string "fop")))
1526190286Sobrien   (set_attr "fp_int_src" "true")
15262169699Skan   (set_attr "mode" "<MODE>")])
1526318334Speter
15264169699Skan(define_insn "*fop_df_4_i387"
1526590286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
1526690286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1526790286Sobrien	   [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
1526890286Sobrien	    (match_operand:DF 2 "register_operand" "0,f")]))]
15269169699Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
1527090286Sobrien   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
1527190286Sobrien  "* return output_387_binary_op (insn, operands);"
1527290286Sobrien  [(set (attr "type") 
1527390286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1527490286Sobrien                 (const_string "fmul")
1527590286Sobrien               (match_operand:DF 3 "div_operator" "") 
1527690286Sobrien                 (const_string "fdiv")
1527790286Sobrien              ]
1527890286Sobrien              (const_string "fop")))
1527990286Sobrien   (set_attr "mode" "SF")])
1528018334Speter
15281169699Skan(define_insn "*fop_df_5_i387"
1528218334Speter  [(set (match_operand:DF 0 "register_operand" "=f,f")
1528390286Sobrien	(match_operator:DF 3 "binary_fp_operator"
1528490286Sobrien	  [(match_operand:DF 1 "register_operand" "0,f")
1528590286Sobrien	   (float_extend:DF
1528690286Sobrien	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
1528790286Sobrien  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1528850650Sobrien  "* return output_387_binary_op (insn, operands);"
1528950650Sobrien  [(set (attr "type") 
1529090286Sobrien        (cond [(match_operand:DF 3 "mult_operator" "") 
1529190286Sobrien                 (const_string "fmul")
1529290286Sobrien               (match_operand:DF 3 "div_operator" "") 
1529390286Sobrien                 (const_string "fdiv")
1529450650Sobrien              ]
1529590286Sobrien              (const_string "fop")))
1529690286Sobrien   (set_attr "mode" "SF")])
1529718334Speter
15298169699Skan(define_insn "*fop_df_6_i387"
15299132727Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
15300132727Skan	(match_operator:DF 3 "binary_fp_operator"
15301132727Skan	  [(float_extend:DF
15302132727Skan	    (match_operand:SF 1 "register_operand" "0,f"))
15303132727Skan	   (float_extend:DF
15304132727Skan	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
15305132727Skan  "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)"
1530650650Sobrien  "* return output_387_binary_op (insn, operands);"
1530750650Sobrien  [(set (attr "type") 
15308132727Skan        (cond [(match_operand:DF 3 "mult_operator" "") 
1530990286Sobrien                 (const_string "fmul")
15310132727Skan               (match_operand:DF 3 "div_operator" "") 
1531190286Sobrien                 (const_string "fdiv")
1531250650Sobrien              ]
1531390286Sobrien              (const_string "fop")))
15314132727Skan   (set_attr "mode" "SF")])
1531518334Speter
15316169699Skan(define_insn "*fop_xf_comm_i387"
15317169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15318169699Skan	(match_operator:XF 3 "binary_fp_operator"
15319169699Skan			[(match_operand:XF 1 "register_operand" "%0")
15320169699Skan			 (match_operand:XF 2 "register_operand" "f")]))]
15321169699Skan  "TARGET_80387
15322169699Skan   && COMMUTATIVE_ARITH_P (operands[3])"
15323169699Skan  "* return output_387_binary_op (insn, operands);"
15324169699Skan  [(set (attr "type") 
15325169699Skan        (if_then_else (match_operand:XF 3 "mult_operator" "") 
15326169699Skan           (const_string "fmul")
15327169699Skan           (const_string "fop")))
15328169699Skan   (set_attr "mode" "XF")])
15329169699Skan
15330169699Skan(define_insn "*fop_xf_1_i387"
15331132727Skan  [(set (match_operand:XF 0 "register_operand" "=f,f")
15332132727Skan	(match_operator:XF 3 "binary_fp_operator"
15333132727Skan			[(match_operand:XF 1 "register_operand" "0,f")
15334132727Skan			 (match_operand:XF 2 "register_operand" "f,0")]))]
1533590286Sobrien  "TARGET_80387
15336169699Skan   && !COMMUTATIVE_ARITH_P (operands[3])"
1533790286Sobrien  "* return output_387_binary_op (insn, operands);"
1533890286Sobrien  [(set (attr "type") 
15339132727Skan        (cond [(match_operand:XF 3 "mult_operator" "") 
1534090286Sobrien                 (const_string "fmul")
15341132727Skan               (match_operand:XF 3 "div_operator" "") 
1534290286Sobrien                 (const_string "fdiv")
1534390286Sobrien              ]
1534490286Sobrien              (const_string "fop")))
1534590286Sobrien   (set_attr "mode" "XF")])
1534690286Sobrien
15347169699Skan(define_insn "*fop_xf_2<mode>_i387"
1534818334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
1534990286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15350169699Skan	   [(float:XF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
1535190286Sobrien	    (match_operand:XF 2 "register_operand" "0,0")]))]
15352169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
1535390286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1535490286Sobrien  [(set (attr "type") 
1535590286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1535690286Sobrien                 (const_string "fmul")
1535790286Sobrien               (match_operand:XF 3 "div_operator" "") 
1535890286Sobrien                 (const_string "fdiv")
1535990286Sobrien              ]
1536090286Sobrien              (const_string "fop")))
1536190286Sobrien   (set_attr "fp_int_src" "true")
15362169699Skan   (set_attr "mode" "<MODE>")])
1536390286Sobrien
15364169699Skan(define_insn "*fop_xf_3<mode>_i387"
1536590286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1536690286Sobrien	(match_operator:XF 3 "binary_fp_operator"
1536790286Sobrien	  [(match_operand:XF 1 "register_operand" "0,0")
15368169699Skan	   (float:XF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
15369169699Skan  "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
1537090286Sobrien  "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
1537190286Sobrien  [(set (attr "type") 
1537290286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1537390286Sobrien                 (const_string "fmul")
1537490286Sobrien               (match_operand:XF 3 "div_operator" "") 
1537590286Sobrien                 (const_string "fdiv")
1537690286Sobrien              ]
1537790286Sobrien              (const_string "fop")))
1537890286Sobrien   (set_attr "fp_int_src" "true")
15379169699Skan   (set_attr "mode" "<MODE>")])
1538090286Sobrien
15381169699Skan(define_insn "*fop_xf_4_i387"
1538290286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1538390286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15384132727Skan	   [(float_extend:XF (match_operand 1 "nonimmediate_operand" "fm,0"))
1538550650Sobrien	    (match_operand:XF 2 "register_operand" "0,f")]))]
15386132727Skan  "TARGET_80387"
1538790286Sobrien  "* return output_387_binary_op (insn, operands);"
1538890286Sobrien  [(set (attr "type") 
1538990286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1539090286Sobrien                 (const_string "fmul")
1539190286Sobrien               (match_operand:XF 3 "div_operator" "") 
1539290286Sobrien                 (const_string "fdiv")
1539390286Sobrien              ]
1539490286Sobrien              (const_string "fop")))
1539590286Sobrien   (set_attr "mode" "SF")])
1539690286Sobrien
15397169699Skan(define_insn "*fop_xf_5_i387"
1539818334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
1539990286Sobrien	(match_operator:XF 3 "binary_fp_operator"
1540050650Sobrien	  [(match_operand:XF 1 "register_operand" "0,f")
1540118334Speter	   (float_extend:XF
15402132727Skan	    (match_operand 2 "nonimmediate_operand" "fm,0"))]))]
15403132727Skan  "TARGET_80387"
1540450650Sobrien  "* return output_387_binary_op (insn, operands);"
1540550650Sobrien  [(set (attr "type") 
1540690286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1540790286Sobrien                 (const_string "fmul")
1540890286Sobrien               (match_operand:XF 3 "div_operator" "") 
1540990286Sobrien                 (const_string "fdiv")
1541050650Sobrien              ]
1541190286Sobrien              (const_string "fop")))
1541290286Sobrien   (set_attr "mode" "SF")])
1541318334Speter
15414169699Skan(define_insn "*fop_xf_6_i387"
1541590286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1541690286Sobrien	(match_operator:XF 3 "binary_fp_operator"
15417132727Skan	  [(float_extend:XF
15418132727Skan	    (match_operand 1 "register_operand" "0,f"))
15419132727Skan	   (float_extend:XF
15420132727Skan	    (match_operand 2 "nonimmediate_operand" "fm,0"))]))]
1542118334Speter  "TARGET_80387"
1542250650Sobrien  "* return output_387_binary_op (insn, operands);"
1542350650Sobrien  [(set (attr "type") 
1542490286Sobrien        (cond [(match_operand:XF 3 "mult_operator" "") 
1542590286Sobrien                 (const_string "fmul")
1542690286Sobrien               (match_operand:XF 3 "div_operator" "") 
1542790286Sobrien                 (const_string "fdiv")
1542890286Sobrien              ]
1542990286Sobrien              (const_string "fop")))
15430132727Skan   (set_attr "mode" "SF")])
1543190286Sobrien
1543290286Sobrien(define_split
1543390286Sobrien  [(set (match_operand 0 "register_operand" "")
1543490286Sobrien	(match_operator 3 "binary_fp_operator"
15435169699Skan	   [(float (match_operand:X87MODEI12 1 "register_operand" ""))
1543690286Sobrien	    (match_operand 2 "register_operand" "")]))]
1543790286Sobrien  "TARGET_80387 && reload_completed
1543890286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))"
1543990286Sobrien  [(const_int 0)]
1544090286Sobrien{ 
1544190286Sobrien  operands[4] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
1544290286Sobrien  operands[4] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[4]);
1544390286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1544490286Sobrien			  gen_rtx_fmt_ee (GET_CODE (operands[3]),
1544590286Sobrien					  GET_MODE (operands[3]),
1544690286Sobrien					  operands[4],
1544790286Sobrien					  operands[2])));
1544890286Sobrien  ix86_free_from_memory (GET_MODE (operands[1]));
1544990286Sobrien  DONE;
1545090286Sobrien})
1545190286Sobrien
1545290286Sobrien(define_split
1545390286Sobrien  [(set (match_operand 0 "register_operand" "")
1545490286Sobrien	(match_operator 3 "binary_fp_operator"
1545590286Sobrien	   [(match_operand 1 "register_operand" "")
15456169699Skan	    (float (match_operand:X87MODEI12 2 "register_operand" ""))]))]
1545790286Sobrien  "TARGET_80387 && reload_completed
1545890286Sobrien   && FLOAT_MODE_P (GET_MODE (operands[0]))"
1545990286Sobrien  [(const_int 0)]
1546090286Sobrien{
1546190286Sobrien  operands[4] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
1546290286Sobrien  operands[4] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[4]);
1546390286Sobrien  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1546490286Sobrien			  gen_rtx_fmt_ee (GET_CODE (operands[3]),
1546590286Sobrien					  GET_MODE (operands[3]),
1546690286Sobrien					  operands[1],
1546790286Sobrien					  operands[4])));
1546890286Sobrien  ix86_free_from_memory (GET_MODE (operands[2]));
1546990286Sobrien  DONE;
1547090286Sobrien})
1547118334Speter
1547290286Sobrien;; FPU special functions.
1547390286Sobrien
1547490286Sobrien(define_expand "sqrtsf2"
1547590286Sobrien  [(set (match_operand:SF 0 "register_operand" "")
1547690286Sobrien	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
15477169699Skan  "TARGET_USE_FANCY_MATH_387 || TARGET_SSE_MATH"
1547890286Sobrien{
1547990286Sobrien  if (!TARGET_SSE_MATH)
1548090286Sobrien    operands[1] = force_reg (SFmode, operands[1]);
1548190286Sobrien})
1548290286Sobrien
15483169699Skan(define_insn "*sqrtsf2_mixed"
15484169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,x")
15485169699Skan	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))]
15486169699Skan  "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387"
1548790286Sobrien  "@
1548890286Sobrien   fsqrt
1548990286Sobrien   sqrtss\t{%1, %0|%0, %1}"
1549090286Sobrien  [(set_attr "type" "fpspc,sse")
1549190286Sobrien   (set_attr "mode" "SF,SF")
1549290286Sobrien   (set_attr "athlon_decode" "direct,*")])
1549390286Sobrien
15494169699Skan(define_insn "*sqrtsf2_sse"
1549590286Sobrien  [(set (match_operand:SF 0 "register_operand" "=x")
1549690286Sobrien	(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "xm")))]
15497169699Skan  "TARGET_SSE_MATH"
1549890286Sobrien  "sqrtss\t{%1, %0|%0, %1}"
1549990286Sobrien  [(set_attr "type" "sse")
1550090286Sobrien   (set_attr "mode" "SF")
1550190286Sobrien   (set_attr "athlon_decode" "*")])
1550290286Sobrien
15503169699Skan(define_insn "*sqrtsf2_i387"
1550490286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
1550590286Sobrien	(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
15506169699Skan  "TARGET_USE_FANCY_MATH_387"
1550790286Sobrien  "fsqrt"
1550890286Sobrien  [(set_attr "type" "fpspc")
1550990286Sobrien   (set_attr "mode" "SF")
1551090286Sobrien   (set_attr "athlon_decode" "direct")])
1551190286Sobrien
1551290286Sobrien(define_expand "sqrtdf2"
1551390286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
1551490286Sobrien	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
15515169699Skan  "TARGET_USE_FANCY_MATH_387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
1551690286Sobrien{
15517169699Skan  if (!(TARGET_SSE2 && TARGET_SSE_MATH))
1551890286Sobrien    operands[1] = force_reg (DFmode, operands[1]);
1551990286Sobrien})
1552090286Sobrien
15521169699Skan(define_insn "*sqrtdf2_mixed"
15522169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,Y")
15523169699Skan	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))]
15524169699Skan  "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387"
1552590286Sobrien  "@
1552690286Sobrien   fsqrt
1552790286Sobrien   sqrtsd\t{%1, %0|%0, %1}"
1552890286Sobrien  [(set_attr "type" "fpspc,sse")
1552990286Sobrien   (set_attr "mode" "DF,DF")
1553090286Sobrien   (set_attr "athlon_decode" "direct,*")])
1553190286Sobrien
15532169699Skan(define_insn "*sqrtdf2_sse"
1553390286Sobrien  [(set (match_operand:DF 0 "register_operand" "=Y")
1553490286Sobrien	(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
15535169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
1553690286Sobrien  "sqrtsd\t{%1, %0|%0, %1}"
1553790286Sobrien  [(set_attr "type" "sse")
1553890286Sobrien   (set_attr "mode" "DF")
1553990286Sobrien   (set_attr "athlon_decode" "*")])
1554090286Sobrien
15541169699Skan(define_insn "*sqrtdf2_i387"
1554290286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1554390286Sobrien	(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
15544169699Skan  "TARGET_USE_FANCY_MATH_387"
1554590286Sobrien  "fsqrt"
1554690286Sobrien  [(set_attr "type" "fpspc")
1554790286Sobrien   (set_attr "mode" "DF")
1554890286Sobrien   (set_attr "athlon_decode" "direct")])
1554990286Sobrien
15550169699Skan(define_insn "*sqrtextendsfdf2_i387"
1555190286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1555290286Sobrien	(sqrt:DF (float_extend:DF
1555390286Sobrien		  (match_operand:SF 1 "register_operand" "0"))))]
15554169699Skan  "TARGET_USE_FANCY_MATH_387
15555169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
1555690286Sobrien  "fsqrt"
1555790286Sobrien  [(set_attr "type" "fpspc")
1555890286Sobrien   (set_attr "mode" "DF")
1555990286Sobrien   (set_attr "athlon_decode" "direct")])
1556090286Sobrien
1556190286Sobrien(define_insn "sqrtxf2"
1556290286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1556390286Sobrien	(sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
15564169699Skan  "TARGET_USE_FANCY_MATH_387"
1556590286Sobrien  "fsqrt"
1556690286Sobrien  [(set_attr "type" "fpspc")
1556790286Sobrien   (set_attr "mode" "XF")
1556890286Sobrien   (set_attr "athlon_decode" "direct")])
1556990286Sobrien
15570169699Skan(define_insn "*sqrtextendsfxf2_i387"
1557190286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1557290286Sobrien	(sqrt:XF (float_extend:XF
15573169699Skan		  (match_operand:SF 1 "register_operand" "0"))))]
15574169699Skan  "TARGET_USE_FANCY_MATH_387"
1557590286Sobrien  "fsqrt"
1557690286Sobrien  [(set_attr "type" "fpspc")
1557790286Sobrien   (set_attr "mode" "XF")
1557890286Sobrien   (set_attr "athlon_decode" "direct")])
1557990286Sobrien
15580169699Skan(define_insn "*sqrtextenddfxf2_i387"
1558190286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
1558290286Sobrien	(sqrt:XF (float_extend:XF
15583169699Skan		  (match_operand:DF 1 "register_operand" "0"))))]
15584169699Skan  "TARGET_USE_FANCY_MATH_387"
1558590286Sobrien  "fsqrt"
1558690286Sobrien  [(set_attr "type" "fpspc")
1558790286Sobrien   (set_attr "mode" "XF")
1558890286Sobrien   (set_attr "athlon_decode" "direct")])
1558990286Sobrien
15590169699Skan(define_insn "fpremxf4"
15591169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15592169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
15593169699Skan		    (match_operand:XF 3 "register_operand" "1")]
15594169699Skan		   UNSPEC_FPREM_F))
15595169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15596169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
15597169699Skan		   UNSPEC_FPREM_U))
15598169699Skan   (set (reg:CCFP FPSR_REG)
15599169699Skan	(unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
15600169699Skan  "TARGET_USE_FANCY_MATH_387
15601169699Skan   && flag_unsafe_math_optimizations"
15602169699Skan  "fprem"
15603169699Skan  [(set_attr "type" "fpspc")
15604169699Skan   (set_attr "mode" "XF")])
15605169699Skan
15606169699Skan(define_expand "fmodsf3"
15607169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
15608169699Skan   (use (match_operand:SF 1 "register_operand" ""))
15609169699Skan   (use (match_operand:SF 2 "register_operand" ""))]
15610169699Skan  "TARGET_USE_FANCY_MATH_387
15611169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15612169699Skan   && flag_unsafe_math_optimizations"
15613169699Skan{
15614169699Skan  rtx label = gen_label_rtx ();
15615169699Skan
15616169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15617169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15618169699Skan
15619169699Skan  emit_insn(gen_extendsfxf2 (op1, operands[1]));
15620169699Skan  emit_insn(gen_extendsfxf2 (op2, operands[2]));
15621169699Skan
15622169699Skan  emit_label (label);
15623169699Skan
15624169699Skan  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
15625169699Skan  ix86_emit_fp_unordered_jump (label);
15626169699Skan
15627169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
15628169699Skan  DONE;
15629169699Skan})
15630169699Skan
15631169699Skan(define_expand "fmoddf3"
15632169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
15633169699Skan   (use (match_operand:DF 1 "register_operand" ""))
15634169699Skan   (use (match_operand:DF 2 "register_operand" ""))]
15635169699Skan  "TARGET_USE_FANCY_MATH_387
15636169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15637169699Skan   && flag_unsafe_math_optimizations"
15638169699Skan{
15639169699Skan  rtx label = gen_label_rtx ();
15640169699Skan
15641169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15642169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15643169699Skan
15644169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
15645169699Skan  emit_insn (gen_extenddfxf2 (op2, operands[2]));
15646169699Skan
15647169699Skan  emit_label (label);
15648169699Skan
15649169699Skan  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
15650169699Skan  ix86_emit_fp_unordered_jump (label);
15651169699Skan
15652169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
15653169699Skan  DONE;
15654169699Skan})
15655169699Skan
15656169699Skan(define_expand "fmodxf3"
15657169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
15658169699Skan   (use (match_operand:XF 1 "register_operand" ""))
15659169699Skan   (use (match_operand:XF 2 "register_operand" ""))]
15660169699Skan  "TARGET_USE_FANCY_MATH_387
15661169699Skan   && flag_unsafe_math_optimizations"
15662169699Skan{
15663169699Skan  rtx label = gen_label_rtx ();
15664169699Skan
15665169699Skan  emit_label (label);
15666169699Skan
15667169699Skan  emit_insn (gen_fpremxf4 (operands[1], operands[2],
15668169699Skan			   operands[1], operands[2]));
15669169699Skan  ix86_emit_fp_unordered_jump (label);
15670169699Skan
15671169699Skan  emit_move_insn (operands[0], operands[1]);
15672169699Skan  DONE;
15673169699Skan})
15674169699Skan
15675169699Skan(define_insn "fprem1xf4"
15676169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15677169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
15678169699Skan		    (match_operand:XF 3 "register_operand" "1")]
15679169699Skan		   UNSPEC_FPREM1_F))
15680169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15681169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
15682169699Skan		   UNSPEC_FPREM1_U))
15683169699Skan   (set (reg:CCFP FPSR_REG)
15684169699Skan	(unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
15685169699Skan  "TARGET_USE_FANCY_MATH_387
15686169699Skan   && flag_unsafe_math_optimizations"
15687169699Skan  "fprem1"
15688169699Skan  [(set_attr "type" "fpspc")
15689169699Skan   (set_attr "mode" "XF")])
15690169699Skan
15691169699Skan(define_expand "dremsf3"
15692169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
15693169699Skan   (use (match_operand:SF 1 "register_operand" ""))
15694169699Skan   (use (match_operand:SF 2 "register_operand" ""))]
15695169699Skan  "TARGET_USE_FANCY_MATH_387
15696169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15697169699Skan   && flag_unsafe_math_optimizations"
15698169699Skan{
15699169699Skan  rtx label = gen_label_rtx ();
15700169699Skan
15701169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15702169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15703169699Skan
15704169699Skan  emit_insn(gen_extendsfxf2 (op1, operands[1]));
15705169699Skan  emit_insn(gen_extendsfxf2 (op2, operands[2]));
15706169699Skan
15707169699Skan  emit_label (label);
15708169699Skan
15709169699Skan  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
15710169699Skan  ix86_emit_fp_unordered_jump (label);
15711169699Skan
15712169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
15713169699Skan  DONE;
15714169699Skan})
15715169699Skan
15716169699Skan(define_expand "dremdf3"
15717169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
15718169699Skan   (use (match_operand:DF 1 "register_operand" ""))
15719169699Skan   (use (match_operand:DF 2 "register_operand" ""))]
15720169699Skan  "TARGET_USE_FANCY_MATH_387
15721169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15722169699Skan   && flag_unsafe_math_optimizations"
15723169699Skan{
15724169699Skan  rtx label = gen_label_rtx ();
15725169699Skan
15726169699Skan  rtx op1 = gen_reg_rtx (XFmode);
15727169699Skan  rtx op2 = gen_reg_rtx (XFmode);
15728169699Skan
15729169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
15730169699Skan  emit_insn (gen_extenddfxf2 (op2, operands[2]));
15731169699Skan
15732169699Skan  emit_label (label);
15733169699Skan
15734169699Skan  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
15735169699Skan  ix86_emit_fp_unordered_jump (label);
15736169699Skan
15737169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
15738169699Skan  DONE;
15739169699Skan})
15740169699Skan
15741169699Skan(define_expand "dremxf3"
15742169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
15743169699Skan   (use (match_operand:XF 1 "register_operand" ""))
15744169699Skan   (use (match_operand:XF 2 "register_operand" ""))]
15745169699Skan  "TARGET_USE_FANCY_MATH_387
15746169699Skan   && flag_unsafe_math_optimizations"
15747169699Skan{
15748169699Skan  rtx label = gen_label_rtx ();
15749169699Skan
15750169699Skan  emit_label (label);
15751169699Skan
15752169699Skan  emit_insn (gen_fprem1xf4 (operands[1], operands[2],
15753169699Skan			    operands[1], operands[2]));
15754169699Skan  ix86_emit_fp_unordered_jump (label);
15755169699Skan
15756169699Skan  emit_move_insn (operands[0], operands[1]);
15757169699Skan  DONE;
15758169699Skan})
15759169699Skan
15760169699Skan(define_insn "*sindf2"
1576190286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
15762117404Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_SIN))]
15763169699Skan  "TARGET_USE_FANCY_MATH_387
15764169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1576590286Sobrien   && flag_unsafe_math_optimizations"
1576690286Sobrien  "fsin"
1576790286Sobrien  [(set_attr "type" "fpspc")
1576890286Sobrien   (set_attr "mode" "DF")])
1576990286Sobrien
15770169699Skan(define_insn "*sinsf2"
1577190286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
15772117404Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_SIN))]
15773169699Skan  "TARGET_USE_FANCY_MATH_387
15774169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
1577590286Sobrien   && flag_unsafe_math_optimizations"
1577690286Sobrien  "fsin"
1577790286Sobrien  [(set_attr "type" "fpspc")
1577890286Sobrien   (set_attr "mode" "SF")])
1577990286Sobrien
1578090286Sobrien(define_insn "*sinextendsfdf2"
1578190286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1578290286Sobrien	(unspec:DF [(float_extend:DF
15783117404Skan		     (match_operand:SF 1 "register_operand" "0"))]
15784117404Skan		   UNSPEC_SIN))]
15785169699Skan  "TARGET_USE_FANCY_MATH_387
15786169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1578790286Sobrien   && flag_unsafe_math_optimizations"
1578890286Sobrien  "fsin"
1578990286Sobrien  [(set_attr "type" "fpspc")
1579090286Sobrien   (set_attr "mode" "DF")])
1579190286Sobrien
15792169699Skan(define_insn "*sinxf2"
1579390286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
15794117404Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_SIN))]
15795169699Skan  "TARGET_USE_FANCY_MATH_387
1579690286Sobrien   && flag_unsafe_math_optimizations"
1579790286Sobrien  "fsin"
1579890286Sobrien  [(set_attr "type" "fpspc")
1579990286Sobrien   (set_attr "mode" "XF")])
1580090286Sobrien
15801169699Skan(define_insn "*cosdf2"
1580290286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
15803117404Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_COS))]
15804169699Skan  "TARGET_USE_FANCY_MATH_387
15805169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1580690286Sobrien   && flag_unsafe_math_optimizations"
1580790286Sobrien  "fcos"
1580890286Sobrien  [(set_attr "type" "fpspc")
1580990286Sobrien   (set_attr "mode" "DF")])
1581090286Sobrien
15811169699Skan(define_insn "*cossf2"
1581290286Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
15813117404Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_COS))]
15814169699Skan  "TARGET_USE_FANCY_MATH_387
15815169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
1581690286Sobrien   && flag_unsafe_math_optimizations"
1581790286Sobrien  "fcos"
1581890286Sobrien  [(set_attr "type" "fpspc")
1581990286Sobrien   (set_attr "mode" "SF")])
1582090286Sobrien
1582190286Sobrien(define_insn "*cosextendsfdf2"
1582290286Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
1582390286Sobrien	(unspec:DF [(float_extend:DF
15824117404Skan		     (match_operand:SF 1 "register_operand" "0"))]
15825117404Skan		   UNSPEC_COS))]
15826169699Skan  "TARGET_USE_FANCY_MATH_387
15827169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1582890286Sobrien   && flag_unsafe_math_optimizations"
1582990286Sobrien  "fcos"
1583090286Sobrien  [(set_attr "type" "fpspc")
1583190286Sobrien   (set_attr "mode" "DF")])
1583290286Sobrien
15833169699Skan(define_insn "*cosxf2"
1583490286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
15835117404Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_COS))]
15836169699Skan  "TARGET_USE_FANCY_MATH_387
1583790286Sobrien   && flag_unsafe_math_optimizations"
1583890286Sobrien  "fcos"
1583990286Sobrien  [(set_attr "type" "fpspc")
1584090286Sobrien   (set_attr "mode" "XF")])
1584190286Sobrien
15842169699Skan;; With sincos pattern defined, sin and cos builtin function will be
15843169699Skan;; expanded to sincos pattern with one of its outputs left unused. 
15844169699Skan;; Cse pass  will detected, if two sincos patterns can be combined,
15845169699Skan;; otherwise sincos pattern will be split back to sin or cos pattern,
15846169699Skan;; depending on the unused output.
15847169699Skan
15848169699Skan(define_insn "sincosdf3"
15849169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
15850169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")]
15851169699Skan		   UNSPEC_SINCOS_COS))
15852169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
15853169699Skan        (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15854169699Skan  "TARGET_USE_FANCY_MATH_387
15855169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15856169699Skan   && flag_unsafe_math_optimizations"
15857169699Skan  "fsincos"
15858169699Skan  [(set_attr "type" "fpspc")
15859169699Skan   (set_attr "mode" "DF")])
15860169699Skan
15861169699Skan(define_split
15862169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15863169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "")]
15864169699Skan		   UNSPEC_SINCOS_COS))
15865169699Skan   (set (match_operand:DF 1 "register_operand" "")
15866169699Skan	(unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15867169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15868169699Skan   && !reload_completed && !reload_in_progress"
15869169699Skan  [(set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_SIN))]
15870169699Skan  "")
15871169699Skan
15872169699Skan(define_split
15873169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15874169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "")]
15875169699Skan		   UNSPEC_SINCOS_COS))
15876169699Skan   (set (match_operand:DF 1 "register_operand" "")
15877169699Skan	(unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15878169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15879169699Skan   && !reload_completed && !reload_in_progress"
15880169699Skan  [(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_COS))]
15881169699Skan  "")
15882169699Skan
15883169699Skan(define_insn "sincossf3"
15884169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
15885169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "0")]
15886169699Skan		   UNSPEC_SINCOS_COS))
15887169699Skan   (set (match_operand:SF 1 "register_operand" "=u")
15888169699Skan        (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15889169699Skan  "TARGET_USE_FANCY_MATH_387
15890169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
15891169699Skan   && flag_unsafe_math_optimizations"
15892169699Skan  "fsincos"
15893169699Skan  [(set_attr "type" "fpspc")
15894169699Skan   (set_attr "mode" "SF")])
15895169699Skan
15896169699Skan(define_split
15897169699Skan  [(set (match_operand:SF 0 "register_operand" "")
15898169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "")]
15899169699Skan		   UNSPEC_SINCOS_COS))
15900169699Skan   (set (match_operand:SF 1 "register_operand" "")
15901169699Skan	(unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15902169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15903169699Skan   && !reload_completed && !reload_in_progress"
15904169699Skan  [(set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_SIN))]
15905169699Skan  "")
15906169699Skan
15907169699Skan(define_split
15908169699Skan  [(set (match_operand:SF 0 "register_operand" "")
15909169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "")]
15910169699Skan		   UNSPEC_SINCOS_COS))
15911169699Skan   (set (match_operand:SF 1 "register_operand" "")
15912169699Skan	(unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15913169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15914169699Skan   && !reload_completed && !reload_in_progress"
15915169699Skan  [(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_COS))]
15916169699Skan  "")
15917169699Skan
15918169699Skan(define_insn "*sincosextendsfdf3"
15919169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
15920169699Skan	(unspec:DF [(float_extend:DF
15921169699Skan		     (match_operand:SF 2 "register_operand" "0"))]
15922169699Skan		   UNSPEC_SINCOS_COS))
15923169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
15924169699Skan        (unspec:DF [(float_extend:DF
15925169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
15926169699Skan  "TARGET_USE_FANCY_MATH_387
15927169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
15928169699Skan   && flag_unsafe_math_optimizations"
15929169699Skan  "fsincos"
15930169699Skan  [(set_attr "type" "fpspc")
15931169699Skan   (set_attr "mode" "DF")])
15932169699Skan
15933169699Skan(define_split
15934169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15935169699Skan	(unspec:DF [(float_extend:DF
15936169699Skan		     (match_operand:SF 2 "register_operand" ""))]
15937169699Skan		   UNSPEC_SINCOS_COS))
15938169699Skan   (set (match_operand:DF 1 "register_operand" "")
15939169699Skan        (unspec:DF [(float_extend:DF
15940169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
15941169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15942169699Skan   && !reload_completed && !reload_in_progress"
15943169699Skan  [(set (match_dup 1) (unspec:DF [(float_extend:DF
15944169699Skan				   (match_dup 2))] UNSPEC_SIN))]
15945169699Skan  "")
15946169699Skan
15947169699Skan(define_split
15948169699Skan  [(set (match_operand:DF 0 "register_operand" "")
15949169699Skan	(unspec:DF [(float_extend:DF
15950169699Skan		     (match_operand:SF 2 "register_operand" ""))]
15951169699Skan		   UNSPEC_SINCOS_COS))
15952169699Skan   (set (match_operand:DF 1 "register_operand" "")
15953169699Skan        (unspec:DF [(float_extend:DF
15954169699Skan		     (match_dup 2))] UNSPEC_SINCOS_SIN))]
15955169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15956169699Skan   && !reload_completed && !reload_in_progress"
15957169699Skan  [(set (match_dup 0) (unspec:DF [(float_extend:DF
15958169699Skan				   (match_dup 2))] UNSPEC_COS))]
15959169699Skan  "")
15960169699Skan
15961169699Skan(define_insn "sincosxf3"
15962169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
15963169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
15964169699Skan		   UNSPEC_SINCOS_COS))
15965169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
15966169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15967169699Skan  "TARGET_USE_FANCY_MATH_387
15968169699Skan   && flag_unsafe_math_optimizations"
15969169699Skan  "fsincos"
15970169699Skan  [(set_attr "type" "fpspc")
15971169699Skan   (set_attr "mode" "XF")])
15972169699Skan
15973169699Skan(define_split
15974169699Skan  [(set (match_operand:XF 0 "register_operand" "")
15975169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "")]
15976169699Skan		   UNSPEC_SINCOS_COS))
15977169699Skan   (set (match_operand:XF 1 "register_operand" "")
15978169699Skan	(unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15979169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
15980169699Skan   && !reload_completed && !reload_in_progress"
15981169699Skan  [(set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_SIN))]
15982169699Skan  "")
15983169699Skan
15984169699Skan(define_split
15985169699Skan  [(set (match_operand:XF 0 "register_operand" "")
15986169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "")]
15987169699Skan		   UNSPEC_SINCOS_COS))
15988169699Skan   (set (match_operand:XF 1 "register_operand" "")
15989169699Skan	(unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
15990169699Skan  "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
15991169699Skan   && !reload_completed && !reload_in_progress"
15992169699Skan  [(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_COS))]
15993169699Skan  "")
15994169699Skan
15995169699Skan(define_insn "*tandf3_1"
15996169699Skan  [(set (match_operand:DF 0 "register_operand" "=f")
15997169699Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")]
15998169699Skan		   UNSPEC_TAN_ONE))
15999169699Skan   (set (match_operand:DF 1 "register_operand" "=u")
16000169699Skan        (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))]
16001169699Skan  "TARGET_USE_FANCY_MATH_387
16002169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16003169699Skan   && flag_unsafe_math_optimizations"
16004169699Skan  "fptan"
16005169699Skan  [(set_attr "type" "fpspc")
16006169699Skan   (set_attr "mode" "DF")])
16007169699Skan
16008169699Skan;; optimize sequence: fptan
16009169699Skan;;		      fstp    %st(0)
16010169699Skan;;		      fld1
16011169699Skan;; into fptan insn.
16012169699Skan
16013169699Skan(define_peephole2
16014169699Skan  [(parallel[(set (match_operand:DF 0 "register_operand" "")
16015169699Skan		  (unspec:DF [(match_operand:DF 2 "register_operand" "")]
16016169699Skan			     UNSPEC_TAN_ONE))
16017169699Skan	     (set (match_operand:DF 1 "register_operand" "")
16018169699Skan		  (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])
16019169699Skan   (set (match_dup 0)
16020169699Skan        (match_operand:DF 3 "immediate_operand" ""))]
16021169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16022169699Skan  [(parallel[(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_TAN_ONE))
16023169699Skan   	     (set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16024169699Skan  "")
16025169699Skan
16026169699Skan(define_expand "tandf2"
16027169699Skan  [(parallel [(set (match_dup 2)
16028169699Skan		   (unspec:DF [(match_operand:DF 1 "register_operand" "")]
16029169699Skan			      UNSPEC_TAN_ONE))
16030169699Skan	      (set (match_operand:DF 0 "register_operand" "")
16031169699Skan		   (unspec:DF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16032169699Skan  "TARGET_USE_FANCY_MATH_387
16033169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16034169699Skan   && flag_unsafe_math_optimizations"
16035169699Skan{
16036169699Skan  operands[2] = gen_reg_rtx (DFmode);
16037169699Skan})
16038169699Skan
16039169699Skan(define_insn "*tansf3_1"
16040169699Skan  [(set (match_operand:SF 0 "register_operand" "=f")
16041169699Skan	(unspec:SF [(match_operand:SF 2 "register_operand" "0")]
16042169699Skan		   UNSPEC_TAN_ONE))
16043169699Skan   (set (match_operand:SF 1 "register_operand" "=u")
16044169699Skan        (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))]
16045169699Skan  "TARGET_USE_FANCY_MATH_387
16046169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16047169699Skan   && flag_unsafe_math_optimizations"
16048169699Skan  "fptan"
16049169699Skan  [(set_attr "type" "fpspc")
16050169699Skan   (set_attr "mode" "SF")])
16051169699Skan
16052169699Skan;; optimize sequence: fptan
16053169699Skan;;		      fstp    %st(0)
16054169699Skan;;		      fld1
16055169699Skan;; into fptan insn.
16056169699Skan
16057169699Skan(define_peephole2
16058169699Skan  [(parallel[(set (match_operand:SF 0 "register_operand" "")
16059169699Skan		  (unspec:SF [(match_operand:SF 2 "register_operand" "")]
16060169699Skan			     UNSPEC_TAN_ONE))
16061169699Skan	     (set (match_operand:SF 1 "register_operand" "")
16062169699Skan		  (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])
16063169699Skan   (set (match_dup 0)
16064169699Skan        (match_operand:SF 3 "immediate_operand" ""))]
16065169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16066169699Skan  [(parallel[(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_TAN_ONE))
16067169699Skan   	     (set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16068169699Skan  "")
16069169699Skan
16070169699Skan(define_expand "tansf2"
16071169699Skan  [(parallel [(set (match_dup 2)
16072169699Skan		   (unspec:SF [(match_operand:SF 1 "register_operand" "")]
16073169699Skan			      UNSPEC_TAN_ONE))
16074169699Skan	      (set (match_operand:SF 0 "register_operand" "")
16075169699Skan		   (unspec:SF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16076169699Skan  "TARGET_USE_FANCY_MATH_387
16077169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16078169699Skan   && flag_unsafe_math_optimizations"
16079169699Skan{
16080169699Skan  operands[2] = gen_reg_rtx (SFmode);
16081169699Skan})
16082169699Skan
16083169699Skan(define_insn "*tanxf3_1"
16084169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16085169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
16086169699Skan		   UNSPEC_TAN_ONE))
16087169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16088169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))]
16089169699Skan  "TARGET_USE_FANCY_MATH_387
16090169699Skan   && flag_unsafe_math_optimizations"
16091169699Skan  "fptan"
16092169699Skan  [(set_attr "type" "fpspc")
16093169699Skan   (set_attr "mode" "XF")])
16094169699Skan
16095169699Skan;; optimize sequence: fptan
16096169699Skan;;		      fstp    %st(0)
16097169699Skan;;		      fld1
16098169699Skan;; into fptan insn.
16099169699Skan
16100169699Skan(define_peephole2
16101169699Skan  [(parallel[(set (match_operand:XF 0 "register_operand" "")
16102169699Skan		  (unspec:XF [(match_operand:XF 2 "register_operand" "")]
16103169699Skan			     UNSPEC_TAN_ONE))
16104169699Skan	     (set (match_operand:XF 1 "register_operand" "")
16105169699Skan		  (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])
16106169699Skan   (set (match_dup 0)
16107169699Skan        (match_operand:XF 3 "immediate_operand" ""))]
16108169699Skan  "standard_80387_constant_p (operands[3]) == 2"
16109169699Skan  [(parallel[(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_TAN_ONE))
16110169699Skan   	     (set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])]
16111169699Skan  "")
16112169699Skan
16113169699Skan(define_expand "tanxf2"
16114169699Skan  [(parallel [(set (match_dup 2)
16115169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16116169699Skan			      UNSPEC_TAN_ONE))
16117169699Skan	      (set (match_operand:XF 0 "register_operand" "")
16118169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_TAN_TAN))])]
16119169699Skan  "TARGET_USE_FANCY_MATH_387
16120169699Skan   && flag_unsafe_math_optimizations"
16121169699Skan{
16122169699Skan  operands[2] = gen_reg_rtx (XFmode);
16123169699Skan})
16124169699Skan
16125132727Skan(define_insn "atan2df3_1"
16126132727Skan  [(set (match_operand:DF 0 "register_operand" "=f")
16127132727Skan	(unspec:DF [(match_operand:DF 2 "register_operand" "0")
16128132727Skan		    (match_operand:DF 1 "register_operand" "u")]
16129132727Skan		   UNSPEC_FPATAN))
16130132727Skan   (clobber (match_scratch:DF 3 "=1"))]
16131169699Skan  "TARGET_USE_FANCY_MATH_387
16132169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
1613390286Sobrien   && flag_unsafe_math_optimizations"
16134132727Skan  "fpatan"
1613590286Sobrien  [(set_attr "type" "fpspc")
16136132727Skan   (set_attr "mode" "DF")])
16137132727Skan
16138132727Skan(define_expand "atan2df3"
16139169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
16140169699Skan   (use (match_operand:DF 2 "register_operand" ""))
16141169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
16142169699Skan  "TARGET_USE_FANCY_MATH_387
16143169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16144132727Skan   && flag_unsafe_math_optimizations"
16145132727Skan{
16146132727Skan  rtx copy = gen_reg_rtx (DFmode);
16147132727Skan  emit_move_insn (copy, operands[1]);
16148132727Skan  emit_insn (gen_atan2df3_1 (operands[0], copy, operands[2]));
16149132727Skan  DONE;
16150132727Skan})
16151132727Skan
16152169699Skan(define_expand "atandf2"
16153169699Skan  [(parallel [(set (match_operand:DF 0 "register_operand" "")
16154169699Skan		   (unspec:DF [(match_dup 2)
16155169699Skan			       (match_operand:DF 1 "register_operand" "")]
16156169699Skan		    UNSPEC_FPATAN))
16157169699Skan	      (clobber (match_scratch:DF 3 ""))])]
16158169699Skan  "TARGET_USE_FANCY_MATH_387
16159169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16160169699Skan   && flag_unsafe_math_optimizations"
16161169699Skan{
16162169699Skan  operands[2] = gen_reg_rtx (DFmode);
16163169699Skan  emit_move_insn (operands[2], CONST1_RTX (DFmode));  /* fld1 */
16164169699Skan})
16165169699Skan
16166132727Skan(define_insn "atan2sf3_1"
16167132727Skan  [(set (match_operand:SF 0 "register_operand" "=f")
16168132727Skan        (unspec:SF [(match_operand:SF 2 "register_operand" "0")
16169132727Skan		    (match_operand:SF 1 "register_operand" "u")]
16170132727Skan		   UNSPEC_FPATAN))
16171132727Skan   (clobber (match_scratch:SF 3 "=1"))]
16172169699Skan  "TARGET_USE_FANCY_MATH_387
16173169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16174132727Skan   && flag_unsafe_math_optimizations"
16175132727Skan  "fpatan"
16176132727Skan  [(set_attr "type" "fpspc")
16177132727Skan   (set_attr "mode" "SF")])
16178132727Skan
16179132727Skan(define_expand "atan2sf3"
16180169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
16181169699Skan   (use (match_operand:SF 2 "register_operand" ""))
16182169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
16183169699Skan  "TARGET_USE_FANCY_MATH_387
16184169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16185132727Skan   && flag_unsafe_math_optimizations"
16186132727Skan{
16187132727Skan  rtx copy = gen_reg_rtx (SFmode);
16188132727Skan  emit_move_insn (copy, operands[1]);
16189132727Skan  emit_insn (gen_atan2sf3_1 (operands[0], copy, operands[2]));
16190132727Skan  DONE;
16191132727Skan})
16192132727Skan
16193169699Skan(define_expand "atansf2"
16194169699Skan  [(parallel [(set (match_operand:SF 0 "register_operand" "")
16195169699Skan		   (unspec:SF [(match_dup 2)
16196169699Skan			       (match_operand:SF 1 "register_operand" "")]
16197169699Skan		    UNSPEC_FPATAN))
16198169699Skan	      (clobber (match_scratch:SF 3 ""))])]
16199169699Skan  "TARGET_USE_FANCY_MATH_387
16200169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16201169699Skan   && flag_unsafe_math_optimizations"
16202169699Skan{
16203169699Skan  operands[2] = gen_reg_rtx (SFmode);
16204169699Skan  emit_move_insn (operands[2], CONST1_RTX (SFmode));  /* fld1 */
16205169699Skan})
16206169699Skan
16207132727Skan(define_insn "atan2xf3_1"
16208132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16209132727Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16210132727Skan	            (match_operand:XF 1 "register_operand" "u")]
16211132727Skan	           UNSPEC_FPATAN))
16212132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16213169699Skan  "TARGET_USE_FANCY_MATH_387
16214132727Skan   && flag_unsafe_math_optimizations"
16215132727Skan  "fpatan"
16216132727Skan  [(set_attr "type" "fpspc")
1621790286Sobrien   (set_attr "mode" "XF")])
16218132727Skan
16219132727Skan(define_expand "atan2xf3"
16220169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
16221169699Skan   (use (match_operand:XF 2 "register_operand" ""))
16222169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
16223169699Skan  "TARGET_USE_FANCY_MATH_387
16224132727Skan   && flag_unsafe_math_optimizations"
16225132727Skan{
16226132727Skan  rtx copy = gen_reg_rtx (XFmode);
16227132727Skan  emit_move_insn (copy, operands[1]);
16228132727Skan  emit_insn (gen_atan2xf3_1 (operands[0], copy, operands[2]));
16229132727Skan  DONE;
16230132727Skan})
16231132727Skan
16232169699Skan(define_expand "atanxf2"
16233169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16234169699Skan		   (unspec:XF [(match_dup 2)
16235169699Skan			       (match_operand:XF 1 "register_operand" "")]
16236169699Skan		    UNSPEC_FPATAN))
16237169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16238169699Skan  "TARGET_USE_FANCY_MATH_387
16239132727Skan   && flag_unsafe_math_optimizations"
16240169699Skan{
16241169699Skan  operands[2] = gen_reg_rtx (XFmode);
16242169699Skan  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
16243169699Skan})
16244132727Skan
16245169699Skan(define_expand "asindf2"
16246169699Skan  [(set (match_dup 2)
16247169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16248169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16249169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16250169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16251169699Skan   (parallel [(set (match_dup 7)
16252169699Skan        	   (unspec:XF [(match_dup 6) (match_dup 2)]
16253169699Skan			      UNSPEC_FPATAN))
16254169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16255169699Skan   (set (match_operand:DF 0 "register_operand" "")
16256169699Skan	(float_truncate:DF (match_dup 7)))]
16257169699Skan  "TARGET_USE_FANCY_MATH_387
16258169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16259132727Skan   && flag_unsafe_math_optimizations"
16260169699Skan{
16261169699Skan  int i;
16262132727Skan
16263169699Skan  for (i=2; i<8; i++)
16264169699Skan    operands[i] = gen_reg_rtx (XFmode);
16265169699Skan
16266169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16267169699Skan})
16268169699Skan
16269169699Skan(define_expand "asinsf2"
16270169699Skan  [(set (match_dup 2)
16271169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16272169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16273169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16274169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16275169699Skan   (parallel [(set (match_dup 7)
16276169699Skan        	   (unspec:XF [(match_dup 6) (match_dup 2)]
16277169699Skan			      UNSPEC_FPATAN))
16278169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16279169699Skan   (set (match_operand:SF 0 "register_operand" "")
16280169699Skan	(float_truncate:SF (match_dup 7)))]
16281169699Skan  "TARGET_USE_FANCY_MATH_387
16282169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16283169699Skan   && flag_unsafe_math_optimizations"
16284169699Skan{
16285169699Skan  int i;
16286169699Skan
16287169699Skan  for (i=2; i<8; i++)
16288169699Skan    operands[i] = gen_reg_rtx (XFmode);
16289169699Skan
16290169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16291169699Skan})
16292169699Skan
16293169699Skan(define_expand "asinxf2"
16294169699Skan  [(set (match_dup 2)
16295169699Skan	(mult:XF (match_operand:XF 1 "register_operand" "")
16296169699Skan		 (match_dup 1)))
16297169699Skan   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
16298169699Skan   (set (match_dup 5) (sqrt:XF (match_dup 4)))
16299169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16300169699Skan        	   (unspec:XF [(match_dup 5) (match_dup 1)]
16301169699Skan			      UNSPEC_FPATAN))
16302169699Skan   	      (clobber (match_scratch:XF 6 ""))])]
16303169699Skan  "TARGET_USE_FANCY_MATH_387
16304169699Skan   && flag_unsafe_math_optimizations"
16305169699Skan{
16306169699Skan  int i;
16307169699Skan
16308169699Skan  for (i=2; i<6; i++)
16309169699Skan    operands[i] = gen_reg_rtx (XFmode);
16310169699Skan
16311169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16312169699Skan})
16313169699Skan
16314169699Skan(define_expand "acosdf2"
16315169699Skan  [(set (match_dup 2)
16316169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16317169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16318169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16319169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16320169699Skan   (parallel [(set (match_dup 7)
16321169699Skan        	   (unspec:XF [(match_dup 2) (match_dup 6)]
16322169699Skan			      UNSPEC_FPATAN))
16323169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16324169699Skan   (set (match_operand:DF 0 "register_operand" "")
16325169699Skan	(float_truncate:DF (match_dup 7)))]
16326169699Skan  "TARGET_USE_FANCY_MATH_387
16327169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16328169699Skan   && flag_unsafe_math_optimizations"
16329169699Skan{
16330169699Skan  int i;
16331169699Skan
16332169699Skan  for (i=2; i<8; i++)
16333169699Skan    operands[i] = gen_reg_rtx (XFmode);
16334169699Skan
16335169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16336169699Skan})
16337169699Skan
16338169699Skan(define_expand "acossf2"
16339169699Skan  [(set (match_dup 2)
16340169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16341169699Skan   (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
16342169699Skan   (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
16343169699Skan   (set (match_dup 6) (sqrt:XF (match_dup 5)))
16344169699Skan   (parallel [(set (match_dup 7)
16345169699Skan        	   (unspec:XF [(match_dup 2) (match_dup 6)]
16346169699Skan			      UNSPEC_FPATAN))
16347169699Skan   	      (clobber (match_scratch:XF 8 ""))])
16348169699Skan   (set (match_operand:SF 0 "register_operand" "")
16349169699Skan	(float_truncate:SF (match_dup 7)))]
16350169699Skan  "TARGET_USE_FANCY_MATH_387
16351169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16352169699Skan   && flag_unsafe_math_optimizations"
16353169699Skan{
16354169699Skan  int i;
16355169699Skan
16356169699Skan  for (i=2; i<8; i++)
16357169699Skan    operands[i] = gen_reg_rtx (XFmode);
16358169699Skan
16359169699Skan  emit_move_insn (operands[4], CONST1_RTX (XFmode));  /* fld1 */
16360169699Skan})
16361169699Skan
16362169699Skan(define_expand "acosxf2"
16363169699Skan  [(set (match_dup 2)
16364169699Skan	(mult:XF (match_operand:XF 1 "register_operand" "")
16365169699Skan		 (match_dup 1)))
16366169699Skan   (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
16367169699Skan   (set (match_dup 5) (sqrt:XF (match_dup 4)))
16368169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16369169699Skan        	   (unspec:XF [(match_dup 1) (match_dup 5)]
16370169699Skan			      UNSPEC_FPATAN))
16371169699Skan   	      (clobber (match_scratch:XF 6 ""))])]
16372169699Skan  "TARGET_USE_FANCY_MATH_387
16373169699Skan   && flag_unsafe_math_optimizations"
16374169699Skan{
16375169699Skan  int i;
16376169699Skan
16377169699Skan  for (i=2; i<6; i++)
16378169699Skan    operands[i] = gen_reg_rtx (XFmode);
16379169699Skan
16380169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16381169699Skan})
16382169699Skan
16383169699Skan(define_insn "fyl2x_xf3"
16384132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16385132727Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16386132727Skan		    (match_operand:XF 1 "register_operand" "u")]
16387132727Skan	           UNSPEC_FYL2X))
16388132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16389169699Skan  "TARGET_USE_FANCY_MATH_387
16390132727Skan   && flag_unsafe_math_optimizations"
16391132727Skan  "fyl2x"
16392132727Skan  [(set_attr "type" "fpspc")
16393132727Skan   (set_attr "mode" "XF")])
16394132727Skan
16395132727Skan(define_expand "logsf2"
16396169699Skan  [(set (match_dup 2)
16397169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16398169699Skan   (parallel [(set (match_dup 4)
16399169699Skan		   (unspec:XF [(match_dup 2)
16400169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16401169699Skan	      (clobber (match_scratch:XF 5 ""))])
16402169699Skan   (set (match_operand:SF 0 "register_operand" "")
16403169699Skan	(float_truncate:SF (match_dup 4)))]
16404169699Skan  "TARGET_USE_FANCY_MATH_387
16405169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16406132727Skan   && flag_unsafe_math_optimizations"
16407132727Skan{
16408132727Skan  rtx temp;
16409132727Skan
16410132727Skan  operands[2] = gen_reg_rtx (XFmode);
16411169699Skan  operands[3] = gen_reg_rtx (XFmode);
16412169699Skan  operands[4] = gen_reg_rtx (XFmode);
16413169699Skan
16414132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16415169699Skan  emit_move_insn (operands[3], temp);
16416132727Skan})
16417132727Skan
16418132727Skan(define_expand "logdf2"
16419169699Skan  [(set (match_dup 2)
16420169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16421169699Skan   (parallel [(set (match_dup 4)
16422169699Skan		   (unspec:XF [(match_dup 2)
16423169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16424169699Skan	      (clobber (match_scratch:XF 5 ""))])
16425169699Skan   (set (match_operand:DF 0 "register_operand" "")
16426169699Skan	(float_truncate:DF (match_dup 4)))]
16427169699Skan  "TARGET_USE_FANCY_MATH_387
16428169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16429132727Skan   && flag_unsafe_math_optimizations"
16430132727Skan{
16431132727Skan  rtx temp;
16432132727Skan
16433132727Skan  operands[2] = gen_reg_rtx (XFmode);
16434169699Skan  operands[3] = gen_reg_rtx (XFmode);
16435169699Skan  operands[4] = gen_reg_rtx (XFmode);
16436169699Skan
16437132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16438169699Skan  emit_move_insn (operands[3], temp);
16439132727Skan})
16440132727Skan
16441132727Skan(define_expand "logxf2"
16442132727Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16443132727Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16444132727Skan			       (match_dup 2)] UNSPEC_FYL2X))
16445132727Skan	      (clobber (match_scratch:XF 3 ""))])]
16446169699Skan  "TARGET_USE_FANCY_MATH_387
16447132727Skan   && flag_unsafe_math_optimizations"
16448132727Skan{
16449132727Skan  rtx temp;
16450132727Skan
16451132727Skan  operands[2] = gen_reg_rtx (XFmode);
16452132727Skan  temp = standard_80387_constant_rtx (4); /* fldln2 */
16453132727Skan  emit_move_insn (operands[2], temp);
16454132727Skan})
16455132727Skan
16456169699Skan(define_expand "log10sf2"
16457169699Skan  [(set (match_dup 2)
16458169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16459169699Skan   (parallel [(set (match_dup 4)
16460169699Skan		   (unspec:XF [(match_dup 2)
16461169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16462169699Skan	      (clobber (match_scratch:XF 5 ""))])
16463169699Skan   (set (match_operand:SF 0 "register_operand" "")
16464169699Skan	(float_truncate:SF (match_dup 4)))]
16465169699Skan  "TARGET_USE_FANCY_MATH_387
16466169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16467132727Skan   && flag_unsafe_math_optimizations"
16468169699Skan{
16469169699Skan  rtx temp;
16470132727Skan
16471169699Skan  operands[2] = gen_reg_rtx (XFmode);
16472169699Skan  operands[3] = gen_reg_rtx (XFmode);
16473169699Skan  operands[4] = gen_reg_rtx (XFmode);
16474169699Skan
16475169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16476169699Skan  emit_move_insn (operands[3], temp);
16477169699Skan})
16478169699Skan
16479169699Skan(define_expand "log10df2"
16480169699Skan  [(set (match_dup 2)
16481169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16482169699Skan   (parallel [(set (match_dup 4)
16483169699Skan		   (unspec:XF [(match_dup 2)
16484169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16485169699Skan	      (clobber (match_scratch:XF 5 ""))])
16486169699Skan   (set (match_operand:DF 0 "register_operand" "")
16487169699Skan	(float_truncate:DF (match_dup 4)))]
16488169699Skan  "TARGET_USE_FANCY_MATH_387
16489169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16490132727Skan   && flag_unsafe_math_optimizations"
16491169699Skan{
16492169699Skan  rtx temp;
16493132727Skan
16494169699Skan  operands[2] = gen_reg_rtx (XFmode);
16495169699Skan  operands[3] = gen_reg_rtx (XFmode);
16496169699Skan  operands[4] = gen_reg_rtx (XFmode);
16497169699Skan
16498169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16499169699Skan  emit_move_insn (operands[3], temp);
16500169699Skan})
16501169699Skan
16502169699Skan(define_expand "log10xf2"
16503169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16504169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16505169699Skan			       (match_dup 2)] UNSPEC_FYL2X))
16506169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16507169699Skan  "TARGET_USE_FANCY_MATH_387
16508169699Skan   && flag_unsafe_math_optimizations"
16509169699Skan{
16510169699Skan  rtx temp;
16511169699Skan
16512169699Skan  operands[2] = gen_reg_rtx (XFmode);
16513169699Skan  temp = standard_80387_constant_rtx (3); /* fldlg2 */
16514169699Skan  emit_move_insn (operands[2], temp);
16515169699Skan})
16516169699Skan
16517169699Skan(define_expand "log2sf2"
16518169699Skan  [(set (match_dup 2)
16519169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16520169699Skan   (parallel [(set (match_dup 4)
16521169699Skan		   (unspec:XF [(match_dup 2)
16522169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16523169699Skan	      (clobber (match_scratch:XF 5 ""))])
16524169699Skan   (set (match_operand:SF 0 "register_operand" "")
16525169699Skan	(float_truncate:SF (match_dup 4)))]
16526169699Skan  "TARGET_USE_FANCY_MATH_387
16527169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16528169699Skan   && flag_unsafe_math_optimizations"
16529169699Skan{
16530169699Skan  operands[2] = gen_reg_rtx (XFmode);
16531169699Skan  operands[3] = gen_reg_rtx (XFmode);
16532169699Skan  operands[4] = gen_reg_rtx (XFmode);
16533169699Skan
16534169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16535169699Skan})
16536169699Skan
16537169699Skan(define_expand "log2df2"
16538169699Skan  [(set (match_dup 2)
16539169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16540169699Skan   (parallel [(set (match_dup 4)
16541169699Skan		   (unspec:XF [(match_dup 2)
16542169699Skan			       (match_dup 3)] UNSPEC_FYL2X))
16543169699Skan	      (clobber (match_scratch:XF 5 ""))])
16544169699Skan   (set (match_operand:DF 0 "register_operand" "")
16545169699Skan	(float_truncate:DF (match_dup 4)))]
16546169699Skan  "TARGET_USE_FANCY_MATH_387
16547169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16548169699Skan   && flag_unsafe_math_optimizations"
16549169699Skan{
16550169699Skan  operands[2] = gen_reg_rtx (XFmode);
16551169699Skan  operands[3] = gen_reg_rtx (XFmode);
16552169699Skan  operands[4] = gen_reg_rtx (XFmode);
16553169699Skan
16554169699Skan  emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
16555169699Skan})
16556169699Skan
16557169699Skan(define_expand "log2xf2"
16558169699Skan  [(parallel [(set (match_operand:XF 0 "register_operand" "")
16559169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
16560169699Skan			       (match_dup 2)] UNSPEC_FYL2X))
16561169699Skan	      (clobber (match_scratch:XF 3 ""))])]
16562169699Skan  "TARGET_USE_FANCY_MATH_387
16563169699Skan   && flag_unsafe_math_optimizations"
16564169699Skan{
16565169699Skan  operands[2] = gen_reg_rtx (XFmode);
16566169699Skan  emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
16567169699Skan})
16568169699Skan
16569169699Skan(define_insn "fyl2xp1_xf3"
16570132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16571169699Skan        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
16572132727Skan		    (match_operand:XF 1 "register_operand" "u")]
16573169699Skan	           UNSPEC_FYL2XP1))
16574132727Skan   (clobber (match_scratch:XF 3 "=1"))]
16575169699Skan  "TARGET_USE_FANCY_MATH_387
16576132727Skan   && flag_unsafe_math_optimizations"
16577169699Skan  "fyl2xp1"
16578132727Skan  [(set_attr "type" "fpspc")
16579132727Skan   (set_attr "mode" "XF")])
16580132727Skan
16581169699Skan(define_expand "log1psf2"
16582169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
16583169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
16584169699Skan  "TARGET_USE_FANCY_MATH_387
16585169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16586169699Skan   && flag_unsafe_math_optimizations"
16587169699Skan{
16588169699Skan  rtx op0 = gen_reg_rtx (XFmode);
16589169699Skan  rtx op1 = gen_reg_rtx (XFmode);
16590169699Skan
16591169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
16592169699Skan  ix86_emit_i387_log1p (op0, op1);
16593169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
16594169699Skan  DONE;
16595169699Skan})
16596169699Skan
16597169699Skan(define_expand "log1pdf2"
16598169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
16599169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
16600169699Skan  "TARGET_USE_FANCY_MATH_387
16601169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16602169699Skan   && flag_unsafe_math_optimizations"
16603169699Skan{
16604169699Skan  rtx op0 = gen_reg_rtx (XFmode);
16605169699Skan  rtx op1 = gen_reg_rtx (XFmode);
16606169699Skan
16607169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
16608169699Skan  ix86_emit_i387_log1p (op0, op1);
16609169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
16610169699Skan  DONE;
16611169699Skan})
16612169699Skan
16613169699Skan(define_expand "log1pxf2"
16614169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
16615169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
16616169699Skan  "TARGET_USE_FANCY_MATH_387
16617169699Skan   && flag_unsafe_math_optimizations"
16618169699Skan{
16619169699Skan  ix86_emit_i387_log1p (operands[0], operands[1]);
16620169699Skan  DONE;
16621169699Skan})
16622169699Skan
16623169699Skan(define_insn "*fxtractxf3"
16624132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16625169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
16626169699Skan		   UNSPEC_XTRACT_FRACT))
16627169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16628169699Skan        (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))]
16629169699Skan  "TARGET_USE_FANCY_MATH_387
16630132727Skan   && flag_unsafe_math_optimizations"
16631169699Skan  "fxtract"
16632132727Skan  [(set_attr "type" "fpspc")
16633132727Skan   (set_attr "mode" "XF")])
16634132727Skan
16635169699Skan(define_expand "logbsf2"
16636169699Skan  [(set (match_dup 2)
16637169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16638169699Skan   (parallel [(set (match_dup 3)
16639169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
16640169699Skan	      (set (match_dup 4)
16641169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
16642169699Skan   (set (match_operand:SF 0 "register_operand" "")
16643169699Skan	(float_truncate:SF (match_dup 4)))]
16644169699Skan  "TARGET_USE_FANCY_MATH_387
16645169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16646169699Skan   && flag_unsafe_math_optimizations"
16647169699Skan{
16648169699Skan  operands[2] = gen_reg_rtx (XFmode);
16649169699Skan  operands[3] = gen_reg_rtx (XFmode);
16650169699Skan  operands[4] = gen_reg_rtx (XFmode);
16651169699Skan})
16652169699Skan
16653169699Skan(define_expand "logbdf2"
16654169699Skan  [(set (match_dup 2)
16655169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16656169699Skan   (parallel [(set (match_dup 3)
16657169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
16658169699Skan	      (set (match_dup 4)
16659169699Skan		   (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
16660169699Skan   (set (match_operand:DF 0 "register_operand" "")
16661169699Skan	(float_truncate:DF (match_dup 4)))]
16662169699Skan  "TARGET_USE_FANCY_MATH_387
16663169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16664169699Skan   && flag_unsafe_math_optimizations"
16665169699Skan{
16666169699Skan  operands[2] = gen_reg_rtx (XFmode);
16667169699Skan  operands[3] = gen_reg_rtx (XFmode);
16668169699Skan  operands[4] = gen_reg_rtx (XFmode);
16669169699Skan})
16670169699Skan
16671169699Skan(define_expand "logbxf2"
16672169699Skan  [(parallel [(set (match_dup 2)
16673169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16674169699Skan			      UNSPEC_XTRACT_FRACT))
16675169699Skan	      (set (match_operand:XF 0 "register_operand" "")
16676169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])]
16677169699Skan  "TARGET_USE_FANCY_MATH_387
16678169699Skan   && flag_unsafe_math_optimizations"
16679169699Skan{
16680169699Skan  operands[2] = gen_reg_rtx (XFmode);
16681169699Skan})
16682169699Skan
16683169699Skan(define_expand "ilogbsi2"
16684169699Skan  [(parallel [(set (match_dup 2)
16685169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")]
16686169699Skan			      UNSPEC_XTRACT_FRACT))
16687169699Skan	      (set (match_operand:XF 3 "register_operand" "")
16688169699Skan		   (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])
16689169699Skan   (parallel [(set (match_operand:SI 0 "register_operand" "")
16690169699Skan	           (fix:SI (match_dup 3)))
16691169699Skan	      (clobber (reg:CC FLAGS_REG))])]
16692169699Skan  "TARGET_USE_FANCY_MATH_387
16693169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16694169699Skan   && flag_unsafe_math_optimizations"
16695169699Skan{
16696169699Skan  operands[2] = gen_reg_rtx (XFmode);
16697169699Skan  operands[3] = gen_reg_rtx (XFmode);
16698169699Skan})
16699169699Skan
16700132727Skan(define_insn "*f2xm1xf2"
16701132727Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16702132727Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
16703132727Skan	 UNSPEC_F2XM1))]
16704169699Skan  "TARGET_USE_FANCY_MATH_387
16705132727Skan   && flag_unsafe_math_optimizations"
16706132727Skan  "f2xm1"
16707132727Skan  [(set_attr "type" "fpspc")
16708132727Skan   (set_attr "mode" "XF")])
16709132727Skan
16710169699Skan(define_insn "*fscalexf4"
16711169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
16712169699Skan	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
16713169699Skan		    (match_operand:XF 3 "register_operand" "1")]
16714169699Skan		   UNSPEC_FSCALE_FRACT))
16715169699Skan   (set (match_operand:XF 1 "register_operand" "=u")
16716169699Skan	(unspec:XF [(match_dup 2) (match_dup 3)]
16717169699Skan		   UNSPEC_FSCALE_EXP))]
16718169699Skan  "TARGET_USE_FANCY_MATH_387
16719169699Skan   && flag_unsafe_math_optimizations"
16720169699Skan  "fscale"
16721169699Skan  [(set_attr "type" "fpspc")
16722169699Skan   (set_attr "mode" "XF")])
16723169699Skan
16724132727Skan(define_expand "expsf2"
16725132727Skan  [(set (match_dup 2)
16726132727Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16727132727Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16728132727Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16729132727Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16730132727Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16731132727Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16732169699Skan   (parallel [(set (match_dup 10)
16733169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16734169699Skan			      UNSPEC_FSCALE_FRACT))
16735169699Skan	      (set (match_dup 11)
16736169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16737169699Skan			      UNSPEC_FSCALE_EXP))])
16738169699Skan   (set (match_operand:SF 0 "register_operand" "")
16739169699Skan	(float_truncate:SF (match_dup 10)))]
16740169699Skan  "TARGET_USE_FANCY_MATH_387
16741169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16742132727Skan   && flag_unsafe_math_optimizations"
16743132727Skan{
16744132727Skan  rtx temp;
16745132727Skan  int i;
16746132727Skan
16747169699Skan  for (i=2; i<12; i++)
16748132727Skan    operands[i] = gen_reg_rtx (XFmode);
16749132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
16750132727Skan  emit_move_insn (operands[3], temp);
16751132727Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16752132727Skan})
16753132727Skan
16754132727Skan(define_expand "expdf2"
16755132727Skan  [(set (match_dup 2)
16756132727Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16757132727Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16758132727Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16759132727Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16760132727Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16761132727Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16762169699Skan   (parallel [(set (match_dup 10)
16763169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16764169699Skan			      UNSPEC_FSCALE_FRACT))
16765169699Skan	      (set (match_dup 11)
16766169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16767169699Skan			      UNSPEC_FSCALE_EXP))])
16768169699Skan   (set (match_operand:DF 0 "register_operand" "")
16769169699Skan	(float_truncate:DF (match_dup 10)))]
16770169699Skan  "TARGET_USE_FANCY_MATH_387
16771169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16772132727Skan   && flag_unsafe_math_optimizations"
16773132727Skan{
16774132727Skan  rtx temp;
16775132727Skan  int i;
16776132727Skan
16777169699Skan  for (i=2; i<12; i++)
16778132727Skan    operands[i] = gen_reg_rtx (XFmode);
16779132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
16780132727Skan  emit_move_insn (operands[3], temp);
16781132727Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16782132727Skan})
16783132727Skan
16784132727Skan(define_expand "expxf2"
16785132727Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
16786132727Skan			       (match_dup 2)))
16787132727Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
16788132727Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
16789132727Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
16790132727Skan   (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
16791132727Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16792169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16793169699Skan			      UNSPEC_FSCALE_FRACT))
16794169699Skan	      (set (match_dup 9)
16795169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16796169699Skan			      UNSPEC_FSCALE_EXP))])]
16797169699Skan  "TARGET_USE_FANCY_MATH_387
16798132727Skan   && flag_unsafe_math_optimizations"
16799132727Skan{
16800132727Skan  rtx temp;
16801132727Skan  int i;
16802132727Skan
16803169699Skan  for (i=2; i<10; i++)
16804132727Skan    operands[i] = gen_reg_rtx (XFmode);
16805132727Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
16806132727Skan  emit_move_insn (operands[2], temp);
16807132727Skan  emit_move_insn (operands[7], CONST1_RTX (XFmode));  /* fld1 */
16808132727Skan})
16809132727Skan
16810169699Skan(define_expand "exp10sf2"
16811169699Skan  [(set (match_dup 2)
16812169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16813169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16814169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16815169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16816169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16817169699Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16818169699Skan   (parallel [(set (match_dup 10)
16819169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16820169699Skan			      UNSPEC_FSCALE_FRACT))
16821169699Skan	      (set (match_dup 11)
16822169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16823169699Skan			      UNSPEC_FSCALE_EXP))])
16824169699Skan   (set (match_operand:SF 0 "register_operand" "")
16825169699Skan	(float_truncate:SF (match_dup 10)))]
16826169699Skan  "TARGET_USE_FANCY_MATH_387
16827169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16828132727Skan   && flag_unsafe_math_optimizations"
16829132727Skan{
16830169699Skan  rtx temp;
16831169699Skan  int i;
16832169699Skan
16833169699Skan  for (i=2; i<12; i++)
16834169699Skan    operands[i] = gen_reg_rtx (XFmode);
16835169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
16836169699Skan  emit_move_insn (operands[3], temp);
16837169699Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16838132727Skan})
16839132727Skan
16840169699Skan(define_expand "exp10df2"
16841169699Skan  [(set (match_dup 2)
16842169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16843169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16844169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16845169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16846169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16847169699Skan   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
16848169699Skan   (parallel [(set (match_dup 10)
16849169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16850169699Skan			      UNSPEC_FSCALE_FRACT))
16851169699Skan	      (set (match_dup 11)
16852169699Skan		   (unspec:XF [(match_dup 9) (match_dup 5)]
16853169699Skan			      UNSPEC_FSCALE_EXP))])
16854169699Skan   (set (match_operand:DF 0 "register_operand" "")
16855169699Skan	(float_truncate:DF (match_dup 10)))]
16856169699Skan  "TARGET_USE_FANCY_MATH_387
16857169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16858132727Skan   && flag_unsafe_math_optimizations"
16859132727Skan{
16860169699Skan  rtx temp;
16861169699Skan  int i;
16862169699Skan
16863169699Skan  for (i=2; i<12; i++)
16864169699Skan    operands[i] = gen_reg_rtx (XFmode);
16865169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
16866169699Skan  emit_move_insn (operands[3], temp);
16867169699Skan  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
16868132727Skan})
16869132727Skan
16870169699Skan(define_expand "exp10xf2"
16871169699Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
16872169699Skan			       (match_dup 2)))
16873169699Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
16874169699Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
16875169699Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
16876169699Skan   (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
16877169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16878169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16879169699Skan			      UNSPEC_FSCALE_FRACT))
16880169699Skan	      (set (match_dup 9)
16881169699Skan		   (unspec:XF [(match_dup 8) (match_dup 4)]
16882169699Skan			      UNSPEC_FSCALE_EXP))])]
16883169699Skan  "TARGET_USE_FANCY_MATH_387
16884132727Skan   && flag_unsafe_math_optimizations"
16885132727Skan{
16886169699Skan  rtx temp;
16887169699Skan  int i;
16888169699Skan
16889169699Skan  for (i=2; i<10; i++)
16890169699Skan    operands[i] = gen_reg_rtx (XFmode);
16891169699Skan  temp = standard_80387_constant_rtx (6); /* fldl2t */
16892169699Skan  emit_move_insn (operands[2], temp);
16893169699Skan  emit_move_insn (operands[7], CONST1_RTX (XFmode));  /* fld1 */
16894132727Skan})
16895169699Skan
16896169699Skan(define_expand "exp2sf2"
16897169699Skan  [(set (match_dup 2)
16898169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
16899169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
16900169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
16901169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
16902169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
16903169699Skan   (parallel [(set (match_dup 8)
16904169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16905169699Skan			      UNSPEC_FSCALE_FRACT))
16906169699Skan	      (set (match_dup 9)
16907169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16908169699Skan			      UNSPEC_FSCALE_EXP))])
16909169699Skan   (set (match_operand:SF 0 "register_operand" "")
16910169699Skan	(float_truncate:SF (match_dup 8)))]
16911169699Skan  "TARGET_USE_FANCY_MATH_387
16912169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
16913169699Skan   && flag_unsafe_math_optimizations"
16914169699Skan{
16915169699Skan  int i;
16916169699Skan
16917169699Skan  for (i=2; i<10; i++)
16918169699Skan    operands[i] = gen_reg_rtx (XFmode);
16919169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
16920169699Skan})
16921169699Skan
16922169699Skan(define_expand "exp2df2"
16923169699Skan  [(set (match_dup 2)
16924169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16925169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
16926169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
16927169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
16928169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
16929169699Skan   (parallel [(set (match_dup 8)
16930169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16931169699Skan			      UNSPEC_FSCALE_FRACT))
16932169699Skan	      (set (match_dup 9)
16933169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16934169699Skan			      UNSPEC_FSCALE_EXP))])
16935169699Skan   (set (match_operand:DF 0 "register_operand" "")
16936169699Skan	(float_truncate:DF (match_dup 8)))]
16937169699Skan  "TARGET_USE_FANCY_MATH_387
16938169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16939169699Skan   && flag_unsafe_math_optimizations"
16940169699Skan{
16941169699Skan  int i;
16942169699Skan
16943169699Skan  for (i=2; i<10; i++)
16944169699Skan    operands[i] = gen_reg_rtx (XFmode);
16945169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
16946169699Skan})
16947169699Skan
16948169699Skan(define_expand "exp2xf2"
16949169699Skan  [(set (match_dup 2) (match_operand:XF 1 "register_operand" ""))
16950169699Skan   (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
16951169699Skan   (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
16952169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
16953169699Skan   (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
16954169699Skan   (parallel [(set (match_operand:XF 0 "register_operand" "")
16955169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16956169699Skan			      UNSPEC_FSCALE_FRACT))
16957169699Skan	      (set (match_dup 8)
16958169699Skan		   (unspec:XF [(match_dup 7) (match_dup 3)]
16959169699Skan			      UNSPEC_FSCALE_EXP))])]
16960169699Skan  "TARGET_USE_FANCY_MATH_387
16961169699Skan   && flag_unsafe_math_optimizations"
16962169699Skan{
16963169699Skan  int i;
16964169699Skan
16965169699Skan  for (i=2; i<9; i++)
16966169699Skan    operands[i] = gen_reg_rtx (XFmode);
16967169699Skan  emit_move_insn (operands[6], CONST1_RTX (XFmode));  /* fld1 */
16968169699Skan})
16969169699Skan
16970169699Skan(define_expand "expm1df2"
16971169699Skan  [(set (match_dup 2)
16972169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
16973169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
16974169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
16975169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
16976169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
16977169699Skan   (parallel [(set (match_dup 8)
16978169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
16979169699Skan			      UNSPEC_FSCALE_FRACT))
16980169699Skan		   (set (match_dup 9)
16981169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
16982169699Skan			      UNSPEC_FSCALE_EXP))])
16983169699Skan   (parallel [(set (match_dup 11)
16984169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
16985169699Skan			      UNSPEC_FSCALE_FRACT))
16986169699Skan	      (set (match_dup 12)
16987169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
16988169699Skan			      UNSPEC_FSCALE_EXP))])
16989169699Skan   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
16990169699Skan   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
16991169699Skan   (set (match_operand:DF 0 "register_operand" "")
16992169699Skan	(float_truncate:DF (match_dup 14)))]
16993169699Skan  "TARGET_USE_FANCY_MATH_387
16994169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
16995169699Skan   && flag_unsafe_math_optimizations"
16996169699Skan{
16997169699Skan  rtx temp;
16998169699Skan  int i;
16999169699Skan
17000169699Skan  for (i=2; i<15; i++)
17001169699Skan    operands[i] = gen_reg_rtx (XFmode);
17002169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17003169699Skan  emit_move_insn (operands[3], temp);
17004169699Skan  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
17005169699Skan})
17006169699Skan
17007169699Skan(define_expand "expm1sf2"
17008169699Skan  [(set (match_dup 2)
17009169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17010169699Skan   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
17011169699Skan   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
17012169699Skan   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
17013169699Skan   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
17014169699Skan   (parallel [(set (match_dup 8)
17015169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17016169699Skan			      UNSPEC_FSCALE_FRACT))
17017169699Skan		   (set (match_dup 9)
17018169699Skan		   (unspec:XF [(match_dup 7) (match_dup 5)]
17019169699Skan			      UNSPEC_FSCALE_EXP))])
17020169699Skan   (parallel [(set (match_dup 11)
17021169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17022169699Skan			      UNSPEC_FSCALE_FRACT))
17023169699Skan	      (set (match_dup 12)
17024169699Skan		   (unspec:XF [(match_dup 10) (match_dup 9)]
17025169699Skan			      UNSPEC_FSCALE_EXP))])
17026169699Skan   (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
17027169699Skan   (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
17028169699Skan   (set (match_operand:SF 0 "register_operand" "")
17029169699Skan	(float_truncate:SF (match_dup 14)))]
17030169699Skan  "TARGET_USE_FANCY_MATH_387
17031169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17032169699Skan   && flag_unsafe_math_optimizations"
17033169699Skan{
17034169699Skan  rtx temp;
17035169699Skan  int i;
17036169699Skan
17037169699Skan  for (i=2; i<15; i++)
17038169699Skan    operands[i] = gen_reg_rtx (XFmode);
17039169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17040169699Skan  emit_move_insn (operands[3], temp);
17041169699Skan  emit_move_insn (operands[10], CONST1_RTX (XFmode));  /* fld1 */
17042169699Skan})
17043169699Skan
17044169699Skan(define_expand "expm1xf2"
17045169699Skan  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
17046169699Skan			       (match_dup 2)))
17047169699Skan   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
17048169699Skan   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
17049169699Skan   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
17050169699Skan   (parallel [(set (match_dup 7)
17051169699Skan		   (unspec:XF [(match_dup 6) (match_dup 4)]
17052169699Skan			      UNSPEC_FSCALE_FRACT))
17053169699Skan		   (set (match_dup 8)
17054169699Skan		   (unspec:XF [(match_dup 6) (match_dup 4)]
17055169699Skan			      UNSPEC_FSCALE_EXP))])
17056169699Skan   (parallel [(set (match_dup 10)
17057169699Skan		   (unspec:XF [(match_dup 9) (match_dup 8)]
17058169699Skan			      UNSPEC_FSCALE_FRACT))
17059169699Skan	      (set (match_dup 11)
17060169699Skan		   (unspec:XF [(match_dup 9) (match_dup 8)]
17061169699Skan			      UNSPEC_FSCALE_EXP))])
17062169699Skan   (set (match_dup 12) (minus:XF (match_dup 10) (match_dup 9)))
17063169699Skan   (set (match_operand:XF 0 "register_operand" "")
17064169699Skan	(plus:XF (match_dup 12) (match_dup 7)))]
17065169699Skan  "TARGET_USE_FANCY_MATH_387
17066169699Skan   && flag_unsafe_math_optimizations"
17067169699Skan{
17068169699Skan  rtx temp;
17069169699Skan  int i;
17070169699Skan
17071169699Skan  for (i=2; i<13; i++)
17072169699Skan    operands[i] = gen_reg_rtx (XFmode);
17073169699Skan  temp = standard_80387_constant_rtx (5); /* fldl2e */
17074169699Skan  emit_move_insn (operands[2], temp);
17075169699Skan  emit_move_insn (operands[9], CONST1_RTX (XFmode));  /* fld1 */
17076169699Skan})
17077169699Skan
17078169699Skan(define_expand "ldexpdf3"
17079169699Skan  [(set (match_dup 3)
17080169699Skan	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
17081169699Skan   (set (match_dup 4)
17082169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17083169699Skan   (parallel [(set (match_dup 5)
17084169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17085169699Skan			      UNSPEC_FSCALE_FRACT))
17086169699Skan	      (set (match_dup 6)
17087169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17088169699Skan			      UNSPEC_FSCALE_EXP))])
17089169699Skan   (set (match_operand:DF 0 "register_operand" "")
17090169699Skan	(float_truncate:DF (match_dup 5)))]
17091169699Skan  "TARGET_USE_FANCY_MATH_387
17092169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17093169699Skan   && flag_unsafe_math_optimizations"
17094169699Skan{
17095169699Skan  int i;
17096169699Skan
17097169699Skan  for (i=3; i<7; i++)
17098169699Skan    operands[i] = gen_reg_rtx (XFmode);
17099169699Skan})
17100169699Skan
17101169699Skan(define_expand "ldexpsf3"
17102169699Skan  [(set (match_dup 3)
17103169699Skan	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
17104169699Skan   (set (match_dup 4)
17105169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17106169699Skan   (parallel [(set (match_dup 5)
17107169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17108169699Skan			      UNSPEC_FSCALE_FRACT))
17109169699Skan	      (set (match_dup 6)
17110169699Skan		   (unspec:XF [(match_dup 3) (match_dup 4)]
17111169699Skan			      UNSPEC_FSCALE_EXP))])
17112169699Skan   (set (match_operand:SF 0 "register_operand" "")
17113169699Skan	(float_truncate:SF (match_dup 5)))]
17114169699Skan  "TARGET_USE_FANCY_MATH_387
17115169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17116169699Skan   && flag_unsafe_math_optimizations"
17117169699Skan{
17118169699Skan  int i;
17119169699Skan
17120169699Skan  for (i=3; i<7; i++)
17121169699Skan    operands[i] = gen_reg_rtx (XFmode);
17122169699Skan})
17123169699Skan
17124169699Skan(define_expand "ldexpxf3"
17125169699Skan  [(set (match_dup 3)
17126169699Skan	(float:XF (match_operand:SI 2 "register_operand" "")))
17127169699Skan   (parallel [(set (match_operand:XF 0 " register_operand" "")
17128169699Skan		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
17129169699Skan			       (match_dup 3)]
17130169699Skan			      UNSPEC_FSCALE_FRACT))
17131169699Skan	      (set (match_dup 4)
17132169699Skan		   (unspec:XF [(match_dup 1) (match_dup 3)]
17133169699Skan			      UNSPEC_FSCALE_EXP))])]
17134169699Skan  "TARGET_USE_FANCY_MATH_387
17135169699Skan   && flag_unsafe_math_optimizations"
17136169699Skan{
17137169699Skan  int i;
17138169699Skan
17139169699Skan  for (i=3; i<5; i++)
17140169699Skan    operands[i] = gen_reg_rtx (XFmode);
17141169699Skan})
1714290286Sobrien
17143169699Skan
17144169699Skan(define_insn "frndintxf2"
17145169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17146169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17147169699Skan	 UNSPEC_FRNDINT))]
17148169699Skan  "TARGET_USE_FANCY_MATH_387
17149169699Skan   && flag_unsafe_math_optimizations"
17150169699Skan  "frndint"
17151169699Skan  [(set_attr "type" "fpspc")
17152169699Skan   (set_attr "mode" "XF")])
17153169699Skan
17154169699Skan(define_expand "rintdf2"
17155169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17156169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17157169699Skan  "TARGET_USE_FANCY_MATH_387
17158169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17159169699Skan   && flag_unsafe_math_optimizations"
17160169699Skan{
17161169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17162169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17163169699Skan
17164169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17165169699Skan  emit_insn (gen_frndintxf2 (op0, op1));
17166169699Skan
17167169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17168169699Skan  DONE;
17169169699Skan})
17170169699Skan
17171169699Skan(define_expand "rintsf2"
17172169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17173169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17174169699Skan  "TARGET_USE_FANCY_MATH_387
17175169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17176169699Skan   && flag_unsafe_math_optimizations"
17177169699Skan{
17178169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17179169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17180169699Skan
17181169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17182169699Skan  emit_insn (gen_frndintxf2 (op0, op1));
17183169699Skan
17184169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17185169699Skan  DONE;
17186169699Skan})
17187169699Skan
17188169699Skan(define_expand "rintxf2"
17189169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17190169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17191169699Skan  "TARGET_USE_FANCY_MATH_387
17192169699Skan   && flag_unsafe_math_optimizations"
17193169699Skan{
17194169699Skan  emit_insn (gen_frndintxf2 (operands[0], operands[1]));
17195169699Skan  DONE;
17196169699Skan})
17197169699Skan
17198169699Skan(define_insn_and_split "*fistdi2_1"
17199169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17200169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17201169699Skan	 UNSPEC_FIST))]
17202169699Skan  "TARGET_USE_FANCY_MATH_387
17203169699Skan   && flag_unsafe_math_optimizations
17204169699Skan   && !(reload_completed || reload_in_progress)"
17205169699Skan  "#"
17206169699Skan  "&& 1"
17207169699Skan  [(const_int 0)]
17208169699Skan{
17209169699Skan  if (memory_operand (operands[0], VOIDmode))
17210169699Skan    emit_insn (gen_fistdi2 (operands[0], operands[1]));
17211169699Skan  else
17212169699Skan    {
17213169699Skan      operands[2] = assign_386_stack_local (DImode, SLOT_TEMP);
17214169699Skan      emit_insn (gen_fistdi2_with_temp (operands[0], operands[1],
17215169699Skan					 operands[2]));
17216169699Skan    }
17217169699Skan  DONE;
17218169699Skan}
17219169699Skan  [(set_attr "type" "fpspc")
17220169699Skan   (set_attr "mode" "DI")])
17221169699Skan
17222169699Skan(define_insn "fistdi2"
17223169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17224169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17225169699Skan	 UNSPEC_FIST))
17226169699Skan   (clobber (match_scratch:XF 2 "=&1f"))]
17227169699Skan  "TARGET_USE_FANCY_MATH_387
17228169699Skan   && flag_unsafe_math_optimizations"
17229169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17230169699Skan  [(set_attr "type" "fpspc")
17231169699Skan   (set_attr "mode" "DI")])
17232169699Skan
17233169699Skan(define_insn "fistdi2_with_temp"
17234169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17235169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17236169699Skan	 UNSPEC_FIST))
17237169699Skan   (clobber (match_operand:DI 2 "memory_operand" "=m,m"))
17238169699Skan   (clobber (match_scratch:XF 3 "=&1f,&1f"))]
17239169699Skan  "TARGET_USE_FANCY_MATH_387
17240169699Skan   && flag_unsafe_math_optimizations"
17241169699Skan  "#"
17242169699Skan  [(set_attr "type" "fpspc")
17243169699Skan   (set_attr "mode" "DI")])
17244169699Skan
17245169699Skan(define_split 
17246169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17247169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17248169699Skan	 UNSPEC_FIST))
17249169699Skan   (clobber (match_operand:DI 2 "memory_operand" ""))
17250169699Skan   (clobber (match_scratch 3 ""))]
17251169699Skan  "reload_completed"
17252169699Skan  [(parallel [(set (match_dup 2) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
17253169699Skan	      (clobber (match_dup 3))])
17254169699Skan   (set (match_dup 0) (match_dup 2))]
17255169699Skan  "")
17256169699Skan
17257169699Skan(define_split 
17258169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17259169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17260169699Skan	 UNSPEC_FIST))
17261169699Skan   (clobber (match_operand:DI 2 "memory_operand" ""))
17262169699Skan   (clobber (match_scratch 3 ""))]
17263169699Skan  "reload_completed"
17264169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
17265169699Skan	      (clobber (match_dup 3))])]
17266169699Skan  "")
17267169699Skan
17268169699Skan(define_insn_and_split "*fist<mode>2_1"
17269169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
17270169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17271169699Skan	 UNSPEC_FIST))]
17272169699Skan  "TARGET_USE_FANCY_MATH_387
17273169699Skan   && flag_unsafe_math_optimizations
17274169699Skan   && !(reload_completed || reload_in_progress)"
17275169699Skan  "#"
17276169699Skan  "&& 1"
17277169699Skan  [(const_int 0)]
17278169699Skan{
17279169699Skan  operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17280169699Skan  emit_insn (gen_fist<mode>2_with_temp (operands[0], operands[1],
17281169699Skan					operands[2]));
17282169699Skan  DONE;
17283169699Skan}
17284169699Skan  [(set_attr "type" "fpspc")
17285169699Skan   (set_attr "mode" "<MODE>")])
17286169699Skan
17287169699Skan(define_insn "fist<mode>2"
17288169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17289169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17290169699Skan	 UNSPEC_FIST))]
17291169699Skan  "TARGET_USE_FANCY_MATH_387
17292169699Skan   && flag_unsafe_math_optimizations"
17293169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17294169699Skan  [(set_attr "type" "fpspc")
17295169699Skan   (set_attr "mode" "<MODE>")])
17296169699Skan
17297169699Skan(define_insn "fist<mode>2_with_temp"
17298169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
17299169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17300169699Skan	 UNSPEC_FIST))
17301169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" "=m"))]
17302169699Skan  "TARGET_USE_FANCY_MATH_387
17303169699Skan   && flag_unsafe_math_optimizations"
17304169699Skan  "#"
17305169699Skan  [(set_attr "type" "fpspc")
17306169699Skan   (set_attr "mode" "<MODE>")])
17307169699Skan
17308169699Skan(define_split 
17309169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17310169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17311169699Skan	 UNSPEC_FIST))
17312169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
17313169699Skan  "reload_completed"
17314169699Skan  [(set (match_dup 2) (unspec:X87MODEI12 [(match_dup 1)]
17315169699Skan		       UNSPEC_FIST))
17316169699Skan   (set (match_dup 0) (match_dup 2))]
17317169699Skan  "")
17318169699Skan
17319169699Skan(define_split 
17320169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17321169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17322169699Skan	 UNSPEC_FIST))
17323169699Skan   (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
17324169699Skan  "reload_completed"
17325169699Skan  [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17326169699Skan		       UNSPEC_FIST))]
17327169699Skan  "")
17328169699Skan
17329169699Skan(define_expand "lrint<mode>2"
17330169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17331169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17332169699Skan	 UNSPEC_FIST))]
17333169699Skan  "TARGET_USE_FANCY_MATH_387
17334169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17335169699Skan   && flag_unsafe_math_optimizations"
17336169699Skan  "")
17337169699Skan
17338169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17339169699Skan(define_insn_and_split "frndintxf2_floor"
17340169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17341169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17342169699Skan	 UNSPEC_FRNDINT_FLOOR))
17343169699Skan   (clobber (reg:CC FLAGS_REG))]
17344169699Skan  "TARGET_USE_FANCY_MATH_387
17345169699Skan   && flag_unsafe_math_optimizations
17346169699Skan   && !(reload_completed || reload_in_progress)"
17347169699Skan  "#"
17348169699Skan  "&& 1"
17349169699Skan  [(const_int 0)]
17350169699Skan{
17351169699Skan  ix86_optimize_mode_switching[I387_FLOOR] = 1;
17352169699Skan
17353169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17354169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
17355169699Skan
17356169699Skan  emit_insn (gen_frndintxf2_floor_i387 (operands[0], operands[1],
17357169699Skan					operands[2], operands[3]));
17358169699Skan  DONE;
17359169699Skan}
17360169699Skan  [(set_attr "type" "frndint")
17361169699Skan   (set_attr "i387_cw" "floor")
17362169699Skan   (set_attr "mode" "XF")])
17363169699Skan
17364169699Skan(define_insn "frndintxf2_floor_i387"
17365169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17366169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17367169699Skan	 UNSPEC_FRNDINT_FLOOR))
17368169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17369169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17370169699Skan  "TARGET_USE_FANCY_MATH_387
17371169699Skan   && flag_unsafe_math_optimizations"
17372169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17373169699Skan  [(set_attr "type" "frndint")
17374169699Skan   (set_attr "i387_cw" "floor")
17375169699Skan   (set_attr "mode" "XF")])
17376169699Skan
17377169699Skan(define_expand "floorxf2"
17378169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17379169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17380169699Skan  "TARGET_USE_FANCY_MATH_387
17381169699Skan   && flag_unsafe_math_optimizations"
17382169699Skan{
17383169699Skan  emit_insn (gen_frndintxf2_floor (operands[0], operands[1]));
17384169699Skan  DONE;
17385169699Skan})
17386169699Skan
17387169699Skan(define_expand "floordf2"
17388169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17389169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17390169699Skan  "TARGET_USE_FANCY_MATH_387
17391169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17392169699Skan   && flag_unsafe_math_optimizations"
17393169699Skan{
17394169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17395169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17396169699Skan
17397169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17398169699Skan  emit_insn (gen_frndintxf2_floor (op0, op1));
17399169699Skan
17400169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17401169699Skan  DONE;
17402169699Skan})
17403169699Skan
17404169699Skan(define_expand "floorsf2"
17405169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17406169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17407169699Skan  "TARGET_USE_FANCY_MATH_387
17408169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17409169699Skan   && flag_unsafe_math_optimizations"
17410169699Skan{
17411169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17412169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17413169699Skan
17414169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17415169699Skan  emit_insn (gen_frndintxf2_floor (op0, op1));
17416169699Skan
17417169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17418169699Skan  DONE;
17419169699Skan})
17420169699Skan
17421169699Skan(define_insn_and_split "*fist<mode>2_floor_1"
17422169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
17423169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
17424169699Skan	 UNSPEC_FIST_FLOOR))
17425169699Skan   (clobber (reg:CC FLAGS_REG))]
17426169699Skan  "TARGET_USE_FANCY_MATH_387
17427169699Skan   && flag_unsafe_math_optimizations
17428169699Skan   && !(reload_completed || reload_in_progress)"
17429169699Skan  "#"
17430169699Skan  "&& 1"
17431169699Skan  [(const_int 0)]
17432169699Skan{
17433169699Skan  ix86_optimize_mode_switching[I387_FLOOR] = 1;
17434169699Skan
17435169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17436169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
17437169699Skan  if (memory_operand (operands[0], VOIDmode))
17438169699Skan    emit_insn (gen_fist<mode>2_floor (operands[0], operands[1],
17439169699Skan				      operands[2], operands[3]));
17440169699Skan  else
17441169699Skan    {
17442169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17443169699Skan      emit_insn (gen_fist<mode>2_floor_with_temp (operands[0], operands[1],
17444169699Skan						  operands[2], operands[3],
17445169699Skan						  operands[4]));
17446169699Skan    }
17447169699Skan  DONE;
17448169699Skan}
17449169699Skan  [(set_attr "type" "fistp")
17450169699Skan   (set_attr "i387_cw" "floor")
17451169699Skan   (set_attr "mode" "<MODE>")])
17452169699Skan
17453169699Skan(define_insn "fistdi2_floor"
17454169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17455169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17456169699Skan	 UNSPEC_FIST_FLOOR))
17457169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17458169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
17459169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
17460169699Skan  "TARGET_USE_FANCY_MATH_387
17461169699Skan   && flag_unsafe_math_optimizations"
17462169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17463169699Skan  [(set_attr "type" "fistp")
17464169699Skan   (set_attr "i387_cw" "floor")
17465169699Skan   (set_attr "mode" "DI")])
17466169699Skan
17467169699Skan(define_insn "fistdi2_floor_with_temp"
17468169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17469169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17470169699Skan	 UNSPEC_FIST_FLOOR))
17471169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17472169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17473169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
17474169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
17475169699Skan  "TARGET_USE_FANCY_MATH_387
17476169699Skan   && flag_unsafe_math_optimizations"
17477169699Skan  "#"
17478169699Skan  [(set_attr "type" "fistp")
17479169699Skan   (set_attr "i387_cw" "floor")
17480169699Skan   (set_attr "mode" "DI")])
17481169699Skan
17482169699Skan(define_split 
17483169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17484169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17485169699Skan	 UNSPEC_FIST_FLOOR))
17486169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17487169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17488169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17489169699Skan   (clobber (match_scratch 5 ""))]
17490169699Skan  "reload_completed"
17491169699Skan  [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
17492169699Skan	      (use (match_dup 2))
17493169699Skan	      (use (match_dup 3))
17494169699Skan	      (clobber (match_dup 5))])
17495169699Skan   (set (match_dup 0) (match_dup 4))]
17496169699Skan  "")
17497169699Skan
17498169699Skan(define_split 
17499169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17500169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17501169699Skan	 UNSPEC_FIST_FLOOR))
17502169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17503169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17504169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17505169699Skan   (clobber (match_scratch 5 ""))]
17506169699Skan  "reload_completed"
17507169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
17508169699Skan	      (use (match_dup 2))
17509169699Skan	      (use (match_dup 3))
17510169699Skan	      (clobber (match_dup 5))])]
17511169699Skan  "")
17512169699Skan
17513169699Skan(define_insn "fist<mode>2_floor"
17514169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17515169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17516169699Skan	 UNSPEC_FIST_FLOOR))
17517169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17518169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17519169699Skan  "TARGET_USE_FANCY_MATH_387
17520169699Skan   && flag_unsafe_math_optimizations"
17521169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17522169699Skan  [(set_attr "type" "fistp")
17523169699Skan   (set_attr "i387_cw" "floor")
17524169699Skan   (set_attr "mode" "<MODE>")])
17525169699Skan
17526169699Skan(define_insn "fist<mode>2_floor_with_temp"
17527169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
17528169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
17529169699Skan	 UNSPEC_FIST_FLOOR))
17530169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17531169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17532169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
17533169699Skan  "TARGET_USE_FANCY_MATH_387
17534169699Skan   && flag_unsafe_math_optimizations"
17535169699Skan  "#"
17536169699Skan  [(set_attr "type" "fistp")
17537169699Skan   (set_attr "i387_cw" "floor")
17538169699Skan   (set_attr "mode" "<MODE>")])
17539169699Skan
17540169699Skan(define_split 
17541169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17542169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17543169699Skan	 UNSPEC_FIST_FLOOR))
17544169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17545169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17546169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17547169699Skan  "reload_completed"
17548169699Skan  [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
17549169699Skan				  UNSPEC_FIST_FLOOR))
17550169699Skan	      (use (match_dup 2))
17551169699Skan	      (use (match_dup 3))])
17552169699Skan   (set (match_dup 0) (match_dup 4))]
17553169699Skan  "")
17554169699Skan
17555169699Skan(define_split 
17556169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17557169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17558169699Skan	 UNSPEC_FIST_FLOOR))
17559169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17560169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17561169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17562169699Skan  "reload_completed"
17563169699Skan  [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17564169699Skan				  UNSPEC_FIST_FLOOR))
17565169699Skan	      (use (match_dup 2))
17566169699Skan	      (use (match_dup 3))])]
17567169699Skan  "")
17568169699Skan
17569169699Skan(define_expand "lfloor<mode>2"
17570169699Skan  [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17571169699Skan		   (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17572169699Skan		    UNSPEC_FIST_FLOOR))
17573169699Skan	      (clobber (reg:CC FLAGS_REG))])]
17574169699Skan  "TARGET_USE_FANCY_MATH_387
17575169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17576169699Skan   && flag_unsafe_math_optimizations"
17577169699Skan  "")
17578169699Skan
17579169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17580169699Skan(define_insn_and_split "frndintxf2_ceil"
17581169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17582169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17583169699Skan	 UNSPEC_FRNDINT_CEIL))
17584169699Skan   (clobber (reg:CC FLAGS_REG))]
17585169699Skan  "TARGET_USE_FANCY_MATH_387
17586169699Skan   && flag_unsafe_math_optimizations
17587169699Skan   && !(reload_completed || reload_in_progress)"
17588169699Skan  "#"
17589169699Skan  "&& 1"
17590169699Skan  [(const_int 0)]
17591169699Skan{
17592169699Skan  ix86_optimize_mode_switching[I387_CEIL] = 1;
17593169699Skan
17594169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17595169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
17596169699Skan
17597169699Skan  emit_insn (gen_frndintxf2_ceil_i387 (operands[0], operands[1],
17598169699Skan				       operands[2], operands[3]));
17599169699Skan  DONE;
17600169699Skan}
17601169699Skan  [(set_attr "type" "frndint")
17602169699Skan   (set_attr "i387_cw" "ceil")
17603169699Skan   (set_attr "mode" "XF")])
17604169699Skan
17605169699Skan(define_insn "frndintxf2_ceil_i387"
17606169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17607169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17608169699Skan	 UNSPEC_FRNDINT_CEIL))
17609169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17610169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17611169699Skan  "TARGET_USE_FANCY_MATH_387
17612169699Skan   && flag_unsafe_math_optimizations"
17613169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17614169699Skan  [(set_attr "type" "frndint")
17615169699Skan   (set_attr "i387_cw" "ceil")
17616169699Skan   (set_attr "mode" "XF")])
17617169699Skan
17618169699Skan(define_expand "ceilxf2"
17619169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17620169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17621169699Skan  "TARGET_USE_FANCY_MATH_387
17622169699Skan   && flag_unsafe_math_optimizations"
17623169699Skan{
17624169699Skan  emit_insn (gen_frndintxf2_ceil (operands[0], operands[1]));
17625169699Skan  DONE;
17626169699Skan})
17627169699Skan
17628169699Skan(define_expand "ceildf2"
17629169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17630169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17631169699Skan  "TARGET_USE_FANCY_MATH_387
17632169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17633169699Skan   && flag_unsafe_math_optimizations"
17634169699Skan{
17635169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17636169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17637169699Skan
17638169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17639169699Skan  emit_insn (gen_frndintxf2_ceil (op0, op1));
17640169699Skan
17641169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17642169699Skan  DONE;
17643169699Skan})
17644169699Skan
17645169699Skan(define_expand "ceilsf2"
17646169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17647169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17648169699Skan  "TARGET_USE_FANCY_MATH_387
17649169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17650169699Skan   && flag_unsafe_math_optimizations"
17651169699Skan{
17652169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17653169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17654169699Skan
17655169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17656169699Skan  emit_insn (gen_frndintxf2_ceil (op0, op1));
17657169699Skan
17658169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17659169699Skan  DONE;
17660169699Skan})
17661169699Skan
17662169699Skan(define_insn_and_split "*fist<mode>2_ceil_1"
17663169699Skan  [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
17664169699Skan	(unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
17665169699Skan	 UNSPEC_FIST_CEIL))
17666169699Skan   (clobber (reg:CC FLAGS_REG))]
17667169699Skan  "TARGET_USE_FANCY_MATH_387
17668169699Skan   && flag_unsafe_math_optimizations
17669169699Skan   && !(reload_completed || reload_in_progress)"
17670169699Skan  "#"
17671169699Skan  "&& 1"
17672169699Skan  [(const_int 0)]
17673169699Skan{
17674169699Skan  ix86_optimize_mode_switching[I387_CEIL] = 1;
17675169699Skan
17676169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17677169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
17678169699Skan  if (memory_operand (operands[0], VOIDmode))
17679169699Skan    emit_insn (gen_fist<mode>2_ceil (operands[0], operands[1],
17680169699Skan				     operands[2], operands[3]));
17681169699Skan  else
17682169699Skan    {
17683169699Skan      operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
17684169699Skan      emit_insn (gen_fist<mode>2_ceil_with_temp (operands[0], operands[1],
17685169699Skan						 operands[2], operands[3],
17686169699Skan						 operands[4]));
17687169699Skan    }
17688169699Skan  DONE;
17689169699Skan}
17690169699Skan  [(set_attr "type" "fistp")
17691169699Skan   (set_attr "i387_cw" "ceil")
17692169699Skan   (set_attr "mode" "<MODE>")])
17693169699Skan
17694169699Skan(define_insn "fistdi2_ceil"
17695169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
17696169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
17697169699Skan	 UNSPEC_FIST_CEIL))
17698169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17699169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))
17700169699Skan   (clobber (match_scratch:XF 4 "=&1f"))]
17701169699Skan  "TARGET_USE_FANCY_MATH_387
17702169699Skan   && flag_unsafe_math_optimizations"
17703169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17704169699Skan  [(set_attr "type" "fistp")
17705169699Skan   (set_attr "i387_cw" "ceil")
17706169699Skan   (set_attr "mode" "DI")])
17707169699Skan
17708169699Skan(define_insn "fistdi2_ceil_with_temp"
17709169699Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
17710169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
17711169699Skan	 UNSPEC_FIST_CEIL))
17712169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17713169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17714169699Skan   (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
17715169699Skan   (clobber (match_scratch:XF 5 "=&1f,&1f"))]
17716169699Skan  "TARGET_USE_FANCY_MATH_387
17717169699Skan   && flag_unsafe_math_optimizations"
17718169699Skan  "#"
17719169699Skan  [(set_attr "type" "fistp")
17720169699Skan   (set_attr "i387_cw" "ceil")
17721169699Skan   (set_attr "mode" "DI")])
17722169699Skan
17723169699Skan(define_split 
17724169699Skan  [(set (match_operand:DI 0 "register_operand" "")
17725169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17726169699Skan	 UNSPEC_FIST_CEIL))
17727169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17728169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17729169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17730169699Skan   (clobber (match_scratch 5 ""))]
17731169699Skan  "reload_completed"
17732169699Skan  [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
17733169699Skan	      (use (match_dup 2))
17734169699Skan	      (use (match_dup 3))
17735169699Skan	      (clobber (match_dup 5))])
17736169699Skan   (set (match_dup 0) (match_dup 4))]
17737169699Skan  "")
17738169699Skan
17739169699Skan(define_split 
17740169699Skan  [(set (match_operand:DI 0 "memory_operand" "")
17741169699Skan	(unspec:DI [(match_operand:XF 1 "register_operand" "")]
17742169699Skan	 UNSPEC_FIST_CEIL))
17743169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17744169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17745169699Skan   (clobber (match_operand:DI 4 "memory_operand" ""))
17746169699Skan   (clobber (match_scratch 5 ""))]
17747169699Skan  "reload_completed"
17748169699Skan  [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
17749169699Skan	      (use (match_dup 2))
17750169699Skan	      (use (match_dup 3))
17751169699Skan	      (clobber (match_dup 5))])]
17752169699Skan  "")
17753169699Skan
17754169699Skan(define_insn "fist<mode>2_ceil"
17755169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
17756169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
17757169699Skan	 UNSPEC_FIST_CEIL))
17758169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17759169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17760169699Skan  "TARGET_USE_FANCY_MATH_387
17761169699Skan   && flag_unsafe_math_optimizations"
17762169699Skan  "* return output_fix_trunc (insn, operands, 0);"
17763169699Skan  [(set_attr "type" "fistp")
17764169699Skan   (set_attr "i387_cw" "ceil")
17765169699Skan   (set_attr "mode" "<MODE>")])
17766169699Skan
17767169699Skan(define_insn "fist<mode>2_ceil_with_temp"
17768169699Skan  [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
17769169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
17770169699Skan	 UNSPEC_FIST_CEIL))
17771169699Skan   (use (match_operand:HI 2 "memory_operand" "m,m"))
17772169699Skan   (use (match_operand:HI 3 "memory_operand" "m,m"))
17773169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
17774169699Skan  "TARGET_USE_FANCY_MATH_387
17775169699Skan   && flag_unsafe_math_optimizations"
17776169699Skan  "#"
17777169699Skan  [(set_attr "type" "fistp")
17778169699Skan   (set_attr "i387_cw" "ceil")
17779169699Skan   (set_attr "mode" "<MODE>")])
17780169699Skan
17781169699Skan(define_split 
17782169699Skan  [(set (match_operand:X87MODEI12 0 "register_operand" "")
17783169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17784169699Skan	 UNSPEC_FIST_CEIL))
17785169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17786169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17787169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17788169699Skan  "reload_completed"
17789169699Skan  [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
17790169699Skan				  UNSPEC_FIST_CEIL))
17791169699Skan	      (use (match_dup 2))
17792169699Skan	      (use (match_dup 3))])
17793169699Skan   (set (match_dup 0) (match_dup 4))]
17794169699Skan  "")
17795169699Skan
17796169699Skan(define_split 
17797169699Skan  [(set (match_operand:X87MODEI12 0 "memory_operand" "")
17798169699Skan	(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
17799169699Skan	 UNSPEC_FIST_CEIL))
17800169699Skan   (use (match_operand:HI 2 "memory_operand" ""))
17801169699Skan   (use (match_operand:HI 3 "memory_operand" ""))
17802169699Skan   (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
17803169699Skan  "reload_completed"
17804169699Skan  [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
17805169699Skan				  UNSPEC_FIST_CEIL))
17806169699Skan	      (use (match_dup 2))
17807169699Skan	      (use (match_dup 3))])]
17808169699Skan  "")
17809169699Skan
17810169699Skan(define_expand "lceil<mode>2"
17811169699Skan  [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
17812169699Skan		   (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
17813169699Skan		    UNSPEC_FIST_CEIL))
17814169699Skan	      (clobber (reg:CC FLAGS_REG))])]
17815169699Skan  "TARGET_USE_FANCY_MATH_387
17816169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17817169699Skan   && flag_unsafe_math_optimizations"
17818169699Skan  "")
17819169699Skan
17820169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17821169699Skan(define_insn_and_split "frndintxf2_trunc"
17822169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17823169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17824169699Skan	 UNSPEC_FRNDINT_TRUNC))
17825169699Skan   (clobber (reg:CC FLAGS_REG))]
17826169699Skan  "TARGET_USE_FANCY_MATH_387
17827169699Skan   && flag_unsafe_math_optimizations
17828169699Skan   && !(reload_completed || reload_in_progress)"
17829169699Skan  "#"
17830169699Skan  "&& 1"
17831169699Skan  [(const_int 0)]
17832169699Skan{
17833169699Skan  ix86_optimize_mode_switching[I387_TRUNC] = 1;
17834169699Skan
17835169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17836169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
17837169699Skan
17838169699Skan  emit_insn (gen_frndintxf2_trunc_i387 (operands[0], operands[1],
17839169699Skan					operands[2], operands[3]));
17840169699Skan  DONE;
17841169699Skan}
17842169699Skan  [(set_attr "type" "frndint")
17843169699Skan   (set_attr "i387_cw" "trunc")
17844169699Skan   (set_attr "mode" "XF")])
17845169699Skan
17846169699Skan(define_insn "frndintxf2_trunc_i387"
17847169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17848169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17849169699Skan	 UNSPEC_FRNDINT_TRUNC))
17850169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17851169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17852169699Skan  "TARGET_USE_FANCY_MATH_387
17853169699Skan   && flag_unsafe_math_optimizations"
17854169699Skan  "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
17855169699Skan  [(set_attr "type" "frndint")
17856169699Skan   (set_attr "i387_cw" "trunc")
17857169699Skan   (set_attr "mode" "XF")])
17858169699Skan
17859169699Skan(define_expand "btruncxf2"
17860169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17861169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17862169699Skan  "TARGET_USE_FANCY_MATH_387
17863169699Skan   && flag_unsafe_math_optimizations"
17864169699Skan{
17865169699Skan  emit_insn (gen_frndintxf2_trunc (operands[0], operands[1]));
17866169699Skan  DONE;
17867169699Skan})
17868169699Skan
17869169699Skan(define_expand "btruncdf2"
17870169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17871169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17872169699Skan  "TARGET_USE_FANCY_MATH_387
17873169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17874169699Skan   && flag_unsafe_math_optimizations"
17875169699Skan{
17876169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17877169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17878169699Skan
17879169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17880169699Skan  emit_insn (gen_frndintxf2_trunc (op0, op1));
17881169699Skan
17882169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17883169699Skan  DONE;
17884169699Skan})
17885169699Skan
17886169699Skan(define_expand "btruncsf2"
17887169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17888169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17889169699Skan  "TARGET_USE_FANCY_MATH_387
17890169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17891169699Skan   && flag_unsafe_math_optimizations"
17892169699Skan{
17893169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17894169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17895169699Skan
17896169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17897169699Skan  emit_insn (gen_frndintxf2_trunc (op0, op1));
17898169699Skan
17899169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17900169699Skan  DONE;
17901169699Skan})
17902169699Skan
17903169699Skan;; Rounding mode control word calculation could clobber FLAGS_REG.
17904169699Skan(define_insn_and_split "frndintxf2_mask_pm"
17905169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17906169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17907169699Skan	 UNSPEC_FRNDINT_MASK_PM))
17908169699Skan   (clobber (reg:CC FLAGS_REG))]
17909169699Skan  "TARGET_USE_FANCY_MATH_387
17910169699Skan   && flag_unsafe_math_optimizations
17911169699Skan   && !(reload_completed || reload_in_progress)"
17912169699Skan  "#"
17913169699Skan  "&& 1"
17914169699Skan  [(const_int 0)]
17915169699Skan{
17916169699Skan  ix86_optimize_mode_switching[I387_MASK_PM] = 1;
17917169699Skan
17918169699Skan  operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
17919169699Skan  operands[3] = assign_386_stack_local (HImode, SLOT_CW_MASK_PM);
17920169699Skan
17921169699Skan  emit_insn (gen_frndintxf2_mask_pm_i387 (operands[0], operands[1],
17922169699Skan					  operands[2], operands[3]));
17923169699Skan  DONE;
17924169699Skan}
17925169699Skan  [(set_attr "type" "frndint")
17926169699Skan   (set_attr "i387_cw" "mask_pm")
17927169699Skan   (set_attr "mode" "XF")])
17928169699Skan
17929169699Skan(define_insn "frndintxf2_mask_pm_i387"
17930169699Skan  [(set (match_operand:XF 0 "register_operand" "=f")
17931169699Skan	(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
17932169699Skan	 UNSPEC_FRNDINT_MASK_PM))
17933169699Skan   (use (match_operand:HI 2 "memory_operand" "m"))
17934169699Skan   (use (match_operand:HI 3 "memory_operand" "m"))]
17935169699Skan  "TARGET_USE_FANCY_MATH_387
17936169699Skan   && flag_unsafe_math_optimizations"
17937169699Skan  "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2"
17938169699Skan  [(set_attr "type" "frndint")
17939169699Skan   (set_attr "i387_cw" "mask_pm")
17940169699Skan   (set_attr "mode" "XF")])
17941169699Skan
17942169699Skan(define_expand "nearbyintxf2"
17943169699Skan  [(use (match_operand:XF 0 "register_operand" ""))
17944169699Skan   (use (match_operand:XF 1 "register_operand" ""))]
17945169699Skan  "TARGET_USE_FANCY_MATH_387
17946169699Skan   && flag_unsafe_math_optimizations"
17947169699Skan{
17948169699Skan  emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1]));
17949169699Skan
17950169699Skan  DONE;
17951169699Skan})
17952169699Skan
17953169699Skan(define_expand "nearbyintdf2"
17954169699Skan  [(use (match_operand:DF 0 "register_operand" ""))
17955169699Skan   (use (match_operand:DF 1 "register_operand" ""))]
17956169699Skan  "TARGET_USE_FANCY_MATH_387
17957169699Skan   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
17958169699Skan   && flag_unsafe_math_optimizations"
17959169699Skan{
17960169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17961169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17962169699Skan
17963169699Skan  emit_insn (gen_extenddfxf2 (op1, operands[1]));
17964169699Skan  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
17965169699Skan
17966169699Skan  emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
17967169699Skan  DONE;
17968169699Skan})
17969169699Skan
17970169699Skan(define_expand "nearbyintsf2"
17971169699Skan  [(use (match_operand:SF 0 "register_operand" ""))
17972169699Skan   (use (match_operand:SF 1 "register_operand" ""))]
17973169699Skan  "TARGET_USE_FANCY_MATH_387
17974169699Skan   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
17975169699Skan   && flag_unsafe_math_optimizations"
17976169699Skan{
17977169699Skan  rtx op0 = gen_reg_rtx (XFmode);
17978169699Skan  rtx op1 = gen_reg_rtx (XFmode);
17979169699Skan
17980169699Skan  emit_insn (gen_extendsfxf2 (op1, operands[1]));
17981169699Skan  emit_insn (gen_frndintxf2_mask_pm (op0, op1));
17982169699Skan
17983169699Skan  emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
17984169699Skan  DONE;
17985169699Skan})
17986169699Skan
17987169699Skan
1798890286Sobrien;; Block operation instructions
1798990286Sobrien
1799090286Sobrien(define_insn "cld"
17991169699Skan [(set (reg:SI DIRFLAG_REG) (const_int 0))]
1799290286Sobrien ""
1799390286Sobrien "cld"
1799490286Sobrien  [(set_attr "type" "cld")])
1799590286Sobrien
17996169699Skan(define_expand "movmemsi"
1799790286Sobrien  [(use (match_operand:BLK 0 "memory_operand" ""))
1799890286Sobrien   (use (match_operand:BLK 1 "memory_operand" ""))
1799990286Sobrien   (use (match_operand:SI 2 "nonmemory_operand" ""))
1800090286Sobrien   (use (match_operand:SI 3 "const_int_operand" ""))]
18001169699Skan  "! optimize_size || TARGET_INLINE_ALL_STRINGOPS"
1800218334Speter{
18003169699Skan if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
1800490286Sobrien   DONE;
1800590286Sobrien else
1800690286Sobrien   FAIL;
1800790286Sobrien})
1800890286Sobrien
18009169699Skan(define_expand "movmemdi"
1801090286Sobrien  [(use (match_operand:BLK 0 "memory_operand" ""))
1801190286Sobrien   (use (match_operand:BLK 1 "memory_operand" ""))
1801290286Sobrien   (use (match_operand:DI 2 "nonmemory_operand" ""))
1801390286Sobrien   (use (match_operand:DI 3 "const_int_operand" ""))]
1801490286Sobrien  "TARGET_64BIT"
1801590286Sobrien{
18016169699Skan if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
1801790286Sobrien   DONE;
1801890286Sobrien else
1801990286Sobrien   FAIL;
1802090286Sobrien})
1802190286Sobrien
1802290286Sobrien;; Most CPUs don't like single string operations
1802390286Sobrien;; Handle this case here to simplify previous expander.
1802490286Sobrien
18025132727Skan(define_expand "strmov"
18026132727Skan  [(set (match_dup 4) (match_operand 3 "memory_operand" ""))
18027132727Skan   (set (match_operand 1 "memory_operand" "") (match_dup 4))
18028132727Skan   (parallel [(set (match_operand 0 "register_operand" "") (match_dup 5))
18029169699Skan	      (clobber (reg:CC FLAGS_REG))])
18030132727Skan   (parallel [(set (match_operand 2 "register_operand" "") (match_dup 6))
18031169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1803290286Sobrien  ""
1803390286Sobrien{
18034132727Skan  rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])));
1803550650Sobrien
18036132727Skan  /* If .md ever supports :P for Pmode, these can be directly
18037132727Skan     in the pattern above.  */
18038132727Skan  operands[5] = gen_rtx_PLUS (Pmode, operands[0], adjust);
18039132727Skan  operands[6] = gen_rtx_PLUS (Pmode, operands[2], adjust);
1804050650Sobrien
1804190286Sobrien  if (TARGET_SINGLE_STRINGOP || optimize_size)
1804290286Sobrien    {
18043132727Skan      emit_insn (gen_strmov_singleop (operands[0], operands[1],
18044132727Skan				      operands[2], operands[3],
18045132727Skan				      operands[5], operands[6]));
1804690286Sobrien      DONE;
1804790286Sobrien    }
1804850650Sobrien
18049132727Skan  operands[4] = gen_reg_rtx (GET_MODE (operands[1]));
1805090286Sobrien})
1805150650Sobrien
18052132727Skan(define_expand "strmov_singleop"
18053132727Skan  [(parallel [(set (match_operand 1 "memory_operand" "")
18054132727Skan		   (match_operand 3 "memory_operand" ""))
18055132727Skan	      (set (match_operand 0 "register_operand" "")
18056132727Skan		   (match_operand 4 "" ""))
18057132727Skan	      (set (match_operand 2 "register_operand" "")
18058132727Skan		   (match_operand 5 "" ""))
18059169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18060132727Skan  "TARGET_SINGLE_STRINGOP || optimize_size"
18061132727Skan  "")
1806218334Speter
18063132727Skan(define_insn "*strmovdi_rex_1"
1806490286Sobrien  [(set (mem:DI (match_operand:DI 2 "register_operand" "0"))
1806590286Sobrien	(mem:DI (match_operand:DI 3 "register_operand" "1")))
1806690286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1806790286Sobrien	(plus:DI (match_dup 2)
1806890286Sobrien		 (const_int 8)))
1806990286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1807090286Sobrien	(plus:DI (match_dup 3)
1807190286Sobrien		 (const_int 8)))
18072169699Skan   (use (reg:SI DIRFLAG_REG))]
1807390286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1807490286Sobrien  "movsq"
1807590286Sobrien  [(set_attr "type" "str")
1807690286Sobrien   (set_attr "mode" "DI")
1807790286Sobrien   (set_attr "memory" "both")])
1807890286Sobrien
18079132727Skan(define_insn "*strmovsi_1"
1808090286Sobrien  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
1808190286Sobrien	(mem:SI (match_operand:SI 3 "register_operand" "1")))
1808290286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1808390286Sobrien	(plus:SI (match_dup 2)
1808490286Sobrien		 (const_int 4)))
1808590286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1808690286Sobrien	(plus:SI (match_dup 3)
1808790286Sobrien		 (const_int 4)))
18088169699Skan   (use (reg:SI DIRFLAG_REG))]
1808990286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1809090286Sobrien  "{movsl|movsd}"
1809190286Sobrien  [(set_attr "type" "str")
1809290286Sobrien   (set_attr "mode" "SI")
1809390286Sobrien   (set_attr "memory" "both")])
1809490286Sobrien
18095132727Skan(define_insn "*strmovsi_rex_1"
1809690286Sobrien  [(set (mem:SI (match_operand:DI 2 "register_operand" "0"))
1809790286Sobrien	(mem:SI (match_operand:DI 3 "register_operand" "1")))
1809890286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1809990286Sobrien	(plus:DI (match_dup 2)
1810090286Sobrien		 (const_int 4)))
1810190286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1810290286Sobrien	(plus:DI (match_dup 3)
1810390286Sobrien		 (const_int 4)))
18104169699Skan   (use (reg:SI DIRFLAG_REG))]
1810590286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1810690286Sobrien  "{movsl|movsd}"
1810790286Sobrien  [(set_attr "type" "str")
1810890286Sobrien   (set_attr "mode" "SI")
1810990286Sobrien   (set_attr "memory" "both")])
1811090286Sobrien
18111132727Skan(define_insn "*strmovhi_1"
1811290286Sobrien  [(set (mem:HI (match_operand:SI 2 "register_operand" "0"))
1811390286Sobrien	(mem:HI (match_operand:SI 3 "register_operand" "1")))
1811490286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1811590286Sobrien	(plus:SI (match_dup 2)
1811690286Sobrien		 (const_int 2)))
1811790286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1811890286Sobrien	(plus:SI (match_dup 3)
1811990286Sobrien		 (const_int 2)))
18120169699Skan   (use (reg:SI DIRFLAG_REG))]
1812190286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1812290286Sobrien  "movsw"
1812390286Sobrien  [(set_attr "type" "str")
1812490286Sobrien   (set_attr "memory" "both")
1812590286Sobrien   (set_attr "mode" "HI")])
1812690286Sobrien
18127132727Skan(define_insn "*strmovhi_rex_1"
1812890286Sobrien  [(set (mem:HI (match_operand:DI 2 "register_operand" "0"))
1812990286Sobrien	(mem:HI (match_operand:DI 3 "register_operand" "1")))
1813090286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1813190286Sobrien	(plus:DI (match_dup 2)
1813290286Sobrien		 (const_int 2)))
1813390286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1813490286Sobrien	(plus:DI (match_dup 3)
1813590286Sobrien		 (const_int 2)))
18136169699Skan   (use (reg:SI DIRFLAG_REG))]
1813790286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1813890286Sobrien  "movsw"
1813990286Sobrien  [(set_attr "type" "str")
1814090286Sobrien   (set_attr "memory" "both")
1814190286Sobrien   (set_attr "mode" "HI")])
1814290286Sobrien
18143132727Skan(define_insn "*strmovqi_1"
1814490286Sobrien  [(set (mem:QI (match_operand:SI 2 "register_operand" "0"))
1814590286Sobrien	(mem:QI (match_operand:SI 3 "register_operand" "1")))
1814690286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1814790286Sobrien	(plus:SI (match_dup 2)
1814890286Sobrien		 (const_int 1)))
1814990286Sobrien   (set (match_operand:SI 1 "register_operand" "=S")
1815090286Sobrien	(plus:SI (match_dup 3)
1815190286Sobrien		 (const_int 1)))
18152169699Skan   (use (reg:SI DIRFLAG_REG))]
1815390286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1815490286Sobrien  "movsb"
1815590286Sobrien  [(set_attr "type" "str")
1815690286Sobrien   (set_attr "memory" "both")
1815790286Sobrien   (set_attr "mode" "QI")])
1815890286Sobrien
18159132727Skan(define_insn "*strmovqi_rex_1"
1816090286Sobrien  [(set (mem:QI (match_operand:DI 2 "register_operand" "0"))
1816190286Sobrien	(mem:QI (match_operand:DI 3 "register_operand" "1")))
1816290286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1816390286Sobrien	(plus:DI (match_dup 2)
1816490286Sobrien		 (const_int 1)))
1816590286Sobrien   (set (match_operand:DI 1 "register_operand" "=S")
1816690286Sobrien	(plus:DI (match_dup 3)
1816790286Sobrien		 (const_int 1)))
18168169699Skan   (use (reg:SI DIRFLAG_REG))]
1816990286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1817090286Sobrien  "movsb"
1817190286Sobrien  [(set_attr "type" "str")
1817290286Sobrien   (set_attr "memory" "both")
1817390286Sobrien   (set_attr "mode" "QI")])
1817490286Sobrien
18175132727Skan(define_expand "rep_mov"
18176132727Skan  [(parallel [(set (match_operand 4 "register_operand" "") (const_int 0))
18177132727Skan	      (set (match_operand 0 "register_operand" "")
18178132727Skan		   (match_operand 5 "" ""))
18179132727Skan	      (set (match_operand 2 "register_operand" "")
18180132727Skan		   (match_operand 6 "" ""))
18181132727Skan	      (set (match_operand 1 "memory_operand" "")
18182132727Skan		   (match_operand 3 "memory_operand" ""))
18183132727Skan	      (use (match_dup 4))
18184169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18185132727Skan  ""
18186132727Skan  "")
18187132727Skan
18188132727Skan(define_insn "*rep_movdi_rex64"
1818990286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
1819090286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1819190286Sobrien        (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
1819290286Sobrien			    (const_int 3))
1819390286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1819490286Sobrien   (set (match_operand:DI 1 "register_operand" "=S") 
1819590286Sobrien        (plus:DI (ashift:DI (match_dup 5) (const_int 3))
1819690286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1819790286Sobrien   (set (mem:BLK (match_dup 3))
1819890286Sobrien	(mem:BLK (match_dup 4)))
1819990286Sobrien   (use (match_dup 5))
18200169699Skan   (use (reg:SI DIRFLAG_REG))]
1820190286Sobrien  "TARGET_64BIT"
1820290286Sobrien  "{rep\;movsq|rep movsq}"
1820390286Sobrien  [(set_attr "type" "str")
1820490286Sobrien   (set_attr "prefix_rep" "1")
1820590286Sobrien   (set_attr "memory" "both")
1820690286Sobrien   (set_attr "mode" "DI")])
1820790286Sobrien
18208132727Skan(define_insn "*rep_movsi"
1820990286Sobrien  [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
1821090286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1821190286Sobrien        (plus:SI (ashift:SI (match_operand:SI 5 "register_operand" "2")
1821290286Sobrien			    (const_int 2))
1821390286Sobrien		 (match_operand:SI 3 "register_operand" "0")))
1821490286Sobrien   (set (match_operand:SI 1 "register_operand" "=S") 
1821590286Sobrien        (plus:SI (ashift:SI (match_dup 5) (const_int 2))
1821690286Sobrien		 (match_operand:SI 4 "register_operand" "1")))
1821790286Sobrien   (set (mem:BLK (match_dup 3))
1821890286Sobrien	(mem:BLK (match_dup 4)))
1821990286Sobrien   (use (match_dup 5))
18220169699Skan   (use (reg:SI DIRFLAG_REG))]
1822190286Sobrien  "!TARGET_64BIT"
1822290286Sobrien  "{rep\;movsl|rep movsd}"
1822390286Sobrien  [(set_attr "type" "str")
1822490286Sobrien   (set_attr "prefix_rep" "1")
1822590286Sobrien   (set_attr "memory" "both")
1822690286Sobrien   (set_attr "mode" "SI")])
1822790286Sobrien
18228132727Skan(define_insn "*rep_movsi_rex64"
1822990286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
1823090286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1823190286Sobrien        (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
1823290286Sobrien			    (const_int 2))
1823390286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1823490286Sobrien   (set (match_operand:DI 1 "register_operand" "=S") 
1823590286Sobrien        (plus:DI (ashift:DI (match_dup 5) (const_int 2))
1823690286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1823790286Sobrien   (set (mem:BLK (match_dup 3))
1823890286Sobrien	(mem:BLK (match_dup 4)))
1823990286Sobrien   (use (match_dup 5))
18240169699Skan   (use (reg:SI DIRFLAG_REG))]
1824190286Sobrien  "TARGET_64BIT"
1824290286Sobrien  "{rep\;movsl|rep movsd}"
1824390286Sobrien  [(set_attr "type" "str")
1824490286Sobrien   (set_attr "prefix_rep" "1")
1824590286Sobrien   (set_attr "memory" "both")
1824690286Sobrien   (set_attr "mode" "SI")])
1824790286Sobrien
18248132727Skan(define_insn "*rep_movqi"
1824990286Sobrien  [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
1825090286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1825190286Sobrien        (plus:SI (match_operand:SI 3 "register_operand" "0")
1825290286Sobrien		 (match_operand:SI 5 "register_operand" "2")))
1825390286Sobrien   (set (match_operand:SI 1 "register_operand" "=S") 
1825490286Sobrien        (plus:SI (match_operand:SI 4 "register_operand" "1") (match_dup 5)))
1825590286Sobrien   (set (mem:BLK (match_dup 3))
1825690286Sobrien	(mem:BLK (match_dup 4)))
1825790286Sobrien   (use (match_dup 5))
18258169699Skan   (use (reg:SI DIRFLAG_REG))]
1825990286Sobrien  "!TARGET_64BIT"
1826090286Sobrien  "{rep\;movsb|rep movsb}"
1826190286Sobrien  [(set_attr "type" "str")
1826290286Sobrien   (set_attr "prefix_rep" "1")
1826390286Sobrien   (set_attr "memory" "both")
1826490286Sobrien   (set_attr "mode" "SI")])
1826590286Sobrien
18266132727Skan(define_insn "*rep_movqi_rex64"
1826790286Sobrien  [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
1826890286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1826990286Sobrien        (plus:DI (match_operand:DI 3 "register_operand" "0")
1827090286Sobrien		 (match_operand:DI 5 "register_operand" "2")))
1827190286Sobrien   (set (match_operand:DI 1 "register_operand" "=S") 
1827290286Sobrien        (plus:DI (match_operand:DI 4 "register_operand" "1") (match_dup 5)))
1827390286Sobrien   (set (mem:BLK (match_dup 3))
1827490286Sobrien	(mem:BLK (match_dup 4)))
1827590286Sobrien   (use (match_dup 5))
18276169699Skan   (use (reg:SI DIRFLAG_REG))]
1827790286Sobrien  "TARGET_64BIT"
1827890286Sobrien  "{rep\;movsb|rep movsb}"
1827990286Sobrien  [(set_attr "type" "str")
1828090286Sobrien   (set_attr "prefix_rep" "1")
1828190286Sobrien   (set_attr "memory" "both")
1828290286Sobrien   (set_attr "mode" "SI")])
1828390286Sobrien
18284169699Skan(define_expand "setmemsi"
1828590286Sobrien   [(use (match_operand:BLK 0 "memory_operand" ""))
1828690286Sobrien    (use (match_operand:SI 1 "nonmemory_operand" ""))
18287169699Skan    (use (match_operand 2 "const_int_operand" ""))
18288169699Skan    (use (match_operand 3 "const_int_operand" ""))]
1828918334Speter  ""
1829018334Speter{
18291169699Skan /* If value to set is not zero, use the library routine.  */
18292169699Skan if (operands[2] != const0_rtx)
18293169699Skan   FAIL;
18294169699Skan
18295169699Skan if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
1829690286Sobrien   DONE;
1829790286Sobrien else
1829890286Sobrien   FAIL;
1829990286Sobrien})
1830018334Speter
18301169699Skan(define_expand "setmemdi"
1830290286Sobrien   [(use (match_operand:BLK 0 "memory_operand" ""))
1830390286Sobrien    (use (match_operand:DI 1 "nonmemory_operand" ""))
18304169699Skan    (use (match_operand 2 "const_int_operand" ""))
18305169699Skan    (use (match_operand 3 "const_int_operand" ""))]
1830690286Sobrien  "TARGET_64BIT"
1830790286Sobrien{
18308169699Skan /* If value to set is not zero, use the library routine.  */
18309169699Skan if (operands[2] != const0_rtx)
18310169699Skan   FAIL;
18311169699Skan
18312169699Skan if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
1831390286Sobrien   DONE;
1831490286Sobrien else
1831590286Sobrien   FAIL;
1831690286Sobrien})
1831750650Sobrien
1831890286Sobrien;; Most CPUs don't like single string operations
1831990286Sobrien;; Handle this case here to simplify previous expander.
1832050650Sobrien
18321132727Skan(define_expand "strset"
18322132727Skan  [(set (match_operand 1 "memory_operand" "")
18323132727Skan	(match_operand 2 "register_operand" ""))
18324132727Skan   (parallel [(set (match_operand 0 "register_operand" "")
18325132727Skan		   (match_dup 3))
18326169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1832790286Sobrien  ""
1832890286Sobrien{
18329132727Skan  if (GET_MODE (operands[1]) != GET_MODE (operands[2]))
18330132727Skan    operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0);
1833190286Sobrien
18332132727Skan  /* If .md ever supports :P for Pmode, this can be directly
18333132727Skan     in the pattern above.  */
18334132727Skan  operands[3] = gen_rtx_PLUS (Pmode, operands[0],
18335132727Skan			      GEN_INT (GET_MODE_SIZE (GET_MODE
18336132727Skan						      (operands[2]))));
1833790286Sobrien  if (TARGET_SINGLE_STRINGOP || optimize_size)
1833890286Sobrien    {
18339132727Skan      emit_insn (gen_strset_singleop (operands[0], operands[1], operands[2],
18340132727Skan				      operands[3]));
1834190286Sobrien      DONE;
1834290286Sobrien    }
1834390286Sobrien})
1834490286Sobrien
18345132727Skan(define_expand "strset_singleop"
18346132727Skan  [(parallel [(set (match_operand 1 "memory_operand" "")
18347132727Skan		   (match_operand 2 "register_operand" ""))
18348132727Skan	      (set (match_operand 0 "register_operand" "")
18349132727Skan		   (match_operand 3 "" ""))
18350169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18351132727Skan  "TARGET_SINGLE_STRINGOP || optimize_size"
18352132727Skan  "")
1835390286Sobrien
18354132727Skan(define_insn "*strsetdi_rex_1"
18355169699Skan  [(set (mem:DI (match_operand:DI 1 "register_operand" "0"))
18356169699Skan	(match_operand:DI 2 "register_operand" "a"))
1835790286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1835890286Sobrien	(plus:DI (match_dup 1)
1835990286Sobrien		 (const_int 8)))
18360169699Skan   (use (reg:SI DIRFLAG_REG))]
1836190286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1836290286Sobrien  "stosq"
1836390286Sobrien  [(set_attr "type" "str")
1836490286Sobrien   (set_attr "memory" "store")
1836590286Sobrien   (set_attr "mode" "DI")])
1836690286Sobrien
18367132727Skan(define_insn "*strsetsi_1"
1836890286Sobrien  [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
1836990286Sobrien	(match_operand:SI 2 "register_operand" "a"))
1837090286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1837190286Sobrien	(plus:SI (match_dup 1)
1837290286Sobrien		 (const_int 4)))
18373169699Skan   (use (reg:SI DIRFLAG_REG))]
1837490286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1837590286Sobrien  "{stosl|stosd}"
1837690286Sobrien  [(set_attr "type" "str")
1837790286Sobrien   (set_attr "memory" "store")
1837890286Sobrien   (set_attr "mode" "SI")])
1837990286Sobrien
18380132727Skan(define_insn "*strsetsi_rex_1"
1838190286Sobrien  [(set (mem:SI (match_operand:DI 1 "register_operand" "0"))
1838290286Sobrien	(match_operand:SI 2 "register_operand" "a"))
1838390286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1838490286Sobrien	(plus:DI (match_dup 1)
1838590286Sobrien		 (const_int 4)))
18386169699Skan   (use (reg:SI DIRFLAG_REG))]
1838790286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1838890286Sobrien  "{stosl|stosd}"
1838990286Sobrien  [(set_attr "type" "str")
1839090286Sobrien   (set_attr "memory" "store")
1839190286Sobrien   (set_attr "mode" "SI")])
1839290286Sobrien
18393132727Skan(define_insn "*strsethi_1"
1839490286Sobrien  [(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
1839590286Sobrien	(match_operand:HI 2 "register_operand" "a"))
1839690286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1839790286Sobrien	(plus:SI (match_dup 1)
1839890286Sobrien		 (const_int 2)))
18399169699Skan   (use (reg:SI DIRFLAG_REG))]
1840090286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1840190286Sobrien  "stosw"
1840290286Sobrien  [(set_attr "type" "str")
1840390286Sobrien   (set_attr "memory" "store")
1840490286Sobrien   (set_attr "mode" "HI")])
1840590286Sobrien
18406132727Skan(define_insn "*strsethi_rex_1"
1840790286Sobrien  [(set (mem:HI (match_operand:DI 1 "register_operand" "0"))
1840890286Sobrien	(match_operand:HI 2 "register_operand" "a"))
1840990286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1841090286Sobrien	(plus:DI (match_dup 1)
1841190286Sobrien		 (const_int 2)))
18412169699Skan   (use (reg:SI DIRFLAG_REG))]
1841390286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1841490286Sobrien  "stosw"
1841590286Sobrien  [(set_attr "type" "str")
1841690286Sobrien   (set_attr "memory" "store")
1841790286Sobrien   (set_attr "mode" "HI")])
1841890286Sobrien
18419132727Skan(define_insn "*strsetqi_1"
1842090286Sobrien  [(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
1842190286Sobrien	(match_operand:QI 2 "register_operand" "a"))
1842290286Sobrien   (set (match_operand:SI 0 "register_operand" "=D")
1842390286Sobrien	(plus:SI (match_dup 1)
1842490286Sobrien		 (const_int 1)))
18425169699Skan   (use (reg:SI DIRFLAG_REG))]
1842690286Sobrien  "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1842790286Sobrien  "stosb"
1842890286Sobrien  [(set_attr "type" "str")
1842990286Sobrien   (set_attr "memory" "store")
1843090286Sobrien   (set_attr "mode" "QI")])
1843190286Sobrien
18432132727Skan(define_insn "*strsetqi_rex_1"
1843390286Sobrien  [(set (mem:QI (match_operand:DI 1 "register_operand" "0"))
1843490286Sobrien	(match_operand:QI 2 "register_operand" "a"))
1843590286Sobrien   (set (match_operand:DI 0 "register_operand" "=D")
1843690286Sobrien	(plus:DI (match_dup 1)
1843790286Sobrien		 (const_int 1)))
18438169699Skan   (use (reg:SI DIRFLAG_REG))]
1843990286Sobrien  "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
1844090286Sobrien  "stosb"
1844190286Sobrien  [(set_attr "type" "str")
1844290286Sobrien   (set_attr "memory" "store")
1844390286Sobrien   (set_attr "mode" "QI")])
1844490286Sobrien
18445132727Skan(define_expand "rep_stos"
18446132727Skan  [(parallel [(set (match_operand 1 "register_operand" "") (const_int 0))
18447132727Skan	      (set (match_operand 0 "register_operand" "")
18448132727Skan		   (match_operand 4 "" ""))
18449132727Skan	      (set (match_operand 2 "memory_operand" "") (const_int 0))
18450132727Skan	      (use (match_operand 3 "register_operand" ""))
18451132727Skan	      (use (match_dup 1))
18452169699Skan	      (use (reg:SI DIRFLAG_REG))])]
18453132727Skan  ""
18454132727Skan  "")
18455132727Skan
18456132727Skan(define_insn "*rep_stosdi_rex64"
1845790286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
1845890286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1845990286Sobrien        (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
1846090286Sobrien			    (const_int 3))
1846190286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1846290286Sobrien   (set (mem:BLK (match_dup 3))
1846390286Sobrien	(const_int 0))
1846490286Sobrien   (use (match_operand:DI 2 "register_operand" "a"))
1846590286Sobrien   (use (match_dup 4))
18466169699Skan   (use (reg:SI DIRFLAG_REG))]
1846790286Sobrien  "TARGET_64BIT"
1846890286Sobrien  "{rep\;stosq|rep stosq}"
1846990286Sobrien  [(set_attr "type" "str")
1847090286Sobrien   (set_attr "prefix_rep" "1")
1847190286Sobrien   (set_attr "memory" "store")
1847290286Sobrien   (set_attr "mode" "DI")])
1847390286Sobrien
18474132727Skan(define_insn "*rep_stossi"
1847590286Sobrien  [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
1847690286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1847790286Sobrien        (plus:SI (ashift:SI (match_operand:SI 4 "register_operand" "1")
1847890286Sobrien			    (const_int 2))
1847990286Sobrien		 (match_operand:SI 3 "register_operand" "0")))
1848090286Sobrien   (set (mem:BLK (match_dup 3))
1848190286Sobrien	(const_int 0))
1848290286Sobrien   (use (match_operand:SI 2 "register_operand" "a"))
1848390286Sobrien   (use (match_dup 4))
18484169699Skan   (use (reg:SI DIRFLAG_REG))]
1848590286Sobrien  "!TARGET_64BIT"
1848690286Sobrien  "{rep\;stosl|rep stosd}"
1848790286Sobrien  [(set_attr "type" "str")
1848890286Sobrien   (set_attr "prefix_rep" "1")
1848990286Sobrien   (set_attr "memory" "store")
1849090286Sobrien   (set_attr "mode" "SI")])
1849190286Sobrien
18492132727Skan(define_insn "*rep_stossi_rex64"
1849390286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
1849490286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1849590286Sobrien        (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
1849690286Sobrien			    (const_int 2))
1849790286Sobrien		 (match_operand:DI 3 "register_operand" "0")))
1849890286Sobrien   (set (mem:BLK (match_dup 3))
1849990286Sobrien	(const_int 0))
1850090286Sobrien   (use (match_operand:SI 2 "register_operand" "a"))
1850190286Sobrien   (use (match_dup 4))
18502169699Skan   (use (reg:SI DIRFLAG_REG))]
1850390286Sobrien  "TARGET_64BIT"
1850490286Sobrien  "{rep\;stosl|rep stosd}"
1850590286Sobrien  [(set_attr "type" "str")
1850690286Sobrien   (set_attr "prefix_rep" "1")
1850790286Sobrien   (set_attr "memory" "store")
1850890286Sobrien   (set_attr "mode" "SI")])
1850990286Sobrien
18510132727Skan(define_insn "*rep_stosqi"
1851190286Sobrien  [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
1851290286Sobrien   (set (match_operand:SI 0 "register_operand" "=D") 
1851390286Sobrien        (plus:SI (match_operand:SI 3 "register_operand" "0")
1851490286Sobrien		 (match_operand:SI 4 "register_operand" "1")))
1851590286Sobrien   (set (mem:BLK (match_dup 3))
1851690286Sobrien	(const_int 0))
1851790286Sobrien   (use (match_operand:QI 2 "register_operand" "a"))
1851890286Sobrien   (use (match_dup 4))
18519169699Skan   (use (reg:SI DIRFLAG_REG))]
1852090286Sobrien  "!TARGET_64BIT"
1852190286Sobrien  "{rep\;stosb|rep stosb}"
1852290286Sobrien  [(set_attr "type" "str")
1852390286Sobrien   (set_attr "prefix_rep" "1")
1852490286Sobrien   (set_attr "memory" "store")
1852590286Sobrien   (set_attr "mode" "QI")])
1852690286Sobrien
18527132727Skan(define_insn "*rep_stosqi_rex64"
1852890286Sobrien  [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
1852990286Sobrien   (set (match_operand:DI 0 "register_operand" "=D") 
1853090286Sobrien        (plus:DI (match_operand:DI 3 "register_operand" "0")
1853190286Sobrien		 (match_operand:DI 4 "register_operand" "1")))
1853290286Sobrien   (set (mem:BLK (match_dup 3))
1853390286Sobrien	(const_int 0))
1853490286Sobrien   (use (match_operand:QI 2 "register_operand" "a"))
1853590286Sobrien   (use (match_dup 4))
18536169699Skan   (use (reg:SI DIRFLAG_REG))]
1853790286Sobrien  "TARGET_64BIT"
1853890286Sobrien  "{rep\;stosb|rep stosb}"
1853990286Sobrien  [(set_attr "type" "str")
1854090286Sobrien   (set_attr "prefix_rep" "1")
1854190286Sobrien   (set_attr "memory" "store")
1854290286Sobrien   (set_attr "mode" "QI")])
1854390286Sobrien
18544169699Skan(define_expand "cmpstrnsi"
1854550650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1854690286Sobrien	(compare:SI (match_operand:BLK 1 "general_operand" "")
1854790286Sobrien		    (match_operand:BLK 2 "general_operand" "")))
1854890286Sobrien   (use (match_operand 3 "general_operand" ""))
1854990286Sobrien   (use (match_operand 4 "immediate_operand" ""))]
18550132727Skan  "! optimize_size || TARGET_INLINE_ALL_STRINGOPS"
1855150650Sobrien{
1855290286Sobrien  rtx addr1, addr2, out, outlow, count, countreg, align;
1855350650Sobrien
18554132727Skan  /* Can't use this if the user has appropriated esi or edi.  */
18555132727Skan  if (global_regs[4] || global_regs[5])
18556132727Skan    FAIL;
18557132727Skan
1855890286Sobrien  out = operands[0];
1855990286Sobrien  if (GET_CODE (out) != REG)
1856090286Sobrien    out = gen_reg_rtx (SImode);
1856150650Sobrien
1856290286Sobrien  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1856390286Sobrien  addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
18564132727Skan  if (addr1 != XEXP (operands[1], 0))
18565132727Skan    operands[1] = replace_equiv_address_nv (operands[1], addr1);
18566132727Skan  if (addr2 != XEXP (operands[2], 0))
18567132727Skan    operands[2] = replace_equiv_address_nv (operands[2], addr2);
18568132727Skan
1856990286Sobrien  count = operands[3];
1857090286Sobrien  countreg = ix86_zero_extend_to_Pmode (count);
1857150650Sobrien
1857290286Sobrien  /* %%% Iff we are testing strict equality, we can use known alignment
1857390286Sobrien     to good advantage.  This may be possible with combine, particularly
1857490286Sobrien     once cc0 is dead.  */
1857590286Sobrien  align = operands[4];
1857650650Sobrien
1857790286Sobrien  emit_insn (gen_cld ());
1857890286Sobrien  if (GET_CODE (count) == CONST_INT)
1857990286Sobrien    {
1858090286Sobrien      if (INTVAL (count) == 0)
1858190286Sobrien	{
1858290286Sobrien	  emit_move_insn (operands[0], const0_rtx);
1858390286Sobrien	  DONE;
1858490286Sobrien	}
18585169699Skan      emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, countreg, align,
18586169699Skan				     operands[1], operands[2]));
1858790286Sobrien    }
1858890286Sobrien  else
1858990286Sobrien    {
1859090286Sobrien      if (TARGET_64BIT)
18591132727Skan	emit_insn (gen_cmpdi_1_rex64 (countreg, countreg));
1859290286Sobrien      else
18593132727Skan	emit_insn (gen_cmpsi_1 (countreg, countreg));
18594169699Skan      emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
18595169699Skan				  operands[1], operands[2]));
1859690286Sobrien    }
1859790286Sobrien
1859890286Sobrien  outlow = gen_lowpart (QImode, out);
1859990286Sobrien  emit_insn (gen_cmpintqi (outlow));
1860090286Sobrien  emit_move_insn (out, gen_rtx_SIGN_EXTEND (SImode, outlow));
1860190286Sobrien
1860290286Sobrien  if (operands[0] != out)
1860390286Sobrien    emit_move_insn (operands[0], out);
1860490286Sobrien
1860590286Sobrien  DONE;
1860690286Sobrien})
1860790286Sobrien
1860890286Sobrien;; Produce a tri-state integer (-1, 0, 1) from condition codes.
1860990286Sobrien
1861090286Sobrien(define_expand "cmpintqi"
1861190286Sobrien  [(set (match_dup 1)
18612169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1861390286Sobrien   (set (match_dup 2)
18614169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
1861590286Sobrien   (parallel [(set (match_operand:QI 0 "register_operand" "")
1861690286Sobrien		   (minus:QI (match_dup 1)
1861790286Sobrien			     (match_dup 2)))
18618169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1861990286Sobrien  ""
1862090286Sobrien  "operands[1] = gen_reg_rtx (QImode);
1862190286Sobrien   operands[2] = gen_reg_rtx (QImode);")
1862290286Sobrien
1862390286Sobrien;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
1862490286Sobrien;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
1862590286Sobrien
18626169699Skan(define_expand "cmpstrnqi_nz_1"
18627169699Skan  [(parallel [(set (reg:CC FLAGS_REG)
18628132727Skan		   (compare:CC (match_operand 4 "memory_operand" "")
18629132727Skan			       (match_operand 5 "memory_operand" "")))
18630132727Skan	      (use (match_operand 2 "register_operand" ""))
18631132727Skan	      (use (match_operand:SI 3 "immediate_operand" ""))
18632169699Skan	      (use (reg:SI DIRFLAG_REG))
18633132727Skan	      (clobber (match_operand 0 "register_operand" ""))
18634132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18635132727Skan	      (clobber (match_dup 2))])]
18636132727Skan  ""
18637132727Skan  "")
18638132727Skan
18639169699Skan(define_insn "*cmpstrnqi_nz_1"
18640169699Skan  [(set (reg:CC FLAGS_REG)
1864190286Sobrien	(compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
1864290286Sobrien		    (mem:BLK (match_operand:SI 5 "register_operand" "1"))))
1864390286Sobrien   (use (match_operand:SI 6 "register_operand" "2"))
1864490286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18645169699Skan   (use (reg:SI DIRFLAG_REG))
1864690286Sobrien   (clobber (match_operand:SI 0 "register_operand" "=S"))
1864790286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
1864890286Sobrien   (clobber (match_operand:SI 2 "register_operand" "=c"))]
1864990286Sobrien  "!TARGET_64BIT"
1865090286Sobrien  "repz{\;| }cmpsb"
1865190286Sobrien  [(set_attr "type" "str")
1865290286Sobrien   (set_attr "mode" "QI")
1865390286Sobrien   (set_attr "prefix_rep" "1")])
1865490286Sobrien
18655169699Skan(define_insn "*cmpstrnqi_nz_rex_1"
18656169699Skan  [(set (reg:CC FLAGS_REG)
1865790286Sobrien	(compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
1865890286Sobrien		    (mem:BLK (match_operand:DI 5 "register_operand" "1"))))
1865990286Sobrien   (use (match_operand:DI 6 "register_operand" "2"))
1866090286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18661169699Skan   (use (reg:SI DIRFLAG_REG))
1866290286Sobrien   (clobber (match_operand:DI 0 "register_operand" "=S"))
1866390286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
1866490286Sobrien   (clobber (match_operand:DI 2 "register_operand" "=c"))]
1866590286Sobrien  "TARGET_64BIT"
1866690286Sobrien  "repz{\;| }cmpsb"
1866790286Sobrien  [(set_attr "type" "str")
1866890286Sobrien   (set_attr "mode" "QI")
1866990286Sobrien   (set_attr "prefix_rep" "1")])
1867090286Sobrien
1867190286Sobrien;; The same, but the count is not known to not be zero.
1867290286Sobrien
18673169699Skan(define_expand "cmpstrnqi_1"
18674169699Skan  [(parallel [(set (reg:CC FLAGS_REG)
18675132727Skan		(if_then_else:CC (ne (match_operand 2 "register_operand" "")
18676132727Skan				     (const_int 0))
18677132727Skan		  (compare:CC (match_operand 4 "memory_operand" "")
18678132727Skan			      (match_operand 5 "memory_operand" ""))
18679132727Skan		  (const_int 0)))
18680132727Skan	      (use (match_operand:SI 3 "immediate_operand" ""))
18681169699Skan	      (use (reg:CC FLAGS_REG))
18682169699Skan	      (use (reg:SI DIRFLAG_REG))
18683132727Skan	      (clobber (match_operand 0 "register_operand" ""))
18684132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18685132727Skan	      (clobber (match_dup 2))])]
18686132727Skan  ""
18687132727Skan  "")
18688132727Skan
18689169699Skan(define_insn "*cmpstrnqi_1"
18690169699Skan  [(set (reg:CC FLAGS_REG)
1869190286Sobrien	(if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
1869290286Sobrien			     (const_int 0))
1869390286Sobrien	  (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
1869490286Sobrien		      (mem:BLK (match_operand:SI 5 "register_operand" "1")))
1869590286Sobrien	  (const_int 0)))
1869690286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18697169699Skan   (use (reg:CC FLAGS_REG))
18698169699Skan   (use (reg:SI DIRFLAG_REG))
1869990286Sobrien   (clobber (match_operand:SI 0 "register_operand" "=S"))
1870090286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
1870190286Sobrien   (clobber (match_operand:SI 2 "register_operand" "=c"))]
1870290286Sobrien  "!TARGET_64BIT"
1870390286Sobrien  "repz{\;| }cmpsb"
1870490286Sobrien  [(set_attr "type" "str")
1870590286Sobrien   (set_attr "mode" "QI")
1870690286Sobrien   (set_attr "prefix_rep" "1")])
1870790286Sobrien
18708169699Skan(define_insn "*cmpstrnqi_rex_1"
18709169699Skan  [(set (reg:CC FLAGS_REG)
1871090286Sobrien	(if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2")
1871190286Sobrien			     (const_int 0))
1871290286Sobrien	  (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
1871390286Sobrien		      (mem:BLK (match_operand:DI 5 "register_operand" "1")))
1871490286Sobrien	  (const_int 0)))
1871590286Sobrien   (use (match_operand:SI 3 "immediate_operand" "i"))
18716169699Skan   (use (reg:CC FLAGS_REG))
18717169699Skan   (use (reg:SI DIRFLAG_REG))
1871890286Sobrien   (clobber (match_operand:DI 0 "register_operand" "=S"))
1871990286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
1872090286Sobrien   (clobber (match_operand:DI 2 "register_operand" "=c"))]
1872190286Sobrien  "TARGET_64BIT"
1872290286Sobrien  "repz{\;| }cmpsb"
1872390286Sobrien  [(set_attr "type" "str")
1872490286Sobrien   (set_attr "mode" "QI")
1872590286Sobrien   (set_attr "prefix_rep" "1")])
1872690286Sobrien
1872790286Sobrien(define_expand "strlensi"
1872852296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1872990286Sobrien	(unspec:SI [(match_operand:BLK 1 "general_operand" "")
1873090286Sobrien		    (match_operand:QI 2 "immediate_operand" "")
18731117404Skan		    (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
1873290286Sobrien  ""
1873390286Sobrien{
1873490286Sobrien if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
1873590286Sobrien   DONE;
1873690286Sobrien else
1873790286Sobrien   FAIL;
1873890286Sobrien})
1873990286Sobrien
1874090286Sobrien(define_expand "strlendi"
1874190286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1874290286Sobrien	(unspec:DI [(match_operand:BLK 1 "general_operand" "")
1874390286Sobrien		    (match_operand:QI 2 "immediate_operand" "")
18744117404Skan		    (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
1874590286Sobrien  ""
1874690286Sobrien{
1874790286Sobrien if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
1874890286Sobrien   DONE;
1874990286Sobrien else
1875090286Sobrien   FAIL;
1875190286Sobrien})
1875290286Sobrien
18753132727Skan(define_expand "strlenqi_1"
18754132727Skan  [(parallel [(set (match_operand 0 "register_operand" "") (match_operand 2 "" ""))
18755169699Skan	      (use (reg:SI DIRFLAG_REG))
18756132727Skan	      (clobber (match_operand 1 "register_operand" ""))
18757169699Skan	      (clobber (reg:CC FLAGS_REG))])]
18758132727Skan  ""
18759132727Skan  "")
18760132727Skan
18761132727Skan(define_insn "*strlenqi_1"
1876290286Sobrien  [(set (match_operand:SI 0 "register_operand" "=&c")
1876390286Sobrien	(unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1"))
1876490286Sobrien		    (match_operand:QI 2 "register_operand" "a")
1876590286Sobrien		    (match_operand:SI 3 "immediate_operand" "i")
18766117404Skan		    (match_operand:SI 4 "register_operand" "0")] UNSPEC_SCAS))
18767169699Skan   (use (reg:SI DIRFLAG_REG))
1876890286Sobrien   (clobber (match_operand:SI 1 "register_operand" "=D"))
18769169699Skan   (clobber (reg:CC FLAGS_REG))]
1877090286Sobrien  "!TARGET_64BIT"
1877190286Sobrien  "repnz{\;| }scasb"
1877290286Sobrien  [(set_attr "type" "str")
1877390286Sobrien   (set_attr "mode" "QI")
1877490286Sobrien   (set_attr "prefix_rep" "1")])
1877590286Sobrien
18776132727Skan(define_insn "*strlenqi_rex_1"
1877790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=&c")
1877890286Sobrien	(unspec:DI [(mem:BLK (match_operand:DI 5 "register_operand" "1"))
1877990286Sobrien		    (match_operand:QI 2 "register_operand" "a")
1878090286Sobrien		    (match_operand:DI 3 "immediate_operand" "i")
18781117404Skan		    (match_operand:DI 4 "register_operand" "0")] UNSPEC_SCAS))
18782169699Skan   (use (reg:SI DIRFLAG_REG))
1878390286Sobrien   (clobber (match_operand:DI 1 "register_operand" "=D"))
18784169699Skan   (clobber (reg:CC FLAGS_REG))]
1878590286Sobrien  "TARGET_64BIT"
1878690286Sobrien  "repnz{\;| }scasb"
1878790286Sobrien  [(set_attr "type" "str")
1878890286Sobrien   (set_attr "mode" "QI")
1878990286Sobrien   (set_attr "prefix_rep" "1")])
1879090286Sobrien
18791169699Skan;; Peephole optimizations to clean up after cmpstrn*.  This should be
1879290286Sobrien;; handled in combine, but it is not currently up to the task.
18793169699Skan;; When used for their truth value, the cmpstrn* expanders generate
1879490286Sobrien;; code like this:
1879590286Sobrien;;
1879690286Sobrien;;   repz cmpsb
1879790286Sobrien;;   seta 	%al
1879890286Sobrien;;   setb 	%dl
1879990286Sobrien;;   cmpb 	%al, %dl
1880090286Sobrien;;   jcc	label
1880190286Sobrien;;
1880290286Sobrien;; The intermediate three instructions are unnecessary.
1880390286Sobrien
18804169699Skan;; This one handles cmpstrn*_nz_1...
1880590286Sobrien(define_peephole2
1880690286Sobrien  [(parallel[
18807169699Skan     (set (reg:CC FLAGS_REG)
1880890286Sobrien	  (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
1880990286Sobrien		      (mem:BLK (match_operand 5 "register_operand" ""))))
1881090286Sobrien     (use (match_operand 6 "register_operand" ""))
1881190286Sobrien     (use (match_operand:SI 3 "immediate_operand" ""))
18812169699Skan     (use (reg:SI DIRFLAG_REG))
1881390286Sobrien     (clobber (match_operand 0 "register_operand" ""))
1881490286Sobrien     (clobber (match_operand 1 "register_operand" ""))
1881590286Sobrien     (clobber (match_operand 2 "register_operand" ""))])
1881690286Sobrien   (set (match_operand:QI 7 "register_operand" "")
18817169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1881890286Sobrien   (set (match_operand:QI 8 "register_operand" "")
18819169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
18820169699Skan   (set (reg FLAGS_REG)
1882190286Sobrien	(compare (match_dup 7) (match_dup 8)))
1882290286Sobrien  ]
1882390286Sobrien  "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
1882490286Sobrien  [(parallel[
18825169699Skan     (set (reg:CC FLAGS_REG)
1882690286Sobrien	  (compare:CC (mem:BLK (match_dup 4))
1882790286Sobrien		      (mem:BLK (match_dup 5))))
1882890286Sobrien     (use (match_dup 6))
1882990286Sobrien     (use (match_dup 3))
18830169699Skan     (use (reg:SI DIRFLAG_REG))
1883190286Sobrien     (clobber (match_dup 0))
1883290286Sobrien     (clobber (match_dup 1))
1883390286Sobrien     (clobber (match_dup 2))])]
1883450650Sobrien  "")
1883550650Sobrien
18836169699Skan;; ...and this one handles cmpstrn*_1.
1883790286Sobrien(define_peephole2
1883890286Sobrien  [(parallel[
18839169699Skan     (set (reg:CC FLAGS_REG)
1884090286Sobrien	  (if_then_else:CC (ne (match_operand 6 "register_operand" "")
1884190286Sobrien			       (const_int 0))
1884290286Sobrien	    (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
1884390286Sobrien		        (mem:BLK (match_operand 5 "register_operand" "")))
1884490286Sobrien	    (const_int 0)))
1884590286Sobrien     (use (match_operand:SI 3 "immediate_operand" ""))
18846169699Skan     (use (reg:CC FLAGS_REG))
18847169699Skan     (use (reg:SI DIRFLAG_REG))
1884890286Sobrien     (clobber (match_operand 0 "register_operand" ""))
1884990286Sobrien     (clobber (match_operand 1 "register_operand" ""))
1885090286Sobrien     (clobber (match_operand 2 "register_operand" ""))])
1885190286Sobrien   (set (match_operand:QI 7 "register_operand" "")
18852169699Skan	(gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
1885390286Sobrien   (set (match_operand:QI 8 "register_operand" "")
18854169699Skan	(ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
18855169699Skan   (set (reg FLAGS_REG)
1885690286Sobrien	(compare (match_dup 7) (match_dup 8)))
1885790286Sobrien  ]
1885890286Sobrien  "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
1885990286Sobrien  [(parallel[
18860169699Skan     (set (reg:CC FLAGS_REG)
1886190286Sobrien	  (if_then_else:CC (ne (match_dup 6)
1886290286Sobrien			       (const_int 0))
1886390286Sobrien	    (compare:CC (mem:BLK (match_dup 4))
1886490286Sobrien			(mem:BLK (match_dup 5)))
1886590286Sobrien	    (const_int 0)))
1886690286Sobrien     (use (match_dup 3))
18867169699Skan     (use (reg:CC FLAGS_REG))
18868169699Skan     (use (reg:SI DIRFLAG_REG))
1886990286Sobrien     (clobber (match_dup 0))
1887090286Sobrien     (clobber (match_dup 1))
1887190286Sobrien     (clobber (match_dup 2))])]
1887250650Sobrien  "")
1887350650Sobrien
1887490286Sobrien
1887590286Sobrien
1887690286Sobrien;; Conditional move instructions.
1887790286Sobrien
1887890286Sobrien(define_expand "movdicc"
1887990286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
1888090286Sobrien	(if_then_else:DI (match_operand 1 "comparison_operator" "")
1888190286Sobrien			 (match_operand:DI 2 "general_operand" "")
1888290286Sobrien			 (match_operand:DI 3 "general_operand" "")))]
1888390286Sobrien  "TARGET_64BIT"
1888490286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1888590286Sobrien
1888690286Sobrien(define_insn "x86_movdicc_0_m1_rex64"
1888790286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r")
18888132727Skan	(if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "")
1888990286Sobrien	  (const_int -1)
1889090286Sobrien	  (const_int 0)))
18891169699Skan   (clobber (reg:CC FLAGS_REG))]
1889290286Sobrien  "TARGET_64BIT"
1889390286Sobrien  "sbb{q}\t%0, %0"
1889490286Sobrien  ; Since we don't have the proper number of operands for an alu insn,
1889590286Sobrien  ; fill in all the blanks.
1889690286Sobrien  [(set_attr "type" "alu")
18897117404Skan   (set_attr "pent_pair" "pu")
1889890286Sobrien   (set_attr "memory" "none")
1889990286Sobrien   (set_attr "imm_disp" "false")
1890090286Sobrien   (set_attr "mode" "DI")
1890190286Sobrien   (set_attr "length_immediate" "0")])
1890290286Sobrien
18903169699Skan(define_insn "*movdicc_c_rex64"
1890490286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1890590286Sobrien	(if_then_else:DI (match_operator 1 "ix86_comparison_operator" 
18906169699Skan				[(reg FLAGS_REG) (const_int 0)])
1890790286Sobrien		      (match_operand:DI 2 "nonimmediate_operand" "rm,0")
1890890286Sobrien		      (match_operand:DI 3 "nonimmediate_operand" "0,rm")))]
1890990286Sobrien  "TARGET_64BIT && TARGET_CMOVE
1891090286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1891190286Sobrien  "@
1891296294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1891396294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1891490286Sobrien  [(set_attr "type" "icmov")
1891590286Sobrien   (set_attr "mode" "DI")])
1891690286Sobrien
1891790286Sobrien(define_expand "movsicc"
1891890286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1891990286Sobrien	(if_then_else:SI (match_operand 1 "comparison_operator" "")
1892090286Sobrien			 (match_operand:SI 2 "general_operand" "")
1892190286Sobrien			 (match_operand:SI 3 "general_operand" "")))]
1892290286Sobrien  ""
1892390286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1892490286Sobrien
1892590286Sobrien;; Data flow gets confused by our desire for `sbbl reg,reg', and clearing
1892690286Sobrien;; the register first winds up with `sbbl $0,reg', which is also weird.
1892790286Sobrien;; So just document what we're doing explicitly.
1892890286Sobrien
1892990286Sobrien(define_insn "x86_movsicc_0_m1"
1893090286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
18931132727Skan	(if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "")
1893290286Sobrien	  (const_int -1)
1893390286Sobrien	  (const_int 0)))
18934169699Skan   (clobber (reg:CC FLAGS_REG))]
1893590286Sobrien  ""
1893690286Sobrien  "sbb{l}\t%0, %0"
1893790286Sobrien  ; Since we don't have the proper number of operands for an alu insn,
1893890286Sobrien  ; fill in all the blanks.
1893990286Sobrien  [(set_attr "type" "alu")
18940117404Skan   (set_attr "pent_pair" "pu")
1894190286Sobrien   (set_attr "memory" "none")
1894290286Sobrien   (set_attr "imm_disp" "false")
1894390286Sobrien   (set_attr "mode" "SI")
1894490286Sobrien   (set_attr "length_immediate" "0")])
1894590286Sobrien
1894690286Sobrien(define_insn "*movsicc_noc"
1894750650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
1894890286Sobrien	(if_then_else:SI (match_operator 1 "ix86_comparison_operator" 
18949169699Skan				[(reg FLAGS_REG) (const_int 0)])
1895050650Sobrien		      (match_operand:SI 2 "nonimmediate_operand" "rm,0")
1895150650Sobrien		      (match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
1895290286Sobrien  "TARGET_CMOVE
1895390286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1895490286Sobrien  "@
1895596294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1895696294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1895790286Sobrien  [(set_attr "type" "icmov")
1895890286Sobrien   (set_attr "mode" "SI")])
1895950650Sobrien
1896050650Sobrien(define_expand "movhicc"
1896150650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
1896250650Sobrien	(if_then_else:HI (match_operand 1 "comparison_operator" "")
18963132727Skan			 (match_operand:HI 2 "general_operand" "")
18964132727Skan			 (match_operand:HI 3 "general_operand" "")))]
18965132727Skan  "TARGET_HIMODE_MATH"
1896690286Sobrien  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
1896750650Sobrien
1896890286Sobrien(define_insn "*movhicc_noc"
1896950650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
1897090286Sobrien	(if_then_else:HI (match_operator 1 "ix86_comparison_operator" 
18971169699Skan				[(reg FLAGS_REG) (const_int 0)])
1897250650Sobrien		      (match_operand:HI 2 "nonimmediate_operand" "rm,0")
1897350650Sobrien		      (match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
1897490286Sobrien  "TARGET_CMOVE
1897590286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1897690286Sobrien  "@
1897796294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1897896294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1897990286Sobrien  [(set_attr "type" "icmov")
1898090286Sobrien   (set_attr "mode" "HI")])
1898150650Sobrien
18982132727Skan(define_expand "movqicc"
18983132727Skan  [(set (match_operand:QI 0 "register_operand" "")
18984132727Skan	(if_then_else:QI (match_operand 1 "comparison_operator" "")
18985132727Skan			 (match_operand:QI 2 "general_operand" "")
18986132727Skan			 (match_operand:QI 3 "general_operand" "")))]
18987132727Skan  "TARGET_QIMODE_MATH"
18988132727Skan  "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
18989132727Skan
18990132727Skan(define_insn_and_split "*movqicc_noc"
18991132727Skan  [(set (match_operand:QI 0 "register_operand" "=r,r")
18992132727Skan	(if_then_else:QI (match_operator 1 "ix86_comparison_operator" 
18993169699Skan				[(match_operand 4 "flags_reg_operand" "")
18994169699Skan				 (const_int 0)])
18995132727Skan		      (match_operand:QI 2 "register_operand" "r,0")
18996132727Skan		      (match_operand:QI 3 "register_operand" "0,r")))]
18997132727Skan  "TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL"
18998132727Skan  "#"
18999132727Skan  "&& reload_completed"
19000132727Skan  [(set (match_dup 0)
19001132727Skan	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
19002132727Skan		      (match_dup 2)
19003132727Skan		      (match_dup 3)))]
19004132727Skan  "operands[0] = gen_lowpart (SImode, operands[0]);
19005132727Skan   operands[2] = gen_lowpart (SImode, operands[2]);
19006132727Skan   operands[3] = gen_lowpart (SImode, operands[3]);"
19007132727Skan  [(set_attr "type" "icmov")
19008132727Skan   (set_attr "mode" "SI")])
19009132727Skan
1901050650Sobrien(define_expand "movsfcc"
1901150650Sobrien  [(set (match_operand:SF 0 "register_operand" "")
1901250650Sobrien	(if_then_else:SF (match_operand 1 "comparison_operator" "")
1901350650Sobrien			 (match_operand:SF 2 "register_operand" "")
1901450650Sobrien			 (match_operand:SF 3 "register_operand" "")))]
19015169699Skan  "(TARGET_80387 && TARGET_CMOVE) || TARGET_SSE_MATH"
1901690286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1901750650Sobrien
19018169699Skan(define_insn "*movsfcc_1_387"
19019169699Skan  [(set (match_operand:SF 0 "register_operand" "=f,f,r,r")
1902090286Sobrien	(if_then_else:SF (match_operator 1 "fcmov_comparison_operator" 
19021169699Skan				[(reg FLAGS_REG) (const_int 0)])
19022169699Skan		      (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0")
19023169699Skan		      (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))]
19024169699Skan  "TARGET_80387 && TARGET_CMOVE
1902590286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1902690286Sobrien  "@
1902790286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1902890286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1902996294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1903096294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1903190286Sobrien  [(set_attr "type" "fcmov,fcmov,icmov,icmov")
1903290286Sobrien   (set_attr "mode" "SF,SF,SI,SI")])
1903350650Sobrien
1903490286Sobrien(define_expand "movdfcc"
1903590286Sobrien  [(set (match_operand:DF 0 "register_operand" "")
1903690286Sobrien	(if_then_else:DF (match_operand 1 "comparison_operator" "")
1903790286Sobrien			 (match_operand:DF 2 "register_operand" "")
1903890286Sobrien			 (match_operand:DF 3 "register_operand" "")))]
19039169699Skan  "(TARGET_80387 && TARGET_CMOVE) || (TARGET_SSE2 && TARGET_SSE_MATH)"
1904090286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1904150650Sobrien
1904290286Sobrien(define_insn "*movdfcc_1"
19043169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r")
1904490286Sobrien	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
19045169699Skan				[(reg FLAGS_REG) (const_int 0)])
19046169699Skan		      (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
19047169699Skan		      (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
19048169699Skan  "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
1904990286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1905090286Sobrien  "@
1905190286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1905290286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1905390286Sobrien   #
1905490286Sobrien   #"
1905590286Sobrien  [(set_attr "type" "fcmov,fcmov,multi,multi")
1905690286Sobrien   (set_attr "mode" "DF")])
1905750650Sobrien
1905890286Sobrien(define_insn "*movdfcc_1_rex64"
19059169699Skan  [(set (match_operand:DF 0 "register_operand" "=f,f,r,r")
1906090286Sobrien	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
19061169699Skan				[(reg FLAGS_REG) (const_int 0)])
19062169699Skan		      (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
19063169699Skan		      (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
19064169699Skan  "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
1906590286Sobrien   && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
1906690286Sobrien  "@
1906790286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1906890286Sobrien   fcmov%f1\t{%3, %0|%0, %3}
1906996294Sobrien   cmov%O2%C1\t{%2, %0|%0, %2}
1907096294Sobrien   cmov%O2%c1\t{%3, %0|%0, %3}"
1907190286Sobrien  [(set_attr "type" "fcmov,fcmov,icmov,icmov")
1907290286Sobrien   (set_attr "mode" "DF")])
1907350650Sobrien
1907490286Sobrien(define_split
19075117404Skan  [(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "")
1907690286Sobrien	(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" 
19077169699Skan				[(match_operand 4 "flags_reg_operand" "")
19078169699Skan				 (const_int 0)])
1907990286Sobrien		      (match_operand:DF 2 "nonimmediate_operand" "")
1908090286Sobrien		      (match_operand:DF 3 "nonimmediate_operand" "")))]
19081117404Skan  "!TARGET_64BIT && reload_completed"
1908290286Sobrien  [(set (match_dup 2)
1908390286Sobrien	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
1908490286Sobrien		      (match_dup 5)
1908590286Sobrien		      (match_dup 7)))
1908690286Sobrien   (set (match_dup 3)
1908790286Sobrien	(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
1908890286Sobrien		      (match_dup 6)
1908990286Sobrien		      (match_dup 8)))]
1909090286Sobrien  "split_di (operands+2, 1, operands+5, operands+6);
1909190286Sobrien   split_di (operands+3, 1, operands+7, operands+8);
1909290286Sobrien   split_di (operands, 1, operands+2, operands+3);")
1909350650Sobrien
1909490286Sobrien(define_expand "movxfcc"
1909590286Sobrien  [(set (match_operand:XF 0 "register_operand" "")
1909690286Sobrien	(if_then_else:XF (match_operand 1 "comparison_operator" "")
1909790286Sobrien			 (match_operand:XF 2 "register_operand" "")
1909890286Sobrien			 (match_operand:XF 3 "register_operand" "")))]
19099169699Skan  "TARGET_80387 && TARGET_CMOVE"
1910090286Sobrien  "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
1910190286Sobrien
1910290286Sobrien(define_insn "*movxfcc_1"
1910390286Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
1910490286Sobrien	(if_then_else:XF (match_operator 1 "fcmov_comparison_operator" 
19105169699Skan				[(reg FLAGS_REG) (const_int 0)])
1910690286Sobrien		      (match_operand:XF 2 "register_operand" "f,0")
1910790286Sobrien		      (match_operand:XF 3 "register_operand" "0,f")))]
19108169699Skan  "TARGET_80387 && TARGET_CMOVE"
1910990286Sobrien  "@
1911090286Sobrien   fcmov%F1\t{%2, %0|%0, %2}
1911190286Sobrien   fcmov%f1\t{%3, %0|%0, %3}"
1911290286Sobrien  [(set_attr "type" "fcmov")
1911390286Sobrien   (set_attr "mode" "XF")])
1911490286Sobrien
19115169699Skan;; These versions of the min/max patterns are intentionally ignorant of
19116169699Skan;; their behavior wrt -0.0 and NaN (via the commutative operand mark).
19117169699Skan;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
19118169699Skan;; are undefined in this condition, we're certain this is correct.
1911990286Sobrien
19120169699Skan(define_insn "sminsf3"
19121169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19122169699Skan	(smin:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
19123169699Skan		 (match_operand:SF 2 "nonimmediate_operand" "xm")))]
19124169699Skan  "TARGET_SSE_MATH"
19125169699Skan  "minss\t{%2, %0|%0, %2}"
19126169699Skan  [(set_attr "type" "sseadd")
19127169699Skan   (set_attr "mode" "SF")])
1912850650Sobrien
19129169699Skan(define_insn "smaxsf3"
19130169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19131169699Skan	(smax:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
19132169699Skan		 (match_operand:SF 2 "nonimmediate_operand" "xm")))]
19133169699Skan  "TARGET_SSE_MATH"
19134169699Skan  "maxss\t{%2, %0|%0, %2}"
19135169699Skan  [(set_attr "type" "sseadd")
19136169699Skan   (set_attr "mode" "SF")])
1913750650Sobrien
19138169699Skan(define_insn "smindf3"
19139169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19140169699Skan	(smin:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
19141169699Skan		 (match_operand:DF 2 "nonimmediate_operand" "xm")))]
19142169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19143169699Skan  "minsd\t{%2, %0|%0, %2}"
19144169699Skan  [(set_attr "type" "sseadd")
19145169699Skan   (set_attr "mode" "DF")])
1914650650Sobrien
19147169699Skan(define_insn "smaxdf3"
19148169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19149169699Skan	(smax:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
19150169699Skan		 (match_operand:DF 2 "nonimmediate_operand" "xm")))]
19151169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19152169699Skan  "maxsd\t{%2, %0|%0, %2}"
19153169699Skan  [(set_attr "type" "sseadd")
19154169699Skan   (set_attr "mode" "DF")])
19155169699Skan
19156169699Skan;; These versions of the min/max patterns implement exactly the operations
19157169699Skan;;   min = (op1 < op2 ? op1 : op2)
19158169699Skan;;   max = (!(op1 < op2) ? op1 : op2)
19159169699Skan;; Their operands are not commutative, and thus they may be used in the
19160169699Skan;; presence of -0.0 and NaN.
19161169699Skan
19162169699Skan(define_insn "*ieee_sminsf3"
19163169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19164169699Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")
19165169699Skan		    (match_operand:SF 2 "nonimmediate_operand" "xm")]
19166169699Skan		   UNSPEC_IEEE_MIN))]
19167169699Skan  "TARGET_SSE_MATH"
19168169699Skan  "minss\t{%2, %0|%0, %2}"
19169169699Skan  [(set_attr "type" "sseadd")
19170169699Skan   (set_attr "mode" "SF")])
19171169699Skan
19172169699Skan(define_insn "*ieee_smaxsf3"
19173169699Skan  [(set (match_operand:SF 0 "register_operand" "=x")
19174169699Skan	(unspec:SF [(match_operand:SF 1 "register_operand" "0")
19175169699Skan		    (match_operand:SF 2 "nonimmediate_operand" "xm")]
19176169699Skan		   UNSPEC_IEEE_MAX))]
19177169699Skan  "TARGET_SSE_MATH"
19178169699Skan  "maxss\t{%2, %0|%0, %2}"
19179169699Skan  [(set_attr "type" "sseadd")
19180169699Skan   (set_attr "mode" "SF")])
19181169699Skan
19182169699Skan(define_insn "*ieee_smindf3"
19183169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19184169699Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")
19185169699Skan		    (match_operand:DF 2 "nonimmediate_operand" "xm")]
19186169699Skan		   UNSPEC_IEEE_MIN))]
19187169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19188169699Skan  "minsd\t{%2, %0|%0, %2}"
19189169699Skan  [(set_attr "type" "sseadd")
19190169699Skan   (set_attr "mode" "DF")])
19191169699Skan
19192169699Skan(define_insn "*ieee_smaxdf3"
19193169699Skan  [(set (match_operand:DF 0 "register_operand" "=x")
19194169699Skan	(unspec:DF [(match_operand:DF 1 "register_operand" "0")
19195169699Skan		    (match_operand:DF 2 "nonimmediate_operand" "xm")]
19196169699Skan		   UNSPEC_IEEE_MAX))]
19197169699Skan  "TARGET_SSE2 && TARGET_SSE_MATH"
19198169699Skan  "maxsd\t{%2, %0|%0, %2}"
19199169699Skan  [(set_attr "type" "sseadd")
19200169699Skan   (set_attr "mode" "DF")])
19201169699Skan
19202169699Skan;; Make two stack loads independent:
19203169699Skan;;   fld aa              fld aa
19204169699Skan;;   fld %st(0)     ->   fld bb
19205169699Skan;;   fmul bb             fmul %st(1), %st
19206169699Skan;;
19207169699Skan;; Actually we only match the last two instructions for simplicity.
19208169699Skan(define_peephole2
19209169699Skan  [(set (match_operand 0 "fp_register_operand" "")
19210169699Skan	(match_operand 1 "fp_register_operand" ""))
19211169699Skan   (set (match_dup 0)
19212169699Skan	(match_operator 2 "binary_fp_operator"
19213169699Skan	   [(match_dup 0)
19214169699Skan	    (match_operand 3 "memory_operand" "")]))]
19215169699Skan  "REGNO (operands[0]) != REGNO (operands[1])"
19216169699Skan  [(set (match_dup 0) (match_dup 3))
19217169699Skan   (set (match_dup 0) (match_dup 4))]
19218169699Skan
19219169699Skan  ;; The % modifier is not operational anymore in peephole2's, so we have to
19220169699Skan  ;; swap the operands manually in the case of addition and multiplication.
19221169699Skan  "if (COMMUTATIVE_ARITH_P (operands[2]))
19222169699Skan     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
19223169699Skan				 operands[0], operands[1]);
19224169699Skan   else
19225169699Skan     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
19226169699Skan				 operands[1], operands[0]);")
19227169699Skan
19228132727Skan;; Conditional addition patterns
19229132727Skan(define_expand "addqicc"
19230132727Skan  [(match_operand:QI 0 "register_operand" "")
19231132727Skan   (match_operand 1 "comparison_operator" "")
19232132727Skan   (match_operand:QI 2 "register_operand" "")
19233132727Skan   (match_operand:QI 3 "const_int_operand" "")]
19234132727Skan  ""
19235132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19236132727Skan
19237132727Skan(define_expand "addhicc"
19238132727Skan  [(match_operand:HI 0 "register_operand" "")
19239132727Skan   (match_operand 1 "comparison_operator" "")
19240132727Skan   (match_operand:HI 2 "register_operand" "")
19241132727Skan   (match_operand:HI 3 "const_int_operand" "")]
19242132727Skan  ""
19243132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19244132727Skan
19245132727Skan(define_expand "addsicc"
19246132727Skan  [(match_operand:SI 0 "register_operand" "")
19247132727Skan   (match_operand 1 "comparison_operator" "")
19248132727Skan   (match_operand:SI 2 "register_operand" "")
19249132727Skan   (match_operand:SI 3 "const_int_operand" "")]
19250132727Skan  ""
19251132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19252132727Skan
19253132727Skan(define_expand "adddicc"
19254132727Skan  [(match_operand:DI 0 "register_operand" "")
19255132727Skan   (match_operand 1 "comparison_operator" "")
19256132727Skan   (match_operand:DI 2 "register_operand" "")
19257132727Skan   (match_operand:DI 3 "const_int_operand" "")]
19258132727Skan  "TARGET_64BIT"
19259132727Skan  "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
19260132727Skan
1926190286Sobrien
1926290286Sobrien;; Misc patterns (?)
1926350650Sobrien
1926490286Sobrien;; This pattern exists to put a dependency on all ebp-based memory accesses.
1926590286Sobrien;; Otherwise there will be nothing to keep
1926690286Sobrien;; 
1926790286Sobrien;; [(set (reg ebp) (reg esp))]
1926890286Sobrien;; [(set (reg esp) (plus (reg esp) (const_int -160000)))
1926990286Sobrien;;  (clobber (eflags)]
1927090286Sobrien;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))]
1927190286Sobrien;;
1927290286Sobrien;; in proper program order.
19273132727Skan(define_insn "pro_epilogue_adjust_stack_1"
1927490286Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
1927590286Sobrien	(plus:SI (match_operand:SI 1 "register_operand" "0,r")
1927690286Sobrien	         (match_operand:SI 2 "immediate_operand" "i,i")))
19277169699Skan   (clobber (reg:CC FLAGS_REG))
1927890286Sobrien   (clobber (mem:BLK (scratch)))]
1927990286Sobrien  "!TARGET_64BIT"
1928090286Sobrien{
1928190286Sobrien  switch (get_attr_type (insn))
1928290286Sobrien    {
1928390286Sobrien    case TYPE_IMOV:
1928490286Sobrien      return "mov{l}\t{%1, %0|%0, %1}";
1928550650Sobrien
1928690286Sobrien    case TYPE_ALU:
1928790286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
1928890286Sobrien          && (INTVAL (operands[2]) == 128
1928990286Sobrien	      || (INTVAL (operands[2]) < 0
1929090286Sobrien	          && INTVAL (operands[2]) != -128)))
1929190286Sobrien	{
1929290286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
1929390286Sobrien	  return "sub{l}\t{%2, %0|%0, %2}";
1929490286Sobrien	}
1929590286Sobrien      return "add{l}\t{%2, %0|%0, %2}";
1929650650Sobrien
1929790286Sobrien    case TYPE_LEA:
1929890286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
1929990286Sobrien      return "lea{l}\t{%a2, %0|%0, %a2}";
1930090286Sobrien
1930190286Sobrien    default:
19302169699Skan      gcc_unreachable ();
1930390286Sobrien    }
1930490286Sobrien}
1930590286Sobrien  [(set (attr "type")
1930690286Sobrien	(cond [(eq_attr "alternative" "0")
1930790286Sobrien		 (const_string "alu")
1930890286Sobrien	       (match_operand:SI 2 "const0_operand" "")
1930990286Sobrien		 (const_string "imov")
1931090286Sobrien	      ]
1931190286Sobrien	      (const_string "lea")))
1931290286Sobrien   (set_attr "mode" "SI")])
1931390286Sobrien
1931490286Sobrien(define_insn "pro_epilogue_adjust_stack_rex64"
1931590286Sobrien  [(set (match_operand:DI 0 "register_operand" "=r,r")
1931690286Sobrien	(plus:DI (match_operand:DI 1 "register_operand" "0,r")
1931790286Sobrien		 (match_operand:DI 2 "x86_64_immediate_operand" "e,e")))
19318169699Skan   (clobber (reg:CC FLAGS_REG))
1931990286Sobrien   (clobber (mem:BLK (scratch)))]
1932090286Sobrien  "TARGET_64BIT"
1932190286Sobrien{
1932290286Sobrien  switch (get_attr_type (insn))
1932350650Sobrien    {
1932490286Sobrien    case TYPE_IMOV:
1932590286Sobrien      return "mov{q}\t{%1, %0|%0, %1}";
1932650650Sobrien
1932790286Sobrien    case TYPE_ALU:
1932890286Sobrien      if (GET_CODE (operands[2]) == CONST_INT
19329132727Skan	  /* Avoid overflows.  */
19330132727Skan	  && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
1933190286Sobrien          && (INTVAL (operands[2]) == 128
1933290286Sobrien	      || (INTVAL (operands[2]) < 0
1933390286Sobrien	          && INTVAL (operands[2]) != -128)))
1933490286Sobrien	{
1933590286Sobrien	  operands[2] = GEN_INT (-INTVAL (operands[2]));
1933690286Sobrien	  return "sub{q}\t{%2, %0|%0, %2}";
1933790286Sobrien	}
1933890286Sobrien      return "add{q}\t{%2, %0|%0, %2}";
1933950650Sobrien
1934090286Sobrien    case TYPE_LEA:
1934190286Sobrien      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
1934290286Sobrien      return "lea{q}\t{%a2, %0|%0, %a2}";
1934350650Sobrien
1934450650Sobrien    default:
19345169699Skan      gcc_unreachable ();
1934650650Sobrien    }
1934790286Sobrien}
1934890286Sobrien  [(set (attr "type")
1934990286Sobrien	(cond [(eq_attr "alternative" "0")
1935090286Sobrien		 (const_string "alu")
1935190286Sobrien	       (match_operand:DI 2 "const0_operand" "")
1935290286Sobrien		 (const_string "imov")
1935390286Sobrien	      ]
1935490286Sobrien	      (const_string "lea")))
1935590286Sobrien   (set_attr "mode" "DI")])
1935650650Sobrien
19357132727Skan(define_insn "pro_epilogue_adjust_stack_rex64_2"
19358132727Skan  [(set (match_operand:DI 0 "register_operand" "=r,r")
19359132727Skan	(plus:DI (match_operand:DI 1 "register_operand" "0,r")
19360132727Skan		 (match_operand:DI 3 "immediate_operand" "i,i")))
19361132727Skan   (use (match_operand:DI 2 "register_operand" "r,r"))
19362169699Skan   (clobber (reg:CC FLAGS_REG))
19363132727Skan   (clobber (mem:BLK (scratch)))]
19364132727Skan  "TARGET_64BIT"
19365132727Skan{
19366132727Skan  switch (get_attr_type (insn))
19367132727Skan    {
19368132727Skan    case TYPE_ALU:
19369132727Skan      return "add{q}\t{%2, %0|%0, %2}";
1937090286Sobrien
19371132727Skan    case TYPE_LEA:
19372132727Skan      operands[2] = gen_rtx_PLUS (DImode, operands[1], operands[2]);
19373132727Skan      return "lea{q}\t{%a2, %0|%0, %a2}";
19374132727Skan
19375132727Skan    default:
19376169699Skan      gcc_unreachable ();
19377132727Skan    }
19378132727Skan}
19379132727Skan  [(set_attr "type" "alu,lea")
19380132727Skan   (set_attr "mode" "DI")])
19381132727Skan
1938290286Sobrien(define_expand "allocate_stack_worker"
1938390286Sobrien  [(match_operand:SI 0 "register_operand" "")]
1938490286Sobrien  "TARGET_STACK_PROBE"
1938590286Sobrien{
19386132727Skan  if (reload_completed)
19387132727Skan    {
19388132727Skan      if (TARGET_64BIT)
19389132727Skan	emit_insn (gen_allocate_stack_worker_rex64_postreload (operands[0]));
19390132727Skan      else
19391132727Skan	emit_insn (gen_allocate_stack_worker_postreload (operands[0]));
19392132727Skan    }
1939390286Sobrien  else
19394132727Skan    {
19395132727Skan      if (TARGET_64BIT)
19396132727Skan	emit_insn (gen_allocate_stack_worker_rex64 (operands[0]));
19397132727Skan      else
19398132727Skan	emit_insn (gen_allocate_stack_worker_1 (operands[0]));
19399132727Skan    }
1940090286Sobrien  DONE;
1940190286Sobrien})
1940250650Sobrien
1940390286Sobrien(define_insn "allocate_stack_worker_1"
19404132727Skan  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
19405132727Skan    UNSPECV_STACK_PROBE)
19406169699Skan   (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
19407132727Skan   (clobber (match_scratch:SI 1 "=0"))
19408169699Skan   (clobber (reg:CC FLAGS_REG))]
1940990286Sobrien  "!TARGET_64BIT && TARGET_STACK_PROBE"
1941090286Sobrien  "call\t__alloca"
1941190286Sobrien  [(set_attr "type" "multi")
1941290286Sobrien   (set_attr "length" "5")])
1941350650Sobrien
19414132727Skan(define_expand "allocate_stack_worker_postreload"
19415132727Skan  [(parallel [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
19416132727Skan				    UNSPECV_STACK_PROBE)
19417169699Skan	      (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
19418132727Skan	      (clobber (match_dup 0))
19419169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19420132727Skan  ""
19421132727Skan  "")
19422132727Skan
1942390286Sobrien(define_insn "allocate_stack_worker_rex64"
19424132727Skan  [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
19425132727Skan    UNSPECV_STACK_PROBE)
19426169699Skan   (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
19427132727Skan   (clobber (match_scratch:DI 1 "=0"))
19428169699Skan   (clobber (reg:CC FLAGS_REG))]
1942990286Sobrien  "TARGET_64BIT && TARGET_STACK_PROBE"
1943090286Sobrien  "call\t__alloca"
1943190286Sobrien  [(set_attr "type" "multi")
1943290286Sobrien   (set_attr "length" "5")])
1943390286Sobrien
19434132727Skan(define_expand "allocate_stack_worker_rex64_postreload"
19435132727Skan  [(parallel [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
19436132727Skan				    UNSPECV_STACK_PROBE)
19437169699Skan	      (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
19438132727Skan	      (clobber (match_dup 0))
19439169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19440132727Skan  ""
19441132727Skan  "")
19442132727Skan
1944350650Sobrien(define_expand "allocate_stack"
1944490286Sobrien  [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
19445169699Skan		   (minus:SI (reg:SI SP_REG)
1944690286Sobrien			     (match_operand:SI 1 "general_operand" "")))
19447169699Skan	      (clobber (reg:CC FLAGS_REG))])
19448169699Skan   (parallel [(set (reg:SI SP_REG)
19449169699Skan		   (minus:SI (reg:SI SP_REG) (match_dup 1)))
19450169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1945190286Sobrien  "TARGET_STACK_PROBE"
1945250650Sobrien{
1945350650Sobrien#ifdef CHECK_STACK_LIMIT
1945450650Sobrien  if (GET_CODE (operands[1]) == CONST_INT
1945550650Sobrien      && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
1945650650Sobrien    emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
1945750650Sobrien			   operands[1]));
1945850650Sobrien  else 
1945950650Sobrien#endif
1946050650Sobrien    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
1946150650Sobrien							    operands[1])));
1946250650Sobrien
1946350650Sobrien  emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
1946450650Sobrien  DONE;
1946590286Sobrien})
1946650650Sobrien
1946790286Sobrien(define_expand "builtin_setjmp_receiver"
1946890286Sobrien  [(label_ref (match_operand 0 "" ""))]
1946990286Sobrien  "!TARGET_64BIT && flag_pic"
1947050650Sobrien{
19471169699Skan  if (TARGET_MACHO)
19472169699Skan    {
19473169699Skan      rtx xops[3];
19474169699Skan      rtx picreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
19475169699Skan      rtx label_rtx = gen_label_rtx ();
19476169699Skan      emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx));
19477169699Skan      xops[0] = xops[1] = picreg;
19478169699Skan      xops[2] = gen_rtx_CONST (SImode,
19479169699Skan	          gen_rtx_MINUS (SImode,
19480169699Skan		    gen_rtx_LABEL_REF (SImode, label_rtx),
19481169699Skan		    gen_rtx_SYMBOL_REF (SImode, GOT_SYMBOL_NAME)));
19482169699Skan      ix86_expand_binary_operator (MINUS, SImode, xops);
19483169699Skan    }
19484169699Skan  else
19485169699Skan    emit_insn (gen_set_got (pic_offset_table_rtx));
1948656391Sobrien  DONE;
1948790286Sobrien})
1948890286Sobrien
1948990286Sobrien;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
1949056391Sobrien
1949190286Sobrien(define_split
1949290286Sobrien  [(set (match_operand 0 "register_operand" "")
1949390286Sobrien	(match_operator 3 "promotable_binary_operator"
1949490286Sobrien	   [(match_operand 1 "register_operand" "")
1949590286Sobrien	    (match_operand 2 "aligned_operand" "")]))
19496169699Skan   (clobber (reg:CC FLAGS_REG))]
1949790286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1949890286Sobrien   && ((GET_MODE (operands[0]) == HImode 
19499117404Skan	&& ((!optimize_size && !TARGET_FAST_PREFIX)
19500169699Skan            /* ??? next two lines just !satisfies_constraint_K (...) */
19501117404Skan	    || GET_CODE (operands[2]) != CONST_INT
19502169699Skan	    || satisfies_constraint_K (operands[2])))
1950390286Sobrien       || (GET_MODE (operands[0]) == QImode 
1950490286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1950590286Sobrien  [(parallel [(set (match_dup 0)
1950690286Sobrien		   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
19507169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1950890286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1950990286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);
1951090286Sobrien   if (GET_CODE (operands[3]) != ASHIFT)
1951190286Sobrien     operands[2] = gen_lowpart (SImode, operands[2]);
1951290286Sobrien   PUT_MODE (operands[3], SImode);")
1951390286Sobrien
19514117404Skan; Promote the QImode tests, as i386 has encoding of the AND
19515117404Skan; instruction with 32-bit sign-extended immediate and thus the
19516117404Skan; instruction size is unchanged, except in the %eax case for
19517117404Skan; which it is increased by one byte, hence the ! optimize_size.
1951890286Sobrien(define_split
19519146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19520146906Skan	(match_operator 2 "compare_operator"
19521146906Skan	  [(and (match_operand 3 "aligned_operand" "")
19522146906Skan		(match_operand 4 "const_int_operand" ""))
19523146906Skan	   (const_int 0)]))
19524146906Skan   (set (match_operand 1 "register_operand" "")
19525146906Skan	(and (match_dup 3) (match_dup 4)))]
1952690286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
19527117404Skan   /* Ensure that the operand will remain sign-extended immediate.  */
19528146906Skan   && ix86_match_ccmode (insn, INTVAL (operands[4]) >= 0 ? CCNOmode : CCZmode)
19529117404Skan   && ! optimize_size
19530146906Skan   && ((GET_MODE (operands[1]) == HImode && ! TARGET_FAST_PREFIX)
19531146906Skan       || (GET_MODE (operands[1]) == QImode && TARGET_PROMOTE_QImode))"
19532146906Skan  [(parallel [(set (match_dup 0)
19533146906Skan		   (match_op_dup 2 [(and:SI (match_dup 3) (match_dup 4))
19534146906Skan			            (const_int 0)]))
19535146906Skan	      (set (match_dup 1)
19536146906Skan		   (and:SI (match_dup 3) (match_dup 4)))])]
19537146906Skan{
19538146906Skan  operands[4]
19539146906Skan    = gen_int_mode (INTVAL (operands[4])
19540146906Skan		    & GET_MODE_MASK (GET_MODE (operands[1])), SImode);
19541146906Skan  operands[1] = gen_lowpart (SImode, operands[1]);
19542146906Skan  operands[3] = gen_lowpart (SImode, operands[3]);
19543146906Skan})
1954490286Sobrien
19545117404Skan; Don't promote the QImode tests, as i386 doesn't have encoding of
19546117404Skan; the TEST instruction with 32-bit sign-extended immediate and thus
19547117404Skan; the instruction size would at least double, which is not what we
19548117404Skan; want even with ! optimize_size.
1954990286Sobrien(define_split
19550146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19551146906Skan	(match_operator 1 "compare_operator"
19552146906Skan	  [(and (match_operand:HI 2 "aligned_operand" "")
19553146906Skan		(match_operand:HI 3 "const_int_operand" ""))
19554146906Skan	   (const_int 0)]))]
1955590286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
19556117404Skan   /* Ensure that the operand will remain sign-extended immediate.  */
19557146906Skan   && ix86_match_ccmode (insn, INTVAL (operands[3]) >= 0 ? CCNOmode : CCZmode)
19558117404Skan   && ! TARGET_FAST_PREFIX
19559117404Skan   && ! optimize_size"
19560146906Skan  [(set (match_dup 0)
19561146906Skan	(match_op_dup 1 [(and:SI (match_dup 2) (match_dup 3))
19562146906Skan		         (const_int 0)]))]
19563146906Skan{
19564146906Skan  operands[3]
19565146906Skan    = gen_int_mode (INTVAL (operands[3])
19566146906Skan		    & GET_MODE_MASK (GET_MODE (operands[2])), SImode);
19567146906Skan  operands[2] = gen_lowpart (SImode, operands[2]);
19568146906Skan})
1956990286Sobrien
1957090286Sobrien(define_split
1957190286Sobrien  [(set (match_operand 0 "register_operand" "")
1957290286Sobrien	(neg (match_operand 1 "register_operand" "")))
19573169699Skan   (clobber (reg:CC FLAGS_REG))]
1957490286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1957590286Sobrien   && (GET_MODE (operands[0]) == HImode
1957690286Sobrien       || (GET_MODE (operands[0]) == QImode 
1957790286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1957890286Sobrien  [(parallel [(set (match_dup 0)
1957990286Sobrien		   (neg:SI (match_dup 1)))
19580169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1958190286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1958290286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);")
1958390286Sobrien
1958490286Sobrien(define_split
1958590286Sobrien  [(set (match_operand 0 "register_operand" "")
1958690286Sobrien	(not (match_operand 1 "register_operand" "")))]
1958790286Sobrien  "! TARGET_PARTIAL_REG_STALL && reload_completed
1958890286Sobrien   && (GET_MODE (operands[0]) == HImode
1958990286Sobrien       || (GET_MODE (operands[0]) == QImode 
1959090286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1959190286Sobrien  [(set (match_dup 0)
1959290286Sobrien	(not:SI (match_dup 1)))]
1959390286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1959490286Sobrien   operands[1] = gen_lowpart (SImode, operands[1]);")
1959590286Sobrien
1959690286Sobrien(define_split 
1959790286Sobrien  [(set (match_operand 0 "register_operand" "")
1959890286Sobrien	(if_then_else (match_operator 1 "comparison_operator" 
19599169699Skan				[(reg FLAGS_REG) (const_int 0)])
1960090286Sobrien		      (match_operand 2 "register_operand" "")
1960190286Sobrien		      (match_operand 3 "register_operand" "")))]
1960290286Sobrien  "! TARGET_PARTIAL_REG_STALL && TARGET_CMOVE
1960390286Sobrien   && (GET_MODE (operands[0]) == HImode
1960490286Sobrien       || (GET_MODE (operands[0]) == QImode 
1960590286Sobrien	   && (TARGET_PROMOTE_QImode || optimize_size)))"
1960690286Sobrien  [(set (match_dup 0)
1960790286Sobrien	(if_then_else:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
1960890286Sobrien  "operands[0] = gen_lowpart (SImode, operands[0]);
1960990286Sobrien   operands[2] = gen_lowpart (SImode, operands[2]);
1961090286Sobrien   operands[3] = gen_lowpart (SImode, operands[3]);")
1961190286Sobrien			
1961290286Sobrien
1961390286Sobrien;; RTL Peephole optimizations, run before sched2.  These primarily look to
1961490286Sobrien;; transform a complex memory operation into two memory to register operations.
1961590286Sobrien
1961690286Sobrien;; Don't push memory operands
1961790286Sobrien(define_peephole2
1961890286Sobrien  [(set (match_operand:SI 0 "push_operand" "")
1961990286Sobrien	(match_operand:SI 1 "memory_operand" ""))
1962090286Sobrien   (match_scratch:SI 2 "r")]
19621169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19622169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1962390286Sobrien  [(set (match_dup 2) (match_dup 1))
1962490286Sobrien   (set (match_dup 0) (match_dup 2))]
1962590286Sobrien  "")
1962690286Sobrien
1962790286Sobrien(define_peephole2
1962890286Sobrien  [(set (match_operand:DI 0 "push_operand" "")
1962990286Sobrien	(match_operand:DI 1 "memory_operand" ""))
1963090286Sobrien   (match_scratch:DI 2 "r")]
19631169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19632169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1963390286Sobrien  [(set (match_dup 2) (match_dup 1))
1963490286Sobrien   (set (match_dup 0) (match_dup 2))]
1963590286Sobrien  "")
1963690286Sobrien
1963790286Sobrien;; We need to handle SFmode only, because DFmode and XFmode is split to
1963890286Sobrien;; SImode pushes.
1963990286Sobrien(define_peephole2
1964090286Sobrien  [(set (match_operand:SF 0 "push_operand" "")
1964190286Sobrien	(match_operand:SF 1 "memory_operand" ""))
1964290286Sobrien   (match_scratch:SF 2 "r")]
19643169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19644169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1964590286Sobrien  [(set (match_dup 2) (match_dup 1))
1964690286Sobrien   (set (match_dup 0) (match_dup 2))]
1964790286Sobrien  "")
1964890286Sobrien
1964990286Sobrien(define_peephole2
1965090286Sobrien  [(set (match_operand:HI 0 "push_operand" "")
1965190286Sobrien	(match_operand:HI 1 "memory_operand" ""))
1965290286Sobrien   (match_scratch:HI 2 "r")]
19653169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19654169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1965590286Sobrien  [(set (match_dup 2) (match_dup 1))
1965690286Sobrien   (set (match_dup 0) (match_dup 2))]
1965790286Sobrien  "")
1965890286Sobrien
1965990286Sobrien(define_peephole2
1966090286Sobrien  [(set (match_operand:QI 0 "push_operand" "")
1966190286Sobrien	(match_operand:QI 1 "memory_operand" ""))
1966290286Sobrien   (match_scratch:QI 2 "q")]
19663169699Skan  "!optimize_size && !TARGET_PUSH_MEMORY
19664169699Skan   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
1966590286Sobrien  [(set (match_dup 2) (match_dup 1))
1966690286Sobrien   (set (match_dup 0) (match_dup 2))]
1966790286Sobrien  "")
1966890286Sobrien
1966990286Sobrien;; Don't move an immediate directly to memory when the instruction
1967090286Sobrien;; gets too big.
1967190286Sobrien(define_peephole2
1967290286Sobrien  [(match_scratch:SI 1 "r")
1967390286Sobrien   (set (match_operand:SI 0 "memory_operand" "")
1967490286Sobrien        (const_int 0))]
1967590286Sobrien  "! optimize_size
1967690286Sobrien   && ! TARGET_USE_MOV0
1967790286Sobrien   && TARGET_SPLIT_LONG_MOVES
1967890286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1967990286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1968090286Sobrien  [(parallel [(set (match_dup 1) (const_int 0))
19681169699Skan	      (clobber (reg:CC FLAGS_REG))])
1968290286Sobrien   (set (match_dup 0) (match_dup 1))]
1968390286Sobrien  "")
1968490286Sobrien
1968590286Sobrien(define_peephole2
1968690286Sobrien  [(match_scratch:HI 1 "r")
1968790286Sobrien   (set (match_operand:HI 0 "memory_operand" "")
1968890286Sobrien        (const_int 0))]
1968990286Sobrien  "! optimize_size
1969090286Sobrien   && ! TARGET_USE_MOV0
1969190286Sobrien   && TARGET_SPLIT_LONG_MOVES
1969290286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1969390286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1969490286Sobrien  [(parallel [(set (match_dup 2) (const_int 0))
19695169699Skan	      (clobber (reg:CC FLAGS_REG))])
1969690286Sobrien   (set (match_dup 0) (match_dup 1))]
19697132727Skan  "operands[2] = gen_lowpart (SImode, operands[1]);")
1969890286Sobrien
1969990286Sobrien(define_peephole2
1970090286Sobrien  [(match_scratch:QI 1 "q")
1970190286Sobrien   (set (match_operand:QI 0 "memory_operand" "")
1970290286Sobrien        (const_int 0))]
1970390286Sobrien  "! optimize_size
1970490286Sobrien   && ! TARGET_USE_MOV0
1970590286Sobrien   && TARGET_SPLIT_LONG_MOVES
1970690286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1970790286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1970890286Sobrien  [(parallel [(set (match_dup 2) (const_int 0))
19709169699Skan	      (clobber (reg:CC FLAGS_REG))])
1971090286Sobrien   (set (match_dup 0) (match_dup 1))]
19711132727Skan  "operands[2] = gen_lowpart (SImode, operands[1]);")
1971290286Sobrien
1971390286Sobrien(define_peephole2
1971490286Sobrien  [(match_scratch:SI 2 "r")
1971590286Sobrien   (set (match_operand:SI 0 "memory_operand" "")
1971690286Sobrien        (match_operand:SI 1 "immediate_operand" ""))]
1971790286Sobrien  "! optimize_size
1971890286Sobrien   && get_attr_length (insn) >= ix86_cost->large_insn
1971990286Sobrien   && TARGET_SPLIT_LONG_MOVES"
1972090286Sobrien  [(set (match_dup 2) (match_dup 1))
1972190286Sobrien   (set (match_dup 0) (match_dup 2))]
1972290286Sobrien  "")
1972390286Sobrien
1972490286Sobrien(define_peephole2
1972590286Sobrien  [(match_scratch:HI 2 "r")
1972690286Sobrien   (set (match_operand:HI 0 "memory_operand" "")
1972790286Sobrien        (match_operand:HI 1 "immediate_operand" ""))]
1972890286Sobrien  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
1972990286Sobrien  && TARGET_SPLIT_LONG_MOVES"
1973090286Sobrien  [(set (match_dup 2) (match_dup 1))
1973190286Sobrien   (set (match_dup 0) (match_dup 2))]
1973290286Sobrien  "")
1973390286Sobrien
1973490286Sobrien(define_peephole2
1973590286Sobrien  [(match_scratch:QI 2 "q")
1973690286Sobrien   (set (match_operand:QI 0 "memory_operand" "")
1973790286Sobrien        (match_operand:QI 1 "immediate_operand" ""))]
1973890286Sobrien  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
1973990286Sobrien  && TARGET_SPLIT_LONG_MOVES"
1974090286Sobrien  [(set (match_dup 2) (match_dup 1))
1974190286Sobrien   (set (match_dup 0) (match_dup 2))]
1974290286Sobrien  "")
1974390286Sobrien
1974490286Sobrien;; Don't compare memory with zero, load and use a test instead.
1974590286Sobrien(define_peephole2
19746146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19747146906Skan 	(match_operator 1 "compare_operator"
19748146906Skan	  [(match_operand:SI 2 "memory_operand" "")
19749146906Skan	   (const_int 0)]))
1975090286Sobrien   (match_scratch:SI 3 "r")]
1975190286Sobrien  "ix86_match_ccmode (insn, CCNOmode) && ! optimize_size"
19752146906Skan  [(set (match_dup 3) (match_dup 2))
19753146906Skan   (set (match_dup 0) (match_op_dup 1 [(match_dup 3) (const_int 0)]))]
1975490286Sobrien  "")
1975590286Sobrien
1975690286Sobrien;; NOT is not pairable on Pentium, while XOR is, but one byte longer. 
1975790286Sobrien;; Don't split NOTs with a displacement operand, because resulting XOR
19758132727Skan;; will not be pairable anyway.
1975990286Sobrien;;
19760169699Skan;; On AMD K6, NOT is vector decoded with memory operand that cannot be
1976190286Sobrien;; represented using a modRM byte.  The XOR replacement is long decoded,
1976290286Sobrien;; so this split helps here as well.
1976390286Sobrien;;
1976490286Sobrien;; Note: Can't do this as a regular split because we can't get proper
1976590286Sobrien;; lifetime information then.
1976690286Sobrien
1976790286Sobrien(define_peephole2
1976890286Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1976990286Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
1977090286Sobrien  "!optimize_size
1977190286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
1977290286Sobrien   && ((TARGET_PENTIUM 
1977390286Sobrien        && (GET_CODE (operands[0]) != MEM
1977490286Sobrien            || !memory_displacement_operand (operands[0], SImode)))
1977590286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], SImode)))"
1977690286Sobrien  [(parallel [(set (match_dup 0)
1977790286Sobrien		   (xor:SI (match_dup 1) (const_int -1)))
19778169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1977990286Sobrien  "")
1978090286Sobrien
1978190286Sobrien(define_peephole2
1978290286Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1978390286Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
1978490286Sobrien  "!optimize_size
1978590286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
1978690286Sobrien   && ((TARGET_PENTIUM 
1978790286Sobrien        && (GET_CODE (operands[0]) != MEM
1978890286Sobrien            || !memory_displacement_operand (operands[0], HImode)))
1978990286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], HImode)))"
1979090286Sobrien  [(parallel [(set (match_dup 0)
1979190286Sobrien		   (xor:HI (match_dup 1) (const_int -1)))
19792169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1979390286Sobrien  "")
1979490286Sobrien
1979590286Sobrien(define_peephole2
1979690286Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1979790286Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
1979890286Sobrien  "!optimize_size
1979990286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)
1980090286Sobrien   && ((TARGET_PENTIUM 
1980190286Sobrien        && (GET_CODE (operands[0]) != MEM
1980290286Sobrien            || !memory_displacement_operand (operands[0], QImode)))
1980390286Sobrien       || (TARGET_K6 && long_memory_operand (operands[0], QImode)))"
1980490286Sobrien  [(parallel [(set (match_dup 0)
1980590286Sobrien		   (xor:QI (match_dup 1) (const_int -1)))
19806169699Skan	      (clobber (reg:CC FLAGS_REG))])]
1980790286Sobrien  "")
1980890286Sobrien
1980990286Sobrien;; Non pairable "test imm, reg" instructions can be translated to
1981090286Sobrien;; "and imm, reg" if reg dies.  The "and" form is also shorter (one
1981190286Sobrien;; byte opcode instead of two, have a short form for byte operands),
1981290286Sobrien;; so do it for other CPUs as well.  Given that the value was dead,
1981390286Sobrien;; this should not create any new dependencies.  Pass on the sub-word
1981490286Sobrien;; versions if we're concerned about partial register stalls.
1981590286Sobrien
1981690286Sobrien(define_peephole2
19817146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19818146906Skan	(match_operator 1 "compare_operator"
19819146906Skan	  [(and:SI (match_operand:SI 2 "register_operand" "")
19820146906Skan		   (match_operand:SI 3 "immediate_operand" ""))
19821146906Skan	   (const_int 0)]))]
1982290286Sobrien  "ix86_match_ccmode (insn, CCNOmode)
19823146906Skan   && (true_regnum (operands[2]) != 0
19824169699Skan       || satisfies_constraint_K (operands[3]))
19825146906Skan   && peep2_reg_dead_p (1, operands[2])"
1982690286Sobrien  [(parallel
19827146906Skan     [(set (match_dup 0)
19828146906Skan	   (match_op_dup 1 [(and:SI (match_dup 2) (match_dup 3))
19829146906Skan		            (const_int 0)]))
19830146906Skan      (set (match_dup 2)
19831146906Skan	   (and:SI (match_dup 2) (match_dup 3)))])]
1983290286Sobrien  "")
1983390286Sobrien
1983490286Sobrien;; We don't need to handle HImode case, because it will be promoted to SImode
1983590286Sobrien;; on ! TARGET_PARTIAL_REG_STALL
1983690286Sobrien
1983790286Sobrien(define_peephole2
19838146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19839146906Skan	(match_operator 1 "compare_operator"
19840146906Skan	  [(and:QI (match_operand:QI 2 "register_operand" "")
19841146906Skan		   (match_operand:QI 3 "immediate_operand" ""))
19842146906Skan	   (const_int 0)]))]
1984390286Sobrien  "! TARGET_PARTIAL_REG_STALL
1984490286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
19845146906Skan   && true_regnum (operands[2]) != 0
19846146906Skan   && peep2_reg_dead_p (1, operands[2])"
1984790286Sobrien  [(parallel
19848146906Skan     [(set (match_dup 0)
19849146906Skan	   (match_op_dup 1 [(and:QI (match_dup 2) (match_dup 3))
19850146906Skan		            (const_int 0)]))
19851146906Skan      (set (match_dup 2)
19852146906Skan	   (and:QI (match_dup 2) (match_dup 3)))])]
1985390286Sobrien  "")
1985490286Sobrien
1985590286Sobrien(define_peephole2
19856146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
19857146906Skan	(match_operator 1 "compare_operator"
19858146906Skan	  [(and:SI
19859146906Skan	     (zero_extract:SI
19860146906Skan	       (match_operand 2 "ext_register_operand" "")
19861146906Skan	       (const_int 8)
19862146906Skan	       (const_int 8))
19863146906Skan	     (match_operand 3 "const_int_operand" ""))
19864146906Skan	   (const_int 0)]))]
1986590286Sobrien  "! TARGET_PARTIAL_REG_STALL
1986690286Sobrien   && ix86_match_ccmode (insn, CCNOmode)
19867146906Skan   && true_regnum (operands[2]) != 0
19868146906Skan   && peep2_reg_dead_p (1, operands[2])"
19869146906Skan  [(parallel [(set (match_dup 0)
19870146906Skan		   (match_op_dup 1
19871146906Skan		     [(and:SI
19872146906Skan			(zero_extract:SI
19873146906Skan			  (match_dup 2)
19874146906Skan			  (const_int 8)
19875146906Skan			  (const_int 8))
19876146906Skan			(match_dup 3))
19877146906Skan		      (const_int 0)]))
19878146906Skan	      (set (zero_extract:SI (match_dup 2)
1987990286Sobrien				    (const_int 8)
1988090286Sobrien				    (const_int 8))
1988190286Sobrien		   (and:SI 
1988290286Sobrien		     (zero_extract:SI
19883146906Skan		       (match_dup 2)
1988490286Sobrien		       (const_int 8)
1988590286Sobrien		       (const_int 8))
19886146906Skan		     (match_dup 3)))])]
1988790286Sobrien  "")
1988890286Sobrien
1988990286Sobrien;; Don't do logical operations with memory inputs.
1989090286Sobrien(define_peephole2
1989190286Sobrien  [(match_scratch:SI 2 "r")
1989290286Sobrien   (parallel [(set (match_operand:SI 0 "register_operand" "")
1989390286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1989490286Sobrien                     [(match_dup 0)
1989590286Sobrien                      (match_operand:SI 1 "memory_operand" "")]))
19896169699Skan              (clobber (reg:CC FLAGS_REG))])]
1989790286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY"
1989890286Sobrien  [(set (match_dup 2) (match_dup 1))
1989990286Sobrien   (parallel [(set (match_dup 0)
1990090286Sobrien                   (match_op_dup 3 [(match_dup 0) (match_dup 2)]))
19901169699Skan              (clobber (reg:CC FLAGS_REG))])]
1990290286Sobrien  "")
1990390286Sobrien
1990490286Sobrien(define_peephole2
1990590286Sobrien  [(match_scratch:SI 2 "r")
1990690286Sobrien   (parallel [(set (match_operand:SI 0 "register_operand" "")
1990790286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1990890286Sobrien                     [(match_operand:SI 1 "memory_operand" "")
1990990286Sobrien                      (match_dup 0)]))
19910169699Skan              (clobber (reg:CC FLAGS_REG))])]
1991190286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY"
1991290286Sobrien  [(set (match_dup 2) (match_dup 1))
1991390286Sobrien   (parallel [(set (match_dup 0)
1991490286Sobrien                   (match_op_dup 3 [(match_dup 2) (match_dup 0)]))
19915169699Skan              (clobber (reg:CC FLAGS_REG))])]
1991690286Sobrien  "")
1991790286Sobrien
1991890286Sobrien; Don't do logical operations with memory outputs
1991990286Sobrien;
1992090286Sobrien; These two don't make sense for PPro/PII -- we're expanding a 4-uop
1992190286Sobrien; instruction into two 1-uop insns plus a 2-uop insn.  That last has
1992290286Sobrien; the same decoder scheduling characteristics as the original.
1992390286Sobrien
1992490286Sobrien(define_peephole2
1992590286Sobrien  [(match_scratch:SI 2 "r")
1992690286Sobrien   (parallel [(set (match_operand:SI 0 "memory_operand" "")
1992790286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1992890286Sobrien                     [(match_dup 0)
1992990286Sobrien                      (match_operand:SI 1 "nonmemory_operand" "")]))
19930169699Skan              (clobber (reg:CC FLAGS_REG))])]
1993190286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY_WRITE"
1993290286Sobrien  [(set (match_dup 2) (match_dup 0))
1993390286Sobrien   (parallel [(set (match_dup 2)
1993490286Sobrien                   (match_op_dup 3 [(match_dup 2) (match_dup 1)]))
19935169699Skan              (clobber (reg:CC FLAGS_REG))])
1993690286Sobrien   (set (match_dup 0) (match_dup 2))]
1993790286Sobrien  "")
1993890286Sobrien
1993990286Sobrien(define_peephole2
1994090286Sobrien  [(match_scratch:SI 2 "r")
1994190286Sobrien   (parallel [(set (match_operand:SI 0 "memory_operand" "")
1994290286Sobrien                   (match_operator:SI 3 "arith_or_logical_operator"
1994390286Sobrien                     [(match_operand:SI 1 "nonmemory_operand" "")
1994490286Sobrien                      (match_dup 0)]))
19945169699Skan              (clobber (reg:CC FLAGS_REG))])]
1994690286Sobrien  "! optimize_size && ! TARGET_READ_MODIFY_WRITE"
1994790286Sobrien  [(set (match_dup 2) (match_dup 0))
1994890286Sobrien   (parallel [(set (match_dup 2)
1994990286Sobrien                   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
19950169699Skan              (clobber (reg:CC FLAGS_REG))])
1995190286Sobrien   (set (match_dup 0) (match_dup 2))]
1995290286Sobrien  "")
1995390286Sobrien
1995490286Sobrien;; Attempt to always use XOR for zeroing registers.
1995590286Sobrien(define_peephole2
1995690286Sobrien  [(set (match_operand 0 "register_operand" "")
19957169699Skan	(match_operand 1 "const0_operand" ""))]
19958169699Skan  "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
1995990286Sobrien   && (! TARGET_USE_MOV0 || optimize_size)
19960169699Skan   && GENERAL_REG_P (operands[0])
1996190286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1996290286Sobrien  [(parallel [(set (match_dup 0) (const_int 0))
19963169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19964169699Skan{
19965169699Skan  operands[0] = gen_lowpart (word_mode, operands[0]);
19966169699Skan})
1996790286Sobrien
1996890286Sobrien(define_peephole2
1996990286Sobrien  [(set (strict_low_part (match_operand 0 "register_operand" ""))
1997090286Sobrien	(const_int 0))]
1997190286Sobrien  "(GET_MODE (operands[0]) == QImode
1997290286Sobrien    || GET_MODE (operands[0]) == HImode)
1997390286Sobrien   && (! TARGET_USE_MOV0 || optimize_size)
1997490286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1997590286Sobrien  [(parallel [(set (strict_low_part (match_dup 0)) (const_int 0))
19976169699Skan	      (clobber (reg:CC FLAGS_REG))])])
1997790286Sobrien
1997890286Sobrien;; For HI and SI modes, or $-1,reg is smaller than mov $-1,reg.
1997990286Sobrien(define_peephole2
1998090286Sobrien  [(set (match_operand 0 "register_operand" "")
1998190286Sobrien	(const_int -1))]
1998290286Sobrien  "(GET_MODE (operands[0]) == HImode
1998390286Sobrien    || GET_MODE (operands[0]) == SImode 
1998490286Sobrien    || (GET_MODE (operands[0]) == DImode && TARGET_64BIT))
1998590286Sobrien   && (optimize_size || TARGET_PENTIUM)
1998690286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
1998790286Sobrien  [(parallel [(set (match_dup 0) (const_int -1))
19988169699Skan	      (clobber (reg:CC FLAGS_REG))])]
19989132727Skan  "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode,
19990132727Skan			      operands[0]);")
1999190286Sobrien
1999290286Sobrien;; Attempt to convert simple leas to adds. These can be created by
1999390286Sobrien;; move expanders.
1999490286Sobrien(define_peephole2
1999590286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
1999690286Sobrien  	(plus:SI (match_dup 0)
1999790286Sobrien		 (match_operand:SI 1 "nonmemory_operand" "")))]
1999890286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG)"
1999990286Sobrien  [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
20000169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2000190286Sobrien  "")
2000290286Sobrien
2000390286Sobrien(define_peephole2
2000490286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2000590286Sobrien  	(subreg:SI (plus:DI (match_operand:DI 1 "register_operand" "")
2000690286Sobrien			    (match_operand:DI 2 "nonmemory_operand" "")) 0))]
2000790286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG) && REGNO (operands[0]) == REGNO (operands[1])"
2000890286Sobrien  [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
20009169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2001090286Sobrien  "operands[2] = gen_lowpart (SImode, operands[2]);")
2001190286Sobrien
2001290286Sobrien(define_peephole2
2001390286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
2001490286Sobrien  	(plus:DI (match_dup 0)
2001590286Sobrien		 (match_operand:DI 1 "x86_64_general_operand" "")))]
2001690286Sobrien  "peep2_regno_dead_p (0, FLAGS_REG)"
2001790286Sobrien  [(parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
20018169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2001990286Sobrien  "")
2002090286Sobrien
2002190286Sobrien(define_peephole2
2002290286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2002390286Sobrien  	(mult:SI (match_dup 0)
2002490286Sobrien		 (match_operand:SI 1 "const_int_operand" "")))]
2002590286Sobrien  "exact_log2 (INTVAL (operands[1])) >= 0
2002690286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2002790286Sobrien  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
20028169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2002990286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
2003090286Sobrien
2003190286Sobrien(define_peephole2
2003290286Sobrien  [(set (match_operand:DI 0 "register_operand" "")
2003390286Sobrien  	(mult:DI (match_dup 0)
2003490286Sobrien		 (match_operand:DI 1 "const_int_operand" "")))]
2003590286Sobrien  "exact_log2 (INTVAL (operands[1])) >= 0
2003690286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2003790286Sobrien  [(parallel [(set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))
20038169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2003990286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
2004090286Sobrien
2004190286Sobrien(define_peephole2
2004290286Sobrien  [(set (match_operand:SI 0 "register_operand" "")
2004390286Sobrien  	(subreg:SI (mult:DI (match_operand:DI 1 "register_operand" "")
2004490286Sobrien		   (match_operand:DI 2 "const_int_operand" "")) 0))]
20045117404Skan  "exact_log2 (INTVAL (operands[2])) >= 0
2004690286Sobrien   && REGNO (operands[0]) == REGNO (operands[1])
2004790286Sobrien   && peep2_regno_dead_p (0, FLAGS_REG)"
2004890286Sobrien  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
20049169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2005090286Sobrien  "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));")
2005190286Sobrien
2005290286Sobrien;; The ESP adjustments can be done by the push and pop instructions.  Resulting
2005390286Sobrien;; code is shorter, since push is only 1 byte, while add imm, %esp 3 bytes.  On
2005490286Sobrien;; many CPUs it is also faster, since special hardware to avoid esp
2005590286Sobrien;; dependencies is present.
2005690286Sobrien
2005790286Sobrien;; While some of these conversions may be done using splitters, we use peepholes
2005890286Sobrien;; in order to allow combine_stack_adjustments pass to see nonobfuscated RTL.
2005990286Sobrien
2006090286Sobrien;; Convert prologue esp subtractions to push.
2006190286Sobrien;; We need register to push.  In order to keep verify_flow_info happy we have
2006290286Sobrien;; two choices
2006390286Sobrien;; - use scratch and clobber it in order to avoid dependencies
2006490286Sobrien;; - use already live register
2006590286Sobrien;; We can't use the second way right now, since there is no reliable way how to
2006690286Sobrien;; verify that given register is live.  First choice will also most likely in
2006790286Sobrien;; fewer dependencies.  On the place of esp adjustments it is very likely that
2006890286Sobrien;; call clobbered registers are dead.  We may want to use base pointer as an
2006990286Sobrien;; alternative when no register is available later.
2007090286Sobrien
2007190286Sobrien(define_peephole2
2007290286Sobrien  [(match_scratch:SI 0 "r")
20073169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
20074169699Skan	      (clobber (reg:CC FLAGS_REG))
2007590286Sobrien	      (clobber (mem:BLK (scratch)))])]
2007690286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2007790286Sobrien  [(clobber (match_dup 0))
20078169699Skan   (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
2007990286Sobrien	      (clobber (mem:BLK (scratch)))])])
2008090286Sobrien
2008190286Sobrien(define_peephole2
2008290286Sobrien  [(match_scratch:SI 0 "r")
20083169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
20084169699Skan	      (clobber (reg:CC FLAGS_REG))
2008590286Sobrien	      (clobber (mem:BLK (scratch)))])]
2008690286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2008790286Sobrien  [(clobber (match_dup 0))
20088169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
20089169699Skan   (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
2009090286Sobrien	      (clobber (mem:BLK (scratch)))])])
2009190286Sobrien
2009290286Sobrien;; Convert esp subtractions to push.
2009390286Sobrien(define_peephole2
2009490286Sobrien  [(match_scratch:SI 0 "r")
20095169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
20096169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2009790286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2009890286Sobrien  [(clobber (match_dup 0))
20099169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
2010090286Sobrien
2010190286Sobrien(define_peephole2
2010290286Sobrien  [(match_scratch:SI 0 "r")
20103169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
20104169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2010590286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2010690286Sobrien  [(clobber (match_dup 0))
20107169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
20108169699Skan   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
2010990286Sobrien
2011090286Sobrien;; Convert epilogue deallocator to pop.
2011190286Sobrien(define_peephole2
2011290286Sobrien  [(match_scratch:SI 0 "r")
20113169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
20114169699Skan	      (clobber (reg:CC FLAGS_REG))
2011590286Sobrien	      (clobber (mem:BLK (scratch)))])]
2011690286Sobrien  "optimize_size || !TARGET_ADD_ESP_4"
20117169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20118169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2011990286Sobrien	      (clobber (mem:BLK (scratch)))])]
2012090286Sobrien  "")
2012190286Sobrien
2012290286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2012390286Sobrien;; We use two registers if available.
2012490286Sobrien(define_peephole2
2012590286Sobrien  [(match_scratch:SI 0 "r")
2012690286Sobrien   (match_scratch:SI 1 "r")
20127169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20128169699Skan	      (clobber (reg:CC FLAGS_REG))
2012990286Sobrien	      (clobber (mem:BLK (scratch)))])]
2013090286Sobrien  "optimize_size || !TARGET_ADD_ESP_8"
20131169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20132169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2013390286Sobrien	      (clobber (mem:BLK (scratch)))])
20134169699Skan   (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
20135169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2013690286Sobrien  "")
2013790286Sobrien
2013890286Sobrien(define_peephole2
2013990286Sobrien  [(match_scratch:SI 0 "r")
20140169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20141169699Skan	      (clobber (reg:CC FLAGS_REG))
2014290286Sobrien	      (clobber (mem:BLK (scratch)))])]
2014390286Sobrien  "optimize_size"
20144169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20145169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
2014690286Sobrien	      (clobber (mem:BLK (scratch)))])
20147169699Skan   (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20148169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2014990286Sobrien  "")
2015090286Sobrien
2015190286Sobrien;; Convert esp additions to pop.
2015290286Sobrien(define_peephole2
2015390286Sobrien  [(match_scratch:SI 0 "r")
20154169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
20155169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2015690286Sobrien  ""
20157169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20158169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2015990286Sobrien  "")
2016090286Sobrien
2016190286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2016290286Sobrien;; We use two registers if available.
2016390286Sobrien(define_peephole2
2016490286Sobrien  [(match_scratch:SI 0 "r")
2016590286Sobrien   (match_scratch:SI 1 "r")
20166169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20167169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2016890286Sobrien  ""
20169169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20170169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
20171169699Skan   (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
20172169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2017390286Sobrien  "")
2017490286Sobrien
2017590286Sobrien(define_peephole2
2017690286Sobrien  [(match_scratch:SI 0 "r")
20177169699Skan   (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
20178169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2017990286Sobrien  "optimize_size"
20180169699Skan  [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20181169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
20182169699Skan   (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
20183169699Skan	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
2018490286Sobrien  "")
2018590286Sobrien
2018690286Sobrien;; Convert compares with 1 to shorter inc/dec operations when CF is not
20187146906Skan;; required and register dies.  Similarly for 128 to plus -128.
2018890286Sobrien(define_peephole2
20189146906Skan  [(set (match_operand 0 "flags_reg_operand" "")
20190146906Skan	(match_operator 1 "compare_operator"
20191146906Skan	  [(match_operand 2 "register_operand" "")
20192146906Skan	   (match_operand 3 "const_int_operand" "")]))]
20193146906Skan  "(INTVAL (operands[3]) == -1
20194146906Skan    || INTVAL (operands[3]) == 1
20195146906Skan    || INTVAL (operands[3]) == 128)
20196146906Skan   && ix86_match_ccmode (insn, CCGCmode)
20197146906Skan   && peep2_reg_dead_p (1, operands[2])"
20198146906Skan  [(parallel [(set (match_dup 0)
20199146906Skan		   (match_op_dup 1 [(match_dup 2) (match_dup 3)]))
20200146906Skan	      (clobber (match_dup 2))])]
2020190286Sobrien  "")
2020290286Sobrien
2020390286Sobrien(define_peephole2
2020490286Sobrien  [(match_scratch:DI 0 "r")
20205169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
20206169699Skan	      (clobber (reg:CC FLAGS_REG))
2020790286Sobrien	      (clobber (mem:BLK (scratch)))])]
2020890286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2020990286Sobrien  [(clobber (match_dup 0))
20210169699Skan   (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
2021190286Sobrien	      (clobber (mem:BLK (scratch)))])])
2021290286Sobrien
2021390286Sobrien(define_peephole2
2021490286Sobrien  [(match_scratch:DI 0 "r")
20215169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
20216169699Skan	      (clobber (reg:CC FLAGS_REG))
2021790286Sobrien	      (clobber (mem:BLK (scratch)))])]
2021890286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2021990286Sobrien  [(clobber (match_dup 0))
20220169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
20221169699Skan   (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
2022290286Sobrien	      (clobber (mem:BLK (scratch)))])])
2022390286Sobrien
2022490286Sobrien;; Convert esp subtractions to push.
2022590286Sobrien(define_peephole2
2022690286Sobrien  [(match_scratch:DI 0 "r")
20227169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
20228169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2022990286Sobrien  "optimize_size || !TARGET_SUB_ESP_4"
2023090286Sobrien  [(clobber (match_dup 0))
20231169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
2023290286Sobrien
2023390286Sobrien(define_peephole2
2023490286Sobrien  [(match_scratch:DI 0 "r")
20235169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
20236169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2023790286Sobrien  "optimize_size || !TARGET_SUB_ESP_8"
2023890286Sobrien  [(clobber (match_dup 0))
20239169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
20240169699Skan   (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
2024190286Sobrien
2024290286Sobrien;; Convert epilogue deallocator to pop.
2024390286Sobrien(define_peephole2
2024490286Sobrien  [(match_scratch:DI 0 "r")
20245169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
20246169699Skan	      (clobber (reg:CC FLAGS_REG))
2024790286Sobrien	      (clobber (mem:BLK (scratch)))])]
2024890286Sobrien  "optimize_size || !TARGET_ADD_ESP_4"
20249169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20250169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2025190286Sobrien	      (clobber (mem:BLK (scratch)))])]
2025290286Sobrien  "")
2025390286Sobrien
2025490286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2025590286Sobrien;; We use two registers if available.
2025690286Sobrien(define_peephole2
2025790286Sobrien  [(match_scratch:DI 0 "r")
2025890286Sobrien   (match_scratch:DI 1 "r")
20259169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20260169699Skan	      (clobber (reg:CC FLAGS_REG))
2026190286Sobrien	      (clobber (mem:BLK (scratch)))])]
2026290286Sobrien  "optimize_size || !TARGET_ADD_ESP_8"
20263169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20264169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2026590286Sobrien	      (clobber (mem:BLK (scratch)))])
20266169699Skan   (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
20267169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2026890286Sobrien  "")
2026990286Sobrien
2027090286Sobrien(define_peephole2
2027190286Sobrien  [(match_scratch:DI 0 "r")
20272169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20273169699Skan	      (clobber (reg:CC FLAGS_REG))
2027490286Sobrien	      (clobber (mem:BLK (scratch)))])]
2027590286Sobrien  "optimize_size"
20276169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20277169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
2027890286Sobrien	      (clobber (mem:BLK (scratch)))])
20279169699Skan   (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20280169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2028190286Sobrien  "")
2028290286Sobrien
2028390286Sobrien;; Convert esp additions to pop.
2028490286Sobrien(define_peephole2
2028590286Sobrien  [(match_scratch:DI 0 "r")
20286169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
20287169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2028890286Sobrien  ""
20289169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20290169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2029190286Sobrien  "")
2029290286Sobrien
2029390286Sobrien;; Two pops case is tricky, since pop causes dependency on destination register.
2029490286Sobrien;; We use two registers if available.
2029590286Sobrien(define_peephole2
2029690286Sobrien  [(match_scratch:DI 0 "r")
2029790286Sobrien   (match_scratch:DI 1 "r")
20298169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20299169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2030090286Sobrien  ""
20301169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20302169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
20303169699Skan   (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
20304169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2030590286Sobrien  "")
2030690286Sobrien
2030790286Sobrien(define_peephole2
2030890286Sobrien  [(match_scratch:DI 0 "r")
20309169699Skan   (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
20310169699Skan	      (clobber (reg:CC FLAGS_REG))])]
2031190286Sobrien  "optimize_size"
20312169699Skan  [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20313169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
20314169699Skan   (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
20315169699Skan	      (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
2031690286Sobrien  "")
2031790286Sobrien
20318169699Skan;; Convert imul by three, five and nine into lea
20319169699Skan(define_peephole2
20320169699Skan  [(parallel
20321169699Skan    [(set (match_operand:SI 0 "register_operand" "")
20322169699Skan	  (mult:SI (match_operand:SI 1 "register_operand" "")
20323169699Skan		   (match_operand:SI 2 "const_int_operand" "")))
20324169699Skan     (clobber (reg:CC FLAGS_REG))])]
20325169699Skan  "INTVAL (operands[2]) == 3
20326169699Skan   || INTVAL (operands[2]) == 5
20327169699Skan   || INTVAL (operands[2]) == 9"
20328169699Skan  [(set (match_dup 0)
20329169699Skan        (plus:SI (mult:SI (match_dup 1) (match_dup 2))
20330169699Skan                 (match_dup 1)))]
20331169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20332169699Skan
20333169699Skan(define_peephole2
20334169699Skan  [(parallel
20335169699Skan    [(set (match_operand:SI 0 "register_operand" "")
20336169699Skan          (mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
20337169699Skan                   (match_operand:SI 2 "const_int_operand" "")))
20338169699Skan     (clobber (reg:CC FLAGS_REG))])]
20339169699Skan  "!optimize_size 
20340169699Skan   && (INTVAL (operands[2]) == 3
20341169699Skan       || INTVAL (operands[2]) == 5
20342169699Skan       || INTVAL (operands[2]) == 9)"
20343169699Skan  [(set (match_dup 0) (match_dup 1))
20344169699Skan   (set (match_dup 0)
20345169699Skan        (plus:SI (mult:SI (match_dup 0) (match_dup 2))
20346169699Skan                 (match_dup 0)))]
20347169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20348169699Skan
20349169699Skan(define_peephole2
20350169699Skan  [(parallel
20351169699Skan    [(set (match_operand:DI 0 "register_operand" "")
20352169699Skan	  (mult:DI (match_operand:DI 1 "register_operand" "")
20353169699Skan		   (match_operand:DI 2 "const_int_operand" "")))
20354169699Skan     (clobber (reg:CC FLAGS_REG))])]
20355169699Skan  "TARGET_64BIT
20356169699Skan   && (INTVAL (operands[2]) == 3
20357169699Skan       || INTVAL (operands[2]) == 5
20358169699Skan       || INTVAL (operands[2]) == 9)"
20359169699Skan  [(set (match_dup 0)
20360169699Skan        (plus:DI (mult:DI (match_dup 1) (match_dup 2))
20361169699Skan                 (match_dup 1)))]
20362169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20363169699Skan
20364169699Skan(define_peephole2
20365169699Skan  [(parallel
20366169699Skan    [(set (match_operand:DI 0 "register_operand" "")
20367169699Skan          (mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
20368169699Skan                   (match_operand:DI 2 "const_int_operand" "")))
20369169699Skan     (clobber (reg:CC FLAGS_REG))])]
20370169699Skan  "TARGET_64BIT
20371169699Skan   && !optimize_size 
20372169699Skan   && (INTVAL (operands[2]) == 3
20373169699Skan       || INTVAL (operands[2]) == 5
20374169699Skan       || INTVAL (operands[2]) == 9)"
20375169699Skan  [(set (match_dup 0) (match_dup 1))
20376169699Skan   (set (match_dup 0)
20377169699Skan        (plus:DI (mult:DI (match_dup 0) (match_dup 2))
20378169699Skan                 (match_dup 0)))]
20379169699Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
20380169699Skan
20381132727Skan;; Imul $32bit_imm, mem, reg is vector decoded, while
20382132727Skan;; imul $32bit_imm, reg, reg is direct decoded.
20383132727Skan(define_peephole2
20384132727Skan  [(match_scratch:DI 3 "r")
20385132727Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
20386132727Skan		   (mult:DI (match_operand:DI 1 "memory_operand" "")
20387132727Skan			    (match_operand:DI 2 "immediate_operand" "")))
20388169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20389169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20390169699Skan   && !satisfies_constraint_K (operands[2])"
20391132727Skan  [(set (match_dup 3) (match_dup 1))
20392132727Skan   (parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2)))
20393169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20394132727Skan"")
20395132727Skan
20396132727Skan(define_peephole2
20397132727Skan  [(match_scratch:SI 3 "r")
20398132727Skan   (parallel [(set (match_operand:SI 0 "register_operand" "")
20399132727Skan		   (mult:SI (match_operand:SI 1 "memory_operand" "")
20400132727Skan			    (match_operand:SI 2 "immediate_operand" "")))
20401169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20402169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20403169699Skan   && !satisfies_constraint_K (operands[2])"
20404132727Skan  [(set (match_dup 3) (match_dup 1))
20405132727Skan   (parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2)))
20406169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20407132727Skan"")
20408132727Skan
20409132727Skan(define_peephole2
20410132727Skan  [(match_scratch:SI 3 "r")
20411132727Skan   (parallel [(set (match_operand:DI 0 "register_operand" "")
20412132727Skan		   (zero_extend:DI
20413132727Skan		     (mult:SI (match_operand:SI 1 "memory_operand" "")
20414132727Skan			      (match_operand:SI 2 "immediate_operand" ""))))
20415169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20416169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20417169699Skan   && !satisfies_constraint_K (operands[2])"
20418132727Skan  [(set (match_dup 3) (match_dup 1))
20419132727Skan   (parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2))))
20420169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20421132727Skan"")
20422132727Skan
20423132727Skan;; imul $8/16bit_imm, regmem, reg is vector decoded.
20424132727Skan;; Convert it into imul reg, reg
20425132727Skan;; It would be better to force assembler to encode instruction using long
20426132727Skan;; immediate, but there is apparently no way to do so.
20427132727Skan(define_peephole2
20428132727Skan  [(parallel [(set (match_operand:DI 0 "register_operand" "")
20429132727Skan		   (mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
20430132727Skan			    (match_operand:DI 2 "const_int_operand" "")))
20431169699Skan	      (clobber (reg:CC FLAGS_REG))])
20432132727Skan   (match_scratch:DI 3 "r")]
20433169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20434169699Skan   && satisfies_constraint_K (operands[2])"
20435132727Skan  [(set (match_dup 3) (match_dup 2))
20436132727Skan   (parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3)))
20437169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20438132727Skan{
20439132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20440132727Skan    emit_move_insn (operands[0], operands[1]);
20441132727Skan})
20442132727Skan
20443132727Skan(define_peephole2
20444132727Skan  [(parallel [(set (match_operand:SI 0 "register_operand" "")
20445132727Skan		   (mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
20446132727Skan			    (match_operand:SI 2 "const_int_operand" "")))
20447169699Skan	      (clobber (reg:CC FLAGS_REG))])
20448132727Skan   (match_scratch:SI 3 "r")]
20449169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
20450169699Skan   && satisfies_constraint_K (operands[2])"
20451132727Skan  [(set (match_dup 3) (match_dup 2))
20452132727Skan   (parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3)))
20453169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20454132727Skan{
20455132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20456132727Skan    emit_move_insn (operands[0], operands[1]);
20457132727Skan})
20458132727Skan
20459132727Skan(define_peephole2
20460132727Skan  [(parallel [(set (match_operand:HI 0 "register_operand" "")
20461132727Skan		   (mult:HI (match_operand:HI 1 "nonimmediate_operand" "")
20462132727Skan			    (match_operand:HI 2 "immediate_operand" "")))
20463169699Skan	      (clobber (reg:CC FLAGS_REG))])
20464132727Skan   (match_scratch:HI 3 "r")]
20465169699Skan  "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
20466132727Skan  [(set (match_dup 3) (match_dup 2))
20467132727Skan   (parallel [(set (match_dup 0) (mult:HI (match_dup 0) (match_dup 3)))
20468169699Skan	      (clobber (reg:CC FLAGS_REG))])]
20469132727Skan{
20470132727Skan  if (!rtx_equal_p (operands[0], operands[1]))
20471132727Skan    emit_move_insn (operands[0], operands[1]);
20472132727Skan})
20473169699Skan
20474169699Skan;; After splitting up read-modify operations, array accesses with memory
20475169699Skan;; operands might end up in form:
20476169699Skan;;  sall    $2, %eax
20477169699Skan;;  movl    4(%esp), %edx
20478169699Skan;;  addl    %edx, %eax
20479169699Skan;; instead of pre-splitting:
20480169699Skan;;  sall    $2, %eax
20481169699Skan;;  addl    4(%esp), %eax
20482169699Skan;; Turn it into:
20483169699Skan;;  movl    4(%esp), %edx
20484169699Skan;;  leal    (%edx,%eax,4), %eax
20485169699Skan
20486169699Skan(define_peephole2
20487169699Skan  [(parallel [(set (match_operand 0 "register_operand" "")
20488169699Skan		   (ashift (match_operand 1 "register_operand" "")
20489169699Skan			   (match_operand 2 "const_int_operand" "")))
20490169699Skan	       (clobber (reg:CC FLAGS_REG))])
20491169699Skan   (set (match_operand 3 "register_operand")
20492169699Skan        (match_operand 4 "x86_64_general_operand" ""))
20493169699Skan   (parallel [(set (match_operand 5 "register_operand" "")
20494169699Skan		   (plus (match_operand 6 "register_operand" "")
20495169699Skan			 (match_operand 7 "register_operand" "")))
20496169699Skan		   (clobber (reg:CC FLAGS_REG))])]
20497169699Skan  "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
20498169699Skan   /* Validate MODE for lea.  */
20499169699Skan   && ((!TARGET_PARTIAL_REG_STALL
20500169699Skan	&& (GET_MODE (operands[0]) == QImode
20501169699Skan	    || GET_MODE (operands[0]) == HImode))
20502169699Skan       || GET_MODE (operands[0]) == SImode 
20503169699Skan       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
20504169699Skan   /* We reorder load and the shift.  */
20505169699Skan   && !rtx_equal_p (operands[1], operands[3])
20506169699Skan   && !reg_overlap_mentioned_p (operands[0], operands[4])
20507169699Skan   /* Last PLUS must consist of operand 0 and 3.  */
20508169699Skan   && !rtx_equal_p (operands[0], operands[3])
20509169699Skan   && (rtx_equal_p (operands[3], operands[6])
20510169699Skan       || rtx_equal_p (operands[3], operands[7]))
20511169699Skan   && (rtx_equal_p (operands[0], operands[6])
20512169699Skan       || rtx_equal_p (operands[0], operands[7]))
20513169699Skan   /* The intermediate operand 0 must die or be same as output.  */
20514169699Skan   && (rtx_equal_p (operands[0], operands[5])
20515169699Skan       || peep2_reg_dead_p (3, operands[0]))"
20516169699Skan  [(set (match_dup 3) (match_dup 4))
20517169699Skan   (set (match_dup 0) (match_dup 1))]
20518169699Skan{
20519169699Skan  enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
20520169699Skan  int scale = 1 << INTVAL (operands[2]);
20521169699Skan  rtx index = gen_lowpart (Pmode, operands[1]);
20522169699Skan  rtx base = gen_lowpart (Pmode, operands[3]);
20523169699Skan  rtx dest = gen_lowpart (mode, operands[5]);
20524169699Skan
20525169699Skan  operands[1] = gen_rtx_PLUS (Pmode, base,
20526169699Skan  			      gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
20527169699Skan  if (mode != Pmode)
20528169699Skan    operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
20529169699Skan  operands[0] = dest;
20530169699Skan})
20531132727Skan
2053290286Sobrien;; Call-value patterns last so that the wildcard operand does not
2053390286Sobrien;; disrupt insn-recog's switch tables.
2053490286Sobrien
2053590286Sobrien(define_insn "*call_value_pop_0"
2053690286Sobrien  [(set (match_operand 0 "" "")
2053790286Sobrien	(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
2053890286Sobrien	      (match_operand:SI 2 "" "")))
20539169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
2054090286Sobrien			    (match_operand:SI 3 "immediate_operand" "")))]
2054190286Sobrien  "!TARGET_64BIT"
2054290286Sobrien{
2054390286Sobrien  if (SIBLING_CALL_P (insn))
2054490286Sobrien    return "jmp\t%P1";
2054590286Sobrien  else
2054690286Sobrien    return "call\t%P1";
2054790286Sobrien}
2054890286Sobrien  [(set_attr "type" "callv")])
2054990286Sobrien
2055090286Sobrien(define_insn "*call_value_pop_1"
2055190286Sobrien  [(set (match_operand 0 "" "")
2055290286Sobrien	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
2055390286Sobrien	      (match_operand:SI 2 "" "")))
20554169699Skan   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
2055590286Sobrien			    (match_operand:SI 3 "immediate_operand" "i")))]
2055690286Sobrien  "!TARGET_64BIT"
2055790286Sobrien{
20558169699Skan  if (constant_call_address_operand (operands[1], Pmode))
2055990286Sobrien    {
2056090286Sobrien      if (SIBLING_CALL_P (insn))
2056190286Sobrien	return "jmp\t%P1";
2056290286Sobrien      else
2056390286Sobrien	return "call\t%P1";
2056490286Sobrien    }
2056590286Sobrien  if (SIBLING_CALL_P (insn))
2056690286Sobrien    return "jmp\t%A1";
2056790286Sobrien  else
2056890286Sobrien    return "call\t%A1";
2056990286Sobrien}
2057090286Sobrien  [(set_attr "type" "callv")])
2057190286Sobrien
2057290286Sobrien(define_insn "*call_value_0"
2057390286Sobrien  [(set (match_operand 0 "" "")
2057490286Sobrien	(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
2057590286Sobrien	      (match_operand:SI 2 "" "")))]
2057690286Sobrien  "!TARGET_64BIT"
2057790286Sobrien{
2057890286Sobrien  if (SIBLING_CALL_P (insn))
2057990286Sobrien    return "jmp\t%P1";
2058090286Sobrien  else
2058190286Sobrien    return "call\t%P1";
2058290286Sobrien}
2058390286Sobrien  [(set_attr "type" "callv")])
2058490286Sobrien
2058590286Sobrien(define_insn "*call_value_0_rex64"
2058690286Sobrien  [(set (match_operand 0 "" "")
2058790286Sobrien	(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
2058890286Sobrien	      (match_operand:DI 2 "const_int_operand" "")))]
2058990286Sobrien  "TARGET_64BIT"
2059090286Sobrien{
2059190286Sobrien  if (SIBLING_CALL_P (insn))
2059290286Sobrien    return "jmp\t%P1";
2059390286Sobrien  else
2059490286Sobrien    return "call\t%P1";
2059590286Sobrien}
2059690286Sobrien  [(set_attr "type" "callv")])
2059790286Sobrien
2059890286Sobrien(define_insn "*call_value_1"
2059990286Sobrien  [(set (match_operand 0 "" "")
2060090286Sobrien	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
2060190286Sobrien	      (match_operand:SI 2 "" "")))]
20602132727Skan  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
2060390286Sobrien{
20604169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20605132727Skan    return "call\t%P1";
20606146906Skan  return "call\t%A1";
2060790286Sobrien}
2060890286Sobrien  [(set_attr "type" "callv")])
2060990286Sobrien
20610132727Skan(define_insn "*sibcall_value_1"
20611132727Skan  [(set (match_operand 0 "" "")
20612132727Skan	(call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,c,d,a"))
20613132727Skan	      (match_operand:SI 2 "" "")))]
20614132727Skan  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
20615132727Skan{
20616169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20617132727Skan    return "jmp\t%P1";
20618146906Skan  return "jmp\t%A1";
20619132727Skan}
20620132727Skan  [(set_attr "type" "callv")])
20621132727Skan
2062290286Sobrien(define_insn "*call_value_1_rex64"
2062390286Sobrien  [(set (match_operand 0 "" "")
2062490286Sobrien	(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
2062590286Sobrien	      (match_operand:DI 2 "" "")))]
20626132727Skan  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
2062790286Sobrien{
20628169699Skan  if (constant_call_address_operand (operands[1], Pmode))
20629132727Skan    return "call\t%P1";
20630132727Skan  return "call\t%A1";
2063190286Sobrien}
2063290286Sobrien  [(set_attr "type" "callv")])
20633132727Skan
20634132727Skan(define_insn "*sibcall_value_1_rex64"
20635132727Skan  [(set (match_operand 0 "" "")
20636132727Skan	(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
20637132727Skan	      (match_operand:DI 2 "" "")))]
20638132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
20639132727Skan  "jmp\t%P1"
20640132727Skan  [(set_attr "type" "callv")])
20641132727Skan
20642132727Skan(define_insn "*sibcall_value_1_rex64_v"
20643132727Skan  [(set (match_operand 0 "" "")
20644132727Skan	(call (mem:QI (reg:DI 40))
20645132727Skan	      (match_operand:DI 1 "" "")))]
20646132727Skan  "SIBLING_CALL_P (insn) && TARGET_64BIT"
20647132727Skan  "jmp\t*%%r11"
20648132727Skan  [(set_attr "type" "callv")])
2064990286Sobrien
20650169699Skan;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5.
20651169699Skan;; That, however, is usually mapped by the OS to SIGSEGV, which is often 
20652169699Skan;; caught for use by garbage collectors and the like.  Using an insn that
20653169699Skan;; maps to SIGILL makes it more likely the program will rightfully die.
20654169699Skan;; Keeping with tradition, "6" is in honor of #UD.
2065590286Sobrien(define_insn "trap"
20656169699Skan  [(trap_if (const_int 1) (const_int 6))]
2065790286Sobrien  ""
20658169699Skan  { return ASM_SHORT "0x0b0f"; }
20659169699Skan  [(set_attr "length" "2")])
2066090286Sobrien
2066190286Sobrien(define_expand "sse_prologue_save"
2066290286Sobrien  [(parallel [(set (match_operand:BLK 0 "" "")
2066390286Sobrien		   (unspec:BLK [(reg:DI 21)
2066490286Sobrien				(reg:DI 22)
2066590286Sobrien				(reg:DI 23)
2066690286Sobrien				(reg:DI 24)
2066790286Sobrien				(reg:DI 25)
2066890286Sobrien				(reg:DI 26)
2066990286Sobrien				(reg:DI 27)
20670117404Skan				(reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
2067190286Sobrien	      (use (match_operand:DI 1 "register_operand" ""))
2067290286Sobrien	      (use (match_operand:DI 2 "immediate_operand" ""))
2067390286Sobrien	      (use (label_ref:DI (match_operand 3 "" "")))])]
2067490286Sobrien  "TARGET_64BIT"
2067590286Sobrien  "")
2067690286Sobrien
2067790286Sobrien(define_insn "*sse_prologue_save_insn"
2067890286Sobrien  [(set (mem:BLK (plus:DI (match_operand:DI 0 "register_operand" "R")
2067990286Sobrien			  (match_operand:DI 4 "const_int_operand" "n")))
2068090286Sobrien	(unspec:BLK [(reg:DI 21)
2068190286Sobrien		     (reg:DI 22)
2068290286Sobrien		     (reg:DI 23)
2068390286Sobrien		     (reg:DI 24)
2068490286Sobrien		     (reg:DI 25)
2068590286Sobrien		     (reg:DI 26)
2068690286Sobrien		     (reg:DI 27)
20687117404Skan		     (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
2068890286Sobrien   (use (match_operand:DI 1 "register_operand" "r"))
2068990286Sobrien   (use (match_operand:DI 2 "const_int_operand" "i"))
2069090286Sobrien   (use (label_ref:DI (match_operand 3 "" "X")))]
2069190286Sobrien  "TARGET_64BIT
2069290286Sobrien   && INTVAL (operands[4]) + SSE_REGPARM_MAX * 16 - 16 < 128
2069390286Sobrien   && INTVAL (operands[4]) + INTVAL (operands[2]) * 16 >= -128"
2069490286Sobrien  "*
2069590286Sobrien{
2069690286Sobrien  int i;
2069790286Sobrien  operands[0] = gen_rtx_MEM (Pmode,
2069890286Sobrien			     gen_rtx_PLUS (Pmode, operands[0], operands[4]));
2069990286Sobrien  output_asm_insn (\"jmp\\t%A1\", operands);
2070090286Sobrien  for (i = SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--)
2070190286Sobrien    {
2070290286Sobrien      operands[4] = adjust_address (operands[0], DImode, i*16);
2070390286Sobrien      operands[5] = gen_rtx_REG (TImode, SSE_REGNO (i));
2070490286Sobrien      PUT_MODE (operands[4], TImode);
2070590286Sobrien      if (GET_CODE (XEXP (operands[0], 0)) != PLUS)
2070690286Sobrien        output_asm_insn (\"rex\", operands);
2070790286Sobrien      output_asm_insn (\"movaps\\t{%5, %4|%4, %5}\", operands);
2070890286Sobrien    }
20709132727Skan  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
2071090286Sobrien			     CODE_LABEL_NUMBER (operands[3]));
2071190286Sobrien  RET;
2071290286Sobrien}
2071356391Sobrien  "
2071490286Sobrien  [(set_attr "type" "other")
2071590286Sobrien   (set_attr "length_immediate" "0")
2071690286Sobrien   (set_attr "length_address" "0")
2071790286Sobrien   (set_attr "length" "135")
2071890286Sobrien   (set_attr "memory" "store")
2071990286Sobrien   (set_attr "modrm" "0")
2072090286Sobrien   (set_attr "mode" "DI")])
2072190286Sobrien
2072290286Sobrien(define_expand "prefetch"
20723102802Skan  [(prefetch (match_operand 0 "address_operand" "")
2072490286Sobrien	     (match_operand:SI 1 "const_int_operand" "")
2072590286Sobrien	     (match_operand:SI 2 "const_int_operand" ""))]
2072690286Sobrien  "TARGET_PREFETCH_SSE || TARGET_3DNOW"
2072756391Sobrien{
2072890286Sobrien  int rw = INTVAL (operands[1]);
2072990286Sobrien  int locality = INTVAL (operands[2]);
2073090286Sobrien
20731169699Skan  gcc_assert (rw == 0 || rw == 1);
20732169699Skan  gcc_assert (locality >= 0 && locality <= 3);
20733169699Skan  gcc_assert (GET_MODE (operands[0]) == Pmode
20734169699Skan	      || GET_MODE (operands[0]) == VOIDmode);
2073590286Sobrien
2073690286Sobrien  /* Use 3dNOW prefetch in case we are asking for write prefetch not
20737169699Skan     supported by SSE counterpart or the SSE prefetch is not available
2073890286Sobrien     (K6 machines).  Otherwise use SSE prefetch as it allows specifying
2073990286Sobrien     of locality.  */
2074090286Sobrien  if (TARGET_3DNOW && (!TARGET_PREFETCH_SSE || rw))
2074190286Sobrien    operands[2] = GEN_INT (3);
2074290286Sobrien  else
2074390286Sobrien    operands[1] = const0_rtx;
2074490286Sobrien})
2074590286Sobrien
2074690286Sobrien(define_insn "*prefetch_sse"
2074790286Sobrien  [(prefetch (match_operand:SI 0 "address_operand" "p")
2074890286Sobrien	     (const_int 0)
2074990286Sobrien	     (match_operand:SI 1 "const_int_operand" ""))]
20750102802Skan  "TARGET_PREFETCH_SSE && !TARGET_64BIT"
2075190286Sobrien{
2075290286Sobrien  static const char * const patterns[4] = {
2075390286Sobrien   "prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
2075490286Sobrien  };
2075590286Sobrien
2075690286Sobrien  int locality = INTVAL (operands[1]);
20757169699Skan  gcc_assert (locality >= 0 && locality <= 3);
2075890286Sobrien
2075990286Sobrien  return patterns[locality];  
2076090286Sobrien}
20761102802Skan  [(set_attr "type" "sse")
20762102802Skan   (set_attr "memory" "none")])
20763102802Skan
20764102802Skan(define_insn "*prefetch_sse_rex"
20765102802Skan  [(prefetch (match_operand:DI 0 "address_operand" "p")
20766102802Skan	     (const_int 0)
20767102802Skan	     (match_operand:SI 1 "const_int_operand" ""))]
20768102802Skan  "TARGET_PREFETCH_SSE && TARGET_64BIT"
20769102802Skan{
20770102802Skan  static const char * const patterns[4] = {
20771102802Skan   "prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
20772102802Skan  };
20773102802Skan
20774102802Skan  int locality = INTVAL (operands[1]);
20775169699Skan  gcc_assert (locality >= 0 && locality <= 3);
20776102802Skan
20777102802Skan  return patterns[locality];  
20778102802Skan}
20779117404Skan  [(set_attr "type" "sse")
20780117404Skan   (set_attr "memory" "none")])
2078190286Sobrien
2078290286Sobrien(define_insn "*prefetch_3dnow"
2078390286Sobrien  [(prefetch (match_operand:SI 0 "address_operand" "p")
2078490286Sobrien	     (match_operand:SI 1 "const_int_operand" "n")
2078590286Sobrien	     (const_int 3))]
20786102802Skan  "TARGET_3DNOW && !TARGET_64BIT"
2078790286Sobrien{
2078890286Sobrien  if (INTVAL (operands[1]) == 0)
2078990286Sobrien    return "prefetch\t%a0";
2079090286Sobrien  else
2079190286Sobrien    return "prefetchw\t%a0";
2079290286Sobrien}
20793102802Skan  [(set_attr "type" "mmx")
20794102802Skan   (set_attr "memory" "none")])
20795102802Skan
20796102802Skan(define_insn "*prefetch_3dnow_rex"
20797102802Skan  [(prefetch (match_operand:DI 0 "address_operand" "p")
20798102802Skan	     (match_operand:SI 1 "const_int_operand" "n")
20799102802Skan	     (const_int 3))]
20800102802Skan  "TARGET_3DNOW && TARGET_64BIT"
20801102802Skan{
20802102802Skan  if (INTVAL (operands[1]) == 0)
20803102802Skan    return "prefetch\t%a0";
20804102802Skan  else
20805102802Skan    return "prefetchw\t%a0";
20806102802Skan}
20807117404Skan  [(set_attr "type" "mmx")
20808117404Skan   (set_attr "memory" "none")])
20809117404Skan
20810169699Skan(define_expand "stack_protect_set"
20811169699Skan  [(match_operand 0 "memory_operand" "")
20812169699Skan   (match_operand 1 "memory_operand" "")]
20813169699Skan  ""
20814117404Skan{
20815169699Skan#ifdef TARGET_THREAD_SSP_OFFSET
20816169699Skan  if (TARGET_64BIT)
20817169699Skan    emit_insn (gen_stack_tls_protect_set_di (operands[0],
20818169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20819117404Skan  else
20820169699Skan    emit_insn (gen_stack_tls_protect_set_si (operands[0],
20821169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20822169699Skan#else
20823169699Skan  if (TARGET_64BIT)
20824169699Skan    emit_insn (gen_stack_protect_set_di (operands[0], operands[1]));
20825117404Skan  else
20826169699Skan    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
20827169699Skan#endif
20828169699Skan  DONE;
20829169699Skan})
20830117404Skan
20831169699Skan(define_insn "stack_protect_set_si"
20832169699Skan  [(set (match_operand:SI 0 "memory_operand" "=m")
20833169699Skan	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
20834169699Skan   (set (match_scratch:SI 2 "=&r") (const_int 0))
20835169699Skan   (clobber (reg:CC FLAGS_REG))]
20836169699Skan  ""
20837169699Skan  "mov{l}\t{%1, %2|%2, %1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
20838169699Skan  [(set_attr "type" "multi")])
20839117404Skan
20840169699Skan(define_insn "stack_protect_set_di"
20841169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
20842169699Skan	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
20843169699Skan   (set (match_scratch:DI 2 "=&r") (const_int 0))
20844169699Skan   (clobber (reg:CC FLAGS_REG))]
20845169699Skan  "TARGET_64BIT"
20846169699Skan  "mov{q}\t{%1, %2|%2, %1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
20847169699Skan  [(set_attr "type" "multi")])
20848117404Skan
20849169699Skan(define_insn "stack_tls_protect_set_si"
20850117404Skan  [(set (match_operand:SI 0 "memory_operand" "=m")
20851169699Skan	(unspec:SI [(match_operand:SI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
20852169699Skan   (set (match_scratch:SI 2 "=&r") (const_int 0))
20853169699Skan   (clobber (reg:CC FLAGS_REG))]
20854169699Skan  ""
20855169699Skan  "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR %%gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
20856169699Skan  [(set_attr "type" "multi")])
20857117404Skan
20858169699Skan(define_insn "stack_tls_protect_set_di"
20859169699Skan  [(set (match_operand:DI 0 "memory_operand" "=m")
20860169699Skan	(unspec:DI [(match_operand:DI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
20861169699Skan   (set (match_scratch:DI 2 "=&r") (const_int 0))
20862169699Skan   (clobber (reg:CC FLAGS_REG))]
20863169699Skan  "TARGET_64BIT"
20864169699Skan  {
20865169699Skan     /* The kernel uses a different segment register for performance reasons; a
20866169699Skan        system call would not have to trash the userspace segment register,
20867169699Skan        which would be expensive */
20868169699Skan     if (ix86_cmodel != CM_KERNEL)
20869169699Skan        return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
20870169699Skan     else
20871169699Skan        return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR %%gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
20872169699Skan  }
20873169699Skan  [(set_attr "type" "multi")])
20874117404Skan
20875169699Skan(define_expand "stack_protect_test"
20876169699Skan  [(match_operand 0 "memory_operand" "")
20877169699Skan   (match_operand 1 "memory_operand" "")
20878169699Skan   (match_operand 2 "" "")]
20879169699Skan  ""
20880169699Skan{
20881169699Skan  rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG);
20882169699Skan  ix86_compare_op0 = operands[0];
20883169699Skan  ix86_compare_op1 = operands[1];
20884169699Skan  ix86_compare_emitted = flags;
20885117404Skan
20886169699Skan#ifdef TARGET_THREAD_SSP_OFFSET
20887169699Skan  if (TARGET_64BIT)
20888169699Skan    emit_insn (gen_stack_tls_protect_test_di (flags, operands[0],
20889169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20890132727Skan  else
20891169699Skan    emit_insn (gen_stack_tls_protect_test_si (flags, operands[0],
20892169699Skan					GEN_INT (TARGET_THREAD_SSP_OFFSET)));
20893169699Skan#else
20894169699Skan  if (TARGET_64BIT)
20895169699Skan    emit_insn (gen_stack_protect_test_di (flags, operands[0], operands[1]));
20896169699Skan  else
20897169699Skan    emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1]));
20898169699Skan#endif
20899169699Skan  emit_jump_insn (gen_beq (operands[2]));
20900117404Skan  DONE;
20901117404Skan})
20902117404Skan
20903169699Skan(define_insn "stack_protect_test_si"
20904169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20905169699Skan	(unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
20906169699Skan		     (match_operand:SI 2 "memory_operand" "m")]
20907169699Skan		    UNSPEC_SP_TEST))
20908169699Skan   (clobber (match_scratch:SI 3 "=&r"))]
20909169699Skan  ""
20910169699Skan  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%2, %3|%3, %2}"
20911169699Skan  [(set_attr "type" "multi")])
20912117404Skan
20913169699Skan(define_insn "stack_protect_test_di"
20914169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20915169699Skan	(unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
20916169699Skan		     (match_operand:DI 2 "memory_operand" "m")]
20917169699Skan		    UNSPEC_SP_TEST))
20918169699Skan   (clobber (match_scratch:DI 3 "=&r"))]
20919169699Skan  "TARGET_64BIT"
20920169699Skan  "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%2, %3|%3, %2}"
20921169699Skan  [(set_attr "type" "multi")])
20922117404Skan
20923169699Skan(define_insn "stack_tls_protect_test_si"
20924169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20925169699Skan	(unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
20926169699Skan		     (match_operand:SI 2 "const_int_operand" "i")]
20927169699Skan		    UNSPEC_SP_TLS_TEST))
20928169699Skan   (clobber (match_scratch:SI 3 "=r"))]
20929169699Skan  ""
20930169699Skan  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR %%gs:%P2}"
20931169699Skan  [(set_attr "type" "multi")])
20932117404Skan
20933169699Skan(define_insn "stack_tls_protect_test_di"
20934169699Skan  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
20935169699Skan	(unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
20936169699Skan		     (match_operand:DI 2 "const_int_operand" "i")]
20937169699Skan		    UNSPEC_SP_TLS_TEST))
20938169699Skan   (clobber (match_scratch:DI 3 "=r"))]
20939169699Skan  "TARGET_64BIT"
20940169699Skan  {
20941169699Skan     /* The kernel uses a different segment register for performance reasons; a
20942169699Skan        system call would not have to trash the userspace segment register,
20943169699Skan        which would be expensive */
20944169699Skan     if (ix86_cmodel != CM_KERNEL)
20945169699Skan        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}";
20946169699Skan     else
20947169699Skan        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR %%gs:%P2}";
20948169699Skan  }
20949169699Skan  [(set_attr "type" "multi")])
20950117404Skan
20951169699Skan(include "sse.md")
20952169699Skan(include "mmx.md")
20953169699Skan(include "sync.md")
20954