|
|
1.1 root 1: ;; GCC machine description for Intel 80386.
2: ;; Copyright (C) 1988 Free Software Foundation, Inc.
3: ;; Mostly by William Schelter.
4:
5: ;; This file is part of GNU CC.
6:
7: ;; GNU CC is free software; you can redistribute it and/or modify
8: ;; it under the terms of the GNU General Public License as published by
9: ;; the Free Software Foundation; either version 2, or (at your option)
10: ;; any later version.
11:
12: ;; GNU CC is distributed in the hope that it will be useful,
13: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: ;; GNU General Public License for more details.
16:
17: ;; You should have received a copy of the GNU General Public License
18: ;; along with GNU CC; see the file COPYING. If not, write to
19: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20:
21:
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.
1.1.1.2 ! root 48: ;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode.
1.1 root 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:
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: }")
1.1.1.2 ! root 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: }")
1.1 root 243:
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"
1.1.1.2 ! root 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"
1.1 root 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:
1.1.1.2 ! root 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:
1.1 root 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:
1.1.1.2 ! root 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:
1.1 root 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:
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:
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"
1.1.1.2 ! root 923: [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q"))
! 924: (match_operand:QI 1 "general_operand" "*qn,m"))]
1.1 root 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:
1.1.1.2 ! root 944: /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */
1.1 root 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 ""
1.1.1.2 ! root 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 ""
1.1 root 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:
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:
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:
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:
1.1.1.2 ! root 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:
1.1 root 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: }")
1.1.1.2 ! root 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:
1.1 root 1645:
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:
1.1.1.2 ! root 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:
1.1 root 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:
1.1.1.2 ! root 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:
1.1 root 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")
1.1.1.2 ! root 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")
1.1 root 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:
1.1.1.2 ! root 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:
1.1 root 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")
1.1.1.2 ! root 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")
1.1 root 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:
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:
1.1.1.2 ! root 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:
1.1 root 1915: ;; This will convert from SImode or DImode to MODE_FLOAT.
1916:
1917: (define_insn ""
1.1.1.2 ! root 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 ""
1.1 root 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 ""
1.1.1.2 ! root 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 ""
1.1 root 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:
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: {
1.1.1.2 ! root 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: CC_STATUS_INIT;
! 2107:
! 2108: operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
! 2109:
! 2110: if (operands[2] == const1_rtx)
! 2111: return AS1 (inc%B0,%h0);
! 2112:
! 2113: if (operands[2] == constm1_rtx)
! 2114: return AS1 (dec%B0,%h0);
! 2115:
! 2116: return AS2 (add%B0,%2,%h0);
! 2117: }
! 2118:
1.1 root 2119: if (operands[2] == const1_rtx)
2120: return AS1 (inc%W0,%0);
2121:
2122: if (operands[2] == constm1_rtx)
2123: return AS1 (dec%W0,%0);
2124:
2125: return AS2 (add%W0,%2,%0);
2126: }")
2127:
2128: (define_insn "addqi3"
2129: [(set (match_operand:QI 0 "general_operand" "=qm,q")
2130: (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
2131: (match_operand:QI 2 "general_operand" "qn,qmn")))]
2132: ""
2133: "*
2134: {
2135: if (operands[2] == const1_rtx)
2136: return AS1 (inc%B0,%0);
2137:
2138: if (operands[2] == constm1_rtx)
2139: return AS1 (dec%B0,%0);
2140:
2141: return AS2 (add%B0,%2,%0);
2142: }")
2143:
2144: ;Lennart Augustsson <[email protected]>
2145: ;says this pattern just makes slower code:
2146: ; pushl %ebp
2147: ; addl $-80,(%esp)
2148: ;instead of
2149: ; leal -80(%ebp),%eax
2150: ; pushl %eax
2151: ;
2152: ;(define_insn ""
2153: ; [(set (match_operand:SI 0 "push_operand" "=<")
2154: ; (plus:SI (match_operand:SI 1 "general_operand" "%r")
2155: ; (match_operand:SI 2 "general_operand" "ri")))]
2156: ; ""
2157: ; "*
2158: ;{
2159: ; rtx xops[4];
2160: ; xops[0] = operands[0];
2161: ; xops[1] = operands[1];
2162: ; xops[2] = operands[2];
2163: ; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx);
2164: ; output_asm_insn (\"push%z1 %1\", xops);
2165: ; output_asm_insn (AS2 (add%z3,%2,%3), xops);
2166: ; RET;
2167: ;}")
2168:
2169: ;; addsi3 is faster, so put this after.
2170:
2171: (define_insn ""
2172: [(set (match_operand:SI 0 "register_operand" "=r")
2173: (match_operand:QI 1 "address_operand" "p"))]
2174: ""
2175: "*
2176: {
2177: CC_STATUS_INIT;
2178: /* Adding a constant to a register is faster with an add. */
2179: /* ??? can this ever happen? */
2180: if (GET_CODE (operands[1]) == PLUS
2181: && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2182: && rtx_equal_p (operands[0], XEXP (operands[1], 0)))
2183: {
2184: operands[1] = XEXP (operands[1], 1);
2185:
2186: if (operands[1] == const1_rtx)
2187: return AS1 (inc%L0,%0);
2188:
2189: if (operands[1] == constm1_rtx)
2190: return AS1 (dec%L0,%0);
2191:
2192: return AS2 (add%L0,%1,%0);
2193: }
2194: return AS2 (lea%L0,%a1,%0);
2195: }")
2196:
2197: ;; The patterns that match these are at the end of this file.
2198:
1.1.1.2 ! root 2199: (define_expand "addxf3"
! 2200: [(set (match_operand:XF 0 "register_operand" "")
! 2201: (plus:XF (match_operand:XF 1 "nonimmediate_operand" "")
! 2202: (match_operand:XF 2 "nonimmediate_operand" "")))]
! 2203: "TARGET_80387"
! 2204: "")
! 2205:
1.1 root 2206: (define_expand "adddf3"
2207: [(set (match_operand:DF 0 "register_operand" "")
2208: (plus:DF (match_operand:DF 1 "nonimmediate_operand" "")
2209: (match_operand:DF 2 "nonimmediate_operand" "")))]
2210: "TARGET_80387"
2211: "")
2212:
2213: (define_expand "addsf3"
2214: [(set (match_operand:SF 0 "register_operand" "")
2215: (plus:SF (match_operand:SF 1 "nonimmediate_operand" "")
2216: (match_operand:SF 2 "nonimmediate_operand" "")))]
2217: "TARGET_80387"
2218: "")
2219:
2220: ;;- subtract instructions
2221:
2222: (define_insn "subdi3"
2223: [(set (match_operand:DI 0 "general_operand" "=&r,ro")
2224: (minus:DI (match_operand:DI 1 "general_operand" "0,0")
2225: (match_operand:DI 2 "general_operand" "o,riF")))]
2226: ""
2227: "*
2228: {
2229: rtx low[3], high[3];
2230:
2231: CC_STATUS_INIT;
2232:
2233: split_di (operands, 3, low, high);
2234:
2235: if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
2236: {
2237: output_asm_insn (AS2 (sub%L0,%2,%0), low);
2238: output_asm_insn (AS2 (sbb%L0,%2,%0), high);
2239: }
2240: else
2241: output_asm_insn (AS2 (sub%L0,%2,%0), high);
2242:
2243: RET;
2244: }")
2245:
2246: (define_insn "subsi3"
2247: [(set (match_operand:SI 0 "general_operand" "=rm,r")
2248: (minus:SI (match_operand:SI 1 "general_operand" "0,0")
2249: (match_operand:SI 2 "general_operand" "ri,rm")))]
2250: ""
2251: "* return AS2 (sub%L0,%2,%0);")
2252:
2253: (define_insn "subhi3"
2254: [(set (match_operand:HI 0 "general_operand" "=rm,r")
2255: (minus:HI (match_operand:HI 1 "general_operand" "0,0")
2256: (match_operand:HI 2 "general_operand" "ri,rm")))]
2257: ""
2258: "* return AS2 (sub%W0,%2,%0);")
2259:
2260: (define_insn "subqi3"
2261: [(set (match_operand:QI 0 "general_operand" "=qm,q")
2262: (minus:QI (match_operand:QI 1 "general_operand" "0,0")
2263: (match_operand:QI 2 "general_operand" "qn,qmn")))]
2264: ""
2265: "* return AS2 (sub%B0,%2,%0);")
2266:
2267: ;; The patterns that match these are at the end of this file.
2268:
1.1.1.2 ! root 2269: (define_expand "subxf3"
! 2270: [(set (match_operand:XF 0 "register_operand" "")
! 2271: (minus:XF (match_operand:XF 1 "nonimmediate_operand" "")
! 2272: (match_operand:XF 2 "nonimmediate_operand" "")))]
! 2273: "TARGET_80387"
! 2274: "")
! 2275:
1.1 root 2276: (define_expand "subdf3"
2277: [(set (match_operand:DF 0 "register_operand" "")
2278: (minus:DF (match_operand:DF 1 "nonimmediate_operand" "")
2279: (match_operand:DF 2 "nonimmediate_operand" "")))]
2280: "TARGET_80387"
2281: "")
2282:
2283: (define_expand "subsf3"
2284: [(set (match_operand:SF 0 "register_operand" "")
2285: (minus:SF (match_operand:SF 1 "nonimmediate_operand" "")
2286: (match_operand:SF 2 "nonimmediate_operand" "")))]
2287: "TARGET_80387"
2288: "")
2289:
2290: ;;- multiply instructions
2291:
2292: ;(define_insn "mulqi3"
2293: ; [(set (match_operand:QI 0 "general_operand" "=a")
2294: ; (mult:QI (match_operand:QI 1 "general_operand" "%0")
2295: ; (match_operand:QI 2 "general_operand" "qm")))]
2296: ; ""
2297: ; "imul%B0 %2,%0")
2298:
2299: (define_insn ""
2300: [(set (match_operand:HI 0 "general_operand" "=r")
2301: (mult:SI (match_operand:HI 1 "general_operand" "%0")
2302: (match_operand:HI 2 "general_operand" "r")))]
2303: "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
2304: "* return AS2 (imul%W0,%2,%0);")
2305:
2306: (define_insn "mulhi3"
2307: [(set (match_operand:HI 0 "general_operand" "=r,r")
2308: (mult:SI (match_operand:HI 1 "general_operand" "%0,rm")
2309: (match_operand:HI 2 "general_operand" "g,i")))]
2310: ""
2311: "*
2312: {
2313: if (GET_CODE (operands[1]) == REG
2314: && REGNO (operands[1]) == REGNO (operands[0])
2315: && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
2316: /* Assembler has weird restrictions. */
2317: return AS2 (imul%W0,%2,%0);
2318: return AS3 (imul%W0,%2,%1,%0);
2319: }")
2320:
2321: (define_insn ""
2322: [(set (match_operand:SI 0 "general_operand" "=r")
2323: (mult:SI (match_operand:SI 1 "general_operand" "%0")
2324: (match_operand:SI 2 "general_operand" "r")))]
2325: "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
2326: "* return AS2 (imul%L0,%2,%0);")
2327:
2328: (define_insn "mulsi3"
2329: [(set (match_operand:SI 0 "general_operand" "=r,r")
2330: (mult:SI (match_operand:SI 1 "general_operand" "%0,rm")
2331: (match_operand:SI 2 "general_operand" "g,i")))]
2332: ""
2333: "*
2334: {
2335: if (GET_CODE (operands[1]) == REG
2336: && REGNO (operands[1]) == REGNO (operands[0])
2337: && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
2338: /* Assembler has weird restrictions. */
2339: return AS2 (imul%L0,%2,%0);
2340: return AS3 (imul%L0,%2,%1,%0);
2341: }")
2342:
2343: (define_insn ""
2344: [(set (match_operand:HI 0 "general_operand" "=a")
2345: (mult:SI (zero_extend:HI
2346: (match_operand:QI 1 "nonimmediate_operand" "%0"))
2347: (zero_extend:HI
2348: (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
2349: ""
2350: "mul%B0 %2")
2351:
2352: ;; The patterns that match these are at the end of this file.
2353:
1.1.1.2 ! root 2354: (define_expand "mulxf3"
! 2355: [(set (match_operand:XF 0 "register_operand" "")
! 2356: (mult:XF (match_operand:XF 1 "nonimmediate_operand" "")
! 2357: (match_operand:XF 2 "nonimmediate_operand" "")))]
! 2358: "TARGET_80387"
! 2359: "")
! 2360:
1.1 root 2361: (define_expand "muldf3"
2362: [(set (match_operand:DF 0 "register_operand" "")
2363: (mult:DF (match_operand:DF 1 "nonimmediate_operand" "")
2364: (match_operand:DF 2 "nonimmediate_operand" "")))]
2365: "TARGET_80387"
2366: "")
2367:
2368: (define_expand "mulsf3"
2369: [(set (match_operand:SF 0 "register_operand" "")
2370: (mult:SF (match_operand:SF 1 "nonimmediate_operand" "")
2371: (match_operand:SF 2 "nonimmediate_operand" "")))]
2372: "TARGET_80387"
2373: "")
2374:
2375: ;;- divide instructions
2376:
2377: (define_insn "divqi3"
2378: [(set (match_operand:QI 0 "general_operand" "=a")
2379: (div:QI (match_operand:HI 1 "general_operand" "0")
2380: (match_operand:QI 2 "general_operand" "qm")))]
2381: ""
2382: "idiv%B0 %2")
2383:
2384: (define_insn "udivqi3"
2385: [(set (match_operand:QI 0 "general_operand" "=a")
2386: (udiv:QI (match_operand:HI 1 "general_operand" "0")
2387: (match_operand:QI 2 "general_operand" "qm")))]
2388: ""
2389: "div%B0 %2")
2390:
2391: ;; The patterns that match these are at the end of this file.
2392:
1.1.1.2 ! root 2393: (define_expand "divxf3"
! 2394: [(set (match_operand:XF 0 "register_operand" "")
! 2395: (div:XF (match_operand:XF 1 "nonimmediate_operand" "")
! 2396: (match_operand:XF 2 "nonimmediate_operand" "")))]
! 2397: "TARGET_80387"
! 2398: "")
! 2399:
1.1 root 2400: (define_expand "divdf3"
2401: [(set (match_operand:DF 0 "register_operand" "")
2402: (div:DF (match_operand:DF 1 "nonimmediate_operand" "")
2403: (match_operand:DF 2 "nonimmediate_operand" "")))]
2404: "TARGET_80387"
2405: "")
2406:
2407: (define_expand "divsf3"
2408: [(set (match_operand:SF 0 "register_operand" "")
2409: (div:SF (match_operand:SF 1 "nonimmediate_operand" "")
2410: (match_operand:SF 2 "nonimmediate_operand" "")))]
2411: "TARGET_80387"
2412: "")
2413:
2414: ;; Remainder instructions.
2415:
2416: (define_insn "divmodsi4"
2417: [(set (match_operand:SI 0 "register_operand" "=a")
2418: (div:SI (match_operand:SI 1 "register_operand" "0")
2419: (match_operand:SI 2 "general_operand" "rm")))
2420: (set (match_operand:SI 3 "register_operand" "=&d")
2421: (mod:SI (match_dup 1) (match_dup 2)))]
2422: ""
2423: "*
2424: {
2425: #ifdef INTEL_SYNTAX
2426: output_asm_insn (\"cdq\", operands);
2427: #else
2428: output_asm_insn (\"cltd\", operands);
2429: #endif
2430: return AS1 (idiv%L0,%2);
2431: }")
2432:
2433: (define_insn "divmodhi4"
2434: [(set (match_operand:HI 0 "register_operand" "=a")
2435: (div:HI (match_operand:HI 1 "register_operand" "0")
2436: (match_operand:HI 2 "general_operand" "rm")))
2437: (set (match_operand:HI 3 "register_operand" "=&d")
2438: (mod:HI (match_dup 1) (match_dup 2)))]
2439: ""
2440: "cwtd\;idiv%W0 %2")
2441:
2442: ;; ??? Can we make gcc zero extend operand[0]?
2443: (define_insn "udivmodsi4"
2444: [(set (match_operand:SI 0 "register_operand" "=a")
2445: (udiv:SI (match_operand:SI 1 "register_operand" "0")
2446: (match_operand:SI 2 "general_operand" "rm")))
2447: (set (match_operand:SI 3 "register_operand" "=&d")
2448: (umod:SI (match_dup 1) (match_dup 2)))]
2449: ""
2450: "*
2451: {
2452: output_asm_insn (AS2 (xor%L3,%3,%3), operands);
2453: return AS1 (div%L0,%2);
2454: }")
2455:
2456: ;; ??? Can we make gcc zero extend operand[0]?
2457: (define_insn "udivmodhi4"
2458: [(set (match_operand:HI 0 "register_operand" "=a")
2459: (udiv:HI (match_operand:HI 1 "register_operand" "0")
2460: (match_operand:HI 2 "general_operand" "rm")))
2461: (set (match_operand:HI 3 "register_operand" "=&d")
2462: (umod:HI (match_dup 1) (match_dup 2)))]
2463: ""
2464: "*
2465: {
2466: output_asm_insn (AS2 (xor%W0,%3,%3), operands);
2467: return AS1 (div%W0,%2);
2468: }")
2469:
2470: /*
2471: ;;this should be a valid double division which we may want to add
2472:
2473: (define_insn ""
2474: [(set (match_operand:SI 0 "register_operand" "=a")
2475: (udiv:DI (match_operand:DI 1 "register_operand" "a")
2476: (match_operand:SI 2 "general_operand" "rm")))
2477: (set (match_operand:SI 3 "register_operand" "=d")
2478: (umod:SI (match_dup 1) (match_dup 2)))]
2479: ""
2480: "div%L0 %2,%0")
2481: */
2482:
2483: ;;- and instructions
2484:
2485: ;; On i386,
2486: ;; movzbl %bl,%ebx
2487: ;; is faster than
2488: ;; andl $255,%ebx
2489: ;;
2490: ;; but if the reg is %eax, then the "andl" is faster.
2491: ;;
2492: ;; On i486, the "andl" is always faster than the "movzbl".
2493: ;;
2494: ;; On both i386 and i486, a three operand AND is as fast with movzbl or
2495: ;; movzwl as with andl, if operands[0] != operands[1].
2496:
2497: ;; The `r' in `rm' for operand 3 looks redundant, but it causes
2498: ;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
2499:
2500: ;; ??? What if we only change one byte of an offsettable memory reference?
2501: (define_insn "andsi3"
2502: [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r")
2503: (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0")
2504: (match_operand:SI 2 "general_operand" "L,K,ri,rm")))]
2505: ""
2506: "*
2507: {
2508: if (GET_CODE (operands[2]) == CONST_INT
2509: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
2510: {
2511: if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0])
2512: && (! REG_P (operands[1])
2513: || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
2514: && (! TARGET_486 || ! rtx_equal_p (operands[0], operands[1])))
2515: {
2516: /* ??? tege: Should forget CC_STATUS only if we clobber a
2517: remembered operand. Fix that later. */
2518: CC_STATUS_INIT;
2519: #ifdef INTEL_SYNTAX
2520: return AS2 (movzx,%w1,%0);
2521: #else
2522: return AS2 (movz%W0%L0,%w1,%0);
2523: #endif
2524: }
2525:
2526: if (INTVAL (operands[2]) == 0xff && REG_P (operands[0])
2527: && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
2528: && (! REG_P (operands[1])
2529: || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
2530: && (! TARGET_486 || ! rtx_equal_p (operands[0], operands[1])))
2531: {
2532: /* ??? tege: Should forget CC_STATUS only if we clobber a
2533: remembered operand. Fix that later. */
2534: CC_STATUS_INIT;
2535: #ifdef INTEL_SYNTAX
2536: return AS2 (movzx,%b1,%0);
2537: #else
2538: return AS2 (movz%B0%L0,%b1,%0);
2539: #endif
2540: }
2541:
2542: if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0)
2543: {
2544: CC_STATUS_INIT;
2545:
2546: if (INTVAL (operands[2]) == 0xffffff00)
2547: {
2548: operands[2] = const0_rtx;
2549: return AS2 (mov%B0,%2,%b0);
2550: }
2551:
2552: operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
2553: return AS2 (and%B0,%2,%b0);
2554: }
2555:
2556: if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0)
2557: {
2558: CC_STATUS_INIT;
2559:
2560: if (INTVAL (operands[2]) == 0xffff00ff)
2561: {
2562: operands[2] = const0_rtx;
2563: return AS2 (mov%B0,%2,%h0);
2564: }
2565:
2566: operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
2567: return AS2 (and%B0,%2,%h0);
2568: }
2569:
2570: if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000)
2571: {
2572: operands[2] = const0_rtx;
2573: return AS2 (mov%W0,%2,%w0);
2574: }
2575: }
2576:
2577: return AS2 (and%L0,%2,%0);
2578: }")
2579:
2580: (define_insn "andhi3"
2581: [(set (match_operand:HI 0 "general_operand" "=rm,r")
2582: (and:HI (match_operand:HI 1 "general_operand" "%0,0")
2583: (match_operand:HI 2 "general_operand" "ri,rm")))]
2584: ""
2585: "*
2586: {
2587: if (GET_CODE (operands[2]) == CONST_INT
2588: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
2589: {
2590: /* Can we ignore the upper byte? */
2591: if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
2592: && (INTVAL (operands[2]) & 0xff00) == 0xff00)
2593: {
2594: CC_STATUS_INIT;
2595:
2596: if ((INTVAL (operands[2]) & 0xff) == 0)
2597: {
2598: operands[2] = const0_rtx;
2599: return AS2 (mov%B0,%2,%b0);
2600: }
2601:
2602: operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
2603: return AS2 (and%B0,%2,%b0);
2604: }
2605:
2606: /* Can we ignore the lower byte? */
2607: /* ??? what about offsettable memory references? */
2608: if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff)
2609: {
2610: CC_STATUS_INIT;
2611:
2612: if ((INTVAL (operands[2]) & 0xff00) == 0)
2613: {
2614: operands[2] = const0_rtx;
2615: return AS2 (mov%B0,%2,%h0);
2616: }
2617:
2618: operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
2619: return AS2 (and%B0,%2,%h0);
2620: }
2621: }
2622:
2623: return AS2 (and%W0,%2,%0);
2624: }")
2625:
2626: (define_insn "andqi3"
2627: [(set (match_operand:QI 0 "general_operand" "=qm,q")
2628: (and:QI (match_operand:QI 1 "general_operand" "%0,0")
2629: (match_operand:QI 2 "general_operand" "qn,qmn")))]
2630: ""
2631: "* return AS2 (and%B0,%2,%0);")
2632:
2633: /* I am nervous about these two.. add them later..
2634: ;I presume this means that we have something in say op0= eax which is small
2635: ;and we want to and it with memory so we can do this by just an
2636: ;andb m,%al and have success.
2637: (define_insn ""
2638: [(set (match_operand:SI 0 "general_operand" "=r")
2639: (and:SI (zero_extend:SI
2640: (match_operand:HI 1 "nonimmediate_operand" "rm"))
2641: (match_operand:SI 2 "general_operand" "0")))]
2642: "GET_CODE (operands[2]) == CONST_INT
2643: && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
2644: "and%W0 %1,%0")
2645:
2646: (define_insn ""
2647: [(set (match_operand:SI 0 "general_operand" "=q")
2648: (and:SI
2649: (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))
2650: (match_operand:SI 2 "general_operand" "0")))]
2651: "GET_CODE (operands[2]) == CONST_INT
2652: && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
2653: "and%L0 %1,%0")
2654:
2655: */
2656:
2657: ;;- Bit set (inclusive or) instructions
2658:
2659: ;; ??? What if we only change one byte of an offsettable memory reference?
2660: (define_insn "iorsi3"
2661: [(set (match_operand:SI 0 "general_operand" "=rm,r")
2662: (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
2663: (match_operand:SI 2 "general_operand" "ri,rm")))]
2664: ""
2665: "*
2666: {
2667: if (GET_CODE (operands[2]) == CONST_INT
2668: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
2669: {
2670: if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
2671: && (INTVAL (operands[2]) & ~0xff) == 0)
2672: {
2673: CC_STATUS_INIT;
2674:
2675: if (INTVAL (operands[2]) == 0xff)
2676: return AS2 (mov%B0,%2,%b0);
2677:
2678: return AS2 (or%B0,%2,%b0);
2679: }
2680:
2681: if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
2682: {
2683: CC_STATUS_INIT;
2684: operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
2685:
2686: if (INTVAL (operands[2]) == 0xff)
2687: return AS2 (mov%B0,%2,%h0);
2688:
2689: return AS2 (or%B0,%2,%h0);
2690: }
2691: }
2692:
2693: return AS2 (or%L0,%2,%0);
2694: }")
2695:
2696: (define_insn "iorhi3"
2697: [(set (match_operand:HI 0 "general_operand" "=rm,r")
2698: (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
2699: (match_operand:HI 2 "general_operand" "ri,rm")))]
2700: ""
2701: "*
2702: {
2703: if (GET_CODE (operands[2]) == CONST_INT
2704: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
2705: {
2706: /* Can we ignore the upper byte? */
2707: if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
2708: && (INTVAL (operands[2]) & 0xff00) == 0)
2709: {
2710: CC_STATUS_INIT;
2711: if (INTVAL (operands[2]) & 0xffff0000)
2712: operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
2713:
2714: if (INTVAL (operands[2]) == 0xff)
2715: return AS2 (mov%B0,%2,%b0);
2716:
2717: return AS2 (or%B0,%2,%b0);
2718: }
2719:
2720: /* Can we ignore the lower byte? */
2721: /* ??? what about offsettable memory references? */
2722: if (QI_REG_P (operands[0])
2723: && (INTVAL (operands[2]) & 0xff) == 0)
2724: {
2725: CC_STATUS_INIT;
2726: operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
2727:
2728: if (INTVAL (operands[2]) == 0xff)
2729: return AS2 (mov%B0,%2,%h0);
2730:
2731: return AS2 (or%B0,%2,%h0);
2732: }
2733: }
2734:
2735: return AS2 (or%W0,%2,%0);
2736: }")
2737:
2738: (define_insn "iorqi3"
2739: [(set (match_operand:QI 0 "general_operand" "=qm,q")
2740: (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
2741: (match_operand:QI 2 "general_operand" "qn,qmn")))]
2742: ""
2743: "* return AS2 (or%B0,%2,%0);")
2744:
2745: ;;- xor instructions
2746:
2747: ;; ??? What if we only change one byte of an offsettable memory reference?
2748: (define_insn "xorsi3"
2749: [(set (match_operand:SI 0 "general_operand" "=rm,r")
2750: (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
2751: (match_operand:SI 2 "general_operand" "ri,rm")))]
2752: ""
2753: "*
2754: {
2755: if (GET_CODE (operands[2]) == CONST_INT
2756: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
2757: {
2758: if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
2759: && (INTVAL (operands[2]) & ~0xff) == 0)
2760: {
2761: CC_STATUS_INIT;
2762:
2763: if (INTVAL (operands[2]) == 0xff)
2764: return AS1 (not%B0,%b0);
2765:
2766: return AS2 (xor%B0,%2,%b0);
2767: }
2768:
2769: if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
2770: {
2771: CC_STATUS_INIT;
2772: operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
2773:
2774: if (INTVAL (operands[2]) == 0xff)
2775: return AS1 (not%B0,%h0);
2776:
2777: return AS2 (xor%B0,%2,%h0);
2778: }
2779: }
2780:
2781: return AS2 (xor%L0,%2,%0);
2782: }")
2783:
2784: (define_insn "xorhi3"
2785: [(set (match_operand:HI 0 "general_operand" "=rm,r")
2786: (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
2787: (match_operand:HI 2 "general_operand" "ri,rm")))]
2788: ""
2789: "*
2790: {
2791: if (GET_CODE (operands[2]) == CONST_INT
2792: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
2793: {
2794: /* Can we ignore the upper byte? */
2795: if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
2796: && (INTVAL (operands[2]) & 0xff00) == 0)
2797: {
2798: CC_STATUS_INIT;
2799: if (INTVAL (operands[2]) & 0xffff0000)
2800: operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
2801:
2802: if (INTVAL (operands[2]) == 0xff)
2803: return AS1 (not%B0,%b0);
2804:
2805: return AS2 (xor%B0,%2,%b0);
2806: }
2807:
2808: /* Can we ignore the lower byte? */
2809: /* ??? what about offsettable memory references? */
2810: if (QI_REG_P (operands[0])
2811: && (INTVAL (operands[2]) & 0xff) == 0)
2812: {
2813: CC_STATUS_INIT;
2814: operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
2815:
2816: if (INTVAL (operands[2]) == 0xff)
2817: return AS1 (not%B0,%h0);
2818:
2819: return AS2 (xor%B0,%2,%h0);
2820: }
2821: }
2822:
2823: return AS2 (xor%W0,%2,%0);
2824: }")
2825:
2826: (define_insn "xorqi3"
2827: [(set (match_operand:QI 0 "general_operand" "=qm,q")
2828: (xor:QI (match_operand:QI 1 "general_operand" "%0,0")
2829: (match_operand:QI 2 "general_operand" "qn,qm")))]
2830: ""
2831: "* return AS2 (xor%B0,%2,%0);")
2832:
2833: ;;- negation instructions
2834:
2835: (define_insn "negdi2"
2836: [(set (match_operand:DI 0 "general_operand" "=&ro")
2837: (neg:DI (match_operand:DI 1 "general_operand" "0")))]
2838: ""
2839: "*
2840: {
2841: rtx xops[2], low[1], high[1];
2842:
2843: CC_STATUS_INIT;
2844:
2845: split_di (operands, 1, low, high);
2846: xops[0] = const0_rtx;
2847: xops[1] = high[0];
2848:
2849: output_asm_insn (AS1 (neg%L0,%0), low);
2850: output_asm_insn (AS2 (adc%L1,%0,%1), xops);
2851: output_asm_insn (AS1 (neg%L0,%0), high);
2852: RET;
2853: }")
2854:
2855: (define_insn "negsi2"
2856: [(set (match_operand:SI 0 "general_operand" "=rm")
2857: (neg:SI (match_operand:SI 1 "general_operand" "0")))]
2858: ""
2859: "neg%L0 %0")
2860:
2861: (define_insn "neghi2"
2862: [(set (match_operand:HI 0 "general_operand" "=rm")
2863: (neg:HI (match_operand:HI 1 "general_operand" "0")))]
2864: ""
2865: "neg%W0 %0")
2866:
2867: (define_insn "negqi2"
2868: [(set (match_operand:QI 0 "general_operand" "=qm")
2869: (neg:QI (match_operand:QI 1 "general_operand" "0")))]
2870: ""
2871: "neg%B0 %0")
2872:
2873: (define_insn "negsf2"
2874: [(set (match_operand:SF 0 "register_operand" "=f")
2875: (neg:SF (match_operand:SF 1 "general_operand" "0")))]
2876: "TARGET_80387"
2877: "fchs")
2878:
2879: (define_insn "negdf2"
2880: [(set (match_operand:DF 0 "register_operand" "=f")
2881: (neg:DF (match_operand:DF 1 "general_operand" "0")))]
2882: "TARGET_80387"
2883: "fchs")
2884:
2885: (define_insn ""
2886: [(set (match_operand:DF 0 "register_operand" "=f")
2887: (neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
2888: "TARGET_80387"
2889: "fchs")
1.1.1.2 ! root 2890:
! 2891: (define_insn "negxf2"
! 2892: [(set (match_operand:XF 0 "register_operand" "=f")
! 2893: (neg:XF (match_operand:XF 1 "general_operand" "0")))]
! 2894: "TARGET_80387"
! 2895: "fchs")
! 2896:
! 2897: (define_insn ""
! 2898: [(set (match_operand:XF 0 "register_operand" "=f")
! 2899: (neg:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
! 2900: "TARGET_80387"
! 2901: "fchs")
1.1 root 2902:
2903: ;; Absolute value instructions
2904:
2905: (define_insn "abssf2"
2906: [(set (match_operand:SF 0 "register_operand" "=f")
2907: (abs:SF (match_operand:SF 1 "general_operand" "0")))]
2908: "TARGET_80387"
2909: "fabs")
2910:
2911: (define_insn "absdf2"
2912: [(set (match_operand:DF 0 "register_operand" "=f")
2913: (abs:DF (match_operand:DF 1 "general_operand" "0")))]
2914: "TARGET_80387"
2915: "fabs")
2916:
2917: (define_insn ""
2918: [(set (match_operand:DF 0 "register_operand" "=f")
2919: (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
2920: "TARGET_80387"
2921: "fabs")
2922:
1.1.1.2 ! root 2923: (define_insn "absxf2"
! 2924: [(set (match_operand:XF 0 "register_operand" "=f")
! 2925: (abs:XF (match_operand:XF 1 "general_operand" "0")))]
! 2926: "TARGET_80387"
! 2927: "fabs")
! 2928:
! 2929: (define_insn ""
! 2930: [(set (match_operand:XF 0 "register_operand" "=f")
! 2931: (abs:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
! 2932: "TARGET_80387"
! 2933: "fabs")
! 2934:
1.1 root 2935: (define_insn "sqrtsf2"
2936: [(set (match_operand:SF 0 "register_operand" "=f")
2937: (sqrt:SF (match_operand:SF 1 "general_operand" "0")))]
2938: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
2939: "fsqrt")
2940:
2941: (define_insn "sqrtdf2"
2942: [(set (match_operand:DF 0 "register_operand" "=f")
2943: (sqrt:DF (match_operand:DF 1 "general_operand" "0")))]
2944: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
2945: "fsqrt")
2946:
2947: (define_insn ""
2948: [(set (match_operand:DF 0 "register_operand" "=f")
2949: (sqrt:DF (float_extend:DF
2950: (match_operand:SF 1 "general_operand" "0"))))]
2951: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
2952: "fsqrt")
2953:
1.1.1.2 ! root 2954: (define_insn "sqrtxf2"
! 2955: [(set (match_operand:XF 0 "register_operand" "=f")
! 2956: (sqrt:XF (match_operand:XF 1 "general_operand" "0")))]
! 2957: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
! 2958: "fsqrt")
! 2959:
! 2960: (define_insn ""
! 2961: [(set (match_operand:XF 0 "register_operand" "=f")
! 2962: (sqrt:XF (float_extend:XF
! 2963: (match_operand:DF 1 "general_operand" "0"))))]
! 2964: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
! 2965: "fsqrt")
! 2966:
! 2967: (define_insn ""
! 2968: [(set (match_operand:XF 0 "register_operand" "=f")
! 2969: (sqrt:XF (float_extend:XF
! 2970: (match_operand:SF 1 "general_operand" "0"))))]
! 2971: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
! 2972: "fsqrt")
! 2973:
1.1 root 2974: (define_insn "sindf2"
2975: [(set (match_operand:DF 0 "register_operand" "=f")
2976: (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
2977: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
2978: "fsin")
2979:
2980: (define_insn "sinsf2"
2981: [(set (match_operand:SF 0 "register_operand" "=f")
2982: (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
2983: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
2984: "fsin")
2985:
2986: (define_insn ""
2987: [(set (match_operand:DF 0 "register_operand" "=f")
2988: (unspec:DF [(float_extend:DF
2989: (match_operand:SF 1 "register_operand" "0"))] 1))]
2990: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
2991: "fsin")
2992:
2993: (define_insn "cosdf2"
2994: [(set (match_operand:DF 0 "register_operand" "=f")
2995: (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
2996: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
2997: "fcos")
2998:
2999: (define_insn "cossf2"
3000: [(set (match_operand:SF 0 "register_operand" "=f")
3001: (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
3002: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
3003: "fcos")
3004:
3005: (define_insn ""
3006: [(set (match_operand:DF 0 "register_operand" "=f")
3007: (unspec:DF [(float_extend:DF
3008: (match_operand:SF 1 "register_operand" "0"))] 2))]
3009: "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
3010: "fcos")
3011:
3012: ;;- one complement instructions
3013:
3014: (define_insn "one_cmplsi2"
3015: [(set (match_operand:SI 0 "general_operand" "=rm")
3016: (not:SI (match_operand:SI 1 "general_operand" "0")))]
3017: ""
3018: "not%L0 %0")
3019:
3020: (define_insn "one_cmplhi2"
3021: [(set (match_operand:HI 0 "general_operand" "=rm")
3022: (not:HI (match_operand:HI 1 "general_operand" "0")))]
3023: ""
3024: "not%W0 %0")
3025:
3026: (define_insn "one_cmplqi2"
3027: [(set (match_operand:QI 0 "general_operand" "=qm")
3028: (not:QI (match_operand:QI 1 "general_operand" "0")))]
3029: ""
3030: "not%B0 %0")
3031:
3032: ;;- arithmetic shift instructions
3033:
3034: ;; DImode shifts are implemented using the i386 "shift double" opcode,
3035: ;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count
3036: ;; is variable, then the count is in %cl and the "imm" operand is dropped
3037: ;; from the assembler input.
3038:
3039: ;; This instruction shifts the target reg/mem as usual, but instead of
3040: ;; shifting in zeros, bits are shifted in from reg operand. If the insn
3041: ;; is a left shift double, bits are taken from the high order bits of
3042: ;; reg, else if the insn is a shift right double, bits are taken from the
3043: ;; low order bits of reg. So if %eax is "1234" and %edx is "5678",
3044: ;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
3045:
3046: ;; Since sh[lr]d does not change the `reg' operand, that is done
3047: ;; separately, making all shifts emit pairs of shift double and normal
3048: ;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to
3049: ;; support a 63 bit shift, each shift where the count is in a reg expands
3050: ;; to three pairs. If the overall shift is by N bits, then the first two
3051: ;; pairs shift by N / 2 and the last pair by N & 1.
3052:
3053: ;; If the shift count is a constant, we need never emit more than one
3054: ;; shift pair, instead using moves and sign extension for counts greater
3055: ;; than 31.
3056:
3057: (define_expand "ashldi3"
3058: [(set (match_operand:DI 0 "register_operand" "")
3059: (ashift:DI (match_operand:DI 1 "register_operand" "")
3060: (match_operand:QI 2 "nonmemory_operand" "")))]
3061: ""
3062: "
3063: {
3064: if (GET_CODE (operands[2]) != CONST_INT
3065: || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
3066: {
3067: operands[2] = copy_to_mode_reg (QImode, operands[2]);
3068: emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1],
3069: operands[2]));
3070: }
3071: else
3072: emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2]));
3073:
3074: DONE;
3075: }")
3076:
3077: (define_insn "ashldi3_const_int"
3078: [(set (match_operand:DI 0 "register_operand" "=&r")
3079: (ashift:DI (match_operand:DI 1 "register_operand" "0")
3080: (match_operand:QI 2 "const_int_operand" "J")))]
3081: ""
3082: "*
3083: {
3084: rtx xops[4], low[1], high[1];
3085:
3086: CC_STATUS_INIT;
3087:
3088: split_di (operands, 1, low, high);
3089: xops[0] = operands[2];
3090: xops[1] = const1_rtx;
3091: xops[2] = low[0];
3092: xops[3] = high[0];
3093:
3094: if (INTVAL (xops[0]) > 31)
3095: {
3096: output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */
3097: output_asm_insn (AS2 (xor%L2,%2,%2), xops);
3098:
3099: if (INTVAL (xops[0]) > 32)
3100: {
3101: xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
3102: output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */
3103: }
3104: }
3105: else
3106: {
3107: output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops);
3108: output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3109: }
3110: RET;
3111: }")
3112:
3113: (define_insn "ashldi3_non_const_int"
3114: [(set (match_operand:DI 0 "register_operand" "=&r")
3115: (ashift:DI (match_operand:DI 1 "register_operand" "0")
3116: (match_operand:QI 2 "register_operand" "c")))
3117: (clobber (match_dup 2))]
3118: ""
3119: "*
3120: {
3121: rtx xops[4], low[1], high[1];
3122:
3123: CC_STATUS_INIT;
3124:
3125: split_di (operands, 1, low, high);
3126: xops[0] = operands[2];
3127: xops[1] = const1_rtx;
3128: xops[2] = low[0];
3129: xops[3] = high[0];
3130:
3131: output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */
3132:
3133: output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
3134: output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3135: output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
3136: output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3137:
3138: xops[1] = GEN_INT (7); /* shift count & 1 */
3139:
3140: output_asm_insn (AS2 (shr%B0,%1,%0), xops);
3141:
3142: output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
3143: output_asm_insn (AS2 (sal%L2,%0,%2), xops);
3144:
3145: RET;
3146: }")
3147:
3148: ;; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg"
3149: ;; On i486, movl/sall appears slightly faster than leal, but the leal
3150: ;; is smaller - use leal for now unless the shift count is 1.
3151:
3152: (define_insn "ashlsi3"
3153: [(set (match_operand:SI 0 "general_operand" "=r,rm")
3154: (ashift:SI (match_operand:SI 1 "general_operand" "r,0")
3155: (match_operand:SI 2 "nonmemory_operand" "M,cI")))]
3156: ""
3157: "*
3158: {
3159: if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
3160: {
3161: if (TARGET_486 && INTVAL (operands[2]) == 1)
3162: {
3163: output_asm_insn (AS2 (mov%L0,%1,%0), operands);
3164: return AS2 (add%L0,%1,%0);
3165: }
3166: else
3167: {
3168: CC_STATUS_INIT;
3169:
3170: if (operands[1] == stack_pointer_rtx)
3171: {
3172: output_asm_insn (AS2 (mov%L0,%1,%0), operands);
3173: operands[1] = operands[0];
3174: }
3175: operands[1] = gen_rtx (MULT, SImode, operands[1],
3176: GEN_INT (1 << INTVAL (operands[2])));
3177: return AS2 (lea%L0,%a1,%0);
3178: }
3179: }
3180:
3181: if (REG_P (operands[2]))
3182: return AS2 (sal%L0,%b2,%0);
3183:
3184: if (REG_P (operands[0]) && operands[2] == const1_rtx)
3185: return AS2 (add%L0,%0,%0);
3186:
3187: return AS2 (sal%L0,%2,%0);
3188: }")
3189:
3190: (define_insn "ashlhi3"
3191: [(set (match_operand:HI 0 "general_operand" "=rm")
3192: (ashift:HI (match_operand:HI 1 "general_operand" "0")
3193: (match_operand:HI 2 "nonmemory_operand" "cI")))]
3194: ""
3195: "*
3196: {
3197: if (REG_P (operands[2]))
3198: return AS2 (sal%W0,%b2,%0);
3199:
3200: if (REG_P (operands[0]) && operands[2] == const1_rtx)
3201: return AS2 (add%W0,%0,%0);
3202:
3203: return AS2 (sal%W0,%2,%0);
3204: }")
3205:
3206: (define_insn "ashlqi3"
3207: [(set (match_operand:QI 0 "general_operand" "=qm")
3208: (ashift:QI (match_operand:QI 1 "general_operand" "0")
3209: (match_operand:QI 2 "nonmemory_operand" "cI")))]
3210: ""
3211: "*
3212: {
3213: if (REG_P (operands[2]))
3214: return AS2 (sal%B0,%b2,%0);
3215:
3216: if (REG_P (operands[0]) && operands[2] == const1_rtx)
3217: return AS2 (add%B0,%0,%0);
3218:
3219: return AS2 (sal%B0,%2,%0);
3220: }")
3221:
3222: ;; See comment above `ashldi3' about how this works.
3223:
3224: (define_expand "ashrdi3"
3225: [(set (match_operand:DI 0 "register_operand" "")
3226: (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
3227: (match_operand:QI 2 "nonmemory_operand" "")))]
3228: ""
3229: "
3230: {
3231: if (GET_CODE (operands[2]) != CONST_INT
3232: || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
3233: {
3234: operands[2] = copy_to_mode_reg (QImode, operands[2]);
3235: emit_insn (gen_ashrdi3_non_const_int (operands[0], operands[1],
3236: operands[2]));
3237: }
3238: else
3239: emit_insn (gen_ashrdi3_const_int (operands[0], operands[1], operands[2]));
3240:
3241: DONE;
3242: }")
3243:
3244: (define_insn "ashrdi3_const_int"
3245: [(set (match_operand:DI 0 "register_operand" "=&r")
3246: (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
3247: (match_operand:QI 2 "const_int_operand" "J")))]
3248: ""
3249: "*
3250: {
3251: rtx xops[4], low[1], high[1];
3252:
3253: CC_STATUS_INIT;
3254:
3255: split_di (operands, 1, low, high);
3256: xops[0] = operands[2];
3257: xops[1] = const1_rtx;
3258: xops[2] = low[0];
3259: xops[3] = high[0];
3260:
3261: if (INTVAL (xops[0]) > 31)
3262: {
3263: xops[1] = GEN_INT (31);
3264: output_asm_insn (AS2 (mov%L2,%3,%2), xops);
3265: output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */
3266:
3267: if (INTVAL (xops[0]) > 32)
3268: {
3269: xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
3270: output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */
3271: }
3272: }
3273: else
3274: {
3275: output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
3276: output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3277: }
3278:
3279: RET;
3280: }")
3281:
3282: (define_insn "ashrdi3_non_const_int"
3283: [(set (match_operand:DI 0 "register_operand" "=&r")
3284: (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
3285: (match_operand:QI 2 "register_operand" "c")))
3286: (clobber (match_dup 2))]
3287: ""
3288: "*
3289: {
3290: rtx xops[4], low[1], high[1];
3291:
3292: CC_STATUS_INIT;
3293:
3294: split_di (operands, 1, low, high);
3295: xops[0] = operands[2];
3296: xops[1] = const1_rtx;
3297: xops[2] = low[0];
3298: xops[3] = high[0];
3299:
3300: output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */
3301:
3302: output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3303: output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3304: output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3305: output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3306:
3307: xops[1] = GEN_INT (7); /* shift count & 1 */
3308:
3309: output_asm_insn (AS2 (shr%B0,%1,%0), xops);
3310:
3311: output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3312: output_asm_insn (AS2 (sar%L3,%0,%3), xops);
3313:
3314: RET;
3315: }")
3316:
3317: (define_insn "ashrsi3"
3318: [(set (match_operand:SI 0 "general_operand" "=rm")
3319: (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
3320: (match_operand:SI 2 "nonmemory_operand" "cI")))]
3321: ""
3322: "*
3323: {
3324: if (REG_P (operands[2]))
3325: return AS2 (sar%L0,%b2,%0);
3326: else
3327: return AS2 (sar%L0,%2,%0);
3328: }")
3329:
3330: (define_insn "ashrhi3"
3331: [(set (match_operand:HI 0 "general_operand" "=rm")
3332: (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
3333: (match_operand:HI 2 "nonmemory_operand" "cI")))]
3334: ""
3335: "*
3336: {
3337: if (REG_P (operands[2]))
3338: return AS2 (sar%W0,%b2,%0);
3339: else
3340: return AS2 (sar%W0,%2,%0);
3341: }")
3342:
3343: (define_insn "ashrqi3"
3344: [(set (match_operand:QI 0 "general_operand" "=qm")
3345: (ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
3346: (match_operand:QI 2 "nonmemory_operand" "cI")))]
3347: ""
3348: "*
3349: {
3350: if (REG_P (operands[2]))
3351: return AS2 (sar%B0,%b2,%0);
3352: else
3353: return AS2 (sar%B0,%2,%0);
3354: }")
3355:
3356: ;;- logical shift instructions
3357:
3358: ;; See comment above `ashldi3' about how this works.
3359:
3360: (define_expand "lshrdi3"
3361: [(set (match_operand:DI 0 "register_operand" "")
3362: (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
3363: (match_operand:QI 2 "nonmemory_operand" "")))]
3364: ""
3365: "
3366: {
3367: if (GET_CODE (operands[2]) != CONST_INT
3368: || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
3369: {
3370: operands[2] = copy_to_mode_reg (QImode, operands[2]);
3371: emit_insn (gen_lshrdi3_non_const_int (operands[0], operands[1],
3372: operands[2]));
3373: }
3374: else
3375: emit_insn (gen_lshrdi3_const_int (operands[0], operands[1], operands[2]));
3376:
3377: DONE;
3378: }")
3379:
3380: (define_insn "lshrdi3_const_int"
3381: [(set (match_operand:DI 0 "register_operand" "=&r")
3382: (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
3383: (match_operand:QI 2 "const_int_operand" "J")))]
3384: ""
3385: "*
3386: {
3387: rtx xops[4], low[1], high[1];
3388:
3389: CC_STATUS_INIT;
3390:
3391: split_di (operands, 1, low, high);
3392: xops[0] = operands[2];
3393: xops[1] = const1_rtx;
3394: xops[2] = low[0];
3395: xops[3] = high[0];
3396:
3397: if (INTVAL (xops[0]) > 31)
3398: {
3399: output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */
3400: output_asm_insn (AS2 (xor%L3,%3,%3), xops);
3401:
3402: if (INTVAL (xops[0]) > 32)
3403: {
3404: xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
3405: output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */
3406: }
3407: }
3408: else
3409: {
3410: output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
3411: output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3412: }
3413:
3414: RET;
3415: }")
3416:
3417: (define_insn "lshrdi3_non_const_int"
3418: [(set (match_operand:DI 0 "register_operand" "=&r")
3419: (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
3420: (match_operand:QI 2 "register_operand" "c")))
3421: (clobber (match_dup 2))]
3422: ""
3423: "*
3424: {
3425: rtx xops[4], low[1], high[1];
3426:
3427: CC_STATUS_INIT;
3428:
3429: split_di (operands, 1, low, high);
3430: xops[0] = operands[2];
3431: xops[1] = const1_rtx;
3432: xops[2] = low[0];
3433: xops[3] = high[0];
3434:
3435: output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */
3436:
3437: output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3438: output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3439: output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3440: output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3441:
3442: xops[1] = GEN_INT (7); /* shift count & 1 */
3443:
3444: output_asm_insn (AS2 (shr%B0,%1,%0), xops);
3445:
3446: output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
3447: output_asm_insn (AS2 (shr%L3,%0,%3), xops);
3448:
3449: RET;
3450: }")
3451:
3452: (define_insn "lshrsi3"
3453: [(set (match_operand:SI 0 "general_operand" "=rm")
3454: (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
3455: (match_operand:SI 2 "nonmemory_operand" "cI")))]
3456: ""
3457: "*
3458: {
3459: if (REG_P (operands[2]))
3460: return AS2 (shr%L0,%b2,%0);
3461: else
3462: return AS2 (shr%L0,%2,%1);
3463: }")
3464:
3465: (define_insn "lshrhi3"
3466: [(set (match_operand:HI 0 "general_operand" "=rm")
3467: (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
3468: (match_operand:HI 2 "nonmemory_operand" "cI")))]
3469: ""
3470: "*
3471: {
3472: if (REG_P (operands[2]))
3473: return AS2 (shr%W0,%b2,%0);
3474: else
3475: return AS2 (shr%W0,%2,%0);
3476: }")
3477:
3478: (define_insn "lshrqi3"
3479: [(set (match_operand:QI 0 "general_operand" "=qm")
3480: (lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
3481: (match_operand:QI 2 "nonmemory_operand" "cI")))]
3482: ""
3483: "*
3484: {
3485: if (REG_P (operands[2]))
3486: return AS2 (shr%B0,%b2,%0);
3487: else
3488: return AS2 (shr%B0,%2,%0);
3489: }")
3490:
3491: ;;- rotate instructions
3492:
3493: (define_insn "rotlsi3"
3494: [(set (match_operand:SI 0 "general_operand" "=rm")
3495: (rotate:SI (match_operand:SI 1 "general_operand" "0")
3496: (match_operand:SI 2 "nonmemory_operand" "cI")))]
3497: ""
3498: "*
3499: {
3500: if (REG_P (operands[2]))
3501: return AS2 (rol%L0,%b2,%0);
3502: else
3503: return AS2 (rol%L0,%2,%0);
3504: }")
3505:
3506: (define_insn "rotlhi3"
3507: [(set (match_operand:HI 0 "general_operand" "=rm")
3508: (rotate:HI (match_operand:HI 1 "general_operand" "0")
3509: (match_operand:HI 2 "nonmemory_operand" "cI")))]
3510: ""
3511: "*
3512: {
3513: if (REG_P (operands[2]))
3514: return AS2 (rol%W0,%b2,%0);
3515: else
3516: return AS2 (rol%W0,%2,%0);
3517: }")
3518:
3519: (define_insn "rotlqi3"
3520: [(set (match_operand:QI 0 "general_operand" "=qm")
3521: (rotate:QI (match_operand:QI 1 "general_operand" "0")
3522: (match_operand:QI 2 "nonmemory_operand" "cI")))]
3523: ""
3524: "*
3525: {
3526: if (REG_P (operands[2]))
3527: return AS2 (rol%B0,%b2,%0);
3528: else
3529: return AS2 (rol%B0,%2,%0);
3530: }")
3531:
3532: (define_insn "rotrsi3"
3533: [(set (match_operand:SI 0 "general_operand" "=rm")
3534: (rotatert:SI (match_operand:SI 1 "general_operand" "0")
3535: (match_operand:SI 2 "nonmemory_operand" "cI")))]
3536: ""
3537: "*
3538: {
3539: if (REG_P (operands[2]))
3540: return AS2 (ror%L0,%b2,%0);
3541: else
3542: return AS2 (ror%L0,%2,%0);
3543: }")
3544:
3545: (define_insn "rotrhi3"
3546: [(set (match_operand:HI 0 "general_operand" "=rm")
3547: (rotatert:HI (match_operand:HI 1 "general_operand" "0")
3548: (match_operand:HI 2 "nonmemory_operand" "cI")))]
3549: ""
3550: "*
3551: {
3552: if (REG_P (operands[2]))
3553: return AS2 (ror%W0,%b2,%0);
3554: else
3555: return AS2 (ror%W0,%2,%0);
3556: }")
3557:
3558: (define_insn "rotrqi3"
3559: [(set (match_operand:QI 0 "general_operand" "=qm")
3560: (rotatert:QI (match_operand:QI 1 "general_operand" "0")
3561: (match_operand:QI 2 "nonmemory_operand" "cI")))]
3562: ""
3563: "*
3564: {
3565: if (REG_P (operands[2]))
3566: return AS2 (ror%B0,%b2,%0);
3567: else
3568: return AS2 (ror%B0,%2,%0);
3569: }")
3570:
3571: /*
3572: ;; This usually looses. But try a define_expand to recognize a few case
3573: ;; we can do efficiently, such as accessing the "high" QImode registers,
3574: ;; %ah, %bh, %ch, %dh.
3575: (define_insn "insv"
3576: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r")
3577: (match_operand:SI 1 "general_operand" "i")
3578: (match_operand:SI 2 "general_operand" "i"))
3579: (match_operand:SI 3 "general_operand" "ri"))]
3580: ""
3581: "*
3582: {
3583: if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode))
3584: abort ();
3585: if (GET_CODE (operands[3]) == CONST_INT)
3586: {
3587: unsigned int mask = (1 << INTVAL (operands[1])) - 1;
3588: operands[1] = GEN_INT (~(mask << INTVAL (operands[2])));
3589: output_asm_insn (AS2 (and%L0,%1,%0), operands);
3590: operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2]));
3591: output_asm_insn (AS2 (or%L0,%3,%0), operands);
3592: }
3593: else
3594: {
3595: operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]));
3596: if (INTVAL (operands[2]))
3597: output_asm_insn (AS2 (ror%L0,%2,%0), operands);
3598: output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands);
3599: operands[2] = GEN_INT (BITS_PER_WORD
3600: - INTVAL (operands[1]) - INTVAL (operands[2]));
3601: if (INTVAL (operands[2]))
3602: output_asm_insn (AS2 (ror%L0,%2,%0), operands);
3603: }
3604: RET;
3605: }")
3606: */
3607: /*
3608: ;; ??? There are problems with the mode of operand[3]. The point of this
3609: ;; is to represent an HImode move to a "high byte" register.
3610:
3611: (define_expand "insv"
3612: [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
3613: (match_operand:SI 1 "immediate_operand" "")
3614: (match_operand:SI 2 "immediate_operand" ""))
3615: (match_operand:QI 3 "general_operand" "ri"))]
3616: ""
3617: "
3618: {
3619: if (GET_CODE (operands[1]) != CONST_INT
3620: || GET_CODE (operands[2]) != CONST_INT)
3621: FAIL;
3622:
3623: if (! (INTVAL (operands[1]) == 8
3624: && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0))
3625: && ! INTVAL (operands[1]) == 1)
3626: FAIL;
3627: }")
3628:
3629: ;; ??? Are these constraints right?
3630: (define_insn ""
3631: [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+&qo")
3632: (const_int 8)
3633: (const_int 8))
3634: (match_operand:QI 1 "general_operand" "qn"))]
3635: ""
3636: "*
3637: {
3638: if (REG_P (operands[0]))
3639: return AS2 (mov%B0,%1,%h0);
3640:
3641: operands[0] = adj_offsettable_operand (operands[0], 1);
3642: return AS2 (mov%B0,%1,%0);
3643: }")
3644: */
3645:
3646: ;; On i386, the register count for a bit operation is *not* truncated,
3647: ;; so SHIFT_COUNT_TRUNCATED must not be defined.
3648:
3649: ;; On i486, the shift & or/and code is faster than bts or btr. If
3650: ;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code.
3651:
3652: ;; On i386, bts is a little faster if operands[0] is a reg, and a
3653: ;; little slower if operands[0] is a MEM, than the shift & or/and code.
3654: ;; Use bts & btr, since they reload better.
3655:
3656: ;; General bit set and clear.
3657: (define_insn ""
3658: [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm")
3659: (const_int 1)
3660: (match_operand:SI 2 "general_operand" "r"))
3661: (match_operand:SI 3 "const_int_operand" "n"))]
3662: "! TARGET_486 && GET_CODE (operands[2]) != CONST_INT"
3663: "*
3664: {
3665: CC_STATUS_INIT;
3666:
3667: if (INTVAL (operands[3]) == 1)
3668: return AS2 (bts%L0,%2,%0);
3669: else
3670: return AS2 (btr%L0,%2,%0);
3671: }")
3672:
3673: ;; Bit complement. See comments on previous pattern.
3674: ;; ??? Is this really worthwhile?
3675: (define_insn ""
3676: [(set (match_operand:SI 0 "general_operand" "=rm")
3677: (xor:SI (ashift:SI (const_int 1)
3678: (match_operand:SI 1 "general_operand" "r"))
3679: (match_operand:SI 2 "general_operand" "0")))]
3680: "! TARGET_486 && GET_CODE (operands[1]) != CONST_INT"
3681: "*
3682: {
3683: CC_STATUS_INIT;
3684:
3685: return AS2 (btc%L0,%1,%0);
3686: }")
3687:
3688: (define_insn ""
3689: [(set (match_operand:SI 0 "general_operand" "=rm")
3690: (xor:SI (match_operand:SI 1 "general_operand" "0")
3691: (ashift:SI (const_int 1)
3692: (match_operand:SI 2 "general_operand" "r"))))]
3693: "! TARGET_486 && GET_CODE (operands[2]) != CONST_INT"
3694: "*
3695: {
3696: CC_STATUS_INIT;
3697:
3698: return AS2 (btc%L0,%2,%0);
3699: }")
3700:
3701: ;; Recognizers for bit-test instructions.
3702:
3703: ;; The bt opcode allows a MEM in operands[0]. But on both i386 and
3704: ;; i486, it is faster to copy a MEM to REG and then use bt, than to use
3705: ;; bt on the MEM directly.
3706:
3707: ;; ??? The first argument of a zero_extract must not be reloaded, so
3708: ;; don't allow a MEM in the operand predicate without allowing it in the
3709: ;; constraint.
3710:
3711: (define_insn ""
3712: [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
3713: (const_int 1)
3714: (match_operand:SI 1 "general_operand" "r")))]
3715: "GET_CODE (operands[1]) != CONST_INT"
3716: "*
3717: {
3718: cc_status.flags |= CC_Z_IN_NOT_C;
3719: return AS2 (bt%L0,%1,%0);
3720: }")
3721:
3722: (define_insn ""
3723: [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
3724: (match_operand:SI 1 "const_int_operand" "n")
3725: (match_operand:SI 2 "const_int_operand" "n")))]
3726: ""
3727: "*
3728: {
3729: unsigned int mask;
3730:
3731: mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
3732: operands[1] = GEN_INT (mask);
3733:
3734: if (QI_REG_P (operands[0]))
3735: {
3736: if ((mask & ~0xff) == 0)
3737: {
3738: cc_status.flags |= CC_NOT_NEGATIVE;
3739: return AS2 (test%B0,%1,%b0);
3740: }
3741:
3742: if ((mask & ~0xff00) == 0)
3743: {
3744: cc_status.flags |= CC_NOT_NEGATIVE;
3745: operands[1] = GEN_INT (mask >> 8);
3746: return AS2 (test%B0,%1,%h0);
3747: }
3748: }
3749:
3750: return AS2 (test%L0,%1,%0);
3751: }")
3752:
3753: ;; ??? All bets are off if operand 0 is a volatile MEM reference.
3754: ;; The CPU may access unspecified bytes around the actual target byte.
3755:
3756: (define_insn ""
3757: [(set (cc0) (zero_extract (match_operand:QI 0 "general_operand" "rm")
3758: (match_operand:SI 1 "const_int_operand" "n")
3759: (match_operand:SI 2 "const_int_operand" "n")))]
3760: "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])"
3761: "*
3762: {
3763: unsigned int mask;
3764:
3765: mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
3766: operands[1] = GEN_INT (mask);
3767:
3768: if (! REG_P (operands[0]) || QI_REG_P (operands[0]))
3769: {
3770: if ((mask & ~0xff) == 0)
3771: {
3772: cc_status.flags |= CC_NOT_NEGATIVE;
3773: return AS2 (test%B0,%1,%b0);
3774: }
3775:
3776: if ((mask & ~0xff00) == 0)
3777: {
3778: cc_status.flags |= CC_NOT_NEGATIVE;
3779: operands[1] = GEN_INT (mask >> 8);
3780:
3781: if (QI_REG_P (operands[0]))
3782: return AS2 (test%B0,%1,%h0);
3783: else
3784: {
3785: operands[0] = adj_offsettable_operand (operands[0], 1);
3786: return AS2 (test%B0,%1,%b0);
3787: }
3788: }
3789:
3790: if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0)
3791: {
3792: cc_status.flags |= CC_NOT_NEGATIVE;
3793: operands[1] = GEN_INT (mask >> 16);
3794: operands[0] = adj_offsettable_operand (operands[0], 2);
3795: return AS2 (test%B0,%1,%b0);
3796: }
3797:
3798: if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0)
3799: {
3800: cc_status.flags |= CC_NOT_NEGATIVE;
3801: operands[1] = GEN_INT (mask >> 24);
3802: operands[0] = adj_offsettable_operand (operands[0], 3);
3803: return AS2 (test%B0,%1,%b0);
3804: }
3805: }
3806:
3807: if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
3808: return AS2 (test%L0,%1,%0);
3809:
3810: return AS2 (test%L1,%0,%1);
3811: }")
3812:
3813: ;; Store-flag instructions.
3814:
3815: ;; For all sCOND expanders, also expand the compare or test insn that
3816: ;; generates cc0. Generate an equality comparison if `seq' or `sne'.
3817:
3818: ;; The 386 sCOND opcodes can write to memory. But a gcc sCOND insn may
3819: ;; not have any input reloads. A MEM write might need an input reload
3820: ;; for the address of the MEM. So don't allow MEM as the SET_DEST.
3821:
3822: (define_expand "seq"
3823: [(match_dup 1)
3824: (set (match_operand:QI 0 "register_operand" "")
3825: (eq:QI (cc0) (const_int 0)))]
3826: ""
3827: "
3828: {
3829: if (TARGET_IEEE_FP
3830: && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
3831: operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
3832: else
3833: operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
3834: }")
3835:
3836: (define_insn ""
3837: [(set (match_operand:QI 0 "register_operand" "=q")
3838: (eq:QI (cc0) (const_int 0)))]
3839: ""
3840: "*
3841: {
3842: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
3843: return AS1 (setnb,%0);
3844: else
3845: return AS1 (sete,%0);
3846: }")
3847:
3848: (define_expand "sne"
3849: [(match_dup 1)
3850: (set (match_operand:QI 0 "register_operand" "")
3851: (ne:QI (cc0) (const_int 0)))]
3852: ""
3853: "
3854: {
3855: if (TARGET_IEEE_FP
3856: && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
3857: operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
3858: else
3859: operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
3860: }")
3861:
3862: (define_insn ""
3863: [(set (match_operand:QI 0 "register_operand" "=q")
3864: (ne:QI (cc0) (const_int 0)))]
3865: ""
3866: "*
3867: {
3868: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
3869: return AS1 (setb,%0);
3870: else
3871: return AS1 (setne,%0);
3872: }
3873: ")
3874:
3875: (define_expand "sgt"
3876: [(match_dup 1)
3877: (set (match_operand:QI 0 "register_operand" "")
3878: (gt:QI (cc0) (const_int 0)))]
3879: ""
3880: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
3881:
3882: (define_insn ""
3883: [(set (match_operand:QI 0 "register_operand" "=q")
3884: (gt:QI (cc0) (const_int 0)))]
3885: ""
3886: "*
3887: {
3888: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
3889: return AS1 (sete,%0);
3890:
3891: OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR);
3892: }")
3893:
3894: (define_expand "sgtu"
3895: [(match_dup 1)
3896: (set (match_operand:QI 0 "register_operand" "")
3897: (gtu:QI (cc0) (const_int 0)))]
3898: ""
3899: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
3900:
3901: (define_insn ""
3902: [(set (match_operand:QI 0 "register_operand" "=q")
3903: (gtu:QI (cc0) (const_int 0)))]
3904: ""
3905: "* return \"seta %0\"; ")
3906:
3907: (define_expand "slt"
3908: [(match_dup 1)
3909: (set (match_operand:QI 0 "register_operand" "")
3910: (lt:QI (cc0) (const_int 0)))]
3911: ""
3912: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
3913:
3914: (define_insn ""
3915: [(set (match_operand:QI 0 "register_operand" "=q")
3916: (lt:QI (cc0) (const_int 0)))]
3917: ""
3918: "*
3919: {
3920: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
3921: return AS1 (sete,%0);
3922:
3923: OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\");
3924: }")
3925:
3926: (define_expand "sltu"
3927: [(match_dup 1)
3928: (set (match_operand:QI 0 "register_operand" "")
3929: (ltu:QI (cc0) (const_int 0)))]
3930: ""
3931: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
3932:
3933: (define_insn ""
3934: [(set (match_operand:QI 0 "register_operand" "=q")
3935: (ltu:QI (cc0) (const_int 0)))]
3936: ""
3937: "* return \"setb %0\"; ")
3938:
3939: (define_expand "sge"
3940: [(match_dup 1)
3941: (set (match_operand:QI 0 "register_operand" "")
3942: (ge:QI (cc0) (const_int 0)))]
3943: ""
3944: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
3945:
3946: (define_insn ""
3947: [(set (match_operand:QI 0 "register_operand" "=q")
3948: (ge:QI (cc0) (const_int 0)))]
3949: ""
3950: "*
3951: {
3952: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
3953: return AS1 (sete,%0);
3954:
3955: OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\");
3956: }")
3957:
3958: (define_expand "sgeu"
3959: [(match_dup 1)
3960: (set (match_operand:QI 0 "register_operand" "")
3961: (geu:QI (cc0) (const_int 0)))]
3962: ""
3963: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
3964:
3965: (define_insn ""
3966: [(set (match_operand:QI 0 "register_operand" "=q")
3967: (geu:QI (cc0) (const_int 0)))]
3968: ""
3969: "* return \"setae %0\"; ")
3970:
3971: (define_expand "sle"
3972: [(match_dup 1)
3973: (set (match_operand:QI 0 "register_operand" "")
3974: (le:QI (cc0) (const_int 0)))]
3975: ""
3976: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
3977:
3978: (define_insn ""
3979: [(set (match_operand:QI 0 "register_operand" "=q")
3980: (le:QI (cc0) (const_int 0)))]
3981: ""
3982: "*
3983: {
3984: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
3985: return AS1 (setb,%0);
3986:
3987: OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR);
3988: }")
3989:
3990: (define_expand "sleu"
3991: [(match_dup 1)
3992: (set (match_operand:QI 0 "register_operand" "")
3993: (leu:QI (cc0) (const_int 0)))]
3994: ""
3995: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
3996:
3997: (define_insn ""
3998: [(set (match_operand:QI 0 "register_operand" "=q")
3999: (leu:QI (cc0) (const_int 0)))]
4000: ""
4001: "* return \"setbe %0\"; ")
4002:
4003: ;; Basic conditional jump instructions.
4004: ;; We ignore the overflow flag for signed branch instructions.
4005:
4006: ;; For all bCOND expanders, also expand the compare or test insn that
4007: ;; generates cc0. Generate an equality comparison if `beq' or `bne'.
4008:
4009: (define_expand "beq"
4010: [(match_dup 1)
4011: (set (pc)
4012: (if_then_else (eq (cc0)
4013: (const_int 0))
4014: (label_ref (match_operand 0 "" ""))
4015: (pc)))]
4016: ""
4017: "
4018: {
4019: if (TARGET_IEEE_FP
4020: && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4021: operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4022: else
4023: operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4024: }")
4025:
4026: (define_insn ""
4027: [(set (pc)
4028: (if_then_else (eq (cc0)
4029: (const_int 0))
4030: (label_ref (match_operand 0 "" ""))
4031: (pc)))]
4032: ""
4033: "*
4034: {
4035: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4036: return \"jnc %l0\";
4037: else
4038: return \"je %l0\";
4039: }")
4040:
4041: (define_expand "bne"
4042: [(match_dup 1)
4043: (set (pc)
4044: (if_then_else (ne (cc0)
4045: (const_int 0))
4046: (label_ref (match_operand 0 "" ""))
4047: (pc)))]
4048: ""
4049: "
4050: {
4051: if (TARGET_IEEE_FP
4052: && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
4053: operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
4054: else
4055: operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
4056: }")
4057:
4058: (define_insn ""
4059: [(set (pc)
4060: (if_then_else (ne (cc0)
4061: (const_int 0))
4062: (label_ref (match_operand 0 "" ""))
4063: (pc)))]
4064: ""
4065: "*
4066: {
4067: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4068: return \"jc %l0\";
4069: else
4070: return \"jne %l0\";
4071: }")
4072:
4073: (define_expand "bgt"
4074: [(match_dup 1)
4075: (set (pc)
4076: (if_then_else (gt (cc0)
4077: (const_int 0))
4078: (label_ref (match_operand 0 "" ""))
4079: (pc)))]
4080: ""
4081: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4082:
4083: (define_insn ""
4084: [(set (pc)
4085: (if_then_else (gt (cc0)
4086: (const_int 0))
4087: (label_ref (match_operand 0 "" ""))
4088: (pc)))]
4089: ""
4090: "*
4091: {
4092: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4093: return AS1 (je,%l0);
4094:
4095: OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
4096: }")
4097:
4098: (define_expand "bgtu"
4099: [(match_dup 1)
4100: (set (pc)
4101: (if_then_else (gtu (cc0)
4102: (const_int 0))
4103: (label_ref (match_operand 0 "" ""))
4104: (pc)))]
4105: ""
4106: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4107:
4108: (define_insn ""
4109: [(set (pc)
4110: (if_then_else (gtu (cc0)
4111: (const_int 0))
4112: (label_ref (match_operand 0 "" ""))
4113: (pc)))]
4114: ""
4115: "ja %l0")
4116:
4117: (define_expand "blt"
4118: [(match_dup 1)
4119: (set (pc)
4120: (if_then_else (lt (cc0)
4121: (const_int 0))
4122: (label_ref (match_operand 0 "" ""))
4123: (pc)))]
4124: ""
4125: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4126:
4127: (define_insn ""
4128: [(set (pc)
4129: (if_then_else (lt (cc0)
4130: (const_int 0))
4131: (label_ref (match_operand 0 "" ""))
4132: (pc)))]
4133: ""
4134: "*
4135: {
4136: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4137: return AS1 (je,%l0);
4138:
4139: OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
4140: }")
4141:
4142: (define_expand "bltu"
4143: [(match_dup 1)
4144: (set (pc)
4145: (if_then_else (ltu (cc0)
4146: (const_int 0))
4147: (label_ref (match_operand 0 "" ""))
4148: (pc)))]
4149: ""
4150: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4151:
4152: (define_insn ""
4153: [(set (pc)
4154: (if_then_else (ltu (cc0)
4155: (const_int 0))
4156: (label_ref (match_operand 0 "" ""))
4157: (pc)))]
4158: ""
4159: "jb %l0")
4160:
4161: (define_expand "bge"
4162: [(match_dup 1)
4163: (set (pc)
4164: (if_then_else (ge (cc0)
4165: (const_int 0))
4166: (label_ref (match_operand 0 "" ""))
4167: (pc)))]
4168: ""
4169: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4170:
4171: (define_insn ""
4172: [(set (pc)
4173: (if_then_else (ge (cc0)
4174: (const_int 0))
4175: (label_ref (match_operand 0 "" ""))
4176: (pc)))]
4177: ""
4178: "*
4179: {
4180: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4181: return AS1 (je,%l0);
4182:
4183: OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
4184: }")
4185:
4186: (define_expand "bgeu"
4187: [(match_dup 1)
4188: (set (pc)
4189: (if_then_else (geu (cc0)
4190: (const_int 0))
4191: (label_ref (match_operand 0 "" ""))
4192: (pc)))]
4193: ""
4194: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4195:
4196: (define_insn ""
4197: [(set (pc)
4198: (if_then_else (geu (cc0)
4199: (const_int 0))
4200: (label_ref (match_operand 0 "" ""))
4201: (pc)))]
4202: ""
4203: "jae %l0")
4204:
4205: (define_expand "ble"
4206: [(match_dup 1)
4207: (set (pc)
4208: (if_then_else (le (cc0)
4209: (const_int 0))
4210: (label_ref (match_operand 0 "" ""))
4211: (pc)))]
4212: ""
4213: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4214:
4215: (define_insn ""
4216: [(set (pc)
4217: (if_then_else (le (cc0)
4218: (const_int 0))
4219: (label_ref (match_operand 0 "" ""))
4220: (pc)))]
4221: ""
4222: "*
4223: {
4224: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4225: return AS1 (jb,%l0);
4226:
4227: OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
4228: }")
4229:
4230: (define_expand "bleu"
4231: [(match_dup 1)
4232: (set (pc)
4233: (if_then_else (leu (cc0)
4234: (const_int 0))
4235: (label_ref (match_operand 0 "" ""))
4236: (pc)))]
4237: ""
4238: "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
4239:
4240: (define_insn ""
4241: [(set (pc)
4242: (if_then_else (leu (cc0)
4243: (const_int 0))
4244: (label_ref (match_operand 0 "" ""))
4245: (pc)))]
4246: ""
4247: "jbe %l0")
4248:
4249: ;; Negated conditional jump instructions.
4250:
4251: (define_insn ""
4252: [(set (pc)
4253: (if_then_else (eq (cc0)
4254: (const_int 0))
4255: (pc)
4256: (label_ref (match_operand 0 "" ""))))]
4257: ""
4258: "*
4259: {
4260: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4261: return \"jc %l0\";
4262: else
4263: return \"jne %l0\";
4264: }")
4265:
4266: (define_insn ""
4267: [(set (pc)
4268: (if_then_else (ne (cc0)
4269: (const_int 0))
4270: (pc)
4271: (label_ref (match_operand 0 "" ""))))]
4272: ""
4273: "*
4274: {
4275: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
4276: return \"jnc %l0\";
4277: else
4278: return \"je %l0\";
4279: }")
4280:
4281: (define_insn ""
4282: [(set (pc)
4283: (if_then_else (gt (cc0)
4284: (const_int 0))
4285: (pc)
4286: (label_ref (match_operand 0 "" ""))))]
4287: ""
4288: "*
4289: {
4290: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4291: return AS1 (jne,%l0);
4292:
4293: OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
4294: }")
4295:
4296: (define_insn ""
4297: [(set (pc)
4298: (if_then_else (gtu (cc0)
4299: (const_int 0))
4300: (pc)
4301: (label_ref (match_operand 0 "" ""))))]
4302: ""
4303: "jbe %l0")
4304:
4305: (define_insn ""
4306: [(set (pc)
4307: (if_then_else (lt (cc0)
4308: (const_int 0))
4309: (pc)
4310: (label_ref (match_operand 0 "" ""))))]
4311: ""
4312: "*
4313: {
4314: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4315: return AS1 (jne,%l0);
4316:
4317: OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
4318: }")
4319:
4320: (define_insn ""
4321: [(set (pc)
4322: (if_then_else (ltu (cc0)
4323: (const_int 0))
4324: (pc)
4325: (label_ref (match_operand 0 "" ""))))]
4326: ""
4327: "jae %l0")
4328:
4329: (define_insn ""
4330: [(set (pc)
4331: (if_then_else (ge (cc0)
4332: (const_int 0))
4333: (pc)
4334: (label_ref (match_operand 0 "" ""))))]
4335: ""
4336: "*
4337: {
4338: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4339: return AS1 (jne,%l0);
4340:
4341: OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
4342: }")
4343:
4344: (define_insn ""
4345: [(set (pc)
4346: (if_then_else (geu (cc0)
4347: (const_int 0))
4348: (pc)
4349: (label_ref (match_operand 0 "" ""))))]
4350: ""
4351: "jb %l0")
4352:
4353: (define_insn ""
4354: [(set (pc)
4355: (if_then_else (le (cc0)
4356: (const_int 0))
4357: (pc)
4358: (label_ref (match_operand 0 "" ""))))]
4359: ""
4360: "*
4361: {
4362: if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
4363: return AS1 (jae,%l0);
4364:
4365: OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
4366: }")
4367:
4368: (define_insn ""
4369: [(set (pc)
4370: (if_then_else (leu (cc0)
4371: (const_int 0))
4372: (pc)
4373: (label_ref (match_operand 0 "" ""))))]
4374: ""
4375: "ja %l0")
4376:
4377: ;; Unconditional and other jump instructions
4378:
4379: (define_insn "jump"
4380: [(set (pc)
4381: (label_ref (match_operand 0 "" "")))]
4382: ""
4383: "jmp %l0")
4384:
4385: (define_insn "indirect_jump"
4386: [(set (pc) (match_operand:SI 0 "general_operand" "rm"))]
4387: ""
4388: "*
4389: {
4390: CC_STATUS_INIT;
4391:
4392: return AS1 (jmp,%*%0);
4393: }")
4394:
4395: ;; Implement switch statements when generating PIC code. Switches are
4396: ;; implemented by `tablejump' when not using -fpic.
4397:
4398: ;; Emit code here to do the range checking and make the index zero based.
4399:
4400: (define_expand "casesi"
4401: [(set (match_dup 5)
4402: (minus:SI (match_operand:SI 0 "general_operand" "")
4403: (match_operand:SI 1 "general_operand" "")))
4404: (set (cc0)
4405: (compare:CC (match_dup 5)
4406: (match_operand:SI 2 "general_operand" "")))
4407: (set (pc)
4408: (if_then_else (gtu (cc0)
4409: (const_int 0))
4410: (label_ref (match_operand 4 "" ""))
4411: (pc)))
4412: (parallel
4413: [(set (pc)
4414: (minus:SI (reg:SI 3)
4415: (mem:SI (plus:SI (mult:SI (match_dup 5)
4416: (const_int 4))
4417: (label_ref (match_operand 3 "" ""))))))
4418: (clobber (match_scratch:SI 6 ""))])]
4419: "flag_pic"
4420: "
4421: {
4422: operands[5] = gen_reg_rtx (SImode);
4423: current_function_uses_pic_offset_table = 1;
4424: }")
4425:
4426: ;; Implement a casesi insn.
4427:
4428: ;; Each entry in the "addr_diff_vec" looks like this as the result of the
4429: ;; two rules below:
4430: ;;
4431: ;; .long _GLOBAL_OFFSET_TABLE_+[.-.L2]
4432: ;;
4433: ;; 1. An expression involving an external reference may only use the
4434: ;; addition operator, and only with an assembly-time constant.
4435: ;; The example above satisfies this because ".-.L2" is a constant.
4436: ;;
4437: ;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is
4438: ;; given the value of "GOT - .", where GOT is the actual address of
4439: ;; the Global Offset Table. Therefore, the .long above actually
4440: ;; stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2". The
4441: ;; expression "GOT - .L2" by itself would generate an error from as(1).
4442: ;;
4443: ;; The pattern below emits code that looks like this:
4444: ;;
4445: ;; movl %ebx,reg
4446: ;; subl TABLE@GOTOFF(%ebx,index,4),reg
4447: ;; jmp reg
4448: ;;
4449: ;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since
4450: ;; the addr_diff_vec is known to be part of this module.
4451: ;;
4452: ;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which
4453: ;; evaluates to just ".L2".
4454:
4455: (define_insn ""
4456: [(set (pc)
4457: (minus:SI (reg:SI 3)
4458: (mem:SI (plus:SI
4459: (mult:SI (match_operand:SI 0 "register_operand" "r")
4460: (const_int 4))
4461: (label_ref (match_operand 1 "" ""))))))
4462: (clobber (match_scratch:SI 2 "=&r"))]
4463: ""
4464: "*
4465: {
4466: rtx xops[4];
4467:
4468: xops[0] = operands[0];
4469: xops[1] = operands[1];
4470: xops[2] = operands[2];
4471: xops[3] = pic_offset_table_rtx;
4472:
4473: output_asm_insn (AS2 (mov%L2,%3,%2), xops);
4474: output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops);
4475: output_asm_insn (AS1 (jmp,%*%2), xops);
4476: ASM_OUTPUT_ALIGN_CODE (asm_out_file);
4477: RET;
4478: }")
4479:
4480: (define_insn "tablejump"
4481: [(set (pc) (match_operand:SI 0 "general_operand" "rm"))
4482: (use (label_ref (match_operand 1 "" "")))]
4483: ""
4484: "*
4485: {
4486: CC_STATUS_INIT;
4487:
4488: return AS1 (jmp,%*%0);
4489: }")
4490:
4491: ;; Call insns.
4492:
4493: ;; If generating PIC code, the predicate indirect_operand will fail
4494: ;; for operands[0] containing symbolic references on all of the named
4495: ;; call* patterns. Each named pattern is followed by an unnamed pattern
4496: ;; that matches any call to a symbolic CONST (ie, a symbol_ref). The
4497: ;; unnamed patterns are only used while generating PIC code, because
4498: ;; otherwise the named patterns match.
4499:
4500: ;; Call subroutine returning no value.
4501:
4502: (define_expand "call_pop"
4503: [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
4504: (match_operand:SI 1 "general_operand" ""))
4505: (set (reg:SI 7)
4506: (plus:SI (reg:SI 7)
4507: (match_operand:SI 3 "immediate_operand" "")))])]
4508: ""
4509: "
4510: {
4511: rtx addr;
4512:
4513: if (flag_pic)
4514: current_function_uses_pic_offset_table = 1;
4515:
4516: /* With half-pic, force the address into a register. */
4517: addr = XEXP (operands[0], 0);
4518: if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
4519: XEXP (operands[0], 0) = force_reg (Pmode, addr);
4520:
4521: if (! expander_call_insn_operand (operands[0], QImode))
4522: operands[0]
4523: = change_address (operands[0], VOIDmode,
4524: copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
4525: }")
4526:
4527: (define_insn ""
4528: [(call (match_operand:QI 0 "call_insn_operand" "m")
4529: (match_operand:SI 1 "general_operand" "g"))
4530: (set (reg:SI 7) (plus:SI (reg:SI 7)
4531: (match_operand:SI 3 "immediate_operand" "i")))]
4532: ""
4533: "*
4534: {
4535: if (GET_CODE (operands[0]) == MEM
4536: && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
4537: {
4538: operands[0] = XEXP (operands[0], 0);
4539: return AS1 (call,%*%0);
4540: }
4541: else
4542: return AS1 (call,%P0);
4543: }")
4544:
4545: (define_insn ""
4546: [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
4547: (match_operand:SI 1 "general_operand" "g"))
4548: (set (reg:SI 7) (plus:SI (reg:SI 7)
4549: (match_operand:SI 3 "immediate_operand" "i")))]
4550: "!HALF_PIC_P ()"
4551: "call %P0")
4552:
4553: (define_expand "call"
4554: [(call (match_operand:QI 0 "indirect_operand" "")
4555: (match_operand:SI 1 "general_operand" ""))]
4556: ;; Operand 1 not used on the i386.
4557: ""
4558: "
4559: {
4560: rtx addr;
4561:
4562: if (flag_pic)
4563: current_function_uses_pic_offset_table = 1;
4564:
4565: /* With half-pic, force the address into a register. */
4566: addr = XEXP (operands[0], 0);
4567: if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
4568: XEXP (operands[0], 0) = force_reg (Pmode, addr);
4569:
4570: if (! expander_call_insn_operand (operands[0], QImode))
4571: operands[0]
4572: = change_address (operands[0], VOIDmode,
4573: copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
4574: }")
4575:
4576: (define_insn ""
4577: [(call (match_operand:QI 0 "call_insn_operand" "m")
4578: (match_operand:SI 1 "general_operand" "g"))]
4579: ;; Operand 1 not used on the i386.
4580: ""
4581: "*
4582: {
4583: if (GET_CODE (operands[0]) == MEM
4584: && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
4585: {
4586: operands[0] = XEXP (operands[0], 0);
4587: return AS1 (call,%*%0);
4588: }
4589: else
4590: return AS1 (call,%P0);
4591: }")
4592:
4593: (define_insn ""
4594: [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
4595: (match_operand:SI 1 "general_operand" "g"))]
4596: ;; Operand 1 not used on the i386.
4597: "!HALF_PIC_P ()"
4598: "call %P0")
4599:
4600: ;; Call subroutine, returning value in operand 0
4601: ;; (which must be a hard register).
4602:
4603: (define_expand "call_value_pop"
4604: [(parallel [(set (match_operand 0 "" "")
4605: (call (match_operand:QI 1 "indirect_operand" "")
4606: (match_operand:SI 2 "general_operand" "")))
4607: (set (reg:SI 7)
4608: (plus:SI (reg:SI 7)
4609: (match_operand:SI 4 "immediate_operand" "")))])]
4610: ""
4611: "
4612: {
4613: rtx addr;
4614:
4615: if (flag_pic)
4616: current_function_uses_pic_offset_table = 1;
4617:
4618: /* With half-pic, force the address into a register. */
4619: addr = XEXP (operands[1], 0);
4620: if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
4621: XEXP (operands[1], 0) = force_reg (Pmode, addr);
4622:
4623: if (! expander_call_insn_operand (operands[1], QImode))
4624: operands[1]
4625: = change_address (operands[1], VOIDmode,
4626: copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
4627: }")
4628:
4629: (define_insn ""
4630: [(set (match_operand 0 "" "=rf")
4631: (call (match_operand:QI 1 "call_insn_operand" "m")
4632: (match_operand:SI 2 "general_operand" "g")))
4633: (set (reg:SI 7) (plus:SI (reg:SI 7)
4634: (match_operand:SI 4 "immediate_operand" "i")))]
4635: ""
4636: "*
4637: {
4638: if (GET_CODE (operands[1]) == MEM
4639: && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
4640: {
4641: operands[1] = XEXP (operands[1], 0);
4642: output_asm_insn (AS1 (call,%*%1), operands);
4643: }
4644: else
4645: output_asm_insn (AS1 (call,%P1), operands);
4646:
4647: RET;
4648: }")
4649:
4650: (define_insn ""
4651: [(set (match_operand 0 "" "=rf")
4652: (call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
4653: (match_operand:SI 2 "general_operand" "g")))
4654: (set (reg:SI 7) (plus:SI (reg:SI 7)
4655: (match_operand:SI 4 "immediate_operand" "i")))]
4656: "!HALF_PIC_P ()"
4657: "call %P1")
4658:
4659: (define_expand "call_value"
4660: [(set (match_operand 0 "" "")
4661: (call (match_operand:QI 1 "indirect_operand" "")
4662: (match_operand:SI 2 "general_operand" "")))]
4663: ;; Operand 2 not used on the i386.
4664: ""
4665: "
4666: {
4667: rtx addr;
4668:
4669: if (flag_pic)
4670: current_function_uses_pic_offset_table = 1;
4671:
4672: /* With half-pic, force the address into a register. */
4673: addr = XEXP (operands[1], 0);
4674: if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
4675: XEXP (operands[1], 0) = force_reg (Pmode, addr);
4676:
4677: if (! expander_call_insn_operand (operands[1], QImode))
4678: operands[1]
4679: = change_address (operands[1], VOIDmode,
4680: copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
4681: }")
4682:
4683: (define_insn ""
4684: [(set (match_operand 0 "" "=rf")
4685: (call (match_operand:QI 1 "call_insn_operand" "m")
4686: (match_operand:SI 2 "general_operand" "g")))]
4687: ;; Operand 2 not used on the i386.
4688: ""
4689: "*
4690: {
4691: if (GET_CODE (operands[1]) == MEM
4692: && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
4693: {
4694: operands[1] = XEXP (operands[1], 0);
4695: output_asm_insn (AS1 (call,%*%1), operands);
4696: }
4697: else
4698: output_asm_insn (AS1 (call,%P1), operands);
4699:
4700: RET;
4701: }")
4702:
4703: (define_insn ""
4704: [(set (match_operand 0 "" "=rf")
4705: (call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
4706: (match_operand:SI 2 "general_operand" "g")))]
4707: ;; Operand 2 not used on the i386.
4708: "!HALF_PIC_P ()"
4709: "call %P1")
4710:
4711: (define_expand "untyped_call"
4712: [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
4713: (const_int 0))
4714: (match_operand:BLK 1 "memory_operand" "")
4715: (match_operand 2 "" "")])]
4716: ""
4717: "
4718: {
4719: rtx addr;
4720:
4721: if (flag_pic)
4722: current_function_uses_pic_offset_table = 1;
4723:
4724: /* With half-pic, force the address into a register. */
4725: addr = XEXP (operands[0], 0);
4726: if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
4727: XEXP (operands[0], 0) = force_reg (Pmode, addr);
4728:
4729: operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0));
4730: if (! expander_call_insn_operand (operands[1], QImode))
4731: operands[1]
4732: = change_address (operands[1], VOIDmode,
4733: copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
4734: }")
4735:
4736: (define_insn ""
4737: [(call (match_operand:QI 0 "call_insn_operand" "m")
4738: (const_int 0))
4739: (match_operand:DI 1 "memory_operand" "o")
4740: (match_operand 2 "" "")]
4741: ""
4742: "*
4743: {
4744: rtx addr = operands[1];
4745:
4746: if (GET_CODE (operands[0]) == MEM
4747: && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
4748: {
4749: operands[0] = XEXP (operands[0], 0);
4750: output_asm_insn (AS1 (call,%*%0), operands);
4751: }
4752: else
4753: output_asm_insn (AS1 (call,%P0), operands);
4754:
4755: operands[2] = gen_rtx (REG, SImode, 0);
4756: output_asm_insn (AS2 (mov%L2,%2,%1), operands);
4757:
4758: operands[2] = gen_rtx (REG, SImode, 1);
4759: operands[1] = adj_offsettable_operand (addr, 4);
4760: output_asm_insn (AS2 (mov%L2,%2,%1), operands);
4761:
4762: operands[1] = adj_offsettable_operand (addr, 8);
4763: return AS1 (fnsave,%1);
4764: }")
4765:
4766: (define_insn ""
4767: [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
4768: (const_int 0))
4769: (match_operand:DI 1 "memory_operand" "o")
4770: (match_operand 2 "" "")]
4771: "!HALF_PIC_P ()"
4772: "*
4773: {
4774: rtx addr = operands[1];
4775:
4776: output_asm_insn (AS1 (call,%P0), operands);
4777:
4778: operands[2] = gen_rtx (REG, SImode, 0);
4779: output_asm_insn (AS2 (mov%L2,%2,%1), operands);
4780:
4781: operands[2] = gen_rtx (REG, SImode, 1);
4782: operands[1] = adj_offsettable_operand (addr, 4);
4783: output_asm_insn (AS2 (mov%L2,%2,%1), operands);
4784:
4785: operands[1] = adj_offsettable_operand (addr, 8);
4786: return AS1 (fnsave,%1);
4787: }")
4788:
4789: ;; We use fnsave and frstor to save and restore the floating point result.
4790: ;; These are expensive instructions and require a large space to save the
4791: ;; FPU state. An more complicated alternative is to use fnstenv to store
4792: ;; the FPU environment and test whether the stack top is valid. Store the
4793: ;; result of the test, and if it is valid, pop and save the value. The
4794: ;; untyped_return would check the test and optionally push the saved value.
4795:
4796: (define_expand "untyped_return"
4797: [(match_operand:BLK 0 "memory_operand" "")
4798: (match_operand 1 "" "")]
4799: ""
4800: "
4801: {
4802: rtx valreg1 = gen_rtx (REG, SImode, 0);
4803: rtx valreg2 = gen_rtx (REG, SImode, 1);
4804: rtx result = operands[0];
4805:
4806: /* Restore the FPU state. */
4807: emit_insn (gen_update_return (change_address (result, SImode,
4808: plus_constant (XEXP (result, 0),
4809: 8))));
4810:
4811: /* Reload the function value registers. */
4812: emit_move_insn (valreg1, change_address (result, SImode, XEXP (result, 0)));
4813: emit_move_insn (valreg2,
4814: change_address (result, SImode,
4815: plus_constant (XEXP (result, 0), 4)));
4816:
4817: /* Put USE insns before the return. */
4818: emit_insn (gen_rtx (USE, VOIDmode, valreg1));
4819: emit_insn (gen_rtx (USE, VOIDmode, valreg2));
4820:
4821: /* Construct the return. */
4822: expand_null_return ();
4823:
4824: DONE;
4825: }")
4826:
4827: (define_insn "update_return"
4828: [(unspec:SI [(match_operand:SI 0 "memory_operand" "m")] 0)]
4829: ""
4830: "frstor %0")
4831:
4832: ;; Insn emitted into the body of a function to return from a function.
4833: ;; This is only done if the function's epilogue is known to be simple.
4834: ;; See comments for simple_386_epilogue in i386.c.
4835:
4836: (define_insn "return"
4837: [(return)]
4838: "simple_386_epilogue ()"
4839: "*
4840: {
4841: function_epilogue (asm_out_file, get_frame_size ());
4842: RET;
4843: }")
4844:
4845: (define_insn "nop"
4846: [(const_int 0)]
4847: ""
4848: "nop")
4849:
4850: (define_expand "movstrsi"
4851: [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
4852: (match_operand:BLK 1 "memory_operand" ""))
4853: (use (match_operand:SI 2 "const_int_operand" ""))
4854: (use (match_operand:SI 3 "const_int_operand" ""))
4855: (clobber (match_scratch:SI 4 ""))
4856: (clobber (match_dup 5))
4857: (clobber (match_dup 6))])]
4858: ""
4859: "
4860: {
4861: rtx addr0, addr1;
4862:
4863: if (GET_CODE (operands[2]) != CONST_INT)
4864: FAIL;
4865:
4866: addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
4867: addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
4868:
4869: operands[5] = addr0;
4870: operands[6] = addr1;
4871:
4872: operands[0] = gen_rtx (MEM, BLKmode, addr0);
4873: operands[1] = gen_rtx (MEM, BLKmode, addr1);
4874: }")
4875:
4876: ;; It might seem that operands 0 & 1 could use predicate register_operand.
4877: ;; But strength reduction might offset the MEM expression. So we let
4878: ;; reload put the address into %edi & %esi.
4879:
4880: (define_insn ""
4881: [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
4882: (mem:BLK (match_operand:SI 1 "address_operand" "S")))
4883: (use (match_operand:SI 2 "const_int_operand" "n"))
4884: (use (match_operand:SI 3 "immediate_operand" "i"))
4885: (clobber (match_scratch:SI 4 "=&c"))
4886: (clobber (match_dup 0))
4887: (clobber (match_dup 1))]
4888: ""
4889: "*
4890: {
4891: rtx xops[2];
4892:
4893: output_asm_insn (\"cld\", operands);
4894: if (GET_CODE (operands[2]) == CONST_INT)
4895: {
4896: if (INTVAL (operands[2]) & ~0x03)
4897: {
4898: xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff);
4899: xops[1] = operands[4];
4900:
4901: output_asm_insn (AS2 (mov%L1,%0,%1), xops);
4902: #ifdef INTEL_SYNTAX
4903: output_asm_insn (\"rep movsd\", xops);
4904: #else
4905: output_asm_insn (\"rep\;movsl\", xops);
4906: #endif
4907: }
4908: if (INTVAL (operands[2]) & 0x02)
4909: output_asm_insn (\"movsw\", operands);
4910: if (INTVAL (operands[2]) & 0x01)
4911: output_asm_insn (\"movsb\", operands);
4912: }
4913: else
4914: abort ();
4915: RET;
4916: }")
4917:
4918: (define_expand "cmpstrsi"
4919: [(parallel [(set (match_operand:SI 0 "general_operand" "")
4920: (compare:SI (match_operand:BLK 1 "general_operand" "")
4921: (match_operand:BLK 2 "general_operand" "")))
4922: (use (match_operand:SI 3 "general_operand" ""))
4923: (use (match_operand:SI 4 "immediate_operand" ""))
4924: (clobber (match_dup 5))
4925: (clobber (match_dup 6))
4926: (clobber (match_dup 3))])]
4927: ""
4928: "
4929: {
4930: rtx addr1, addr2;
4931:
4932: addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
4933: addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
4934: operands[3] = copy_to_mode_reg (SImode, operands[3]);
4935:
4936: operands[5] = addr1;
4937: operands[6] = addr2;
4938:
4939: operands[1] = gen_rtx (MEM, BLKmode, addr1);
4940: operands[2] = gen_rtx (MEM, BLKmode, addr2);
4941:
4942: }")
4943:
4944: ;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is
4945: ;; zero. Emit extra code to make sure that a zero-length compare is EQ.
4946:
4947: ;; It might seem that operands 0 & 1 could use predicate register_operand.
4948: ;; But strength reduction might offset the MEM expression. So we let
4949: ;; reload put the address into %edi & %esi.
4950:
4951: ;; ??? Most comparisons have a constant length, and it's therefore
4952: ;; possible to know that the length is non-zero, and to avoid the extra
4953: ;; code to handle zero-length compares.
4954:
4955: (define_insn ""
4956: [(set (match_operand:SI 0 "general_operand" "=&r")
4957: (compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S"))
4958: (mem:BLK (match_operand:SI 2 "address_operand" "D"))))
4959: (use (match_operand:SI 3 "register_operand" "c"))
4960: (use (match_operand:SI 4 "immediate_operand" "i"))
4961: (clobber (match_dup 1))
4962: (clobber (match_dup 2))
4963: (clobber (match_dup 3))]
4964: ""
4965: "*
4966: {
4967: rtx xops[4], label;
4968:
4969: label = gen_label_rtx ();
4970:
4971: output_asm_insn (\"cld\", operands);
4972: output_asm_insn (AS2 (xor%L0,%0,%0), operands);
4973: output_asm_insn (\"repz\;cmps%B2\", operands);
4974: output_asm_insn (\"je %l0\", &label);
4975:
4976: xops[0] = operands[0];
4977: xops[1] = gen_rtx (MEM, QImode,
4978: gen_rtx (PLUS, SImode, operands[1], constm1_rtx));
4979: xops[2] = gen_rtx (MEM, QImode,
4980: gen_rtx (PLUS, SImode, operands[2], constm1_rtx));
4981: xops[3] = operands[3];
4982:
4983: output_asm_insn (AS2 (movz%B1%L0,%1,%0), xops);
4984: output_asm_insn (AS2 (movz%B2%L3,%2,%3), xops);
4985:
4986: output_asm_insn (AS2 (sub%L0,%3,%0), xops);
4987: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label));
4988: RET;
4989: }")
4990:
4991: (define_insn ""
4992: [(set (cc0)
4993: (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
4994: (mem:BLK (match_operand:SI 1 "address_operand" "D"))))
4995: (use (match_operand:SI 2 "register_operand" "c"))
4996: (use (match_operand:SI 3 "immediate_operand" "i"))
4997: (clobber (match_dup 0))
4998: (clobber (match_dup 1))
4999: (clobber (match_dup 2))]
5000: ""
5001: "*
5002: {
5003: rtx xops[2];
5004:
5005: cc_status.flags |= CC_NOT_SIGNED;
5006:
5007: xops[0] = gen_rtx (REG, QImode, 0);
5008: xops[1] = CONST0_RTX (QImode);
5009:
5010: output_asm_insn (\"cld\", operands);
5011: output_asm_insn (AS2 (test%B0,%1,%0), xops);
5012: return \"repz\;cmps%B2\";
5013: }")
5014:
5015: (define_expand "ffssi2"
5016: [(set (match_dup 2)
5017: (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" ""))
5018: (const_int -1)))
5019: (set (match_operand:SI 0 "general_operand" "")
5020: (plus:SI (match_dup 2) (const_int 1)))]
5021: ""
5022: "operands[2] = gen_reg_rtx (SImode);")
5023:
5024: (define_insn ""
5025: [(set (match_operand:SI 0 "general_operand" "=&r")
5026: (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "rm"))
5027: (const_int -1)))]
5028: ""
5029: "*
5030: {
1.1.1.2 ! root 5031: rtx xops[3];
! 5032: static int ffssi_label_number;
! 5033: char buffer[30];
1.1 root 5034:
5035: xops[0] = operands[0];
1.1.1.2 ! root 5036: xops[1] = operands[1];
! 5037: xops[2] = constm1_rtx;
! 5038: /* Can there be a way to avoid the jump here? */
! 5039: output_asm_insn (AS2 (bsf%L0,%1,%0), xops);
! 5040: #ifdef LOCAL_LABEL_PREFIX
! 5041: sprintf (buffer, \"jnz %sLFFSSI%d\",
! 5042: LOCAL_LABEL_PREFIX, ffssi_label_number);
! 5043: #else
! 5044: sprintf (buffer, \"jnz %sLFFSSI%d\",
! 5045: \"\", ffssi_label_number);
! 5046: #endif
! 5047: output_asm_insn (buffer, xops);
! 5048: output_asm_insn (AS2 (mov%L0,%2,%0), xops);
! 5049: #ifdef LOCAL_LABEL_PREFIX
! 5050: sprintf (buffer, \"%sLFFSSI%d:\",
! 5051: LOCAL_LABEL_PREFIX, ffssi_label_number);
! 5052: #else
! 5053: sprintf (buffer, \"%sLFFSSI%d:\",
! 5054: \"\", ffssi_label_number);
! 5055: #endif
! 5056: output_asm_insn (buffer, xops);
! 5057:
! 5058: ffssi_label_number++;
! 5059: return \"\";
1.1 root 5060: }")
5061:
5062: (define_expand "ffshi2"
5063: [(set (match_dup 2)
5064: (plus:HI (ffs:HI (match_operand:HI 1 "general_operand" ""))
5065: (const_int -1)))
5066: (set (match_operand:HI 0 "general_operand" "")
5067: (plus:HI (match_dup 2) (const_int 1)))]
5068: ""
5069: "operands[2] = gen_reg_rtx (HImode);")
5070:
5071: (define_insn ""
5072: [(set (match_operand:HI 0 "general_operand" "=&r")
5073: (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm"))
5074: (const_int -1)))]
5075: ""
5076: "*
5077: {
1.1.1.2 ! root 5078: rtx xops[3];
! 5079: static int ffshi_label_number;
! 5080: char buffer[30];
1.1 root 5081:
5082: xops[0] = operands[0];
1.1.1.2 ! root 5083: xops[1] = operands[1];
! 5084: xops[2] = constm1_rtx;
! 5085: output_asm_insn (AS2 (bsf%W0,%1,%0), xops);
! 5086: #ifdef LOCAL_LABEL_PREFIX
! 5087: sprintf (buffer, \"jnz %sLFFSHI%d\",
! 5088: LOCAL_LABEL_PREFIX, ffshi_label_number);
! 5089: #else
! 5090: sprintf (buffer, \"jnz %sLFFSHI%d\",
! 5091: \"\", ffshi_label_number);
! 5092: #endif
! 5093: output_asm_insn (buffer, xops);
! 5094: output_asm_insn (AS2 (mov%W0,%2,%0), xops);
! 5095: #ifdef LOCAL_LABEL_PREFIX
! 5096: sprintf (buffer, \"%sLFFSHI%d:\",
! 5097: LOCAL_LABEL_PREFIX, ffshi_label_number);
! 5098: #else
! 5099: sprintf (buffer, \"%sLFFSHI%d:\",
! 5100: \"\", ffshi_label_number);
! 5101: #endif
! 5102: output_asm_insn (buffer, xops);
! 5103:
! 5104: ffshi_label_number++;
! 5105: return \"\";
1.1 root 5106: }")
5107:
5108: ;; These patterns match the binary 387 instructions for addM3, subM3,
5109: ;; mulM3 and divM3. There are three patterns for each of DFmode and
5110: ;; SFmode. The first is the normal insn, the second the same insn but
5111: ;; with one operand a conversion, and the third the same insn but with
5112: ;; the other operand a conversion. The conversion may be SFmode or
5113: ;; SImode if the target mode DFmode, but only SImode if the target mode
5114: ;; is SFmode.
5115:
5116: (define_insn ""
5117: [(set (match_operand:DF 0 "register_operand" "=f,f")
5118: (match_operator:DF 3 "binary_387_op"
5119: [(match_operand:DF 1 "nonimmediate_operand" "0,fm")
5120: (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
5121: "TARGET_80387"
5122: "* return (char *) output_387_binary_op (insn, operands);")
5123:
5124: (define_insn ""
5125: [(set (match_operand:DF 0 "register_operand" "=f")
5126: (match_operator:DF 3 "binary_387_op"
5127: [(float:DF (match_operand:SI 1 "general_operand" "rm"))
5128: (match_operand:DF 2 "general_operand" "0")]))]
5129: "TARGET_80387"
5130: "* return (char *) output_387_binary_op (insn, operands);")
5131:
5132: (define_insn ""
1.1.1.2 ! root 5133: [(set (match_operand:XF 0 "register_operand" "=f,f")
! 5134: (match_operator:XF 3 "binary_387_op"
! 5135: [(match_operand:XF 1 "nonimmediate_operand" "0,f")
! 5136: (match_operand:XF 2 "nonimmediate_operand" "f,0")]))]
! 5137: "TARGET_80387"
! 5138: "* return (char *) output_387_binary_op (insn, operands);")
! 5139:
! 5140: (define_insn ""
! 5141: [(set (match_operand:XF 0 "register_operand" "=f")
! 5142: (match_operator:XF 3 "binary_387_op"
! 5143: [(float:XF (match_operand:SI 1 "general_operand" "rm"))
! 5144: (match_operand:XF 2 "general_operand" "0")]))]
! 5145: "TARGET_80387"
! 5146: "* return (char *) output_387_binary_op (insn, operands);")
! 5147:
! 5148: (define_insn ""
! 5149: [(set (match_operand:XF 0 "register_operand" "=f,f")
! 5150: (match_operator:XF 3 "binary_387_op"
! 5151: [(float_extend:XF (match_operand:SF 1 "general_operand" "fm,0"))
! 5152: (match_operand:XF 2 "general_operand" "0,f")]))]
! 5153: "TARGET_80387"
! 5154: "* return (char *) output_387_binary_op (insn, operands);")
! 5155:
! 5156: (define_insn ""
! 5157: [(set (match_operand:XF 0 "register_operand" "=f")
! 5158: (match_operator:XF 3 "binary_387_op"
! 5159: [(match_operand:XF 1 "general_operand" "0")
! 5160: (float:XF (match_operand:SI 2 "general_operand" "rm"))]))]
! 5161: "TARGET_80387"
! 5162: "* return (char *) output_387_binary_op (insn, operands);")
! 5163:
! 5164: (define_insn ""
! 5165: [(set (match_operand:XF 0 "register_operand" "=f,f")
! 5166: (match_operator:XF 3 "binary_387_op"
! 5167: [(match_operand:XF 1 "general_operand" "0,f")
! 5168: (float_extend:XF
! 5169: (match_operand:SF 2 "general_operand" "fm,0"))]))]
! 5170: "TARGET_80387"
! 5171: "* return (char *) output_387_binary_op (insn, operands);")
! 5172:
! 5173: (define_insn ""
1.1 root 5174: [(set (match_operand:DF 0 "register_operand" "=f,f")
5175: (match_operator:DF 3 "binary_387_op"
5176: [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0"))
5177: (match_operand:DF 2 "general_operand" "0,f")]))]
5178: "TARGET_80387"
5179: "* return (char *) output_387_binary_op (insn, operands);")
5180:
5181: (define_insn ""
5182: [(set (match_operand:DF 0 "register_operand" "=f")
5183: (match_operator:DF 3 "binary_387_op"
5184: [(match_operand:DF 1 "general_operand" "0")
5185: (float:DF (match_operand:SI 2 "general_operand" "rm"))]))]
5186: "TARGET_80387"
5187: "* return (char *) output_387_binary_op (insn, operands);")
5188:
5189: (define_insn ""
5190: [(set (match_operand:DF 0 "register_operand" "=f,f")
5191: (match_operator:DF 3 "binary_387_op"
5192: [(match_operand:DF 1 "general_operand" "0,f")
5193: (float_extend:DF
5194: (match_operand:SF 2 "general_operand" "fm,0"))]))]
5195: "TARGET_80387"
5196: "* return (char *) output_387_binary_op (insn, operands);")
5197:
5198: (define_insn ""
5199: [(set (match_operand:SF 0 "register_operand" "=f,f")
5200: (match_operator:SF 3 "binary_387_op"
5201: [(match_operand:SF 1 "nonimmediate_operand" "0,fm")
5202: (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
5203: "TARGET_80387"
5204: "* return (char *) output_387_binary_op (insn, operands);")
5205:
5206: (define_insn ""
5207: [(set (match_operand:SF 0 "register_operand" "=f")
5208: (match_operator:SF 3 "binary_387_op"
5209: [(float:SF (match_operand:SI 1 "general_operand" "rm"))
5210: (match_operand:SF 2 "general_operand" "0")]))]
5211: "TARGET_80387"
5212: "* return (char *) output_387_binary_op (insn, operands);")
5213:
5214: (define_insn ""
5215: [(set (match_operand:SF 0 "register_operand" "=f")
5216: (match_operator:SF 3 "binary_387_op"
5217: [(match_operand:SF 1 "general_operand" "0")
5218: (float:SF (match_operand:SI 2 "general_operand" "rm"))]))]
5219: "TARGET_80387"
5220: "* return (char *) output_387_binary_op (insn, operands);")
5221:
5222: (define_expand "strlensi"
5223: [(parallel [(set (match_dup 4)
5224: (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" ""))
5225: (match_operand:QI 2 "register_operand" "")
5226: (match_operand:SI 3 "immediate_operand" "")] 0))
5227: (clobber (match_dup 1))])
5228: (set (match_dup 5)
5229: (not:SI (match_dup 4)))
5230: (set (match_operand:SI 0 "register_operand" "")
5231: (minus:SI (match_dup 5)
5232: (const_int 1)))]
5233: ""
5234: "
5235: {
5236: operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5237: operands[4] = gen_reg_rtx (SImode);
5238: operands[5] = gen_reg_rtx (SImode);
5239: }")
5240:
5241: ;; It might seem that operands 0 & 1 could use predicate register_operand.
5242: ;; But strength reduction might offset the MEM expression. So we let
5243: ;; reload put the address into %edi.
5244:
5245: (define_insn ""
5246: [(set (match_operand:SI 0 "register_operand" "=&c")
5247: (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D"))
5248: (match_operand:QI 2 "register_operand" "a")
5249: (match_operand:SI 3 "immediate_operand" "i")] 0))
5250: (clobber (match_dup 1))]
5251: ""
5252: "*
5253: {
5254: rtx xops[2];
5255:
5256: xops[0] = operands[0];
5257: xops[1] = constm1_rtx;
5258: output_asm_insn (\"cld\", operands);
5259: output_asm_insn (AS2 (mov%L0,%1,%0), xops);
5260: return \"repnz\;scas%B2\";
5261: }")
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.