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