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