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