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