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