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