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