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