OSDN Git Service

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