ff0119631cb44cfe3f67b10e5945a41fa2c9a7ef
[fw/sdcc] / support / cpp / i386 / i386.md
1 ;; GCC machine description for Intel X86.
2 ;; Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc.
3 ;; Mostly by William Schelter.
4
5 ;; This file is part of GNU CC.
6
7 ;; GNU CC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
10 ;; any later version.
11
12 ;; GNU CC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU CC; see the file COPYING.  If not, write to
19 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
20 ;; Boston, MA 02111-1307, USA.
21
22
23 ;; The original PO technology requires these to be ordered by speed,
24 ;; so that assigner will pick the fastest.
25
26 ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
27
28 ;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code
29 ;; updates for most instructions.
30
31 ;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register
32 ;; constraint letters.
33
34 ;; the special asm out single letter directives following a '%' are:
35 ;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of
36 ;;     operands[1].
37 ;; 'L' Print the opcode suffix for a 32-bit integer opcode.
38 ;; 'W' Print the opcode suffix for a 16-bit integer opcode.
39 ;; 'B' Print the opcode suffix for an 8-bit integer opcode.
40 ;; 'S' Print the opcode suffix for a 32-bit float opcode.
41 ;; 'Q' Print the opcode suffix for a 64-bit float opcode.
42 ;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode.
43 ;; 'J' Print the appropriate jump operand.
44
45 ;; 'b' Print the QImode name of the register for the indicated operand.
46 ;;     %b0 would print %al if operands[0] is reg 0.
47 ;; 'w' Likewise, print the HImode name of the register.
48 ;; 'k' Likewise, print the SImode name of the register.
49 ;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh.
50 ;; 'y' Print "st(0)" instead of "st" as a register.
51
52 ;; UNSPEC usage:
53 ;; 0  This is a `scas' operation.  The mode of the UNSPEC is always SImode.
54 ;;    operand 0 is the memory address to scan.
55 ;;    operand 1 is a register containing the value to scan for.  The mode
56 ;;       of the scas opcode will be the same as the mode of this operand.
57 ;;    operand 2 is the known alignment of operand 0.
58 ;; 1  This is a `sin' operation.  The mode of the UNSPEC is MODE_FLOAT.
59 ;;    operand 0 is the argument for `sin'.
60 ;; 2  This is a `cos' operation.  The mode of the UNSPEC is MODE_FLOAT.
61 ;;    operand 0 is the argument for `cos'.
62 \f
63 ;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM".
64 ;; But restricting MEM here would mean that gcc could not remove a redundant
65 ;; test in cases like "incl MEM / je TARGET".
66 ;;
67 ;; We don't want to allow a constant operand for test insns because
68 ;; (set (cc0) (const_int foo)) has no mode information.  Such insns will
69 ;; be folded while optimizing anyway.
70
71 ;; All test insns have expanders that save the operands away without
72 ;; actually generating RTL.  The bCOND or sCOND (emitted immediately
73 ;; after the tstM or cmp) will actually emit the tstM or cmpM.
74
75 (define_insn "tstsi_1"
76   [(set (cc0)
77         (match_operand:SI 0 "nonimmediate_operand" "rm"))]
78   ""
79   "*
80 {
81   if (REG_P (operands[0]))
82     return AS2 (test%L0,%0,%0);
83
84   operands[1] = const0_rtx;
85   return AS2 (cmp%L0,%1,%0);
86 }")
87
88 (define_expand "tstsi"
89   [(set (cc0)
90         (match_operand:SI 0 "nonimmediate_operand" ""))]
91   ""
92   "
93 {
94   i386_compare_gen = gen_tstsi_1;
95   i386_compare_op0 = operands[0];
96   DONE;
97 }")
98
99 (define_insn "tsthi_1"
100   [(set (cc0)
101         (match_operand:HI 0 "nonimmediate_operand" "rm"))]
102   ""
103   "*
104 {
105   if (REG_P (operands[0]))
106     return AS2 (test%W0,%0,%0);
107
108   operands[1] = const0_rtx;
109   return AS2 (cmp%W0,%1,%0);
110 }")
111
112 (define_expand "tsthi"
113   [(set (cc0)
114         (match_operand:HI 0 "nonimmediate_operand" ""))]
115   ""
116   "
117 {
118   i386_compare_gen = gen_tsthi_1;
119   i386_compare_op0 = operands[0];
120   DONE;
121 }")
122
123 (define_insn "tstqi_1"
124   [(set (cc0)
125         (match_operand:QI 0 "nonimmediate_operand" "qm"))]
126   ""
127   "*
128 {
129   if (REG_P (operands[0]))
130     return AS2 (test%B0,%0,%0);
131
132   operands[1] = const0_rtx;
133   return AS2 (cmp%B0,%1,%0);
134 }")
135
136 (define_expand "tstqi"
137   [(set (cc0)
138         (match_operand:QI 0 "nonimmediate_operand" ""))]
139   ""
140   "
141 {
142   i386_compare_gen = gen_tstqi_1;
143   i386_compare_op0 = operands[0];
144   DONE;
145 }")
146
147 (define_insn "tstsf_cc"
148   [(set (cc0)
149         (match_operand:SF 0 "register_operand" "f"))
150    (clobber (match_scratch:HI 1 "=a"))]
151   "TARGET_80387 && ! TARGET_IEEE_FP"
152   "*
153 {
154   if (! STACK_TOP_P (operands[0]))
155     abort ();
156
157   output_asm_insn (\"ftst\", operands);
158
159   if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
160     output_asm_insn (AS1 (fstp,%y0), operands);
161
162   return output_fp_cc0_set (insn);
163 }")
164
165 ;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode
166 ;; isn't IEEE compliant.
167
168 (define_expand "tstsf"
169   [(parallel [(set (cc0)
170                    (match_operand:SF 0 "register_operand" ""))
171               (clobber (match_scratch:HI 1 ""))])]
172   "TARGET_80387 && ! TARGET_IEEE_FP"
173   "
174 {
175   i386_compare_gen = gen_tstsf_cc;
176   i386_compare_op0 = operands[0];
177   DONE;
178 }")
179
180 (define_insn "tstdf_cc"
181   [(set (cc0)
182         (match_operand:DF 0 "register_operand" "f"))
183    (clobber (match_scratch:HI 1 "=a"))]
184   "TARGET_80387 && ! TARGET_IEEE_FP"
185   "*
186 {
187   if (! STACK_TOP_P (operands[0]))
188     abort ();
189
190   output_asm_insn (\"ftst\", operands);
191
192   if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
193     output_asm_insn (AS1 (fstp,%y0), operands);
194
195   return output_fp_cc0_set (insn);
196 }")
197
198 ;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
199 ;; isn't IEEE compliant.
200
201 (define_expand "tstdf"
202   [(parallel [(set (cc0)
203                    (match_operand:DF 0 "register_operand" ""))
204               (clobber (match_scratch:HI 1 ""))])]
205   "TARGET_80387 && ! TARGET_IEEE_FP"
206   "
207 {
208   i386_compare_gen = gen_tstdf_cc;
209   i386_compare_op0 = operands[0];
210   DONE;
211 }")
212
213 (define_insn "tstxf_cc"
214   [(set (cc0)
215         (match_operand:XF 0 "register_operand" "f"))
216    (clobber (match_scratch:HI 1 "=a"))]
217   "TARGET_80387 && ! TARGET_IEEE_FP"
218   "*
219 {
220   if (! STACK_TOP_P (operands[0]))
221     abort ();
222
223   output_asm_insn (\"ftst\", operands);
224
225   if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
226     output_asm_insn (AS1 (fstp,%y0), operands);
227
228   return output_fp_cc0_set (insn);
229 }")
230
231 ;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
232 ;; isn't IEEE compliant.
233
234 (define_expand "tstxf"
235   [(parallel [(set (cc0)
236                    (match_operand:XF 0 "register_operand" ""))
237               (clobber (match_scratch:HI 1 ""))])]
238   "TARGET_80387 && ! TARGET_IEEE_FP"
239   "
240 {
241   i386_compare_gen = gen_tstxf_cc;
242   i386_compare_op0 = operands[0];
243   DONE;
244 }")
245 \f
246 ;;- compare instructions.  See comments above tstM patterns about
247 ;;  expansion of these insns.
248
249 (define_insn "cmpsi_1"
250   [(set (cc0)
251         (compare (match_operand:SI 0 "nonimmediate_operand" "mr,r")
252                  (match_operand:SI 1 "general_operand" "ri,mr")))]
253   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
254   "*
255 {
256   if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
257     {
258       cc_status.flags |= CC_REVERSED;
259       return AS2 (cmp%L0,%0,%1);
260     }
261   return AS2 (cmp%L0,%1,%0);
262 }")
263
264 (define_expand "cmpsi"
265   [(set (cc0)
266         (compare (match_operand:SI 0 "nonimmediate_operand" "")
267                  (match_operand:SI 1 "general_operand" "")))]
268   ""
269   "
270 {
271   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
272     operands[0] = force_reg (SImode, operands[0]);
273
274   i386_compare_gen = gen_cmpsi_1;
275   i386_compare_op0 = operands[0];
276   i386_compare_op1 = operands[1];
277   DONE;
278 }")
279
280 (define_insn "cmphi_1"
281   [(set (cc0)
282         (compare (match_operand:HI 0 "nonimmediate_operand" "mr,r")
283                  (match_operand:HI 1 "general_operand" "ri,mr")))]
284   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
285   "*
286 {
287   if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
288     {
289       cc_status.flags |= CC_REVERSED;
290       return AS2 (cmp%W0,%0,%1);
291     }
292   return AS2 (cmp%W0,%1,%0);
293 }")
294
295 (define_expand "cmphi"
296   [(set (cc0)
297         (compare (match_operand:HI 0 "nonimmediate_operand" "")
298                  (match_operand:HI 1 "general_operand" "")))]
299   ""
300   "
301 {
302   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
303     operands[0] = force_reg (HImode, operands[0]);
304
305   i386_compare_gen = gen_cmphi_1;
306   i386_compare_op0 = operands[0];
307   i386_compare_op1 = operands[1];
308   DONE;
309 }")
310
311 (define_insn "cmpqi_1"
312   [(set (cc0)
313         (compare (match_operand:QI 0 "nonimmediate_operand" "q,mq")
314                  (match_operand:QI 1 "general_operand" "qm,nq")))]
315   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
316   "*
317 {
318   if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
319     {
320       cc_status.flags |= CC_REVERSED;
321       return AS2 (cmp%B0,%0,%1);
322     }
323   return AS2 (cmp%B0,%1,%0);
324 }")
325
326 (define_expand "cmpqi"
327   [(set (cc0)
328         (compare (match_operand:QI 0 "nonimmediate_operand" "")
329                  (match_operand:QI 1 "general_operand" "")))]
330   ""
331   "
332 {
333   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
334     operands[0] = force_reg (QImode, operands[0]);
335
336   i386_compare_gen = gen_cmpqi_1;
337   i386_compare_op0 = operands[0];
338   i386_compare_op1 = operands[1];
339   DONE;
340 }")
341
342 ;; These implement float point compares.  For each of DFmode and
343 ;; SFmode, there is the normal insn, and an insn where the second operand
344 ;; is converted to the desired mode.
345
346 (define_insn ""
347   [(set (cc0)
348         (match_operator 2 "VOIDmode_compare_op"
349                         [(match_operand:XF 0 "nonimmediate_operand" "f")
350                          (match_operand:XF 1 "nonimmediate_operand" "f")]))
351    (clobber (match_scratch:HI 3 "=a"))]
352   "TARGET_80387
353    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
354   "* return output_float_compare (insn, operands);")
355
356 (define_insn ""
357   [(set (cc0)
358         (match_operator 2 "VOIDmode_compare_op"
359                         [(match_operand:XF 0 "register_operand" "f")
360                          (float:XF
361                           (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
362    (clobber (match_scratch:HI 3 "=a"))]
363   "TARGET_80387"
364   "* return output_float_compare (insn, operands);")
365
366 (define_insn ""
367   [(set (cc0)
368         (match_operator 2 "VOIDmode_compare_op"
369                         [(float:XF
370                           (match_operand:SI 0 "nonimmediate_operand" "rm"))
371                          (match_operand:XF 1 "register_operand" "f")]))
372    (clobber (match_scratch:HI 3 "=a"))]
373   "TARGET_80387"
374   "* return output_float_compare (insn, operands);")
375
376 (define_insn ""
377   [(set (cc0)
378         (match_operator 2 "VOIDmode_compare_op"
379                         [(match_operand:XF 0 "register_operand" "f")
380                          (float_extend:XF
381                           (match_operand:DF 1 "nonimmediate_operand" "fm"))]))
382    (clobber (match_scratch:HI 3 "=a"))]
383   "TARGET_80387"
384   "* return output_float_compare (insn, operands);")
385
386 (define_insn ""
387   [(set (cc0)
388         (match_operator 2 "VOIDmode_compare_op"
389                         [(match_operand:XF 0 "register_operand" "f")
390                          (float_extend:XF
391                           (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
392    (clobber (match_scratch:HI 3 "=a"))]
393   "TARGET_80387"
394   "* return output_float_compare (insn, operands);")
395
396 (define_insn ""
397   [(set (cc0)
398         (compare:CCFPEQ (match_operand:XF 0 "register_operand" "f")
399                         (match_operand:XF 1 "register_operand" "f")))
400    (clobber (match_scratch:HI 2 "=a"))]
401   "TARGET_80387"
402   "* return output_float_compare (insn, operands);")
403
404 (define_insn ""
405   [(set (cc0)
406         (match_operator 2 "VOIDmode_compare_op"
407                         [(match_operand:DF 0 "nonimmediate_operand" "f,fm")
408                          (match_operand:DF 1 "nonimmediate_operand" "fm,f")]))
409    (clobber (match_scratch:HI 3 "=a,a"))]
410   "TARGET_80387
411    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
412   "* return output_float_compare (insn, operands);")
413
414 (define_insn ""
415   [(set (cc0)
416         (match_operator 2 "VOIDmode_compare_op"
417                         [(match_operand:DF 0 "register_operand" "f")
418                          (float:DF
419                           (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
420    (clobber (match_scratch:HI 3 "=a"))]
421   "TARGET_80387"
422   "* return output_float_compare (insn, operands);")
423
424 (define_insn ""
425   [(set (cc0)
426         (match_operator 2 "VOIDmode_compare_op"
427                         [(float:DF
428                           (match_operand:SI 0 "nonimmediate_operand" "rm"))
429                          (match_operand:DF 1 "register_operand" "f")]))
430    (clobber (match_scratch:HI 3 "=a"))]
431   "TARGET_80387"
432   "* return output_float_compare (insn, operands);")
433
434 (define_insn ""
435   [(set (cc0)
436         (match_operator 2 "VOIDmode_compare_op"
437                         [(match_operand:DF 0 "register_operand" "f")
438                          (float_extend:DF
439                           (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
440    (clobber (match_scratch:HI 3 "=a"))]
441   "TARGET_80387"
442   "* return output_float_compare (insn, operands);")
443
444 (define_insn ""
445   [(set (cc0)
446         (match_operator 2 "VOIDmode_compare_op"
447                         [(float_extend:DF
448                           (match_operand:SF 0 "nonimmediate_operand" "fm"))
449                          (match_operand:DF 1 "register_operand" "f")]))
450    (clobber (match_scratch:HI 3 "=a"))]
451   "TARGET_80387"
452   "* return output_float_compare (insn, operands);")
453
454 (define_insn ""
455   [(set (cc0)
456         (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
457                         (match_operand:DF 1 "register_operand" "f")))
458    (clobber (match_scratch:HI 2 "=a"))]
459   "TARGET_80387"
460   "* return output_float_compare (insn, operands);")
461
462 ;; These two insns will never be generated by combine due to the mode of
463 ;; the COMPARE.
464 ;(define_insn ""
465 ;  [(set (cc0)
466 ;       (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
467 ;                       (float_extend:DF
468 ;                        (match_operand:SF 1 "register_operand" "f"))))
469 ;   (clobber (match_scratch:HI 2 "=a"))]
470 ;  "TARGET_80387"
471 ;  "* return output_float_compare (insn, operands);")
472 ;
473 ;(define_insn ""
474 ;  [(set (cc0)
475 ;       (compare:CCFPEQ (float_extend:DF
476 ;                        (match_operand:SF 0 "register_operand" "f"))
477 ;                       (match_operand:DF 1 "register_operand" "f")))
478 ;   (clobber (match_scratch:HI 2 "=a"))]
479 ;  "TARGET_80387"
480 ;  "* return output_float_compare (insn, operands);")
481
482 (define_insn "cmpsf_cc_1"
483   [(set (cc0)
484         (match_operator 2 "VOIDmode_compare_op"
485                         [(match_operand:SF 0 "nonimmediate_operand" "f,fm")
486                          (match_operand:SF 1 "nonimmediate_operand" "fm,f")]))
487    (clobber (match_scratch:HI 3 "=a,a"))]
488   "TARGET_80387
489    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
490   "* return output_float_compare (insn, operands);")
491
492 (define_insn ""
493   [(set (cc0)
494         (match_operator 2 "VOIDmode_compare_op"
495                         [(match_operand:SF 0 "register_operand" "f")
496                          (float:SF
497                           (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
498    (clobber (match_scratch:HI 3 "=a"))]
499   "TARGET_80387"
500   "* return output_float_compare (insn, operands);")
501
502 (define_insn ""
503   [(set (cc0)
504         (match_operator 2 "VOIDmode_compare_op"
505                         [(float:SF
506                           (match_operand:SI 0 "nonimmediate_operand" "rm"))
507                          (match_operand:SF 1 "register_operand" "f")]))
508    (clobber (match_scratch:HI 3 "=a"))]
509   "TARGET_80387"
510   "* return output_float_compare (insn, operands);")
511
512 (define_insn ""
513   [(set (cc0)
514         (compare:CCFPEQ (match_operand:SF 0 "register_operand" "f")
515                         (match_operand:SF 1 "register_operand" "f")))
516    (clobber (match_scratch:HI 2 "=a"))]
517   "TARGET_80387"
518   "* return output_float_compare (insn, operands);")
519
520 (define_expand "cmpxf"
521   [(set (cc0)
522         (compare (match_operand:XF 0 "register_operand" "")
523                  (match_operand:XF 1 "nonimmediate_operand" "")))]
524   "TARGET_80387"
525   "
526 {
527   i386_compare_gen = gen_cmpxf_cc;
528   i386_compare_gen_eq = gen_cmpxf_ccfpeq;
529   i386_compare_op0 = operands[0];
530   i386_compare_op1 = operands[1];
531   DONE;
532 }")
533
534 (define_expand "cmpdf"
535   [(set (cc0)
536         (compare (match_operand:DF 0 "register_operand" "")
537                  (match_operand:DF 1 "nonimmediate_operand" "")))]
538   "TARGET_80387"
539   "
540 {
541   i386_compare_gen = gen_cmpdf_cc;
542   i386_compare_gen_eq = gen_cmpdf_ccfpeq;
543   i386_compare_op0 = operands[0];
544   i386_compare_op1 = operands[1];
545   DONE;
546 }")
547
548 (define_expand "cmpsf"
549   [(set (cc0)
550         (compare (match_operand:SF 0 "register_operand" "")
551                  (match_operand:SF 1 "nonimmediate_operand" "")))]
552   "TARGET_80387"
553   "
554 {
555   i386_compare_gen = gen_cmpsf_cc;
556   i386_compare_gen_eq = gen_cmpsf_ccfpeq;
557   i386_compare_op0 = operands[0];
558   i386_compare_op1 = operands[1];
559   DONE;
560 }")
561
562 (define_expand "cmpxf_cc"
563   [(parallel [(set (cc0)
564                    (compare (match_operand:XF 0 "register_operand" "")
565                             (match_operand:XF 1 "register_operand" "")))
566               (clobber (match_scratch:HI 2 ""))])]
567   "TARGET_80387"
568   "")
569
570 (define_expand "cmpxf_ccfpeq"
571   [(parallel [(set (cc0)
572                    (compare:CCFPEQ (match_operand:XF 0 "register_operand" "")
573                                    (match_operand:XF 1 "register_operand" "")))
574               (clobber (match_scratch:HI 2 ""))])]
575   "TARGET_80387"
576   "
577 {
578   if (! register_operand (operands[1], XFmode))
579     operands[1] = copy_to_mode_reg (XFmode, operands[1]);
580 }")
581
582 (define_expand "cmpdf_cc"
583   [(parallel [(set (cc0)
584                    (compare (match_operand:DF 0 "register_operand" "")
585                             (match_operand:DF 1 "register_operand" "")))
586               (clobber (match_scratch:HI 2 ""))])]
587   "TARGET_80387"
588   "")
589
590 (define_expand "cmpdf_ccfpeq"
591   [(parallel [(set (cc0)
592                    (compare:CCFPEQ (match_operand:DF 0 "register_operand" "")
593                                    (match_operand:DF 1 "register_operand" "")))
594               (clobber (match_scratch:HI 2 ""))])]
595   "TARGET_80387"
596   "
597 {
598   if (! register_operand (operands[1], DFmode))
599     operands[1] = copy_to_mode_reg (DFmode, operands[1]);
600 }")
601
602 (define_expand "cmpsf_cc"
603   [(parallel [(set (cc0)
604                    (compare (match_operand:SF 0 "register_operand" "")
605                             (match_operand:SF 1 "register_operand" "")))
606               (clobber (match_scratch:HI 2 ""))])]
607   "TARGET_80387"
608   "")
609
610 (define_expand "cmpsf_ccfpeq"
611   [(parallel [(set (cc0)
612                    (compare:CCFPEQ (match_operand:SF 0 "register_operand" "")
613                                    (match_operand:SF 1 "register_operand" "")))
614               (clobber (match_scratch:HI 2 ""))])]
615   "TARGET_80387"
616   "
617 {
618   if (! register_operand (operands[1], SFmode))
619     operands[1] = copy_to_mode_reg (SFmode, operands[1]);
620 }")
621 \f
622 ;; logical compare
623
624 (define_insn ""
625   [(set (cc0)
626         (and:SI (match_operand:SI 0 "general_operand" "%ro")
627                 (match_operand:SI 1 "general_operand" "ri")))]
628   ""
629   "*
630 {
631   /* For small integers, we may actually use testb. */
632   if (GET_CODE (operands[1]) == CONST_INT
633       && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
634       && (! REG_P (operands[0]) || QI_REG_P (operands[0])))
635     {
636       /* We may set the sign bit spuriously.  */
637
638       if ((INTVAL (operands[1]) & ~0xff) == 0)
639         {
640           cc_status.flags |= CC_NOT_NEGATIVE;
641           return AS2 (test%B0,%1,%b0);
642         }
643
644       if ((INTVAL (operands[1]) & ~0xff00) == 0)
645         {
646           cc_status.flags |= CC_NOT_NEGATIVE;
647           operands[1] = GEN_INT (INTVAL (operands[1]) >> 8);
648
649           if (QI_REG_P (operands[0]))
650             return AS2 (test%B0,%1,%h0);
651           else
652             {
653               operands[0] = adj_offsettable_operand (operands[0], 1);
654               return AS2 (test%B0,%1,%b0);
655             }
656         }
657
658       if (GET_CODE (operands[0]) == MEM
659           && (INTVAL (operands[1]) & ~0xff0000) == 0)
660         {
661           cc_status.flags |= CC_NOT_NEGATIVE;
662           operands[1] = GEN_INT (INTVAL (operands[1]) >> 16);
663           operands[0] = adj_offsettable_operand (operands[0], 2);
664           return AS2 (test%B0,%1,%b0);
665         }
666
667       if (GET_CODE (operands[0]) == MEM
668           && (INTVAL (operands[1]) & ~0xff000000) == 0)
669         {
670           operands[1] = GEN_INT ((INTVAL (operands[1]) >> 24) & 0xff);
671           operands[0] = adj_offsettable_operand (operands[0], 3);
672           return AS2 (test%B0,%1,%b0);
673         }
674     }
675
676   if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
677     return AS2 (test%L0,%1,%0);
678
679   return AS2 (test%L1,%0,%1);
680 }")
681
682 (define_insn ""
683   [(set (cc0)
684         (and:HI (match_operand:HI 0 "general_operand" "%ro")
685                 (match_operand:HI 1 "general_operand" "ri")))]
686   ""
687   "*
688 {
689   if (GET_CODE (operands[1]) == CONST_INT
690       && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
691       && (! REG_P (operands[0]) || QI_REG_P (operands[0])))
692     {
693       if ((INTVAL (operands[1]) & 0xff00) == 0)
694         {
695           /* ??? This might not be necessary. */
696           if (INTVAL (operands[1]) & 0xffff0000)
697             operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
698
699           /* We may set the sign bit spuriously.  */
700           cc_status.flags |= CC_NOT_NEGATIVE;
701           return AS2 (test%B0,%1,%b0);
702         }
703
704       if ((INTVAL (operands[1]) & 0xff) == 0)
705         {
706           operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff);
707
708           if (QI_REG_P (operands[0]))
709             return AS2 (test%B0,%1,%h0);
710           else
711             {
712               operands[0] = adj_offsettable_operand (operands[0], 1);
713               return AS2 (test%B0,%1,%b0);
714             }
715         }
716     }
717
718   if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
719     return AS2 (test%W0,%1,%0);
720
721   return AS2 (test%W1,%0,%1);
722 }")
723
724 (define_insn ""
725   [(set (cc0)
726         (and:QI (match_operand:QI 0 "general_operand" "%qm")
727                 (match_operand:QI 1 "general_operand" "qi")))]
728   ""
729   "*
730 {
731   if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
732     return AS2 (test%B0,%1,%0);
733
734   return AS2 (test%B1,%0,%1);
735 }")
736 \f
737 ;; move instructions.
738 ;; There is one for each machine mode,
739 ;; and each is preceded by a corresponding push-insn pattern
740 ;; (since pushes are not general_operands on the 386).
741
742 (define_insn ""
743   [(set (match_operand:SI 0 "push_operand" "=<")
744         (match_operand:SI 1 "general_operand" "g"))]
745   "TARGET_386"
746   "push%L0 %1")
747
748 ;; On a 486, it is faster to move MEM to a REG and then push, rather than
749 ;; push MEM directly.
750
751 (define_insn ""
752   [(set (match_operand:SI 0 "push_operand" "=<")
753         (match_operand:SI 1 "nonmemory_operand" "ri"))]
754   "!TARGET_386 && TARGET_MOVE"
755   "push%L0 %1")
756
757 (define_insn ""
758   [(set (match_operand:SI 0 "push_operand" "=<")
759         (match_operand:SI 1 "general_operand" "ri"))]
760   "!TARGET_386 && !TARGET_MOVE"
761   "push%L0 %1")
762
763 ;; General case of fullword move.
764
765 ;; If generating PIC code and operands[1] is a symbolic CONST, emit a
766 ;; move to get the address of the symbolic object from the GOT.
767
768 (define_expand "movsi"
769   [(set (match_operand:SI 0 "general_operand" "")
770         (match_operand:SI 1 "general_operand" ""))]
771   ""
772   "
773 {
774   extern int flag_pic;
775
776   if (flag_pic && SYMBOLIC_CONST (operands[1]))
777     emit_pic_move (operands, SImode);
778
779   /* Don't generate memory->memory moves, go through a register */
780   else if (TARGET_MOVE
781            && (reload_in_progress | reload_completed) == 0
782            && GET_CODE (operands[0]) == MEM
783            && GET_CODE (operands[1]) == MEM)
784     {
785       operands[1] = force_reg (SImode, operands[1]);
786     }
787 }")
788
789 ;; On i486, incl reg is faster than movl $1,reg.
790
791 (define_insn ""
792   [(set (match_operand:SI 0 "general_operand" "=g,r")
793         (match_operand:SI 1 "general_operand" "ri,m"))]
794   "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
795   "*
796 {
797   rtx link;
798   if (operands[1] == const0_rtx && REG_P (operands[0]))
799     return AS2 (xor%L0,%0,%0);
800
801   if (operands[1] == const1_rtx
802       && (link = find_reg_note (insn, REG_WAS_0, 0))
803       /* Make sure the insn that stored the 0 is still present.  */
804       && ! INSN_DELETED_P (XEXP (link, 0))
805       && GET_CODE (XEXP (link, 0)) != NOTE
806       /* Make sure cross jumping didn't happen here.  */
807       && no_labels_between_p (XEXP (link, 0), insn)
808       /* Make sure the reg hasn't been clobbered.  */
809       && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
810     /* Fastest way to change a 0 to a 1.  */
811     return AS1 (inc%L0,%0);
812
813   if (flag_pic && SYMBOLIC_CONST (operands[1]))
814     return AS2 (lea%L0,%a1,%0);
815
816   return AS2 (mov%L0,%1,%0);
817 }")
818
819 (define_insn ""
820   [(set (match_operand:HI 0 "push_operand" "=<")
821         (match_operand:HI 1 "general_operand" "g"))]
822   "TARGET_386"
823   "push%W0 %1")
824
825 (define_insn ""
826   [(set (match_operand:HI 0 "push_operand" "=<")
827         (match_operand:HI 1 "nonmemory_operand" "ri"))]
828   "!TARGET_386 && TARGET_MOVE"
829   "push%W0 %1")
830
831 (define_insn ""
832   [(set (match_operand:HI 0 "push_operand" "=<")
833         (match_operand:HI 1 "general_operand" "ri"))]
834   "!TARGET_386 && !TARGET_MOVE"
835   "push%W0 %1")
836
837 ;; On i486, an incl and movl are both faster than incw and movw.
838
839 (define_expand "movhi"
840   [(set (match_operand:HI 0 "general_operand" "")
841         (match_operand:HI 1 "general_operand" ""))]
842   ""
843   "
844 {
845   /* Don't generate memory->memory moves, go through a register */
846   if (TARGET_MOVE
847       && (reload_in_progress | reload_completed) == 0
848       && GET_CODE (operands[0]) == MEM
849       && GET_CODE (operands[1]) == MEM)
850     {
851       operands[1] = force_reg (HImode, operands[1]);
852     }
853 }")
854
855 (define_insn ""
856   [(set (match_operand:HI 0 "general_operand" "=g,r")
857         (match_operand:HI 1 "general_operand" "ri,m"))]
858   "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
859   "*
860 {
861   rtx link;
862   if (REG_P (operands[0]) && operands[1] == const0_rtx)
863     return AS2 (xor%L0,%k0,%k0);
864
865   if (REG_P (operands[0]) && operands[1] == const1_rtx 
866       && (link = find_reg_note (insn, REG_WAS_0, 0))
867       /* Make sure the insn that stored the 0 is still present.  */
868       && ! INSN_DELETED_P (XEXP (link, 0))
869       && GET_CODE (XEXP (link, 0)) != NOTE
870       /* Make sure cross jumping didn't happen here.  */
871       && no_labels_between_p (XEXP (link, 0), insn)
872       /* Make sure the reg hasn't been clobbered.  */
873       && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
874     /* Fastest way to change a 0 to a 1.  */
875     return AS1 (inc%L0,%k0);
876
877   if (REG_P (operands[0]))
878     {
879       if (REG_P (operands[1]))
880         return AS2 (mov%L0,%k1,%k0);
881       else if (CONSTANT_P (operands[1]))
882         return AS2 (mov%L0,%1,%k0);
883     }
884
885   return AS2 (mov%W0,%1,%0);
886 }")
887
888 (define_expand "movstricthi"
889   [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
890         (match_operand:HI 1 "general_operand" ""))]
891   ""
892   "
893 {
894   /* Don't generate memory->memory moves, go through a register */
895   if (TARGET_MOVE
896       && (reload_in_progress | reload_completed) == 0
897       && GET_CODE (operands[0]) == MEM
898       && GET_CODE (operands[1]) == MEM)
899     {
900       operands[1] = force_reg (HImode, operands[1]);
901     }
902 }")
903
904 (define_insn ""
905   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r"))
906         (match_operand:HI 1 "general_operand" "ri,m"))]
907   "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
908   "*
909 {
910   rtx link;
911   if (operands[1] == const0_rtx && REG_P (operands[0]))
912     return AS2 (xor%W0,%0,%0);
913
914   if (operands[1] == const1_rtx
915       && (link = find_reg_note (insn, REG_WAS_0, 0))
916       /* Make sure the insn that stored the 0 is still present.  */
917       && ! INSN_DELETED_P (XEXP (link, 0))
918       && GET_CODE (XEXP (link, 0)) != NOTE
919       /* Make sure cross jumping didn't happen here.  */
920       && no_labels_between_p (XEXP (link, 0), insn)
921       /* Make sure the reg hasn't been clobbered.  */
922       && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
923     /* Fastest way to change a 0 to a 1.  */
924     return AS1 (inc%W0,%0);
925
926   return AS2 (mov%W0,%1,%0);
927 }")
928
929 ;; emit_push_insn when it calls move_by_pieces
930 ;; requires an insn to "push a byte".
931 ;; But actually we use pushw, which has the effect of rounding
932 ;; the amount pushed up to a halfword.
933 (define_insn ""
934   [(set (match_operand:QI 0 "push_operand" "=<")
935         (match_operand:QI 1 "immediate_operand" "n"))]
936   ""
937   "* return AS1 (push%W0,%1);")
938
939 (define_insn ""
940   [(set (match_operand:QI 0 "push_operand" "=<")
941         (match_operand:QI 1 "nonimmediate_operand" "q"))]
942   "!TARGET_MOVE"
943   "*
944 {
945   operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
946   return AS1 (push%W0,%1);
947 }")
948
949 (define_insn ""
950   [(set (match_operand:QI 0 "push_operand" "=<")
951         (match_operand:QI 1 "register_operand" "q"))]
952   "TARGET_MOVE"
953   "*
954 {
955   operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
956   return AS1 (push%W0,%1);
957 }")
958
959 ;; On i486, incb reg is faster than movb $1,reg.
960
961 ;; ??? Do a recognizer for zero_extract that looks just like this, but reads
962 ;; or writes %ah, %bh, %ch, %dh.
963
964 (define_expand "movqi"
965   [(set (match_operand:QI 0 "general_operand" "")
966         (match_operand:QI 1 "general_operand" ""))]
967   ""
968   "
969 {
970   /* Don't generate memory->memory moves, go through a register */
971   if (TARGET_MOVE
972       && (reload_in_progress | reload_completed) == 0
973       && GET_CODE (operands[0]) == MEM
974       && GET_CODE (operands[1]) == MEM)
975     {
976       operands[1] = force_reg (QImode, operands[1]);
977     }
978 }")
979
980 (define_insn ""
981   [(set (match_operand:QI 0 "general_operand" "=q,*r,qm")
982         (match_operand:QI 1 "general_operand" "*g,q,qn"))]
983   "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
984   "*
985 {
986   rtx link;
987   if (operands[1] == const0_rtx && REG_P (operands[0]))
988     return AS2 (xor%B0,%0,%0);
989
990   if (operands[1] == const1_rtx
991       && (link = find_reg_note (insn, REG_WAS_0, 0))
992       /* Make sure the insn that stored the 0 is still present.  */
993       && ! INSN_DELETED_P (XEXP (link, 0))
994       && GET_CODE (XEXP (link, 0)) != NOTE
995       /* Make sure cross jumping didn't happen here.  */
996       && no_labels_between_p (XEXP (link, 0), insn)
997       /* Make sure the reg hasn't been clobbered.  */
998       && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
999     /* Fastest way to change a 0 to a 1.  */
1000     return AS1 (inc%B0,%0);
1001
1002   /* If mov%B0 isn't allowed for one of these regs, use mov%L0.  */
1003   if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
1004     return (AS2 (mov%L0,%k1,%k0));
1005
1006   return (AS2 (mov%B0,%1,%0));
1007 }")
1008
1009 ;; If it becomes necessary to support movstrictqi into %esi or %edi,
1010 ;; use the insn sequence:
1011 ;;
1012 ;;      shrdl $8,srcreg,dstreg
1013 ;;      rorl $24,dstreg
1014 ;;
1015 ;; If operands[1] is a constant, then an andl/orl sequence would be
1016 ;; faster.
1017
1018 (define_expand "movstrictqi"
1019   [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
1020         (match_operand:QI 1 "general_operand" ""))]
1021   ""
1022   "
1023 {
1024   /* Don't generate memory->memory moves, go through a register */
1025   if (TARGET_MOVE
1026       && (reload_in_progress | reload_completed) == 0
1027       && GET_CODE (operands[0]) == MEM
1028       && GET_CODE (operands[1]) == MEM)
1029     {
1030       operands[1] = force_reg (QImode, operands[1]);
1031     }
1032 }")
1033
1034 (define_insn ""
1035   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q"))
1036         (match_operand:QI 1 "general_operand" "*qn,m"))]
1037   "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1038   "*
1039 {
1040   rtx link;
1041   if (operands[1] == const0_rtx && REG_P (operands[0]))
1042     return AS2 (xor%B0,%0,%0);
1043
1044   if (operands[1] == const1_rtx
1045       && (link = find_reg_note (insn, REG_WAS_0, 0))
1046       /* Make sure the insn that stored the 0 is still present.  */
1047       && ! INSN_DELETED_P (XEXP (link, 0))
1048       && GET_CODE (XEXP (link, 0)) != NOTE
1049       /* Make sure cross jumping didn't happen here.  */
1050       && no_labels_between_p (XEXP (link, 0), insn)
1051       /* Make sure the reg hasn't been clobbered.  */
1052       && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
1053     /* Fastest way to change a 0 to a 1.  */
1054     return AS1 (inc%B0,%0);
1055
1056   /* If mov%B0 isn't allowed for one of these regs, use mov%L0.  */
1057   if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
1058     {
1059       abort ();
1060       return (AS2 (mov%L0,%k1,%k0));
1061     }
1062
1063   return AS2 (mov%B0,%1,%0);
1064 }")
1065
1066 (define_expand "movsf"
1067   [(set (match_operand:SF 0 "general_operand" "")
1068         (match_operand:SF 1 "general_operand" ""))]
1069   ""
1070   "
1071 {
1072   /* Special case memory->memory moves and pushes */
1073   if (TARGET_MOVE
1074       && (reload_in_progress | reload_completed) == 0
1075       && GET_CODE (operands[0]) == MEM
1076       && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode)))
1077     {
1078       rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode))
1079                                                 ? gen_movsf_push
1080                                                 : gen_movsf_mem;
1081
1082       emit_insn ((*genfunc) (operands[0], operands[1]));
1083       DONE;
1084     }
1085
1086   /* If we are loading a floating point constant that isn't 0 or 1 into a register,
1087      indicate we need the pic register loaded.  This could be optimized into stores
1088      of constants if the target eventually moves to memory, but better safe than
1089      sorry.  */
1090   if (flag_pic
1091       && GET_CODE (operands[0]) != MEM
1092       && GET_CODE (operands[1]) == CONST_DOUBLE
1093       && !standard_80387_constant_p (operands[1]))
1094     {
1095       current_function_uses_pic_offset_table = 1;
1096     }
1097 }")
1098
1099 (define_insn "movsf_push_nomove"
1100   [(set (match_operand:SF 0 "push_operand" "=<,<")
1101         (match_operand:SF 1 "general_operand" "gF,f"))]
1102   "!TARGET_MOVE"
1103   "*
1104 {
1105   if (STACK_REG_P (operands[1]))
1106     {
1107       rtx xops[3];
1108
1109       if (! STACK_TOP_P (operands[1]))
1110         abort ();
1111
1112       xops[0] = AT_SP (SFmode);
1113       xops[1] = GEN_INT (4);
1114       xops[2] = stack_pointer_rtx;
1115
1116       output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1117
1118       if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1119         output_asm_insn (AS1 (fstp%S0,%0), xops);
1120       else
1121         output_asm_insn (AS1 (fst%S0,%0), xops);
1122       RET;
1123     }
1124   return AS1 (push%L1,%1);
1125 }")
1126
1127 (define_insn "movsf_push"
1128   [(set (match_operand:SF 0 "push_operand" "=<,<,<,<")
1129         (match_operand:SF 1 "general_operand" "rF,f,m,m"))
1130    (clobber (match_scratch:SI 2 "=X,X,r,X"))]
1131   ""
1132   "*
1133 {
1134   if (STACK_REG_P (operands[1]))
1135     {
1136       rtx xops[3];
1137
1138       if (! STACK_TOP_P (operands[1]))
1139         abort ();
1140
1141       xops[0] = AT_SP (SFmode);
1142       xops[1] = GEN_INT (4);
1143       xops[2] = stack_pointer_rtx;
1144
1145       output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1146
1147       if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1148         output_asm_insn (AS1 (fstp%S0,%0), xops);
1149       else
1150         output_asm_insn (AS1 (fst%S0,%0), xops);
1151       RET;
1152     }
1153
1154   else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG)
1155     return AS1 (push%L1,%1);
1156
1157   else
1158     {
1159       output_asm_insn (AS2 (mov%L2,%1,%2), operands);
1160       return AS1 (push%L2,%2);
1161     }
1162 }")
1163
1164 ;; Special memory<->memory pattern that combine will recreate from the
1165 ;; moves to pseudos.
1166 (define_insn "movsf_mem"
1167   [(set (match_operand:SF 0 "memory_operand" "=m")
1168         (match_operand:SF 1 "memory_operand" "m"))
1169    (clobber (match_scratch:SI 2 "=&r"))]
1170   ""
1171   "*
1172 {
1173   output_asm_insn (AS2 (mov%L2,%1,%2), operands);
1174   return AS2 (mov%L0,%2,%0);
1175 }")
1176
1177 ;; For the purposes of regclass, prefer FLOAT_REGS.
1178 (define_insn "movsf_normal"
1179   [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm")
1180         (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))]
1181   "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1182   "*
1183 {
1184   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1185
1186   /* First handle a `pop' insn or a `fld %st(0)' */
1187
1188   if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
1189     {
1190       if (stack_top_dies)
1191         return AS1 (fstp,%y0);
1192       else
1193         return AS1 (fld,%y0);
1194     }
1195
1196   /* Handle a transfer between the 387 and a 386 register */
1197
1198   if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
1199     {
1200       output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1201       RET;
1202     }
1203
1204   if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
1205     {
1206       output_to_reg (operands[0], stack_top_dies);
1207       RET;
1208     }
1209
1210   /* Handle other kinds of writes from the 387 */
1211
1212   if (STACK_TOP_P (operands[1]))
1213     {
1214       if (stack_top_dies)
1215         return AS1 (fstp%z0,%y0);
1216       else
1217         return AS1 (fst%z0,%y0);
1218     }
1219
1220   /* Handle other kinds of reads to the 387 */
1221
1222   if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
1223     return output_move_const_single (operands);
1224
1225   if (STACK_TOP_P (operands[0]))
1226     return AS1 (fld%z1,%y1);
1227
1228   /* Handle all SFmode moves not involving the 387 */
1229
1230   return singlemove_string (operands);
1231 }")
1232
1233 (define_insn "swapsf"
1234   [(set (match_operand:SF 0 "register_operand" "f")
1235         (match_operand:SF 1 "register_operand" "f"))
1236    (set (match_dup 1)
1237         (match_dup 0))]
1238   ""
1239   "*
1240 {
1241   if (STACK_TOP_P (operands[0]))
1242     return AS1 (fxch,%1);
1243   else
1244     return AS1 (fxch,%0);
1245 }")
1246
1247 (define_expand "movdf"
1248   [(set (match_operand:DF 0 "general_operand" "")
1249         (match_operand:DF 1 "general_operand" ""))]
1250   ""
1251   "
1252 {
1253   /* Special case memory->memory moves and pushes */
1254   if (TARGET_MOVE
1255       && (reload_in_progress | reload_completed) == 0
1256       && GET_CODE (operands[0]) == MEM
1257       && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode)))
1258     {
1259       rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode))
1260                                                 ? gen_movdf_push
1261                                                 : gen_movdf_mem;
1262
1263       emit_insn ((*genfunc) (operands[0], operands[1]));
1264       DONE;
1265     }
1266
1267   /* If we are loading a floating point constant that isn't 0 or 1 into a register,
1268      indicate we need the pic register loaded.  This could be optimized into stores
1269      of constants if the target eventually moves to memory, but better safe than
1270      sorry.  */
1271   if (flag_pic
1272       && GET_CODE (operands[0]) != MEM
1273       && GET_CODE (operands[1]) == CONST_DOUBLE
1274       && !standard_80387_constant_p (operands[1]))
1275     {
1276       current_function_uses_pic_offset_table = 1;
1277     }
1278 }")
1279
1280 (define_insn "movdf_push_nomove"
1281   [(set (match_operand:DF 0 "push_operand" "=<,<")
1282         (match_operand:DF 1 "general_operand" "gF,f"))]
1283   "!TARGET_MOVE"
1284   "*
1285 {
1286   if (STACK_REG_P (operands[1]))
1287     {
1288       rtx xops[3];
1289
1290       xops[0] = AT_SP (SFmode);
1291       xops[1] = GEN_INT (8);
1292       xops[2] = stack_pointer_rtx;
1293
1294       output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1295
1296       if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1297         output_asm_insn (AS1 (fstp%Q0,%0), xops);
1298       else
1299         output_asm_insn (AS1 (fst%Q0,%0), xops);
1300
1301       RET;
1302     }
1303   else
1304     return output_move_double (operands);
1305 }")
1306
1307 (define_insn "movdf_push"
1308   [(set (match_operand:DF 0 "push_operand" "=<,<,<,<,<")
1309         (match_operand:DF 1 "general_operand" "rF,f,o,o,o"))
1310    (clobber (match_scratch:SI 2 "=X,X,&r,&r,X"))
1311    (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))]
1312   ""
1313   "*
1314 {
1315   if (STACK_REG_P (operands[1]))
1316     {
1317       rtx xops[3];
1318
1319       xops[0] = AT_SP (SFmode);
1320       xops[1] = GEN_INT (8);
1321       xops[2] = stack_pointer_rtx;
1322
1323       output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1324
1325       if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1326         output_asm_insn (AS1 (fstp%Q0,%0), xops);
1327       else
1328         output_asm_insn (AS1 (fst%Q0,%0), xops);
1329
1330       RET;
1331     }
1332
1333   else if (GET_CODE (operands[1]) != MEM)
1334     return output_move_double (operands);
1335
1336   else
1337     return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);
1338 }")
1339
1340 (define_insn "movdf_mem"
1341   [(set (match_operand:DF 0 "memory_operand" "=o,o")
1342         (match_operand:DF 1 "memory_operand" "o,o"))
1343    (clobber (match_scratch:SI 2 "=&r,&r"))
1344    (clobber (match_scratch:SI 3 "=&r,X"))]
1345   ""
1346   "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);")
1347
1348 ;; For the purposes of regclass, prefer FLOAT_REGS.
1349 (define_insn "movdf_normal"
1350   [(set (match_operand:DF 0 "general_operand" "=f,fm,!*rf,!*rm")
1351         (match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
1352   "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1353   "*
1354 {
1355   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1356
1357   /* First handle a `pop' insn or a `fld %st(0)' */
1358
1359   if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
1360     {
1361       if (stack_top_dies)
1362         return AS1 (fstp,%y0);
1363       else
1364         return AS1 (fld,%y0);
1365     }
1366
1367   /* Handle a transfer between the 387 and a 386 register */
1368
1369   if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
1370     {
1371       output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1372       RET;
1373     }
1374
1375   if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
1376     {
1377       output_to_reg (operands[0], stack_top_dies);
1378       RET;
1379     }
1380
1381   /* Handle other kinds of writes from the 387 */
1382
1383   if (STACK_TOP_P (operands[1]))
1384     {
1385       if (stack_top_dies)
1386         return AS1 (fstp%z0,%y0);
1387       else
1388         return AS1 (fst%z0,%y0);
1389     }
1390
1391   /* Handle other kinds of reads to the 387 */
1392
1393   if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
1394     return output_move_const_single (operands);
1395
1396   if (STACK_TOP_P (operands[0]))
1397     return AS1 (fld%z1,%y1);
1398
1399   /* Handle all DFmode moves not involving the 387 */
1400
1401   return output_move_double (operands);
1402 }")
1403
1404 (define_insn "swapdf"
1405   [(set (match_operand:DF 0 "register_operand" "f")
1406         (match_operand:DF 1 "register_operand" "f"))
1407    (set (match_dup 1)
1408         (match_dup 0))]
1409   ""
1410   "*
1411 {
1412   if (STACK_TOP_P (operands[0]))
1413     return AS1 (fxch,%1);
1414   else
1415     return AS1 (fxch,%0);
1416 }")
1417
1418 (define_expand "movxf"
1419   [(set (match_operand:XF 0 "general_operand" "")
1420         (match_operand:XF 1 "general_operand" ""))]
1421   ""
1422   "
1423 {
1424   /* Special case memory->memory moves and pushes */
1425   if (TARGET_MOVE
1426       && (reload_in_progress | reload_completed) == 0
1427       && GET_CODE (operands[0]) == MEM
1428       && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], XFmode)))
1429     {
1430       rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], XFmode))
1431                                                 ? gen_movxf_push
1432                                                 : gen_movxf_mem;
1433
1434       emit_insn ((*genfunc) (operands[0], operands[1]));
1435       DONE;
1436     }
1437
1438   /* If we are loading a floating point constant that isn't 0 or 1 into a register,
1439      indicate we need the pic register loaded.  This could be optimized into stores
1440      of constants if the target eventually moves to memory, but better safe than
1441      sorry.  */
1442   if (flag_pic
1443       && GET_CODE (operands[0]) != MEM
1444       && GET_CODE (operands[1]) == CONST_DOUBLE
1445       && !standard_80387_constant_p (operands[1]))
1446     {
1447       current_function_uses_pic_offset_table = 1;
1448     }
1449 }")
1450
1451
1452 (define_insn "movxf_push_nomove"
1453   [(set (match_operand:XF 0 "push_operand" "=<,<")
1454         (match_operand:XF 1 "general_operand" "gF,f"))]
1455   "!TARGET_MOVE"
1456   "*
1457 {
1458   if (STACK_REG_P (operands[1]))
1459     {
1460       rtx xops[3];
1461
1462       xops[0] = AT_SP (SFmode);
1463       xops[1] = GEN_INT (12);
1464       xops[2] = stack_pointer_rtx;
1465
1466       output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1467       output_asm_insn (AS1 (fstp%T0,%0), xops);
1468       if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1469         output_asm_insn (AS1 (fld%T0,%0), xops);
1470
1471       RET;
1472     }
1473   else
1474     return output_move_double (operands);
1475  }")
1476
1477 (define_insn "movxf_push"
1478   [(set (match_operand:XF 0 "push_operand" "=<,<,<,<,<")
1479         (match_operand:XF 1 "general_operand" "rF,f,o,o,o"))
1480    (clobber (match_scratch:SI 2 "=X,X,&r,&r,X"))
1481    (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))]
1482   ""
1483   "*
1484 {
1485   if (STACK_REG_P (operands[1]))
1486     {
1487       rtx xops[3];
1488
1489       xops[0] = AT_SP (SFmode);
1490       xops[1] = GEN_INT (12);
1491       xops[2] = stack_pointer_rtx;
1492
1493       output_asm_insn (AS2 (sub%L2,%1,%2), xops);
1494       output_asm_insn (AS1 (fstp%T0,%0), xops);
1495       if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
1496         output_asm_insn (AS1 (fld%T0,%0), xops);
1497
1498       RET;
1499     }
1500
1501   else if (GET_CODE (operands[1]) != MEM
1502            || GET_CODE (operands[2]) != REG)
1503     return output_move_double (operands);
1504
1505   else
1506     return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);
1507 }")
1508
1509 (define_insn "movxf_mem"
1510   [(set (match_operand:XF 0 "memory_operand" "=o,o")
1511         (match_operand:XF 1 "memory_operand" "o,o"))
1512    (clobber (match_scratch:SI 2 "=&r,&r"))
1513    (clobber (match_scratch:SI 3 "=&r,X"))]
1514   ""
1515   "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);")
1516
1517 (define_insn "movxf_normal"
1518   [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm")
1519         (match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
1520   "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
1521   "*
1522 {
1523   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1524
1525   /* First handle a `pop' insn or a `fld %st(0)' */
1526
1527   if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
1528     {
1529       if (stack_top_dies)
1530         return AS1 (fstp,%y0);
1531       else
1532         return AS1 (fld,%y0);
1533     }
1534
1535   /* Handle a transfer between the 387 and a 386 register */
1536
1537   if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
1538     {
1539       output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1540       RET;
1541     }
1542
1543   if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
1544     {
1545       output_to_reg (operands[0], stack_top_dies);
1546       RET;
1547     }
1548
1549   /* Handle other kinds of writes from the 387 */
1550
1551   if (STACK_TOP_P (operands[1]))
1552     {
1553       output_asm_insn (AS1 (fstp%z0,%y0), operands);
1554       if (! stack_top_dies)
1555         return AS1 (fld%z0,%y0);
1556
1557       RET;
1558     }
1559
1560   /* Handle other kinds of reads to the 387 */
1561
1562   if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
1563     return output_move_const_single (operands);
1564
1565   if (STACK_TOP_P (operands[0]))
1566        return AS1 (fld%z1,%y1);
1567
1568   /* Handle all XFmode moves not involving the 387 */
1569
1570   return output_move_double (operands);
1571 }")
1572
1573 (define_insn "swapxf"
1574   [(set (match_operand:XF 0 "register_operand" "f")
1575         (match_operand:XF 1 "register_operand" "f"))
1576    (set (match_dup 1)
1577         (match_dup 0))]
1578   ""
1579   "*
1580 {
1581   if (STACK_TOP_P (operands[0]))
1582     return AS1 (fxch,%1);
1583   else
1584     return AS1 (fxch,%0);
1585 }")
1586
1587 (define_insn ""
1588   [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
1589         (match_operand:DI 1 "general_operand" "riF,o,o,o"))
1590    (clobber (match_scratch:SI 2 "=X,&r,&r,X"))
1591    (clobber (match_scratch:SI 3 "=X,&r,X,X"))]
1592   ""
1593   "*
1594 {
1595   if (GET_CODE (operands[1]) != MEM)
1596     return output_move_double (operands);
1597
1598   else
1599     return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
1600 }")
1601
1602 (define_insn "movdi"
1603   [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm")
1604         (match_operand:DI 1 "general_operand" "o,o,m,riF"))
1605    (clobber (match_scratch:SI 2 "=&r,&r,X,X"))
1606    (clobber (match_scratch:SI 3 "=&r,X,X,X"))]
1607   ""
1608   "*
1609 {
1610   rtx low[2], high[2], xop[6];
1611
1612   if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
1613     return output_move_double (operands);
1614   else
1615     return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
1616 }")
1617
1618 \f
1619 ;;- conversion instructions
1620 ;;- NONE
1621
1622 ;;- zero extension instructions
1623 ;; See comments by `andsi' for when andl is faster than movzx.
1624
1625 (define_insn "zero_extendhisi2"
1626   [(set (match_operand:SI 0 "general_operand" "=r")
1627         (zero_extend:SI
1628          (match_operand:HI 1 "nonimmediate_operand" "rm")))]
1629   ""
1630   "*
1631 {
1632   if ((!TARGET_386 || REGNO (operands[0]) == 0)
1633       && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
1634     {
1635       rtx xops[2];
1636       xops[0] = operands[0];
1637       xops[1] = GEN_INT (0xffff);
1638       output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1639       RET;
1640     }
1641
1642 #ifdef INTEL_SYNTAX
1643   return AS2 (movzx,%1,%0);
1644 #else
1645   return AS2 (movz%W0%L0,%1,%0);
1646 #endif
1647 }")
1648
1649 (define_insn "zero_extendqihi2"
1650   [(set (match_operand:HI 0 "general_operand" "=r")
1651         (zero_extend:HI
1652          (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1653   ""
1654   "*
1655 {
1656   if ((!TARGET_386 || REGNO (operands[0]) == 0)
1657       && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
1658     {
1659       rtx xops[2];
1660       xops[0] = operands[0];
1661       xops[1] = GEN_INT (0xff);
1662       output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1663       RET;
1664     }
1665
1666 #ifdef INTEL_SYNTAX
1667   return AS2 (movzx,%1,%0);
1668 #else
1669   return AS2 (movz%B0%W0,%1,%0);
1670 #endif
1671 }")
1672
1673 (define_insn "zero_extendqisi2"
1674   [(set (match_operand:SI 0 "general_operand" "=r")
1675         (zero_extend:SI
1676          (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1677   ""
1678   "*
1679 {
1680   if ((!TARGET_386 || REGNO (operands[0]) == 0)
1681       && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
1682     {
1683       rtx xops[2];
1684       xops[0] = operands[0];
1685       xops[1] = GEN_INT (0xff);
1686       output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1687       RET;
1688     }
1689
1690 #ifdef INTEL_SYNTAX
1691   return AS2 (movzx,%1,%0);
1692 #else
1693   return AS2 (movz%B0%L0,%1,%0);
1694 #endif
1695 }")
1696
1697 (define_insn "zero_extendsidi2"
1698   [(set (match_operand:DI 0 "register_operand" "=r")
1699         (zero_extend:DI
1700          (match_operand:SI 1 "register_operand" "0")))]
1701   ""
1702   "*
1703 {
1704   operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1705   return AS2 (xor%L0,%0,%0);
1706 }")
1707 \f
1708 ;;- sign extension instructions
1709
1710 (define_insn "extendsidi2"
1711   [(set (match_operand:DI 0 "register_operand" "=r")
1712         (sign_extend:DI
1713          (match_operand:SI 1 "register_operand" "0")))]
1714   ""
1715   "*
1716 {
1717   if (REGNO (operands[0]) == 0)
1718     {
1719       /* This used to be cwtl, but that extends HI to SI somehow.  */
1720 #ifdef INTEL_SYNTAX
1721       return \"cdq\";
1722 #else
1723       return \"cltd\";
1724 #endif
1725     }
1726
1727   operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1728   output_asm_insn (AS2 (mov%L0,%0,%1), operands);
1729
1730   operands[0] = GEN_INT (31);
1731   return AS2 (sar%L1,%0,%1);
1732 }")
1733
1734 ;; Note that the i386 programmers' manual says that the opcodes
1735 ;; are named movsx..., but the assembler on Unix does not accept that.
1736 ;; We use what the Unix assembler expects.
1737
1738 (define_insn "extendhisi2"
1739   [(set (match_operand:SI 0 "general_operand" "=r")
1740         (sign_extend:SI
1741          (match_operand:HI 1 "nonimmediate_operand" "rm")))]
1742   ""
1743   "*
1744 {
1745   if (REGNO (operands[0]) == 0
1746       && REG_P (operands[1]) && REGNO (operands[1]) == 0)
1747 #ifdef INTEL_SYNTAX
1748     return \"cwde\";
1749 #else
1750     return \"cwtl\";
1751 #endif
1752
1753 #ifdef INTEL_SYNTAX
1754   return AS2 (movsx,%1,%0);
1755 #else
1756   return AS2 (movs%W0%L0,%1,%0);
1757 #endif
1758 }")
1759
1760 (define_insn "extendqihi2"
1761   [(set (match_operand:HI 0 "general_operand" "=r")
1762         (sign_extend:HI
1763          (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1764   ""
1765   "*
1766 {
1767   if (REGNO (operands[0]) == 0
1768       && REG_P (operands[1]) && REGNO (operands[1]) == 0)
1769     return \"cbtw\";
1770
1771 #ifdef INTEL_SYNTAX
1772   return AS2 (movsx,%1,%0);
1773 #else
1774   return AS2 (movs%B0%W0,%1,%0);
1775 #endif
1776 }")
1777
1778 (define_insn "extendqisi2"
1779   [(set (match_operand:SI 0 "general_operand" "=r")
1780         (sign_extend:SI
1781          (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1782   ""
1783   "*
1784 {
1785 #ifdef INTEL_SYNTAX
1786   return AS2 (movsx,%1,%0);
1787 #else
1788   return AS2 (movs%B0%L0,%1,%0);
1789 #endif
1790 }")
1791 \f
1792 ;; Conversions between float and double.
1793
1794 (define_insn "extendsfdf2"
1795   [(set (match_operand:DF 0 "general_operand" "=fm,f")
1796         (float_extend:DF
1797          (match_operand:SF 1 "general_operand" "f,fm")))]
1798   "TARGET_80387"
1799   "*
1800 {
1801   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1802
1803   if (NON_STACK_REG_P (operands[1]))
1804     {
1805       output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1806       RET;
1807     }
1808
1809   if (NON_STACK_REG_P (operands[0]))
1810     {
1811       output_to_reg (operands[0], stack_top_dies);
1812       RET;
1813     }
1814
1815   if (STACK_TOP_P (operands[0]))
1816     return AS1 (fld%z1,%y1);
1817
1818   if (GET_CODE (operands[0]) == MEM)
1819     {
1820       if (stack_top_dies)
1821         return AS1 (fstp%z0,%y0);
1822       else
1823         return AS1 (fst%z0,%y0);
1824     }
1825
1826   abort ();
1827 }")
1828
1829 (define_insn "extenddfxf2"
1830   [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r")
1831         (float_extend:XF
1832          (match_operand:DF 1 "general_operand" "f,fm,!*r,f")))]
1833   "TARGET_80387"
1834   "*
1835 {
1836   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1837
1838   if (NON_STACK_REG_P (operands[1]))
1839     {
1840       output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1841       RET;
1842     }
1843
1844   if (NON_STACK_REG_P (operands[0]))
1845     {
1846       output_to_reg (operands[0], stack_top_dies);
1847       RET;
1848     }
1849
1850   if (STACK_TOP_P (operands[0]))
1851     return AS1 (fld%z1,%y1);
1852
1853   if (GET_CODE (operands[0]) == MEM)
1854     {
1855       output_asm_insn (AS1 (fstp%z0,%y0), operands);
1856       if (! stack_top_dies)
1857         return AS1 (fld%z0,%y0);
1858       RET;
1859     }
1860
1861   abort ();
1862 }")
1863
1864 (define_insn "extendsfxf2"
1865   [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r")
1866         (float_extend:XF
1867          (match_operand:SF 1 "general_operand" "f,fm,!*r,f")))]
1868   "TARGET_80387"
1869   "*
1870 {
1871   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1872
1873   if (NON_STACK_REG_P (operands[1]))
1874     {
1875       output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
1876       RET;
1877     }
1878
1879   if (NON_STACK_REG_P (operands[0]))
1880     {
1881       output_to_reg (operands[0], stack_top_dies);
1882       RET;
1883     }
1884
1885   if (STACK_TOP_P (operands[0]))
1886     return AS1 (fld%z1,%y1);
1887
1888   if (GET_CODE (operands[0]) == MEM)
1889     {
1890       output_asm_insn (AS1 (fstp%z0,%y0), operands);
1891       if (! stack_top_dies)
1892         return AS1 (fld%z0,%y0);
1893       RET;
1894     }
1895
1896   abort ();
1897 }")
1898
1899 (define_expand "truncdfsf2"
1900   [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
1901                    (float_truncate:SF
1902                     (match_operand:DF 1 "register_operand" "")))
1903               (clobber (match_dup 2))])]
1904   "TARGET_80387"
1905   "
1906 {
1907   operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
1908 }")
1909
1910 ;; This cannot output into an f-reg because there is no way to be sure
1911 ;; of truncating in that case.  Otherwise this is just like a simple move
1912 ;; insn.  So we pretend we can output to a reg in order to get better
1913 ;; register preferencing, but we really use a stack slot.
1914
1915 (define_insn ""
1916   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m")
1917         (float_truncate:SF
1918          (match_operand:DF 1 "register_operand" "0,f")))
1919    (clobber (match_operand:SF 2 "memory_operand" "m,m"))]
1920   "TARGET_80387"
1921   "*
1922 {
1923   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1924
1925   if (GET_CODE (operands[0]) == MEM)
1926     {
1927       if (stack_top_dies)
1928         return AS1 (fstp%z0,%0);
1929       else
1930         return AS1 (fst%z0,%0);
1931     }
1932   else if (STACK_TOP_P (operands[0]))
1933     {
1934       output_asm_insn (AS1 (fstp%z2,%y2), operands);
1935       return AS1 (fld%z2,%y2);
1936     }
1937   else
1938     abort ();
1939 }")
1940
1941 (define_insn "truncxfsf2"
1942   [(set (match_operand:SF 0 "general_operand" "=m,!*r")
1943         (float_truncate:SF
1944          (match_operand:XF 1 "register_operand" "f,f")))]
1945   "TARGET_80387"
1946   "*
1947 {
1948   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1949
1950   if (NON_STACK_REG_P (operands[0]))
1951     {
1952       if (stack_top_dies == 0)
1953         {
1954           output_asm_insn (AS1 (fld,%y1), operands);
1955           stack_top_dies = 1;
1956         }
1957       output_to_reg (operands[0], stack_top_dies);
1958       RET;
1959     }
1960   else if (GET_CODE (operands[0]) == MEM)
1961     {
1962       if (stack_top_dies)
1963         return AS1 (fstp%z0,%0);
1964       else
1965         {
1966           output_asm_insn (AS1 (fld,%y1), operands);
1967           return AS1 (fstp%z0,%0);
1968         }
1969     }
1970   else
1971     abort ();
1972 }")
1973
1974 (define_insn "truncxfdf2"
1975   [(set (match_operand:DF 0 "general_operand" "=m,!*r")
1976         (float_truncate:DF
1977          (match_operand:XF 1 "register_operand" "f,f")))]
1978   "TARGET_80387"
1979   "*
1980 {
1981   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1982
1983   if (NON_STACK_REG_P (operands[0]))
1984     {
1985       if (stack_top_dies == 0)
1986         {
1987           output_asm_insn (AS1 (fld,%y1), operands);
1988           stack_top_dies = 1;
1989         }
1990       output_to_reg (operands[0], stack_top_dies);
1991       RET;
1992     }
1993   else if (GET_CODE (operands[0]) == MEM)
1994     {
1995       if (stack_top_dies)
1996         return AS1 (fstp%z0,%0);
1997       else
1998         {
1999           output_asm_insn (AS1 (fld,%y1), operands);
2000           return AS1 (fstp%z0,%0);
2001         }
2002     }
2003   else
2004     abort ();
2005 }")
2006
2007 \f
2008 ;; The 387 requires that the stack top dies after converting to DImode.
2009
2010 ;; Represent an unsigned conversion from SImode to MODE_FLOAT by first
2011 ;; doing a signed conversion to DImode, and then taking just the low
2012 ;; part.
2013
2014 (define_expand "fixuns_truncxfsi2"
2015   [(set (match_dup 4)
2016         (match_operand:XF 1 "register_operand" ""))
2017    (parallel [(set (match_dup 2)
2018                    (fix:DI (fix:XF (match_dup 4))))
2019               (clobber (match_dup 4))
2020               (clobber (match_dup 5))
2021               (clobber (match_dup 6))
2022               (clobber (match_scratch:SI 7 ""))])
2023    (set (match_operand:SI 0 "general_operand" "")
2024         (match_dup 3))]
2025   "TARGET_80387"
2026   "
2027 {
2028   operands[2] = gen_reg_rtx (DImode);
2029   operands[3] = gen_lowpart (SImode, operands[2]);
2030   operands[4] = gen_reg_rtx (XFmode);
2031   operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2032   operands[6] = (rtx) assign_386_stack_local (SImode, 1);
2033 }")
2034
2035 (define_expand "fixuns_truncdfsi2"
2036   [(set (match_dup 4)
2037         (match_operand:DF 1 "register_operand" ""))
2038    (parallel [(set (match_dup 2)
2039                    (fix:DI (fix:DF (match_dup 4))))
2040               (clobber (match_dup 4))
2041               (clobber (match_dup 5))
2042               (clobber (match_dup 6))
2043               (clobber (match_scratch:SI 7 ""))])
2044    (set (match_operand:SI 0 "general_operand" "")
2045         (match_dup 3))]
2046   "TARGET_80387"
2047   "
2048 {
2049   operands[2] = gen_reg_rtx (DImode);
2050   operands[3] = gen_lowpart (SImode, operands[2]);
2051   operands[4] = gen_reg_rtx (DFmode);
2052   operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2053   operands[6] = (rtx) assign_386_stack_local (SImode, 1);
2054 }")
2055
2056 (define_expand "fixuns_truncsfsi2"
2057   [(set (match_dup 4)
2058         (match_operand:SF 1 "register_operand" ""))
2059    (parallel [(set (match_dup 2)
2060                    (fix:DI (fix:SF (match_dup 4))))
2061               (clobber (match_dup 4))
2062               (clobber (match_dup 5))
2063               (clobber (match_dup 6))
2064               (clobber (match_scratch:SI 7 ""))])
2065    (set (match_operand:SI 0 "general_operand" "")
2066         (match_dup 3))]
2067   "TARGET_80387"
2068   "
2069 {
2070   operands[2] = gen_reg_rtx (DImode);
2071   operands[3] = gen_lowpart (SImode, operands[2]);
2072   operands[4] = gen_reg_rtx (SFmode);
2073   operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2074   operands[6] = (rtx) assign_386_stack_local (SImode, 1);
2075 }")
2076
2077 ;; Signed conversion to DImode.
2078
2079 (define_expand "fix_truncxfdi2"
2080   [(set (match_dup 2)
2081         (match_operand:XF 1 "register_operand" ""))
2082    (parallel [(set (match_operand:DI 0 "general_operand" "")
2083                    (fix:DI (fix:XF (match_dup 2))))
2084               (clobber (match_dup 2))
2085               (clobber (match_dup 3))
2086               (clobber (match_dup 4))
2087               (clobber (match_scratch:SI 5 ""))])]
2088   "TARGET_80387"
2089   "
2090 {
2091   operands[1] = copy_to_mode_reg (XFmode, operands[1]);
2092   operands[2] = gen_reg_rtx (XFmode);
2093   operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2094   operands[4] = (rtx) assign_386_stack_local (SImode, 1);
2095 }")
2096
2097 (define_expand "fix_truncdfdi2"
2098   [(set (match_dup 2)
2099         (match_operand:DF 1 "register_operand" ""))
2100    (parallel [(set (match_operand:DI 0 "general_operand" "")
2101                    (fix:DI (fix:DF (match_dup 2))))
2102               (clobber (match_dup 2))
2103               (clobber (match_dup 3))
2104               (clobber (match_dup 4))
2105               (clobber (match_scratch:SI 5 ""))])]
2106   "TARGET_80387"
2107   "
2108 {
2109   operands[1] = copy_to_mode_reg (DFmode, operands[1]);
2110   operands[2] = gen_reg_rtx (DFmode);
2111   operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2112   operands[4] = (rtx) assign_386_stack_local (SImode, 1);
2113 }")
2114
2115 (define_expand "fix_truncsfdi2"
2116   [(set (match_dup 2)
2117         (match_operand:SF 1 "register_operand" ""))
2118    (parallel [(set (match_operand:DI 0 "general_operand" "")
2119                    (fix:DI (fix:SF (match_dup 2))))
2120               (clobber (match_dup 2))
2121               (clobber (match_dup 3))
2122               (clobber (match_dup 4))
2123               (clobber (match_scratch:SI 5 ""))])]
2124   "TARGET_80387"
2125   "
2126 {
2127   operands[1] = copy_to_mode_reg (SFmode, operands[1]);
2128   operands[2] = gen_reg_rtx (SFmode);
2129   operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2130   operands[4] = (rtx) assign_386_stack_local (SImode, 1);
2131 }")
2132
2133 ;; These match a signed conversion of either DFmode or SFmode to DImode.
2134
2135 (define_insn ""
2136   [(set (match_operand:DI 0 "general_operand" "=rm")
2137         (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
2138    (clobber (match_dup 1))
2139    (clobber (match_operand:SI 2 "memory_operand" "m"))
2140    (clobber (match_operand:SI 3 "memory_operand" "m"))
2141    (clobber (match_scratch:SI 4 "=&q"))]
2142   "TARGET_80387"
2143   "* return output_fix_trunc (insn, operands);")
2144
2145 (define_insn ""
2146   [(set (match_operand:DI 0 "general_operand" "=rm")
2147         (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
2148    (clobber (match_dup 1))
2149    (clobber (match_operand:SI 2 "memory_operand" "m"))
2150    (clobber (match_operand:SI 3 "memory_operand" "m"))
2151    (clobber (match_scratch:SI 4 "=&q"))]
2152   "TARGET_80387"
2153   "* return output_fix_trunc (insn, operands);")
2154
2155 (define_insn ""
2156   [(set (match_operand:DI 0 "general_operand" "=rm")
2157         (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
2158    (clobber (match_dup 1))
2159    (clobber (match_operand:SI 2 "memory_operand" "m"))
2160    (clobber (match_operand:SI 3 "memory_operand" "m"))
2161    (clobber (match_scratch:SI 4 "=&q"))]
2162   "TARGET_80387"
2163   "* return output_fix_trunc (insn, operands);")
2164
2165 ;; Signed MODE_FLOAT conversion to SImode.
2166
2167 (define_expand "fix_truncxfsi2"
2168   [(parallel [(set (match_operand:SI 0 "general_operand" "")
2169                    (fix:SI
2170                     (fix:XF (match_operand:XF 1 "register_operand" ""))))
2171               (clobber (match_dup 2))
2172               (clobber (match_dup 3))
2173               (clobber (match_scratch:SI 4 ""))])]
2174   "TARGET_80387"
2175   "
2176 {
2177   operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2178   operands[3] = (rtx) assign_386_stack_local (SImode, 1);
2179 }")
2180
2181 (define_expand "fix_truncdfsi2"
2182   [(parallel [(set (match_operand:SI 0 "general_operand" "")
2183                    (fix:SI
2184                     (fix:DF (match_operand:DF 1 "register_operand" ""))))
2185               (clobber (match_dup 2))
2186               (clobber (match_dup 3))
2187               (clobber (match_scratch:SI 4 ""))])]
2188   "TARGET_80387"
2189   "
2190 {
2191   operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2192   operands[3] = (rtx) assign_386_stack_local (SImode, 1);
2193 }")
2194
2195 (define_expand "fix_truncsfsi2"
2196   [(parallel [(set (match_operand:SI 0 "general_operand" "")
2197                    (fix:SI
2198                     (fix:SF (match_operand:SF 1 "register_operand" ""))))
2199               (clobber (match_dup 2))
2200               (clobber (match_dup 3))
2201               (clobber (match_scratch:SI 4 ""))])]
2202   "TARGET_80387"
2203   "
2204 {
2205   operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2206   operands[3] = (rtx) assign_386_stack_local (SImode, 1);
2207 }")
2208
2209 (define_insn ""
2210   [(set (match_operand:SI 0 "general_operand" "=rm")
2211         (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
2212    (clobber (match_operand:SI 2 "memory_operand" "m"))
2213    (clobber (match_operand:SI 3 "memory_operand" "m"))
2214    (clobber (match_scratch:SI 4 "=&q"))]
2215   "TARGET_80387"
2216   "* return output_fix_trunc (insn, operands);")
2217
2218 (define_insn ""
2219   [(set (match_operand:SI 0 "general_operand" "=rm")
2220         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
2221    (clobber (match_operand:SI 2 "memory_operand" "m"))
2222    (clobber (match_operand:SI 3 "memory_operand" "m"))
2223    (clobber (match_scratch:SI 4 "=&q"))]
2224   "TARGET_80387"
2225   "* return output_fix_trunc (insn, operands);")
2226
2227 (define_insn ""
2228   [(set (match_operand:SI 0 "general_operand" "=rm")
2229         (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
2230    (clobber (match_operand:SI 2 "memory_operand" "m"))
2231    (clobber (match_operand:SI 3 "memory_operand" "m"))
2232    (clobber (match_scratch:SI 4 "=&q"))]
2233   "TARGET_80387"
2234   "* return output_fix_trunc (insn, operands);")
2235 \f
2236 ;; Conversion between fixed point and floating point.
2237 ;; The actual pattern that matches these is at the end of this file.
2238
2239 ;; ??? Possibly represent floatunssidf2 here in gcc2.
2240
2241 (define_expand "floatsisf2"
2242   [(set (match_operand:SF 0 "register_operand" "")
2243         (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
2244   "TARGET_80387"
2245   "")
2246
2247 (define_expand "floatdisf2"
2248   [(set (match_operand:SF 0 "register_operand" "")
2249         (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
2250   "TARGET_80387"
2251   "")
2252
2253 (define_expand "floatsidf2"
2254   [(set (match_operand:DF 0 "register_operand" "")
2255         (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
2256   "TARGET_80387"
2257   "")
2258
2259 (define_expand "floatdidf2"
2260   [(set (match_operand:DF 0 "register_operand" "")
2261         (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
2262   "TARGET_80387"
2263   "")
2264
2265 (define_expand "floatsixf2"
2266   [(set (match_operand:XF 0 "register_operand" "")
2267         (float:XF (match_operand:SI 1 "nonimmediate_operand" "")))]
2268   "TARGET_80387"
2269   "")
2270
2271 (define_expand "floatdixf2"
2272   [(set (match_operand:XF 0 "register_operand" "")
2273         (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))]
2274   "TARGET_80387"
2275   "")
2276
2277 ;; This will convert from SImode or DImode to MODE_FLOAT.
2278
2279 (define_insn ""
2280   [(set (match_operand:XF 0 "register_operand" "=f")
2281         (float:XF (match_operand:DI 1 "general_operand" "rm")))]
2282   "TARGET_80387"
2283   "*
2284 {
2285   if (NON_STACK_REG_P (operands[1]))
2286     {
2287       output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2288       RET;
2289     }
2290   else if (GET_CODE (operands[1]) == MEM)
2291     return AS1 (fild%z1,%1);
2292   else
2293     abort ();
2294 }")
2295
2296 (define_insn ""
2297   [(set (match_operand:DF 0 "register_operand" "=f")
2298         (float:DF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2299   "TARGET_80387"
2300   "*
2301 {
2302   if (NON_STACK_REG_P (operands[1]))
2303     {
2304       output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2305       RET;
2306     }
2307   else if (GET_CODE (operands[1]) == MEM)
2308     return AS1 (fild%z1,%1);
2309   else
2310     abort ();
2311 }")
2312
2313 (define_insn ""
2314   [(set (match_operand:SF 0 "register_operand" "=f")
2315         (float:SF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2316   "TARGET_80387"
2317   "*
2318 {
2319   if (NON_STACK_REG_P (operands[1]))
2320     {
2321       output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2322       RET;
2323     }
2324   else if (GET_CODE (operands[1]) == MEM)
2325     return AS1 (fild%z1,%1);
2326   else
2327     abort ();
2328 }")
2329
2330 (define_insn ""
2331   [(set (match_operand:DF 0 "register_operand" "=f")
2332         (float:DF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
2333   "TARGET_80387"
2334   "*
2335 {
2336   if (NON_STACK_REG_P (operands[1]))
2337     {
2338       output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2339       RET;
2340     }
2341   else if (GET_CODE (operands[1]) == MEM)
2342     return AS1 (fild%z1,%1);
2343   else
2344     abort ();
2345 }")
2346
2347 (define_insn ""
2348   [(set (match_operand:XF 0 "register_operand" "=f,f")
2349         (float:XF (match_operand:SI 1 "general_operand" "m,!*r")))]
2350   "TARGET_80387"
2351   "*
2352 {
2353   if (NON_STACK_REG_P (operands[1]))
2354     {
2355       output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2356       RET;
2357     }
2358   else if (GET_CODE (operands[1]) == MEM)
2359     return AS1 (fild%z1,%1);
2360   else
2361     abort ();
2362 }")
2363
2364 (define_insn ""
2365   [(set (match_operand:SF 0 "register_operand" "=f")
2366         (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
2367   "TARGET_80387"
2368   "*
2369 {
2370   if (NON_STACK_REG_P (operands[1]))
2371     {
2372       output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2373       RET;
2374     }
2375   else if (GET_CODE (operands[1]) == MEM)
2376     return AS1 (fild%z1,%1);
2377   else
2378     abort ();
2379 }")
2380 \f
2381 ;;- add instructions
2382
2383 (define_insn "adddi3"
2384   [(set (match_operand:DI 0 "general_operand" "=&r,ro,o,&r,ro,o,&r,o,o,o")
2385         (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,o,riF,o,or,riF,riF,o")
2386                  (match_operand:DI 2 "general_operand" "o,riF,o,0,0,0,oriF,riF,o,o")))
2387    (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r,X,&r,&r,&r"))]
2388   ""
2389   "*
2390 {
2391   rtx low[3], high[3], xops[7], temp;
2392
2393   CC_STATUS_INIT;
2394
2395   if (rtx_equal_p (operands[0], operands[2]))
2396     {
2397       temp = operands[1];
2398       operands[1] = operands[2];
2399       operands[2] = temp;
2400     }
2401
2402   split_di (operands, 3, low, high);
2403   if (!rtx_equal_p (operands[0], operands[1]))
2404     {
2405       xops[0] = high[0];
2406       xops[1] = low[0];
2407       xops[2] = high[1];
2408       xops[3] = low[1];
2409
2410       if (GET_CODE (operands[0]) != MEM)
2411         {
2412           output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2413           output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2414         }
2415       else
2416         {
2417           xops[4] = high[2];
2418           xops[5] = low[2];
2419           xops[6] = operands[3];
2420           output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2421           output_asm_insn (AS2 (add%L6,%5,%6), xops);
2422           output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2423           output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2424           output_asm_insn (AS2 (adc%L6,%4,%6), xops);
2425           output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2426           RET;
2427         }
2428     }
2429
2430   if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
2431     {
2432       xops[0] = high[0];
2433       xops[1] = low[0];
2434       xops[2] = high[2];
2435       xops[3] = low[2];
2436       xops[4] = operands[3];
2437
2438       output_asm_insn (AS2 (mov%L4,%3,%4), xops);
2439       output_asm_insn (AS2 (add%L1,%4,%1), xops);
2440       output_asm_insn (AS2 (mov%L4,%2,%4), xops);
2441       output_asm_insn (AS2 (adc%L0,%4,%0), xops);
2442     }
2443
2444   else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
2445     {
2446       output_asm_insn (AS2 (add%L0,%2,%0), low);
2447       output_asm_insn (AS2 (adc%L0,%2,%0), high);
2448     }
2449
2450   else
2451     output_asm_insn (AS2 (add%L0,%2,%0), high);
2452
2453   RET;
2454 }")
2455
2456 ;; On a 486, it is faster to do movl/addl than to do a single leal if
2457 ;; operands[1] and operands[2] are both registers.
2458
2459 (define_insn "addsi3"
2460   [(set (match_operand:SI 0 "general_operand" "=?r,rm,r")
2461         (plus:SI (match_operand:SI 1 "general_operand" "%r,0,0")
2462                  (match_operand:SI 2 "general_operand" "ri,ri,rm")))]
2463   ""
2464   "*
2465 {
2466   if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
2467     {
2468       if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
2469         return AS2 (add%L0,%1,%0);
2470
2471       if (operands[2] == stack_pointer_rtx)
2472         {
2473           rtx temp;
2474
2475           temp = operands[1];
2476           operands[1] = operands[2];
2477           operands[2] = temp;
2478         }
2479
2480       if (operands[2] != stack_pointer_rtx)
2481         {
2482           CC_STATUS_INIT;
2483           operands[1] = SET_SRC (PATTERN (insn));
2484           return AS2 (lea%L0,%a1,%0);
2485         }
2486
2487       output_asm_insn (AS2 (mov%L0,%1,%0), operands);
2488     }
2489
2490   if (operands[2] == const1_rtx)
2491     return AS1 (inc%L0,%0);
2492
2493   if (operands[2] == constm1_rtx)
2494     return AS1 (dec%L0,%0);
2495
2496   return AS2 (add%L0,%2,%0);
2497 }")
2498
2499 ;; ??? `lea' here, for three operand add?  If leaw is used, only %bx,
2500 ;; %si and %di can appear in SET_SRC, and output_asm_insn might not be
2501 ;; able to handle the operand.  But leal always works?
2502
2503 (define_insn "addhi3"
2504   [(set (match_operand:HI 0 "general_operand" "=rm,r")
2505         (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
2506                  (match_operand:HI 2 "general_operand" "ri,rm")))]
2507   ""
2508   "*
2509 {
2510   /* ??? what about offsettable memory references? */
2511   if (QI_REG_P (operands[0])
2512       && GET_CODE (operands[2]) == CONST_INT
2513       && (INTVAL (operands[2]) & 0xff) == 0)
2514     {
2515       int byteval = (INTVAL (operands[2]) >> 8) & 0xff;
2516       CC_STATUS_INIT;
2517
2518       if (byteval == 1)
2519         return AS1 (inc%B0,%h0);
2520       else if (byteval == 255)
2521         return AS1 (dec%B0,%h0);
2522
2523       operands[2] = GEN_INT (byteval);
2524       return AS2 (add%B0,%2,%h0);
2525     }
2526
2527   if (operands[2] == const1_rtx)
2528     return AS1 (inc%W0,%0);
2529
2530   if (operands[2] == constm1_rtx
2531       || (GET_CODE (operands[2]) == CONST_INT
2532           && INTVAL (operands[2]) == 65535))
2533     return AS1 (dec%W0,%0);
2534
2535   return AS2 (add%W0,%2,%0);
2536 }")
2537
2538 (define_insn "addqi3"
2539   [(set (match_operand:QI 0 "general_operand" "=qm,q")
2540         (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
2541                  (match_operand:QI 2 "general_operand" "qn,qmn")))]
2542   ""
2543   "*
2544 {
2545   if (operands[2] == const1_rtx)
2546     return AS1 (inc%B0,%0);
2547
2548   if (operands[2] == constm1_rtx
2549       || (GET_CODE (operands[2]) == CONST_INT
2550           && INTVAL (operands[2]) == 255))
2551     return AS1 (dec%B0,%0);
2552
2553   return AS2 (add%B0,%2,%0);
2554 }")
2555
2556 ;Lennart Augustsson <augustss@cs.chalmers.se>
2557 ;says this pattern just makes slower code:
2558 ;       pushl   %ebp
2559 ;       addl    $-80,(%esp)
2560 ;instead of
2561 ;       leal    -80(%ebp),%eax
2562 ;       pushl   %eax
2563 ;
2564 ;(define_insn ""
2565 ;  [(set (match_operand:SI 0 "push_operand" "=<")
2566 ;       (plus:SI (match_operand:SI 1 "general_operand" "%r")
2567 ;                (match_operand:SI 2 "general_operand" "ri")))]
2568 ;  ""
2569 ;  "*
2570 ;{
2571 ;  rtx xops[4];
2572 ;  xops[0] = operands[0];
2573 ;  xops[1] = operands[1];
2574 ;  xops[2] = operands[2];
2575 ;  xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx);
2576 ;  output_asm_insn (\"push%z1 %1\", xops);
2577 ;  output_asm_insn (AS2 (add%z3,%2,%3), xops);
2578 ;  RET;
2579 ;}")
2580
2581 ;; addsi3 is faster, so put this after.
2582
2583 (define_insn "movsi_lea"
2584   [(set (match_operand:SI 0 "register_operand" "=r")
2585         (match_operand:QI 1 "address_operand" "p"))]
2586   ""
2587   "*
2588 {
2589   CC_STATUS_INIT;
2590   /* Adding a constant to a register is faster with an add.  */
2591   /* ??? can this ever happen? */
2592   if (GET_CODE (operands[1]) == PLUS
2593       && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2594       && rtx_equal_p (operands[0], XEXP (operands[1], 0)))
2595     {
2596       operands[1] = XEXP (operands[1], 1);
2597
2598       if (operands[1] == const1_rtx)
2599         return AS1 (inc%L0,%0);
2600
2601       if (operands[1] == constm1_rtx)
2602         return AS1 (dec%L0,%0);
2603
2604       return AS2 (add%L0,%1,%0);
2605     }
2606   return AS2 (lea%L0,%a1,%0);
2607 }")
2608
2609 ;; The patterns that match these are at the end of this file.
2610
2611 (define_expand "addxf3"
2612   [(set (match_operand:XF 0 "register_operand" "")
2613         (plus:XF (match_operand:XF 1 "nonimmediate_operand" "")
2614                  (match_operand:XF 2 "nonimmediate_operand" "")))]
2615   "TARGET_80387"
2616   "")
2617
2618 (define_expand "adddf3"
2619   [(set (match_operand:DF 0 "register_operand" "")
2620         (plus:DF (match_operand:DF 1 "nonimmediate_operand" "")
2621                  (match_operand:DF 2 "nonimmediate_operand" "")))]
2622   "TARGET_80387"
2623   "")
2624
2625 (define_expand "addsf3"
2626   [(set (match_operand:SF 0 "register_operand" "")
2627         (plus:SF (match_operand:SF 1 "nonimmediate_operand" "")
2628                  (match_operand:SF 2 "nonimmediate_operand" "")))]
2629   "TARGET_80387"
2630   "")
2631 \f
2632 ;;- subtract instructions
2633
2634 (define_insn "subdi3"
2635   [(set (match_operand:DI 0 "general_operand" "=&r,ro,&r,o,o")
2636         (minus:DI (match_operand:DI 1 "general_operand" "0,0,roiF,riF,o")
2637                   (match_operand:DI 2 "general_operand" "o,riF,roiF,riF,o")))
2638    (clobber (match_scratch:SI 3 "=X,X,X,&r,&r"))]
2639   ""
2640   "*
2641 {
2642   rtx low[3], high[3], xops[7];
2643
2644   CC_STATUS_INIT;
2645
2646   split_di (operands, 3, low, high);
2647
2648   if (!rtx_equal_p (operands[0], operands[1]))
2649     {
2650       xops[0] = high[0];
2651       xops[1] = low[0];
2652       xops[2] = high[1];
2653       xops[3] = low[1];
2654
2655       if (GET_CODE (operands[0]) != MEM)
2656         {
2657           output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2658           output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2659         }
2660       else
2661         {
2662           xops[4] = high[2];
2663           xops[5] = low[2];
2664           xops[6] = operands[3];
2665           output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2666           output_asm_insn (AS2 (sub%L6,%5,%6), xops);
2667           output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2668           output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2669           output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
2670           output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2671           RET;
2672         }
2673     }
2674
2675   if (GET_CODE (operands[3]) == REG)
2676     {
2677       xops[0] = high[0];
2678       xops[1] = low[0];
2679       xops[2] = high[2];
2680       xops[3] = low[2];
2681       xops[4] = operands[3];
2682
2683       output_asm_insn (AS2 (mov%L4,%3,%4), xops);
2684       output_asm_insn (AS2 (sub%L1,%4,%1), xops);
2685       output_asm_insn (AS2 (mov%L4,%2,%4), xops);
2686       output_asm_insn (AS2 (sbb%L0,%4,%0), xops);
2687     }
2688
2689   else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
2690     {
2691       output_asm_insn (AS2 (sub%L0,%2,%0), low);
2692       output_asm_insn (AS2 (sbb%L0,%2,%0), high);
2693     }
2694
2695   else
2696     output_asm_insn (AS2 (sub%L0,%2,%0), high);
2697
2698   RET;
2699 }")
2700
2701 (define_insn "subsi3"
2702   [(set (match_operand:SI 0 "general_operand" "=rm,r")
2703         (minus:SI (match_operand:SI 1 "general_operand" "0,0")
2704                   (match_operand:SI 2 "general_operand" "ri,rm")))]
2705   ""
2706   "* return AS2 (sub%L0,%2,%0);")
2707
2708 (define_insn "subhi3"
2709   [(set (match_operand:HI 0 "general_operand" "=rm,r")
2710         (minus:HI (match_operand:HI 1 "general_operand" "0,0")
2711                   (match_operand:HI 2 "general_operand" "ri,rm")))]
2712   ""
2713   "* return AS2 (sub%W0,%2,%0);")
2714
2715 (define_insn "subqi3"
2716   [(set (match_operand:QI 0 "general_operand" "=qm,q")
2717         (minus:QI (match_operand:QI 1 "general_operand" "0,0")
2718                   (match_operand:QI 2 "general_operand" "qn,qmn")))]
2719   ""
2720   "* return AS2 (sub%B0,%2,%0);")
2721
2722 ;; The patterns that match these are at the end of this file.
2723
2724 (define_expand "subxf3"
2725   [(set (match_operand:XF 0 "register_operand" "")
2726         (minus:XF (match_operand:XF 1 "nonimmediate_operand" "")
2727                   (match_operand:XF 2 "nonimmediate_operand" "")))]
2728   "TARGET_80387"
2729   "")
2730
2731 (define_expand "subdf3"
2732   [(set (match_operand:DF 0 "register_operand" "")
2733         (minus:DF (match_operand:DF 1 "nonimmediate_operand" "")
2734                   (match_operand:DF 2 "nonimmediate_operand" "")))]
2735   "TARGET_80387"
2736   "")
2737
2738 (define_expand "subsf3"
2739   [(set (match_operand:SF 0 "register_operand" "")
2740         (minus:SF (match_operand:SF 1 "nonimmediate_operand" "")
2741                   (match_operand:SF 2 "nonimmediate_operand" "")))]
2742   "TARGET_80387"
2743   "")
2744 \f
2745 ;;- multiply instructions
2746
2747 ;(define_insn "mulqi3"
2748 ;  [(set (match_operand:QI 0 "general_operand" "=a")
2749 ;       (mult:QI (match_operand:QI 1 "general_operand" "%0")
2750 ;                (match_operand:QI 2 "general_operand" "qm")))]
2751 ;  ""
2752 ;  "imul%B0 %2,%0")
2753
2754 (define_insn ""
2755   [(set (match_operand:HI 0 "general_operand" "=r")
2756         (mult:HI (match_operand:HI 1 "general_operand" "%0")
2757                  (match_operand:HI 2 "general_operand" "r")))]
2758   "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
2759   "* return AS2 (imul%W0,%2,%0);")
2760
2761 (define_insn "mulhi3"
2762   [(set (match_operand:HI 0 "general_operand" "=r,r")
2763         (mult:HI (match_operand:HI 1 "general_operand" "%0,rm")
2764                  (match_operand:HI 2 "general_operand" "g,i")))]
2765   ""
2766   "*
2767 {
2768   if (GET_CODE (operands[1]) == REG
2769       && REGNO (operands[1]) == REGNO (operands[0])
2770       && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
2771     /* Assembler has weird restrictions.  */
2772     return AS2 (imul%W0,%2,%0);
2773   return AS3 (imul%W0,%2,%1,%0);
2774 }")
2775
2776 (define_insn ""
2777   [(set (match_operand:SI 0 "general_operand" "=r")
2778         (mult:SI (match_operand:SI 1 "general_operand" "%0")
2779                  (match_operand:SI 2 "general_operand" "r")))]
2780   "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
2781   "* return AS2 (imul%L0,%2,%0);")
2782
2783 (define_insn "mulsi3"
2784   [(set (match_operand:SI 0 "general_operand" "=r,r")
2785         (mult:SI (match_operand:SI 1 "general_operand" "%0,rm")
2786                  (match_operand:SI 2 "general_operand" "g,i")))]
2787   ""
2788   "*
2789 {
2790   if (GET_CODE (operands[1]) == REG
2791       && REGNO (operands[1]) == REGNO (operands[0])
2792       && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
2793     /* Assembler has weird restrictions.  */
2794     return AS2 (imul%L0,%2,%0);
2795   return AS3 (imul%L0,%2,%1,%0);
2796 }")
2797
2798 (define_insn "umulqihi3"
2799   [(set (match_operand:HI 0 "general_operand" "=a")
2800         (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
2801                  (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
2802   ""
2803   "mul%B0 %2")
2804
2805 (define_insn "mulqihi3"
2806   [(set (match_operand:HI 0 "general_operand" "=a")
2807         (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
2808                  (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
2809   ""
2810   "imul%B0 %2")
2811
2812 (define_insn "umulsidi3"
2813   [(set (match_operand:DI 0 "register_operand" "=A")
2814         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
2815                  (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
2816   "TARGET_WIDE_MULTIPLY"
2817   "mul%L0 %2")
2818
2819 (define_insn "mulsidi3"
2820   [(set (match_operand:DI 0 "register_operand" "=A")
2821         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
2822                  (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
2823   "TARGET_WIDE_MULTIPLY"
2824   "imul%L0 %2")
2825
2826 (define_insn "umulsi3_highpart"
2827   [(set (match_operand:SI 0 "register_operand" "=d")
2828         (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a"))
2829                                            (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
2830                                   (const_int 32))))
2831    (clobber (match_scratch:SI 3 "=a"))]
2832   "TARGET_WIDE_MULTIPLY"
2833   "mul%L0 %2")
2834
2835 (define_insn "smulsi3_highpart"
2836   [(set (match_operand:SI 0 "register_operand" "=d")
2837         (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%a"))
2838                                            (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
2839                                   (const_int 32))))
2840    (clobber (match_scratch:SI 3 "=a"))]
2841   "TARGET_WIDE_MULTIPLY"
2842   "imul%L0 %2")
2843
2844 ;; The patterns that match these are at the end of this file.
2845
2846 (define_expand "mulxf3"
2847   [(set (match_operand:XF 0 "register_operand" "")
2848         (mult:XF (match_operand:XF 1 "nonimmediate_operand" "")
2849                  (match_operand:XF 2 "nonimmediate_operand" "")))]
2850   "TARGET_80387"
2851   "")
2852
2853 (define_expand "muldf3"
2854   [(set (match_operand:DF 0 "register_operand" "")
2855         (mult:DF (match_operand:DF 1 "nonimmediate_operand" "")
2856                  (match_operand:DF 2 "nonimmediate_operand" "")))]
2857   "TARGET_80387"
2858   "")
2859
2860 (define_expand "mulsf3"
2861   [(set (match_operand:SF 0 "register_operand" "")
2862         (mult:SF (match_operand:SF 1 "nonimmediate_operand" "")
2863                  (match_operand:SF 2 "nonimmediate_operand" "")))]
2864   "TARGET_80387"
2865   "")
2866 \f
2867 ;;- divide instructions
2868
2869 (define_insn "divqi3"
2870   [(set (match_operand:QI 0 "general_operand" "=a")
2871         (div:QI (match_operand:HI 1 "general_operand" "0")
2872                 (match_operand:QI 2 "general_operand" "qm")))]
2873   ""
2874   "idiv%B0 %2")
2875
2876 (define_insn "udivqi3"
2877   [(set (match_operand:QI 0 "general_operand" "=a")
2878         (udiv:QI (match_operand:HI 1 "general_operand" "0")
2879                  (match_operand:QI 2 "general_operand" "qm")))]
2880   ""
2881   "div%B0 %2")
2882
2883 ;; The patterns that match these are at the end of this file.
2884
2885 (define_expand "divxf3"
2886   [(set (match_operand:XF 0 "register_operand" "")
2887         (div:XF (match_operand:XF 1 "nonimmediate_operand" "")
2888                 (match_operand:XF 2 "nonimmediate_operand" "")))]
2889   "TARGET_80387"
2890   "")
2891
2892 (define_expand "divdf3"
2893   [(set (match_operand:DF 0 "register_operand" "")
2894         (div:DF (match_operand:DF 1 "nonimmediate_operand" "")
2895                 (match_operand:DF 2 "nonimmediate_operand" "")))]
2896   "TARGET_80387"
2897   "")
2898
2899 (define_expand "divsf3"
2900   [(set (match_operand:SF 0 "register_operand" "")
2901         (div:SF (match_operand:SF 1 "nonimmediate_operand" "")
2902                 (match_operand:SF 2 "nonimmediate_operand" "")))]
2903   "TARGET_80387"
2904   "")
2905 \f
2906 ;; Remainder instructions.
2907
2908 (define_insn "divmodsi4"
2909   [(set (match_operand:SI 0 "register_operand" "=a")
2910         (div:SI (match_operand:SI 1 "register_operand" "0")
2911                 (match_operand:SI 2 "general_operand" "rm")))
2912    (set (match_operand:SI 3 "register_operand" "=&d")
2913         (mod:SI (match_dup 1) (match_dup 2)))]
2914   ""
2915   "*
2916 {
2917 #ifdef INTEL_SYNTAX
2918   output_asm_insn (\"cdq\", operands);
2919 #else
2920   output_asm_insn (\"cltd\", operands);
2921 #endif
2922   return AS1 (idiv%L0,%2);
2923 }")
2924
2925 (define_insn "divmodhi4"
2926   [(set (match_operand:HI 0 "register_operand" "=a")
2927         (div:HI (match_operand:HI 1 "register_operand" "0")
2928                 (match_operand:HI 2 "general_operand" "rm")))
2929    (set (match_operand:HI 3 "register_operand" "=&d")
2930         (mod:HI (match_dup 1) (match_dup 2)))]
2931   ""
2932   "cwtd\;idiv%W0 %2")
2933
2934 ;; ??? Can we make gcc zero extend operand[0]?
2935 (define_insn "udivmodsi4"
2936   [(set (match_operand:SI 0 "register_operand" "=a")
2937         (udiv:SI (match_operand:SI 1 "register_operand" "0")
2938                  (match_operand:SI 2 "general_operand" "rm")))
2939    (set (match_operand:SI 3 "register_operand" "=&d")
2940         (umod:SI (match_dup 1) (match_dup 2)))]
2941   ""
2942   "*
2943 {
2944   output_asm_insn (AS2 (xor%L3,%3,%3), operands);
2945   return AS1 (div%L0,%2);
2946 }")
2947
2948 ;; ??? Can we make gcc zero extend operand[0]?
2949 (define_insn "udivmodhi4"
2950   [(set (match_operand:HI 0 "register_operand" "=a")
2951         (udiv:HI (match_operand:HI 1 "register_operand" "0")
2952                  (match_operand:HI 2 "general_operand" "rm")))
2953    (set (match_operand:HI 3 "register_operand" "=&d")
2954         (umod:HI (match_dup 1) (match_dup 2)))]
2955   ""
2956   "*
2957 {
2958   output_asm_insn (AS2 (xor%W0,%3,%3), operands);
2959   return AS1 (div%W0,%2);
2960 }")
2961
2962 /*
2963 ;;this should be a valid double division which we may want to add
2964
2965 (define_insn ""
2966   [(set (match_operand:SI 0 "register_operand" "=a")
2967         (udiv:DI (match_operand:DI 1 "register_operand" "a")
2968                  (match_operand:SI 2 "general_operand" "rm")))
2969    (set (match_operand:SI 3 "register_operand" "=d")
2970         (umod:SI (match_dup 1) (match_dup 2)))]
2971   ""
2972   "div%L0 %2,%0")
2973 */
2974 \f
2975 ;;- and instructions
2976
2977 ;; On i386,
2978 ;;                      movzbl %bl,%ebx
2979 ;; is faster than
2980 ;;                      andl $255,%ebx
2981 ;;
2982 ;; but if the reg is %eax, then the "andl" is faster.
2983 ;;
2984 ;; On i486, the "andl" is always faster than the "movzbl".
2985 ;;
2986 ;; On both i386 and i486, a three operand AND is as fast with movzbl or
2987 ;; movzwl as with andl, if operands[0] != operands[1].
2988
2989 ;; The `r' in `rm' for operand 3 looks redundant, but it causes
2990 ;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
2991
2992 ;; ??? What if we only change one byte of an offsettable memory reference?
2993 (define_insn "andsi3"
2994   [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r")
2995         (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0")
2996                 (match_operand:SI 2 "general_operand" "L,K,ri,rm")))]
2997   ""
2998   "*
2999 {
3000   if (GET_CODE (operands[2]) == CONST_INT
3001       && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3002     {
3003       if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0])
3004           && (! REG_P (operands[1])
3005               || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
3006           && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1])))
3007         {
3008           /* ??? tege: Should forget CC_STATUS only if we clobber a
3009              remembered operand.  Fix that later.  */
3010           CC_STATUS_INIT;
3011 #ifdef INTEL_SYNTAX
3012           return AS2 (movzx,%w1,%0);
3013 #else
3014           return AS2 (movz%W0%L0,%w1,%0);
3015 #endif
3016         }
3017
3018       if (INTVAL (operands[2]) == 0xff && REG_P (operands[0])
3019           && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
3020           && (! REG_P (operands[1])
3021               || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
3022           && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1])))
3023         {
3024           /* ??? tege: Should forget CC_STATUS only if we clobber a
3025              remembered operand.  Fix that later.  */
3026           CC_STATUS_INIT;
3027 #ifdef INTEL_SYNTAX
3028           return AS2 (movzx,%b1,%0);
3029 #else
3030           return AS2 (movz%B0%L0,%b1,%0);
3031 #endif
3032         }
3033
3034       if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0)
3035         {
3036           CC_STATUS_INIT;
3037
3038           if (INTVAL (operands[2]) == 0xffffff00)
3039             {
3040               operands[2] = const0_rtx;
3041               return AS2 (mov%B0,%2,%b0);
3042             }
3043
3044           operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
3045           return AS2 (and%B0,%2,%b0);
3046         }
3047
3048       if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0)
3049         {
3050           CC_STATUS_INIT;
3051
3052           if (INTVAL (operands[2]) == 0xffff00ff)
3053             {
3054               operands[2] = const0_rtx;
3055               return AS2 (mov%B0,%2,%h0);
3056             }
3057
3058           operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3059           return AS2 (and%B0,%2,%h0);
3060         }
3061
3062       if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000)
3063         {
3064           operands[2] = const0_rtx;
3065           return AS2 (mov%W0,%2,%w0);
3066         }
3067     }
3068
3069   return AS2 (and%L0,%2,%0);
3070 }")
3071
3072 (define_insn "andhi3"
3073   [(set (match_operand:HI 0 "general_operand" "=rm,r")
3074         (and:HI (match_operand:HI 1 "general_operand" "%0,0")
3075                 (match_operand:HI 2 "general_operand" "ri,rm")))]
3076   ""
3077   "*
3078 {
3079   if (GET_CODE (operands[2]) == CONST_INT
3080       && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3081     {
3082       /* Can we ignore the upper byte? */
3083       if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3084           && (INTVAL (operands[2]) & 0xff00) == 0xff00)
3085         {
3086           CC_STATUS_INIT;
3087
3088           if ((INTVAL (operands[2]) & 0xff) == 0)
3089             {
3090               operands[2] = const0_rtx;
3091               return AS2 (mov%B0,%2,%b0);
3092             }
3093
3094           operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
3095           return AS2 (and%B0,%2,%b0);
3096         }
3097
3098       /* Can we ignore the lower byte? */
3099       /* ??? what about offsettable memory references? */
3100       if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff)
3101         {
3102           CC_STATUS_INIT;
3103
3104           if ((INTVAL (operands[2]) & 0xff00) == 0)
3105             {
3106               operands[2] = const0_rtx;
3107               return AS2 (mov%B0,%2,%h0);
3108             }
3109
3110           operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3111           return AS2 (and%B0,%2,%h0);
3112         }
3113     }
3114
3115   return AS2 (and%W0,%2,%0);
3116 }")
3117
3118 (define_insn "andqi3"
3119   [(set (match_operand:QI 0 "general_operand" "=qm,q")
3120         (and:QI (match_operand:QI 1 "general_operand" "%0,0")
3121                 (match_operand:QI 2 "general_operand" "qn,qmn")))]
3122   ""
3123   "* return AS2 (and%B0,%2,%0);")
3124
3125 /* I am nervous about these two.. add them later..
3126 ;I presume this means that we have something in say op0= eax which is small
3127 ;and we want to and it with memory so we can do this by just an
3128 ;andb m,%al  and have success.
3129 (define_insn ""
3130   [(set (match_operand:SI 0 "general_operand" "=r")
3131         (and:SI (zero_extend:SI
3132                  (match_operand:HI 1 "nonimmediate_operand" "rm"))
3133                 (match_operand:SI 2 "general_operand" "0")))]
3134   "GET_CODE (operands[2]) == CONST_INT
3135    && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
3136   "and%W0 %1,%0")
3137
3138 (define_insn ""
3139   [(set (match_operand:SI 0 "general_operand" "=q")
3140         (and:SI
3141          (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))
3142                 (match_operand:SI 2 "general_operand" "0")))]
3143   "GET_CODE (operands[2]) == CONST_INT
3144    && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
3145   "and%L0 %1,%0")
3146
3147 */
3148 \f
3149 ;;- Bit set (inclusive or) instructions
3150
3151 ;; ??? What if we only change one byte of an offsettable memory reference?
3152 (define_insn "iorsi3"
3153   [(set (match_operand:SI 0 "general_operand" "=rm,r")
3154         (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
3155                 (match_operand:SI 2 "general_operand" "ri,rm")))]
3156   ""
3157   "*
3158 {
3159   if (GET_CODE (operands[2]) == CONST_INT
3160       && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3161     {
3162       if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3163           && (INTVAL (operands[2]) & ~0xff) == 0)
3164         {
3165           CC_STATUS_INIT;
3166
3167           if (INTVAL (operands[2]) == 0xff)
3168             return AS2 (mov%B0,%2,%b0);
3169
3170           return AS2 (or%B0,%2,%b0);
3171         }
3172
3173       if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
3174         {
3175           CC_STATUS_INIT;
3176           operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
3177
3178           if (INTVAL (operands[2]) == 0xff)
3179             return AS2 (mov%B0,%2,%h0);
3180
3181           return AS2 (or%B0,%2,%h0);
3182         }
3183     }
3184
3185   return AS2 (or%L0,%2,%0);
3186 }")
3187
3188 (define_insn "iorhi3"
3189   [(set (match_operand:HI 0 "general_operand" "=rm,r")
3190         (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
3191                 (match_operand:HI 2 "general_operand" "ri,rm")))]
3192   ""
3193   "*
3194 {
3195   if (GET_CODE (operands[2]) == CONST_INT
3196       && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3197     {
3198       /* Can we ignore the upper byte? */
3199       if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3200           && (INTVAL (operands[2]) & 0xff00) == 0)
3201         {
3202           CC_STATUS_INIT;
3203           if (INTVAL (operands[2]) & 0xffff0000)
3204             operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
3205
3206           if (INTVAL (operands[2]) == 0xff)
3207             return AS2 (mov%B0,%2,%b0);
3208
3209           return AS2 (or%B0,%2,%b0);
3210         }
3211
3212       /* Can we ignore the lower byte? */
3213       /* ??? what about offsettable memory references? */
3214       if (QI_REG_P (operands[0])
3215           && (INTVAL (operands[2]) & 0xff) == 0)
3216         {
3217           CC_STATUS_INIT;
3218           operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3219
3220           if (INTVAL (operands[2]) == 0xff)
3221             return AS2 (mov%B0,%2,%h0);
3222
3223           return AS2 (or%B0,%2,%h0);
3224         }
3225     }
3226
3227   return AS2 (or%W0,%2,%0);
3228 }")
3229
3230 (define_insn "iorqi3"
3231   [(set (match_operand:QI 0 "general_operand" "=qm,q")
3232         (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
3233                 (match_operand:QI 2 "general_operand" "qn,qmn")))]
3234   ""
3235   "* return AS2 (or%B0,%2,%0);")
3236 \f
3237 ;;- xor instructions
3238
3239 ;; ??? What if we only change one byte of an offsettable memory reference?
3240 (define_insn "xorsi3"
3241   [(set (match_operand:SI 0 "general_operand" "=rm,r")
3242         (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
3243                 (match_operand:SI 2 "general_operand" "ri,rm")))]
3244   ""
3245   "*
3246 {
3247   if (GET_CODE (operands[2]) == CONST_INT
3248       && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3249     {
3250       if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3251           && (INTVAL (operands[2]) & ~0xff) == 0)
3252         {
3253           CC_STATUS_INIT;
3254
3255           if (INTVAL (operands[2]) == 0xff)
3256             return AS1 (not%B0,%b0);
3257
3258           return AS2 (xor%B0,%2,%b0);
3259         }
3260
3261       if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
3262         {
3263           CC_STATUS_INIT;
3264           operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
3265
3266           if (INTVAL (operands[2]) == 0xff)
3267             return AS1 (not%B0,%h0);
3268
3269           return AS2 (xor%B0,%2,%h0);
3270         }
3271     }
3272
3273   return AS2 (xor%L0,%2,%0);
3274 }")
3275
3276 (define_insn "xorhi3"
3277   [(set (match_operand:HI 0 "general_operand" "=rm,r")
3278         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
3279                 (match_operand:HI 2 "general_operand" "ri,rm")))]
3280   ""
3281   "*
3282 {
3283   if (GET_CODE (operands[2]) == CONST_INT
3284       && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3285     {
3286       /* Can we ignore the upper byte? */
3287       if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3288           && (INTVAL (operands[2]) & 0xff00) == 0)
3289         {
3290           CC_STATUS_INIT;
3291           if (INTVAL (operands[2]) & 0xffff0000)
3292             operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
3293
3294           if (INTVAL (operands[2]) == 0xff)
3295             return AS1 (not%B0,%b0);
3296
3297           return AS2 (xor%B0,%2,%b0);
3298         }
3299
3300       /* Can we ignore the lower byte? */
3301       /* ??? what about offsettable memory references? */
3302       if (QI_REG_P (operands[0])
3303           && (INTVAL (operands[2]) & 0xff) == 0)
3304         {
3305           CC_STATUS_INIT;
3306           operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3307
3308           if (INTVAL (operands[2]) == 0xff)
3309             return AS1 (not%B0,%h0);
3310
3311           return AS2 (xor%B0,%2,%h0);
3312         }
3313     }
3314
3315   return AS2 (xor%W0,%2,%0);
3316 }")
3317
3318 (define_insn "xorqi3"
3319   [(set (match_operand:QI 0 "general_operand" "=qm,q")
3320         (xor:QI (match_operand:QI 1 "general_operand" "%0,0")
3321                 (match_operand:QI 2 "general_operand" "qn,qm")))]
3322   ""
3323   "* return AS2 (xor%B0,%2,%0);")
3324 \f
3325 ;;- negation instructions
3326
3327 (define_insn "negdi2"
3328   [(set (match_operand:DI 0 "general_operand" "=&ro")
3329         (neg:DI (match_operand:DI 1 "general_operand" "0")))]
3330   ""
3331   "*
3332 {
3333   rtx xops[2], low[1], high[1];
3334
3335   CC_STATUS_INIT;
3336
3337   split_di (operands, 1, low, high);
3338   xops[0] = const0_rtx;
3339   xops[1] = high[0];
3340
3341   output_asm_insn (AS1 (neg%L0,%0), low);
3342   output_asm_insn (AS2 (adc%L1,%0,%1), xops);
3343   output_asm_insn (AS1 (neg%L0,%0), high);
3344   RET;
3345 }")
3346
3347 (define_insn "negsi2"
3348   [(set (match_operand:SI 0 "general_operand" "=rm")
3349         (neg:SI (match_operand:SI 1 "general_operand" "0")))]
3350   ""
3351   "neg%L0 %0")
3352
3353 (define_insn "neghi2"
3354   [(set (match_operand:HI 0 "general_operand" "=rm")
3355         (neg:HI (match_operand:HI 1 "general_operand" "0")))]
3356   ""
3357   "neg%W0 %0")
3358
3359 (define_insn "negqi2"
3360   [(set (match_operand:QI 0 "general_operand" "=qm")
3361         (neg:QI (match_operand:QI 1 "general_operand" "0")))]
3362   ""
3363   "neg%B0 %0")
3364
3365 (define_insn "negsf2"
3366   [(set (match_operand:SF 0 "register_operand" "=f")
3367         (neg:SF (match_operand:SF 1 "general_operand" "0")))]
3368   "TARGET_80387"
3369   "fchs")
3370
3371 (define_insn "negdf2"
3372   [(set (match_operand:DF 0 "register_operand" "=f")
3373         (neg:DF (match_operand:DF 1 "general_operand" "0")))]
3374   "TARGET_80387"
3375   "fchs")
3376
3377 (define_insn ""
3378   [(set (match_operand:DF 0 "register_operand" "=f")
3379         (neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
3380   "TARGET_80387"
3381   "fchs")
3382
3383 (define_insn "negxf2"
3384   [(set (match_operand:XF 0 "register_operand" "=f")
3385         (neg:XF (match_operand:XF 1 "general_operand" "0")))]
3386   "TARGET_80387"
3387   "fchs")
3388
3389 (define_insn ""
3390   [(set (match_operand:XF 0 "register_operand" "=f")
3391         (neg:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
3392   "TARGET_80387"
3393   "fchs")
3394 \f
3395 ;; Absolute value instructions
3396
3397 (define_insn "abssf2"
3398   [(set (match_operand:SF 0 "register_operand" "=f")
3399         (abs:SF (match_operand:SF 1 "general_operand" "0")))]
3400   "TARGET_80387"
3401   "fabs")
3402
3403 (define_insn "absdf2"
3404   [(set (match_operand:DF 0 "register_operand" "=f")
3405         (abs:DF (match_operand:DF 1 "general_operand" "0")))]
3406   "TARGET_80387"
3407   "fabs")
3408
3409 (define_insn ""
3410   [(set (match_operand:DF 0 "register_operand" "=f")
3411         (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
3412   "TARGET_80387"
3413   "fabs")
3414
3415 (define_insn "absxf2"
3416   [(set (match_operand:XF 0 "register_operand" "=f")
3417         (abs:XF (match_operand:XF 1 "general_operand" "0")))]
3418   "TARGET_80387"
3419   "fabs")
3420
3421 (define_insn ""
3422   [(set (match_operand:XF 0 "register_operand" "=f")
3423         (abs:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
3424   "TARGET_80387"
3425   "fabs")
3426
3427 (define_insn "sqrtsf2"
3428   [(set (match_operand:SF 0 "register_operand" "=f")
3429         (sqrt:SF (match_operand:SF 1 "general_operand" "0")))]
3430   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
3431    && (TARGET_IEEE_FP || flag_fast_math) "
3432   "fsqrt")
3433
3434 (define_insn "sqrtdf2"
3435   [(set (match_operand:DF 0 "register_operand" "=f")
3436         (sqrt:DF (match_operand:DF 1 "general_operand" "0")))]
3437   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
3438    && (TARGET_IEEE_FP || flag_fast_math) "
3439   "fsqrt")
3440
3441 (define_insn ""
3442   [(set (match_operand:DF 0 "register_operand" "=f")
3443         (sqrt:DF (float_extend:DF
3444                   (match_operand:SF 1 "general_operand" "0"))))]
3445   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3446    && (TARGET_IEEE_FP || flag_fast_math) "
3447   "fsqrt")
3448
3449 (define_insn "sqrtxf2"
3450   [(set (match_operand:XF 0 "register_operand" "=f")
3451         (sqrt:XF (match_operand:XF 1 "general_operand" "0")))]
3452   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3453    && (TARGET_IEEE_FP || flag_fast_math) "
3454   "fsqrt")
3455
3456 (define_insn ""
3457   [(set (match_operand:XF 0 "register_operand" "=f")
3458         (sqrt:XF (float_extend:XF
3459                   (match_operand:DF 1 "general_operand" "0"))))]
3460   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3461    && (TARGET_IEEE_FP || flag_fast_math) "
3462   "fsqrt")
3463
3464 (define_insn ""
3465   [(set (match_operand:XF 0 "register_operand" "=f")
3466         (sqrt:XF (float_extend:XF
3467                   (match_operand:SF 1 "general_operand" "0"))))]
3468   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3469    && (TARGET_IEEE_FP || flag_fast_math) "
3470   "fsqrt")
3471
3472 (define_insn "sindf2"
3473   [(set (match_operand:DF 0 "register_operand" "=f")
3474         (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
3475   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3476    && (TARGET_IEEE_FP || flag_fast_math) "
3477   "fsin")
3478
3479 (define_insn "sinsf2"
3480   [(set (match_operand:SF 0 "register_operand" "=f")
3481         (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
3482   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3483    && (TARGET_IEEE_FP || flag_fast_math) "
3484   "fsin")
3485
3486 (define_insn ""
3487   [(set (match_operand:DF 0 "register_operand" "=f")
3488         (unspec:DF [(float_extend:DF
3489                      (match_operand:SF 1 "register_operand" "0"))] 1))]
3490   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3491    && (TARGET_IEEE_FP || flag_fast_math) "
3492   "fsin")
3493
3494 (define_insn "sinxf2"
3495   [(set (match_operand:XF 0 "register_operand" "=f")
3496         (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
3497   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3498    && (TARGET_IEEE_FP || flag_fast_math) "
3499   "fsin")
3500
3501 (define_insn "cosdf2"
3502   [(set (match_operand:DF 0 "register_operand" "=f")
3503         (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
3504   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3505    && (TARGET_IEEE_FP || flag_fast_math) "
3506   "fcos")
3507
3508 (define_insn "cossf2"
3509   [(set (match_operand:SF 0 "register_operand" "=f")
3510         (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
3511   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3512    && (TARGET_IEEE_FP || flag_fast_math) "
3513   "fcos")
3514
3515 (define_insn ""
3516   [(set (match_operand:DF 0 "register_operand" "=f")
3517         (unspec:DF [(float_extend:DF
3518                      (match_operand:SF 1 "register_operand" "0"))] 2))]
3519   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3520    && (TARGET_IEEE_FP || flag_fast_math) "
3521   "fcos")
3522
3523 (define_insn "cosxf2"
3524   [(set (match_operand:XF 0 "register_operand" "=f")
3525         (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))]
3526   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
3527    && (TARGET_IEEE_FP || flag_fast_math) "
3528   "fcos")
3529 \f
3530 ;;- one complement instructions
3531
3532 (define_insn "one_cmplsi2"
3533   [(set (match_operand:SI 0 "general_operand" "=rm")
3534         (not:SI (match_operand:SI 1 "general_operand" "0")))]
3535   ""
3536   "not%L0 %0")
3537
3538 (define_insn "one_cmplhi2"
3539   [(set (match_operand:HI 0 "general_operand" "=rm")
3540         (not:HI (match_operand:HI 1 "general_operand" "0")))]
3541   ""
3542   "not%W0 %0")
3543
3544 (define_insn "one_cmplqi2"
3545   [(set (match_operand:QI 0 "general_operand" "=qm")
3546         (not:QI (match_operand:QI 1 "general_operand" "0")))]
3547   ""
3548   "not%B0 %0")
3549 \f
3550 ;;- arithmetic shift instructions
3551
3552 ;; DImode shifts are implemented using the i386 "shift double" opcode,
3553 ;; which is written as "sh[lr]d[lw] imm,reg,reg/mem".  If the shift count
3554 ;; is variable, then the count is in %cl and the "imm" operand is dropped
3555 ;; from the assembler input.
3556
3557 ;; This instruction shifts the target reg/mem as usual, but instead of
3558 ;; shifting in zeros, bits are shifted in from reg operand.  If the insn
3559 ;; is a left shift double, bits are taken from the high order bits of
3560 ;; reg, else if the insn is a shift right double, bits are taken from the
3561 ;; low order bits of reg.  So if %eax is "1234" and %edx is "5678",
3562 ;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
3563
3564 ;; Since sh[lr]d does not change the `reg' operand, that is done
3565 ;; separately, making all shifts emit pairs of shift double and normal
3566 ;; shift.  Since sh[lr]d does not shift more than 31 bits, and we wish to
3567 ;; support a 63 bit shift, each shift where the count is in a reg expands
3568 ;; to three pairs.  If the overall shift is by N bits, then the first two
3569 ;; pairs shift by N / 2 and the last pair by N & 1.
3570
3571 ;; If the shift count is a constant, we need never emit more than one
3572 ;; shift pair, instead using moves and sign extension for counts greater
3573 ;; than 31.
3574
3575 (define_expand "ashldi3"
3576   [(set (match_operand:DI 0 "register_operand" "")
3577         (ashift:DI (match_operand:DI 1 "register_operand" "")
3578                    (match_operand:QI 2 "nonmemory_operand" "")))]
3579   ""
3580   "
3581 {
3582   if (GET_CODE (operands[2]) != CONST_INT
3583       || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
3584     {
3585       operands[2] = copy_to_mode_reg (QImode, operands[2]);
3586       emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1],
3587                                             operands[2]));
3588     }
3589   else
3590     emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2]));
3591
3592   DONE;
3593 }")
3594
3595 (define_insn "ashldi3_const_int"
3596   [(set (match_operand:DI 0 "register_operand" "=&r")
3597         (ashift:DI (match_operand:DI 1 "register_operand" "0")
3598                    (match_operand:QI 2 "const_int_operand" "J")))]
3599   ""
3600   "*
3601 {
3602   rtx xops[4], low[1], high[1];
3603
3604   CC_STATUS_INIT;
3605
3606   split_di (operands, 1, low, high);
3607   xops[0] = operands[2];
3608   xops[1] = const1_rtx;
3609   xops[2] = low[0];
3610   xops[3] = high[0];
3611
3612   if (INTVAL (xops[0]) > 31)
3613     {
3614       output_asm_insn (AS2 (mov%L3,%2,%3), xops);       /* Fast shift by 32 */
3615       output_asm_insn (AS2 (xor%L2,%2,%2), xops);
3616
3617       if (INTVAL (xops[0]) > 32)
3618         {
3619           xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
3620           output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */
3621         }
3622     }
3623   else
3624     {
3625       output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops);
3626       output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3627     }
3628   RET;
3629 }")
3630
3631 (define_insn "ashldi3_non_const_int"
3632   [(set (match_operand:DI 0 "register_operand" "=&r")
3633         (ashift:DI (match_operand:DI 1 "register_operand" "0")
3634                    (match_operand:QI 2 "register_operand" "c")))
3635    (clobber (match_dup 2))]
3636   ""
3637   "*
3638 {
3639   rtx xops[4], low[1], high[1];
3640
3641   CC_STATUS_INIT;
3642
3643   split_di (operands, 1, low, high);
3644   xops[0] = operands[2];
3645   xops[1] = const1_rtx;
3646   xops[2] = low[0];
3647   xops[3] = high[0];
3648
3649   output_asm_insn (AS2 (ror%B0,%1,%0), xops);   /* shift count / 2 */
3650
3651   output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
3652   output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3653   output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
3654   output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3655
3656   xops[1] = GEN_INT (7);                        /* shift count & 1 */
3657
3658   output_asm_insn (AS2 (shr%B0,%1,%0), xops);
3659
3660   output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
3661   output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3662
3663   RET;
3664 }")
3665
3666 ;; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg"
3667 ;; On i486, movl/sall appears slightly faster than leal, but the leal
3668 ;; is smaller - use leal for now unless the shift count is 1.
3669
3670 (define_insn "ashlsi3"
3671   [(set (match_operand:SI 0 "general_operand" "=r,rm")
3672         (ashift:SI (match_operand:SI 1 "general_operand" "r,0")
3673                    (match_operand:SI 2 "nonmemory_operand" "M,cI")))]
3674   ""
3675   "*
3676 {
3677   if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
3678     {
3679       if (!TARGET_386 && INTVAL (operands[2]) == 1)
3680         {
3681           output_asm_insn (AS2 (mov%L0,%1,%0), operands);
3682           return AS2 (add%L0,%1,%0);
3683         }
3684       else
3685         {
3686           CC_STATUS_INIT;
3687
3688           if (operands[1] == stack_pointer_rtx)
3689             {
3690               output_asm_insn (AS2 (mov%L0,%1,%0), operands);
3691               operands[1] = operands[0];
3692             }
3693           operands[1] = gen_rtx (MULT, SImode, operands[1],
3694                                  GEN_INT (1 << INTVAL (operands[2])));
3695           return AS2 (lea%L0,%a1,%0);
3696         }
3697     }
3698
3699   if (REG_P (operands[2]))
3700     return AS2 (sal%L0,%b2,%0);
3701
3702   if (REG_P (operands[0]) && operands[2] == const1_rtx)
3703     return AS2 (add%L0,%0,%0);
3704
3705   return AS2 (sal%L0,%2,%0);
3706 }")
3707
3708 (define_insn "ashlhi3"
3709   [(set (match_operand:HI 0 "general_operand" "=rm")
3710         (ashift:HI (match_operand:HI 1 "general_operand" "0")
3711                    (match_operand:HI 2 "nonmemory_operand" "cI")))]
3712   ""
3713   "*
3714 {
3715   if (REG_P (operands[2]))
3716     return AS2 (sal%W0,%b2,%0);
3717
3718   if (REG_P (operands[0]) && operands[2] == const1_rtx)
3719     return AS2 (add%W0,%0,%0);
3720
3721   return AS2 (sal%W0,%2,%0);
3722 }")
3723
3724 (define_insn "ashlqi3"
3725   [(set (match_operand:QI 0 "general_operand" "=qm")
3726         (ashift:QI (match_operand:QI 1 "general_operand" "0")
3727                    (match_operand:QI 2 "nonmemory_operand" "cI")))]
3728   ""
3729   "*
3730 {
3731   if (REG_P (operands[2]))
3732     return AS2 (sal%B0,%b2,%0);
3733
3734   if (REG_P (operands[0]) && operands[2] == const1_rtx)
3735     return AS2 (add%B0,%0,%0);
3736
3737   return AS2 (sal%B0,%2,%0);
3738 }")
3739
3740 ;; See comment above `ashldi3' about how this works.
3741
3742 (define_expand "ashrdi3"
3743   [(set (match_operand:DI 0 "register_operand" "")
3744         (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
3745                      (match_operand:QI 2 "nonmemory_operand" "")))]
3746   ""
3747   "
3748 {
3749   if (GET_CODE (operands[2]) != CONST_INT
3750       || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
3751     {
3752       operands[2] = copy_to_mode_reg (QImode, operands[2]);
3753       emit_insn (gen_ashrdi3_non_const_int (operands[0], operands[1],
3754                                             operands[2]));
3755     }
3756   else
3757     emit_insn (gen_ashrdi3_const_int (operands[0], operands[1], operands[2]));
3758
3759   DONE;
3760 }")
3761
3762 (define_insn "ashrdi3_const_int"
3763   [(set (match_operand:DI 0 "register_operand" "=&r")
3764         (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
3765                      (match_operand:QI 2 "const_int_operand" "J")))]
3766   ""
3767   "*
3768 {
3769   rtx xops[4], low[1], high[1];
3770
3771   CC_STATUS_INIT;
3772
3773   split_di (operands, 1, low, high);
3774   xops[0] = operands[2];
3775   xops[1] = const1_rtx;
3776   xops[2] = low[0];
3777   xops[3] = high[0];
3778
3779   if (INTVAL (xops[0]) > 31)
3780     {
3781       xops[1] = GEN_INT (31);
3782       output_asm_insn (AS2 (mov%L2,%3,%2), xops);
3783       output_asm_insn (AS2 (sar%L3,%1,%3), xops);       /* shift by 32 */
3784
3785       if (INTVAL (xops[0]) > 32)
3786         {
3787           xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
3788           output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */
3789         }
3790     }
3791   else
3792     {
3793       output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
3794       output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3795     }
3796
3797   RET;
3798 }")
3799
3800 (define_insn "ashrdi3_non_const_int"
3801   [(set (match_operand:DI 0 "register_operand" "=&r")
3802         (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
3803                      (match_operand:QI 2 "register_operand" "c")))
3804    (clobber (match_dup 2))]
3805   ""
3806   "*
3807 {
3808   rtx xops[4], low[1], high[1];
3809
3810   CC_STATUS_INIT;
3811
3812   split_di (operands, 1, low, high);
3813   xops[0] = operands[2];
3814   xops[1] = const1_rtx;
3815   xops[2] = low[0];
3816   xops[3] = high[0];
3817
3818   output_asm_insn (AS2 (ror%B0,%1,%0), xops);   /* shift count / 2 */
3819
3820   output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3821   output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3822   output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3823   output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3824
3825   xops[1] = GEN_INT (7);                        /* shift count & 1 */
3826
3827   output_asm_insn (AS2 (shr%B0,%1,%0), xops);
3828
3829   output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3830   output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3831
3832   RET;
3833 }")
3834
3835 (define_insn "ashrsi3"
3836   [(set (match_operand:SI 0 "general_operand" "=rm")
3837         (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
3838                      (match_operand:SI 2 "nonmemory_operand" "cI")))]
3839   ""
3840   "*
3841 {
3842   if (REG_P (operands[2]))
3843     return AS2 (sar%L0,%b2,%0);
3844   else
3845     return AS2 (sar%L0,%2,%0);
3846 }")
3847
3848 (define_insn "ashrhi3"
3849   [(set (match_operand:HI 0 "general_operand" "=rm")
3850         (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
3851                      (match_operand:HI 2 "nonmemory_operand" "cI")))]
3852   ""
3853   "*
3854 {
3855   if (REG_P (operands[2]))
3856     return AS2 (sar%W0,%b2,%0);
3857   else
3858     return AS2 (sar%W0,%2,%0);
3859 }")
3860
3861 (define_insn "ashrqi3"
3862   [(set (match_operand:QI 0 "general_operand" "=qm")
3863         (ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
3864                      (match_operand:QI 2 "nonmemory_operand" "cI")))]
3865   ""
3866   "*
3867 {
3868   if (REG_P (operands[2]))
3869     return AS2 (sar%B0,%b2,%0);
3870   else
3871     return AS2 (sar%B0,%2,%0);
3872 }")
3873 \f
3874 ;;- logical shift instructions
3875
3876 ;; See comment above `ashldi3' about how this works.
3877
3878 (define_expand "lshrdi3"
3879   [(set (match_operand:DI 0 "register_operand" "")
3880         (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
3881                      (match_operand:QI 2 "nonmemory_operand" "")))]
3882   ""
3883   "
3884 {
3885   if (GET_CODE (operands[2]) != CONST_INT
3886       || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
3887     {
3888       operands[2] = copy_to_mode_reg (QImode, operands[2]);
3889       emit_insn (gen_lshrdi3_non_const_int (operands[0], operands[1],
3890                                             operands[2]));
3891     }
3892   else
3893     emit_insn (gen_lshrdi3_const_int (operands[0], operands[1], operands[2]));
3894
3895   DONE;
3896 }")
3897
3898 (define_insn "lshrdi3_const_int"
3899   [(set (match_operand:DI 0 "register_operand" "=&r")
3900         (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
3901                      (match_operand:QI 2 "const_int_operand" "J")))]
3902   ""
3903   "*
3904 {
3905   rtx xops[4], low[1], high[1];
3906
3907   CC_STATUS_INIT;
3908
3909   split_di (operands, 1, low, high);
3910   xops[0] = operands[2];
3911   xops[1] = const1_rtx;
3912   xops[2] = low[0];
3913   xops[3] = high[0];
3914
3915   if (INTVAL (xops[0]) > 31)
3916     {
3917       output_asm_insn (AS2 (mov%L2,%3,%2), xops);       /* Fast shift by 32 */
3918       output_asm_insn (AS2 (xor%L3,%3,%3), xops);
3919
3920       if (INTVAL (xops[0]) > 32)
3921         {
3922           xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
3923           output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */
3924         }
3925     }
3926   else
3927     {
3928       output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
3929       output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3930     }
3931
3932   RET;
3933 }")
3934
3935 (define_insn "lshrdi3_non_const_int"
3936   [(set (match_operand:DI 0 "register_operand" "=&r")
3937         (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
3938                      (match_operand:QI 2 "register_operand" "c")))
3939    (clobber (match_dup 2))]
3940   ""
3941   "*
3942 {
3943   rtx xops[4], low[1], high[1];
3944
3945   CC_STATUS_INIT;
3946
3947   split_di (operands, 1, low, high);
3948   xops[0] = operands[2];
3949   xops[1] = const1_rtx;
3950   xops[2] = low[0];
3951   xops[3] = high[0];
3952
3953   output_asm_insn (AS2 (ror%B0,%1,%0), xops);   /* shift count / 2 */
3954
3955   output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3956   output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3957   output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3958   output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3959
3960   xops[1] = GEN_INT (7);                        /* shift count & 1 */
3961
3962   output_asm_insn (AS2 (shr%B0,%1,%0), xops);
3963
3964   output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3965   output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3966
3967   RET;
3968 }")
3969
3970 (define_insn "lshrsi3"
3971   [(set (match_operand:SI 0 "general_operand" "=rm")
3972         (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
3973                      (match_operand:SI 2 "nonmemory_operand" "cI")))]
3974   ""
3975   "*
3976 {
3977   if (REG_P (operands[2]))
3978     return AS2 (shr%L0,%b2,%0);
3979   else
3980     return AS2 (shr%L0,%2,%1);
3981 }")
3982
3983 (define_insn "lshrhi3"
3984   [(set (match_operand:HI 0 "general_operand" "=rm")
3985         (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
3986                      (match_operand:HI 2 "nonmemory_operand" "cI")))]
3987   ""
3988   "*
3989 {
3990   if (REG_P (operands[2]))
3991     return AS2 (shr%W0,%b2,%0);
3992   else
3993     return AS2 (shr%W0,%2,%0);
3994 }")
3995
3996 (define_insn "lshrqi3"
3997   [(set (match_operand:QI 0 "general_operand" "=qm")
3998         (lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
3999                      (match_operand:QI 2 "nonmemory_operand" "cI")))]
4000   ""
4001   "*
4002 {
4003   if (REG_P (operands[2]))
4004     return AS2 (shr%B0,%b2,%0);
4005   else
4006     return AS2 (shr%B0,%2,%0);
4007 }")
4008 \f
4009 ;;- rotate instructions
4010
4011 (define_insn "rotlsi3"
4012   [(set (match_operand:SI 0 "general_operand" "=rm")
4013         (rotate:SI (match_operand:SI 1 "general_operand" "0")
4014                    (match_operand:SI 2 "nonmemory_operand" "cI")))]
4015   ""
4016   "*
4017 {
4018   if (REG_P (operands[2]))
4019     return AS2 (rol%L0,%b2,%0);
4020   else
4021     return AS2 (rol%L0,%2,%0);
4022 }")
4023
4024 (define_insn "rotlhi3"
4025   [(set (match_operand:HI 0 "general_operand" "=rm")
4026         (rotate:HI (match_operand:HI 1 "general_operand" "0")
4027                    (match_operand:HI 2 "nonmemory_operand" "cI")))]
4028   ""
4029   "*
4030 {
4031   if (REG_P (operands[2]))
4032     return AS2 (rol%W0,%b2,%0);
4033   else
4034     return AS2 (rol%W0,%2,%0);
4035 }")
4036
4037 (define_insn "rotlqi3"
4038   [(set (match_operand:QI 0 "general_operand" "=qm")
4039         (rotate:QI (match_operand:QI 1 "general_operand" "0")
4040                    (match_operand:QI 2 "nonmemory_operand" "cI")))]
4041   ""
4042   "*
4043 {
4044   if (REG_P (operands[2]))
4045     return AS2 (rol%B0,%b2,%0);
4046   else
4047     return AS2 (rol%B0,%2,%0);
4048 }")
4049
4050 (define_insn "rotrsi3"
4051   [(set (match_operand:SI 0 "general_operand" "=rm")
4052         (rotatert:SI (match_operand:SI 1 "general_operand" "0")
4053                      (match_operand:SI 2 "nonmemory_operand" "cI")))]
4054   ""
4055   "*
4056 {
4057   if (REG_P (operands[2]))
4058     return AS2 (ror%L0,%b2,%0);
4059   else
4060     return AS2 (ror%L0,%2,%0);
4061 }")
4062
4063 (define_insn "rotrhi3"
4064   [(set (match_operand:HI 0 "general_operand" "=rm")
4065         (rotatert:HI (match_operand:HI 1 "general_operand" "0")
4066                      (match_operand:HI 2 "nonmemory_operand" "cI")))]
4067   ""
4068   "*
4069 {
4070   if (REG_P (operands[2]))
4071     return AS2 (ror%W0,%b2,%0);
4072   else
4073     return AS2 (ror%W0,%2,%0);
4074 }")
4075
4076 (define_insn "rotrqi3"
4077   [(set (match_operand:QI 0 "general_operand" "=qm")
4078         (rotatert:QI (match_operand:QI 1 "general_operand" "0")
4079                      (match_operand:QI 2 "nonmemory_operand" "cI")))]
4080   ""
4081   "*
4082 {
4083   if (REG_P (operands[2]))
4084     return AS2 (ror%B0,%b2,%0);
4085   else
4086     return AS2 (ror%B0,%2,%0);
4087 }")
4088 \f
4089 /*
4090 ;; This usually looses.  But try a define_expand to recognize a few case
4091 ;; we can do efficiently, such as accessing the "high" QImode registers,
4092 ;; %ah, %bh, %ch, %dh.
4093 (define_insn "insv"
4094   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r")
4095                          (match_operand:SI 1 "general_operand" "i")
4096                          (match_operand:SI 2 "general_operand" "i"))
4097         (match_operand:SI 3 "general_operand" "ri"))]
4098   ""
4099   "*
4100 {
4101   if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode))
4102     abort ();
4103   if (GET_CODE (operands[3]) == CONST_INT)
4104     {
4105       unsigned int mask = (1 << INTVAL (operands[1])) - 1; 
4106       operands[1] = GEN_INT (~(mask << INTVAL (operands[2])));
4107       output_asm_insn (AS2 (and%L0,%1,%0), operands);
4108       operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2]));
4109       output_asm_insn (AS2 (or%L0,%3,%0), operands);
4110     }
4111   else
4112     {
4113       operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]));
4114       if (INTVAL (operands[2]))
4115         output_asm_insn (AS2 (ror%L0,%2,%0), operands);
4116       output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands);
4117       operands[2] = GEN_INT (BITS_PER_WORD
4118                              - INTVAL (operands[1]) - INTVAL (operands[2]));
4119       if (INTVAL (operands[2]))
4120         output_asm_insn (AS2 (ror%L0,%2,%0), operands);
4121     }
4122   RET;
4123 }")
4124 */
4125 /*
4126 ;; ??? There are problems with the mode of operand[3].  The point of this
4127 ;; is to represent an HImode move to a "high byte" register.
4128
4129 (define_expand "insv"
4130   [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
4131                          (match_operand:SI 1 "immediate_operand" "")
4132                          (match_operand:SI 2 "immediate_operand" ""))
4133         (match_operand:QI 3 "general_operand" "ri"))]
4134   ""
4135   "
4136 {
4137   if (GET_CODE (operands[1]) != CONST_INT
4138       || GET_CODE (operands[2]) != CONST_INT)
4139     FAIL;
4140
4141   if (! (INTVAL (operands[1]) == 8
4142          && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0))
4143       && ! INTVAL (operands[1]) == 1)
4144     FAIL;
4145 }")
4146
4147 ;; ??? Are these constraints right?
4148 (define_insn ""
4149   [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+&qo")
4150                          (const_int 8)
4151                          (const_int 8))
4152         (match_operand:QI 1 "general_operand" "qn"))]
4153   ""
4154   "*
4155 {
4156   if (REG_P (operands[0]))
4157     return AS2 (mov%B0,%1,%h0);
4158
4159   operands[0] = adj_offsettable_operand (operands[0], 1);
4160   return AS2 (mov%B0,%1,%0);
4161 }")
4162 */
4163
4164 ;; On i386, the register count for a bit operation is *not* truncated,
4165 ;; so SHIFT_COUNT_TRUNCATED must not be defined.
4166
4167 ;; On i486, the shift & or/and code is faster than bts or btr.  If
4168 ;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code.
4169
4170 ;; On i386, bts is a little faster if operands[0] is a reg, and a
4171 ;; little slower if operands[0] is a MEM, than the shift & or/and code.
4172 ;; Use bts & btr, since they reload better.
4173
4174 ;; General bit set and clear.
4175 (define_insn ""
4176   [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm")
4177                          (const_int 1)
4178                          (match_operand:SI 2 "general_operand" "r"))
4179         (match_operand:SI 3 "const_int_operand" "n"))]
4180   "TARGET_386 && GET_CODE (operands[2]) != CONST_INT"
4181   "*
4182 {
4183   CC_STATUS_INIT;
4184
4185   if (INTVAL (operands[3]) == 1)
4186     return AS2 (bts%L0,%2,%0);
4187   else
4188     return AS2 (btr%L0,%2,%0);
4189 }")
4190
4191 ;; Bit complement.  See comments on previous pattern.
4192 ;; ??? Is this really worthwhile?
4193 (define_insn ""
4194   [(set (match_operand:SI 0 "general_operand" "=rm")
4195         (xor:SI (ashift:SI (const_int 1)
4196                            (match_operand:SI 1 "general_operand" "r"))
4197                 (match_operand:SI 2 "general_operand" "0")))]
4198   "TARGET_386 && GET_CODE (operands[1]) != CONST_INT"
4199   "*
4200 {
4201   CC_STATUS_INIT;
4202
4203   return AS2 (btc%L0,%1,%0);
4204 }")
4205
4206 (define_insn ""
4207   [(set (match_operand:SI 0 "general_operand" "=rm")
4208         (xor:SI (match_operand:SI 1 "general_operand" "0")
4209                 (ashift:SI (const_int 1)
4210                            (match_operand:SI 2 "general_operand" "r"))))]
4211   "TARGET_386 && GET_CODE (operands[2]) != CONST_INT"
4212   "*
4213 {
4214   CC_STATUS_INIT;
4215
4216   return AS2 (btc%L0,%2,%0);
4217 }")
4218 \f
4219 ;; Recognizers for bit-test instructions.
4220
4221 ;; The bt opcode allows a MEM in operands[0].  But on both i386 and
4222 ;; i486, it is faster to copy a MEM to REG and then use bt, than to use
4223 ;; bt on the MEM directly.
4224
4225 ;; ??? The first argument of a zero_extract must not be reloaded, so
4226 ;; don't allow a MEM in the operand predicate without allowing it in the
4227 ;; constraint.
4228
4229 (define_insn ""
4230   [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
4231                             (const_int 1)
4232                             (match_operand:SI 1 "general_operand" "r")))]
4233   "GET_CODE (operands[1]) != CONST_INT"
4234   "*
4235 {
4236   cc_status.flags |= CC_Z_IN_NOT_C;
4237   return AS2 (bt%L0,%1,%0);
4238 }")
4239
4240 (define_insn ""
4241   [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
4242                             (match_operand:SI 1 "const_int_operand" "n")
4243                             (match_operand:SI 2 "const_int_operand" "n")))]
4244   ""
4245   "*
4246 {
4247   unsigned int mask;
4248
4249   mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
4250   operands[1] = GEN_INT (mask);
4251
4252   if (QI_REG_P (operands[0]))
4253     {
4254       if ((mask & ~0xff) == 0)
4255         {
4256           cc_status.flags |= CC_NOT_NEGATIVE;
4257           return AS2 (test%B0,%1,%b0);
4258         }
4259
4260       if ((mask & ~0xff00) == 0)
4261         {
4262           cc_status.flags |= CC_NOT_NEGATIVE;
4263           operands[1] = GEN_INT (mask >> 8);
4264           return AS2 (test%B0,%1,%h0);
4265         }
4266     }
4267
4268   return AS2 (test%L0,%1,%0);
4269 }")
4270
4271 ;; ??? All bets are off if operand 0 is a volatile MEM reference.
4272 ;; The CPU may access unspecified bytes around the actual target byte.
4273
4274 (define_insn ""
4275   [(set (cc0) (zero_extract (match_operand:QI 0 "general_operand" "rm")
4276                             (match_operand:SI 1 "const_int_operand" "n")
4277                             (match_operand:SI 2 "const_int_operand" "n")))]
4278   "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])"
4279   "*
4280 {
4281   unsigned int mask;
4282
4283   mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
4284   operands[1] = GEN_INT (mask);
4285
4286   if (! REG_P (operands[0]) || QI_REG_P (operands[0]))
4287     {
4288       if ((mask & ~0xff) == 0)
4289         {
4290           cc_status.flags |= CC_NOT_NEGATIVE;
4291           return AS2 (test%B0,%1,%b0);
4292         }
4293
4294       if ((mask & ~0xff00) == 0)
4295         {
4296           cc_status.flags |= CC_NOT_NEGATIVE;
4297           operands[1] = GEN_INT (mask >> 8);
4298
4299           if (QI_REG_P (operands[0]))
4300             return AS2 (test%B0,%1,%h0);
4301           else
4302             {
4303               operands[0] = adj_offsettable_operand (operands[0], 1);
4304               return AS2 (test%B0,%1,%b0);
4305             }
4306         }
4307
4308       if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0)
4309         {
4310           cc_status.flags |= CC_NOT_NEGATIVE;
4311           operands[1] = GEN_INT (mask >> 16);
4312           operands[0] = adj_offsettable_operand (operands[0], 2);
4313           return AS2 (test%B0,%1,%b0);
4314         }
4315
4316       if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0)
4317         {
4318           cc_status.flags |= CC_NOT_NEGATIVE;
4319           operands[1] = GEN_INT (mask >> 24);
4320           operands[0] = adj_offsettable_operand (operands[0], 3);
4321           return AS2 (test%B0,%1,%b0);
4322         }
4323     }
4324
4325   if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
4326     return AS2 (test%L0,%1,%0);
4327
4328   return AS2 (test%L1,%0,%1);
4329 }")
4330 \f
4331 ;; Store-flag instructions.
4332
4333 ;; For all sCOND expanders, also expand the compare or test insn that
4334 ;; generates cc0.  Generate an equality comparison if `seq' or `sne'.
4335
4336 ;; The 386 sCOND opcodes can write to memory.  But a gcc sCOND insn may
4337 ;; not have any input reloads.  A MEM write might need an input reload
4338 ;; for the address of the MEM.  So don't allow MEM as the SET_DEST.
4339
4340 (define_expand "seq"
4341   [(match_dup 1)
4342    (set (match_operand:QI 0 "register_operand" "")
4343         (eq:QI (cc0) (const_int 0)))]
4344   ""
4345   "
4346 {
4347   if (TARGET_IEEE_FP
4348       && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4349     operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4350   else
4351     operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4352 }")
4353
4354 (define_insn ""
4355   [(set (match_operand:QI 0 "register_operand" "=q")
4356         (eq:QI (cc0) (const_int 0)))]
4357   ""
4358   "*
4359 {
4360   if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4361     return AS1 (setnb,%0);
4362   else
4363     return AS1 (sete,%0);
4364 }")
4365
4366 (define_expand "sne"
4367   [(match_dup 1)
4368    (set (match_operand:QI 0 "register_operand" "")
4369         (ne:QI (cc0) (const_int 0)))]
4370   ""
4371   "
4372 {
4373   if (TARGET_IEEE_FP
4374       && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4375     operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4376   else
4377     operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4378 }")
4379
4380 (define_insn ""
4381   [(set (match_operand:QI 0 "register_operand" "=q")
4382         (ne:QI (cc0) (const_int 0)))]
4383   ""
4384   "*
4385 {
4386   if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4387     return AS1 (setb,%0);
4388   else
4389     return AS1 (setne,%0);
4390 }
4391 ")
4392
4393 (define_expand "sgt"
4394   [(match_dup 1)
4395    (set (match_operand:QI 0 "register_operand" "")
4396         (gt:QI (cc0) (const_int 0)))]
4397   ""
4398   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4399
4400 (define_insn ""
4401   [(set (match_operand:QI 0 "register_operand" "=q")
4402         (gt:QI (cc0) (const_int 0)))]
4403   ""
4404   "*
4405 {
4406   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4407     return AS1 (sete,%0);
4408
4409   OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR);
4410 }")
4411
4412 (define_expand "sgtu"
4413   [(match_dup 1)
4414    (set (match_operand:QI 0 "register_operand" "")
4415         (gtu:QI (cc0) (const_int 0)))]
4416   ""
4417   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4418
4419 (define_insn ""
4420   [(set (match_operand:QI 0 "register_operand" "=q")
4421         (gtu:QI (cc0) (const_int 0)))]
4422   ""
4423   "* return \"seta %0\"; ")
4424
4425 (define_expand "slt"
4426   [(match_dup 1)
4427    (set (match_operand:QI 0 "register_operand" "")
4428         (lt:QI (cc0) (const_int 0)))]
4429   ""
4430   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4431
4432 (define_insn ""
4433   [(set (match_operand:QI 0 "register_operand" "=q")
4434         (lt:QI (cc0) (const_int 0)))]
4435   ""
4436   "*
4437 {
4438   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4439     return AS1 (sete,%0);
4440
4441   OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\");
4442 }")
4443
4444 (define_expand "sltu"
4445   [(match_dup 1)
4446    (set (match_operand:QI 0 "register_operand" "")
4447         (ltu:QI (cc0) (const_int 0)))]
4448   ""
4449   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4450
4451 (define_insn ""
4452   [(set (match_operand:QI 0 "register_operand" "=q")
4453         (ltu:QI (cc0) (const_int 0)))]
4454   ""
4455   "* return \"setb %0\"; ")
4456
4457 (define_expand "sge"
4458   [(match_dup 1)
4459    (set (match_operand:QI 0 "register_operand" "")
4460         (ge:QI (cc0) (const_int 0)))]
4461   ""
4462   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4463
4464 (define_insn ""
4465   [(set (match_operand:QI 0 "register_operand" "=q")
4466         (ge:QI (cc0) (const_int 0)))]
4467   ""
4468   "*
4469 {
4470   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4471     return AS1 (sete,%0);
4472
4473   OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\");
4474 }")
4475
4476 (define_expand "sgeu"
4477   [(match_dup 1)
4478    (set (match_operand:QI 0 "register_operand" "")
4479         (geu:QI (cc0) (const_int 0)))]
4480   ""
4481   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4482
4483 (define_insn ""
4484   [(set (match_operand:QI 0 "register_operand" "=q")
4485         (geu:QI (cc0) (const_int 0)))]
4486   ""
4487   "* return \"setae %0\"; ")
4488
4489 (define_expand "sle"
4490   [(match_dup 1)
4491    (set (match_operand:QI 0 "register_operand" "")
4492         (le:QI (cc0) (const_int 0)))]
4493   ""
4494   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4495
4496 (define_insn ""
4497   [(set (match_operand:QI 0 "register_operand" "=q")
4498         (le:QI (cc0) (const_int 0)))]
4499   ""
4500   "*
4501 {
4502   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4503     return AS1 (setb,%0);
4504
4505   OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR);
4506 }")
4507
4508 (define_expand "sleu"
4509   [(match_dup 1)
4510    (set (match_operand:QI 0 "register_operand" "")
4511         (leu:QI (cc0) (const_int 0)))]
4512   ""
4513   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4514
4515 (define_insn ""
4516   [(set (match_operand:QI 0 "register_operand" "=q")
4517         (leu:QI (cc0) (const_int 0)))]
4518   ""
4519   "* return \"setbe %0\"; ")
4520 \f
4521 ;; Basic conditional jump instructions.
4522 ;; We ignore the overflow flag for signed branch instructions.
4523
4524 ;; For all bCOND expanders, also expand the compare or test insn that
4525 ;; generates cc0.  Generate an equality comparison if `beq' or `bne'.
4526
4527 (define_expand "beq"
4528   [(match_dup 1)
4529    (set (pc)
4530         (if_then_else (eq (cc0)
4531                           (const_int 0))
4532                       (label_ref (match_operand 0 "" ""))
4533                       (pc)))]
4534   ""
4535   "
4536 {
4537   if (TARGET_IEEE_FP
4538       && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4539     operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4540   else
4541     operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4542 }")
4543
4544 (define_insn ""
4545   [(set (pc)
4546         (if_then_else (eq (cc0)
4547                           (const_int 0))
4548                       (label_ref (match_operand 0 "" ""))
4549                       (pc)))]
4550   ""
4551   "*
4552 {
4553   if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4554     return \"jnc %l0\";
4555   else
4556     return \"je %l0\";
4557 }")
4558
4559 (define_expand "bne"
4560   [(match_dup 1)
4561    (set (pc)
4562         (if_then_else (ne (cc0)
4563                           (const_int 0))
4564                       (label_ref (match_operand 0 "" ""))
4565                       (pc)))]
4566   ""
4567   "
4568 {
4569   if (TARGET_IEEE_FP
4570       && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4571     operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4572   else
4573     operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4574 }")
4575
4576 (define_insn ""
4577   [(set (pc)
4578         (if_then_else (ne (cc0)
4579                           (const_int 0))
4580                       (label_ref (match_operand 0 "" ""))
4581                       (pc)))]
4582   ""
4583   "*
4584 {
4585   if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4586     return \"jc %l0\";
4587   else
4588     return \"jne %l0\";
4589 }")
4590
4591 (define_expand "bgt"
4592   [(match_dup 1)
4593    (set (pc)
4594         (if_then_else (gt (cc0)
4595                           (const_int 0))
4596                       (label_ref (match_operand 0 "" ""))
4597                       (pc)))]
4598   ""
4599   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4600
4601 (define_insn ""
4602   [(set (pc)
4603         (if_then_else (gt (cc0)
4604                           (const_int 0))
4605                       (label_ref (match_operand 0 "" ""))
4606                       (pc)))]
4607   ""
4608   "*
4609 {
4610   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4611     return AS1 (je,%l0);
4612
4613   OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
4614 }")
4615
4616 (define_expand "bgtu"
4617   [(match_dup 1)
4618    (set (pc)
4619         (if_then_else (gtu (cc0)
4620                            (const_int 0))
4621                       (label_ref (match_operand 0 "" ""))
4622                       (pc)))]
4623   ""
4624   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4625
4626 (define_insn ""
4627   [(set (pc)
4628         (if_then_else (gtu (cc0)
4629                            (const_int 0))
4630                       (label_ref (match_operand 0 "" ""))
4631                       (pc)))]
4632   ""
4633   "ja %l0")
4634
4635 (define_expand "blt"
4636   [(match_dup 1)
4637    (set (pc)
4638         (if_then_else (lt (cc0)
4639                           (const_int 0))
4640                       (label_ref (match_operand 0 "" ""))
4641                       (pc)))]
4642   ""
4643   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4644
4645 (define_insn ""
4646   [(set (pc)
4647         (if_then_else (lt (cc0)
4648                           (const_int 0))
4649                       (label_ref (match_operand 0 "" ""))
4650                       (pc)))]
4651   ""
4652   "*
4653 {
4654   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4655     return AS1 (je,%l0);
4656
4657   OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
4658 }")
4659
4660 (define_expand "bltu"
4661   [(match_dup 1)
4662    (set (pc)
4663         (if_then_else (ltu (cc0)
4664                            (const_int 0))
4665                       (label_ref (match_operand 0 "" ""))
4666                       (pc)))]
4667   ""
4668   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4669
4670 (define_insn ""
4671   [(set (pc)
4672         (if_then_else (ltu (cc0)
4673                            (const_int 0))
4674                       (label_ref (match_operand 0 "" ""))
4675                       (pc)))]
4676   ""
4677   "jb %l0")
4678
4679 (define_expand "bge"
4680   [(match_dup 1)
4681    (set (pc)
4682         (if_then_else (ge (cc0)
4683                           (const_int 0))
4684                       (label_ref (match_operand 0 "" ""))
4685                       (pc)))]
4686   ""
4687   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4688
4689 (define_insn ""
4690   [(set (pc)
4691         (if_then_else (ge (cc0)
4692                           (const_int 0))
4693                       (label_ref (match_operand 0 "" ""))
4694                       (pc)))]
4695   ""
4696   "*
4697 {
4698   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4699     return AS1 (je,%l0);
4700
4701   OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
4702 }")
4703
4704 (define_expand "bgeu"
4705   [(match_dup 1)
4706    (set (pc)
4707         (if_then_else (geu (cc0)
4708                            (const_int 0))
4709                       (label_ref (match_operand 0 "" ""))
4710                       (pc)))]
4711   ""
4712   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4713
4714 (define_insn ""
4715   [(set (pc)
4716         (if_then_else (geu (cc0)
4717                            (const_int 0))
4718                       (label_ref (match_operand 0 "" ""))
4719                       (pc)))]
4720   ""
4721   "jae %l0")
4722
4723 (define_expand "ble"
4724   [(match_dup 1)
4725    (set (pc)
4726         (if_then_else (le (cc0)
4727                           (const_int 0))
4728                       (label_ref (match_operand 0 "" ""))
4729                       (pc)))]
4730   ""
4731   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4732
4733 (define_insn ""
4734   [(set (pc)
4735         (if_then_else (le (cc0)
4736                           (const_int 0))
4737                       (label_ref (match_operand 0 "" ""))
4738                       (pc)))]
4739   ""
4740   "*
4741 {
4742   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4743     return AS1 (jb,%l0);
4744
4745   OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
4746 }")
4747
4748 (define_expand "bleu"
4749   [(match_dup 1)
4750    (set (pc)
4751         (if_then_else (leu (cc0)
4752                            (const_int 0))
4753                       (label_ref (match_operand 0 "" ""))
4754                       (pc)))]
4755   ""
4756   "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4757
4758 (define_insn ""
4759   [(set (pc)
4760         (if_then_else (leu (cc0)
4761                            (const_int 0))
4762                       (label_ref (match_operand 0 "" ""))
4763                       (pc)))]
4764   ""
4765   "jbe %l0")
4766 \f
4767 ;; Negated conditional jump instructions.
4768
4769 (define_insn ""
4770   [(set (pc)
4771         (if_then_else (eq (cc0)
4772                           (const_int 0))
4773                       (pc)
4774                       (label_ref (match_operand 0 "" ""))))]
4775   ""
4776   "*
4777 {
4778   if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4779     return \"jc %l0\";
4780   else
4781     return \"jne %l0\";
4782 }")
4783
4784 (define_insn ""
4785   [(set (pc)
4786         (if_then_else (ne (cc0)
4787                           (const_int 0))
4788                       (pc)
4789                       (label_ref (match_operand 0 "" ""))))]
4790   ""
4791   "*
4792 {
4793   if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4794     return \"jnc %l0\";
4795   else
4796     return \"je %l0\";
4797 }")
4798
4799 (define_insn ""
4800   [(set (pc)
4801         (if_then_else (gt (cc0)
4802                           (const_int 0))
4803                       (pc)
4804                       (label_ref (match_operand 0 "" ""))))]
4805   ""
4806   "*
4807 {
4808   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4809     return AS1 (jne,%l0);
4810
4811   OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
4812 }")
4813
4814 (define_insn ""
4815   [(set (pc)
4816         (if_then_else (gtu (cc0)
4817                            (const_int 0))
4818                       (pc)
4819                       (label_ref (match_operand 0 "" ""))))]
4820   ""
4821   "jbe %l0")
4822
4823 (define_insn ""
4824   [(set (pc)
4825         (if_then_else (lt (cc0)
4826                           (const_int 0))
4827                       (pc)
4828                       (label_ref (match_operand 0 "" ""))))]
4829   ""
4830   "*
4831 {
4832   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4833     return AS1 (jne,%l0);
4834
4835   OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
4836 }")
4837
4838 (define_insn ""
4839   [(set (pc)
4840         (if_then_else (ltu (cc0)
4841                            (const_int 0))
4842                       (pc)
4843                       (label_ref (match_operand 0 "" ""))))]
4844   ""
4845   "jae %l0")
4846
4847 (define_insn ""
4848   [(set (pc)
4849         (if_then_else (ge (cc0)
4850                           (const_int 0))
4851                       (pc)
4852                       (label_ref (match_operand 0 "" ""))))]
4853   ""
4854   "*
4855 {
4856   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4857     return AS1 (jne,%l0);
4858
4859   OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
4860 }")
4861
4862 (define_insn ""
4863   [(set (pc)
4864         (if_then_else (geu (cc0)
4865                            (const_int 0))
4866                       (pc)
4867                       (label_ref (match_operand 0 "" ""))))]
4868   ""
4869   "jb %l0")
4870
4871 (define_insn ""
4872   [(set (pc)
4873         (if_then_else (le (cc0)
4874                           (const_int 0))
4875                       (pc)
4876                       (label_ref (match_operand 0 "" ""))))]
4877   ""
4878   "*
4879 {
4880   if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4881     return AS1 (jae,%l0);
4882
4883   OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
4884 }")
4885
4886 (define_insn ""
4887   [(set (pc)
4888         (if_then_else (leu (cc0)
4889                            (const_int 0))
4890                       (pc)
4891                       (label_ref (match_operand 0 "" ""))))]
4892   ""
4893   "ja %l0")
4894 \f
4895 ;; Unconditional and other jump instructions
4896
4897 (define_insn "jump"
4898   [(set (pc)
4899         (label_ref (match_operand 0 "" "")))]
4900   ""
4901   "jmp %l0")
4902
4903 (define_insn "indirect_jump"
4904   [(set (pc) (match_operand:SI 0 "general_operand" "rm"))]
4905   ""
4906   "*
4907 {
4908   CC_STATUS_INIT;
4909
4910   return AS1 (jmp,%*%0);
4911 }")
4912
4913 ;; ??? could transform while(--i > 0) S; to if (--i > 0) do S; while(--i);
4914 ;;     if S does not change i
4915
4916 (define_expand "decrement_and_branch_until_zero"
4917   [(parallel [(set (pc)
4918                    (if_then_else (ge (plus:SI (match_operand:SI 0 "general_operand" "")
4919                                               (const_int -1))
4920                                      (const_int 0))
4921                                  (label_ref (match_operand 1 "" ""))
4922                                  (pc)))
4923               (set (match_dup 0)
4924                    (plus:SI (match_dup 0)
4925                             (const_int -1)))])]
4926   ""
4927   "")
4928
4929 (define_insn ""
4930   [(set (pc)
4931         (if_then_else (match_operator 0 "arithmetic_comparison_operator"
4932                                       [(plus:SI (match_operand:SI 1 "general_operand" "+r,m")
4933                                                 (match_operand:SI 2 "general_operand" "rmi,ri"))
4934                                        (const_int 0)])
4935                       (label_ref (match_operand 3 "" ""))
4936                       (pc)))
4937    (set (match_dup 1)
4938         (plus:SI (match_dup 1)
4939                  (match_dup 2)))]
4940   ""
4941   "*
4942 {
4943   CC_STATUS_INIT;
4944   if (operands[2] == constm1_rtx)
4945     output_asm_insn (AS1 (dec%L1,%1), operands);
4946
4947   else if (operands[1] == const1_rtx)
4948     output_asm_insn (AS1 (inc%L1,%1), operands);
4949
4950   else
4951     output_asm_insn (AS2 (add%L1,%2,%1), operands);
4952
4953   return AS1 (%J0,%l3);
4954 }")
4955
4956 (define_insn ""
4957   [(set (pc)
4958         (if_then_else (match_operator 0 "arithmetic_comparison_operator"
4959                                       [(minus:SI (match_operand:SI 1 "general_operand" "+r,m")
4960                                                  (match_operand:SI 2 "general_operand" "rmi,ri"))
4961                                        (const_int 0)])
4962                       (label_ref (match_operand 3 "" ""))
4963                       (pc)))
4964    (set (match_dup 1)
4965         (minus:SI (match_dup 1)
4966                   (match_dup 2)))]
4967   ""
4968   "*
4969 {
4970   CC_STATUS_INIT;
4971   if (operands[2] == const1_rtx)
4972     output_asm_insn (AS1 (dec%L1,%1), operands);
4973
4974   else if (operands[1] == constm1_rtx)
4975     output_asm_insn (AS1 (inc%L1,%1), operands);
4976
4977   else
4978     output_asm_insn (AS2 (sub%L1,%2,%1), operands);
4979
4980   return AS1 (%J0,%l3);
4981 }")
4982
4983 ;; Implement switch statements when generating PIC code.  Switches are
4984 ;; implemented by `tablejump' when not using -fpic.
4985
4986 ;; Emit code here to do the range checking and make the index zero based.
4987
4988 (define_expand "casesi"
4989   [(set (match_dup 5)
4990         (minus:SI (match_operand:SI 0 "general_operand" "")
4991                   (match_operand:SI 1 "general_operand" "")))
4992    (set (cc0)
4993         (compare:CC (match_dup 5)
4994                     (match_operand:SI 2 "general_operand" "")))
4995    (set (pc)
4996         (if_then_else (gtu (cc0)
4997                            (const_int 0))
4998                       (label_ref (match_operand 4 "" ""))
4999                       (pc)))
5000    (parallel
5001     [(set (pc)
5002           (minus:SI (reg:SI 3)
5003                     (mem:SI (plus:SI (mult:SI (match_dup 5)
5004                                               (const_int 4))
5005                                      (label_ref (match_operand 3 "" ""))))))
5006      (clobber (match_scratch:SI 6 ""))])]
5007   "flag_pic"
5008   "
5009 {
5010   operands[5] = gen_reg_rtx (SImode);
5011   current_function_uses_pic_offset_table = 1;
5012 }")
5013
5014 ;; Implement a casesi insn.
5015
5016 ;; Each entry in the "addr_diff_vec" looks like this as the result of the
5017 ;; two rules below:
5018 ;; 
5019 ;;      .long _GLOBAL_OFFSET_TABLE_+[.-.L2]
5020 ;; 
5021 ;; 1. An expression involving an external reference may only use the
5022 ;;    addition operator, and only with an assembly-time constant.
5023 ;;    The example above satisfies this because ".-.L2" is a constant.
5024 ;; 
5025 ;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is
5026 ;;    given the value of "GOT - .", where GOT is the actual address of
5027 ;;    the Global Offset Table.  Therefore, the .long above actually
5028 ;;    stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2".  The
5029 ;;    expression "GOT - .L2" by itself would generate an error from as(1).
5030 ;; 
5031 ;; The pattern below emits code that looks like this:
5032 ;; 
5033 ;;      movl %ebx,reg
5034 ;;      subl TABLE@GOTOFF(%ebx,index,4),reg
5035 ;;      jmp reg
5036 ;; 
5037 ;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since
5038 ;; the addr_diff_vec is known to be part of this module.
5039 ;; 
5040 ;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which
5041 ;; evaluates to just ".L2".
5042
5043 (define_insn ""
5044   [(set (pc)
5045         (minus:SI (reg:SI 3)
5046                   (mem:SI (plus:SI
5047                            (mult:SI (match_operand:SI 0 "register_operand" "r")
5048                                     (const_int 4))
5049                            (label_ref (match_operand 1 "" ""))))))
5050    (clobber (match_scratch:SI 2 "=&r"))]
5051   ""
5052   "*
5053 {
5054   rtx xops[4];
5055
5056   xops[0] = operands[0];
5057   xops[1] = operands[1];
5058   xops[2] = operands[2];
5059   xops[3] = pic_offset_table_rtx;
5060
5061   output_asm_insn (AS2 (mov%L2,%3,%2), xops);
5062   output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops);
5063   output_asm_insn (AS1 (jmp,%*%2), xops);
5064   ASM_OUTPUT_ALIGN_CODE (asm_out_file);
5065   RET;
5066 }")
5067
5068 (define_insn "tablejump"
5069   [(set (pc) (match_operand:SI 0 "general_operand" "rm"))
5070    (use (label_ref (match_operand 1 "" "")))]
5071   ""
5072   "*
5073 {
5074   CC_STATUS_INIT;
5075
5076   return AS1 (jmp,%*%0);
5077 }")
5078
5079 ;; Call insns.
5080
5081 ;; If generating PIC code, the predicate indirect_operand will fail
5082 ;; for operands[0] containing symbolic references on all of the named
5083 ;; call* patterns.  Each named pattern is followed by an unnamed pattern
5084 ;; that matches any call to a symbolic CONST (ie, a symbol_ref).  The
5085 ;; unnamed patterns are only used while generating PIC code, because
5086 ;; otherwise the named patterns match.
5087
5088 ;; Call subroutine returning no value.
5089
5090 (define_expand "call_pop"
5091   [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
5092                     (match_operand:SI 1 "general_operand" ""))
5093               (set (reg:SI 7)
5094                    (plus:SI (reg:SI 7)
5095                             (match_operand:SI 3 "immediate_operand" "")))])]
5096   ""
5097   "
5098 {
5099   rtx addr;
5100
5101   if (flag_pic)
5102     current_function_uses_pic_offset_table = 1;
5103
5104   /* With half-pic, force the address into a register.  */
5105   addr = XEXP (operands[0], 0);
5106   if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
5107     XEXP (operands[0], 0) = force_reg (Pmode, addr);
5108
5109   if (! expander_call_insn_operand (operands[0], QImode))
5110     operands[0]
5111       = change_address (operands[0], VOIDmode,
5112                         copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
5113 }")
5114
5115 (define_insn ""
5116   [(call (match_operand:QI 0 "call_insn_operand" "m")
5117          (match_operand:SI 1 "general_operand" "g"))
5118    (set (reg:SI 7) (plus:SI (reg:SI 7)
5119                             (match_operand:SI 3 "immediate_operand" "i")))]
5120   ""
5121   "*
5122 {
5123   if (GET_CODE (operands[0]) == MEM
5124       && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
5125     {
5126       operands[0] = XEXP (operands[0], 0);
5127       return AS1 (call,%*%0);
5128     }
5129   else
5130     return AS1 (call,%P0);
5131 }")
5132
5133 (define_insn ""
5134   [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
5135          (match_operand:SI 1 "general_operand" "g"))
5136    (set (reg:SI 7) (plus:SI (reg:SI 7)
5137                             (match_operand:SI 3 "immediate_operand" "i")))]
5138   "!HALF_PIC_P ()"
5139   "call %P0")
5140
5141 (define_expand "call"
5142   [(call (match_operand:QI 0 "indirect_operand" "")
5143          (match_operand:SI 1 "general_operand" ""))]
5144   ;; Operand 1 not used on the i386.
5145   ""
5146   "
5147 {
5148   rtx addr;
5149
5150   if (flag_pic)
5151     current_function_uses_pic_offset_table = 1;
5152
5153   /* With half-pic, force the address into a register.  */
5154   addr = XEXP (operands[0], 0);
5155   if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
5156     XEXP (operands[0], 0) = force_reg (Pmode, addr);
5157
5158   if (! expander_call_insn_operand (operands[0], QImode))
5159     operands[0]
5160       = change_address (operands[0], VOIDmode,
5161                         copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
5162 }")
5163
5164 (define_insn ""
5165   [(call (match_operand:QI 0 "call_insn_operand" "m")
5166          (match_operand:SI 1 "general_operand" "g"))]
5167   ;; Operand 1 not used on the i386.
5168   ""
5169   "*
5170 {
5171   if (GET_CODE (operands[0]) == MEM
5172       && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
5173     {
5174       operands[0] = XEXP (operands[0], 0);
5175       return AS1 (call,%*%0);
5176     }
5177   else
5178     return AS1 (call,%P0);
5179 }")
5180
5181 (define_insn ""
5182   [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
5183          (match_operand:SI 1 "general_operand" "g"))]
5184   ;; Operand 1 not used on the i386.
5185   "!HALF_PIC_P ()"
5186   "call %P0")
5187
5188 ;; Call subroutine, returning value in operand 0
5189 ;; (which must be a hard register).
5190
5191 (define_expand "call_value_pop"
5192   [(parallel [(set (match_operand 0 "" "")
5193                    (call (match_operand:QI 1 "indirect_operand" "")
5194                          (match_operand:SI 2 "general_operand" "")))
5195               (set (reg:SI 7)
5196                    (plus:SI (reg:SI 7)
5197                             (match_operand:SI 4 "immediate_operand" "")))])]
5198   ""
5199   "
5200 {
5201   rtx addr;
5202
5203   if (flag_pic)
5204     current_function_uses_pic_offset_table = 1;
5205
5206   /* With half-pic, force the address into a register.  */
5207   addr = XEXP (operands[1], 0);
5208   if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
5209     XEXP (operands[1], 0) = force_reg (Pmode, addr);
5210
5211   if (! expander_call_insn_operand (operands[1], QImode))
5212     operands[1]
5213       = change_address (operands[1], VOIDmode,
5214                         copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
5215 }")
5216
5217 (define_insn ""
5218   [(set (match_operand 0 "" "=rf")
5219         (call (match_operand:QI 1 "call_insn_operand" "m")
5220               (match_operand:SI 2 "general_operand" "g")))
5221    (set (reg:SI 7) (plus:SI (reg:SI 7)
5222                             (match_operand:SI 4 "immediate_operand" "i")))]
5223   ""
5224   "*
5225 {
5226   if (GET_CODE (operands[1]) == MEM
5227       && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
5228     {
5229       operands[1] = XEXP (operands[1], 0);
5230       output_asm_insn (AS1 (call,%*%1), operands);
5231     }
5232   else
5233     output_asm_insn (AS1 (call,%P1), operands);
5234
5235   RET;
5236 }")
5237
5238 (define_insn ""
5239   [(set (match_operand 0 "" "=rf")
5240         (call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
5241               (match_operand:SI 2 "general_operand" "g")))
5242    (set (reg:SI 7) (plus:SI (reg:SI 7)
5243                             (match_operand:SI 4 "immediate_operand" "i")))]
5244   "!HALF_PIC_P ()"
5245   "call %P1")
5246
5247 (define_expand "call_value"
5248   [(set (match_operand 0 "" "")
5249         (call (match_operand:QI 1 "indirect_operand" "")
5250               (match_operand:SI 2 "general_operand" "")))]
5251   ;; Operand 2 not used on the i386.
5252   ""
5253   "
5254 {
5255   rtx addr;
5256
5257   if (flag_pic)
5258     current_function_uses_pic_offset_table = 1;
5259
5260   /* With half-pic, force the address into a register.  */
5261   addr = XEXP (operands[1], 0);
5262   if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
5263     XEXP (operands[1], 0) = force_reg (Pmode, addr);
5264
5265   if (! expander_call_insn_operand (operands[1], QImode))
5266     operands[1]
5267       = change_address (operands[1], VOIDmode,
5268                         copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
5269 }")
5270
5271 (define_insn ""
5272   [(set (match_operand 0 "" "=rf")
5273         (call (match_operand:QI 1 "call_insn_operand" "m")
5274               (match_operand:SI 2 "general_operand" "g")))]
5275   ;; Operand 2 not used on the i386.
5276   ""
5277   "*
5278 {
5279   if (GET_CODE (operands[1]) == MEM
5280       && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
5281     {
5282       operands[1] = XEXP (operands[1], 0);
5283       output_asm_insn (AS1 (call,%*%1), operands);
5284     }
5285   else
5286     output_asm_insn (AS1 (call,%P1), operands);
5287
5288   RET;
5289 }")
5290
5291 (define_insn ""
5292   [(set (match_operand 0 "" "=rf")
5293         (call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
5294               (match_operand:SI 2 "general_operand" "g")))]
5295   ;; Operand 2 not used on the i386.
5296   "!HALF_PIC_P ()"
5297   "call %P1")
5298
5299 ;; Call subroutine returning any type.
5300
5301 (define_expand "untyped_call"
5302   [(parallel [(call (match_operand 0 "" "")
5303                     (const_int 0))
5304               (match_operand 1 "" "")
5305               (match_operand 2 "" "")])]
5306   ""
5307   "
5308 {
5309   int i;
5310
5311   /* In order to give reg-stack an easier job in validating two
5312      coprocessor registers as containing a possible return value,
5313      simply pretend the untyped call returns a complex long double
5314      value.  */
5315   emit_call_insn (TARGET_80387
5316                   ? gen_call_value (gen_rtx (REG, XCmode, FIRST_FLOAT_REG),
5317                                   operands[0], const0_rtx)
5318                   : gen_call (operands[0], const0_rtx));
5319
5320   for (i = 0; i < XVECLEN (operands[2], 0); i++)
5321     {
5322       rtx set = XVECEXP (operands[2], 0, i);
5323       emit_move_insn (SET_DEST (set), SET_SRC (set));
5324     }
5325
5326   /* The optimizer does not know that the call sets the function value
5327      registers we stored in the result block.  We avoid problems by
5328      claiming that all hard registers are used and clobbered at this
5329      point.  */
5330   emit_insn (gen_blockage ());
5331
5332   DONE;
5333 }")
5334
5335 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5336 ;; all of memory.  This blocks insns from being moved across this point.
5337
5338 (define_insn "blockage"
5339   [(unspec_volatile [(const_int 0)] 0)]
5340   ""
5341   "")
5342
5343 ;; Insn emitted into the body of a function to return from a function.
5344 ;; This is only done if the function's epilogue is known to be simple.
5345 ;; See comments for simple_386_epilogue in i386.c.
5346
5347 (define_insn "return"
5348   [(return)]
5349   "simple_386_epilogue ()"
5350   "*
5351 {
5352   function_epilogue (asm_out_file, get_frame_size ());
5353   RET;
5354 }")
5355
5356 (define_insn "nop"
5357   [(const_int 0)]
5358   ""
5359   "nop")
5360
5361 (define_expand "movstrsi"
5362   [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
5363                    (match_operand:BLK 1 "memory_operand" ""))
5364               (use (match_operand:SI 2 "const_int_operand" ""))
5365               (use (match_operand:SI 3 "const_int_operand" ""))
5366               (clobber (match_scratch:SI 4 ""))
5367               (clobber (match_dup 5))
5368               (clobber (match_dup 6))])]
5369   ""
5370   "
5371 {
5372   rtx addr0, addr1;
5373
5374   if (GET_CODE (operands[2]) != CONST_INT)
5375     FAIL;
5376
5377   addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
5378   addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
5379
5380   operands[5] = addr0;
5381   operands[6] = addr1;
5382
5383   operands[0] = gen_rtx (MEM, BLKmode, addr0);
5384   operands[1] = gen_rtx (MEM, BLKmode, addr1);
5385 }")
5386
5387 ;; It might seem that operands 0 & 1 could use predicate register_operand.
5388 ;; But strength reduction might offset the MEM expression.  So we let
5389 ;; reload put the address into %edi & %esi.
5390
5391 (define_insn ""
5392   [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
5393         (mem:BLK (match_operand:SI 1 "address_operand" "S")))
5394    (use (match_operand:SI 2 "const_int_operand" "n"))
5395    (use (match_operand:SI 3 "immediate_operand" "i"))
5396    (clobber (match_scratch:SI 4 "=&c"))
5397    (clobber (match_dup 0))
5398    (clobber (match_dup 1))]
5399   ""
5400   "*
5401 {
5402   rtx xops[2];
5403
5404   output_asm_insn (\"cld\", operands);
5405   if (GET_CODE (operands[2]) == CONST_INT)
5406     {
5407       if (INTVAL (operands[2]) & ~0x03)
5408         {
5409           xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff);
5410           xops[1] = operands[4];
5411
5412           output_asm_insn (AS2 (mov%L1,%0,%1), xops);
5413 #ifdef INTEL_SYNTAX
5414           output_asm_insn (\"rep movsd\", xops);
5415 #else
5416           output_asm_insn (\"rep\;movsl\", xops);
5417 #endif
5418         }
5419       if (INTVAL (operands[2]) & 0x02)
5420         output_asm_insn (\"movsw\", operands);
5421       if (INTVAL (operands[2]) & 0x01)
5422         output_asm_insn (\"movsb\", operands);
5423     }
5424   else
5425     abort ();
5426   RET;
5427 }")
5428
5429 (define_expand "cmpstrsi"
5430   [(parallel [(set (match_operand:SI 0 "general_operand" "")
5431                    (compare:SI (match_operand:BLK 1 "general_operand" "")
5432                                (match_operand:BLK 2 "general_operand" "")))
5433               (use (match_operand:SI 3 "general_operand" ""))
5434               (use (match_operand:SI 4 "immediate_operand" ""))
5435               (clobber (match_dup 5))
5436               (clobber (match_dup 6))
5437               (clobber (match_dup 3))])]
5438   ""
5439   "
5440 {
5441   rtx addr1, addr2;
5442
5443   addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
5444   addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
5445   operands[3] = copy_to_mode_reg (SImode, operands[3]);
5446
5447   operands[5] = addr1;
5448   operands[6] = addr2;
5449
5450   operands[1] = gen_rtx (MEM, BLKmode, addr1);
5451   operands[2] = gen_rtx (MEM, BLKmode, addr2);
5452
5453 }")
5454
5455 ;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
5456 ;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
5457
5458 ;; It might seem that operands 0 & 1 could use predicate register_operand.
5459 ;; But strength reduction might offset the MEM expression.  So we let
5460 ;; reload put the address into %edi & %esi.
5461
5462 ;; ??? Most comparisons have a constant length, and it's therefore
5463 ;; possible to know that the length is non-zero, and to avoid the extra
5464 ;; code to handle zero-length compares.
5465
5466 (define_insn ""
5467   [(set (match_operand:SI 0 "general_operand" "=&r")
5468         (compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S"))
5469                     (mem:BLK (match_operand:SI 2 "address_operand" "D"))))
5470    (use (match_operand:SI 3 "register_operand" "c"))
5471    (use (match_operand:SI 4 "immediate_operand" "i"))
5472    (clobber (match_dup 1))
5473    (clobber (match_dup 2))
5474    (clobber (match_dup 3))]
5475   ""
5476   "*
5477 {
5478   rtx xops[4], label;
5479
5480   label = gen_label_rtx ();
5481
5482   output_asm_insn (\"cld\", operands);
5483   output_asm_insn (AS2 (xor%L0,%0,%0), operands);
5484   output_asm_insn (\"repz\;cmps%B2\", operands);
5485   output_asm_insn (\"je %l0\", &label);
5486
5487   xops[0] = operands[0];
5488   xops[1] = gen_rtx (MEM, QImode,
5489                      gen_rtx (PLUS, SImode, operands[1], constm1_rtx));
5490   xops[2] = gen_rtx (MEM, QImode,
5491                      gen_rtx (PLUS, SImode, operands[2], constm1_rtx));
5492   xops[3] = operands[3];
5493
5494   output_asm_insn (AS2 (movz%B1%L0,%1,%0), xops);
5495   output_asm_insn (AS2 (movz%B2%L3,%2,%3), xops);
5496
5497   output_asm_insn (AS2 (sub%L0,%3,%0), xops);
5498   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label));
5499   RET;
5500 }")
5501
5502 (define_insn ""
5503   [(set (cc0)
5504         (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
5505                     (mem:BLK (match_operand:SI 1 "address_operand" "D"))))
5506    (use (match_operand:SI 2 "register_operand" "c"))
5507    (use (match_operand:SI 3 "immediate_operand" "i"))
5508    (clobber (match_dup 0))
5509    (clobber (match_dup 1))
5510    (clobber (match_dup 2))]
5511   ""
5512   "*
5513 {
5514   rtx xops[2];
5515
5516   cc_status.flags |= CC_NOT_SIGNED;
5517
5518   xops[0] = gen_rtx (REG, QImode, 0);
5519   xops[1] = CONST0_RTX (QImode);
5520
5521   output_asm_insn (\"cld\", operands);
5522   output_asm_insn (AS2 (test%B0,%1,%0), xops);
5523   return \"repz\;cmps%B2\";
5524 }")
5525
5526 (define_expand "ffssi2"
5527   [(set (match_dup 2)
5528         (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" ""))
5529                  (const_int -1)))
5530    (set (match_operand:SI 0 "general_operand" "")
5531         (plus:SI (match_dup 2) (const_int 1)))]
5532   ""
5533   "operands[2] = gen_reg_rtx (SImode);")
5534
5535 ;; Note, you cannot optimize away the branch following the bsfl by assuming
5536 ;; that the destination is not modified if the input is 0, since not all
5537 ;; x86 implementations do this.
5538
5539 (define_insn ""
5540   [(set (match_operand:SI 0 "general_operand" "=&r")
5541         (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "rm"))
5542                  (const_int -1)))]
5543   ""
5544   "*
5545 {
5546   rtx xops[3];
5547   static int ffssi_label_number;
5548   char buffer[30];
5549
5550   xops[0] = operands[0];
5551   xops[1] = operands[1];
5552   xops[2] = constm1_rtx;
5553   output_asm_insn (AS2 (bsf%L0,%1,%0), xops);
5554 #ifdef LOCAL_LABEL_PREFIX
5555   sprintf (buffer, \"jnz %sLFFSSI%d\",
5556            LOCAL_LABEL_PREFIX, ffssi_label_number);
5557 #else
5558   sprintf (buffer, \"jnz %sLFFSSI%d\",
5559            \"\", ffssi_label_number);
5560 #endif
5561   output_asm_insn (buffer, xops);
5562   output_asm_insn (AS2 (mov%L0,%2,%0), xops);
5563 #ifdef LOCAL_LABEL_PREFIX
5564   sprintf (buffer, \"%sLFFSSI%d:\",
5565            LOCAL_LABEL_PREFIX, ffssi_label_number);
5566 #else
5567   sprintf (buffer, \"%sLFFSSI%d:\",
5568            \"\", ffssi_label_number);
5569 #endif
5570   output_asm_insn (buffer, xops);
5571
5572   ffssi_label_number++;
5573   return \"\";
5574 }")
5575
5576 (define_expand "ffshi2"
5577   [(set (match_dup 2)
5578         (plus:HI (ffs:HI (match_operand:HI 1 "general_operand" ""))
5579                  (const_int -1)))
5580    (set (match_operand:HI 0 "general_operand" "")
5581         (plus:HI (match_dup 2) (const_int 1)))]
5582   ""
5583   "operands[2] = gen_reg_rtx (HImode);")
5584
5585 (define_insn ""
5586   [(set (match_operand:HI 0 "general_operand" "=&r")
5587         (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm"))
5588                  (const_int -1)))]
5589   ""
5590   "*
5591 {
5592   rtx xops[3];
5593   static int ffshi_label_number;
5594   char buffer[30];
5595
5596   xops[0] = operands[0];
5597   xops[1] = operands[1];
5598   xops[2] = constm1_rtx;
5599   output_asm_insn (AS2 (bsf%W0,%1,%0), xops);
5600 #ifdef LOCAL_LABEL_PREFIX
5601   sprintf (buffer, \"jnz %sLFFSHI%d\",
5602            LOCAL_LABEL_PREFIX, ffshi_label_number);
5603 #else
5604   sprintf (buffer, \"jnz %sLFFSHI%d\",
5605            \"\", ffshi_label_number);
5606 #endif
5607   output_asm_insn (buffer, xops);
5608   output_asm_insn (AS2 (mov%W0,%2,%0), xops);
5609 #ifdef LOCAL_LABEL_PREFIX
5610   sprintf (buffer, \"%sLFFSHI%d:\",
5611            LOCAL_LABEL_PREFIX, ffshi_label_number);
5612 #else
5613   sprintf (buffer, \"%sLFFSHI%d:\",
5614            \"\", ffshi_label_number);
5615 #endif
5616   output_asm_insn (buffer, xops);
5617
5618   ffshi_label_number++;
5619   return \"\";
5620 }")
5621 \f
5622 ;; These patterns match the binary 387 instructions for addM3, subM3,
5623 ;; mulM3 and divM3.  There are three patterns for each of DFmode and
5624 ;; SFmode.  The first is the normal insn, the second the same insn but
5625 ;; with one operand a conversion, and the third the same insn but with
5626 ;; the other operand a conversion.  The conversion may be SFmode or
5627 ;; SImode if the target mode DFmode, but only SImode if the target mode
5628 ;; is SFmode.
5629
5630 (define_insn ""
5631   [(set (match_operand:DF 0 "register_operand" "=f,f")
5632         (match_operator:DF 3 "binary_387_op"
5633                         [(match_operand:DF 1 "nonimmediate_operand" "0,fm")
5634                          (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
5635   "TARGET_80387"
5636   "* return output_387_binary_op (insn, operands);")
5637
5638 (define_insn ""
5639   [(set (match_operand:DF 0 "register_operand" "=f")
5640         (match_operator:DF 3 "binary_387_op"
5641            [(float:DF (match_operand:SI 1 "general_operand" "rm"))
5642             (match_operand:DF 2 "general_operand" "0")]))]
5643   "TARGET_80387"
5644   "* return output_387_binary_op (insn, operands);")
5645
5646 (define_insn ""
5647   [(set (match_operand:XF 0 "register_operand" "=f,f")
5648         (match_operator:XF 3 "binary_387_op"
5649                         [(match_operand:XF 1 "nonimmediate_operand" "0,f")
5650                          (match_operand:XF 2 "nonimmediate_operand" "f,0")]))]
5651   "TARGET_80387"
5652   "* return output_387_binary_op (insn, operands);")
5653
5654 (define_insn ""
5655   [(set (match_operand:XF 0 "register_operand" "=f")
5656         (match_operator:XF 3 "binary_387_op"
5657            [(float:XF (match_operand:SI 1 "general_operand" "rm"))
5658             (match_operand:XF 2 "general_operand" "0")]))]
5659   "TARGET_80387"
5660   "* return output_387_binary_op (insn, operands);")
5661
5662 (define_insn ""
5663   [(set (match_operand:XF 0 "register_operand" "=f,f")
5664         (match_operator:XF 3 "binary_387_op"
5665            [(float_extend:XF (match_operand:SF 1 "general_operand" "fm,0"))
5666             (match_operand:XF 2 "general_operand" "0,f")]))]
5667   "TARGET_80387"
5668   "* return output_387_binary_op (insn, operands);")
5669
5670 (define_insn ""
5671   [(set (match_operand:XF 0 "register_operand" "=f")
5672         (match_operator:XF 3 "binary_387_op"
5673           [(match_operand:XF 1 "general_operand" "0")
5674            (float:XF (match_operand:SI 2 "general_operand" "rm"))]))]
5675   "TARGET_80387"
5676   "* return output_387_binary_op (insn, operands);")
5677
5678 (define_insn ""
5679   [(set (match_operand:XF 0 "register_operand" "=f,f")
5680         (match_operator:XF 3 "binary_387_op"
5681           [(match_operand:XF 1 "general_operand" "0,f")
5682            (float_extend:XF
5683             (match_operand:SF 2 "general_operand" "fm,0"))]))]
5684   "TARGET_80387"
5685   "* return output_387_binary_op (insn, operands);")
5686
5687 (define_insn ""
5688   [(set (match_operand:DF 0 "register_operand" "=f,f")
5689         (match_operator:DF 3 "binary_387_op"
5690            [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0"))
5691             (match_operand:DF 2 "general_operand" "0,f")]))]
5692   "TARGET_80387"
5693   "* return output_387_binary_op (insn, operands);")
5694
5695 (define_insn ""
5696   [(set (match_operand:DF 0 "register_operand" "=f")
5697         (match_operator:DF 3 "binary_387_op"
5698           [(match_operand:DF 1 "general_operand" "0")
5699            (float:DF (match_operand:SI 2 "general_operand" "rm"))]))]
5700   "TARGET_80387"
5701   "* return output_387_binary_op (insn, operands);")
5702
5703 (define_insn ""
5704   [(set (match_operand:DF 0 "register_operand" "=f,f")
5705         (match_operator:DF 3 "binary_387_op"
5706           [(match_operand:DF 1 "general_operand" "0,f")
5707            (float_extend:DF
5708             (match_operand:SF 2 "general_operand" "fm,0"))]))]
5709   "TARGET_80387"
5710   "* return output_387_binary_op (insn, operands);")
5711
5712 (define_insn ""
5713   [(set (match_operand:SF 0 "register_operand" "=f,f")
5714         (match_operator:SF 3 "binary_387_op"
5715                         [(match_operand:SF 1 "nonimmediate_operand" "0,fm")
5716                          (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
5717   "TARGET_80387"
5718   "* return output_387_binary_op (insn, operands);")
5719
5720 (define_insn ""
5721   [(set (match_operand:SF 0 "register_operand" "=f")
5722         (match_operator:SF 3 "binary_387_op"
5723           [(float:SF (match_operand:SI 1 "general_operand" "rm"))
5724            (match_operand:SF 2 "general_operand" "0")]))]
5725   "TARGET_80387"
5726   "* return output_387_binary_op (insn, operands);")
5727
5728 (define_insn ""
5729   [(set (match_operand:SF 0 "register_operand" "=f")
5730         (match_operator:SF 3 "binary_387_op"
5731           [(match_operand:SF 1 "general_operand" "0")
5732            (float:SF (match_operand:SI 2 "general_operand" "rm"))]))]
5733   "TARGET_80387"
5734   "* return output_387_binary_op (insn, operands);")
5735 \f
5736 (define_expand "strlensi"
5737   [(parallel [(set (match_dup 4)
5738                    (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" ""))
5739                                (match_operand:QI 2 "register_operand" "")
5740                                (match_operand:SI 3 "immediate_operand" "")] 0))
5741               (clobber (match_dup 1))])
5742    (set (match_dup 5)
5743         (not:SI (match_dup 4)))
5744    (set (match_operand:SI 0 "register_operand" "")
5745         (minus:SI (match_dup 5)
5746                  (const_int 1)))]
5747   ""
5748   "
5749 {
5750   operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5751   operands[4] = gen_reg_rtx (SImode);
5752   operands[5] = gen_reg_rtx (SImode);
5753 }")
5754
5755 ;; It might seem that operands 0 & 1 could use predicate register_operand.
5756 ;; But strength reduction might offset the MEM expression.  So we let
5757 ;; reload put the address into %edi.
5758
5759 (define_insn ""
5760   [(set (match_operand:SI 0 "register_operand" "=&c")
5761         (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D"))
5762                     (match_operand:QI 2 "register_operand" "a")
5763                     (match_operand:SI 3 "immediate_operand" "i")] 0))
5764    (clobber (match_dup 1))]
5765   ""
5766   "*
5767 {
5768   rtx xops[2];
5769
5770   xops[0] = operands[0];
5771   xops[1] = constm1_rtx;
5772   output_asm_insn (\"cld\", operands);
5773   output_asm_insn (AS2 (mov%L0,%1,%0), xops);
5774   return \"repnz\;scas%B2\";
5775 }")