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