]> gcc.gnu.org Git - gcc.git/blob - gcc/config/i386/i386.md
* i386.md (movdi-1, movdi): Rewrite based on SI move patterns.
[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"))]
1638 ""
1639 "* return output_move_double (operands);")
1640
1641 (define_insn ""
1642 [(set (match_operand:DI 0 "push_operand" "=<")
1643 (match_operand:DI 1 "memory_operand" "o"))]
1644 "TARGET_PUSH_MEMORY"
1645 "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode),0,0);")
1646
1647 (define_expand "movdi"
1648 [(set (match_operand:DI 0 "general_operand" "")
1649 (match_operand:DI 1 "general_operand" ""))]
1650 ""
1651 "
1652 {
1653 /* Don't generate memory->memory moves, go through a register */
1654 if (TARGET_MOVE
1655 && (reload_in_progress | reload_completed) == 0
1656 && GET_CODE (operands[0]) == MEM
1657 && GET_CODE (operands[1]) == MEM)
1658 {
1659 operands[1] = force_reg (DImode, operands[1]);
1660 }
1661 }")
1662
1663 (define_insn ""
1664 [(set (match_operand:DI 0 "general_operand" "=g,r")
1665 (match_operand:DI 1 "general_operand" "riF,m"))]
1666 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
1667 || (GET_CODE (operands[1]) != MEM)"
1668 "* return output_move_double (operands);")
1669
1670 \f
1671 ;;- conversion instructions
1672 ;;- NONE
1673
1674 ;;- zero extension instructions
1675 ;; See comments by `andsi' for when andl is faster than movzx.
1676
1677 (define_insn "zero_extendhisi2"
1678 [(set (match_operand:SI 0 "register_operand" "=r,&r,?r")
1679 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,rm,rm")))]
1680 ""
1681 "*
1682 {
1683 rtx xops[2];
1684
1685 if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
1686 && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
1687 {
1688 xops[0] = operands[0];
1689 xops[1] = GEN_INT (0xffff);
1690 output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1691 RET;
1692 }
1693 if (TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1]))
1694 {
1695 output_asm_insn (AS2 (xor%L0,%0,%0),operands);
1696 output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
1697 RET;
1698 }
1699
1700 if (TARGET_ZERO_EXTEND_WITH_AND)
1701 {
1702 xops[0] = operands[0];
1703 xops[1] = GEN_INT (0xffff);
1704 if (i386_aligned_p (operands[1]))
1705 output_asm_insn (AS2 (mov%L0,%k1,%k0),operands);
1706 else
1707 output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
1708 output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1709 RET;
1710 }
1711
1712 #ifdef INTEL_SYNTAX
1713 return AS2 (movzx,%1,%0);
1714 #else
1715 return AS2 (movz%W0%L0,%1,%0);
1716 #endif
1717 }")
1718
1719 (define_split
1720 [(set (match_operand:SI 0 "register_operand" "")
1721 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
1722 "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1])"
1723 [(set (match_dup 0)
1724 (const_int 0))
1725 (set (strict_low_part (match_dup 2))
1726 (match_dup 1))]
1727 "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));")
1728
1729
1730 (define_split
1731 [(set (match_operand:SI 0 "register_operand" "")
1732 (zero_extend:SI (match_operand:HI 1 "memory_operand" "")))]
1733 "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && reg_overlap_mentioned_p (operands[0], operands[1])"
1734 [(set (strict_low_part (match_dup 2))
1735 (match_dup 1))
1736 (set (match_dup 0)
1737 (and:SI (match_dup 0)
1738 (const_int 65535)))]
1739 "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));")
1740
1741 (define_insn "zero_extendqihi2"
1742 [(set (match_operand:HI 0 "register_operand" "=q,&q,?r")
1743 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
1744 ""
1745 "*
1746 {
1747 rtx xops[2];
1748
1749 if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
1750 && REG_P (operands[1])
1751 && REGNO (operands[0]) == REGNO (operands[1]))
1752 {
1753 xops[0] = operands[0];
1754 xops[1] = GEN_INT (0xff);
1755 output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1756 RET;
1757 }
1758 if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0]))
1759 {
1760 if(!reg_overlap_mentioned_p(operands[0],operands[1]))
1761 {
1762 output_asm_insn (AS2 (xor%L0,%k0,%k0), operands);
1763 output_asm_insn (AS2 (mov%B0,%1,%b0), operands);
1764 }
1765 else
1766 {
1767 xops[0] = operands[0];
1768 xops[1] = GEN_INT (0xff);
1769 output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
1770 output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1771 }
1772 RET;
1773 }
1774
1775 #ifdef INTEL_SYNTAX
1776 return AS2 (movzx,%1,%0);
1777 #else
1778 return AS2 (movz%B0%W0,%1,%0);
1779 #endif
1780 }")
1781
1782 (define_split
1783 [(set (match_operand:HI 0 "register_operand" "")
1784 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
1785 "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
1786 && !reg_overlap_mentioned_p (operands[0], operands[1])"
1787 [(set (match_dup 0)
1788 (const_int 0))
1789 (set (strict_low_part (match_dup 2))
1790 (match_dup 1))]
1791 "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
1792
1793
1794 (define_split
1795 [(set (match_operand:HI 0 "register_operand" "")
1796 (zero_extend:HI (match_operand:QI 1 "memory_operand" "")))]
1797 "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
1798 && reg_overlap_mentioned_p (operands[0], operands[1])"
1799 [(set (strict_low_part (match_dup 2))
1800 (match_dup 1))
1801 (set (match_dup 0)
1802 (and:HI (match_dup 0)
1803 (const_int 255)))]
1804 "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
1805
1806 (define_split
1807 [(set (match_operand:HI 0 "register_operand" "")
1808 (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
1809 "reload_completed && TARGET_ZERO_EXTEND_WITH_AND"
1810 [(set (match_dup 0)
1811 (match_dup 2))
1812 (set (match_dup 0)
1813 (and:HI (match_dup 0)
1814 (const_int 255)))]
1815 "if (GET_CODE (operands[1]) == SUBREG && SUBREG_WORD (operands[1]) == 0)
1816 operands[1] = SUBREG_REG (operands[1]);
1817 if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG
1818 || REGNO (operands[0]) == REGNO (operands[1]))
1819 FAIL;
1820 operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
1821
1822 (define_insn "zero_extendqisi2"
1823 [(set (match_operand:SI 0 "register_operand" "=q,&q,?r")
1824 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
1825 ""
1826 "*
1827 {
1828 rtx xops[2];
1829
1830 if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
1831 && REG_P (operands[1])
1832 && REGNO (operands[0]) == REGNO (operands[1]))
1833 {
1834 xops[0] = operands[0];
1835 xops[1] = GEN_INT (0xff);
1836 output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1837 RET;
1838 }
1839 if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0]))
1840 {
1841 if(!reg_overlap_mentioned_p (operands[0], operands[1]))
1842 {
1843 output_asm_insn (AS2 (xor%L0,%0,%0),operands);
1844 output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
1845 }
1846 else
1847 {
1848 xops[0] = operands[0];
1849 xops[1] = GEN_INT (0xff);
1850 output_asm_insn (AS2 (mov%B0,%1,%b0), operands);
1851 output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1852 }
1853 RET;
1854 }
1855
1856 if (TARGET_ZERO_EXTEND_WITH_AND && GET_CODE (operands[1]) == REG)
1857 {
1858 xops[0] = operands[0];
1859 xops[1] = GEN_INT (0xff);
1860 operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]));
1861 output_asm_insn (AS2 (mov%L0,%1,%0), operands);
1862 output_asm_insn (AS2 (and%L0,%1,%k0), xops);
1863 RET;
1864 }
1865
1866 #ifdef INTEL_SYNTAX
1867 return AS2 (movzx,%1,%0);
1868 #else
1869 return AS2 (movz%B0%L0,%1,%0);
1870 #endif
1871 }")
1872
1873 (define_split
1874 [(set (match_operand:SI 0 "register_operand" "")
1875 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1876 "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
1877 && !reg_overlap_mentioned_p (operands[0], operands[1])"
1878 [(set (match_dup 0)
1879 (const_int 0))
1880 (set (strict_low_part (match_dup 2))
1881 (match_dup 1))]
1882 "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
1883
1884
1885 (define_split
1886 [(set (match_operand:SI 0 "register_operand" "")
1887 (zero_extend:SI (match_operand:QI 1 "memory_operand" "")))]
1888 "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
1889 && reg_overlap_mentioned_p (operands[0], operands[1])"
1890 [(set (strict_low_part (match_dup 2))
1891 (match_dup 1))
1892 (set (match_dup 0)
1893 (and:SI (match_dup 0)
1894 (const_int 255)))]
1895 "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
1896
1897 (define_split
1898 [(set (match_operand:SI 0 "register_operand" "")
1899 (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
1900 "reload_completed && TARGET_ZERO_EXTEND_WITH_AND
1901 && ! reg_overlap_mentioned_p (operands[0], operands[1])"
1902 [(set (match_dup 0)
1903 (match_dup 2))
1904 (set (match_dup 0)
1905 (and:SI (match_dup 0)
1906 (const_int 255)))]
1907 "operands[2] = gen_rtx_REG (SImode, true_regnum (operands[1]));")
1908
1909 (define_insn "zero_extendsidi2"
1910 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?m")
1911 (zero_extend:DI (match_operand:SI 1 "register_operand" "0,rm,r")))]
1912 ""
1913 "*
1914 {
1915 rtx high[2], low[2], xops[4];
1916
1917 if (REG_P (operands[0]) && REG_P (operands[1])
1918 && REGNO (operands[0]) == REGNO (operands[1]))
1919 {
1920 operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
1921 return AS2 (xor%L0,%0,%0);
1922 }
1923
1924 split_di (operands, 1, low, high);
1925 xops[0] = low[0];
1926 xops[1] = operands[1];
1927 xops[2] = high[0];
1928 xops[3] = const0_rtx;
1929
1930 output_asm_insn (AS2 (mov%L0,%1,%0), xops);
1931 if (GET_CODE (low[0]) == MEM)
1932 output_asm_insn (AS2 (mov%L2,%3,%2), xops);
1933 else
1934 output_asm_insn (AS2 (xor%L2,%2,%2), xops);
1935
1936 RET;
1937 }")
1938 \f
1939 ;;- sign extension instructions
1940
1941 (define_insn "extendsidi2"
1942 [(set (match_operand:DI 0 "register_operand" "=r")
1943 (sign_extend:DI (match_operand:SI 1 "register_operand" "0")))]
1944 ""
1945 "*
1946 {
1947 if (REGNO (operands[0]) == 0)
1948 {
1949 /* This used to be cwtl, but that extends HI to SI somehow. */
1950 #ifdef INTEL_SYNTAX
1951 return \"cdq\";
1952 #else
1953 return \"cltd\";
1954 #endif
1955 }
1956
1957 operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
1958 output_asm_insn (AS2 (mov%L0,%0,%1), operands);
1959
1960 operands[0] = GEN_INT (31);
1961 return AS2 (sar%L1,%0,%1);
1962 }")
1963
1964 ;; Note that the i386 programmers' manual says that the opcodes
1965 ;; are named movsx..., but the assembler on Unix does not accept that.
1966 ;; We use what the Unix assembler expects.
1967
1968 (define_insn "extendhisi2"
1969 [(set (match_operand:SI 0 "register_operand" "=r")
1970 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
1971 ""
1972 "*
1973 {
1974 if (REGNO (operands[0]) == 0
1975 && REG_P (operands[1]) && REGNO (operands[1]) == 0)
1976 #ifdef INTEL_SYNTAX
1977 return \"cwde\";
1978 #else
1979 return \"cwtl\";
1980 #endif
1981
1982 #ifdef INTEL_SYNTAX
1983 return AS2 (movsx,%1,%0);
1984 #else
1985 return AS2 (movs%W0%L0,%1,%0);
1986 #endif
1987 }")
1988
1989 (define_insn "extendqihi2"
1990 [(set (match_operand:HI 0 "register_operand" "=r")
1991 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
1992 ""
1993 "*
1994 {
1995 if (REGNO (operands[0]) == 0
1996 && REG_P (operands[1]) && REGNO (operands[1]) == 0)
1997 return \"cbtw\";
1998
1999 #ifdef INTEL_SYNTAX
2000 return AS2 (movsx,%1,%0);
2001 #else
2002 return AS2 (movs%B0%W0,%1,%0);
2003 #endif
2004 }")
2005
2006 (define_insn "extendqisi2"
2007 [(set (match_operand:SI 0 "register_operand" "=r")
2008 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
2009 ""
2010 "*
2011 {
2012 #ifdef INTEL_SYNTAX
2013 return AS2 (movsx,%1,%0);
2014 #else
2015 return AS2 (movs%B0%L0,%1,%0);
2016 #endif
2017 }")
2018
2019 \f
2020 ;; Truncation of long long -> 32 bit
2021
2022 (define_expand "truncdisi2"
2023 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
2024 (truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))]
2025 ""
2026 "
2027 {
2028 /* Don't generate memory->memory moves, go through a register */
2029 if (TARGET_MOVE
2030 && (reload_in_progress | reload_completed) == 0
2031 && GET_CODE (operands[0]) == MEM
2032 && GET_CODE (operands[1]) == MEM)
2033 {
2034 rtx target = gen_reg_rtx (SImode);
2035 emit_insn (gen_truncdisi2 (target, operands[1]));
2036 emit_move_insn (operands[0], target);
2037 DONE;
2038 }
2039 }")
2040
2041 (define_insn ""
2042 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
2043 (truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))]
2044 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
2045 "*
2046 {
2047 rtx low[2], high[2], xops[2];
2048
2049 split_di (&operands[1], 1, low, high);
2050 xops[0] = operands[0];
2051 xops[1] = low[0];
2052 if (!rtx_equal_p (xops[0], xops[1]))
2053 output_asm_insn (AS2 (mov%L0,%1,%0), xops);
2054
2055 RET;
2056 }")
2057
2058 (define_insn ""
2059 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
2060 (truncate:SI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r")
2061 (const_int 32))))]
2062 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
2063 "*
2064 {
2065 rtx low[2], high[2], xops[2];
2066
2067 split_di (&operands[1], 1, low, high);
2068 xops[0] = operands[0];
2069 xops[1] = high[0];
2070 if (!rtx_equal_p (xops[0], xops[1]))
2071 output_asm_insn (AS2 (mov%L0,%1,%0), xops);
2072
2073 RET;
2074 }")
2075
2076
2077 \f
2078 ;; Conversions between float and double.
2079
2080 (define_insn "extendsfdf2"
2081 [(set (match_operand:DF 0 "nonimmediate_operand" "=fm,f")
2082 (float_extend:DF
2083 (match_operand:SF 1 "nonimmediate_operand" "f,fm")))]
2084 "TARGET_80387"
2085 "*
2086 {
2087 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2088
2089 if (NON_STACK_REG_P (operands[1]))
2090 {
2091 output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
2092 RET;
2093 }
2094
2095 if (NON_STACK_REG_P (operands[0]))
2096 {
2097 output_to_reg (operands[0], stack_top_dies, 0);
2098 RET;
2099 }
2100
2101 if (STACK_TOP_P (operands[0]))
2102 return AS1 (fld%z1,%y1);
2103
2104 if (GET_CODE (operands[0]) == MEM)
2105 {
2106 if (stack_top_dies)
2107 return AS1 (fstp%z0,%y0);
2108 else
2109 return AS1 (fst%z0,%y0);
2110 }
2111
2112 abort ();
2113 }")
2114
2115 (define_insn "extenddfxf2"
2116 [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
2117 (float_extend:XF
2118 (match_operand:DF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
2119 "TARGET_80387"
2120 "*
2121 {
2122 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2123
2124 if (NON_STACK_REG_P (operands[1]))
2125 {
2126 output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
2127 RET;
2128 }
2129
2130 if (NON_STACK_REG_P (operands[0]))
2131 {
2132 output_to_reg (operands[0], stack_top_dies, 0);
2133 RET;
2134 }
2135
2136 if (STACK_TOP_P (operands[0]))
2137 return AS1 (fld%z1,%y1);
2138
2139 if (GET_CODE (operands[0]) == MEM)
2140 {
2141 output_asm_insn (AS1 (fstp%z0,%y0), operands);
2142 if (! stack_top_dies)
2143 return AS1 (fld%z0,%y0);
2144 RET;
2145 }
2146
2147 abort ();
2148 }")
2149
2150 (define_insn "extendsfxf2"
2151 [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
2152 (float_extend:XF
2153 (match_operand:SF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
2154 "TARGET_80387"
2155 "*
2156 {
2157 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2158
2159 if (NON_STACK_REG_P (operands[1]))
2160 {
2161 output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
2162 RET;
2163 }
2164
2165 if (NON_STACK_REG_P (operands[0]))
2166 {
2167 output_to_reg (operands[0], stack_top_dies, 0);
2168 RET;
2169 }
2170
2171 if (STACK_TOP_P (operands[0]))
2172 return AS1 (fld%z1,%y1);
2173
2174 if (GET_CODE (operands[0]) == MEM)
2175 {
2176 output_asm_insn (AS1 (fstp%z0,%y0), operands);
2177 if (! stack_top_dies)
2178 return AS1 (fld%z0,%y0);
2179 RET;
2180 }
2181
2182 abort ();
2183 }")
2184
2185 (define_expand "truncdfsf2"
2186 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
2187 (float_truncate:SF
2188 (match_operand:DF 1 "register_operand" "")))
2189 (clobber (match_dup 2))])]
2190 "TARGET_80387"
2191 "
2192 {
2193 operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
2194 }")
2195
2196 ;; This cannot output into an f-reg because there is no way to be sure
2197 ;; of truncating in that case. Otherwise this is just like a simple move
2198 ;; insn. So we pretend we can output to a reg in order to get better
2199 ;; register preferencing, but we really use a stack slot.
2200
2201 (define_insn ""
2202 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m")
2203 (float_truncate:SF
2204 (match_operand:DF 1 "register_operand" "0,f")))
2205 (clobber (match_operand:SF 2 "memory_operand" "m,m"))]
2206 "TARGET_80387"
2207 "*
2208 {
2209 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2210
2211 if (GET_CODE (operands[0]) == MEM)
2212 {
2213 if (stack_top_dies)
2214 return AS1 (fstp%z0,%0);
2215 else
2216 return AS1 (fst%z0,%0);
2217 }
2218 else if (STACK_TOP_P (operands[0]))
2219 {
2220 output_asm_insn (AS1 (fstp%z2,%y2), operands);
2221 return AS1 (fld%z2,%y2);
2222 }
2223 else
2224 abort ();
2225 }")
2226
2227 (define_insn "truncxfsf2"
2228 [(set (match_operand:SF 0 "nonimmediate_operand" "=m,!*r")
2229 (float_truncate:SF
2230 (match_operand:XF 1 "register_operand" "f,f")))]
2231 "TARGET_80387"
2232 "*
2233 {
2234 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2235
2236 if (NON_STACK_REG_P (operands[0]))
2237 {
2238 if (stack_top_dies == 0)
2239 {
2240 output_asm_insn (AS1 (fld,%y1), operands);
2241 stack_top_dies = 1;
2242 }
2243 output_to_reg (operands[0], stack_top_dies, 0);
2244 RET;
2245 }
2246 else if (GET_CODE (operands[0]) == MEM)
2247 {
2248 if (stack_top_dies)
2249 return AS1 (fstp%z0,%0);
2250 else
2251 {
2252 output_asm_insn (AS1 (fld,%y1), operands);
2253 return AS1 (fstp%z0,%0);
2254 }
2255 }
2256 else
2257 abort ();
2258 }")
2259
2260 (define_insn "truncxfdf2"
2261 [(set (match_operand:DF 0 "nonimmediate_operand" "=m,!*r")
2262 (float_truncate:DF
2263 (match_operand:XF 1 "register_operand" "f,f")))]
2264 "TARGET_80387"
2265 "*
2266 {
2267 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
2268
2269 if (NON_STACK_REG_P (operands[0]))
2270 {
2271 if (stack_top_dies == 0)
2272 {
2273 output_asm_insn (AS1 (fld,%y1), operands);
2274 stack_top_dies = 1;
2275 }
2276 output_to_reg (operands[0], stack_top_dies, 0);
2277 RET;
2278 }
2279 else if (GET_CODE (operands[0]) == MEM)
2280 {
2281 if (stack_top_dies)
2282 return AS1 (fstp%z0,%0);
2283 else
2284 {
2285 output_asm_insn (AS1 (fld,%y1), operands);
2286 return AS1 (fstp%z0,%0);
2287 }
2288 }
2289 else
2290 abort ();
2291 }")
2292
2293 \f
2294 ;; The 387 requires that the stack top dies after converting to DImode.
2295
2296 ;; Represent an unsigned conversion from SImode to MODE_FLOAT by first
2297 ;; doing a signed conversion to DImode, and then taking just the low
2298 ;; part.
2299
2300 (define_expand "fixuns_truncxfsi2"
2301 [(set (match_dup 4)
2302 (match_operand:XF 1 "register_operand" ""))
2303 (parallel [(set (match_dup 2)
2304 (fix:DI (fix:XF (match_dup 4))))
2305 (clobber (match_dup 4))
2306 (clobber (match_dup 5))
2307 (clobber (match_dup 6))
2308 (clobber (match_scratch:SI 7 ""))])
2309 (set (match_operand:SI 0 "general_operand" "")
2310 (match_dup 3))]
2311 "TARGET_80387"
2312 "
2313 {
2314 operands[2] = gen_reg_rtx (DImode);
2315 operands[3] = gen_lowpart (SImode, operands[2]);
2316 operands[4] = gen_reg_rtx (XFmode);
2317 operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2318 operands[6] = (rtx) assign_386_stack_local (DImode, 1);
2319 }")
2320
2321 (define_expand "fixuns_truncdfsi2"
2322 [(set (match_dup 4)
2323 (match_operand:DF 1 "register_operand" ""))
2324 (parallel [(set (match_dup 2)
2325 (fix:DI (fix:DF (match_dup 4))))
2326 (clobber (match_dup 4))
2327 (clobber (match_dup 5))
2328 (clobber (match_dup 6))
2329 (clobber (match_scratch:SI 7 ""))])
2330 (set (match_operand:SI 0 "general_operand" "")
2331 (match_dup 3))]
2332 "TARGET_80387"
2333 "
2334 {
2335 operands[2] = gen_reg_rtx (DImode);
2336 operands[3] = gen_lowpart (SImode, operands[2]);
2337 operands[4] = gen_reg_rtx (DFmode);
2338 operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2339 operands[6] = (rtx) assign_386_stack_local (DImode, 1);
2340 }")
2341
2342 (define_expand "fixuns_truncsfsi2"
2343 [(set (match_dup 4)
2344 (match_operand:SF 1 "register_operand" ""))
2345 (parallel [(set (match_dup 2)
2346 (fix:DI (fix:SF (match_dup 4))))
2347 (clobber (match_dup 4))
2348 (clobber (match_dup 5))
2349 (clobber (match_dup 6))
2350 (clobber (match_scratch:SI 7 ""))])
2351 (set (match_operand:SI 0 "general_operand" "")
2352 (match_dup 3))]
2353 "TARGET_80387"
2354 "
2355 {
2356 operands[2] = gen_reg_rtx (DImode);
2357 operands[3] = gen_lowpart (SImode, operands[2]);
2358 operands[4] = gen_reg_rtx (SFmode);
2359 operands[5] = (rtx) assign_386_stack_local (SImode, 0);
2360 operands[6] = (rtx) assign_386_stack_local (DImode, 1);
2361 }")
2362
2363 ;; Signed conversion to DImode.
2364
2365 (define_expand "fix_truncxfdi2"
2366 [(set (match_dup 2)
2367 (match_operand:XF 1 "register_operand" ""))
2368 (parallel [(set (match_operand:DI 0 "general_operand" "")
2369 (fix:DI (fix:XF (match_dup 2))))
2370 (clobber (match_dup 2))
2371 (clobber (match_dup 3))
2372 (clobber (match_dup 4))
2373 (clobber (match_scratch:SI 5 ""))])]
2374 "TARGET_80387"
2375 "
2376 {
2377 operands[1] = copy_to_mode_reg (XFmode, operands[1]);
2378 operands[2] = gen_reg_rtx (XFmode);
2379 operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2380 operands[4] = (rtx) assign_386_stack_local (DImode, 1);
2381 }")
2382
2383 (define_expand "fix_truncdfdi2"
2384 [(set (match_dup 2)
2385 (match_operand:DF 1 "register_operand" ""))
2386 (parallel [(set (match_operand:DI 0 "general_operand" "")
2387 (fix:DI (fix:DF (match_dup 2))))
2388 (clobber (match_dup 2))
2389 (clobber (match_dup 3))
2390 (clobber (match_dup 4))
2391 (clobber (match_scratch:SI 5 ""))])]
2392 "TARGET_80387"
2393 "
2394 {
2395 operands[1] = copy_to_mode_reg (DFmode, operands[1]);
2396 operands[2] = gen_reg_rtx (DFmode);
2397 operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2398 operands[4] = (rtx) assign_386_stack_local (DImode, 1);
2399 }")
2400
2401 (define_expand "fix_truncsfdi2"
2402 [(set (match_dup 2)
2403 (match_operand:SF 1 "register_operand" ""))
2404 (parallel [(set (match_operand:DI 0 "general_operand" "")
2405 (fix:DI (fix:SF (match_dup 2))))
2406 (clobber (match_dup 2))
2407 (clobber (match_dup 3))
2408 (clobber (match_dup 4))
2409 (clobber (match_scratch:SI 5 ""))])]
2410 "TARGET_80387"
2411 "
2412 {
2413 operands[1] = copy_to_mode_reg (SFmode, operands[1]);
2414 operands[2] = gen_reg_rtx (SFmode);
2415 operands[3] = (rtx) assign_386_stack_local (SImode, 0);
2416 operands[4] = (rtx) assign_386_stack_local (DImode, 1);
2417 }")
2418
2419 ;; These match a signed conversion of either DFmode or SFmode to DImode.
2420
2421 (define_insn ""
2422 [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
2423 (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "+f"))))
2424 (clobber (match_dup 1))
2425 (clobber (match_operand:SI 2 "memory_operand" "m"))
2426 (clobber (match_operand:DI 3 "memory_operand" "m"))
2427 (clobber (match_scratch:SI 4 "=&q"))]
2428 "TARGET_80387"
2429 "* return output_fix_trunc (insn, operands);")
2430
2431 (define_insn ""
2432 [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
2433 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "+f"))))
2434 (clobber (match_dup 1))
2435 (clobber (match_operand:SI 2 "memory_operand" "m"))
2436 (clobber (match_operand:DI 3 "memory_operand" "m"))
2437 (clobber (match_scratch:SI 4 "=&q"))]
2438 "TARGET_80387"
2439 "* return output_fix_trunc (insn, operands);")
2440
2441 (define_insn ""
2442 [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
2443 (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "+f"))))
2444 (clobber (match_dup 1))
2445 (clobber (match_operand:SI 2 "memory_operand" "m"))
2446 (clobber (match_operand:DI 3 "memory_operand" "m"))
2447 (clobber (match_scratch:SI 4 "=&q"))]
2448 "TARGET_80387"
2449 "* return output_fix_trunc (insn, operands);")
2450
2451 ;; Signed MODE_FLOAT conversion to SImode.
2452
2453 (define_expand "fix_truncxfsi2"
2454 [(parallel [(set (match_operand:SI 0 "general_operand" "")
2455 (fix:SI
2456 (fix:XF (match_operand:XF 1 "register_operand" ""))))
2457 (clobber (match_dup 2))
2458 (clobber (match_dup 3))
2459 (clobber (match_scratch:SI 4 ""))])]
2460 "TARGET_80387"
2461 "
2462 {
2463 operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2464 operands[3] = (rtx) assign_386_stack_local (DImode, 1);
2465 }")
2466
2467 (define_expand "fix_truncdfsi2"
2468 [(parallel [(set (match_operand:SI 0 "general_operand" "")
2469 (fix:SI
2470 (fix:DF (match_operand:DF 1 "register_operand" ""))))
2471 (clobber (match_dup 2))
2472 (clobber (match_dup 3))
2473 (clobber (match_scratch:SI 4 ""))])]
2474 "TARGET_80387"
2475 "
2476 {
2477 operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2478 operands[3] = (rtx) assign_386_stack_local (DImode, 1);
2479 }")
2480
2481 (define_expand "fix_truncsfsi2"
2482 [(parallel [(set (match_operand:SI 0 "general_operand" "")
2483 (fix:SI
2484 (fix:SF (match_operand:SF 1 "register_operand" ""))))
2485 (clobber (match_dup 2))
2486 (clobber (match_dup 3))
2487 (clobber (match_scratch:SI 4 ""))])]
2488 "TARGET_80387"
2489 "
2490 {
2491 operands[2] = (rtx) assign_386_stack_local (SImode, 0);
2492 operands[3] = (rtx) assign_386_stack_local (DImode, 1);
2493 }")
2494
2495 (define_insn ""
2496 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
2497 (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
2498 (clobber (match_operand:SI 2 "memory_operand" "m"))
2499 (clobber (match_operand:DI 3 "memory_operand" "m"))
2500 (clobber (match_scratch:SI 4 "=&q"))]
2501 "TARGET_80387"
2502 "* return output_fix_trunc (insn, operands);")
2503
2504 (define_insn ""
2505 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
2506 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
2507 (clobber (match_operand:SI 2 "memory_operand" "m"))
2508 (clobber (match_operand:DI 3 "memory_operand" "m"))
2509 (clobber (match_scratch:SI 4 "=&q"))]
2510 "TARGET_80387"
2511 "* return output_fix_trunc (insn, operands);")
2512
2513 (define_insn ""
2514 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
2515 (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
2516 (clobber (match_operand:SI 2 "memory_operand" "m"))
2517 (clobber (match_operand:DI 3 "memory_operand" "m"))
2518 (clobber (match_scratch:SI 4 "=&q"))]
2519 "TARGET_80387"
2520 "* return output_fix_trunc (insn, operands);")
2521 \f
2522 ;; Conversion between fixed point and floating point.
2523 ;; The actual pattern that matches these is at the end of this file.
2524
2525 ;; ??? Possibly represent floatunssidf2 here in gcc2.
2526
2527 (define_expand "floatsisf2"
2528 [(set (match_operand:SF 0 "register_operand" "")
2529 (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
2530 "TARGET_80387"
2531 "")
2532
2533 (define_expand "floatdisf2"
2534 [(set (match_operand:SF 0 "register_operand" "")
2535 (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
2536 "TARGET_80387"
2537 "")
2538
2539 (define_expand "floatsidf2"
2540 [(set (match_operand:DF 0 "register_operand" "")
2541 (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
2542 "TARGET_80387"
2543 "")
2544
2545 (define_expand "floatdidf2"
2546 [(set (match_operand:DF 0 "register_operand" "")
2547 (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
2548 "TARGET_80387"
2549 "")
2550
2551 (define_expand "floatsixf2"
2552 [(set (match_operand:XF 0 "register_operand" "")
2553 (float:XF (match_operand:SI 1 "nonimmediate_operand" "")))]
2554 "TARGET_80387"
2555 "")
2556
2557 (define_expand "floatdixf2"
2558 [(set (match_operand:XF 0 "register_operand" "")
2559 (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))]
2560 "TARGET_80387 && LONG_DOUBLE_TYPE_SIZE == 96"
2561 "")
2562
2563 ;; This will convert from SImode or DImode to MODE_FLOAT.
2564
2565 (define_insn ""
2566 [(set (match_operand:XF 0 "register_operand" "=f")
2567 (float:XF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2568 "TARGET_80387"
2569 "*
2570 {
2571 if (NON_STACK_REG_P (operands[1]))
2572 {
2573 output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2574 RET;
2575 }
2576 else if (GET_CODE (operands[1]) == MEM)
2577 return AS1 (fild%z1,%1);
2578 else
2579 abort ();
2580 }")
2581
2582 (define_insn ""
2583 [(set (match_operand:DF 0 "register_operand" "=f")
2584 (float:DF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2585 "TARGET_80387"
2586 "*
2587 {
2588 if (NON_STACK_REG_P (operands[1]))
2589 {
2590 output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2591 RET;
2592 }
2593 else if (GET_CODE (operands[1]) == MEM)
2594 return AS1 (fild%z1,%1);
2595 else
2596 abort ();
2597 }")
2598
2599 (define_insn ""
2600 [(set (match_operand:SF 0 "register_operand" "=f")
2601 (float:SF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
2602 "TARGET_80387"
2603 "*
2604 {
2605 if (NON_STACK_REG_P (operands[1]))
2606 {
2607 output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2608 RET;
2609 }
2610 else if (GET_CODE (operands[1]) == MEM)
2611 return AS1 (fild%z1,%1);
2612 else
2613 abort ();
2614 }")
2615
2616 (define_insn ""
2617 [(set (match_operand:DF 0 "register_operand" "=f")
2618 (float:DF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
2619 "TARGET_80387"
2620 "*
2621 {
2622 if (NON_STACK_REG_P (operands[1]))
2623 {
2624 output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2625 RET;
2626 }
2627 else if (GET_CODE (operands[1]) == MEM)
2628 return AS1 (fild%z1,%1);
2629 else
2630 abort ();
2631 }")
2632
2633 (define_insn ""
2634 [(set (match_operand:XF 0 "register_operand" "=f,f")
2635 (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,!*r")))]
2636 "TARGET_80387"
2637 "*
2638 {
2639 if (NON_STACK_REG_P (operands[1]))
2640 {
2641 output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2642 RET;
2643 }
2644 else if (GET_CODE (operands[1]) == MEM)
2645 return AS1 (fild%z1,%1);
2646 else
2647 abort ();
2648 }")
2649
2650 (define_insn ""
2651 [(set (match_operand:SF 0 "register_operand" "=f")
2652 (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
2653 "TARGET_80387"
2654 "*
2655 {
2656 if (NON_STACK_REG_P (operands[1]))
2657 {
2658 output_op_from_reg (operands[1], AS1 (fild%z0,%1));
2659 RET;
2660 }
2661 else if (GET_CODE (operands[1]) == MEM)
2662 return AS1 (fild%z1,%1);
2663 else
2664 abort ();
2665 }")
2666 \f
2667 ;;- add instructions
2668
2669 (define_insn "addsidi3_1"
2670 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,!&r,!r,o,!o")
2671 (plus:DI (match_operand:DI 1 "general_operand" "0,0,0,o,riF,riF,o")
2672 (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,roi,roi,ri,ri"))))
2673 (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,&r"))]
2674 ""
2675 "*
2676 {
2677 rtx low[3], high[3], xops[7], temp;
2678
2679 CC_STATUS_INIT;
2680
2681 split_di (operands, 2, low, high);
2682 high[2] = const0_rtx;
2683 low[2] = operands[2];
2684
2685 if (!rtx_equal_p (operands[0], operands[1]))
2686 {
2687 xops[0] = high[0];
2688 xops[1] = low[0];
2689 xops[2] = high[1];
2690 xops[3] = low[1];
2691
2692 if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2693 {
2694 output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2695 output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2696 }
2697 else
2698 {
2699 xops[4] = high[2];
2700 xops[5] = low[2];
2701 xops[6] = operands[3];
2702 output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2703 output_asm_insn (AS2 (add%L6,%5,%6), xops);
2704 output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2705 output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2706 output_asm_insn (AS2 (adc%L6,%4,%6), xops);
2707 output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2708 RET;
2709 }
2710 }
2711
2712 output_asm_insn (AS2 (add%L0,%2,%0), low);
2713 output_asm_insn (AS2 (adc%L0,%2,%0), high);
2714 RET;
2715 }")
2716
2717 (define_insn "addsidi3_2"
2718 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,&r,!&r,&r,o,o,!o")
2719 (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,o,ri,ri,i,r"))
2720 (match_operand:DI 1 "general_operand" "0,0,0,iF,ro,roiF,riF,o,o")))
2721 (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,X,&r,&r"))]
2722 ""
2723 "*
2724 {
2725 rtx low[3], high[3], xops[7], temp;
2726
2727 CC_STATUS_INIT;
2728
2729 split_di (operands, 2, low, high);
2730 high[2] = const0_rtx;
2731 low[2] = operands[2];
2732
2733 if (!rtx_equal_p (operands[0], operands[1]))
2734 {
2735 xops[0] = high[0];
2736 xops[1] = low[0];
2737 xops[2] = high[1];
2738 xops[3] = low[1];
2739
2740 if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
2741 {
2742 if (rtx_equal_p (low[0], operands[2]))
2743 {
2744 output_asm_insn (AS2 (mov%L0,%2,%0), high);
2745 output_asm_insn (AS2 (add%L0,%1,%0), low);
2746 output_asm_insn (AS2 (adc%L0,%1,%0), high);
2747 RET;
2748 }
2749 if (rtx_equal_p (high[0], operands[2]))
2750 {
2751 if (GET_CODE (operands[0]) != MEM)
2752 {
2753 output_asm_insn (AS2 (mov%L0,%2,%0), low);
2754 output_asm_insn (AS2 (mov%L0,%2,%0), high);
2755 output_asm_insn (AS2 (add%L0,%1,%0), low);
2756 output_asm_insn (AS2 (adc%L0,%1,%0), high);
2757 }
2758 else
2759 {
2760 /* It's too late to ask for a scratch now - but this
2761 will probably not happen too often. */
2762 output_asm_insn (AS2 (add%L1,%2,%1), low);
2763 output_asm_insn (AS2 (mov%L0,%1,%0), low);
2764 output_asm_insn (AS2 (mov%L1,%2,%1), low);
2765 output_asm_insn (AS2 (mov%L0,%2,%0), high);
2766 output_asm_insn (AS2 (adc%L0,%1,%0), high);
2767 output_asm_insn (AS2 (sub%L1,%0,%1), low);
2768 output_asm_insn (AS1 (neg%L1,%1), low);
2769 }
2770 RET;
2771 }
2772 output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2773 output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2774 }
2775 else
2776 {
2777 xops[4] = high[2];
2778 xops[5] = low[2];
2779 xops[6] = operands[3];
2780 output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2781 output_asm_insn (AS2 (add%L6,%5,%6), xops);
2782 output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2783 output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2784 output_asm_insn (AS2 (adc%L6,%4,%6), xops);
2785 output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2786 RET;
2787 }
2788 }
2789
2790 output_asm_insn (AS2 (add%L0,%2,%0), low);
2791 output_asm_insn (AS2 (adc%L0,%2,%0), high);
2792 RET;
2793 }")
2794
2795 (define_insn "adddi3"
2796 [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
2797 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
2798 (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
2799 (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
2800 ""
2801 "*
2802 {
2803 rtx low[3], high[3], xops[7], temp;
2804
2805 CC_STATUS_INIT;
2806
2807 if (rtx_equal_p (operands[0], operands[2]))
2808 {
2809 temp = operands[1];
2810 operands[1] = operands[2];
2811 operands[2] = temp;
2812 }
2813
2814 split_di (operands, 3, low, high);
2815 if (!rtx_equal_p (operands[0], operands[1]))
2816 {
2817 xops[0] = high[0];
2818 xops[1] = low[0];
2819 xops[2] = high[1];
2820 xops[3] = low[1];
2821
2822 if (GET_CODE (operands[0]) != MEM)
2823 {
2824 output_asm_insn (AS2 (mov%L1,%3,%1), xops);
2825 output_asm_insn (AS2 (mov%L0,%2,%0), xops);
2826 }
2827 else
2828 {
2829 xops[4] = high[2];
2830 xops[5] = low[2];
2831 xops[6] = operands[3];
2832 output_asm_insn (AS2 (mov%L6,%3,%6), xops);
2833 output_asm_insn (AS2 (add%L6,%5,%6), xops);
2834 output_asm_insn (AS2 (mov%L1,%6,%1), xops);
2835 output_asm_insn (AS2 (mov%L6,%2,%6), xops);
2836 output_asm_insn (AS2 (adc%L6,%4,%6), xops);
2837 output_asm_insn (AS2 (mov%L0,%6,%0), xops);
2838 RET;
2839 }
2840 }
2841
2842 if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
2843 {
2844 xops[0] = high[0];
2845 xops[1] = low[0];
2846 xops[2] = high[2];
2847 xops[3] = low[2];
2848 xops[4] = operands[3];
2849
2850 output_asm_insn (AS2 (mov%L4,%3,%4), xops);
2851 output_asm_insn (AS2 (add%L1,%4,%1), xops);
2852 output_asm_insn (AS2 (mov%L4,%2,%4), xops);
2853 output_asm_insn (AS2 (adc%L0,%4,%0), xops);
2854 }
2855
2856 else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
2857 {
2858 output_asm_insn (AS2 (add%L0,%2,%0), low);
2859 output_asm_insn (AS2 (adc%L0,%2,%0), high);
2860 }
2861
2862 else
2863 output_asm_insn (AS2 (add%L0,%2,%0), high);
2864
2865 RET;
2866 }")
2867
2868 ;; On a 486, it is faster to do movl/addl than to do a single leal if
2869 ;; operands[1] and operands[2] are both registers.
2870
2871 (define_expand "addsi3"
2872 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2873 (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
2874 (match_operand:SI 2 "general_operand" "")))]
2875 ""
2876 "IX86_EXPAND_BINARY_OPERATOR (PLUS, SImode, operands);")
2877
2878 (define_insn ""
2879 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
2880 (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
2881 (match_operand:SI 2 "general_operand" "rmi,ri,ri")))]
2882 "ix86_binary_operator_ok (PLUS, SImode, operands)"
2883 "*
2884 {
2885 if (REG_P (operands[0]) && REG_P (operands[1])
2886 && (REG_P (operands[2]) || GET_CODE (operands[2]) == CONST_INT)
2887 && REGNO (operands[0]) != REGNO (operands[1]))
2888 {
2889 if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
2890 return AS2 (add%L0,%1,%0);
2891
2892 if (operands[2] == stack_pointer_rtx)
2893 {
2894 rtx temp;
2895
2896 temp = operands[1];
2897 operands[1] = operands[2];
2898 operands[2] = temp;
2899 }
2900
2901 if (operands[2] != stack_pointer_rtx)
2902 {
2903 CC_STATUS_INIT;
2904 operands[1] = SET_SRC (PATTERN (insn));
2905 return AS2 (lea%L0,%a1,%0);
2906 }
2907 }
2908
2909 if (!rtx_equal_p (operands[0], operands[1]))
2910 output_asm_insn (AS2 (mov%L0,%1,%0), operands);
2911
2912 if (operands[2] == const1_rtx)
2913 return AS1 (inc%L0,%0);
2914
2915 if (operands[2] == constm1_rtx)
2916 return AS1 (dec%L0,%0);
2917
2918 /* subl $-128,%ebx is smaller than addl $128,%ebx. */
2919 if (GET_CODE (operands[2]) == CONST_INT
2920 && INTVAL (operands[2]) == 128)
2921 {
2922 /* This doesn't compute the carry bit in the same way
2923 * as add%L0, but we use inc and dec above and they
2924 * don't set the carry bit at all. If inc/dec don't need
2925 * a CC_STATUS_INIT, this doesn't either... */
2926 operands[2] = GEN_INT (-128);
2927 return AS2 (sub%L0,%2,%0);
2928 }
2929
2930 return AS2 (add%L0,%2,%0);
2931 }")
2932
2933 ;; addsi3 is faster, so put this after.
2934
2935 (define_insn "movsi_lea"
2936 [(set (match_operand:SI 0 "register_operand" "=r")
2937 (match_operand:QI 1 "address_operand" "p"))]
2938 ""
2939 "*
2940 {
2941 /* Adding a constant to a register is faster with an add. */
2942 /* ??? can this ever happen? */
2943 if (GET_CODE (operands[1]) == PLUS
2944 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2945 && rtx_equal_p (operands[0], XEXP (operands[1], 0)))
2946 {
2947 operands[1] = XEXP (operands[1], 1);
2948
2949 if (operands[1] == const1_rtx)
2950 return AS1 (inc%L0,%0);
2951
2952 if (operands[1] == constm1_rtx)
2953 return AS1 (dec%L0,%0);
2954
2955 return AS2 (add%L0,%1,%0);
2956 }
2957
2958 CC_STATUS_INIT;
2959 return AS2 (lea%L0,%a1,%0);
2960 }")
2961
2962 ;; ??? `lea' here, for three operand add? If leaw is used, only %bx,
2963 ;; %si and %di can appear in SET_SRC, and output_asm_insn might not be
2964 ;; able to handle the operand. But leal always works?
2965
2966 (define_expand "addhi3"
2967 [(set (match_operand:HI 0 "general_operand" "")
2968 (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
2969 (match_operand:HI 2 "general_operand" "")))]
2970 ""
2971 "IX86_EXPAND_BINARY_OPERATOR (PLUS, HImode, operands);")
2972
2973 (define_insn ""
2974 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
2975 (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
2976 (match_operand:HI 2 "general_operand" "ri,rm")))]
2977 "ix86_binary_operator_ok (PLUS, HImode, operands)"
2978 "*
2979 {
2980 /* ??? what about offsettable memory references? */
2981 if (!TARGET_PENTIUMPRO /* partial stalls are just too painful to risk. */
2982 && QI_REG_P (operands[0])
2983 && GET_CODE (operands[2]) == CONST_INT
2984 && (INTVAL (operands[2]) & 0xff) == 0
2985 && i386_cc_probably_useless_p (insn))
2986 {
2987 int byteval = (INTVAL (operands[2]) >> 8) & 0xff;
2988 CC_STATUS_INIT;
2989
2990 if (byteval == 1)
2991 return AS1 (inc%B0,%h0);
2992 else if (byteval == 255)
2993 return AS1 (dec%B0,%h0);
2994
2995 operands[2] = GEN_INT (byteval);
2996 return AS2 (add%B0,%2,%h0);
2997 }
2998
2999 /* Use a 32-bit operation when possible, to avoid the prefix penalty. */
3000 if (REG_P (operands[0])
3001 && i386_aligned_p (operands[2])
3002 && i386_cc_probably_useless_p (insn))
3003 {
3004 CC_STATUS_INIT;
3005
3006 if (GET_CODE (operands[2]) == CONST_INT)
3007 {
3008 HOST_WIDE_INT intval = 0xffff & INTVAL (operands[2]);
3009
3010 if (intval == 1)
3011 return AS1 (inc%L0,%k0);
3012
3013 if (intval == 0xffff)
3014 return AS1 (dec%L0,%k0);
3015
3016 operands[2] = i386_sext16_if_const (operands[2]);
3017 }
3018 return AS2 (add%L0,%k2,%k0);
3019 }
3020
3021 if (operands[2] == const1_rtx)
3022 return AS1 (inc%W0,%0);
3023
3024 if (operands[2] == constm1_rtx
3025 || (GET_CODE (operands[2]) == CONST_INT
3026 && INTVAL (operands[2]) == 65535))
3027 return AS1 (dec%W0,%0);
3028
3029 return AS2 (add%W0,%2,%0);
3030 }")
3031
3032 (define_expand "addqi3"
3033 [(set (match_operand:QI 0 "general_operand" "")
3034 (plus:QI (match_operand:QI 1 "general_operand" "")
3035 (match_operand:QI 2 "general_operand" "")))]
3036 ""
3037 "IX86_EXPAND_BINARY_OPERATOR (PLUS, QImode, operands);")
3038
3039 (define_insn ""
3040 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
3041 (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
3042 (match_operand:QI 2 "general_operand" "qn,qmn")))]
3043 "ix86_binary_operator_ok (PLUS, QImode, operands)"
3044 "*
3045 {
3046 if (operands[2] == const1_rtx)
3047 return AS1 (inc%B0,%0);
3048
3049 if (operands[2] == constm1_rtx
3050 || (GET_CODE (operands[2]) == CONST_INT
3051 && INTVAL (operands[2]) == 255))
3052 return AS1 (dec%B0,%0);
3053
3054 return AS2 (add%B0,%2,%0);
3055 }")
3056
3057 ;Lennart Augustsson <augustss@cs.chalmers.se>
3058 ;says this pattern just makes slower code:
3059 ; pushl %ebp
3060 ; addl $-80,(%esp)
3061 ;instead of
3062 ; leal -80(%ebp),%eax
3063 ; pushl %eax
3064 ;
3065 ;(define_insn ""
3066 ; [(set (match_operand:SI 0 "push_operand" "=<")
3067 ; (plus:SI (match_operand:SI 1 "register_operand" "%r")
3068 ; (match_operand:SI 2 "nonmemory_operand" "ri")))]
3069 ; ""
3070 ; "*
3071 ;{
3072 ; rtx xops[4];
3073 ; xops[0] = operands[0];
3074 ; xops[1] = operands[1];
3075 ; xops[2] = operands[2];
3076 ; xops[3] = gen_rtx_MEM (SImode, stack_pointer_rtx);
3077 ; output_asm_insn (\"push%z1 %1\", xops);
3078 ; output_asm_insn (AS2 (add%z3,%2,%3), xops);
3079 ; RET;
3080 ;}")
3081
3082 ;; The patterns that match these are at the end of this file.
3083
3084 (define_expand "addxf3"
3085 [(set (match_operand:XF 0 "register_operand" "")
3086 (plus:XF (match_operand:XF 1 "register_operand" "")
3087 (match_operand:XF 2 "register_operand" "")))]
3088 "TARGET_80387"
3089 "")
3090
3091 (define_expand "adddf3"
3092 [(set (match_operand:DF 0 "register_operand" "")
3093 (plus:DF (match_operand:DF 1 "nonimmediate_operand" "")
3094 (match_operand:DF 2 "nonimmediate_operand" "")))]
3095 "TARGET_80387"
3096 "")
3097
3098 (define_expand "addsf3"
3099 [(set (match_operand:SF 0 "register_operand" "")
3100 (plus:SF (match_operand:SF 1 "nonimmediate_operand" "")
3101 (match_operand:SF 2 "nonimmediate_operand" "")))]
3102 "TARGET_80387"
3103 "")
3104 \f
3105 ;;- subtract instructions
3106
3107 (define_insn "subsidi3"
3108 [(set (match_operand:DI 0 "general_operand" "=&r,&ro,&r,!&r,o,o,!o")
3109 (minus:DI (match_operand:DI 1 "general_operand" "0iF,0,roiF,roiF,riF,o,o")
3110 (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,ri,i,r"))))
3111 (clobber (match_scratch:SI 3 "=X,X,X,X,X,&r,&r"))]
3112 ""
3113 "*
3114 {
3115 rtx low[3], high[3], xops[7];
3116
3117 CC_STATUS_INIT;
3118
3119 split_di (operands, 2, low, high);
3120 high[2] = const0_rtx;
3121 low[2] = operands[2];
3122
3123 if (!rtx_equal_p (operands[0], operands[1]))
3124 {
3125 xops[0] = high[0];
3126 xops[1] = low[0];
3127 xops[2] = high[1];
3128 xops[3] = low[1];
3129
3130 if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
3131 {
3132 output_asm_insn (AS2 (mov%L1,%3,%1), xops);
3133 output_asm_insn (AS2 (mov%L0,%2,%0), xops);
3134 }
3135 else
3136 {
3137 xops[4] = high[2];
3138 xops[5] = low[2];
3139 xops[6] = operands[3];
3140 output_asm_insn (AS2 (mov%L6,%3,%6), xops);
3141 output_asm_insn (AS2 (sub%L6,%5,%6), xops);
3142 output_asm_insn (AS2 (mov%L1,%6,%1), xops);
3143 output_asm_insn (AS2 (mov%L6,%2,%6), xops);
3144 output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
3145 output_asm_insn (AS2 (mov%L0,%6,%0), xops);
3146 RET;
3147 }
3148 }
3149
3150 output_asm_insn (AS2 (sub%L0,%2,%0), low);
3151 output_asm_insn (AS2 (sbb%L0,%2,%0), high);
3152 RET;
3153 }")
3154
3155 (define_insn "subdi3"
3156 [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,o,!&r,!o")
3157 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0iF,or,roiF,roiF")
3158 (match_operand:DI 2 "general_operand" "or,riF,or,iF,roiF,roiF")))
3159 (clobber (match_scratch:SI 3 "=X,X,&r,&r,X,&r"))]
3160 ""
3161 "*
3162 {
3163 rtx low[3], high[3], xops[7];
3164
3165 CC_STATUS_INIT;
3166
3167 split_di (operands, 3, low, high);
3168
3169 if (!rtx_equal_p (operands[0], operands[1]))
3170 {
3171 xops[0] = high[0];
3172 xops[1] = low[0];
3173 xops[2] = high[1];
3174 xops[3] = low[1];
3175
3176 if (GET_CODE (operands[0]) != MEM)
3177 {
3178 output_asm_insn (AS2 (mov%L1,%3,%1), xops);
3179 output_asm_insn (AS2 (mov%L0,%2,%0), xops);
3180 }
3181 else
3182 {
3183 xops[4] = high[2];
3184 xops[5] = low[2];
3185 xops[6] = operands[3];
3186 output_asm_insn (AS2 (mov%L6,%3,%6), xops);
3187 output_asm_insn (AS2 (sub%L6,%5,%6), xops);
3188 output_asm_insn (AS2 (mov%L1,%6,%1), xops);
3189 output_asm_insn (AS2 (mov%L6,%2,%6), xops);
3190 output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
3191 output_asm_insn (AS2 (mov%L0,%6,%0), xops);
3192 RET;
3193 }
3194 }
3195
3196 if (GET_CODE (operands[3]) == REG)
3197 {
3198 xops[0] = high[0];
3199 xops[1] = low[0];
3200 xops[2] = high[2];
3201 xops[3] = low[2];
3202 xops[4] = operands[3];
3203
3204 output_asm_insn (AS2 (mov%L4,%3,%4), xops);
3205 output_asm_insn (AS2 (sub%L1,%4,%1), xops);
3206 output_asm_insn (AS2 (mov%L4,%2,%4), xops);
3207 output_asm_insn (AS2 (sbb%L0,%4,%0), xops);
3208 }
3209
3210 else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
3211 {
3212 output_asm_insn (AS2 (sub%L0,%2,%0), low);
3213 output_asm_insn (AS2 (sbb%L0,%2,%0), high);
3214 }
3215
3216 else
3217 output_asm_insn (AS2 (sub%L0,%2,%0), high);
3218
3219 RET;
3220 }")
3221
3222 (define_expand "subsi3"
3223 [(set (match_operand:SI 0 "nonimmediate_operand" "")
3224 (minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
3225 (match_operand:SI 2 "general_operand" "")))]
3226 ""
3227 "IX86_EXPAND_BINARY_OPERATOR (MINUS, SImode, operands);")
3228
3229 (define_insn ""
3230 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
3231 (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
3232 (match_operand:SI 2 "general_operand" "ri,rm")))]
3233 "ix86_binary_operator_ok (MINUS, SImode, operands)"
3234 "* return AS2 (sub%L0,%2,%0);")
3235
3236 (define_expand "subhi3"
3237 [(set (match_operand:HI 0 "general_operand" "")
3238 (minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
3239 (match_operand:HI 2 "general_operand" "")))]
3240 ""
3241 "IX86_EXPAND_BINARY_OPERATOR (MINUS, HImode, operands);")
3242
3243 (define_insn ""
3244 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
3245 (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
3246 (match_operand:HI 2 "general_operand" "ri,rm")))]
3247 "ix86_binary_operator_ok (MINUS, HImode, operands)"
3248 "*
3249 {
3250 if (REG_P (operands[0])
3251 && i386_aligned_p (operands[2])
3252 && i386_cc_probably_useless_p (insn))
3253 {
3254 CC_STATUS_INIT;
3255 operands[2] = i386_sext16_if_const (operands[2]);
3256 return AS2 (sub%L0,%k2,%k0);
3257 }
3258 return AS2 (sub%W0,%2,%0);
3259 }")
3260
3261 (define_expand "subqi3"
3262 [(set (match_operand:QI 0 "general_operand" "")
3263 (minus:QI (match_operand:QI 1 "general_operand" "")
3264 (match_operand:QI 2 "general_operand" "")))]
3265 ""
3266 "IX86_EXPAND_BINARY_OPERATOR (MINUS, QImode, operands);")
3267
3268 (define_insn ""
3269 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
3270 (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
3271 (match_operand:QI 2 "general_operand" "qn,qmn")))]
3272 "ix86_binary_operator_ok (MINUS, QImode, operands)"
3273 "* return AS2 (sub%B0,%2,%0);")
3274
3275 ;; The patterns that match these are at the end of this file.
3276
3277 (define_expand "subxf3"
3278 [(set (match_operand:XF 0 "register_operand" "")
3279 (minus:XF (match_operand:XF 1 "register_operand" "")
3280 (match_operand:XF 2 "register_operand" "")))]
3281 "TARGET_80387"
3282 "")
3283
3284 (define_expand "subdf3"
3285 [(set (match_operand:DF 0 "register_operand" "")
3286 (minus:DF (match_operand:DF 1 "nonimmediate_operand" "")
3287 (match_operand:DF 2 "nonimmediate_operand" "")))]
3288 "TARGET_80387"
3289 "")
3290
3291 (define_expand "subsf3"
3292 [(set (match_operand:SF 0 "register_operand" "")
3293 (minus:SF (match_operand:SF 1 "nonimmediate_operand" "")
3294 (match_operand:SF 2 "nonimmediate_operand" "")))]
3295 "TARGET_80387"
3296 "")
3297 \f
3298 ;;- multiply instructions
3299
3300 ;(define_insn "mulqi3"
3301 ; [(set (match_operand:QI 0 "register_operand" "=a")
3302 ; (mult:QI (match_operand:QI 1 "register_operand" "%0")
3303 ; (match_operand:QI 2 "nonimmediate_operand" "qm")))]
3304 ; ""
3305 ; "imul%B0 %2,%0")
3306
3307 (define_insn "mulhi3"
3308 [(set (match_operand:HI 0 "register_operand" "=r,r")
3309 (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%0,rm")
3310 (match_operand:HI 2 "general_operand" "g,i")))]
3311 ""
3312 "*
3313 {
3314 if (GET_CODE (operands[1]) == REG
3315 && REGNO (operands[1]) == REGNO (operands[0])
3316 && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
3317 /* Assembler has weird restrictions. */
3318 return AS2 (imul%W0,%2,%0);
3319 return AS3 (imul%W0,%2,%1,%0);
3320 }"
3321 [(set_attr "type" "imul")])
3322
3323 (define_insn "mulsi3"
3324 [(set (match_operand:SI 0 "register_operand" "=r,r")
3325 (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm")
3326 (match_operand:SI 2 "general_operand" "g,i")))]
3327 ""
3328 "*
3329 {
3330 if (GET_CODE (operands[1]) == REG
3331 && REGNO (operands[1]) == REGNO (operands[0])
3332 && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
3333 /* Assembler has weird restrictions. */
3334 return AS2 (imul%L0,%2,%0);
3335 return AS3 (imul%L0,%2,%1,%0);
3336 }"
3337 [(set_attr "type" "imul")])
3338
3339 (define_insn "umulqihi3"
3340 [(set (match_operand:HI 0 "register_operand" "=a")
3341 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0"))
3342 (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
3343 ""
3344 "mul%B0 %2"
3345 [(set_attr "type" "imul")])
3346
3347 (define_insn "mulqihi3"
3348 [(set (match_operand:HI 0 "register_operand" "=a")
3349 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
3350 (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
3351 ""
3352 "imul%B0 %2"
3353 [(set_attr "type" "imul")])
3354
3355 (define_insn "umulsidi3"
3356 [(set (match_operand:DI 0 "register_operand" "=A")
3357 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
3358 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
3359 "TARGET_WIDE_MULTIPLY"
3360 "mul%L0 %2"
3361 [(set_attr "type" "imul")])
3362
3363 (define_insn "mulsidi3"
3364 [(set (match_operand:DI 0 "register_operand" "=A")
3365 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
3366 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
3367 "TARGET_WIDE_MULTIPLY"
3368 "imul%L0 %2"
3369 [(set_attr "type" "imul")])
3370
3371 (define_insn "umulsi3_highpart"
3372 [(set (match_operand:SI 0 "register_operand" "=d")
3373 (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a"))
3374 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
3375 (const_int 32))))
3376 (clobber (match_scratch:SI 3 "=a"))]
3377 "TARGET_WIDE_MULTIPLY"
3378 "mul%L0 %2"
3379 [(set_attr "type" "imul")])
3380
3381 (define_insn "smulsi3_highpart"
3382 [(set (match_operand:SI 0 "register_operand" "=d")
3383 (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%a"))
3384 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
3385 (const_int 32))))
3386 (clobber (match_scratch:SI 3 "=a"))]
3387 "TARGET_WIDE_MULTIPLY"
3388 "imul%L0 %2"
3389 [(set_attr "type" "imul")])
3390
3391 ;; The patterns that match these are at the end of this file.
3392
3393 (define_expand "mulxf3"
3394 [(set (match_operand:XF 0 "register_operand" "")
3395 (mult:XF (match_operand:XF 1 "register_operand" "")
3396 (match_operand:XF 2 "register_operand" "")))]
3397 "TARGET_80387"
3398 "")
3399
3400 (define_expand "muldf3"
3401 [(set (match_operand:DF 0 "register_operand" "")
3402 (mult:DF (match_operand:DF 1 "register_operand" "")
3403 (match_operand:DF 2 "nonimmediate_operand" "")))]
3404 "TARGET_80387"
3405 "")
3406
3407 (define_expand "mulsf3"
3408 [(set (match_operand:SF 0 "register_operand" "")
3409 (mult:SF (match_operand:SF 1 "register_operand" "")
3410 (match_operand:SF 2 "nonimmediate_operand" "")))]
3411 "TARGET_80387"
3412 "")
3413 \f
3414 ;;- divide instructions
3415
3416 (define_insn "divqi3"
3417 [(set (match_operand:QI 0 "register_operand" "=a")
3418 (div:QI (match_operand:HI 1 "register_operand" "0")
3419 (match_operand:QI 2 "nonimmediate_operand" "qm")))]
3420 ""
3421 "idiv%B0 %2")
3422
3423 (define_insn "udivqi3"
3424 [(set (match_operand:QI 0 "register_operand" "=a")
3425 (udiv:QI (match_operand:HI 1 "register_operand" "0")
3426 (match_operand:QI 2 "nonimmediate_operand" "qm")))]
3427 ""
3428 "div%B0 %2"
3429 [(set_attr "type" "idiv")])
3430
3431 ;; The patterns that match these are at the end of this file.
3432
3433 (define_expand "divxf3"
3434 [(set (match_operand:XF 0 "register_operand" "")
3435 (div:XF (match_operand:XF 1 "register_operand" "")
3436 (match_operand:XF 2 "register_operand" "")))]
3437 "TARGET_80387"
3438 "")
3439
3440 (define_expand "divdf3"
3441 [(set (match_operand:DF 0 "register_operand" "")
3442 (div:DF (match_operand:DF 1 "register_operand" "")
3443 (match_operand:DF 2 "nonimmediate_operand" "")))]
3444 "TARGET_80387"
3445 "")
3446
3447 (define_expand "divsf3"
3448 [(set (match_operand:SF 0 "register_operand" "")
3449 (div:SF (match_operand:SF 1 "register_operand" "")
3450 (match_operand:SF 2 "nonimmediate_operand" "")))]
3451 "TARGET_80387"
3452 "")
3453 \f
3454 ;; Remainder instructions.
3455
3456 (define_insn "divmodsi4"
3457 [(set (match_operand:SI 0 "register_operand" "=a")
3458 (div:SI (match_operand:SI 1 "register_operand" "0")
3459 (match_operand:SI 2 "nonimmediate_operand" "rm")))
3460 (set (match_operand:SI 3 "register_operand" "=&d")
3461 (mod:SI (match_dup 1) (match_dup 2)))]
3462 ""
3463 "*
3464 {
3465 #ifdef INTEL_SYNTAX
3466 output_asm_insn (\"cdq\", operands);
3467 #else
3468 output_asm_insn (\"cltd\", operands);
3469 #endif
3470 return AS1 (idiv%L0,%2);
3471 }"
3472 [(set_attr "type" "idiv")])
3473
3474 (define_insn "divmodhi4"
3475 [(set (match_operand:HI 0 "register_operand" "=a")
3476 (div:HI (match_operand:HI 1 "register_operand" "0")
3477 (match_operand:HI 2 "nonimmediate_operand" "rm")))
3478 (set (match_operand:HI 3 "register_operand" "=&d")
3479 (mod:HI (match_dup 1) (match_dup 2)))]
3480 ""
3481 "cwtd\;idiv%W0 %2"
3482 [(set_attr "type" "idiv")])
3483
3484 ;; ??? Can we make gcc zero extend operand[0]?
3485 (define_insn "udivmodsi4"
3486 [(set (match_operand:SI 0 "register_operand" "=a")
3487 (udiv:SI (match_operand:SI 1 "register_operand" "0")
3488 (match_operand:SI 2 "nonimmediate_operand" "rm")))
3489 (set (match_operand:SI 3 "register_operand" "=&d")
3490 (umod:SI (match_dup 1) (match_dup 2)))]
3491 ""
3492 "*
3493 {
3494 output_asm_insn (AS2 (xor%L3,%3,%3), operands);
3495 return AS1 (div%L0,%2);
3496 }"
3497 [(set_attr "type" "idiv")])
3498
3499 ;; ??? Can we make gcc zero extend operand[0]?
3500 (define_insn "udivmodhi4"
3501 [(set (match_operand:HI 0 "register_operand" "=a")
3502 (udiv:HI (match_operand:HI 1 "register_operand" "0")
3503 (match_operand:HI 2 "nonimmediate_operand" "rm")))
3504 (set (match_operand:HI 3 "register_operand" "=&d")
3505 (umod:HI (match_dup 1) (match_dup 2)))]
3506 ""
3507 "*
3508 {
3509 output_asm_insn (AS2 (xor%W0,%3,%3), operands);
3510 return AS1 (div%W0,%2);
3511 }"
3512 [(set_attr "type" "idiv")])
3513
3514 /*
3515 ;;this should be a valid double division which we may want to add
3516
3517 (define_insn ""
3518 [(set (match_operand:SI 0 "register_operand" "=a")
3519 (udiv:DI (match_operand:DI 1 "register_operand" "a")
3520 (match_operand:SI 2 "nonimmediate_operand" "rm")))
3521 (set (match_operand:SI 3 "register_operand" "=d")
3522 (umod:SI (match_dup 1) (match_dup 2)))]
3523 ""
3524 "div%L0 %2,%0"
3525 [(set_attr "type" "idiv")])
3526 */
3527 \f
3528 ;;- and instructions
3529
3530 ;; On i386,
3531 ;; movzbl %bl,%ebx
3532 ;; is faster than
3533 ;; andl $255,%ebx
3534 ;;
3535 ;; but if the reg is %eax, then the "andl" is faster.
3536 ;;
3537 ;; On i486, the "andl" is always faster than the "movzbl".
3538 ;;
3539 ;; On both i386 and i486, a three operand AND is as fast with movzbl or
3540 ;; movzwl as with andl, if operands[0] != operands[1].
3541
3542 ;; The `r' in `rm' for operand 3 looks redundant, but it causes
3543 ;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
3544
3545 (define_insn "andsi3"
3546 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
3547 (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
3548 (match_operand:SI 2 "general_operand" "ri,rm")))]
3549 ""
3550 "*
3551 {
3552 HOST_WIDE_INT intval;
3553 if (!rtx_equal_p (operands[0], operands[1])
3554 && rtx_equal_p (operands[0], operands[2]))
3555 {
3556 rtx tmp;
3557 tmp = operands[1];
3558 operands[1] = operands[2];
3559 operands[2] = tmp;
3560 }
3561 switch (GET_CODE (operands[2]))
3562 {
3563 case CONST_INT:
3564 if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
3565 break;
3566 intval = INTVAL (operands[2]);
3567 /* zero-extend 16->32? */
3568 if (intval == 0xffff && REG_P (operands[0])
3569 && (! REG_P (operands[1])
3570 || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
3571 && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1])))
3572 {
3573 /* ??? tege: Should forget CC_STATUS only if we clobber a
3574 remembered operand. Fix that later. */
3575 CC_STATUS_INIT;
3576 #ifdef INTEL_SYNTAX
3577 return AS2 (movzx,%w1,%0);
3578 #else
3579 return AS2 (movz%W0%L0,%w1,%0);
3580 #endif
3581 }
3582
3583 /* zero extend 8->32? */
3584 if (intval == 0xff && REG_P (operands[0])
3585 && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
3586 && (! REG_P (operands[1])
3587 || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
3588 && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1])))
3589 {
3590 /* ??? tege: Should forget CC_STATUS only if we clobber a
3591 remembered operand. Fix that later. */
3592 CC_STATUS_INIT;
3593 #ifdef INTEL_SYNTAX
3594 return AS2 (movzx,%b1,%0);
3595 #else
3596 return AS2 (movz%B0%L0,%b1,%0);
3597 #endif
3598 }
3599
3600 /* Check partial bytes.. non-QI-regs are not available */
3601 if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
3602 break;
3603
3604 /* only low byte has zero bits? */
3605 if (~(intval | 0xff) == 0)
3606 {
3607 intval &= 0xff;
3608 if (REG_P (operands[0]))
3609 {
3610 if (intval == 0)
3611 {
3612 CC_STATUS_INIT;
3613 return AS2 (xor%B0,%b0,%b0);
3614 }
3615
3616 /* we're better off with the 32-bit version if reg != EAX */
3617 /* the value is sign-extended in 8 bits */
3618 if (REGNO (operands[0]) != 0 && (intval & 0x80))
3619 break;
3620 }
3621
3622 CC_STATUS_INIT;
3623
3624 operands[2] = GEN_INT (intval);
3625
3626 if (intval == 0)
3627 return AS2 (mov%B0,%2,%b0);
3628
3629 return AS2 (and%B0,%2,%b0);
3630 }
3631
3632 /* only second byte has zero? */
3633 if (~(intval | 0xff00) == 0)
3634 {
3635 CC_STATUS_INIT;
3636
3637 intval = (intval >> 8) & 0xff;
3638 operands[2] = GEN_INT (intval);
3639 if (intval == 0)
3640 {
3641 if (REG_P (operands[0]))
3642 return AS2 (xor%B0,%h0,%h0);
3643 operands[0] = adj_offsettable_operand (operands[0], 1);
3644 return AS2 (mov%B0,%2,%b0);
3645 }
3646
3647 if (REG_P (operands[0]))
3648 return AS2 (and%B0,%2,%h0);
3649
3650 operands[0] = adj_offsettable_operand (operands[0], 1);
3651 return AS2 (and%B0,%2,%b0);
3652 }
3653
3654 if (REG_P (operands[0]))
3655 break;
3656
3657 /* third byte has zero bits? */
3658 if (~(intval | 0xff0000) == 0)
3659 {
3660 intval = (intval >> 16) & 0xff;
3661 operands[0] = adj_offsettable_operand (operands[0], 2);
3662 byte_and_operation:
3663 CC_STATUS_INIT;
3664 operands[2] = GEN_INT (intval);
3665 if (intval == 0)
3666 return AS2 (mov%B0,%2,%b0);
3667 return AS2 (and%B0,%2,%b0);
3668 }
3669
3670 /* fourth byte has zero bits? */
3671 if (~(intval | 0xff000000) == 0)
3672 {
3673 intval = (intval >> 24) & 0xff;
3674 operands[0] = adj_offsettable_operand (operands[0], 3);
3675 goto byte_and_operation;
3676 }
3677
3678 /* Low word is zero? */
3679 if (intval == 0xffff0000)
3680 {
3681 word_zero_and_operation:
3682 CC_STATUS_INIT;
3683 operands[2] = const0_rtx;
3684 return AS2 (mov%W0,%2,%w0);
3685 }
3686
3687 /* High word is zero? */
3688 if (intval == 0x0000ffff)
3689 {
3690 operands[0] = adj_offsettable_operand (operands[0], 2);
3691 goto word_zero_and_operation;
3692 }
3693
3694 default:
3695 break;
3696 }
3697
3698 return AS2 (and%L0,%2,%0);
3699 }")
3700
3701 (define_insn "andhi3"
3702 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
3703 (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
3704 (match_operand:HI 2 "general_operand" "ri,rm")))]
3705 ""
3706 "*
3707 {
3708 if (GET_CODE (operands[2]) == CONST_INT
3709 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
3710 {
3711 /* Can we ignore the upper byte? */
3712 if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
3713 && (INTVAL (operands[2]) & 0xff00) == 0xff00)
3714 {
3715 CC_STATUS_INIT;
3716
3717 if ((INTVAL (operands[2]) & 0xff) == 0)
3718 {
3719 operands[2] = const0_rtx;
3720 return AS2 (mov%B0,%2,%b0);
3721 }
3722
3723 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
3724 return AS2 (and%B0,%2,%b0);
3725 }
3726
3727 /* Can we ignore the lower byte? */
3728 /* ??? what about offsettable memory references? */
3729 if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff)
3730 {
3731 CC_STATUS_INIT;
3732
3733 if ((INTVAL (operands[2]) & 0xff00) == 0)
3734 {
3735 operands[2] = const0_rtx;
3736 return AS2 (mov%B0,%2,%h0);
3737 }
3738
3739 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
3740 return AS2 (and%B0,%2,%h0);
3741 }
3742
3743 /* use 32-bit ops on registers when there are no sign issues.. */
3744 if (REG_P (operands[0]))
3745 {
3746 if (!(INTVAL (operands[2]) & ~0x7fff))
3747 return AS2 (and%L0,%2,%k0);
3748 }
3749 }
3750
3751 if (REG_P (operands[0])
3752 && i386_aligned_p (operands[2]))
3753 {
3754 CC_STATUS_INIT;
3755 /* If op[2] is constant, we should zero-extend it and */
3756 /* make a note that op[0] has been zero-extended, so */
3757 /* that we could use 32-bit ops on it forthwith, but */
3758 /* there is no such reg-note available. Instead we do */
3759 /* a sign extension as that can result in shorter asm */
3760 operands[2] = i386_sext16_if_const (operands[2]);
3761 return AS2 (and%L0,%k2,%k0);
3762 }
3763
3764 /* Use a 32-bit word with the upper bits set, invalidate CC */
3765 if (GET_CODE (operands[2]) == CONST_INT
3766 && i386_aligned_p (operands[0]))
3767 {
3768 HOST_WIDE_INT val = INTVAL (operands[2]);
3769 CC_STATUS_INIT;
3770 val |= ~0xffff;
3771 if (val != INTVAL (operands[2]))
3772 operands[2] = GEN_INT (val);
3773 return AS2 (and%L0,%k2,%k0);
3774 }
3775
3776 return AS2 (and%W0,%2,%0);
3777 }")
3778
3779 (define_insn "andqi3"
3780 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
3781 (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
3782 (match_operand:QI 2 "general_operand" "qn,qmn")))]
3783 ""
3784 "* return AS2 (and%B0,%2,%0);")
3785
3786 /* I am nervous about these two.. add them later..
3787 ;I presume this means that we have something in say op0= eax which is small
3788 ;and we want to and it with memory so we can do this by just an
3789 ;andb m,%al and have success.
3790 (define_insn ""
3791 [(set (match_operand:SI 0 "general_operand" "=r")
3792 (and:SI (zero_extend:SI
3793 (match_operand:HI 1 "nonimmediate_operand" "rm"))
3794 (match_operand:SI 2 "general_operand" "0")))]
3795 "GET_CODE (operands[2]) == CONST_INT
3796 && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
3797 "and%W0 %1,%0")
3798
3799 (define_insn ""
3800 [(set (match_operand:SI 0 "register_operand" "=q")
3801 (and:SI
3802 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))
3803 (match_operand:SI 2 "register_operand" "0")))]
3804 "GET_CODE (operands[2]) == CONST_INT
3805 && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
3806 "and%L0 %1,%0")
3807
3808 */
3809 \f
3810 ;;- Bit set (inclusive or) instructions
3811
3812 ;; This optimizes known byte-wide operations to memory, and in some cases
3813 ;; to QI registers.. Note that we don't want to use the QI registers too
3814 ;; aggressively, because often the 32-bit register instruction is the same
3815 ;; size, and likely to be faster on PentiumPro.
3816 (define_insn "iorsi3"
3817 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
3818 (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
3819 (match_operand:SI 2 "general_operand" "ri,rm")))]
3820 ""
3821 "*
3822 {
3823 HOST_WIDE_INT intval;
3824 switch (GET_CODE (operands[2]))
3825 {
3826 case CONST_INT:
3827
3828 if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
3829 break;
3830
3831 /* don't try to optimize volatile accesses */
3832 if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
3833 break;
3834
3835 intval = INTVAL (operands[2]);
3836 if ((intval & ~0xff) == 0)
3837 {
3838 if (REG_P (operands[0]))
3839 {
3840 /* Do low byte access only for %eax or when high bit is set */
3841 if (REGNO (operands[0]) != 0 && !(intval & 0x80))
3842 break;
3843 }
3844
3845 byte_or_operation:
3846 CC_STATUS_INIT;
3847
3848 if (intval != INTVAL (operands[2]))
3849 operands[2] = GEN_INT (intval);
3850
3851 if (intval == 0xff)
3852 return AS2 (mov%B0,%2,%b0);
3853
3854 return AS2 (or%B0,%2,%b0);
3855 }
3856
3857 /* second byte? */
3858 if ((intval & ~0xff00) == 0)
3859 {
3860 intval >>= 8;
3861
3862 if (REG_P (operands[0]))
3863 {
3864 CC_STATUS_INIT;
3865 operands[2] = GEN_INT (intval);
3866 if (intval == 0xff)
3867 return AS2 (mov%B0,%2,%h0);
3868
3869 return AS2 (or%B0,%2,%h0);
3870 }
3871
3872 operands[0] = adj_offsettable_operand (operands[0], 1);
3873 goto byte_or_operation;
3874 }
3875
3876 if (REG_P (operands[0]))
3877 break;
3878
3879 /* third byte? */
3880 if ((intval & ~0xff0000) == 0)
3881 {
3882 intval >>= 16;
3883 operands[0] = adj_offsettable_operand (operands[0], 2);
3884 goto byte_or_operation;
3885 }
3886
3887 /* fourth byte? */
3888 if ((intval & ~0xff000000) == 0)
3889 {
3890 intval = (intval >> 24) & 0xff;
3891 operands[0] = adj_offsettable_operand (operands[0], 3);
3892 goto byte_or_operation;
3893 }
3894
3895 default:
3896 break;
3897 }
3898
3899 return AS2 (or%L0,%2,%0);
3900 }")
3901
3902 (define_insn "iorhi3"
3903 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
3904 (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
3905 (match_operand:HI 2 "general_operand" "ri,rm")))]
3906 ""
3907 "*
3908 {
3909 HOST_WIDE_INT intval;
3910 switch (GET_CODE (operands[2]))
3911 {
3912 case CONST_INT:
3913
3914 if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
3915 break;
3916
3917 /* don't try to optimize volatile accesses */
3918 if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
3919 break;
3920
3921 intval = 0xffff & INTVAL (operands[2]);
3922
3923 if ((intval & 0xff00) == 0)
3924 {
3925 if (REG_P (operands[0]))
3926 {
3927 /* Do low byte access only for %eax or when high bit is set */
3928 if (REGNO (operands[0]) != 0 && !(intval & 0x80))
3929 break;
3930 }
3931
3932 byte_or_operation:
3933 CC_STATUS_INIT;
3934
3935 if (intval == 0xff)
3936 return AS2 (mov%B0,%2,%b0);
3937
3938 return AS2 (or%B0,%2,%b0);
3939 }
3940
3941 /* high byte? */
3942 if ((intval & 0xff) == 0)
3943 {
3944 intval >>= 8;
3945 operands[2] = GEN_INT (intval);
3946
3947 if (REG_P (operands[0]))
3948 {
3949 CC_STATUS_INIT;
3950 if (intval == 0xff)
3951 return AS2 (mov%B0,%2,%h0);
3952
3953 return AS2 (or%B0,%2,%h0);
3954 }
3955
3956 operands[0] = adj_offsettable_operand (operands[0], 1);
3957
3958 goto byte_or_operation;
3959 }
3960
3961 default:
3962 break;
3963 }
3964
3965 if (REG_P (operands[0])
3966 && i386_aligned_p (operands[2]))
3967 {
3968 CC_STATUS_INIT;
3969 operands[2] = i386_sext16_if_const (operands[2]);
3970 return AS2 (or%L0,%k2,%k0);
3971 }
3972
3973 if (GET_CODE (operands[2]) == CONST_INT
3974 && i386_aligned_p (operands[0]))
3975 {
3976 CC_STATUS_INIT;
3977 intval = 0xffff & INTVAL (operands[2]);
3978 if (intval != INTVAL (operands[2]))
3979 operands[2] = GEN_INT (intval);
3980 return AS2 (or%L0,%2,%k0);
3981 }
3982
3983 return AS2 (or%W0,%2,%0);
3984 }")
3985
3986 (define_insn "iorqi3"
3987 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
3988 (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
3989 (match_operand:QI 2 "general_operand" "qn,qmn")))]
3990 ""
3991 "* return AS2 (or%B0,%2,%0);")
3992 \f
3993 ;;- xor instructions
3994
3995 (define_insn "xorsi3"
3996 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
3997 (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
3998 (match_operand:SI 2 "general_operand" "ri,rm")))]
3999 ""
4000 "*
4001 {
4002 HOST_WIDE_INT intval;
4003 switch (GET_CODE (operands[2]))
4004 {
4005 case CONST_INT:
4006
4007 if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
4008 break;
4009
4010 /* don't try to optimize volatile accesses */
4011 if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
4012 break;
4013
4014 intval = INTVAL (operands[2]);
4015 if ((intval & ~0xff) == 0)
4016 {
4017 if (REG_P (operands[0]))
4018 {
4019 /* Do low byte access only for %eax or when high bit is set */
4020 if (REGNO (operands[0]) != 0 && !(intval & 0x80))
4021 break;
4022 }
4023
4024 byte_xor_operation:
4025 CC_STATUS_INIT;
4026
4027 if (intval == 0xff)
4028 return AS1 (not%B0,%b0);
4029
4030 if (intval != INTVAL (operands[2]))
4031 operands[2] = GEN_INT (intval);
4032 return AS2 (xor%B0,%2,%b0);
4033 }
4034
4035 /* second byte? */
4036 if ((intval & ~0xff00) == 0)
4037 {
4038 intval >>= 8;
4039
4040 if (REG_P (operands[0]))
4041 {
4042 CC_STATUS_INIT;
4043 if (intval == 0xff)
4044 return AS1 (not%B0,%h0);
4045
4046 operands[2] = GEN_INT (intval);
4047 return AS2 (xor%B0,%2,%h0);
4048 }
4049
4050 operands[0] = adj_offsettable_operand (operands[0], 1);
4051
4052 goto byte_xor_operation;
4053 }
4054
4055 if (REG_P (operands[0]))
4056 break;
4057
4058 /* third byte? */
4059 if ((intval & ~0xff0000) == 0)
4060 {
4061 intval >>= 16;
4062 operands[0] = adj_offsettable_operand (operands[0], 2);
4063 goto byte_xor_operation;
4064 }
4065
4066 /* fourth byte? */
4067 if ((intval & ~0xff000000) == 0)
4068 {
4069 intval = (intval >> 24) & 0xff;
4070 operands[0] = adj_offsettable_operand (operands[0], 3);
4071 goto byte_xor_operation;
4072 }
4073
4074 default:
4075 break;
4076 }
4077
4078 return AS2 (xor%L0,%2,%0);
4079 }")
4080
4081 (define_insn "xorhi3"
4082 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
4083 (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
4084 (match_operand:HI 2 "general_operand" "ri,rm")))]
4085 ""
4086 "*
4087 {
4088 if (GET_CODE (operands[2]) == CONST_INT
4089 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
4090 {
4091 /* Can we ignore the upper byte? */
4092 if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
4093 && (INTVAL (operands[2]) & 0xff00) == 0)
4094 {
4095 CC_STATUS_INIT;
4096 if (INTVAL (operands[2]) & 0xffff0000)
4097 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
4098
4099 if (INTVAL (operands[2]) == 0xff)
4100 return AS1 (not%B0,%b0);
4101
4102 return AS2 (xor%B0,%2,%b0);
4103 }
4104
4105 /* Can we ignore the lower byte? */
4106 /* ??? what about offsettable memory references? */
4107 if (QI_REG_P (operands[0])
4108 && (INTVAL (operands[2]) & 0xff) == 0)
4109 {
4110 CC_STATUS_INIT;
4111 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
4112
4113 if (INTVAL (operands[2]) == 0xff)
4114 return AS1 (not%B0,%h0);
4115
4116 return AS2 (xor%B0,%2,%h0);
4117 }
4118 }
4119
4120 if (REG_P (operands[0])
4121 && i386_aligned_p (operands[2]))
4122 {
4123 CC_STATUS_INIT;
4124 operands[2] = i386_sext16_if_const (operands[2]);
4125 return AS2 (xor%L0,%k2,%k0);
4126 }
4127
4128 if (GET_CODE (operands[2]) == CONST_INT
4129 && i386_aligned_p (operands[0]))
4130 {
4131 HOST_WIDE_INT intval;
4132 CC_STATUS_INIT;
4133 intval = 0xffff & INTVAL (operands[2]);
4134 if (intval != INTVAL (operands[2]))
4135 operands[2] = GEN_INT (intval);
4136 return AS2 (xor%L0,%2,%k0);
4137 }
4138
4139 return AS2 (xor%W0,%2,%0);
4140 }")
4141
4142 (define_insn "xorqi3"
4143 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
4144 (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
4145 (match_operand:QI 2 "general_operand" "qn,qm")))]
4146 ""
4147 "* return AS2 (xor%B0,%2,%0);")
4148 \f
4149 ;; logical operations for DImode
4150
4151
4152 (define_insn "anddi3"
4153 [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
4154 (and:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
4155 (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
4156 (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
4157 ""
4158 "#")
4159
4160 (define_insn "iordi3"
4161 [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
4162 (ior:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
4163 (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
4164 (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
4165 ""
4166 "#")
4167
4168 (define_insn "xordi3"
4169 [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
4170 (xor:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
4171 (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
4172 (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
4173 ""
4174 "#")
4175
4176 (define_split
4177 [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
4178 (match_operator:DI 4 "ix86_logical_operator"
4179 [(match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
4180 (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")]))
4181 (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
4182 "reload_completed"
4183 [(const_int 0)]
4184 "
4185 {
4186 rtx low[3], high[3], xops[7], temp;
4187 rtx (*genfunc)() = (GET_CODE (operands[4]) == AND ? gen_andsi3
4188 : GET_CODE (operands[4]) == IOR ? gen_iorsi3
4189 : GET_CODE (operands[4]) == XOR ? gen_xorsi3
4190 : 0);
4191
4192 if (rtx_equal_p (operands[0], operands[2]))
4193 {
4194 temp = operands[1];
4195 operands[1] = operands[2];
4196 operands[2] = temp;
4197 }
4198
4199 split_di (operands, 3, low, high);
4200 if (!rtx_equal_p (operands[0], operands[1]))
4201 {
4202 xops[0] = high[0];
4203 xops[1] = low[0];
4204 xops[2] = high[1];
4205 xops[3] = low[1];
4206
4207 if (GET_CODE (operands[0]) != MEM)
4208 {
4209 emit_insn (gen_movsi (xops[1], xops[3]));
4210 emit_insn (gen_movsi (xops[0], xops[2]));
4211 }
4212 else
4213 {
4214 xops[4] = high[2];
4215 xops[5] = low[2];
4216 xops[6] = operands[3];
4217 emit_insn (gen_movsi (xops[6], xops[3]));
4218 emit_insn ((*genfunc) (xops[6], xops[6], xops[5]));
4219 emit_insn (gen_movsi (xops[1], xops[6]));
4220 emit_insn (gen_movsi (xops[6], xops[2]));
4221 emit_insn ((*genfunc) (xops[6], xops[6], xops[4]));
4222 emit_insn (gen_movsi (xops[0], xops[6]));
4223 DONE;
4224 }
4225 }
4226
4227 if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
4228 {
4229 xops[0] = high[0];
4230 xops[1] = low[0];
4231 xops[2] = high[2];
4232 xops[3] = low[2];
4233 xops[4] = operands[3];
4234
4235 emit_insn (gen_movsi (xops[4], xops[3]));
4236 emit_insn ((*genfunc) (xops[1], xops[1], xops[4]));
4237 emit_insn (gen_movsi (xops[4], xops[2]));
4238 emit_insn ((*genfunc) (xops[0], xops[0], xops[4]));
4239 }
4240
4241 else
4242 {
4243 emit_insn ((*genfunc) (low[0], low[0], low[2]));
4244 emit_insn ((*genfunc) (high[0], high[0], high[2]));
4245 }
4246
4247 DONE;
4248 }")
4249
4250 ;;- negation instructions
4251
4252 (define_insn "negdi2"
4253 [(set (match_operand:DI 0 "general_operand" "=&ro")
4254 (neg:DI (match_operand:DI 1 "general_operand" "0")))]
4255 ""
4256 "*
4257 {
4258 rtx xops[2], low[1], high[1];
4259
4260 CC_STATUS_INIT;
4261
4262 split_di (operands, 1, low, high);
4263 xops[0] = const0_rtx;
4264 xops[1] = high[0];
4265
4266 output_asm_insn (AS1 (neg%L0,%0), low);
4267 output_asm_insn (AS2 (adc%L1,%0,%1), xops);
4268 output_asm_insn (AS1 (neg%L0,%0), high);
4269 RET;
4270 }")
4271
4272 (define_insn "negsi2"
4273 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4274 (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
4275 ""
4276 "neg%L0 %0")
4277
4278 (define_insn "neghi2"
4279 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4280 (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
4281 ""
4282 "neg%W0 %0")
4283
4284 (define_insn "negqi2"
4285 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4286 (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
4287 ""
4288 "neg%B0 %0")
4289
4290 (define_insn "negsf2"
4291 [(set (match_operand:SF 0 "register_operand" "=f")
4292 (neg:SF (match_operand:SF 1 "register_operand" "0")))]
4293 "TARGET_80387"
4294 "fchs")
4295
4296 (define_insn "negdf2"
4297 [(set (match_operand:DF 0 "register_operand" "=f")
4298 (neg:DF (match_operand:DF 1 "register_operand" "0")))]
4299 "TARGET_80387"
4300 "fchs")
4301
4302 (define_insn ""
4303 [(set (match_operand:DF 0 "register_operand" "=f")
4304 (neg:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
4305 "TARGET_80387"
4306 "fchs")
4307
4308 (define_insn "negxf2"
4309 [(set (match_operand:XF 0 "register_operand" "=f")
4310 (neg:XF (match_operand:XF 1 "register_operand" "0")))]
4311 "TARGET_80387"
4312 "fchs")
4313
4314 (define_insn ""
4315 [(set (match_operand:XF 0 "register_operand" "=f")
4316 (neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
4317 "TARGET_80387"
4318 "fchs")
4319 \f
4320 ;; Absolute value instructions
4321
4322 (define_insn "abssf2"
4323 [(set (match_operand:SF 0 "register_operand" "=f")
4324 (abs:SF (match_operand:SF 1 "register_operand" "0")))]
4325 "TARGET_80387"
4326 "fabs"
4327 [(set_attr "type" "fpop")])
4328
4329 (define_insn "absdf2"
4330 [(set (match_operand:DF 0 "register_operand" "=f")
4331 (abs:DF (match_operand:DF 1 "register_operand" "0")))]
4332 "TARGET_80387"
4333 "fabs"
4334 [(set_attr "type" "fpop")])
4335
4336 (define_insn ""
4337 [(set (match_operand:DF 0 "register_operand" "=f")
4338 (abs:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
4339 "TARGET_80387"
4340 "fabs"
4341 [(set_attr "type" "fpop")])
4342
4343 (define_insn "absxf2"
4344 [(set (match_operand:XF 0 "register_operand" "=f")
4345 (abs:XF (match_operand:XF 1 "register_operand" "0")))]
4346 "TARGET_80387"
4347 "fabs"
4348 [(set_attr "type" "fpop")])
4349
4350 (define_insn ""
4351 [(set (match_operand:XF 0 "register_operand" "=f")
4352 (abs:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
4353 "TARGET_80387"
4354 "fabs"
4355 [(set_attr "type" "fpop")])
4356
4357 (define_insn "sqrtsf2"
4358 [(set (match_operand:SF 0 "register_operand" "=f")
4359 (sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
4360 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
4361 "fsqrt")
4362
4363 (define_insn "sqrtdf2"
4364 [(set (match_operand:DF 0 "register_operand" "=f")
4365 (sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
4366 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
4367 && (TARGET_IEEE_FP || flag_fast_math) "
4368 "fsqrt")
4369
4370 (define_insn ""
4371 [(set (match_operand:DF 0 "register_operand" "=f")
4372 (sqrt:DF (float_extend:DF
4373 (match_operand:SF 1 "register_operand" "0"))))]
4374 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
4375 "fsqrt")
4376
4377 (define_insn "sqrtxf2"
4378 [(set (match_operand:XF 0 "register_operand" "=f")
4379 (sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
4380 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
4381 && (TARGET_IEEE_FP || flag_fast_math) "
4382 "fsqrt")
4383
4384 (define_insn ""
4385 [(set (match_operand:XF 0 "register_operand" "=f")
4386 (sqrt:XF (float_extend:XF
4387 (match_operand:DF 1 "register_operand" "0"))))]
4388 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
4389 "fsqrt")
4390
4391 (define_insn ""
4392 [(set (match_operand:XF 0 "register_operand" "=f")
4393 (sqrt:XF (float_extend:XF
4394 (match_operand:SF 1 "register_operand" "0"))))]
4395 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
4396 "fsqrt")
4397
4398 (define_insn "sindf2"
4399 [(set (match_operand:DF 0 "register_operand" "=f")
4400 (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
4401 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4402 "fsin")
4403
4404 (define_insn "sinsf2"
4405 [(set (match_operand:SF 0 "register_operand" "=f")
4406 (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
4407 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4408 "fsin")
4409
4410 (define_insn ""
4411 [(set (match_operand:DF 0 "register_operand" "=f")
4412 (unspec:DF [(float_extend:DF
4413 (match_operand:SF 1 "register_operand" "0"))] 1))]
4414 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4415 "fsin")
4416
4417 (define_insn "sinxf2"
4418 [(set (match_operand:XF 0 "register_operand" "=f")
4419 (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
4420 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4421 "fsin")
4422
4423 (define_insn "cosdf2"
4424 [(set (match_operand:DF 0 "register_operand" "=f")
4425 (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
4426 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4427 "fcos")
4428
4429 (define_insn "cossf2"
4430 [(set (match_operand:SF 0 "register_operand" "=f")
4431 (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
4432 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4433 "fcos")
4434
4435 (define_insn ""
4436 [(set (match_operand:DF 0 "register_operand" "=f")
4437 (unspec:DF [(float_extend:DF
4438 (match_operand:SF 1 "register_operand" "0"))] 2))]
4439 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4440 "fcos")
4441
4442 (define_insn "cosxf2"
4443 [(set (match_operand:XF 0 "register_operand" "=f")
4444 (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))]
4445 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
4446 "fcos")
4447 \f
4448 ;;- one complement instructions
4449
4450 (define_insn "one_cmplsi2"
4451 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4452 (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
4453 ""
4454 "not%L0 %0")
4455
4456 (define_insn "one_cmplhi2"
4457 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4458 (not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
4459 ""
4460 "not%W0 %0")
4461
4462 (define_insn "one_cmplqi2"
4463 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4464 (not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
4465 ""
4466 "not%B0 %0")
4467 \f
4468 ;;- arithmetic shift instructions
4469
4470 ;; DImode shifts are implemented using the i386 "shift double" opcode,
4471 ;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count
4472 ;; is variable, then the count is in %cl and the "imm" operand is dropped
4473 ;; from the assembler input.
4474
4475 ;; This instruction shifts the target reg/mem as usual, but instead of
4476 ;; shifting in zeros, bits are shifted in from reg operand. If the insn
4477 ;; is a left shift double, bits are taken from the high order bits of
4478 ;; reg, else if the insn is a shift right double, bits are taken from the
4479 ;; low order bits of reg. So if %eax is "1234" and %edx is "5678",
4480 ;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
4481
4482 ;; Since sh[lr]d does not change the `reg' operand, that is done
4483 ;; separately, making all shifts emit pairs of shift double and normal
4484 ;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to
4485 ;; support a 63 bit shift, each shift where the count is in a reg expands
4486 ;; to a pair of shifts, a branch, a shift by 32 and a label.
4487
4488 ;; If the shift count is a constant, we need never emit more than one
4489 ;; shift pair, instead using moves and sign extension for counts greater
4490 ;; than 31.
4491
4492 (define_expand "ashldi3"
4493 [(set (match_operand:DI 0 "register_operand" "")
4494 (ashift:DI (match_operand:DI 1 "register_operand" "")
4495 (match_operand:QI 2 "nonmemory_operand" "")))]
4496 ""
4497 "
4498 {
4499 if (GET_CODE (operands[2]) != CONST_INT
4500 || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
4501 {
4502 operands[2] = copy_to_mode_reg (QImode, operands[2]);
4503 emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1],
4504 operands[2]));
4505 }
4506 else
4507 emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2]));
4508
4509 DONE;
4510 }")
4511
4512 (define_insn "ashldi3_const_int"
4513 [(set (match_operand:DI 0 "register_operand" "=&r")
4514 (ashift:DI (match_operand:DI 1 "register_operand" "0")
4515 (match_operand:QI 2 "const_int_operand" "J")))]
4516 "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')"
4517 "*
4518 {
4519 rtx xops[4], low[1], high[1];
4520
4521 CC_STATUS_INIT;
4522
4523 split_di (operands, 1, low, high);
4524 xops[0] = operands[2];
4525 xops[1] = const1_rtx;
4526 xops[2] = low[0];
4527 xops[3] = high[0];
4528
4529 if (INTVAL (xops[0]) > 31)
4530 {
4531 output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */
4532 output_asm_insn (AS2 (xor%L2,%2,%2), xops);
4533
4534 if (INTVAL (xops[0]) > 32)
4535 {
4536 xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
4537 output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */
4538 }
4539 }
4540 else
4541 {
4542 output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops);
4543 output_asm_insn (AS2 (sal%L2,%0,%2), xops);
4544 }
4545 RET;
4546 }")
4547
4548 (define_insn "ashldi3_non_const_int"
4549 [(set (match_operand:DI 0 "register_operand" "=&r")
4550 (ashift:DI (match_operand:DI 1 "register_operand" "0")
4551 (match_operand:QI 2 "register_operand" "c")))]
4552 ""
4553 "*
4554 {
4555 rtx xops[4], low[1], high[1];
4556 static HOST_WIDE_INT ashldi_label_number;
4557
4558 CC_STATUS_INIT;
4559
4560 split_di (operands, 1, low, high);
4561 xops[0] = operands[2];
4562 xops[1] = GEN_INT (32);
4563 xops[2] = low[0];
4564 xops[3] = high[0];
4565
4566 output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
4567 output_asm_insn (AS2 (sal%L2,%0,%2), xops);
4568 output_asm_insn (AS2 (test%B0,%1,%b0), xops);
4569 asm_fprintf (asm_out_file, \"\\tje %LLASHLDI%d\\n\", ashldi_label_number);
4570 output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */
4571 output_asm_insn (AS2 (xor%L2,%2,%2), xops);
4572 asm_fprintf (asm_out_file, \"%LLASHLDI%d:\\n\", ashldi_label_number++);
4573
4574 RET;
4575 }")
4576
4577 ;; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg"
4578 ;; On i486, movl/sall appears slightly faster than leal, but the leal
4579 ;; is smaller - use leal for now unless the shift count is 1.
4580
4581 (define_insn "ashlsi3"
4582 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
4583 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,0")
4584 (match_operand:SI 2 "nonmemory_operand" "M,cI")))]
4585 ""
4586 "*
4587 {
4588 if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
4589 {
4590 if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1)
4591 {
4592 output_asm_insn (AS2 (mov%L0,%1,%0), operands);
4593 return AS2 (add%L0,%1,%0);
4594 }
4595 else
4596 {
4597 CC_STATUS_INIT;
4598
4599 if (operands[1] == stack_pointer_rtx)
4600 {
4601 output_asm_insn (AS2 (mov%L0,%1,%0), operands);
4602 operands[1] = operands[0];
4603 }
4604 operands[1] = gen_rtx_MULT (SImode, operands[1],
4605 GEN_INT (1 << INTVAL (operands[2])));
4606 return AS2 (lea%L0,%a1,%0);
4607 }
4608 }
4609
4610 if (REG_P (operands[2]))
4611 return AS2 (sal%L0,%b2,%0);
4612
4613 if (REG_P (operands[0]) && operands[2] == const1_rtx)
4614 return AS2 (add%L0,%0,%0);
4615
4616 return AS2 (sal%L0,%2,%0);
4617 }")
4618
4619 (define_insn "ashlhi3"
4620 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4621 (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
4622 (match_operand:HI 2 "nonmemory_operand" "cI")))]
4623 ""
4624 "*
4625 {
4626 if (REG_P (operands[2]))
4627 return AS2 (sal%W0,%b2,%0);
4628
4629 if (REG_P (operands[0]) && operands[2] == const1_rtx)
4630 return AS2 (add%W0,%0,%0);
4631
4632 return AS2 (sal%W0,%2,%0);
4633 }")
4634
4635 (define_insn "ashlqi3"
4636 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4637 (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
4638 (match_operand:QI 2 "nonmemory_operand" "cI")))]
4639 ""
4640 "*
4641 {
4642 if (REG_P (operands[2]))
4643 return AS2 (sal%B0,%b2,%0);
4644
4645 if (REG_P (operands[0]) && operands[2] == const1_rtx)
4646 return AS2 (add%B0,%0,%0);
4647
4648 return AS2 (sal%B0,%2,%0);
4649 }")
4650
4651 ;; See comment above `ashldi3' about how this works.
4652
4653 (define_expand "ashrdi3"
4654 [(set (match_operand:DI 0 "register_operand" "")
4655 (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
4656 (match_operand:QI 2 "nonmemory_operand" "")))]
4657 ""
4658 "
4659 {
4660 if (GET_CODE (operands[2]) != CONST_INT
4661 || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
4662 {
4663 operands[2] = copy_to_mode_reg (QImode, operands[2]);
4664 emit_insn (gen_ashrdi3_non_const_int (operands[0], operands[1],
4665 operands[2]));
4666 }
4667 else
4668 emit_insn (gen_ashrdi3_const_int (operands[0], operands[1], operands[2]));
4669
4670 DONE;
4671 }")
4672
4673 (define_insn "ashldi3_32"
4674 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m")
4675 (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r")
4676 (const_int 32)))]
4677 ""
4678 "*
4679 {
4680 rtx low[2], high[2], xops[4];
4681
4682 split_di (operands, 2, low, high);
4683 xops[0] = high[0];
4684 xops[1] = low[1];
4685 xops[2] = low[0];
4686 xops[3] = const0_rtx;
4687 if (!rtx_equal_p (xops[0], xops[1]))
4688 output_asm_insn (AS2 (mov%L0,%1,%0), xops);
4689
4690 if (GET_CODE (low[0]) == MEM)
4691 output_asm_insn (AS2 (mov%L2,%3,%2), xops);
4692 else
4693 output_asm_insn (AS2 (xor%L2,%2,%2), xops);
4694
4695 RET;
4696 }")
4697
4698 (define_insn "ashrdi3_const_int"
4699 [(set (match_operand:DI 0 "register_operand" "=&r")
4700 (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
4701 (match_operand:QI 2 "const_int_operand" "J")))]
4702 "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')"
4703 "*
4704 {
4705 rtx xops[4], low[1], high[1];
4706
4707 CC_STATUS_INIT;
4708
4709 split_di (operands, 1, low, high);
4710 xops[0] = operands[2];
4711 xops[1] = const1_rtx;
4712 xops[2] = low[0];
4713 xops[3] = high[0];
4714
4715 if (INTVAL (xops[0]) > 31)
4716 {
4717 xops[1] = GEN_INT (31);
4718 output_asm_insn (AS2 (mov%L2,%3,%2), xops);
4719 output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */
4720
4721 if (INTVAL (xops[0]) > 32)
4722 {
4723 xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
4724 output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */
4725 }
4726 }
4727 else
4728 {
4729 output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
4730 output_asm_insn (AS2 (sar%L3,%0,%3), xops);
4731 }
4732
4733 RET;
4734 }")
4735
4736 (define_insn "ashrdi3_non_const_int"
4737 [(set (match_operand:DI 0 "register_operand" "=&r")
4738 (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
4739 (match_operand:QI 2 "register_operand" "c")))]
4740 ""
4741 "*
4742 {
4743 rtx xops[4], low[1], high[1];
4744 static HOST_WIDE_INT ashrdi_label_number;
4745
4746 CC_STATUS_INIT;
4747
4748 split_di (operands, 1, low, high);
4749 xops[0] = operands[2];
4750 xops[1] = GEN_INT (32);
4751 xops[2] = low[0];
4752 xops[3] = high[0];
4753
4754 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
4755 output_asm_insn (AS2 (sar%L3,%0,%3), xops);
4756 output_asm_insn (AS2 (test%B0,%1,%b0), xops);
4757 asm_fprintf (asm_out_file, \"\\tje %LLASHRDI%d\\n\", ashrdi_label_number);
4758 xops[1] = GEN_INT (31);
4759 output_asm_insn (AS2 (mov%L2,%3,%2), xops);
4760 output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */
4761 asm_fprintf (asm_out_file, \"%LLASHRDI%d:\\n\", ashrdi_label_number++);
4762
4763 RET;
4764 }")
4765
4766 (define_insn "ashrsi3"
4767 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4768 (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
4769 (match_operand:SI 2 "nonmemory_operand" "cI")))]
4770 ""
4771 "*
4772 {
4773 if (REG_P (operands[2]))
4774 return AS2 (sar%L0,%b2,%0);
4775 else
4776 return AS2 (sar%L0,%2,%0);
4777 }")
4778
4779 (define_insn "ashrhi3"
4780 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4781 (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
4782 (match_operand:HI 2 "nonmemory_operand" "cI")))]
4783 ""
4784 "*
4785 {
4786 if (REG_P (operands[2]))
4787 return AS2 (sar%W0,%b2,%0);
4788 else
4789 return AS2 (sar%W0,%2,%0);
4790 }")
4791
4792 (define_insn "ashrqi3"
4793 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4794 (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
4795 (match_operand:QI 2 "nonmemory_operand" "cI")))]
4796 ""
4797 "*
4798 {
4799 if (REG_P (operands[2]))
4800 return AS2 (sar%B0,%b2,%0);
4801 else
4802 return AS2 (sar%B0,%2,%0);
4803 }")
4804 \f
4805 ;;- logical shift instructions
4806
4807 ;; See comment above `ashldi3' about how this works.
4808
4809 (define_expand "lshrdi3"
4810 [(set (match_operand:DI 0 "register_operand" "")
4811 (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
4812 (match_operand:QI 2 "nonmemory_operand" "")))]
4813 ""
4814 "
4815 {
4816 if (GET_CODE (operands[2]) != CONST_INT
4817 || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
4818 {
4819 operands[2] = copy_to_mode_reg (QImode, operands[2]);
4820 emit_insn (gen_lshrdi3_non_const_int (operands[0], operands[1],
4821 operands[2]));
4822 }
4823 else
4824 emit_insn (gen_lshrdi3_const_int (operands[0], operands[1], operands[2]));
4825
4826 DONE;
4827 }")
4828
4829 (define_insn "lshrdi3_32"
4830 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m")
4831 (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r")
4832 (const_int 32)))]
4833 ""
4834 "*
4835 {
4836 rtx low[2], high[2], xops[4];
4837
4838 split_di (operands, 2, low, high);
4839 xops[0] = low[0];
4840 xops[1] = high[1];
4841 xops[2] = high[0];
4842 xops[3] = const0_rtx;
4843 if (!rtx_equal_p (xops[0], xops[1]))
4844 output_asm_insn (AS2 (mov%L0,%1,%0), xops);
4845
4846 if (GET_CODE (low[0]) == MEM)
4847 output_asm_insn (AS2 (mov%L2,%3,%2), xops);
4848 else
4849 output_asm_insn (AS2 (xor%L2,%2,%2), xops);
4850
4851 RET;
4852 }")
4853
4854 (define_insn "lshrdi3_const_int"
4855 [(set (match_operand:DI 0 "register_operand" "=&r")
4856 (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
4857 (match_operand:QI 2 "const_int_operand" "J")))]
4858 "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')"
4859 "*
4860 {
4861 rtx xops[4], low[1], high[1];
4862
4863 CC_STATUS_INIT;
4864
4865 split_di (operands, 1, low, high);
4866 xops[0] = operands[2];
4867 xops[1] = const1_rtx;
4868 xops[2] = low[0];
4869 xops[3] = high[0];
4870
4871 if (INTVAL (xops[0]) > 31)
4872 {
4873 output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */
4874 output_asm_insn (AS2 (xor%L3,%3,%3), xops);
4875
4876 if (INTVAL (xops[0]) > 32)
4877 {
4878 xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
4879 output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */
4880 }
4881 }
4882 else
4883 {
4884 output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
4885 output_asm_insn (AS2 (shr%L3,%0,%3), xops);
4886 }
4887
4888 RET;
4889 }")
4890
4891 (define_insn "lshrdi3_non_const_int"
4892 [(set (match_operand:DI 0 "register_operand" "=&r")
4893 (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
4894 (match_operand:QI 2 "register_operand" "c")))]
4895 ""
4896 "*
4897 {
4898 rtx xops[4], low[1], high[1];
4899 static HOST_WIDE_INT lshrdi_label_number;
4900
4901 CC_STATUS_INIT;
4902
4903 split_di (operands, 1, low, high);
4904 xops[0] = operands[2];
4905 xops[1] = GEN_INT (32);
4906 xops[2] = low[0];
4907 xops[3] = high[0];
4908
4909 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
4910 output_asm_insn (AS2 (shr%L3,%0,%3), xops);
4911 output_asm_insn (AS2 (test%B0,%1,%b0), xops);
4912 asm_fprintf (asm_out_file, \"\\tje %LLLSHRDI%d\\n\", lshrdi_label_number);
4913 output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */
4914 output_asm_insn (AS2 (xor%L3,%3,%3), xops);
4915 asm_fprintf (asm_out_file, \"%LLLSHRDI%d:\\n\", lshrdi_label_number++);
4916
4917 RET;
4918 }")
4919
4920 (define_insn "lshrsi3"
4921 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4922 (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
4923 (match_operand:SI 2 "nonmemory_operand" "cI")))]
4924 ""
4925 "*
4926 {
4927 if (REG_P (operands[2]))
4928 return AS2 (shr%L0,%b2,%0);
4929 else
4930 return AS2 (shr%L0,%2,%1);
4931 }")
4932
4933 (define_insn "lshrhi3"
4934 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4935 (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
4936 (match_operand:HI 2 "nonmemory_operand" "cI")))]
4937 ""
4938 "*
4939 {
4940 if (REG_P (operands[2]))
4941 return AS2 (shr%W0,%b2,%0);
4942 else
4943 return AS2 (shr%W0,%2,%0);
4944 }")
4945
4946 (define_insn "lshrqi3"
4947 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4948 (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
4949 (match_operand:QI 2 "nonmemory_operand" "cI")))]
4950 ""
4951 "*
4952 {
4953 if (REG_P (operands[2]))
4954 return AS2 (shr%B0,%b2,%0);
4955 else
4956 return AS2 (shr%B0,%2,%0);
4957 }")
4958 \f
4959 ;;- rotate instructions
4960
4961 (define_insn "rotlsi3"
4962 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
4963 (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0")
4964 (match_operand:SI 2 "nonmemory_operand" "cI")))]
4965 ""
4966 "*
4967 {
4968 if (REG_P (operands[2]))
4969 return AS2 (rol%L0,%b2,%0);
4970 else
4971 return AS2 (rol%L0,%2,%0);
4972 }")
4973
4974 (define_insn "rotlhi3"
4975 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
4976 (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0")
4977 (match_operand:HI 2 "nonmemory_operand" "cI")))]
4978 ""
4979 "*
4980 {
4981 if (REG_P (operands[2]))
4982 return AS2 (rol%W0,%b2,%0);
4983 else
4984 return AS2 (rol%W0,%2,%0);
4985 }")
4986
4987 (define_insn "rotlqi3"
4988 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
4989 (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
4990 (match_operand:QI 2 "nonmemory_operand" "cI")))]
4991 ""
4992 "*
4993 {
4994 if (REG_P (operands[2]))
4995 return AS2 (rol%B0,%b2,%0);
4996 else
4997 return AS2 (rol%B0,%2,%0);
4998 }")
4999
5000 (define_insn "rotrsi3"
5001 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
5002 (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5003 (match_operand:SI 2 "nonmemory_operand" "cI")))]
5004 ""
5005 "*
5006 {
5007 if (REG_P (operands[2]))
5008 return AS2 (ror%L0,%b2,%0);
5009 else
5010 return AS2 (ror%L0,%2,%0);
5011 }")
5012
5013 (define_insn "rotrhi3"
5014 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
5015 (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0")
5016 (match_operand:HI 2 "nonmemory_operand" "cI")))]
5017 ""
5018 "*
5019 {
5020 if (REG_P (operands[2]))
5021 return AS2 (ror%W0,%b2,%0);
5022 else
5023 return AS2 (ror%W0,%2,%0);
5024 }")
5025
5026 (define_insn "rotrqi3"
5027 [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
5028 (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0")
5029 (match_operand:QI 2 "nonmemory_operand" "cI")))]
5030 ""
5031 "*
5032 {
5033 if (REG_P (operands[2]))
5034 return AS2 (ror%B0,%b2,%0);
5035 else
5036 return AS2 (ror%B0,%2,%0);
5037 }")
5038 \f
5039 /*
5040 ;; This usually looses. But try a define_expand to recognize a few case
5041 ;; we can do efficiently, such as accessing the "high" QImode registers,
5042 ;; %ah, %bh, %ch, %dh.
5043 ;; ??? Note this has a botch on the mode of operand 0, which needs to be
5044 ;; fixed if this is ever enabled.
5045 (define_insn "insv"
5046 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r")
5047 (match_operand:SI 1 "immediate_operand" "i")
5048 (match_operand:SI 2 "immediate_operand" "i"))
5049 (match_operand:SI 3 "nonmemory_operand" "ri"))]
5050 ""
5051 "*
5052 {
5053 if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode))
5054 abort ();
5055 if (GET_CODE (operands[3]) == CONST_INT)
5056 {
5057 unsigned int mask = (1 << INTVAL (operands[1])) - 1;
5058 operands[1] = GEN_INT (~(mask << INTVAL (operands[2])));
5059 output_asm_insn (AS2 (and%L0,%1,%0), operands);
5060 operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2]));
5061 output_asm_insn (AS2 (or%L0,%3,%0), operands);
5062 }
5063 else
5064 {
5065 operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
5066 if (INTVAL (operands[2]))
5067 output_asm_insn (AS2 (ror%L0,%2,%0), operands);
5068 output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands);
5069 operands[2] = GEN_INT (BITS_PER_WORD
5070 - INTVAL (operands[1]) - INTVAL (operands[2]));
5071 if (INTVAL (operands[2]))
5072 output_asm_insn (AS2 (ror%L0,%2,%0), operands);
5073 }
5074 RET;
5075 }")
5076 */
5077 /*
5078 ;; ??? There are problems with the mode of operand[3]. The point of this
5079 ;; is to represent an HImode move to a "high byte" register.
5080
5081 (define_expand "insv"
5082 [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
5083 (match_operand:SI 1 "immediate_operand" "")
5084 (match_operand:SI 2 "immediate_operand" ""))
5085 (match_operand:QI 3 "nonmemory_operand" "ri"))]
5086 ""
5087 "
5088 {
5089 if (GET_CODE (operands[1]) != CONST_INT
5090 || GET_CODE (operands[2]) != CONST_INT)
5091 FAIL;
5092
5093 if (! (INTVAL (operands[1]) == 8
5094 && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0))
5095 && ! INTVAL (operands[1]) == 1)
5096 FAIL;
5097 }")
5098 */
5099
5100 ;; On i386, the register count for a bit operation is *not* truncated,
5101 ;; so SHIFT_COUNT_TRUNCATED must not be defined.
5102
5103 ;; On i486, the shift & or/and code is faster than bts or btr. If
5104 ;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code.
5105
5106 ;; On i386, bts is a little faster if operands[0] is a reg, and a
5107 ;; little slower if operands[0] is a MEM, than the shift & or/and code.
5108 ;; Use bts & btr, since they reload better.
5109
5110 ;; General bit set and clear.
5111 (define_insn ""
5112 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+rm")
5113 (const_int 1)
5114 (match_operand:SI 2 "register_operand" "r"))
5115 (match_operand:SI 3 "const_int_operand" "n"))]
5116 "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT"
5117 "*
5118 {
5119 CC_STATUS_INIT;
5120
5121 if (INTVAL (operands[3]) == 1)
5122 return AS2 (bts%L0,%2,%0);
5123 else
5124 return AS2 (btr%L0,%2,%0);
5125 }")
5126
5127 ;; Bit complement. See comments on previous pattern.
5128 ;; ??? Is this really worthwhile?
5129 (define_insn ""
5130 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
5131 (xor:SI (ashift:SI (const_int 1)
5132 (match_operand:SI 1 "register_operand" "r"))
5133 (match_operand:SI 2 "nonimmediate_operand" "0")))]
5134 "TARGET_USE_BIT_TEST && GET_CODE (operands[1]) != CONST_INT"
5135 "*
5136 {
5137 CC_STATUS_INIT;
5138
5139 return AS2 (btc%L0,%1,%0);
5140 }")
5141
5142 (define_insn ""
5143 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
5144 (xor:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5145 (ashift:SI (const_int 1)
5146 (match_operand:SI 2 "register_operand" "r"))))]
5147 "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT"
5148 "*
5149 {
5150 CC_STATUS_INIT;
5151
5152 return AS2 (btc%L0,%2,%0);
5153 }")
5154 \f
5155 ;; Recognizers for bit-test instructions.
5156
5157 ;; The bt opcode allows a MEM in operands[0]. But on both i386 and
5158 ;; i486, it is faster to copy a MEM to REG and then use bt, than to use
5159 ;; bt on the MEM directly.
5160
5161 ;; ??? The first argument of a zero_extract must not be reloaded, so
5162 ;; don't allow a MEM in the operand predicate without allowing it in the
5163 ;; constraint.
5164
5165 (define_insn ""
5166 [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
5167 (const_int 1)
5168 (match_operand:SI 1 "register_operand" "r")))]
5169 "GET_CODE (operands[1]) != CONST_INT"
5170 "*
5171 {
5172 cc_status.flags |= CC_Z_IN_NOT_C;
5173 return AS2 (bt%L0,%1,%0);
5174 }")
5175
5176 (define_insn ""
5177 [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
5178 (match_operand:SI 1 "const_int_operand" "n")
5179 (match_operand:SI 2 "const_int_operand" "n")))]
5180 ""
5181 "*
5182 {
5183 unsigned int mask;
5184
5185 mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
5186 operands[1] = GEN_INT (mask);
5187
5188 if (QI_REG_P (operands[0]))
5189 {
5190 if ((mask & ~0xff) == 0)
5191 {
5192 cc_status.flags |= CC_NOT_NEGATIVE;
5193 return AS2 (test%B0,%1,%b0);
5194 }
5195
5196 if ((mask & ~0xff00) == 0)
5197 {
5198 cc_status.flags |= CC_NOT_NEGATIVE;
5199 operands[1] = GEN_INT (mask >> 8);
5200 return AS2 (test%B0,%1,%h0);
5201 }
5202 }
5203
5204 return AS2 (test%L0,%1,%0);
5205 }")
5206
5207 ;; ??? All bets are off if operand 0 is a volatile MEM reference.
5208 ;; The CPU may access unspecified bytes around the actual target byte.
5209
5210 (define_insn ""
5211 [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
5212 (match_operand:SI 1 "const_int_operand" "n")
5213 (match_operand:SI 2 "const_int_operand" "n")))]
5214 "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])"
5215 "*
5216 {
5217 unsigned int mask;
5218
5219 mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
5220 operands[1] = GEN_INT (mask);
5221
5222 if (! REG_P (operands[0]) || QI_REG_P (operands[0]))
5223 {
5224 if ((mask & ~0xff) == 0)
5225 {
5226 cc_status.flags |= CC_NOT_NEGATIVE;
5227 return AS2 (test%B0,%1,%b0);
5228 }
5229
5230 if ((mask & ~0xff00) == 0)
5231 {
5232 cc_status.flags |= CC_NOT_NEGATIVE;
5233 operands[1] = GEN_INT (mask >> 8);
5234
5235 if (QI_REG_P (operands[0]))
5236 return AS2 (test%B0,%1,%h0);
5237 else
5238 {
5239 operands[0] = adj_offsettable_operand (operands[0], 1);
5240 return AS2 (test%B0,%1,%b0);
5241 }
5242 }
5243
5244 if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0)
5245 {
5246 cc_status.flags |= CC_NOT_NEGATIVE;
5247 operands[1] = GEN_INT (mask >> 16);
5248 operands[0] = adj_offsettable_operand (operands[0], 2);
5249 return AS2 (test%B0,%1,%b0);
5250 }
5251
5252 if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0)
5253 {
5254 cc_status.flags |= CC_NOT_NEGATIVE;
5255 operands[1] = GEN_INT (mask >> 24);
5256 operands[0] = adj_offsettable_operand (operands[0], 3);
5257 return AS2 (test%B0,%1,%b0);
5258 }
5259 }
5260
5261 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
5262 return AS2 (test%L0,%1,%0);
5263
5264 return AS2 (test%L1,%0,%1);
5265 }")
5266 \f
5267 ;; Store-flag instructions.
5268
5269 ;; For all sCOND expanders, also expand the compare or test insn that
5270 ;; generates cc0. Generate an equality comparison if `seq' or `sne'.
5271
5272 ;; The 386 sCOND opcodes can write to memory. But a gcc sCOND insn may
5273 ;; not have any input reloads. A MEM write might need an input reload
5274 ;; for the address of the MEM. So don't allow MEM as the SET_DEST.
5275
5276 (define_expand "seq"
5277 [(match_dup 1)
5278 (set (match_operand:QI 0 "register_operand" "")
5279 (eq:QI (cc0) (const_int 0)))]
5280 ""
5281 "
5282 {
5283 if (TARGET_IEEE_FP
5284 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
5285 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
5286 else
5287 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
5288 }")
5289
5290 (define_insn ""
5291 [(set (match_operand:QI 0 "register_operand" "=q")
5292 (eq:QI (cc0) (const_int 0)))]
5293 ""
5294 "*
5295 {
5296 if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5297 return AS1 (setnb,%0);
5298 else
5299 return AS1 (sete,%0);
5300 }")
5301
5302 (define_expand "sne"
5303 [(match_dup 1)
5304 (set (match_operand:QI 0 "register_operand" "")
5305 (ne:QI (cc0) (const_int 0)))]
5306 ""
5307 "
5308 {
5309 if (TARGET_IEEE_FP
5310 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
5311 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
5312 else
5313 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
5314 }")
5315
5316 (define_insn ""
5317 [(set (match_operand:QI 0 "register_operand" "=q")
5318 (ne:QI (cc0) (const_int 0)))]
5319 ""
5320 "*
5321 {
5322 if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5323 return AS1 (setb,%0);
5324 else
5325 return AS1 (setne,%0);
5326 }
5327 ")
5328
5329 (define_expand "sgt"
5330 [(match_dup 1)
5331 (set (match_operand:QI 0 "register_operand" "")
5332 (gt:QI (cc0) (const_int 0)))]
5333 ""
5334 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5335
5336 (define_insn ""
5337 [(set (match_operand:QI 0 "register_operand" "=q")
5338 (gt:QI (cc0) (const_int 0)))]
5339 ""
5340 "*
5341 {
5342 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5343 && ! (cc_prev_status.flags & CC_FCOMI))
5344 return AS1 (sete,%0);
5345
5346 OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR);
5347 }")
5348
5349 (define_expand "sgtu"
5350 [(match_dup 1)
5351 (set (match_operand:QI 0 "register_operand" "")
5352 (gtu:QI (cc0) (const_int 0)))]
5353 ""
5354 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5355
5356 (define_insn ""
5357 [(set (match_operand:QI 0 "register_operand" "=q")
5358 (gtu:QI (cc0) (const_int 0)))]
5359 ""
5360 "* return \"seta %0\"; ")
5361
5362 (define_expand "slt"
5363 [(match_dup 1)
5364 (set (match_operand:QI 0 "register_operand" "")
5365 (lt:QI (cc0) (const_int 0)))]
5366 ""
5367 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5368
5369 (define_insn ""
5370 [(set (match_operand:QI 0 "register_operand" "=q")
5371 (lt:QI (cc0) (const_int 0)))]
5372 ""
5373 "*
5374 {
5375 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5376 && ! (cc_prev_status.flags & CC_FCOMI))
5377 return AS1 (sete,%0);
5378
5379 OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\");
5380 }")
5381
5382 (define_expand "sltu"
5383 [(match_dup 1)
5384 (set (match_operand:QI 0 "register_operand" "")
5385 (ltu:QI (cc0) (const_int 0)))]
5386 ""
5387 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5388
5389 (define_insn ""
5390 [(set (match_operand:QI 0 "register_operand" "=q")
5391 (ltu:QI (cc0) (const_int 0)))]
5392 ""
5393 "* return \"setb %0\"; ")
5394
5395 (define_expand "sge"
5396 [(match_dup 1)
5397 (set (match_operand:QI 0 "register_operand" "")
5398 (ge:QI (cc0) (const_int 0)))]
5399 ""
5400 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5401
5402 (define_insn ""
5403 [(set (match_operand:QI 0 "register_operand" "=q")
5404 (ge:QI (cc0) (const_int 0)))]
5405 ""
5406 "*
5407 {
5408 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5409 && ! (cc_prev_status.flags & CC_FCOMI))
5410 return AS1 (sete,%0);
5411
5412 OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\");
5413 }")
5414
5415 (define_expand "sgeu"
5416 [(match_dup 1)
5417 (set (match_operand:QI 0 "register_operand" "")
5418 (geu:QI (cc0) (const_int 0)))]
5419 ""
5420 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5421
5422 (define_insn ""
5423 [(set (match_operand:QI 0 "register_operand" "=q")
5424 (geu:QI (cc0) (const_int 0)))]
5425 ""
5426 "* return \"setae %0\"; ")
5427
5428 (define_expand "sle"
5429 [(match_dup 1)
5430 (set (match_operand:QI 0 "register_operand" "")
5431 (le:QI (cc0) (const_int 0)))]
5432 ""
5433 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5434
5435 (define_insn ""
5436 [(set (match_operand:QI 0 "register_operand" "=q")
5437 (le:QI (cc0) (const_int 0)))]
5438 ""
5439 "*
5440 {
5441 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5442 && ! (cc_prev_status.flags & CC_FCOMI))
5443 return AS1 (setb,%0);
5444
5445 OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR);
5446 }")
5447
5448 (define_expand "sleu"
5449 [(match_dup 1)
5450 (set (match_operand:QI 0 "register_operand" "")
5451 (leu:QI (cc0) (const_int 0)))]
5452 ""
5453 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5454
5455 (define_insn ""
5456 [(set (match_operand:QI 0 "register_operand" "=q")
5457 (leu:QI (cc0) (const_int 0)))]
5458 ""
5459 "* return \"setbe %0\"; ")
5460 \f
5461 ;; Basic conditional jump instructions.
5462 ;; We ignore the overflow flag for signed branch instructions.
5463
5464 ;; For all bCOND expanders, also expand the compare or test insn that
5465 ;; generates cc0. Generate an equality comparison if `beq' or `bne'.
5466
5467 (define_expand "beq"
5468 [(match_dup 1)
5469 (set (pc)
5470 (if_then_else (eq (cc0)
5471 (const_int 0))
5472 (label_ref (match_operand 0 "" ""))
5473 (pc)))]
5474 ""
5475 "
5476 {
5477 if (TARGET_IEEE_FP
5478 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
5479 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
5480 else
5481 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
5482 }")
5483
5484 (define_insn ""
5485 [(set (pc)
5486 (if_then_else (eq (cc0)
5487 (const_int 0))
5488 (label_ref (match_operand 0 "" ""))
5489 (pc)))]
5490 ""
5491 "*
5492 {
5493 if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5494 return \"jnc %l0\";
5495 else
5496 if (cc_prev_status.flags & CC_TEST_AX)
5497 {
5498 operands[1] = gen_rtx_REG (SImode, 0);
5499 operands[2] = GEN_INT (0x4000);
5500 output_asm_insn (AS2 (testl,%2,%1), operands);
5501 return AS1 (jne,%l0);
5502 }
5503
5504 return \"je %l0\";
5505 }")
5506
5507 (define_expand "bne"
5508 [(match_dup 1)
5509 (set (pc)
5510 (if_then_else (ne (cc0)
5511 (const_int 0))
5512 (label_ref (match_operand 0 "" ""))
5513 (pc)))]
5514 ""
5515 "
5516 {
5517 if (TARGET_IEEE_FP
5518 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
5519 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
5520 else
5521 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
5522 }")
5523
5524 (define_insn ""
5525 [(set (pc)
5526 (if_then_else (ne (cc0)
5527 (const_int 0))
5528 (label_ref (match_operand 0 "" ""))
5529 (pc)))]
5530 ""
5531 "*
5532 {
5533 if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5534 return \"jc %l0\";
5535 else
5536 if (cc_prev_status.flags & CC_TEST_AX)
5537 {
5538 operands[1] = gen_rtx_REG (SImode, 0);
5539 operands[2] = GEN_INT (0x4000);
5540 output_asm_insn (AS2 (testl,%2,%1), operands);
5541 return AS1 (je,%l0);
5542 }
5543
5544 return \"jne %l0\";
5545 }")
5546
5547 (define_expand "bgt"
5548 [(match_dup 1)
5549 (set (pc)
5550 (if_then_else (gt (cc0)
5551 (const_int 0))
5552 (label_ref (match_operand 0 "" ""))
5553 (pc)))]
5554 ""
5555 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5556
5557 (define_insn ""
5558 [(set (pc)
5559 (if_then_else (gt (cc0)
5560 (const_int 0))
5561 (label_ref (match_operand 0 "" ""))
5562 (pc)))]
5563 ""
5564 "*
5565 {
5566 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5567 && ! (cc_prev_status.flags & CC_FCOMI))
5568 return AS1 (je,%l0);
5569
5570 if (cc_prev_status.flags & CC_TEST_AX)
5571 {
5572 operands[1] = gen_rtx_REG (SImode, 0);
5573 operands[2] = GEN_INT (0x4100);
5574 output_asm_insn (AS2 (testl,%2,%1), operands);
5575 return AS1 (je,%l0);
5576 }
5577 OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
5578 }")
5579
5580 (define_expand "bgtu"
5581 [(match_dup 1)
5582 (set (pc)
5583 (if_then_else (gtu (cc0)
5584 (const_int 0))
5585 (label_ref (match_operand 0 "" ""))
5586 (pc)))]
5587 ""
5588 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5589
5590 (define_insn ""
5591 [(set (pc)
5592 (if_then_else (gtu (cc0)
5593 (const_int 0))
5594 (label_ref (match_operand 0 "" ""))
5595 (pc)))]
5596 ""
5597 "ja %l0")
5598
5599 (define_expand "blt"
5600 [(match_dup 1)
5601 (set (pc)
5602 (if_then_else (lt (cc0)
5603 (const_int 0))
5604 (label_ref (match_operand 0 "" ""))
5605 (pc)))]
5606 ""
5607 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5608
5609 (define_insn ""
5610 [(set (pc)
5611 (if_then_else (lt (cc0)
5612 (const_int 0))
5613 (label_ref (match_operand 0 "" ""))
5614 (pc)))]
5615 ""
5616 "*
5617 {
5618 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5619 && ! (cc_prev_status.flags & CC_FCOMI))
5620 return AS1 (je,%l0);
5621
5622 if (cc_prev_status.flags & CC_TEST_AX)
5623 {
5624 operands[1] = gen_rtx_REG (SImode, 0);
5625 operands[2] = GEN_INT (0x100);
5626 output_asm_insn (AS2 (testl,%2,%1), operands);
5627 return AS1 (jne,%l0);
5628 }
5629 OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
5630 }")
5631
5632 (define_expand "bltu"
5633 [(match_dup 1)
5634 (set (pc)
5635 (if_then_else (ltu (cc0)
5636 (const_int 0))
5637 (label_ref (match_operand 0 "" ""))
5638 (pc)))]
5639 ""
5640 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5641
5642 (define_insn ""
5643 [(set (pc)
5644 (if_then_else (ltu (cc0)
5645 (const_int 0))
5646 (label_ref (match_operand 0 "" ""))
5647 (pc)))]
5648 ""
5649 "jb %l0")
5650
5651 (define_expand "bge"
5652 [(match_dup 1)
5653 (set (pc)
5654 (if_then_else (ge (cc0)
5655 (const_int 0))
5656 (label_ref (match_operand 0 "" ""))
5657 (pc)))]
5658 ""
5659 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5660
5661 (define_insn ""
5662 [(set (pc)
5663 (if_then_else (ge (cc0)
5664 (const_int 0))
5665 (label_ref (match_operand 0 "" ""))
5666 (pc)))]
5667 ""
5668 "*
5669 {
5670 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5671 && ! (cc_prev_status.flags & CC_FCOMI))
5672 return AS1 (je,%l0);
5673 if (cc_prev_status.flags & CC_TEST_AX)
5674 {
5675 operands[1] = gen_rtx_REG (SImode, 0);
5676 operands[2] = GEN_INT (0x100);
5677 output_asm_insn (AS2 (testl,%2,%1), operands);
5678 return AS1 (je,%l0);
5679 }
5680 OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
5681 }")
5682
5683 (define_expand "bgeu"
5684 [(match_dup 1)
5685 (set (pc)
5686 (if_then_else (geu (cc0)
5687 (const_int 0))
5688 (label_ref (match_operand 0 "" ""))
5689 (pc)))]
5690 ""
5691 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5692
5693 (define_insn ""
5694 [(set (pc)
5695 (if_then_else (geu (cc0)
5696 (const_int 0))
5697 (label_ref (match_operand 0 "" ""))
5698 (pc)))]
5699 ""
5700 "jae %l0")
5701
5702 (define_expand "ble"
5703 [(match_dup 1)
5704 (set (pc)
5705 (if_then_else (le (cc0)
5706 (const_int 0))
5707 (label_ref (match_operand 0 "" ""))
5708 (pc)))]
5709 ""
5710 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5711
5712 (define_insn ""
5713 [(set (pc)
5714 (if_then_else (le (cc0)
5715 (const_int 0))
5716 (label_ref (match_operand 0 "" ""))
5717 (pc)))]
5718 ""
5719 "*
5720 {
5721 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5722 && ! (cc_prev_status.flags & CC_FCOMI))
5723 return AS1 (jb,%l0);
5724 if (cc_prev_status.flags & CC_TEST_AX)
5725 {
5726 operands[1] = gen_rtx_REG (SImode, 0);
5727 operands[2] = GEN_INT (0x4100);
5728 output_asm_insn (AS2 (testl,%2,%1), operands);
5729 return AS1 (jne,%l0);
5730 }
5731
5732 OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
5733 }")
5734
5735 (define_expand "bleu"
5736 [(match_dup 1)
5737 (set (pc)
5738 (if_then_else (leu (cc0)
5739 (const_int 0))
5740 (label_ref (match_operand 0 "" ""))
5741 (pc)))]
5742 ""
5743 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
5744
5745 (define_insn ""
5746 [(set (pc)
5747 (if_then_else (leu (cc0)
5748 (const_int 0))
5749 (label_ref (match_operand 0 "" ""))
5750 (pc)))]
5751 ""
5752 "jbe %l0")
5753 \f
5754 ;; Negated conditional jump instructions.
5755
5756 (define_insn ""
5757 [(set (pc)
5758 (if_then_else (eq (cc0)
5759 (const_int 0))
5760 (pc)
5761 (label_ref (match_operand 0 "" ""))))]
5762 ""
5763 "*
5764 {
5765 if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5766 return \"jc %l0\";
5767 else
5768 if (cc_prev_status.flags & CC_TEST_AX)
5769 {
5770 operands[1] = gen_rtx_REG (SImode, 0);
5771 operands[2] = GEN_INT (0x4000);
5772 output_asm_insn (AS2 (testl,%2,%1), operands);
5773 return AS1 (je,%l0);
5774 }
5775 return \"jne %l0\";
5776 }")
5777
5778 (define_insn ""
5779 [(set (pc)
5780 (if_then_else (ne (cc0)
5781 (const_int 0))
5782 (pc)
5783 (label_ref (match_operand 0 "" ""))))]
5784 ""
5785 "*
5786 {
5787 if (cc_prev_status.flags & CC_Z_IN_NOT_C)
5788 return \"jnc %l0\";
5789 else
5790 if (cc_prev_status.flags & CC_TEST_AX)
5791 {
5792 operands[1] = gen_rtx_REG (SImode, 0);
5793 operands[2] = GEN_INT (0x4000);
5794 output_asm_insn (AS2 (testl,%2,%1), operands);
5795 return AS1 (jne,%l0);
5796 }
5797 return \"je %l0\";
5798 }")
5799
5800 (define_insn ""
5801 [(set (pc)
5802 (if_then_else (gt (cc0)
5803 (const_int 0))
5804 (pc)
5805 (label_ref (match_operand 0 "" ""))))]
5806 ""
5807 "*
5808 {
5809 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5810 && ! (cc_prev_status.flags & CC_FCOMI))
5811 return AS1 (jne,%l0);
5812 if (cc_prev_status.flags & CC_TEST_AX)
5813 {
5814 operands[1] = gen_rtx_REG (SImode, 0);
5815 operands[2] = GEN_INT (0x4100);
5816 output_asm_insn (AS2 (testl,%2,%1), operands);
5817 return AS1 (jne,%l0);
5818 }
5819 OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
5820 }")
5821
5822 (define_insn ""
5823 [(set (pc)
5824 (if_then_else (gtu (cc0)
5825 (const_int 0))
5826 (pc)
5827 (label_ref (match_operand 0 "" ""))))]
5828 ""
5829 "jbe %l0")
5830
5831 (define_insn ""
5832 [(set (pc)
5833 (if_then_else (lt (cc0)
5834 (const_int 0))
5835 (pc)
5836 (label_ref (match_operand 0 "" ""))))]
5837 ""
5838 "*
5839 {
5840 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5841 && ! (cc_prev_status.flags & CC_FCOMI))
5842 return AS1 (jne,%l0);
5843 if (cc_prev_status.flags & CC_TEST_AX)
5844 {
5845 operands[1] = gen_rtx_REG (SImode, 0);
5846 operands[2] = GEN_INT (0x100);
5847 output_asm_insn (AS2 (testl,%2,%1), operands);
5848 return AS1 (je,%l0);
5849 }
5850
5851 OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
5852 }")
5853
5854 (define_insn ""
5855 [(set (pc)
5856 (if_then_else (ltu (cc0)
5857 (const_int 0))
5858 (pc)
5859 (label_ref (match_operand 0 "" ""))))]
5860 ""
5861 "jae %l0")
5862
5863 (define_insn ""
5864 [(set (pc)
5865 (if_then_else (ge (cc0)
5866 (const_int 0))
5867 (pc)
5868 (label_ref (match_operand 0 "" ""))))]
5869 ""
5870 "*
5871 {
5872 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5873 && ! (cc_prev_status.flags & CC_FCOMI))
5874 return AS1 (jne,%l0);
5875 if (cc_prev_status.flags & CC_TEST_AX)
5876 {
5877 operands[1] = gen_rtx_REG (SImode, 0);
5878 operands[2] = GEN_INT (0x100);
5879 output_asm_insn (AS2 (testl,%2,%1), operands);
5880 return AS1 (jne,%l0);
5881 }
5882 OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
5883 }")
5884
5885 (define_insn ""
5886 [(set (pc)
5887 (if_then_else (geu (cc0)
5888 (const_int 0))
5889 (pc)
5890 (label_ref (match_operand 0 "" ""))))]
5891 ""
5892 "jb %l0")
5893
5894 (define_insn ""
5895 [(set (pc)
5896 (if_then_else (le (cc0)
5897 (const_int 0))
5898 (pc)
5899 (label_ref (match_operand 0 "" ""))))]
5900 ""
5901 "*
5902 {
5903 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
5904 && ! (cc_prev_status.flags & CC_FCOMI))
5905 return AS1 (jae,%l0);
5906
5907 if (cc_prev_status.flags & CC_TEST_AX)
5908 {
5909 operands[1] = gen_rtx_REG (SImode, 0);
5910 operands[2] = GEN_INT (0x4100);
5911 output_asm_insn (AS2 (testl,%2,%1), operands);
5912 return AS1 (je,%l0);
5913 }
5914 OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
5915 }")
5916
5917 (define_insn ""
5918 [(set (pc)
5919 (if_then_else (leu (cc0)
5920 (const_int 0))
5921 (pc)
5922 (label_ref (match_operand 0 "" ""))))]
5923 ""
5924 "ja %l0")
5925 \f
5926 ;; Unconditional and other jump instructions
5927
5928 (define_insn "jump"
5929 [(set (pc)
5930 (label_ref (match_operand 0 "" "")))]
5931 ""
5932 "jmp %l0")
5933
5934 (define_insn "indirect_jump"
5935 [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
5936 ""
5937 "*
5938 {
5939 CC_STATUS_INIT;
5940
5941 return AS1 (jmp,%*%0);
5942 }")
5943
5944 ;; ??? could transform while(--i > 0) S; to if (--i > 0) do S; while(--i);
5945 ;; if S does not change i
5946
5947 (define_expand "decrement_and_branch_until_zero"
5948 [(parallel [(set (pc)
5949 (if_then_else (ge (plus:SI (match_operand:SI 0 "general_operand" "")
5950 (const_int -1))
5951 (const_int 0))
5952 (label_ref (match_operand 1 "" ""))
5953 (pc)))
5954 (set (match_dup 0)
5955 (plus:SI (match_dup 0)
5956 (const_int -1)))])]
5957 ""
5958 "")
5959
5960 (define_insn ""
5961 [(set (pc)
5962 (if_then_else (match_operator 0 "arithmetic_comparison_operator"
5963 [(plus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m")
5964 (match_operand:SI 2 "general_operand" "rmi,ri"))
5965 (const_int 0)])
5966 (label_ref (match_operand 3 "" ""))
5967 (pc)))
5968 (set (match_dup 1)
5969 (plus:SI (match_dup 1)
5970 (match_dup 2)))]
5971 ""
5972 "*
5973 {
5974 CC_STATUS_INIT;
5975 if (operands[2] == constm1_rtx)
5976 output_asm_insn (AS1 (dec%L1,%1), operands);
5977
5978 else if (operands[2] == const1_rtx)
5979 output_asm_insn (AS1 (inc%L1,%1), operands);
5980
5981 else
5982 output_asm_insn (AS2 (add%L1,%2,%1), operands);
5983
5984 return AS1 (%J0,%l3);
5985 }")
5986
5987 (define_insn ""
5988 [(set (pc)
5989 (if_then_else (match_operator 0 "arithmetic_comparison_operator"
5990 [(minus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m")
5991 (match_operand:SI 2 "general_operand" "rmi,ri"))
5992 (const_int 0)])
5993 (label_ref (match_operand 3 "" ""))
5994 (pc)))
5995 (set (match_dup 1)
5996 (minus:SI (match_dup 1)
5997 (match_dup 2)))]
5998 ""
5999 "*
6000 {
6001 CC_STATUS_INIT;
6002 if (operands[2] == const1_rtx)
6003 output_asm_insn (AS1 (dec%L1,%1), operands);
6004
6005 else if (operands[1] == constm1_rtx)
6006 output_asm_insn (AS1 (inc%L1,%1), operands);
6007
6008 else
6009 output_asm_insn (AS2 (sub%L1,%2,%1), operands);
6010
6011 return AS1 (%J0,%l3);
6012 }")
6013
6014 (define_insn ""
6015 [(set (pc)
6016 (if_then_else (ne (match_operand:SI 0 "general_operand" "+g")
6017 (const_int 0))
6018 (label_ref (match_operand 1 "" ""))
6019 (pc)))
6020 (set (match_dup 0)
6021 (plus:SI (match_dup 0)
6022 (const_int -1)))]
6023 ""
6024 "*
6025 {
6026 CC_STATUS_INIT;
6027 operands[2] = const1_rtx;
6028 output_asm_insn (AS2 (sub%L0,%2,%0), operands);
6029 return \"jnc %l1\";
6030 }")
6031
6032 (define_insn ""
6033 [(set (pc)
6034 (if_then_else (eq (match_operand:SI 0 "general_operand" "+g")
6035 (const_int 0))
6036 (label_ref (match_operand 1 "" ""))
6037 (pc)))
6038 (set (match_dup 0)
6039 (plus:SI (match_dup 0)
6040 (const_int -1)))]
6041 ""
6042 "*
6043 {
6044 CC_STATUS_INIT;
6045 operands[2] = const1_rtx;
6046 output_asm_insn (AS2 (sub%L0,%2,%0), operands);
6047 return \"jc %l1\";
6048 }")
6049
6050 (define_insn ""
6051 [(set (pc)
6052 (if_then_else (ne (match_operand:SI 0 "general_operand" "+g")
6053 (const_int 1))
6054 (label_ref (match_operand 1 "" ""))
6055 (pc)))
6056 (set (match_dup 0)
6057 (plus:SI (match_dup 0)
6058 (const_int -1)))]
6059 ""
6060 "*
6061 {
6062 CC_STATUS_INIT;
6063 output_asm_insn (AS1 (dec%L0,%0), operands);
6064 return \"jnz %l1\";
6065 }")
6066
6067 (define_insn ""
6068 [(set (pc)
6069 (if_then_else (eq (match_operand:SI 0 "general_operand" "+g")
6070 (const_int 1))
6071 (label_ref (match_operand 1 "" ""))
6072 (pc)))
6073 (set (match_dup 0)
6074 (plus:SI (match_dup 0)
6075 (const_int -1)))]
6076 ""
6077 "*
6078 {
6079 CC_STATUS_INIT;
6080 output_asm_insn (AS1 (dec%L0,%0), operands);
6081 return \"jz %l1\";
6082 }")
6083
6084 (define_insn ""
6085 [(set (pc)
6086 (if_then_else (ne (match_operand:SI 0 "general_operand" "+g")
6087 (const_int -1))
6088 (label_ref (match_operand 1 "" ""))
6089 (pc)))
6090 (set (match_dup 0)
6091 (plus:SI (match_dup 0)
6092 (const_int 1)))]
6093 ""
6094 "*
6095 {
6096 CC_STATUS_INIT;
6097 output_asm_insn (AS1 (inc%L0,%0), operands);
6098 return \"jnz %l1\";
6099 }")
6100
6101 (define_insn ""
6102 [(set (pc)
6103 (if_then_else (eq (match_operand:SI 0 "general_operand" "+g")
6104 (const_int -1))
6105 (label_ref (match_operand 1 "" ""))
6106 (pc)))
6107 (set (match_dup 0)
6108 (plus:SI (match_dup 0)
6109 (const_int 1)))]
6110 ""
6111 "*
6112 {
6113 CC_STATUS_INIT;
6114 output_asm_insn (AS1 (inc%L0,%0), operands);
6115 return \"jz %l1\";
6116 }")
6117
6118 ;; Implement switch statements when generating PIC code. Switches are
6119 ;; implemented by `tablejump' when not using -fpic.
6120
6121 ;; Emit code here to do the range checking and make the index zero based.
6122
6123 (define_expand "casesi"
6124 [(set (match_dup 5)
6125 (match_operand:SI 0 "general_operand" ""))
6126 (set (match_dup 6)
6127 (minus:SI (match_dup 5)
6128 (match_operand:SI 1 "general_operand" "")))
6129 (set (cc0)
6130 (compare:CC (match_dup 6)
6131 (match_operand:SI 2 "general_operand" "")))
6132 (set (pc)
6133 (if_then_else (gtu (cc0)
6134 (const_int 0))
6135 (label_ref (match_operand 4 "" ""))
6136 (pc)))
6137 (parallel
6138 [(set (pc)
6139 (minus:SI (reg:SI 3)
6140 (mem:SI (plus:SI (mult:SI (match_dup 6)
6141 (const_int 4))
6142 (label_ref (match_operand 3 "" ""))))))
6143 (clobber (match_scratch:SI 7 ""))])]
6144 "flag_pic"
6145 "
6146 {
6147 operands[5] = gen_reg_rtx (SImode);
6148 operands[6] = gen_reg_rtx (SImode);
6149 current_function_uses_pic_offset_table = 1;
6150 }")
6151
6152 ;; Implement a casesi insn.
6153
6154 ;; Each entry in the "addr_diff_vec" looks like this as the result of the
6155 ;; two rules below:
6156 ;;
6157 ;; .long _GLOBAL_OFFSET_TABLE_+[.-.L2]
6158 ;;
6159 ;; 1. An expression involving an external reference may only use the
6160 ;; addition operator, and only with an assembly-time constant.
6161 ;; The example above satisfies this because ".-.L2" is a constant.
6162 ;;
6163 ;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is
6164 ;; given the value of "GOT - .", where GOT is the actual address of
6165 ;; the Global Offset Table. Therefore, the .long above actually
6166 ;; stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2". The
6167 ;; expression "GOT - .L2" by itself would generate an error from as(1).
6168 ;;
6169 ;; The pattern below emits code that looks like this:
6170 ;;
6171 ;; movl %ebx,reg
6172 ;; subl TABLE@GOTOFF(%ebx,index,4),reg
6173 ;; jmp reg
6174 ;;
6175 ;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since
6176 ;; the addr_diff_vec is known to be part of this module.
6177 ;;
6178 ;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which
6179 ;; evaluates to just ".L2".
6180
6181 (define_insn ""
6182 [(set (pc)
6183 (minus:SI (reg:SI 3)
6184 (mem:SI (plus:SI
6185 (mult:SI (match_operand:SI 0 "register_operand" "r")
6186 (const_int 4))
6187 (label_ref (match_operand 1 "" ""))))))
6188 (clobber (match_scratch:SI 2 "=&r"))]
6189 ""
6190 "*
6191 {
6192 rtx xops[4];
6193
6194 xops[0] = operands[0];
6195 xops[1] = operands[1];
6196 xops[2] = operands[2];
6197 xops[3] = pic_offset_table_rtx;
6198
6199 output_asm_insn (AS2 (mov%L2,%3,%2), xops);
6200 output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops);
6201 output_asm_insn (AS1 (jmp,%*%2), xops);
6202 ASM_OUTPUT_ALIGN (asm_out_file, i386_align_jumps);
6203 RET;
6204 }")
6205
6206 (define_insn "tablejump"
6207 [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
6208 (use (label_ref (match_operand 1 "" "")))]
6209 ""
6210 "*
6211 {
6212 CC_STATUS_INIT;
6213
6214 return AS1 (jmp,%*%0);
6215 }")
6216
6217 ;; Call insns.
6218
6219 ;; If generating PIC code, the predicate indirect_operand will fail
6220 ;; for operands[0] containing symbolic references on all of the named
6221 ;; call* patterns. Each named pattern is followed by an unnamed pattern
6222 ;; that matches any call to a symbolic CONST (ie, a symbol_ref). The
6223 ;; unnamed patterns are only used while generating PIC code, because
6224 ;; otherwise the named patterns match.
6225
6226 ;; Call subroutine returning no value.
6227
6228 (define_expand "call_pop"
6229 [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
6230 (match_operand:SI 1 "general_operand" ""))
6231 (set (reg:SI 7)
6232 (plus:SI (reg:SI 7)
6233 (match_operand:SI 3 "immediate_operand" "")))])]
6234 ""
6235 "
6236 {
6237 rtx addr;
6238
6239 if (flag_pic)
6240 current_function_uses_pic_offset_table = 1;
6241
6242 /* With half-pic, force the address into a register. */
6243 addr = XEXP (operands[0], 0);
6244 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
6245 XEXP (operands[0], 0) = force_reg (Pmode, addr);
6246
6247 if (! expander_call_insn_operand (operands[0], QImode))
6248 operands[0]
6249 = change_address (operands[0], VOIDmode,
6250 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
6251 }")
6252
6253 (define_insn ""
6254 [(call (match_operand:QI 0 "call_insn_operand" "m")
6255 (match_operand:SI 1 "general_operand" "g"))
6256 (set (reg:SI 7) (plus:SI (reg:SI 7)
6257 (match_operand:SI 3 "immediate_operand" "i")))]
6258 ""
6259 "*
6260 {
6261 if (GET_CODE (operands[0]) == MEM
6262 && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
6263 {
6264 operands[0] = XEXP (operands[0], 0);
6265 return AS1 (call,%*%0);
6266 }
6267 else
6268 return AS1 (call,%P0);
6269 }")
6270
6271 (define_insn ""
6272 [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
6273 (match_operand:SI 1 "general_operand" "g"))
6274 (set (reg:SI 7) (plus:SI (reg:SI 7)
6275 (match_operand:SI 3 "immediate_operand" "i")))]
6276 "!HALF_PIC_P ()"
6277 "call %P0")
6278
6279 (define_expand "call"
6280 [(call (match_operand:QI 0 "indirect_operand" "")
6281 (match_operand:SI 1 "general_operand" ""))]
6282 ;; Operand 1 not used on the i386.
6283 ""
6284 "
6285 {
6286 rtx addr;
6287
6288 if (flag_pic)
6289 current_function_uses_pic_offset_table = 1;
6290
6291 /* With half-pic, force the address into a register. */
6292 addr = XEXP (operands[0], 0);
6293 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
6294 XEXP (operands[0], 0) = force_reg (Pmode, addr);
6295
6296 if (! expander_call_insn_operand (operands[0], QImode))
6297 operands[0]
6298 = change_address (operands[0], VOIDmode,
6299 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
6300 }")
6301
6302 (define_insn ""
6303 [(call (match_operand:QI 0 "call_insn_operand" "m")
6304 (match_operand:SI 1 "general_operand" "g"))]
6305 ;; Operand 1 not used on the i386.
6306 ""
6307 "*
6308 {
6309 if (GET_CODE (operands[0]) == MEM
6310 && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
6311 {
6312 operands[0] = XEXP (operands[0], 0);
6313 return AS1 (call,%*%0);
6314 }
6315 else
6316 return AS1 (call,%P0);
6317 }")
6318
6319 (define_insn ""
6320 [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
6321 (match_operand:SI 1 "general_operand" "g"))]
6322 ;; Operand 1 not used on the i386.
6323 "!HALF_PIC_P ()"
6324 "call %P0")
6325
6326 ;; Call subroutine, returning value in operand 0
6327 ;; (which must be a hard register).
6328
6329 (define_expand "call_value_pop"
6330 [(parallel [(set (match_operand 0 "" "")
6331 (call (match_operand:QI 1 "indirect_operand" "")
6332 (match_operand:SI 2 "general_operand" "")))
6333 (set (reg:SI 7)
6334 (plus:SI (reg:SI 7)
6335 (match_operand:SI 4 "immediate_operand" "")))])]
6336 ""
6337 "
6338 {
6339 rtx addr;
6340
6341 if (flag_pic)
6342 current_function_uses_pic_offset_table = 1;
6343
6344 /* With half-pic, force the address into a register. */
6345 addr = XEXP (operands[1], 0);
6346 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
6347 XEXP (operands[1], 0) = force_reg (Pmode, addr);
6348
6349 if (! expander_call_insn_operand (operands[1], QImode))
6350 operands[1]
6351 = change_address (operands[1], VOIDmode,
6352 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
6353 }")
6354
6355 (define_insn ""
6356 [(set (match_operand 0 "" "=rf")
6357 (call (match_operand:QI 1 "call_insn_operand" "m")
6358 (match_operand:SI 2 "general_operand" "g")))
6359 (set (reg:SI 7) (plus:SI (reg:SI 7)
6360 (match_operand:SI 4 "immediate_operand" "i")))]
6361 ""
6362 "*
6363 {
6364 if (GET_CODE (operands[1]) == MEM
6365 && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
6366 {
6367 operands[1] = XEXP (operands[1], 0);
6368 output_asm_insn (AS1 (call,%*%1), operands);
6369 }
6370 else
6371 output_asm_insn (AS1 (call,%P1), operands);
6372
6373 RET;
6374 }")
6375
6376 (define_insn ""
6377 [(set (match_operand 0 "" "=rf")
6378 (call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
6379 (match_operand:SI 2 "general_operand" "g")))
6380 (set (reg:SI 7) (plus:SI (reg:SI 7)
6381 (match_operand:SI 4 "immediate_operand" "i")))]
6382 "!HALF_PIC_P ()"
6383 "call %P1")
6384
6385 (define_expand "call_value"
6386 [(set (match_operand 0 "" "")
6387 (call (match_operand:QI 1 "indirect_operand" "")
6388 (match_operand:SI 2 "general_operand" "")))]
6389 ;; Operand 2 not used on the i386.
6390 ""
6391 "
6392 {
6393 rtx addr;
6394
6395 if (flag_pic)
6396 current_function_uses_pic_offset_table = 1;
6397
6398 /* With half-pic, force the address into a register. */
6399 addr = XEXP (operands[1], 0);
6400 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
6401 XEXP (operands[1], 0) = force_reg (Pmode, addr);
6402
6403 if (! expander_call_insn_operand (operands[1], QImode))
6404 operands[1]
6405 = change_address (operands[1], VOIDmode,
6406 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
6407 }")
6408
6409 (define_insn ""
6410 [(set (match_operand 0 "" "=rf")
6411 (call (match_operand:QI 1 "call_insn_operand" "m")
6412 (match_operand:SI 2 "general_operand" "g")))]
6413 ;; Operand 2 not used on the i386.
6414 ""
6415 "*
6416 {
6417 if (GET_CODE (operands[1]) == MEM
6418 && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
6419 {
6420 operands[1] = XEXP (operands[1], 0);
6421 output_asm_insn (AS1 (call,%*%1), operands);
6422 }
6423 else
6424 output_asm_insn (AS1 (call,%P1), operands);
6425
6426 RET;
6427 }")
6428
6429 (define_insn ""
6430 [(set (match_operand 0 "" "=rf")
6431 (call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
6432 (match_operand:SI 2 "general_operand" "g")))]
6433 ;; Operand 2 not used on the i386.
6434 "!HALF_PIC_P ()"
6435 "call %P1")
6436
6437 ;; Call subroutine returning any type.
6438
6439 (define_expand "untyped_call"
6440 [(parallel [(call (match_operand 0 "" "")
6441 (const_int 0))
6442 (match_operand 1 "" "")
6443 (match_operand 2 "" "")])]
6444 ""
6445 "
6446 {
6447 int i;
6448
6449 /* In order to give reg-stack an easier job in validating two
6450 coprocessor registers as containing a possible return value,
6451 simply pretend the untyped call returns a complex long double
6452 value. */
6453
6454 emit_call_insn (TARGET_80387
6455 ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG),
6456 operands[0], const0_rtx)
6457 : gen_call (operands[0], const0_rtx));
6458
6459 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6460 {
6461 rtx set = XVECEXP (operands[2], 0, i);
6462 emit_move_insn (SET_DEST (set), SET_SRC (set));
6463 }
6464
6465 /* The optimizer does not know that the call sets the function value
6466 registers we stored in the result block. We avoid problems by
6467 claiming that all hard registers are used and clobbered at this
6468 point. */
6469 emit_insn (gen_blockage ());
6470
6471 DONE;
6472 }")
6473
6474 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6475 ;; all of memory. This blocks insns from being moved across this point.
6476
6477 (define_insn "blockage"
6478 [(unspec_volatile [(const_int 0)] 0)]
6479 ""
6480 "")
6481
6482 ;; Insn emitted into the body of a function to return from a function.
6483 ;; This is only done if the function's epilogue is known to be simple.
6484 ;; See comments for simple_386_epilogue in i386.c.
6485
6486 (define_expand "return"
6487 [(return)]
6488 "ix86_can_use_return_insn_p ()"
6489 "")
6490
6491 (define_insn "return_internal"
6492 [(return)]
6493 "reload_completed"
6494 "ret")
6495
6496 (define_insn "return_pop_internal"
6497 [(return)
6498 (use (match_operand:SI 0 "const_int_operand" ""))]
6499 "reload_completed"
6500 "ret %0")
6501
6502 (define_insn "nop"
6503 [(const_int 0)]
6504 ""
6505 "nop")
6506
6507 (define_expand "prologue"
6508 [(const_int 1)]
6509 ""
6510 "
6511 {
6512 ix86_expand_prologue ();
6513 DONE;
6514 }")
6515
6516 ;; The use of UNSPEC here is currently not necessary - a simple SET of ebp
6517 ;; to itself would be enough. But this way we are safe even if some optimizer
6518 ;; becomes too clever in the future.
6519 (define_insn "prologue_set_stack_ptr"
6520 [(set (reg:SI 7)
6521 (minus:SI (reg:SI 7) (match_operand:SI 0 "immediate_operand" "i")))
6522 (set (reg:SI 6) (unspec:SI [(reg:SI 6)] 4))]
6523 ""
6524 "*
6525 {
6526 rtx xops [2];
6527
6528 xops[0] = operands[0];
6529 xops[1] = stack_pointer_rtx;
6530 output_asm_insn (AS2 (sub%L1,%0,%1), xops);
6531 RET;
6532 }")
6533
6534 (define_insn "prologue_set_got"
6535 [(set (match_operand:SI 0 "" "")
6536 (unspec_volatile
6537 [(plus:SI (match_dup 0)
6538 (plus:SI (match_operand:SI 1 "symbolic_operand" "")
6539 (minus:SI (pc) (match_operand 2 "" ""))))] 1))]
6540 ""
6541 "*
6542 {
6543 char buffer[64];
6544
6545 if (TARGET_DEEP_BRANCH_PREDICTION)
6546 {
6547 sprintf (buffer, \"addl %s,%%0\", XSTR (operands[1], 0));
6548 output_asm_insn (buffer, operands);
6549 }
6550 else
6551 {
6552 sprintf (buffer, \"addl %s+[.-%%X2],%%0\", XSTR (operands[1], 0));
6553 output_asm_insn (buffer, operands);
6554 }
6555 RET;
6556 }")
6557
6558 (define_insn "prologue_get_pc"
6559 [(set (match_operand:SI 0 "" "")
6560 (unspec_volatile [(plus:SI (pc) (match_operand 1 "" ""))] 2))]
6561 ""
6562 "*
6563 {
6564 char buffer[64];
6565
6566 output_asm_insn (AS1 (call,%X1), operands);
6567 if (! TARGET_DEEP_BRANCH_PREDICTION)
6568 {
6569 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (operands[1]));
6570 }
6571 RET;
6572 }")
6573
6574 (define_insn "prologue_get_pc_and_set_got"
6575 [(unspec_volatile [(match_operand:SI 0 "" "")] 3)]
6576 ""
6577 "*
6578 {
6579 operands[1] = gen_label_rtx ();
6580 output_asm_insn (AS1 (call,%X1), operands);
6581 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
6582 CODE_LABEL_NUMBER (operands[1]));
6583 output_asm_insn (AS1 (pop%L0,%0), operands);
6584 output_asm_insn (\"addl $_GLOBAL_OFFSET_TABLE_+[.-%X1],%0\", operands);
6585 RET;
6586 }")
6587
6588 (define_expand "epilogue"
6589 [(const_int 1)]
6590 ""
6591 "
6592 {
6593 ix86_expand_epilogue ();
6594 DONE;
6595 }")
6596
6597 (define_insn "epilogue_set_stack_ptr"
6598 [(set (reg:SI 7) (reg:SI 6))
6599 (clobber (reg:SI 6))]
6600 ""
6601 "*
6602 {
6603 rtx xops [2];
6604
6605 xops[0] = frame_pointer_rtx;
6606 xops[1] = stack_pointer_rtx;
6607 output_asm_insn (AS2 (mov%L0,%0,%1), xops);
6608 RET;
6609 }")
6610
6611 (define_insn "leave"
6612 [(const_int 2)
6613 (clobber (reg:SI 6))
6614 (clobber (reg:SI 7))]
6615 ""
6616 "leave")
6617
6618 (define_insn "pop"
6619 [(set (match_operand:SI 0 "register_operand" "r")
6620 (mem:SI (reg:SI 7)))
6621 (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))]
6622 ""
6623 "*
6624 {
6625 output_asm_insn (AS1 (pop%L0,%P0), operands);
6626 RET;
6627 }")
6628
6629 (define_expand "movstrsi"
6630 [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
6631 (match_operand:BLK 1 "memory_operand" ""))
6632 (use (match_operand:SI 2 "const_int_operand" ""))
6633 (use (match_operand:SI 3 "const_int_operand" ""))
6634 (clobber (match_scratch:SI 4 ""))
6635 (clobber (match_dup 5))
6636 (clobber (match_dup 6))])]
6637 ""
6638 "
6639 {
6640 rtx addr0, addr1;
6641
6642 if (GET_CODE (operands[2]) != CONST_INT)
6643 FAIL;
6644
6645 addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
6646 addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
6647
6648 operands[5] = addr0;
6649 operands[6] = addr1;
6650
6651 operands[0] = change_address (operands[0], VOIDmode, addr0);
6652 operands[1] = change_address (operands[1], VOIDmode, addr1);
6653 }")
6654
6655 ;; It might seem that operands 0 & 1 could use predicate register_operand.
6656 ;; But strength reduction might offset the MEM expression. So we let
6657 ;; reload put the address into %edi & %esi.
6658
6659 (define_insn ""
6660 [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
6661 (mem:BLK (match_operand:SI 1 "address_operand" "S")))
6662 (use (match_operand:SI 2 "const_int_operand" "n"))
6663 (use (match_operand:SI 3 "immediate_operand" "i"))
6664 (clobber (match_scratch:SI 4 "=&c"))
6665 (clobber (match_dup 0))
6666 (clobber (match_dup 1))]
6667 ""
6668 "*
6669 {
6670 rtx xops[2];
6671
6672 output_asm_insn (\"cld\", operands);
6673 if (GET_CODE (operands[2]) == CONST_INT)
6674 {
6675 if (INTVAL (operands[2]) & ~0x03)
6676 {
6677 xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff);
6678 xops[1] = operands[4];
6679
6680 output_asm_insn (AS2 (mov%L1,%0,%1), xops);
6681 #ifdef INTEL_SYNTAX
6682 output_asm_insn (\"rep movsd\", xops);
6683 #else
6684 output_asm_insn (\"rep\;movsl\", xops);
6685 #endif
6686 }
6687 if (INTVAL (operands[2]) & 0x02)
6688 output_asm_insn (\"movsw\", operands);
6689 if (INTVAL (operands[2]) & 0x01)
6690 output_asm_insn (\"movsb\", operands);
6691 }
6692 else
6693 abort ();
6694 RET;
6695 }")
6696
6697 (define_expand "clrstrsi"
6698 [(set (match_dup 3) (const_int 0))
6699 (parallel [(set (match_operand:BLK 0 "memory_operand" "")
6700 (const_int 0))
6701 (use (match_operand:SI 1 "const_int_operand" ""))
6702 (use (match_operand:SI 2 "const_int_operand" ""))
6703 (use (match_dup 3))
6704 (clobber (match_scratch:SI 4 ""))
6705 (clobber (match_dup 5))])]
6706 ""
6707 "
6708 {
6709 rtx addr0, addr1;
6710
6711 if (GET_CODE (operands[1]) != CONST_INT)
6712 FAIL;
6713
6714 addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
6715
6716 operands[3] = gen_reg_rtx (SImode);
6717 operands[5] = addr0;
6718
6719 operands[0] = gen_rtx_MEM (BLKmode, addr0);
6720 }")
6721
6722 ;; It might seem that operand 0 could use predicate register_operand.
6723 ;; But strength reduction might offset the MEM expression. So we let
6724 ;; reload put the address into %edi.
6725
6726 (define_insn ""
6727 [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
6728 (const_int 0))
6729 (use (match_operand:SI 1 "const_int_operand" "n"))
6730 (use (match_operand:SI 2 "immediate_operand" "i"))
6731 (use (match_operand:SI 3 "register_operand" "a"))
6732 (clobber (match_scratch:SI 4 "=&c"))
6733 (clobber (match_dup 0))]
6734 ""
6735 "*
6736 {
6737 rtx xops[2];
6738
6739 output_asm_insn (\"cld\", operands);
6740 if (GET_CODE (operands[1]) == CONST_INT)
6741 {
6742 if (INTVAL (operands[1]) & ~0x03)
6743 {
6744 xops[0] = GEN_INT ((INTVAL (operands[1]) >> 2) & 0x3fffffff);
6745 xops[1] = operands[4];
6746
6747 output_asm_insn (AS2 (mov%L1,%0,%1), xops);
6748 #ifdef INTEL_SYNTAX
6749 output_asm_insn (\"rep stosd\", xops);
6750 #else
6751 output_asm_insn (\"rep\;stosl\", xops);
6752 #endif
6753 }
6754 if (INTVAL (operands[1]) & 0x02)
6755 output_asm_insn (\"stosw\", operands);
6756 if (INTVAL (operands[1]) & 0x01)
6757 output_asm_insn (\"stosb\", operands);
6758 }
6759 else
6760 abort ();
6761 RET;
6762 }")
6763
6764 (define_expand "cmpstrsi"
6765 [(parallel [(set (match_operand:SI 0 "general_operand" "")
6766 (compare:SI (match_operand:BLK 1 "general_operand" "")
6767 (match_operand:BLK 2 "general_operand" "")))
6768 (use (match_operand:SI 3 "general_operand" ""))
6769 (use (match_operand:SI 4 "immediate_operand" ""))
6770 (clobber (match_dup 5))
6771 (clobber (match_dup 6))
6772 (clobber (match_dup 3))])]
6773 ""
6774 "
6775 {
6776 rtx addr1, addr2;
6777
6778 addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
6779 addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
6780 operands[3] = copy_to_mode_reg (SImode, operands[3]);
6781
6782 operands[5] = addr1;
6783 operands[6] = addr2;
6784
6785 operands[1] = gen_rtx_MEM (BLKmode, addr1);
6786 operands[2] = gen_rtx_MEM (BLKmode, addr2);
6787
6788 }")
6789
6790 ;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is
6791 ;; zero. Emit extra code to make sure that a zero-length compare is EQ.
6792
6793 ;; It might seem that operands 0 & 1 could use predicate register_operand.
6794 ;; But strength reduction might offset the MEM expression. So we let
6795 ;; reload put the address into %edi & %esi.
6796
6797 ;; ??? Most comparisons have a constant length, and it's therefore
6798 ;; possible to know that the length is non-zero, and to avoid the extra
6799 ;; code to handle zero-length compares.
6800
6801 (define_insn ""
6802 [(set (match_operand:SI 0 "register_operand" "=&r")
6803 (compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S"))
6804 (mem:BLK (match_operand:SI 2 "address_operand" "D"))))
6805 (use (match_operand:SI 3 "register_operand" "c"))
6806 (use (match_operand:SI 4 "immediate_operand" "i"))
6807 (clobber (match_dup 1))
6808 (clobber (match_dup 2))
6809 (clobber (match_dup 3))]
6810 ""
6811 "*
6812 {
6813 rtx xops[2], label;
6814
6815 label = gen_label_rtx ();
6816
6817 output_asm_insn (\"cld\", operands);
6818 output_asm_insn (AS2 (xor%L0,%0,%0), operands);
6819 output_asm_insn (\"repz\;cmps%B2\", operands);
6820 output_asm_insn (\"je %l0\", &label);
6821
6822 xops[0] = operands[0];
6823 xops[1] = const1_rtx;
6824 output_asm_insn (AS2 (sbb%L0,%0,%0), xops);
6825 if (QI_REG_P (xops[0]))
6826 output_asm_insn (AS2 (or%B0,%1,%b0), xops);
6827 else
6828 output_asm_insn (AS2 (or%L0,%1,%0), xops);
6829
6830 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label));
6831 RET;
6832 }")
6833
6834 (define_insn ""
6835 [(set (cc0)
6836 (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
6837 (mem:BLK (match_operand:SI 1 "address_operand" "D"))))
6838 (use (match_operand:SI 2 "register_operand" "c"))
6839 (use (match_operand:SI 3 "immediate_operand" "i"))
6840 (clobber (match_dup 0))
6841 (clobber (match_dup 1))
6842 (clobber (match_dup 2))]
6843 ""
6844 "*
6845 {
6846 rtx xops[2];
6847
6848 cc_status.flags |= CC_NOT_SIGNED;
6849
6850 xops[0] = gen_rtx_REG (QImode, 0);
6851 xops[1] = CONST0_RTX (QImode);
6852
6853 output_asm_insn (\"cld\", operands);
6854 output_asm_insn (AS2 (test%B0,%1,%0), xops);
6855 return \"repz\;cmps%B2\";
6856 }")
6857
6858 \f
6859 ;; Note, you cannot optimize away the branch following the bsfl by assuming
6860 ;; that the destination is not modified if the input is 0, since not all
6861 ;; x86 implementations do this.
6862
6863 (define_expand "ffssi2"
6864 [(set (match_operand:SI 0 "general_operand" "")
6865 (ffs:SI (match_operand:SI 1 "general_operand" "")))]
6866 ""
6867 "
6868 {
6869 rtx label = gen_label_rtx (), temp = gen_reg_rtx (SImode);
6870
6871 emit_insn (gen_ffssi_1 (temp, operands[1]));
6872 emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, SImode, 0, 0);
6873 emit_jump_insn (gen_bne (label));
6874 emit_move_insn (temp, constm1_rtx);
6875 emit_label (label);
6876 temp = expand_binop (SImode, add_optab, temp, const1_rtx,
6877 operands[0], 0, OPTAB_WIDEN);
6878
6879 if (temp != operands[0])
6880 emit_move_insn (operands[0], temp);
6881 DONE;
6882 }")
6883
6884 (define_insn "ffssi_1"
6885 [(set (match_operand:SI 0 "register_operand" "=r")
6886 (unspec:SI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))]
6887 ""
6888 "* return AS2 (bsf%L0,%1,%0);")
6889
6890 (define_expand "ffshi2"
6891 [(set (match_operand:SI 0 "general_operand" "")
6892 (ffs:HI (match_operand:HI 1 "general_operand" "")))]
6893 ""
6894 "
6895 {
6896 rtx label = gen_label_rtx (), temp = gen_reg_rtx (HImode);
6897
6898 emit_insn (gen_ffshi_1 (temp, operands[1]));
6899 emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, HImode, 0, 0);
6900 emit_jump_insn (gen_bne (label));
6901 emit_move_insn (temp, constm1_rtx);
6902 emit_label (label);
6903 temp = expand_binop (HImode, add_optab, temp, const1_rtx,
6904 operands[0], 0, OPTAB_WIDEN);
6905
6906 if (temp != operands[0])
6907 emit_move_insn (operands[0], temp);
6908 DONE;
6909 }")
6910
6911 (define_insn "ffshi_1"
6912 [(set (match_operand:HI 0 "register_operand" "=r")
6913 (unspec:HI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))]
6914 ""
6915 "* return AS2 (bsf%W0,%1,%0);")
6916 \f
6917 ;; These patterns match the binary 387 instructions for addM3, subM3,
6918 ;; mulM3 and divM3. There are three patterns for each of DFmode and
6919 ;; SFmode. The first is the normal insn, the second the same insn but
6920 ;; with one operand a conversion, and the third the same insn but with
6921 ;; the other operand a conversion. The conversion may be SFmode or
6922 ;; SImode if the target mode DFmode, but only SImode if the target mode
6923 ;; is SFmode.
6924
6925 (define_insn ""
6926 [(set (match_operand:DF 0 "register_operand" "=f,f")
6927 (match_operator:DF 3 "binary_387_op"
6928 [(match_operand:DF 1 "nonimmediate_operand" "0,fm")
6929 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
6930 "TARGET_80387"
6931 "* return output_387_binary_op (insn, operands);"
6932 [(set (attr "type")
6933 (cond [(match_operand:DF 3 "is_mul" "")
6934 (const_string "fpmul")
6935 (match_operand:DF 3 "is_div" "")
6936 (const_string "fpdiv")
6937 ]
6938 (const_string "fpop")
6939 )
6940 )])
6941
6942 (define_insn ""
6943 [(set (match_operand:DF 0 "register_operand" "=f")
6944 (match_operator:DF 3 "binary_387_op"
6945 [(float:DF (match_operand:SI 1 "nonimmediate_operand" "rm"))
6946 (match_operand:DF 2 "register_operand" "0")]))]
6947 "TARGET_80387"
6948 "* return output_387_binary_op (insn, operands);"
6949 [(set (attr "type")
6950 (cond [(match_operand:DF 3 "is_mul" "")
6951 (const_string "fpmul")
6952 (match_operand:DF 3 "is_div" "")
6953 (const_string "fpdiv")
6954 ]
6955 (const_string "fpop")
6956 )
6957 )])
6958
6959 (define_insn ""
6960 [(set (match_operand:XF 0 "register_operand" "=f,f")
6961 (match_operator:XF 3 "binary_387_op"
6962 [(match_operand:XF 1 "register_operand" "0,f")
6963 (match_operand:XF 2 "register_operand" "f,0")]))]
6964 "TARGET_80387"
6965 "* return output_387_binary_op (insn, operands);"
6966 [(set (attr "type")
6967 (cond [(match_operand:DF 3 "is_mul" "")
6968 (const_string "fpmul")
6969 (match_operand:DF 3 "is_div" "")
6970 (const_string "fpdiv")
6971 ]
6972 (const_string "fpop")
6973 )
6974 )])
6975
6976 (define_insn ""
6977 [(set (match_operand:XF 0 "register_operand" "=f")
6978 (match_operator:XF 3 "binary_387_op"
6979 [(float:XF (match_operand:SI 1 "nonimmediate_operand" "rm"))
6980 (match_operand:XF 2 "register_operand" "0")]))]
6981 "TARGET_80387"
6982 "* return output_387_binary_op (insn, operands);"
6983 [(set (attr "type")
6984 (cond [(match_operand:DF 3 "is_mul" "")
6985 (const_string "fpmul")
6986 (match_operand:DF 3 "is_div" "")
6987 (const_string "fpdiv")
6988 ]
6989 (const_string "fpop")
6990 )
6991 )])
6992
6993 (define_insn ""
6994 [(set (match_operand:XF 0 "register_operand" "=f,f")
6995 (match_operator:XF 3 "binary_387_op"
6996 [(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
6997 (match_operand:XF 2 "register_operand" "0,f")]))]
6998 "TARGET_80387"
6999 "* return output_387_binary_op (insn, operands);"
7000 [(set (attr "type")
7001 (cond [(match_operand:DF 3 "is_mul" "")
7002 (const_string "fpmul")
7003 (match_operand:DF 3 "is_div" "")
7004 (const_string "fpdiv")
7005 ]
7006 (const_string "fpop")
7007 )
7008 )])
7009
7010 (define_insn ""
7011 [(set (match_operand:XF 0 "register_operand" "=f")
7012 (match_operator:XF 3 "binary_387_op"
7013 [(match_operand:XF 1 "register_operand" "0")
7014 (float:XF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
7015 "TARGET_80387"
7016 "* return output_387_binary_op (insn, operands);"
7017 [(set (attr "type")
7018 (cond [(match_operand:DF 3 "is_mul" "")
7019 (const_string "fpmul")
7020 (match_operand:DF 3 "is_div" "")
7021 (const_string "fpdiv")
7022 ]
7023 (const_string "fpop")
7024 )
7025 )])
7026
7027 (define_insn ""
7028 [(set (match_operand:XF 0 "register_operand" "=f,f")
7029 (match_operator:XF 3 "binary_387_op"
7030 [(match_operand:XF 1 "register_operand" "0,f")
7031 (float_extend:XF
7032 (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
7033 "TARGET_80387"
7034 "* return output_387_binary_op (insn, operands);"
7035 [(set (attr "type")
7036 (cond [(match_operand:DF 3 "is_mul" "")
7037 (const_string "fpmul")
7038 (match_operand:DF 3 "is_div" "")
7039 (const_string "fpdiv")
7040 ]
7041 (const_string "fpop")
7042 )
7043 )])
7044
7045 (define_insn ""
7046 [(set (match_operand:DF 0 "register_operand" "=f,f")
7047 (match_operator:DF 3 "binary_387_op"
7048 [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
7049 (match_operand:DF 2 "register_operand" "0,f")]))]
7050 "TARGET_80387"
7051 "* return output_387_binary_op (insn, operands);"
7052 [(set (attr "type")
7053 (cond [(match_operand:DF 3 "is_mul" "")
7054 (const_string "fpmul")
7055 (match_operand:DF 3 "is_div" "")
7056 (const_string "fpdiv")
7057 ]
7058 (const_string "fpop")
7059 )
7060 )])
7061
7062 (define_insn ""
7063 [(set (match_operand:DF 0 "register_operand" "=f")
7064 (match_operator:DF 3 "binary_387_op"
7065 [(match_operand:DF 1 "register_operand" "0")
7066 (float:DF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
7067 "TARGET_80387"
7068 "* return output_387_binary_op (insn, operands);"
7069 [(set (attr "type")
7070 (cond [(match_operand:DF 3 "is_mul" "")
7071 (const_string "fpmul")
7072 (match_operand:DF 3 "is_div" "")
7073 (const_string "fpdiv")
7074 ]
7075 (const_string "fpop")
7076 )
7077 )])
7078
7079 (define_insn ""
7080 [(set (match_operand:DF 0 "register_operand" "=f,f")
7081 (match_operator:DF 3 "binary_387_op"
7082 [(match_operand:DF 1 "register_operand" "0,f")
7083 (float_extend:DF
7084 (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
7085 "TARGET_80387"
7086 "* return output_387_binary_op (insn, operands);"
7087 [(set (attr "type")
7088 (cond [(match_operand:DF 3 "is_mul" "")
7089 (const_string "fpmul")
7090 (match_operand:DF 3 "is_div" "")
7091 (const_string "fpdiv")
7092 ]
7093 (const_string "fpop")
7094 )
7095 )])
7096
7097 (define_insn ""
7098 [(set (match_operand:SF 0 "register_operand" "=f,f")
7099 (match_operator:SF 3 "binary_387_op"
7100 [(match_operand:SF 1 "nonimmediate_operand" "0,fm")
7101 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
7102 "TARGET_80387"
7103 "* return output_387_binary_op (insn, operands);"
7104 [(set (attr "type")
7105 (cond [(match_operand:DF 3 "is_mul" "")
7106 (const_string "fpmul")
7107 (match_operand:DF 3 "is_div" "")
7108 (const_string "fpdiv")
7109 ]
7110 (const_string "fpop")
7111 )
7112 )])
7113
7114 (define_insn ""
7115 [(set (match_operand:SF 0 "register_operand" "=f")
7116 (match_operator:SF 3 "binary_387_op"
7117 [(float:SF (match_operand:SI 1 "nonimmediate_operand" "rm"))
7118 (match_operand:SF 2 "register_operand" "0")]))]
7119 "TARGET_80387"
7120 "* return output_387_binary_op (insn, operands);"
7121 [(set (attr "type")
7122 (cond [(match_operand:DF 3 "is_mul" "")
7123 (const_string "fpmul")
7124 (match_operand:DF 3 "is_div" "")
7125 (const_string "fpdiv")
7126 ]
7127 (const_string "fpop")
7128 )
7129 )])
7130
7131 (define_insn ""
7132 [(set (match_operand:SF 0 "register_operand" "=f")
7133 (match_operator:SF 3 "binary_387_op"
7134 [(match_operand:SF 1 "register_operand" "0")
7135 (float:SF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
7136 "TARGET_80387"
7137 "* return output_387_binary_op (insn, operands);"
7138 [(set (attr "type")
7139 (cond [(match_operand:DF 3 "is_mul" "")
7140 (const_string "fpmul")
7141 (match_operand:DF 3 "is_div" "")
7142 (const_string "fpdiv")
7143 ]
7144 (const_string "fpop")
7145 )
7146 )])
7147 \f
7148 (define_expand "strlensi"
7149 [(parallel [(set (match_dup 4)
7150 (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" ""))
7151 (match_operand:QI 2 "immediate_operand" "")
7152 (match_operand:SI 3 "immediate_operand" "")] 0))
7153 (clobber (match_dup 1))])
7154 (set (match_dup 5)
7155 (not:SI (match_dup 4)))
7156 (set (match_operand:SI 0 "register_operand" "")
7157 (plus:SI (match_dup 5)
7158 (const_int -1)))]
7159 ""
7160 "
7161 {
7162 if (TARGET_UNROLL_STRLEN && operands[2] == const0_rtx && optimize > 1)
7163 {
7164 rtx address;
7165 rtx scratch;
7166
7167 /* well it seems that some optimizer does not combine a call like
7168 foo(strlen(bar), strlen(bar));
7169 when the move and the subtraction is done here. It does calculate
7170 the length just once when these instructions are done inside of
7171 output_strlen_unroll(). But I think since &bar[strlen(bar)] is
7172 often used and I use one fewer register for the lifetime of
7173 output_strlen_unroll() this is better. */
7174 scratch = gen_reg_rtx (SImode);
7175 address = force_reg (SImode, XEXP (operands[1], 0));
7176
7177 /* move address to scratch-register
7178 this is done here because the i586 can do the following and
7179 in the same cycle with the following move. */
7180 if (GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[3]) < 4)
7181 emit_insn (gen_movsi (scratch, address));
7182
7183 emit_insn (gen_movsi (operands[0], address));
7184
7185 if(TARGET_USE_Q_REG)
7186 emit_insn (gen_strlensi_unroll5 (operands[0],
7187 operands[3],
7188 scratch,
7189 operands[0]));
7190 else
7191 emit_insn (gen_strlensi_unroll4 (operands[0],
7192 operands[3],
7193 scratch,
7194 operands[0]));
7195
7196 /* gen_strlensi_unroll[45] returns the address of the zero
7197 at the end of the string, like memchr(), so compute the
7198 length by subtracting the startaddress. */
7199 emit_insn (gen_subsi3 (operands[0], operands[0], address));
7200 DONE;
7201 }
7202
7203 operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
7204 operands[4] = gen_reg_rtx (SImode);
7205 operands[5] = gen_reg_rtx (SImode);
7206 }")
7207
7208 ;; It might seem that operands 0 & 1 could use predicate register_operand.
7209 ;; But strength reduction might offset the MEM expression. So we let
7210 ;; reload put the address into %edi.
7211
7212 (define_insn ""
7213 [(set (match_operand:SI 0 "register_operand" "=&c")
7214 (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D"))
7215 (match_operand:QI 2 "immediate_operand" "a")
7216 (match_operand:SI 3 "immediate_operand" "i")] 0))
7217 (clobber (match_dup 1))]
7218 ""
7219 "*
7220 {
7221 rtx xops[2];
7222
7223 xops[0] = operands[0];
7224 xops[1] = constm1_rtx;
7225 output_asm_insn (\"cld\", operands);
7226 output_asm_insn (AS2 (mov%L0,%1,%0), xops);
7227 return \"repnz\;scas%B2\";
7228 }")
7229
7230 /* Conditional move define_insns. */
7231
7232 ;; These are all disabled, because they are buggy. They are all susceptible
7233 ;; to problems with input reloads clobbering the condition code registers.
7234 ;; It appears the only safe way to write a integer/FP conditional move pattern
7235 ;; is to write one which emits both the compare and the cmov, and which can be
7236 ;; split only after reload.
7237
7238 (define_expand "movsicc"
7239 [(match_dup 4)
7240 (parallel [(set (match_operand 0 "register_operand" "")
7241 (if_then_else:SI (match_operand 1 "comparison_operator" "")
7242 (match_operand:SI 2 "general_operand" "")
7243 (match_operand:SI 3 "general_operand" "")))
7244 (clobber (match_scratch:SI 4 "=&r"))])]
7245 "0 && TARGET_CMOVE"
7246 "
7247 {
7248 operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
7249 }")
7250
7251 (define_expand "movhicc"
7252 [(match_dup 4)
7253 (parallel [(set (match_operand 0 "register_operand" "")
7254 (if_then_else:HI (match_operand 1 "comparison_operator" "")
7255 (match_operand:HI 2 "general_operand" "")
7256 (match_operand:HI 3 "general_operand" "")))
7257 (clobber (match_scratch:SI 4 "=&r"))])]
7258 "0 && TARGET_CMOVE"
7259 "
7260 {
7261 operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
7262 }")
7263
7264 (define_insn "movsicc_1"
7265 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,&r,rm")
7266 (if_then_else:SI (match_operator 1 "comparison_operator"
7267 [(cc0) (const_int 0)])
7268 (match_operand:SI 2 "general_operand" "rm,0,rm,g")
7269 (match_operand:SI 3 "general_operand" "0,rm,rm,g")))
7270 (clobber (match_scratch:SI 4 "X,X,X,=&r"))]
7271 "0 && TARGET_CMOVE"
7272 "*
7273 {
7274 if (which_alternative == 0)
7275 {
7276 /* r <- cond ? arg : r */
7277 output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
7278 }
7279 else if (which_alternative == 1)
7280 {
7281 /* r <- cond ? r : arg */
7282 output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
7283 }
7284 else if (which_alternative == 2)
7285 {
7286 /* r <- cond ? arg1 : arg2 */
7287 output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
7288 output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
7289 }
7290 else if (which_alternative == 3)
7291 {
7292 /* r <- cond ? arg1 : arg2 */
7293 rtx xops[3];
7294
7295 xops[0] = gen_label_rtx ();
7296 xops[1] = gen_label_rtx ();
7297 xops[2] = operands[1];
7298
7299 output_asm_insn (\"j%c2 %l0\", xops);
7300 if (! rtx_equal_p (operands[0], operands[2]))
7301 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
7302 {
7303 output_asm_insn (AS2 (mov%z2,%2,%4), operands);
7304 output_asm_insn (AS2 (mov%z2,%4,%0), operands);
7305 }
7306 else
7307 output_asm_insn (AS2 (mov%z0,%2,%0), operands);
7308 output_asm_insn (\"jmp %l1\", xops);
7309 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
7310 if (! rtx_equal_p (operands[0], operands[3]))
7311 {
7312 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
7313 {
7314 output_asm_insn (AS2 (mov%z3,%3,%4), operands);
7315 output_asm_insn (AS2 (mov%z3,%4,%0), operands);
7316 }
7317 else
7318 output_asm_insn (AS2 (mov%z0,%3,%0), operands);
7319 }
7320 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
7321 }
7322 RET;
7323 }")
7324
7325 (define_insn "movhicc_1"
7326 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,&r,rm")
7327 (if_then_else:HI (match_operator 1 "comparison_operator"
7328 [(cc0) (const_int 0)])
7329 (match_operand:HI 2 "general_operand" "rm,0,rm,g")
7330 (match_operand:HI 3 "general_operand" "0,rm,rm,g")))
7331 (clobber (match_scratch:SI 4 "X,X,X,=&r"))]
7332 "0 && TARGET_CMOVE"
7333 "*
7334 {
7335 if (which_alternative == 0)
7336 {
7337 /* r <- cond ? arg : r */
7338 output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
7339 }
7340 else if (which_alternative == 1)
7341 {
7342 /* r <- cond ? r : arg */
7343 output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
7344 }
7345 else if (which_alternative == 2)
7346 {
7347 /* r <- cond ? arg1 : arg2 */
7348 output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
7349 output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
7350 }
7351 else if (which_alternative == 3)
7352 {
7353 /* r <- cond ? arg1 : arg2 */
7354 rtx xops[3];
7355
7356 xops[0] = gen_label_rtx ();
7357 xops[1] = gen_label_rtx ();
7358 xops[2] = operands[1];
7359
7360 output_asm_insn (\"j%c2 %l0\", xops);
7361 if (! rtx_equal_p (operands[0], operands[2]))
7362 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
7363 {
7364 output_asm_insn (AS2 (mov%z2,%2,%4), operands);
7365 output_asm_insn (AS2 (mov%z2,%4,%0), operands);
7366 }
7367 else
7368 output_asm_insn (AS2 (mov%z0,%2,%0), operands);
7369 output_asm_insn (\"jmp %l1\", xops);
7370 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
7371 if (! rtx_equal_p (operands[0], operands[3]))
7372 {
7373 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
7374 {
7375 output_asm_insn (AS2 (mov%z3,%3,%4), operands);
7376 output_asm_insn (AS2 (mov%z3,%4,%0), operands);
7377 }
7378 else
7379 output_asm_insn (AS2 (mov%z0,%3,%0), operands);
7380 }
7381 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
7382 }
7383 RET;
7384 }")
7385 ;; We need to disable the FP forms of these since they do not support
7386 ;; memory as written, but no input reloads are permitted for insns
7387 ;; that use cc0. Also, movxfcc is not present.
7388
7389 (define_expand "movsfcc"
7390 [(match_dup 4)
7391 (set (match_operand 0 "register_operand" "")
7392 (if_then_else:SF (match_operand 1 "comparison_operator" "")
7393 (match_operand:SF 2 "register_operand" "")
7394 (match_operand:SF 3 "register_operand" "")))]
7395 "0 && TARGET_CMOVE"
7396 "
7397 {
7398 operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
7399 }")
7400
7401 (define_expand "movdfcc"
7402 [(match_dup 4)
7403 (set (match_operand 0 "register_operand" "t")
7404 (if_then_else:DF (match_operand 1 "comparison_operator" "")
7405 (match_operand:DF 2 "register_operand" "")
7406 (match_operand:DF 3 "register_operand" "")))]
7407 "0 && TARGET_CMOVE"
7408 "
7409 {
7410 operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
7411 }")
7412
7413 (define_expand "movxfcc"
7414 [(match_dup 4)
7415 (set (match_operand 0 "register_operand" "")
7416 (if_then_else:XF (match_operand 1 "comparison_operator" "")
7417 (match_operand:XF 2 "register_operand" "")
7418 (match_operand:XF 3 "register_operand" "")))]
7419 "0 && TARGET_CMOVE"
7420 "
7421 {
7422 operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
7423 }")
7424
7425 (define_insn "movsfcc_1"
7426 [(set (match_operand:SF 0 "general_operand" "=f,f,&f")
7427 (if_then_else:SF (match_operator 1 "comparison_operator"
7428 [(cc0) (const_int 0)])
7429 (match_operand:SF 2 "register_operand" "0,f,f")
7430 (match_operand:SF 3 "register_operand" "f,0,f")))]
7431 "0 && TARGET_CMOVE"
7432 "*
7433 {
7434 switch (which_alternative)
7435 {
7436 case 0:
7437 /* r <- cond ? arg : r */
7438 output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
7439 break;
7440
7441 case 1:
7442 /* r <- cond ? r : arg */
7443 output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
7444 break;
7445
7446 case 2:
7447 /* r <- cond ? r : arg */
7448 output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
7449 output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
7450 break;
7451 }
7452
7453 RET;
7454 }")
7455
7456 (define_insn "movdfcc_1"
7457 [(set (match_operand:DF 0 "general_operand" "=f,f,&f")
7458 (if_then_else:DF (match_operator 1 "comparison_operator"
7459 [(cc0) (const_int 0)])
7460 (match_operand:DF 2 "register_operand" "0,f,f")
7461 (match_operand:DF 3 "register_operand" "f,0,f")))]
7462 "0 && TARGET_CMOVE"
7463 "*
7464 {
7465 switch (which_alternative)
7466 {
7467 case 0:
7468 /* r <- cond ? arg : r */
7469 output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
7470 break;
7471
7472 case 1:
7473 /* r <- cond ? r : arg */
7474 output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
7475 break;
7476
7477 case 2:
7478 /* r <- cond ? r : arg */
7479 output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
7480 output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
7481 break;
7482 }
7483
7484 RET;
7485 }")
7486
7487 (define_insn "strlensi_unroll"
7488 [(set (match_operand:SI 0 "register_operand" "=&r,&r")
7489 (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "r,r"))
7490 (match_operand:SI 2 "immediate_operand" "i,i")] 0))
7491 (clobber (match_scratch:SI 3 "=&q,&r"))]
7492 "optimize > 1"
7493 "* return output_strlen_unroll (operands);")
7494
7495 ;; the only difference between the following patterns is the register preference
7496 ;; on a pentium using a q-register saves one clock cycle per 4 characters
7497
7498 (define_insn "strlensi_unroll4"
7499 [(set (match_operand:SI 0 "register_operand" "=r,r")
7500 (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0,0"))
7501 (match_operand:SI 1 "immediate_operand" "i,i")
7502 (match_operand:SI 2 "register_operand" "+q,!r")] 0))
7503 (clobber (match_dup 2))]
7504 "(TARGET_USE_ANY_REG && optimize > 1)"
7505 "* return output_strlen_unroll (operands);")
7506
7507 (define_insn "strlensi_unroll5"
7508 [(set (match_operand:SI 0 "register_operand" "=r")
7509 (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0"))
7510 (match_operand:SI 1 "immediate_operand" "i")
7511 (match_operand:SI 2 "register_operand" "+q")] 0))
7512 (clobber (match_dup 2))]
7513 "(TARGET_USE_Q_REG && optimize > 1)"
7514 "* return output_strlen_unroll (operands);"
7515 )
7516
7517 (define_insn "allocate_stack_worker"
7518 [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] 3)
7519 (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0)))
7520 (clobber (match_dup 0))]
7521 "TARGET_STACK_PROBE"
7522 "* return AS1(call,__alloca);")
7523
7524 (define_expand "allocate_stack"
7525 [(set (match_operand:SI 0 "register_operand" "=r")
7526 (minus:SI (reg:SI 7) (match_operand:SI 1 "general_operand" "")))
7527 (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 1)))]
7528 "TARGET_STACK_PROBE"
7529 "
7530 {
7531 #ifdef CHECK_STACK_LIMIT
7532 if (GET_CODE (operands[1]) == CONST_INT
7533 && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
7534 emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
7535 operands[1]));
7536 else
7537 #endif
7538 emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
7539 operands[1])));
7540
7541 emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
7542 DONE;
7543 }")
7544
7545 (define_expand "nonlocal_goto_receiver"
7546 [(const_int 0)]
7547 "flag_pic"
7548 "
7549 {
7550 load_pic_register (1);
7551 DONE;
7552 }")
This page took 0.391994 seconds and 5 git commands to generate.