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