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