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