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