i386.md revision 19194
1185573Srwatson;; GCC machine description for Intel X86.
2155131Srwatson;; Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc.
3168777Srwatson;; Mostly by William Schelter.
4155131Srwatson
5155131Srwatson;; This file is part of GNU CC.
6155131Srwatson
7155131Srwatson;; GNU CC is free software; you can redistribute it and/or modify
8168777Srwatson;; it under the terms of the GNU General Public License as published by
9155131Srwatson;; the Free Software Foundation; either version 2, or (at your option)
10155131Srwatson;; any later version.
11168777Srwatson
12185573Srwatson;; GNU CC is distributed in the hope that it will be useful,
13155131Srwatson;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14168777Srwatson;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15168777Srwatson;; GNU General Public License for more details.
16155131Srwatson
17155131Srwatson;; You should have received a copy of the GNU General Public License
18155131Srwatson;; along with GNU CC; see the file COPYING.  If not, write to
19155131Srwatson;; the Free Software Foundation, 59 Temple Place - Suite 330,
20155131Srwatson;; Boston, MA 02111-1307, USA.
21155131Srwatson
22155131Srwatson
23155131Srwatson;; The original PO technology requires these to be ordered by speed,
24155131Srwatson;; so that assigner will pick the fastest.
25155131Srwatson
26155131Srwatson;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
27155131Srwatson
28243750Srwatson;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code
29155131Srwatson;; updates for most instructions.
30155364Srwatson
31155131Srwatson;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register
32155131Srwatson;; constraint letters.
33155131Srwatson
34155131Srwatson;; the special asm out single letter directives following a '%' are:
35155131Srwatson;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of
36155131Srwatson;;     operands[1].
37168777Srwatson;; 'L' Print the opcode suffix for a 32-bit integer opcode.
38155131Srwatson;; 'W' Print the opcode suffix for a 16-bit integer opcode.
39168777Srwatson;; 'B' Print the opcode suffix for an 8-bit integer opcode.
40168777Srwatson;; 'S' Print the opcode suffix for a 32-bit float opcode.
41155131Srwatson;; 'Q' Print the opcode suffix for a 64-bit float opcode.
42155131Srwatson;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode.
43155131Srwatson;; 'J' Print the appropriate jump operand.
44155131Srwatson
45155131Srwatson;; 'b' Print the QImode name of the register for the indicated operand.
46168777Srwatson;;     %b0 would print %al if operands[0] is reg 0.
47168777Srwatson;; 'w' Likewise, print the HImode name of the register.
48168777Srwatson;; 'k' Likewise, print the SImode name of the register.
49155131Srwatson;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh.
50155131Srwatson;; 'y' Print "st(0)" instead of "st" as a register.
51185573Srwatson
52168777Srwatson;; UNSPEC usage:
53155131Srwatson;; 0  This is a `scas' operation.  The mode of the UNSPEC is always SImode.
54155131Srwatson;;    operand 0 is the memory address to scan.
55168777Srwatson;;    operand 1 is a register containing the value to scan for.  The mode
56155131Srwatson;;       of the scas opcode will be the same as the mode of this operand.
57155131Srwatson;;    operand 2 is the known alignment of operand 0.
58155131Srwatson;; 1  This is a `sin' operation.  The mode of the UNSPEC is MODE_FLOAT.
59155131Srwatson;;    operand 0 is the argument for `sin'.
60168777Srwatson;; 2  This is a `cos' operation.  The mode of the UNSPEC is MODE_FLOAT.
61168777Srwatson;;    operand 0 is the argument for `cos'.
62168777Srwatson
63155131Srwatson;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM".
64168777Srwatson;; But restricting MEM here would mean that gcc could not remove a redundant
65168777Srwatson;; test in cases like "incl MEM / je TARGET".
66155131Srwatson;;
67155131Srwatson;; We don't want to allow a constant operand for test insns because
68155131Srwatson;; (set (cc0) (const_int foo)) has no mode information.  Such insns will
69168777Srwatson;; be folded while optimizing anyway.
70155131Srwatson
71155131Srwatson;; All test insns have expanders that save the operands away without
72168777Srwatson;; actually generating RTL.  The bCOND or sCOND (emitted immediately
73155131Srwatson;; after the tstM or cmp) will actually emit the tstM or cmpM.
74168777Srwatson
75155131Srwatson(define_insn "tstsi_1"
76155131Srwatson  [(set (cc0)
77155131Srwatson	(match_operand:SI 0 "nonimmediate_operand" "rm"))]
78155131Srwatson  ""
79155131Srwatson  "*
80155131Srwatson{
81155131Srwatson  if (REG_P (operands[0]))
82155131Srwatson    return AS2 (test%L0,%0,%0);
83155131Srwatson
84155131Srwatson  operands[1] = const0_rtx;
85155131Srwatson  return AS2 (cmp%L0,%1,%0);
86155131Srwatson}")
87155290Srwatson
88155131Srwatson(define_expand "tstsi"
89168777Srwatson  [(set (cc0)
90155131Srwatson	(match_operand:SI 0 "nonimmediate_operand" ""))]
91168777Srwatson  ""
92155131Srwatson  "
93168777Srwatson{
94155131Srwatson  i386_compare_gen = gen_tstsi_1;
95243750Srwatson  i386_compare_op0 = operands[0];
96155131Srwatson  DONE;
97185573Srwatson}")
98185573Srwatson
99155131Srwatson(define_insn "tsthi_1"
100155131Srwatson  [(set (cc0)
101155131Srwatson	(match_operand:HI 0 "nonimmediate_operand" "rm"))]
102168777Srwatson  ""
103168777Srwatson  "*
104168777Srwatson{
105162621Srwatson  if (REG_P (operands[0]))
106162621Srwatson    return AS2 (test%W0,%0,%0);
107162621Srwatson
108168777Srwatson  operands[1] = const0_rtx;
109168777Srwatson  return AS2 (cmp%W0,%1,%0);
110168777Srwatson}")
111162621Srwatson
112162621Srwatson(define_expand "tsthi"
113162621Srwatson  [(set (cc0)
114162621Srwatson	(match_operand:HI 0 "nonimmediate_operand" ""))]
115168777Srwatson  ""
116168777Srwatson  "
117168777Srwatson{
118162621Srwatson  i386_compare_gen = gen_tsthi_1;
119168777Srwatson  i386_compare_op0 = operands[0];
120168777Srwatson  DONE;
121168777Srwatson}")
122168777Srwatson
123168777Srwatson(define_insn "tstqi_1"
124168777Srwatson  [(set (cc0)
125168777Srwatson	(match_operand:QI 0 "nonimmediate_operand" "qm"))]
126168777Srwatson  ""
127155131Srwatson  "*
128168777Srwatson{
129168777Srwatson  if (REG_P (operands[0]))
130168777Srwatson    return AS2 (test%B0,%0,%0);
131168777Srwatson
132185573Srwatson  operands[1] = const0_rtx;
133185573Srwatson  return AS2 (cmp%B0,%1,%0);
134155131Srwatson}")
135168777Srwatson
136155131Srwatson(define_expand "tstqi"
137155364Srwatson  [(set (cc0)
138155364Srwatson	(match_operand:QI 0 "nonimmediate_operand" ""))]
139168777Srwatson  ""
140168777Srwatson  "
141168777Srwatson{
142168777Srwatson  i386_compare_gen = gen_tstqi_1;
143155131Srwatson  i386_compare_op0 = operands[0];
144155131Srwatson  DONE;
145155131Srwatson}")
146155131Srwatson
147168777Srwatson(define_insn "tstsf_cc"
148168777Srwatson  [(set (cc0)
149168777Srwatson	(match_operand:SF 0 "register_operand" "f"))
150168777Srwatson   (clobber (match_scratch:HI 1 "=a"))]
151155131Srwatson  "TARGET_80387 && ! TARGET_IEEE_FP"
152162621Srwatson  "*
153162621Srwatson{
154162621Srwatson  if (! STACK_TOP_P (operands[0]))
155162621Srwatson    abort ();
156162621Srwatson
157162621Srwatson  output_asm_insn (\"ftst\", operands);
158168777Srwatson
159168777Srwatson  if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
160168777Srwatson    output_asm_insn (AS1 (fstp,%y0), operands);
161168777Srwatson
162168777Srwatson  return output_fp_cc0_set (insn);
163162621Srwatson}")
164162621Srwatson
165162621Srwatson;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode
166168777Srwatson;; isn't IEEE compliant.
167168777Srwatson
168168777Srwatson(define_expand "tstsf"
169168777Srwatson  [(parallel [(set (cc0)
170162621Srwatson		   (match_operand:SF 0 "register_operand" ""))
171162621Srwatson	      (clobber (match_scratch:HI 1 ""))])]
172162621Srwatson  "TARGET_80387 && ! TARGET_IEEE_FP"
173168777Srwatson  "
174168777Srwatson{
175168777Srwatson  i386_compare_gen = gen_tstsf_cc;
176168777Srwatson  i386_compare_op0 = operands[0];
177168777Srwatson  DONE;
178155131Srwatson}")
179155364Srwatson
180155131Srwatson(define_insn "tstdf_cc"
181155364Srwatson  [(set (cc0)
182168777Srwatson	(match_operand:DF 0 "register_operand" "f"))
183168777Srwatson   (clobber (match_scratch:HI 1 "=a"))]
184168777Srwatson  "TARGET_80387 && ! TARGET_IEEE_FP"
185168777Srwatson  "*
186168777Srwatson{
187155131Srwatson  if (! STACK_TOP_P (operands[0]))
188168777Srwatson    abort ();
189155131Srwatson
190155131Srwatson  output_asm_insn (\"ftst\", operands);
191168777Srwatson
192168777Srwatson  if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
193168777Srwatson    output_asm_insn (AS1 (fstp,%y0), operands);
194168777Srwatson
195155131Srwatson  return output_fp_cc0_set (insn);
196155131Srwatson}")
197155131Srwatson
198;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
199;; isn't IEEE compliant.
200
201(define_expand "tstdf"
202  [(parallel [(set (cc0)
203		   (match_operand:DF 0 "register_operand" ""))
204	      (clobber (match_scratch:HI 1 ""))])]
205  "TARGET_80387 && ! TARGET_IEEE_FP"
206  "
207{
208  i386_compare_gen = gen_tstdf_cc;
209  i386_compare_op0 = operands[0];
210  DONE;
211}")
212
213(define_insn "tstxf_cc"
214  [(set (cc0)
215	(match_operand:XF 0 "register_operand" "f"))
216   (clobber (match_scratch:HI 1 "=a"))]
217  "TARGET_80387 && ! TARGET_IEEE_FP"
218  "*
219{
220  if (! STACK_TOP_P (operands[0]))
221    abort ();
222
223  output_asm_insn (\"ftst\", operands);
224
225  if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
226    output_asm_insn (AS1 (fstp,%y0), operands);
227
228  return output_fp_cc0_set (insn);
229}")
230
231;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
232;; isn't IEEE compliant.
233
234(define_expand "tstxf"
235  [(parallel [(set (cc0)
236		   (match_operand:XF 0 "register_operand" ""))
237	      (clobber (match_scratch:HI 1 ""))])]
238  "TARGET_80387 && ! TARGET_IEEE_FP"
239  "
240{
241  i386_compare_gen = gen_tstxf_cc;
242  i386_compare_op0 = operands[0];
243  DONE;
244}")
245
246;;- compare instructions.  See comments above tstM patterns about
247;;  expansion of these insns.
248
249(define_insn "cmpsi_1"
250  [(set (cc0)
251	(compare (match_operand:SI 0 "nonimmediate_operand" "mr,r")
252		 (match_operand:SI 1 "general_operand" "ri,mr")))]
253  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
254  "*
255{
256  if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
257    {
258      cc_status.flags |= CC_REVERSED;
259      return AS2 (cmp%L0,%0,%1);
260    }
261  return AS2 (cmp%L0,%1,%0);
262}")
263
264(define_expand "cmpsi"
265  [(set (cc0)
266	(compare (match_operand:SI 0 "nonimmediate_operand" "")
267		 (match_operand:SI 1 "general_operand" "")))]
268  ""
269  "
270{
271  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
272    operands[0] = force_reg (SImode, operands[0]);
273
274  i386_compare_gen = gen_cmpsi_1;
275  i386_compare_op0 = operands[0];
276  i386_compare_op1 = operands[1];
277  DONE;
278}")
279
280(define_insn "cmphi_1"
281  [(set (cc0)
282	(compare (match_operand:HI 0 "nonimmediate_operand" "mr,r")
283		 (match_operand:HI 1 "general_operand" "ri,mr")))]
284  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
285  "*
286{
287  if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
288    {
289      cc_status.flags |= CC_REVERSED;
290      return AS2 (cmp%W0,%0,%1);
291    }
292  return AS2 (cmp%W0,%1,%0);
293}")
294
295(define_expand "cmphi"
296  [(set (cc0)
297	(compare (match_operand:HI 0 "nonimmediate_operand" "")
298		 (match_operand:HI 1 "general_operand" "")))]
299  ""
300  "
301{
302  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
303    operands[0] = force_reg (HImode, operands[0]);
304
305  i386_compare_gen = gen_cmphi_1;
306  i386_compare_op0 = operands[0];
307  i386_compare_op1 = operands[1];
308  DONE;
309}")
310
311(define_insn "cmpqi_1"
312  [(set (cc0)
313	(compare (match_operand:QI 0 "nonimmediate_operand" "q,mq")
314		 (match_operand:QI 1 "general_operand" "qm,nq")))]
315  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
316  "*
317{
318  if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
319    {
320      cc_status.flags |= CC_REVERSED;
321      return AS2 (cmp%B0,%0,%1);
322    }
323  return AS2 (cmp%B0,%1,%0);
324}")
325
326(define_expand "cmpqi"
327  [(set (cc0)
328	(compare (match_operand:QI 0 "nonimmediate_operand" "")
329		 (match_operand:QI 1 "general_operand" "")))]
330  ""
331  "
332{
333  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
334    operands[0] = force_reg (QImode, operands[0]);
335
336  i386_compare_gen = gen_cmpqi_1;
337  i386_compare_op0 = operands[0];
338  i386_compare_op1 = operands[1];
339  DONE;
340}")
341
342;; These implement float point compares.  For each of DFmode and
343;; SFmode, there is the normal insn, and an insn where the second operand
344;; is converted to the desired mode.
345
346(define_insn ""
347  [(set (cc0)
348	(match_operator 2 "VOIDmode_compare_op"
349			[(match_operand:XF 0 "nonimmediate_operand" "f")
350			 (match_operand:XF 1 "nonimmediate_operand" "f")]))
351   (clobber (match_scratch:HI 3 "=a"))]
352  "TARGET_80387
353   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
354  "* return output_float_compare (insn, operands);")
355
356(define_insn ""
357  [(set (cc0)
358	(match_operator 2 "VOIDmode_compare_op"
359			[(match_operand:XF 0 "register_operand" "f")
360			 (float:XF
361			  (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
362   (clobber (match_scratch:HI 3 "=a"))]
363  "TARGET_80387"
364  "* return output_float_compare (insn, operands);")
365
366(define_insn ""
367  [(set (cc0)
368	(match_operator 2 "VOIDmode_compare_op"
369			[(float:XF
370			  (match_operand:SI 0 "nonimmediate_operand" "rm"))
371			 (match_operand:XF 1 "register_operand" "f")]))
372   (clobber (match_scratch:HI 3 "=a"))]
373  "TARGET_80387"
374  "* return output_float_compare (insn, operands);")
375
376(define_insn ""
377  [(set (cc0)
378	(match_operator 2 "VOIDmode_compare_op"
379			[(match_operand:XF 0 "register_operand" "f")
380			 (float_extend:XF
381			  (match_operand:DF 1 "nonimmediate_operand" "fm"))]))
382   (clobber (match_scratch:HI 3 "=a"))]
383  "TARGET_80387"
384  "* return output_float_compare (insn, operands);")
385
386(define_insn ""
387  [(set (cc0)
388	(match_operator 2 "VOIDmode_compare_op"
389			[(match_operand:XF 0 "register_operand" "f")
390			 (float_extend:XF
391			  (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
392   (clobber (match_scratch:HI 3 "=a"))]
393  "TARGET_80387"
394  "* return output_float_compare (insn, operands);")
395
396(define_insn ""
397  [(set (cc0)
398	(compare:CCFPEQ (match_operand:XF 0 "register_operand" "f")
399			(match_operand:XF 1 "register_operand" "f")))
400   (clobber (match_scratch:HI 2 "=a"))]
401  "TARGET_80387"
402  "* return output_float_compare (insn, operands);")
403
404(define_insn ""
405  [(set (cc0)
406	(match_operator 2 "VOIDmode_compare_op"
407			[(match_operand:DF 0 "nonimmediate_operand" "f,fm")
408			 (match_operand:DF 1 "nonimmediate_operand" "fm,f")]))
409   (clobber (match_scratch:HI 3 "=a,a"))]
410  "TARGET_80387
411   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
412  "* return output_float_compare (insn, operands);")
413
414(define_insn ""
415  [(set (cc0)
416	(match_operator 2 "VOIDmode_compare_op"
417			[(match_operand:DF 0 "register_operand" "f")
418			 (float:DF
419			  (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
420   (clobber (match_scratch:HI 3 "=a"))]
421  "TARGET_80387"
422  "* return output_float_compare (insn, operands);")
423
424(define_insn ""
425  [(set (cc0)
426	(match_operator 2 "VOIDmode_compare_op"
427			[(float:DF
428			  (match_operand:SI 0 "nonimmediate_operand" "rm"))
429			 (match_operand:DF 1 "register_operand" "f")]))
430   (clobber (match_scratch:HI 3 "=a"))]
431  "TARGET_80387"
432  "* return output_float_compare (insn, operands);")
433
434(define_insn ""
435  [(set (cc0)
436	(match_operator 2 "VOIDmode_compare_op"
437			[(match_operand:DF 0 "register_operand" "f")
438			 (float_extend:DF
439			  (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
440   (clobber (match_scratch:HI 3 "=a"))]
441  "TARGET_80387"
442  "* return output_float_compare (insn, operands);")
443
444(define_insn ""
445  [(set (cc0)
446	(match_operator 2 "VOIDmode_compare_op"
447			[(float_extend:DF
448			  (match_operand:SF 0 "nonimmediate_operand" "fm"))
449			 (match_operand:DF 1 "register_operand" "f")]))
450   (clobber (match_scratch:HI 3 "=a"))]
451  "TARGET_80387"
452  "* return output_float_compare (insn, operands);")
453
454(define_insn ""
455  [(set (cc0)
456	(compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
457			(match_operand:DF 1 "register_operand" "f")))
458   (clobber (match_scratch:HI 2 "=a"))]
459  "TARGET_80387"
460  "* return output_float_compare (insn, operands);")
461
462;; These two insns will never be generated by combine due to the mode of
463;; the COMPARE.
464;(define_insn ""
465;  [(set (cc0)
466;	(compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
467;			(float_extend:DF
468;			 (match_operand:SF 1 "register_operand" "f"))))
469;   (clobber (match_scratch:HI 2 "=a"))]
470;  "TARGET_80387"
471;  "* return output_float_compare (insn, operands);")
472;
473;(define_insn ""
474;  [(set (cc0)
475;	(compare:CCFPEQ (float_extend:DF
476;			 (match_operand:SF 0 "register_operand" "f"))
477;			(match_operand:DF 1 "register_operand" "f")))
478;   (clobber (match_scratch:HI 2 "=a"))]
479;  "TARGET_80387"
480;  "* return output_float_compare (insn, operands);")
481
482(define_insn "cmpsf_cc_1"
483  [(set (cc0)
484	(match_operator 2 "VOIDmode_compare_op"
485			[(match_operand:SF 0 "nonimmediate_operand" "f,fm")
486			 (match_operand:SF 1 "nonimmediate_operand" "fm,f")]))
487   (clobber (match_scratch:HI 3 "=a,a"))]
488  "TARGET_80387
489   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
490  "* return output_float_compare (insn, operands);")
491
492(define_insn ""
493  [(set (cc0)
494	(match_operator 2 "VOIDmode_compare_op"
495			[(match_operand:SF 0 "register_operand" "f")
496			 (float:SF
497			  (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
498   (clobber (match_scratch:HI 3 "=a"))]
499  "TARGET_80387"
500  "* return output_float_compare (insn, operands);")
501
502(define_insn ""
503  [(set (cc0)
504	(match_operator 2 "VOIDmode_compare_op"
505			[(float:SF
506			  (match_operand:SI 0 "nonimmediate_operand" "rm"))
507			 (match_operand:SF 1 "register_operand" "f")]))
508   (clobber (match_scratch:HI 3 "=a"))]
509  "TARGET_80387"
510  "* return output_float_compare (insn, operands);")
511
512(define_insn ""
513  [(set (cc0)
514	(compare:CCFPEQ (match_operand:SF 0 "register_operand" "f")
515			(match_operand:SF 1 "register_operand" "f")))
516   (clobber (match_scratch:HI 2 "=a"))]
517  "TARGET_80387"
518  "* return output_float_compare (insn, operands);")
519
520(define_expand "cmpxf"
521  [(set (cc0)
522	(compare (match_operand:XF 0 "register_operand" "")
523		 (match_operand:XF 1 "nonimmediate_operand" "")))]
524  "TARGET_80387"
525  "
526{
527  i386_compare_gen = gen_cmpxf_cc;
528  i386_compare_gen_eq = gen_cmpxf_ccfpeq;
529  i386_compare_op0 = operands[0];
530  i386_compare_op1 = operands[1];
531  DONE;
532}")
533
534(define_expand "cmpdf"
535  [(set (cc0)
536	(compare (match_operand:DF 0 "register_operand" "")
537		 (match_operand:DF 1 "nonimmediate_operand" "")))]
538  "TARGET_80387"
539  "
540{
541  i386_compare_gen = gen_cmpdf_cc;
542  i386_compare_gen_eq = gen_cmpdf_ccfpeq;
543  i386_compare_op0 = operands[0];
544  i386_compare_op1 = operands[1];
545  DONE;
546}")
547
548(define_expand "cmpsf"
549  [(set (cc0)
550	(compare (match_operand:SF 0 "register_operand" "")
551		 (match_operand:SF 1 "nonimmediate_operand" "")))]
552  "TARGET_80387"
553  "
554{
555  i386_compare_gen = gen_cmpsf_cc;
556  i386_compare_gen_eq = gen_cmpsf_ccfpeq;
557  i386_compare_op0 = operands[0];
558  i386_compare_op1 = operands[1];
559  DONE;
560}")
561
562(define_expand "cmpxf_cc"
563  [(parallel [(set (cc0)
564		   (compare (match_operand:XF 0 "register_operand" "")
565			    (match_operand:XF 1 "register_operand" "")))
566	      (clobber (match_scratch:HI 2 ""))])]
567  "TARGET_80387"
568  "")
569
570(define_expand "cmpxf_ccfpeq"
571  [(parallel [(set (cc0)
572		   (compare:CCFPEQ (match_operand:XF 0 "register_operand" "")
573				   (match_operand:XF 1 "register_operand" "")))
574	      (clobber (match_scratch:HI 2 ""))])]
575  "TARGET_80387"
576  "
577{
578  if (! register_operand (operands[1], XFmode))
579    operands[1] = copy_to_mode_reg (XFmode, operands[1]);
580}")
581
582(define_expand "cmpdf_cc"
583  [(parallel [(set (cc0)
584		   (compare (match_operand:DF 0 "register_operand" "")
585			    (match_operand:DF 1 "register_operand" "")))
586	      (clobber (match_scratch:HI 2 ""))])]
587  "TARGET_80387"
588  "")
589
590(define_expand "cmpdf_ccfpeq"
591  [(parallel [(set (cc0)
592		   (compare:CCFPEQ (match_operand:DF 0 "register_operand" "")
593				   (match_operand:DF 1 "register_operand" "")))
594	      (clobber (match_scratch:HI 2 ""))])]
595  "TARGET_80387"
596  "
597{
598  if (! register_operand (operands[1], DFmode))
599    operands[1] = copy_to_mode_reg (DFmode, operands[1]);
600}")
601
602(define_expand "cmpsf_cc"
603  [(parallel [(set (cc0)
604		   (compare (match_operand:SF 0 "register_operand" "")
605			    (match_operand:SF 1 "register_operand" "")))
606	      (clobber (match_scratch:HI 2 ""))])]
607  "TARGET_80387"
608  "")
609
610(define_expand "cmpsf_ccfpeq"
611  [(parallel [(set (cc0)
612		   (compare:CCFPEQ (match_operand:SF 0 "register_operand" "")
613				   (match_operand:SF 1 "register_operand" "")))
614	      (clobber (match_scratch:HI 2 ""))])]
615  "TARGET_80387"
616  "
617{
618  if (! register_operand (operands[1], SFmode))
619    operands[1] = copy_to_mode_reg (SFmode, operands[1]);
620}")
621
622;; logical compare
623
624(define_insn ""
625  [(set (cc0)
626	(and:SI (match_operand:SI 0 "general_operand" "%ro")
627		(match_operand:SI 1 "general_operand" "ri")))]
628  ""
629  "*
630{
631  /* For small integers, we may actually use testb. */
632  if (GET_CODE (operands[1]) == CONST_INT
633      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
634      && (! REG_P (operands[0]) || QI_REG_P (operands[0])))
635    {
636      /* We may set the sign bit spuriously.  */
637
638      if ((INTVAL (operands[1]) & ~0xff) == 0)
639        {
640	  cc_status.flags |= CC_NOT_NEGATIVE;
641	  return AS2 (test%B0,%1,%b0);
642	}
643
644      if ((INTVAL (operands[1]) & ~0xff00) == 0)
645        {
646	  cc_status.flags |= CC_NOT_NEGATIVE;
647	  operands[1] = GEN_INT (INTVAL (operands[1]) >> 8);
648
649	  if (QI_REG_P (operands[0]))
650	    return AS2 (test%B0,%1,%h0);
651	  else
652	    {
653	      operands[0] = adj_offsettable_operand (operands[0], 1);
654	      return AS2 (test%B0,%1,%b0);
655	    }
656	}
657
658      if (GET_CODE (operands[0]) == MEM
659	  && (INTVAL (operands[1]) & ~0xff0000) == 0)
660        {
661	  cc_status.flags |= CC_NOT_NEGATIVE;
662	  operands[1] = GEN_INT (INTVAL (operands[1]) >> 16);
663	  operands[0] = adj_offsettable_operand (operands[0], 2);
664	  return AS2 (test%B0,%1,%b0);
665	}
666
667      if (GET_CODE (operands[0]) == MEM
668	  && (INTVAL (operands[1]) & ~0xff000000) == 0)
669        {
670	  operands[1] = GEN_INT ((INTVAL (operands[1]) >> 24) & 0xff);
671	  operands[0] = adj_offsettable_operand (operands[0], 3);
672	  return AS2 (test%B0,%1,%b0);
673	}
674    }
675
676  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
677    return AS2 (test%L0,%1,%0);
678
679  return AS2 (test%L1,%0,%1);
680}")
681
682(define_insn ""
683  [(set (cc0)
684	(and:HI (match_operand:HI 0 "general_operand" "%ro")
685		(match_operand:HI 1 "general_operand" "ri")))]
686  ""
687  "*
688{
689  if (GET_CODE (operands[1]) == CONST_INT
690      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
691      && (! REG_P (operands[0]) || QI_REG_P (operands[0])))
692    {
693      if ((INTVAL (operands[1]) & 0xff00) == 0)
694	{
695	  /* ??? This might not be necessary. */
696	  if (INTVAL (operands[1]) & 0xffff0000)
697	    operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
698
699	  /* We may set the sign bit spuriously.  */
700	  cc_status.flags |= CC_NOT_NEGATIVE;
701	  return AS2 (test%B0,%1,%b0);
702	}
703
704      if ((INTVAL (operands[1]) & 0xff) == 0)
705        {
706	  operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff);
707
708	  if (QI_REG_P (operands[0]))
709	    return AS2 (test%B0,%1,%h0);
710	  else
711	    {
712	      operands[0] = adj_offsettable_operand (operands[0], 1);
713	      return AS2 (test%B0,%1,%b0);
714	    }
715	}
716    }
717
718  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
719    return AS2 (test%W0,%1,%0);
720
721  return AS2 (test%W1,%0,%1);
722}")
723
724(define_insn ""
725  [(set (cc0)
726	(and:QI (match_operand:QI 0 "general_operand" "%qm")
727		(match_operand:QI 1 "general_operand" "qi")))]
728  ""
729  "*
730{
731  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
732    return AS2 (test%B0,%1,%0);
733
734  return AS2 (test%B1,%0,%1);
735}")
736
737;; move instructions.
738;; There is one for each machine mode,
739;; and each is preceded by a corresponding push-insn pattern
740;; (since pushes are not general_operands on the 386).
741
742(define_insn ""
743  [(set (match_operand:SI 0 "push_operand" "=<")
744	(match_operand:SI 1 "general_operand" "g"))]
745  "TARGET_386"
746  "push%L0 %1")
747
748;; On a 486, it is faster to move MEM to a REG and then push, rather than
749;; push MEM directly.
750
751(define_insn ""
752  [(set (match_operand:SI 0 "push_operand" "=<")
753	(match_operand:SI 1 "nonmemory_operand" "ri"))]
754  "!TARGET_386 && TARGET_MOVE"
755  "push%L0 %1")
756
757(define_insn ""
758  [(set (match_operand:SI 0 "push_operand" "=<")
759	(match_operand:SI 1 "general_operand" "ri"))]
760  "!TARGET_386 && !TARGET_MOVE"
761  "push%L0 %1")
762
763;; General case of fullword move.
764
765;; If generating PIC code and operands[1] is a symbolic CONST, emit a
766;; move to get the address of the symbolic object from the GOT.
767
768(define_expand "movsi"
769  [(set (match_operand:SI 0 "general_operand" "")
770	(match_operand:SI 1 "general_operand" ""))]
771  ""
772  "
773{
774  extern int flag_pic;
775
776  if (flag_pic && SYMBOLIC_CONST (operands[1]))
777    emit_pic_move (operands, SImode);
778
779  /* Don't generate memory->memory moves, go through a register */
780  else if (TARGET_MOVE
781	   && (reload_in_progress | reload_completed) == 0
782	   && GET_CODE (operands[0]) == MEM
783	   && GET_CODE (operands[1]) == MEM)
784    {
785      operands[1] = force_reg (SImode, operands[1]);
786    }
787}")
788
789;; On i486, incl reg is faster than movl $1,reg.
790
791(define_insn ""
792  [(set (match_operand:SI 0 "general_operand" "=g,r")
793	(match_operand:SI 1 "general_operand" "ri,m"))]
794  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
795  "*
796{
797  rtx link;
798  if (operands[1] == const0_rtx && REG_P (operands[0]))
799    return AS2 (xor%L0,%0,%0);
800
801  if (operands[1] == const1_rtx
802      && (link = find_reg_note (insn, REG_WAS_0, 0))
803      /* Make sure the insn that stored the 0 is still present.  */
804      && ! INSN_DELETED_P (XEXP (link, 0))
805      && GET_CODE (XEXP (link, 0)) != NOTE
806      /* Make sure cross jumping didn't happen here.  */
807      && no_labels_between_p (XEXP (link, 0), insn)
808      /* Make sure the reg hasn't been clobbered.  */
809      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
810    /* Fastest way to change a 0 to a 1.  */
811    return AS1 (inc%L0,%0);
812
813  if (flag_pic && SYMBOLIC_CONST (operands[1]))
814    return AS2 (lea%L0,%a1,%0);
815
816  return AS2 (mov%L0,%1,%0);
817}")
818
819(define_insn ""
820  [(set (match_operand:HI 0 "push_operand" "=<")
821	(match_operand:HI 1 "general_operand" "g"))]
822  "TARGET_386"
823  "push%W0 %1")
824
825(define_insn ""
826  [(set (match_operand:HI 0 "push_operand" "=<")
827	(match_operand:HI 1 "nonmemory_operand" "ri"))]
828  "!TARGET_386 && TARGET_MOVE"
829  "push%W0 %1")
830
831(define_insn ""
832  [(set (match_operand:HI 0 "push_operand" "=<")
833	(match_operand:HI 1 "general_operand" "ri"))]
834  "!TARGET_386 && !TARGET_MOVE"
835  "push%W0 %1")
836
837;; On i486, an incl and movl are both faster than incw and movw.
838
839(define_expand "movhi"
840  [(set (match_operand:HI 0 "general_operand" "")
841	(match_operand:HI 1 "general_operand" ""))]
842  ""
843  "
844{
845  /* Don't generate memory->memory moves, go through a register */
846  if (TARGET_MOVE
847      && (reload_in_progress | reload_completed) == 0
848      && GET_CODE (operands[0]) == MEM
849      && GET_CODE (operands[1]) == MEM)
850    {
851      operands[1] = force_reg (HImode, operands[1]);
852    }
853}")
854
855(define_insn ""
856  [(set (match_operand:HI 0 "general_operand" "=g,r")
857	(match_operand:HI 1 "general_operand" "ri,m"))]
858  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
859  "*
860{
861  rtx link;
862  if (REG_P (operands[0]) && operands[1] == const0_rtx)
863    return AS2 (xor%L0,%k0,%k0);
864
865  if (REG_P (operands[0]) && operands[1] == const1_rtx 
866      && (link = find_reg_note (insn, REG_WAS_0, 0))
867      /* Make sure the insn that stored the 0 is still present.  */
868      && ! INSN_DELETED_P (XEXP (link, 0))
869      && GET_CODE (XEXP (link, 0)) != NOTE
870      /* Make sure cross jumping didn't happen here.  */
871      && no_labels_between_p (XEXP (link, 0), insn)
872      /* Make sure the reg hasn't been clobbered.  */
873      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
874    /* Fastest way to change a 0 to a 1.  */
875    return AS1 (inc%L0,%k0);
876
877  if (REG_P (operands[0]))
878    {
879      if (REG_P (operands[1]))
880	return AS2 (mov%L0,%k1,%k0);
881      else if (CONSTANT_P (operands[1]))
882	return AS2 (mov%L0,%1,%k0);
883    }
884
885  return AS2 (mov%W0,%1,%0);
886}")
887
888(define_expand "movstricthi"
889  [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
890	(match_operand:HI 1 "general_operand" ""))]
891  ""
892  "
893{
894  /* Don't generate memory->memory moves, go through a register */
895  if (TARGET_MOVE
896      && (reload_in_progress | reload_completed) == 0
897      && GET_CODE (operands[0]) == MEM
898      && GET_CODE (operands[1]) == MEM)
899    {
900      operands[1] = force_reg (HImode, operands[1]);
901    }
902}")
903
904(define_insn ""
905  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r"))
906	(match_operand:HI 1 "general_operand" "ri,m"))]
907  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
908  "*
909{
910  rtx link;
911  if (operands[1] == const0_rtx && REG_P (operands[0]))
912    return AS2 (xor%W0,%0,%0);
913
914  if (operands[1] == const1_rtx
915      && (link = find_reg_note (insn, REG_WAS_0, 0))
916      /* Make sure the insn that stored the 0 is still present.  */
917      && ! INSN_DELETED_P (XEXP (link, 0))
918      && GET_CODE (XEXP (link, 0)) != NOTE
919      /* Make sure cross jumping didn't happen here.  */
920      && no_labels_between_p (XEXP (link, 0), insn)
921      /* Make sure the reg hasn't been clobbered.  */
922      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
923    /* Fastest way to change a 0 to a 1.  */
924    return AS1 (inc%W0,%0);
925
926  return AS2 (mov%W0,%1,%0);
927}")
928
929;; emit_push_insn when it calls move_by_pieces
930;; requires an insn to "push a byte".
931;; But actually we use pushw, which has the effect of rounding
932;; the amount pushed up to a halfword.
933(define_insn ""
934  [(set (match_operand:QI 0 "push_operand" "=<")
935	(match_operand:QI 1 "immediate_operand" "n"))]
936  ""
937  "* return AS1 (push%W0,%1);")
938
939(define_insn ""
940  [(set (match_operand:QI 0 "push_operand" "=<")
941	(match_operand:QI 1 "nonimmediate_operand" "q"))]
942  "!TARGET_MOVE"
943  "*
944{
945  operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
946  return AS1 (push%W0,%1);
947}")
948
949(define_insn ""
950  [(set (match_operand:QI 0 "push_operand" "=<")
951	(match_operand:QI 1 "register_operand" "q"))]
952  "TARGET_MOVE"
953  "*
954{
955  operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
956  return AS1 (push%W0,%1);
957}")
958
959;; On i486, incb reg is faster than movb $1,reg.
960
961;; ??? Do a recognizer for zero_extract that looks just like this, but reads
962;; or writes %ah, %bh, %ch, %dh.
963
964(define_expand "movqi"
965  [(set (match_operand:QI 0 "general_operand" "")
966	(match_operand:QI 1 "general_operand" ""))]
967  ""
968  "
969{
970  /* Don't generate memory->memory moves, go through a register */
971  if (TARGET_MOVE
972      && (reload_in_progress | reload_completed) == 0
973      && GET_CODE (operands[0]) == MEM
974      && GET_CODE (operands[1]) == MEM)
975    {
976      operands[1] = force_reg (QImode, operands[1]);
977    }
978}")
979
980(define_insn ""
981  [(set (match_operand:QI 0 "general_operand" "=q,*r,qm")
982	(match_operand:QI 1 "general_operand" "*g,q,qn"))]
983  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
984  "*
985{
986  rtx link;
987  if (operands[1] == const0_rtx && REG_P (operands[0]))
988    return AS2 (xor%B0,%0,%0);
989
990  if (operands[1] == const1_rtx
991      && (link = find_reg_note (insn, REG_WAS_0, 0))
992      /* Make sure the insn that stored the 0 is still present.  */
993      && ! INSN_DELETED_P (XEXP (link, 0))
994      && GET_CODE (XEXP (link, 0)) != NOTE
995      /* Make sure cross jumping didn't happen here.  */
996      && no_labels_between_p (XEXP (link, 0), insn)
997      /* Make sure the reg hasn't been clobbered.  */
998      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
999    /* Fastest way to change a 0 to a 1.  */
1000    return AS1 (inc%B0,%0);
1001
1002  /* If mov%B0 isn't allowed for one of these regs, use mov%L0.  */
1003  if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
1004    return (AS2 (mov%L0,%k1,%k0));
1005
1006  return (AS2 (mov%B0,%1,%0));
1007}")
1008
1009;; If it becomes necessary to support movstrictqi into %esi or %edi,
1010;; use the insn sequence:
1011;;
1012;;	shrdl $8,srcreg,dstreg
1013;;	rorl $24,dstreg
1014;;
1015;; If operands[1] is a constant, then an andl/orl sequence would be
1016;; faster.
1017
1018(define_expand "movstrictqi"
1019  [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
1020	(match_operand:QI 1 "general_operand" ""))]
1021  ""
1022  "
1023{
1024  /* Don't generate memory->memory moves, go through a register */
1025  if (TARGET_MOVE
1026      && (reload_in_progress | reload_completed) == 0
1027      && GET_CODE (operands[0]) == MEM
1028      && GET_CODE (operands[1]) == MEM)
1029    {
1030      operands[1] = force_reg (QImode, operands[1]);
1031    }
1032}")
1033
1034(define_insn ""
1035  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q"))
1036	(match_operand:QI 1 "general_operand" "*qn,m"))]
1037  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1038  "*
1039{
1040  rtx link;
1041  if (operands[1] == const0_rtx && REG_P (operands[0]))
1042    return AS2 (xor%B0,%0,%0);
1043
1044  if (operands[1] == const1_rtx
1045      && (link = find_reg_note (insn, REG_WAS_0, 0))
1046      /* Make sure the insn that stored the 0 is still present.  */
1047      && ! INSN_DELETED_P (XEXP (link, 0))
1048      && GET_CODE (XEXP (link, 0)) != NOTE
1049      /* Make sure cross jumping didn't happen here.  */
1050      && no_labels_between_p (XEXP (link, 0), insn)
1051      /* Make sure the reg hasn't been clobbered.  */
1052      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
1053    /* Fastest way to change a 0 to a 1.  */
1054    return AS1 (inc%B0,%0);
1055
1056  /* If mov%B0 isn't allowed for one of these regs, use mov%L0.  */
1057  if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
1058    {
1059      abort ();
1060      return (AS2 (mov%L0,%k1,%k0));
1061    }
1062
1063  return AS2 (mov%B0,%1,%0);
1064}")
1065
1066(define_expand "movsf"
1067  [(set (match_operand:SF 0 "general_operand" "")
1068	(match_operand:SF 1 "general_operand" ""))]
1069  ""
1070  "
1071{
1072  /* Special case memory->memory moves and pushes */
1073  if (TARGET_MOVE
1074      && (reload_in_progress | reload_completed) == 0
1075      && GET_CODE (operands[0]) == MEM
1076      && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode)))
1077    {
1078      rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode))
1079						? gen_movsf_push
1080						: gen_movsf_mem;
1081
1082      emit_insn ((*genfunc) (operands[0], operands[1]));
1083      DONE;
1084    }
1085
1086  /* If we are loading a floating point constant that isn't 0 or 1 into a register,
1087     indicate we need the pic register loaded.  This could be optimized into stores
1088     of constants if the target eventually moves to memory, but better safe than
1089     sorry.  */
1090  if (flag_pic
1091      && GET_CODE (operands[0]) != MEM
1092      && GET_CODE (operands[1]) == CONST_DOUBLE
1093      && !standard_80387_constant_p (operands[1]))
1094    {
1095      current_function_uses_pic_offset_table = 1;
1096    }
1097}")
1098
1099(define_insn "movsf_push_nomove"
1100  [(set (match_operand:SF 0 "push_operand" "=<,<")
1101	(match_operand:SF 1 "general_operand" "gF,f"))]
1102  "!TARGET_MOVE"
1103  "*
1104{
1105  if (STACK_REG_P (operands[1]))
1106    {
1107      rtx xops[3];
1108
1109      if (! STACK_TOP_P (operands[1]))
1110        abort ();
1111
1112      xops[0] = AT_SP (SFmode);
1113      xops[1] = GEN_INT (4);
1114      xops[2] = stack_pointer_rtx;
1115
1116      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1117
1118      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1119        output_asm_insn (AS1 (fstp%S0,%0), xops);
1120      else
1121        output_asm_insn (AS1 (fst%S0,%0), xops);
1122      RET;
1123    }
1124  return AS1 (push%L1,%1);
1125}")
1126
1127(define_insn "movsf_push"
1128  [(set (match_operand:SF 0 "push_operand" "=<,<,<,<")
1129	(match_operand:SF 1 "general_operand" "rF,f,m,m"))
1130   (clobber (match_scratch:SI 2 "=X,X,r,X"))]
1131  ""
1132  "*
1133{
1134  if (STACK_REG_P (operands[1]))
1135    {
1136      rtx xops[3];
1137
1138      if (! STACK_TOP_P (operands[1]))
1139        abort ();
1140
1141      xops[0] = AT_SP (SFmode);
1142      xops[1] = GEN_INT (4);
1143      xops[2] = stack_pointer_rtx;
1144
1145      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1146
1147      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1148        output_asm_insn (AS1 (fstp%S0,%0), xops);
1149      else
1150        output_asm_insn (AS1 (fst%S0,%0), xops);
1151      RET;
1152    }
1153
1154  else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG)
1155    return AS1 (push%L1,%1);
1156
1157  else
1158    {
1159      output_asm_insn (AS2 (mov%L2,%1,%2), operands);
1160      return AS1 (push%L2,%2);
1161    }
1162}")
1163
1164;; Special memory<->memory pattern that combine will recreate from the
1165;; moves to pseudos.
1166(define_insn "movsf_mem"
1167  [(set (match_operand:SF 0 "memory_operand" "=m")
1168	(match_operand:SF 1 "memory_operand" "m"))
1169   (clobber (match_scratch:SI 2 "=&r"))]
1170  ""
1171  "*
1172{
1173  output_asm_insn (AS2 (mov%L2,%1,%2), operands);
1174  return AS2 (mov%L0,%2,%0);
1175}")
1176
1177;; For the purposes of regclass, prefer FLOAT_REGS.
1178(define_insn "movsf_normal"
1179  [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm")
1180	(match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))]
1181  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1182  "*
1183{
1184  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1185
1186  /* First handle a `pop' insn or a `fld %st(0)' */
1187
1188  if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
1189    {
1190      if (stack_top_dies)
1191	return AS1 (fstp,%y0);
1192      else
1193        return AS1 (fld,%y0);
1194    }
1195
1196  /* Handle a transfer between the 387 and a 386 register */
1197
1198  if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
1199    {
1200      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1201      RET;
1202    }
1203
1204  if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
1205    {
1206      output_to_reg (operands[0], stack_top_dies);
1207      RET;
1208    }
1209
1210  /* Handle other kinds of writes from the 387 */
1211
1212  if (STACK_TOP_P (operands[1]))
1213    {
1214      if (stack_top_dies)
1215	return AS1 (fstp%z0,%y0);
1216      else
1217        return AS1 (fst%z0,%y0);
1218    }
1219
1220  /* Handle other kinds of reads to the 387 */
1221
1222  if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
1223    return output_move_const_single (operands);
1224
1225  if (STACK_TOP_P (operands[0]))
1226    return AS1 (fld%z1,%y1);
1227
1228  /* Handle all SFmode moves not involving the 387 */
1229
1230  return singlemove_string (operands);
1231}")
1232
1233(define_insn "swapsf"
1234  [(set (match_operand:SF 0 "register_operand" "f")
1235	(match_operand:SF 1 "register_operand" "f"))
1236   (set (match_dup 1)
1237	(match_dup 0))]
1238  ""
1239  "*
1240{
1241  if (STACK_TOP_P (operands[0]))
1242    return AS1 (fxch,%1);
1243  else
1244    return AS1 (fxch,%0);
1245}")
1246
1247(define_expand "movdf"
1248  [(set (match_operand:DF 0 "general_operand" "")
1249	(match_operand:DF 1 "general_operand" ""))]
1250  ""
1251  "
1252{
1253  /* Special case memory->memory moves and pushes */
1254  if (TARGET_MOVE
1255      && (reload_in_progress | reload_completed) == 0
1256      && GET_CODE (operands[0]) == MEM
1257      && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode)))
1258    {
1259      rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode))
1260						? gen_movdf_push
1261						: gen_movdf_mem;
1262
1263      emit_insn ((*genfunc) (operands[0], operands[1]));
1264      DONE;
1265    }
1266
1267  /* If we are loading a floating point constant that isn't 0 or 1 into a register,
1268     indicate we need the pic register loaded.  This could be optimized into stores
1269     of constants if the target eventually moves to memory, but better safe than
1270     sorry.  */
1271  if (flag_pic
1272      && GET_CODE (operands[0]) != MEM
1273      && GET_CODE (operands[1]) == CONST_DOUBLE
1274      && !standard_80387_constant_p (operands[1]))
1275    {
1276      current_function_uses_pic_offset_table = 1;
1277    }
1278}")
1279
1280(define_insn "movdf_push_nomove"
1281  [(set (match_operand:DF 0 "push_operand" "=<,<")
1282	(match_operand:DF 1 "general_operand" "gF,f"))]
1283  "!TARGET_MOVE"
1284  "*
1285{
1286  if (STACK_REG_P (operands[1]))
1287    {
1288      rtx xops[3];
1289
1290      xops[0] = AT_SP (SFmode);
1291      xops[1] = GEN_INT (8);
1292      xops[2] = stack_pointer_rtx;
1293
1294      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1295
1296      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1297        output_asm_insn (AS1 (fstp%Q0,%0), xops);
1298      else
1299        output_asm_insn (AS1 (fst%Q0,%0), xops);
1300
1301      RET;
1302    }
1303  else
1304    return output_move_double (operands);
1305}")
1306
1307(define_insn "movdf_push"
1308  [(set (match_operand:DF 0 "push_operand" "=<,<,<,<,<")
1309	(match_operand:DF 1 "general_operand" "rF,f,o,o,o"))
1310   (clobber (match_scratch:SI 2 "=X,X,&r,&r,X"))
1311   (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))]
1312  ""
1313  "*
1314{
1315  if (STACK_REG_P (operands[1]))
1316    {
1317      rtx xops[3];
1318
1319      xops[0] = AT_SP (SFmode);
1320      xops[1] = GEN_INT (8);
1321      xops[2] = stack_pointer_rtx;
1322
1323      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1324
1325      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1326        output_asm_insn (AS1 (fstp%Q0,%0), xops);
1327      else
1328        output_asm_insn (AS1 (fst%Q0,%0), xops);
1329
1330      RET;
1331    }
1332
1333  else if (GET_CODE (operands[1]) != MEM)
1334    return output_move_double (operands);
1335
1336  else
1337    return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);
1338}")
1339
1340(define_insn "movdf_mem"
1341  [(set (match_operand:DF 0 "memory_operand" "=o,o")
1342	(match_operand:DF 1 "memory_operand" "o,o"))
1343   (clobber (match_scratch:SI 2 "=&r,&r"))
1344   (clobber (match_scratch:SI 3 "=&r,X"))]
1345  ""
1346  "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);")
1347
1348;; For the purposes of regclass, prefer FLOAT_REGS.
1349(define_insn "movdf_normal"
1350  [(set (match_operand:DF 0 "general_operand" "=f,fm,!*rf,!*rm")
1351	(match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
1352  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1353  "*
1354{
1355  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1356
1357  /* First handle a `pop' insn or a `fld %st(0)' */
1358
1359  if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
1360    {
1361      if (stack_top_dies)
1362	return AS1 (fstp,%y0);
1363      else
1364        return AS1 (fld,%y0);
1365    }
1366
1367  /* Handle a transfer between the 387 and a 386 register */
1368
1369  if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
1370    {
1371      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1372      RET;
1373    }
1374
1375  if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
1376    {
1377      output_to_reg (operands[0], stack_top_dies);
1378      RET;
1379    }
1380
1381  /* Handle other kinds of writes from the 387 */
1382
1383  if (STACK_TOP_P (operands[1]))
1384    {
1385      if (stack_top_dies)
1386	return AS1 (fstp%z0,%y0);
1387      else
1388        return AS1 (fst%z0,%y0);
1389    }
1390
1391  /* Handle other kinds of reads to the 387 */
1392
1393  if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
1394    return output_move_const_single (operands);
1395
1396  if (STACK_TOP_P (operands[0]))
1397    return AS1 (fld%z1,%y1);
1398
1399  /* Handle all DFmode moves not involving the 387 */
1400
1401  return output_move_double (operands);
1402}")
1403
1404(define_insn "swapdf"
1405  [(set (match_operand:DF 0 "register_operand" "f")
1406	(match_operand:DF 1 "register_operand" "f"))
1407   (set (match_dup 1)
1408	(match_dup 0))]
1409  ""
1410  "*
1411{
1412  if (STACK_TOP_P (operands[0]))
1413    return AS1 (fxch,%1);
1414  else
1415    return AS1 (fxch,%0);
1416}")
1417
1418(define_expand "movxf"
1419  [(set (match_operand:XF 0 "general_operand" "")
1420	(match_operand:XF 1 "general_operand" ""))]
1421  ""
1422  "
1423{
1424  /* Special case memory->memory moves and pushes */
1425  if (TARGET_MOVE
1426      && (reload_in_progress | reload_completed) == 0
1427      && GET_CODE (operands[0]) == MEM
1428      && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], XFmode)))
1429    {
1430      rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], XFmode))
1431						? gen_movxf_push
1432						: gen_movxf_mem;
1433
1434      emit_insn ((*genfunc) (operands[0], operands[1]));
1435      DONE;
1436    }
1437
1438  /* If we are loading a floating point constant that isn't 0 or 1 into a register,
1439     indicate we need the pic register loaded.  This could be optimized into stores
1440     of constants if the target eventually moves to memory, but better safe than
1441     sorry.  */
1442  if (flag_pic
1443      && GET_CODE (operands[0]) != MEM
1444      && GET_CODE (operands[1]) == CONST_DOUBLE
1445      && !standard_80387_constant_p (operands[1]))
1446    {
1447      current_function_uses_pic_offset_table = 1;
1448    }
1449}")
1450
1451
1452(define_insn "movxf_push_nomove"
1453  [(set (match_operand:XF 0 "push_operand" "=<,<")
1454 	(match_operand:XF 1 "general_operand" "gF,f"))]
1455  "!TARGET_MOVE"
1456  "*
1457{
1458  if (STACK_REG_P (operands[1]))
1459    {
1460      rtx xops[3];
1461
1462      xops[0] = AT_SP (SFmode);
1463      xops[1] = GEN_INT (12);
1464      xops[2] = stack_pointer_rtx;
1465
1466      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1467      output_asm_insn (AS1 (fstp%T0,%0), xops);
1468      if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1469	output_asm_insn (AS1 (fld%T0,%0), xops);
1470
1471      RET;
1472    }
1473  else
1474    return output_move_double (operands);
1475 }")
1476
1477(define_insn "movxf_push"
1478  [(set (match_operand:XF 0 "push_operand" "=<,<,<,<,<")
1479 	(match_operand:XF 1 "general_operand" "rF,f,o,o,o"))
1480   (clobber (match_scratch:SI 2 "=X,X,&r,&r,X"))
1481   (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))]
1482  ""
1483  "*
1484{
1485  if (STACK_REG_P (operands[1]))
1486    {
1487      rtx xops[3];
1488
1489      xops[0] = AT_SP (SFmode);
1490      xops[1] = GEN_INT (12);
1491      xops[2] = stack_pointer_rtx;
1492
1493      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1494      output_asm_insn (AS1 (fstp%T0,%0), xops);
1495      if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1496	output_asm_insn (AS1 (fld%T0,%0), xops);
1497
1498      RET;
1499    }
1500
1501  else if (GET_CODE (operands[1]) != MEM
1502	   || GET_CODE (operands[2]) != REG)
1503    return output_move_double (operands);
1504
1505  else
1506    return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);
1507}")
1508
1509(define_insn "movxf_mem"
1510  [(set (match_operand:XF 0 "memory_operand" "=o,o")
1511	(match_operand:XF 1 "memory_operand" "o,o"))
1512   (clobber (match_scratch:SI 2 "=&r,&r"))
1513   (clobber (match_scratch:SI 3 "=&r,X"))]
1514  ""
1515  "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);")
1516
1517(define_insn "movxf_normal"
1518  [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm")
1519	(match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
1520  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1521  "*
1522{
1523  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1524
1525  /* First handle a `pop' insn or a `fld %st(0)' */
1526
1527  if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
1528    {
1529      if (stack_top_dies)
1530	return AS1 (fstp,%y0);
1531      else
1532        return AS1 (fld,%y0);
1533    }
1534
1535  /* Handle a transfer between the 387 and a 386 register */
1536
1537  if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
1538    {
1539      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1540      RET;
1541    }
1542
1543  if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
1544    {
1545      output_to_reg (operands[0], stack_top_dies);
1546      RET;
1547    }
1548
1549  /* Handle other kinds of writes from the 387 */
1550
1551  if (STACK_TOP_P (operands[1]))
1552    {
1553      output_asm_insn (AS1 (fstp%z0,%y0), operands);
1554      if (! stack_top_dies)
1555	return AS1 (fld%z0,%y0);
1556
1557      RET;
1558    }
1559
1560  /* Handle other kinds of reads to the 387 */
1561
1562  if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
1563    return output_move_const_single (operands);
1564
1565  if (STACK_TOP_P (operands[0]))
1566       return AS1 (fld%z1,%y1);
1567
1568  /* Handle all XFmode moves not involving the 387 */
1569
1570  return output_move_double (operands);
1571}")
1572
1573(define_insn "swapxf"
1574  [(set (match_operand:XF 0 "register_operand" "f")
1575	(match_operand:XF 1 "register_operand" "f"))
1576   (set (match_dup 1)
1577	(match_dup 0))]
1578  ""
1579  "*
1580{
1581  if (STACK_TOP_P (operands[0]))
1582    return AS1 (fxch,%1);
1583  else
1584    return AS1 (fxch,%0);
1585}")
1586
1587(define_insn ""
1588  [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
1589	(match_operand:DI 1 "general_operand" "riF,o,o,o"))
1590   (clobber (match_scratch:SI 2 "=X,&r,&r,X"))
1591   (clobber (match_scratch:SI 3 "=X,&r,X,X"))]
1592  ""
1593  "*
1594{
1595  if (GET_CODE (operands[1]) != MEM)
1596    return output_move_double (operands);
1597
1598  else
1599    return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
1600}")
1601
1602(define_insn "movdi"
1603  [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm")
1604	(match_operand:DI 1 "general_operand" "o,o,m,riF"))
1605   (clobber (match_scratch:SI 2 "=&r,&r,X,X"))
1606   (clobber (match_scratch:SI 3 "=&r,X,X,X"))]
1607  ""
1608  "*
1609{
1610  rtx low[2], high[2], xop[6];
1611
1612  if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
1613    return output_move_double (operands);
1614  else
1615    return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
1616}")
1617
1618
1619;;- conversion instructions
1620;;- NONE
1621
1622;;- zero extension instructions
1623;; See comments by `andsi' for when andl is faster than movzx.
1624
1625(define_insn "zero_extendhisi2"
1626  [(set (match_operand:SI 0 "general_operand" "=r")
1627	(zero_extend:SI
1628	 (match_operand:HI 1 "nonimmediate_operand" "rm")))]
1629  ""
1630  "*
1631{
1632  if ((!TARGET_386 || REGNO (operands[0]) == 0)
1633      && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
1634    {
1635      rtx xops[2];
1636      xops[0] = operands[0];
1637      xops[1] = GEN_INT (0xffff);
1638      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1639      RET;
1640    }
1641
1642#ifdef INTEL_SYNTAX
1643  return AS2 (movzx,%1,%0);
1644#else
1645  return AS2 (movz%W0%L0,%1,%0);
1646#endif
1647}")
1648
1649(define_insn "zero_extendqihi2"
1650  [(set (match_operand:HI 0 "general_operand" "=r")
1651	(zero_extend:HI
1652	 (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1653  ""
1654  "*
1655{
1656  if ((!TARGET_386 || REGNO (operands[0]) == 0)
1657      && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
1658    {
1659      rtx xops[2];
1660      xops[0] = operands[0];
1661      xops[1] = GEN_INT (0xff);
1662      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1663      RET;
1664    }
1665
1666#ifdef INTEL_SYNTAX
1667  return AS2 (movzx,%1,%0);
1668#else
1669  return AS2 (movz%B0%W0,%1,%0);
1670#endif
1671}")
1672
1673(define_insn "zero_extendqisi2"
1674  [(set (match_operand:SI 0 "general_operand" "=r")
1675	(zero_extend:SI
1676	 (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1677  ""
1678  "*
1679{
1680  if ((!TARGET_386 || REGNO (operands[0]) == 0)
1681      && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
1682    {
1683      rtx xops[2];
1684      xops[0] = operands[0];
1685      xops[1] = GEN_INT (0xff);
1686      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1687      RET;
1688    }
1689
1690#ifdef INTEL_SYNTAX
1691  return AS2 (movzx,%1,%0);
1692#else
1693  return AS2 (movz%B0%L0,%1,%0);
1694#endif
1695}")
1696
1697(define_insn "zero_extendsidi2"
1698  [(set (match_operand:DI 0 "register_operand" "=r")
1699	(zero_extend:DI
1700	 (match_operand:SI 1 "register_operand" "0")))]
1701  ""
1702  "*
1703{
1704  operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1705  return AS2 (xor%L0,%0,%0);
1706}")
1707
1708;;- sign extension instructions
1709
1710(define_insn "extendsidi2"
1711  [(set (match_operand:DI 0 "register_operand" "=r")
1712	(sign_extend:DI
1713	 (match_operand:SI 1 "register_operand" "0")))]
1714  ""
1715  "*
1716{
1717  if (REGNO (operands[0]) == 0)
1718    {
1719      /* This used to be cwtl, but that extends HI to SI somehow.  */
1720#ifdef INTEL_SYNTAX
1721      return \"cdq\";
1722#else
1723      return \"cltd\";
1724#endif
1725    }
1726
1727  operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1728  output_asm_insn (AS2 (mov%L0,%0,%1), operands);
1729
1730  operands[0] = GEN_INT (31);
1731  return AS2 (sar%L1,%0,%1);
1732}")
1733
1734;; Note that the i386 programmers' manual says that the opcodes
1735;; are named movsx..., but the assembler on Unix does not accept that.
1736;; We use what the Unix assembler expects.
1737
1738(define_insn "extendhisi2"
1739  [(set (match_operand:SI 0 "general_operand" "=r")
1740	(sign_extend:SI
1741	 (match_operand:HI 1 "nonimmediate_operand" "rm")))]
1742  ""
1743  "*
1744{
1745  if (REGNO (operands[0]) == 0
1746      && REG_P (operands[1]) && REGNO (operands[1]) == 0)
1747#ifdef INTEL_SYNTAX
1748    return \"cwde\";
1749#else
1750    return \"cwtl\";
1751#endif
1752
1753#ifdef INTEL_SYNTAX
1754  return AS2 (movsx,%1,%0);
1755#else
1756  return AS2 (movs%W0%L0,%1,%0);
1757#endif
1758}")
1759
1760(define_insn "extendqihi2"
1761  [(set (match_operand:HI 0 "general_operand" "=r")
1762	(sign_extend:HI
1763	 (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1764  ""
1765  "*
1766{
1767  if (REGNO (operands[0]) == 0
1768      && REG_P (operands[1]) && REGNO (operands[1]) == 0)
1769    return \"cbtw\";
1770
1771#ifdef INTEL_SYNTAX
1772  return AS2 (movsx,%1,%0);
1773#else
1774  return AS2 (movs%B0%W0,%1,%0);
1775#endif
1776}")
1777
1778(define_insn "extendqisi2"
1779  [(set (match_operand:SI 0 "general_operand" "=r")
1780	(sign_extend:SI
1781	 (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1782  ""
1783  "*
1784{
1785#ifdef INTEL_SYNTAX
1786  return AS2 (movsx,%1,%0);
1787#else
1788  return AS2 (movs%B0%L0,%1,%0);
1789#endif
1790}")
1791
1792;; Conversions between float and double.
1793
1794(define_insn "extendsfdf2"
1795  [(set (match_operand:DF 0 "general_operand" "=fm,f")
1796	(float_extend:DF
1797	 (match_operand:SF 1 "general_operand" "f,fm")))]
1798  "TARGET_80387"
1799  "*
1800{
1801  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1802
1803  if (NON_STACK_REG_P (operands[1]))
1804    {
1805      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1806      RET;
1807    }
1808
1809  if (NON_STACK_REG_P (operands[0]))
1810    {
1811      output_to_reg (operands[0], stack_top_dies);
1812      RET;
1813    }
1814
1815  if (STACK_TOP_P (operands[0]))
1816    return AS1 (fld%z1,%y1);
1817
1818  if (GET_CODE (operands[0]) == MEM)
1819    {
1820      if (stack_top_dies)
1821	return AS1 (fstp%z0,%y0);
1822      else
1823        return AS1 (fst%z0,%y0);
1824    }
1825
1826  abort ();
1827}")
1828
1829(define_insn "extenddfxf2"
1830  [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r")
1831	(float_extend:XF
1832	 (match_operand:DF 1 "general_operand" "f,fm,!*r,f")))]
1833  "TARGET_80387"
1834  "*
1835{
1836  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1837
1838  if (NON_STACK_REG_P (operands[1]))
1839    {
1840      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1841      RET;
1842    }
1843
1844  if (NON_STACK_REG_P (operands[0]))
1845    {
1846      output_to_reg (operands[0], stack_top_dies);
1847      RET;
1848    }
1849
1850  if (STACK_TOP_P (operands[0]))
1851    return AS1 (fld%z1,%y1);
1852
1853  if (GET_CODE (operands[0]) == MEM)
1854    {
1855      output_asm_insn (AS1 (fstp%z0,%y0), operands);
1856      if (! stack_top_dies)
1857	return AS1 (fld%z0,%y0);
1858      RET;
1859    }
1860
1861  abort ();
1862}")
1863
1864(define_insn "extendsfxf2"
1865  [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r")
1866	(float_extend:XF
1867	 (match_operand:SF 1 "general_operand" "f,fm,!*r,f")))]
1868  "TARGET_80387"
1869  "*
1870{
1871  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1872
1873  if (NON_STACK_REG_P (operands[1]))
1874    {
1875      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1876      RET;
1877    }
1878
1879  if (NON_STACK_REG_P (operands[0]))
1880    {
1881      output_to_reg (operands[0], stack_top_dies);
1882      RET;
1883    }
1884
1885  if (STACK_TOP_P (operands[0]))
1886    return AS1 (fld%z1,%y1);
1887
1888  if (GET_CODE (operands[0]) == MEM)
1889    {
1890      output_asm_insn (AS1 (fstp%z0,%y0), operands);
1891      if (! stack_top_dies)
1892	return AS1 (fld%z0,%y0);
1893      RET;
1894    }
1895
1896  abort ();
1897}")
1898
1899(define_expand "truncdfsf2"
1900  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
1901		   (float_truncate:SF
1902		    (match_operand:DF 1 "register_operand" "")))
1903	      (clobber (match_dup 2))])]
1904  "TARGET_80387"
1905  "
1906{
1907  operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
1908}")
1909
1910;; This cannot output into an f-reg because there is no way to be sure
1911;; of truncating in that case.  Otherwise this is just like a simple move
1912;; insn.  So we pretend we can output to a reg in order to get better
1913;; register preferencing, but we really use a stack slot.
1914
1915(define_insn ""
1916  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m")
1917	(float_truncate:SF
1918	 (match_operand:DF 1 "register_operand" "0,f")))
1919   (clobber (match_operand:SF 2 "memory_operand" "m,m"))]
1920  "TARGET_80387"
1921  "*
1922{
1923  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1924
1925  if (GET_CODE (operands[0]) == MEM)
1926    {
1927      if (stack_top_dies)
1928	return AS1 (fstp%z0,%0);
1929      else
1930        return AS1 (fst%z0,%0);
1931    }
1932  else if (STACK_TOP_P (operands[0]))
1933    {
1934      output_asm_insn (AS1 (fstp%z2,%y2), operands);
1935      return AS1 (fld%z2,%y2);
1936    }
1937  else
1938    abort ();
1939}")
1940
1941(define_insn "truncxfsf2"
1942  [(set (match_operand:SF 0 "general_operand" "=m,!*r")
1943	(float_truncate:SF
1944	 (match_operand:XF 1 "register_operand" "f,f")))]
1945  "TARGET_80387"
1946  "*
1947{
1948  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1949
1950  if (NON_STACK_REG_P (operands[0]))
1951    {
1952      if (stack_top_dies == 0)
1953	{
1954	  output_asm_insn (AS1 (fld,%y1), operands);
1955	  stack_top_dies = 1;
1956	}
1957      output_to_reg (operands[0], stack_top_dies);
1958      RET;
1959    }
1960  else if (GET_CODE (operands[0]) == MEM)
1961    {
1962      if (stack_top_dies)
1963	return AS1 (fstp%z0,%0);
1964      else
1965	{
1966	  output_asm_insn (AS1 (fld,%y1), operands);
1967	  return AS1 (fstp%z0,%0);
1968	}
1969    }
1970  else
1971    abort ();
1972}")
1973
1974(define_insn "truncxfdf2"
1975  [(set (match_operand:DF 0 "general_operand" "=m,!*r")
1976	(float_truncate:DF
1977	 (match_operand:XF 1 "register_operand" "f,f")))]
1978  "TARGET_80387"
1979  "*
1980{
1981  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1982
1983  if (NON_STACK_REG_P (operands[0]))
1984    {
1985      if (stack_top_dies == 0)
1986	{
1987	  output_asm_insn (AS1 (fld,%y1), operands);
1988	  stack_top_dies = 1;
1989	}
1990      output_to_reg (operands[0], stack_top_dies);
1991      RET;
1992    }
1993  else if (GET_CODE (operands[0]) == MEM)
1994    {
1995      if (stack_top_dies)
1996	return AS1 (fstp%z0,%0);
1997      else
1998	{
1999	  output_asm_insn (AS1 (fld,%y1), operands);
2000	  return AS1 (fstp%z0,%0);
2001	}
2002    }
2003  else
2004    abort ();
2005}")
2006
2007
2008;; The 387 requires that the stack top dies after converting to DImode.
2009
2010;; Represent an unsigned conversion from SImode to MODE_FLOAT by first
2011;; doing a signed conversion to DImode, and then taking just the low
2012;; part.
2013
2014(define_expand "fixuns_truncxfsi2"
2015  [(set (match_dup 4)
2016	(match_operand:XF 1 "register_operand" ""))
2017   (parallel [(set (match_dup 2)
2018		   (fix:DI (fix:XF (match_dup 4))))
2019	      (clobber (match_dup 4))
2020	      (clobber (match_dup 5))
2021	      (clobber (match_dup 6))
2022	      (clobber (match_scratch:SI 7 ""))])
2023   (set (match_operand:SI 0 "general_operand" "")
2024	(match_dup 3))]
2025  "TARGET_80387"
2026  "
2027{
2028  operands[2] = gen_reg_rtx (DImode);
2029  operands[3] = gen_lowpart (SImode, operands[2]);
2030  operands[4] = gen_reg_rtx (XFmode);
2031  operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2032  operands[6] = (rtx) assign_386_stack_local (SImode, 1);
2033}")
2034
2035(define_expand "fixuns_truncdfsi2"
2036  [(set (match_dup 4)
2037	(match_operand:DF 1 "register_operand" ""))
2038   (parallel [(set (match_dup 2)
2039		   (fix:DI (fix:DF (match_dup 4))))
2040	      (clobber (match_dup 4))
2041	      (clobber (match_dup 5))
2042	      (clobber (match_dup 6))
2043	      (clobber (match_scratch:SI 7 ""))])
2044   (set (match_operand:SI 0 "general_operand" "")
2045	(match_dup 3))]
2046  "TARGET_80387"
2047  "
2048{
2049  operands[2] = gen_reg_rtx (DImode);
2050  operands[3] = gen_lowpart (SImode, operands[2]);
2051  operands[4] = gen_reg_rtx (DFmode);
2052  operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2053  operands[6] = (rtx) assign_386_stack_local (SImode, 1);
2054}")
2055
2056(define_expand "fixuns_truncsfsi2"
2057  [(set (match_dup 4)
2058	(match_operand:SF 1 "register_operand" ""))
2059   (parallel [(set (match_dup 2)
2060		   (fix:DI (fix:SF (match_dup 4))))
2061	      (clobber (match_dup 4))
2062	      (clobber (match_dup 5))
2063	      (clobber (match_dup 6))
2064	      (clobber (match_scratch:SI 7 ""))])
2065   (set (match_operand:SI 0 "general_operand" "")
2066	(match_dup 3))]
2067  "TARGET_80387"
2068  "
2069{
2070  operands[2] = gen_reg_rtx (DImode);
2071  operands[3] = gen_lowpart (SImode, operands[2]);
2072  operands[4] = gen_reg_rtx (SFmode);
2073  operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2074  operands[6] = (rtx) assign_386_stack_local (SImode, 1);
2075}")
2076
2077;; Signed conversion to DImode.
2078
2079(define_expand "fix_truncxfdi2"
2080  [(set (match_dup 2)
2081	(match_operand:XF 1 "register_operand" ""))
2082   (parallel [(set (match_operand:DI 0 "general_operand" "")
2083		   (fix:DI (fix:XF (match_dup 2))))
2084	      (clobber (match_dup 2))
2085	      (clobber (match_dup 3))
2086	      (clobber (match_dup 4))
2087	      (clobber (match_scratch:SI 5 ""))])]
2088  "TARGET_80387"
2089  "
2090{
2091  operands[1] = copy_to_mode_reg (XFmode, operands[1]);
2092  operands[2] = gen_reg_rtx (XFmode);
2093  operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2094  operands[4] = (rtx) assign_386_stack_local (SImode, 1);
2095}")
2096
2097(define_expand "fix_truncdfdi2"
2098  [(set (match_dup 2)
2099	(match_operand:DF 1 "register_operand" ""))
2100   (parallel [(set (match_operand:DI 0 "general_operand" "")
2101		   (fix:DI (fix:DF (match_dup 2))))
2102	      (clobber (match_dup 2))
2103	      (clobber (match_dup 3))
2104	      (clobber (match_dup 4))
2105	      (clobber (match_scratch:SI 5 ""))])]
2106  "TARGET_80387"
2107  "
2108{
2109  operands[1] = copy_to_mode_reg (DFmode, operands[1]);
2110  operands[2] = gen_reg_rtx (DFmode);
2111  operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2112  operands[4] = (rtx) assign_386_stack_local (SImode, 1);
2113}")
2114
2115(define_expand "fix_truncsfdi2"
2116  [(set (match_dup 2)
2117	(match_operand:SF 1 "register_operand" ""))
2118   (parallel [(set (match_operand:DI 0 "general_operand" "")
2119		   (fix:DI (fix:SF (match_dup 2))))
2120	      (clobber (match_dup 2))
2121	      (clobber (match_dup 3))
2122	      (clobber (match_dup 4))
2123	      (clobber (match_scratch:SI 5 ""))])]
2124  "TARGET_80387"
2125  "
2126{
2127  operands[1] = copy_to_mode_reg (SFmode, operands[1]);
2128  operands[2] = gen_reg_rtx (SFmode);
2129  operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2130  operands[4] = (rtx) assign_386_stack_local (SImode, 1);
2131}")
2132
2133;; These match a signed conversion of either DFmode or SFmode to DImode.
2134
2135(define_insn ""
2136  [(set (match_operand:DI 0 "general_operand" "=rm")
2137	(fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
2138   (clobber (match_dup 1))
2139   (clobber (match_operand:SI 2 "memory_operand" "m"))
2140   (clobber (match_operand:SI 3 "memory_operand" "m"))
2141   (clobber (match_scratch:SI 4 "=&q"))]
2142  "TARGET_80387"
2143  "* return output_fix_trunc (insn, operands);")
2144
2145(define_insn ""
2146  [(set (match_operand:DI 0 "general_operand" "=rm")
2147	(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
2148   (clobber (match_dup 1))
2149   (clobber (match_operand:SI 2 "memory_operand" "m"))
2150   (clobber (match_operand:SI 3 "memory_operand" "m"))
2151   (clobber (match_scratch:SI 4 "=&q"))]
2152  "TARGET_80387"
2153  "* return output_fix_trunc (insn, operands);")
2154
2155(define_insn ""
2156  [(set (match_operand:DI 0 "general_operand" "=rm")
2157	(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
2158   (clobber (match_dup 1))
2159   (clobber (match_operand:SI 2 "memory_operand" "m"))
2160   (clobber (match_operand:SI 3 "memory_operand" "m"))
2161   (clobber (match_scratch:SI 4 "=&q"))]
2162  "TARGET_80387"
2163  "* return output_fix_trunc (insn, operands);")
2164
2165;; Signed MODE_FLOAT conversion to SImode.
2166
2167(define_expand "fix_truncxfsi2"
2168  [(parallel [(set (match_operand:SI 0 "general_operand" "")
2169		   (fix:SI
2170		    (fix:XF (match_operand:XF 1 "register_operand" ""))))
2171	      (clobber (match_dup 2))
2172	      (clobber (match_dup 3))
2173	      (clobber (match_scratch:SI 4 ""))])]
2174  "TARGET_80387"
2175  "
2176{
2177  operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2178  operands[3] = (rtx) assign_386_stack_local (SImode, 1);
2179}")
2180
2181(define_expand "fix_truncdfsi2"
2182  [(parallel [(set (match_operand:SI 0 "general_operand" "")
2183		   (fix:SI
2184		    (fix:DF (match_operand:DF 1 "register_operand" ""))))
2185	      (clobber (match_dup 2))
2186	      (clobber (match_dup 3))
2187	      (clobber (match_scratch:SI 4 ""))])]
2188  "TARGET_80387"
2189  "
2190{
2191  operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2192  operands[3] = (rtx) assign_386_stack_local (SImode, 1);
2193}")
2194
2195(define_expand "fix_truncsfsi2"
2196  [(parallel [(set (match_operand:SI 0 "general_operand" "")
2197		   (fix:SI
2198		    (fix:SF (match_operand:SF 1 "register_operand" ""))))
2199	      (clobber (match_dup 2))
2200	      (clobber (match_dup 3))
2201	      (clobber (match_scratch:SI 4 ""))])]
2202  "TARGET_80387"
2203  "
2204{
2205  operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2206  operands[3] = (rtx) assign_386_stack_local (SImode, 1);
2207}")
2208
2209(define_insn ""
2210  [(set (match_operand:SI 0 "general_operand" "=rm")
2211	(fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
2212   (clobber (match_operand:SI 2 "memory_operand" "m"))
2213   (clobber (match_operand:SI 3 "memory_operand" "m"))
2214   (clobber (match_scratch:SI 4 "=&q"))]
2215  "TARGET_80387"
2216  "* return output_fix_trunc (insn, operands);")
2217
2218(define_insn ""
2219  [(set (match_operand:SI 0 "general_operand" "=rm")
2220	(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
2221   (clobber (match_operand:SI 2 "memory_operand" "m"))
2222   (clobber (match_operand:SI 3 "memory_operand" "m"))
2223   (clobber (match_scratch:SI 4 "=&q"))]
2224  "TARGET_80387"
2225  "* return output_fix_trunc (insn, operands);")
2226
2227(define_insn ""
2228  [(set (match_operand:SI 0 "general_operand" "=rm")
2229	(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
2230   (clobber (match_operand:SI 2 "memory_operand" "m"))
2231   (clobber (match_operand:SI 3 "memory_operand" "m"))
2232   (clobber (match_scratch:SI 4 "=&q"))]
2233  "TARGET_80387"
2234  "* return output_fix_trunc (insn, operands);")
2235
2236;; Conversion between fixed point and floating point.
2237;; The actual pattern that matches these is at the end of this file.
2238
2239;; ??? Possibly represent floatunssidf2 here in gcc2.
2240
2241(define_expand "floatsisf2"
2242  [(set (match_operand:SF 0 "register_operand" "")
2243	(float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
2244  "TARGET_80387"
2245  "")
2246
2247(define_expand "floatdisf2"
2248  [(set (match_operand:SF 0 "register_operand" "")
2249	(float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
2250  "TARGET_80387"
2251  "")
2252
2253(define_expand "floatsidf2"
2254  [(set (match_operand:DF 0 "register_operand" "")
2255	(float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
2256  "TARGET_80387"
2257  "")
2258
2259(define_expand "floatdidf2"
2260  [(set (match_operand:DF 0 "register_operand" "")
2261	(float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
2262  "TARGET_80387"
2263  "")
2264
2265(define_expand "floatsixf2"
2266  [(set (match_operand:XF 0 "register_operand" "")
2267	(float:XF (match_operand:SI 1 "nonimmediate_operand" "")))]
2268  "TARGET_80387"
2269  "")
2270
2271(define_expand "floatdixf2"
2272  [(set (match_operand:XF 0 "register_operand" "")
2273	(float:XF (match_operand:DI 1 "nonimmediate_operand" "")))]
2274  "TARGET_80387"
2275  "")
2276
2277;; This will convert from SImode or DImode to MODE_FLOAT.
2278
2279(define_insn ""
2280  [(set (match_operand:XF 0 "register_operand" "=f")
2281	(float:XF (match_operand:DI 1 "general_operand" "rm")))]
2282  "TARGET_80387"
2283  "*
2284{
2285  if (NON_STACK_REG_P (operands[1]))
2286    {
2287      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2288      RET;
2289    }
2290  else if (GET_CODE (operands[1]) == MEM)
2291    return AS1 (fild%z1,%1);
2292  else
2293    abort ();
2294}")
2295
2296(define_insn ""
2297  [(set (match_operand:DF 0 "register_operand" "=f")
2298	(float:DF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2299  "TARGET_80387"
2300  "*
2301{
2302  if (NON_STACK_REG_P (operands[1]))
2303    {
2304      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2305      RET;
2306    }
2307  else if (GET_CODE (operands[1]) == MEM)
2308    return AS1 (fild%z1,%1);
2309  else
2310    abort ();
2311}")
2312
2313(define_insn ""
2314  [(set (match_operand:SF 0 "register_operand" "=f")
2315	(float:SF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2316  "TARGET_80387"
2317  "*
2318{
2319  if (NON_STACK_REG_P (operands[1]))
2320    {
2321      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2322      RET;
2323    }
2324  else if (GET_CODE (operands[1]) == MEM)
2325    return AS1 (fild%z1,%1);
2326  else
2327    abort ();
2328}")
2329
2330(define_insn ""
2331  [(set (match_operand:DF 0 "register_operand" "=f")
2332	(float:DF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
2333  "TARGET_80387"
2334  "*
2335{
2336  if (NON_STACK_REG_P (operands[1]))
2337    {
2338      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2339      RET;
2340    }
2341  else if (GET_CODE (operands[1]) == MEM)
2342    return AS1 (fild%z1,%1);
2343  else
2344    abort ();
2345}")
2346
2347(define_insn ""
2348  [(set (match_operand:XF 0 "register_operand" "=f,f")
2349	(float:XF (match_operand:SI 1 "general_operand" "m,!*r")))]
2350  "TARGET_80387"
2351  "*
2352{
2353  if (NON_STACK_REG_P (operands[1]))
2354    {
2355      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2356      RET;
2357    }
2358  else if (GET_CODE (operands[1]) == MEM)
2359    return AS1 (fild%z1,%1);
2360  else
2361    abort ();
2362}")
2363
2364(define_insn ""
2365  [(set (match_operand:SF 0 "register_operand" "=f")
2366	(float:SF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
2367  "TARGET_80387"
2368  "*
2369{
2370  if (NON_STACK_REG_P (operands[1]))
2371    {
2372      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2373      RET;
2374    }
2375  else if (GET_CODE (operands[1]) == MEM)
2376    return AS1 (fild%z1,%1);
2377  else
2378    abort ();
2379}")
2380
2381;;- add instructions
2382
2383(define_insn "adddi3"
2384  [(set (match_operand:DI 0 "general_operand" "=&r,ro,o,&r,ro,o,&r,o,o,o")
2385	(plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,o,riF,o,or,riF,riF,o")
2386		 (match_operand:DI 2 "general_operand" "o,riF,o,0,0,0,oriF,riF,o,o")))
2387   (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r,X,&r,&r,&r"))]
2388  ""
2389  "*
2390{
2391  rtx low[3], high[3], xops[7], temp;
2392
2393  CC_STATUS_INIT;
2394
2395  if (rtx_equal_p (operands[0], operands[2]))
2396    {
2397      temp = operands[1];
2398      operands[1] = operands[2];
2399      operands[2] = temp;
2400    }
2401
2402  split_di (operands, 3, low, high);
2403  if (!rtx_equal_p (operands[0], operands[1]))
2404    {
2405      xops[0] = high[0];
2406      xops[1] = low[0];
2407      xops[2] = high[1];
2408      xops[3] = low[1];
2409
2410      if (GET_CODE (operands[0]) != MEM)
2411	{
2412	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2413	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2414	}
2415      else
2416	{
2417	  xops[4] = high[2];
2418	  xops[5] = low[2];
2419	  xops[6] = operands[3];
2420	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2421	  output_asm_insn (AS2 (add%L6,%5,%6), xops);
2422	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2423	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2424	  output_asm_insn (AS2 (adc%L6,%4,%6), xops);
2425	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2426	  RET;
2427	}
2428    }
2429
2430  if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
2431    {
2432      xops[0] = high[0];
2433      xops[1] = low[0];
2434      xops[2] = high[2];
2435      xops[3] = low[2];
2436      xops[4] = operands[3];
2437
2438      output_asm_insn (AS2 (mov%L4,%3,%4), xops);
2439      output_asm_insn (AS2 (add%L1,%4,%1), xops);
2440      output_asm_insn (AS2 (mov%L4,%2,%4), xops);
2441      output_asm_insn (AS2 (adc%L0,%4,%0), xops);
2442    }
2443
2444  else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
2445    {
2446      output_asm_insn (AS2 (add%L0,%2,%0), low);
2447      output_asm_insn (AS2 (adc%L0,%2,%0), high);
2448    }
2449
2450  else
2451    output_asm_insn (AS2 (add%L0,%2,%0), high);
2452
2453  RET;
2454}")
2455
2456;; On a 486, it is faster to do movl/addl than to do a single leal if
2457;; operands[1] and operands[2] are both registers.
2458
2459(define_insn "addsi3"
2460  [(set (match_operand:SI 0 "general_operand" "=?r,rm,r")
2461	(plus:SI (match_operand:SI 1 "general_operand" "%r,0,0")
2462		 (match_operand:SI 2 "general_operand" "ri,ri,rm")))]
2463  ""
2464  "*
2465{
2466  if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
2467    {
2468      if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
2469	return AS2 (add%L0,%1,%0);
2470
2471      if (operands[2] == stack_pointer_rtx)
2472	{
2473	  rtx temp;
2474
2475	  temp = operands[1];
2476	  operands[1] = operands[2];
2477	  operands[2] = temp;
2478	}
2479
2480      if (operands[2] != stack_pointer_rtx)
2481	{
2482	  CC_STATUS_INIT;
2483	  operands[1] = SET_SRC (PATTERN (insn));
2484	  return AS2 (lea%L0,%a1,%0);
2485	}
2486
2487      output_asm_insn (AS2 (mov%L0,%1,%0), operands);
2488    }
2489
2490  if (operands[2] == const1_rtx)
2491    return AS1 (inc%L0,%0);
2492
2493  if (operands[2] == constm1_rtx)
2494    return AS1 (dec%L0,%0);
2495
2496  return AS2 (add%L0,%2,%0);
2497}")
2498
2499;; ??? `lea' here, for three operand add?  If leaw is used, only %bx,
2500;; %si and %di can appear in SET_SRC, and output_asm_insn might not be
2501;; able to handle the operand.  But leal always works?
2502
2503(define_insn "addhi3"
2504  [(set (match_operand:HI 0 "general_operand" "=rm,r")
2505	(plus:HI (match_operand:HI 1 "general_operand" "%0,0")
2506		 (match_operand:HI 2 "general_operand" "ri,rm")))]
2507  ""
2508  "*
2509{
2510  /* ??? what about offsettable memory references? */
2511  if (QI_REG_P (operands[0])
2512      && GET_CODE (operands[2]) == CONST_INT
2513      && (INTVAL (operands[2]) & 0xff) == 0)
2514    {
2515      int byteval = (INTVAL (operands[2]) >> 8) & 0xff;
2516      CC_STATUS_INIT;
2517
2518      if (byteval == 1)
2519	return AS1 (inc%B0,%h0);
2520      else if (byteval == 255)
2521	return AS1 (dec%B0,%h0);
2522
2523      operands[2] = GEN_INT (byteval);
2524      return AS2 (add%B0,%2,%h0);
2525    }
2526
2527  if (operands[2] == const1_rtx)
2528    return AS1 (inc%W0,%0);
2529
2530  if (operands[2] == constm1_rtx
2531      || (GET_CODE (operands[2]) == CONST_INT
2532	  && INTVAL (operands[2]) == 65535))
2533    return AS1 (dec%W0,%0);
2534
2535  return AS2 (add%W0,%2,%0);
2536}")
2537
2538(define_insn "addqi3"
2539  [(set (match_operand:QI 0 "general_operand" "=qm,q")
2540	(plus:QI (match_operand:QI 1 "general_operand" "%0,0")
2541		 (match_operand:QI 2 "general_operand" "qn,qmn")))]
2542  ""
2543  "*
2544{
2545  if (operands[2] == const1_rtx)
2546    return AS1 (inc%B0,%0);
2547
2548  if (operands[2] == constm1_rtx
2549      || (GET_CODE (operands[2]) == CONST_INT
2550	  && INTVAL (operands[2]) == 255))
2551    return AS1 (dec%B0,%0);
2552
2553  return AS2 (add%B0,%2,%0);
2554}")
2555
2556;Lennart Augustsson <augustss@cs.chalmers.se>
2557;says this pattern just makes slower code:
2558;	pushl	%ebp
2559;	addl	$-80,(%esp)
2560;instead of
2561;	leal	-80(%ebp),%eax
2562;	pushl	%eax
2563;
2564;(define_insn ""
2565;  [(set (match_operand:SI 0 "push_operand" "=<")
2566;	(plus:SI (match_operand:SI 1 "general_operand" "%r")
2567;		 (match_operand:SI 2 "general_operand" "ri")))]
2568;  ""
2569;  "*
2570;{
2571;  rtx xops[4];
2572;  xops[0] = operands[0];
2573;  xops[1] = operands[1];
2574;  xops[2] = operands[2];
2575;  xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx);
2576;  output_asm_insn (\"push%z1 %1\", xops);
2577;  output_asm_insn (AS2 (add%z3,%2,%3), xops);
2578;  RET;
2579;}")
2580
2581;; addsi3 is faster, so put this after.
2582
2583(define_insn "movsi_lea"
2584  [(set (match_operand:SI 0 "register_operand" "=r")
2585        (match_operand:QI 1 "address_operand" "p"))]
2586  ""
2587  "*
2588{
2589  CC_STATUS_INIT;
2590  /* Adding a constant to a register is faster with an add.  */
2591  /* ??? can this ever happen? */
2592  if (GET_CODE (operands[1]) == PLUS
2593      && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2594      && rtx_equal_p (operands[0], XEXP (operands[1], 0)))
2595    {
2596      operands[1] = XEXP (operands[1], 1);
2597
2598      if (operands[1] == const1_rtx)
2599        return AS1 (inc%L0,%0);
2600
2601      if (operands[1] == constm1_rtx)
2602        return AS1 (dec%L0,%0);
2603
2604      return AS2 (add%L0,%1,%0);
2605    }
2606  return AS2 (lea%L0,%a1,%0);
2607}")
2608
2609;; The patterns that match these are at the end of this file.
2610
2611(define_expand "addxf3"
2612  [(set (match_operand:XF 0 "register_operand" "")
2613	(plus:XF (match_operand:XF 1 "nonimmediate_operand" "")
2614		 (match_operand:XF 2 "nonimmediate_operand" "")))]
2615  "TARGET_80387"
2616  "")
2617
2618(define_expand "adddf3"
2619  [(set (match_operand:DF 0 "register_operand" "")
2620	(plus:DF (match_operand:DF 1 "nonimmediate_operand" "")
2621		 (match_operand:DF 2 "nonimmediate_operand" "")))]
2622  "TARGET_80387"
2623  "")
2624
2625(define_expand "addsf3"
2626  [(set (match_operand:SF 0 "register_operand" "")
2627	(plus:SF (match_operand:SF 1 "nonimmediate_operand" "")
2628		 (match_operand:SF 2 "nonimmediate_operand" "")))]
2629  "TARGET_80387"
2630  "")
2631
2632;;- subtract instructions
2633
2634(define_insn "subdi3"
2635  [(set (match_operand:DI 0 "general_operand" "=&r,ro,&r,o,o")
2636	(minus:DI (match_operand:DI 1 "general_operand" "0,0,roiF,riF,o")
2637		  (match_operand:DI 2 "general_operand" "o,riF,roiF,riF,o")))
2638   (clobber (match_scratch:SI 3 "=X,X,X,&r,&r"))]
2639  ""
2640  "*
2641{
2642  rtx low[3], high[3], xops[7];
2643
2644  CC_STATUS_INIT;
2645
2646  split_di (operands, 3, low, high);
2647
2648  if (!rtx_equal_p (operands[0], operands[1]))
2649    {
2650      xops[0] = high[0];
2651      xops[1] = low[0];
2652      xops[2] = high[1];
2653      xops[3] = low[1];
2654
2655      if (GET_CODE (operands[0]) != MEM)
2656	{
2657	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2658	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2659	}
2660      else
2661	{
2662	  xops[4] = high[2];
2663	  xops[5] = low[2];
2664	  xops[6] = operands[3];
2665	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2666	  output_asm_insn (AS2 (sub%L6,%5,%6), xops);
2667	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2668	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2669	  output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
2670	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2671	  RET;
2672	}
2673    }
2674
2675  if (GET_CODE (operands[3]) == REG)
2676    {
2677      xops[0] = high[0];
2678      xops[1] = low[0];
2679      xops[2] = high[2];
2680      xops[3] = low[2];
2681      xops[4] = operands[3];
2682
2683      output_asm_insn (AS2 (mov%L4,%3,%4), xops);
2684      output_asm_insn (AS2 (sub%L1,%4,%1), xops);
2685      output_asm_insn (AS2 (mov%L4,%2,%4), xops);
2686      output_asm_insn (AS2 (sbb%L0,%4,%0), xops);
2687    }
2688
2689  else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
2690    {
2691      output_asm_insn (AS2 (sub%L0,%2,%0), low);
2692      output_asm_insn (AS2 (sbb%L0,%2,%0), high);
2693    }
2694
2695  else
2696    output_asm_insn (AS2 (sub%L0,%2,%0), high);
2697
2698  RET;
2699}")
2700
2701(define_insn "subsi3"
2702  [(set (match_operand:SI 0 "general_operand" "=rm,r")
2703	(minus:SI (match_operand:SI 1 "general_operand" "0,0")
2704		  (match_operand:SI 2 "general_operand" "ri,rm")))]
2705  ""
2706  "* return AS2 (sub%L0,%2,%0);")
2707
2708(define_insn "subhi3"
2709  [(set (match_operand:HI 0 "general_operand" "=rm,r")
2710	(minus:HI (match_operand:HI 1 "general_operand" "0,0")
2711		  (match_operand:HI 2 "general_operand" "ri,rm")))]
2712  ""
2713  "* return AS2 (sub%W0,%2,%0);")
2714
2715(define_insn "subqi3"
2716  [(set (match_operand:QI 0 "general_operand" "=qm,q")
2717	(minus:QI (match_operand:QI 1 "general_operand" "0,0")
2718		  (match_operand:QI 2 "general_operand" "qn,qmn")))]
2719  ""
2720  "* return AS2 (sub%B0,%2,%0);")
2721
2722;; The patterns that match these are at the end of this file.
2723
2724(define_expand "subxf3"
2725  [(set (match_operand:XF 0 "register_operand" "")
2726	(minus:XF (match_operand:XF 1 "nonimmediate_operand" "")
2727		  (match_operand:XF 2 "nonimmediate_operand" "")))]
2728  "TARGET_80387"
2729  "")
2730
2731(define_expand "subdf3"
2732  [(set (match_operand:DF 0 "register_operand" "")
2733	(minus:DF (match_operand:DF 1 "nonimmediate_operand" "")
2734		  (match_operand:DF 2 "nonimmediate_operand" "")))]
2735  "TARGET_80387"
2736  "")
2737
2738(define_expand "subsf3"
2739  [(set (match_operand:SF 0 "register_operand" "")
2740	(minus:SF (match_operand:SF 1 "nonimmediate_operand" "")
2741		  (match_operand:SF 2 "nonimmediate_operand" "")))]
2742  "TARGET_80387"
2743  "")
2744
2745;;- multiply instructions
2746
2747;(define_insn "mulqi3"
2748;  [(set (match_operand:QI 0 "general_operand" "=a")
2749;	(mult:QI (match_operand:QI 1 "general_operand" "%0")
2750;		 (match_operand:QI 2 "general_operand" "qm")))]
2751;  ""
2752;  "imul%B0 %2,%0")
2753
2754(define_insn ""
2755  [(set (match_operand:HI 0 "general_operand" "=r")
2756	(mult:HI (match_operand:HI 1 "general_operand" "%0")
2757		 (match_operand:HI 2 "general_operand" "r")))]
2758  "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
2759  "* return AS2 (imul%W0,%2,%0);")
2760
2761(define_insn "mulhi3"
2762  [(set (match_operand:HI 0 "general_operand" "=r,r")
2763	(mult:HI (match_operand:HI 1 "general_operand" "%0,rm")
2764		 (match_operand:HI 2 "general_operand" "g,i")))]
2765  ""
2766  "*
2767{
2768  if (GET_CODE (operands[1]) == REG
2769      && REGNO (operands[1]) == REGNO (operands[0])
2770      && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
2771    /* Assembler has weird restrictions.  */
2772    return AS2 (imul%W0,%2,%0);
2773  return AS3 (imul%W0,%2,%1,%0);
2774}")
2775
2776(define_insn ""
2777  [(set (match_operand:SI 0 "general_operand" "=r")
2778	(mult:SI (match_operand:SI 1 "general_operand" "%0")
2779		 (match_operand:SI 2 "general_operand" "r")))]
2780  "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
2781  "* return AS2 (imul%L0,%2,%0);")
2782
2783(define_insn "mulsi3"
2784  [(set (match_operand:SI 0 "general_operand" "=r,r")
2785	(mult:SI (match_operand:SI 1 "general_operand" "%0,rm")
2786		 (match_operand:SI 2 "general_operand" "g,i")))]
2787  ""
2788  "*
2789{
2790  if (GET_CODE (operands[1]) == REG
2791      && REGNO (operands[1]) == REGNO (operands[0])
2792      && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
2793    /* Assembler has weird restrictions.  */
2794    return AS2 (imul%L0,%2,%0);
2795  return AS3 (imul%L0,%2,%1,%0);
2796}")
2797
2798(define_insn "umulqihi3"
2799  [(set (match_operand:HI 0 "general_operand" "=a")
2800	(mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
2801		 (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
2802  ""
2803  "mul%B0 %2")
2804
2805(define_insn "mulqihi3"
2806  [(set (match_operand:HI 0 "general_operand" "=a")
2807	(mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
2808		 (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
2809  ""
2810  "imul%B0 %2")
2811
2812(define_insn "umulsidi3"
2813  [(set (match_operand:DI 0 "register_operand" "=A")
2814	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
2815		 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
2816  "TARGET_WIDE_MULTIPLY"
2817  "mul%L0 %2")
2818
2819(define_insn "mulsidi3"
2820  [(set (match_operand:DI 0 "register_operand" "=A")
2821	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
2822		 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
2823  "TARGET_WIDE_MULTIPLY"
2824  "imul%L0 %2")
2825
2826(define_insn "umulsi3_highpart"
2827  [(set (match_operand:SI 0 "register_operand" "=d")
2828	(truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a"))
2829					   (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
2830				  (const_int 32))))
2831   (clobber (match_scratch:SI 3 "=a"))]
2832  "TARGET_WIDE_MULTIPLY"
2833  "mul%L0 %2")
2834
2835(define_insn "smulsi3_highpart"
2836  [(set (match_operand:SI 0 "register_operand" "=d")
2837	(truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%a"))
2838					   (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
2839				  (const_int 32))))
2840   (clobber (match_scratch:SI 3 "=a"))]
2841  "TARGET_WIDE_MULTIPLY"
2842  "imul%L0 %2")
2843
2844;; The patterns that match these are at the end of this file.
2845
2846(define_expand "mulxf3"
2847  [(set (match_operand:XF 0 "register_operand" "")
2848	(mult:XF (match_operand:XF 1 "nonimmediate_operand" "")
2849		 (match_operand:XF 2 "nonimmediate_operand" "")))]
2850  "TARGET_80387"
2851  "")
2852
2853(define_expand "muldf3"
2854  [(set (match_operand:DF 0 "register_operand" "")
2855	(mult:DF (match_operand:DF 1 "nonimmediate_operand" "")
2856		 (match_operand:DF 2 "nonimmediate_operand" "")))]
2857  "TARGET_80387"
2858  "")
2859
2860(define_expand "mulsf3"
2861  [(set (match_operand:SF 0 "register_operand" "")
2862	(mult:SF (match_operand:SF 1 "nonimmediate_operand" "")
2863		 (match_operand:SF 2 "nonimmediate_operand" "")))]
2864  "TARGET_80387"
2865  "")
2866
2867;;- divide instructions
2868
2869(define_insn "divqi3"
2870  [(set (match_operand:QI 0 "general_operand" "=a")
2871	(div:QI (match_operand:HI 1 "general_operand" "0")
2872		(match_operand:QI 2 "general_operand" "qm")))]
2873  ""
2874  "idiv%B0 %2")
2875
2876(define_insn "udivqi3"
2877  [(set (match_operand:QI 0 "general_operand" "=a")
2878	(udiv:QI (match_operand:HI 1 "general_operand" "0")
2879		 (match_operand:QI 2 "general_operand" "qm")))]
2880  ""
2881  "div%B0 %2")
2882
2883;; The patterns that match these are at the end of this file.
2884
2885(define_expand "divxf3"
2886  [(set (match_operand:XF 0 "register_operand" "")
2887	(div:XF (match_operand:XF 1 "nonimmediate_operand" "")
2888		(match_operand:XF 2 "nonimmediate_operand" "")))]
2889  "TARGET_80387"
2890  "")
2891
2892(define_expand "divdf3"
2893  [(set (match_operand:DF 0 "register_operand" "")
2894	(div:DF (match_operand:DF 1 "nonimmediate_operand" "")
2895		(match_operand:DF 2 "nonimmediate_operand" "")))]
2896  "TARGET_80387"
2897  "")
2898
2899(define_expand "divsf3"
2900  [(set (match_operand:SF 0 "register_operand" "")
2901	(div:SF (match_operand:SF 1 "nonimmediate_operand" "")
2902		(match_operand:SF 2 "nonimmediate_operand" "")))]
2903  "TARGET_80387"
2904  "")
2905
2906;; Remainder instructions.
2907
2908(define_insn "divmodsi4"
2909  [(set (match_operand:SI 0 "register_operand" "=a")
2910	(div:SI (match_operand:SI 1 "register_operand" "0")
2911		(match_operand:SI 2 "general_operand" "rm")))
2912   (set (match_operand:SI 3 "register_operand" "=&d")
2913	(mod:SI (match_dup 1) (match_dup 2)))]
2914  ""
2915  "*
2916{
2917#ifdef INTEL_SYNTAX
2918  output_asm_insn (\"cdq\", operands);
2919#else
2920  output_asm_insn (\"cltd\", operands);
2921#endif
2922  return AS1 (idiv%L0,%2);
2923}")
2924
2925(define_insn "divmodhi4"
2926  [(set (match_operand:HI 0 "register_operand" "=a")
2927	(div:HI (match_operand:HI 1 "register_operand" "0")
2928		(match_operand:HI 2 "general_operand" "rm")))
2929   (set (match_operand:HI 3 "register_operand" "=&d")
2930	(mod:HI (match_dup 1) (match_dup 2)))]
2931  ""
2932  "cwtd\;idiv%W0 %2")
2933
2934;; ??? Can we make gcc zero extend operand[0]?
2935(define_insn "udivmodsi4"
2936  [(set (match_operand:SI 0 "register_operand" "=a")
2937	(udiv:SI (match_operand:SI 1 "register_operand" "0")
2938		 (match_operand:SI 2 "general_operand" "rm")))
2939   (set (match_operand:SI 3 "register_operand" "=&d")
2940	(umod:SI (match_dup 1) (match_dup 2)))]
2941  ""
2942  "*
2943{
2944  output_asm_insn (AS2 (xor%L3,%3,%3), operands);
2945  return AS1 (div%L0,%2);
2946}")
2947
2948;; ??? Can we make gcc zero extend operand[0]?
2949(define_insn "udivmodhi4"
2950  [(set (match_operand:HI 0 "register_operand" "=a")
2951	(udiv:HI (match_operand:HI 1 "register_operand" "0")
2952		 (match_operand:HI 2 "general_operand" "rm")))
2953   (set (match_operand:HI 3 "register_operand" "=&d")
2954	(umod:HI (match_dup 1) (match_dup 2)))]
2955  ""
2956  "*
2957{
2958  output_asm_insn (AS2 (xor%W0,%3,%3), operands);
2959  return AS1 (div%W0,%2);
2960}")
2961
2962/*
2963;;this should be a valid double division which we may want to add
2964
2965(define_insn ""
2966  [(set (match_operand:SI 0 "register_operand" "=a")
2967	(udiv:DI (match_operand:DI 1 "register_operand" "a")
2968		 (match_operand:SI 2 "general_operand" "rm")))
2969   (set (match_operand:SI 3 "register_operand" "=d")
2970	(umod:SI (match_dup 1) (match_dup 2)))]
2971  ""
2972  "div%L0 %2,%0")
2973*/
2974
2975;;- and instructions
2976
2977;; On i386,
2978;;			movzbl %bl,%ebx
2979;; is faster than
2980;;			andl $255,%ebx
2981;;
2982;; but if the reg is %eax, then the "andl" is faster.
2983;;
2984;; On i486, the "andl" is always faster than the "movzbl".
2985;;
2986;; On both i386 and i486, a three operand AND is as fast with movzbl or
2987;; movzwl as with andl, if operands[0] != operands[1].
2988
2989;; The `r' in `rm' for operand 3 looks redundant, but it causes
2990;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
2991
2992;; ??? What if we only change one byte of an offsettable memory reference?
2993(define_insn "andsi3"
2994  [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r")
2995	(and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0")
2996		(match_operand:SI 2 "general_operand" "L,K,ri,rm")))]
2997  ""
2998  "*
2999{
3000  if (GET_CODE (operands[2]) == CONST_INT
3001      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3002    {
3003      if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0])
3004	  && (! REG_P (operands[1])
3005	      || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
3006	  && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1])))
3007	{
3008	  /* ??? tege: Should forget CC_STATUS only if we clobber a
3009	     remembered operand.  Fix that later.  */
3010	  CC_STATUS_INIT;
3011#ifdef INTEL_SYNTAX
3012	  return AS2 (movzx,%w1,%0);
3013#else
3014	  return AS2 (movz%W0%L0,%w1,%0);
3015#endif
3016	}
3017
3018      if (INTVAL (operands[2]) == 0xff && REG_P (operands[0])
3019	  && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
3020	  && (! REG_P (operands[1])
3021	      || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
3022	  && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1])))
3023	{
3024	  /* ??? tege: Should forget CC_STATUS only if we clobber a
3025	     remembered operand.  Fix that later.  */
3026	  CC_STATUS_INIT;
3027#ifdef INTEL_SYNTAX
3028	  return AS2 (movzx,%b1,%0);
3029#else
3030	  return AS2 (movz%B0%L0,%b1,%0);
3031#endif
3032	}
3033
3034      if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0)
3035	{
3036	  CC_STATUS_INIT;
3037
3038	  if (INTVAL (operands[2]) == 0xffffff00)
3039	    {
3040	      operands[2] = const0_rtx;
3041	      return AS2 (mov%B0,%2,%b0);
3042	    }
3043
3044	  operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
3045	  return AS2 (and%B0,%2,%b0);
3046	}
3047
3048      if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0)
3049	{
3050	  CC_STATUS_INIT;
3051
3052	  if (INTVAL (operands[2]) == 0xffff00ff)
3053	    {
3054	      operands[2] = const0_rtx;
3055	      return AS2 (mov%B0,%2,%h0);
3056	    }
3057
3058	  operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3059	  return AS2 (and%B0,%2,%h0);
3060	}
3061
3062      if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000)
3063        {
3064	  operands[2] = const0_rtx;
3065	  return AS2 (mov%W0,%2,%w0);
3066	}
3067    }
3068
3069  return AS2 (and%L0,%2,%0);
3070}")
3071
3072(define_insn "andhi3"
3073  [(set (match_operand:HI 0 "general_operand" "=rm,r")
3074	(and:HI (match_operand:HI 1 "general_operand" "%0,0")
3075		(match_operand:HI 2 "general_operand" "ri,rm")))]
3076  ""
3077  "*
3078{
3079  if (GET_CODE (operands[2]) == CONST_INT
3080      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3081    {
3082      /* Can we ignore the upper byte? */
3083      if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3084	  && (INTVAL (operands[2]) & 0xff00) == 0xff00)
3085	{
3086	  CC_STATUS_INIT;
3087
3088	  if ((INTVAL (operands[2]) & 0xff) == 0)
3089	    {
3090	      operands[2] = const0_rtx;
3091	      return AS2 (mov%B0,%2,%b0);
3092	    }
3093
3094	  operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
3095	  return AS2 (and%B0,%2,%b0);
3096	}
3097
3098      /* Can we ignore the lower byte? */
3099      /* ??? what about offsettable memory references? */
3100      if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff)
3101	{
3102	  CC_STATUS_INIT;
3103
3104	  if ((INTVAL (operands[2]) & 0xff00) == 0)
3105	    {
3106	      operands[2] = const0_rtx;
3107	      return AS2 (mov%B0,%2,%h0);
3108	    }
3109
3110	  operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3111	  return AS2 (and%B0,%2,%h0);
3112	}
3113    }
3114
3115  return AS2 (and%W0,%2,%0);
3116}")
3117
3118(define_insn "andqi3"
3119  [(set (match_operand:QI 0 "general_operand" "=qm,q")
3120	(and:QI (match_operand:QI 1 "general_operand" "%0,0")
3121		(match_operand:QI 2 "general_operand" "qn,qmn")))]
3122  ""
3123  "* return AS2 (and%B0,%2,%0);")
3124
3125/* I am nervous about these two.. add them later..
3126;I presume this means that we have something in say op0= eax which is small
3127;and we want to and it with memory so we can do this by just an
3128;andb m,%al  and have success.
3129(define_insn ""
3130  [(set (match_operand:SI 0 "general_operand" "=r")
3131	(and:SI (zero_extend:SI
3132		 (match_operand:HI 1 "nonimmediate_operand" "rm"))
3133		(match_operand:SI 2 "general_operand" "0")))]
3134  "GET_CODE (operands[2]) == CONST_INT
3135   && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
3136  "and%W0 %1,%0")
3137
3138(define_insn ""
3139  [(set (match_operand:SI 0 "general_operand" "=q")
3140	(and:SI
3141	 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))
3142		(match_operand:SI 2 "general_operand" "0")))]
3143  "GET_CODE (operands[2]) == CONST_INT
3144   && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
3145  "and%L0 %1,%0")
3146
3147*/
3148
3149;;- Bit set (inclusive or) instructions
3150
3151;; ??? What if we only change one byte of an offsettable memory reference?
3152(define_insn "iorsi3"
3153  [(set (match_operand:SI 0 "general_operand" "=rm,r")
3154	(ior:SI (match_operand:SI 1 "general_operand" "%0,0")
3155		(match_operand:SI 2 "general_operand" "ri,rm")))]
3156  ""
3157  "*
3158{
3159  if (GET_CODE (operands[2]) == CONST_INT
3160      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3161    {
3162      if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3163	  && (INTVAL (operands[2]) & ~0xff) == 0)
3164	{
3165	  CC_STATUS_INIT;
3166
3167	  if (INTVAL (operands[2]) == 0xff)
3168	    return AS2 (mov%B0,%2,%b0);
3169
3170	  return AS2 (or%B0,%2,%b0);
3171	}
3172
3173      if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
3174	{
3175	  CC_STATUS_INIT;
3176	  operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
3177
3178	  if (INTVAL (operands[2]) == 0xff)
3179	    return AS2 (mov%B0,%2,%h0);
3180
3181	  return AS2 (or%B0,%2,%h0);
3182	}
3183    }
3184
3185  return AS2 (or%L0,%2,%0);
3186}")
3187
3188(define_insn "iorhi3"
3189  [(set (match_operand:HI 0 "general_operand" "=rm,r")
3190	(ior:HI (match_operand:HI 1 "general_operand" "%0,0")
3191		(match_operand:HI 2 "general_operand" "ri,rm")))]
3192  ""
3193  "*
3194{
3195  if (GET_CODE (operands[2]) == CONST_INT
3196      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3197    {
3198      /* Can we ignore the upper byte? */
3199      if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3200	  && (INTVAL (operands[2]) & 0xff00) == 0)
3201	{
3202	  CC_STATUS_INIT;
3203	  if (INTVAL (operands[2]) & 0xffff0000)
3204	    operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
3205
3206	  if (INTVAL (operands[2]) == 0xff)
3207	    return AS2 (mov%B0,%2,%b0);
3208
3209	  return AS2 (or%B0,%2,%b0);
3210	}
3211
3212      /* Can we ignore the lower byte? */
3213      /* ??? what about offsettable memory references? */
3214      if (QI_REG_P (operands[0])
3215	  && (INTVAL (operands[2]) & 0xff) == 0)
3216	{
3217	  CC_STATUS_INIT;
3218	  operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3219
3220	  if (INTVAL (operands[2]) == 0xff)
3221	    return AS2 (mov%B0,%2,%h0);
3222
3223	  return AS2 (or%B0,%2,%h0);
3224	}
3225    }
3226
3227  return AS2 (or%W0,%2,%0);
3228}")
3229
3230(define_insn "iorqi3"
3231  [(set (match_operand:QI 0 "general_operand" "=qm,q")
3232	(ior:QI (match_operand:QI 1 "general_operand" "%0,0")
3233		(match_operand:QI 2 "general_operand" "qn,qmn")))]
3234  ""
3235  "* return AS2 (or%B0,%2,%0);")
3236
3237;;- xor instructions
3238
3239;; ??? What if we only change one byte of an offsettable memory reference?
3240(define_insn "xorsi3"
3241  [(set (match_operand:SI 0 "general_operand" "=rm,r")
3242	(xor:SI (match_operand:SI 1 "general_operand" "%0,0")
3243		(match_operand:SI 2 "general_operand" "ri,rm")))]
3244  ""
3245  "*
3246{
3247  if (GET_CODE (operands[2]) == CONST_INT
3248      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3249    {
3250      if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3251	  && (INTVAL (operands[2]) & ~0xff) == 0)
3252	{
3253	  CC_STATUS_INIT;
3254
3255	  if (INTVAL (operands[2]) == 0xff)
3256	    return AS1 (not%B0,%b0);
3257
3258	  return AS2 (xor%B0,%2,%b0);
3259	}
3260
3261      if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
3262	{
3263	  CC_STATUS_INIT;
3264	  operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
3265
3266	  if (INTVAL (operands[2]) == 0xff)
3267	    return AS1 (not%B0,%h0);
3268
3269	  return AS2 (xor%B0,%2,%h0);
3270	}
3271    }
3272
3273  return AS2 (xor%L0,%2,%0);
3274}")
3275
3276(define_insn "xorhi3"
3277  [(set (match_operand:HI 0 "general_operand" "=rm,r")
3278	(xor:HI (match_operand:HI 1 "general_operand" "%0,0")
3279		(match_operand:HI 2 "general_operand" "ri,rm")))]
3280  ""
3281  "*
3282{
3283  if (GET_CODE (operands[2]) == CONST_INT
3284      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3285    {
3286      /* Can we ignore the upper byte? */
3287      if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3288	  && (INTVAL (operands[2]) & 0xff00) == 0)
3289	{
3290	  CC_STATUS_INIT;
3291	  if (INTVAL (operands[2]) & 0xffff0000)
3292	    operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
3293
3294	  if (INTVAL (operands[2]) == 0xff)
3295	    return AS1 (not%B0,%b0);
3296
3297	  return AS2 (xor%B0,%2,%b0);
3298	}
3299
3300      /* Can we ignore the lower byte? */
3301      /* ??? what about offsettable memory references? */
3302      if (QI_REG_P (operands[0])
3303	  && (INTVAL (operands[2]) & 0xff) == 0)
3304	{
3305	  CC_STATUS_INIT;
3306	  operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3307
3308	  if (INTVAL (operands[2]) == 0xff)
3309	    return AS1 (not%B0,%h0);
3310
3311	  return AS2 (xor%B0,%2,%h0);
3312	}
3313    }
3314
3315  return AS2 (xor%W0,%2,%0);
3316}")
3317
3318(define_insn "xorqi3"
3319  [(set (match_operand:QI 0 "general_operand" "=qm,q")
3320	(xor:QI (match_operand:QI 1 "general_operand" "%0,0")
3321		(match_operand:QI 2 "general_operand" "qn,qm")))]
3322  ""
3323  "* return AS2 (xor%B0,%2,%0);")
3324
3325;;- negation instructions
3326
3327(define_insn "negdi2"
3328  [(set (match_operand:DI 0 "general_operand" "=&ro")
3329	(neg:DI (match_operand:DI 1 "general_operand" "0")))]
3330  ""
3331  "*
3332{
3333  rtx xops[2], low[1], high[1];
3334
3335  CC_STATUS_INIT;
3336
3337  split_di (operands, 1, low, high);
3338  xops[0] = const0_rtx;
3339  xops[1] = high[0];
3340
3341  output_asm_insn (AS1 (neg%L0,%0), low);
3342  output_asm_insn (AS2 (adc%L1,%0,%1), xops);
3343  output_asm_insn (AS1 (neg%L0,%0), high);
3344  RET;
3345}")
3346
3347(define_insn "negsi2"
3348  [(set (match_operand:SI 0 "general_operand" "=rm")
3349	(neg:SI (match_operand:SI 1 "general_operand" "0")))]
3350  ""
3351  "neg%L0 %0")
3352
3353(define_insn "neghi2"
3354  [(set (match_operand:HI 0 "general_operand" "=rm")
3355	(neg:HI (match_operand:HI 1 "general_operand" "0")))]
3356  ""
3357  "neg%W0 %0")
3358
3359(define_insn "negqi2"
3360  [(set (match_operand:QI 0 "general_operand" "=qm")
3361	(neg:QI (match_operand:QI 1 "general_operand" "0")))]
3362  ""
3363  "neg%B0 %0")
3364
3365(define_insn "negsf2"
3366  [(set (match_operand:SF 0 "register_operand" "=f")
3367	(neg:SF (match_operand:SF 1 "general_operand" "0")))]
3368  "TARGET_80387"
3369  "fchs")
3370
3371(define_insn "negdf2"
3372  [(set (match_operand:DF 0 "register_operand" "=f")
3373	(neg:DF (match_operand:DF 1 "general_operand" "0")))]
3374  "TARGET_80387"
3375  "fchs")
3376
3377(define_insn ""
3378  [(set (match_operand:DF 0 "register_operand" "=f")
3379	(neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
3380  "TARGET_80387"
3381  "fchs")
3382
3383(define_insn "negxf2"
3384  [(set (match_operand:XF 0 "register_operand" "=f")
3385	(neg:XF (match_operand:XF 1 "general_operand" "0")))]
3386  "TARGET_80387"
3387  "fchs")
3388
3389(define_insn ""
3390  [(set (match_operand:XF 0 "register_operand" "=f")
3391	(neg:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
3392  "TARGET_80387"
3393  "fchs")
3394
3395;; Absolute value instructions
3396
3397(define_insn "abssf2"
3398  [(set (match_operand:SF 0 "register_operand" "=f")
3399	(abs:SF (match_operand:SF 1 "general_operand" "0")))]
3400  "TARGET_80387"
3401  "fabs")
3402
3403(define_insn "absdf2"
3404  [(set (match_operand:DF 0 "register_operand" "=f")
3405	(abs:DF (match_operand:DF 1 "general_operand" "0")))]
3406  "TARGET_80387"
3407  "fabs")
3408
3409(define_insn ""
3410  [(set (match_operand:DF 0 "register_operand" "=f")
3411	(abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
3412  "TARGET_80387"
3413  "fabs")
3414
3415(define_insn "absxf2"
3416  [(set (match_operand:XF 0 "register_operand" "=f")
3417	(abs:XF (match_operand:XF 1 "general_operand" "0")))]
3418  "TARGET_80387"
3419  "fabs")
3420
3421(define_insn ""
3422  [(set (match_operand:XF 0 "register_operand" "=f")
3423	(abs:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
3424  "TARGET_80387"
3425  "fabs")
3426
3427(define_insn "sqrtsf2"
3428  [(set (match_operand:SF 0 "register_operand" "=f")
3429	(sqrt:SF (match_operand:SF 1 "general_operand" "0")))]
3430  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
3431   && (TARGET_IEEE_FP || flag_fast_math) "
3432  "fsqrt")
3433
3434(define_insn "sqrtdf2"
3435  [(set (match_operand:DF 0 "register_operand" "=f")
3436	(sqrt:DF (match_operand:DF 1 "general_operand" "0")))]
3437  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
3438   && (TARGET_IEEE_FP || flag_fast_math) "
3439  "fsqrt")
3440
3441(define_insn ""
3442  [(set (match_operand:DF 0 "register_operand" "=f")
3443	(sqrt:DF (float_extend:DF
3444		  (match_operand:SF 1 "general_operand" "0"))))]
3445  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3446   && (TARGET_IEEE_FP || flag_fast_math) "
3447  "fsqrt")
3448
3449(define_insn "sqrtxf2"
3450  [(set (match_operand:XF 0 "register_operand" "=f")
3451	(sqrt:XF (match_operand:XF 1 "general_operand" "0")))]
3452  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3453   && (TARGET_IEEE_FP || flag_fast_math) "
3454  "fsqrt")
3455
3456(define_insn ""
3457  [(set (match_operand:XF 0 "register_operand" "=f")
3458	(sqrt:XF (float_extend:XF
3459		  (match_operand:DF 1 "general_operand" "0"))))]
3460  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3461   && (TARGET_IEEE_FP || flag_fast_math) "
3462  "fsqrt")
3463
3464(define_insn ""
3465  [(set (match_operand:XF 0 "register_operand" "=f")
3466	(sqrt:XF (float_extend:XF
3467		  (match_operand:SF 1 "general_operand" "0"))))]
3468  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3469   && (TARGET_IEEE_FP || flag_fast_math) "
3470  "fsqrt")
3471
3472(define_insn "sindf2"
3473  [(set (match_operand:DF 0 "register_operand" "=f")
3474	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
3475  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3476   && (TARGET_IEEE_FP || flag_fast_math) "
3477  "fsin")
3478
3479(define_insn "sinsf2"
3480  [(set (match_operand:SF 0 "register_operand" "=f")
3481	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
3482  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3483   && (TARGET_IEEE_FP || flag_fast_math) "
3484  "fsin")
3485
3486(define_insn ""
3487  [(set (match_operand:DF 0 "register_operand" "=f")
3488	(unspec:DF [(float_extend:DF
3489		     (match_operand:SF 1 "register_operand" "0"))] 1))]
3490  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3491   && (TARGET_IEEE_FP || flag_fast_math) "
3492  "fsin")
3493
3494(define_insn "sinxf2"
3495  [(set (match_operand:XF 0 "register_operand" "=f")
3496	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
3497  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3498   && (TARGET_IEEE_FP || flag_fast_math) "
3499  "fsin")
3500
3501(define_insn "cosdf2"
3502  [(set (match_operand:DF 0 "register_operand" "=f")
3503	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
3504  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3505   && (TARGET_IEEE_FP || flag_fast_math) "
3506  "fcos")
3507
3508(define_insn "cossf2"
3509  [(set (match_operand:SF 0 "register_operand" "=f")
3510	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
3511  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3512   && (TARGET_IEEE_FP || flag_fast_math) "
3513  "fcos")
3514
3515(define_insn ""
3516  [(set (match_operand:DF 0 "register_operand" "=f")
3517	(unspec:DF [(float_extend:DF
3518		     (match_operand:SF 1 "register_operand" "0"))] 2))]
3519  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3520   && (TARGET_IEEE_FP || flag_fast_math) "
3521  "fcos")
3522
3523(define_insn "cosxf2"
3524  [(set (match_operand:XF 0 "register_operand" "=f")
3525	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))]
3526  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3527   && (TARGET_IEEE_FP || flag_fast_math) "
3528  "fcos")
3529
3530;;- one complement instructions
3531
3532(define_insn "one_cmplsi2"
3533  [(set (match_operand:SI 0 "general_operand" "=rm")
3534	(not:SI (match_operand:SI 1 "general_operand" "0")))]
3535  ""
3536  "not%L0 %0")
3537
3538(define_insn "one_cmplhi2"
3539  [(set (match_operand:HI 0 "general_operand" "=rm")
3540	(not:HI (match_operand:HI 1 "general_operand" "0")))]
3541  ""
3542  "not%W0 %0")
3543
3544(define_insn "one_cmplqi2"
3545  [(set (match_operand:QI 0 "general_operand" "=qm")
3546	(not:QI (match_operand:QI 1 "general_operand" "0")))]
3547  ""
3548  "not%B0 %0")
3549
3550;;- arithmetic shift instructions
3551
3552;; DImode shifts are implemented using the i386 "shift double" opcode,
3553;; which is written as "sh[lr]d[lw] imm,reg,reg/mem".  If the shift count
3554;; is variable, then the count is in %cl and the "imm" operand is dropped
3555;; from the assembler input.
3556
3557;; This instruction shifts the target reg/mem as usual, but instead of
3558;; shifting in zeros, bits are shifted in from reg operand.  If the insn
3559;; is a left shift double, bits are taken from the high order bits of
3560;; reg, else if the insn is a shift right double, bits are taken from the
3561;; low order bits of reg.  So if %eax is "1234" and %edx is "5678",
3562;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
3563
3564;; Since sh[lr]d does not change the `reg' operand, that is done
3565;; separately, making all shifts emit pairs of shift double and normal
3566;; shift.  Since sh[lr]d does not shift more than 31 bits, and we wish to
3567;; support a 63 bit shift, each shift where the count is in a reg expands
3568;; to three pairs.  If the overall shift is by N bits, then the first two
3569;; pairs shift by N / 2 and the last pair by N & 1.
3570
3571;; If the shift count is a constant, we need never emit more than one
3572;; shift pair, instead using moves and sign extension for counts greater
3573;; than 31.
3574
3575(define_expand "ashldi3"
3576  [(set (match_operand:DI 0 "register_operand" "")
3577	(ashift:DI (match_operand:DI 1 "register_operand" "")
3578		   (match_operand:QI 2 "nonmemory_operand" "")))]
3579  ""
3580  "
3581{
3582  if (GET_CODE (operands[2]) != CONST_INT
3583      || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
3584    {
3585      operands[2] = copy_to_mode_reg (QImode, operands[2]);
3586      emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1],
3587					    operands[2]));
3588    }
3589  else
3590    emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2]));
3591
3592  DONE;
3593}")
3594
3595(define_insn "ashldi3_const_int"
3596  [(set (match_operand:DI 0 "register_operand" "=&r")
3597	(ashift:DI (match_operand:DI 1 "register_operand" "0")
3598		   (match_operand:QI 2 "const_int_operand" "J")))]
3599  ""
3600  "*
3601{
3602  rtx xops[4], low[1], high[1];
3603
3604  CC_STATUS_INIT;
3605
3606  split_di (operands, 1, low, high);
3607  xops[0] = operands[2];
3608  xops[1] = const1_rtx;
3609  xops[2] = low[0];
3610  xops[3] = high[0];
3611
3612  if (INTVAL (xops[0]) > 31)
3613    {
3614      output_asm_insn (AS2 (mov%L3,%2,%3), xops);	/* Fast shift by 32 */
3615      output_asm_insn (AS2 (xor%L2,%2,%2), xops);
3616
3617      if (INTVAL (xops[0]) > 32)
3618        {
3619	  xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
3620	  output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */
3621	}
3622    }
3623  else
3624    {
3625      output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops);
3626      output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3627    }
3628  RET;
3629}")
3630
3631(define_insn "ashldi3_non_const_int"
3632  [(set (match_operand:DI 0 "register_operand" "=&r")
3633	(ashift:DI (match_operand:DI 1 "register_operand" "0")
3634		   (match_operand:QI 2 "register_operand" "c")))
3635   (clobber (match_dup 2))]
3636  ""
3637  "*
3638{
3639  rtx xops[4], low[1], high[1];
3640
3641  CC_STATUS_INIT;
3642
3643  split_di (operands, 1, low, high);
3644  xops[0] = operands[2];
3645  xops[1] = const1_rtx;
3646  xops[2] = low[0];
3647  xops[3] = high[0];
3648
3649  output_asm_insn (AS2 (ror%B0,%1,%0), xops);	/* shift count / 2 */
3650
3651  output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
3652  output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3653  output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
3654  output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3655
3656  xops[1] = GEN_INT (7);			/* shift count & 1 */
3657
3658  output_asm_insn (AS2 (shr%B0,%1,%0), xops);
3659
3660  output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
3661  output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3662
3663  RET;
3664}")
3665
3666;; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg"
3667;; On i486, movl/sall appears slightly faster than leal, but the leal
3668;; is smaller - use leal for now unless the shift count is 1.
3669
3670(define_insn "ashlsi3"
3671  [(set (match_operand:SI 0 "general_operand" "=r,rm")
3672	(ashift:SI (match_operand:SI 1 "general_operand" "r,0")
3673		   (match_operand:SI 2 "nonmemory_operand" "M,cI")))]
3674  ""
3675  "*
3676{
3677  if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
3678    {
3679      if (!TARGET_386 && INTVAL (operands[2]) == 1)
3680	{
3681	  output_asm_insn (AS2 (mov%L0,%1,%0), operands);
3682	  return AS2 (add%L0,%1,%0);
3683	}
3684      else
3685        {
3686          CC_STATUS_INIT;
3687
3688	  if (operands[1] == stack_pointer_rtx)
3689	    {
3690	      output_asm_insn (AS2 (mov%L0,%1,%0), operands);
3691	      operands[1] = operands[0];
3692	    }
3693          operands[1] = gen_rtx (MULT, SImode, operands[1],
3694				 GEN_INT (1 << INTVAL (operands[2])));
3695	  return AS2 (lea%L0,%a1,%0);
3696	}
3697    }
3698
3699  if (REG_P (operands[2]))
3700    return AS2 (sal%L0,%b2,%0);
3701
3702  if (REG_P (operands[0]) && operands[2] == const1_rtx)
3703    return AS2 (add%L0,%0,%0);
3704
3705  return AS2 (sal%L0,%2,%0);
3706}")
3707
3708(define_insn "ashlhi3"
3709  [(set (match_operand:HI 0 "general_operand" "=rm")
3710	(ashift:HI (match_operand:HI 1 "general_operand" "0")
3711		   (match_operand:HI 2 "nonmemory_operand" "cI")))]
3712  ""
3713  "*
3714{
3715  if (REG_P (operands[2]))
3716    return AS2 (sal%W0,%b2,%0);
3717
3718  if (REG_P (operands[0]) && operands[2] == const1_rtx)
3719    return AS2 (add%W0,%0,%0);
3720
3721  return AS2 (sal%W0,%2,%0);
3722}")
3723
3724(define_insn "ashlqi3"
3725  [(set (match_operand:QI 0 "general_operand" "=qm")
3726	(ashift:QI (match_operand:QI 1 "general_operand" "0")
3727		   (match_operand:QI 2 "nonmemory_operand" "cI")))]
3728  ""
3729  "*
3730{
3731  if (REG_P (operands[2]))
3732    return AS2 (sal%B0,%b2,%0);
3733
3734  if (REG_P (operands[0]) && operands[2] == const1_rtx)
3735    return AS2 (add%B0,%0,%0);
3736
3737  return AS2 (sal%B0,%2,%0);
3738}")
3739
3740;; See comment above `ashldi3' about how this works.
3741
3742(define_expand "ashrdi3"
3743  [(set (match_operand:DI 0 "register_operand" "")
3744	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
3745		     (match_operand:QI 2 "nonmemory_operand" "")))]
3746  ""
3747  "
3748{
3749  if (GET_CODE (operands[2]) != CONST_INT
3750      || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
3751    {
3752      operands[2] = copy_to_mode_reg (QImode, operands[2]);
3753      emit_insn (gen_ashrdi3_non_const_int (operands[0], operands[1],
3754					    operands[2]));
3755    }
3756  else
3757    emit_insn (gen_ashrdi3_const_int (operands[0], operands[1], operands[2]));
3758
3759  DONE;
3760}")
3761
3762(define_insn "ashrdi3_const_int"
3763  [(set (match_operand:DI 0 "register_operand" "=&r")
3764	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
3765		     (match_operand:QI 2 "const_int_operand" "J")))]
3766  ""
3767  "*
3768{
3769  rtx xops[4], low[1], high[1];
3770
3771  CC_STATUS_INIT;
3772
3773  split_di (operands, 1, low, high);
3774  xops[0] = operands[2];
3775  xops[1] = const1_rtx;
3776  xops[2] = low[0];
3777  xops[3] = high[0];
3778
3779  if (INTVAL (xops[0]) > 31)
3780    {
3781      xops[1] = GEN_INT (31);
3782      output_asm_insn (AS2 (mov%L2,%3,%2), xops);
3783      output_asm_insn (AS2 (sar%L3,%1,%3), xops);	/* shift by 32 */
3784
3785      if (INTVAL (xops[0]) > 32)
3786        {
3787	  xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
3788	  output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */
3789	}
3790    }
3791  else
3792    {
3793      output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
3794      output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3795    }
3796
3797  RET;
3798}")
3799
3800(define_insn "ashrdi3_non_const_int"
3801  [(set (match_operand:DI 0 "register_operand" "=&r")
3802	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
3803		     (match_operand:QI 2 "register_operand" "c")))
3804   (clobber (match_dup 2))]
3805  ""
3806  "*
3807{
3808  rtx xops[4], low[1], high[1];
3809
3810  CC_STATUS_INIT;
3811
3812  split_di (operands, 1, low, high);
3813  xops[0] = operands[2];
3814  xops[1] = const1_rtx;
3815  xops[2] = low[0];
3816  xops[3] = high[0];
3817
3818  output_asm_insn (AS2 (ror%B0,%1,%0), xops);	/* shift count / 2 */
3819
3820  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3821  output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3822  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3823  output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3824
3825  xops[1] = GEN_INT (7);			/* shift count & 1 */
3826
3827  output_asm_insn (AS2 (shr%B0,%1,%0), xops);
3828
3829  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3830  output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3831
3832  RET;
3833}")
3834
3835(define_insn "ashrsi3"
3836  [(set (match_operand:SI 0 "general_operand" "=rm")
3837	(ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
3838		     (match_operand:SI 2 "nonmemory_operand" "cI")))]
3839  ""
3840  "*
3841{
3842  if (REG_P (operands[2]))
3843    return AS2 (sar%L0,%b2,%0);
3844  else
3845    return AS2 (sar%L0,%2,%0);
3846}")
3847
3848(define_insn "ashrhi3"
3849  [(set (match_operand:HI 0 "general_operand" "=rm")
3850	(ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
3851		     (match_operand:HI 2 "nonmemory_operand" "cI")))]
3852  ""
3853  "*
3854{
3855  if (REG_P (operands[2]))
3856    return AS2 (sar%W0,%b2,%0);
3857  else
3858    return AS2 (sar%W0,%2,%0);
3859}")
3860
3861(define_insn "ashrqi3"
3862  [(set (match_operand:QI 0 "general_operand" "=qm")
3863	(ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
3864		     (match_operand:QI 2 "nonmemory_operand" "cI")))]
3865  ""
3866  "*
3867{
3868  if (REG_P (operands[2]))
3869    return AS2 (sar%B0,%b2,%0);
3870  else
3871    return AS2 (sar%B0,%2,%0);
3872}")
3873
3874;;- logical shift instructions
3875
3876;; See comment above `ashldi3' about how this works.
3877
3878(define_expand "lshrdi3"
3879  [(set (match_operand:DI 0 "register_operand" "")
3880	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
3881		     (match_operand:QI 2 "nonmemory_operand" "")))]
3882  ""
3883  "
3884{
3885  if (GET_CODE (operands[2]) != CONST_INT
3886      || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
3887    {
3888      operands[2] = copy_to_mode_reg (QImode, operands[2]);
3889      emit_insn (gen_lshrdi3_non_const_int (operands[0], operands[1],
3890					    operands[2]));
3891    }
3892  else
3893    emit_insn (gen_lshrdi3_const_int (operands[0], operands[1], operands[2]));
3894
3895  DONE;
3896}")
3897
3898(define_insn "lshrdi3_const_int"
3899  [(set (match_operand:DI 0 "register_operand" "=&r")
3900	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
3901		     (match_operand:QI 2 "const_int_operand" "J")))]
3902  ""
3903  "*
3904{
3905  rtx xops[4], low[1], high[1];
3906
3907  CC_STATUS_INIT;
3908
3909  split_di (operands, 1, low, high);
3910  xops[0] = operands[2];
3911  xops[1] = const1_rtx;
3912  xops[2] = low[0];
3913  xops[3] = high[0];
3914
3915  if (INTVAL (xops[0]) > 31)
3916    {
3917      output_asm_insn (AS2 (mov%L2,%3,%2), xops);	/* Fast shift by 32 */
3918      output_asm_insn (AS2 (xor%L3,%3,%3), xops);
3919
3920      if (INTVAL (xops[0]) > 32)
3921        {
3922	  xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
3923	  output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */
3924	}
3925    }
3926  else
3927    {
3928      output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
3929      output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3930    }
3931
3932  RET;
3933}")
3934
3935(define_insn "lshrdi3_non_const_int"
3936  [(set (match_operand:DI 0 "register_operand" "=&r")
3937	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
3938		     (match_operand:QI 2 "register_operand" "c")))
3939   (clobber (match_dup 2))]
3940  ""
3941  "*
3942{
3943  rtx xops[4], low[1], high[1];
3944
3945  CC_STATUS_INIT;
3946
3947  split_di (operands, 1, low, high);
3948  xops[0] = operands[2];
3949  xops[1] = const1_rtx;
3950  xops[2] = low[0];
3951  xops[3] = high[0];
3952
3953  output_asm_insn (AS2 (ror%B0,%1,%0), xops);	/* shift count / 2 */
3954
3955  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3956  output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3957  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3958  output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3959
3960  xops[1] = GEN_INT (7);			/* shift count & 1 */
3961
3962  output_asm_insn (AS2 (shr%B0,%1,%0), xops);
3963
3964  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3965  output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3966
3967  RET;
3968}")
3969
3970(define_insn "lshrsi3"
3971  [(set (match_operand:SI 0 "general_operand" "=rm")
3972	(lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
3973		     (match_operand:SI 2 "nonmemory_operand" "cI")))]
3974  ""
3975  "*
3976{
3977  if (REG_P (operands[2]))
3978    return AS2 (shr%L0,%b2,%0);
3979  else
3980    return AS2 (shr%L0,%2,%1);
3981}")
3982
3983(define_insn "lshrhi3"
3984  [(set (match_operand:HI 0 "general_operand" "=rm")
3985	(lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
3986		     (match_operand:HI 2 "nonmemory_operand" "cI")))]
3987  ""
3988  "*
3989{
3990  if (REG_P (operands[2]))
3991    return AS2 (shr%W0,%b2,%0);
3992  else
3993    return AS2 (shr%W0,%2,%0);
3994}")
3995
3996(define_insn "lshrqi3"
3997  [(set (match_operand:QI 0 "general_operand" "=qm")
3998	(lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
3999		     (match_operand:QI 2 "nonmemory_operand" "cI")))]
4000  ""
4001  "*
4002{
4003  if (REG_P (operands[2]))
4004    return AS2 (shr%B0,%b2,%0);
4005  else
4006    return AS2 (shr%B0,%2,%0);
4007}")
4008
4009;;- rotate instructions
4010
4011(define_insn "rotlsi3"
4012  [(set (match_operand:SI 0 "general_operand" "=rm")
4013	(rotate:SI (match_operand:SI 1 "general_operand" "0")
4014		   (match_operand:SI 2 "nonmemory_operand" "cI")))]
4015  ""
4016  "*
4017{
4018  if (REG_P (operands[2]))
4019    return AS2 (rol%L0,%b2,%0);
4020  else
4021    return AS2 (rol%L0,%2,%0);
4022}")
4023
4024(define_insn "rotlhi3"
4025  [(set (match_operand:HI 0 "general_operand" "=rm")
4026	(rotate:HI (match_operand:HI 1 "general_operand" "0")
4027		   (match_operand:HI 2 "nonmemory_operand" "cI")))]
4028  ""
4029  "*
4030{
4031  if (REG_P (operands[2]))
4032    return AS2 (rol%W0,%b2,%0);
4033  else
4034    return AS2 (rol%W0,%2,%0);
4035}")
4036
4037(define_insn "rotlqi3"
4038  [(set (match_operand:QI 0 "general_operand" "=qm")
4039	(rotate:QI (match_operand:QI 1 "general_operand" "0")
4040		   (match_operand:QI 2 "nonmemory_operand" "cI")))]
4041  ""
4042  "*
4043{
4044  if (REG_P (operands[2]))
4045    return AS2 (rol%B0,%b2,%0);
4046  else
4047    return AS2 (rol%B0,%2,%0);
4048}")
4049
4050(define_insn "rotrsi3"
4051  [(set (match_operand:SI 0 "general_operand" "=rm")
4052	(rotatert:SI (match_operand:SI 1 "general_operand" "0")
4053		     (match_operand:SI 2 "nonmemory_operand" "cI")))]
4054  ""
4055  "*
4056{
4057  if (REG_P (operands[2]))
4058    return AS2 (ror%L0,%b2,%0);
4059  else
4060    return AS2 (ror%L0,%2,%0);
4061}")
4062
4063(define_insn "rotrhi3"
4064  [(set (match_operand:HI 0 "general_operand" "=rm")
4065	(rotatert:HI (match_operand:HI 1 "general_operand" "0")
4066		     (match_operand:HI 2 "nonmemory_operand" "cI")))]
4067  ""
4068  "*
4069{
4070  if (REG_P (operands[2]))
4071    return AS2 (ror%W0,%b2,%0);
4072  else
4073    return AS2 (ror%W0,%2,%0);
4074}")
4075
4076(define_insn "rotrqi3"
4077  [(set (match_operand:QI 0 "general_operand" "=qm")
4078	(rotatert:QI (match_operand:QI 1 "general_operand" "0")
4079		     (match_operand:QI 2 "nonmemory_operand" "cI")))]
4080  ""
4081  "*
4082{
4083  if (REG_P (operands[2]))
4084    return AS2 (ror%B0,%b2,%0);
4085  else
4086    return AS2 (ror%B0,%2,%0);
4087}")
4088
4089/*
4090;; This usually looses.  But try a define_expand to recognize a few case
4091;; we can do efficiently, such as accessing the "high" QImode registers,
4092;; %ah, %bh, %ch, %dh.
4093(define_insn "insv"
4094  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r")
4095			 (match_operand:SI 1 "general_operand" "i")
4096			 (match_operand:SI 2 "general_operand" "i"))
4097	(match_operand:SI 3 "general_operand" "ri"))]
4098  ""
4099  "*
4100{
4101  if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode))
4102    abort ();
4103  if (GET_CODE (operands[3]) == CONST_INT)
4104    {
4105      unsigned int mask = (1 << INTVAL (operands[1])) - 1; 
4106      operands[1] = GEN_INT (~(mask << INTVAL (operands[2])));
4107      output_asm_insn (AS2 (and%L0,%1,%0), operands);
4108      operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2]));
4109      output_asm_insn (AS2 (or%L0,%3,%0), operands);
4110    }
4111  else
4112    {
4113      operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]));
4114      if (INTVAL (operands[2]))
4115	output_asm_insn (AS2 (ror%L0,%2,%0), operands);
4116      output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands);
4117      operands[2] = GEN_INT (BITS_PER_WORD
4118			     - INTVAL (operands[1]) - INTVAL (operands[2]));
4119      if (INTVAL (operands[2]))
4120	output_asm_insn (AS2 (ror%L0,%2,%0), operands);
4121    }
4122  RET;
4123}")
4124*/
4125/*
4126;; ??? There are problems with the mode of operand[3].  The point of this
4127;; is to represent an HImode move to a "high byte" register.
4128
4129(define_expand "insv"
4130  [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
4131			 (match_operand:SI 1 "immediate_operand" "")
4132			 (match_operand:SI 2 "immediate_operand" ""))
4133	(match_operand:QI 3 "general_operand" "ri"))]
4134  ""
4135  "
4136{
4137  if (GET_CODE (operands[1]) != CONST_INT
4138      || GET_CODE (operands[2]) != CONST_INT)
4139    FAIL;
4140
4141  if (! (INTVAL (operands[1]) == 8
4142	 && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0))
4143      && ! INTVAL (operands[1]) == 1)
4144    FAIL;
4145}")
4146
4147;; ??? Are these constraints right?
4148(define_insn ""
4149  [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+&qo")
4150			 (const_int 8)
4151			 (const_int 8))
4152	(match_operand:QI 1 "general_operand" "qn"))]
4153  ""
4154  "*
4155{
4156  if (REG_P (operands[0]))
4157    return AS2 (mov%B0,%1,%h0);
4158
4159  operands[0] = adj_offsettable_operand (operands[0], 1);
4160  return AS2 (mov%B0,%1,%0);
4161}")
4162*/
4163
4164;; On i386, the register count for a bit operation is *not* truncated,
4165;; so SHIFT_COUNT_TRUNCATED must not be defined.
4166
4167;; On i486, the shift & or/and code is faster than bts or btr.  If
4168;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code.
4169
4170;; On i386, bts is a little faster if operands[0] is a reg, and a
4171;; little slower if operands[0] is a MEM, than the shift & or/and code.
4172;; Use bts & btr, since they reload better.
4173
4174;; General bit set and clear.
4175(define_insn ""
4176  [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm")
4177			 (const_int 1)
4178			 (match_operand:SI 2 "general_operand" "r"))
4179	(match_operand:SI 3 "const_int_operand" "n"))]
4180  "TARGET_386 && GET_CODE (operands[2]) != CONST_INT"
4181  "*
4182{
4183  CC_STATUS_INIT;
4184
4185  if (INTVAL (operands[3]) == 1)
4186    return AS2 (bts%L0,%2,%0);
4187  else
4188    return AS2 (btr%L0,%2,%0);
4189}")
4190
4191;; Bit complement.  See comments on previous pattern.
4192;; ??? Is this really worthwhile?
4193(define_insn ""
4194  [(set (match_operand:SI 0 "general_operand" "=rm")
4195	(xor:SI (ashift:SI (const_int 1)
4196			   (match_operand:SI 1 "general_operand" "r"))
4197		(match_operand:SI 2 "general_operand" "0")))]
4198  "TARGET_386 && GET_CODE (operands[1]) != CONST_INT"
4199  "*
4200{
4201  CC_STATUS_INIT;
4202
4203  return AS2 (btc%L0,%1,%0);
4204}")
4205
4206(define_insn ""
4207  [(set (match_operand:SI 0 "general_operand" "=rm")
4208	(xor:SI (match_operand:SI 1 "general_operand" "0")
4209		(ashift:SI (const_int 1)
4210			   (match_operand:SI 2 "general_operand" "r"))))]
4211  "TARGET_386 && GET_CODE (operands[2]) != CONST_INT"
4212  "*
4213{
4214  CC_STATUS_INIT;
4215
4216  return AS2 (btc%L0,%2,%0);
4217}")
4218
4219;; Recognizers for bit-test instructions.
4220
4221;; The bt opcode allows a MEM in operands[0].  But on both i386 and
4222;; i486, it is faster to copy a MEM to REG and then use bt, than to use
4223;; bt on the MEM directly.
4224
4225;; ??? The first argument of a zero_extract must not be reloaded, so
4226;; don't allow a MEM in the operand predicate without allowing it in the
4227;; constraint.
4228
4229(define_insn ""
4230  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
4231			    (const_int 1)
4232			    (match_operand:SI 1 "general_operand" "r")))]
4233  "GET_CODE (operands[1]) != CONST_INT"
4234  "*
4235{
4236  cc_status.flags |= CC_Z_IN_NOT_C;
4237  return AS2 (bt%L0,%1,%0);
4238}")
4239
4240(define_insn ""
4241  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
4242			    (match_operand:SI 1 "const_int_operand" "n")
4243			    (match_operand:SI 2 "const_int_operand" "n")))]
4244  ""
4245  "*
4246{
4247  unsigned int mask;
4248
4249  mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
4250  operands[1] = GEN_INT (mask);
4251
4252  if (QI_REG_P (operands[0]))
4253    {
4254      if ((mask & ~0xff) == 0)
4255        {
4256	  cc_status.flags |= CC_NOT_NEGATIVE;
4257	  return AS2 (test%B0,%1,%b0);
4258	}
4259
4260      if ((mask & ~0xff00) == 0)
4261        {
4262	  cc_status.flags |= CC_NOT_NEGATIVE;
4263	  operands[1] = GEN_INT (mask >> 8);
4264	  return AS2 (test%B0,%1,%h0);
4265	}
4266    }
4267
4268  return AS2 (test%L0,%1,%0);
4269}")
4270
4271;; ??? All bets are off if operand 0 is a volatile MEM reference.
4272;; The CPU may access unspecified bytes around the actual target byte.
4273
4274(define_insn ""
4275  [(set (cc0) (zero_extract (match_operand:QI 0 "general_operand" "rm")
4276			    (match_operand:SI 1 "const_int_operand" "n")
4277			    (match_operand:SI 2 "const_int_operand" "n")))]
4278  "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])"
4279  "*
4280{
4281  unsigned int mask;
4282
4283  mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
4284  operands[1] = GEN_INT (mask);
4285
4286  if (! REG_P (operands[0]) || QI_REG_P (operands[0]))
4287    {
4288      if ((mask & ~0xff) == 0)
4289        {
4290	  cc_status.flags |= CC_NOT_NEGATIVE;
4291	  return AS2 (test%B0,%1,%b0);
4292	}
4293
4294      if ((mask & ~0xff00) == 0)
4295        {
4296	  cc_status.flags |= CC_NOT_NEGATIVE;
4297	  operands[1] = GEN_INT (mask >> 8);
4298
4299	  if (QI_REG_P (operands[0]))
4300	    return AS2 (test%B0,%1,%h0);
4301	  else
4302	    {
4303	      operands[0] = adj_offsettable_operand (operands[0], 1);
4304	      return AS2 (test%B0,%1,%b0);
4305	    }
4306	}
4307
4308      if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0)
4309        {
4310	  cc_status.flags |= CC_NOT_NEGATIVE;
4311	  operands[1] = GEN_INT (mask >> 16);
4312	  operands[0] = adj_offsettable_operand (operands[0], 2);
4313	  return AS2 (test%B0,%1,%b0);
4314	}
4315
4316      if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0)
4317        {
4318	  cc_status.flags |= CC_NOT_NEGATIVE;
4319	  operands[1] = GEN_INT (mask >> 24);
4320	  operands[0] = adj_offsettable_operand (operands[0], 3);
4321	  return AS2 (test%B0,%1,%b0);
4322	}
4323    }
4324
4325  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
4326    return AS2 (test%L0,%1,%0);
4327
4328  return AS2 (test%L1,%0,%1);
4329}")
4330
4331;; Store-flag instructions.
4332
4333;; For all sCOND expanders, also expand the compare or test insn that
4334;; generates cc0.  Generate an equality comparison if `seq' or `sne'.
4335
4336;; The 386 sCOND opcodes can write to memory.  But a gcc sCOND insn may
4337;; not have any input reloads.  A MEM write might need an input reload
4338;; for the address of the MEM.  So don't allow MEM as the SET_DEST.
4339
4340(define_expand "seq"
4341  [(match_dup 1)
4342   (set (match_operand:QI 0 "register_operand" "")
4343	(eq:QI (cc0) (const_int 0)))]
4344  ""
4345  "
4346{
4347  if (TARGET_IEEE_FP
4348      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4349    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4350  else
4351    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4352}")
4353
4354(define_insn ""
4355  [(set (match_operand:QI 0 "register_operand" "=q")
4356	(eq:QI (cc0) (const_int 0)))]
4357  ""
4358  "*
4359{
4360  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4361    return AS1 (setnb,%0);
4362  else
4363    return AS1 (sete,%0);
4364}")
4365
4366(define_expand "sne"
4367  [(match_dup 1)
4368   (set (match_operand:QI 0 "register_operand" "")
4369	(ne:QI (cc0) (const_int 0)))]
4370  ""
4371  "
4372{
4373  if (TARGET_IEEE_FP
4374      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4375    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4376  else
4377    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4378}")
4379
4380(define_insn ""
4381  [(set (match_operand:QI 0 "register_operand" "=q")
4382	(ne:QI (cc0) (const_int 0)))]
4383  ""
4384  "*
4385{
4386  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4387    return AS1 (setb,%0);
4388  else
4389    return AS1 (setne,%0);
4390}
4391")
4392
4393(define_expand "sgt"
4394  [(match_dup 1)
4395   (set (match_operand:QI 0 "register_operand" "")
4396	(gt:QI (cc0) (const_int 0)))]
4397  ""
4398  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4399
4400(define_insn ""
4401  [(set (match_operand:QI 0 "register_operand" "=q")
4402	(gt:QI (cc0) (const_int 0)))]
4403  ""
4404  "*
4405{
4406  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4407    return AS1 (sete,%0);
4408
4409  OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR);
4410}")
4411
4412(define_expand "sgtu"
4413  [(match_dup 1)
4414   (set (match_operand:QI 0 "register_operand" "")
4415	(gtu:QI (cc0) (const_int 0)))]
4416  ""
4417  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4418
4419(define_insn ""
4420  [(set (match_operand:QI 0 "register_operand" "=q")
4421	(gtu:QI (cc0) (const_int 0)))]
4422  ""
4423  "* return \"seta %0\"; ")
4424
4425(define_expand "slt"
4426  [(match_dup 1)
4427   (set (match_operand:QI 0 "register_operand" "")
4428	(lt:QI (cc0) (const_int 0)))]
4429  ""
4430  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4431
4432(define_insn ""
4433  [(set (match_operand:QI 0 "register_operand" "=q")
4434	(lt:QI (cc0) (const_int 0)))]
4435  ""
4436  "*
4437{
4438  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4439    return AS1 (sete,%0);
4440
4441  OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\");
4442}")
4443
4444(define_expand "sltu"
4445  [(match_dup 1)
4446   (set (match_operand:QI 0 "register_operand" "")
4447	(ltu:QI (cc0) (const_int 0)))]
4448  ""
4449  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4450
4451(define_insn ""
4452  [(set (match_operand:QI 0 "register_operand" "=q")
4453	(ltu:QI (cc0) (const_int 0)))]
4454  ""
4455  "* return \"setb %0\"; ")
4456
4457(define_expand "sge"
4458  [(match_dup 1)
4459   (set (match_operand:QI 0 "register_operand" "")
4460	(ge:QI (cc0) (const_int 0)))]
4461  ""
4462  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4463
4464(define_insn ""
4465  [(set (match_operand:QI 0 "register_operand" "=q")
4466	(ge:QI (cc0) (const_int 0)))]
4467  ""
4468  "*
4469{
4470  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4471    return AS1 (sete,%0);
4472
4473  OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\");
4474}")
4475
4476(define_expand "sgeu"
4477  [(match_dup 1)
4478   (set (match_operand:QI 0 "register_operand" "")
4479	(geu:QI (cc0) (const_int 0)))]
4480  ""
4481  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4482
4483(define_insn ""
4484  [(set (match_operand:QI 0 "register_operand" "=q")
4485	(geu:QI (cc0) (const_int 0)))]
4486  ""
4487  "* return \"setae %0\"; ")
4488
4489(define_expand "sle"
4490  [(match_dup 1)
4491   (set (match_operand:QI 0 "register_operand" "")
4492	(le:QI (cc0) (const_int 0)))]
4493  ""
4494  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4495
4496(define_insn ""
4497  [(set (match_operand:QI 0 "register_operand" "=q")
4498	(le:QI (cc0) (const_int 0)))]
4499  ""
4500  "*
4501{
4502  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4503    return AS1 (setb,%0);
4504
4505  OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR);
4506}")
4507
4508(define_expand "sleu"
4509  [(match_dup 1)
4510   (set (match_operand:QI 0 "register_operand" "")
4511	(leu:QI (cc0) (const_int 0)))]
4512  ""
4513  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4514
4515(define_insn ""
4516  [(set (match_operand:QI 0 "register_operand" "=q")
4517	(leu:QI (cc0) (const_int 0)))]
4518  ""
4519  "* return \"setbe %0\"; ")
4520
4521;; Basic conditional jump instructions.
4522;; We ignore the overflow flag for signed branch instructions.
4523
4524;; For all bCOND expanders, also expand the compare or test insn that
4525;; generates cc0.  Generate an equality comparison if `beq' or `bne'.
4526
4527(define_expand "beq"
4528  [(match_dup 1)
4529   (set (pc)
4530	(if_then_else (eq (cc0)
4531			  (const_int 0))
4532		      (label_ref (match_operand 0 "" ""))
4533		      (pc)))]
4534  ""
4535  "
4536{
4537  if (TARGET_IEEE_FP
4538      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4539    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4540  else
4541    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4542}")
4543
4544(define_insn ""
4545  [(set (pc)
4546	(if_then_else (eq (cc0)
4547			  (const_int 0))
4548		      (label_ref (match_operand 0 "" ""))
4549		      (pc)))]
4550  ""
4551  "*
4552{
4553  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4554    return \"jnc %l0\";
4555  else
4556    return \"je %l0\";
4557}")
4558
4559(define_expand "bne"
4560  [(match_dup 1)
4561   (set (pc)
4562	(if_then_else (ne (cc0)
4563			  (const_int 0))
4564		      (label_ref (match_operand 0 "" ""))
4565		      (pc)))]
4566  ""
4567  "
4568{
4569  if (TARGET_IEEE_FP
4570      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4571    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4572  else
4573    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4574}")
4575
4576(define_insn ""
4577  [(set (pc)
4578	(if_then_else (ne (cc0)
4579			  (const_int 0))
4580		      (label_ref (match_operand 0 "" ""))
4581		      (pc)))]
4582  ""
4583  "*
4584{
4585  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4586    return \"jc %l0\";
4587  else
4588    return \"jne %l0\";
4589}")
4590
4591(define_expand "bgt"
4592  [(match_dup 1)
4593   (set (pc)
4594	(if_then_else (gt (cc0)
4595			  (const_int 0))
4596		      (label_ref (match_operand 0 "" ""))
4597		      (pc)))]
4598  ""
4599  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4600
4601(define_insn ""
4602  [(set (pc)
4603	(if_then_else (gt (cc0)
4604			  (const_int 0))
4605		      (label_ref (match_operand 0 "" ""))
4606		      (pc)))]
4607  ""
4608  "*
4609{
4610  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4611    return AS1 (je,%l0);
4612
4613  OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
4614}")
4615
4616(define_expand "bgtu"
4617  [(match_dup 1)
4618   (set (pc)
4619	(if_then_else (gtu (cc0)
4620			   (const_int 0))
4621		      (label_ref (match_operand 0 "" ""))
4622		      (pc)))]
4623  ""
4624  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4625
4626(define_insn ""
4627  [(set (pc)
4628	(if_then_else (gtu (cc0)
4629			   (const_int 0))
4630		      (label_ref (match_operand 0 "" ""))
4631		      (pc)))]
4632  ""
4633  "ja %l0")
4634
4635(define_expand "blt"
4636  [(match_dup 1)
4637   (set (pc)
4638	(if_then_else (lt (cc0)
4639			  (const_int 0))
4640		      (label_ref (match_operand 0 "" ""))
4641		      (pc)))]
4642  ""
4643  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4644
4645(define_insn ""
4646  [(set (pc)
4647	(if_then_else (lt (cc0)
4648			  (const_int 0))
4649		      (label_ref (match_operand 0 "" ""))
4650		      (pc)))]
4651  ""
4652  "*
4653{
4654  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4655    return AS1 (je,%l0);
4656
4657  OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
4658}")
4659
4660(define_expand "bltu"
4661  [(match_dup 1)
4662   (set (pc)
4663	(if_then_else (ltu (cc0)
4664			   (const_int 0))
4665		      (label_ref (match_operand 0 "" ""))
4666		      (pc)))]
4667  ""
4668  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4669
4670(define_insn ""
4671  [(set (pc)
4672	(if_then_else (ltu (cc0)
4673			   (const_int 0))
4674		      (label_ref (match_operand 0 "" ""))
4675		      (pc)))]
4676  ""
4677  "jb %l0")
4678
4679(define_expand "bge"
4680  [(match_dup 1)
4681   (set (pc)
4682	(if_then_else (ge (cc0)
4683			  (const_int 0))
4684		      (label_ref (match_operand 0 "" ""))
4685		      (pc)))]
4686  ""
4687  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4688
4689(define_insn ""
4690  [(set (pc)
4691	(if_then_else (ge (cc0)
4692			  (const_int 0))
4693		      (label_ref (match_operand 0 "" ""))
4694		      (pc)))]
4695  ""
4696  "*
4697{
4698  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4699    return AS1 (je,%l0);
4700
4701  OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
4702}")
4703
4704(define_expand "bgeu"
4705  [(match_dup 1)
4706   (set (pc)
4707	(if_then_else (geu (cc0)
4708			   (const_int 0))
4709		      (label_ref (match_operand 0 "" ""))
4710		      (pc)))]
4711  ""
4712  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4713
4714(define_insn ""
4715  [(set (pc)
4716	(if_then_else (geu (cc0)
4717			   (const_int 0))
4718		      (label_ref (match_operand 0 "" ""))
4719		      (pc)))]
4720  ""
4721  "jae %l0")
4722
4723(define_expand "ble"
4724  [(match_dup 1)
4725   (set (pc)
4726	(if_then_else (le (cc0)
4727			  (const_int 0))
4728		      (label_ref (match_operand 0 "" ""))
4729		      (pc)))]
4730  ""
4731  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4732
4733(define_insn ""
4734  [(set (pc)
4735	(if_then_else (le (cc0)
4736			  (const_int 0))
4737		      (label_ref (match_operand 0 "" ""))
4738		      (pc)))]
4739  ""
4740  "*
4741{
4742  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4743    return AS1 (jb,%l0);
4744
4745  OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
4746}")
4747
4748(define_expand "bleu"
4749  [(match_dup 1)
4750   (set (pc)
4751	(if_then_else (leu (cc0)
4752			   (const_int 0))
4753		      (label_ref (match_operand 0 "" ""))
4754		      (pc)))]
4755  ""
4756  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4757
4758(define_insn ""
4759  [(set (pc)
4760	(if_then_else (leu (cc0)
4761			   (const_int 0))
4762		      (label_ref (match_operand 0 "" ""))
4763		      (pc)))]
4764  ""
4765  "jbe %l0")
4766
4767;; Negated conditional jump instructions.
4768
4769(define_insn ""
4770  [(set (pc)
4771	(if_then_else (eq (cc0)
4772			  (const_int 0))
4773		      (pc)
4774		      (label_ref (match_operand 0 "" ""))))]
4775  ""
4776  "*
4777{
4778  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4779    return \"jc %l0\";
4780  else
4781    return \"jne %l0\";
4782}")
4783
4784(define_insn ""
4785  [(set (pc)
4786	(if_then_else (ne (cc0)
4787			  (const_int 0))
4788		      (pc)
4789		      (label_ref (match_operand 0 "" ""))))]
4790  ""
4791  "*
4792{
4793  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4794    return \"jnc %l0\";
4795  else
4796    return \"je %l0\";
4797}")
4798
4799(define_insn ""
4800  [(set (pc)
4801	(if_then_else (gt (cc0)
4802			  (const_int 0))
4803		      (pc)
4804		      (label_ref (match_operand 0 "" ""))))]
4805  ""
4806  "*
4807{
4808  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4809    return AS1 (jne,%l0);
4810
4811  OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
4812}")
4813
4814(define_insn ""
4815  [(set (pc)
4816	(if_then_else (gtu (cc0)
4817			   (const_int 0))
4818		      (pc)
4819		      (label_ref (match_operand 0 "" ""))))]
4820  ""
4821  "jbe %l0")
4822
4823(define_insn ""
4824  [(set (pc)
4825	(if_then_else (lt (cc0)
4826			  (const_int 0))
4827		      (pc)
4828		      (label_ref (match_operand 0 "" ""))))]
4829  ""
4830  "*
4831{
4832  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4833    return AS1 (jne,%l0);
4834
4835  OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
4836}")
4837
4838(define_insn ""
4839  [(set (pc)
4840	(if_then_else (ltu (cc0)
4841			   (const_int 0))
4842		      (pc)
4843		      (label_ref (match_operand 0 "" ""))))]
4844  ""
4845  "jae %l0")
4846
4847(define_insn ""
4848  [(set (pc)
4849	(if_then_else (ge (cc0)
4850			  (const_int 0))
4851		      (pc)
4852		      (label_ref (match_operand 0 "" ""))))]
4853  ""
4854  "*
4855{
4856  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4857    return AS1 (jne,%l0);
4858
4859  OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
4860}")
4861
4862(define_insn ""
4863  [(set (pc)
4864	(if_then_else (geu (cc0)
4865			   (const_int 0))
4866		      (pc)
4867		      (label_ref (match_operand 0 "" ""))))]
4868  ""
4869  "jb %l0")
4870
4871(define_insn ""
4872  [(set (pc)
4873	(if_then_else (le (cc0)
4874			  (const_int 0))
4875		      (pc)
4876		      (label_ref (match_operand 0 "" ""))))]
4877  ""
4878  "*
4879{
4880  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4881    return AS1 (jae,%l0);
4882
4883  OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
4884}")
4885
4886(define_insn ""
4887  [(set (pc)
4888	(if_then_else (leu (cc0)
4889			   (const_int 0))
4890		      (pc)
4891		      (label_ref (match_operand 0 "" ""))))]
4892  ""
4893  "ja %l0")
4894
4895;; Unconditional and other jump instructions
4896
4897(define_insn "jump"
4898  [(set (pc)
4899	(label_ref (match_operand 0 "" "")))]
4900  ""
4901  "jmp %l0")
4902
4903(define_insn "indirect_jump"
4904  [(set (pc) (match_operand:SI 0 "general_operand" "rm"))]
4905  ""
4906  "*
4907{
4908  CC_STATUS_INIT;
4909
4910  return AS1 (jmp,%*%0);
4911}")
4912
4913;; ??? could transform while(--i > 0) S; to if (--i > 0) do S; while(--i);
4914;;     if S does not change i
4915
4916(define_expand "decrement_and_branch_until_zero"
4917  [(parallel [(set (pc)
4918		   (if_then_else (ge (plus:SI (match_operand:SI 0 "general_operand" "")
4919					      (const_int -1))
4920				     (const_int 0))
4921				 (label_ref (match_operand 1 "" ""))
4922				 (pc)))
4923	      (set (match_dup 0)
4924		   (plus:SI (match_dup 0)
4925			    (const_int -1)))])]
4926  ""
4927  "")
4928
4929(define_insn ""
4930  [(set (pc)
4931	(if_then_else (match_operator 0 "arithmetic_comparison_operator"
4932				      [(plus:SI (match_operand:SI 1 "general_operand" "+r,m")
4933						(match_operand:SI 2 "general_operand" "rmi,ri"))
4934				       (const_int 0)])
4935		      (label_ref (match_operand 3 "" ""))
4936		      (pc)))
4937   (set (match_dup 1)
4938	(plus:SI (match_dup 1)
4939		 (match_dup 2)))]
4940  ""
4941  "*
4942{
4943  CC_STATUS_INIT;
4944  if (operands[2] == constm1_rtx)
4945    output_asm_insn (AS1 (dec%L1,%1), operands);
4946
4947  else if (operands[1] == const1_rtx)
4948    output_asm_insn (AS1 (inc%L1,%1), operands);
4949
4950  else
4951    output_asm_insn (AS2 (add%L1,%2,%1), operands);
4952
4953  return AS1 (%J0,%l3);
4954}")
4955
4956(define_insn ""
4957  [(set (pc)
4958	(if_then_else (match_operator 0 "arithmetic_comparison_operator"
4959				      [(minus:SI (match_operand:SI 1 "general_operand" "+r,m")
4960						 (match_operand:SI 2 "general_operand" "rmi,ri"))
4961				       (const_int 0)])
4962		      (label_ref (match_operand 3 "" ""))
4963		      (pc)))
4964   (set (match_dup 1)
4965	(minus:SI (match_dup 1)
4966		  (match_dup 2)))]
4967  ""
4968  "*
4969{
4970  CC_STATUS_INIT;
4971  if (operands[2] == const1_rtx)
4972    output_asm_insn (AS1 (dec%L1,%1), operands);
4973
4974  else if (operands[1] == constm1_rtx)
4975    output_asm_insn (AS1 (inc%L1,%1), operands);
4976
4977  else
4978    output_asm_insn (AS2 (sub%L1,%2,%1), operands);
4979
4980  return AS1 (%J0,%l3);
4981}")
4982
4983;; Implement switch statements when generating PIC code.  Switches are
4984;; implemented by `tablejump' when not using -fpic.
4985
4986;; Emit code here to do the range checking and make the index zero based.
4987
4988(define_expand "casesi"
4989  [(set (match_dup 5)
4990	(minus:SI (match_operand:SI 0 "general_operand" "")
4991		  (match_operand:SI 1 "general_operand" "")))
4992   (set (cc0)
4993	(compare:CC (match_dup 5)
4994		    (match_operand:SI 2 "general_operand" "")))
4995   (set (pc)
4996	(if_then_else (gtu (cc0)
4997			   (const_int 0))
4998		      (label_ref (match_operand 4 "" ""))
4999		      (pc)))
5000   (parallel
5001    [(set (pc)
5002	  (minus:SI (reg:SI 3)
5003		    (mem:SI (plus:SI (mult:SI (match_dup 5)
5004					      (const_int 4))
5005				     (label_ref (match_operand 3 "" ""))))))
5006     (clobber (match_scratch:SI 6 ""))])]
5007  "flag_pic"
5008  "
5009{
5010  operands[5] = gen_reg_rtx (SImode);
5011  current_function_uses_pic_offset_table = 1;
5012}")
5013
5014;; Implement a casesi insn.
5015
5016;; Each entry in the "addr_diff_vec" looks like this as the result of the
5017;; two rules below:
5018;; 
5019;; 	.long _GLOBAL_OFFSET_TABLE_+[.-.L2]
5020;; 
5021;; 1. An expression involving an external reference may only use the
5022;;    addition operator, and only with an assembly-time constant.
5023;;    The example above satisfies this because ".-.L2" is a constant.
5024;; 
5025;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is
5026;;    given the value of "GOT - .", where GOT is the actual address of
5027;;    the Global Offset Table.  Therefore, the .long above actually
5028;;    stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2".  The
5029;;    expression "GOT - .L2" by itself would generate an error from as(1).
5030;; 
5031;; The pattern below emits code that looks like this:
5032;; 
5033;; 	movl %ebx,reg
5034;; 	subl TABLE@GOTOFF(%ebx,index,4),reg
5035;; 	jmp reg
5036;; 
5037;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since
5038;; the addr_diff_vec is known to be part of this module.
5039;; 
5040;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which
5041;; evaluates to just ".L2".
5042
5043(define_insn ""
5044  [(set (pc)
5045	(minus:SI (reg:SI 3)
5046		  (mem:SI (plus:SI
5047			   (mult:SI (match_operand:SI 0 "register_operand" "r")
5048				    (const_int 4))
5049			   (label_ref (match_operand 1 "" ""))))))
5050   (clobber (match_scratch:SI 2 "=&r"))]
5051  ""
5052  "*
5053{
5054  rtx xops[4];
5055
5056  xops[0] = operands[0];
5057  xops[1] = operands[1];
5058  xops[2] = operands[2];
5059  xops[3] = pic_offset_table_rtx;
5060
5061  output_asm_insn (AS2 (mov%L2,%3,%2), xops);
5062  output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops);
5063  output_asm_insn (AS1 (jmp,%*%2), xops);
5064  ASM_OUTPUT_ALIGN_CODE (asm_out_file);
5065  RET;
5066}")
5067
5068(define_insn "tablejump"
5069  [(set (pc) (match_operand:SI 0 "general_operand" "rm"))
5070   (use (label_ref (match_operand 1 "" "")))]
5071  ""
5072  "*
5073{
5074  CC_STATUS_INIT;
5075
5076  return AS1 (jmp,%*%0);
5077}")
5078
5079;; Call insns.
5080
5081;; If generating PIC code, the predicate indirect_operand will fail
5082;; for operands[0] containing symbolic references on all of the named
5083;; call* patterns.  Each named pattern is followed by an unnamed pattern
5084;; that matches any call to a symbolic CONST (ie, a symbol_ref).  The
5085;; unnamed patterns are only used while generating PIC code, because
5086;; otherwise the named patterns match.
5087
5088;; Call subroutine returning no value.
5089
5090(define_expand "call_pop"
5091  [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
5092		    (match_operand:SI 1 "general_operand" ""))
5093	      (set (reg:SI 7)
5094		   (plus:SI (reg:SI 7)
5095			    (match_operand:SI 3 "immediate_operand" "")))])]
5096  ""
5097  "
5098{
5099  rtx addr;
5100
5101  if (flag_pic)
5102    current_function_uses_pic_offset_table = 1;
5103
5104  /* With half-pic, force the address into a register.  */
5105  addr = XEXP (operands[0], 0);
5106  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
5107    XEXP (operands[0], 0) = force_reg (Pmode, addr);
5108
5109  if (! expander_call_insn_operand (operands[0], QImode))
5110    operands[0]
5111      = change_address (operands[0], VOIDmode,
5112			copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
5113}")
5114
5115(define_insn ""
5116  [(call (match_operand:QI 0 "call_insn_operand" "m")
5117	 (match_operand:SI 1 "general_operand" "g"))
5118   (set (reg:SI 7) (plus:SI (reg:SI 7)
5119			    (match_operand:SI 3 "immediate_operand" "i")))]
5120  ""
5121  "*
5122{
5123  if (GET_CODE (operands[0]) == MEM
5124      && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
5125    {
5126      operands[0] = XEXP (operands[0], 0);
5127      return AS1 (call,%*%0);
5128    }
5129  else
5130    return AS1 (call,%P0);
5131}")
5132
5133(define_insn ""
5134  [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
5135	 (match_operand:SI 1 "general_operand" "g"))
5136   (set (reg:SI 7) (plus:SI (reg:SI 7)
5137			    (match_operand:SI 3 "immediate_operand" "i")))]
5138  "!HALF_PIC_P ()"
5139  "call %P0")
5140
5141(define_expand "call"
5142  [(call (match_operand:QI 0 "indirect_operand" "")
5143	 (match_operand:SI 1 "general_operand" ""))]
5144  ;; Operand 1 not used on the i386.
5145  ""
5146  "
5147{
5148  rtx addr;
5149
5150  if (flag_pic)
5151    current_function_uses_pic_offset_table = 1;
5152
5153  /* With half-pic, force the address into a register.  */
5154  addr = XEXP (operands[0], 0);
5155  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
5156    XEXP (operands[0], 0) = force_reg (Pmode, addr);
5157
5158  if (! expander_call_insn_operand (operands[0], QImode))
5159    operands[0]
5160      = change_address (operands[0], VOIDmode,
5161			copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
5162}")
5163
5164(define_insn ""
5165  [(call (match_operand:QI 0 "call_insn_operand" "m")
5166	 (match_operand:SI 1 "general_operand" "g"))]
5167  ;; Operand 1 not used on the i386.
5168  ""
5169  "*
5170{
5171  if (GET_CODE (operands[0]) == MEM
5172      && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
5173    {
5174      operands[0] = XEXP (operands[0], 0);
5175      return AS1 (call,%*%0);
5176    }
5177  else
5178    return AS1 (call,%P0);
5179}")
5180
5181(define_insn ""
5182  [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
5183	 (match_operand:SI 1 "general_operand" "g"))]
5184  ;; Operand 1 not used on the i386.
5185  "!HALF_PIC_P ()"
5186  "call %P0")
5187
5188;; Call subroutine, returning value in operand 0
5189;; (which must be a hard register).
5190
5191(define_expand "call_value_pop"
5192  [(parallel [(set (match_operand 0 "" "")
5193		   (call (match_operand:QI 1 "indirect_operand" "")
5194			 (match_operand:SI 2 "general_operand" "")))
5195	      (set (reg:SI 7)
5196		   (plus:SI (reg:SI 7)
5197			    (match_operand:SI 4 "immediate_operand" "")))])]
5198  ""
5199  "
5200{
5201  rtx addr;
5202
5203  if (flag_pic)
5204    current_function_uses_pic_offset_table = 1;
5205
5206  /* With half-pic, force the address into a register.  */
5207  addr = XEXP (operands[1], 0);
5208  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
5209    XEXP (operands[1], 0) = force_reg (Pmode, addr);
5210
5211  if (! expander_call_insn_operand (operands[1], QImode))
5212    operands[1]
5213      = change_address (operands[1], VOIDmode,
5214			copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
5215}")
5216
5217(define_insn ""
5218  [(set (match_operand 0 "" "=rf")
5219	(call (match_operand:QI 1 "call_insn_operand" "m")
5220	      (match_operand:SI 2 "general_operand" "g")))
5221   (set (reg:SI 7) (plus:SI (reg:SI 7)
5222			    (match_operand:SI 4 "immediate_operand" "i")))]
5223  ""
5224  "*
5225{
5226  if (GET_CODE (operands[1]) == MEM
5227      && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
5228    {
5229      operands[1] = XEXP (operands[1], 0);
5230      output_asm_insn (AS1 (call,%*%1), operands);
5231    }
5232  else
5233    output_asm_insn (AS1 (call,%P1), operands);
5234
5235  RET;
5236}")
5237
5238(define_insn ""
5239  [(set (match_operand 0 "" "=rf")
5240	(call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
5241	      (match_operand:SI 2 "general_operand" "g")))
5242   (set (reg:SI 7) (plus:SI (reg:SI 7)
5243			    (match_operand:SI 4 "immediate_operand" "i")))]
5244  "!HALF_PIC_P ()"
5245  "call %P1")
5246
5247(define_expand "call_value"
5248  [(set (match_operand 0 "" "")
5249	(call (match_operand:QI 1 "indirect_operand" "")
5250	      (match_operand:SI 2 "general_operand" "")))]
5251  ;; Operand 2 not used on the i386.
5252  ""
5253  "
5254{
5255  rtx addr;
5256
5257  if (flag_pic)
5258    current_function_uses_pic_offset_table = 1;
5259
5260  /* With half-pic, force the address into a register.  */
5261  addr = XEXP (operands[1], 0);
5262  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
5263    XEXP (operands[1], 0) = force_reg (Pmode, addr);
5264
5265  if (! expander_call_insn_operand (operands[1], QImode))
5266    operands[1]
5267      = change_address (operands[1], VOIDmode,
5268			copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
5269}")
5270
5271(define_insn ""
5272  [(set (match_operand 0 "" "=rf")
5273	(call (match_operand:QI 1 "call_insn_operand" "m")
5274	      (match_operand:SI 2 "general_operand" "g")))]
5275  ;; Operand 2 not used on the i386.
5276  ""
5277  "*
5278{
5279  if (GET_CODE (operands[1]) == MEM
5280      && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
5281    {
5282      operands[1] = XEXP (operands[1], 0);
5283      output_asm_insn (AS1 (call,%*%1), operands);
5284    }
5285  else
5286    output_asm_insn (AS1 (call,%P1), operands);
5287
5288  RET;
5289}")
5290
5291(define_insn ""
5292  [(set (match_operand 0 "" "=rf")
5293	(call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
5294	      (match_operand:SI 2 "general_operand" "g")))]
5295  ;; Operand 2 not used on the i386.
5296  "!HALF_PIC_P ()"
5297  "call %P1")
5298
5299;; Call subroutine returning any type.
5300
5301(define_expand "untyped_call"
5302  [(parallel [(call (match_operand 0 "" "")
5303		    (const_int 0))
5304	      (match_operand 1 "" "")
5305	      (match_operand 2 "" "")])]
5306  ""
5307  "
5308{
5309  int i;
5310
5311  /* In order to give reg-stack an easier job in validating two
5312     coprocessor registers as containing a possible return value,
5313     simply pretend the untyped call returns a complex long double
5314     value.  */
5315#if 1
5316  /* this may be part of (set (reg: ..) (call_insn ...)), and we can't
5317     directly set a fp register from the call.  so we revert to the
5318     old behavior - jlemon@netcom.com (Jonathan Lemon) */
5319  emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
5320#else
5321  emit_call_insn (TARGET_80387
5322                  ? gen_call_value (gen_rtx (REG, XCmode, FIRST_FLOAT_REG),
5323		                  operands[0], const0_rtx)
5324                  : gen_call (operands[0], const0_rtx));
5325#endif
5326
5327  for (i = 0; i < XVECLEN (operands[2], 0); i++)
5328    {
5329      rtx set = XVECEXP (operands[2], 0, i);
5330      emit_move_insn (SET_DEST (set), SET_SRC (set));
5331    }
5332
5333  /* The optimizer does not know that the call sets the function value
5334     registers we stored in the result block.  We avoid problems by
5335     claiming that all hard registers are used and clobbered at this
5336     point.  */
5337  emit_insn (gen_blockage ());
5338
5339  DONE;
5340}")
5341
5342;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5343;; all of memory.  This blocks insns from being moved across this point.
5344
5345(define_insn "blockage"
5346  [(unspec_volatile [(const_int 0)] 0)]
5347  ""
5348  "")
5349
5350;; Insn emitted into the body of a function to return from a function.
5351;; This is only done if the function's epilogue is known to be simple.
5352;; See comments for simple_386_epilogue in i386.c.
5353
5354(define_insn "return"
5355  [(return)]
5356  "simple_386_epilogue ()"
5357  "*
5358{
5359  function_epilogue (asm_out_file, get_frame_size ());
5360  RET;
5361}")
5362
5363(define_insn "nop"
5364  [(const_int 0)]
5365  ""
5366  "nop")
5367
5368(define_expand "movstrsi"
5369  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
5370		   (match_operand:BLK 1 "memory_operand" ""))
5371	      (use (match_operand:SI 2 "const_int_operand" ""))
5372	      (use (match_operand:SI 3 "const_int_operand" ""))
5373	      (clobber (match_scratch:SI 4 ""))
5374	      (clobber (match_dup 5))
5375	      (clobber (match_dup 6))])]
5376  ""
5377  "
5378{
5379  rtx addr0, addr1;
5380
5381  if (GET_CODE (operands[2]) != CONST_INT)
5382    FAIL;
5383
5384  addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
5385  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
5386
5387  operands[5] = addr0;
5388  operands[6] = addr1;
5389
5390  operands[0] = gen_rtx (MEM, BLKmode, addr0);
5391  operands[1] = gen_rtx (MEM, BLKmode, addr1);
5392}")
5393
5394;; It might seem that operands 0 & 1 could use predicate register_operand.
5395;; But strength reduction might offset the MEM expression.  So we let
5396;; reload put the address into %edi & %esi.
5397
5398(define_insn ""
5399  [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
5400	(mem:BLK (match_operand:SI 1 "address_operand" "S")))
5401   (use (match_operand:SI 2 "const_int_operand" "n"))
5402   (use (match_operand:SI 3 "immediate_operand" "i"))
5403   (clobber (match_scratch:SI 4 "=&c"))
5404   (clobber (match_dup 0))
5405   (clobber (match_dup 1))]
5406  ""
5407  "*
5408{
5409  rtx xops[2];
5410
5411  output_asm_insn (\"cld\", operands);
5412  if (GET_CODE (operands[2]) == CONST_INT)
5413    {
5414      if (INTVAL (operands[2]) & ~0x03)
5415	{
5416	  xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff);
5417	  xops[1] = operands[4];
5418
5419	  output_asm_insn (AS2 (mov%L1,%0,%1), xops);
5420#ifdef INTEL_SYNTAX
5421	  output_asm_insn (\"rep movsd\", xops);
5422#else
5423	  output_asm_insn (\"rep\;movsl\", xops);
5424#endif
5425	}
5426      if (INTVAL (operands[2]) & 0x02)
5427	output_asm_insn (\"movsw\", operands);
5428      if (INTVAL (operands[2]) & 0x01)
5429	output_asm_insn (\"movsb\", operands);
5430    }
5431  else
5432    abort ();
5433  RET;
5434}")
5435
5436(define_expand "cmpstrsi"
5437  [(parallel [(set (match_operand:SI 0 "general_operand" "")
5438		   (compare:SI (match_operand:BLK 1 "general_operand" "")
5439			       (match_operand:BLK 2 "general_operand" "")))
5440	      (use (match_operand:SI 3 "general_operand" ""))
5441	      (use (match_operand:SI 4 "immediate_operand" ""))
5442	      (clobber (match_dup 5))
5443	      (clobber (match_dup 6))
5444	      (clobber (match_dup 3))])]
5445  ""
5446  "
5447{
5448  rtx addr1, addr2;
5449
5450  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
5451  addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
5452  operands[3] = copy_to_mode_reg (SImode, operands[3]);
5453
5454  operands[5] = addr1;
5455  operands[6] = addr2;
5456
5457  operands[1] = gen_rtx (MEM, BLKmode, addr1);
5458  operands[2] = gen_rtx (MEM, BLKmode, addr2);
5459
5460}")
5461
5462;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
5463;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
5464
5465;; It might seem that operands 0 & 1 could use predicate register_operand.
5466;; But strength reduction might offset the MEM expression.  So we let
5467;; reload put the address into %edi & %esi.
5468
5469;; ??? Most comparisons have a constant length, and it's therefore
5470;; possible to know that the length is non-zero, and to avoid the extra
5471;; code to handle zero-length compares.
5472
5473(define_insn ""
5474  [(set (match_operand:SI 0 "general_operand" "=&r")
5475	(compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S"))
5476		    (mem:BLK (match_operand:SI 2 "address_operand" "D"))))
5477   (use (match_operand:SI 3 "register_operand" "c"))
5478   (use (match_operand:SI 4 "immediate_operand" "i"))
5479   (clobber (match_dup 1))
5480   (clobber (match_dup 2))
5481   (clobber (match_dup 3))]
5482  ""
5483  "*
5484{
5485  rtx xops[4], label;
5486
5487  label = gen_label_rtx ();
5488
5489  output_asm_insn (\"cld\", operands);
5490  output_asm_insn (AS2 (xor%L0,%0,%0), operands);
5491  output_asm_insn (\"repz\;cmps%B2\", operands);
5492  output_asm_insn (\"je %l0\", &label);
5493
5494  xops[0] = operands[0];
5495  xops[1] = gen_rtx (MEM, QImode,
5496		     gen_rtx (PLUS, SImode, operands[1], constm1_rtx));
5497  xops[2] = gen_rtx (MEM, QImode,
5498		     gen_rtx (PLUS, SImode, operands[2], constm1_rtx));
5499  xops[3] = operands[3];
5500
5501  output_asm_insn (AS2 (movz%B1%L0,%1,%0), xops);
5502  output_asm_insn (AS2 (movz%B2%L3,%2,%3), xops);
5503
5504  output_asm_insn (AS2 (sub%L0,%3,%0), xops);
5505  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label));
5506  RET;
5507}")
5508
5509(define_insn ""
5510  [(set (cc0)
5511	(compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
5512		    (mem:BLK (match_operand:SI 1 "address_operand" "D"))))
5513   (use (match_operand:SI 2 "register_operand" "c"))
5514   (use (match_operand:SI 3 "immediate_operand" "i"))
5515   (clobber (match_dup 0))
5516   (clobber (match_dup 1))
5517   (clobber (match_dup 2))]
5518  ""
5519  "*
5520{
5521  rtx xops[2];
5522
5523  cc_status.flags |= CC_NOT_SIGNED;
5524
5525  xops[0] = gen_rtx (REG, QImode, 0);
5526  xops[1] = CONST0_RTX (QImode);
5527
5528  output_asm_insn (\"cld\", operands);
5529  output_asm_insn (AS2 (test%B0,%1,%0), xops);
5530  return \"repz\;cmps%B2\";
5531}")
5532
5533(define_expand "ffssi2"
5534  [(set (match_dup 2)
5535	(plus:SI (ffs:SI (match_operand:SI 1 "general_operand" ""))
5536		 (const_int -1)))
5537   (set (match_operand:SI 0 "general_operand" "")
5538	(plus:SI (match_dup 2) (const_int 1)))]
5539  ""
5540  "operands[2] = gen_reg_rtx (SImode);")
5541
5542;; Note, you cannot optimize away the branch following the bsfl by assuming
5543;; that the destination is not modified if the input is 0, since not all
5544;; x86 implementations do this.
5545
5546(define_insn ""
5547  [(set (match_operand:SI 0 "general_operand" "=&r")
5548	(plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "rm"))
5549		 (const_int -1)))]
5550  ""
5551  "*
5552{
5553  rtx xops[3];
5554  static int ffssi_label_number;
5555  char buffer[30];
5556
5557  xops[0] = operands[0];
5558  xops[1] = operands[1];
5559  xops[2] = constm1_rtx;
5560  output_asm_insn (AS2 (bsf%L0,%1,%0), xops);
5561#ifdef LOCAL_LABEL_PREFIX
5562  sprintf (buffer, \"jnz %sLFFSSI%d\",
5563	   LOCAL_LABEL_PREFIX, ffssi_label_number);
5564#else
5565  sprintf (buffer, \"jnz %sLFFSSI%d\",
5566	   \"\", ffssi_label_number);
5567#endif
5568  output_asm_insn (buffer, xops);
5569  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
5570#ifdef LOCAL_LABEL_PREFIX
5571  sprintf (buffer, \"%sLFFSSI%d:\",
5572	   LOCAL_LABEL_PREFIX, ffssi_label_number);
5573#else
5574  sprintf (buffer, \"%sLFFSSI%d:\",
5575	   \"\", ffssi_label_number);
5576#endif
5577  output_asm_insn (buffer, xops);
5578
5579  ffssi_label_number++;
5580  return \"\";
5581}")
5582
5583(define_expand "ffshi2"
5584  [(set (match_dup 2)
5585	(plus:HI (ffs:HI (match_operand:HI 1 "general_operand" ""))
5586		 (const_int -1)))
5587   (set (match_operand:HI 0 "general_operand" "")
5588	(plus:HI (match_dup 2) (const_int 1)))]
5589  ""
5590  "operands[2] = gen_reg_rtx (HImode);")
5591
5592(define_insn ""
5593  [(set (match_operand:HI 0 "general_operand" "=&r")
5594	(plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm"))
5595		 (const_int -1)))]
5596  ""
5597  "*
5598{
5599  rtx xops[3];
5600  static int ffshi_label_number;
5601  char buffer[30];
5602
5603  xops[0] = operands[0];
5604  xops[1] = operands[1];
5605  xops[2] = constm1_rtx;
5606  output_asm_insn (AS2 (bsf%W0,%1,%0), xops);
5607#ifdef LOCAL_LABEL_PREFIX
5608  sprintf (buffer, \"jnz %sLFFSHI%d\",
5609	   LOCAL_LABEL_PREFIX, ffshi_label_number);
5610#else
5611  sprintf (buffer, \"jnz %sLFFSHI%d\",
5612	   \"\", ffshi_label_number);
5613#endif
5614  output_asm_insn (buffer, xops);
5615  output_asm_insn (AS2 (mov%W0,%2,%0), xops);
5616#ifdef LOCAL_LABEL_PREFIX
5617  sprintf (buffer, \"%sLFFSHI%d:\",
5618	   LOCAL_LABEL_PREFIX, ffshi_label_number);
5619#else
5620  sprintf (buffer, \"%sLFFSHI%d:\",
5621	   \"\", ffshi_label_number);
5622#endif
5623  output_asm_insn (buffer, xops);
5624
5625  ffshi_label_number++;
5626  return \"\";
5627}")
5628
5629;; These patterns match the binary 387 instructions for addM3, subM3,
5630;; mulM3 and divM3.  There are three patterns for each of DFmode and
5631;; SFmode.  The first is the normal insn, the second the same insn but
5632;; with one operand a conversion, and the third the same insn but with
5633;; the other operand a conversion.  The conversion may be SFmode or
5634;; SImode if the target mode DFmode, but only SImode if the target mode
5635;; is SFmode.
5636
5637(define_insn ""
5638  [(set (match_operand:DF 0 "register_operand" "=f,f")
5639	(match_operator:DF 3 "binary_387_op"
5640			[(match_operand:DF 1 "nonimmediate_operand" "0,fm")
5641			 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
5642  "TARGET_80387"
5643  "* return output_387_binary_op (insn, operands);")
5644
5645(define_insn ""
5646  [(set (match_operand:DF 0 "register_operand" "=f")
5647	(match_operator:DF 3 "binary_387_op"
5648	   [(float:DF (match_operand:SI 1 "general_operand" "rm"))
5649	    (match_operand:DF 2 "general_operand" "0")]))]
5650  "TARGET_80387"
5651  "* return output_387_binary_op (insn, operands);")
5652
5653(define_insn ""
5654  [(set (match_operand:XF 0 "register_operand" "=f,f")
5655	(match_operator:XF 3 "binary_387_op"
5656			[(match_operand:XF 1 "nonimmediate_operand" "0,f")
5657			 (match_operand:XF 2 "nonimmediate_operand" "f,0")]))]
5658  "TARGET_80387"
5659  "* return output_387_binary_op (insn, operands);")
5660
5661(define_insn ""
5662  [(set (match_operand:XF 0 "register_operand" "=f")
5663	(match_operator:XF 3 "binary_387_op"
5664	   [(float:XF (match_operand:SI 1 "general_operand" "rm"))
5665	    (match_operand:XF 2 "general_operand" "0")]))]
5666  "TARGET_80387"
5667  "* return output_387_binary_op (insn, operands);")
5668
5669(define_insn ""
5670  [(set (match_operand:XF 0 "register_operand" "=f,f")
5671	(match_operator:XF 3 "binary_387_op"
5672	   [(float_extend:XF (match_operand:SF 1 "general_operand" "fm,0"))
5673	    (match_operand:XF 2 "general_operand" "0,f")]))]
5674  "TARGET_80387"
5675  "* return output_387_binary_op (insn, operands);")
5676
5677(define_insn ""
5678  [(set (match_operand:XF 0 "register_operand" "=f")
5679	(match_operator:XF 3 "binary_387_op"
5680	  [(match_operand:XF 1 "general_operand" "0")
5681	   (float:XF (match_operand:SI 2 "general_operand" "rm"))]))]
5682  "TARGET_80387"
5683  "* return output_387_binary_op (insn, operands);")
5684
5685(define_insn ""
5686  [(set (match_operand:XF 0 "register_operand" "=f,f")
5687	(match_operator:XF 3 "binary_387_op"
5688	  [(match_operand:XF 1 "general_operand" "0,f")
5689	   (float_extend:XF
5690	    (match_operand:SF 2 "general_operand" "fm,0"))]))]
5691  "TARGET_80387"
5692  "* return output_387_binary_op (insn, operands);")
5693
5694(define_insn ""
5695  [(set (match_operand:DF 0 "register_operand" "=f,f")
5696	(match_operator:DF 3 "binary_387_op"
5697	   [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0"))
5698	    (match_operand:DF 2 "general_operand" "0,f")]))]
5699  "TARGET_80387"
5700  "* return output_387_binary_op (insn, operands);")
5701
5702(define_insn ""
5703  [(set (match_operand:DF 0 "register_operand" "=f")
5704	(match_operator:DF 3 "binary_387_op"
5705	  [(match_operand:DF 1 "general_operand" "0")
5706	   (float:DF (match_operand:SI 2 "general_operand" "rm"))]))]
5707  "TARGET_80387"
5708  "* return output_387_binary_op (insn, operands);")
5709
5710(define_insn ""
5711  [(set (match_operand:DF 0 "register_operand" "=f,f")
5712	(match_operator:DF 3 "binary_387_op"
5713	  [(match_operand:DF 1 "general_operand" "0,f")
5714	   (float_extend:DF
5715	    (match_operand:SF 2 "general_operand" "fm,0"))]))]
5716  "TARGET_80387"
5717  "* return output_387_binary_op (insn, operands);")
5718
5719(define_insn ""
5720  [(set (match_operand:SF 0 "register_operand" "=f,f")
5721	(match_operator:SF 3 "binary_387_op"
5722			[(match_operand:SF 1 "nonimmediate_operand" "0,fm")
5723			 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
5724  "TARGET_80387"
5725  "* return output_387_binary_op (insn, operands);")
5726
5727(define_insn ""
5728  [(set (match_operand:SF 0 "register_operand" "=f")
5729	(match_operator:SF 3 "binary_387_op"
5730	  [(float:SF (match_operand:SI 1 "general_operand" "rm"))
5731	   (match_operand:SF 2 "general_operand" "0")]))]
5732  "TARGET_80387"
5733  "* return output_387_binary_op (insn, operands);")
5734
5735(define_insn ""
5736  [(set (match_operand:SF 0 "register_operand" "=f")
5737	(match_operator:SF 3 "binary_387_op"
5738	  [(match_operand:SF 1 "general_operand" "0")
5739	   (float:SF (match_operand:SI 2 "general_operand" "rm"))]))]
5740  "TARGET_80387"
5741  "* return output_387_binary_op (insn, operands);")
5742
5743(define_expand "strlensi"
5744  [(parallel [(set (match_dup 4)
5745		   (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" ""))
5746			       (match_operand:QI 2 "register_operand" "")
5747			       (match_operand:SI 3 "immediate_operand" "")] 0))
5748	      (clobber (match_dup 1))])
5749   (set (match_dup 5)
5750	(not:SI (match_dup 4)))
5751   (set (match_operand:SI 0 "register_operand" "")
5752	(minus:SI (match_dup 5)
5753		 (const_int 1)))]
5754  ""
5755  "
5756{
5757  operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5758  operands[4] = gen_reg_rtx (SImode);
5759  operands[5] = gen_reg_rtx (SImode);
5760}")
5761
5762;; It might seem that operands 0 & 1 could use predicate register_operand.
5763;; But strength reduction might offset the MEM expression.  So we let
5764;; reload put the address into %edi.
5765
5766(define_insn ""
5767  [(set (match_operand:SI 0 "register_operand" "=&c")
5768	(unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D"))
5769		    (match_operand:QI 2 "register_operand" "a")
5770		    (match_operand:SI 3 "immediate_operand" "i")] 0))
5771   (clobber (match_dup 1))]
5772  ""
5773  "*
5774{
5775  rtx xops[2];
5776
5777  xops[0] = operands[0];
5778  xops[1] = constm1_rtx;
5779  output_asm_insn (\"cld\", operands);
5780  output_asm_insn (AS2 (mov%L0,%1,%0), xops);
5781  return \"repnz\;scas%B2\";
5782}")
5783