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