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