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