|
|
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: ;;- instruction definitions
23:
24: ;;- @@The original PO technology requires these to be ordered by speed,
25: ;;- @@ so that assigner will pick the fastest.
26:
27: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28:
29: ;;- When naming insn's (operand 0 of define_insn) be careful about using
30: ;;- names from other targets machine descriptions.
31:
32: ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
33: ;;- updates for most instructions.
34:
35: ;;- Operand classes for the register allocator:
36: ;;- 'a' for eax
37: ;;- 'd' for edx
38: ;;- 'c' for ecx
39: ;;- 'b' for ebx
40: ;;- 'f' for anything in FLOAT_REGS
41: ;;- 'r' any (non-floating-point) register
42: ;;- 'q' regs that allow byte operations (A, B, C and D)
43: ;;- 'A' A and D registers
44:
45: ;; the special asm out single letter directives following a '%' are:
46: ;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of operands[1]
47: ;; 's' output a '*'
48: ;; 'w' If the operand is a REG, it uses the mode size to determine the
49: ;; printing of the reg
50:
51:
52:
53: ;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM".
54: ;; But restricting MEM here would mean that gcc could not remove a redundant
55: ;; test in cases like "incl MEM / je TARGET".
56: ;;
57: ;; We don't want to allow a constant operand for test insns because
58: ;; (set (cc0) (const_int foo)) has no mode information. Such insns will
59: ;; be folded while optimizing anyway.
60:
61: (define_insn "tstsi"
62: [(set (cc0)
63: (match_operand:SI 0 "nonimmediate_operand" "rm"))]
64: ""
65: "*
66: {
67: if (REG_P (operands[0]))
68: return AS2 (test%L0,%0,%0);
69:
70: operands[1] = const0_rtx;
71: return AS2 (cmp%L0,%1,%0);
72: }")
73:
74: (define_insn "tsthi"
75: [(set (cc0)
76: (match_operand:HI 0 "nonimmediate_operand" "rm"))]
77: ""
78: "*
79: {
80: if (REG_P (operands[0]))
81: return AS2 (test%W0,%0,%0);
82:
83: operands[1] = const0_rtx;
84: return AS2 (cmp%W0,%1,%0);
85: }")
86:
87: (define_insn "tstqi"
88: [(set (cc0)
89: (match_operand:QI 0 "nonimmediate_operand" "qm"))]
90: ""
91: "*
92: {
93: if (REG_P (operands[0]))
94: return AS2 (test%B0,%0,%0);
95:
96: operands[1] = const0_rtx;
97: return AS2 (cmp%B0,%1,%0);
98: }")
99:
100: (define_insn "tstsf"
101: [(set (cc0)
102: (match_operand:SF 0 "register_operand" "f"))
103: (clobber (match_scratch:HI 1 "=a"))]
104: "TARGET_80387"
105: "*
106: {
107: if (! STACK_TOP_P (operands[0]))
108: abort ();
109:
110: output_asm_insn (\"ftst\", operands);
111: cc_status.flags |= CC_IN_80387;
112:
113: if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
114: output_asm_insn (AS1 (fstp,%y0), operands);
115:
116: output_asm_insn (AS1 (fnsts%W1,%1), operands);
117:
118: return \"sahf\";
119: }")
120:
121: (define_insn "tstdf"
122: [(set (cc0)
123: (match_operand:DF 0 "register_operand" "f"))
124: (clobber (match_scratch:HI 1 "=a"))]
125: "TARGET_80387"
126: "*
127: {
128: if (! STACK_TOP_P (operands[0]))
129: abort ();
130:
131: output_asm_insn (\"ftst\", operands);
132: cc_status.flags |= CC_IN_80387;
133:
134: if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
135: output_asm_insn (AS1 (fstp,%y0), operands);
136:
137: output_asm_insn (AS1 (fnsts%W1,%1), operands);
138:
139: return \"sahf\";
140: }")
141:
142: ;;- compare instructions
143:
144: (define_insn "cmpsi"
145: [(set (cc0)
146: (compare (match_operand:SI 0 "nonimmediate_operand" "mr,ri")
147: (match_operand:SI 1 "general_operand" "ri,mr")))]
148: ""
149: "*
150: {
151: if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
152: {
153: cc_status.flags |= CC_REVERSED;
154: return AS2 (cmp%L0,%0,%1);
155: }
156: return AS2 (cmp%L0,%1,%0);
157: }")
158:
159: (define_insn "cmphi"
160: [(set (cc0)
161: (compare (match_operand:HI 0 "nonimmediate_operand" "mr,ri")
162: (match_operand:HI 1 "general_operand" "ri,mr")))]
163: ""
164: "*
165: {
166: if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
167: {
168: cc_status.flags |= CC_REVERSED;
169: return AS2 (cmp%W0,%0,%1);
170: }
171: return AS2 (cmp%W0,%1,%0);
172: }")
173:
174: (define_insn "cmpqi"
175: [(set (cc0)
176: (compare (match_operand:QI 0 "nonimmediate_operand" "qn,mq")
177: (match_operand:QI 1 "general_operand" "qm,nq")))]
178: ""
179: "*
180: {
181: if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
182: {
183: cc_status.flags |= CC_REVERSED;
184: return AS2 (cmp%B0,%0,%1);
185: }
186: return AS2 (cmp%B0,%1,%0);
187: }")
188:
189: ;; These implement float point compares. For each of DFmode and
190: ;; SFmode, there is the normal insn, and an insn where the second operand
191: ;; is converted to the desired mode.
192:
193: (define_expand "cmpdf"
194: [(parallel [(set (cc0)
195: (compare (match_operand:DF 0 "nonimmediate_operand" "")
196: (match_operand:DF 1 "nonimmediate_operand" "")))
197: (clobber (match_scratch:HI 2 ""))])]
198: "TARGET_80387"
199: "")
200:
201: (define_expand "cmpsf"
202: [(parallel [(set (cc0)
203: (compare (match_operand:SF 0 "nonimmediate_operand" "")
204: (match_operand:SF 1 "nonimmediate_operand" "")))
205: (clobber (match_scratch:HI 2 ""))])]
206: "TARGET_80387"
207: "")
208:
209: ;; The `ble' and `blt' patterns can reverse a compare, so we must allow
210: ;; an immediate operand as operand 0 in the recognizers below.
211:
212: (define_insn ""
213: [(set (cc0)
214: (compare (match_operand:DF 0 "general_operand" "f")
215: (match_operand:DF 1 "general_operand" "fm")))
216: (clobber (match_scratch:HI 2 "=a"))]
217: "TARGET_80387"
218: "* return (char *) output_float_compare (insn, operands);")
219:
220: (define_insn ""
221: [(set (cc0)
222: (compare (match_operand:DF 0 "general_operand" "f,f")
223: (float:DF (match_operand:SI 1 "general_operand" "m,!*r"))))
224: (clobber (match_scratch:HI 2 "=a,a"))]
225: "TARGET_80387"
226: "* return (char *) output_float_compare (insn, operands);")
227:
228: (define_insn ""
229: [(set (cc0)
230: (compare (match_operand:DF 0 "general_operand" "f,f")
231: (float_extend:DF
232: (match_operand:SF 1 "general_operand" "fm,!*r"))))
233: (clobber (match_scratch:HI 2 "=a,a"))]
234: "TARGET_80387"
235: "* return (char *) output_float_compare (insn, operands);")
236:
237: (define_insn ""
238: [(set (cc0)
239: (compare (match_operand:SF 0 "general_operand" "f")
240: (match_operand:SF 1 "general_operand" "fm")))
241: (clobber (match_scratch:HI 2 "=a"))]
242: "TARGET_80387"
243: "* return (char *) output_float_compare (insn, operands);")
244:
245: (define_insn ""
246: [(set (cc0)
247: (compare (match_operand:SF 0 "general_operand" "f,f")
248: (float:SF (match_operand:SI 1 "general_operand" "m,!*r"))))
249: (clobber (match_scratch:HI 2 "=a,a"))]
250: "TARGET_80387"
251: "* return (char *) output_float_compare (insn, operands);")
252:
253: ;; logical compare
254:
255: (define_insn ""
256: [(set (cc0)
1.1.1.2 ! root 257: (and:SI (match_operand:SI 0 "general_operand" "%ro")
1.1 root 258: (match_operand:SI 1 "general_operand" "ri")))]
259: ""
260: "*
261: {
262: /* For small integers, we may actually use testb. */
263: if (GET_CODE (operands[1]) == CONST_INT
1.1.1.2 ! root 264: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
! 265: && ! NON_QI_REG_P (operands[0]))
1.1 root 266: {
267: /* We may set the sign bit spuriously. */
268:
1.1.1.2 ! root 269: if ((INTVAL (operands[1]) & ~0xff) == 0)
! 270: {
! 271: cc_status.flags |= CC_NOT_NEGATIVE;
! 272: return AS2 (test%B0,%1,%b0);
! 273: }
1.1 root 274:
1.1.1.2 ! root 275: if ((INTVAL (operands[1]) & ~0xff00) == 0)
1.1 root 276: {
1.1.1.2 ! root 277: cc_status.flags |= CC_NOT_NEGATIVE;
1.1 root 278: operands[1] = gen_rtx (CONST_INT, VOIDmode,
279: INTVAL (operands[1]) >> 8);
1.1.1.2 ! root 280:
! 281: if (QI_REG_P (operands[0]))
! 282: return AS2 (test%B0,%1,%h0);
! 283: else
! 284: {
! 285: operands[0] = adj_offsettable_operand (operands[0], 1);
! 286: return AS2 (test%B0,%1,%b0);
! 287: }
! 288: }
! 289:
! 290: if (GET_CODE (operands[0]) == MEM
! 291: && (INTVAL (operands[1]) & ~0xff0000) == 0)
! 292: {
! 293: cc_status.flags |= CC_NOT_NEGATIVE;
! 294: operands[1] = gen_rtx (CONST_INT, VOIDmode,
! 295: INTVAL (operands[1]) >> 16);
! 296:
! 297: operands[0] = adj_offsettable_operand (operands[0], 2);
! 298: return AS2 (test%B0,%1,%b0);
! 299: }
! 300:
! 301: if (GET_CODE (operands[0]) == MEM
! 302: && (INTVAL (operands[1]) & ~0xff000000) == 0)
! 303: {
! 304: operands[1] = gen_rtx (CONST_INT, VOIDmode,
! 305: (INTVAL (operands[1]) >> 24) & 0xff);
! 306:
! 307: operands[0] = adj_offsettable_operand (operands[0], 3);
! 308: return AS2 (test%B0,%1,%b0);
1.1 root 309: }
310: }
311:
312: if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
313: return AS2 (test%L0,%1,%0);
314:
315: return AS2 (test%L1,%0,%1);
316: }")
317:
318: (define_insn ""
319: [(set (cc0)
1.1.1.2 ! root 320: (and:HI (match_operand:HI 0 "general_operand" "%ro")
1.1 root 321: (match_operand:HI 1 "general_operand" "ri")))]
322: ""
323: "*
324: {
325: if (GET_CODE (operands[1]) == CONST_INT
1.1.1.2 ! root 326: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
! 327: && ! NON_QI_REG_P (operands[0]))
1.1 root 328: {
1.1.1.2 ! root 329: if ((INTVAL (operands[1]) & 0xff00) == 0)
1.1 root 330: {
1.1.1.2 ! root 331: /* ??? This might not be necessary. */
1.1 root 332: if (INTVAL (operands[1]) & 0xffff0000)
333: operands[1] = gen_rtx (CONST_INT, VOIDmode,
334: INTVAL (operands[1]) & 0xff);
335:
336: /* We may set the sign bit spuriously. */
337: cc_status.flags |= CC_NOT_NEGATIVE;
338: return AS2 (test%B0,%1,%b0);
339: }
340:
1.1.1.2 ! root 341: if ((INTVAL (operands[1]) & 0xff) == 0)
1.1 root 342: {
343: operands[1] = gen_rtx (CONST_INT, VOIDmode,
344: (INTVAL (operands[1]) >> 8) & 0xff);
1.1.1.2 ! root 345:
! 346: if (QI_REG_P (operands[0]))
! 347: return AS2 (test%B0,%1,%h0);
! 348: else
! 349: {
! 350: operands[0] = adj_offsettable_operand (operands[0], 1);
! 351: return AS2 (test%B0,%1,%b0);
! 352: }
1.1 root 353: }
354: }
355:
356: if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
357: return AS2 (test%W0,%1,%0);
358:
359: return AS2 (test%W1,%0,%1);
360: }")
361:
362: (define_insn ""
363: [(set (cc0)
364: (and:QI (match_operand:QI 0 "general_operand" "%qm")
365: (match_operand:QI 1 "general_operand" "qi")))]
366: ""
367: "*
368: {
369: if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
370: return AS2 (test%B0,%1,%0);
371:
372: return AS2 (test%B1,%0,%1);
373: }")
374:
375: ;; move instructions.
376: ;; There is one for each machine mode,
377: ;; and each is preceded by a corresponding push-insn pattern
378: ;; (since pushes are not general_operands on the 386).
379:
380: (define_insn ""
381: [(set (match_operand:SI 0 "push_operand" "=<")
382: (match_operand:SI 1 "general_operand" "g"))]
383: "! TARGET_486"
384: "push%L0 %1")
385:
386: ;; On a 486, it is faster to move MEM to a REG and then push, rather than
387: ;; push MEM directly.
388:
389: (define_insn ""
390: [(set (match_operand:SI 0 "push_operand" "=<")
391: (match_operand:SI 1 "general_operand" "ri"))]
392: "TARGET_486"
393: "push%L0 %1")
394:
395: ;; General case of fullword move.
396:
397: ;; If generating PIC code and operands[1] is a symbolic CONST, emit a
398: ;; move to get the address of the symbolic object from the GOT.
399:
400: (define_expand "movsi"
401: [(set (match_operand:SI 0 "general_operand" "")
402: (match_operand:SI 1 "general_operand" ""))]
403: ""
404: "
405: {
406: extern int flag_pic;
407:
408: if (flag_pic && SYMBOLIC_CONST (operands[1]))
409: emit_pic_move (operands, SImode);
410: }")
411:
412: ;; On i486, incl reg is faster than movl $1,reg.
413:
414: (define_insn ""
415: [(set (match_operand:SI 0 "general_operand" "=g,r")
416: (match_operand:SI 1 "general_operand" "ri,m"))]
417: ""
418: "*
419: {
420: rtx link;
421: if (operands[1] == const0_rtx && REG_P (operands[0]))
422: return AS2 (xor%L0,%0,%0);
423:
424: if (operands[1] == const1_rtx
425: && (link = find_reg_note (insn, REG_WAS_0, 0))
426: /* Make sure the insn that stored the 0 is still present. */
427: && ! XEXP (link, 0)->volatil
428: && GET_CODE (XEXP (link, 0)) != NOTE
429: /* Make sure cross jumping didn't happen here. */
430: && no_labels_between_p (XEXP (link, 0), insn))
431: /* Fastest way to change a 0 to a 1. */
432: return AS1 (inc%L0,%0);
433:
434: return AS2 (mov%L0,%1,%0);
435: }")
436:
437: (define_insn ""
438: [(set (match_operand:HI 0 "push_operand" "=<")
439: (match_operand:HI 1 "general_operand" "g"))]
440: ""
441: "push%W0 %1")
442:
443: ;; On i486, an incl and movl are both faster than incw and movw.
444:
445: (define_insn "movhi"
446: [(set (match_operand:HI 0 "general_operand" "=g,r")
447: (match_operand:HI 1 "general_operand" "ri,m"))]
448: ""
449: "*
450: {
451: rtx link;
452: if (REG_P (operands[0]) && operands[1] == const0_rtx)
453: return AS2 (xor%L0,%k0,%k0);
454:
455: if (REG_P (operands[0]) && operands[1] == const1_rtx
456: && (link = find_reg_note (insn, REG_WAS_0, 0))
457: /* Make sure the insn that stored the 0 is still present. */
458: && ! XEXP (link, 0)->volatil
459: && GET_CODE (XEXP (link, 0)) != NOTE
460: /* Make sure cross jumping didn't happen here. */
461: && no_labels_between_p (XEXP (link, 0), insn))
462: /* Fastest way to change a 0 to a 1. */
463: return AS1 (inc%L0,%k0);
464:
465: if (REG_P (operands[0]))
466: {
467: if (REG_P (operands[1]))
468: return AS2 (mov%L0,%k1,%k0);
469: else if (CONSTANT_P (operands[1]))
470: return AS2 (mov%L0,%1,%k0);
471: }
472:
473: return AS2 (mov%W0,%1,%0);
474: }")
475:
476: (define_insn "movstricthi"
477: [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r"))
478: (match_operand:HI 1 "general_operand" "ri,m"))]
479: ""
480: "*
481: {
482: rtx link;
483: if (operands[1] == const0_rtx && REG_P (operands[0]))
484: return AS2 (xor%W0,%0,%0);
485:
486: if (operands[1] == const1_rtx
487: && (link = find_reg_note (insn, REG_WAS_0, 0))
488: /* Make sure the insn that stored the 0 is still present. */
489: && ! XEXP (link, 0)->volatil
490: && GET_CODE (XEXP (link, 0)) != NOTE
491: /* Make sure cross jumping didn't happen here. */
492: && no_labels_between_p (XEXP (link, 0), insn))
493: /* Fastest way to change a 0 to a 1. */
494: return AS1 (inc%W0,%0);
495:
496: return AS2 (mov%W0,%1,%0);
497: }")
498:
499: ;; emit_push_insn when it calls move_by_pieces
500: ;; requires an insn to "push a byte".
501: ;; But actually we use pushw, which has the effect of rounding
502: ;; the amount pushed up to a halfword.
503: (define_insn ""
504: [(set (match_operand:QI 0 "push_operand" "=<")
505: (match_operand:QI 1 "general_operand" "q"))]
506: ""
507: "*
508: {
509: operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
510: return AS1 (push%W0,%1);
511: }")
512:
513: ;; On i486, incb reg is faster than movb $1,reg.
514:
515: ;; ??? Do a recognizer for zero_extract that looks just like this, but reads
516: ;; or writes %ah, %bh, %ch, %dh.
517:
518: (define_insn "movqi"
519: [(set (match_operand:QI 0 "general_operand" "=q,*r,qm")
520: (match_operand:QI 1 "general_operand" "*g,q,qn"))]
521: ""
522: "*
523: {
524: rtx link;
525: if (operands[1] == const0_rtx && REG_P (operands[0]))
526: return AS2 (xor%B0,%0,%0);
527:
528: if (operands[1] == const1_rtx
529: && (link = find_reg_note (insn, REG_WAS_0, 0))
530: /* Make sure the insn that stored the 0 is still present. */
531: && ! XEXP (link, 0)->volatil
532: && GET_CODE (XEXP (link, 0)) != NOTE
533: /* Make sure cross jumping didn't happen here. */
534: && no_labels_between_p (XEXP (link, 0), insn))
535: /* Fastest way to change a 0 to a 1. */
536: return AS1 (inc%B0,%0);
537:
538: /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */
539: if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
540: return (AS2 (mov%L0,%k1,%k0));
541:
542: return (AS2 (mov%B0,%1,%0));
543: }")
544:
545: ;; If it becomes necessary to support movstrictqi into %esi or %edi,
546: ;; use the insn sequence:
547: ;;
548: ;; shrdl $8,srcreg,dstreg
549: ;; rorl $24,dstreg
550: ;;
551: ;; If operands[1] is a constant, then an andl/orl sequence would be
552: ;; faster.
553:
554: (define_insn "movstrictqi"
555: [(set (strict_low_part (match_operand:QI 0 "general_operand" "+q,qm"))
556: (match_operand:QI 1 "general_operand" "*g,qn"))]
557: ""
558: "*
559: {
560: rtx link;
561: if (operands[1] == const0_rtx && REG_P (operands[0]))
562: return AS2 (xor%B0,%0,%0);
563:
564: if (operands[1] == const1_rtx
565: && (link = find_reg_note (insn, REG_WAS_0, 0))
566: /* Make sure the insn that stored the 0 is still present. */
567: && ! XEXP (link, 0)->volatil
568: && GET_CODE (XEXP (link, 0)) != NOTE
569: /* Make sure cross jumping didn't happen here. */
570: && no_labels_between_p (XEXP (link, 0), insn))
571: /* Fastest way to change a 0 to a 1. */
572: return AS1 (inc%B0,%0);
573:
574: /* If mov%B0 isn't allowed for one of these regs, use mov%W0. */
575: if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
576: {
577: abort ();
578: return (AS2 (mov%L0,%k1,%k0));
579: }
580:
581: return AS2 (mov%B0,%1,%0);
582: }")
583:
584: (define_insn ""
585: [(set (match_operand:SF 0 "push_operand" "=<,<")
586: (match_operand:SF 1 "general_operand" "gF,f"))]
587: ""
588: "*
589: {
590: if (STACK_REG_P (operands[1]))
591: {
592: rtx xops[3];
593:
594: if (! STACK_TOP_P (operands[1]))
595: abort ();
596:
597: xops[0] = AT_SP (SFmode);
598: xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
599: xops[2] = stack_pointer_rtx;
600:
601: output_asm_insn (AS2 (sub%L2,%1,%2), xops);
602:
603: if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
604: output_asm_insn (AS1 (fstp%S0,%0), xops);
605: else
606: output_asm_insn (AS1 (fst%S0,%0), xops);
607: RET;
608: }
609: return AS1 (push%L1,%1);
610: }")
611:
612: (define_insn "movsf"
613: [(set (match_operand:SF 0 "general_operand" "=f,fm,!*rf,!*rm")
614: (match_operand:SF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
615: ""
616: "*
617: {
618: int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
619:
620: /* First handle a `pop' insn or a `fld %st(0)' */
621:
622: if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
623: {
624: if (stack_top_dies)
625: return AS1 (fstp,%y0);
626: else
627: return AS1 (fld,%y0);
628: }
629:
630: /* Handle a transfer between the 387 and a 386 register */
631:
632: if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
633: {
634: output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
635: RET;
636: }
637:
638: if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
639: {
640: output_to_reg (operands[0], stack_top_dies);
641: RET;
642: }
643:
644: /* Handle other kinds of writes from the 387 */
645:
646: if (STACK_TOP_P (operands[1]))
647: {
648: if (stack_top_dies)
649: return AS1 (fstp%z0,%y0);
650: else
651: return AS1 (fst%z0,%y0);
652: }
653:
654: /* Handle other kinds of reads to the 387 */
655:
656: if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
657: return (char *) output_move_const_single (operands);
658:
659: if (STACK_TOP_P (operands[0]))
660: return AS1 (fld%z1,%y1);
661:
662: /* Handle all SFmode moves not involving the 387 */
663:
664: return (char *) singlemove_string (operands);
665: }")
666:
667: ;;should change to handle the memory operands[1] without doing df push..
668: (define_insn ""
669: [(set (match_operand:DF 0 "push_operand" "=<,<")
670: (match_operand:DF 1 "general_operand" "gF,f"))]
671: ""
672: "*
673: {
674: if (STACK_REG_P (operands[1]))
675: {
676: rtx xops[3];
677:
678: xops[0] = AT_SP (SFmode);
679: xops[1] = gen_rtx (CONST_INT, VOIDmode, 8);
680: xops[2] = stack_pointer_rtx;
681:
682: output_asm_insn (AS2 (sub%L2,%1,%2), xops);
683:
684: if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
685: output_asm_insn (AS1 (fstp%Q0,%0), xops);
686: else
687: output_asm_insn (AS1 (fst%Q0,%0), xops);
688:
689: RET;
690: }
691: else
692: return (char *) output_move_double (operands);
693: }")
694:
695: (define_insn "swapdf"
696: [(set (match_operand:DF 0 "register_operand" "f")
697: (match_operand:DF 1 "register_operand" "f"))
698: (set (match_dup 1)
699: (match_dup 0))]
700: ""
701: "*
702: {
703: if (STACK_TOP_P (operands[0]))
704: return AS1 (fxch,%1);
705: else
706: return AS1 (fxch,%0);
707: }")
708:
709: (define_insn "movdf"
710: [(set (match_operand:DF 0 "general_operand" "=f,fm,!*rf,!*rm")
711: (match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
712: ""
713: "*
714: {
715: int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
716:
717: /* First handle a `pop' insn or a `fld %st(0)' */
718:
719: if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
720: {
721: if (stack_top_dies)
722: return AS1 (fstp,%y0);
723: else
724: return AS1 (fld,%y0);
725: }
726:
727: /* Handle a transfer between the 387 and a 386 register */
728:
729: if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
730: {
731: output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
732: RET;
733: }
734:
735: if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
736: {
737: output_to_reg (operands[0], stack_top_dies);
738: RET;
739: }
740:
741: /* Handle other kinds of writes from the 387 */
742:
743: if (STACK_TOP_P (operands[1]))
744: {
745: if (stack_top_dies)
746: return AS1 (fstp%z0,%y0);
747: else
748: return AS1 (fst%z0,%y0);
749: }
750:
751: /* Handle other kinds of reads to the 387 */
752:
753: if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
754: return (char *) output_move_const_single (operands);
755:
756: if (STACK_TOP_P (operands[0]))
757: return AS1 (fld%z1,%y1);
758:
759: /* Handle all DFmode moves not involving the 387 */
760:
761: return (char *) output_move_double (operands);
762: }")
763:
764: (define_insn ""
765: [(set (match_operand:DI 0 "push_operand" "=<")
766: (match_operand:DI 1 "general_operand" "roiF"))]
767: ""
768: "*
769: {
770: return (char *) output_move_double (operands);
771: }")
772:
773: (define_insn "movdi"
774: [(set (match_operand:DI 0 "general_operand" "=&r,rm")
775: (match_operand:DI 1 "general_operand" "m,riF"))]
776: ""
777: "*
778: {
779: return (char *) output_move_double (operands);
780: }")
781:
782: ;;- conversion instructions
783: ;;- NONE
784:
785: ;;- zero extension instructions
786: ;; See comments by `andsi' for when andl is faster than movzx.
787:
788: (define_insn "zero_extendhisi2"
789: [(set (match_operand:SI 0 "general_operand" "=r")
790: (zero_extend:SI
791: (match_operand:HI 1 "nonimmediate_operand" "rm")))]
792: ""
793: "*
794: {
795: if ((TARGET_486 || REGNO (operands[0]) == 0)
796: && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
797: {
798: rtx xops[2];
799: xops[0] = operands[0];
800: xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xffff);
801: output_asm_insn (AS2 (and%L0,%1,%k0), xops);
802: RET;
803: }
804:
805: #ifdef INTEL_SYNTAX
806: return AS2 (movzx,%1,%0);
807: #else
808: return AS2 (movz%W0%L0,%1,%0);
809: #endif
810: }")
811:
812: (define_insn "zero_extendqihi2"
813: [(set (match_operand:HI 0 "general_operand" "=r")
814: (zero_extend:HI
815: (match_operand:QI 1 "nonimmediate_operand" "qm")))]
816: ""
817: "*
818: {
819: if ((TARGET_486 || REGNO (operands[0]) == 0)
820: && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
821: {
822: rtx xops[2];
823: xops[0] = operands[0];
824: xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xff);
825: output_asm_insn (AS2 (and%L0,%1,%k0), xops);
826: RET;
827: }
828:
829: #ifdef INTEL_SYNTAX
830: return AS2 (movzx,%1,%0);
831: #else
832: return AS2 (movz%B0%W0,%1,%0);
833: #endif
834: }")
835:
836: (define_insn "zero_extendqisi2"
837: [(set (match_operand:SI 0 "general_operand" "=r")
838: (zero_extend:SI
839: (match_operand:QI 1 "nonimmediate_operand" "qm")))]
840: ""
841: "*
842: {
843: if ((TARGET_486 || REGNO (operands[0]) == 0)
844: && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
845: {
846: rtx xops[2];
847: xops[0] = operands[0];
848: xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xff);
849: output_asm_insn (AS2 (and%L0,%1,%k0), xops);
850: RET;
851: }
852:
853: #ifdef INTEL_SYNTAX
854: return AS2 (movzx,%1,%0);
855: #else
856: return AS2 (movz%B0%L0,%1,%0);
857: #endif
858: }")
859:
860: ;;- sign extension instructions
861:
862: /*
863: (define_insn "extendsidi2"
864: [(set (match_operand:DI 0 "general_operand" "=a")
865: (sign_extend:DI
866: (match_operand:SI 1 "nonimmediate_operand" "a")))]
867: ""
868: "clq")
869: */
870:
871: ;; Note that the i386 programmers' manual says that the opcodes
872: ;; are named movsx..., but the assembler on Unix does not accept that.
873: ;; We use what the Unix assembler expects.
874:
875: (define_insn "extendhisi2"
876: [(set (match_operand:SI 0 "general_operand" "=r")
877: (sign_extend:SI
878: (match_operand:HI 1 "nonimmediate_operand" "rm")))]
879: ""
880: "*
881: {
882: if (REGNO (operands[0]) == 0
883: && REG_P (operands[1]) && REGNO (operands[1]) == 0)
884: #ifdef INTEL_SYNTAX
885: return \"cwde\";
886: #else
887: return \"cwtl\";
888: #endif
889:
890: #ifdef INTEL_SYNTAX
891: return AS2 (movsx,%1,%0);
892: #else
893: return AS2 (movs%W0%L0,%1,%0);
894: #endif
895: }")
896:
897: (define_insn "extendqihi2"
898: [(set (match_operand:HI 0 "general_operand" "=r")
899: (sign_extend:HI
900: (match_operand:QI 1 "nonimmediate_operand" "qm")))]
901: ""
902: "*
903: {
904: if (REGNO (operands[0]) == 0
905: && REG_P (operands[1]) && REGNO (operands[1]) == 0)
906: return \"cbtw\";
907:
908: #ifdef INTEL_SYNTAX
909: return AS2 (movsx,%1,%0);
910: #else
911: return AS2 (movs%B0%W0,%1,%0);
912: #endif
913: }")
914:
915: (define_insn "extendqisi2"
916: [(set (match_operand:SI 0 "general_operand" "=r")
917: (sign_extend:SI
918: (match_operand:QI 1 "nonimmediate_operand" "qm")))]
919: ""
920: "*
921: {
922: #ifdef INTEL_SYNTAX
923: return AS2 (movsx,%1,%0);
924: #else
925: return AS2 (movs%B0%L0,%1,%0);
926: #endif
927: }")
928:
929: ;; Conversions between float and double.
930:
931: (define_insn "extendsfdf2"
932: [(set (match_operand:DF 0 "general_operand" "=fm,f,f,!*r")
933: (float_extend:DF
934: (match_operand:SF 1 "general_operand" "f,fm,!*r,f")))]
935: "TARGET_80387"
936: "*
937: {
938: int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
939:
940: if (NON_STACK_REG_P (operands[1]))
941: {
942: output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
943: RET;
944: }
945:
946: if (NON_STACK_REG_P (operands[0]))
947: {
948: output_to_reg (operands[0], stack_top_dies);
949: RET;
950: }
951:
952: if (STACK_TOP_P (operands[0]))
953: return AS1 (fld%z1,%y1);
954:
955: if (GET_CODE (operands[0]) == MEM)
956: {
957: if (stack_top_dies)
958: return AS1 (fstp%z0,%y0);
959: else
960: return AS1 (fst%z0,%y0);
961: }
962:
963: abort ();
964: }")
965:
966: ;; This cannot output into an f-reg because there is no way to be sure
967: ;; of truncating in that case. Otherwise this is just like a simple move
968: ;; insn.
969:
970: (define_insn "truncdfsf2"
971: [(set (match_operand:SF 0 "general_operand" "=m,!*r")
972: (float_truncate:SF
973: (match_operand:DF 1 "register_operand" "f,f")))]
974: "TARGET_80387"
975: "*
976: {
977: int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
978:
979: if (NON_STACK_REG_P (operands[0]))
980: {
981: output_to_reg (operands[0], stack_top_dies);
982: RET;
983: }
984: else if (GET_CODE (operands[0]) == MEM)
985: {
986: if (stack_top_dies)
987: return AS1 (fstp%z0,%0);
988: else
989: return AS1 (fst%z0,%0);
990: }
991: else
992: abort ();
993: }")
994:
995: ;; The 387 requires that the stack top dies after converting to DImode.
996:
997: ;; Represent an unsigned conversion from SImode to MODE_FLOAT by first
998: ;; doing a signed conversion to DImode, and then taking just the low
999: ;; part.
1000:
1001: (define_expand "fixuns_truncdfsi2"
1002: [(parallel [(set (match_dup 3)
1003: (fix:DI
1004: (fix:DF (match_operand:DF 1 "register_operand" ""))))
1005: (clobber (match_scratch:HI 2 ""))
1006: (clobber (match_dup 1))])
1007: (set (match_operand:SI 0 "general_operand" "")
1008: (match_dup 4))]
1009: "TARGET_80387"
1010: "
1011: {
1012: operands[3] = gen_reg_rtx (DImode);
1013: operands[4] = gen_lowpart (SImode, operands[3]);
1014: }")
1015:
1016: (define_expand "fixuns_truncsfsi2"
1017: [(parallel [(set (match_dup 3)
1018: (fix:DI
1019: (fix:SF (match_operand:SF 1 "register_operand" ""))))
1020: (clobber (match_scratch:HI 2 ""))
1021: (clobber (match_dup 1))])
1022: (set (match_operand:SI 0 "general_operand" "")
1023: (match_dup 4))]
1024: "TARGET_80387"
1025: "
1026: {
1027: operands[3] = gen_reg_rtx (DImode);
1028: operands[4] = gen_lowpart (SImode, operands[3]);
1029: }")
1030:
1031: ;; Signed conversion to DImode.
1032:
1033: (define_expand "fix_truncdfdi2"
1034: [(parallel [(set (match_operand:DI 0 "general_operand" "")
1035: (fix:DI
1036: (fix:DF (match_operand:DF 1 "register_operand" ""))))
1037: (clobber (match_scratch:HI 2 ""))
1038: (clobber (match_dup 1))])]
1039: "TARGET_80387"
1040: "
1041: {
1042: operands[1] = copy_to_mode_reg (DFmode, operands[1]);
1043: }")
1044:
1045: (define_expand "fix_truncsfdi2"
1046: [(parallel [(set (match_operand:DI 0 "general_operand" "")
1047: (fix:DI
1048: (fix:SF (match_operand:SF 1 "register_operand" ""))))
1049: (clobber (match_scratch:HI 2 ""))
1050: (clobber (match_dup 1))])]
1051: "TARGET_80387"
1052: "
1053: {
1054: operands[1] = copy_to_mode_reg (SFmode, operands[1]);
1055: }")
1056:
1.1.1.2 ! root 1057: ;; These match a signed conversion of either DFmode or SFmode to DImode.
1.1 root 1058:
1059: (define_insn ""
1060: [(set (match_operand:DI 0 "general_operand" "=m,!*r")
1061: (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f,f"))))
1062: (clobber (match_scratch:HI 2 "=&r,&r"))
1063: (clobber (match_dup 1))]
1064: "TARGET_80387"
1065: "* return (char *) output_fix_trunc (insn, operands);")
1066:
1067: (define_insn ""
1068: [(set (match_operand:DI 0 "general_operand" "=m,!*r")
1069: (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f,f"))))
1070: (clobber (match_scratch:HI 2 "=&r,&r"))
1071: (clobber (match_dup 1))]
1072: "TARGET_80387"
1073: "* return (char *) output_fix_trunc (insn, operands);")
1074:
1075: ;; Signed MODE_FLOAT conversion to SImode.
1076:
1077: (define_expand "fix_truncdfsi2"
1078: [(parallel [(set (match_operand:SI 0 "general_operand" "")
1079: (fix:SI
1080: (fix:DF (match_operand:DF 1 "register_operand" ""))))
1081: (clobber (match_scratch:HI 2 ""))])]
1082: "TARGET_80387"
1083: "")
1084:
1085: (define_expand "fix_truncsfsi2"
1086: [(parallel [(set (match_operand:SI 0 "general_operand" "")
1087: (fix:SI
1088: (fix:SF (match_operand:SF 1 "register_operand" ""))))
1089: (clobber (match_scratch:HI 2 ""))])]
1090: "TARGET_80387"
1091: "")
1092:
1093: (define_insn ""
1094: [(set (match_operand:SI 0 "general_operand" "=m,!*r")
1095: (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f,f"))))
1096: (clobber (match_scratch:HI 2 "=&r,&r"))]
1097: "TARGET_80387"
1098: "* return (char *) output_fix_trunc (insn, operands);")
1099:
1100: (define_insn ""
1101: [(set (match_operand:SI 0 "general_operand" "=m,!*r")
1102: (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f,f"))))
1103: (clobber (match_scratch:HI 2 "=&r,&r"))]
1104: "TARGET_80387"
1105: "* return (char *) output_fix_trunc (insn, operands);")
1106:
1107: ;; Conversion between fixed point and floating point.
1108: ;; The actual pattern that matches these is at the end of this file.
1109:
1.1.1.2 ! root 1110: ;; ??? Possibly represent floatunssidf2 here in gcc2.
1.1 root 1111:
1112: (define_expand "floatsisf2"
1113: [(set (match_operand:SF 0 "register_operand" "")
1114: (float:SF (match_operand:SI 1 "general_operand" "")))]
1115: "TARGET_80387"
1116: "")
1117:
1118: (define_expand "floatdisf2"
1119: [(set (match_operand:SF 0 "register_operand" "")
1120: (float:SF (match_operand:DI 1 "general_operand" "")))]
1121: "TARGET_80387"
1122: "")
1123:
1124: (define_expand "floatsidf2"
1125: [(set (match_operand:DF 0 "register_operand" "")
1126: (float:DF (match_operand:SI 1 "general_operand" "")))]
1127: "TARGET_80387"
1128: "")
1129:
1130: (define_expand "floatdidf2"
1131: [(set (match_operand:DF 0 "register_operand" "")
1132: (float:DF (match_operand:DI 1 "general_operand" "")))]
1133: "TARGET_80387"
1134: "")
1135:
1136: ;; This will convert from SImode or DImode to MODE_FLOAT.
1137:
1138: (define_insn ""
1139: [(set (match_operand 0 "register_operand" "=f,f")
1140: (match_operator 2 "float_op"
1141: [(match_operand:DI 1 "general_operand" "m,!*r")]))]
1142: "TARGET_80387 && GET_MODE (operands[0]) == GET_MODE (operands[2])
1143: && GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_FLOAT"
1144: "*
1145: {
1146: if (NON_STACK_REG_P (operands[1]))
1147: {
1148: output_op_from_reg (operands[1], AS1 (fild%z0,%1));
1149: RET;
1150: }
1151: else if (GET_CODE (operands[1]) == MEM)
1152: return AS1 (fild%z1,%1);
1153: else
1154: abort ();
1155: }")
1156:
1157: (define_insn ""
1158: [(set (match_operand 0 "register_operand" "=f,f")
1159: (match_operator 2 "float_op"
1160: [(match_operand:SI 1 "general_operand" "m,!*r")]))]
1161: "TARGET_80387 && GET_MODE (operands[0]) == GET_MODE (operands[2])
1162: && GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_FLOAT"
1163: "*
1164: {
1165: if (NON_STACK_REG_P (operands[1]))
1166: {
1167: output_op_from_reg (operands[1], AS1 (fild%z0,%1));
1168: RET;
1169: }
1170: else if (GET_CODE (operands[1]) == MEM)
1171: return AS1 (fild%z1,%1);
1172: else
1173: abort ();
1174: }")
1175:
1176: ;;- add instructions
1177:
1178: (define_insn "adddi3"
1179: [(set (match_operand:DI 0 "general_operand" "=&r,ro")
1180: (plus:DI (match_operand:DI 1 "general_operand" "%0,0")
1181: (match_operand:DI 2 "general_operand" "o,riF")))]
1182: ""
1183: "*
1184: {
1185: rtx low[3], high[3];
1186:
1187: CC_STATUS_INIT;
1188:
1189: split_di (operands, 3, low, high);
1190:
1191: output_asm_insn (AS2 (add%L0,%2,%0), low);
1192: output_asm_insn (AS2 (adc%L0,%2,%0), high);
1193: RET;
1194: }")
1195:
1196: ;; On a 486, it is faster to do movl/addl than to do a single leal if
1197: ;; operands[1] and operands[2] are both registers.
1198:
1199: (define_insn "addsi3"
1200: [(set (match_operand:SI 0 "general_operand" "=?r,rm,r")
1201: (plus:SI (match_operand:SI 1 "general_operand" "%r,0,0")
1202: (match_operand:SI 2 "general_operand" "ri,ri,rm")))]
1203: ""
1204: "*
1205: {
1206: if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
1207: {
1208: if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
1209: return AS2 (add%L0,%1,%0);
1210:
1211: if (! TARGET_486 || ! REG_P (operands[2]))
1212: {
1213: CC_STATUS_INIT;
1214: operands[1] = SET_SRC (PATTERN (insn));
1215: return AS2 (lea%L0,%a1,%0);
1216: }
1217:
1218: output_asm_insn (AS2 (mov%L0,%1,%0), operands);
1219: }
1220:
1221: if (operands[2] == const1_rtx)
1222: return AS1 (inc%L0,%0);
1223:
1224: if (operands[2] == constm1_rtx)
1225: return AS1 (dec%L0,%0);
1226:
1227: return AS2 (add%L0,%2,%0);
1228: }")
1229:
1230: ;; ??? `lea' here, for three operand add? If leaw is used, only %bx,
1231: ;; %si and %di can appear in SET_SRC, and output_asm_insn might not be
1232: ;; able to handle the operand. But leal always works?
1233:
1234: (define_insn "addhi3"
1235: [(set (match_operand:HI 0 "general_operand" "=rm,r")
1236: (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
1237: (match_operand:HI 2 "general_operand" "ri,rm")))]
1238: ""
1239: "*
1240: {
1241: if (operands[2] == const1_rtx)
1242: return AS1 (inc%W0,%0);
1243:
1244: if (operands[2] == constm1_rtx)
1245: return AS1 (dec%W0,%0);
1246:
1247: return AS2 (add%W0,%2,%0);
1248: }")
1249:
1250: (define_insn "addqi3"
1251: [(set (match_operand:QI 0 "general_operand" "=qm,q")
1252: (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1253: (match_operand:QI 2 "general_operand" "qn,qmn")))]
1254: ""
1255: "*
1256: {
1257: if (operands[2] == const1_rtx)
1258: return AS1 (inc%B0,%0);
1259:
1260: if (operands[2] == constm1_rtx)
1261: return AS1 (dec%B0,%0);
1262:
1263: return AS2 (add%B0,%2,%0);
1264: }")
1265:
1266: ;Lennart Augustsson <[email protected]>
1267: ;says this pattern just makes slower code:
1268: ; pushl %ebp
1269: ; addl $-80,(%esp)
1270: ;instead of
1271: ; leal -80(%ebp),%eax
1272: ; pushl %eax
1273: ;
1274: ;(define_insn ""
1275: ; [(set (match_operand:SI 0 "push_operand" "=<")
1276: ; (plus:SI (match_operand:SI 1 "general_operand" "%r")
1277: ; (match_operand:SI 2 "general_operand" "ri")))]
1278: ; ""
1279: ; "*
1280: ;{
1281: ; rtx xops[4];
1282: ; xops[0] = operands[0];
1283: ; xops[1] = operands[1];
1284: ; xops[2] = operands[2];
1285: ; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx);
1286: ; output_asm_insn (\"push%z1 %1\", xops);
1287: ; output_asm_insn (AS2 (add%z3,%2,%3), xops);
1288: ; RET;
1289: ;}")
1290:
1291: ;; addsi3 is faster, so put this after.
1292:
1293: (define_insn ""
1294: [(set (match_operand:SI 0 "register_operand" "=r")
1295: (match_operand:QI 1 "address_operand" "p"))]
1296: ""
1297: "*
1298: {
1299: CC_STATUS_INIT;
1300: /* Adding a constant to a register is faster with an add. */
1301: /* ??? can this ever happen? */
1302: if (GET_CODE (operands[1]) == PLUS
1303: && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
1304: && rtx_equal_p (operands[0], XEXP (operands[1], 0)))
1305: {
1306: operands[1] = XEXP (operands[1], 1);
1307:
1308: if (operands[1] == const1_rtx)
1309: return AS1 (inc%L0,%0);
1310:
1311: if (operands[1] == constm1_rtx)
1312: return AS1 (dec%L0,%0);
1313:
1314: return AS2 (add%L0,%1,%0);
1315: }
1316: return AS2 (lea%L0,%a1,%0);
1317: }")
1318:
1319: ;; The patterns that match these are at the end of this file.
1320:
1321: (define_expand "adddf3"
1322: [(set (match_operand:DF 0 "register_operand" "")
1323: (plus:DF (match_operand:DF 1 "nonimmediate_operand" "")
1324: (match_operand:DF 2 "nonimmediate_operand" "")))]
1325: "TARGET_80387"
1326: "")
1327:
1328: (define_expand "addsf3"
1329: [(set (match_operand:SF 0 "register_operand" "")
1330: (plus:SF (match_operand:SF 1 "nonimmediate_operand" "")
1331: (match_operand:SF 2 "nonimmediate_operand" "")))]
1332: "TARGET_80387"
1333: "")
1334:
1335: ;;- subtract instructions
1336:
1337: (define_insn "subdi3"
1338: [(set (match_operand:DI 0 "general_operand" "=&r,ro")
1339: (minus:DI (match_operand:DI 1 "general_operand" "0,0")
1340: (match_operand:DI 2 "general_operand" "o,riF")))]
1341: ""
1342: "*
1343: {
1344: rtx low[3], high[3];
1345:
1346: CC_STATUS_INIT;
1347:
1348: split_di (operands, 3, low, high);
1349:
1350: output_asm_insn (AS2 (sub%L0,%2,%0), low);
1351: output_asm_insn (AS2 (sbb%L0,%2,%0), high);
1352: RET;
1353: }")
1354:
1355: (define_insn "subsi3"
1356: [(set (match_operand:SI 0 "general_operand" "=rm,r")
1357: (minus:SI (match_operand:SI 1 "general_operand" "0,0")
1358: (match_operand:SI 2 "general_operand" "ri,rm")))]
1359: ""
1360: "* return AS2 (sub%L0,%2,%0);")
1361:
1362: (define_insn "subhi3"
1363: [(set (match_operand:HI 0 "general_operand" "=rm,r")
1364: (minus:HI (match_operand:HI 1 "general_operand" "0,0")
1365: (match_operand:HI 2 "general_operand" "ri,rm")))]
1366: ""
1367: "* return AS2 (sub%W0,%2,%0);")
1368:
1369: (define_insn "subqi3"
1370: [(set (match_operand:QI 0 "general_operand" "=qm,q")
1371: (minus:QI (match_operand:QI 1 "general_operand" "0,0")
1372: (match_operand:QI 2 "general_operand" "qn,qmn")))]
1373: ""
1374: "* return AS2 (sub%B0,%2,%0);")
1375:
1376: ;; The patterns that match these are at the end of this file.
1377:
1378: (define_expand "subdf3"
1379: [(set (match_operand:DF 0 "register_operand" "")
1380: (minus:DF (match_operand:DF 1 "nonimmediate_operand" "")
1381: (match_operand:DF 2 "nonimmediate_operand" "")))]
1382: "TARGET_80387"
1383: "")
1384:
1385: (define_expand "subsf3"
1386: [(set (match_operand:SF 0 "register_operand" "")
1387: (minus:SF (match_operand:SF 1 "nonimmediate_operand" "")
1388: (match_operand:SF 2 "nonimmediate_operand" "")))]
1389: "TARGET_80387"
1390: "")
1391:
1392: ;;- multiply instructions
1393:
1394: ;(define_insn "mulqi3"
1395: ; [(set (match_operand:QI 0 "general_operand" "=a")
1396: ; (mult:QI (match_operand:QI 1 "general_operand" "%0")
1397: ; (match_operand:QI 2 "general_operand" "qm")))]
1398: ; ""
1399: ; "imul%B0 %2,%0")
1400:
1401: (define_insn ""
1402: [(set (match_operand:HI 0 "general_operand" "=r")
1403: (mult:SI (match_operand:HI 1 "general_operand" "%0")
1404: (match_operand:HI 2 "general_operand" "r")))]
1405: "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
1406: "* return AS2 (imul%W0,%2,%0);")
1407:
1408: (define_insn "mulhi3"
1409: [(set (match_operand:HI 0 "general_operand" "=r,r")
1410: (mult:SI (match_operand:HI 1 "general_operand" "%0,rm")
1411: (match_operand:HI 2 "general_operand" "g,i")))]
1412: ""
1413: "*
1414: {
1415: if (GET_CODE (operands[1]) == REG
1416: && REGNO (operands[1]) == REGNO (operands[0])
1417: && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
1418: /* Assembler has weird restrictions. */
1419: return AS2 (imul%W0,%2,%0);
1420: return AS3 (imul%W0,%2,%1,%0);
1421: }")
1422:
1423: (define_insn ""
1424: [(set (match_operand:SI 0 "general_operand" "=r")
1425: (mult:SI (match_operand:SI 1 "general_operand" "%0")
1426: (match_operand:SI 2 "general_operand" "r")))]
1427: "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
1428: "* return AS2 (imul%L0,%2,%0);")
1429:
1430: (define_insn "mulsi3"
1431: [(set (match_operand:SI 0 "general_operand" "=r,r")
1432: (mult:SI (match_operand:SI 1 "general_operand" "%0,rm")
1433: (match_operand:SI 2 "general_operand" "g,i")))]
1434: ""
1435: "*
1436: {
1437: if (GET_CODE (operands[1]) == REG
1438: && REGNO (operands[1]) == REGNO (operands[0])
1439: && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
1440: /* Assembler has weird restrictions. */
1441: return AS2 (imul%L0,%2,%0);
1442: return AS3 (imul%L0,%2,%1,%0);
1443: }")
1444:
1445: (define_insn "mulqihi3_1"
1446: [(set (match_operand:HI 0 "general_operand" "=a")
1447: (mult:SI (zero_extend:HI
1448: (match_operand:QI 1 "nonimmediate_operand" "%0"))
1449: (zero_extend:HI
1450: (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
1451: ""
1452: "mul%B0 %2")
1453:
1454: ;; The patterns that match these are at the end of this file.
1455:
1456: (define_expand "muldf3"
1457: [(set (match_operand:DF 0 "register_operand" "")
1458: (mult:DF (match_operand:DF 1 "nonimmediate_operand" "")
1459: (match_operand:DF 2 "nonimmediate_operand" "")))]
1460: "TARGET_80387"
1461: "")
1462:
1463: (define_expand "mulsf3"
1464: [(set (match_operand:SF 0 "register_operand" "")
1465: (mult:SF (match_operand:SF 1 "nonimmediate_operand" "")
1466: (match_operand:SF 2 "nonimmediate_operand" "")))]
1467: "TARGET_80387"
1468: "")
1469:
1470: ;;- divide instructions
1471:
1472: (define_insn "divqi3"
1473: [(set (match_operand:QI 0 "general_operand" "=a")
1474: (div:QI (match_operand:HI 1 "general_operand" "0")
1475: (match_operand:QI 2 "general_operand" "qm")))]
1476: ""
1477: "idiv%B0 %2")
1478:
1479: (define_insn "udivqi3"
1480: [(set (match_operand:QI 0 "general_operand" "=a")
1481: (udiv:QI (match_operand:HI 1 "general_operand" "0")
1482: (match_operand:QI 2 "general_operand" "qm")))]
1483: ""
1484: "div%B0 %2")
1485:
1486: ;; The patterns that match these are at the end of this file.
1487:
1488: (define_expand "divdf3"
1489: [(set (match_operand:DF 0 "register_operand" "")
1490: (div:DF (match_operand:DF 1 "nonimmediate_operand" "")
1491: (match_operand:DF 2 "nonimmediate_operand" "")))]
1492: "TARGET_80387"
1493: "")
1494:
1495: (define_expand "divsf3"
1496: [(set (match_operand:SF 0 "register_operand" "")
1497: (div:SF (match_operand:SF 1 "nonimmediate_operand" "")
1498: (match_operand:SF 2 "nonimmediate_operand" "")))]
1499: "TARGET_80387"
1500: "")
1501:
1502: ;; Remainder instructions.
1503:
1504: (define_insn "divmodsi4"
1505: [(set (match_operand:SI 0 "register_operand" "=a")
1506: (div:SI (match_operand:SI 1 "register_operand" "0")
1507: (match_operand:SI 2 "general_operand" "rm")))
1508: (set (match_operand:SI 3 "register_operand" "=&d")
1509: (mod:SI (match_dup 1) (match_dup 2)))]
1510: ""
1511: "*
1512: {
1513: #ifdef INTEL_SYNTAX
1514: output_asm_insn (\"cdq\", operands);
1515: #else
1516: output_asm_insn (\"cltd\", operands);
1517: #endif
1518: return AS1 (idiv%L0,%2);
1519: }")
1520:
1521: (define_insn "divmodhi4"
1522: [(set (match_operand:HI 0 "register_operand" "=a")
1523: (div:HI (match_operand:HI 1 "register_operand" "0")
1524: (match_operand:HI 2 "general_operand" "rm")))
1525: (set (match_operand:HI 3 "register_operand" "=&d")
1526: (mod:HI (match_dup 1) (match_dup 2)))]
1527: ""
1528: "cwtd\;idiv%W0 %2")
1529:
1530: ;; ??? Can we make gcc zero extend operand[0]?
1531: (define_insn "udivmodsi4"
1532: [(set (match_operand:SI 0 "register_operand" "=a")
1533: (udiv:SI (match_operand:SI 1 "register_operand" "0")
1534: (match_operand:SI 2 "general_operand" "rm")))
1535: (set (match_operand:SI 3 "register_operand" "=&d")
1536: (umod:SI (match_dup 1) (match_dup 2)))]
1537: ""
1538: "*
1539: {
1540: output_asm_insn (AS2 (xor%L3,%3,%3), operands);
1541: return AS1 (div%L0,%2);
1542: }")
1543:
1544: ;; ??? Can we make gcc zero extend operand[0]?
1545: (define_insn "udivmodhi4"
1546: [(set (match_operand:HI 0 "register_operand" "=a")
1547: (udiv:HI (match_operand:HI 1 "register_operand" "0")
1548: (match_operand:HI 2 "general_operand" "rm")))
1549: (set (match_operand:HI 3 "register_operand" "=&d")
1550: (umod:HI (match_dup 1) (match_dup 2)))]
1551: ""
1552: "*
1553: {
1554: output_asm_insn (AS2 (xor%W0,%3,%3), operands);
1555: return AS1 (div%W0,%2);
1556: }")
1557:
1558: /*
1559: ;;this should be a valid double division which we may want to add
1560:
1561: (define_insn ""
1562: [(set (match_operand:SI 0 "register_operand" "=a")
1563: (udiv:DI (match_operand:DI 1 "register_operand" "a")
1564: (match_operand:SI 2 "general_operand" "rm")))
1565: (set (match_operand:SI 3 "register_operand" "=d")
1566: (umod:SI (match_dup 1) (match_dup 2)))]
1567: ""
1568: "div%L0 %2,%0")
1569: */
1570:
1571: ;;- and instructions
1572:
1573: ;; On i386,
1574: ;; movzbl %bl,%ebx
1575: ;; is faster than
1576: ;; andl $255,%ebx
1577: ;;
1578: ;; but if the reg is %eax, then the "andl" is faster.
1579: ;;
1580: ;; On i486, the "andl" is always faster than the "movzbl".
1581: ;;
1582: ;; On both i386 and i486, a three operand AND is as fast with movzbl or
1583: ;; movzwl as with andl, if operands[0] != operands[1].
1584:
1585: ;; The `r' in `rm' for operand 3 looks redundant, but it causes
1586: ;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
1587:
1588: ;; ??? What if we only change one byte of an offsettable memory reference?
1589: (define_insn "andsi3"
1590: [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r")
1591: (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0")
1592: (match_operand:SI 2 "general_operand" "L,K,ri,rm")))]
1593: ""
1594: "*
1595: {
1596: if (GET_CODE (operands[2]) == CONST_INT
1597: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
1598: {
1599: if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0])
1600: && (! REG_P (operands[1])
1601: || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
1602: && (! TARGET_486 || ! rtx_equal_p (operands[0], operands[1])))
1603: {
1604: /* ??? tege: Should forget CC_STATUS only if we clobber a
1605: remembered operand. Fix that later. */
1606: CC_STATUS_INIT;
1607: #ifdef INTEL_SYNTAX
1608: return AS2 (movzx,%w1,%0);
1609: #else
1610: return AS2 (movz%W0%L0,%w1,%0);
1611: #endif
1612: }
1613:
1614: if (INTVAL (operands[2]) == 0xff && REG_P (operands[0])
1615: && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
1616: && (! REG_P (operands[1])
1617: || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
1618: && (! TARGET_486 || ! rtx_equal_p (operands[0], operands[1])))
1619: {
1620: /* ??? tege: Should forget CC_STATUS only if we clobber a
1621: remembered operand. Fix that later. */
1622: CC_STATUS_INIT;
1623: #ifdef INTEL_SYNTAX
1624: return AS2 (movzx,%b1,%0);
1625: #else
1626: return AS2 (movz%B0%L0,%b1,%0);
1627: #endif
1628: }
1629:
1630: if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0)
1631: {
1632: CC_STATUS_INIT;
1633:
1634: if (INTVAL (operands[2]) == 0xffffff00)
1635: {
1636: operands[2] = const0_rtx;
1637: return AS2 (mov%B0,%2,%b0);
1638: }
1639:
1640: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1641: INTVAL (operands[2]) & 0xff);
1642: return AS2 (and%B0,%2,%b0);
1643: }
1644:
1645: if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0)
1646: {
1647: CC_STATUS_INIT;
1648:
1649: if (INTVAL (operands[2]) == 0xffff00ff)
1650: {
1651: operands[2] = const0_rtx;
1652: return AS2 (mov%B0,%2,%h0);
1653: }
1654:
1655: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1656: INTVAL (operands[2]) >> 8);
1657: return AS2 (and%B0,%2,%h0);
1658: }
1659:
1660: if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000)
1661: {
1662: operands[2] = const0_rtx;
1663: return AS2 (mov%W0,%2,%w0);
1664: }
1665: }
1666:
1667: return AS2 (and%L0,%2,%0);
1668: }")
1669:
1670: (define_insn "andhi3"
1671: [(set (match_operand:HI 0 "general_operand" "=rm,r")
1672: (and:HI (match_operand:HI 1 "general_operand" "%0,0")
1673: (match_operand:HI 2 "general_operand" "ri,rm")))]
1674: ""
1675: "*
1676: {
1677: if (GET_CODE (operands[2]) == CONST_INT
1678: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
1679: {
1680: /* Can we ignore the upper byte? */
1681: if (! NON_QI_REG_P (operands[0])
1682: && (INTVAL (operands[2]) & 0xff00) == 0xff00)
1683: {
1684: CC_STATUS_INIT;
1685:
1686: if ((INTVAL (operands[2]) & 0xff) == 0)
1687: {
1688: operands[2] = const0_rtx;
1689: return AS2 (mov%B0,%2,%b0);
1690: }
1691:
1692: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1693: INTVAL (operands[2]) & 0xff);
1694: return AS2 (and%B0,%2,%b0);
1695: }
1696:
1697: /* Can we ignore the lower byte? */
1698: /* ??? what about offsettable memory references? */
1699: if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff)
1700: {
1701: CC_STATUS_INIT;
1702:
1703: if ((INTVAL (operands[2]) & 0xff00) == 0)
1704: {
1705: operands[2] = const0_rtx;
1706: return AS2 (mov%B0,%2,%h0);
1707: }
1708:
1709: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1710: (INTVAL (operands[2]) >> 8) & 0xff);
1711: return AS2 (and%B0,%2,%h0);
1712: }
1713: }
1714:
1715: return AS2 (and%W0,%2,%0);
1716: }")
1717:
1718: (define_insn "andqi3"
1719: [(set (match_operand:QI 0 "general_operand" "=qm,q")
1720: (and:QI (match_operand:QI 1 "general_operand" "%0,0")
1721: (match_operand:QI 2 "general_operand" "qn,qmn")))]
1722: ""
1723: "* return AS2 (and%B0,%2,%0);")
1724:
1725: /* I am nervous about these two.. add them later..
1726: ;I presume this means that we have something in say op0= eax which is small
1727: ;and we want to and it with memory so we can do this by just an
1728: ;andb m,%al and have success.
1729: (define_insn ""
1730: [(set (match_operand:SI 0 "general_operand" "=r")
1731: (and:SI (zero_extend:SI
1732: (match_operand:HI 1 "nonimmediate_operand" "rm"))
1733: (match_operand:SI 2 "general_operand" "0")))]
1734: "GET_CODE (operands[2]) == CONST_INT
1735: && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
1736: "and%W0 %1,%0")
1737:
1738: (define_insn ""
1739: [(set (match_operand:SI 0 "general_operand" "=q")
1740: (and:SI
1741: (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))
1742: (match_operand:SI 2 "general_operand" "0")))]
1743: "GET_CODE (operands[2]) == CONST_INT
1744: && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
1745: "and%L0 %1,%0")
1746:
1747: */
1748:
1749: ;;- Bit set (inclusive or) instructions
1750:
1751: ;; ??? What if we only change one byte of an offsettable memory reference?
1752: (define_insn "iorsi3"
1753: [(set (match_operand:SI 0 "general_operand" "=rm,r")
1754: (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
1755: (match_operand:SI 2 "general_operand" "ri,rm")))]
1756: ""
1757: "*
1758: {
1759: if (GET_CODE (operands[2]) == CONST_INT
1760: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
1761: {
1762: if (! NON_QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff) == 0)
1763: {
1764: CC_STATUS_INIT;
1765:
1766: if (INTVAL (operands[2]) == 0xff)
1767: return AS2 (mov%B0,%2,%b0);
1768:
1769: return AS2 (or%B0,%2,%b0);
1770: }
1771:
1772: if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
1773: {
1774: CC_STATUS_INIT;
1775: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1776: INTVAL (operands[2]) >> 8);
1777:
1778: if (INTVAL (operands[2]) == 0xff)
1779: return AS2 (mov%B0,%2,%h0);
1780:
1781: return AS2 (or%B0,%2,%h0);
1782: }
1783: }
1784:
1785: return AS2 (or%L0,%2,%0);
1786: }")
1787:
1788: (define_insn "iorhi3"
1789: [(set (match_operand:HI 0 "general_operand" "=rm,r")
1790: (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
1791: (match_operand:HI 2 "general_operand" "ri,rm")))]
1792: ""
1793: "*
1794: {
1795: if (GET_CODE (operands[2]) == CONST_INT
1796: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
1797: {
1798: /* Can we ignore the upper byte? */
1799: if (! NON_QI_REG_P (operands[0])
1800: && (INTVAL (operands[2]) & 0xff00) == 0)
1801: {
1802: CC_STATUS_INIT;
1803: if (INTVAL (operands[2]) & 0xffff0000)
1804: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1805: INTVAL (operands[2]) & 0xffff);
1806:
1807: if (INTVAL (operands[2]) == 0xff)
1808: return AS2 (mov%B0,%2,%b0);
1809:
1810: return AS2 (or%B0,%2,%b0);
1811: }
1812:
1813: /* Can we ignore the lower byte? */
1814: /* ??? what about offsettable memory references? */
1815: if (QI_REG_P (operands[0])
1816: && (INTVAL (operands[2]) & 0xff) == 0)
1817: {
1818: CC_STATUS_INIT;
1819: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1820: (INTVAL (operands[2]) >> 8) & 0xff);
1821:
1822: if (INTVAL (operands[2]) == 0xff)
1823: return AS2 (mov%B0,%2,%h0);
1824:
1825: return AS2 (or%B0,%2,%h0);
1826: }
1827: }
1828:
1829: return AS2 (or%W0,%2,%0);
1830: }")
1831:
1832: (define_insn "iorqi3"
1833: [(set (match_operand:QI 0 "general_operand" "=qm,q")
1834: (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
1835: (match_operand:QI 2 "general_operand" "qn,qmn")))]
1836: ""
1837: "* return AS2 (or%B0,%2,%0);")
1838:
1839: ;;- xor instructions
1840:
1841: ;; ??? What if we only change one byte of an offsettable memory reference?
1842: (define_insn "xorsi3"
1843: [(set (match_operand:SI 0 "general_operand" "=rm,r")
1844: (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
1845: (match_operand:SI 2 "general_operand" "ri,rm")))]
1846: ""
1847: "*
1848: {
1849: if (GET_CODE (operands[2]) == CONST_INT
1850: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
1851: {
1852: if (! NON_QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff) == 0)
1853: {
1854: CC_STATUS_INIT;
1855:
1856: if (INTVAL (operands[2]) == 0xff)
1.1.1.2 ! root 1857: return AS1 (not%B0,%b0);
1.1 root 1858:
1859: return AS2 (xor%B0,%2,%b0);
1860: }
1861:
1862: if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
1863: {
1864: CC_STATUS_INIT;
1865: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1866: INTVAL (operands[2]) >> 8);
1867:
1868: if (INTVAL (operands[2]) == 0xff)
1869: return AS1 (not%B0,%h0);
1870:
1871: return AS2 (xor%B0,%2,%h0);
1872: }
1873: }
1874:
1875: return AS2 (xor%L0,%2,%0);
1876: }")
1877:
1878: (define_insn "xorhi3"
1879: [(set (match_operand:HI 0 "general_operand" "=rm,r")
1880: (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1881: (match_operand:HI 2 "general_operand" "ri,rm")))]
1882: ""
1883: "*
1884: {
1885: if (GET_CODE (operands[2]) == CONST_INT
1886: && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
1887: {
1888: /* Can we ignore the upper byte? */
1889: if (! NON_QI_REG_P (operands[0])
1890: && (INTVAL (operands[2]) & 0xff00) == 0)
1891: {
1892: CC_STATUS_INIT;
1893: if (INTVAL (operands[2]) & 0xffff0000)
1894: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1895: INTVAL (operands[2]) & 0xffff);
1896:
1897: if (INTVAL (operands[2]) == 0xff)
1.1.1.2 ! root 1898: return AS1 (not%B0,%b0);
1.1 root 1899:
1900: return AS2 (xor%B0,%2,%b0);
1901: }
1902:
1903: /* Can we ignore the lower byte? */
1904: /* ??? what about offsettable memory references? */
1905: if (QI_REG_P (operands[0])
1906: && (INTVAL (operands[2]) & 0xff) == 0)
1907: {
1908: CC_STATUS_INIT;
1909: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1910: (INTVAL (operands[2]) >> 8) & 0xff);
1911:
1912: if (INTVAL (operands[2]) == 0xff)
1913: return AS1 (not%B0,%h0);
1914:
1915: return AS2 (xor%B0,%2,%h0);
1916: }
1917: }
1918:
1919: return AS2 (xor%W0,%2,%0);
1920: }")
1921:
1922: (define_insn "xorqi3"
1923: [(set (match_operand:QI 0 "general_operand" "=qm,q")
1924: (xor:QI (match_operand:QI 1 "general_operand" "%0,0")
1925: (match_operand:QI 2 "general_operand" "qn,qm")))]
1926: ""
1927: "* return AS2 (xor%B0,%2,%0);")
1928:
1929: ;;- negation instructions
1930:
1931: (define_insn "negdi2"
1932: [(set (match_operand:DI 0 "general_operand" "=&ro")
1933: (neg:DI (match_operand:DI 1 "general_operand" "0")))]
1934: ""
1935: "*
1936: {
1937: rtx xops[2], low[1], high[1];
1938:
1939: CC_STATUS_INIT;
1940:
1941: split_di (operands, 1, low, high);
1942: xops[0] = const0_rtx;
1943: xops[1] = high[0];
1944:
1945: output_asm_insn (AS1 (neg%L0,%0), low);
1946: output_asm_insn (AS2 (adc%L1,%0,%1), xops);
1947: output_asm_insn (AS1 (neg%L0,%0), high);
1948: RET;
1949: }")
1950:
1951: (define_insn "negsi2"
1952: [(set (match_operand:SI 0 "general_operand" "=rm")
1953: (neg:SI (match_operand:SI 1 "general_operand" "0")))]
1954: ""
1955: "neg%L0 %0")
1956:
1957: (define_insn "neghi2"
1958: [(set (match_operand:HI 0 "general_operand" "=rm")
1959: (neg:HI (match_operand:HI 1 "general_operand" "0")))]
1960: ""
1961: "neg%W0 %0")
1962:
1963: (define_insn "negqi2"
1964: [(set (match_operand:QI 0 "general_operand" "=qm")
1965: (neg:QI (match_operand:QI 1 "general_operand" "0")))]
1966: ""
1967: "neg%B0 %0")
1968:
1969: (define_insn "negsf2"
1970: [(set (match_operand:SF 0 "register_operand" "=f")
1971: (neg:SF (match_operand:SF 1 "general_operand" "0")))]
1972: "TARGET_80387"
1973: "fchs")
1974:
1975: (define_insn "negdf2"
1976: [(set (match_operand:DF 0 "register_operand" "=f")
1977: (neg:DF (match_operand:DF 1 "general_operand" "0")))]
1978: "TARGET_80387"
1979: "fchs")
1980:
1981: (define_insn ""
1982: [(set (match_operand:DF 0 "register_operand" "=f")
1983: (neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
1984: "TARGET_80387"
1985: "fchs")
1986:
1987: ;; Absolute value instructions
1988:
1989: (define_insn "abssf2"
1990: [(set (match_operand:SF 0 "register_operand" "=f")
1991: (abs:SF (match_operand:SF 1 "general_operand" "0")))]
1992: "TARGET_80387"
1993: "fabs")
1994:
1995: (define_insn "absdf2"
1996: [(set (match_operand:DF 0 "register_operand" "=f")
1997: (abs:DF (match_operand:DF 1 "general_operand" "0")))]
1998: "TARGET_80387"
1999: "fabs")
2000:
2001: (define_insn ""
2002: [(set (match_operand:DF 0 "register_operand" "=f")
2003: (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
2004: "TARGET_80387"
2005: "fabs")
2006:
2007: (define_insn "sqrtsf2"
2008: [(set (match_operand:SF 0 "register_operand" "=f")
2009: (sqrt:SF (match_operand:SF 1 "general_operand" "0")))]
2010: "TARGET_80387"
2011: "fsqrt")
2012:
2013: (define_insn "sqrtdf2"
2014: [(set (match_operand:DF 0 "register_operand" "=f")
2015: (sqrt:DF (match_operand:DF 1 "general_operand" "0")))]
2016: "TARGET_80387"
2017: "fsqrt")
2018:
2019: (define_insn ""
2020: [(set (match_operand:DF 0 "register_operand" "=f")
2021: (sqrt:DF (float_extend:DF
2022: (match_operand:SF 1 "general_operand" "0"))))]
2023: "TARGET_80387"
2024: "fsqrt")
2025:
2026: ;;- one complement instructions
2027:
2028: (define_insn "one_cmplsi2"
2029: [(set (match_operand:SI 0 "general_operand" "=rm")
2030: (not:SI (match_operand:SI 1 "general_operand" "0")))]
2031: ""
2032: "not%L0 %0")
2033:
2034: (define_insn "one_cmplhi2"
2035: [(set (match_operand:HI 0 "general_operand" "=rm")
2036: (not:HI (match_operand:HI 1 "general_operand" "0")))]
2037: ""
2038: "not%W0 %0")
2039:
2040: (define_insn "one_cmplqi2"
2041: [(set (match_operand:QI 0 "general_operand" "=qm")
2042: (not:QI (match_operand:QI 1 "general_operand" "0")))]
2043: ""
2044: "not%B0 %0")
2045:
2046: ;;- arithmetic shift instructions
2047:
2048: ;; DImode shifts are implemented using the i386 "shift double" opcode,
2049: ;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count
2050: ;; is variable, then the count is in %cl and the "imm" operand is dropped
2051: ;; from the assembler input.
2052:
2053: ;; This instruction shifts the target reg/mem as usual, but instead of
2054: ;; shifting in zeros, bits are shifted in from reg operand. If the insn
2055: ;; is a left shift double, bits are taken from the high order bits of
2056: ;; reg, else if the insn is a shift right double, bits are taken from the
2057: ;; low order bits of reg. So if %eax is "1234" and %edx is "5678",
2058: ;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
2059:
2060: ;; Since sh[lr]d does not change the `reg' operand, that is done
2061: ;; separately, making all shifts emit pairs of shift double and normal
2062: ;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to
2063: ;; support a 63 bit shift, each shift where the count is in a reg expands
2064: ;; to three pairs. If the overall shift is by N bits, then the first two
2065: ;; pairs shift by N / 2 and the last pair by N & 1.
2066:
2067: ;; If the shift count is a constant, we need never emit more than one
2068: ;; shift pair, instead using moves and sign extension for counts greater
2069: ;; than 31.
2070:
2071: (define_insn "ashldi3"
2072: [(set (match_operand:DI 0 "general_operand" "=&r")
2073: (ashift:DI (match_operand:DI 1 "general_operand" "0")
2074: (match_operand:QI 2 "general_operand" "cJ")))
2075: (clobber (match_dup 2))]
2076: ""
2077: "*
2078: {
2079: rtx xops[4], low[1], high[1];
2080:
2081: CC_STATUS_INIT;
2082:
2083: split_di (operands, 1, low, high);
2084: xops[0] = operands[2];
2085: xops[1] = const1_rtx;
2086: xops[2] = low[0];
2087: xops[3] = high[0];
2088:
2089: if (REG_P (xops[0])) /* If shift count in %cl */
2090: {
2091: output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */
2092:
2093: output_asm_insn (AS2 (shld%L3,%2,%3), xops);
2094: output_asm_insn (AS2 (sal%L2,%0,%2), xops);
2095: output_asm_insn (AS2 (shld%L3,%2,%3), xops);
2096: output_asm_insn (AS2 (sal%L2,%0,%2), xops);
2097:
2098: xops[1] = gen_rtx (CONST_INT, VOIDmode, 7); /* shift count & 1 */
2099:
2100: output_asm_insn (AS2 (shr%B0,%1,%0), xops);
2101:
2102: output_asm_insn (AS2 (shld%L3,%2,%3), xops);
2103: output_asm_insn (AS2 (sal%L2,%0,%2), xops);
2104: }
2105: else if (GET_CODE (xops[0]) == CONST_INT)
2106: {
2107: if (INTVAL (xops[0]) > 31)
2108: {
2109: output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */
2110: output_asm_insn (AS2 (xor%L2,%2,%2), xops);
2111:
2112: if (INTVAL (xops[0]) > 32)
2113: {
2114: xops[0] = gen_rtx (CONST_INT, VOIDmode, INTVAL (xops[0]) - 32);
2115:
2116: output_asm_insn (AS2 (sal%3,%0,%3), xops); /* Remaining shift */
2117: }
2118: }
2119: else
2120: {
2121: output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops);
2122: output_asm_insn (AS2 (sal%L2,%0,%2), xops);
2123: }
2124: }
2125: RET;
2126: }")
2127:
2128: ;; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg"
2129: ;; On i486, movl/sall appears slightly faster than leal, but the leal
2130: ;; is smaller - use leal for now unless the shift count is 1.
2131:
2132: (define_insn "ashlsi3"
2133: [(set (match_operand:SI 0 "general_operand" "=r,rm")
2134: (ashift:SI (match_operand:SI 1 "general_operand" "r,0")
2135: (match_operand:SI 2 "general_operand" "M,cI")))]
2136: ""
2137: "*
2138: {
2139: if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
2140: {
2141: if (TARGET_486 && INTVAL (operands[2]) == 1)
2142: {
2143: output_asm_insn (AS2 (mov%L0,%1,%0), operands);
2144: return AS2 (add%L0,%1,%0);
2145: }
2146: else
2147: {
2148: CC_STATUS_INIT;
2149: operands[1] = gen_rtx (MULT, SImode, operands[1],
2150: gen_rtx (CONST_INT, VOIDmode,
2151: 1 << INTVAL (operands[2])));
2152: return AS2 (lea%L0,%a1,%0);
2153: }
2154: }
2155:
2156: if (REG_P (operands[2]))
2157: return AS2 (sal%L0,%b2,%0);
2158:
2159: if (REG_P (operands[0]) && operands[2] == const1_rtx)
2160: return AS2 (add%L0,%0,%0);
2161:
2162: return AS2 (sal%L0,%2,%0);
2163: }")
2164:
2165: (define_insn "ashlhi3"
2166: [(set (match_operand:HI 0 "general_operand" "=rm")
2167: (ashift:HI (match_operand:HI 1 "general_operand" "0")
2168: (match_operand:HI 2 "general_operand" "cI")))]
2169: ""
2170: "*
2171: {
2172: if (REG_P (operands[2]))
2173: return AS2 (sal%W0,%b2,%0);
2174:
2175: if (REG_P (operands[0]) && operands[2] == const1_rtx)
2176: return AS2 (add%W0,%0,%0);
2177:
2178: return AS2 (sal%W0,%2,%0);
2179: }")
2180:
2181: (define_insn "ashlqi3"
2182: [(set (match_operand:QI 0 "general_operand" "=qm")
2183: (ashift:QI (match_operand:QI 1 "general_operand" "0")
2184: (match_operand:QI 2 "general_operand" "cI")))]
2185: ""
2186: "*
2187: {
2188: if (REG_P (operands[2]))
2189: return AS2 (sal%B0,%b2,%0);
2190:
2191: if (REG_P (operands[0]) && operands[2] == const1_rtx)
2192: return AS2 (add%B0,%0,%0);
2193:
2194: return AS2 (sal%B0,%2,%0);
2195: }")
2196:
2197: ;; See comment above `ashldi3' about how this works.
2198:
2199: (define_insn "ashrdi3"
2200: [(set (match_operand:DI 0 "general_operand" "=&r")
2201: (ashiftrt:DI (match_operand:DI 1 "general_operand" "0")
2202: (match_operand:QI 2 "general_operand" "cJ")))
2203: (clobber (match_dup 2))]
2204: ""
2205: "*
2206: {
2207: rtx xops[5], low[1], high[1];
2208:
2209: CC_STATUS_INIT;
2210:
2211: split_di (operands, 1, low, high);
2212: xops[0] = operands[2];
2213: xops[1] = const1_rtx;
2214: xops[2] = low[0];
2215: xops[3] = high[0];
2216:
2217: if (REG_P (xops[0])) /* If shift count in %cl */
2218: {
2219: output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */
2220:
2221: output_asm_insn (AS2 (shrd%L2,%3,%2), xops);
2222: output_asm_insn (AS2 (sar%L3,%0,%3), xops);
2223: output_asm_insn (AS2 (shrd%L2,%3,%2), xops);
2224: output_asm_insn (AS2 (sar%L3,%0,%3), xops);
2225:
2226: xops[1] = gen_rtx (CONST_INT, VOIDmode, 7); /* shift count & 1 */
2227:
2228: output_asm_insn (AS2 (shr%B0,%1,%0), xops);
2229:
2230: output_asm_insn (AS2 (shrd%L2,%3,%2), xops);
2231: output_asm_insn (AS2 (sar%L3,%0,%3), xops);
2232: }
2233: else if (GET_CODE (xops[0]) == CONST_INT)
2234: {
2235: if (INTVAL (xops[0]) > 31)
2236: {
2237: xops[1] = gen_rtx (CONST_INT, VOIDmode, 31);
2238: output_asm_insn (AS2 (mov%L2,%3,%2), xops);
2239: output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */
2240:
2241: if (INTVAL (xops[0]) > 32)
2242: {
2243: xops[0] = gen_rtx (CONST_INT, VOIDmode, INTVAL (xops[0]) - 32);
2244:
2245: output_asm_insn (AS2 (sar%2,%0,%2), xops); /* Remaining shift */
2246: }
2247: }
2248: else
2249: {
2250: output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
2251: output_asm_insn (AS2 (sar%L3,%0,%3), xops);
2252: }
2253: }
2254: RET;
2255: }")
2256:
2257: (define_insn "ashrsi3"
2258: [(set (match_operand:SI 0 "general_operand" "=rm")
2259: (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
2260: (match_operand:SI 2 "general_operand" "cI")))]
2261: ""
2262: "*
2263: {
2264: if (REG_P (operands[2]))
2265: return AS2 (sar%L0,%b2,%0);
2266: else
2267: return AS2 (sar%L0,%2,%0);
2268: }")
2269:
2270: (define_insn "ashrhi3"
2271: [(set (match_operand:HI 0 "general_operand" "=rm")
2272: (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
2273: (match_operand:HI 2 "general_operand" "cI")))]
2274: ""
2275: "*
2276: {
2277: if (REG_P (operands[2]))
2278: return AS2 (sar%W0,%b2,%0);
2279: else
2280: return AS2 (sar%W0,%2,%0);
2281: }")
2282:
2283: (define_insn "ashrqi3"
2284: [(set (match_operand:QI 0 "general_operand" "=qm")
2285: (ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
2286: (match_operand:QI 2 "general_operand" "cI")))]
2287: ""
2288: "*
2289: {
2290: if (REG_P (operands[2]))
2291: return AS2 (sar%B0,%b2,%0);
2292: else
2293: return AS2 (sar%B0,%2,%0);
2294: }")
2295:
2296: ;;- logical shift instructions
2297:
2298: ;; See comment above `ashldi3' about how this works.
2299:
2300: (define_insn "lshrdi3"
2301: [(set (match_operand:DI 0 "general_operand" "=&r")
2302: (lshiftrt:DI (match_operand:DI 1 "general_operand" "0")
2303: (match_operand:QI 2 "general_operand" "cJ")))
2304: (clobber (match_dup 2))]
2305: ""
2306: "*
2307: {
2308: rtx xops[5], low[1], high[1];
2309:
2310: CC_STATUS_INIT;
2311:
2312: split_di (operands, 1, low, high);
2313: xops[0] = operands[2];
2314: xops[1] = const1_rtx;
2315: xops[2] = low[0];
2316: xops[3] = high[0];
2317:
2318: if (REG_P (xops[0])) /* If shift count in %cl */
2319: {
2320: output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */
2321:
2322: output_asm_insn (AS2 (shrd%L2,%3,%2), xops);
2323: output_asm_insn (AS2 (shr%L3,%0,%3), xops);
2324: output_asm_insn (AS2 (shrd%L2,%3,%2), xops);
2325: output_asm_insn (AS2 (shr%L3,%0,%3), xops);
2326:
2327: xops[1] = gen_rtx (CONST_INT, VOIDmode, 7); /* shift count & 1 */
2328:
2329: output_asm_insn (AS2 (shr%B0,%1,%0), xops);
2330:
2331: output_asm_insn (AS2 (shrd%L2,%3,%2), xops);
2332: output_asm_insn (AS2 (shr%L3,%0,%3), xops);
2333: }
2334: else if (GET_CODE (xops[0]) == CONST_INT)
2335: {
2336: if (INTVAL (xops[0]) > 31)
2337: {
2338: output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */
2339: output_asm_insn (AS2 (xor%L3,%3,%3), xops);
2340:
2341: if (INTVAL (xops[0]) > 32)
2342: {
2343: xops[0] = gen_rtx (CONST_INT, VOIDmode, INTVAL (xops[0]) - 32);
2344:
2345: output_asm_insn (AS2 (shr%2,%0,%2), xops); /* Remaining shift */
2346: }
2347: }
2348: else
2349: {
2350: output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
2351: output_asm_insn (AS2 (shr%L3,%0,%3), xops);
2352: }
2353: }
2354: RET;
2355: }")
2356:
2357: (define_insn "lshrsi3"
2358: [(set (match_operand:SI 0 "general_operand" "=rm")
2359: (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
2360: (match_operand:SI 2 "general_operand" "cI")))]
2361: ""
2362: "*
2363: {
2364: if (REG_P (operands[2]))
2365: return AS2 (shr%L0,%b2,%0);
2366: else
2367: return AS2 (shr%L0,%2,%1);
2368: }")
2369:
2370: (define_insn "lshrhi3"
2371: [(set (match_operand:HI 0 "general_operand" "=rm")
2372: (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
2373: (match_operand:HI 2 "general_operand" "cI")))]
2374: ""
2375: "*
2376: {
2377: if (REG_P (operands[2]))
2378: return AS2 (shr%W0,%b2,%0);
2379: else
2380: return AS2 (shr%W0,%2,%0);
2381: }")
2382:
2383: (define_insn "lshrqi3"
2384: [(set (match_operand:QI 0 "general_operand" "=qm")
2385: (lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
2386: (match_operand:QI 2 "general_operand" "cI")))]
2387: ""
2388: "*
2389: {
2390: if (REG_P (operands[2]))
2391: return AS2 (shr%B0,%b2,%0);
2392: else
2393: return AS2 (shr%B0,%2,%0);
2394: }")
2395:
2396: ;;- rotate instructions
2397:
2398: (define_insn "rotlsi3"
2399: [(set (match_operand:SI 0 "general_operand" "=rm")
2400: (rotate:SI (match_operand:SI 1 "general_operand" "0")
2401: (match_operand:SI 2 "general_operand" "cI")))]
2402: ""
2403: "*
2404: {
2405: if (REG_P (operands[2]))
2406: return AS2 (rol%L0,%b2,%0);
2407: else
2408: return AS2 (rol%L0,%2,%0);
2409: }")
2410:
2411: (define_insn "rotlhi3"
2412: [(set (match_operand:HI 0 "general_operand" "=rm")
2413: (rotate:HI (match_operand:HI 1 "general_operand" "0")
2414: (match_operand:HI 2 "general_operand" "cI")))]
2415: ""
2416: "*
2417: {
2418: if (REG_P (operands[2]))
2419: return AS2 (rol%W0,%b2,%0);
2420: else
2421: return AS2 (rol%W0,%2,%0);
2422: }")
2423:
2424: (define_insn "rotlqi3"
2425: [(set (match_operand:QI 0 "general_operand" "=qm")
2426: (rotate:QI (match_operand:QI 1 "general_operand" "0")
2427: (match_operand:QI 2 "general_operand" "cI")))]
2428: ""
2429: "*
2430: {
2431: if (REG_P (operands[2]))
2432: return AS2 (rol%B0,%b2,%0);
2433: else
2434: return AS2 (rol%B0,%2,%0);
2435: }")
2436:
2437: (define_insn "rotrsi3"
2438: [(set (match_operand:SI 0 "general_operand" "=rm")
2439: (rotatert:SI (match_operand:SI 1 "general_operand" "0")
2440: (match_operand:SI 2 "general_operand" "cI")))]
2441: ""
2442: "*
2443: {
2444: if (REG_P (operands[2]))
2445: return AS2 (ror%L0,%b2,%0);
2446: else
2447: return AS2 (ror%L0,%2,%0);
2448: }")
2449:
2450: (define_insn "rotrhi3"
2451: [(set (match_operand:HI 0 "general_operand" "=rm")
2452: (rotatert:HI (match_operand:HI 1 "general_operand" "0")
2453: (match_operand:HI 2 "general_operand" "cI")))]
2454: ""
2455: "*
2456: {
2457: if (REG_P (operands[2]))
2458: return AS2 (ror%W0,%b2,%0);
2459: else
2460: return AS2 (ror%W0,%2,%0);
2461: }")
2462:
2463: (define_insn "rotrqi3"
2464: [(set (match_operand:QI 0 "general_operand" "=qm")
2465: (rotatert:QI (match_operand:QI 1 "general_operand" "0")
2466: (match_operand:QI 2 "general_operand" "cI")))]
2467: ""
2468: "*
2469: {
2470: if (REG_P (operands[2]))
2471: return AS2 (ror%B0,%b2,%0);
2472: else
2473: return AS2 (ror%B0,%2,%0);
2474: }")
2475:
2476: /*
2477: ;; This usually looses. But try a define_expand to recognize a few case
2478: ;; we can do efficiently, such as accessing the "high" QImode registers,
2479: ;; %ah, %bh, %ch, %dh.
2480: (define_insn "insv"
2481: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r")
2482: (match_operand:SI 1 "general_operand" "i")
2483: (match_operand:SI 2 "general_operand" "i"))
2484: (match_operand:SI 3 "general_operand" "ri"))]
2485: ""
2486: "*
2487: {
2488: if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode))
2489: abort ();
2490: if (GET_CODE (operands[3]) == CONST_INT)
2491: {
2492: unsigned int mask = (1 << INTVAL (operands[1])) - 1;
2493: operands[1] = gen_rtx (CONST_INT, VOIDmode,
2494: ~(mask << INTVAL (operands[2])));
2495: output_asm_insn (AS2 (and%L0,%1,%0), operands);
2496: operands[3] = gen_rtx (CONST_INT, VOIDmode,
2497: INTVAL (operands[3]) << INTVAL (operands[2]));
2498: output_asm_insn (AS2 (or%L0,%3,%0), operands);
2499: }
2500: else
2501: {
2502: operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]));
2503: if (INTVAL (operands[2]))
2504: output_asm_insn (AS2 (ror%L0,%2,%0), operands);
2505: output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands);
2506: operands[2] = gen_rtx (CONST_INT, VOIDmode,
2507: BITS_PER_WORD
2508: - INTVAL (operands[1]) - INTVAL (operands[2]));
2509: if (INTVAL (operands[2]))
2510: output_asm_insn (AS2 (ror%L0,%2,%0), operands);
2511: }
2512: RET;
2513: }")
2514: */
2515: /*
2516: ;; ??? There are problems with the mode of operand[3]. The point of this
2517: ;; is to represent an HImode move to a "high byte" register.
2518:
2519: (define_expand "insv"
2520: [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
2521: (match_operand:SI 1 "immediate_operand" "")
2522: (match_operand:SI 2 "immediate_operand" ""))
2523: (match_operand:QI 3 "general_operand" "ri"))]
2524: ""
2525: "
2526: {
2527: if (GET_CODE (operands[1]) != CONST_INT
2528: || GET_CODE (operands[2]) != CONST_INT)
2529: FAIL;
2530:
2531: if (! (INTVAL (operands[1]) == 8
2532: && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0))
2533: && ! INTVAL (operands[1]) == 1)
2534: FAIL;
2535: }")
2536:
2537: ;; ??? Are these constraints right?
2538: (define_insn ""
2539: [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+&qo")
2540: (const_int 8)
2541: (const_int 8))
2542: (match_operand:QI 1 "general_operand" "qn"))]
2543: ""
2544: "*
2545: {
2546: if (REG_P (operands[0]))
2547: return AS2 (mov%B0,%1,%h0);
2548:
2549: operands[0] = adj_offsettable_operand (operands[0], 1);
2550: return AS2 (mov%B0,%1,%0);
2551: }")
2552: */
2553:
2554: ;; On i386, the register count for a bit operation is *not* truncated,
2555: ;; so SHIFT_COUNT_TRUNCATED must not be defined.
2556:
2557: ;; On i486, the shift & or/and code is faster than bts or btr. If
2558: ;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code.
2559:
2560: ;; On i386, bts is a little faster if operands[0] is a reg, and a
2561: ;; little slower if operands[0] is a MEM, than the shift & or/and code.
2562: ;; Use bts & btr, since they reload better.
2563:
2564: ;; General bit set and clear.
2565: (define_insn ""
2566: [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm")
2567: (const_int 1)
2568: (match_operand:SI 2 "nonimmediate_operand" "r"))
2569: (match_operand:SI 3 "immediate_operand" "i"))]
2570: "! TARGET_486"
2571: "*
2572: {
2573: CC_STATUS_INIT;
2574:
2575: if (INTVAL (operands[3]) == 1)
2576: return AS2 (bts%L0,%2,%0);
2577: else
2578: return AS2 (btr%L0,%2,%0);
2579: }")
2580:
2581: ;; Bit complement. See comments on previous pattern.
2582: ;; ??? Is this really worthwhile?
2583: (define_insn ""
2584: [(set (match_operand:SI 0 "general_operand" "+rm")
2585: (xor:SI (ashift:SI (const_int 1)
2586: (match_operand:SI 1 "general_operand" "r"))
2587: (match_dup 0)))]
2588: "! TARGET_486"
2589: "*
2590: {
2591: CC_STATUS_INIT;
2592:
2593: return AS2 (btc%L0,%1,%0);
2594: }")
2595:
2596: /* ??? This works, but that SUBREG looks dangerous.
2597: (define_insn ""
2598: [(set (match_operand:HI 0 "general_operand" "+rm")
2599: (xor:HI (subreg:HI
2600: (ashift:SI (const_int 1)
2601: (sign_extend:SI
2602: (match_operand:HI 1 "nonimmediate_operand" "r"))) 0)
2603: (match_dup 0)))]
2604: "! TARGET_486"
2605: "*
2606: {
2607: CC_STATUS_INIT;
2608:
2609: return AS2 (btc%W0,%1,%0);
2610: }")
2611: */
2612:
2613: ;; Recognizers for bit-test instructions.
2614:
2615: ;; The bt opcode allows a MEM in operands[0]. But on both i386 and
2616: ;; i486, it is faster to copy a MEM to REG and then use bt, than to use
2617: ;; bt on the MEM directly.
2618:
1.1.1.2 ! root 2619: ;; ??? The first argument of a zero_extract must not be reloaded, so
! 2620: ;; don't allow a MEM in the operand predicate without allowing it in the
! 2621: ;; constraint.
! 2622:
1.1 root 2623: (define_insn ""
2624: [(set (cc0) (zero_extract (match_operand:QI 0 "register_operand" "q")
2625: (const_int 1)
2626: (match_operand:SI 1 "general_operand" "ri")))]
2627: ""
2628: "*
2629: {
2630: if (GET_CODE (operands[1]) == CONST_INT)
2631: {
2632: operands[1] = gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (operands[1]));
2633: output_asm_insn (AS2 (test%B0,%1,%0), operands);
2634: }
2635: else
2636: {
2637: operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]));
2638: cc_status.flags |= CC_Z_IN_NOT_C;
2639: output_asm_insn (AS2 (bt%L0,%1,%0), operands);
2640: }
2641: RET;
2642: }")
2643:
1.1.1.2 ! root 2644: ;; ??? The first argument of a zero_extract must not be reloaded, so
! 2645: ;; don't allow a MEM in the operand predicate without allowing it in the
! 2646: ;; constraint.
1.1 root 2647:
2648: (define_insn ""
1.1.1.2 ! root 2649: [(set (cc0) (zero_extract (match_operand:HI 0 "register_operand" "r")
1.1 root 2650: (const_int 1)
2651: (match_operand:SI 1 "general_operand" "ri")))]
2652: ""
2653: "*
2654: {
2655: if (GET_CODE (operands[1]) == CONST_INT)
2656: {
1.1.1.2 ! root 2657: if (QI_REG_P (operands[0]) && INTVAL (operands[1]) < 8)
! 2658: {
! 2659: cc_status.flags |= CC_NOT_NEGATIVE;
! 2660: operands[1] = gen_rtx (CONST_INT, VOIDmode,
! 2661: 1 << INTVAL (operands[1]));
! 2662:
! 2663: output_asm_insn (AS2 (test%B0,%1,%b0), operands);
! 2664: }
! 2665: else if (QI_REG_P (operands[0]))
! 2666: {
! 2667: operands[1] = gen_rtx (CONST_INT, VOIDmode,
! 2668: 1 << (INTVAL (operands[1]) - 8));
! 2669:
! 2670: output_asm_insn (AS2 (test%B0,%1,%h0), operands);
! 2671: }
! 2672: else
! 2673: {
! 2674: /* ??? This will never set CC to negative, even if we test
! 2675: the sign bit of the HImode reg. But CC0 is only tested
! 2676: for EQ and NE after this insn. */
! 2677:
! 2678: operands[1] = gen_rtx (CONST_INT, VOIDmode,
! 2679: 1 << INTVAL (operands[1]));
! 2680:
! 2681: output_asm_insn (AS2 (test%L0,%1,%k0), operands);
! 2682: }
1.1 root 2683: }
2684: else
2685: {
2686: cc_status.flags |= CC_Z_IN_NOT_C;
2687: output_asm_insn (AS2 (bt%W0,%1,%0), operands);
2688: }
2689: RET;
2690: }")
2691:
1.1.1.2 ! root 2692: ;; ??? The first argument of a zero_extract must not be reloaded, so
! 2693: ;; don't allow a MEM in the operand predicate without allowing it in the
! 2694: ;; constraint.
! 2695:
1.1 root 2696: (define_insn ""
1.1.1.2 ! root 2697: [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
1.1 root 2698: (const_int 1)
2699: (match_operand:SI 1 "general_operand" "ri")))]
2700: ""
2701: "*
2702: {
2703: if (GET_CODE (operands[1]) == CONST_INT)
2704: {
1.1.1.2 ! root 2705: if (QI_REG_P (operands[0]) && INTVAL (operands[1]) < 8)
! 2706: {
! 2707: cc_status.flags |= CC_NOT_NEGATIVE;
! 2708: operands[1] = gen_rtx (CONST_INT, VOIDmode,
! 2709: 1 << INTVAL (operands[1]));
! 2710:
! 2711: output_asm_insn (AS2 (test%B0,%1,%b0), operands);
! 2712: }
! 2713: else if (QI_REG_P (operands[0]) && INTVAL (operands[1]) < 16)
! 2714: {
! 2715: cc_status.flags |= CC_NOT_NEGATIVE;
! 2716: operands[1] = gen_rtx (CONST_INT, VOIDmode,
! 2717: 1 << (INTVAL (operands[1]) - 8));
! 2718:
! 2719: output_asm_insn (AS2 (test%B0,%1,%h0), operands);
! 2720: }
! 2721: else
! 2722: {
! 2723: operands[1] = gen_rtx (CONST_INT, VOIDmode,
! 2724: 1 << INTVAL (operands[1]));
! 2725:
! 2726: output_asm_insn (AS2 (test%L0,%1,%0), operands);
! 2727: }
1.1 root 2728: }
2729: else
2730: {
2731: cc_status.flags |= CC_Z_IN_NOT_C;
2732: output_asm_insn (AS2 (bt%L0,%1,%0), operands);
2733: }
2734: RET;
2735: }")
2736:
2737: ;; Store-flag instructions.
2738:
2739: (define_insn "seq"
2740: [(set (match_operand:QI 0 "general_operand" "=qm")
2741: (eq:QI (cc0) (const_int 0)))]
2742: ""
2743: "*
2744: {
2745: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2746: return AS1 (setnb,%0);
2747: else
2748: return AS1 (sete,%0);
2749: }
2750: ")
2751:
2752: (define_insn "sne"
2753: [(set (match_operand:QI 0 "general_operand" "=qm")
2754: (ne:QI (cc0) (const_int 0)))]
2755: ""
2756: "*
2757: {
2758: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2759: return AS1 (setb,%0);
2760: else
2761: return AS1 (setne,%0);
2762: }
2763: ")
2764:
2765: (define_insn "sgt"
2766: [(set (match_operand:QI 0 "general_operand" "=qm")
2767: (gt:QI (cc0) (const_int 0)))]
2768: ""
2769: "* OUTPUT_JUMP (\"setg %0\", \"seta %0\", 0); ")
2770:
2771: (define_insn "sgtu"
2772: [(set (match_operand:QI 0 "general_operand" "=qm")
2773: (gtu:QI (cc0) (const_int 0)))]
2774: ""
2775: "* return \"seta %0\"; ")
2776:
2777: (define_insn "slt"
2778: [(set (match_operand:QI 0 "general_operand" "=qm")
2779: (lt:QI (cc0) (const_int 0)))]
2780: ""
2781: "* OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\"); ")
2782:
2783: (define_insn "sltu"
2784: [(set (match_operand:QI 0 "general_operand" "=qm")
2785: (ltu:QI (cc0) (const_int 0)))]
2786: ""
2787: "* return \"setb %0\"; ")
2788:
2789: (define_insn "sge"
2790: [(set (match_operand:QI 0 "general_operand" "=qm")
2791: (ge:QI (cc0) (const_int 0)))]
2792: ""
2793: "* OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\"); ")
2794:
2795: (define_insn "sgeu"
2796: [(set (match_operand:QI 0 "general_operand" "=qm")
2797: (geu:QI (cc0) (const_int 0)))]
2798: ""
2799: "* return \"setae %0\"; ")
2800:
2801: (define_insn "sle"
2802: [(set (match_operand:QI 0 "general_operand" "=qm")
2803: (le:QI (cc0) (const_int 0)))]
2804: ""
2805: "* OUTPUT_JUMP (\"setle %0\", \"setbe %0\", 0); ")
2806:
2807: (define_insn "sleu"
2808: [(set (match_operand:QI 0 "general_operand" "=qm")
2809: (leu:QI (cc0) (const_int 0)))]
2810: ""
2811: "* return \"setbe %0\"; ")
2812:
2813: ;; Basic conditional jump instructions.
2814: ;; We ignore the overflow flag for signed branch instructions.
2815:
2816: (define_insn "beq"
2817: [(set (pc)
2818: (if_then_else (eq (cc0)
2819: (const_int 0))
2820: (label_ref (match_operand 0 "" ""))
2821: (pc)))]
2822: ""
2823: "*
2824: {
2825: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2826: return \"jnc %l0\";
2827: else
2828: return \"je %l0\";
2829: }")
2830:
2831: (define_insn "bne"
2832: [(set (pc)
2833: (if_then_else (ne (cc0)
2834: (const_int 0))
2835: (label_ref (match_operand 0 "" ""))
2836: (pc)))]
2837: ""
2838: "*
2839: {
2840: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2841: return \"jc %l0\";
2842: else
2843: return \"jne %l0\";
2844: }")
2845:
2846: (define_insn "bgt"
2847: [(set (pc)
2848: (if_then_else (gt (cc0)
2849: (const_int 0))
2850: (label_ref (match_operand 0 "" ""))
2851: (pc)))]
2852: ""
2853: "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)")
2854:
2855: (define_insn "bgtu"
2856: [(set (pc)
2857: (if_then_else (gtu (cc0)
2858: (const_int 0))
2859: (label_ref (match_operand 0 "" ""))
2860: (pc)))]
2861: ""
2862: "ja %l0")
2863:
2864: ;; There is no jump insn to check for `<' on IEEE floats.
2865: ;; Page 17-80 in the 80387 manual says jb, but that's wrong;
2866: ;; jb checks for `not >='. So swap the operands and do `>'.
2867: (define_expand "blt"
2868: [(set (pc)
2869: (if_then_else (lt (cc0)
2870: (const_int 0))
2871: (label_ref (match_operand 0 "" ""))
2872: (pc)))]
2873: ""
2874: "
2875: {
2876: rtx prev = get_last_insn_anywhere ();
2877: rtx body = PATTERN (prev);
2878: rtx comp;
2879: if (GET_CODE (body) == SET)
2880: comp = SET_SRC (body);
2881: else
2882: comp = SET_SRC (XVECEXP (body, 0, 0));
2883:
2884: if (GET_CODE (comp) == COMPARE
2885: ? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT
2886: : GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT)
2887: {
2888: reverse_comparison (prev);
2889: emit_insn (gen_bgt (operands[0]));
2890: DONE;
2891: }
2892: }")
2893:
2894: (define_insn ""
2895: [(set (pc)
2896: (if_then_else (lt (cc0)
2897: (const_int 0))
2898: (label_ref (match_operand 0 "" ""))
2899: (pc)))]
2900: ""
2901: "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")")
2902:
2903: (define_insn "bltu"
2904: [(set (pc)
2905: (if_then_else (ltu (cc0)
2906: (const_int 0))
2907: (label_ref (match_operand 0 "" ""))
2908: (pc)))]
2909: ""
2910: "jb %l0")
2911:
2912: (define_insn "bge"
2913: [(set (pc)
2914: (if_then_else (ge (cc0)
2915: (const_int 0))
2916: (label_ref (match_operand 0 "" ""))
2917: (pc)))]
2918: ""
2919: "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\")")
2920:
2921: (define_insn "bgeu"
2922: [(set (pc)
2923: (if_then_else (geu (cc0)
2924: (const_int 0))
2925: (label_ref (match_operand 0 "" ""))
2926: (pc)))]
2927: ""
2928: "jae %l0")
2929:
2930: ;; See comment on `blt', above.
2931: (define_expand "ble"
2932: [(set (pc)
2933: (if_then_else (le (cc0)
2934: (const_int 0))
2935: (label_ref (match_operand 0 "" ""))
2936: (pc)))]
2937: ""
2938: "
2939: {
2940: rtx prev = get_last_insn_anywhere ();
2941: rtx body = PATTERN (prev);
2942: rtx comp;
2943: if (GET_CODE (body) == SET)
2944: comp = SET_SRC (body);
2945: else
2946: comp = SET_SRC (XVECEXP (body, 0, 0));
2947:
2948: if (GET_CODE (comp) == COMPARE
2949: ? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT
2950: : GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT)
2951: {
2952: reverse_comparison (prev);
2953: emit_insn (gen_bge (operands[0]));
2954: DONE;
2955: }
2956: }")
2957:
2958: (define_insn ""
2959: [(set (pc)
2960: (if_then_else (le (cc0)
2961: (const_int 0))
2962: (label_ref (match_operand 0 "" ""))
2963: (pc)))]
2964: ""
2965: "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ")
2966:
2967: (define_insn "bleu"
2968: [(set (pc)
2969: (if_then_else (leu (cc0)
2970: (const_int 0))
2971: (label_ref (match_operand 0 "" ""))
2972: (pc)))]
2973: ""
2974: "jbe %l0")
2975:
2976: ;; Negated conditional jump instructions.
2977:
2978: (define_insn ""
2979: [(set (pc)
2980: (if_then_else (eq (cc0)
2981: (const_int 0))
2982: (pc)
2983: (label_ref (match_operand 0 "" ""))))]
2984: ""
2985: "*
2986: {
2987: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2988: return \"jc %l0\";
2989: else
2990: return \"jne %l0\";
2991: }")
2992:
2993: (define_insn ""
2994: [(set (pc)
2995: (if_then_else (ne (cc0)
2996: (const_int 0))
2997: (pc)
2998: (label_ref (match_operand 0 "" ""))))]
2999: ""
3000: "*
3001: {
3002: if (cc_prev_status.flags & CC_Z_IN_NOT_C)
3003: return \"jnc %l0\";
3004: else
3005: return \"je %l0\";
3006: }")
3007:
3008: (define_insn ""
3009: [(set (pc)
3010: (if_then_else (gt (cc0)
3011: (const_int 0))
3012: (pc)
3013: (label_ref (match_operand 0 "" ""))))]
3014: ""
3015: "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ")
3016:
3017: (define_insn ""
3018: [(set (pc)
3019: (if_then_else (gtu (cc0)
3020: (const_int 0))
3021: (pc)
3022: (label_ref (match_operand 0 "" ""))))]
3023: ""
3024: "jbe %l0")
3025:
3026: (define_insn ""
3027: [(set (pc)
3028: (if_then_else (lt (cc0)
3029: (const_int 0))
3030: (pc)
3031: (label_ref (match_operand 0 "" ""))))]
3032: ""
3033: "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\")
3034: ")
3035:
3036: (define_insn ""
3037: [(set (pc)
3038: (if_then_else (ltu (cc0)
3039: (const_int 0))
3040: (pc)
3041: (label_ref (match_operand 0 "" ""))))]
3042: ""
3043: "jae %l0")
3044:
3045: (define_insn ""
3046: [(set (pc)
3047: (if_then_else (ge (cc0)
3048: (const_int 0))
3049: (pc)
3050: (label_ref (match_operand 0 "" ""))))]
3051: ""
3052: "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")")
3053:
3054: (define_insn ""
3055: [(set (pc)
3056: (if_then_else (geu (cc0)
3057: (const_int 0))
3058: (pc)
3059: (label_ref (match_operand 0 "" ""))))]
3060: ""
3061: "jb %l0")
3062:
3063: (define_insn ""
3064: [(set (pc)
3065: (if_then_else (le (cc0)
3066: (const_int 0))
3067: (pc)
3068: (label_ref (match_operand 0 "" ""))))]
3069: ""
3070: "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)")
3071:
3072: (define_insn ""
3073: [(set (pc)
3074: (if_then_else (leu (cc0)
3075: (const_int 0))
3076: (pc)
3077: (label_ref (match_operand 0 "" ""))))]
3078: ""
3079: "ja %l0")
3080:
3081: ;; Unconditional and other jump instructions
3082:
3083: (define_insn "jump"
3084: [(set (pc)
3085: (label_ref (match_operand 0 "" "")))]
3086: ""
3087: "jmp %l0")
3088:
3089: (define_insn "indirect_jump"
3090: [(set (pc) (match_operand:SI 0 "general_operand" "rm"))]
3091: ""
3092: "*
3093: {
3094: CC_STATUS_INIT;
3095:
3096: return AS1 (jmp,%*%0);
3097: }")
3098:
3099: ;; Implement switch statements when generating PIC code. Switches are
3100: ;; implemented by `tablejump' when not using -fpic.
3101:
3102: ;; Emit code here to do the range checking and make the index zero based.
3103:
3104: (define_expand "casesi"
1.1.1.2 ! root 3105: [(set (match_dup 5)
! 3106: (minus:SI (match_operand:SI 0 "general_operand" "")
! 3107: (match_operand:SI 1 "general_operand" "")))
! 3108: (set (cc0)
! 3109: (compare (match_dup 5)
! 3110: (match_operand:SI 2 "general_operand" "")))
! 3111: (set (pc)
! 3112: (if_then_else (gtu (cc0)
! 3113: (const_int 0))
! 3114: (label_ref (match_operand 4 "" ""))
! 3115: (pc)))
! 3116: (parallel
1.1 root 3117: [(set (pc)
1.1.1.2 ! root 3118: (minus:SI (reg:SI 3)
! 3119: (mem:SI (plus:SI (mult:SI (match_dup 5)
! 3120: (const_int 4))
! 3121: (label_ref (match_operand 3 "" ""))))))
! 3122: (clobber (match_scratch:SI 6 ""))])]
1.1 root 3123: "flag_pic"
3124: "
3125: {
1.1.1.2 ! root 3126: operands[5] = gen_reg_rtx (SImode);
1.1 root 3127: current_function_uses_pic_offset_table = 1;
3128: }")
3129:
3130: ;; Implement a casesi insn.
3131:
3132: ;; Each entry in the "addr_diff_vec" looks like this as the result of the
3133: ;; two rules below:
3134: ;;
3135: ;; .long _GLOBAL_OFFSET_TABLE_+[.-.L2]
3136: ;;
3137: ;; 1. An expression involving an external reference may only use the
3138: ;; addition operator, and only with an assembly-time constant.
3139: ;; The example above satisfies this because ".-.L2" is a constant.
3140: ;;
3141: ;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is
3142: ;; given the value of "GOT - .", where GOT is the actual address of
3143: ;; the Global Offset Table. Therefore, the .long above actually
3144: ;; stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2". The
3145: ;; expression "GOT - .L2" by itself would generate an error from as(1).
3146: ;;
3147: ;; The pattern below emits code that looks like this:
3148: ;;
3149: ;; movl %ebx,reg
3150: ;; subl TABLE@GOTOFF(%ebx,index,4),reg
3151: ;; jmp reg
3152: ;;
3153: ;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since
3154: ;; the addr_diff_vec is known to be part of this module.
3155: ;;
3156: ;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which
3157: ;; evaluates to just ".L2".
3158:
3159: (define_insn ""
3160: [(set (pc)
1.1.1.2 ! root 3161: (minus:SI (reg:SI 3)
! 3162: (mem:SI (plus:SI
! 3163: (mult:SI (match_operand:SI 0 "register_operand" "r")
! 3164: (const_int 4))
! 3165: (label_ref (match_operand 1 "" ""))))))
! 3166: (clobber (match_scratch:SI 2 "=&r"))]
1.1 root 3167: ""
3168: "*
3169: {
3170: rtx xops[4];
3171:
1.1.1.2 ! root 3172: xops[0] = operands[0];
! 3173: xops[1] = operands[1];
! 3174: xops[2] = operands[2];
! 3175: xops[3] = pic_offset_table_rtx;
! 3176:
! 3177: output_asm_insn (AS2 (mov%L2,%3,%2), xops);
! 3178: output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops);
! 3179: output_asm_insn (AS1 (jmp,%*%2), xops);
1.1 root 3180: ASM_OUTPUT_ALIGN_CODE (asm_out_file);
3181: RET;
3182: }")
3183:
3184: (define_insn "tablejump"
3185: [(set (pc) (match_operand:SI 0 "general_operand" "rm"))
3186: (use (label_ref (match_operand 1 "" "")))]
3187: ""
3188: "*
3189: {
3190: CC_STATUS_INIT;
3191:
3192: return AS1 (jmp,%*%0);
3193: }")
3194:
3195: ;; Call insns.
3196:
3197: ;; If generating PIC code, the predicate indirect_operand will fail
3198: ;; for operands[0] containing symbolic references on all of the named
3199: ;; call* patterns. Each named pattern is followed by an unnamed pattern
3200: ;; that matches any call to a symbolic CONST (ie, a symbol_ref). The
3201: ;; unnamed patterns are only used while generating PIC code, because
3202: ;; otherwise the named patterns match.
3203:
3204: ;; Call subroutine returning no value.
3205:
3206: (define_expand "call_pop"
3207: [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
3208: (match_operand:SI 1 "general_operand" ""))
3209: (set (reg:SI 7)
3210: (plus:SI (reg:SI 7)
3211: (match_operand:SI 3 "immediate_operand" "")))])]
3212: ""
3213: "
3214: {
3215: if (flag_pic)
3216: current_function_uses_pic_offset_table = 1;
3217: }")
3218:
3219: (define_insn ""
3220: [(call (match_operand:QI 0 "indirect_operand" "m")
3221: (match_operand:SI 1 "general_operand" "g"))
3222: (set (reg:SI 7) (plus:SI (reg:SI 7)
3223: (match_operand:SI 3 "immediate_operand" "i")))]
3224: ""
3225: "*
3226: {
3227: if (GET_CODE (operands[0]) == MEM
3228: && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
3229: {
3230: operands[0] = XEXP (operands[0], 0);
3231: return AS1 (call,%*%0);
3232: }
3233: else
3234: return AS1 (call,%P0);
3235: }")
3236:
3237: (define_insn ""
3238: [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
3239: (match_operand:SI 1 "general_operand" "g"))
3240: (set (reg:SI 7) (plus:SI (reg:SI 7)
3241: (match_operand:SI 3 "immediate_operand" "i")))]
3242: ""
3243: "call %P0")
3244:
3245: (define_expand "call"
3246: [(call (match_operand:QI 0 "indirect_operand" "")
3247: (match_operand:SI 1 "general_operand" ""))]
3248: ;; Operand 1 not used on the i386.
3249: ""
3250: "
3251: {
3252: if (flag_pic)
3253: current_function_uses_pic_offset_table = 1;
3254: }")
3255:
3256: (define_insn ""
3257: [(call (match_operand:QI 0 "indirect_operand" "m")
3258: (match_operand:SI 1 "general_operand" "g"))]
3259: ;; Operand 1 not used on the i386.
3260: ""
3261: "*
3262: {
3263: if (GET_CODE (operands[0]) == MEM
3264: && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
3265: {
3266: operands[0] = XEXP (operands[0], 0);
3267: return AS1 (call,%*%0);
3268: }
3269: else
3270: return AS1 (call,%P0);
3271: }")
3272:
3273: (define_insn ""
3274: [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
3275: (match_operand:SI 1 "general_operand" "g"))]
3276: ;; Operand 1 not used on the i386.
3277: ""
3278: "call %P0")
3279:
3280: ;; Call subroutine, returning value in operand 0
3281: ;; (which must be a hard register).
3282:
3283: (define_expand "call_value_pop"
3284: [(parallel [(set (match_operand 0 "" "")
3285: (call (match_operand:QI 1 "indirect_operand" "")
3286: (match_operand:SI 2 "general_operand" "")))
3287: (set (reg:SI 7)
3288: (plus:SI (reg:SI 7)
3289: (match_operand:SI 4 "immediate_operand" "")))])]
3290: ""
3291: "
3292: {
3293: if (flag_pic)
3294: current_function_uses_pic_offset_table = 1;
3295: }")
3296:
3297: (define_insn ""
3298: [(set (match_operand 0 "" "=rf")
3299: (call (match_operand:QI 1 "indirect_operand" "m")
3300: (match_operand:SI 2 "general_operand" "g")))
3301: (set (reg:SI 7) (plus:SI (reg:SI 7)
3302: (match_operand:SI 4 "immediate_operand" "i")))]
3303: ""
3304: "*
3305: {
3306: if (GET_CODE (operands[1]) == MEM
3307: && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
3308: {
3309: operands[1] = XEXP (operands[1], 0);
3310: output_asm_insn (AS1 (call,%*%1), operands);
3311: }
3312: else
3313: output_asm_insn (AS1 (call,%P1), operands);
3314:
3315: RET;
3316: }")
3317:
3318: (define_insn ""
3319: [(set (match_operand 0 "" "=rf")
3320: (call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
3321: (match_operand:SI 2 "general_operand" "g")))
3322: (set (reg:SI 7) (plus:SI (reg:SI 7)
3323: (match_operand:SI 4 "immediate_operand" "i")))]
3324: ""
3325: "call %P1")
3326:
3327: (define_expand "call_value"
3328: [(set (match_operand 0 "" "")
3329: (call (match_operand:QI 1 "indirect_operand" "")
3330: (match_operand:SI 2 "general_operand" "")))]
3331: ;; Operand 2 not used on the i386.
3332: ""
3333: "
3334: {
3335: if (flag_pic)
3336: current_function_uses_pic_offset_table = 1;
3337: }")
3338:
3339: (define_insn ""
3340: [(set (match_operand 0 "" "=rf")
3341: (call (match_operand:QI 1 "indirect_operand" "m")
3342: (match_operand:SI 2 "general_operand" "g")))]
3343: ;; Operand 2 not used on the i386.
3344: ""
3345: "*
3346: {
3347: if (GET_CODE (operands[1]) == MEM
3348: && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
3349: {
3350: operands[1] = XEXP (operands[1], 0);
3351: output_asm_insn (AS1 (call,%*%1), operands);
3352: }
3353: else
3354: output_asm_insn (AS1 (call,%P1), operands);
3355:
3356: RET;
3357: }")
3358:
3359: (define_insn ""
3360: [(set (match_operand 0 "" "=rf")
3361: (call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
3362: (match_operand:SI 2 "general_operand" "g")))]
3363: ;; Operand 2 not used on the i386.
3364: ""
3365: "call %P1")
3366:
3367: ;; Insn emitted into the body of a function to return from a function.
3368: ;; This is only done if the function's epilogue is known to be simple.
3369: ;; See comments for simple_386_epilogue in i386.c.
3370:
3371: (define_insn "return"
3372: [(return)]
3373: "simple_386_epilogue ()"
3374: "*
3375: {
3376: function_epilogue (asm_out_file, get_frame_size ());
3377: RET;
3378: }")
3379:
3380: (define_insn "nop"
3381: [(const_int 0)]
3382: ""
3383: "nop")
3384:
3385: (define_expand "movstrsi"
3386: [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
3387: (mem:BLK (match_operand:BLK 1 "general_operand" "")))
3388: (use (match_operand:SI 2 "immediate_operand" ""))
3389: (use (match_operand:SI 3 "immediate_operand" ""))
3390: (set (match_operand:SI 4 "register_operand" "")
3391: (const_int 0))
3392: (set (match_dup 0)
3393: (plus:SI (match_dup 0)
3394: (match_dup 2)))
3395: (set (match_dup 1)
3396: (plus:SI (match_dup 1)
3397: (match_dup 2)))])]
3398: ""
3399: "
3400: {
3401: if (GET_CODE (operands[2]) != CONST_INT)
3402: FAIL;
3403: operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
3404: operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3405: operands[4] = gen_reg_rtx (SImode);
3406: }")
3407:
3408: (define_insn ""
3409: [(set (mem:BLK (match_operand:SI 0 "register_operand" "D"))
3410: (mem:BLK (match_operand:SI 1 "register_operand" "S")))
3411: (use (match_operand:SI 2 "immediate_operand" "n"))
3412: (use (match_operand:SI 3 "immediate_operand" "i"))
3413: (set (match_operand:SI 4 "register_operand" "c")
3414: (const_int 0))
3415: (set (match_operand:SI 5 "register_operand" "=0")
3416: (plus:SI (match_dup 0)
3417: (match_dup 2)))
3418: (set (match_operand:SI 7 "register_operand" "=1")
3419: (plus:SI (match_dup 1)
3420: (match_dup 2)))]
3421: ""
3422: "*
3423: {
3424: rtx xops[2];
3425:
3426: if (GET_CODE (operands[2]) == CONST_INT)
3427: {
3428: if (INTVAL (operands[2]) & ~0x03)
3429: {
3430: xops[0] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) >> 2);
3431: xops[1] = gen_rtx (REG, SImode, 2);
3432:
3433: output_asm_insn (AS2 (mov%L1,%0,%1), xops);
3434: #ifdef INTEL_SYNTAX
3435: output_asm_insn (\"rep movsd\", xops);
3436: #else
1.1.1.2 ! root 3437: output_asm_insn (\"rep\;movsl\", xops);
1.1 root 3438: #endif
3439: }
3440: if (INTVAL (operands[2]) & 0x02)
3441: output_asm_insn (\"movsw\", operands);
3442: if (INTVAL (operands[2]) & 0x01)
3443: output_asm_insn (\"movsb\", operands);
3444: }
3445: else
3446: abort ();
3447: RET;
3448: }")
3449:
3450: (define_expand "cmpstrsi"
3451: [(parallel [(set (match_operand:QI 0 "general_operand" "")
3452: (compare
3453: (mem:BLK (match_operand:BLK 1 "general_operand" ""))
3454: (mem:BLK (match_operand:BLK 2 "general_operand" ""))))
3455: (use (match_operand:SI 3 "general_operand" ""))
3456: (use (match_operand:SI 4 "immediate_operand" ""))
3457: (clobber (match_dup 1))
3458: (clobber (match_dup 2))
3459: (clobber (match_dup 3))])]
3460: ""
3461: "
3462: {
3463: operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3464: operands[2] = copy_to_mode_reg (SImode, XEXP (operands[2], 0));
3465: operands[3] = copy_to_mode_reg (SImode, operands[3]);
3466: }")
3467:
3468: (define_insn ""
3469: [(set (match_operand:QI 0 "general_operand" "=q")
1.1.1.2 ! root 3470: (compare (mem:BLK (match_operand:SI 1 "general_operand" "S"))
! 3471: (mem:BLK (match_operand:SI 2 "general_operand" "D"))))
1.1 root 3472: (use (match_operand:SI 3 "general_operand" "c"))
3473: (use (match_operand:SI 4 "immediate_operand" "i"))
3474: (clobber (match_dup 1))
3475: (clobber (match_dup 2))
3476: (clobber (match_dup 3))]
3477: ""
3478: "*
3479: {
3480: rtx xops[3];
3481:
3482: output_asm_insn (\"repz\;cmps%B2\", operands);
3483:
3484: xops[0] = operands[0];
3485: xops[1] = gen_rtx (MEM, QImode,
3486: gen_rtx (PLUS, SImode, operands[1], constm1_rtx));
3487: xops[2] = gen_rtx (MEM, QImode,
3488: gen_rtx (PLUS, SImode, operands[2], constm1_rtx));
3489:
3490: output_asm_insn (AS2 (mov%B0,%1,%b0), xops);
3491: output_asm_insn (AS2 (sub%B0,%2,%b0), xops);
3492: RET;
3493: }")
3494:
3495: (define_insn ""
3496: [(set (cc0)
1.1.1.2 ! root 3497: (compare (mem:BLK (match_operand:SI 0 "general_operand" "S"))
! 3498: (mem:BLK (match_operand:SI 1 "general_operand" "D"))))
1.1 root 3499: (use (match_operand:SI 2 "general_operand" "c"))
3500: (use (match_operand:SI 3 "immediate_operand" "i"))
3501: (clobber (match_dup 0))
3502: (clobber (match_dup 1))
3503: (clobber (match_dup 2))]
3504: ""
3505: "repz\;cmps%B2")
3506:
3507: (define_expand "ffssi2"
3508: [(set (match_dup 2)
3509: (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" ""))
3510: (const_int -1)))
3511: (set (match_operand:SI 0 "general_operand" "")
3512: (plus:SI (match_dup 2) (const_int 1)))]
3513: ""
3514: "operands[2] = gen_reg_rtx (SImode);")
3515:
3516: (define_insn ""
3517: [(set (match_operand:SI 0 "general_operand" "=&r")
3518: (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "rm"))
3519: (const_int -1)))]
3520: ""
3521: "*
3522: {
3523: rtx xops[2];
3524:
3525: xops[0] = operands[0];
3526: xops[1] = constm1_rtx;
3527: output_asm_insn (AS2 (mov%L0,%1,%0), xops);
3528: return AS2 (bsf%L0,%1,%0);
3529: }")
3530:
3531: (define_expand "ffshi2"
3532: [(set (match_dup 2)
3533: (plus:HI (ffs:HI (match_operand:HI 1 "general_operand" ""))
3534: (const_int -1)))
3535: (set (match_operand:HI 0 "general_operand" "")
3536: (plus:HI (match_dup 2) (const_int 1)))]
3537: ""
3538: "operands[2] = gen_reg_rtx (HImode);")
3539:
3540: (define_insn ""
3541: [(set (match_operand:HI 0 "general_operand" "=&r")
3542: (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm"))
3543: (const_int -1)))]
3544: ""
3545: "*
3546: {
3547: rtx xops[2];
3548:
3549: xops[0] = operands[0];
3550: xops[1] = constm1_rtx;
3551: output_asm_insn (AS2 (mov%W0,%1,%0), xops);
3552: return AS2 (bsf%W0,%1,%0);
3553: }")
3554:
3555: ;; These patterns match the binary 387 instructions for addM3, subM3,
3556: ;; mulM3 and divM3. There are three patterns for each of DFmode and
3557: ;; SFmode. The first is the normal insn, the second the same insn but
3558: ;; with one operand a conversion, and the third the same insn but with
3559: ;; the other operand a conversion. The conversion may be SFmode or
3560: ;; SImode if the target mode DFmode, but only SImode if the target mode
3561: ;; is SFmode.
3562:
3563: (define_insn ""
3564: [(set (match_operand:DF 0 "register_operand" "=f,f")
3565: (match_operator:DF 3 "binary_387_op"
3566: [(match_operand:DF 1 "general_operand" "0,fm")
3567: (match_operand:DF 2 "general_operand" "fm,0")]))]
3568: "TARGET_80387"
3569: "* return (char *) output_387_binary_op (insn, operands);")
3570:
3571: (define_insn ""
3572: [(set (match_operand:DF 0 "register_operand" "=f,f")
3573: (match_operator:DF 3 "binary_387_op"
3574: [(float:DF (match_operand:SI 1 "general_operand" "m,!*r"))
3575: (match_operand:DF 2 "general_operand" "0,0")]))]
3576: "TARGET_80387"
3577: "* return (char *) output_387_binary_op (insn, operands);")
3578:
3579: (define_insn ""
3580: [(set (match_operand:DF 0 "register_operand" "=f,f,f")
3581: (match_operator:DF 3 "binary_387_op"
3582: [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,!*r,0"))
3583: (match_operand:DF 2 "general_operand" "0,0,f")]))]
3584: "TARGET_80387"
3585: "* return (char *) output_387_binary_op (insn, operands);")
3586:
3587: (define_insn ""
3588: [(set (match_operand:DF 0 "register_operand" "=f,f")
3589: (match_operator:DF 3 "binary_387_op"
3590: [(match_operand:DF 1 "general_operand" "0,0")
3591: (float:DF (match_operand:SI 2 "general_operand" "m,!*r"))]))]
3592: "TARGET_80387"
3593: "* return (char *) output_387_binary_op (insn, operands);")
3594:
3595: (define_insn ""
3596: [(set (match_operand:DF 0 "register_operand" "=f,f,f")
3597: (match_operator:DF 3 "binary_387_op"
3598: [(match_operand:DF 1 "general_operand" "0,0,f")
3599: (float_extend:DF
3600: (match_operand:SF 2 "general_operand" "fm,!*r,0"))]))]
3601: "TARGET_80387"
3602: "* return (char *) output_387_binary_op (insn, operands);")
3603:
3604: (define_insn ""
3605: [(set (match_operand:SF 0 "register_operand" "=f,f")
3606: (match_operator:SF 3 "binary_387_op"
3607: [(match_operand:SF 1 "general_operand" "0,fm")
3608: (match_operand:SF 2 "general_operand" "fm,0")]))]
3609: "TARGET_80387"
3610: "* return (char *) output_387_binary_op (insn, operands);")
3611:
3612: (define_insn ""
3613: [(set (match_operand:SF 0 "register_operand" "=f,f")
3614: (match_operator:SF 3 "binary_387_op"
3615: [(float:SF (match_operand:SI 1 "general_operand" "m,!*r"))
3616: (match_operand:SF 2 "general_operand" "0,0")]))]
3617: "TARGET_80387"
3618: "* return (char *) output_387_binary_op (insn, operands);")
3619:
3620: (define_insn ""
3621: [(set (match_operand:SF 0 "register_operand" "=f,f")
3622: (match_operator:SF 3 "binary_387_op"
3623: [(match_operand:SF 1 "general_operand" "0,0")
3624: (float:SF (match_operand:SI 2 "general_operand" "m,!*r"))]))]
3625: "TARGET_80387"
3626: "* return (char *) output_387_binary_op (insn, operands);")
3627:
3628: ;;- Local variables:
3629: ;;- mode:emacs-lisp
3630: ;;- comment-start: ";;- "
3631: ;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
3632: ;;- eval: (modify-syntax-entry ?[ "(]")
3633: ;;- eval: (modify-syntax-entry ?] ")[")
3634: ;;- eval: (modify-syntax-entry ?{ "(}")
3635: ;;- eval: (modify-syntax-entry ?} "){")
3636: ;;- End:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.