i386.md revision 50650
1; GCC machine description for Intel X86.
2;; Copyright (C) 1988, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
3;; Mostly by William Schelter.
4
5;; This file is part of GNU CC.
6
7;; GNU CC is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 2, or (at your option)
10;; any later version.
11
12;; GNU CC is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU CC; see the file COPYING.  If not, write to
19;; the Free Software Foundation, 59 Temple Place - Suite 330,
20;; Boston, MA 02111-1307, USA. */
21
22;; The original PO technology requires these to be ordered by speed,
23;; so that assigner will pick the fastest.
24
25;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code
28;; updates for most instructions.
29
30;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register
31;; constraint letters.
32
33;; the special asm out single letter directives following a '%' are:
34;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of
35;;     operands[1].
36;; 'L' Print the opcode suffix for a 32-bit integer opcode.
37;; 'W' Print the opcode suffix for a 16-bit integer opcode.
38;; 'B' Print the opcode suffix for an 8-bit integer opcode.
39;; 'Q' Print the opcode suffix for a 64-bit float opcode.
40;; 'S' Print the opcode suffix for a 32-bit float opcode.
41;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode.
42;; 'J' Print the appropriate jump operand.
43
44;; 'b' Print the QImode name of the register for the indicated operand.
45;;     %b0 would print %al if operands[0] is reg 0.
46;; 'w' Likewise, print the HImode name of the register.
47;; 'k' Likewise, print the SImode name of the register.
48;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh.
49;; 'y' Print "st(0)" instead of "st" as a register.
50
51;; UNSPEC usage:
52;; 0  This is a `scas' operation.  The mode of the UNSPEC is always SImode.
53;;    operand 0 is the memory address to scan.
54;;    operand 1 is a register containing the value to scan for.  The mode
55;;       of the scas opcode will be the same as the mode of this operand.
56;;    operand 2 is the known alignment of operand 0.
57;; 1  This is a `sin' operation.  The mode of the UNSPEC is MODE_FLOAT.
58;;    operand 0 is the argument for `sin'.
59;; 2  This is a `cos' operation.  The mode of the UNSPEC is MODE_FLOAT.
60;;    operand 0 is the argument for `cos'.
61;; 3  This is part of a `stack probe' operation.  The mode of the UNSPEC is 
62;;    always SImode.  operand 0 is the size of the stack allocation.
63;; 4  This is the source of a fake SET of the frame pointer which is used to
64;;    prevent insns referencing it being scheduled across the initial
65;;    decrement of the stack pointer.
66;; 5  This is a `bsf' operation.
67
68;; This shadows the processor_type enumeration, so changes must be made
69;; to i386.h at the same time.
70
71(define_attr "type" "integer,idiv,imul,fld,fpop,fpdiv,fpmul"
72  (const_string "integer"))
73
74;; Functional units
75
76; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
77;                       TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
78
79; pentiumpro has a reservation station with 5 ports
80; port  0 has integer, float add, integer divide, float divide, float 
81;        multiply, and shifter units.
82; port  1 has integer, and jump units.
83; port  2 has the load address generation unit
84; ports 3 and 4 have the store address generation units
85
86; pentium has two integer pipelines, the main u pipe and the secondary v pipe.
87; and a float pipeline
88
89;; Floating point
90
91(define_function_unit "fp" 1 0
92 (and (eq_attr "type" "fpop") (eq_attr "cpu" "i386,i486"))
93 5 5)
94
95(define_function_unit "fp" 1 0
96 (and (eq_attr "type" "fpop") (eq_attr "cpu" "pentium,pentiumpro")) 
97 3 0)
98
99(define_function_unit "fp" 1 0
100 (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentium")) 
101 7 0)
102
103(define_function_unit "fp" 1 0
104 (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentiumpro")) 
105 5 0)
106
107(define_function_unit "fp" 1 0
108 (and (eq_attr "type" "idiv") (eq_attr "cpu" "pentiumpro")) 
109 10 10)
110
111(define_function_unit "fp" 1 0
112 (and (eq_attr "type" "imul") (eq_attr "cpu" "pentiumpro")) 
113 6 0)
114
115(define_function_unit "fp" 1 0
116 (eq_attr "type" "fpdiv") 
117 10 10)
118
119(define_function_unit "fp" 1 0
120 (eq_attr "type" "fld") 
121 1 0)
122
123(define_function_unit "integer" 1 0
124  (and (eq_attr "type" "integer") (eq_attr "cpu" "!i386"))
125 2 0)
126
127
128;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM".
129;; But restricting MEM here would mean that gcc could not remove a redundant
130;; test in cases like "incl MEM / je TARGET".
131;;
132;; We don't want to allow a constant operand for test insns because
133;; (set (cc0) (const_int foo)) has no mode information.  Such insns will
134;; be folded while optimizing anyway.
135
136;; All test insns have expanders that save the operands away without
137;; actually generating RTL.  The bCOND or sCOND (emitted immediately
138;; after the tstM or cmp) will actually emit the tstM or cmpM.
139
140;; Processor type -- this attribute must exactly match the processor_type
141;; enumeration in i386.h.
142
143(define_attr "cpu" "i386,i486,pentium,pentiumpro"
144  (const (symbol_ref "ix86_cpu")))
145
146(define_insn "tstsi_1"
147  [(set (cc0)
148	(match_operand:SI 0 "nonimmediate_operand" "rm"))]
149  ""
150  "*
151{
152  if (REG_P (operands[0]))
153    return AS2 (test%L0,%0,%0);
154
155  operands[1] = const0_rtx;
156  return AS2 (cmp%L0,%1,%0);
157}")
158
159(define_expand "tstsi"
160  [(set (cc0)
161	(match_operand:SI 0 "nonimmediate_operand" ""))]
162  ""
163  "
164{
165  i386_compare_gen = gen_tstsi_1;
166  i386_compare_op0 = operands[0];
167  i386_compare_op1 = const0_rtx;
168  DONE;
169}")
170
171(define_insn "tsthi_1"
172  [(set (cc0)
173	(match_operand:HI 0 "nonimmediate_operand" "rm"))]
174  ""
175  "*
176{
177  if (REG_P (operands[0]))
178    return AS2 (test%W0,%0,%0);
179
180  operands[1] = const0_rtx;
181  return AS2 (cmp%W0,%1,%0);
182}")
183
184(define_expand "tsthi"
185  [(set (cc0)
186	(match_operand:HI 0 "nonimmediate_operand" ""))]
187  ""
188  "
189{
190  i386_compare_gen = gen_tsthi_1;
191  i386_compare_op0 = operands[0];
192  i386_compare_op1 = const0_rtx;
193  DONE;
194}")
195
196(define_insn "tstqi_1"
197  [(set (cc0)
198	(match_operand:QI 0 "nonimmediate_operand" "qm"))]
199  ""
200  "*
201{
202  if (REG_P (operands[0]))
203    return AS2 (test%B0,%0,%0);
204
205  operands[1] = const0_rtx;
206  return AS2 (cmp%B0,%1,%0);
207}")
208
209(define_expand "tstqi"
210  [(set (cc0)
211	(match_operand:QI 0 "nonimmediate_operand" ""))]
212  ""
213  "
214{
215  i386_compare_gen = gen_tstqi_1;
216  i386_compare_op0 = operands[0];
217  i386_compare_op1 = const0_rtx;
218  DONE;
219}")
220
221(define_insn "tstsf_cc"
222  [(set (cc0)
223	(match_operand:SF 0 "register_operand" "f"))
224   (clobber (match_scratch:HI 1 "=a"))]
225  "TARGET_80387 && ! TARGET_IEEE_FP"
226  "*
227{
228  if (! STACK_TOP_P (operands[0]))
229    abort ();
230
231  output_asm_insn (\"ftst\", operands);
232
233  if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
234    output_asm_insn (AS1 (fstp,%y0), operands);
235
236  return output_fp_cc0_set (insn);
237}")
238
239;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode
240;; isn't IEEE compliant.
241
242(define_expand "tstsf"
243  [(parallel [(set (cc0)
244		   (match_operand:SF 0 "register_operand" ""))
245	      (clobber (match_scratch:HI 1 ""))])]
246  "TARGET_80387 && ! TARGET_IEEE_FP"
247  "
248{
249  i386_compare_gen = gen_tstsf_cc;
250  i386_compare_op0 = operands[0];
251  i386_compare_op1 = const0_rtx;
252  DONE;
253}")
254
255(define_insn "tstdf_cc"
256  [(set (cc0)
257	(match_operand:DF 0 "register_operand" "f"))
258   (clobber (match_scratch:HI 1 "=a"))]
259  "TARGET_80387 && ! TARGET_IEEE_FP"
260  "*
261{
262  if (! STACK_TOP_P (operands[0]))
263    abort ();
264
265  output_asm_insn (\"ftst\", operands);
266
267  if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
268    output_asm_insn (AS1 (fstp,%y0), operands);
269
270  return output_fp_cc0_set (insn);
271}")
272
273;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
274;; isn't IEEE compliant.
275
276(define_expand "tstdf"
277  [(parallel [(set (cc0)
278		   (match_operand:DF 0 "register_operand" ""))
279	      (clobber (match_scratch:HI 1 ""))])]
280  "TARGET_80387 && ! TARGET_IEEE_FP"
281  "
282{
283  i386_compare_gen = gen_tstdf_cc;
284  i386_compare_op0 = operands[0];
285  i386_compare_op1 = const0_rtx;
286  DONE;
287}")
288
289(define_insn "tstxf_cc"
290  [(set (cc0)
291	(match_operand:XF 0 "register_operand" "f"))
292   (clobber (match_scratch:HI 1 "=a"))]
293  "TARGET_80387 && ! TARGET_IEEE_FP"
294  "*
295{
296  if (! STACK_TOP_P (operands[0]))
297    abort ();
298
299  output_asm_insn (\"ftst\", operands);
300
301  if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
302    output_asm_insn (AS1 (fstp,%y0), operands);
303
304  return output_fp_cc0_set (insn);
305}")
306
307;; Don't generate tstxf if generating IEEE code, since the `ftst' opcode
308;; isn't IEEE compliant.
309
310(define_expand "tstxf"
311  [(parallel [(set (cc0)
312		   (match_operand:XF 0 "register_operand" ""))
313	      (clobber (match_scratch:HI 1 ""))])]
314  "TARGET_80387 && ! TARGET_IEEE_FP"
315  "
316{
317  i386_compare_gen = gen_tstxf_cc;
318  i386_compare_op0 = operands[0];
319  i386_compare_op1 = const0_rtx;
320  DONE;
321}")
322
323;;- compare instructions.  See comments above tstM patterns about
324;;  expansion of these insns.
325
326(define_insn "cmpsi_1"
327  [(set (cc0)
328	(compare (match_operand:SI 0 "nonimmediate_operand" "mr,r")
329		 (match_operand:SI 1 "general_operand" "ri,mr")))]
330  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
331  "* return AS2 (cmp%L0,%1,%0);")
332
333(define_expand "cmpsi"
334  [(set (cc0)
335	(compare (match_operand:SI 0 "nonimmediate_operand" "")
336		 (match_operand:SI 1 "general_operand" "")))]
337  ""
338  "
339{
340  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
341    operands[0] = force_reg (SImode, operands[0]);
342
343  i386_compare_gen = gen_cmpsi_1;
344  i386_compare_op0 = operands[0];
345  i386_compare_op1 = operands[1];
346  DONE;
347}")
348
349(define_insn "cmphi_1"
350  [(set (cc0)
351	(compare (match_operand:HI 0 "nonimmediate_operand" "mr,r")
352		 (match_operand:HI 1 "general_operand" "ri,mr")))]
353  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
354  "* return AS2 (cmp%W0,%1,%0);")
355
356(define_expand "cmphi"
357  [(set (cc0)
358	(compare (match_operand:HI 0 "nonimmediate_operand" "")
359		 (match_operand:HI 1 "general_operand" "")))]
360  ""
361  "
362{
363  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
364    operands[0] = force_reg (HImode, operands[0]);
365
366  i386_compare_gen = gen_cmphi_1;
367  i386_compare_op0 = operands[0];
368  i386_compare_op1 = operands[1];
369  DONE;
370}")
371
372(define_insn "cmpqi_1"
373  [(set (cc0)
374	(compare (match_operand:QI 0 "nonimmediate_operand" "q,mq")
375		 (match_operand:QI 1 "general_operand" "qm,nq")))]
376  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
377  "* return AS2 (cmp%B0,%1,%0);")
378
379(define_expand "cmpqi"
380  [(set (cc0)
381	(compare (match_operand:QI 0 "nonimmediate_operand" "")
382		 (match_operand:QI 1 "general_operand" "")))]
383  ""
384  "
385{
386  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
387    operands[0] = force_reg (QImode, operands[0]);
388
389  i386_compare_gen = gen_cmpqi_1;
390  i386_compare_op0 = operands[0];
391  i386_compare_op1 = operands[1];
392  DONE;
393}")
394
395;; These implement float point compares.  For each of DFmode and
396;; SFmode, there is the normal insn, and an insn where the second operand
397;; is converted to the desired mode.
398
399(define_insn ""
400  [(set (cc0)
401	(match_operator 2 "VOIDmode_compare_op"
402			[(match_operand:XF 0 "register_operand" "f")
403			 (match_operand:XF 1 "register_operand" "f")]))
404   (clobber (match_scratch:HI 3 "=a"))]
405  "TARGET_80387"
406  "* return output_float_compare (insn, operands);")
407
408(define_insn ""
409  [(set (cc0)
410	(match_operator 2 "VOIDmode_compare_op"
411			[(match_operand:XF 0 "register_operand" "f")
412			 (float:XF
413			  (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
414   (clobber (match_scratch:HI 3 "=a"))]
415  "TARGET_80387"
416  "* return output_float_compare (insn, operands);")
417
418(define_insn ""
419  [(set (cc0)
420	(match_operator 2 "VOIDmode_compare_op"
421			[(float:XF
422			  (match_operand:SI 0 "nonimmediate_operand" "rm"))
423			 (match_operand:XF 1 "register_operand" "f")]))
424   (clobber (match_scratch:HI 3 "=a"))]
425  "TARGET_80387"
426  "* return output_float_compare (insn, operands);")
427
428(define_insn ""
429  [(set (cc0)
430	(match_operator 2 "VOIDmode_compare_op"
431			[(match_operand:XF 0 "register_operand" "f")
432			 (float_extend:XF
433			  (match_operand:DF 1 "nonimmediate_operand" "fm"))]))
434   (clobber (match_scratch:HI 3 "=a"))]
435  "TARGET_80387"
436  "* return output_float_compare (insn, operands);")
437
438(define_insn ""
439  [(set (cc0)
440	(match_operator 2 "VOIDmode_compare_op"
441			[(float_extend:XF
442			  (match_operand:DF 0 "nonimmediate_operand" "fm"))
443			 (match_operand:XF 1 "register_operand" "f")]))
444   (clobber (match_scratch:HI 3 "=a"))]
445  "TARGET_80387"
446  "* return output_float_compare (insn, operands);")
447
448(define_insn ""
449  [(set (cc0)
450	(match_operator 2 "VOIDmode_compare_op"
451			[(match_operand:XF 0 "register_operand" "f")
452			 (float_extend:XF
453			  (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
454   (clobber (match_scratch:HI 3 "=a"))]
455  "TARGET_80387"
456  "* return output_float_compare (insn, operands);")
457
458(define_insn ""
459  [(set (cc0)
460	(match_operator 2 "VOIDmode_compare_op"
461			[(float_extend:XF
462			  (match_operand:SF 0 "nonimmediate_operand" "fm"))
463			 (match_operand:XF 1 "register_operand" "f")]))
464   (clobber (match_scratch:HI 3 "=a"))]
465  "TARGET_80387"
466  "* return output_float_compare (insn, operands);")
467
468(define_insn ""
469  [(set (cc0)
470	(compare:CCFPEQ (match_operand:XF 0 "register_operand" "f")
471			(match_operand:XF 1 "register_operand" "f")))
472   (clobber (match_scratch:HI 2 "=a"))]
473  "TARGET_80387"
474  "* return output_float_compare (insn, operands);")
475
476(define_insn ""
477  [(set (cc0)
478	(match_operator 2 "VOIDmode_compare_op"
479			[(match_operand:DF 0 "nonimmediate_operand" "f,fm")
480			 (match_operand:DF 1 "nonimmediate_operand" "fm,f")]))
481   (clobber (match_scratch:HI 3 "=a,a"))]
482  "TARGET_80387
483   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
484  "* return output_float_compare (insn, operands);")
485
486(define_insn ""
487  [(set (cc0)
488	(match_operator 2 "VOIDmode_compare_op"
489			[(match_operand:DF 0 "register_operand" "f")
490			 (float:DF
491			  (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
492   (clobber (match_scratch:HI 3 "=a"))]
493  "TARGET_80387"
494  "* return output_float_compare (insn, operands);")
495
496(define_insn ""
497  [(set (cc0)
498	(match_operator 2 "VOIDmode_compare_op"
499			[(float:DF
500			  (match_operand:SI 0 "nonimmediate_operand" "rm"))
501			 (match_operand:DF 1 "register_operand" "f")]))
502   (clobber (match_scratch:HI 3 "=a"))]
503  "TARGET_80387"
504  "* return output_float_compare (insn, operands);")
505
506(define_insn ""
507  [(set (cc0)
508	(match_operator 2 "VOIDmode_compare_op"
509			[(match_operand:DF 0 "register_operand" "f")
510			 (float_extend:DF
511			  (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
512   (clobber (match_scratch:HI 3 "=a"))]
513  "TARGET_80387"
514  "* return output_float_compare (insn, operands);")
515
516(define_insn ""
517  [(set (cc0)
518	(match_operator 2 "VOIDmode_compare_op"
519			[(float_extend:DF
520			  (match_operand:SF 0 "nonimmediate_operand" "fm"))
521			 (match_operand:DF 1 "register_operand" "f")]))
522   (clobber (match_scratch:HI 3 "=a"))]
523  "TARGET_80387"
524  "* return output_float_compare (insn, operands);")
525
526(define_insn ""
527  [(set (cc0)
528	(match_operator 2 "VOIDmode_compare_op"
529			[(float_extend:DF
530			  (match_operand:SF 0 "register_operand" "f"))
531			 (match_operand:DF 1 "nonimmediate_operand" "fm")]))
532   (clobber (match_scratch:HI 3 "=a"))]
533  "TARGET_80387"
534  "* return output_float_compare (insn, operands);")
535
536(define_insn ""
537  [(set (cc0)
538	(compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
539			(match_operand:DF 1 "register_operand" "f")))
540   (clobber (match_scratch:HI 2 "=a"))]
541  "TARGET_80387"
542  "* return output_float_compare (insn, operands);")
543
544;; These two insns will never be generated by combine due to the mode of
545;; the COMPARE.
546;(define_insn ""
547;  [(set (cc0)
548;	(compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
549;			(float_extend:DF
550;			 (match_operand:SF 1 "register_operand" "f"))))
551;   (clobber (match_scratch:HI 2 "=a"))]
552;  "TARGET_80387"
553;  "* return output_float_compare (insn, operands);")
554;
555;(define_insn ""
556;  [(set (cc0)
557;	(compare:CCFPEQ (float_extend:DF
558;			 (match_operand:SF 0 "register_operand" "f"))
559;			(match_operand:DF 1 "register_operand" "f")))
560;   (clobber (match_scratch:HI 2 "=a"))]
561;  "TARGET_80387"
562;  "* return output_float_compare (insn, operands);")
563
564(define_insn "cmpsf_cc_1"
565  [(set (cc0)
566	(match_operator 2 "VOIDmode_compare_op"
567			[(match_operand:SF 0 "nonimmediate_operand" "f,fm")
568			 (match_operand:SF 1 "nonimmediate_operand" "fm,f")]))
569   (clobber (match_scratch:HI 3 "=a,a"))]
570  "TARGET_80387
571   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
572  "* return output_float_compare (insn, operands);")
573
574(define_insn ""
575  [(set (cc0)
576	(match_operator 2 "VOIDmode_compare_op"
577			[(match_operand:SF 0 "register_operand" "f")
578			 (float:SF
579			  (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
580   (clobber (match_scratch:HI 3 "=a"))]
581  "TARGET_80387"
582  "* return output_float_compare (insn, operands);")
583
584(define_insn ""
585  [(set (cc0)
586	(match_operator 2 "VOIDmode_compare_op"
587			[(float:SF
588			  (match_operand:SI 0 "nonimmediate_operand" "rm"))
589			 (match_operand:SF 1 "register_operand" "f")]))
590   (clobber (match_scratch:HI 3 "=a"))]
591  "TARGET_80387"
592  "* return output_float_compare (insn, operands);")
593
594(define_insn ""
595  [(set (cc0)
596	(compare:CCFPEQ (match_operand:SF 0 "register_operand" "f")
597			(match_operand:SF 1 "register_operand" "f")))
598   (clobber (match_scratch:HI 2 "=a"))]
599  "TARGET_80387"
600  "* return output_float_compare (insn, operands);")
601
602(define_expand "cmpxf"
603  [(set (cc0)
604	(compare (match_operand:XF 0 "register_operand" "")
605		 (match_operand:XF 1 "register_operand" "")))]
606  "TARGET_80387"
607  "
608{
609  i386_compare_gen = gen_cmpxf_cc;
610  i386_compare_gen_eq = gen_cmpxf_ccfpeq;
611  i386_compare_op0 = operands[0];
612  i386_compare_op1 = operands[1];
613  DONE;
614}")
615
616(define_expand "cmpdf"
617  [(set (cc0)
618	(compare (match_operand:DF 0 "register_operand" "")
619		 (match_operand:DF 1 "general_operand" "")))]
620  "TARGET_80387"
621  "
622{
623  i386_compare_gen = gen_cmpdf_cc;
624  i386_compare_gen_eq = gen_cmpdf_ccfpeq;
625  i386_compare_op0 = operands[0];
626  i386_compare_op1 = (immediate_operand (operands[1], DFmode))
627			? copy_to_mode_reg (DFmode, operands[1]) : operands[1];
628  DONE;
629}")
630
631(define_expand "cmpsf"
632  [(set (cc0)
633	(compare (match_operand:SF 0 "register_operand" "")
634		 (match_operand:SF 1 "general_operand" "")))]
635  "TARGET_80387"
636  "
637{
638  i386_compare_gen = gen_cmpsf_cc;
639  i386_compare_gen_eq = gen_cmpsf_ccfpeq;
640  i386_compare_op0 = operands[0];
641  i386_compare_op1 = (immediate_operand (operands[1], SFmode))
642			? copy_to_mode_reg (SFmode, operands[1]) : operands[1];
643  DONE;
644}")
645
646(define_expand "cmpxf_cc"
647  [(parallel [(set (cc0)
648		   (compare (match_operand:XF 0 "register_operand" "")
649			    (match_operand:XF 1 "register_operand" "")))
650	      (clobber (match_scratch:HI 2 ""))])]
651  "TARGET_80387"
652  "")
653
654(define_expand "cmpxf_ccfpeq"
655  [(parallel [(set (cc0)
656		   (compare:CCFPEQ (match_operand:XF 0 "register_operand" "")
657				   (match_operand:XF 1 "register_operand" "")))
658	      (clobber (match_scratch:HI 2 ""))])]
659  "TARGET_80387"
660  "")
661
662(define_expand "cmpdf_cc"
663  [(parallel [(set (cc0)
664		   (compare (match_operand:DF 0 "register_operand" "")
665			    (match_operand:DF 1 "register_operand" "")))
666	      (clobber (match_scratch:HI 2 ""))])]
667  "TARGET_80387"
668  "")
669
670(define_expand "cmpdf_ccfpeq"
671  [(parallel [(set (cc0)
672		   (compare:CCFPEQ (match_operand:DF 0 "register_operand" "")
673				   (match_operand:DF 1 "register_operand" "")))
674	      (clobber (match_scratch:HI 2 ""))])]
675  "TARGET_80387"
676  "
677{
678  if (! register_operand (operands[1], DFmode))
679    operands[1] = copy_to_mode_reg (DFmode, operands[1]);
680}")
681
682(define_expand "cmpsf_cc"
683  [(parallel [(set (cc0)
684		   (compare (match_operand:SF 0 "register_operand" "")
685			    (match_operand:SF 1 "register_operand" "")))
686	      (clobber (match_scratch:HI 2 ""))])]
687  "TARGET_80387"
688  "")
689
690(define_expand "cmpsf_ccfpeq"
691  [(parallel [(set (cc0)
692		   (compare:CCFPEQ (match_operand:SF 0 "register_operand" "")
693				   (match_operand:SF 1 "register_operand" "")))
694	      (clobber (match_scratch:HI 2 ""))])]
695  "TARGET_80387"
696  "
697{
698  if (! register_operand (operands[1], SFmode))
699    operands[1] = copy_to_mode_reg (SFmode, operands[1]);
700}")
701
702;; logical compare
703
704(define_insn ""
705  [(set (cc0)
706	(and:SI (match_operand:SI 0 "general_operand" "%ro")
707		(match_operand:SI 1 "nonmemory_operand" "ri")))]
708  ""
709  "*
710{
711  /* For small integers, we may actually use testb. */
712  if (GET_CODE (operands[1]) == CONST_INT
713      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
714      && (! REG_P (operands[0]) || QI_REG_P (operands[0])))
715    {
716      /* We may set the sign bit spuriously.  */
717
718      if ((INTVAL (operands[1]) & ~0xff) == 0)
719        {
720	  cc_status.flags |= CC_NOT_NEGATIVE;
721	  return AS2 (test%B0,%1,%b0);
722	}
723
724      if ((INTVAL (operands[1]) & ~0xff00) == 0)
725        {
726	  cc_status.flags |= CC_NOT_NEGATIVE;
727	  operands[1] = GEN_INT (INTVAL (operands[1]) >> 8);
728
729	  if (QI_REG_P (operands[0]))
730	    return AS2 (test%B0,%1,%h0);
731	  else
732	    {
733	      operands[0] = adj_offsettable_operand (operands[0], 1);
734	      return AS2 (test%B0,%1,%b0);
735	    }
736	}
737
738      if (GET_CODE (operands[0]) == MEM
739	  && (INTVAL (operands[1]) & ~0xff0000) == 0)
740        {
741	  cc_status.flags |= CC_NOT_NEGATIVE;
742	  operands[1] = GEN_INT (INTVAL (operands[1]) >> 16);
743	  operands[0] = adj_offsettable_operand (operands[0], 2);
744	  return AS2 (test%B0,%1,%b0);
745	}
746
747      if (GET_CODE (operands[0]) == MEM
748	  && (INTVAL (operands[1]) & ~0xff000000) == 0)
749        {
750	  operands[1] = GEN_INT ((INTVAL (operands[1]) >> 24) & 0xff);
751	  operands[0] = adj_offsettable_operand (operands[0], 3);
752	  return AS2 (test%B0,%1,%b0);
753	}
754    }
755
756  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
757    return AS2 (test%L0,%1,%0);
758
759  return AS2 (test%L1,%0,%1);
760}")
761
762(define_insn ""
763  [(set (cc0)
764	(and:HI (match_operand:HI 0 "general_operand" "%ro")
765		(match_operand:HI 1 "nonmemory_operand" "ri")))]
766  ""
767  "*
768{
769  if (GET_CODE (operands[1]) == CONST_INT
770      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
771      && (! REG_P (operands[0]) || QI_REG_P (operands[0])))
772    {
773      if ((INTVAL (operands[1]) & 0xff00) == 0)
774	{
775	  /* ??? This might not be necessary. */
776	  if (INTVAL (operands[1]) & 0xffff0000)
777	    operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
778
779	  /* We may set the sign bit spuriously.  */
780	  cc_status.flags |= CC_NOT_NEGATIVE;
781	  return AS2 (test%B0,%1,%b0);
782	}
783
784      if ((INTVAL (operands[1]) & 0xff) == 0)
785        {
786	  operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff);
787
788	  if (QI_REG_P (operands[0]))
789	    return AS2 (test%B0,%1,%h0);
790	  else
791	    {
792	      operands[0] = adj_offsettable_operand (operands[0], 1);
793	      return AS2 (test%B0,%1,%b0);
794	    }
795	}
796    }
797
798  /* use 32-bit test instruction if there are no sign issues */
799  if (GET_CODE (operands[1]) == CONST_INT
800      && !(INTVAL (operands[1]) & ~0x7fff)
801      && i386_aligned_p (operands[0]))
802    return AS2 (test%L0,%1,%k0);
803
804  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
805    return AS2 (test%W0,%1,%0);
806
807  return AS2 (test%W1,%0,%1);
808}")
809
810(define_insn ""
811  [(set (cc0)
812	(and:QI (match_operand:QI 0 "nonimmediate_operand" "%qm")
813		(match_operand:QI 1 "nonmemory_operand" "qi")))]
814  ""
815  "*
816{
817  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
818    return AS2 (test%B0,%1,%0);
819
820  return AS2 (test%B1,%0,%1);
821}")
822
823;; move instructions.
824;; There is one for each machine mode,
825;; and each is preceded by a corresponding push-insn pattern
826;; (since pushes are not general_operands on the 386).
827
828(define_insn ""
829  [(set (match_operand:SI 0 "push_operand" "=<")
830	(match_operand:SI 1 "nonmemory_operand" "rn"))]
831  "flag_pic"
832  "* return AS1 (push%L0,%1);")
833
834(define_insn ""
835  [(set (match_operand:SI 0 "push_operand" "=<")
836	(match_operand:SI 1 "nonmemory_operand" "ri"))]
837  "!flag_pic"
838  "* return AS1 (push%L0,%1);")
839
840;; On a 386, it is faster to push MEM directly.
841
842(define_insn ""
843  [(set (match_operand:SI 0 "push_operand" "=<")
844	(match_operand:SI 1 "memory_operand" "m"))]
845  "TARGET_PUSH_MEMORY"
846  "* return AS1 (push%L0,%1);")
847
848;; General case of fullword move.
849
850;; If generating PIC code and operands[1] is a symbolic CONST, emit a
851;; move to get the address of the symbolic object from the GOT.
852
853(define_expand "movsi"
854  [(set (match_operand:SI 0 "general_operand" "")
855	(match_operand:SI 1 "general_operand" ""))]
856  ""
857  "
858{
859  extern int flag_pic;
860
861  if (flag_pic && SYMBOLIC_CONST (operands[1]))
862    emit_pic_move (operands, SImode);
863
864  /* Don't generate memory->memory moves, go through a register */
865  else if (TARGET_MOVE
866	   && (reload_in_progress | reload_completed) == 0
867	   && GET_CODE (operands[0]) == MEM
868	   && GET_CODE (operands[1]) == MEM)
869    {
870      operands[1] = force_reg (SImode, operands[1]);
871    }
872}")
873
874;; On i486, incl reg is faster than movl $1,reg.
875
876(define_insn ""
877  [(set (match_operand:SI 0 "general_operand" "=g,r")
878	(match_operand:SI 1 "general_operand" "rn,im"))]
879  "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
880    || (GET_CODE (operands[1]) != MEM))
881   && flag_pic"
882  "*
883{
884  rtx link;
885  if (operands[1] == const0_rtx && REG_P (operands[0]))
886    return AS2 (xor%L0,%0,%0);
887
888  if (operands[1] == const1_rtx
889      && (link = find_reg_note (insn, REG_WAS_0, 0))
890      /* Make sure the insn that stored the 0 is still present.  */
891      && ! INSN_DELETED_P (XEXP (link, 0))
892      && GET_CODE (XEXP (link, 0)) != NOTE
893      /* Make sure cross jumping didn't happen here.  */
894      && no_labels_between_p (XEXP (link, 0), insn)
895      /* Make sure the reg hasn't been clobbered.  */
896      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
897    /* Fastest way to change a 0 to a 1.  */
898    return AS1 (inc%L0,%0);
899
900  if (SYMBOLIC_CONST (operands[1]))
901    return AS2 (lea%L0,%a1,%0);
902
903  return AS2 (mov%L0,%1,%0);
904}")
905
906(define_insn ""
907  [(set (match_operand:SI 0 "general_operand" "=g,r")
908	(match_operand:SI 1 "general_operand" "ri,m"))]
909  "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
910    || (GET_CODE (operands[1]) != MEM))
911   && !flag_pic"
912  "*
913{
914  rtx link;
915  if (operands[1] == const0_rtx && REG_P (operands[0]))
916    return AS2 (xor%L0,%0,%0);
917
918  if (operands[1] == const1_rtx
919      && (link = find_reg_note (insn, REG_WAS_0, 0))
920      /* Make sure the insn that stored the 0 is still present.  */
921      && ! INSN_DELETED_P (XEXP (link, 0))
922      && GET_CODE (XEXP (link, 0)) != NOTE
923      /* Make sure cross jumping didn't happen here.  */
924      && no_labels_between_p (XEXP (link, 0), insn)
925      /* Make sure the reg hasn't been clobbered.  */
926      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
927    /* Fastest way to change a 0 to a 1.  */
928    return AS1 (inc%L0,%0);
929
930  return AS2 (mov%L0,%1,%0);
931}")
932
933(define_insn ""
934  [(set (match_operand:HI 0 "push_operand" "=<")
935	(match_operand:HI 1 "nonmemory_operand" "ri"))]
936  ""
937  "* return AS1 (push%W0,%1);")
938
939(define_insn ""
940  [(set (match_operand:HI 0 "push_operand" "=<")
941	(match_operand:HI 1 "memory_operand" "m"))]
942  "TARGET_PUSH_MEMORY"
943  "* return AS1 (push%W0,%1);")
944
945;; On i486, an incl and movl are both faster than incw and movw.
946
947(define_expand "movhi"
948  [(set (match_operand:HI 0 "general_operand" "")
949	(match_operand:HI 1 "general_operand" ""))]
950  ""
951  "
952{
953  /* Don't generate memory->memory moves, go through a register */
954  if (TARGET_MOVE
955      && (reload_in_progress | reload_completed) == 0
956      && GET_CODE (operands[0]) == MEM
957      && GET_CODE (operands[1]) == MEM)
958    {
959      operands[1] = force_reg (HImode, operands[1]);
960    }
961}")
962
963(define_insn ""
964  [(set (match_operand:HI 0 "general_operand" "=g,r")
965	(match_operand:HI 1 "general_operand" "ri,m"))]
966  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
967  "*
968{
969  rtx link;
970  if (REG_P (operands[0]) && operands[1] == const0_rtx)
971    return AS2 (xor%L0,%k0,%k0);
972
973  if (REG_P (operands[0]) && operands[1] == const1_rtx 
974      && (link = find_reg_note (insn, REG_WAS_0, 0))
975      /* Make sure the insn that stored the 0 is still present.  */
976      && ! INSN_DELETED_P (XEXP (link, 0))
977      && GET_CODE (XEXP (link, 0)) != NOTE
978      /* Make sure cross jumping didn't happen here.  */
979      && no_labels_between_p (XEXP (link, 0), insn)
980      /* Make sure the reg hasn't been clobbered.  */
981      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
982    /* Fastest way to change a 0 to a 1.  */
983    return AS1 (inc%L0,%k0);
984
985  if (REG_P (operands[0]))
986    {
987      if (i386_aligned_p (operands[1]))
988	{
989	  operands[1] = i386_sext16_if_const (operands[1]);
990	  return AS2 (mov%L0,%k1,%k0);
991	}
992      if (TARGET_PENTIUMPRO)
993	{
994	  /* movzwl is faster than movw on the Pentium Pro,
995	   * although not as fast as an aligned movl. */
996#ifdef INTEL_SYNTAX
997	  return AS2 (movzx,%1,%k0);
998#else
999	  return AS2 (movz%W0%L0,%1,%k0);
1000#endif
1001	}
1002    }
1003
1004  return AS2 (mov%W0,%1,%0);
1005}")
1006
1007(define_expand "movstricthi"
1008  [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
1009	(match_operand:HI 1 "general_operand" ""))]
1010  ""
1011  "
1012{
1013  /* Don't generate memory->memory moves, go through a register */
1014  if (TARGET_MOVE
1015      && (reload_in_progress | reload_completed) == 0
1016      && GET_CODE (operands[0]) == MEM
1017      && GET_CODE (operands[1]) == MEM)
1018    {
1019      operands[1] = force_reg (HImode, operands[1]);
1020    }
1021}")
1022
1023(define_insn ""
1024  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r"))
1025	(match_operand:HI 1 "general_operand" "ri,m"))]
1026  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1027  "*
1028{
1029  rtx link;
1030  if (operands[1] == const0_rtx && REG_P (operands[0]))
1031    return AS2 (xor%W0,%0,%0);
1032
1033  if (operands[1] == const1_rtx
1034      && (link = find_reg_note (insn, REG_WAS_0, 0))
1035      /* Make sure the insn that stored the 0 is still present.  */
1036      && ! INSN_DELETED_P (XEXP (link, 0))
1037      && GET_CODE (XEXP (link, 0)) != NOTE
1038      /* Make sure cross jumping didn't happen here.  */
1039      && no_labels_between_p (XEXP (link, 0), insn)
1040      /* Make sure the reg hasn't been clobbered.  */
1041      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
1042    /* Fastest way to change a 0 to a 1.  */
1043    return AS1 (inc%W0,%0);
1044
1045  return AS2 (mov%W0,%1,%0);
1046}")
1047
1048;; emit_push_insn when it calls move_by_pieces
1049;; requires an insn to "push a byte".
1050;; But actually we use pushw, which has the effect of rounding
1051;; the amount pushed up to a halfword.
1052(define_insn ""
1053  [(set (match_operand:QI 0 "push_operand" "=<")
1054	(match_operand:QI 1 "const_int_operand" "n"))]
1055  ""
1056  "* return AS1(push%W0,%1);")
1057
1058(define_insn ""
1059  [(set (match_operand:QI 0 "push_operand" "=<")
1060	(match_operand:QI 1 "register_operand" "q"))]
1061  ""
1062  "*
1063{
1064  operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
1065  return AS1 (push%W0,%1);
1066}")
1067
1068;; On i486, incb reg is faster than movb $1,reg.
1069
1070;; ??? Do a recognizer for zero_extract that looks just like this, but reads
1071;; or writes %ah, %bh, %ch, %dh.
1072
1073(define_expand "movqi"
1074  [(set (match_operand:QI 0 "general_operand" "")
1075	(match_operand:QI 1 "general_operand" ""))]
1076  ""
1077  "
1078{
1079  /* Don't generate memory->memory moves, go through a register */
1080  if (TARGET_MOVE
1081      && (reload_in_progress | reload_completed) == 0
1082      && GET_CODE (operands[0]) == MEM
1083      && GET_CODE (operands[1]) == MEM)
1084    {
1085      operands[1] = force_reg (QImode, operands[1]);
1086    }
1087}")
1088
1089(define_insn ""
1090  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,*r,qm")
1091	(match_operand:QI 1 "general_operand" "*g,*rn,qn"))]
1092  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1093  "*
1094{
1095  rtx link;
1096  if (operands[1] == const0_rtx && REG_P (operands[0]))
1097    return AS2 (xor%L0,%k0,%k0);
1098
1099  if (operands[1] == const1_rtx
1100      && (link = find_reg_note (insn, REG_WAS_0, 0))
1101      /* Make sure the insn that stored the 0 is still present.  */
1102      && ! INSN_DELETED_P (XEXP (link, 0))
1103      && GET_CODE (XEXP (link, 0)) != NOTE
1104      /* Make sure cross jumping didn't happen here.  */
1105      && no_labels_between_p (XEXP (link, 0), insn)
1106      /* Make sure the reg hasn't been clobbered.  */
1107      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
1108    {
1109      /* Fastest way to change a 0 to a 1.
1110	 If inc%B0 isn't allowed, use inc%L0.  */
1111      if (NON_QI_REG_P (operands[0]))
1112	return AS1 (inc%L0,%k0);
1113      else
1114	return AS1 (inc%B0,%0);
1115    }
1116
1117  /* If mov%B0 isn't allowed for one of these regs, use mov%L0.  */
1118  if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
1119    return (AS2 (mov%L0,%k1,%k0));
1120
1121  return (AS2 (mov%B0,%1,%0));
1122}")
1123
1124;; If it becomes necessary to support movstrictqi into %esi or %edi,
1125;; use the insn sequence:
1126;;
1127;;	shrdl $8,srcreg,dstreg
1128;;	rorl $24,dstreg
1129;;
1130;; If operands[1] is a constant, then an andl/orl sequence would be
1131;; faster.
1132
1133(define_expand "movstrictqi"
1134  [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
1135	(match_operand:QI 1 "general_operand" ""))]
1136  ""
1137  "
1138{
1139  /* Don't generate memory->memory moves, go through a register */
1140  if (TARGET_MOVE
1141      && (reload_in_progress | reload_completed) == 0
1142      && GET_CODE (operands[0]) == MEM
1143      && GET_CODE (operands[1]) == MEM)
1144    {
1145      operands[1] = force_reg (QImode, operands[1]);
1146    }
1147}")
1148
1149(define_insn ""
1150  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
1151	(match_operand:QI 1 "general_operand" "*qn,m"))]
1152  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1153  "*
1154{
1155  rtx link;
1156  if (operands[1] == const0_rtx && REG_P (operands[0]))
1157    return AS2 (xor%B0,%0,%0);
1158
1159  if (operands[1] == const1_rtx
1160      && ! NON_QI_REG_P (operands[0])
1161      && (link = find_reg_note (insn, REG_WAS_0, 0))
1162      /* Make sure the insn that stored the 0 is still present.  */
1163      && ! INSN_DELETED_P (XEXP (link, 0))
1164      && GET_CODE (XEXP (link, 0)) != NOTE
1165      /* Make sure cross jumping didn't happen here.  */
1166      && no_labels_between_p (XEXP (link, 0), insn)
1167      /* Make sure the reg hasn't been clobbered.  */
1168      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
1169    /* Fastest way to change a 0 to a 1.  */
1170    return AS1 (inc%B0,%0);
1171
1172  /* If mov%B0 isn't allowed for one of these regs, use mov%L0.  */
1173  if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
1174    {
1175      abort ();
1176      return (AS2 (mov%L0,%k1,%k0));
1177    }
1178
1179  return AS2 (mov%B0,%1,%0);
1180}")
1181
1182(define_insn "movsf_push"
1183  [(set (match_operand:SF 0 "push_operand" "=<,<")
1184	(match_operand:SF 1 "general_operand" "*rfF,m"))]
1185  "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed"
1186  "*
1187{
1188  if (STACK_REG_P (operands[1]))
1189    {
1190      rtx xops[3];
1191
1192      if (! STACK_TOP_P (operands[1]))
1193        abort ();
1194
1195      xops[0] = AT_SP (SFmode);
1196      xops[1] = GEN_INT (4);
1197      xops[2] = stack_pointer_rtx;
1198
1199      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1200
1201      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1202        output_asm_insn (AS1 (fstp%S0,%0), xops);
1203      else
1204        output_asm_insn (AS1 (fst%S0,%0), xops);
1205
1206      RET;
1207    }
1208
1209  return AS1 (push%L0,%1);
1210}")
1211
1212(define_insn "movsf_push_memory"
1213  [(set (match_operand:SF 0 "push_operand" "=<")
1214	(match_operand:SF 1 "memory_operand" "m"))]
1215  "TARGET_PUSH_MEMORY"
1216  "* return AS1 (push%L0,%1);")
1217
1218(define_expand "movsf"
1219  [(set (match_operand:SF 0 "general_operand" "")
1220	(match_operand:SF 1 "general_operand" ""))]
1221  ""
1222  "
1223{
1224  /* Don't generate memory->memory moves, go through a register */
1225  if (TARGET_MOVE
1226      && (reload_in_progress | reload_completed) == 0
1227      && GET_CODE (operands[0]) == MEM
1228      && GET_CODE (operands[1]) == MEM)
1229    {
1230      operands[1] = force_reg (SFmode, operands[1]);
1231    }
1232
1233  /* If we are loading a floating point constant that isn't 0 or 1
1234     into a register, indicate we need the pic register loaded.  This could
1235     be optimized into stores of constants if the target eventually moves
1236     to memory, but better safe than sorry.  */
1237  else if ((reload_in_progress | reload_completed) == 0
1238      && GET_CODE (operands[0]) != MEM
1239      && GET_CODE (operands[1]) == CONST_DOUBLE
1240      && !standard_80387_constant_p (operands[1]))
1241    {
1242      rtx insn, note, fp_const;
1243
1244      fp_const = force_const_mem (SFmode, operands[1]);
1245      if (flag_pic)
1246	current_function_uses_pic_offset_table = 1;
1247
1248      insn = emit_insn (gen_rtx_SET (SFmode, operands[0], fp_const));
1249      note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
1250
1251      if (note)
1252	XEXP (note, 0) = operands[1];
1253      else
1254	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn));
1255    }
1256}")
1257
1258;; For the purposes of regclass, prefer FLOAT_REGS.
1259(define_insn ""
1260  [(set (match_operand:SF 0 "nonimmediate_operand" "=*rfm,*rf,f,!*rm")
1261	(match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))]
1262  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1263  "*
1264{
1265  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1266
1267  /* First handle a `pop' insn or a `fld %st(0)' */
1268
1269  if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
1270    {
1271      if (stack_top_dies)
1272	return AS1 (fstp,%y0);
1273      else
1274        return AS1 (fld,%y0);
1275    }
1276
1277  /* Handle a transfer between the 387 and a 386 register */
1278
1279  if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
1280    {
1281      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1282      RET;
1283    }
1284
1285  if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
1286    {
1287      output_to_reg (operands[0], stack_top_dies, 0);
1288      RET;
1289    }
1290
1291  /* Handle other kinds of writes from the 387 */
1292
1293  if (STACK_TOP_P (operands[1]))
1294    {
1295      if (stack_top_dies)
1296	return AS1 (fstp%z0,%y0);
1297      else
1298        return AS1 (fst%z0,%y0);
1299    }
1300
1301  /* Handle other kinds of reads to the 387 */
1302
1303  if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
1304    return output_move_const_single (operands);
1305
1306  if (STACK_TOP_P (operands[0]))
1307    return AS1 (fld%z1,%y1);
1308
1309  /* Handle all SFmode moves not involving the 387 */
1310
1311  return singlemove_string (operands);
1312}"
1313  [(set_attr "type" "fld")])
1314
1315
1316(define_insn "swapsf"
1317  [(set (match_operand:SF 0 "register_operand" "f")
1318	(match_operand:SF 1 "register_operand" "f"))
1319   (set (match_dup 1)
1320	(match_dup 0))]
1321  ""
1322  "*
1323{
1324  if (STACK_TOP_P (operands[0]))
1325    return AS1 (fxch,%1);
1326  else
1327    return AS1 (fxch,%0);
1328}")
1329
1330(define_insn "movdf_push"
1331  [(set (match_operand:DF 0 "push_operand" "=<,<")
1332	(match_operand:DF 1 "general_operand" "*rfF,o"))]
1333  "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed"
1334  "*
1335{
1336  if (STACK_REG_P (operands[1]))
1337    {
1338      rtx xops[3];
1339
1340      xops[0] = AT_SP (DFmode);
1341      xops[1] = GEN_INT (8);
1342      xops[2] = stack_pointer_rtx;
1343
1344      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1345
1346      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1347        output_asm_insn (AS1 (fstp%Q0,%0), xops);
1348      else
1349        output_asm_insn (AS1 (fst%Q0,%0), xops);
1350
1351      RET;
1352    }
1353
1354  if (which_alternative == 1)
1355    return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 0, 0);
1356
1357  return output_move_double (operands);
1358}")
1359
1360(define_insn "movdf_push_memory"
1361  [(set (match_operand:DF 0 "push_operand" "=<")
1362	(match_operand:DF 1 "memory_operand" "o"))]
1363  "TARGET_PUSH_MEMORY"
1364  "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode),0,0);")
1365
1366(define_expand "movdf"
1367  [(set (match_operand:DF 0 "general_operand" "")
1368	(match_operand:DF 1 "general_operand" ""))]
1369  ""
1370  "
1371{
1372  /* Don't generate memory->memory moves, go through a register */
1373  if (TARGET_MOVE
1374      && (reload_in_progress | reload_completed) == 0
1375      && GET_CODE (operands[0]) == MEM
1376      && GET_CODE (operands[1]) == MEM)
1377    {
1378      operands[1] = force_reg (DFmode, operands[1]);
1379    }
1380
1381  /* If we are loading a floating point constant that isn't 0 or 1 into a
1382     register, indicate we need the pic register loaded.  This could be
1383     optimized into stores of constants if the target eventually moves to
1384     memory, but better safe than sorry.  */
1385  else if ((reload_in_progress | reload_completed) == 0
1386      && GET_CODE (operands[0]) != MEM
1387      && GET_CODE (operands[1]) == CONST_DOUBLE
1388      && !standard_80387_constant_p (operands[1]))
1389    {
1390      rtx insn, note, fp_const;
1391
1392      fp_const = force_const_mem (DFmode, operands[1]);
1393      if (flag_pic)
1394	current_function_uses_pic_offset_table = 1;
1395
1396      insn = emit_insn (gen_rtx_SET (DFmode, operands[0], fp_const));
1397      note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
1398
1399      if (note)
1400	XEXP (note, 0) = operands[1];
1401      else
1402	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn));
1403    }
1404}")
1405
1406;; For the purposes of regclass, prefer FLOAT_REGS.
1407(define_insn ""
1408  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm")
1409	(match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
1410  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
1411   || (GET_CODE (operands[1]) != MEM)"
1412  "*
1413{
1414  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1415
1416  /* First handle a `pop' insn or a `fld %st(0)' */
1417
1418  if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
1419    {
1420      if (stack_top_dies)
1421	return AS1 (fstp,%y0);
1422      else
1423        return AS1 (fld,%y0);
1424    }
1425
1426  /* Handle a transfer between the 387 and a 386 register */
1427
1428  if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
1429    {
1430      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1431      RET;
1432    }
1433
1434  if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
1435    {
1436      output_to_reg (operands[0], stack_top_dies, 0);
1437      RET;
1438    }
1439
1440  /* Handle other kinds of writes from the 387 */
1441
1442  if (STACK_TOP_P (operands[1]))
1443    {
1444      if (stack_top_dies)
1445	return AS1 (fstp%z0,%y0);
1446      else
1447        return AS1 (fst%z0,%y0);
1448    }
1449
1450  /* Handle other kinds of reads to the 387 */
1451
1452  if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
1453    return output_move_const_single (operands);
1454
1455  if (STACK_TOP_P (operands[0]))
1456    return AS1 (fld%z1,%y1);
1457
1458  /* Handle all DFmode moves not involving the 387 */
1459
1460  return output_move_double (operands);
1461}"
1462  [(set_attr "type" "fld")])
1463
1464
1465
1466(define_insn "swapdf"
1467  [(set (match_operand:DF 0 "register_operand" "f")
1468	(match_operand:DF 1 "register_operand" "f"))
1469   (set (match_dup 1)
1470	(match_dup 0))]
1471  ""
1472  "*
1473{
1474  if (STACK_TOP_P (operands[0]))
1475    return AS1 (fxch,%1);
1476  else
1477    return AS1 (fxch,%0);
1478}")
1479
1480(define_insn "movxf_push"
1481  [(set (match_operand:XF 0 "push_operand" "=<,<")
1482 	(match_operand:XF 1 "general_operand" "*rfF,o"))]
1483  "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed"
1484  "*
1485{
1486  if (STACK_REG_P (operands[1]))
1487    {
1488      rtx xops[3];
1489
1490      xops[0] = AT_SP (XFmode);
1491      xops[1] = GEN_INT (12);
1492      xops[2] = stack_pointer_rtx;
1493
1494      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1495
1496      output_asm_insn (AS1 (fstp%T0,%0), xops);
1497      if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1498	output_asm_insn (AS1 (fld%T0,%0), xops);
1499
1500      RET;
1501    }
1502
1503  if (which_alternative == 1)
1504    return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 0, 0);
1505
1506  return output_move_double (operands);
1507 }")
1508
1509(define_insn "movxf_push_memory"
1510  [(set (match_operand:XF 0 "push_operand" "=<")
1511 	(match_operand:XF 1 "memory_operand" "o"))]
1512  "TARGET_PUSH_MEMORY"
1513  "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode),0,0);")
1514
1515(define_expand "movxf"
1516  [(set (match_operand:XF 0 "general_operand" "")
1517	(match_operand:XF 1 "general_operand" ""))]
1518  ""
1519  "
1520{
1521  /* Don't generate memory->memory moves, go through a register */
1522  if (TARGET_MOVE
1523      && (reload_in_progress | reload_completed) == 0
1524      && GET_CODE (operands[0]) == MEM
1525      && GET_CODE (operands[1]) == MEM)
1526    {
1527      operands[1] = force_reg (XFmode, operands[1]);
1528    }
1529
1530  /* If we are loading a floating point constant that isn't 0 or 1
1531     into a register, indicate we need the pic register loaded.  This could
1532     be optimized into stores of constants if the target eventually moves
1533     to memory, but better safe than sorry.  */
1534  else if ((reload_in_progress | reload_completed) == 0
1535      && GET_CODE (operands[0]) != MEM
1536      && GET_CODE (operands[1]) == CONST_DOUBLE
1537      && !standard_80387_constant_p (operands[1]))
1538    {
1539      rtx insn, note, fp_const;
1540
1541      fp_const = force_const_mem (XFmode, operands[1]);
1542      if (flag_pic)
1543	current_function_uses_pic_offset_table = 1;
1544
1545      insn = emit_insn (gen_rtx_SET (XFmode, operands[0], fp_const));
1546      note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
1547
1548      if (note)
1549	XEXP (note, 0) = operands[1];
1550      else
1551	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn));
1552    }
1553}")
1554
1555
1556(define_insn ""
1557  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm")
1558	(match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
1559  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
1560   || (GET_CODE (operands[1]) != MEM)"
1561  "*
1562{
1563  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1564
1565  /* First handle a `pop' insn or a `fld %st(0)' */
1566
1567  if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
1568    {
1569      if (stack_top_dies)
1570	return AS1 (fstp,%y0);
1571      else
1572        return AS1 (fld,%y0);
1573    }
1574
1575  /* Handle a transfer between the 387 and a 386 register */
1576
1577  if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
1578    {
1579      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1580      RET;
1581    }
1582
1583  if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
1584    {
1585      output_to_reg (operands[0], stack_top_dies, 0);
1586      RET;
1587    }
1588
1589  /* Handle other kinds of writes from the 387 */
1590
1591  if (STACK_TOP_P (operands[1]))
1592    {
1593      output_asm_insn (AS1 (fstp%z0,%y0), operands);
1594      if (! stack_top_dies)
1595	return AS1 (fld%z0,%y0);
1596
1597      RET;
1598    }
1599
1600  /* Handle other kinds of reads to the 387 */
1601
1602  if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
1603    return output_move_const_single (operands);
1604
1605  if (STACK_TOP_P (operands[0]))
1606       return AS1 (fld%z1,%y1);
1607
1608  /* Handle all XFmode moves not involving the 387 */
1609
1610  return output_move_double (operands);
1611}")
1612
1613(define_insn "swapxf" 
1614  [(set (match_operand:XF 0 "register_operand" "f")
1615	(match_operand:XF 1 "register_operand" "f"))
1616   (set (match_dup 1)
1617	(match_dup 0))]
1618  ""
1619  "*
1620{
1621  if (STACK_TOP_P (operands[0]))
1622    return AS1 (fxch,%1);
1623  else
1624    return AS1 (fxch,%0);
1625}")
1626
1627(define_insn ""
1628  [(set (match_operand:DI 0 "push_operand" "=<")
1629	(match_operand:DI 1 "general_operand" "riF"))]
1630  ""
1631  "* return output_move_double (operands);")
1632
1633(define_insn ""
1634  [(set (match_operand:DI 0 "push_operand" "=<")
1635	(match_operand:DI 1 "memory_operand" "o"))]
1636  "TARGET_PUSH_MEMORY"
1637  "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode),0,0);")
1638
1639(define_expand "movdi"
1640  [(set (match_operand:DI 0 "general_operand" "")
1641	(match_operand:DI 1 "general_operand" ""))]
1642  ""
1643  "
1644{
1645  /* Don't generate memory->memory moves, go through a register */
1646  if (TARGET_MOVE
1647      && (reload_in_progress | reload_completed) == 0
1648      && GET_CODE (operands[0]) == MEM
1649      && GET_CODE (operands[1]) == MEM)
1650    {
1651      operands[1] = force_reg (DImode, operands[1]);
1652    }
1653}")
1654
1655(define_insn ""
1656  [(set (match_operand:DI 0 "general_operand" "=g,r")
1657	(match_operand:DI 1 "general_operand" "riF,m"))]
1658  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
1659   || (GET_CODE (operands[1]) != MEM)"
1660  "* return output_move_double (operands);")
1661
1662
1663;;- conversion instructions
1664;;- NONE
1665
1666;;- zero extension instructions
1667;; See comments by `andsi' for when andl is faster than movzx.
1668
1669(define_insn "zero_extendhisi2"
1670  [(set (match_operand:SI 0 "register_operand" "=r,&r,?r")
1671	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,rm,rm")))]
1672  ""
1673  "*
1674  {
1675  rtx xops[2];
1676
1677  if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) 
1678      && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
1679    {
1680      xops[0] = operands[0];
1681      xops[1] = GEN_INT (0xffff);
1682      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1683      RET;
1684    }
1685  if (TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1]))
1686    {
1687      output_asm_insn (AS2 (xor%L0,%0,%0),operands);
1688      output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
1689      RET;
1690    }
1691
1692  if (TARGET_ZERO_EXTEND_WITH_AND)
1693    {
1694      xops[0] = operands[0];
1695      xops[1] = GEN_INT (0xffff);
1696      if (i386_aligned_p (operands[1]))
1697	output_asm_insn (AS2 (mov%L0,%k1,%k0),operands);
1698      else
1699	output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
1700      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1701      RET;
1702    }
1703
1704#ifdef INTEL_SYNTAX
1705  return AS2 (movzx,%1,%0);
1706#else
1707  return AS2 (movz%W0%L0,%1,%0);
1708#endif
1709}")
1710
1711(define_split
1712  [(set (match_operand:SI 0 "register_operand" "")
1713	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
1714 "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1])"
1715 [(set (match_dup 0)
1716       (const_int 0))
1717  (set (strict_low_part (match_dup 2))
1718       (match_dup 1))]
1719 "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));")
1720
1721
1722(define_split
1723  [(set (match_operand:SI 0 "register_operand" "")
1724	(zero_extend:SI (match_operand:HI 1 "memory_operand" "")))]
1725 "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && reg_overlap_mentioned_p (operands[0], operands[1])"
1726 [(set (strict_low_part (match_dup 2))
1727       (match_dup 1))
1728  (set (match_dup 0)
1729       (and:SI (match_dup 0)
1730	       (const_int 65535)))]
1731  "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));")
1732
1733(define_insn "zero_extendqihi2"
1734  [(set (match_operand:HI 0 "register_operand" "=q,&q,?r")
1735	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
1736  ""
1737  "*
1738  {
1739  rtx xops[2];
1740
1741  if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
1742      && REG_P (operands[1]) 
1743      && REGNO (operands[0]) == REGNO (operands[1]))
1744    {
1745      xops[0] = operands[0];
1746      xops[1] = GEN_INT (0xff);
1747      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1748      RET;
1749    }
1750  if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0]))
1751    {
1752      if(!reg_overlap_mentioned_p(operands[0],operands[1]))
1753	{
1754	  output_asm_insn (AS2 (xor%L0,%k0,%k0), operands);
1755	  output_asm_insn (AS2 (mov%B0,%1,%b0), operands);
1756	}
1757      else
1758	{
1759	  xops[0] = operands[0];
1760	  xops[1] = GEN_INT (0xff);
1761	  output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
1762	  output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1763	}
1764      RET;
1765    }
1766  
1767#ifdef INTEL_SYNTAX
1768  return AS2 (movzx,%1,%0);
1769#else
1770  return AS2 (movz%B0%W0,%1,%0);
1771#endif
1772}")
1773
1774(define_split
1775  [(set (match_operand:HI 0 "register_operand" "")
1776	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
1777 "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
1778  && !reg_overlap_mentioned_p (operands[0], operands[1])"
1779 [(set (match_dup 0)
1780       (const_int 0))
1781  (set (strict_low_part (match_dup 2))
1782       (match_dup 1))]
1783 "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
1784
1785
1786(define_split
1787  [(set (match_operand:HI 0 "register_operand" "")
1788	(zero_extend:HI (match_operand:QI 1 "memory_operand" "")))]
1789 "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
1790  && reg_overlap_mentioned_p (operands[0], operands[1])"
1791 [(set (strict_low_part (match_dup 2))
1792       (match_dup 1))
1793  (set (match_dup 0)
1794       (and:HI (match_dup 0)
1795	       (const_int 255)))]
1796 "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
1797
1798(define_split
1799  [(set (match_operand:HI 0 "register_operand" "")
1800	(zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
1801 "reload_completed && TARGET_ZERO_EXTEND_WITH_AND"
1802 [(set (match_dup 0)
1803       (match_dup 2))
1804  (set (match_dup 0)
1805       (and:HI (match_dup 0)
1806	       (const_int 255)))]
1807 "if (GET_CODE (operands[1]) == SUBREG && SUBREG_WORD (operands[1]) == 0)
1808    operands[1] = SUBREG_REG (operands[1]);
1809  if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG
1810      || REGNO (operands[0]) == REGNO (operands[1]))
1811    FAIL;
1812  operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
1813
1814(define_insn "zero_extendqisi2"
1815  [(set (match_operand:SI 0 "register_operand" "=q,&q,?r")
1816	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
1817  ""
1818  "*
1819  {
1820  rtx xops[2];
1821
1822  if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
1823      && REG_P (operands[1]) 
1824      && REGNO (operands[0]) == REGNO (operands[1]))
1825    {
1826      xops[0] = operands[0];
1827      xops[1] = GEN_INT (0xff);
1828      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1829      RET;
1830    }
1831  if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0]))
1832    {
1833      if(!reg_overlap_mentioned_p (operands[0], operands[1]))
1834	{
1835	  output_asm_insn (AS2 (xor%L0,%0,%0),operands);
1836	  output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
1837	}
1838      else
1839	{
1840	  xops[0] = operands[0];
1841	  xops[1] = GEN_INT (0xff);
1842	  output_asm_insn (AS2 (mov%B0,%1,%b0), operands);
1843	  output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1844	}
1845      RET;
1846    }
1847
1848  if (TARGET_ZERO_EXTEND_WITH_AND && GET_CODE (operands[1]) == REG)
1849    {
1850      xops[0] = operands[0];
1851      xops[1] = GEN_INT (0xff);
1852      operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]));
1853      output_asm_insn (AS2 (mov%L0,%1,%0), operands);
1854      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1855      RET;
1856    }
1857
1858#ifdef INTEL_SYNTAX
1859  return AS2 (movzx,%1,%0);
1860#else
1861  return AS2 (movz%B0%L0,%1,%0);
1862#endif
1863}")
1864
1865(define_split
1866  [(set (match_operand:SI 0 "register_operand" "")
1867	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1868 "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
1869  && !reg_overlap_mentioned_p (operands[0], operands[1])"
1870 [(set (match_dup 0)
1871       (const_int 0))
1872  (set (strict_low_part (match_dup 2))
1873       (match_dup 1))]
1874 "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
1875
1876
1877(define_split
1878  [(set (match_operand:SI 0 "register_operand" "")
1879	(zero_extend:SI (match_operand:QI 1 "memory_operand" "")))]
1880 "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
1881  && reg_overlap_mentioned_p (operands[0], operands[1])"
1882 [(set (strict_low_part (match_dup 2))
1883       (match_dup 1))
1884  (set (match_dup 0)
1885       (and:SI (match_dup 0)
1886	       (const_int 255)))]
1887 "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
1888
1889(define_split
1890  [(set (match_operand:SI 0 "register_operand" "")
1891	(zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
1892 "reload_completed && TARGET_ZERO_EXTEND_WITH_AND
1893  && ! reg_overlap_mentioned_p (operands[0], operands[1])"
1894 [(set (match_dup 0)
1895       (match_dup 2))
1896  (set (match_dup 0)
1897       (and:SI (match_dup 0)
1898	       (const_int 255)))]
1899 "operands[2] = gen_rtx_REG (SImode, true_regnum (operands[1]));")
1900
1901(define_insn "zero_extendsidi2"
1902  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?m")
1903	(zero_extend:DI (match_operand:SI 1 "register_operand" "0,rm,r")))]
1904  ""
1905  "*
1906  {
1907  rtx high[2], low[2], xops[4];
1908
1909  if (REG_P (operands[0]) && REG_P (operands[1])
1910      && REGNO (operands[0]) == REGNO (operands[1]))
1911    {
1912      operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
1913      return AS2 (xor%L0,%0,%0);
1914    }
1915
1916  split_di (operands, 1, low, high);
1917  xops[0] = low[0];
1918  xops[1] = operands[1];
1919  xops[2] = high[0];
1920  xops[3] = const0_rtx;
1921
1922  output_asm_insn (AS2 (mov%L0,%1,%0), xops);
1923  if (GET_CODE (low[0]) == MEM)
1924    output_asm_insn (AS2 (mov%L2,%3,%2), xops);
1925  else
1926    output_asm_insn (AS2 (xor%L2,%2,%2), xops);
1927
1928  RET;
1929}")
1930
1931;;- sign extension instructions
1932
1933(define_insn "extendsidi2"
1934  [(set (match_operand:DI 0 "register_operand" "=r")
1935	(sign_extend:DI (match_operand:SI 1 "register_operand" "0")))]
1936  ""
1937  "*
1938{
1939  if (REGNO (operands[0]) == 0)
1940    {
1941      /* This used to be cwtl, but that extends HI to SI somehow.  */
1942#ifdef INTEL_SYNTAX
1943      return \"cdq\";
1944#else
1945      return \"cltd\";
1946#endif
1947    }
1948
1949  operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
1950  output_asm_insn (AS2 (mov%L0,%0,%1), operands);
1951
1952  operands[0] = GEN_INT (31);
1953  return AS2 (sar%L1,%0,%1);
1954}")
1955
1956;; Note that the i386 programmers' manual says that the opcodes
1957;; are named movsx..., but the assembler on Unix does not accept that.
1958;; We use what the Unix assembler expects.
1959
1960(define_insn "extendhisi2"
1961  [(set (match_operand:SI 0 "register_operand" "=r")
1962	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
1963  ""
1964  "*
1965{
1966  if (REGNO (operands[0]) == 0
1967      && REG_P (operands[1]) && REGNO (operands[1]) == 0)
1968#ifdef INTEL_SYNTAX
1969    return \"cwde\";
1970#else
1971    return \"cwtl\";
1972#endif
1973
1974#ifdef INTEL_SYNTAX
1975  return AS2 (movsx,%1,%0);
1976#else
1977  return AS2 (movs%W0%L0,%1,%0);
1978#endif
1979}")
1980
1981(define_insn "extendqihi2"
1982  [(set (match_operand:HI 0 "register_operand" "=r")
1983	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1984  ""
1985  "*
1986{
1987  if (REGNO (operands[0]) == 0
1988      && REG_P (operands[1]) && REGNO (operands[1]) == 0)
1989    return \"cbtw\";
1990
1991#ifdef INTEL_SYNTAX
1992  return AS2 (movsx,%1,%0);
1993#else
1994  return AS2 (movs%B0%W0,%1,%0);
1995#endif
1996}")
1997
1998(define_insn "extendqisi2"
1999  [(set (match_operand:SI 0 "register_operand" "=r")
2000	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
2001  ""
2002  "*
2003{
2004#ifdef INTEL_SYNTAX
2005  return AS2 (movsx,%1,%0);
2006#else
2007  return AS2 (movs%B0%L0,%1,%0);
2008#endif
2009}")
2010
2011
2012;; Truncation of long long -> 32 bit
2013
2014(define_expand "truncdisi2"
2015  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
2016	(truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))]
2017  ""
2018  "
2019{
2020  /* Don't generate memory->memory moves, go through a register */
2021  if (TARGET_MOVE
2022      && (reload_in_progress | reload_completed) == 0
2023      && GET_CODE (operands[0]) == MEM
2024      && GET_CODE (operands[1]) == MEM)
2025    {
2026      rtx target = gen_reg_rtx (SImode);
2027      emit_insn (gen_truncdisi2 (target, operands[1]));
2028      emit_move_insn (operands[0], target);
2029      DONE;
2030    }
2031}")
2032
2033(define_insn ""
2034  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
2035	(truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))]
2036  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
2037  "*
2038{
2039  rtx low[2], high[2], xops[2];
2040
2041  split_di (&operands[1], 1, low, high);
2042  xops[0] = operands[0];
2043  xops[1] = low[0];
2044  if (!rtx_equal_p (xops[0], xops[1]))
2045    output_asm_insn (AS2 (mov%L0,%1,%0), xops);
2046
2047  RET;
2048}")
2049
2050(define_insn ""
2051  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
2052	(truncate:SI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r")
2053				  (const_int 32))))]
2054  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
2055  "*
2056{
2057  rtx low[2], high[2], xops[2];
2058
2059  split_di (&operands[1], 1, low, high);
2060  xops[0] = operands[0];
2061  xops[1] = high[0];
2062  if (!rtx_equal_p (xops[0], xops[1]))
2063    output_asm_insn (AS2 (mov%L0,%1,%0), xops);
2064
2065  RET;
2066}")
2067
2068
2069
2070;; Conversions between float and double.
2071
2072(define_insn "extendsfdf2"
2073  [(set (match_operand:DF 0 "nonimmediate_operand" "=fm,f")
2074	(float_extend:DF
2075	 (match_operand:SF 1 "nonimmediate_operand" "f,fm")))]
2076  "TARGET_80387"
2077  "*
2078{
2079  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2080
2081  if (NON_STACK_REG_P (operands[1]))
2082    {
2083      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
2084      RET;
2085    }
2086
2087  if (NON_STACK_REG_P (operands[0]))
2088    {
2089      output_to_reg (operands[0], stack_top_dies, 0);
2090      RET;
2091    }
2092
2093  if (STACK_TOP_P (operands[0]))
2094    return AS1 (fld%z1,%y1);
2095
2096  if (GET_CODE (operands[0]) == MEM)
2097    {
2098      if (stack_top_dies)
2099	return AS1 (fstp%z0,%y0);
2100      else
2101        return AS1 (fst%z0,%y0);
2102    }
2103
2104  abort ();
2105}")
2106
2107(define_insn "extenddfxf2"
2108  [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
2109	(float_extend:XF
2110	 (match_operand:DF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
2111  "TARGET_80387"
2112  "*
2113{
2114  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2115
2116  if (NON_STACK_REG_P (operands[1]))
2117    {
2118      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
2119      RET;
2120    }
2121
2122  if (NON_STACK_REG_P (operands[0]))
2123    {
2124      output_to_reg (operands[0], stack_top_dies, 0);
2125      RET;
2126    }
2127
2128  if (STACK_TOP_P (operands[0]))
2129    return AS1 (fld%z1,%y1);
2130
2131  if (GET_CODE (operands[0]) == MEM)
2132    {
2133      output_asm_insn (AS1 (fstp%z0,%y0), operands);
2134      if (! stack_top_dies)
2135	return AS1 (fld%z0,%y0);
2136      RET;
2137    }
2138
2139  abort ();
2140}")
2141
2142(define_insn "extendsfxf2"
2143  [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
2144	(float_extend:XF
2145	 (match_operand:SF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
2146  "TARGET_80387"
2147  "*
2148{
2149  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2150
2151  if (NON_STACK_REG_P (operands[1]))
2152    {
2153      output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
2154      RET;
2155    }
2156
2157  if (NON_STACK_REG_P (operands[0]))
2158    {
2159      output_to_reg (operands[0], stack_top_dies, 0);
2160      RET;
2161    }
2162
2163  if (STACK_TOP_P (operands[0]))
2164    return AS1 (fld%z1,%y1);
2165
2166  if (GET_CODE (operands[0]) == MEM)
2167    {
2168      output_asm_insn (AS1 (fstp%z0,%y0), operands);
2169      if (! stack_top_dies)
2170	return AS1 (fld%z0,%y0);
2171      RET;
2172    }
2173
2174  abort ();
2175}")
2176
2177(define_expand "truncdfsf2"
2178  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
2179		   (float_truncate:SF
2180		    (match_operand:DF 1 "register_operand" "")))
2181	      (clobber (match_dup 2))])]
2182  "TARGET_80387"
2183  "
2184{
2185  operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
2186}")
2187
2188;; This cannot output into an f-reg because there is no way to be sure
2189;; of truncating in that case.  Otherwise this is just like a simple move
2190;; insn.  So we pretend we can output to a reg in order to get better
2191;; register preferencing, but we really use a stack slot.
2192
2193(define_insn ""
2194  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m")
2195	(float_truncate:SF
2196	 (match_operand:DF 1 "register_operand" "0,f")))
2197   (clobber (match_operand:SF 2 "memory_operand" "m,m"))]
2198  "TARGET_80387"
2199  "*
2200{
2201  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2202
2203  if (GET_CODE (operands[0]) == MEM)
2204    {
2205      if (stack_top_dies)
2206	return AS1 (fstp%z0,%0);
2207      else
2208        return AS1 (fst%z0,%0);
2209    }
2210  else if (STACK_TOP_P (operands[0]))
2211    {
2212      output_asm_insn (AS1 (fstp%z2,%y2), operands);
2213      return AS1 (fld%z2,%y2);
2214    }
2215  else
2216    abort ();
2217}")
2218
2219(define_insn "truncxfsf2"
2220  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,!*r")
2221	(float_truncate:SF
2222	 (match_operand:XF 1 "register_operand" "f,f")))]
2223  "TARGET_80387"
2224  "*
2225{
2226  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2227
2228  if (NON_STACK_REG_P (operands[0]))
2229    {
2230      if (stack_top_dies == 0)
2231	{
2232	  output_asm_insn (AS1 (fld,%y1), operands);
2233	  stack_top_dies = 1;
2234	}
2235      output_to_reg (operands[0], stack_top_dies, 0);
2236      RET;
2237    }
2238  else if (GET_CODE (operands[0]) == MEM)
2239    {
2240      if (stack_top_dies)
2241	return AS1 (fstp%z0,%0);
2242      else
2243	{
2244	  output_asm_insn (AS1 (fld,%y1), operands);
2245	  return AS1 (fstp%z0,%0);
2246	}
2247    }
2248  else
2249    abort ();
2250}")
2251
2252(define_insn "truncxfdf2"
2253  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,!*r")
2254	(float_truncate:DF
2255	 (match_operand:XF 1 "register_operand" "f,f")))]
2256  "TARGET_80387"
2257  "*
2258{
2259  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2260
2261  if (NON_STACK_REG_P (operands[0]))
2262    {
2263      if (stack_top_dies == 0)
2264	{
2265	  output_asm_insn (AS1 (fld,%y1), operands);
2266	  stack_top_dies = 1;
2267	}
2268      output_to_reg (operands[0], stack_top_dies, 0);
2269      RET;
2270    }
2271  else if (GET_CODE (operands[0]) == MEM)
2272    {
2273      if (stack_top_dies)
2274	return AS1 (fstp%z0,%0);
2275      else
2276	{
2277	  output_asm_insn (AS1 (fld,%y1), operands);
2278	  return AS1 (fstp%z0,%0);
2279	}
2280    }
2281  else
2282    abort ();
2283}")
2284
2285
2286;; The 387 requires that the stack top dies after converting to DImode.
2287
2288;; Represent an unsigned conversion from SImode to MODE_FLOAT by first
2289;; doing a signed conversion to DImode, and then taking just the low
2290;; part.
2291
2292(define_expand "fixuns_truncxfsi2"
2293  [(set (match_dup 4)
2294	(match_operand:XF 1 "register_operand" ""))
2295   (parallel [(set (match_dup 2)
2296		   (fix:DI (fix:XF (match_dup 4))))
2297	      (clobber (match_dup 4))
2298	      (clobber (match_dup 5))
2299	      (clobber (match_dup 6))
2300	      (clobber (match_scratch:SI 7 ""))])
2301   (set (match_operand:SI 0 "general_operand" "")
2302	(match_dup 3))]
2303  "TARGET_80387"
2304  "
2305{
2306  operands[2] = gen_reg_rtx (DImode);
2307  operands[3] = gen_lowpart (SImode, operands[2]);
2308  operands[4] = gen_reg_rtx (XFmode);
2309  operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2310  operands[6] = (rtx) assign_386_stack_local (DImode, 1);
2311}")
2312
2313(define_expand "fixuns_truncdfsi2"
2314  [(set (match_dup 4)
2315	(match_operand:DF 1 "register_operand" ""))
2316   (parallel [(set (match_dup 2)
2317		   (fix:DI (fix:DF (match_dup 4))))
2318	      (clobber (match_dup 4))
2319	      (clobber (match_dup 5))
2320	      (clobber (match_dup 6))
2321	      (clobber (match_scratch:SI 7 ""))])
2322   (set (match_operand:SI 0 "general_operand" "")
2323	(match_dup 3))]
2324  "TARGET_80387"
2325  "
2326{
2327  operands[2] = gen_reg_rtx (DImode);
2328  operands[3] = gen_lowpart (SImode, operands[2]);
2329  operands[4] = gen_reg_rtx (DFmode);
2330  operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2331  operands[6] = (rtx) assign_386_stack_local (DImode, 1);
2332}")
2333
2334(define_expand "fixuns_truncsfsi2"
2335  [(set (match_dup 4)
2336	(match_operand:SF 1 "register_operand" ""))
2337   (parallel [(set (match_dup 2)
2338		   (fix:DI (fix:SF (match_dup 4))))
2339	      (clobber (match_dup 4))
2340	      (clobber (match_dup 5))
2341	      (clobber (match_dup 6))
2342	      (clobber (match_scratch:SI 7 ""))])
2343   (set (match_operand:SI 0 "general_operand" "")
2344	(match_dup 3))]
2345  "TARGET_80387"
2346  "
2347{
2348  operands[2] = gen_reg_rtx (DImode);
2349  operands[3] = gen_lowpart (SImode, operands[2]);
2350  operands[4] = gen_reg_rtx (SFmode);
2351  operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2352  operands[6] = (rtx) assign_386_stack_local (DImode, 1);
2353}")
2354
2355;; Signed conversion to DImode.
2356
2357(define_expand "fix_truncxfdi2"
2358  [(set (match_dup 2)
2359	(match_operand:XF 1 "register_operand" ""))
2360   (parallel [(set (match_operand:DI 0 "general_operand" "")
2361		   (fix:DI (fix:XF (match_dup 2))))
2362	      (clobber (match_dup 2))
2363	      (clobber (match_dup 3))
2364	      (clobber (match_dup 4))
2365	      (clobber (match_scratch:SI 5 ""))])]
2366  "TARGET_80387"
2367  "
2368{
2369  operands[1] = copy_to_mode_reg (XFmode, operands[1]);
2370  operands[2] = gen_reg_rtx (XFmode);
2371  operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2372  operands[4] = (rtx) assign_386_stack_local (DImode, 1);
2373}")
2374
2375(define_expand "fix_truncdfdi2"
2376  [(set (match_dup 2)
2377	(match_operand:DF 1 "register_operand" ""))
2378   (parallel [(set (match_operand:DI 0 "general_operand" "")
2379		   (fix:DI (fix:DF (match_dup 2))))
2380	      (clobber (match_dup 2))
2381	      (clobber (match_dup 3))
2382	      (clobber (match_dup 4))
2383	      (clobber (match_scratch:SI 5 ""))])]
2384  "TARGET_80387"
2385  "
2386{
2387  operands[1] = copy_to_mode_reg (DFmode, operands[1]);
2388  operands[2] = gen_reg_rtx (DFmode);
2389  operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2390  operands[4] = (rtx) assign_386_stack_local (DImode, 1);
2391}")
2392
2393(define_expand "fix_truncsfdi2"
2394  [(set (match_dup 2)
2395	(match_operand:SF 1 "register_operand" ""))
2396   (parallel [(set (match_operand:DI 0 "general_operand" "")
2397		   (fix:DI (fix:SF (match_dup 2))))
2398	      (clobber (match_dup 2))
2399	      (clobber (match_dup 3))
2400	      (clobber (match_dup 4))
2401	      (clobber (match_scratch:SI 5 ""))])]
2402  "TARGET_80387"
2403  "
2404{
2405  operands[1] = copy_to_mode_reg (SFmode, operands[1]);
2406  operands[2] = gen_reg_rtx (SFmode);
2407  operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2408  operands[4] = (rtx) assign_386_stack_local (DImode, 1);
2409}")
2410
2411;; These match a signed conversion of either DFmode or SFmode to DImode.
2412
2413(define_insn ""
2414  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
2415	(fix:DI (fix:XF (match_operand:XF 1 "register_operand" "+f"))))
2416   (clobber (match_dup 1))
2417   (clobber (match_operand:SI 2 "memory_operand" "m"))
2418   (clobber (match_operand:DI 3 "memory_operand" "m"))
2419   (clobber (match_scratch:SI 4 "=&q"))]
2420  "TARGET_80387"
2421  "* return output_fix_trunc (insn, operands);")
2422
2423(define_insn ""
2424  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
2425	(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "+f"))))
2426   (clobber (match_dup 1))
2427   (clobber (match_operand:SI 2 "memory_operand" "m"))
2428   (clobber (match_operand:DI 3 "memory_operand" "m"))
2429   (clobber (match_scratch:SI 4 "=&q"))]
2430  "TARGET_80387"
2431  "* return output_fix_trunc (insn, operands);")
2432
2433(define_insn ""
2434  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
2435	(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "+f"))))
2436   (clobber (match_dup 1))
2437   (clobber (match_operand:SI 2 "memory_operand" "m"))
2438   (clobber (match_operand:DI 3 "memory_operand" "m"))
2439   (clobber (match_scratch:SI 4 "=&q"))]
2440  "TARGET_80387"
2441  "* return output_fix_trunc (insn, operands);")
2442
2443;; Signed MODE_FLOAT conversion to SImode.
2444
2445(define_expand "fix_truncxfsi2"
2446  [(parallel [(set (match_operand:SI 0 "general_operand" "")
2447		   (fix:SI
2448		    (fix:XF (match_operand:XF 1 "register_operand" ""))))
2449	      (clobber (match_dup 2))
2450	      (clobber (match_dup 3))
2451	      (clobber (match_scratch:SI 4 ""))])]
2452  "TARGET_80387"
2453  "
2454{
2455  operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2456  operands[3] = (rtx) assign_386_stack_local (DImode, 1);
2457}")
2458
2459(define_expand "fix_truncdfsi2"
2460  [(parallel [(set (match_operand:SI 0 "general_operand" "")
2461		   (fix:SI
2462		    (fix:DF (match_operand:DF 1 "register_operand" ""))))
2463	      (clobber (match_dup 2))
2464	      (clobber (match_dup 3))
2465	      (clobber (match_scratch:SI 4 ""))])]
2466  "TARGET_80387"
2467  "
2468{
2469  operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2470  operands[3] = (rtx) assign_386_stack_local (DImode, 1);
2471}")
2472
2473(define_expand "fix_truncsfsi2"
2474  [(parallel [(set (match_operand:SI 0 "general_operand" "")
2475		   (fix:SI
2476		    (fix:SF (match_operand:SF 1 "register_operand" ""))))
2477	      (clobber (match_dup 2))
2478	      (clobber (match_dup 3))
2479	      (clobber (match_scratch:SI 4 ""))])]
2480  "TARGET_80387"
2481  "
2482{
2483  operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2484  operands[3] = (rtx) assign_386_stack_local (DImode, 1);
2485}")
2486
2487(define_insn ""
2488  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
2489	(fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
2490   (clobber (match_operand:SI 2 "memory_operand" "m"))
2491   (clobber (match_operand:DI 3 "memory_operand" "m"))
2492   (clobber (match_scratch:SI 4 "=&q"))]
2493  "TARGET_80387"
2494  "* return output_fix_trunc (insn, operands);")
2495
2496(define_insn ""
2497  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
2498	(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
2499   (clobber (match_operand:SI 2 "memory_operand" "m"))
2500   (clobber (match_operand:DI 3 "memory_operand" "m"))
2501   (clobber (match_scratch:SI 4 "=&q"))]
2502  "TARGET_80387"
2503  "* return output_fix_trunc (insn, operands);")
2504
2505(define_insn ""
2506  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
2507	(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
2508   (clobber (match_operand:SI 2 "memory_operand" "m"))
2509   (clobber (match_operand:DI 3 "memory_operand" "m"))
2510   (clobber (match_scratch:SI 4 "=&q"))]
2511  "TARGET_80387"
2512  "* return output_fix_trunc (insn, operands);")
2513
2514;; Conversion between fixed point and floating point.
2515;; The actual pattern that matches these is at the end of this file.
2516
2517;; ??? Possibly represent floatunssidf2 here in gcc2.
2518
2519(define_expand "floatsisf2"
2520  [(set (match_operand:SF 0 "register_operand" "")
2521	(float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
2522  "TARGET_80387"
2523  "")
2524
2525(define_expand "floatdisf2"
2526  [(set (match_operand:SF 0 "register_operand" "")
2527	(float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
2528  "TARGET_80387"
2529  "")
2530
2531(define_expand "floatsidf2"
2532  [(set (match_operand:DF 0 "register_operand" "")
2533	(float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
2534  "TARGET_80387"
2535  "")
2536
2537(define_expand "floatdidf2"
2538  [(set (match_operand:DF 0 "register_operand" "")
2539	(float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
2540  "TARGET_80387"
2541  "")
2542
2543(define_expand "floatsixf2"
2544  [(set (match_operand:XF 0 "register_operand" "")
2545	(float:XF (match_operand:SI 1 "nonimmediate_operand" "")))]
2546  "TARGET_80387"
2547  "")
2548
2549(define_expand "floatdixf2"
2550  [(set (match_operand:XF 0 "register_operand" "")
2551	(float:XF (match_operand:DI 1 "nonimmediate_operand" "")))]
2552  "TARGET_80387 && LONG_DOUBLE_TYPE_SIZE == 96"
2553  "")
2554
2555;; This will convert from SImode or DImode to MODE_FLOAT.
2556
2557(define_insn ""
2558  [(set (match_operand:XF 0 "register_operand" "=f")
2559	(float:XF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2560  "TARGET_80387"
2561  "*
2562{
2563  if (NON_STACK_REG_P (operands[1]))
2564    {
2565      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2566      RET;
2567    }
2568  else if (GET_CODE (operands[1]) == MEM)
2569    return AS1 (fild%z1,%1);
2570  else
2571    abort ();
2572}")
2573
2574(define_insn ""
2575  [(set (match_operand:DF 0 "register_operand" "=f")
2576	(float:DF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2577  "TARGET_80387"
2578  "*
2579{
2580  if (NON_STACK_REG_P (operands[1]))
2581    {
2582      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2583      RET;
2584    }
2585  else if (GET_CODE (operands[1]) == MEM)
2586    return AS1 (fild%z1,%1);
2587  else
2588    abort ();
2589}")
2590
2591(define_insn ""
2592  [(set (match_operand:SF 0 "register_operand" "=f")
2593	(float:SF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2594  "TARGET_80387"
2595  "*
2596{
2597  if (NON_STACK_REG_P (operands[1]))
2598    {
2599      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2600      RET;
2601    }
2602  else if (GET_CODE (operands[1]) == MEM)
2603    return AS1 (fild%z1,%1);
2604  else
2605    abort ();
2606}")
2607
2608(define_insn ""
2609  [(set (match_operand:DF 0 "register_operand" "=f")
2610	(float:DF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
2611  "TARGET_80387"
2612  "*
2613{
2614  if (NON_STACK_REG_P (operands[1]))
2615    {
2616      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2617      RET;
2618    }
2619  else if (GET_CODE (operands[1]) == MEM)
2620    return AS1 (fild%z1,%1);
2621  else
2622    abort ();
2623}")
2624
2625(define_insn ""
2626  [(set (match_operand:XF 0 "register_operand" "=f,f")
2627	(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,!*r")))]
2628  "TARGET_80387"
2629  "*
2630{
2631  if (NON_STACK_REG_P (operands[1]))
2632    {
2633      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2634      RET;
2635    }
2636  else if (GET_CODE (operands[1]) == MEM)
2637    return AS1 (fild%z1,%1);
2638  else
2639    abort ();
2640}")
2641
2642(define_insn ""
2643  [(set (match_operand:SF 0 "register_operand" "=f")
2644	(float:SF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
2645  "TARGET_80387"
2646  "*
2647{
2648  if (NON_STACK_REG_P (operands[1]))
2649    {
2650      output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2651      RET;
2652    }
2653  else if (GET_CODE (operands[1]) == MEM)
2654    return AS1 (fild%z1,%1);
2655  else
2656    abort ();
2657}")
2658
2659;;- add instructions
2660
2661(define_insn "addsidi3_1"
2662  [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,!&r,!r,o,!o")
2663	(plus:DI (match_operand:DI 1 "general_operand" "0,0,0,o,riF,riF,o")
2664		 (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,roi,roi,ri,ri"))))
2665   (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,&r"))]
2666  ""
2667  "*
2668{
2669  rtx low[3], high[3], xops[7], temp;
2670
2671  CC_STATUS_INIT;
2672
2673  split_di (operands, 2, low, high);
2674  high[2] = const0_rtx;
2675  low[2]  = operands[2];
2676
2677  if (!rtx_equal_p (operands[0], operands[1]))
2678    {
2679      xops[0] = high[0];
2680      xops[1] = low[0];
2681      xops[2] = high[1];
2682      xops[3] = low[1];
2683
2684      if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2685	{
2686	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2687	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2688	}
2689      else
2690	{
2691	  xops[4] = high[2];
2692	  xops[5] = low[2];
2693	  xops[6] = operands[3];
2694	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2695	  output_asm_insn (AS2 (add%L6,%5,%6), xops);
2696	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2697	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2698	  output_asm_insn (AS2 (adc%L6,%4,%6), xops);
2699	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2700	  RET;
2701	}
2702    }
2703
2704  output_asm_insn (AS2 (add%L0,%2,%0), low);
2705  output_asm_insn (AS2 (adc%L0,%2,%0), high);
2706  RET;
2707}")
2708
2709(define_insn "addsidi3_2"
2710  [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,&r,!&r,&r,o,o,!o")
2711	(plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,o,ri,ri,i,r"))
2712		 (match_operand:DI 1 "general_operand" "0,0,0,iF,ro,roiF,riF,o,o")))
2713   (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,X,&r,&r"))]
2714  ""
2715  "*
2716{
2717  rtx low[3], high[3], xops[7], temp;
2718
2719  CC_STATUS_INIT;
2720
2721  split_di (operands, 2, low, high);
2722  high[2] = const0_rtx;
2723  low[2]  = operands[2];
2724
2725  if (!rtx_equal_p (operands[0], operands[1]))
2726    {
2727      xops[0] = high[0];
2728      xops[1] = low[0];
2729      xops[2] = high[1];
2730      xops[3] = low[1];
2731
2732      if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2733	{
2734	  if (rtx_equal_p (low[0], operands[2]))
2735	    {
2736	      output_asm_insn (AS2 (mov%L0,%2,%0), high);
2737	      output_asm_insn (AS2 (add%L0,%1,%0), low);
2738	      output_asm_insn (AS2 (adc%L0,%1,%0), high);
2739	      RET;
2740	    }
2741	  if (rtx_equal_p (high[0], operands[2]))
2742	    {
2743	      if (GET_CODE (operands[0]) != MEM)
2744		{
2745		  output_asm_insn (AS2 (mov%L0,%2,%0), low);
2746		  output_asm_insn (AS2 (mov%L0,%2,%0), high);
2747		  output_asm_insn (AS2 (add%L0,%1,%0), low);
2748		  output_asm_insn (AS2 (adc%L0,%1,%0), high);
2749		}
2750	      else
2751		{
2752		  /* It's too late to ask for a scratch now - but this
2753		     will probably not happen too often.  */
2754		  output_asm_insn (AS2 (add%L1,%2,%1), low);
2755		  output_asm_insn (AS2 (mov%L0,%1,%0), low);
2756		  output_asm_insn (AS2 (mov%L1,%2,%1), low);
2757		  output_asm_insn (AS2 (mov%L0,%2,%0), high);
2758		  output_asm_insn (AS2 (adc%L0,%1,%0), high);
2759		  output_asm_insn (AS2 (sub%L1,%0,%1), low);
2760		  output_asm_insn (AS1 (neg%L1,%1), low);
2761		}
2762	      RET;
2763	    }
2764	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2765	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2766	}
2767      else
2768	{
2769	  xops[4] = high[2];
2770	  xops[5] = low[2];
2771	  xops[6] = operands[3];
2772	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2773	  output_asm_insn (AS2 (add%L6,%5,%6), xops);
2774	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2775	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2776	  output_asm_insn (AS2 (adc%L6,%4,%6), xops);
2777	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2778	  RET;
2779	}
2780    }
2781
2782  output_asm_insn (AS2 (add%L0,%2,%0), low);
2783  output_asm_insn (AS2 (adc%L0,%2,%0), high);
2784  RET;
2785}")
2786
2787(define_insn "adddi3"
2788  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
2789	(plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
2790		 (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
2791   (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
2792  ""
2793  "*
2794{
2795  rtx low[3], high[3], xops[7], temp;
2796
2797  CC_STATUS_INIT;
2798
2799  if (rtx_equal_p (operands[0], operands[2]))
2800    {
2801      temp = operands[1];
2802      operands[1] = operands[2];
2803      operands[2] = temp;
2804    }
2805
2806  split_di (operands, 3, low, high);
2807  if (!rtx_equal_p (operands[0], operands[1]))
2808    {
2809      xops[0] = high[0];
2810      xops[1] = low[0];
2811      xops[2] = high[1];
2812      xops[3] = low[1];
2813
2814      if (GET_CODE (operands[0]) != MEM)
2815	{
2816	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2817	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2818	}
2819      else
2820	{
2821	  xops[4] = high[2];
2822	  xops[5] = low[2];
2823	  xops[6] = operands[3];
2824	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2825	  output_asm_insn (AS2 (add%L6,%5,%6), xops);
2826	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2827	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2828	  output_asm_insn (AS2 (adc%L6,%4,%6), xops);
2829	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2830	  RET;
2831	}
2832    }
2833
2834  if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
2835    {
2836      xops[0] = high[0];
2837      xops[1] = low[0];
2838      xops[2] = high[2];
2839      xops[3] = low[2];
2840      xops[4] = operands[3];
2841
2842      output_asm_insn (AS2 (mov%L4,%3,%4), xops);
2843      output_asm_insn (AS2 (add%L1,%4,%1), xops);
2844      output_asm_insn (AS2 (mov%L4,%2,%4), xops);
2845      output_asm_insn (AS2 (adc%L0,%4,%0), xops);
2846    }
2847
2848  else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
2849    {
2850      output_asm_insn (AS2 (add%L0,%2,%0), low);
2851      output_asm_insn (AS2 (adc%L0,%2,%0), high);
2852    }
2853
2854  else
2855    output_asm_insn (AS2 (add%L0,%2,%0), high);
2856
2857  RET;
2858}")
2859
2860;; On a 486, it is faster to do movl/addl than to do a single leal if
2861;; operands[1] and operands[2] are both registers.
2862
2863(define_expand "addsi3"
2864  [(set (match_operand:SI 0 "nonimmediate_operand" "")
2865	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
2866		 (match_operand:SI 2 "general_operand" "")))]
2867  ""
2868  "IX86_EXPAND_BINARY_OPERATOR (PLUS, SImode, operands);")
2869
2870(define_insn ""
2871  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
2872	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
2873		 (match_operand:SI 2 "general_operand" "rmi,ri,ri")))]
2874  "ix86_binary_operator_ok (PLUS, SImode, operands)"
2875  "*
2876{
2877  if (REG_P (operands[0]) && REG_P (operands[1])
2878      && (REG_P (operands[2]) || GET_CODE (operands[2]) == CONST_INT)
2879      && REGNO (operands[0]) != REGNO (operands[1]))
2880    {
2881      if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
2882	return AS2 (add%L0,%1,%0);
2883
2884      if (operands[2] == stack_pointer_rtx)
2885	{
2886	  rtx temp;
2887
2888	  temp = operands[1];
2889	  operands[1] = operands[2];
2890	  operands[2] = temp;
2891	}
2892
2893      if (operands[2] != stack_pointer_rtx)
2894	{
2895	  CC_STATUS_INIT;
2896	  operands[1] = SET_SRC (PATTERN (insn));
2897	  return AS2 (lea%L0,%a1,%0);
2898	}
2899    }
2900
2901  if (!rtx_equal_p (operands[0], operands[1]))
2902    output_asm_insn (AS2 (mov%L0,%1,%0), operands);
2903
2904  if (operands[2] == const1_rtx)
2905    return AS1 (inc%L0,%0);
2906
2907  if (operands[2] == constm1_rtx)
2908    return AS1 (dec%L0,%0);
2909
2910  /* subl $-128,%ebx is smaller than addl $128,%ebx. */
2911  if (GET_CODE (operands[2]) == CONST_INT
2912      && INTVAL (operands[2]) == 128)
2913    {
2914      /* This doesn't compute the carry bit in the same way
2915       * as add%L0, but we use inc and dec above and they
2916       * don't set the carry bit at all.  If inc/dec don't need
2917       * a CC_STATUS_INIT, this doesn't either... */
2918      operands[2] = GEN_INT (-128);
2919      return AS2 (sub%L0,%2,%0);
2920    }
2921
2922  return AS2 (add%L0,%2,%0);
2923}")
2924
2925;; addsi3 is faster, so put this after.
2926
2927(define_insn "movsi_lea"
2928  [(set (match_operand:SI 0 "register_operand" "=r")
2929        (match_operand:QI 1 "address_operand" "p"))]
2930  ""
2931  "*
2932{
2933  /* Adding a constant to a register is faster with an add.  */
2934  /* ??? can this ever happen? */
2935  if (GET_CODE (operands[1]) == PLUS
2936      && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2937      && rtx_equal_p (operands[0], XEXP (operands[1], 0)))
2938    {
2939      operands[1] = XEXP (operands[1], 1);
2940
2941      if (operands[1] == const1_rtx)
2942        return AS1 (inc%L0,%0);
2943
2944      if (operands[1] == constm1_rtx)
2945        return AS1 (dec%L0,%0);
2946
2947      return AS2 (add%L0,%1,%0);
2948    }
2949
2950  CC_STATUS_INIT;
2951  return AS2 (lea%L0,%a1,%0);
2952}")
2953
2954;; ??? `lea' here, for three operand add?  If leaw is used, only %bx,
2955;; %si and %di can appear in SET_SRC, and output_asm_insn might not be
2956;; able to handle the operand.  But leal always works?
2957
2958(define_expand "addhi3"
2959  [(set (match_operand:HI 0 "general_operand" "")
2960	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
2961		 (match_operand:HI 2 "general_operand" "")))]
2962  ""
2963  "IX86_EXPAND_BINARY_OPERATOR (PLUS, HImode, operands);")
2964
2965(define_insn ""
2966  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
2967	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
2968		 (match_operand:HI 2 "general_operand" "ri,rm")))]
2969  "ix86_binary_operator_ok (PLUS, HImode, operands)"
2970  "*
2971{
2972  /* ??? what about offsettable memory references? */
2973  if (!TARGET_PENTIUMPRO /* partial stalls are just too painful to risk. */
2974      && QI_REG_P (operands[0])
2975      && GET_CODE (operands[2]) == CONST_INT
2976      && (INTVAL (operands[2]) & 0xff) == 0
2977      && i386_cc_probably_useless_p (insn))
2978    {
2979      int byteval = (INTVAL (operands[2]) >> 8) & 0xff;
2980      CC_STATUS_INIT;
2981
2982      if (byteval == 1)
2983	return AS1 (inc%B0,%h0);
2984      else if (byteval == 255)
2985	return AS1 (dec%B0,%h0);
2986
2987      operands[2] = GEN_INT (byteval);
2988      return AS2 (add%B0,%2,%h0);
2989    }
2990
2991  /* Use a 32-bit operation when possible, to avoid the prefix penalty. */
2992  if (REG_P (operands[0])
2993      && i386_aligned_p (operands[2])
2994      && i386_cc_probably_useless_p (insn))
2995    {
2996      CC_STATUS_INIT;
2997
2998      if (GET_CODE (operands[2]) == CONST_INT)
2999	{
3000	  HOST_WIDE_INT intval = 0xffff & INTVAL (operands[2]);
3001
3002	  if (intval == 1)
3003	    return AS1 (inc%L0,%k0);
3004
3005	  if (intval == 0xffff)
3006	    return AS1 (dec%L0,%k0);
3007
3008	  operands[2] = i386_sext16_if_const (operands[2]);
3009	}
3010      return AS2 (add%L0,%k2,%k0);
3011    }
3012
3013  if (operands[2] == const1_rtx)
3014    return AS1 (inc%W0,%0);
3015
3016  if (operands[2] == constm1_rtx
3017      || (GET_CODE (operands[2]) == CONST_INT
3018	  && INTVAL (operands[2]) == 65535))
3019    return AS1 (dec%W0,%0);
3020
3021  return AS2 (add%W0,%2,%0);
3022}")
3023
3024(define_expand "addqi3"
3025  [(set (match_operand:QI 0 "general_operand" "")
3026	(plus:QI (match_operand:QI 1 "general_operand" "")
3027		 (match_operand:QI 2 "general_operand" "")))]
3028  ""
3029  "IX86_EXPAND_BINARY_OPERATOR (PLUS, QImode, operands);")
3030
3031(define_insn ""
3032  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
3033	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
3034		 (match_operand:QI 2 "general_operand" "qn,qmn")))]
3035  "ix86_binary_operator_ok (PLUS, QImode, operands)"
3036  "*
3037{
3038  if (operands[2] == const1_rtx)
3039    return AS1 (inc%B0,%0);
3040
3041  if (operands[2] == constm1_rtx
3042      || (GET_CODE (operands[2]) == CONST_INT
3043	  && INTVAL (operands[2]) == 255))
3044    return AS1 (dec%B0,%0);
3045
3046  return AS2 (add%B0,%2,%0);
3047}")
3048
3049;Lennart Augustsson <augustss@cs.chalmers.se>
3050;says this pattern just makes slower code:
3051;	pushl	%ebp
3052;	addl	$-80,(%esp)
3053;instead of
3054;	leal	-80(%ebp),%eax
3055;	pushl	%eax
3056;
3057;(define_insn ""
3058;  [(set (match_operand:SI 0 "push_operand" "=<")
3059;	(plus:SI (match_operand:SI 1 "register_operand" "%r")
3060;		 (match_operand:SI 2 "nonmemory_operand" "ri")))]
3061;  ""
3062;  "*
3063;{
3064;  rtx xops[4];
3065;  xops[0] = operands[0];
3066;  xops[1] = operands[1];
3067;  xops[2] = operands[2];
3068;  xops[3] = gen_rtx_MEM (SImode, stack_pointer_rtx);
3069;  output_asm_insn (\"push%z1 %1\", xops);
3070;  output_asm_insn (AS2 (add%z3,%2,%3), xops);
3071;  RET;
3072;}")
3073
3074;; The patterns that match these are at the end of this file.
3075
3076(define_expand "addxf3"
3077  [(set (match_operand:XF 0 "register_operand" "")
3078	(plus:XF (match_operand:XF 1 "register_operand" "")
3079		 (match_operand:XF 2 "register_operand" "")))]
3080  "TARGET_80387"
3081  "")
3082
3083(define_expand "adddf3"
3084  [(set (match_operand:DF 0 "register_operand" "")
3085	(plus:DF (match_operand:DF 1 "nonimmediate_operand" "")
3086		 (match_operand:DF 2 "nonimmediate_operand" "")))]
3087  "TARGET_80387"
3088  "")
3089
3090(define_expand "addsf3"
3091  [(set (match_operand:SF 0 "register_operand" "")
3092	(plus:SF (match_operand:SF 1 "nonimmediate_operand" "")
3093		 (match_operand:SF 2 "nonimmediate_operand" "")))]
3094  "TARGET_80387"
3095  "")
3096
3097;;- subtract instructions
3098
3099(define_insn "subsidi3"
3100  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,&r,!&r,o,o,!o")
3101	(minus:DI (match_operand:DI 1 "general_operand" "0iF,0,roiF,roiF,riF,o,o")
3102		  (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,ri,i,r"))))
3103   (clobber (match_scratch:SI 3 "=X,X,X,X,X,&r,&r"))]
3104  ""
3105  "*
3106{
3107  rtx low[3], high[3], xops[7];
3108
3109  CC_STATUS_INIT;
3110
3111  split_di (operands, 2, low, high);
3112  high[2] = const0_rtx;
3113  low[2]  = operands[2];
3114
3115  if (!rtx_equal_p (operands[0], operands[1]))
3116    {
3117      xops[0] = high[0];
3118      xops[1] = low[0];
3119      xops[2] = high[1];
3120      xops[3] = low[1];
3121
3122      if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
3123	{
3124	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
3125	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
3126	}
3127      else
3128	{
3129	  xops[4] = high[2];
3130	  xops[5] = low[2];
3131	  xops[6] = operands[3];
3132	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
3133	  output_asm_insn (AS2 (sub%L6,%5,%6), xops);
3134	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
3135	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
3136	  output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
3137	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
3138	  RET;
3139	}
3140    }
3141
3142  output_asm_insn (AS2 (sub%L0,%2,%0), low);
3143  output_asm_insn (AS2 (sbb%L0,%2,%0), high);
3144  RET;
3145}")
3146
3147(define_insn "subdi3"
3148  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,o,!&r,!o")
3149	(minus:DI (match_operand:DI 1 "general_operand" "0,0,0iF,or,roiF,roiF")
3150		  (match_operand:DI 2 "general_operand" "or,riF,or,iF,roiF,roiF")))
3151   (clobber (match_scratch:SI 3 "=X,X,&r,&r,X,&r"))]
3152  ""
3153  "*
3154{
3155  rtx low[3], high[3], xops[7];
3156
3157  CC_STATUS_INIT;
3158
3159  split_di (operands, 3, low, high);
3160
3161  if (!rtx_equal_p (operands[0], operands[1]))
3162    {
3163      xops[0] = high[0];
3164      xops[1] = low[0];
3165      xops[2] = high[1];
3166      xops[3] = low[1];
3167
3168      if (GET_CODE (operands[0]) != MEM)
3169	{
3170	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
3171	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
3172	}
3173      else
3174	{
3175	  xops[4] = high[2];
3176	  xops[5] = low[2];
3177	  xops[6] = operands[3];
3178	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
3179	  output_asm_insn (AS2 (sub%L6,%5,%6), xops);
3180	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
3181	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
3182	  output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
3183	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
3184	  RET;
3185	}
3186    }
3187
3188  if (GET_CODE (operands[3]) == REG)
3189    {
3190      xops[0] = high[0];
3191      xops[1] = low[0];
3192      xops[2] = high[2];
3193      xops[3] = low[2];
3194      xops[4] = operands[3];
3195
3196      output_asm_insn (AS2 (mov%L4,%3,%4), xops);
3197      output_asm_insn (AS2 (sub%L1,%4,%1), xops);
3198      output_asm_insn (AS2 (mov%L4,%2,%4), xops);
3199      output_asm_insn (AS2 (sbb%L0,%4,%0), xops);
3200    }
3201
3202  else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
3203    {
3204      output_asm_insn (AS2 (sub%L0,%2,%0), low);
3205      output_asm_insn (AS2 (sbb%L0,%2,%0), high);
3206    }
3207
3208  else
3209    output_asm_insn (AS2 (sub%L0,%2,%0), high);
3210
3211  RET;
3212}")
3213
3214(define_expand "subsi3"
3215  [(set (match_operand:SI 0 "nonimmediate_operand" "")
3216	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
3217		  (match_operand:SI 2 "general_operand" "")))]
3218  ""
3219  "IX86_EXPAND_BINARY_OPERATOR (MINUS, SImode, operands);")
3220
3221(define_insn ""
3222  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
3223	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
3224		  (match_operand:SI 2 "general_operand" "ri,rm")))]
3225  "ix86_binary_operator_ok (MINUS, SImode, operands)"
3226  "* return AS2 (sub%L0,%2,%0);")
3227
3228(define_expand "subhi3"
3229  [(set (match_operand:HI 0 "general_operand" "")
3230	(minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
3231		  (match_operand:HI 2 "general_operand" "")))]
3232  ""
3233  "IX86_EXPAND_BINARY_OPERATOR (MINUS, HImode, operands);")
3234
3235(define_insn ""
3236  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
3237	(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
3238		  (match_operand:HI 2 "general_operand" "ri,rm")))]
3239  "ix86_binary_operator_ok (MINUS, HImode, operands)"
3240  "*
3241{
3242  if (REG_P (operands[0])
3243      && i386_aligned_p (operands[2])
3244      && i386_cc_probably_useless_p (insn))
3245    {
3246      CC_STATUS_INIT;
3247      operands[2] = i386_sext16_if_const (operands[2]);
3248      return AS2 (sub%L0,%k2,%k0);
3249    }
3250 return AS2 (sub%W0,%2,%0);
3251}")
3252
3253(define_expand "subqi3"
3254  [(set (match_operand:QI 0 "general_operand" "")
3255	(minus:QI (match_operand:QI 1 "general_operand" "")
3256		  (match_operand:QI 2 "general_operand" "")))]
3257  ""
3258  "IX86_EXPAND_BINARY_OPERATOR (MINUS, QImode, operands);")
3259
3260(define_insn ""
3261  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
3262	(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
3263		  (match_operand:QI 2 "general_operand" "qn,qmn")))]
3264  "ix86_binary_operator_ok (MINUS, QImode, operands)"
3265  "* return AS2 (sub%B0,%2,%0);")
3266
3267;; The patterns that match these are at the end of this file.
3268
3269(define_expand "subxf3"
3270  [(set (match_operand:XF 0 "register_operand" "")
3271	(minus:XF (match_operand:XF 1 "register_operand" "")
3272		  (match_operand:XF 2 "register_operand" "")))]
3273  "TARGET_80387"
3274  "")
3275
3276(define_expand "subdf3"
3277  [(set (match_operand:DF 0 "register_operand" "")
3278	(minus:DF (match_operand:DF 1 "nonimmediate_operand" "")
3279		  (match_operand:DF 2 "nonimmediate_operand" "")))]
3280  "TARGET_80387"
3281  "")
3282
3283(define_expand "subsf3"
3284  [(set (match_operand:SF 0 "register_operand" "")
3285	(minus:SF (match_operand:SF 1 "nonimmediate_operand" "")
3286		  (match_operand:SF 2 "nonimmediate_operand" "")))]
3287  "TARGET_80387"
3288  "")
3289
3290;;- multiply instructions
3291
3292;(define_insn "mulqi3"
3293;  [(set (match_operand:QI 0 "register_operand" "=a")
3294;	(mult:QI (match_operand:QI 1 "register_operand" "%0")
3295;		 (match_operand:QI 2 "nonimmediate_operand" "qm")))]
3296;  ""
3297;  "imul%B0 %2,%0")
3298
3299(define_insn "mulhi3"
3300  [(set (match_operand:HI 0 "register_operand" "=r,r")
3301	(mult:HI (match_operand:HI 1 "nonimmediate_operand" "%0,rm")
3302		 (match_operand:HI 2 "general_operand" "g,i")))]
3303  ""
3304  "*
3305{
3306  if (GET_CODE (operands[1]) == REG
3307      && REGNO (operands[1]) == REGNO (operands[0])
3308      && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
3309    /* Assembler has weird restrictions.  */
3310    return AS2 (imul%W0,%2,%0);
3311  return AS3 (imul%W0,%2,%1,%0);
3312}"
3313  [(set_attr "type" "imul")])
3314
3315(define_insn "mulsi3"
3316  [(set (match_operand:SI 0 "register_operand" "=r,r")
3317	(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm")
3318		 (match_operand:SI 2 "general_operand" "g,i")))]
3319  ""
3320  "*
3321{
3322  if (GET_CODE (operands[1]) == REG
3323      && REGNO (operands[1]) == REGNO (operands[0])
3324      && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
3325    /* Assembler has weird restrictions.  */
3326    return AS2 (imul%L0,%2,%0);
3327  return AS3 (imul%L0,%2,%1,%0);
3328}"
3329  [(set_attr "type" "imul")])
3330
3331(define_insn "umulqihi3"
3332  [(set (match_operand:HI 0 "register_operand" "=a")
3333	(mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0"))
3334		 (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
3335  ""
3336  "mul%B0 %2"
3337  [(set_attr "type" "imul")])
3338
3339(define_insn "mulqihi3"
3340  [(set (match_operand:HI 0 "register_operand" "=a")
3341	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
3342		 (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
3343  ""
3344  "imul%B0 %2"
3345  [(set_attr "type" "imul")])
3346
3347(define_insn "umulsidi3"
3348  [(set (match_operand:DI 0 "register_operand" "=A")
3349	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
3350		 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
3351  "TARGET_WIDE_MULTIPLY"
3352  "mul%L0 %2"
3353  [(set_attr "type" "imul")])
3354
3355(define_insn "mulsidi3"
3356  [(set (match_operand:DI 0 "register_operand" "=A")
3357	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
3358		 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
3359  "TARGET_WIDE_MULTIPLY"
3360  "imul%L0 %2"
3361  [(set_attr "type" "imul")])
3362
3363(define_insn "umulsi3_highpart"
3364  [(set (match_operand:SI 0 "register_operand" "=d")
3365	(truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a"))
3366					   (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
3367				  (const_int 32))))
3368   (clobber (match_scratch:SI 3 "=a"))]
3369  "TARGET_WIDE_MULTIPLY"
3370  "mul%L0 %2"
3371  [(set_attr "type" "imul")])
3372
3373(define_insn "smulsi3_highpart"
3374  [(set (match_operand:SI 0 "register_operand" "=d")
3375	(truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%a"))
3376					   (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
3377				  (const_int 32))))
3378   (clobber (match_scratch:SI 3 "=a"))]
3379  "TARGET_WIDE_MULTIPLY"
3380  "imul%L0 %2"
3381  [(set_attr "type" "imul")])
3382
3383;; The patterns that match these are at the end of this file.
3384
3385(define_expand "mulxf3"
3386  [(set (match_operand:XF 0 "register_operand" "")
3387	(mult:XF (match_operand:XF 1 "register_operand" "")
3388		 (match_operand:XF 2 "register_operand" "")))]
3389  "TARGET_80387"
3390  "")
3391
3392(define_expand "muldf3"
3393  [(set (match_operand:DF 0 "register_operand" "")
3394	(mult:DF (match_operand:DF 1 "register_operand" "")
3395		 (match_operand:DF 2 "nonimmediate_operand" "")))]
3396  "TARGET_80387"
3397  "")
3398
3399(define_expand "mulsf3"
3400  [(set (match_operand:SF 0 "register_operand" "")
3401	(mult:SF (match_operand:SF 1 "register_operand" "")
3402		 (match_operand:SF 2 "nonimmediate_operand" "")))]
3403  "TARGET_80387"
3404  "")
3405
3406;;- divide instructions
3407
3408(define_insn "divqi3"
3409  [(set (match_operand:QI 0 "register_operand" "=a")
3410	(div:QI (match_operand:HI 1 "register_operand" "0")
3411		(match_operand:QI 2 "nonimmediate_operand" "qm")))]
3412  ""
3413  "idiv%B0 %2")
3414
3415(define_insn "udivqi3"
3416  [(set (match_operand:QI 0 "register_operand" "=a")
3417	(udiv:QI (match_operand:HI 1 "register_operand" "0")
3418		 (match_operand:QI 2 "nonimmediate_operand" "qm")))]
3419  ""
3420  "div%B0 %2"
3421  [(set_attr "type" "idiv")])
3422
3423;; The patterns that match these are at the end of this file.
3424
3425(define_expand "divxf3"
3426  [(set (match_operand:XF 0 "register_operand" "")
3427	(div:XF (match_operand:XF 1 "register_operand" "")
3428		(match_operand:XF 2 "register_operand" "")))]
3429  "TARGET_80387"
3430  "")
3431
3432(define_expand "divdf3"
3433  [(set (match_operand:DF 0 "register_operand" "")
3434 	(div:DF (match_operand:DF 1 "register_operand" "")
3435 		(match_operand:DF 2 "nonimmediate_operand" "")))]
3436   "TARGET_80387"
3437   "")
3438 
3439(define_expand "divsf3"
3440  [(set (match_operand:SF 0 "register_operand" "")
3441	(div:SF (match_operand:SF 1 "register_operand" "")
3442		(match_operand:SF 2 "nonimmediate_operand" "")))]
3443  "TARGET_80387"
3444  "")
3445
3446;; Remainder instructions.
3447
3448(define_insn "divmodsi4"
3449  [(set (match_operand:SI 0 "register_operand" "=a")
3450	(div:SI (match_operand:SI 1 "register_operand" "0")
3451		(match_operand:SI 2 "nonimmediate_operand" "rm")))
3452   (set (match_operand:SI 3 "register_operand" "=&d")
3453	(mod:SI (match_dup 1) (match_dup 2)))]
3454  ""
3455  "*
3456{
3457#ifdef INTEL_SYNTAX
3458  output_asm_insn (\"cdq\", operands);
3459#else
3460  output_asm_insn (\"cltd\", operands);
3461#endif
3462  return AS1 (idiv%L0,%2);
3463}"
3464  [(set_attr "type" "idiv")])
3465
3466(define_insn "divmodhi4"
3467  [(set (match_operand:HI 0 "register_operand" "=a")
3468	(div:HI (match_operand:HI 1 "register_operand" "0")
3469		(match_operand:HI 2 "nonimmediate_operand" "rm")))
3470   (set (match_operand:HI 3 "register_operand" "=&d")
3471	(mod:HI (match_dup 1) (match_dup 2)))]
3472  ""
3473  "cwtd\;idiv%W0 %2"
3474  [(set_attr "type" "idiv")])
3475
3476;; ??? Can we make gcc zero extend operand[0]?
3477(define_insn "udivmodsi4"
3478  [(set (match_operand:SI 0 "register_operand" "=a")
3479	(udiv:SI (match_operand:SI 1 "register_operand" "0")
3480		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
3481   (set (match_operand:SI 3 "register_operand" "=&d")
3482	(umod:SI (match_dup 1) (match_dup 2)))]
3483  ""
3484  "*
3485{
3486  output_asm_insn (AS2 (xor%L3,%3,%3), operands);
3487  return AS1 (div%L0,%2);
3488}"
3489  [(set_attr "type" "idiv")])
3490
3491;; ??? Can we make gcc zero extend operand[0]?
3492(define_insn "udivmodhi4"
3493  [(set (match_operand:HI 0 "register_operand" "=a")
3494	(udiv:HI (match_operand:HI 1 "register_operand" "0")
3495		 (match_operand:HI 2 "nonimmediate_operand" "rm")))
3496   (set (match_operand:HI 3 "register_operand" "=&d")
3497	(umod:HI (match_dup 1) (match_dup 2)))]
3498  ""
3499  "*
3500{
3501  output_asm_insn (AS2 (xor%W0,%3,%3), operands);
3502  return AS1 (div%W0,%2);
3503}"
3504  [(set_attr "type" "idiv")])
3505
3506/*
3507;;this should be a valid double division which we may want to add
3508
3509(define_insn ""
3510  [(set (match_operand:SI 0 "register_operand" "=a")
3511	(udiv:DI (match_operand:DI 1 "register_operand" "a")
3512		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
3513   (set (match_operand:SI 3 "register_operand" "=d")
3514	(umod:SI (match_dup 1) (match_dup 2)))]
3515  ""
3516  "div%L0 %2,%0"
3517  [(set_attr "type" "idiv")])
3518*/
3519
3520;;- and instructions
3521
3522;; On i386,
3523;;			movzbl %bl,%ebx
3524;; is faster than
3525;;			andl $255,%ebx
3526;;
3527;; but if the reg is %eax, then the "andl" is faster.
3528;;
3529;; On i486, the "andl" is always faster than the "movzbl".
3530;;
3531;; On both i386 and i486, a three operand AND is as fast with movzbl or
3532;; movzwl as with andl, if operands[0] != operands[1].
3533
3534;; The `r' in `rm' for operand 3 looks redundant, but it causes
3535;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
3536
3537(define_insn "andsi3"
3538  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
3539	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
3540		(match_operand:SI 2 "general_operand" "ri,rm")))]
3541  ""
3542  "*
3543{
3544  HOST_WIDE_INT intval;
3545  if (!rtx_equal_p (operands[0], operands[1])
3546      && rtx_equal_p (operands[0], operands[2]))
3547    {
3548      rtx tmp;
3549      tmp = operands[1];
3550      operands[1] = operands[2];
3551      operands[2] = tmp;
3552    }
3553  switch (GET_CODE (operands[2]))
3554    {
3555    case CONST_INT:
3556      if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
3557	break;
3558      intval = INTVAL (operands[2]);
3559      /* zero-extend 16->32? */
3560      if (intval == 0xffff && REG_P (operands[0])
3561	  && (! REG_P (operands[1])
3562	      || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
3563	  && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1])))
3564	{
3565	  /* ??? tege: Should forget CC_STATUS only if we clobber a
3566	     remembered operand.  Fix that later.  */
3567	  CC_STATUS_INIT;
3568#ifdef INTEL_SYNTAX
3569	  return AS2 (movzx,%w1,%0);
3570#else
3571	  return AS2 (movz%W0%L0,%w1,%0);
3572#endif
3573	}
3574
3575      /* zero extend 8->32? */
3576      if (intval == 0xff && REG_P (operands[0])
3577	  && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
3578	  && (! REG_P (operands[1])
3579	      || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
3580	  && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1])))
3581	{
3582	  /* ??? tege: Should forget CC_STATUS only if we clobber a
3583	     remembered operand.  Fix that later.  */
3584	  CC_STATUS_INIT;
3585#ifdef INTEL_SYNTAX
3586	  return AS2 (movzx,%b1,%0);
3587#else
3588	  return AS2 (movz%B0%L0,%b1,%0);
3589#endif
3590	}
3591
3592      /* Check partial bytes.. non-QI-regs are not available */
3593      if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
3594	break;
3595
3596      /* only low byte has zero bits? */
3597      if (~(intval | 0xff) == 0)
3598	{
3599	  intval &= 0xff;
3600	  if (REG_P (operands[0]))
3601	    {
3602	      if (intval == 0)
3603		{
3604		  CC_STATUS_INIT;
3605		  return AS2 (xor%B0,%b0,%b0);
3606		}
3607
3608	      /* we're better off with the 32-bit version if reg != EAX */
3609	      /* the value is sign-extended in 8 bits */
3610	      if (REGNO (operands[0]) != 0 && (intval & 0x80))
3611		break;
3612	    }
3613
3614	  CC_STATUS_INIT;
3615
3616	  operands[2] = GEN_INT (intval);
3617
3618	  if (intval == 0)
3619	    return AS2 (mov%B0,%2,%b0);
3620
3621	  return AS2 (and%B0,%2,%b0);
3622	}
3623
3624      /* only second byte has zero? */
3625      if (~(intval | 0xff00) == 0)
3626	{
3627	  CC_STATUS_INIT;
3628
3629	  intval = (intval >> 8) & 0xff;
3630	  operands[2] = GEN_INT (intval);
3631	  if (intval == 0)
3632	    {
3633	      if (REG_P (operands[0]))
3634		return AS2 (xor%B0,%h0,%h0);
3635	      operands[0] = adj_offsettable_operand (operands[0], 1);
3636	      return AS2 (mov%B0,%2,%b0);
3637	    }
3638
3639	  if (REG_P (operands[0]))
3640	    return AS2 (and%B0,%2,%h0);
3641
3642	  operands[0] = adj_offsettable_operand (operands[0], 1);
3643	  return AS2 (and%B0,%2,%b0);
3644	}
3645
3646      if (REG_P (operands[0]))
3647	break;
3648
3649      /* third byte has zero bits? */
3650      if (~(intval | 0xff0000) == 0)
3651	{
3652	  intval = (intval >> 16) & 0xff;
3653	  operands[0] = adj_offsettable_operand (operands[0], 2);
3654byte_and_operation:
3655	  CC_STATUS_INIT;
3656	  operands[2] = GEN_INT (intval);
3657	  if (intval == 0)
3658	    return AS2 (mov%B0,%2,%b0);
3659	  return AS2 (and%B0,%2,%b0);
3660	}
3661
3662      /* fourth byte has zero bits? */
3663      if (~(intval | 0xff000000) == 0)
3664	{
3665	  intval = (intval >> 24) & 0xff;
3666	  operands[0] = adj_offsettable_operand (operands[0], 3);
3667	  goto byte_and_operation;
3668	}
3669
3670      /* Low word is zero? */
3671      if (intval == 0xffff0000)
3672        {
3673word_zero_and_operation:
3674	  CC_STATUS_INIT;
3675	  operands[2] = const0_rtx;
3676	  return AS2 (mov%W0,%2,%w0);
3677	}
3678
3679      /* High word is zero? */
3680      if (intval == 0x0000ffff)
3681        {
3682	  operands[0] = adj_offsettable_operand (operands[0], 2);
3683	  goto word_zero_and_operation;
3684	}
3685
3686    default:
3687      break;
3688    }
3689
3690  return AS2 (and%L0,%2,%0);
3691}")
3692
3693(define_insn "andhi3"
3694  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
3695	(and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
3696		(match_operand:HI 2 "general_operand" "ri,rm")))]
3697  ""
3698  "*
3699{
3700  if (GET_CODE (operands[2]) == CONST_INT
3701      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3702    {
3703      /* Can we ignore the upper byte? */
3704      if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3705	  && (INTVAL (operands[2]) & 0xff00) == 0xff00)
3706	{
3707	  CC_STATUS_INIT;
3708
3709	  if ((INTVAL (operands[2]) & 0xff) == 0)
3710	    {
3711	      operands[2] = const0_rtx;
3712	      return AS2 (mov%B0,%2,%b0);
3713	    }
3714
3715	  operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
3716	  return AS2 (and%B0,%2,%b0);
3717	}
3718
3719      /* Can we ignore the lower byte? */
3720      /* ??? what about offsettable memory references? */
3721      if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff)
3722	{
3723	  CC_STATUS_INIT;
3724
3725	  if ((INTVAL (operands[2]) & 0xff00) == 0)
3726	    {
3727	      operands[2] = const0_rtx;
3728	      return AS2 (mov%B0,%2,%h0);
3729	    }
3730
3731	  operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3732	  return AS2 (and%B0,%2,%h0);
3733	}
3734
3735      /* use 32-bit ops on registers when there are no sign issues.. */
3736      if (REG_P (operands[0]))
3737	{
3738	  if (!(INTVAL (operands[2]) & ~0x7fff))
3739	    return AS2 (and%L0,%2,%k0);
3740	}
3741    }
3742
3743  if (REG_P (operands[0])
3744      && i386_aligned_p (operands[2]))
3745    {
3746      CC_STATUS_INIT;
3747      /* If op[2] is constant, we should zero-extend it and */
3748      /* make a note that op[0] has been zero-extended, so  */
3749      /* that we could use 32-bit ops on it forthwith, but  */
3750      /* there is no such reg-note available. Instead we do */
3751      /* a sign extension as that can result in shorter asm */
3752      operands[2] = i386_sext16_if_const (operands[2]);
3753      return AS2 (and%L0,%k2,%k0);
3754    }
3755
3756  /* Use a 32-bit word with the upper bits set, invalidate CC */
3757  if (GET_CODE (operands[2]) == CONST_INT
3758      && i386_aligned_p (operands[0]))
3759    {
3760      HOST_WIDE_INT val = INTVAL (operands[2]);
3761      CC_STATUS_INIT;
3762      val |= ~0xffff;
3763      if (val != INTVAL (operands[2]))
3764	operands[2] = GEN_INT (val);
3765      return AS2 (and%L0,%k2,%k0);
3766    }
3767
3768  return AS2 (and%W0,%2,%0);
3769}")
3770
3771(define_insn "andqi3"
3772  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
3773	(and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
3774		(match_operand:QI 2 "general_operand" "qn,qmn")))]
3775  ""
3776  "* return AS2 (and%B0,%2,%0);")
3777
3778/* I am nervous about these two.. add them later..
3779;I presume this means that we have something in say op0= eax which is small
3780;and we want to and it with memory so we can do this by just an
3781;andb m,%al  and have success.
3782(define_insn ""
3783  [(set (match_operand:SI 0 "general_operand" "=r")
3784	(and:SI (zero_extend:SI
3785		 (match_operand:HI 1 "nonimmediate_operand" "rm"))
3786		(match_operand:SI 2 "general_operand" "0")))]
3787  "GET_CODE (operands[2]) == CONST_INT
3788   && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
3789  "and%W0 %1,%0")
3790
3791(define_insn ""
3792  [(set (match_operand:SI 0 "register_operand" "=q")
3793	(and:SI
3794	 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))
3795		(match_operand:SI 2 "register_operand" "0")))]
3796  "GET_CODE (operands[2]) == CONST_INT
3797   && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
3798  "and%L0 %1,%0")
3799
3800*/
3801
3802;;- Bit set (inclusive or) instructions
3803
3804;; This optimizes known byte-wide operations to memory, and in some cases
3805;; to QI registers.. Note that we don't want to use the QI registers too
3806;; aggressively, because often the 32-bit register instruction is the same
3807;; size, and likely to be faster on PentiumPro.
3808(define_insn "iorsi3"
3809  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
3810	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
3811		(match_operand:SI 2 "general_operand" "ri,rm")))]
3812  ""
3813  "*
3814{
3815  HOST_WIDE_INT intval;
3816  switch (GET_CODE (operands[2]))
3817    {
3818    case CONST_INT:
3819
3820      if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
3821	break;
3822
3823      /* don't try to optimize volatile accesses */
3824      if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
3825	break;
3826
3827      intval = INTVAL (operands[2]);
3828      if ((intval & ~0xff) == 0)
3829        {
3830	  if (REG_P (operands[0]))
3831	    {
3832	      /* Do low byte access only for %eax or when high bit is set */
3833	      if (REGNO (operands[0]) != 0 && !(intval & 0x80))
3834	        break;
3835	    }
3836
3837byte_or_operation:
3838	    CC_STATUS_INIT;
3839
3840	    if (intval != INTVAL (operands[2]))
3841	      operands[2] = GEN_INT (intval);
3842
3843	    if (intval == 0xff)
3844	      return AS2 (mov%B0,%2,%b0);
3845
3846	    return AS2 (or%B0,%2,%b0);
3847	}
3848
3849      /* second byte? */
3850      if ((intval & ~0xff00) == 0)
3851	{
3852	  intval >>= 8;
3853
3854	  if (REG_P (operands[0]))
3855	    {
3856	      CC_STATUS_INIT;
3857	      operands[2] = GEN_INT (intval);
3858	      if (intval == 0xff)
3859		return AS2 (mov%B0,%2,%h0);
3860
3861	      return AS2 (or%B0,%2,%h0);
3862	    }
3863
3864	  operands[0] = adj_offsettable_operand (operands[0], 1);
3865	  goto byte_or_operation;
3866	}
3867
3868      if (REG_P (operands[0]))
3869	break;
3870
3871      /* third byte? */
3872      if ((intval & ~0xff0000) == 0)
3873	{
3874	  intval >>= 16;
3875	  operands[0] = adj_offsettable_operand (operands[0], 2);
3876	  goto byte_or_operation;
3877	}
3878
3879      /* fourth byte? */
3880      if ((intval & ~0xff000000) == 0)
3881	{
3882	  intval = (intval >> 24) & 0xff;
3883	  operands[0] = adj_offsettable_operand (operands[0], 3);
3884	  goto byte_or_operation;
3885	}
3886
3887    default:
3888      break;
3889    }
3890
3891  return AS2 (or%L0,%2,%0);
3892}")
3893
3894(define_insn "iorhi3"
3895  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
3896	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
3897		(match_operand:HI 2 "general_operand" "ri,rm")))]
3898  ""
3899  "*
3900{
3901  HOST_WIDE_INT intval;
3902  switch (GET_CODE (operands[2]))
3903    {
3904    case CONST_INT:
3905
3906      if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
3907	break;
3908
3909      /* don't try to optimize volatile accesses */
3910      if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
3911	break;
3912
3913      intval = 0xffff & INTVAL (operands[2]);
3914
3915      if ((intval & 0xff00) == 0)
3916        {
3917	  if (REG_P (operands[0]))
3918	    {
3919	      /* Do low byte access only for %eax or when high bit is set */
3920	      if (REGNO (operands[0]) != 0 && !(intval & 0x80))
3921	        break;
3922	    }
3923
3924byte_or_operation:
3925	    CC_STATUS_INIT;
3926
3927	    if (intval == 0xff)
3928	      return AS2 (mov%B0,%2,%b0);
3929
3930	    return AS2 (or%B0,%2,%b0);
3931	}
3932
3933      /* high byte? */
3934      if ((intval & 0xff) == 0)
3935	{
3936	  intval >>= 8;
3937	  operands[2] = GEN_INT (intval);
3938
3939	  if (REG_P (operands[0]))
3940	    {
3941	      CC_STATUS_INIT;
3942	      if (intval == 0xff)
3943		return AS2 (mov%B0,%2,%h0);
3944
3945	      return AS2 (or%B0,%2,%h0);
3946	    }
3947
3948	  operands[0] = adj_offsettable_operand (operands[0], 1);
3949
3950	  goto byte_or_operation;
3951	}
3952
3953    default:
3954      break;
3955    }
3956
3957  if (REG_P (operands[0])
3958      && i386_aligned_p (operands[2]))
3959    {
3960      CC_STATUS_INIT;
3961      operands[2] = i386_sext16_if_const (operands[2]);
3962      return AS2 (or%L0,%k2,%k0);
3963    }
3964
3965  if (GET_CODE (operands[2]) == CONST_INT
3966      && i386_aligned_p (operands[0]))
3967    {
3968      CC_STATUS_INIT;
3969      intval = 0xffff & INTVAL (operands[2]);
3970      if (intval != INTVAL (operands[2]))
3971	operands[2] = GEN_INT (intval);
3972      return AS2 (or%L0,%2,%k0);
3973    }
3974
3975  return AS2 (or%W0,%2,%0);
3976}")
3977
3978(define_insn "iorqi3"
3979  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
3980	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
3981		(match_operand:QI 2 "general_operand" "qn,qmn")))]
3982  ""
3983  "* return AS2 (or%B0,%2,%0);")
3984
3985;;- xor instructions
3986
3987(define_insn "xorsi3"
3988  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
3989	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
3990		(match_operand:SI 2 "general_operand" "ri,rm")))]
3991  ""
3992  "*
3993{
3994  HOST_WIDE_INT intval;
3995  switch (GET_CODE (operands[2]))
3996    {
3997    case CONST_INT:
3998
3999      if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
4000	break;
4001
4002      /* don't try to optimize volatile accesses */
4003      if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
4004	break;
4005
4006      intval = INTVAL (operands[2]);
4007      if ((intval & ~0xff) == 0)
4008        {
4009	  if (REG_P (operands[0]))
4010	    {
4011	      /* Do low byte access only for %eax or when high bit is set */
4012	      if (REGNO (operands[0]) != 0 && !(intval & 0x80))
4013	        break;
4014	    }
4015
4016byte_xor_operation:
4017	    CC_STATUS_INIT;
4018	      
4019	    if (intval == 0xff)
4020	      return AS1 (not%B0,%b0);
4021
4022	    if (intval != INTVAL (operands[2]))
4023	      operands[2] = GEN_INT (intval);
4024	    return AS2 (xor%B0,%2,%b0);
4025	}
4026
4027      /* second byte? */
4028      if ((intval & ~0xff00) == 0)
4029	{
4030	  intval >>= 8;
4031
4032	  if (REG_P (operands[0]))
4033	    {
4034	      CC_STATUS_INIT;
4035	      if (intval == 0xff)
4036		return AS1 (not%B0,%h0);
4037
4038	      operands[2] = GEN_INT (intval);
4039	      return AS2 (xor%B0,%2,%h0);
4040	    }
4041
4042	  operands[0] = adj_offsettable_operand (operands[0], 1);
4043
4044	  goto byte_xor_operation;
4045	}
4046
4047      if (REG_P (operands[0]))
4048	break;
4049
4050      /* third byte? */
4051      if ((intval & ~0xff0000) == 0)
4052	{
4053	  intval >>= 16;
4054	  operands[0] = adj_offsettable_operand (operands[0], 2);
4055	  goto byte_xor_operation;
4056	}
4057
4058      /* fourth byte? */
4059      if ((intval & ~0xff000000) == 0)
4060	{
4061	  intval = (intval >> 24) & 0xff;
4062	  operands[0] = adj_offsettable_operand (operands[0], 3);
4063	  goto byte_xor_operation;
4064	}
4065
4066    default:
4067      break;
4068    }
4069
4070  return AS2 (xor%L0,%2,%0);
4071}")
4072
4073(define_insn "xorhi3"
4074  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
4075	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
4076		(match_operand:HI 2 "general_operand" "ri,rm")))]
4077  ""
4078  "*
4079{
4080  if (GET_CODE (operands[2]) == CONST_INT
4081      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
4082    {
4083      /* Can we ignore the upper byte? */
4084      if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
4085	  && (INTVAL (operands[2]) & 0xff00) == 0)
4086	{
4087	  CC_STATUS_INIT;
4088	  if (INTVAL (operands[2]) & 0xffff0000)
4089	    operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
4090
4091	  if (INTVAL (operands[2]) == 0xff)
4092	    return AS1 (not%B0,%b0);
4093
4094	  return AS2 (xor%B0,%2,%b0);
4095	}
4096
4097      /* Can we ignore the lower byte? */
4098      /* ??? what about offsettable memory references? */
4099      if (QI_REG_P (operands[0])
4100	  && (INTVAL (operands[2]) & 0xff) == 0)
4101	{
4102	  CC_STATUS_INIT;
4103	  operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
4104
4105	  if (INTVAL (operands[2]) == 0xff)
4106	    return AS1 (not%B0,%h0);
4107
4108	  return AS2 (xor%B0,%2,%h0);
4109	}
4110    }
4111
4112  if (REG_P (operands[0])
4113      && i386_aligned_p (operands[2]))
4114    {
4115      CC_STATUS_INIT;
4116      operands[2] = i386_sext16_if_const (operands[2]);
4117      return AS2 (xor%L0,%k2,%k0);
4118    }
4119
4120  if (GET_CODE (operands[2]) == CONST_INT
4121      && i386_aligned_p (operands[0]))
4122    {
4123      HOST_WIDE_INT intval;
4124      CC_STATUS_INIT;
4125      intval = 0xffff & INTVAL (operands[2]);
4126      if (intval != INTVAL (operands[2]))
4127	operands[2] = GEN_INT (intval);
4128      return AS2 (xor%L0,%2,%k0);
4129    }
4130
4131  return AS2 (xor%W0,%2,%0);
4132}")
4133
4134(define_insn "xorqi3"
4135  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
4136	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
4137		(match_operand:QI 2 "general_operand" "qn,qm")))]
4138  ""
4139  "* return AS2 (xor%B0,%2,%0);")
4140
4141;; logical operations for DImode
4142
4143
4144(define_insn "anddi3"
4145  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
4146	(and:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
4147		(match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
4148   (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
4149  ""
4150  "#")
4151
4152(define_insn "iordi3"
4153  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
4154	(ior:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
4155		(match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
4156   (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
4157  ""
4158  "#")
4159  
4160(define_insn "xordi3"
4161  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
4162	(xor:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
4163		(match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
4164   (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
4165  ""
4166  "#")
4167
4168(define_split
4169  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
4170	(match_operator:DI 4 "ix86_logical_operator"
4171	  [(match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
4172	   (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")]))
4173   (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
4174  "reload_completed"
4175  [(const_int 0)]
4176  "
4177{
4178  rtx low[3], high[3], xops[7], temp;
4179  rtx (*genfunc)() = (GET_CODE (operands[4]) == AND ? gen_andsi3
4180		      : GET_CODE (operands[4]) == IOR ? gen_iorsi3
4181		      : GET_CODE (operands[4]) == XOR ? gen_xorsi3
4182		      : 0);
4183
4184  if (rtx_equal_p (operands[0], operands[2]))
4185    {
4186      temp = operands[1];
4187      operands[1] = operands[2];
4188      operands[2] = temp;
4189    }
4190
4191  split_di (operands, 3, low, high);
4192  if (!rtx_equal_p (operands[0], operands[1]))
4193    {
4194      xops[0] = high[0];
4195      xops[1] = low[0];
4196      xops[2] = high[1];
4197      xops[3] = low[1];
4198
4199      if (GET_CODE (operands[0]) != MEM)
4200	{
4201	  emit_insn (gen_movsi (xops[1], xops[3]));
4202	  emit_insn (gen_movsi (xops[0], xops[2]));
4203	}
4204      else
4205	{
4206	  xops[4] = high[2];
4207	  xops[5] = low[2];
4208	  xops[6] = operands[3];
4209	  emit_insn (gen_movsi (xops[6], xops[3]));
4210	  emit_insn ((*genfunc) (xops[6], xops[6], xops[5]));
4211	  emit_insn (gen_movsi (xops[1], xops[6]));
4212	  emit_insn (gen_movsi (xops[6], xops[2]));
4213	  emit_insn ((*genfunc) (xops[6], xops[6], xops[4]));
4214	  emit_insn (gen_movsi (xops[0], xops[6]));
4215	  DONE;
4216	}
4217    }
4218
4219  if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
4220    {
4221      xops[0] = high[0];
4222      xops[1] = low[0];
4223      xops[2] = high[2];
4224      xops[3] = low[2];
4225      xops[4] = operands[3];
4226
4227      emit_insn (gen_movsi (xops[4], xops[3]));
4228      emit_insn ((*genfunc) (xops[1], xops[1], xops[4]));
4229      emit_insn (gen_movsi (xops[4], xops[2]));
4230      emit_insn ((*genfunc) (xops[0], xops[0], xops[4]));
4231    }
4232
4233  else
4234    {
4235      emit_insn ((*genfunc) (low[0], low[0], low[2]));
4236      emit_insn ((*genfunc) (high[0], high[0], high[2]));
4237    }
4238
4239  DONE;
4240}")
4241
4242;;- negation instructions
4243
4244(define_insn "negdi2"
4245  [(set (match_operand:DI 0 "general_operand" "=&ro")
4246	(neg:DI (match_operand:DI 1 "general_operand" "0")))]
4247  ""
4248  "*
4249{
4250  rtx xops[2], low[1], high[1];
4251
4252  CC_STATUS_INIT;
4253
4254  split_di (operands, 1, low, high);
4255  xops[0] = const0_rtx;
4256  xops[1] = high[0];
4257
4258  output_asm_insn (AS1 (neg%L0,%0), low);
4259  output_asm_insn (AS2 (adc%L1,%0,%1), xops);
4260  output_asm_insn (AS1 (neg%L0,%0), high);
4261  RET;
4262}")
4263
4264(define_insn "negsi2"
4265  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4266	(neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
4267  ""
4268  "neg%L0 %0")
4269
4270(define_insn "neghi2"
4271  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4272	(neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
4273  ""
4274  "neg%W0 %0")
4275
4276(define_insn "negqi2"
4277  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4278	(neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
4279  ""
4280  "neg%B0 %0")
4281
4282(define_insn "negsf2"
4283  [(set (match_operand:SF 0 "register_operand" "=f")
4284	(neg:SF (match_operand:SF 1 "register_operand" "0")))]
4285  "TARGET_80387"
4286  "fchs")
4287
4288(define_insn "negdf2"
4289  [(set (match_operand:DF 0 "register_operand" "=f")
4290	(neg:DF (match_operand:DF 1 "register_operand" "0")))]
4291  "TARGET_80387"
4292  "fchs")
4293
4294(define_insn ""
4295  [(set (match_operand:DF 0 "register_operand" "=f")
4296	(neg:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
4297  "TARGET_80387"
4298  "fchs")
4299
4300(define_insn "negxf2"
4301  [(set (match_operand:XF 0 "register_operand" "=f")
4302	(neg:XF (match_operand:XF 1 "register_operand" "0")))]
4303  "TARGET_80387"
4304  "fchs")
4305
4306(define_insn ""
4307  [(set (match_operand:XF 0 "register_operand" "=f")
4308	(neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
4309  "TARGET_80387"
4310  "fchs")
4311
4312;; Absolute value instructions
4313
4314(define_insn "abssf2"
4315  [(set (match_operand:SF 0 "register_operand" "=f")
4316	(abs:SF (match_operand:SF 1 "register_operand" "0")))]
4317  "TARGET_80387"
4318  "fabs"
4319  [(set_attr "type" "fpop")])
4320
4321(define_insn "absdf2"
4322  [(set (match_operand:DF 0 "register_operand" "=f")
4323	(abs:DF (match_operand:DF 1 "register_operand" "0")))]
4324  "TARGET_80387"
4325  "fabs"
4326  [(set_attr "type" "fpop")])
4327
4328(define_insn ""
4329  [(set (match_operand:DF 0 "register_operand" "=f")
4330	(abs:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
4331  "TARGET_80387"
4332  "fabs"
4333  [(set_attr "type" "fpop")])
4334
4335(define_insn "absxf2"
4336  [(set (match_operand:XF 0 "register_operand" "=f")
4337	(abs:XF (match_operand:XF 1 "register_operand" "0")))]
4338  "TARGET_80387"
4339  "fabs"
4340  [(set_attr "type" "fpop")])
4341
4342(define_insn ""
4343  [(set (match_operand:XF 0 "register_operand" "=f")
4344	(abs:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
4345  "TARGET_80387"
4346  "fabs"
4347  [(set_attr "type" "fpop")])
4348
4349(define_insn "sqrtsf2"
4350  [(set (match_operand:SF 0 "register_operand" "=f")
4351	(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
4352  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
4353  "fsqrt")
4354
4355(define_insn "sqrtdf2"
4356  [(set (match_operand:DF 0 "register_operand" "=f")
4357	(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
4358  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
4359   && (TARGET_IEEE_FP || flag_fast_math) "
4360  "fsqrt")
4361
4362(define_insn ""
4363  [(set (match_operand:DF 0 "register_operand" "=f")
4364	(sqrt:DF (float_extend:DF
4365		  (match_operand:SF 1 "register_operand" "0"))))]
4366  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
4367  "fsqrt")
4368
4369(define_insn "sqrtxf2"
4370  [(set (match_operand:XF 0 "register_operand" "=f")
4371	(sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
4372  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
4373   && (TARGET_IEEE_FP || flag_fast_math) "
4374  "fsqrt")
4375
4376(define_insn ""
4377  [(set (match_operand:XF 0 "register_operand" "=f")
4378	(sqrt:XF (float_extend:XF
4379		  (match_operand:DF 1 "register_operand" "0"))))]
4380  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
4381  "fsqrt")
4382
4383(define_insn ""
4384  [(set (match_operand:XF 0 "register_operand" "=f")
4385	(sqrt:XF (float_extend:XF
4386		  (match_operand:SF 1 "register_operand" "0"))))]
4387  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
4388  "fsqrt")
4389
4390(define_insn "sindf2"
4391  [(set (match_operand:DF 0 "register_operand" "=f")
4392	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
4393  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4394  "fsin")
4395
4396(define_insn "sinsf2"
4397  [(set (match_operand:SF 0 "register_operand" "=f")
4398	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
4399  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4400  "fsin")
4401
4402(define_insn ""
4403  [(set (match_operand:DF 0 "register_operand" "=f")
4404	(unspec:DF [(float_extend:DF
4405		     (match_operand:SF 1 "register_operand" "0"))] 1))]
4406  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4407  "fsin")
4408
4409(define_insn "sinxf2"
4410  [(set (match_operand:XF 0 "register_operand" "=f")
4411	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
4412  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4413  "fsin")
4414
4415(define_insn "cosdf2"
4416  [(set (match_operand:DF 0 "register_operand" "=f")
4417	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
4418  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4419  "fcos")
4420
4421(define_insn "cossf2"
4422  [(set (match_operand:SF 0 "register_operand" "=f")
4423	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
4424  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4425  "fcos")
4426
4427(define_insn ""
4428  [(set (match_operand:DF 0 "register_operand" "=f")
4429	(unspec:DF [(float_extend:DF
4430		     (match_operand:SF 1 "register_operand" "0"))] 2))]
4431  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4432  "fcos")
4433
4434(define_insn "cosxf2"
4435  [(set (match_operand:XF 0 "register_operand" "=f")
4436	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))]
4437  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4438  "fcos")
4439
4440;;- one complement instructions
4441
4442(define_insn "one_cmplsi2"
4443  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4444	(not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
4445  ""
4446  "not%L0 %0")
4447
4448(define_insn "one_cmplhi2"
4449  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4450	(not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
4451  ""
4452  "not%W0 %0")
4453
4454(define_insn "one_cmplqi2"
4455  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4456	(not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
4457  ""
4458  "not%B0 %0")
4459
4460;;- arithmetic shift instructions
4461
4462;; DImode shifts are implemented using the i386 "shift double" opcode,
4463;; which is written as "sh[lr]d[lw] imm,reg,reg/mem".  If the shift count
4464;; is variable, then the count is in %cl and the "imm" operand is dropped
4465;; from the assembler input.
4466
4467;; This instruction shifts the target reg/mem as usual, but instead of
4468;; shifting in zeros, bits are shifted in from reg operand.  If the insn
4469;; is a left shift double, bits are taken from the high order bits of
4470;; reg, else if the insn is a shift right double, bits are taken from the
4471;; low order bits of reg.  So if %eax is "1234" and %edx is "5678",
4472;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
4473
4474;; Since sh[lr]d does not change the `reg' operand, that is done
4475;; separately, making all shifts emit pairs of shift double and normal
4476;; shift.  Since sh[lr]d does not shift more than 31 bits, and we wish to
4477;; support a 63 bit shift, each shift where the count is in a reg expands
4478;; to a pair of shifts, a branch, a shift by 32 and a label.
4479
4480;; If the shift count is a constant, we need never emit more than one
4481;; shift pair, instead using moves and sign extension for counts greater
4482;; than 31.
4483
4484(define_expand "ashldi3"
4485  [(set (match_operand:DI 0 "register_operand" "")
4486	(ashift:DI (match_operand:DI 1 "register_operand" "")
4487		   (match_operand:QI 2 "nonmemory_operand" "")))]
4488  ""
4489  "
4490{
4491  if (GET_CODE (operands[2]) != CONST_INT
4492      || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
4493    {
4494      operands[2] = copy_to_mode_reg (QImode, operands[2]);
4495      emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1],
4496					    operands[2]));
4497    }
4498  else
4499    emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2]));
4500
4501  DONE;
4502}")
4503
4504(define_insn "ashldi3_const_int"
4505  [(set (match_operand:DI 0 "register_operand" "=&r")
4506	(ashift:DI (match_operand:DI 1 "register_operand" "0")
4507		   (match_operand:QI 2 "const_int_operand" "J")))]
4508  "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')"
4509  "*
4510{
4511  rtx xops[4], low[1], high[1];
4512
4513  CC_STATUS_INIT;
4514
4515  split_di (operands, 1, low, high);
4516  xops[0] = operands[2];
4517  xops[1] = const1_rtx;
4518  xops[2] = low[0];
4519  xops[3] = high[0];
4520
4521  if (INTVAL (xops[0]) > 31)
4522    {
4523      output_asm_insn (AS2 (mov%L3,%2,%3), xops);	/* Fast shift by 32 */
4524      output_asm_insn (AS2 (xor%L2,%2,%2), xops);
4525
4526      if (INTVAL (xops[0]) > 32)
4527        {
4528	  xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
4529	  output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */
4530	}
4531    }
4532  else
4533    {
4534      output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops);
4535      output_asm_insn (AS2 (sal%L2,%0,%2), xops);
4536    }
4537  RET;
4538}")
4539
4540(define_insn "ashldi3_non_const_int"
4541  [(set (match_operand:DI 0 "register_operand" "=&r")
4542	(ashift:DI (match_operand:DI 1 "register_operand" "0")
4543		   (match_operand:QI 2 "register_operand" "c")))]
4544  ""
4545  "*
4546{
4547  rtx xops[5], low[1], high[1];
4548
4549  CC_STATUS_INIT;
4550
4551  split_di (operands, 1, low, high);
4552  xops[0] = operands[2];
4553  xops[1] = GEN_INT (32);
4554  xops[2] = low[0];
4555  xops[3] = high[0];
4556  xops[4] = gen_label_rtx ();
4557
4558  output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
4559  output_asm_insn (AS2 (sal%L2,%0,%2), xops);
4560  output_asm_insn (AS2 (test%B0,%1,%b0), xops);
4561  output_asm_insn (AS1 (je,%X4), xops);
4562  output_asm_insn (AS2 (mov%L3,%2,%3), xops);	/* Fast shift by 32 */
4563  output_asm_insn (AS2 (xor%L2,%2,%2), xops);
4564  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4565                             CODE_LABEL_NUMBER (xops[4]));
4566  RET;
4567}")
4568
4569;; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg"
4570;; On i486, movl/sall appears slightly faster than leal, but the leal
4571;; is smaller - use leal for now unless the shift count is 1.
4572
4573(define_insn "ashlsi3"
4574  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
4575	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,0")
4576		   (match_operand:SI 2 "nonmemory_operand" "M,cI")))]
4577  ""
4578  "*
4579{
4580  if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
4581    {
4582      if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1)
4583	{
4584	  output_asm_insn (AS2 (mov%L0,%1,%0), operands);
4585	  return AS2 (add%L0,%1,%0);
4586	}
4587      else
4588        {
4589          CC_STATUS_INIT;
4590
4591	  if (operands[1] == stack_pointer_rtx)
4592	    {
4593	      output_asm_insn (AS2 (mov%L0,%1,%0), operands);
4594	      operands[1] = operands[0];
4595	    }
4596          operands[1] = gen_rtx_MULT (SImode, operands[1],
4597				      GEN_INT (1 << INTVAL (operands[2])));
4598	  return AS2 (lea%L0,%a1,%0);
4599	}
4600    }
4601
4602  if (REG_P (operands[2]))
4603    return AS2 (sal%L0,%b2,%0);
4604
4605  if (REG_P (operands[0]) && operands[2] == const1_rtx)
4606    return AS2 (add%L0,%0,%0);
4607
4608  return AS2 (sal%L0,%2,%0);
4609}")
4610
4611(define_insn "ashlhi3"
4612  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4613	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
4614		   (match_operand:HI 2 "nonmemory_operand" "cI")))]
4615  ""
4616  "*
4617{
4618  if (REG_P (operands[2]))
4619    return AS2 (sal%W0,%b2,%0);
4620
4621  if (REG_P (operands[0]) && operands[2] == const1_rtx)
4622    return AS2 (add%W0,%0,%0);
4623
4624  return AS2 (sal%W0,%2,%0);
4625}")
4626
4627(define_insn "ashlqi3"
4628  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4629	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
4630		   (match_operand:QI 2 "nonmemory_operand" "cI")))]
4631  ""
4632  "*
4633{
4634  if (REG_P (operands[2]))
4635    return AS2 (sal%B0,%b2,%0);
4636
4637  if (REG_P (operands[0]) && operands[2] == const1_rtx)
4638    return AS2 (add%B0,%0,%0);
4639
4640  return AS2 (sal%B0,%2,%0);
4641}")
4642
4643;; See comment above `ashldi3' about how this works.
4644
4645(define_expand "ashrdi3"
4646  [(set (match_operand:DI 0 "register_operand" "")
4647	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
4648		     (match_operand:QI 2 "nonmemory_operand" "")))]
4649  ""
4650  "
4651{
4652  if (GET_CODE (operands[2]) != CONST_INT
4653      || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
4654    {
4655      operands[2] = copy_to_mode_reg (QImode, operands[2]);
4656      emit_insn (gen_ashrdi3_non_const_int (operands[0], operands[1],
4657					    operands[2]));
4658    }
4659  else
4660    emit_insn (gen_ashrdi3_const_int (operands[0], operands[1], operands[2]));
4661
4662  DONE;
4663}")
4664
4665(define_insn "ashldi3_32"
4666  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m")
4667	(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r")
4668		   (const_int 32)))]
4669  ""
4670  "*
4671{
4672  rtx low[2], high[2], xops[4];
4673
4674  split_di (operands, 2, low, high);
4675  xops[0] = high[0];
4676  xops[1] = low[1];
4677  xops[2] = low[0];
4678  xops[3] = const0_rtx;
4679  if (!rtx_equal_p (xops[0], xops[1]))
4680    output_asm_insn (AS2 (mov%L0,%1,%0), xops);
4681
4682  if (GET_CODE (low[0]) == MEM)
4683    output_asm_insn (AS2 (mov%L2,%3,%2), xops);
4684  else
4685    output_asm_insn (AS2 (xor%L2,%2,%2), xops);
4686
4687  RET;
4688}")
4689
4690(define_insn "ashrdi3_const_int"
4691  [(set (match_operand:DI 0 "register_operand" "=&r")
4692	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
4693		     (match_operand:QI 2 "const_int_operand" "J")))]
4694  "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')"
4695  "*
4696{
4697  rtx xops[4], low[1], high[1];
4698
4699  CC_STATUS_INIT;
4700
4701  split_di (operands, 1, low, high);
4702  xops[0] = operands[2];
4703  xops[1] = const1_rtx;
4704  xops[2] = low[0];
4705  xops[3] = high[0];
4706
4707  if (INTVAL (xops[0]) > 31)
4708    {
4709      xops[1] = GEN_INT (31);
4710      output_asm_insn (AS2 (mov%L2,%3,%2), xops);
4711      output_asm_insn (AS2 (sar%L3,%1,%3), xops);	/* shift by 32 */
4712
4713      if (INTVAL (xops[0]) > 32)
4714        {
4715	  xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
4716	  output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */
4717	}
4718    }
4719  else
4720    {
4721      output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
4722      output_asm_insn (AS2 (sar%L3,%0,%3), xops);
4723    }
4724
4725  RET;
4726}")
4727
4728(define_insn "ashrdi3_non_const_int"
4729  [(set (match_operand:DI 0 "register_operand" "=&r")
4730	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
4731		     (match_operand:QI 2 "register_operand" "c")))]
4732  ""
4733  "*
4734{
4735  rtx xops[5], low[1], high[1];
4736
4737  CC_STATUS_INIT;
4738
4739  split_di (operands, 1, low, high);
4740  xops[0] = operands[2];
4741  xops[1] = GEN_INT (32);
4742  xops[2] = low[0];
4743  xops[3] = high[0];
4744  xops[4] = gen_label_rtx ();
4745
4746  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
4747  output_asm_insn (AS2 (sar%L3,%0,%3), xops);
4748  output_asm_insn (AS2 (test%B0,%1,%b0), xops);
4749  output_asm_insn (AS1 (je,%X4), xops);
4750  xops[1] = GEN_INT (31);
4751  output_asm_insn (AS2 (mov%L2,%3,%2), xops);
4752  output_asm_insn (AS2 (sar%L3,%1,%3), xops);	/* shift by 32 */
4753  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4754                             CODE_LABEL_NUMBER (xops[4]));
4755  RET;
4756}")
4757
4758(define_insn "ashrsi3"
4759  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4760	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
4761		     (match_operand:SI 2 "nonmemory_operand" "cI")))]
4762  ""
4763  "*
4764{
4765  if (REG_P (operands[2]))
4766    return AS2 (sar%L0,%b2,%0);
4767  else
4768    return AS2 (sar%L0,%2,%0);
4769}")
4770
4771(define_insn "ashrhi3"
4772  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4773	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
4774		     (match_operand:HI 2 "nonmemory_operand" "cI")))]
4775  ""
4776  "*
4777{
4778  if (REG_P (operands[2]))
4779    return AS2 (sar%W0,%b2,%0);
4780  else
4781    return AS2 (sar%W0,%2,%0);
4782}")
4783
4784(define_insn "ashrqi3"
4785  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4786	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
4787		     (match_operand:QI 2 "nonmemory_operand" "cI")))]
4788  ""
4789  "*
4790{
4791  if (REG_P (operands[2]))
4792    return AS2 (sar%B0,%b2,%0);
4793  else
4794    return AS2 (sar%B0,%2,%0);
4795}")
4796
4797;;- logical shift instructions
4798
4799;; See comment above `ashldi3' about how this works.
4800
4801(define_expand "lshrdi3"
4802  [(set (match_operand:DI 0 "register_operand" "")
4803	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
4804		     (match_operand:QI 2 "nonmemory_operand" "")))]
4805  ""
4806  "
4807{
4808  if (GET_CODE (operands[2]) != CONST_INT
4809      || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
4810    {
4811      operands[2] = copy_to_mode_reg (QImode, operands[2]);
4812      emit_insn (gen_lshrdi3_non_const_int (operands[0], operands[1],
4813					    operands[2]));
4814    }
4815  else
4816    emit_insn (gen_lshrdi3_const_int (operands[0], operands[1], operands[2]));
4817
4818  DONE;
4819}")
4820
4821(define_insn "lshrdi3_32"
4822  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m")
4823	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r")
4824		     (const_int 32)))]
4825  ""
4826  "*
4827{
4828  rtx low[2], high[2], xops[4];
4829
4830  split_di (operands, 2, low, high);
4831  xops[0] = low[0];
4832  xops[1] = high[1];
4833  xops[2] = high[0];
4834  xops[3] = const0_rtx;
4835  if (!rtx_equal_p (xops[0], xops[1]))
4836    output_asm_insn (AS2 (mov%L0,%1,%0), xops);
4837
4838  if (GET_CODE (low[0]) == MEM)
4839    output_asm_insn (AS2 (mov%L2,%3,%2), xops);
4840  else
4841    output_asm_insn (AS2 (xor%L2,%2,%2), xops);
4842
4843  RET;
4844}")
4845
4846(define_insn "lshrdi3_const_int"
4847  [(set (match_operand:DI 0 "register_operand" "=&r")
4848	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
4849		     (match_operand:QI 2 "const_int_operand" "J")))]
4850  "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')"
4851  "*
4852{
4853  rtx xops[4], low[1], high[1];
4854
4855  CC_STATUS_INIT;
4856
4857  split_di (operands, 1, low, high);
4858  xops[0] = operands[2];
4859  xops[1] = const1_rtx;
4860  xops[2] = low[0];
4861  xops[3] = high[0];
4862
4863  if (INTVAL (xops[0]) > 31)
4864    {
4865      output_asm_insn (AS2 (mov%L2,%3,%2), xops);	/* Fast shift by 32 */
4866      output_asm_insn (AS2 (xor%L3,%3,%3), xops);
4867
4868      if (INTVAL (xops[0]) > 32)
4869        {
4870	  xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
4871	  output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */
4872	}
4873    }
4874  else
4875    {
4876      output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
4877      output_asm_insn (AS2 (shr%L3,%0,%3), xops);
4878    }
4879
4880  RET;
4881}")
4882
4883(define_insn "lshrdi3_non_const_int"
4884  [(set (match_operand:DI 0 "register_operand" "=&r")
4885	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
4886		     (match_operand:QI 2 "register_operand" "c")))]
4887  ""
4888  "*
4889{
4890  rtx xops[5], low[1], high[1];
4891
4892  CC_STATUS_INIT;
4893
4894  split_di (operands, 1, low, high);
4895  xops[0] = operands[2];
4896  xops[1] = GEN_INT (32);
4897  xops[2] = low[0];
4898  xops[3] = high[0];
4899  xops[4] = gen_label_rtx ();
4900
4901  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
4902  output_asm_insn (AS2 (shr%L3,%0,%3), xops);
4903  output_asm_insn (AS2 (test%B0,%1,%b0), xops);
4904  output_asm_insn (AS1 (je,%X4), xops);
4905  output_asm_insn (AS2 (mov%L2,%3,%2), xops);	/* Fast shift by 32 */
4906  output_asm_insn (AS2 (xor%L3,%3,%3), xops);
4907  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4908                             CODE_LABEL_NUMBER (xops[4]));
4909  RET;
4910}")
4911
4912(define_insn "lshrsi3"
4913  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4914	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
4915		     (match_operand:SI 2 "nonmemory_operand" "cI")))]
4916  ""
4917  "*
4918{
4919  if (REG_P (operands[2]))
4920    return AS2 (shr%L0,%b2,%0);
4921  else
4922    return AS2 (shr%L0,%2,%1);
4923}")
4924
4925(define_insn "lshrhi3"
4926  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4927	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
4928		     (match_operand:HI 2 "nonmemory_operand" "cI")))]
4929  ""
4930  "*
4931{
4932  if (REG_P (operands[2]))
4933    return AS2 (shr%W0,%b2,%0);
4934  else
4935    return AS2 (shr%W0,%2,%0);
4936}")
4937
4938(define_insn "lshrqi3"
4939  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4940	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
4941		     (match_operand:QI 2 "nonmemory_operand" "cI")))]
4942  ""
4943  "*
4944{
4945  if (REG_P (operands[2]))
4946    return AS2 (shr%B0,%b2,%0);
4947  else
4948    return AS2 (shr%B0,%2,%0);
4949}")
4950
4951;;- rotate instructions
4952
4953(define_insn "rotlsi3"
4954  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4955	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0")
4956		   (match_operand:SI 2 "nonmemory_operand" "cI")))]
4957  ""
4958  "*
4959{
4960  if (REG_P (operands[2]))
4961    return AS2 (rol%L0,%b2,%0);
4962  else
4963    return AS2 (rol%L0,%2,%0);
4964}")
4965
4966(define_insn "rotlhi3"
4967  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4968	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0")
4969		   (match_operand:HI 2 "nonmemory_operand" "cI")))]
4970  ""
4971  "*
4972{
4973  if (REG_P (operands[2]))
4974    return AS2 (rol%W0,%b2,%0);
4975  else
4976    return AS2 (rol%W0,%2,%0);
4977}")
4978
4979(define_insn "rotlqi3"
4980  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4981	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
4982		   (match_operand:QI 2 "nonmemory_operand" "cI")))]
4983  ""
4984  "*
4985{
4986  if (REG_P (operands[2]))
4987    return AS2 (rol%B0,%b2,%0);
4988  else
4989    return AS2 (rol%B0,%2,%0);
4990}")
4991
4992(define_insn "rotrsi3"
4993  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4994	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0")
4995		     (match_operand:SI 2 "nonmemory_operand" "cI")))]
4996  ""
4997  "*
4998{
4999  if (REG_P (operands[2]))
5000    return AS2 (ror%L0,%b2,%0);
5001  else
5002    return AS2 (ror%L0,%2,%0);
5003}")
5004
5005(define_insn "rotrhi3"
5006  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
5007	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0")
5008		     (match_operand:HI 2 "nonmemory_operand" "cI")))]
5009  ""
5010  "*
5011{
5012  if (REG_P (operands[2]))
5013    return AS2 (ror%W0,%b2,%0);
5014  else
5015    return AS2 (ror%W0,%2,%0);
5016}")
5017
5018(define_insn "rotrqi3"
5019  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
5020	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0")
5021		     (match_operand:QI 2 "nonmemory_operand" "cI")))]
5022  ""
5023  "*
5024{
5025  if (REG_P (operands[2]))
5026    return AS2 (ror%B0,%b2,%0);
5027  else
5028    return AS2 (ror%B0,%2,%0);
5029}")
5030
5031/*
5032;; This usually looses.  But try a define_expand to recognize a few case
5033;; we can do efficiently, such as accessing the "high" QImode registers,
5034;; %ah, %bh, %ch, %dh.
5035;; ??? Note this has a botch on the mode of operand 0, which needs to be
5036;; fixed if this is ever enabled.
5037(define_insn "insv"
5038  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r")
5039			 (match_operand:SI 1 "immediate_operand" "i")
5040			 (match_operand:SI 2 "immediate_operand" "i"))
5041	(match_operand:SI 3 "nonmemory_operand" "ri"))]
5042  ""
5043  "*
5044{
5045  if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode))
5046    abort ();
5047  if (GET_CODE (operands[3]) == CONST_INT)
5048    {
5049      unsigned int mask = (1 << INTVAL (operands[1])) - 1; 
5050      operands[1] = GEN_INT (~(mask << INTVAL (operands[2])));
5051      output_asm_insn (AS2 (and%L0,%1,%0), operands);
5052      operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2]));
5053      output_asm_insn (AS2 (or%L0,%3,%0), operands);
5054    }
5055  else
5056    {
5057      operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
5058      if (INTVAL (operands[2]))
5059	output_asm_insn (AS2 (ror%L0,%2,%0), operands);
5060      output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands);
5061      operands[2] = GEN_INT (BITS_PER_WORD
5062			     - INTVAL (operands[1]) - INTVAL (operands[2]));
5063      if (INTVAL (operands[2]))
5064	output_asm_insn (AS2 (ror%L0,%2,%0), operands);
5065    }
5066  RET;
5067}")
5068*/
5069/*
5070;; ??? There are problems with the mode of operand[3].  The point of this
5071;; is to represent an HImode move to a "high byte" register.
5072
5073(define_expand "insv"
5074  [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
5075			 (match_operand:SI 1 "immediate_operand" "")
5076			 (match_operand:SI 2 "immediate_operand" ""))
5077	(match_operand:QI 3 "nonmemory_operand" "ri"))]
5078  ""
5079  "
5080{
5081  if (GET_CODE (operands[1]) != CONST_INT
5082      || GET_CODE (operands[2]) != CONST_INT)
5083    FAIL;
5084
5085  if (! (INTVAL (operands[1]) == 8
5086	 && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0))
5087      && ! INTVAL (operands[1]) == 1)
5088    FAIL;
5089}")
5090*/
5091
5092;; On i386, the register count for a bit operation is *not* truncated,
5093;; so SHIFT_COUNT_TRUNCATED must not be defined.
5094
5095;; On i486, the shift & or/and code is faster than bts or btr.  If
5096;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code.
5097
5098;; On i386, bts is a little faster if operands[0] is a reg, and a
5099;; little slower if operands[0] is a MEM, than the shift & or/and code.
5100;; Use bts & btr, since they reload better.
5101
5102;; General bit set and clear.
5103(define_insn ""
5104  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+rm")
5105			 (const_int 1)
5106			 (match_operand:SI 2 "register_operand" "r"))
5107	(match_operand:SI 3 "const_int_operand" "n"))]
5108  "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT"
5109  "*
5110{
5111  CC_STATUS_INIT;
5112
5113  if (INTVAL (operands[3]) == 1)
5114    return AS2 (bts%L0,%2,%0);
5115  else
5116    return AS2 (btr%L0,%2,%0);
5117}")
5118
5119;; Bit complement.  See comments on previous pattern.
5120;; ??? Is this really worthwhile?
5121(define_insn ""
5122  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
5123	(xor:SI (ashift:SI (const_int 1)
5124			   (match_operand:SI 1 "register_operand" "r"))
5125		(match_operand:SI 2 "nonimmediate_operand" "0")))]
5126  "TARGET_USE_BIT_TEST && GET_CODE (operands[1]) != CONST_INT"
5127  "*
5128{
5129  CC_STATUS_INIT;
5130
5131  return AS2 (btc%L0,%1,%0);
5132}")
5133
5134(define_insn ""
5135  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
5136	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5137		(ashift:SI (const_int 1)
5138			   (match_operand:SI 2 "register_operand" "r"))))]
5139  "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT"
5140  "*
5141{
5142  CC_STATUS_INIT;
5143
5144  return AS2 (btc%L0,%2,%0);
5145}")
5146
5147;; Recognizers for bit-test instructions.
5148
5149;; The bt opcode allows a MEM in operands[0].  But on both i386 and
5150;; i486, it is faster to copy a MEM to REG and then use bt, than to use
5151;; bt on the MEM directly.
5152
5153;; ??? The first argument of a zero_extract must not be reloaded, so
5154;; don't allow a MEM in the operand predicate without allowing it in the
5155;; constraint.
5156
5157(define_insn ""
5158  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
5159			    (const_int 1)
5160			    (match_operand:SI 1 "register_operand" "r")))]
5161  "GET_CODE (operands[1]) != CONST_INT"
5162  "*
5163{
5164  cc_status.flags |= CC_Z_IN_NOT_C;
5165  return AS2 (bt%L0,%1,%0);
5166}")
5167
5168(define_insn ""
5169  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
5170			    (match_operand:SI 1 "const_int_operand" "n")
5171			    (match_operand:SI 2 "const_int_operand" "n")))]
5172  ""
5173  "*
5174{
5175  unsigned int mask;
5176
5177  mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
5178  operands[1] = GEN_INT (mask);
5179
5180  if (QI_REG_P (operands[0]))
5181    {
5182      if ((mask & ~0xff) == 0)
5183        {
5184	  cc_status.flags |= CC_NOT_NEGATIVE;
5185	  return AS2 (test%B0,%1,%b0);
5186	}
5187
5188      if ((mask & ~0xff00) == 0)
5189        {
5190	  cc_status.flags |= CC_NOT_NEGATIVE;
5191	  operands[1] = GEN_INT (mask >> 8);
5192	  return AS2 (test%B0,%1,%h0);
5193	}
5194    }
5195
5196  return AS2 (test%L0,%1,%0);
5197}")
5198
5199;; ??? All bets are off if operand 0 is a volatile MEM reference.
5200;; The CPU may access unspecified bytes around the actual target byte.
5201
5202(define_insn ""
5203  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
5204			    (match_operand:SI 1 "const_int_operand" "n")
5205			    (match_operand:SI 2 "const_int_operand" "n")))]
5206  "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])"
5207  "*
5208{
5209  unsigned int mask;
5210
5211  mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
5212  operands[1] = GEN_INT (mask);
5213
5214  if (! REG_P (operands[0]) || QI_REG_P (operands[0]))
5215    {
5216      if ((mask & ~0xff) == 0)
5217        {
5218	  cc_status.flags |= CC_NOT_NEGATIVE;
5219	  return AS2 (test%B0,%1,%b0);
5220	}
5221
5222      if ((mask & ~0xff00) == 0)
5223        {
5224	  cc_status.flags |= CC_NOT_NEGATIVE;
5225	  operands[1] = GEN_INT (mask >> 8);
5226
5227	  if (QI_REG_P (operands[0]))
5228	    return AS2 (test%B0,%1,%h0);
5229	  else
5230	    {
5231	      operands[0] = adj_offsettable_operand (operands[0], 1);
5232	      return AS2 (test%B0,%1,%b0);
5233	    }
5234	}
5235
5236      if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0)
5237        {
5238	  cc_status.flags |= CC_NOT_NEGATIVE;
5239	  operands[1] = GEN_INT (mask >> 16);
5240	  operands[0] = adj_offsettable_operand (operands[0], 2);
5241	  return AS2 (test%B0,%1,%b0);
5242	}
5243
5244      if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0)
5245        {
5246	  cc_status.flags |= CC_NOT_NEGATIVE;
5247	  operands[1] = GEN_INT (mask >> 24);
5248	  operands[0] = adj_offsettable_operand (operands[0], 3);
5249	  return AS2 (test%B0,%1,%b0);
5250	}
5251    }
5252
5253  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
5254    return AS2 (test%L0,%1,%0);
5255
5256  return AS2 (test%L1,%0,%1);
5257}")
5258
5259;; Store-flag instructions.
5260
5261;; For all sCOND expanders, also expand the compare or test insn that
5262;; generates cc0.  Generate an equality comparison if `seq' or `sne'.
5263
5264;; The 386 sCOND opcodes can write to memory.  But a gcc sCOND insn may
5265;; not have any input reloads.  A MEM write might need an input reload
5266;; for the address of the MEM.  So don't allow MEM as the SET_DEST.
5267
5268(define_expand "seq"
5269  [(match_dup 1)
5270   (set (match_operand:QI 0 "register_operand" "")
5271	(eq:QI (cc0) (const_int 0)))]
5272  ""
5273  "
5274{
5275  if (TARGET_IEEE_FP
5276      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
5277    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
5278  else
5279    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
5280}")
5281
5282(define_insn ""
5283  [(set (match_operand:QI 0 "register_operand" "=q")
5284	(eq:QI (cc0) (const_int 0)))]
5285  ""
5286  "*
5287{
5288  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5289    return AS1 (setnb,%0);
5290  else
5291    return AS1 (sete,%0);
5292}")
5293
5294(define_expand "sne"
5295  [(match_dup 1)
5296   (set (match_operand:QI 0 "register_operand" "")
5297	(ne:QI (cc0) (const_int 0)))]
5298  ""
5299  "
5300{
5301  if (TARGET_IEEE_FP
5302      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
5303    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
5304  else
5305    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
5306}")
5307
5308(define_insn ""
5309  [(set (match_operand:QI 0 "register_operand" "=q")
5310	(ne:QI (cc0) (const_int 0)))]
5311  ""
5312  "*
5313{
5314  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5315    return AS1 (setb,%0);
5316  else
5317    return AS1 (setne,%0);
5318}
5319")
5320
5321(define_expand "sgt"
5322  [(match_dup 1)
5323   (set (match_operand:QI 0 "register_operand" "")
5324	(gt:QI (cc0) (const_int 0)))]
5325  ""
5326  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5327
5328(define_insn ""
5329  [(set (match_operand:QI 0 "register_operand" "=q")
5330	(gt:QI (cc0) (const_int 0)))]
5331  ""
5332  "*
5333{
5334  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5335      && ! (cc_prev_status.flags & CC_FCOMI))
5336    return AS1 (sete,%0);
5337
5338  OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR);
5339}")
5340
5341(define_expand "sgtu"
5342  [(match_dup 1)
5343   (set (match_operand:QI 0 "register_operand" "")
5344	(gtu:QI (cc0) (const_int 0)))]
5345  ""
5346  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5347
5348(define_insn ""
5349  [(set (match_operand:QI 0 "register_operand" "=q")
5350	(gtu:QI (cc0) (const_int 0)))]
5351  ""
5352  "* return \"seta %0\"; ")
5353
5354(define_expand "slt"
5355  [(match_dup 1)
5356   (set (match_operand:QI 0 "register_operand" "")
5357	(lt:QI (cc0) (const_int 0)))]
5358  ""
5359  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5360
5361(define_insn ""
5362  [(set (match_operand:QI 0 "register_operand" "=q")
5363	(lt:QI (cc0) (const_int 0)))]
5364  ""
5365  "*
5366{
5367  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5368      && ! (cc_prev_status.flags & CC_FCOMI))
5369    return AS1 (sete,%0);
5370
5371  OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\");
5372}")
5373
5374(define_expand "sltu"
5375  [(match_dup 1)
5376   (set (match_operand:QI 0 "register_operand" "")
5377	(ltu:QI (cc0) (const_int 0)))]
5378  ""
5379  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5380
5381(define_insn ""
5382  [(set (match_operand:QI 0 "register_operand" "=q")
5383	(ltu:QI (cc0) (const_int 0)))]
5384  ""
5385  "* return \"setb %0\"; ")
5386
5387(define_expand "sge"
5388  [(match_dup 1)
5389   (set (match_operand:QI 0 "register_operand" "")
5390	(ge:QI (cc0) (const_int 0)))]
5391  ""
5392  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5393
5394(define_insn ""
5395  [(set (match_operand:QI 0 "register_operand" "=q")
5396	(ge:QI (cc0) (const_int 0)))]
5397  ""
5398  "*
5399{
5400  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5401      && ! (cc_prev_status.flags & CC_FCOMI))
5402    return AS1 (sete,%0);
5403
5404  OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\");
5405}")
5406
5407(define_expand "sgeu"
5408  [(match_dup 1)
5409   (set (match_operand:QI 0 "register_operand" "")
5410	(geu:QI (cc0) (const_int 0)))]
5411  ""
5412  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5413
5414(define_insn ""
5415  [(set (match_operand:QI 0 "register_operand" "=q")
5416	(geu:QI (cc0) (const_int 0)))]
5417  ""
5418  "* return \"setae %0\"; ")
5419
5420(define_expand "sle"
5421  [(match_dup 1)
5422   (set (match_operand:QI 0 "register_operand" "")
5423	(le:QI (cc0) (const_int 0)))]
5424  ""
5425  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5426
5427(define_insn ""
5428  [(set (match_operand:QI 0 "register_operand" "=q")
5429	(le:QI (cc0) (const_int 0)))]
5430  ""
5431  "*
5432{
5433  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5434      && ! (cc_prev_status.flags & CC_FCOMI))
5435    return AS1 (setb,%0);
5436
5437  OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR);
5438}")
5439
5440(define_expand "sleu"
5441  [(match_dup 1)
5442   (set (match_operand:QI 0 "register_operand" "")
5443	(leu:QI (cc0) (const_int 0)))]
5444  ""
5445  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5446
5447(define_insn ""
5448  [(set (match_operand:QI 0 "register_operand" "=q")
5449	(leu:QI (cc0) (const_int 0)))]
5450  ""
5451  "* return \"setbe %0\"; ")
5452
5453;; Basic conditional jump instructions.
5454;; We ignore the overflow flag for signed branch instructions.
5455
5456;; For all bCOND expanders, also expand the compare or test insn that
5457;; generates cc0.  Generate an equality comparison if `beq' or `bne'.
5458
5459(define_expand "beq"
5460  [(match_dup 1)
5461   (set (pc)
5462	(if_then_else (eq (cc0)
5463			  (const_int 0))
5464		      (label_ref (match_operand 0 "" ""))
5465		      (pc)))]
5466  ""
5467  "
5468{
5469  if (TARGET_IEEE_FP
5470      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
5471    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
5472  else
5473    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
5474}")
5475
5476(define_insn ""
5477  [(set (pc)
5478	(if_then_else (eq (cc0)
5479			  (const_int 0))
5480		      (label_ref (match_operand 0 "" ""))
5481		      (pc)))]
5482  ""
5483  "*
5484{
5485  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5486    return \"jnc %l0\";
5487  else
5488  if (cc_prev_status.flags & CC_TEST_AX)
5489    {
5490      operands[1] = gen_rtx_REG (SImode, 0);
5491      operands[2] = GEN_INT (0x4000);
5492      output_asm_insn (AS2 (testl,%2,%1), operands);
5493      return AS1 (jne,%l0);
5494    }
5495
5496    return \"je %l0\";
5497}")
5498
5499(define_expand "bne"
5500  [(match_dup 1)
5501   (set (pc)
5502	(if_then_else (ne (cc0)
5503			  (const_int 0))
5504		      (label_ref (match_operand 0 "" ""))
5505		      (pc)))]
5506  ""
5507  "
5508{
5509  if (TARGET_IEEE_FP
5510      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
5511    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
5512  else
5513    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
5514}")
5515
5516(define_insn ""
5517  [(set (pc)
5518	(if_then_else (ne (cc0)
5519			  (const_int 0))
5520		      (label_ref (match_operand 0 "" ""))
5521		      (pc)))]
5522  ""
5523  "*
5524{
5525  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5526    return \"jc %l0\";
5527  else
5528  if (cc_prev_status.flags & CC_TEST_AX)
5529    {
5530      operands[1] = gen_rtx_REG (SImode, 0);
5531      operands[2] = GEN_INT (0x4000);
5532      output_asm_insn (AS2 (testl,%2,%1), operands);
5533      return AS1 (je,%l0);
5534    }
5535
5536    return \"jne %l0\";
5537}")
5538
5539(define_expand "bgt"
5540  [(match_dup 1)
5541   (set (pc)
5542	(if_then_else (gt (cc0)
5543			  (const_int 0))
5544		      (label_ref (match_operand 0 "" ""))
5545		      (pc)))]
5546  ""
5547  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5548
5549(define_insn ""
5550  [(set (pc)
5551	(if_then_else (gt (cc0)
5552			  (const_int 0))
5553		      (label_ref (match_operand 0 "" ""))
5554		      (pc)))]
5555  ""
5556  "*
5557{
5558  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5559      && ! (cc_prev_status.flags & CC_FCOMI))
5560    return AS1 (je,%l0);
5561
5562  if (cc_prev_status.flags & CC_TEST_AX)
5563    {
5564      operands[1] = gen_rtx_REG (SImode, 0);
5565      operands[2] = GEN_INT (0x4100);
5566      output_asm_insn (AS2 (testl,%2,%1), operands);
5567      return AS1 (je,%l0);
5568    }
5569  OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
5570}")
5571
5572(define_expand "bgtu"
5573  [(match_dup 1)
5574   (set (pc)
5575	(if_then_else (gtu (cc0)
5576			   (const_int 0))
5577		      (label_ref (match_operand 0 "" ""))
5578		      (pc)))]
5579  ""
5580  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5581
5582(define_insn ""
5583  [(set (pc)
5584	(if_then_else (gtu (cc0)
5585			   (const_int 0))
5586		      (label_ref (match_operand 0 "" ""))
5587		      (pc)))]
5588  ""
5589  "ja %l0")
5590
5591(define_expand "blt"
5592  [(match_dup 1)
5593   (set (pc)
5594	(if_then_else (lt (cc0)
5595			  (const_int 0))
5596		      (label_ref (match_operand 0 "" ""))
5597		      (pc)))]
5598  ""
5599  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5600
5601(define_insn ""
5602  [(set (pc)
5603	(if_then_else (lt (cc0)
5604			  (const_int 0))
5605		      (label_ref (match_operand 0 "" ""))
5606		      (pc)))]
5607  ""
5608  "*
5609{
5610  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5611      && ! (cc_prev_status.flags & CC_FCOMI))
5612    return AS1 (je,%l0);
5613
5614  if (cc_prev_status.flags & CC_TEST_AX)
5615    {
5616      operands[1] = gen_rtx_REG (SImode, 0);
5617      operands[2] = GEN_INT (0x100);
5618      output_asm_insn (AS2 (testl,%2,%1), operands);
5619      return AS1 (jne,%l0);
5620    }
5621  OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
5622}")
5623
5624(define_expand "bltu"
5625  [(match_dup 1)
5626   (set (pc)
5627	(if_then_else (ltu (cc0)
5628			   (const_int 0))
5629		      (label_ref (match_operand 0 "" ""))
5630		      (pc)))]
5631  ""
5632  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5633
5634(define_insn ""
5635  [(set (pc)
5636	(if_then_else (ltu (cc0)
5637			   (const_int 0))
5638		      (label_ref (match_operand 0 "" ""))
5639		      (pc)))]
5640  ""
5641  "jb %l0")
5642
5643(define_expand "bge"
5644  [(match_dup 1)
5645   (set (pc)
5646	(if_then_else (ge (cc0)
5647			  (const_int 0))
5648		      (label_ref (match_operand 0 "" ""))
5649		      (pc)))]
5650  ""
5651  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5652
5653(define_insn ""
5654  [(set (pc)
5655	(if_then_else (ge (cc0)
5656			  (const_int 0))
5657		      (label_ref (match_operand 0 "" ""))
5658		      (pc)))]
5659  ""
5660  "*
5661{
5662  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5663      && ! (cc_prev_status.flags & CC_FCOMI))
5664    return AS1 (je,%l0);
5665  if (cc_prev_status.flags & CC_TEST_AX)
5666    {
5667      operands[1] = gen_rtx_REG (SImode, 0);
5668      operands[2] = GEN_INT (0x100);
5669      output_asm_insn (AS2 (testl,%2,%1), operands);
5670      return AS1 (je,%l0);
5671    }
5672  OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
5673}")
5674
5675(define_expand "bgeu"
5676  [(match_dup 1)
5677   (set (pc)
5678	(if_then_else (geu (cc0)
5679			   (const_int 0))
5680		      (label_ref (match_operand 0 "" ""))
5681		      (pc)))]
5682  ""
5683  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5684
5685(define_insn ""
5686  [(set (pc)
5687	(if_then_else (geu (cc0)
5688			   (const_int 0))
5689		      (label_ref (match_operand 0 "" ""))
5690		      (pc)))]
5691  ""
5692  "jae %l0")
5693
5694(define_expand "ble"
5695  [(match_dup 1)
5696   (set (pc)
5697	(if_then_else (le (cc0)
5698			  (const_int 0))
5699		      (label_ref (match_operand 0 "" ""))
5700		      (pc)))]
5701  ""
5702  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5703
5704(define_insn ""
5705  [(set (pc)
5706	(if_then_else (le (cc0)
5707			  (const_int 0))
5708		      (label_ref (match_operand 0 "" ""))
5709		      (pc)))]
5710  ""
5711  "*
5712{
5713  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5714      && ! (cc_prev_status.flags & CC_FCOMI))
5715    return AS1 (jb,%l0);
5716  if (cc_prev_status.flags & CC_TEST_AX)
5717    {
5718      operands[1] = gen_rtx_REG (SImode, 0);
5719      operands[2] = GEN_INT (0x4100);
5720      output_asm_insn (AS2 (testl,%2,%1), operands);
5721      return AS1 (jne,%l0);
5722    }
5723
5724  OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
5725}")
5726
5727(define_expand "bleu"
5728  [(match_dup 1)
5729   (set (pc)
5730	(if_then_else (leu (cc0)
5731			   (const_int 0))
5732		      (label_ref (match_operand 0 "" ""))
5733		      (pc)))]
5734  ""
5735  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5736
5737(define_insn ""
5738  [(set (pc)
5739	(if_then_else (leu (cc0)
5740			   (const_int 0))
5741		      (label_ref (match_operand 0 "" ""))
5742		      (pc)))]
5743  ""
5744  "jbe %l0")
5745
5746;; Negated conditional jump instructions.
5747
5748(define_insn ""
5749  [(set (pc)
5750	(if_then_else (eq (cc0)
5751			  (const_int 0))
5752		      (pc)
5753		      (label_ref (match_operand 0 "" ""))))]
5754  ""
5755  "*
5756{
5757  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5758    return \"jc %l0\";
5759  else
5760  if (cc_prev_status.flags & CC_TEST_AX)
5761    {
5762      operands[1] = gen_rtx_REG (SImode, 0);
5763      operands[2] = GEN_INT (0x4000);
5764      output_asm_insn (AS2 (testl,%2,%1), operands);
5765      return AS1 (je,%l0);
5766    }
5767    return \"jne %l0\";
5768}")
5769
5770(define_insn ""
5771  [(set (pc)
5772	(if_then_else (ne (cc0)
5773			  (const_int 0))
5774		      (pc)
5775		      (label_ref (match_operand 0 "" ""))))]
5776  ""
5777  "*
5778{
5779  if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5780    return \"jnc %l0\";
5781  else
5782  if (cc_prev_status.flags & CC_TEST_AX)
5783    {
5784      operands[1] = gen_rtx_REG (SImode, 0);
5785      operands[2] = GEN_INT (0x4000);
5786      output_asm_insn (AS2 (testl,%2,%1), operands);
5787      return AS1 (jne,%l0);
5788    }
5789    return \"je %l0\";
5790}")
5791
5792(define_insn ""
5793  [(set (pc)
5794	(if_then_else (gt (cc0)
5795			  (const_int 0))
5796		      (pc)
5797		      (label_ref (match_operand 0 "" ""))))]
5798  ""
5799  "*
5800{
5801  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5802      && ! (cc_prev_status.flags & CC_FCOMI))
5803    return AS1 (jne,%l0);
5804  if (cc_prev_status.flags & CC_TEST_AX)
5805    {
5806      operands[1] = gen_rtx_REG (SImode, 0);
5807      operands[2] = GEN_INT (0x4100);
5808      output_asm_insn (AS2 (testl,%2,%1), operands);
5809      return AS1 (jne,%l0);
5810    }
5811  OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
5812}")
5813
5814(define_insn ""
5815  [(set (pc)
5816	(if_then_else (gtu (cc0)
5817			   (const_int 0))
5818		      (pc)
5819		      (label_ref (match_operand 0 "" ""))))]
5820  ""
5821  "jbe %l0")
5822
5823(define_insn ""
5824  [(set (pc)
5825	(if_then_else (lt (cc0)
5826			  (const_int 0))
5827		      (pc)
5828		      (label_ref (match_operand 0 "" ""))))]
5829  ""
5830  "*
5831{
5832  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5833      && ! (cc_prev_status.flags & CC_FCOMI))
5834    return AS1 (jne,%l0);
5835  if (cc_prev_status.flags & CC_TEST_AX)
5836    {
5837      operands[1] = gen_rtx_REG (SImode, 0);
5838      operands[2] = GEN_INT (0x100);
5839      output_asm_insn (AS2 (testl,%2,%1), operands);
5840      return AS1 (je,%l0);
5841    }
5842
5843  OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
5844}")
5845
5846(define_insn ""
5847  [(set (pc)
5848	(if_then_else (ltu (cc0)
5849			   (const_int 0))
5850		      (pc)
5851		      (label_ref (match_operand 0 "" ""))))]
5852  ""
5853  "jae %l0")
5854
5855(define_insn ""
5856  [(set (pc)
5857	(if_then_else (ge (cc0)
5858			  (const_int 0))
5859		      (pc)
5860		      (label_ref (match_operand 0 "" ""))))]
5861  ""
5862  "*
5863{
5864  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5865      && ! (cc_prev_status.flags & CC_FCOMI))
5866    return AS1 (jne,%l0);
5867  if (cc_prev_status.flags & CC_TEST_AX)
5868    {
5869      operands[1] = gen_rtx_REG (SImode, 0);
5870      operands[2] = GEN_INT (0x100);
5871      output_asm_insn (AS2 (testl,%2,%1), operands);
5872      return AS1 (jne,%l0);
5873    }
5874  OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
5875}")
5876
5877(define_insn ""
5878  [(set (pc)
5879	(if_then_else (geu (cc0)
5880			   (const_int 0))
5881		      (pc)
5882		      (label_ref (match_operand 0 "" ""))))]
5883  ""
5884  "jb %l0")
5885
5886(define_insn ""
5887  [(set (pc)
5888	(if_then_else (le (cc0)
5889			  (const_int 0))
5890		      (pc)
5891		      (label_ref (match_operand 0 "" ""))))]
5892  ""
5893  "*
5894{
5895  if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5896      && ! (cc_prev_status.flags & CC_FCOMI))
5897    return AS1 (jae,%l0);
5898
5899  if (cc_prev_status.flags & CC_TEST_AX)
5900    {
5901      operands[1] = gen_rtx_REG (SImode, 0);
5902      operands[2] = GEN_INT (0x4100);
5903      output_asm_insn (AS2 (testl,%2,%1), operands);
5904      return AS1 (je,%l0);
5905    }
5906  OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
5907}")
5908
5909(define_insn ""
5910  [(set (pc)
5911	(if_then_else (leu (cc0)
5912			   (const_int 0))
5913		      (pc)
5914		      (label_ref (match_operand 0 "" ""))))]
5915  ""
5916  "ja %l0")
5917
5918;; Unconditional and other jump instructions
5919
5920(define_insn "jump"
5921  [(set (pc)
5922	(label_ref (match_operand 0 "" "")))]
5923  ""
5924  "jmp %l0")
5925
5926(define_insn "indirect_jump"
5927  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
5928  ""
5929  "*
5930{
5931  CC_STATUS_INIT;
5932
5933  return AS1 (jmp,%*%0);
5934}")
5935
5936;; ??? could transform while(--i > 0) S; to if (--i > 0) do S; while(--i);
5937;;     if S does not change i
5938
5939(define_expand "decrement_and_branch_until_zero"
5940  [(parallel [(set (pc)
5941		   (if_then_else (ge (plus:SI (match_operand:SI 0 "general_operand" "")
5942					      (const_int -1))
5943				     (const_int 0))
5944				 (label_ref (match_operand 1 "" ""))
5945				 (pc)))
5946	      (set (match_dup 0)
5947		   (plus:SI (match_dup 0)
5948			    (const_int -1)))])]
5949  ""
5950  "")
5951
5952(define_insn ""
5953  [(set (pc)
5954	(if_then_else (match_operator 0 "arithmetic_comparison_operator"
5955				      [(plus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m")
5956						(match_operand:SI 2 "general_operand" "rmi,ri"))
5957				       (const_int 0)])
5958		      (label_ref (match_operand 3 "" ""))
5959		      (pc)))
5960   (set (match_dup 1)
5961	(plus:SI (match_dup 1)
5962		 (match_dup 2)))]
5963  ""
5964  "*
5965{
5966  CC_STATUS_INIT;
5967  if (operands[2] == constm1_rtx)
5968    output_asm_insn (AS1 (dec%L1,%1), operands);
5969
5970  else if (operands[2] == const1_rtx)
5971    output_asm_insn (AS1 (inc%L1,%1), operands);
5972
5973  else
5974    output_asm_insn (AS2 (add%L1,%2,%1), operands);
5975
5976  return AS1 (%J0,%l3);
5977}")
5978
5979(define_insn ""
5980  [(set (pc)
5981	(if_then_else (match_operator 0 "arithmetic_comparison_operator"
5982				      [(minus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m")
5983						 (match_operand:SI 2 "general_operand" "rmi,ri"))
5984				       (const_int 0)])
5985		      (label_ref (match_operand 3 "" ""))
5986		      (pc)))
5987   (set (match_dup 1)
5988	(minus:SI (match_dup 1)
5989		  (match_dup 2)))]
5990  ""
5991  "*
5992{
5993  CC_STATUS_INIT;
5994  if (operands[2] == const1_rtx)
5995    output_asm_insn (AS1 (dec%L1,%1), operands);
5996
5997  else if (operands[1] == constm1_rtx)
5998    output_asm_insn (AS1 (inc%L1,%1), operands);
5999
6000  else
6001    output_asm_insn (AS2 (sub%L1,%2,%1), operands);
6002
6003  return AS1 (%J0,%l3);
6004}")
6005
6006(define_insn ""
6007  [(set (pc)
6008	(if_then_else (ne (match_operand:SI 0 "general_operand" "+g")
6009			  (const_int 0))
6010		      (label_ref (match_operand 1 "" ""))
6011		      (pc)))
6012   (set (match_dup 0)
6013	(plus:SI (match_dup 0)
6014		 (const_int -1)))]
6015  ""
6016  "*
6017{
6018  CC_STATUS_INIT;
6019  operands[2] = const1_rtx;
6020  output_asm_insn (AS2 (sub%L0,%2,%0), operands);
6021  return \"jnc %l1\";
6022}")
6023
6024(define_insn ""
6025  [(set (pc)
6026	(if_then_else (eq (match_operand:SI 0 "general_operand" "+g")
6027			  (const_int 0))
6028		      (label_ref (match_operand 1 "" ""))
6029		      (pc)))
6030   (set (match_dup 0)
6031	(plus:SI (match_dup 0)
6032		 (const_int -1)))]
6033  ""
6034  "*
6035{
6036  CC_STATUS_INIT;
6037  operands[2] = const1_rtx;
6038  output_asm_insn (AS2 (sub%L0,%2,%0), operands);
6039  return \"jc %l1\";
6040}")
6041
6042(define_insn ""
6043  [(set (pc)
6044	(if_then_else (ne (match_operand:SI 0 "general_operand" "+g")
6045			  (const_int 1))
6046		      (label_ref (match_operand 1 "" ""))
6047		      (pc)))
6048   (set (match_dup 0)
6049	(plus:SI (match_dup 0)
6050		 (const_int -1)))]
6051  ""
6052  "*
6053{
6054  CC_STATUS_INIT;
6055  output_asm_insn (AS1 (dec%L0,%0), operands);
6056  return \"jnz %l1\";
6057}")
6058
6059(define_insn ""
6060  [(set (pc)
6061	(if_then_else (eq (match_operand:SI 0 "general_operand" "+g")
6062			  (const_int 1))
6063		      (label_ref (match_operand 1 "" ""))
6064		      (pc)))
6065   (set (match_dup 0)
6066	(plus:SI (match_dup 0)
6067		 (const_int -1)))]
6068  ""
6069  "*
6070{
6071  CC_STATUS_INIT;
6072  output_asm_insn (AS1 (dec%L0,%0), operands);
6073  return \"jz %l1\";
6074}")
6075
6076(define_insn ""
6077  [(set (pc)
6078	(if_then_else (ne (match_operand:SI 0 "general_operand" "+g")
6079			  (const_int -1))
6080		      (label_ref (match_operand 1 "" ""))
6081		      (pc)))
6082   (set (match_dup 0)
6083	(plus:SI (match_dup 0)
6084		 (const_int 1)))]
6085  ""
6086  "*
6087{
6088  CC_STATUS_INIT;
6089  output_asm_insn (AS1 (inc%L0,%0), operands);
6090  return \"jnz %l1\";
6091}")
6092
6093(define_insn ""
6094  [(set (pc)
6095	(if_then_else (eq (match_operand:SI 0 "general_operand" "+g")
6096			  (const_int -1))
6097		      (label_ref (match_operand 1 "" ""))
6098		      (pc)))
6099   (set (match_dup 0)
6100	(plus:SI (match_dup 0)
6101		 (const_int 1)))]
6102  ""
6103  "*
6104{
6105  CC_STATUS_INIT;
6106  output_asm_insn (AS1 (inc%L0,%0), operands);
6107  return \"jz %l1\";
6108}")
6109
6110;; Implement switch statements when generating PIC code.  Switches are
6111;; implemented by `tablejump' when not using -fpic.
6112
6113;; Emit code here to do the range checking and make the index zero based.
6114
6115(define_expand "casesi"
6116  [(set (match_dup 5)
6117	(match_operand:SI 0 "general_operand" ""))
6118   (set (match_dup 6)
6119	(minus:SI (match_dup 5)
6120		  (match_operand:SI 1 "general_operand" "")))
6121   (set (cc0)
6122	(compare:CC (match_dup 6)
6123		    (match_operand:SI 2 "general_operand" "")))
6124   (set (pc)
6125	(if_then_else (gtu (cc0)
6126			   (const_int 0))
6127		      (label_ref (match_operand 4 "" ""))
6128		      (pc)))
6129   (parallel
6130    [(set (pc)
6131	  (minus:SI (reg:SI 3)
6132		    (mem:SI (plus:SI (mult:SI (match_dup 6)
6133					      (const_int 4))
6134				     (label_ref (match_operand 3 "" ""))))))
6135     (clobber (match_scratch:SI 7 ""))])]
6136  "flag_pic"
6137  "
6138{
6139  operands[5] = gen_reg_rtx (SImode);
6140  operands[6] = gen_reg_rtx (SImode);
6141  current_function_uses_pic_offset_table = 1;
6142}")
6143
6144;; Implement a casesi insn.
6145
6146;; Each entry in the "addr_diff_vec" looks like this as the result of the
6147;; two rules below:
6148;; 
6149;; 	.long _GLOBAL_OFFSET_TABLE_+[.-.L2]
6150;; 
6151;; 1. An expression involving an external reference may only use the
6152;;    addition operator, and only with an assembly-time constant.
6153;;    The example above satisfies this because ".-.L2" is a constant.
6154;; 
6155;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is
6156;;    given the value of "GOT - .", where GOT is the actual address of
6157;;    the Global Offset Table.  Therefore, the .long above actually
6158;;    stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2".  The
6159;;    expression "GOT - .L2" by itself would generate an error from as(1).
6160;; 
6161;; The pattern below emits code that looks like this:
6162;; 
6163;; 	movl %ebx,reg
6164;; 	subl TABLE@GOTOFF(%ebx,index,4),reg
6165;; 	jmp reg
6166;; 
6167;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since
6168;; the addr_diff_vec is known to be part of this module.
6169;; 
6170;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which
6171;; evaluates to just ".L2".
6172
6173(define_insn ""
6174  [(set (pc)
6175	(minus:SI (reg:SI 3)
6176		  (mem:SI (plus:SI
6177			   (mult:SI (match_operand:SI 0 "register_operand" "r")
6178				    (const_int 4))
6179			   (label_ref (match_operand 1 "" ""))))))
6180   (clobber (match_scratch:SI 2 "=&r"))]
6181  ""
6182  "*
6183{
6184  rtx xops[4];
6185
6186  xops[0] = operands[0];
6187  xops[1] = operands[1];
6188  xops[2] = operands[2];
6189  xops[3] = pic_offset_table_rtx;
6190
6191  output_asm_insn (AS2 (mov%L2,%3,%2), xops);
6192  output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops);
6193  output_asm_insn (AS1 (jmp,%*%2), xops);
6194  ASM_OUTPUT_ALIGN (asm_out_file, i386_align_jumps);
6195  RET;
6196}")
6197
6198(define_insn "tablejump"
6199  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
6200   (use (label_ref (match_operand 1 "" "")))]
6201  ""
6202  "*
6203{
6204  CC_STATUS_INIT;
6205
6206  return AS1 (jmp,%*%0);
6207}")
6208
6209;; Call insns.
6210
6211;; If generating PIC code, the predicate indirect_operand will fail
6212;; for operands[0] containing symbolic references on all of the named
6213;; call* patterns.  Each named pattern is followed by an unnamed pattern
6214;; that matches any call to a symbolic CONST (ie, a symbol_ref).  The
6215;; unnamed patterns are only used while generating PIC code, because
6216;; otherwise the named patterns match.
6217
6218;; Call subroutine returning no value.
6219
6220(define_expand "call_pop"
6221  [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
6222		    (match_operand:SI 1 "general_operand" ""))
6223	      (set (reg:SI 7)
6224		   (plus:SI (reg:SI 7)
6225			    (match_operand:SI 3 "immediate_operand" "")))])]
6226  ""
6227  "
6228{
6229  rtx addr;
6230
6231  if (flag_pic)
6232    current_function_uses_pic_offset_table = 1;
6233
6234  /* With half-pic, force the address into a register.  */
6235  addr = XEXP (operands[0], 0);
6236  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
6237    XEXP (operands[0], 0) = force_reg (Pmode, addr);
6238
6239  if (! expander_call_insn_operand (operands[0], QImode))
6240    operands[0]
6241      = change_address (operands[0], VOIDmode,
6242			copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
6243}")
6244
6245(define_insn ""
6246  [(call (match_operand:QI 0 "call_insn_operand" "m")
6247	 (match_operand:SI 1 "general_operand" "g"))
6248   (set (reg:SI 7) (plus:SI (reg:SI 7)
6249			    (match_operand:SI 3 "immediate_operand" "i")))]
6250  ""
6251  "*
6252{
6253  if (GET_CODE (operands[0]) == MEM
6254      && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
6255    {
6256      operands[0] = XEXP (operands[0], 0);
6257      return AS1 (call,%*%0);
6258    }
6259  else
6260    return AS1 (call,%P0);
6261}")
6262
6263(define_insn ""
6264  [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
6265	 (match_operand:SI 1 "general_operand" "g"))
6266   (set (reg:SI 7) (plus:SI (reg:SI 7)
6267			    (match_operand:SI 3 "immediate_operand" "i")))]
6268  "!HALF_PIC_P ()"
6269  "call %P0")
6270
6271(define_expand "call"
6272  [(call (match_operand:QI 0 "indirect_operand" "")
6273	 (match_operand:SI 1 "general_operand" ""))]
6274  ;; Operand 1 not used on the i386.
6275  ""
6276  "
6277{
6278  rtx addr;
6279
6280  if (flag_pic)
6281    current_function_uses_pic_offset_table = 1;
6282
6283  /* With half-pic, force the address into a register.  */
6284  addr = XEXP (operands[0], 0);
6285  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
6286    XEXP (operands[0], 0) = force_reg (Pmode, addr);
6287
6288  if (! expander_call_insn_operand (operands[0], QImode))
6289    operands[0]
6290      = change_address (operands[0], VOIDmode,
6291			copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
6292}")
6293
6294(define_insn ""
6295  [(call (match_operand:QI 0 "call_insn_operand" "m")
6296	 (match_operand:SI 1 "general_operand" "g"))]
6297  ;; Operand 1 not used on the i386.
6298  ""
6299  "*
6300{
6301  if (GET_CODE (operands[0]) == MEM
6302      && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
6303    {
6304      operands[0] = XEXP (operands[0], 0);
6305      return AS1 (call,%*%0);
6306    }
6307  else
6308    return AS1 (call,%P0);
6309}")
6310
6311(define_insn ""
6312  [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
6313	 (match_operand:SI 1 "general_operand" "g"))]
6314  ;; Operand 1 not used on the i386.
6315  "!HALF_PIC_P ()"
6316  "call %P0")
6317
6318;; Call subroutine, returning value in operand 0
6319;; (which must be a hard register).
6320
6321(define_expand "call_value_pop"
6322  [(parallel [(set (match_operand 0 "" "")
6323		   (call (match_operand:QI 1 "indirect_operand" "")
6324			 (match_operand:SI 2 "general_operand" "")))
6325	      (set (reg:SI 7)
6326		   (plus:SI (reg:SI 7)
6327			    (match_operand:SI 4 "immediate_operand" "")))])]
6328  ""
6329  "
6330{
6331  rtx addr;
6332
6333  if (flag_pic)
6334    current_function_uses_pic_offset_table = 1;
6335
6336  /* With half-pic, force the address into a register.  */
6337  addr = XEXP (operands[1], 0);
6338  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
6339    XEXP (operands[1], 0) = force_reg (Pmode, addr);
6340
6341  if (! expander_call_insn_operand (operands[1], QImode))
6342    operands[1]
6343      = change_address (operands[1], VOIDmode,
6344			copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
6345}")
6346
6347(define_insn ""
6348  [(set (match_operand 0 "" "=rf")
6349	(call (match_operand:QI 1 "call_insn_operand" "m")
6350	      (match_operand:SI 2 "general_operand" "g")))
6351   (set (reg:SI 7) (plus:SI (reg:SI 7)
6352			    (match_operand:SI 4 "immediate_operand" "i")))]
6353  ""
6354  "*
6355{
6356  if (GET_CODE (operands[1]) == MEM
6357      && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
6358    {
6359      operands[1] = XEXP (operands[1], 0);
6360      output_asm_insn (AS1 (call,%*%1), operands);
6361    }
6362  else
6363    output_asm_insn (AS1 (call,%P1), operands);
6364
6365  RET;
6366}")
6367
6368(define_insn ""
6369  [(set (match_operand 0 "" "=rf")
6370	(call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
6371	      (match_operand:SI 2 "general_operand" "g")))
6372   (set (reg:SI 7) (plus:SI (reg:SI 7)
6373			    (match_operand:SI 4 "immediate_operand" "i")))]
6374  "!HALF_PIC_P ()"
6375  "call %P1")
6376
6377(define_expand "call_value"
6378  [(set (match_operand 0 "" "")
6379	(call (match_operand:QI 1 "indirect_operand" "")
6380	      (match_operand:SI 2 "general_operand" "")))]
6381  ;; Operand 2 not used on the i386.
6382  ""
6383  "
6384{
6385  rtx addr;
6386
6387  if (flag_pic)
6388    current_function_uses_pic_offset_table = 1;
6389
6390  /* With half-pic, force the address into a register.  */
6391  addr = XEXP (operands[1], 0);
6392  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
6393    XEXP (operands[1], 0) = force_reg (Pmode, addr);
6394
6395  if (! expander_call_insn_operand (operands[1], QImode))
6396    operands[1]
6397      = change_address (operands[1], VOIDmode,
6398			copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
6399}")
6400
6401(define_insn ""
6402  [(set (match_operand 0 "" "=rf")
6403	(call (match_operand:QI 1 "call_insn_operand" "m")
6404	      (match_operand:SI 2 "general_operand" "g")))]
6405  ;; Operand 2 not used on the i386.
6406  ""
6407  "*
6408{
6409  if (GET_CODE (operands[1]) == MEM
6410      && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
6411    {
6412      operands[1] = XEXP (operands[1], 0);
6413      output_asm_insn (AS1 (call,%*%1), operands);
6414    }
6415  else
6416    output_asm_insn (AS1 (call,%P1), operands);
6417
6418  RET;
6419}")
6420
6421(define_insn ""
6422  [(set (match_operand 0 "" "=rf")
6423	(call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
6424	      (match_operand:SI 2 "general_operand" "g")))]
6425  ;; Operand 2 not used on the i386.
6426  "!HALF_PIC_P ()"
6427  "call %P1")
6428
6429;; Call subroutine returning any type.
6430
6431(define_expand "untyped_call"
6432  [(parallel [(call (match_operand 0 "" "")
6433		    (const_int 0))
6434	      (match_operand 1 "" "")
6435	      (match_operand 2 "" "")])]
6436  ""
6437  "
6438{
6439  int i;
6440
6441  /* In order to give reg-stack an easier job in validating two
6442     coprocessor registers as containing a possible return value,
6443     simply pretend the untyped call returns a complex long double
6444     value.  */
6445
6446  emit_call_insn (TARGET_80387
6447                  ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG),
6448				    operands[0], const0_rtx)
6449                  : gen_call (operands[0], const0_rtx));
6450
6451  for (i = 0; i < XVECLEN (operands[2], 0); i++)
6452    {
6453      rtx set = XVECEXP (operands[2], 0, i);
6454      emit_move_insn (SET_DEST (set), SET_SRC (set));
6455    }
6456
6457  /* The optimizer does not know that the call sets the function value
6458     registers we stored in the result block.  We avoid problems by
6459     claiming that all hard registers are used and clobbered at this
6460     point.  */
6461  emit_insn (gen_blockage ());
6462
6463  DONE;
6464}")
6465
6466;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6467;; all of memory.  This blocks insns from being moved across this point.
6468
6469(define_insn "blockage"
6470  [(unspec_volatile [(const_int 0)] 0)]
6471  ""
6472  "")
6473
6474;; Insn emitted into the body of a function to return from a function.
6475;; This is only done if the function's epilogue is known to be simple.
6476;; See comments for simple_386_epilogue in i386.c.
6477
6478(define_expand "return"
6479  [(return)]
6480  "ix86_can_use_return_insn_p ()"
6481  "")
6482
6483(define_insn "return_internal"
6484  [(return)]
6485  "reload_completed"
6486  "ret")
6487
6488(define_insn "return_pop_internal"
6489  [(return)
6490   (use (match_operand:SI 0 "const_int_operand" ""))]
6491  "reload_completed"
6492  "ret %0")
6493
6494(define_insn "nop"
6495  [(const_int 0)]
6496  ""
6497  "nop")
6498
6499(define_expand "prologue"
6500  [(const_int 1)]
6501  ""
6502  "
6503{
6504  ix86_expand_prologue ();
6505  DONE;
6506}")
6507
6508;; The use of UNSPEC here is currently not necessary - a simple SET of ebp
6509;; to itself would be enough. But this way we are safe even if some optimizer
6510;; becomes too clever in the future.
6511(define_insn "prologue_set_stack_ptr"
6512  [(set (reg:SI 7)
6513	(minus:SI (reg:SI 7) (match_operand:SI 0 "immediate_operand" "i")))
6514   (set (reg:SI 6) (unspec:SI [(reg:SI 6)] 4))]
6515  ""
6516  "*
6517{
6518  rtx xops [2];
6519
6520  xops[0] = operands[0];
6521  xops[1] = stack_pointer_rtx;
6522  output_asm_insn (AS2 (sub%L1,%0,%1), xops);
6523  RET;
6524}")
6525
6526(define_insn "prologue_set_got"
6527  [(set (match_operand:SI 0 "" "")
6528	(unspec_volatile
6529	 [(plus:SI (match_dup 0)
6530		   (plus:SI (match_operand:SI 1 "symbolic_operand" "")
6531			    (minus:SI (pc) (match_operand 2 "" ""))))] 1))]
6532  ""
6533  "*
6534{
6535  char buffer[64];
6536
6537  if (TARGET_DEEP_BRANCH_PREDICTION) 
6538    {
6539      sprintf (buffer, \"addl %s,%%0\", XSTR (operands[1], 0));
6540      output_asm_insn (buffer, operands);
6541    }
6542  else  
6543    {
6544      sprintf (buffer, \"addl %s+[.-%%X2],%%0\", XSTR (operands[1], 0));
6545      output_asm_insn (buffer, operands);
6546    }    
6547  RET;
6548}")
6549
6550(define_insn "prologue_get_pc"
6551  [(set (match_operand:SI 0 "" "")
6552    (unspec_volatile [(plus:SI (pc) (match_operand 1 "" ""))] 2))]
6553  ""
6554  "*
6555{
6556  char buffer[64];
6557
6558  output_asm_insn (AS1 (call,%X1), operands);
6559  if (! TARGET_DEEP_BRANCH_PREDICTION) 
6560    {
6561      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (operands[1]));
6562    }    
6563  RET;
6564}")
6565
6566(define_insn "prologue_get_pc_and_set_got"
6567  [(unspec_volatile [(match_operand:SI 0 "" "")] 3)]
6568  ""
6569  "*
6570{
6571  operands[1] = gen_label_rtx ();
6572  output_asm_insn (AS1 (call,%X1), operands);
6573  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
6574			     CODE_LABEL_NUMBER (operands[1]));
6575  output_asm_insn (AS1 (pop%L0,%0), operands);
6576  output_asm_insn (\"addl $_GLOBAL_OFFSET_TABLE_+[.-%X1],%0\", operands);
6577  RET;
6578}")
6579
6580(define_expand "epilogue"
6581  [(const_int 1)]
6582  ""
6583  "
6584{
6585  ix86_expand_epilogue ();
6586  DONE;
6587}")
6588
6589(define_insn "epilogue_set_stack_ptr"
6590  [(set (reg:SI 7) (reg:SI 6))
6591	(clobber (reg:SI 6))]
6592  ""
6593  "*
6594{
6595  rtx xops [2];
6596
6597    xops[0] = frame_pointer_rtx;
6598    xops[1] = stack_pointer_rtx;
6599    output_asm_insn (AS2 (mov%L0,%0,%1), xops);
6600    RET;
6601}")
6602
6603(define_insn "leave"
6604  [(const_int 2)
6605      (clobber (reg:SI 6))
6606      (clobber (reg:SI 7))]
6607  ""
6608  "leave")
6609
6610(define_insn "pop"
6611  [(set (match_operand:SI 0 "register_operand" "r")
6612	(mem:SI (reg:SI 7)))
6613   (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))]
6614  ""
6615  "*
6616{
6617    output_asm_insn (AS1 (pop%L0,%P0), operands);
6618    RET;
6619}")
6620
6621(define_expand "movstrsi"
6622  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
6623		   (match_operand:BLK 1 "memory_operand" ""))
6624	      (use (match_operand:SI 2 "const_int_operand" ""))
6625	      (use (match_operand:SI 3 "const_int_operand" ""))
6626	      (clobber (match_scratch:SI 4 ""))
6627	      (clobber (match_dup 5))
6628	      (clobber (match_dup 6))])]
6629  ""
6630  "
6631{
6632  rtx addr0, addr1;
6633
6634  if (GET_CODE (operands[2]) != CONST_INT)
6635    FAIL;
6636
6637  addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
6638  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
6639
6640  operands[5] = addr0;
6641  operands[6] = addr1;
6642
6643  operands[0] = change_address (operands[0], VOIDmode, addr0);
6644  operands[1] = change_address (operands[1], VOIDmode, addr1);
6645}")
6646
6647;; It might seem that operands 0 & 1 could use predicate register_operand.
6648;; But strength reduction might offset the MEM expression.  So we let
6649;; reload put the address into %edi & %esi.
6650
6651(define_insn ""
6652  [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
6653	(mem:BLK (match_operand:SI 1 "address_operand" "S")))
6654   (use (match_operand:SI 2 "const_int_operand" "n"))
6655   (use (match_operand:SI 3 "immediate_operand" "i"))
6656   (clobber (match_scratch:SI 4 "=&c"))
6657   (clobber (match_dup 0))
6658   (clobber (match_dup 1))]
6659  ""
6660  "*
6661{
6662  rtx xops[2];
6663
6664  output_asm_insn (\"cld\", operands);
6665  if (GET_CODE (operands[2]) == CONST_INT)
6666    {
6667      if (INTVAL (operands[2]) & ~0x03)
6668	{
6669	  xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff);
6670	  xops[1] = operands[4];
6671
6672	  output_asm_insn (AS2 (mov%L1,%0,%1), xops);
6673#ifdef INTEL_SYNTAX
6674	  output_asm_insn (\"rep movsd\", xops);
6675#else
6676	  output_asm_insn (\"rep\;movsl\", xops);
6677#endif
6678	}
6679      if (INTVAL (operands[2]) & 0x02)
6680	output_asm_insn (\"movsw\", operands);
6681      if (INTVAL (operands[2]) & 0x01)
6682	output_asm_insn (\"movsb\", operands);
6683    }
6684  else
6685    abort ();
6686  RET;
6687}")
6688
6689(define_expand "clrstrsi"
6690  [(set (match_dup 3) (const_int 0))
6691   (parallel [(set (match_operand:BLK 0 "memory_operand" "")
6692		   (const_int 0))
6693	      (use (match_operand:SI 1 "const_int_operand" ""))
6694	      (use (match_operand:SI 2 "const_int_operand" ""))
6695	      (use (match_dup 3))
6696	      (clobber (match_scratch:SI 4 ""))
6697	      (clobber (match_dup 5))])]
6698  ""
6699  "
6700{
6701  rtx addr0, addr1;
6702
6703  if (GET_CODE (operands[1]) != CONST_INT)
6704    FAIL;
6705
6706  addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
6707
6708  operands[3] = gen_reg_rtx (SImode);
6709  operands[5] = addr0;
6710
6711  operands[0] = gen_rtx_MEM (BLKmode, addr0);
6712}")
6713
6714;; It might seem that operand 0 could use predicate register_operand.
6715;; But strength reduction might offset the MEM expression.  So we let
6716;; reload put the address into %edi.
6717
6718(define_insn ""
6719  [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
6720	(const_int 0))
6721   (use (match_operand:SI 1 "const_int_operand" "n"))
6722   (use (match_operand:SI 2 "immediate_operand" "i"))
6723   (use (match_operand:SI 3 "register_operand" "a"))
6724   (clobber (match_scratch:SI 4 "=&c"))
6725   (clobber (match_dup 0))]
6726  ""
6727  "*
6728{
6729  rtx xops[2];
6730
6731  output_asm_insn (\"cld\", operands);
6732  if (GET_CODE (operands[1]) == CONST_INT)
6733    {
6734      if (INTVAL (operands[1]) & ~0x03)
6735	{
6736	  xops[0] = GEN_INT ((INTVAL (operands[1]) >> 2) & 0x3fffffff);
6737	  xops[1] = operands[4];
6738
6739	  output_asm_insn (AS2 (mov%L1,%0,%1), xops);
6740#ifdef INTEL_SYNTAX
6741	  output_asm_insn (\"rep stosd\", xops);
6742#else
6743	  output_asm_insn (\"rep\;stosl\", xops);
6744#endif
6745	}
6746      if (INTVAL (operands[1]) & 0x02)
6747	output_asm_insn (\"stosw\", operands);
6748      if (INTVAL (operands[1]) & 0x01)
6749	output_asm_insn (\"stosb\", operands);
6750    }
6751  else
6752    abort ();
6753  RET;
6754}")
6755
6756(define_expand "cmpstrsi"
6757  [(parallel [(set (match_operand:SI 0 "general_operand" "")
6758		   (compare:SI (match_operand:BLK 1 "general_operand" "")
6759			       (match_operand:BLK 2 "general_operand" "")))
6760	      (use (match_operand:SI 3 "general_operand" ""))
6761	      (use (match_operand:SI 4 "immediate_operand" ""))
6762	      (clobber (match_dup 5))
6763	      (clobber (match_dup 6))
6764	      (clobber (match_dup 3))])]
6765  ""
6766  "
6767{
6768  rtx addr1, addr2;
6769
6770  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
6771  addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
6772  operands[3] = copy_to_mode_reg (SImode, operands[3]);
6773
6774  operands[5] = addr1;
6775  operands[6] = addr2;
6776
6777  operands[1] = gen_rtx_MEM (BLKmode, addr1);
6778  operands[2] = gen_rtx_MEM (BLKmode, addr2);
6779
6780}")
6781
6782;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
6783;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
6784
6785;; It might seem that operands 0 & 1 could use predicate register_operand.
6786;; But strength reduction might offset the MEM expression.  So we let
6787;; reload put the address into %edi & %esi.
6788
6789;; ??? Most comparisons have a constant length, and it's therefore
6790;; possible to know that the length is non-zero, and to avoid the extra
6791;; code to handle zero-length compares.
6792
6793(define_insn ""
6794  [(set (match_operand:SI 0 "register_operand" "=&r")
6795	(compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S"))
6796		    (mem:BLK (match_operand:SI 2 "address_operand" "D"))))
6797   (use (match_operand:SI 3 "register_operand" "c"))
6798   (use (match_operand:SI 4 "immediate_operand" "i"))
6799   (clobber (match_dup 1))
6800   (clobber (match_dup 2))
6801   (clobber (match_dup 3))]
6802  ""
6803  "*
6804{
6805  rtx xops[2], label;
6806
6807  label = gen_label_rtx ();
6808
6809  output_asm_insn (\"cld\", operands);
6810  output_asm_insn (AS2 (xor%L0,%0,%0), operands);
6811  output_asm_insn (\"repz\;cmps%B2\", operands);
6812  output_asm_insn (\"je %l0\", &label);
6813
6814  xops[0] = operands[0];
6815  xops[1] = const1_rtx;
6816  output_asm_insn (AS2 (sbb%L0,%0,%0), xops);
6817  if (QI_REG_P (xops[0]))
6818     output_asm_insn (AS2 (or%B0,%1,%b0), xops);
6819  else
6820     output_asm_insn (AS2 (or%L0,%1,%0), xops);
6821	
6822  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label));
6823  RET;
6824}")
6825
6826(define_insn ""
6827  [(set (cc0)
6828	(compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
6829		    (mem:BLK (match_operand:SI 1 "address_operand" "D"))))
6830   (use (match_operand:SI 2 "register_operand" "c"))
6831   (use (match_operand:SI 3 "immediate_operand" "i"))
6832   (clobber (match_dup 0))
6833   (clobber (match_dup 1))
6834   (clobber (match_dup 2))]
6835  ""
6836  "*
6837{
6838  rtx xops[2];
6839
6840  cc_status.flags |= CC_NOT_SIGNED;
6841
6842  xops[0] = gen_rtx_REG (QImode, 0);
6843  xops[1] = CONST0_RTX (QImode);
6844
6845  output_asm_insn (\"cld\", operands);
6846  output_asm_insn (AS2 (test%B0,%1,%0), xops);
6847  return \"repz\;cmps%B2\";
6848}")
6849
6850
6851;; Note, you cannot optimize away the branch following the bsfl by assuming
6852;; that the destination is not modified if the input is 0, since not all
6853;; x86 implementations do this.
6854
6855(define_expand "ffssi2"
6856  [(set (match_operand:SI 0 "general_operand" "") 
6857	(ffs:SI (match_operand:SI 1 "general_operand" "")))]
6858  ""
6859  "
6860{
6861  rtx label = gen_label_rtx (), temp = gen_reg_rtx (SImode);
6862
6863  emit_insn (gen_ffssi_1 (temp, operands[1]));
6864  emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, SImode, 0, 0);
6865  emit_jump_insn (gen_bne (label));
6866  emit_move_insn (temp, constm1_rtx);
6867  emit_label (label);
6868  temp = expand_binop (SImode, add_optab, temp, const1_rtx,
6869		       operands[0], 0, OPTAB_WIDEN);
6870
6871  if (temp != operands[0])
6872    emit_move_insn (operands[0], temp);
6873  DONE;  
6874}")
6875
6876(define_insn "ffssi_1"
6877  [(set (match_operand:SI 0 "register_operand" "=r")
6878	(unspec:SI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))]
6879  ""
6880  "* return AS2 (bsf%L0,%1,%0);")
6881
6882(define_expand "ffshi2"
6883  [(set (match_operand:SI 0 "general_operand" "") 
6884	(ffs:HI (match_operand:HI 1 "general_operand" "")))]
6885  ""
6886  "
6887{
6888  rtx label = gen_label_rtx (), temp = gen_reg_rtx (HImode);
6889
6890  emit_insn (gen_ffshi_1 (temp, operands[1]));
6891  emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, HImode, 0, 0);
6892  emit_jump_insn (gen_bne (label));
6893  emit_move_insn (temp, constm1_rtx);
6894  emit_label (label);
6895  temp = expand_binop (HImode, add_optab, temp, const1_rtx,
6896		       operands[0], 0, OPTAB_WIDEN);
6897
6898  if (temp != operands[0])
6899    emit_move_insn (operands[0], temp);
6900  DONE;  
6901}")
6902
6903(define_insn "ffshi_1"
6904  [(set (match_operand:HI 0 "register_operand" "=r")
6905	(unspec:HI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))]
6906  ""
6907  "* return AS2 (bsf%W0,%1,%0);")
6908
6909;; These patterns match the binary 387 instructions for addM3, subM3,
6910;; mulM3 and divM3.  There are three patterns for each of DFmode and
6911;; SFmode.  The first is the normal insn, the second the same insn but
6912;; with one operand a conversion, and the third the same insn but with
6913;; the other operand a conversion.  The conversion may be SFmode or
6914;; SImode if the target mode DFmode, but only SImode if the target mode
6915;; is SFmode.
6916
6917(define_insn ""
6918  [(set (match_operand:DF 0 "register_operand" "=f,f")
6919	(match_operator:DF 3 "binary_387_op"
6920			[(match_operand:DF 1 "nonimmediate_operand" "0,fm")
6921			 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
6922  "TARGET_80387"
6923  "* return output_387_binary_op (insn, operands);"
6924  [(set (attr "type") 
6925        (cond [(match_operand:DF 3 "is_mul" "") 
6926                 (const_string "fpmul")
6927               (match_operand:DF 3 "is_div" "") 
6928                 (const_string "fpdiv")
6929              ]
6930               (const_string "fpop")
6931        )
6932  )])
6933
6934(define_insn ""
6935  [(set (match_operand:DF 0 "register_operand" "=f")
6936	(match_operator:DF 3 "binary_387_op"
6937	   [(float:DF (match_operand:SI 1 "nonimmediate_operand" "rm"))
6938	    (match_operand:DF 2 "register_operand" "0")]))]
6939  "TARGET_80387"
6940  "* return output_387_binary_op (insn, operands);"
6941  [(set (attr "type") 
6942        (cond [(match_operand:DF 3 "is_mul" "") 
6943                 (const_string "fpmul")
6944               (match_operand:DF 3 "is_div" "") 
6945                 (const_string "fpdiv")
6946              ]
6947               (const_string "fpop")
6948        )
6949  )])
6950
6951(define_insn ""
6952  [(set (match_operand:XF 0 "register_operand" "=f,f")
6953	(match_operator:XF 3 "binary_387_op"
6954			[(match_operand:XF 1 "register_operand" "0,f")
6955			 (match_operand:XF 2 "register_operand" "f,0")]))]
6956  "TARGET_80387"
6957  "* return output_387_binary_op (insn, operands);"
6958  [(set (attr "type") 
6959        (cond [(match_operand:DF 3 "is_mul" "") 
6960                 (const_string "fpmul")
6961               (match_operand:DF 3 "is_div" "") 
6962                 (const_string "fpdiv")
6963              ]
6964               (const_string "fpop")
6965        )
6966  )])
6967
6968(define_insn ""
6969  [(set (match_operand:XF 0 "register_operand" "=f")
6970	(match_operator:XF 3 "binary_387_op"
6971	   [(float:XF (match_operand:SI 1 "nonimmediate_operand" "rm"))
6972	    (match_operand:XF 2 "register_operand" "0")]))]
6973  "TARGET_80387"
6974  "* return output_387_binary_op (insn, operands);"
6975  [(set (attr "type") 
6976        (cond [(match_operand:DF 3 "is_mul" "") 
6977                 (const_string "fpmul")
6978               (match_operand:DF 3 "is_div" "") 
6979                 (const_string "fpdiv")
6980              ]
6981               (const_string "fpop")
6982        )
6983  )])
6984
6985(define_insn ""
6986  [(set (match_operand:XF 0 "register_operand" "=f,f")
6987	(match_operator:XF 3 "binary_387_op"
6988	   [(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
6989	    (match_operand:XF 2 "register_operand" "0,f")]))]
6990  "TARGET_80387"
6991  "* return output_387_binary_op (insn, operands);"
6992  [(set (attr "type") 
6993        (cond [(match_operand:DF 3 "is_mul" "") 
6994                 (const_string "fpmul")
6995               (match_operand:DF 3 "is_div" "") 
6996                 (const_string "fpdiv")
6997              ]
6998               (const_string "fpop")
6999        )
7000  )])
7001
7002(define_insn ""
7003  [(set (match_operand:XF 0 "register_operand" "=f")
7004	(match_operator:XF 3 "binary_387_op"
7005	  [(match_operand:XF 1 "register_operand" "0")
7006	   (float:XF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
7007  "TARGET_80387"
7008  "* return output_387_binary_op (insn, operands);"
7009  [(set (attr "type") 
7010        (cond [(match_operand:DF 3 "is_mul" "") 
7011                 (const_string "fpmul")
7012               (match_operand:DF 3 "is_div" "") 
7013                 (const_string "fpdiv")
7014              ]
7015               (const_string "fpop")
7016        )
7017  )])
7018
7019(define_insn ""
7020  [(set (match_operand:XF 0 "register_operand" "=f,f")
7021	(match_operator:XF 3 "binary_387_op"
7022	  [(match_operand:XF 1 "register_operand" "0,f")
7023	   (float_extend:XF
7024	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
7025  "TARGET_80387"
7026  "* return output_387_binary_op (insn, operands);"
7027  [(set (attr "type") 
7028        (cond [(match_operand:DF 3 "is_mul" "") 
7029                 (const_string "fpmul")
7030               (match_operand:DF 3 "is_div" "") 
7031                 (const_string "fpdiv")
7032              ]
7033               (const_string "fpop")
7034        )
7035  )])
7036
7037(define_insn ""
7038  [(set (match_operand:DF 0 "register_operand" "=f,f")
7039	(match_operator:DF 3 "binary_387_op"
7040	   [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
7041	    (match_operand:DF 2 "register_operand" "0,f")]))]
7042  "TARGET_80387"
7043  "* return output_387_binary_op (insn, operands);"
7044  [(set (attr "type") 
7045        (cond [(match_operand:DF 3 "is_mul" "") 
7046                 (const_string "fpmul")
7047               (match_operand:DF 3 "is_div" "") 
7048                 (const_string "fpdiv")
7049              ]
7050               (const_string "fpop")
7051        )
7052  )])
7053
7054(define_insn ""
7055  [(set (match_operand:DF 0 "register_operand" "=f")
7056	(match_operator:DF 3 "binary_387_op"
7057	  [(match_operand:DF 1 "register_operand" "0")
7058	   (float:DF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
7059  "TARGET_80387"
7060  "* return output_387_binary_op (insn, operands);"
7061  [(set (attr "type") 
7062        (cond [(match_operand:DF 3 "is_mul" "") 
7063                 (const_string "fpmul")
7064               (match_operand:DF 3 "is_div" "") 
7065                 (const_string "fpdiv")
7066              ]
7067               (const_string "fpop")
7068        )
7069  )])
7070
7071(define_insn ""
7072  [(set (match_operand:DF 0 "register_operand" "=f,f")
7073	(match_operator:DF 3 "binary_387_op"
7074	  [(match_operand:DF 1 "register_operand" "0,f")
7075	   (float_extend:DF
7076	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
7077  "TARGET_80387"
7078  "* return output_387_binary_op (insn, operands);"
7079  [(set (attr "type") 
7080        (cond [(match_operand:DF 3 "is_mul" "") 
7081                 (const_string "fpmul")
7082               (match_operand:DF 3 "is_div" "") 
7083                 (const_string "fpdiv")
7084              ]
7085               (const_string "fpop")
7086        )
7087  )])
7088
7089(define_insn ""
7090  [(set (match_operand:SF 0 "register_operand" "=f,f")
7091	(match_operator:SF 3 "binary_387_op"
7092			[(match_operand:SF 1 "nonimmediate_operand" "0,fm")
7093			 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
7094  "TARGET_80387"
7095  "* return output_387_binary_op (insn, operands);"
7096  [(set (attr "type") 
7097        (cond [(match_operand:DF 3 "is_mul" "") 
7098                 (const_string "fpmul")
7099               (match_operand:DF 3 "is_div" "") 
7100                 (const_string "fpdiv")
7101              ]
7102               (const_string "fpop")
7103        )
7104  )])
7105
7106(define_insn ""
7107  [(set (match_operand:SF 0 "register_operand" "=f")
7108	(match_operator:SF 3 "binary_387_op"
7109	  [(float:SF (match_operand:SI 1 "nonimmediate_operand" "rm"))
7110	   (match_operand:SF 2 "register_operand" "0")]))]
7111  "TARGET_80387"
7112  "* return output_387_binary_op (insn, operands);"
7113  [(set (attr "type") 
7114        (cond [(match_operand:DF 3 "is_mul" "") 
7115                 (const_string "fpmul")
7116               (match_operand:DF 3 "is_div" "") 
7117                 (const_string "fpdiv")
7118              ]
7119               (const_string "fpop")
7120        )
7121  )])
7122
7123(define_insn ""
7124  [(set (match_operand:SF 0 "register_operand" "=f")
7125	(match_operator:SF 3 "binary_387_op"
7126	  [(match_operand:SF 1 "register_operand" "0")
7127	   (float:SF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
7128  "TARGET_80387"
7129  "* return output_387_binary_op (insn, operands);"
7130  [(set (attr "type") 
7131        (cond [(match_operand:DF 3 "is_mul" "") 
7132                 (const_string "fpmul")
7133               (match_operand:DF 3 "is_div" "") 
7134                 (const_string "fpdiv")
7135              ]
7136               (const_string "fpop")
7137        )
7138  )])
7139
7140(define_expand "strlensi"
7141  [(parallel [(set (match_dup 4)
7142		   (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" ""))
7143			       (match_operand:QI 2 "immediate_operand" "")
7144			       (match_operand:SI 3 "immediate_operand" "")] 0))
7145	      (clobber (match_dup 1))])
7146   (set (match_dup 5)
7147	(not:SI (match_dup 4)))
7148   (set (match_operand:SI 0 "register_operand" "")
7149	(plus:SI (match_dup 5)
7150	         (const_int -1)))]
7151  ""
7152  "
7153{
7154  if (TARGET_UNROLL_STRLEN && operands[2] == const0_rtx && optimize > 1)
7155    {
7156      rtx address;
7157      rtx scratch;
7158
7159	/* well it seems that some optimizer does not combine a call like
7160	     foo(strlen(bar), strlen(bar));
7161	   when the move and the subtraction is done here.  It does calculate
7162	   the length just once when these instructions are done inside of
7163	   output_strlen_unroll().  But I think since &bar[strlen(bar)] is
7164	   often used and I use one fewer register for the lifetime of
7165	   output_strlen_unroll() this is better.  */
7166      scratch = gen_reg_rtx (SImode);
7167      address = force_reg (SImode, XEXP (operands[1], 0));
7168
7169	/* move address to scratch-register
7170	   this is done here because the i586 can do the following and
7171	   in the same cycle with the following move.  */
7172      if (GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[3]) < 4)
7173	  emit_insn (gen_movsi (scratch, address));
7174
7175      emit_insn (gen_movsi (operands[0], address));
7176
7177      if(TARGET_USE_Q_REG)
7178	emit_insn (gen_strlensi_unroll5 (operands[0],
7179					operands[3],
7180					scratch,
7181					operands[0]));
7182      else
7183	emit_insn (gen_strlensi_unroll4 (operands[0],
7184					operands[3],
7185					scratch,
7186					operands[0]));
7187
7188        /* gen_strlensi_unroll[45] returns the address of the zero
7189           at the end of the string, like memchr(), so compute the
7190           length by subtracting the startaddress.  */
7191      emit_insn (gen_subsi3 (operands[0], operands[0], address));
7192      DONE;
7193    }
7194
7195  operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
7196  operands[4] = gen_reg_rtx (SImode);
7197  operands[5] = gen_reg_rtx (SImode);
7198}")
7199
7200;; It might seem that operands 0 & 1 could use predicate register_operand.
7201;; But strength reduction might offset the MEM expression.  So we let
7202;; reload put the address into %edi.
7203
7204(define_insn ""
7205  [(set (match_operand:SI 0 "register_operand" "=&c")
7206	(unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D"))
7207		    (match_operand:QI 2 "immediate_operand" "a")
7208		    (match_operand:SI 3 "immediate_operand" "i")] 0))
7209   (clobber (match_dup 1))]
7210  ""
7211  "*
7212{
7213  rtx xops[2];
7214
7215  xops[0] = operands[0];
7216  xops[1] = constm1_rtx;
7217  output_asm_insn (\"cld\", operands);
7218  output_asm_insn (AS2 (mov%L0,%1,%0), xops);
7219  return \"repnz\;scas%B2\";
7220}")
7221
7222/* Conditional move define_insns.  */
7223
7224(define_expand "movsicc"
7225  [(set (match_operand:SI 0 "register_operand" "")
7226	(if_then_else:SI (match_operand 1 "comparison_operator" "")
7227			 (match_operand:SI 2 "nonimmediate_operand" "")
7228			 (match_operand:SI 3 "nonimmediate_operand" "")))]
7229  "TARGET_CMOVE"
7230  "
7231{
7232  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
7233    FAIL;
7234
7235  operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
7236			GET_MODE (i386_compare_op0),
7237			i386_compare_op0, i386_compare_op1);
7238}")
7239
7240(define_insn ""
7241  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
7242	(if_then_else:SI (match_operator 1 "comparison_operator" 
7243	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
7244		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
7245	      (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0")
7246	      (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))]
7247  "TARGET_CMOVE"
7248  "#")
7249
7250(define_insn ""
7251  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
7252	(if_then_else:SI (match_operator 1 "comparison_operator" 
7253	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
7254		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
7255	      (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0")
7256	      (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))]
7257  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT"
7258  "#")
7259
7260(define_split
7261  [(set (match_operand:SI 0 "register_operand" "=r,r")
7262	(if_then_else:SI (match_operator 1 "comparison_operator" 
7263				[(match_operand 2 "nonimmediate_operand" "")
7264				 (const_int 0)])
7265		      (match_operand:SI 3 "nonimmediate_operand" "rm,0")
7266		      (match_operand:SI 4 "nonimmediate_operand" "0,rm")))]
7267  "TARGET_CMOVE && reload_completed"
7268  [(set (cc0)
7269	(match_dup 2))
7270   (set (match_dup 0)
7271	(if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
7272		      (match_dup 3) (match_dup 4)))]
7273  "")
7274
7275(define_split
7276  [(set (match_operand:SI 0 "register_operand" "=r,r")
7277	(if_then_else:SI (match_operator 1 "comparison_operator" 
7278				[(match_operand 2 "nonimmediate_operand" "")
7279				 (match_operand 3 "general_operand" "")])
7280		      (match_operand:SI 4 "nonimmediate_operand" "rm,0")
7281		      (match_operand:SI 5 "nonimmediate_operand" "0,rm")))]
7282  "TARGET_CMOVE && reload_completed"
7283  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
7284   (set (match_dup 0)
7285	(if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
7286		      (match_dup 4) (match_dup 5)))]
7287  "")
7288
7289(define_insn ""
7290  [(set (match_operand:SI 0 "register_operand" "=r,r")
7291	(if_then_else:SI (match_operator 1 "comparison_operator" 
7292				[(cc0) (const_int 0)])
7293		      (match_operand:SI 2 "nonimmediate_operand" "rm,0")
7294		      (match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
7295  "TARGET_CMOVE && reload_completed"
7296  "* return output_int_conditional_move (which_alternative, operands);")
7297
7298(define_expand "movhicc"
7299  [(set (match_operand:HI 0 "register_operand" "")
7300	(if_then_else:HI (match_operand 1 "comparison_operator" "")
7301			 (match_operand:HI 2 "nonimmediate_operand" "")
7302			 (match_operand:HI 3 "nonimmediate_operand" "")))]
7303  "TARGET_CMOVE"
7304  "
7305{
7306  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
7307    FAIL;
7308
7309  operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
7310			GET_MODE (i386_compare_op0),
7311			i386_compare_op0, i386_compare_op1);
7312}")
7313
7314(define_insn ""
7315  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
7316	(if_then_else:HI (match_operator 1 "comparison_operator" 
7317	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
7318		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
7319	      (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0")
7320	      (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))]
7321  "TARGET_CMOVE"
7322  "#")
7323
7324(define_insn ""
7325  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
7326	(if_then_else:HI (match_operator 1 "comparison_operator" 
7327	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
7328		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
7329	      (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0")
7330	      (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))]
7331  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT"
7332  "#")
7333
7334(define_split
7335  [(set (match_operand:HI 0 "register_operand" "=r,r")
7336	(if_then_else:HI (match_operator 1 "comparison_operator" 
7337				[(match_operand 2 "nonimmediate_operand" "")
7338				 (const_int 0)])
7339		      (match_operand:HI 3 "nonimmediate_operand" "rm,0")
7340		      (match_operand:HI 4 "nonimmediate_operand" "0,rm")))]
7341  "TARGET_CMOVE && reload_completed"
7342  [(set (cc0)
7343	(match_dup 2))
7344   (set (match_dup 0)
7345	(if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)])
7346		      (match_dup 3) (match_dup 4)))]
7347  "")
7348
7349(define_split
7350  [(set (match_operand:HI 0 "register_operand" "=r,r")
7351	(if_then_else:HI (match_operator 1 "comparison_operator" 
7352				[(match_operand 2 "nonimmediate_operand" "")
7353				 (match_operand 3 "general_operand" "")])
7354		      (match_operand:HI 4 "nonimmediate_operand" "rm,0")
7355		      (match_operand:HI 5 "nonimmediate_operand" "0,rm")))]
7356  "TARGET_CMOVE && reload_completed"
7357  [(set (cc0)
7358	(compare (match_dup 2) (match_dup 3)))
7359   (set (match_dup 0)
7360	(if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)])
7361		      (match_dup 4) (match_dup 5)))]
7362  "")
7363
7364(define_insn ""
7365  [(set (match_operand:HI 0 "register_operand" "=r,r")
7366	(if_then_else:HI (match_operator 1 "comparison_operator" 
7367				[(cc0) (const_int 0)])
7368		      (match_operand:HI 2 "nonimmediate_operand" "rm,0")
7369		      (match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
7370  "TARGET_CMOVE && reload_completed"
7371  "* return output_int_conditional_move (which_alternative, operands);")
7372
7373(define_expand "movsfcc"
7374  [(set (match_operand:SF 0 "register_operand" "")
7375	(if_then_else:SF (match_operand 1 "comparison_operator" "")
7376			 (match_operand:SF 2 "register_operand" "")
7377			 (match_operand:SF 3 "register_operand" "")))]
7378  "TARGET_CMOVE"
7379  "
7380{
7381  rtx temp;
7382
7383  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
7384    FAIL;
7385
7386  /* The floating point conditional move instructions don't directly
7387     support conditions resulting from a signed integer comparison. */
7388
7389  switch (GET_CODE (operands[1]))
7390    {
7391    case LT:
7392    case LE:
7393    case GE:
7394    case GT:
7395      temp = emit_store_flag (gen_reg_rtx (QImode),
7396		GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1,
7397		VOIDmode, 0, 0);
7398
7399      if (!temp)
7400        FAIL;
7401
7402      operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx);
7403      break;
7404
7405    default:
7406      operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
7407			GET_MODE (i386_compare_op0),
7408			i386_compare_op0, i386_compare_op1);
7409      break;
7410    }
7411}")
7412
7413(define_insn ""
7414  [(set (match_operand:SF 0 "register_operand" "=f,f,f,f")
7415	(if_then_else:SF (match_operator 1 "comparison_operator" 
7416	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
7417		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
7418	      (match_operand:SF 4 "register_operand" "f,f,0,0")
7419	      (match_operand:SF 5 "register_operand" "0,0,f,f")))]
7420  "TARGET_CMOVE
7421    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
7422    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
7423  "#")
7424
7425(define_insn ""
7426  [(set (match_operand:SF 0 "register_operand" "=f,f,f,f")
7427	(if_then_else:SF (match_operator 1 "comparison_operator" 
7428		[(match_operand 2 "nonimmediate_operand" "r,m,r,m")
7429		 (match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
7430	      (match_operand:SF 4 "register_operand" "f,f,0,0")
7431	      (match_operand:SF 5 "register_operand" "0,0,f,f")))]
7432  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT
7433    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
7434    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
7435  "#")
7436
7437(define_split
7438  [(set (match_operand:SF 0 "register_operand" "=f,f")
7439	(if_then_else:SF (match_operator 1 "comparison_operator" 
7440				[(match_operand 2 "nonimmediate_operand" "")
7441				 (const_int 0)])
7442		      (match_operand:SF 3 "register_operand" "f,0")
7443		      (match_operand:SF 4 "register_operand" "0,f")))]
7444  "TARGET_CMOVE && reload_completed"
7445  [(set (cc0)
7446	(match_dup 2))
7447   (set (match_dup 0)
7448	(if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)])
7449		      (match_dup 3) (match_dup 4)))]
7450  "")
7451
7452(define_split
7453  [(set (match_operand:SF 0 "register_operand" "=f,f")
7454	(if_then_else:SF (match_operator 1 "comparison_operator" 
7455				[(match_operand 2 "nonimmediate_operand" "")
7456				 (match_operand 3 "general_operand" "")])
7457		      (match_operand:SF 4 "register_operand" "f,0")
7458		      (match_operand:SF 5 "register_operand" "0,f")))]
7459  "TARGET_CMOVE && reload_completed"
7460  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
7461   (set (match_dup 0)
7462	(if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)])
7463		      (match_dup 4) (match_dup 5)))]
7464  "")
7465
7466(define_insn ""
7467  [(set (match_operand:SF 0 "register_operand" "=f,f")
7468	(if_then_else:SF (match_operator 1 "comparison_operator" 
7469				[(cc0) (const_int 0)])
7470		      (match_operand:SF 2 "register_operand" "f,0")
7471		      (match_operand:SF 3 "register_operand" "0,f")))]
7472  "TARGET_CMOVE && reload_completed"
7473  "* return output_fp_conditional_move (which_alternative, operands);")
7474
7475(define_expand "movdfcc"
7476  [(set (match_operand:DF 0 "register_operand" "")
7477	(if_then_else:DF (match_operand 1 "comparison_operator" "")
7478			 (match_operand:DF 2 "register_operand" "")
7479			 (match_operand:DF 3 "register_operand" "")))]
7480  "TARGET_CMOVE"
7481  "
7482{
7483  rtx temp;
7484
7485  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
7486    FAIL;
7487
7488  /* The floating point conditional move instructions don't directly
7489     support conditions resulting from a signed integer comparison. */
7490
7491  switch (GET_CODE (operands[1]))
7492    {
7493    case LT:
7494    case LE:
7495    case GE:
7496    case GT:
7497      temp = emit_store_flag (gen_reg_rtx (QImode),
7498		GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1,
7499		VOIDmode, 0, 0);
7500
7501      if (!temp)
7502        FAIL;
7503
7504      operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx);
7505      break;
7506
7507    default:
7508      operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
7509			GET_MODE (i386_compare_op0),
7510			i386_compare_op0, i386_compare_op1);
7511      break;
7512    }
7513}")
7514
7515(define_insn ""
7516  [(set (match_operand:DF 0 "register_operand" "=f,f,f,f")
7517	(if_then_else:DF (match_operator 1 "comparison_operator" 
7518	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
7519		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
7520	      (match_operand:DF 4 "register_operand" "f,f,0,0")
7521	      (match_operand:DF 5 "register_operand" "0,0,f,f")))]
7522  "TARGET_CMOVE
7523    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
7524    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
7525  "#")
7526
7527(define_insn ""
7528  [(set (match_operand:DF 0 "register_operand" "=f,f,f,f")
7529	(if_then_else:DF (match_operator 1 "comparison_operator" 
7530	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
7531		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
7532	      (match_operand:DF 4 "register_operand" "f,f,0,0")
7533	      (match_operand:DF 5 "register_operand" "0,0,f,f")))]
7534  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT
7535    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
7536    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
7537  "#")
7538
7539(define_split
7540  [(set (match_operand:DF 0 "register_operand" "=f,f")
7541	(if_then_else:DF (match_operator 1 "comparison_operator" 
7542				[(match_operand 2 "nonimmediate_operand" "")
7543				 (const_int 0)])
7544		      (match_operand:DF 3 "register_operand" "f,0")
7545		      (match_operand:DF 4 "register_operand" "0,f")))]
7546  "TARGET_CMOVE && reload_completed"
7547  [(set (cc0)
7548	(match_dup 2))
7549   (set (match_dup 0)
7550	(if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)])
7551		      (match_dup 3) (match_dup 4)))]
7552  "")
7553
7554(define_split
7555  [(set (match_operand:DF 0 "register_operand" "=f,f")
7556	(if_then_else:DF (match_operator 1 "comparison_operator" 
7557				[(match_operand 2 "nonimmediate_operand" "")
7558				 (match_operand 3 "general_operand" "")])
7559		      (match_operand:DF 4 "register_operand" "f,0")
7560		      (match_operand:DF 5 "register_operand" "0,f")))]
7561  "TARGET_CMOVE && reload_completed"
7562  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
7563   (set (match_dup 0)
7564	(if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)])
7565		      (match_dup 4) (match_dup 5)))]
7566  "")
7567
7568(define_insn ""
7569  [(set (match_operand:DF 0 "register_operand" "=f,f")
7570	(if_then_else:DF (match_operator 1 "comparison_operator" 
7571				[(cc0) (const_int 0)])
7572		      (match_operand:DF 2 "register_operand" "f,0")
7573		      (match_operand:DF 3 "register_operand" "0,f")))]
7574  "TARGET_CMOVE && reload_completed"
7575  "* return output_fp_conditional_move (which_alternative, operands);")
7576
7577(define_expand "movxfcc"
7578  [(set (match_operand:XF 0 "register_operand" "")
7579	(if_then_else:XF (match_operand 1 "comparison_operator" "")
7580			 (match_operand:XF 2 "register_operand" "")
7581			 (match_operand:XF 3 "register_operand" "")))]
7582  "TARGET_CMOVE"
7583  "
7584{
7585  rtx temp;
7586
7587  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
7588    FAIL;
7589
7590  /* The floating point conditional move instructions don't directly
7591     support conditions resulting from a signed integer comparison. */
7592
7593  switch (GET_CODE (operands[1]))
7594    {
7595    case LT:
7596    case LE:
7597    case GE:
7598    case GT:
7599      temp = emit_store_flag (gen_reg_rtx (QImode),
7600		GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1,
7601		VOIDmode, 0, 0);
7602
7603      if (!temp)
7604        FAIL;
7605
7606      operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx);
7607      break;
7608
7609    default:
7610      operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
7611			GET_MODE (i386_compare_op0),
7612			i386_compare_op0, i386_compare_op1);
7613      break;
7614    }
7615}")
7616
7617(define_insn ""
7618  [(set (match_operand:XF 0 "register_operand" "=f,f,f,f")
7619	(if_then_else:XF (match_operator 1 "comparison_operator" 
7620	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
7621		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
7622	      (match_operand:XF 4 "register_operand" "f,f,0,0")
7623	      (match_operand:XF 5 "register_operand" "0,0,f,f")))]
7624  "TARGET_CMOVE
7625    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
7626    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
7627  "#")
7628
7629(define_insn ""
7630  [(set (match_operand:XF 0 "register_operand" "=f,f,f,f")
7631	(if_then_else:XF (match_operator 1 "comparison_operator" 
7632	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
7633		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
7634	      (match_operand:XF 4 "register_operand" "f,f,0,0")
7635	      (match_operand:XF 5 "register_operand" "0,0,f,f")))]
7636  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT
7637    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
7638    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
7639  "#")
7640
7641(define_split
7642  [(set (match_operand:XF 0 "register_operand" "=f,f")
7643	(if_then_else:XF (match_operator 1 "comparison_operator" 
7644				[(match_operand 2 "nonimmediate_operand" "")
7645				 (const_int 0)])
7646		      (match_operand:XF 3 "register_operand" "f,0")
7647		      (match_operand:XF 4 "register_operand" "0,f")))]
7648  "TARGET_CMOVE && reload_completed"
7649  [(set (cc0)
7650	(match_dup 2))
7651   (set (match_dup 0)
7652	(if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)])
7653		      (match_dup 3) (match_dup 4)))]
7654  "")
7655
7656(define_split
7657  [(set (match_operand:XF 0 "register_operand" "=f,f")
7658	(if_then_else:XF (match_operator 1 "comparison_operator" 
7659				[(match_operand 2 "nonimmediate_operand" "")
7660				 (match_operand 3 "general_operand" "")])
7661		      (match_operand:XF 4 "register_operand" "f,0")
7662		      (match_operand:XF 5 "register_operand" "0,f")))]
7663  "TARGET_CMOVE && reload_completed"
7664  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
7665   (set (match_dup 0)
7666	(if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)])
7667		      (match_dup 4) (match_dup 5)))]
7668  "")
7669
7670(define_insn ""
7671  [(set (match_operand:XF 0 "register_operand" "=f,f")
7672	(if_then_else:XF (match_operator 1 "comparison_operator" 
7673				[(cc0) (const_int 0)])
7674		      (match_operand:XF 2 "register_operand" "f,0")
7675		      (match_operand:XF 3 "register_operand" "0,f")))]
7676  "TARGET_CMOVE && reload_completed"
7677  "* return output_fp_conditional_move (which_alternative, operands);")
7678
7679(define_expand "movdicc"
7680  [(set (match_operand:DI 0 "register_operand" "")
7681	(if_then_else:DI (match_operand 1 "comparison_operator" "")
7682			 (match_operand:DI 2 "nonimmediate_operand" "")
7683			 (match_operand:DI 3 "nonimmediate_operand" "")))]
7684  "TARGET_CMOVE"
7685  "
7686{
7687  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
7688    FAIL;
7689
7690  operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
7691			GET_MODE (i386_compare_op0),
7692			i386_compare_op0, i386_compare_op1);
7693}")
7694
7695(define_insn ""
7696  [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r")
7697	(if_then_else:DI (match_operator 1 "comparison_operator" 
7698	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
7699		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
7700	      (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0")
7701	      (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))]
7702  "TARGET_CMOVE"
7703  "#")
7704
7705(define_insn ""
7706  [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r")
7707	(if_then_else:DI (match_operator 1 "comparison_operator" 
7708	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
7709		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
7710	      (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0")
7711	      (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))]
7712  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT"
7713  "#")
7714
7715(define_split
7716  [(set (match_operand:DI 0 "register_operand" "=&r,&r")
7717	(if_then_else:DI (match_operator 1 "comparison_operator" 
7718				[(match_operand 2 "nonimmediate_operand" "")
7719				 (const_int 0)])
7720		      (match_operand:DI 3 "nonimmediate_operand" "ro,0")
7721		      (match_operand:DI 4 "nonimmediate_operand" "0,ro")))]
7722  "TARGET_CMOVE && reload_completed"
7723  [(set (cc0)
7724	(match_dup 2))
7725   (set (match_dup 0)
7726	(if_then_else:DI (match_op_dup 1 [(cc0) (const_int 0)])
7727		      (match_dup 3) (match_dup 4)))]
7728  "")
7729
7730(define_split
7731  [(set (match_operand:DI 0 "register_operand" "=&r,&r")
7732	(if_then_else:DI (match_operator 1 "comparison_operator" 
7733				[(match_operand 2 "nonimmediate_operand" "")
7734				 (match_operand 3 "general_operand" "")])
7735		      (match_operand:DI 4 "nonimmediate_operand" "ro,0")
7736		      (match_operand:DI 5 "nonimmediate_operand" "0,ro")))]
7737  "TARGET_CMOVE && reload_completed"
7738  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
7739   (set (match_dup 0)
7740	(if_then_else:DI (match_op_dup 1 [(cc0) (const_int 0)])
7741		      (match_dup 4) (match_dup 5)))]
7742  "")
7743
7744(define_insn ""
7745  [(set (match_operand:DI 0 "register_operand" "=&r,&r")
7746	(if_then_else:DI (match_operator 1 "comparison_operator" 
7747				[(cc0) (const_int 0)])
7748		      (match_operand:DI 2 "nonimmediate_operand" "ro,0")
7749		      (match_operand:DI 3 "nonimmediate_operand" "0,ro")))]
7750  "TARGET_CMOVE && reload_completed"
7751  "* return output_int_conditional_move (which_alternative, operands);")
7752
7753(define_insn "strlensi_unroll"
7754  [(set (match_operand:SI 0 "register_operand" "=&r,&r")
7755	(unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "r,r"))
7756		    (match_operand:SI 2 "immediate_operand" "i,i")] 0))
7757   (clobber (match_scratch:SI 3 "=&q,&r"))]
7758  "optimize > 1"
7759  "* return output_strlen_unroll (operands);")
7760
7761;; the only difference between the following patterns is the register preference
7762;; on a pentium using a q-register saves one clock cycle per 4 characters
7763
7764(define_insn "strlensi_unroll4"
7765  [(set (match_operand:SI 0 "register_operand" "=r,r")
7766		   (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0,0"))
7767			       (match_operand:SI 1 "immediate_operand" "i,i")
7768			       (match_operand:SI 2 "register_operand" "+q,!r")] 0))
7769   (clobber (match_dup 2))]
7770  "(TARGET_USE_ANY_REG && optimize > 1)"
7771  "* return output_strlen_unroll (operands);")
7772
7773(define_insn "strlensi_unroll5"
7774  [(set (match_operand:SI 0 "register_operand" "=r")
7775		   (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0"))
7776			       (match_operand:SI 1 "immediate_operand" "i")
7777			       (match_operand:SI 2 "register_operand" "+q")] 0))
7778   (clobber (match_dup 2))]
7779  "(TARGET_USE_Q_REG && optimize > 1)"
7780  "* return output_strlen_unroll (operands);"
7781)
7782
7783(define_insn "allocate_stack_worker"
7784  [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] 3)
7785   (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0)))
7786   (clobber (match_dup 0))]
7787  "TARGET_STACK_PROBE"
7788  "* return AS1(call,__alloca);")
7789
7790(define_expand "allocate_stack"
7791  [(set (match_operand:SI 0 "register_operand" "=r")
7792  	(minus:SI (reg:SI 7) (match_operand:SI 1 "general_operand" "")))
7793   (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 1)))]
7794   "TARGET_STACK_PROBE"
7795  "
7796{
7797#ifdef CHECK_STACK_LIMIT
7798  if (GET_CODE (operands[1]) == CONST_INT
7799      && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
7800    emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
7801			   operands[1]));
7802  else 
7803#endif
7804    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
7805							    operands[1])));
7806
7807  emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
7808  DONE;
7809}")
7810
7811(define_expand "exception_receiver"
7812  [(const_int 0)]
7813  "flag_pic"
7814  "
7815{
7816  load_pic_register (1);
7817  DONE;
7818}")
7819