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