|
|
1.1 root 1: ;;- Machine description for SPARC chip for GNU C compiler 1.1.1.2 ! root 2: ;; Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc. 1.1 root 3: ;; Contributed by Michael Tiemann ([email protected]) 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: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. 23: 24: ;; Insn type. Used to default other attribute values. 25: 26: ;; type "unary" insns have one input operand (1) and one output operand (0) 27: ;; type "binary" insns have two input operands (1,2) and one output (0) 28: ;; type "compare" insns have one or two input operands (0,1) and no output 29: ;; type "call_no_delay_slot" is a call followed by an unimp instruction. 30: 31: (define_attr "type" 32: "move,unary,binary,compare,load,store,uncond_branch,branch,call,call_no_delay_slot,address,fpload,fpstore,fp,fpcmp,fpmul,fpdiv,fpsqrt,multi,misc" 33: (const_string "binary")) 34: 35: ;; Set true if insn uses call-clobbered intermediate register. 36: (define_attr "use_clobbered" "false,true" 37: (if_then_else (and (eq_attr "type" "address") 38: (match_operand 0 "clobbered_register" "")) 39: (const_string "true") 40: (const_string "false"))) 41: 42: ;; Length (in # of insns). 43: (define_attr "length" "" 44: (cond [(eq_attr "type" "load,fpload") 45: (if_then_else (match_operand 1 "symbolic_memory_operand" "") 46: (const_int 2) (const_int 1)) 47: 48: (eq_attr "type" "store,fpstore") 49: (if_then_else (match_operand 0 "symbolic_memory_operand" "") 50: (const_int 2) (const_int 1)) 51: 52: (eq_attr "type" "address") (const_int 2) 53: 54: (eq_attr "type" "binary") 55: (if_then_else (ior (match_operand 2 "arith_operand" "") 56: (match_operand 2 "arith_double_operand" "")) 57: (const_int 1) (const_int 3)) 58: 59: (eq_attr "type" "multi") (const_int 2) 60: 61: (eq_attr "type" "move,unary") 62: (if_then_else (ior (match_operand 1 "arith_operand" "") 63: (match_operand 1 "arith_double_operand" "")) 64: (const_int 1) (const_int 2))] 65: 66: (const_int 1))) 67: 68: (define_asm_attributes 69: [(set_attr "length" "1") 70: (set_attr "type" "multi")]) 71: 72: ;; Attributes for instruction and branch scheduling 73: 74: (define_attr "in_call_delay" "false,true" 75: (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi") 76: (const_string "false") 77: (eq_attr "type" "load,fpload,store,fpstore") 78: (if_then_else (eq_attr "length" "1") 79: (const_string "true") 80: (const_string "false")) 81: (eq_attr "type" "address") 82: (if_then_else (eq_attr "use_clobbered" "false") 83: (const_string "true") 84: (const_string "false"))] 85: (if_then_else (eq_attr "length" "1") 86: (const_string "true") 87: (const_string "false")))) 88: 89: (define_delay (eq_attr "type" "call") 90: [(eq_attr "in_call_delay" "true") (nil) (nil)]) 91: 92: ;; ??? Should implement the notion of predelay slots for floating point 93: ;; branches. This would allow us to remove the nop always inserted before 94: ;; a floating point branch. 95: 96: ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions 97: ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so. 98: ;; This is because doing so will add several pipeline stalls to the path 99: ;; that the load/store did not come from. Unfortunately, there is no way 100: ;; to prevent fill_eager_delay_slots from using load/store without completely 101: ;; disabling them. For the SPEC benchmark set, this is a serious lose, 102: ;; because it prevents us from moving back the final store of inner loops. 103: 104: (define_attr "in_branch_delay" "false,true" 105: (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") 106: (eq_attr "length" "1")) 107: (const_string "true") 108: (const_string "false"))) 109: 110: (define_attr "in_uncond_branch_delay" "false,true" 111: (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") 112: (eq_attr "length" "1")) 113: (const_string "true") 114: (const_string "false"))) 115: 116: (define_attr "in_annul_branch_delay" "false,true" 117: (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") 118: (eq_attr "length" "1")) 119: (const_string "true") 120: (const_string "false"))) 121: 122: (define_delay (eq_attr "type" "branch") 123: [(eq_attr "in_branch_delay" "true") 124: (nil) (eq_attr "in_annul_branch_delay" "true")]) 125: 126: (define_delay (eq_attr "type" "uncond_branch") 127: [(eq_attr "in_uncond_branch_delay" "true") 128: (nil) (nil)]) 129: 130: ;; Function units of the SPARC 131: 132: ;; (define_function_unit {name} {num-units} {n-users} {test} 133: ;; {ready-delay} {issue-delay} [{conflict-list}]) 134: 135: ;; The integer ALU. 136: ;; (Noted only for documentation; units that take one cycle do not need to 137: ;; be specified.) 138: 139: ;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on 140: ;; the inputs. 141: 142: ;; (define_function_unit "alu" 1 0 143: ;; (eq_attr "type" "unary,binary,move,address") 1 0) 144: 145: ;; Memory with load-delay of 1 (i.e., 2 cycle load). 146: (define_function_unit "memory" 1 1 (eq_attr "type" "load,fpload") 2 0) 147: 148: ;; SPARC has two floating-point units: the FP ALU, 149: ;; and the FP MUL/DIV/SQRT unit. 150: ;; Instruction timings on the CY7C602 are as follows 151: ;; FABSs 4 152: ;; FADDs/d 5/5 153: ;; FCMPs/d 4/4 154: ;; FDIVs/d 23/37 155: ;; FMOVs 4 156: ;; FMULs/d 5/7 157: ;; FNEGs 4 158: ;; FSQRTs/d 34/63 159: ;; FSUBs/d 5/5 160: ;; FdTOi/s 5/5 161: ;; FsTOi/d 5/5 162: ;; FiTOs/d 9/5 163: 164: ;; The CY7C602 can only support 2 fp isnsn simultaneously. 165: ;; More insns cause the chip to stall. 166: 167: (define_function_unit "fp_alu" 1 1 (eq_attr "type" "fp") 5 0) 168: (define_function_unit "fp_mds" 1 1 (eq_attr "type" "fpmul") 7 0) 169: (define_function_unit "fp_mds" 1 1 (eq_attr "type" "fpdiv") 37 0) 170: (define_function_unit "fp_mds" 1 1 (eq_attr "type" "fpsqrt") 63 0) 171: 172: ;; Compare instructions. 173: ;; This controls RTL generation and register allocation. 174: 175: ;; We generate RTL for comparisons and branches by having the cmpxx 176: ;; patterns store away the operands. Then, the scc and bcc patterns 177: ;; emit RTL for both the compare and the branch. 178: ;; 179: ;; We do this because we want to generate different code for an sne and 180: ;; seq insn. In those cases, if the second operand of the compare is not 181: ;; const0_rtx, we want to compute the xor of the two operands and test 182: ;; it against zero. 183: ;; 184: ;; We start with the DEFINE_EXPANDs, then then DEFINE_INSNs to match 185: ;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc 186: ;; insns that actually require more than one machine instruction. 187: 188: ;; Put cmpsi first among compare insns so it matches two CONST_INT operands. 189: 190: (define_expand "cmpsi" 191: [(set (reg:CC 0) 192: (compare:CC (match_operand:SI 0 "register_operand" "") 193: (match_operand:SI 1 "arith_operand" "")))] 194: "" 195: " 196: { 197: sparc_compare_op0 = operands[0]; 198: sparc_compare_op1 = operands[1]; 199: DONE; 200: }") 201: 202: (define_expand "cmpsf" 203: [(set (reg:CCFP 0) 204: (compare:CCFP (match_operand:SF 0 "register_operand" "") 205: (match_operand:SF 1 "register_operand" "")))] 206: "TARGET_FPU" 207: " 208: { 209: sparc_compare_op0 = operands[0]; 210: sparc_compare_op1 = operands[1]; 211: DONE; 212: }") 213: 214: (define_expand "cmpdf" 215: [(set (reg:CCFP 0) 216: (compare:CCFP (match_operand:DF 0 "register_operand" "") 217: (match_operand:DF 1 "register_operand" "")))] 218: "TARGET_FPU" 219: " 220: { 221: sparc_compare_op0 = operands[0]; 222: sparc_compare_op1 = operands[1]; 223: DONE; 224: }") 225: 226: (define_expand "cmptf" 227: [(set (reg:CCFP 0) 228: (compare:CCFP (match_operand:TF 0 "register_operand" "") 229: (match_operand:TF 1 "register_operand" "")))] 230: "TARGET_FPU" 231: " 232: { 233: sparc_compare_op0 = operands[0]; 234: sparc_compare_op1 = operands[1]; 235: DONE; 236: }") 237: 238: ;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this 239: ;; without jumps using the addx/subx instructions. For the rest, we do 240: ;; branches. Seq_special and sne_special clobber the CC reg, because they 241: ;; generate addcc/subcc instructions. 242: 243: (define_expand "seq_special" 244: [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "") 245: (match_operand:SI 2 "register_operand" ""))) 246: (parallel [(set (match_operand:SI 0 "register_operand" "") 247: (eq:SI (match_dup 3) (const_int 0))) 248: (clobber (reg:CC 0))])] 249: 250: "" 251: "{ operands[3] = gen_reg_rtx (SImode); }") 252: 253: (define_expand "sne_special" 254: [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "") 255: (match_operand:SI 2 "register_operand" ""))) 256: (parallel [(set (match_operand:SI 0 "register_operand" "") 257: (ne:SI (match_dup 3) (const_int 0))) 258: (clobber (reg:CC 0))])] 259: "" 260: "{ operands[3] = gen_reg_rtx (SImode); }") 261: 262: (define_expand "seq" 263: [(set (match_operand:SI 0 "register_operand" "") 264: (eq:SI (match_dup 1) (const_int 0)))] 265: "" 266: " 267: { if (GET_MODE (sparc_compare_op0) == SImode) 268: { 269: emit_insn (gen_seq_special (operands[0], sparc_compare_op0, 270: sparc_compare_op1)); 271: DONE; 272: } 273: else 274: operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); 275: }") 276: 277: (define_expand "sne" 278: [(set (match_operand:SI 0 "register_operand" "") 279: (ne:SI (match_dup 1) (const_int 0)))] 280: "" 281: " 282: { if (GET_MODE (sparc_compare_op0) == SImode) 283: { 284: emit_insn (gen_sne_special (operands[0], sparc_compare_op0, 285: sparc_compare_op1)); 286: DONE; 287: } 288: else 289: operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); 290: }") 291: 292: (define_expand "sgt" 293: [(set (match_operand:SI 0 "register_operand" "") 294: (gt:SI (match_dup 1) (const_int 0)))] 295: "" 296: " 297: { operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }") 298: 299: (define_expand "slt" 300: [(set (match_operand:SI 0 "register_operand" "") 301: (lt:SI (match_dup 1) (const_int 0)))] 302: "" 303: " 304: { operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }") 305: 306: (define_expand "sge" 307: [(set (match_operand:SI 0 "register_operand" "") 308: (ge:SI (match_dup 1) (const_int 0)))] 309: "" 310: " 311: { operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }") 312: 313: (define_expand "sle" 314: [(set (match_operand:SI 0 "register_operand" "") 315: (le:SI (match_dup 1) (const_int 0)))] 316: "" 317: " 318: { operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }") 319: 320: (define_expand "sgtu" 321: [(set (match_operand:SI 0 "register_operand" "") 322: (gtu:SI (match_dup 1) (const_int 0)))] 323: "" 324: " 325: { 326: rtx tem; 327: 328: /* We can do ltu easily, so if both operands are registers, swap them and 329: do a LTU. */ 330: if ((GET_CODE (sparc_compare_op0) == REG 331: || GET_CODE (sparc_compare_op0) == SUBREG) 332: && (GET_CODE (sparc_compare_op1) == REG 333: || GET_CODE (sparc_compare_op1) == SUBREG)) 334: { 335: tem = sparc_compare_op0; 336: sparc_compare_op0 = sparc_compare_op1; 337: sparc_compare_op1 = tem; 338: emit_insn (gen_sltu (operands[0])); 339: DONE; 340: } 341: 342: operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); 343: }") 344: 345: (define_expand "sltu" 346: [(set (match_operand:SI 0 "register_operand" "") 347: (ltu:SI (match_dup 1) (const_int 0)))] 348: "" 349: " 350: { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1); 351: }") 352: 353: (define_expand "sgeu" 354: [(set (match_operand:SI 0 "register_operand" "") 355: (geu:SI (match_dup 1) (const_int 0)))] 356: "" 357: " 358: { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1); 359: }") 360: 361: (define_expand "sleu" 362: [(set (match_operand:SI 0 "register_operand" "") 363: (leu:SI (match_dup 1) (const_int 0)))] 364: "" 365: " 366: { 367: rtx tem; 368: 369: /* We can do geu easily, so if both operands are registers, swap them and 370: do a GEU. */ 371: if ((GET_CODE (sparc_compare_op0) == REG 372: || GET_CODE (sparc_compare_op0) == SUBREG) 373: && (GET_CODE (sparc_compare_op1) == REG 374: || GET_CODE (sparc_compare_op1) == SUBREG)) 375: { 376: tem = sparc_compare_op0; 377: sparc_compare_op0 = sparc_compare_op1; 378: sparc_compare_op1 = tem; 379: emit_insn (gen_sgeu (operands[0])); 380: DONE; 381: } 382: 383: operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); 384: }") 385: 386: ;; Now the DEFINE_INSNs for the compare and scc cases. First the compares. 387: 388: (define_insn "" 389: [(set (reg:CC 0) 390: (compare:CC (match_operand:SI 0 "register_operand" "r") 391: (match_operand:SI 1 "arith_operand" "rI")))] 392: "" 393: "cmp %r0,%1" 394: [(set_attr "type" "compare")]) 395: 396: (define_insn "" 397: [(set (reg:CCFPE 0) 398: (compare:CCFPE (match_operand:DF 0 "register_operand" "f") 399: (match_operand:DF 1 "register_operand" "f")))] 400: "TARGET_FPU" 401: "fcmped %0,%1" 402: [(set_attr "type" "fpcmp")]) 403: 404: (define_insn "" 405: [(set (reg:CCFPE 0) 406: (compare:CCFPE (match_operand:SF 0 "register_operand" "f") 407: (match_operand:SF 1 "register_operand" "f")))] 408: "TARGET_FPU" 409: "fcmpes %0,%1" 410: [(set_attr "type" "fpcmp")]) 411: 412: (define_insn "" 413: [(set (reg:CCFPE 0) 414: (compare:CCFPE (match_operand:TF 0 "register_operand" "f") 415: (match_operand:TF 1 "register_operand" "f")))] 416: "TARGET_FPU" 417: "fcmpeq %0,%1" 418: [(set_attr "type" "fpcmp")]) 419: 420: (define_insn "" 421: [(set (reg:CCFP 0) 422: (compare:CCFP (match_operand:DF 0 "register_operand" "f") 423: (match_operand:DF 1 "register_operand" "f")))] 424: "TARGET_FPU" 425: "fcmpd %0,%1" 426: [(set_attr "type" "fpcmp")]) 427: 428: (define_insn "" 429: [(set (reg:CCFP 0) 430: (compare:CCFP (match_operand:SF 0 "register_operand" "f") 431: (match_operand:SF 1 "register_operand" "f")))] 432: "TARGET_FPU" 433: "fcmps %0,%1" 434: [(set_attr "type" "fpcmp")]) 435: 436: (define_insn "" 437: [(set (reg:CCFP 0) 438: (compare:CCFP (match_operand:TF 0 "register_operand" "f") 439: (match_operand:TF 1 "register_operand" "f")))] 440: "TARGET_FPU" 441: "fcmpq %0,%1" 442: [(set_attr "type" "fpcmp")]) 443: 444: ;; The SEQ and SNE patterns are special because they can be done 445: ;; without any branching and do not involve a COMPARE. 446: 447: (define_insn "" 448: [(set (match_operand:SI 0 "register_operand" "=r") 449: (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))) 450: (clobber (reg:CC 0))] 451: "" 452: "subcc %%g0,%1,%%g0\;addx %%g0,0,%0" 453: [(set_attr "type" "unary") 454: (set_attr "length" "2")]) 455: 456: (define_insn "" 457: [(set (match_operand:SI 0 "register_operand" "=r") 458: (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r") 459: (const_int 0)))) 460: (clobber (reg:CC 0))] 461: "" 462: "subcc %%g0,%1,%%g0\;subx %%g0,0,%0" 463: [(set_attr "type" "unary") 464: (set_attr "length" "2")]) 465: 466: (define_insn "" 467: [(set (match_operand:SI 0 "register_operand" "=r") 468: (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))) 469: (clobber (reg:CC 0))] 470: "" 471: "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0" 472: [(set_attr "type" "unary") 473: (set_attr "length" "2")]) 474: 475: (define_insn "" 476: [(set (match_operand:SI 0 "register_operand" "=r") 477: (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r") 478: (const_int 0)))) 479: (clobber (reg:CC 0))] 480: "" 481: "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0" 482: [(set_attr "type" "unary") 483: (set_attr "length" "2")]) 484: 485: ;; We can also do (x + (i == 0)) and related, so put them in. 486: 487: (define_insn "" 488: [(set (match_operand:SI 0 "register_operand" "=r") 489: (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r") 490: (const_int 0)) 491: (match_operand:SI 2 "register_operand" "r"))) 492: (clobber (reg:CC 0))] 493: "" 494: "subcc %%g0,%1,%%g0\;addx %2,0,%0" 495: [(set_attr "length" "2")]) 496: 497: (define_insn "" 498: [(set (match_operand:SI 0 "register_operand" "=r") 499: (minus:SI (match_operand:SI 2 "register_operand" "r") 500: (ne:SI (match_operand:SI 1 "register_operand" "r") 501: (const_int 0)))) 502: (clobber (reg:CC 0))] 503: "" 504: "subcc %%g0,%1,%%g0\;subx %2,0,%0" 505: [(set_attr "length" "2")]) 506: 507: (define_insn "" 508: [(set (match_operand:SI 0 "register_operand" "=r") 509: (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r") 510: (const_int 0)) 511: (match_operand:SI 2 "register_operand" "r"))) 512: (clobber (reg:CC 0))] 513: "" 514: "subcc %%g0,%1,%%g0\;subx %2,-1,%0" 515: [(set_attr "length" "2")]) 516: 517: (define_insn "" 518: [(set (match_operand:SI 0 "register_operand" "=r") 519: (minus:SI (match_operand:SI 2 "register_operand" "r") 520: (eq:SI (match_operand:SI 1 "register_operand" "r") 521: (const_int 0)))) 522: (clobber (reg:CC 0))] 523: "" 524: "subcc %%g0,%1,%%g0\;addx %2,-1,%0" 525: [(set_attr "length" "2")]) 526: 527: ;; We can also do GEU and LTU directly, but these operate after a 528: ;; compare. 529: 530: (define_insn "" 531: [(set (match_operand:SI 0 "register_operand" "=r") 532: (ltu:SI (reg:CC 0) (const_int 0)))] 533: "" 534: "addx %%g0,0,%0" 535: [(set_attr "type" "misc")]) 536: 537: (define_insn "" 538: [(set (match_operand:SI 0 "register_operand" "=r") 539: (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))] 540: "" 541: "subx %%g0,0,%0" 542: [(set_attr "type" "misc")]) 543: 544: ;; ??? Combine should canonicalize these next two to the same pattern. 545: (define_insn "" 546: [(set (match_operand:SI 0 "register_operand" "=r") 547: (minus:SI (neg:SI (ltu:SI (reg:CC 0) (const_int 0))) 548: (match_operand:SI 1 "arith_operand" "rI")))] 549: "" 550: "subx %%g0,%1,%0" 551: [(set_attr "type" "unary")]) 552: 553: (define_insn "" 554: [(set (match_operand:SI 0 "register_operand" "=r") 555: (neg:SI (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 556: (match_operand:SI 1 "arith_operand" "rI"))))] 557: "" 558: "subx %%g0,%1,%0" 559: [(set_attr "type" "unary")]) 560: 561: (define_insn "" 562: [(set (match_operand:SI 0 "register_operand" "=r") 563: (geu:SI (reg:CC 0) (const_int 0)))] 564: "" 565: "subx %%g0,-1,%0" 566: [(set_attr "type" "misc")]) 567: 568: (define_insn "" 569: [(set (match_operand:SI 0 "register_operand" "=r") 570: (neg:SI (geu:SI (reg:CC 0) (const_int 0))))] 571: "" 572: "addx %%g0,-1,%0" 573: [(set_attr "type" "misc")]) 574: 575: ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in. 576: 577: (define_insn "" 578: [(set (match_operand:SI 0 "register_operand" "=r") 579: (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 580: (match_operand:SI 1 "arith_operand" "rI")))] 581: "" 582: "addx %%g0,%1,%0" 583: [(set_attr "type" "unary")]) 584: 585: (define_insn "" 586: [(set (match_operand:SI 0 "register_operand" "=r") 587: (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 588: (plus:SI (match_operand:SI 1 "arith_operand" "%r") 589: (match_operand:SI 2 "arith_operand" "rI"))))] 590: "" 591: "addx %1,%2,%0") 592: 593: (define_insn "" 594: [(set (match_operand:SI 0 "register_operand" "=r") 595: (minus:SI (match_operand:SI 1 "register_operand" "r") 596: (ltu:SI (reg:CC 0) (const_int 0))))] 597: "" 598: "subx %1,0,%0" 599: [(set_attr "type" "unary")]) 600: 601: ;; ??? Combine should canonicalize these next two to the same pattern. 602: (define_insn "" 603: [(set (match_operand:SI 0 "register_operand" "=r") 604: (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") 605: (match_operand:SI 2 "arith_operand" "rI")) 606: (ltu:SI (reg:CC 0) (const_int 0))))] 607: "" 608: "subx %1,%2,%0") 609: 610: (define_insn "" 611: [(set (match_operand:SI 0 "register_operand" "=r") 612: (minus:SI (match_operand:SI 1 "register_operand" "r") 613: (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 614: (match_operand:SI 2 "arith_operand" "rI"))))] 615: "" 616: "subx %1,%2,%0") 617: 618: (define_insn "" 619: [(set (match_operand:SI 0 "register_operand" "=r") 620: (plus:SI (geu:SI (reg:CC 0) (const_int 0)) 621: (match_operand:SI 1 "register_operand" "r")))] 622: "" 623: "subx %1,-1,%0" 624: [(set_attr "type" "unary")]) 625: 626: (define_insn "" 627: [(set (match_operand:SI 0 "register_operand" "=r") 628: (minus:SI (match_operand:SI 1 "register_operand" "r") 629: (geu:SI (reg:CC 0) (const_int 0))))] 630: "" 631: "addx %1,-1,%0" 632: [(set_attr "type" "unary")]) 633: 634: ;; Now we have the generic scc insns. These will be done using a jump. 635: ;; We have to exclude the cases above, since we will not want combine to 636: ;; turn something that does not require a jump into something that does. 637: (define_insn "" 638: [(set (match_operand:SI 0 "register_operand" "=r") 639: (match_operator:SI 1 "noov_compare_op" [(reg 0) (const_int 0)]))] 640: "" 641: "* return output_scc_insn (operands, insn); " 642: [(set_attr "type" "multi") 643: (set_attr "length" "3")]) 644: 645: ;; These control RTL generation for conditional jump insns 646: 647: (define_expand "beq" 648: [(set (pc) 649: (if_then_else (eq (match_dup 1) (const_int 0)) 650: (label_ref (match_operand 0 "" "")) 651: (pc)))] 652: "" 653: " 654: { operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); }") 655: 656: (define_expand "bne" 657: [(set (pc) 658: (if_then_else (ne (match_dup 1) (const_int 0)) 659: (label_ref (match_operand 0 "" "")) 660: (pc)))] 661: "" 662: " 663: { operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); }") 664: 665: (define_expand "bgt" 666: [(set (pc) 667: (if_then_else (gt (match_dup 1) (const_int 0)) 668: (label_ref (match_operand 0 "" "")) 669: (pc)))] 670: "" 671: " 672: { operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }") 673: 674: (define_expand "bgtu" 675: [(set (pc) 676: (if_then_else (gtu (match_dup 1) (const_int 0)) 677: (label_ref (match_operand 0 "" "")) 678: (pc)))] 679: "" 680: " 681: { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1); 682: }") 683: 684: (define_expand "blt" 685: [(set (pc) 686: (if_then_else (lt (match_dup 1) (const_int 0)) 687: (label_ref (match_operand 0 "" "")) 688: (pc)))] 689: "" 690: " 691: { operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }") 692: 693: (define_expand "bltu" 694: [(set (pc) 695: (if_then_else (ltu (match_dup 1) (const_int 0)) 696: (label_ref (match_operand 0 "" "")) 697: (pc)))] 698: "" 699: " 700: { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1); 701: }") 702: 703: (define_expand "bge" 704: [(set (pc) 705: (if_then_else (ge (match_dup 1) (const_int 0)) 706: (label_ref (match_operand 0 "" "")) 707: (pc)))] 708: "" 709: " 710: { operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }") 711: 712: (define_expand "bgeu" 713: [(set (pc) 714: (if_then_else (geu (match_dup 1) (const_int 0)) 715: (label_ref (match_operand 0 "" "")) 716: (pc)))] 717: "" 718: " 719: { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1); 720: }") 721: 722: (define_expand "ble" 723: [(set (pc) 724: (if_then_else (le (match_dup 1) (const_int 0)) 725: (label_ref (match_operand 0 "" "")) 726: (pc)))] 727: "" 728: " 729: { operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }") 730: 731: (define_expand "bleu" 732: [(set (pc) 733: (if_then_else (leu (match_dup 1) (const_int 0)) 734: (label_ref (match_operand 0 "" "")) 735: (pc)))] 736: "" 737: " 738: { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); 739: }") 740: 741: ;; Now match both normal and inverted jump. 742: 743: (define_insn "" 744: [(set (pc) 745: (if_then_else (match_operator 0 "noov_compare_op" 746: [(reg 0) (const_int 0)]) 747: (label_ref (match_operand 1 "" "")) 748: (pc)))] 749: "" 750: "* 751: { 752: return output_cbranch (operands[0], 1, 0, 753: final_sequence && INSN_ANNULLED_BRANCH_P (insn), 754: ! final_sequence); 755: }" 756: [(set_attr "type" "branch")]) 757: 758: (define_insn "" 759: [(set (pc) 760: (if_then_else (match_operator 0 "noov_compare_op" 761: [(reg 0) (const_int 0)]) 762: (pc) 763: (label_ref (match_operand 1 "" ""))))] 764: "" 765: "* 766: { 767: return output_cbranch (operands[0], 1, 1, 768: final_sequence && INSN_ANNULLED_BRANCH_P (insn), 769: ! final_sequence); 770: }" 771: [(set_attr "type" "branch")]) 772: 773: ;; Move instructions 774: 1.1.1.2 ! root 775: (define_expand "movqi" ! 776: [(set (match_operand:QI 0 "general_operand" "") ! 777: (match_operand:QI 1 "general_operand" ""))] 1.1 root 778: "" 779: " 780: { 1.1.1.2 ! root 781: if (emit_move_sequence (operands, QImode)) 1.1 root 782: DONE; 783: }") 784: 1.1.1.2 ! root 785: (define_insn "" ! 786: [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") ! 787: (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))] ! 788: "register_operand (operands[0], QImode) ! 789: || register_operand (operands[1], QImode) ! 790: || operands[1] == const0_rtx" ! 791: "@ ! 792: mov %1,%0 ! 793: sethi %%hi(%a1),%0 ! 794: ldub %1,%0 ! 795: stb %r1,%0" ! 796: [(set_attr "type" "move,move,load,store") ! 797: (set_attr "length" "*,1,*,1")]) ! 798: ! 799: (define_insn "" ! 800: [(set (match_operand:QI 0 "register_operand" "=r") ! 801: (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r") ! 802: (match_operand 2 "immediate_operand" "in")) 0))] ! 803: "" ! 804: "or %1,%%lo(%a2),%0" ! 805: [(set_attr "length" "1")]) ! 806: ! 807: (define_insn "" ! 808: [(set (mem:QI (match_operand:SI 0 "symbolic_operand" "")) ! 809: (match_operand:QI 1 "reg_or_0_operand" "rJ")) ! 810: (clobber (match_scratch:SI 2 "=&r"))] ! 811: "" ! 812: "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]" ! 813: [(set_attr "type" "store") ! 814: (set_attr "length" "2")]) ! 815: ! 816: (define_expand "movhi" ! 817: [(set (match_operand:HI 0 "general_operand" "") ! 818: (match_operand:HI 1 "general_operand" ""))] 1.1 root 819: "" 820: " 821: { 1.1.1.2 ! root 822: if (emit_move_sequence (operands, HImode)) 1.1 root 823: DONE; 1.1.1.2 ! root 824: }") 1.1 root 825: 1.1.1.2 ! root 826: (define_insn "" ! 827: [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") ! 828: (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))] ! 829: "register_operand (operands[0], HImode) ! 830: || register_operand (operands[1], HImode) ! 831: || operands[1] == const0_rtx" ! 832: "@ ! 833: mov %1,%0 ! 834: sethi %%hi(%a1),%0 ! 835: lduh %1,%0 ! 836: sth %r1,%0" ! 837: [(set_attr "type" "move,move,load,store") ! 838: (set_attr "length" "*,1,*,1")]) ! 839: ! 840: (define_insn "" ! 841: [(set (match_operand:HI 0 "register_operand" "=r") ! 842: (lo_sum:HI (match_operand:HI 1 "register_operand" "r") ! 843: (match_operand 2 "immediate_operand" "in")))] ! 844: "" ! 845: "or %1,%%lo(%a2),%0" ! 846: [(set_attr "length" "1")]) ! 847: ! 848: (define_insn "" ! 849: [(set (mem:HI (match_operand:SI 0 "symbolic_operand" "")) ! 850: (match_operand:HI 1 "reg_or_0_operand" "rJ")) ! 851: (clobber (match_scratch:SI 2 "=&r"))] ! 852: "" ! 853: "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]" ! 854: [(set_attr "type" "store") ! 855: (set_attr "length" "2")]) ! 856: ! 857: (define_expand "movsi" ! 858: [(set (match_operand:SI 0 "general_operand" "") ! 859: (match_operand:SI 1 "general_operand" ""))] ! 860: "" ! 861: " ! 862: { ! 863: if (emit_move_sequence (operands, SImode)) ! 864: DONE; 1.1 root 865: }") 866: 867: ;; We must support both 'r' and 'f' registers here, because combine may 868: ;; convert SFmode hard registers to SImode hard registers when simplifying 869: ;; subreg sets. 870: 871: ;; We cannot combine the similar 'r' and 'f' constraints, because it causes 872: ;; problems with register allocation. Reload might try to put an integer 873: ;; in an fp register, or an fp number is an integer register. 874: 875: (define_insn "" 876: [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q") 877: (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))] 878: "register_operand (operands[0], SImode) 879: || register_operand (operands[1], SImode) 880: || operands[1] == const0_rtx" 881: "@ 882: mov %1,%0 883: fmovs %1,%0 884: sethi %%hi(%a1),%0 885: ld %1,%0 886: ld %1,%0 887: st %r1,%0 888: st %r1,%0" 889: [(set_attr "type" "move,fp,move,load,load,store,store") 890: (set_attr "length" "*,*,1,*,*,*,*")]) 891: 892: ;; Special pic pattern, for loading the address of a label into a register. 893: ;; It clobbers o7 because the call puts the return address (i.e. pc value) 894: ;; there. 895: 896: (define_insn "" 897: [(set (match_operand:SI 0 "register_operand" "=r") 898: (match_operand:SI 1 "move_pic_label" "i")) 899: (set (reg:SI 15) (pc))] 900: "" 901: "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0" 902: [(set_attr "type" "multi") 903: (set_attr "length" "4")]) 904: 905: (define_insn "" 906: [(set (match_operand:DI 0 "register_operand" "=r") 907: (high:DI (match_operand 1 "" "")))] 908: "check_pic (1)" 909: "* 910: { 911: rtx op0 = operands[0]; 912: rtx op1 = operands[1]; 913: 914: if (GET_CODE (op1) == CONST_INT) 915: { 916: operands[0] = operand_subword (op0, 1, 0, DImode); 917: output_asm_insn (\"sethi %%hi(%a1),%0\", operands); 918: 919: operands[0] = operand_subword (op0, 0, 0, DImode); 920: if (INTVAL (op1) < 0) 921: return \"mov -1,%0\"; 922: else 923: return \"mov 0,%0\"; 924: } 925: else if (GET_CODE (op1) == CONST_DOUBLE) 926: { 927: operands[0] = operand_subword (op0, 1, 0, DImode); 928: operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1)); 929: output_asm_insn (\"sethi %%hi(%a1),%0\", operands); 930: 931: operands[0] = operand_subword (op0, 0, 0, DImode); 932: operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1)); 933: return singlemove_string (operands); 934: } 935: else 936: abort (); 937: return \"\"; 938: }" 939: [(set_attr "type" "move") 940: (set_attr "length" "2")]) 941: 942: ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't 943: ;; confuse them with real addresses. 944: (define_insn "" 945: [(set (match_operand:SI 0 "register_operand" "=r") 946: (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))] 947: "check_pic (1)" 948: "sethi %%hi(%a1),%0" 949: [(set_attr "type" "move") 950: (set_attr "length" "1")]) 951: 952: (define_insn "" 953: [(set (match_operand:SI 0 "register_operand" "=r") 954: (high:SI (match_operand 1 "" "")))] 955: "check_pic (1)" 956: "sethi %%hi(%a1),%0" 957: [(set_attr "type" "move") 958: (set_attr "length" "1")]) 959: 960: (define_insn "" 961: [(set (match_operand:HI 0 "register_operand" "=r") 962: (high:HI (match_operand 1 "" "")))] 963: "check_pic (1)" 964: "sethi %%hi(%a1),%0" 965: [(set_attr "type" "move") 966: (set_attr "length" "1")]) 967: 968: ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't 969: ;; confuse them with real addresses. 970: (define_insn "" 971: [(set (match_operand:SI 0 "register_operand" "=r") 972: (lo_sum:SI (match_operand:SI 1 "register_operand" "r") 973: (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))] 974: "" 975: "or %1,%%lo(%a2),%0" 976: ;; Need to set length for this arith insn because operand2 977: ;; is not an "arith_operand". 978: [(set_attr "length" "1")]) 979: 1.1.1.2 ! root 980: ;; ??? Can the next two be moved above the PIC stuff? ! 981: 1.1 root 982: (define_insn "" 983: [(set (match_operand:SI 0 "register_operand" "=r") 984: (lo_sum:SI (match_operand:SI 1 "register_operand" "r") 985: (match_operand:SI 2 "immediate_operand" "in")))] 986: "" 987: "or %1,%%lo(%a2),%0" 988: ;; Need to set length for this arith insn because operand2 989: ;; is not an "arith_operand". 990: [(set_attr "length" "1")]) 991: 992: (define_insn "" 993: [(set (mem:SI (match_operand:SI 0 "symbolic_operand" "")) 994: (match_operand:SI 1 "reg_or_0_operand" "rJ")) 995: (clobber (match_scratch:SI 2 "=&r"))] 996: "" 997: "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" 998: [(set_attr "type" "store") 999: (set_attr "length" "2")]) 1000: 1.1.1.2 ! root 1001: (define_expand "movdi" ! 1002: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") ! 1003: (match_operand:DI 1 "general_operand" ""))] 1.1 root 1004: "" 1005: " 1006: { 1.1.1.2 ! root 1007: if (emit_move_sequence (operands, DImode)) 1.1 root 1008: DONE; 1009: }") 1010: 1011: (define_insn "" 1.1.1.2 ! root 1012: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,Q,r,r,?f,?f,?Q") ! 1013: (match_operand:DI 1 "general_operand" "r,r,Q,i,f,Q,f"))] ! 1014: "register_operand (operands[0], DImode) ! 1015: || register_operand (operands[1], DImode) 1.1 root 1016: || operands[1] == const0_rtx" 1.1.1.2 ! root 1017: "* 1.1 root 1018: { 1.1.1.2 ! root 1019: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) ! 1020: return output_fp_move_double (operands); ! 1021: return output_move_double (operands); ! 1022: }" ! 1023: [(set_attr "type" "move,store,load,multi,fp,fpload,fpstore") ! 1024: (set_attr "length" "2,3,3,3,2,3,3")]) 1.1 root 1025: 1026: (define_insn "" 1.1.1.2 ! root 1027: [(set (match_operand:DI 0 "register_operand" "=r") ! 1028: (lo_sum:DI (match_operand:DI 1 "register_operand" "0") ! 1029: (match_operand:DI 2 "immediate_operand" "in")))] 1.1 root 1030: "" 1.1.1.2 ! root 1031: "* ! 1032: { ! 1033: /* Don't output a 64 bit constant, since we can't trust the assembler to ! 1034: handle it correctly. */ ! 1035: if (GET_CODE (operands[2]) == CONST_DOUBLE) ! 1036: operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2])); ! 1037: return \"or %R1,%%lo(%a2),%R0\"; ! 1038: }" ! 1039: ;; Need to set length for this arith insn because operand2 ! 1040: ;; is not an "arith_operand". 1.1 root 1041: [(set_attr "length" "1")]) 1042: 1.1.1.2 ! root 1043: ;; ??? There's no symbolic (set (mem:DI ...) ...). ! 1044: ! 1045: ;; Block move insns. 1.1 root 1046: 1047: ;; ??? We get better code without it. See output_block_move in sparc.c. 1048: 1049: ;; The definition of this insn does not really explain what it does, 1050: ;; but it should suffice 1051: ;; that anything generated as this insn will be recognized as one 1052: ;; and that it will not successfully combine with anything. 1053: ;(define_expand "movstrsi" 1054: ; [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) 1055: ; (mem:BLK (match_operand:BLK 1 "general_operand" ""))) 1056: ; (use (match_operand:SI 2 "nonmemory_operand" "")) 1057: ; (use (match_operand:SI 3 "immediate_operand" "")) 1058: ; (clobber (match_dup 0)) 1059: ; (clobber (match_dup 1)) 1060: ; (clobber (match_scratch:SI 4 "")) 1061: ; (clobber (reg:SI 0)) 1062: ; (clobber (reg:SI 1))])] 1063: ; "" 1064: ; " 1065: ;{ 1066: ; /* If the size isn't known, don't emit inline code. output_block_move 1067: ; would output code that's much slower than the library function. 1068: ; Also don't output code for large blocks. */ 1069: ; if (GET_CODE (operands[2]) != CONST_INT 1070: ; || GET_CODE (operands[3]) != CONST_INT 1071: ; || INTVAL (operands[2]) / INTVAL (operands[3]) > 16) 1072: ; FAIL; 1073: ; 1074: ; operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); 1075: ; operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); 1076: ; operands[2] = force_not_mem (operands[2]); 1077: ;}") 1078: 1079: ;(define_insn "" 1080: ; [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r")) 1081: ; (mem:BLK (match_operand:SI 1 "register_operand" "+r"))) 1082: ; (use (match_operand:SI 2 "nonmemory_operand" "rn")) 1083: ; (use (match_operand:SI 3 "immediate_operand" "i")) 1084: ; (clobber (match_dup 0)) 1085: ; (clobber (match_dup 1)) 1086: ; (clobber (match_scratch:SI 4 "=&r")) 1087: ; (clobber (reg:SI 0)) 1088: ; (clobber (reg:SI 1))] 1089: ; "" 1090: ; "* return output_block_move (operands);" 1091: ; [(set_attr "type" "multi") 1092: ; (set_attr "length" "6")]) 1093: 1094: ;; Floating point move insns 1095: 1.1.1.2 ! root 1096: ;; This pattern forces (set (reg:SF ...) (const_double ...)) 1.1 root 1097: ;; to be reloaded by putting the constant into memory. 1.1.1.2 ! root 1098: ;; It must come before the more general movsf pattern. 1.1 root 1099: (define_insn "" 1.1.1.2 ! root 1100: [(set (match_operand:SF 0 "general_operand" "=?r,f,m") ! 1101: (match_operand:SF 1 "" "?E,m,G"))] 1.1 root 1102: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" 1103: "* 1104: { 1105: switch (which_alternative) 1106: { 1107: case 0: 1.1.1.2 ! root 1108: return singlemove_string (operands); 1.1 root 1109: case 1: 1.1.1.2 ! root 1110: return \"ld %1,%0\"; 1.1 root 1111: case 2: 1.1.1.2 ! root 1112: return \"st %%g0,%0\"; 1.1 root 1113: } 1114: }" 1115: [(set_attr "type" "load,fpload,store") 1.1.1.2 ! root 1116: (set_attr "length" "2,1,1")]) 1.1 root 1117: 1.1.1.2 ! root 1118: (define_expand "movsf" ! 1119: [(set (match_operand:SF 0 "general_operand" "") ! 1120: (match_operand:SF 1 "general_operand" ""))] 1.1 root 1121: "" 1122: " 1123: { 1.1.1.2 ! root 1124: if (emit_move_sequence (operands, SFmode)) 1.1 root 1125: DONE; 1126: }") 1127: 1128: (define_insn "" 1.1.1.2 ! root 1129: [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q") ! 1130: (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))] 1.1 root 1131: "TARGET_FPU 1.1.1.2 ! root 1132: && (register_operand (operands[0], SFmode) ! 1133: || register_operand (operands[1], SFmode))" ! 1134: "@ ! 1135: fmovs %1,%0 ! 1136: mov %1,%0 ! 1137: ld %1,%0 ! 1138: ld %1,%0 ! 1139: st %r1,%0 ! 1140: st %r1,%0" ! 1141: [(set_attr "type" "fp,move,fpload,load,fpstore,store")]) 1.1 root 1142: 1143: ;; Exactly the same as above, except that all `f' cases are deleted. 1144: ;; This is necessary to prevent reload from ever trying to use a `f' reg 1145: ;; when -mno-fpu. 1146: 1147: (define_insn "" 1.1.1.2 ! root 1148: [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q") ! 1149: (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))] 1.1 root 1150: "! TARGET_FPU 1.1.1.2 ! root 1151: && (register_operand (operands[0], SFmode) ! 1152: || register_operand (operands[1], SFmode))" ! 1153: "@ ! 1154: mov %1,%0 ! 1155: ld %1,%0 ! 1156: st %r1,%0" ! 1157: [(set_attr "type" "move,load,store")]) 1.1 root 1158: 1159: (define_insn "" 1.1.1.2 ! root 1160: [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i")) ! 1161: (match_operand:SF 1 "reg_or_0_operand" "rfG")) ! 1162: (clobber (match_scratch:SI 2 "=&r"))] 1.1 root 1163: "" 1.1.1.2 ! root 1164: "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" 1.1 root 1165: [(set_attr "type" "store") 1.1.1.2 ! root 1166: (set_attr "length" "2")]) ! 1167: 1.1 root 1168: ;; This pattern forces (set (reg:DF ...) (const_double ...)) 1169: ;; to be reloaded by putting the constant into memory. 1170: ;; It must come before the more general movdf pattern. 1171: 1172: (define_insn "" 1173: [(set (match_operand:DF 0 "general_operand" "=?r,f,o") 1174: (match_operand:DF 1 "" "?E,m,G"))] 1175: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" 1176: "* 1177: { 1178: switch (which_alternative) 1179: { 1180: case 0: 1181: return output_move_double (operands); 1182: case 1: 1183: return output_fp_move_double (operands); 1184: case 2: 1185: operands[1] = adj_offsettable_operand (operands[0], 4); 1186: return \"st %%g0,%0\;st %%g0,%1\"; 1187: } 1188: }" 1189: [(set_attr "type" "load,fpload,store") 1190: (set_attr "length" "3,3,3")]) 1191: 1192: (define_expand "movdf" 1193: [(set (match_operand:DF 0 "general_operand" "") 1194: (match_operand:DF 1 "general_operand" ""))] 1195: "" 1196: " 1197: { 1.1.1.2 ! root 1198: if (emit_move_sequence (operands, DFmode)) 1.1 root 1199: DONE; 1200: }") 1201: 1202: (define_insn "" 1.1.1.2 ! root 1203: [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,f,r,Q,Q,f,r") 1.1 root 1204: (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,f,r,f,r,Q,Q"))] 1205: "TARGET_FPU 1206: && (register_operand (operands[0], DFmode) 1207: || register_operand (operands[1], DFmode))" 1208: "* 1209: { 1210: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) 1211: return output_fp_move_double (operands); 1212: return output_move_double (operands); 1213: }" 1214: [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load") 1215: (set_attr "length" "1,1,2,2,3,3,3,3")]) 1216: 1217: ;; Exactly the same as above, except that all `f' cases are deleted. 1218: ;; This is necessary to prevent reload from ever trying to use a `f' reg 1219: ;; when -mno-fpu. 1220: 1221: (define_insn "" 1222: [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r") 1223: (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))] 1224: "! TARGET_FPU 1225: && (register_operand (operands[0], DFmode) 1226: || register_operand (operands[1], DFmode))" 1227: "* return output_move_double (operands);" 1228: [(set_attr "type" "store,load,move,store,load") 1229: (set_attr "length" "1,1,2,3,3")]) 1230: 1231: (define_split 1232: [(set (match_operand:DF 0 "register_operand" "") 1233: (match_operand:DF 1 "register_operand" ""))] 1234: "reload_completed" 1235: [(set (match_dup 2) (match_dup 3)) 1236: (set (match_dup 4) (match_dup 5))] 1237: " 1238: { operands[2] = operand_subword (operands[0], 0, 0, DFmode); 1239: operands[3] = operand_subword (operands[1], 0, 0, DFmode); 1240: operands[4] = operand_subword (operands[0], 1, 0, DFmode); 1241: operands[5] = operand_subword (operands[1], 1, 0, DFmode); }") 1242: 1243: (define_insn "" 1244: [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i")) 1245: (match_operand:DF 1 "reg_or_0_operand" "rf,G")) 1246: (clobber (match_scratch:SI 2 "=&r,&r"))] 1247: "" 1248: "* 1249: { 1250: output_asm_insn (\"sethi %%hi(%a0),%2\", operands); 1251: if (which_alternative == 0) 1252: return \"std %1,[%2+%%lo(%a0)]\"; 1253: else 1254: return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\"; 1255: }" 1256: [(set_attr "type" "store") 1257: (set_attr "length" "3")]) 1258: 1.1.1.2 ! root 1259: ;; This pattern forces (set (reg:TF ...) (const_double ...)) 1.1 root 1260: ;; to be reloaded by putting the constant into memory. 1.1.1.2 ! root 1261: ;; It must come before the more general movtf pattern. 1.1 root 1262: (define_insn "" 1.1.1.2 ! root 1263: [(set (match_operand:TF 0 "general_operand" "=?r,f,o") ! 1264: (match_operand:TF 1 "" "?E,m,G"))] 1.1 root 1265: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" 1266: "* 1267: { 1268: switch (which_alternative) 1269: { 1270: case 0: 1.1.1.2 ! root 1271: return output_move_quad (operands); 1.1 root 1272: case 1: 1.1.1.2 ! root 1273: return output_fp_move_quad (operands); 1.1 root 1274: case 2: 1.1.1.2 ! root 1275: operands[1] = adj_offsettable_operand (operands[0], 4); ! 1276: operands[2] = adj_offsettable_operand (operands[0], 8); ! 1277: operands[3] = adj_offsettable_operand (operands[0], 12); ! 1278: return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\"; 1.1 root 1279: } 1280: }" 1281: [(set_attr "type" "load,fpload,store") 1.1.1.2 ! root 1282: (set_attr "length" "5,5,5")]) 1.1 root 1283: 1.1.1.2 ! root 1284: (define_expand "movtf" ! 1285: [(set (match_operand:TF 0 "general_operand" "") ! 1286: (match_operand:TF 1 "general_operand" ""))] 1.1 root 1287: "" 1288: " 1289: { 1.1.1.2 ! root 1290: if (emit_move_sequence (operands, TFmode)) 1.1 root 1291: DONE; 1292: }") 1293: 1294: (define_insn "" 1.1.1.2 ! root 1295: [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=f,r,Q,Q,f,&r") ! 1296: (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "f,r,f,r,Q,Q"))] 1.1 root 1297: "TARGET_FPU 1.1.1.2 ! root 1298: && (register_operand (operands[0], TFmode) ! 1299: || register_operand (operands[1], TFmode))" ! 1300: "* ! 1301: { ! 1302: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) ! 1303: return output_fp_move_quad (operands); ! 1304: return output_move_quad (operands); ! 1305: }" ! 1306: [(set_attr "type" "fp,move,fpstore,store,fpload,load") ! 1307: (set_attr "length" "4,4,5,5,5,5")]) 1.1 root 1308: 1309: ;; Exactly the same as above, except that all `f' cases are deleted. 1310: ;; This is necessary to prevent reload from ever trying to use a `f' reg 1311: ;; when -mno-fpu. 1312: 1313: (define_insn "" 1.1.1.2 ! root 1314: [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r") ! 1315: (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))] 1.1 root 1316: "! TARGET_FPU 1.1.1.2 ! root 1317: && (register_operand (operands[0], TFmode) ! 1318: || register_operand (operands[1], TFmode))" ! 1319: "* ! 1320: { ! 1321: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) ! 1322: return output_fp_move_quad (operands); ! 1323: return output_move_quad (operands); ! 1324: }" ! 1325: [(set_attr "type" "move,store,load") ! 1326: (set_attr "length" "4,5,5")]) 1.1 root 1327: 1328: (define_insn "" 1.1.1.2 ! root 1329: [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i")) ! 1330: (match_operand:TF 1 "reg_or_0_operand" "rf,G")) ! 1331: (clobber (match_scratch:SI 2 "=&r,&r"))] 1.1 root 1332: "" 1.1.1.2 ! root 1333: "* ! 1334: { ! 1335: output_asm_insn (\"sethi %%hi(%a0),%2\", operands); ! 1336: if (which_alternative == 0) ! 1337: return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\"; ! 1338: else ! 1339: return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\"; ! 1340: }" 1.1 root 1341: [(set_attr "type" "store") 1.1.1.2 ! root 1342: (set_attr "length" "5")]) 1.1 root 1343: 1344: ;;- zero extension instructions 1345: 1346: ;; These patterns originally accepted general_operands, however, slightly 1347: ;; better code is generated by only accepting register_operands, and then 1348: ;; letting combine generate the ldu[hb] insns. 1349: 1350: (define_expand "zero_extendhisi2" 1351: [(set (match_operand:SI 0 "register_operand" "") 1352: (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] 1353: "" 1354: " 1355: { 1356: rtx temp = gen_reg_rtx (SImode); 1357: rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); 1.1.1.2 ! root 1358: int op1_subword = 0; 1.1 root 1359: 1360: if (GET_CODE (operand1) == SUBREG) 1.1.1.2 ! root 1361: { ! 1362: op1_subword = SUBREG_WORD (operand1); ! 1363: operand1 = XEXP (operand1, 0); ! 1364: } 1.1 root 1365: 1.1.1.2 ! root 1366: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, ! 1367: op1_subword), 1.1 root 1368: shift_16)); 1369: emit_insn (gen_lshrsi3 (operand0, temp, shift_16)); 1370: DONE; 1371: }") 1372: 1373: (define_insn "" 1374: [(set (match_operand:SI 0 "register_operand" "=r") 1375: (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 1376: "" 1377: "lduh %1,%0" 1378: [(set_attr "type" "load")]) 1379: 1380: (define_expand "zero_extendqihi2" 1381: [(set (match_operand:HI 0 "register_operand" "") 1382: (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] 1383: "" 1384: "") 1385: 1386: (define_insn "" 1387: [(set (match_operand:HI 0 "register_operand" "=r,r") 1388: (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))] 1389: "GET_CODE (operands[1]) != CONST_INT" 1390: "@ 1391: and %1,0xff,%0 1392: ldub %1,%0" 1393: [(set_attr "type" "unary,load") 1394: (set_attr "length" "1")]) 1395: 1396: (define_expand "zero_extendqisi2" 1397: [(set (match_operand:SI 0 "register_operand" "") 1398: (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] 1399: "" 1400: "") 1401: 1402: (define_insn "" 1403: [(set (match_operand:SI 0 "register_operand" "=r,r") 1404: (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))] 1405: "GET_CODE (operands[1]) != CONST_INT" 1406: "@ 1407: and %1,0xff,%0 1408: ldub %1,%0" 1409: [(set_attr "type" "unary,load") 1410: (set_attr "length" "1")]) 1411: 1412: (define_insn "" 1413: [(set (reg:CC 0) 1414: (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r")) 1415: (const_int 0)))] 1416: "" 1417: "andcc %0,0xff,%%g0" 1418: [(set_attr "type" "compare")]) 1419: 1420: (define_insn "" 1421: [(set (reg:CC 0) 1422: (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) 1423: (const_int 0))) 1424: (set (match_operand:SI 0 "register_operand" "=r") 1425: (zero_extend:SI (match_dup 1)))] 1426: "" 1427: "andcc %1,0xff,%0" 1428: [(set_attr "type" "unary")]) 1429: 1430: ;; Similarly, handle SI->QI mode truncation followed by a compare. 1431: 1432: (define_insn "" 1433: [(set (reg:CC 0) 1434: (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0) 1435: (const_int 0)))] 1436: "" 1437: "andcc %0,0xff,%%g0" 1438: [(set_attr "type" "compare")]) 1439: 1440: (define_insn "" 1441: [(set (reg:CC 0) 1442: (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0) 1443: (const_int 0))) 1444: (set (match_operand:QI 0 "register_operand" "=r") 1445: (match_dup 1))] 1446: "" 1447: "andcc %1,0xff,%0" 1448: [(set_attr "type" "unary")]) 1449: 1450: ;;- sign extension instructions 1451: 1452: ;; These patterns originally accepted general_operands, however, slightly 1453: ;; better code is generated by only accepting register_operands, and then 1454: ;; letting combine generate the lds[hb] insns. 1455: 1456: (define_expand "extendhisi2" 1457: [(set (match_operand:SI 0 "register_operand" "") 1458: (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] 1459: "" 1460: " 1461: { 1462: rtx temp = gen_reg_rtx (SImode); 1463: rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); 1.1.1.2 ! root 1464: int op1_subword = 0; 1.1 root 1465: 1466: if (GET_CODE (operand1) == SUBREG) 1.1.1.2 ! root 1467: { ! 1468: op1_subword = SUBREG_WORD (operand1); ! 1469: operand1 = XEXP (operand1, 0); ! 1470: } 1.1 root 1471: 1.1.1.2 ! root 1472: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, ! 1473: op1_subword), 1.1 root 1474: shift_16)); 1475: emit_insn (gen_ashrsi3 (operand0, temp, shift_16)); 1476: DONE; 1477: }") 1478: 1479: (define_insn "" 1480: [(set (match_operand:SI 0 "register_operand" "=r") 1481: (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 1482: "" 1483: "ldsh %1,%0" 1484: [(set_attr "type" "load")]) 1485: 1486: (define_expand "extendqihi2" 1487: [(set (match_operand:HI 0 "register_operand" "") 1488: (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] 1489: "" 1490: " 1491: { 1492: rtx temp = gen_reg_rtx (SImode); 1493: rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); 1.1.1.2 ! root 1494: int op1_subword = 0; ! 1495: int op0_subword = 0; 1.1 root 1496: 1497: if (GET_CODE (operand1) == SUBREG) 1.1.1.2 ! root 1498: { ! 1499: op1_subword = SUBREG_WORD (operand1); ! 1500: operand1 = XEXP (operand1, 0); ! 1501: } 1.1 root 1502: if (GET_CODE (operand0) == SUBREG) 1.1.1.2 ! root 1503: { ! 1504: op0_subword = SUBREG_WORD (operand0); ! 1505: operand0 = XEXP (operand0, 0); ! 1506: } ! 1507: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, ! 1508: op1_subword), 1.1 root 1509: shift_24)); 1510: if (GET_MODE (operand0) != SImode) 1.1.1.2 ! root 1511: operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword); 1.1 root 1512: emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); 1513: DONE; 1514: }") 1515: 1516: (define_insn "" 1517: [(set (match_operand:HI 0 "register_operand" "=r") 1518: (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] 1519: "" 1520: "ldsb %1,%0" 1521: [(set_attr "type" "load")]) 1522: 1523: (define_expand "extendqisi2" 1524: [(set (match_operand:SI 0 "register_operand" "") 1525: (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] 1526: "" 1527: " 1528: { 1529: rtx temp = gen_reg_rtx (SImode); 1530: rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); 1.1.1.2 ! root 1531: int op1_subword = 0; 1.1 root 1532: 1533: if (GET_CODE (operand1) == SUBREG) 1.1.1.2 ! root 1534: { ! 1535: op1_subword = SUBREG_WORD (operand1); ! 1536: operand1 = XEXP (operand1, 0); ! 1537: } ! 1538: ! 1539: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, ! 1540: op1_subword), 1.1 root 1541: shift_24)); 1542: emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); 1543: DONE; 1544: }") 1545: 1546: (define_insn "" 1547: [(set (match_operand:SI 0 "register_operand" "=r") 1548: (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 1549: "" 1550: "ldsb %1,%0" 1551: [(set_attr "type" "load")]) 1552: 1553: ;; Special pattern for optimizing bit-field compares. This is needed 1554: ;; because combine uses this as a canonical form. 1555: 1556: (define_insn "" 1557: [(set (reg:CC 0) 1558: (compare:CC 1559: (zero_extract:SI (match_operand:SI 0 "register_operand" "r") 1560: (match_operand:SI 1 "small_int" "n") 1561: (match_operand:SI 2 "small_int" "n")) 1562: (const_int 0)))] 1563: "INTVAL (operands[2]) > 19" 1564: "* 1565: { 1566: int len = INTVAL (operands[1]); 1567: int pos = 32 - INTVAL (operands[2]) - len; 1568: unsigned mask = ((1 << len) - 1) << pos; 1569: 1570: operands[1] = gen_rtx (CONST_INT, VOIDmode, mask); 1571: return \"andcc %0,%1,%%g0\"; 1572: }") 1573: 1574: ;; Conversions between float, double and long double. 1575: 1576: (define_insn "extendsfdf2" 1577: [(set (match_operand:DF 0 "register_operand" "=f") 1578: (float_extend:DF 1579: (match_operand:SF 1 "register_operand" "f")))] 1580: "TARGET_FPU" 1581: "fstod %1,%0" 1582: [(set_attr "type" "fp")]) 1583: 1584: (define_insn "extendsftf2" 1585: [(set (match_operand:TF 0 "register_operand" "=f") 1586: (float_extend:TF 1587: (match_operand:SF 1 "register_operand" "f")))] 1588: "TARGET_FPU" 1589: "fstoq %1,%0" 1590: [(set_attr "type" "fp")]) 1591: 1592: (define_insn "extenddftf2" 1593: [(set (match_operand:TF 0 "register_operand" "=f") 1594: (float_extend:TF 1595: (match_operand:DF 1 "register_operand" "f")))] 1596: "TARGET_FPU" 1597: "fdtoq %1,%0" 1598: [(set_attr "type" "fp")]) 1599: 1600: (define_insn "truncdfsf2" 1601: [(set (match_operand:SF 0 "register_operand" "=f") 1602: (float_truncate:SF 1603: (match_operand:DF 1 "register_operand" "f")))] 1604: "TARGET_FPU" 1605: "fdtos %1,%0" 1606: [(set_attr "type" "fp")]) 1607: 1608: (define_insn "trunctfsf2" 1609: [(set (match_operand:SF 0 "register_operand" "=f") 1610: (float_truncate:SF 1611: (match_operand:TF 1 "register_operand" "f")))] 1612: "TARGET_FPU" 1613: "fqtos %1,%0" 1614: [(set_attr "type" "fp")]) 1615: 1616: (define_insn "trunctfdf2" 1617: [(set (match_operand:DF 0 "register_operand" "=f") 1618: (float_truncate:DF 1619: (match_operand:TF 1 "register_operand" "f")))] 1620: "TARGET_FPU" 1621: "fqtod %1,%0" 1622: [(set_attr "type" "fp")]) 1623: 1624: ;; Conversion between fixed point and floating point. 1625: 1626: (define_insn "floatsisf2" 1627: [(set (match_operand:SF 0 "register_operand" "=f") 1628: (float:SF (match_operand:SI 1 "register_operand" "f")))] 1629: "TARGET_FPU" 1630: "fitos %1,%0" 1631: [(set_attr "type" "fp")]) 1632: 1633: (define_insn "floatsidf2" 1634: [(set (match_operand:DF 0 "register_operand" "=f") 1635: (float:DF (match_operand:SI 1 "register_operand" "f")))] 1636: "TARGET_FPU" 1637: "fitod %1,%0" 1638: [(set_attr "type" "fp")]) 1639: 1640: (define_insn "floatsitf2" 1641: [(set (match_operand:TF 0 "register_operand" "=f") 1642: (float:TF (match_operand:SI 1 "register_operand" "f")))] 1643: "TARGET_FPU" 1644: "fitoq %1,%0" 1645: [(set_attr "type" "fp")]) 1646: 1647: ;; Convert a float to an actual integer. 1648: ;; Truncation is performed as part of the conversion. 1649: 1650: (define_insn "fix_truncsfsi2" 1651: [(set (match_operand:SI 0 "register_operand" "=f") 1652: (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] 1653: "TARGET_FPU" 1654: "fstoi %1,%0" 1655: [(set_attr "type" "fp")]) 1656: 1657: (define_insn "fix_truncdfsi2" 1658: [(set (match_operand:SI 0 "register_operand" "=f") 1659: (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] 1660: "TARGET_FPU" 1661: "fdtoi %1,%0" 1662: [(set_attr "type" "fp")]) 1663: 1664: (define_insn "fix_trunctfsi2" 1665: [(set (match_operand:SI 0 "register_operand" "=f") 1666: (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "f"))))] 1667: "TARGET_FPU" 1668: "fqtoi %1,%0" 1669: [(set_attr "type" "fp")]) 1670: 1671: ;;- arithmetic instructions 1672: 1673: (define_insn "adddi3" 1674: [(set (match_operand:DI 0 "register_operand" "=r") 1675: (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") 1676: (match_operand:DI 2 "arith_double_operand" "rHI"))) 1677: (clobber (reg:SI 0))] 1678: "" 1679: "* 1680: { 1681: rtx op2 = operands[2]; 1682: 1683: /* If constant is positive, upper bits zeroed, otherwise unchanged. 1684: Give the assembler a chance to pick the move instruction. */ 1685: if (GET_CODE (op2) == CONST_INT) 1686: { 1687: int sign = INTVAL (op2); 1688: if (sign < 0) 1689: return \"addcc %R1,%2,%R0\;addx %1,-1,%0\"; 1690: return \"addcc %R1,%2,%R0\;addx %1,0,%0\"; 1691: } 1692: else if (GET_CODE (op2) == CONST_DOUBLE) 1693: { 1694: int sign = CONST_DOUBLE_HIGH (op2); 1695: operands[2] = gen_rtx (CONST_INT, VOIDmode, 1696: CONST_DOUBLE_LOW (operands[1])); 1697: if (sign < 0) 1698: return \"addcc %R1,%2,%R0\;addx %1,-1,%0\"; 1699: return \"addcc %R1,%2,%R0\;addx %1,0,%0\"; 1700: } 1701: return \"addcc %R1,%R2,%R0\;addx %1,%2,%0\"; 1702: }" 1703: [(set_attr "length" "2")]) 1704: 1705: (define_insn "addsi3" 1706: [(set (match_operand:SI 0 "register_operand" "=r") 1707: (plus:SI (match_operand:SI 1 "arith_operand" "%r") 1708: (match_operand:SI 2 "arith_operand" "rI")))] 1709: "" 1710: "add %1,%2,%0") 1711: 1712: (define_insn "" 1713: [(set (reg:CC_NOOV 0) 1714: (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r") 1715: (match_operand:SI 1 "arith_operand" "rI")) 1716: (const_int 0)))] 1717: "" 1718: "addcc %0,%1,%%g0" 1719: [(set_attr "type" "compare")]) 1720: 1721: (define_insn "" 1722: [(set (reg:CC_NOOV 0) 1723: (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r") 1724: (match_operand:SI 2 "arith_operand" "rI")) 1725: (const_int 0))) 1726: (set (match_operand:SI 0 "register_operand" "=r") 1727: (plus:SI (match_dup 1) (match_dup 2)))] 1728: "" 1729: "addcc %1,%2,%0") 1730: 1731: (define_insn "subdi3" 1732: [(set (match_operand:DI 0 "register_operand" "=r") 1733: (minus:DI (match_operand:DI 1 "register_operand" "r") 1734: (match_operand:DI 2 "arith_double_operand" "rHI"))) 1735: (clobber (reg:SI 0))] 1736: "" 1737: "* 1738: { 1739: rtx op2 = operands[2]; 1740: 1741: /* If constant is positive, upper bits zeroed, otherwise unchanged. 1742: Give the assembler a chance to pick the move instruction. */ 1743: if (GET_CODE (op2) == CONST_INT) 1744: { 1745: int sign = INTVAL (op2); 1746: if (sign < 0) 1747: return \"subcc %R1,%2,%R0\;subx %1,-1,%0\"; 1748: return \"subcc %R1,%2,%R0\;subx %1,0,%0\"; 1749: } 1750: else if (GET_CODE (op2) == CONST_DOUBLE) 1751: { 1752: int sign = CONST_DOUBLE_HIGH (op2); 1753: operands[2] = gen_rtx (CONST_INT, VOIDmode, 1754: CONST_DOUBLE_LOW (operands[1])); 1755: if (sign < 0) 1756: return \"subcc %R1,%2,%R0\;subx %1,-1,%0\"; 1757: return \"subcc %R1,%2,%R0\;subx %1,0,%0\"; 1758: } 1759: return \"subcc %R1,%R2,%R0\;subx %1,%2,%0\"; 1760: }" 1761: [(set_attr "length" "2")]) 1762: 1763: (define_insn "subsi3" 1764: [(set (match_operand:SI 0 "register_operand" "=r") 1765: (minus:SI (match_operand:SI 1 "register_operand" "r") 1766: (match_operand:SI 2 "arith_operand" "rI")))] 1767: "" 1768: "sub %1,%2,%0") 1769: 1770: (define_insn "" 1771: [(set (reg:CC_NOOV 0) 1772: (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r") 1773: (match_operand:SI 1 "arith_operand" "rI")) 1774: (const_int 0)))] 1775: "" 1776: "subcc %0,%1,%%g0" 1777: [(set_attr "type" "compare")]) 1778: 1779: (define_insn "" 1780: [(set (reg:CC_NOOV 0) 1781: (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r") 1782: (match_operand:SI 2 "arith_operand" "rI")) 1783: (const_int 0))) 1784: (set (match_operand:SI 0 "register_operand" "=r") 1785: (minus:SI (match_dup 1) (match_dup 2)))] 1786: "" 1787: "subcc %1,%2,%0") 1788: 1789: (define_insn "mulsi3" 1790: [(set (match_operand:SI 0 "register_operand" "=r") 1791: (mult:SI (match_operand:SI 1 "arith_operand" "%r") 1792: (match_operand:SI 2 "arith_operand" "rI")))] 1793: "TARGET_V8 || TARGET_SPARCLITE" 1794: "smul %1,%2,%0") 1795: 1796: ;; It is not known whether this will match. 1797: 1798: (define_insn "" 1799: [(set (match_operand:SI 0 "register_operand" "=r") 1800: (mult:SI (match_operand:SI 1 "arith_operand" "%r") 1801: (match_operand:SI 2 "arith_operand" "rI"))) 1802: (set (reg:CC_NOOV 0) 1803: (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2)) 1804: (const_int 0)))] 1805: "TARGET_V8 || TARGET_SPARCLITE" 1806: "smulcc %1,%2,%0") 1807: 1808: (define_expand "mulsidi3" 1809: [(set (match_operand:DI 0 "register_operand" "") 1810: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) 1811: (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))] 1812: "TARGET_V8 || TARGET_SPARCLITE" 1813: " 1814: { 1815: if (CONSTANT_P (operands[2])) 1816: { 1817: emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2])); 1818: DONE; 1819: } 1820: }") 1821: 1822: (define_insn "" 1823: [(set (match_operand:DI 0 "register_operand" "=r") 1824: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) 1825: (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1826: "TARGET_V8 || TARGET_SPARCLITE" 1827: "smul %1,%2,%R0\;rd %%y,%0" 1828: [(set_attr "length" "2")]) 1829: 1830: ;; Extra pattern, because sign_extend of a constant isn't legal. 1831: 1832: (define_insn "const_mulsidi3" 1833: [(set (match_operand:DI 0 "register_operand" "=r") 1834: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) 1835: (match_operand:SI 2 "small_int" "I")))] 1836: "TARGET_V8 || TARGET_SPARCLITE" 1837: "smul %1,%2,%R0\;rd %%y,%0" 1838: [(set_attr "length" "2")]) 1839: 1840: (define_expand "umulsidi3" 1841: [(set (match_operand:DI 0 "register_operand" "") 1842: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) 1.1.1.2 ! root 1843: (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))] 1.1 root 1844: "TARGET_V8 || TARGET_SPARCLITE" 1845: " 1846: { 1847: if (CONSTANT_P (operands[2])) 1848: { 1849: emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2])); 1850: DONE; 1851: } 1852: }") 1853: 1854: (define_insn "" 1855: [(set (match_operand:DI 0 "register_operand" "=r") 1856: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) 1857: (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1858: "TARGET_V8 || TARGET_SPARCLITE" 1859: "umul %1,%2,%R0\;rd %%y,%0" 1860: [(set_attr "length" "2")]) 1861: 1862: ;; Extra pattern, because sign_extend of a constant isn't legal. 1863: 1864: (define_insn "const_umulsidi3" 1865: [(set (match_operand:DI 0 "register_operand" "=r") 1866: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) 1.1.1.2 ! root 1867: (match_operand:SI 2 "uns_small_int" "")))] 1.1 root 1868: "TARGET_V8 || TARGET_SPARCLITE" 1869: "umul %1,%2,%R0\;rd %%y,%0" 1870: [(set_attr "length" "2")]) 1871: 1872: ;; The architecture specifies that there must be 3 instructions between 1873: ;; a y register write and a use of it for correct results. 1874: 1875: (define_insn "divsi3" 1876: [(set (match_operand:SI 0 "register_operand" "=r") 1877: (div:SI (match_operand:SI 1 "register_operand" "r") 1878: (match_operand:SI 2 "arith_operand" "rI"))) 1879: (clobber (match_scratch:SI 3 "=&r"))] 1880: "TARGET_V8" 1881: "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0" 1882: [(set_attr "length" "6")]) 1883: 1884: ;; It is not known whether this will match. 1885: 1886: (define_insn "" 1887: [(set (match_operand:SI 0 "register_operand" "=r") 1888: (div:SI (match_operand:SI 1 "register_operand" "r") 1889: (match_operand:SI 2 "arith_operand" "rI"))) 1890: (set (reg:CC 0) 1891: (compare:CC (div:SI (match_dup 1) (match_dup 2)) 1892: (const_int 0))) 1893: (clobber (match_scratch:SI 3 "=&r"))] 1894: "TARGET_V8" 1895: "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0" 1896: [(set_attr "length" "6")]) 1897: 1898: (define_insn "udivsi3" 1899: [(set (match_operand:SI 0 "register_operand" "=r") 1900: (udiv:SI (match_operand:SI 1 "register_operand" "r") 1901: (match_operand:SI 2 "arith_operand" "rI")))] 1902: "TARGET_V8" 1903: "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0" 1904: [(set_attr "length" "5")]) 1905: 1906: ;; It is not known whether this will match. 1907: 1908: (define_insn "" 1909: [(set (match_operand:SI 0 "register_operand" "=r") 1910: (udiv:SI (match_operand:SI 1 "register_operand" "r") 1911: (match_operand:SI 2 "arith_operand" "rI"))) 1912: (set (reg:CC 0) 1913: (compare:CC (udiv:SI (match_dup 1) (match_dup 2)) 1914: (const_int 0)))] 1915: "TARGET_V8" 1916: "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0" 1917: [(set_attr "length" "5")]) 1.1.1.2 ! root 1918: ! 1919: ;;- Boolean instructions 1.1 root 1920: ;; We define DImode `and` so with DImode `not` we can get 1921: ;; DImode `andn`. Other combinations are possible. 1922: 1923: (define_expand "anddi3" 1924: [(set (match_operand:DI 0 "register_operand" "") 1925: (and:DI (match_operand:DI 1 "arith_double_operand" "") 1926: (match_operand:DI 2 "arith_double_operand" "")))] 1927: "" 1928: "") 1929: 1930: (define_insn "" 1931: [(set (match_operand:DI 0 "register_operand" "=r") 1932: (and:DI (match_operand:DI 1 "arith_double_operand" "%r") 1933: (match_operand:DI 2 "arith_double_operand" "rHI")))] 1934: "" 1935: "* 1936: { 1937: rtx op2 = operands[2]; 1938: 1939: /* If constant is positive, upper bits zeroed, otherwise unchanged. 1940: Give the assembler a chance to pick the move instruction. */ 1941: if (GET_CODE (op2) == CONST_INT) 1942: { 1943: int sign = INTVAL (op2); 1944: if (sign < 0) 1945: return \"mov %1,%0\;and %R1,%2,%R0\"; 1946: return \"mov 0,%0\;and %R1,%2,%R0\"; 1947: } 1948: else if (GET_CODE (op2) == CONST_DOUBLE) 1949: { 1950: int sign = CONST_DOUBLE_HIGH (op2); 1951: operands[2] = gen_rtx (CONST_INT, VOIDmode, 1952: CONST_DOUBLE_LOW (operands[1])); 1953: if (sign < 0) 1954: return \"mov %1,%0\;and %R1,%2,%R0\"; 1955: return \"mov 0,%0\;and %R1,%2,%R0\"; 1956: } 1957: return \"and %1,%2,%0\;and %R1,%R2,%R0\"; 1958: }" 1959: [(set_attr "length" "2")]) 1960: 1961: (define_insn "andsi3" 1962: [(set (match_operand:SI 0 "register_operand" "=r") 1963: (and:SI (match_operand:SI 1 "arith_operand" "%r") 1964: (match_operand:SI 2 "arith_operand" "rI")))] 1965: "" 1966: "and %1,%2,%0") 1967: 1968: (define_split 1969: [(set (match_operand:SI 0 "register_operand" "") 1970: (and:SI (match_operand:SI 1 "register_operand" "") 1971: (match_operand:SI 2 "" ""))) 1972: (clobber (match_operand:SI 3 "register_operand" ""))] 1973: "GET_CODE (operands[2]) == CONST_INT 1974: && !SMALL_INT (operands[2]) 1975: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" 1976: [(set (match_dup 3) (match_dup 4)) 1977: (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))] 1978: " 1979: { 1980: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); 1981: }") 1982: 1983: (define_insn "" 1984: [(set (match_operand:DI 0 "register_operand" "=r") 1985: (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) 1986: (match_operand:DI 2 "register_operand" "r")))] 1987: "" 1988: "andn %2,%1,%0\;andn %R2,%R1,%R0" 1989: [(set_attr "length" "2")]) 1990: 1991: (define_insn "" 1992: [(set (match_operand:SI 0 "register_operand" "=r") 1993: (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) 1994: (match_operand:SI 2 "register_operand" "r")))] 1995: "" 1996: "andn %2,%1,%0") 1997: 1998: (define_expand "iordi3" 1999: [(set (match_operand:DI 0 "register_operand" "") 2000: (ior:DI (match_operand:DI 1 "arith_double_operand" "") 2001: (match_operand:DI 2 "arith_double_operand" "")))] 2002: "" 2003: "") 2004: 2005: (define_insn "" 2006: [(set (match_operand:DI 0 "register_operand" "=r") 2007: (ior:DI (match_operand:DI 1 "arith_double_operand" "%r") 2008: (match_operand:DI 2 "arith_double_operand" "rHI")))] 2009: "" 2010: "* 2011: { 2012: rtx op2 = operands[2]; 2013: 2014: /* If constant is positive, upper bits zeroed, otherwise unchanged. 2015: Give the assembler a chance to pick the move instruction. */ 2016: if (GET_CODE (op2) == CONST_INT) 2017: { 2018: int sign = INTVAL (op2); 2019: if (sign < 0) 2020: return \"mov -1,%0\;or %R1,%2,%R0\"; 2021: return \"mov %1,%0\;or %R1,%2,%R0\"; 2022: } 2023: else if (GET_CODE (op2) == CONST_DOUBLE) 2024: { 2025: int sign = CONST_DOUBLE_HIGH (op2); 2026: operands[2] = gen_rtx (CONST_INT, VOIDmode, 2027: CONST_DOUBLE_LOW (operands[1])); 2028: if (sign < 0) 2029: return \"mov -1,%0\;or %R1,%2,%R0\"; 2030: return \"mov %1,%0\;or %R1,%2,%R0\"; 2031: } 2032: return \"or %1,%2,%0\;or %R1,%R2,%R0\"; 2033: }" 2034: [(set_attr "length" "2")]) 2035: 2036: (define_insn "iorsi3" 2037: [(set (match_operand:SI 0 "register_operand" "=r") 2038: (ior:SI (match_operand:SI 1 "arith_operand" "%r") 2039: (match_operand:SI 2 "arith_operand" "rI")))] 2040: "" 2041: "or %1,%2,%0") 2042: 2043: (define_split 2044: [(set (match_operand:SI 0 "register_operand" "") 2045: (ior:SI (match_operand:SI 1 "register_operand" "") 2046: (match_operand:SI 2 "" ""))) 2047: (clobber (match_operand:SI 3 "register_operand" ""))] 2048: "GET_CODE (operands[2]) == CONST_INT 2049: && !SMALL_INT (operands[2]) 2050: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" 2051: [(set (match_dup 3) (match_dup 4)) 2052: (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))] 2053: " 2054: { 2055: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); 2056: }") 2057: 2058: (define_insn "" 2059: [(set (match_operand:DI 0 "register_operand" "=r") 2060: (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r")) 2061: (match_operand:DI 2 "register_operand" "r")))] 2062: "" 2063: "orn %2,%1,%0\;orn %R2,%R1,%R0" 2064: [(set_attr "length" "2")]) 2065: 2066: (define_insn "" 2067: [(set (match_operand:SI 0 "register_operand" "=r") 2068: (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r")) 2069: (match_operand:SI 2 "register_operand" "r")))] 2070: "" 2071: "orn %2,%1,%0") 2072: 2073: (define_expand "xordi3" 2074: [(set (match_operand:DI 0 "register_operand" "") 2075: (xor:DI (match_operand:DI 1 "arith_double_operand" "") 2076: (match_operand:DI 2 "arith_double_operand" "")))] 2077: "" 2078: "") 2079: 2080: (define_insn "" 2081: [(set (match_operand:DI 0 "register_operand" "=r") 2082: (xor:DI (match_operand:DI 1 "arith_double_operand" "%r") 2083: (match_operand:DI 2 "arith_double_operand" "rHI")))] 2084: "" 2085: "* 2086: { 2087: rtx op2 = operands[2]; 2088: 2089: /* If constant is positive, upper bits zeroed, otherwise unchanged. 2090: Give the assembler a chance to pick the move instruction. */ 2091: if (GET_CODE (op2) == CONST_INT) 2092: { 2093: int sign = INTVAL (op2); 2094: if (sign < 0) 2095: return \"xor %1,-1,%0\;xor %R1,%2,%R0\"; 2096: return \"mov %1,%0\;xor %R1,%2,%R0\"; 2097: } 2098: else if (GET_CODE (op2) == CONST_DOUBLE) 2099: { 2100: int sign = CONST_DOUBLE_HIGH (op2); 2101: operands[2] = gen_rtx (CONST_INT, VOIDmode, 2102: CONST_DOUBLE_LOW (operands[1])); 2103: if (sign < 0) 2104: return \"xor %1,-1,%0\;xor %R1,%2,%R0\"; 2105: return \"mov %1,%0\;xor %R1,%2,%R0\"; 2106: } 2107: return \"xor %1,%2,%0\;xor %R1,%R2,%R0\"; 2108: }" 2109: [(set_attr "length" "2")]) 2110: 2111: (define_insn "xorsi3" 2112: [(set (match_operand:SI 0 "register_operand" "=r") 2113: (xor:SI (match_operand:SI 1 "arith_operand" "%rJ") 2114: (match_operand:SI 2 "arith_operand" "rI")))] 2115: "" 2116: "xor %r1,%2,%0") 2117: 2118: (define_split 2119: [(set (match_operand:SI 0 "register_operand" "") 2120: (xor:SI (match_operand:SI 1 "register_operand" "") 2121: (match_operand:SI 2 "" ""))) 2122: (clobber (match_operand:SI 3 "register_operand" ""))] 2123: "GET_CODE (operands[2]) == CONST_INT 2124: && !SMALL_INT (operands[2]) 2125: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" 2126: [(set (match_dup 3) (match_dup 4)) 2127: (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))] 2128: " 2129: { 2130: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); 2131: }") 2132: 2133: (define_split 2134: [(set (match_operand:SI 0 "register_operand" "") 2135: (not:SI (xor:SI (match_operand:SI 1 "register_operand" "") 2136: (match_operand:SI 2 "" "")))) 2137: (clobber (match_operand:SI 3 "register_operand" ""))] 2138: "GET_CODE (operands[2]) == CONST_INT 2139: && !SMALL_INT (operands[2]) 2140: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" 2141: [(set (match_dup 3) (match_dup 4)) 2142: (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))] 2143: " 2144: { 2145: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); 2146: }") 2147: 2148: ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b). 2149: ;; Combine now canonicalizes to the rightmost expression. 2150: (define_insn "" 2151: [(set (match_operand:DI 0 "register_operand" "=r") 2152: (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r") 2153: (match_operand:DI 2 "register_operand" "r"))))] 2154: "" 2155: "xnor %1,%2,%0\;xnor %R1,%R2,%R0" 2156: [(set_attr "length" "2")]) 2157: 2158: (define_insn "" 2159: [(set (match_operand:SI 0 "register_operand" "=r") 2160: (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") 2161: (match_operand:SI 2 "arith_operand" "rI"))))] 2162: "" 2163: "xnor %r1,%2,%0") 2164: 2165: ;; These correspond to the above in the case where we also (or only) 2166: ;; want to set the condition code. 2167: 2168: (define_insn "" 2169: [(set (reg:CC 0) 2170: (compare:CC 2171: (match_operator:SI 2 "cc_arithop" 2172: [(match_operand:SI 0 "arith_operand" "%r") 2173: (match_operand:SI 1 "arith_operand" "rI")]) 2174: (const_int 0)))] 2175: "" 2176: "%A2cc %0,%1,%%g0" 2177: [(set_attr "type" "compare")]) 2178: 2179: (define_insn "" 2180: [(set (reg:CC 0) 2181: (compare:CC 2182: (match_operator:SI 3 "cc_arithop" 2183: [(match_operand:SI 1 "arith_operand" "%r") 2184: (match_operand:SI 2 "arith_operand" "rI")]) 2185: (const_int 0))) 2186: (set (match_operand:SI 0 "register_operand" "=r") 2187: (match_dup 3))] 2188: "" 2189: "%A3cc %1,%2,%0") 2190: 2191: (define_insn "" 2192: [(set (reg:CC 0) 2193: (compare:CC 2194: (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ") 2195: (match_operand:SI 1 "arith_operand" "rI"))) 2196: (const_int 0)))] 2197: "" 2198: "xnorcc %r0,%1,%%g0" 2199: [(set_attr "type" "compare")]) 2200: 2201: (define_insn "" 2202: [(set (reg:CC 0) 2203: (compare:CC 2204: (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") 2205: (match_operand:SI 2 "arith_operand" "rI"))) 2206: (const_int 0))) 2207: (set (match_operand:SI 0 "register_operand" "=r") 2208: (not:SI (xor:SI (match_dup 1) (match_dup 2))))] 2209: "" 2210: "xnorcc %r1,%2,%0") 2211: 2212: (define_insn "" 2213: [(set (reg:CC 0) 2214: (compare:CC 2215: (match_operator:SI 2 "cc_arithopn" 2216: [(not:SI (match_operand:SI 0 "arith_operand" "rI")) 2217: (match_operand:SI 1 "reg_or_0_operand" "rJ")]) 2218: (const_int 0)))] 2219: "" 2220: "%B2cc %r1,%0,%%g0" 2221: [(set_attr "type" "compare")]) 2222: 2223: (define_insn "" 2224: [(set (reg:CC 0) 2225: (compare:CC 2226: (match_operator:SI 3 "cc_arithopn" 2227: [(not:SI (match_operand:SI 1 "arith_operand" "rI")) 2228: (match_operand:SI 2 "reg_or_0_operand" "rJ")]) 2229: (const_int 0))) 2230: (set (match_operand:SI 0 "register_operand" "=r") 2231: (match_dup 3))] 2232: "" 2233: "%B3cc %r2,%1,%0") 2234: 2235: ;; We cannot use the "neg" pseudo insn because the Sun assembler 2236: ;; does not know how to make it work for constants. 2237: 2238: (define_insn "negdi2" 2239: [(set (match_operand:DI 0 "register_operand" "=r") 2240: (neg:DI (match_operand:DI 1 "register_operand" "r"))) 2241: (clobber (reg:SI 0))] 2242: "" 2243: "subcc %%g0,%R1,%R0\;subx %%g0,%1,%0" 2244: [(set_attr "type" "unary") 2245: (set_attr "length" "2")]) 2246: 2247: (define_insn "negsi2" 2248: [(set (match_operand:SI 0 "general_operand" "=r") 2249: (neg:SI (match_operand:SI 1 "arith_operand" "rI")))] 2250: "" 2251: "sub %%g0,%1,%0" 2252: [(set_attr "type" "unary")]) 2253: 2254: (define_insn "" 2255: [(set (reg:CC_NOOV 0) 2256: (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI")) 2257: (const_int 0)))] 2258: "" 2259: "subcc %%g0,%0,%%g0" 2260: [(set_attr "type" "compare")]) 2261: 2262: (define_insn "" 2263: [(set (reg:CC_NOOV 0) 2264: (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI")) 2265: (const_int 0))) 2266: (set (match_operand:SI 0 "register_operand" "=r") 2267: (neg:SI (match_dup 1)))] 2268: "" 2269: "subcc %%g0,%1,%0" 2270: [(set_attr "type" "unary")]) 2271: 2272: ;; We cannot use the "not" pseudo insn because the Sun assembler 2273: ;; does not know how to make it work for constants. 2274: (define_expand "one_cmpldi2" 2275: [(set (match_operand:DI 0 "register_operand" "=r") 2276: (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))] 2277: "" 2278: "") 2279: 2280: (define_insn "" 2281: [(set (match_operand:DI 0 "register_operand" "=r") 2282: (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))] 2283: "" 2284: "* 2285: { 2286: rtx op1 = operands[1]; 2287: 2288: if (GET_CODE (op1) == CONST_INT) 2289: { 2290: int sign = INTVAL (op1); 2291: if (sign < 0) 2292: return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\"; 2293: return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\"; 2294: } 2295: else if (GET_CODE (op1) == CONST_DOUBLE) 2296: { 2297: int sign = CONST_DOUBLE_HIGH (op1); 2298: operands[1] = gen_rtx (CONST_INT, VOIDmode, 2299: CONST_DOUBLE_LOW (operands[1])); 2300: if (sign < 0) 2301: return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\"; 2302: return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\"; 2303: } 2304: return \"xnor %%g0,%1,%0\;xnor %%g0,%R1,%R0\"; 2305: }" 2306: [(set_attr "type" "unary") 2307: (set_attr "length" "2")]) 2308: 2309: (define_insn "one_cmplsi2" 2310: [(set (match_operand:SI 0 "register_operand" "=r") 2311: (not:SI (match_operand:SI 1 "arith_operand" "rI")))] 2312: "" 2313: "xnor %%g0,%1,%0" 2314: [(set_attr "type" "unary")]) 2315: 2316: (define_insn "" 2317: [(set (reg:CC 0) 2318: (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI")) 2319: (const_int 0)))] 2320: "" 2321: "xnorcc %%g0,%0,%%g0" 2322: [(set_attr "type" "compare")]) 2323: 2324: (define_insn "" 2325: [(set (reg:CC 0) 2326: (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI")) 2327: (const_int 0))) 2328: (set (match_operand:SI 0 "register_operand" "=r") 2329: (not:SI (match_dup 1)))] 2330: "" 2331: "xnorcc %%g0,%1,%0" 2332: [(set_attr "type" "unary")]) 2333: 2334: ;; Floating point arithmetic instructions. 2335: 2336: (define_insn "addtf3" 2337: [(set (match_operand:TF 0 "register_operand" "=f") 2338: (plus:TF (match_operand:TF 1 "register_operand" "f") 2339: (match_operand:TF 2 "register_operand" "f")))] 2340: "TARGET_FPU" 2341: "faddq %1,%2,%0" 2342: [(set_attr "type" "fp")]) 2343: 2344: (define_insn "adddf3" 2345: [(set (match_operand:DF 0 "register_operand" "=f") 2346: (plus:DF (match_operand:DF 1 "register_operand" "f") 2347: (match_operand:DF 2 "register_operand" "f")))] 2348: "TARGET_FPU" 2349: "faddd %1,%2,%0" 2350: [(set_attr "type" "fp")]) 2351: 2352: (define_insn "addsf3" 2353: [(set (match_operand:SF 0 "register_operand" "=f") 2354: (plus:SF (match_operand:SF 1 "register_operand" "f") 2355: (match_operand:SF 2 "register_operand" "f")))] 2356: "TARGET_FPU" 2357: "fadds %1,%2,%0" 2358: [(set_attr "type" "fp")]) 2359: 2360: (define_insn "subtf3" 2361: [(set (match_operand:TF 0 "register_operand" "=f") 2362: (minus:TF (match_operand:TF 1 "register_operand" "f") 2363: (match_operand:TF 2 "register_operand" "f")))] 2364: "TARGET_FPU" 2365: "fsubq %1,%2,%0" 2366: [(set_attr "type" "fp")]) 2367: 2368: (define_insn "subdf3" 2369: [(set (match_operand:DF 0 "register_operand" "=f") 2370: (minus:DF (match_operand:DF 1 "register_operand" "f") 2371: (match_operand:DF 2 "register_operand" "f")))] 2372: "TARGET_FPU" 2373: "fsubd %1,%2,%0" 2374: [(set_attr "type" "fp")]) 2375: 2376: (define_insn "subsf3" 2377: [(set (match_operand:SF 0 "register_operand" "=f") 2378: (minus:SF (match_operand:SF 1 "register_operand" "f") 2379: (match_operand:SF 2 "register_operand" "f")))] 2380: "TARGET_FPU" 2381: "fsubs %1,%2,%0" 2382: [(set_attr "type" "fp")]) 2383: 2384: (define_insn "multf3" 2385: [(set (match_operand:TF 0 "register_operand" "=f") 2386: (mult:TF (match_operand:TF 1 "register_operand" "f") 2387: (match_operand:TF 2 "register_operand" "f")))] 2388: "TARGET_FPU" 2389: "fmulq %1,%2,%0" 2390: [(set_attr "type" "fpmul")]) 2391: 2392: (define_insn "muldf3" 2393: [(set (match_operand:DF 0 "register_operand" "=f") 2394: (mult:DF (match_operand:DF 1 "register_operand" "f") 2395: (match_operand:DF 2 "register_operand" "f")))] 2396: "TARGET_FPU" 2397: "fmuld %1,%2,%0" 2398: [(set_attr "type" "fpmul")]) 2399: 2400: (define_insn "mulsf3" 2401: [(set (match_operand:SF 0 "register_operand" "=f") 2402: (mult:SF (match_operand:SF 1 "register_operand" "f") 2403: (match_operand:SF 2 "register_operand" "f")))] 2404: "TARGET_FPU" 2405: "fmuls %1,%2,%0" 2406: [(set_attr "type" "fpmul")]) 2407: 2408: (define_insn "" 2409: [(set (match_operand:DF 0 "register_operand" "=f") 2410: (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f")) 2411: (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))] 2412: "TARGET_V8 && TARGET_FPU" 2413: "fsmuld %1,%2,%0" 2414: [(set_attr "type" "fpmul")]) 2415: 2416: (define_insn "" 2417: [(set (match_operand:TF 0 "register_operand" "=f") 2418: (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "f")) 2419: (float_extend:TF (match_operand:DF 2 "register_operand" "f"))))] 2420: "TARGET_V8 && TARGET_FPU" 2421: "fdmulq %1,%2,%0" 2422: [(set_attr "type" "fpmul")]) 2423: 2424: (define_insn "divtf3" 2425: [(set (match_operand:TF 0 "register_operand" "=f") 2426: (div:TF (match_operand:TF 1 "register_operand" "f") 2427: (match_operand:TF 2 "register_operand" "f")))] 2428: "TARGET_FPU" 2429: "fdivq %1,%2,%0" 2430: [(set_attr "type" "fpdiv")]) 2431: 2432: (define_insn "divdf3" 2433: [(set (match_operand:DF 0 "register_operand" "=f") 2434: (div:DF (match_operand:DF 1 "register_operand" "f") 2435: (match_operand:DF 2 "register_operand" "f")))] 2436: "TARGET_FPU" 2437: "fdivd %1,%2,%0" 2438: [(set_attr "type" "fpdiv")]) 2439: 2440: (define_insn "divsf3" 2441: [(set (match_operand:SF 0 "register_operand" "=f") 2442: (div:SF (match_operand:SF 1 "register_operand" "f") 2443: (match_operand:SF 2 "register_operand" "f")))] 2444: "TARGET_FPU" 2445: "fdivs %1,%2,%0" 2446: [(set_attr "type" "fpdiv")]) 2447: 2448: (define_insn "negtf2" 2449: [(set (match_operand:TF 0 "register_operand" "=f,f") 2450: (neg:TF (match_operand:TF 1 "register_operand" "0,f")))] 2451: "TARGET_FPU" 2452: "@ 2453: fnegs %0,%0 2454: fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0" 2455: [(set_attr "type" "fp") 2456: (set_attr "length" "1,4")]) 2457: 2458: (define_insn "negdf2" 2459: [(set (match_operand:DF 0 "register_operand" "=f,f") 2460: (neg:DF (match_operand:DF 1 "register_operand" "0,f")))] 2461: "TARGET_FPU" 2462: "@ 2463: fnegs %0,%0 2464: fnegs %1,%0\;fmovs %R1,%R0" 2465: [(set_attr "type" "fp") 2466: (set_attr "length" "1,2")]) 2467: 2468: (define_insn "negsf2" 2469: [(set (match_operand:SF 0 "register_operand" "=f") 2470: (neg:SF (match_operand:SF 1 "register_operand" "f")))] 2471: "TARGET_FPU" 2472: "fnegs %1,%0" 2473: [(set_attr "type" "fp")]) 2474: 2475: (define_insn "abstf2" 2476: [(set (match_operand:TF 0 "register_operand" "=f,f") 2477: (abs:TF (match_operand:TF 1 "register_operand" "0,f")))] 2478: "TARGET_FPU" 2479: "@ 2480: fabss %0,%0 2481: fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0" 2482: [(set_attr "type" "fp") 2483: (set_attr "length" "1,4")]) 2484: 2485: (define_insn "absdf2" 2486: [(set (match_operand:DF 0 "register_operand" "=f,f") 2487: (abs:DF (match_operand:DF 1 "register_operand" "0,f")))] 2488: "TARGET_FPU" 2489: "@ 2490: fabss %0,%0 2491: fabss %1,%0\;fmovs %R1,%R0" 2492: [(set_attr "type" "fp") 2493: (set_attr "length" "1,2")]) 2494: 2495: (define_insn "abssf2" 2496: [(set (match_operand:SF 0 "register_operand" "=f") 2497: (abs:SF (match_operand:SF 1 "register_operand" "f")))] 2498: "TARGET_FPU" 2499: "fabss %1,%0" 2500: [(set_attr "type" "fp")]) 2501: 2502: (define_insn "sqrttf2" 2503: [(set (match_operand:TF 0 "register_operand" "=f") 2504: (sqrt:TF (match_operand:TF 1 "register_operand" "f")))] 2505: "TARGET_FPU" 2506: "fsqrtq %1,%0" 2507: [(set_attr "type" "fpsqrt")]) 2508: 2509: (define_insn "sqrtdf2" 2510: [(set (match_operand:DF 0 "register_operand" "=f") 2511: (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] 2512: "TARGET_FPU" 2513: "fsqrtd %1,%0" 2514: [(set_attr "type" "fpsqrt")]) 2515: 2516: (define_insn "sqrtsf2" 2517: [(set (match_operand:SF 0 "register_operand" "=f") 2518: (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] 2519: "TARGET_FPU" 2520: "fsqrts %1,%0" 2521: [(set_attr "type" "fpsqrt")]) 2522: 2523: ;;- arithmetic shift instructions 2524: 2525: (define_insn "ashlsi3" 2526: [(set (match_operand:SI 0 "register_operand" "=r") 2527: (ashift:SI (match_operand:SI 1 "register_operand" "r") 2528: (match_operand:SI 2 "arith_operand" "rI")))] 2529: "" 1.1.1.2 ! root 2530: "* 1.1 root 2531: { 1.1.1.2 ! root 2532: if (GET_CODE (operands[2]) == CONST_INT ! 2533: && (unsigned) INTVAL (operands[2]) > 31) ! 2534: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); ! 2535: ! 2536: return \"sll %1,%2,%0\"; 1.1 root 2537: }") 2538: 2539: (define_insn "" 1.1.1.2 ! root 2540: [(set (reg:CC_NOOV 0) ! 2541: (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r") ! 2542: (const_int 1)) ! 2543: (const_int 0)))] ! 2544: "" ! 2545: "addcc %0,%0,%%g0" ! 2546: [(set_attr "type" "compare")]) 1.1 root 2547: 2548: (define_insn "" 1.1.1.2 ! root 2549: [(set (reg:CC_NOOV 0) ! 2550: (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r") ! 2551: (const_int 1)) ! 2552: (const_int 0))) ! 2553: (set (match_operand:SI 0 "register_operand" "=r") ! 2554: (ashift:SI (match_dup 1) (const_int 1)))] ! 2555: "" ! 2556: "addcc %1,%1,%0") 1.1 root 2557: 2558: (define_insn "ashrsi3" 2559: [(set (match_operand:SI 0 "register_operand" "=r") 2560: (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") 2561: (match_operand:SI 2 "arith_operand" "rI")))] 2562: "" 1.1.1.2 ! root 2563: "* ! 2564: { ! 2565: if (GET_CODE (operands[2]) == CONST_INT ! 2566: && (unsigned) INTVAL (operands[2]) > 31) ! 2567: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); ! 2568: ! 2569: return \"sra %1,%2,%0\"; ! 2570: }") 1.1 root 2571: 2572: (define_insn "lshrsi3" 2573: [(set (match_operand:SI 0 "register_operand" "=r") 2574: (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") 2575: (match_operand:SI 2 "arith_operand" "rI")))] 2576: "" 2577: "* 2578: { 1.1.1.2 ! root 2579: if (GET_CODE (operands[2]) == CONST_INT ! 2580: && (unsigned) INTVAL (operands[2]) > 31) ! 2581: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); 1.1 root 2582: 1.1.1.2 ! root 2583: return \"srl %1,%2,%0\"; ! 2584: }") 1.1 root 2585: 2586: ;; Unconditional and other jump instructions 2587: ;; On the Sparc, by setting the annul bit on an unconditional branch, the 2588: ;; following insn is never executed. This saves us a nop. Dbx does not 2589: ;; handle such branches though, so we only use them when optimizing. 2590: (define_insn "jump" 2591: [(set (pc) (label_ref (match_operand 0 "" "")))] 2592: "" 2593: "b%* %l0%(" 2594: [(set_attr "type" "uncond_branch")]) 2595: 2596: (define_expand "tablejump" 2597: [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "r")) 2598: (use (label_ref (match_operand 1 "" "")))])] 2599: "" 2600: " 2601: { 2602: /* We need to use the PC value in %o7 that was set up when the address 2603: of the label was loaded into a register, so we need different RTL. */ 2604: if (flag_pic) 2605: { 2606: emit_insn (gen_pic_tablejump (operands[0], operands[1])); 2607: DONE; 2608: } 2609: }") 2610: 2611: (define_insn "pic_tablejump" 2612: [(set (pc) (match_operand:SI 0 "register_operand" "r")) 2613: (use (label_ref (match_operand 1 "" ""))) 2614: (use (reg:SI 15))] 2615: "" 2616: "jmp %%o7+%0%#" 2617: [(set_attr "type" "uncond_branch")]) 2618: 2619: (define_insn "" 2620: [(set (pc) (match_operand:SI 0 "address_operand" "p")) 2621: (use (label_ref (match_operand 1 "" "")))] 2622: "" 2623: "jmp %a0%#" 2624: [(set_attr "type" "uncond_branch")]) 2625: 2626: (define_insn "" 2627: [(set (pc) (label_ref (match_operand 0 "" ""))) 2628: (set (reg:SI 15) (label_ref (match_dup 0)))] 2629: "" 2630: "call %l0%#" 2631: [(set_attr "type" "uncond_branch")]) 2632: 2633: ;; This pattern recognizes the "instruction" that appears in 2634: ;; a function call that wants a structure value, 2635: ;; to inform the called function if compiled with Sun CC. 2636: ;(define_insn "" 2637: ; [(match_operand:SI 0 "immediate_operand" "")] 2638: ; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0" 2639: ; "unimp %0" 2640: ; [(set_attr "type" "marker")]) 2641: 2642: ;;- jump to subroutine 2643: (define_expand "call" 2644: ;; Note that this expression is not used for generating RTL. 2645: ;; All the RTL is generated explicitly below. 2646: [(call (match_operand:SI 0 "call_operand" "") 2647: (match_operand 3 "" "i"))] 2648: ;; operands[2] is next_arg_register 2649: ;; operands[3] is struct_value_size_rtx. 2650: "" 2651: " 2652: { 2653: rtx fn_rtx, nregs_rtx; 2654: 2655: if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF) 2656: { 2657: /* This is really a PIC sequence. We want to represent 2658: it as a funny jump so it's delay slots can be filled. 2659: 2660: ??? But if this really *is* a CALL, will not it clobber the 2661: call-clobbered registers? We lose this if it is a JUMP_INSN. 2662: Why cannot we have delay slots filled if it were a CALL? */ 2663: 2664: if (INTVAL (operands[3]) > 0) 2665: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3, 2666: gen_rtx (SET, VOIDmode, pc_rtx, 2667: XEXP (operands[0], 0)), 2668: operands[3], 2669: gen_rtx (CLOBBER, VOIDmode, 2670: gen_rtx (REG, SImode, 15))))); 2671: else 2672: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, 2673: gen_rtx (SET, VOIDmode, pc_rtx, 2674: XEXP (operands[0], 0)), 2675: gen_rtx (CLOBBER, VOIDmode, 2676: gen_rtx (REG, SImode, 15))))); 2677: goto finish_call; 2678: } 2679: 2680: fn_rtx = operands[0]; 2681: 2682: /* Count the number of parameter registers being used by this call. 2683: if that argument is NULL, it means we are using them all, which 2684: means 6 on the sparc. */ 2685: #if 0 2686: if (operands[2]) 2687: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8); 2688: else 2689: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6); 2690: #else 2691: nregs_rtx = const0_rtx; 2692: #endif 2693: 2694: if (INTVAL (operands[3]) > 0) 2695: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3, 2696: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx), 2697: operands[3], 2698: gen_rtx (CLOBBER, VOIDmode, 2699: gen_rtx (REG, SImode, 15))))); 2700: else 2701: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, 2702: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx), 2703: gen_rtx (CLOBBER, VOIDmode, 2704: gen_rtx (REG, SImode, 15))))); 2705: 2706: finish_call: 2707: #if 0 2708: /* If this call wants a structure value, 2709: emit an unimp insn to let the called function know about this. */ 2710: if (INTVAL (operands[3]) > 0) 2711: { 2712: rtx insn = emit_insn (operands[3]); 2713: SCHED_GROUP_P (insn) = 1; 2714: } 2715: #endif 2716: 2717: DONE; 2718: }") 2719: 1.1.1.2 ! root 2720: ;; We can't use the same pattern for these two insns, because then registers ! 2721: ;; in the address may not be properly reloaded. ! 2722: ! 2723: (define_insn "" ! 2724: [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) ! 2725: (match_operand 1 "" "")) ! 2726: (clobber (reg:SI 15))] ! 2727: ;;- Do not use operand 1 for most machines. ! 2728: "" ! 2729: "* ! 2730: { ! 2731: return \"call %a0,%1%#\"; ! 2732: }" ! 2733: [(set_attr "type" "call")]) ! 2734: 1.1 root 2735: (define_insn "" 1.1.1.2 ! root 2736: [(call (mem:SI (match_operand:SI 0 "immediate_operand" "i")) 1.1 root 2737: (match_operand 1 "" "")) 2738: (clobber (reg:SI 15))] 2739: ;;- Do not use operand 1 for most machines. 2740: "" 2741: "* 2742: { 2743: return \"call %a0,%1%#\"; 2744: }" 2745: [(set_attr "type" "call")]) 2746: 2747: ;; This is a call that wants a structure value. 2748: (define_insn "" 1.1.1.2 ! root 2749: [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) ! 2750: (match_operand 1 "" "")) ! 2751: (match_operand 2 "immediate_operand" "") ! 2752: (clobber (reg:SI 15))] ! 2753: ;;- Do not use operand 1 for most machines. ! 2754: "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0" ! 2755: "* ! 2756: { ! 2757: return \"call %a0,%1\;nop\;unimp %2\"; ! 2758: }" ! 2759: [(set_attr "type" "call_no_delay_slot")]) ! 2760: ! 2761: ;; This is a call that wants a structure value. ! 2762: (define_insn "" ! 2763: [(call (mem:SI (match_operand:SI 0 "immediate_operand" "i")) 1.1 root 2764: (match_operand 1 "" "")) 2765: (match_operand 2 "immediate_operand" "") 2766: (clobber (reg:SI 15))] 2767: ;;- Do not use operand 1 for most machines. 2768: "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0" 2769: "* 2770: { 2771: return \"call %a0,%1\;nop\;unimp %2\"; 2772: }" 2773: [(set_attr "type" "call_no_delay_slot")]) 2774: 2775: (define_expand "call_value" 2776: [(set (match_operand 0 "register_operand" "=rf") 2777: (call (match_operand:SI 1 "" "") 2778: (match_operand 4 "" "")))] 2779: ;; operand 3 is next_arg_register 2780: "" 2781: " 2782: { 2783: rtx fn_rtx, nregs_rtx; 2784: rtvec vec; 2785: 2786: fn_rtx = operands[1]; 2787: 2788: #if 0 2789: if (operands[3]) 2790: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8); 2791: else 2792: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6); 2793: #else 2794: nregs_rtx = const0_rtx; 2795: #endif 2796: 2797: vec = gen_rtvec (2, 2798: gen_rtx (SET, VOIDmode, operands[0], 2799: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)), 2800: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 15))); 2801: 2802: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec)); 2803: 2804: DONE; 2805: }") 2806: 2807: (define_insn "" 2808: [(set (match_operand 0 "" "=rf") 1.1.1.2 ! root 2809: (call (mem:SI (match_operand:SI 1 "address_operand" "p")) ! 2810: (match_operand 2 "" ""))) ! 2811: (clobber (reg:SI 15))] ! 2812: ;;- Do not use operand 2 for most machines. ! 2813: "" ! 2814: "* ! 2815: { ! 2816: return \"call %a1,%2%#\"; ! 2817: }" ! 2818: [(set_attr "type" "call")]) ! 2819: ! 2820: (define_insn "" ! 2821: [(set (match_operand 0 "" "=rf") ! 2822: (call (mem:SI (match_operand:SI 1 "immediate_operand" "i")) 1.1 root 2823: (match_operand 2 "" ""))) 2824: (clobber (reg:SI 15))] 2825: ;;- Do not use operand 2 for most machines. 2826: "" 2827: "* 2828: { 2829: return \"call %a1,%2%#\"; 2830: }" 2831: [(set_attr "type" "call")]) 2832: 2833: (define_expand "untyped_call" 2834: [(parallel [(call (match_operand:SI 0 "call_operand" "") 2835: (const_int 0)) 2836: (match_operand:BLK 1 "memory_operand" "") 2837: (match_operand 2 "" "") 2838: (clobber (reg:SI 15))])] 2839: "" 2840: " 2841: { 2842: operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0)); 2843: }") 2844: 2845: ;; Make a call followed by two nops in case the function being called 2846: ;; returns a structure value and expects to skip an unimp instruction. 2847: 2848: (define_insn "" 1.1.1.2 ! root 2849: [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) ! 2850: (const_int 0)) ! 2851: (match_operand:DI 1 "memory_operand" "o") ! 2852: (match_operand 2 "" "") ! 2853: (clobber (reg:SI 15))] ! 2854: "" ! 2855: "* ! 2856: { ! 2857: operands[2] = adj_offsettable_operand (operands[1], 8); ! 2858: return \"call %a0,0\;nop\;nop\;std %%o0,%1\;std %%f0,%2\"; ! 2859: }" ! 2860: [(set_attr "type" "multi")]) ! 2861: ! 2862: ;; Make a call followed by two nops in case the function being called ! 2863: ;; returns a structure value and expects to skip an unimp instruction. ! 2864: ! 2865: (define_insn "" ! 2866: [(call (mem:SI (match_operand:SI 0 "immediate_operand" "i")) 1.1 root 2867: (const_int 0)) 2868: (match_operand:DI 1 "memory_operand" "o") 2869: (match_operand 2 "" "") 2870: (clobber (reg:SI 15))] 2871: "" 2872: "* 2873: { 2874: operands[2] = adj_offsettable_operand (operands[1], 8); 1.1.1.2 ! root 2875: return \"call %a0,0\;nop\;nop\;std %%o0,%1\;std %%f0,%2\"; 1.1 root 2876: }" 2877: [(set_attr "type" "multi")]) 2878: 2879: ;; Prepare to return any type including a structure value. 2880: 2881: (define_expand "untyped_return" 2882: [(match_operand:BLK 0 "memory_operand" "") 2883: (match_operand 1 "" "")] 2884: "" 2885: " 2886: { 2887: rtx valreg1 = gen_rtx (REG, DImode, 24); 2888: rtx valreg2 = gen_rtx (REG, DFmode, 32); 2889: rtx result = operands[0]; 2890: rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31)); 2891: rtx value = gen_reg_rtx (SImode); 2892: 2893: /* Fetch the instruction where we will return to and see if it's an unimp 2894: instruction (the most significant 10 bits will be zero). If so, 2895: update the return address to skip the unimp instruction. */ 2896: emit_move_insn (value, 2897: gen_rtx (MEM, SImode, plus_constant (rtnreg, 8))); 2898: emit_insn (gen_lshrsi3 (value, value, GEN_INT (22))); 2899: emit_insn (gen_update_return (rtnreg, value)); 2900: 2901: /* Reload the function value registers. */ 2902: emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0))); 2903: emit_move_insn (valreg2, 2904: change_address (result, DFmode, 2905: plus_constant (XEXP (result, 0), 8))); 2906: 2907: /* Put USE insns before the return. */ 2908: emit_insn (gen_rtx (USE, VOIDmode, valreg1)); 2909: emit_insn (gen_rtx (USE, VOIDmode, valreg2)); 2910: 2911: /* Construct the return. */ 2912: expand_null_return (); 2913: 2914: DONE; 2915: }") 2916: 2917: ;; This is a bit of a hack. We're incrementing a fixed register (%i7), 2918: ;; and parts of the compiler don't want to believe that the add is needed. 2919: 2920: (define_insn "update_return" 2921: [(unspec:SI [(match_operand:SI 0 "register_operand" "r") 2922: (match_operand:SI 1 "register_operand" "r")] 0)] 2923: "" 2924: "cmp %1,0\;be,a .+8\;add %0,4,%0" 2925: [(set_attr "type" "multi")]) 2926: 2927: (define_insn "return" 2928: [(return)] 2929: "! TARGET_EPILOGUE" 2930: "* return output_return (operands);" 2931: [(set_attr "type" "multi")]) 2932: 2933: (define_insn "nop" 2934: [(const_int 0)] 2935: "" 2936: "nop") 2937: 2938: (define_insn "indirect_jump" 2939: [(set (pc) (match_operand:SI 0 "address_operand" "p"))] 2940: "" 2941: "jmp %a0%#" 2942: [(set_attr "type" "uncond_branch")]) 2943: 2944: (define_expand "nonlocal_goto" 2945: [(match_operand:SI 0 "general_operand" "") 2946: (match_operand:SI 1 "general_operand" "") 2947: (match_operand:SI 2 "general_operand" "") 2948: (match_operand:SI 3 "" "")] 2949: "" 2950: " 2951: { 2952: /* Trap instruction to flush all the registers window. */ 2953: emit_insn (gen_flush_register_windows ()); 2954: /* Load the fp value for the containing fn into %fp. 2955: This is needed because operands[2] refers to %fp. 2956: Virtual register instantiation fails if the virtual %fp isn't set from a 2957: register. Thus we must copy operands[0] into a register if it isn't 2958: already one. */ 2959: if (GET_CODE (operands[0]) != REG) 2960: operands[0] = force_reg (SImode, operands[0]); 2961: emit_move_insn (virtual_stack_vars_rtx, operands[0]); 2962: /* Find the containing function's current nonlocal goto handler, 2963: which will do any cleanups and then jump to the label. */ 2964: emit_move_insn (gen_rtx (REG, SImode, 8), operands[1]); 2965: /* Restore %fp from stack pointer value for containing function. 2966: The restore insn that follows will move this to %sp, 2967: and reload the appropriate value into %fp. */ 2968: emit_move_insn (frame_pointer_rtx, operands[2]); 2969: /* Put in the static chain register the nonlocal label address. */ 2970: emit_move_insn (static_chain_rtx, operands[3]); 2971: /* USE of frame_pointer_rtx added for consistency; not clear if 2972: really needed. */ 2973: emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx)); 2974: emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); 2975: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx)); 2976: emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 8))); 2977: /* Return, restoring reg window and jumping to goto handler. */ 2978: emit_insn (gen_goto_handler_and_restore ()); 2979: DONE; 2980: }") 2981: 2982: ;; Special trap insn to flush register windows. 2983: (define_insn "flush_register_windows" 2984: [(unspec_volatile [(const_int 0)] 0)] 2985: "" 2986: "ta 3" 2987: [(set_attr "type" "misc")]) 2988: 2989: (define_insn "goto_handler_and_restore" 2990: [(unspec_volatile [(const_int 0)] 1)] 2991: "" 2992: "jmp %%o0+0\;restore" 2993: [(set_attr "type" "misc") 2994: (set_attr "length" "2")]) 1.1.1.2 ! root 2995: ! 2996: ;; Special pattern for the FLUSH instruction. ! 2997: ! 2998: (define_insn "flush" ! 2999: [(unspec_volatile [(match_operand 0 "" "")] 2)] ! 3000: "" ! 3001: "iflush %a0" ! 3002: [(set_attr "type" "misc")]) 1.1 root 3003: 3004: ;; find first set. 3005: 3006: ;; The scan instruction searches from the most significant bit while ffs 3007: ;; searches from the least significant bit. The bit index and treatment of 3008: ;; zero also differ. It takes at least 7 instructions to get the proper 3009: ;; result. Here is an obvious 8 instruction seequence. 3010: 3011: (define_insn "ffssi2" 3012: [(set (match_operand:SI 0 "register_operand" "=&r") 3013: (ffs:SI (match_operand:SI 1 "register_operand" "r"))) 3014: (clobber (match_scratch:SI 2 "=&r"))] 3015: "TARGET_SPARCLITE" 3016: "sub %%g0,%1,%0\;and %0,%1,%0\;scan %0,0,%0\;mov 32,%2\;sub %2,%0,%0\;sra %0,31,%2\;and %2,31,%2\;add %2,%0,%0" 3017: [(set_attr "type" "multi") 3018: (set_attr "length" "8")]) 3019: 3020: ;; Split up troublesome insns for better scheduling. */ 3021: 3022: ;; The following patterns are straightforward. They can be applied 3023: ;; either before or after register allocation. 3024: 3025: (define_split 3026: [(set (match_operator 0 "memop" [(match_operand:SI 1 "symbolic_operand" "")]) 3027: (match_operand 2 "reg_or_0_operand" "")) 3028: (clobber (match_operand:SI 3 "register_operand" ""))] 3029: "! flag_pic" 3030: [(set (match_dup 3) (high:SI (match_dup 1))) 3031: (set (match_op_dup 0 [(lo_sum:SI (match_dup 3) (match_dup 1))]) 3032: (match_dup 2))] 3033: "") 3034: 3035: (define_split 3036: [(set (match_operator 0 "memop" 3037: [(match_operand:SI 1 "immediate_operand" "")]) 3038: (match_operand 2 "general_operand" "")) 3039: (clobber (match_operand:SI 3 "register_operand" ""))] 3040: "flag_pic" 3041: [(set (match_op_dup 0 [(match_dup 1)]) 3042: (match_dup 2))] 3043: " 3044: { 3045: operands[1] = legitimize_pic_address (operands[1], GET_MODE (operands[0]), 1.1.1.2 ! root 3046: operands[3]); 1.1 root 3047: }") 3048: 3049: (define_split 3050: [(set (match_operand 0 "register_operand" "") 3051: (match_operator 1 "memop" 3052: [(match_operand:SI 2 "immediate_operand" "")]))] 3053: "flag_pic" 3054: [(set (match_dup 0) 3055: (match_op_dup 1 [(match_dup 2)]))] 3056: " 3057: { 3058: operands[2] = legitimize_pic_address (operands[2], GET_MODE (operands[1]), 1.1.1.2 ! root 3059: operands[0]); 1.1 root 3060: }") 3061: 3062: ;; Sign- and Zero-extend operations can have symbolic memory operands. 3063: 3064: (define_split 3065: [(set (match_operand 0 "register_operand" "") 3066: (match_operator 1 "extend_op" 3067: [(match_operator 2 "memop" 3068: [(match_operand:SI 3 "immediate_operand" "")])]))] 3069: "flag_pic" 3070: [(set (match_dup 0) 3071: (match_op_dup 1 [(match_op_dup 2 [(match_dup 3)])]))] 3072: " 3073: { 3074: operands[3] = legitimize_pic_address (operands[3], GET_MODE (operands[2]), 1.1.1.2 ! root 3075: operands[0]); 1.1 root 3076: }") 3077: 3078: (define_split 3079: [(set (match_operand:SI 0 "register_operand" "") 3080: (match_operand:SI 1 "immediate_operand" ""))] 3081: "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF 3082: || GET_CODE (operands[1]) == CONST 3083: || GET_CODE (operands[1]) == LABEL_REF)" 3084: [(set (match_dup 0) (high:SI (match_dup 1))) 3085: (set (match_dup 0) 3086: (lo_sum:SI (match_dup 0) (match_dup 1)))] 3087: "") 3088: 3089: ;; LABEL_REFs are not modified by `legitimize_pic_address` 3090: ;; so do not recurse infinitely in the PIC case. 3091: (define_split 3092: [(set (match_operand:SI 0 "register_operand" "") 3093: (match_operand:SI 1 "immediate_operand" ""))] 3094: "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF 3095: || GET_CODE (operands[1]) == CONST)" 3096: [(set (match_dup 0) (match_dup 1))] 3097: " 3098: { 1.1.1.2 ! root 3099: operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]); 1.1 root 3100: }") 3101: 3102: ;; These split sne/seq insns. The forms of the resulting insns are 3103: ;; somewhat bogus, but they avoid extra patterns and show data dependency. 3104: ;; Nothing will look at these in detail after splitting has occurred. 3105: 3106: (define_split 3107: [(set (match_operand:SI 0 "register_operand" "") 3108: (ne:SI (match_operand:SI 1 "register_operand" "") (const_int 0))) 3109: (clobber (reg:CC 0))] 3110: "" 3111: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 3112: (const_int 0))) 3113: (set (match_dup 0) (ltu:SI (reg:CC 0) (const_int 0)))] 3114: "") 3115: 3116: (define_split 3117: [(set (match_operand:SI 0 "register_operand" "") 3118: (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "") 3119: (const_int 0)))) 3120: (clobber (reg:CC 0))] 3121: "" 3122: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 3123: (const_int 0))) 3124: (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))] 3125: "") 3126: 3127: (define_split 3128: [(set (match_operand:SI 0 "register_operand" "") 3129: (eq:SI (match_operand:SI 1 "register_operand" "") (const_int 0))) 3130: (clobber (reg:CC 0))] 3131: "" 3132: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 3133: (const_int 0))) 3134: (set (match_dup 0) (geu:SI (reg:CC 0) (const_int 0)))] 3135: "") 3136: 3137: (define_split 3138: [(set (match_operand:SI 0 "register_operand" "") 3139: (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "") 3140: (const_int 0)))) 3141: (clobber (reg:CC 0))] 3142: "" 3143: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 3144: (const_int 0))) 3145: (set (match_dup 0) (neg:SI (geu:SI (reg:CC 0) (const_int 0))))] 3146: "") 3147: 3148: (define_split 3149: [(set (match_operand:SI 0 "register_operand" "") 3150: (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "") 3151: (const_int 0)) 3152: (match_operand:SI 2 "register_operand" ""))) 3153: (clobber (reg:CC 0))] 3154: "" 3155: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 3156: (const_int 0))) 3157: (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 3158: (match_dup 2)))] 3159: "") 3160: 3161: (define_split 3162: [(set (match_operand:SI 0 "register_operand" "") 3163: (minus:SI (match_operand:SI 2 "register_operand" "") 3164: (ne:SI (match_operand:SI 1 "register_operand" "") 3165: (const_int 0)))) 3166: (clobber (reg:CC 0))] 3167: "" 3168: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 3169: (const_int 0))) 3170: (set (match_dup 0) (minus:SI (match_dup 2) 3171: (ltu:SI (reg:CC 0) (const_int 0))))] 3172: "") 3173: 3174: (define_split 3175: [(set (match_operand:SI 0 "register_operand" "") 3176: (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "") 3177: (const_int 0)) 3178: (match_operand:SI 2 "register_operand" ""))) 3179: (clobber (reg:CC 0))] 3180: "" 3181: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 3182: (const_int 0))) 3183: (set (match_dup 0) (plus:SI (geu:SI (reg:CC 0) (const_int 0)) 3184: (match_dup 2)))] 3185: "") 3186: 3187: (define_split 3188: [(set (match_operand:SI 0 "register_operand" "") 3189: (minus:SI (match_operand:SI 2 "register_operand" "") 3190: (eq:SI (match_operand:SI 1 "register_operand" "") 3191: (const_int 0)))) 3192: (clobber (reg:CC 0))] 3193: "" 3194: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 3195: (const_int 0))) 3196: (set (match_dup 0) (minus:SI (match_dup 2) 3197: (geu:SI (reg:CC 0) (const_int 0))))] 3198: "") 3199: 3200: ;; Peepholes go at the end. 3201: 3202: ;; Optimize consecutive loads or stores into ldd and std when possible. 3203: ;; The conditions in which we do this are very restricted and are 3204: ;; explained in the code for {registers,memory}_ok_for_ldd functions. 3205: 3206: (define_peephole 3207: [(set (match_operand:SI 0 "register_operand" "=rf") 3208: (match_operand:SI 1 "memory_operand" "")) 3209: (set (match_operand:SI 2 "register_operand" "=rf") 3210: (match_operand:SI 3 "memory_operand" ""))] 3211: "registers_ok_for_ldd_peep (operands[0], operands[2]) 3212: && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) 3213: && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" 3214: "ldd %1,%0") 3215: 3216: (define_peephole 3217: [(set (match_operand:SI 0 "memory_operand" "") 3218: (match_operand:SI 1 "register_operand" "rf")) 3219: (set (match_operand:SI 2 "memory_operand" "") 3220: (match_operand:SI 3 "register_operand" "rf"))] 3221: "registers_ok_for_ldd_peep (operands[1], operands[3]) 3222: && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) 3223: && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" 3224: "std %1,%0") 3225: 3226: (define_peephole 3227: [(set (match_operand:SF 0 "register_operand" "=fr") 3228: (match_operand:SF 1 "memory_operand" "")) 3229: (set (match_operand:SF 2 "register_operand" "=fr") 3230: (match_operand:SF 3 "memory_operand" ""))] 3231: "registers_ok_for_ldd_peep (operands[0], operands[2]) 3232: && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) 3233: && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" 3234: "ldd %1,%0") 3235: 3236: (define_peephole 3237: [(set (match_operand:SF 0 "memory_operand" "") 3238: (match_operand:SF 1 "register_operand" "fr")) 3239: (set (match_operand:SF 2 "memory_operand" "") 3240: (match_operand:SF 3 "register_operand" "fr"))] 3241: "registers_ok_for_ldd_peep (operands[1], operands[3]) 3242: && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) 3243: && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" 3244: "std %1,%0") 3245: 3246: (define_peephole 3247: [(set (match_operand:SI 0 "register_operand" "=rf") 3248: (match_operand:SI 1 "memory_operand" "")) 3249: (set (match_operand:SI 2 "register_operand" "=rf") 3250: (match_operand:SI 3 "memory_operand" ""))] 3251: "registers_ok_for_ldd_peep (operands[2], operands[0]) 3252: && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) 3253: && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" 3254: "ldd %3,%2") 3255: 3256: (define_peephole 3257: [(set (match_operand:SI 0 "memory_operand" "") 3258: (match_operand:SI 1 "register_operand" "rf")) 3259: (set (match_operand:SI 2 "memory_operand" "") 3260: (match_operand:SI 3 "register_operand" "rf"))] 3261: "registers_ok_for_ldd_peep (operands[3], operands[1]) 3262: && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) 3263: && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 3264: "std %3,%2") 3265: 3266: (define_peephole 3267: [(set (match_operand:SF 0 "register_operand" "=fr") 3268: (match_operand:SF 1 "memory_operand" "")) 3269: (set (match_operand:SF 2 "register_operand" "=fr") 3270: (match_operand:SF 3 "memory_operand" ""))] 3271: "registers_ok_for_ldd_peep (operands[2], operands[0]) 3272: && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) 3273: && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" 3274: "ldd %3,%2") 3275: 3276: (define_peephole 3277: [(set (match_operand:SF 0 "memory_operand" "") 3278: (match_operand:SF 1 "register_operand" "fr")) 3279: (set (match_operand:SF 2 "memory_operand" "") 3280: (match_operand:SF 3 "register_operand" "fr"))] 3281: "registers_ok_for_ldd_peep (operands[3], operands[1]) 3282: && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) 3283: && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 3284: "std %3,%2") 3285: 3286: ;; Optimize the case of following a reg-reg move with a test 3287: ;; of reg just moved. Don't allow floating point regs for operand 0 or 1. 3288: ;; This can result from a float to fix conversion. 3289: 3290: (define_peephole 3291: [(set (match_operand:SI 0 "register_operand" "=r") 3292: (match_operand:SI 1 "register_operand" "r")) 3293: (set (reg:CC 0) 3294: (compare:CC (match_operand:SI 2 "register_operand" "r") 3295: (const_int 0)))] 3296: "(rtx_equal_p (operands[2], operands[0]) 3297: || rtx_equal_p (operands[2], operands[1])) 3298: && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" 3299: "orcc %1,%%g0,%0") 3300: 3301: ;; Do {sign,zero}-extended compares somewhat more efficiently. 3302: ;; ??? Is this now the Right Way to do this? Or will SCRATCH 3303: ;; eventually have some impact here? 3304: 3305: (define_peephole 3306: [(set (match_operand:HI 0 "register_operand" "") 3307: (match_operand:HI 1 "memory_operand" "")) 3308: (set (match_operand:SI 2 "register_operand" "") 3309: (sign_extend:SI (match_dup 0))) 3310: (set (reg:CC 0) 3311: (compare:CC (match_dup 2) 3312: (const_int 0)))] 3313: "" 3314: "ldsh %1,%0\;orcc %0,%%g0,%2") 3315: 3316: (define_peephole 3317: [(set (match_operand:QI 0 "register_operand" "") 3318: (match_operand:QI 1 "memory_operand" "")) 3319: (set (match_operand:SI 2 "register_operand" "") 3320: (sign_extend:SI (match_dup 0))) 3321: (set (reg:CC 0) 3322: (compare:CC (match_dup 2) 3323: (const_int 0)))] 3324: "" 3325: "ldsb %1,%0\;orcc %0,%%g0,%2") 3326: 3327: (define_peephole 3328: [(set (match_operand:HI 0 "register_operand" "") 3329: (match_operand:HI 1 "memory_operand" "")) 3330: (set (match_operand:SI 2 "register_operand" "") 3331: (sign_extend:SI (match_dup 0)))] 3332: "dead_or_set_p (insn, operands[0])" 3333: "* 3334: { 3335: warning (\"bad peephole\"); 3336: if (! MEM_VOLATILE_P (operands[1])) 3337: abort (); 3338: return \"ldsh %1,%2\"; 3339: }") 3340: 3341: (define_peephole 3342: [(set (match_operand:QI 0 "register_operand" "") 3343: (match_operand:QI 1 "memory_operand" "")) 3344: (set (match_operand:SI 2 "register_operand" "") 3345: (sign_extend:SI (match_dup 0)))] 3346: "dead_or_set_p (insn, operands[0])" 3347: "* 3348: { 3349: warning (\"bad peephole\"); 3350: if (! MEM_VOLATILE_P (operands[1])) 3351: abort (); 3352: return \"ldsb %1,%2\"; 3353: }") 3354: 3355: ;; Floating-point move peepholes 3356: 3357: (define_peephole 3358: [(set (match_operand:SI 0 "register_operand" "=r") 3359: (lo_sum:SI (match_dup 0) 3360: (match_operand:SI 1 "immediate_operand" "i"))) 3361: (set (match_operand:DF 2 "register_operand" "=fr") 3362: (mem:DF (match_dup 0)))] 3363: "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)" 3364: "* 3365: { 3366: /* Go by way of output_move_double in case the register in operand 2 3367: is not properly aligned for ldd. */ 3368: operands[1] = gen_rtx (MEM, DFmode, 3369: gen_rtx (LO_SUM, SImode, operands[0], operands[1])); 3370: operands[0] = operands[2]; 3371: return output_move_double (operands); 3372: }") 3373: 3374: (define_peephole 3375: [(set (match_operand:SI 0 "register_operand" "=r") 3376: (lo_sum:SI (match_dup 0) 3377: (match_operand:SI 1 "immediate_operand" "i"))) 3378: (set (match_operand:SF 2 "register_operand" "=fr") 3379: (mem:SF (match_dup 0)))] 3380: "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)" 3381: "ld [%0+%%lo(%a1)],%2") 3382: 3383: ;; Return peepholes. First the "normal" ones 3384: 3385: ;; ??? There are QImode, HImode, and SImode versions of this pattern. 3386: ;; It might be possible to write one more general pattern instead of three. 3387: 3388: (define_insn "" 3389: [(set (match_operand:QI 0 "restore_operand" "") 3390: (match_operand:QI 1 "arith_operand" "rI")) 3391: (return)] 3392: "! TARGET_EPILOGUE" 3393: "* 3394: { 3395: if (current_function_returns_struct) 3396: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; 3397: else 3398: return \"ret\;restore %%g0,%1,%Y0\"; 3399: }" 3400: [(set_attr "type" "multi")]) 3401: 3402: (define_insn "" 3403: [(set (match_operand:HI 0 "restore_operand" "") 3404: (match_operand:HI 1 "arith_operand" "rI")) 3405: (return)] 3406: "! TARGET_EPILOGUE" 3407: "* 3408: { 3409: if (current_function_returns_struct) 3410: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; 3411: else 3412: return \"ret\;restore %%g0,%1,%Y0\"; 3413: }" 3414: [(set_attr "type" "multi")]) 3415: 3416: (define_insn "" 3417: [(set (match_operand:SI 0 "restore_operand" "") 3418: (match_operand:SI 1 "arith_operand" "rI")) 3419: (return)] 3420: "! TARGET_EPILOGUE" 3421: "* 3422: { 3423: if (current_function_returns_struct) 3424: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; 3425: else 3426: return \"ret\;restore %%g0,%1,%Y0\"; 3427: }" 3428: [(set_attr "type" "multi")]) 3429: 3430: ;; The following pattern is only generated by delayed-branch scheduling, 3431: ;; when the insn winds up in the epilogue. This can only happen when 3432: ;; ! TARGET_FPU because otherwise fp return values are in %f0. 3433: (define_insn "" 3434: [(set (match_operand:SF 0 "restore_operand" "r") 3435: (match_operand:SF 1 "register_operand" "r")) 3436: (return)] 3437: "! TARGET_FPU && ! TARGET_EPILOGUE" 3438: "* 3439: { 3440: if (current_function_returns_struct) 3441: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; 3442: else 3443: return \"ret\;restore %%g0,%1,%Y0\"; 3444: }" 3445: [(set_attr "type" "multi")]) 3446: 3447: (define_insn "" 3448: [(set (match_operand:SI 0 "restore_operand" "") 3449: (plus:SI (match_operand:SI 1 "arith_operand" "%r") 3450: (match_operand:SI 2 "arith_operand" "rI"))) 3451: (return)] 3452: "! TARGET_EPILOGUE" 3453: "* 3454: { 3455: if (current_function_returns_struct) 3456: return \"jmp %%i7+12\;restore %r1,%2,%Y0\"; 3457: else 3458: return \"ret\;restore %r1,%2,%Y0\"; 3459: }" 3460: [(set_attr "type" "multi")]) 3461: 3462: ;; Turned off because it should never match (subtracting a constant 3463: ;; is turned into addition) and because it would do the wrong thing 3464: ;; when operand 2 is -4096 (--4096 == 4096 is not a valid immediate). 3465: ;;(define_insn "" 3466: ;; [(set (match_operand:SI 0 "restore_operand" "") 3467: ;; (minus:SI (match_operand:SI 1 "register_operand" "r") 3468: ;; (match_operand:SI 2 "small_int" "I"))) 3469: ;; (return)] 3470: ;; "! TARGET_EPILOGUE" 3471: ;; "ret\;restore %1,-(%2),%Y0" 3472: ;; [(set_attr "type" "multi")]) 3473: 3474: ;; The following pattern is only generated by delayed-branch scheduling, 3475: ;; when the insn winds up in the epilogue. 3476: (define_insn "" 3477: [(set (reg:SF 32) 3478: (match_operand:SF 0 "register_operand" "f")) 3479: (return)] 3480: "! TARGET_EPILOGUE" 3481: "ret\;fmovs %0,%%f0" 3482: [(set_attr "type" "multi")]) 3483: 3484: ;; Now peepholes to go a call followed by a jump. 3485: 3486: (define_peephole 3487: [(parallel [(set (match_operand 0 "" "") 1.1.1.2 ! root 3488: (call (mem:SI (match_operand:SI 1 "call_operand_address" "pi")) 1.1 root 3489: (match_operand 2 "" ""))) 3490: (clobber (reg:SI 15))]) 3491: (set (pc) (label_ref (match_operand 3 "" "")))] 3492: "short_branch (INSN_UID (insn), INSN_UID (operands[3]))" 3493: "* 3494: { 3495: return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\"; 3496: }") 3497: 3498: (define_peephole 1.1.1.2 ! root 3499: [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "pi")) 1.1 root 3500: (match_operand 1 "" "")) 3501: (clobber (reg:SI 15))]) 3502: (set (pc) (label_ref (match_operand 2 "" "")))] 3503: "short_branch (INSN_UID (insn), INSN_UID (operands[2]))" 3504: "* 3505: { 3506: return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\"; 3507: }") 3508: 3509: (define_peephole 3510: [(parallel [(set (match_operand:SI 0 "register_operand" "=r") 3511: (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") 3512: (reg:SI 0))) 3513: (clobber (reg:CC 0))]) 3514: (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))] 3515: "" 3516: "subxcc %r1,0,%0")
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.