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