|
|
1.1 ! root 1: ;;- Machine description for SPARC chip for GNU C compiler ! 2: ;; Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc. ! 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: ! 775: (define_expand "movqi" ! 776: [(set (match_operand:QI 0 "general_operand" "") ! 777: (match_operand:QI 1 "general_operand" ""))] ! 778: "" ! 779: " ! 780: { ! 781: if (emit_move_sequence (operands, QImode)) ! 782: DONE; ! 783: }") ! 784: ! 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" ""))] ! 819: "" ! 820: " ! 821: { ! 822: if (emit_move_sequence (operands, HImode)) ! 823: DONE; ! 824: }") ! 825: ! 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; ! 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: ! 980: ;; ??? Can the next two be moved above the PIC stuff? ! 981: ! 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: ! 1001: (define_expand "movdi" ! 1002: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") ! 1003: (match_operand:DI 1 "general_operand" ""))] ! 1004: "" ! 1005: " ! 1006: { ! 1007: if (emit_move_sequence (operands, DImode)) ! 1008: DONE; ! 1009: }") ! 1010: ! 1011: (define_insn "" ! 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) ! 1016: || operands[1] == const0_rtx" ! 1017: "* ! 1018: { ! 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")]) ! 1025: ! 1026: (define_insn "" ! 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")))] ! 1030: "" ! 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". ! 1041: [(set_attr "length" "1")]) ! 1042: ! 1043: ;; ??? There's no symbolic (set (mem:DI ...) ...). ! 1044: ! 1045: ;; Block move insns. ! 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: ! 1096: ;; This pattern forces (set (reg:SF ...) (const_double ...)) ! 1097: ;; to be reloaded by putting the constant into memory. ! 1098: ;; It must come before the more general movsf pattern. ! 1099: (define_insn "" ! 1100: [(set (match_operand:SF 0 "general_operand" "=?r,f,m") ! 1101: (match_operand:SF 1 "" "?E,m,G"))] ! 1102: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" ! 1103: "* ! 1104: { ! 1105: switch (which_alternative) ! 1106: { ! 1107: case 0: ! 1108: return singlemove_string (operands); ! 1109: case 1: ! 1110: return \"ld %1,%0\"; ! 1111: case 2: ! 1112: return \"st %%g0,%0\"; ! 1113: } ! 1114: }" ! 1115: [(set_attr "type" "load,fpload,store") ! 1116: (set_attr "length" "2,1,1")]) ! 1117: ! 1118: (define_expand "movsf" ! 1119: [(set (match_operand:SF 0 "general_operand" "") ! 1120: (match_operand:SF 1 "general_operand" ""))] ! 1121: "" ! 1122: " ! 1123: { ! 1124: if (emit_move_sequence (operands, SFmode)) ! 1125: DONE; ! 1126: }") ! 1127: ! 1128: (define_insn "" ! 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"))] ! 1131: "TARGET_FPU ! 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")]) ! 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 "" ! 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"))] ! 1150: "! TARGET_FPU ! 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")]) ! 1158: ! 1159: (define_insn "" ! 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"))] ! 1163: "" ! 1164: "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" ! 1165: [(set_attr "type" "store") ! 1166: (set_attr "length" "2")]) ! 1167: ! 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: { ! 1198: if (emit_move_sequence (operands, DFmode)) ! 1199: DONE; ! 1200: }") ! 1201: ! 1202: (define_insn "" ! 1203: [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,f,r,Q,Q,f,r") ! 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: ! 1259: ;; This pattern forces (set (reg:TF ...) (const_double ...)) ! 1260: ;; to be reloaded by putting the constant into memory. ! 1261: ;; It must come before the more general movtf pattern. ! 1262: (define_insn "" ! 1263: [(set (match_operand:TF 0 "general_operand" "=?r,f,o") ! 1264: (match_operand:TF 1 "" "?E,m,G"))] ! 1265: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" ! 1266: "* ! 1267: { ! 1268: switch (which_alternative) ! 1269: { ! 1270: case 0: ! 1271: return output_move_quad (operands); ! 1272: case 1: ! 1273: return output_fp_move_quad (operands); ! 1274: case 2: ! 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\"; ! 1279: } ! 1280: }" ! 1281: [(set_attr "type" "load,fpload,store") ! 1282: (set_attr "length" "5,5,5")]) ! 1283: ! 1284: (define_expand "movtf" ! 1285: [(set (match_operand:TF 0 "general_operand" "") ! 1286: (match_operand:TF 1 "general_operand" ""))] ! 1287: "" ! 1288: " ! 1289: { ! 1290: if (emit_move_sequence (operands, TFmode)) ! 1291: DONE; ! 1292: }") ! 1293: ! 1294: (define_insn "" ! 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"))] ! 1297: "TARGET_FPU ! 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")]) ! 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 "" ! 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"))] ! 1316: "! TARGET_FPU ! 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")]) ! 1327: ! 1328: (define_insn "" ! 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"))] ! 1332: "" ! 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: }" ! 1341: [(set_attr "type" "store") ! 1342: (set_attr "length" "5")]) ! 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); ! 1358: int op1_subword = 0; ! 1359: ! 1360: if (GET_CODE (operand1) == SUBREG) ! 1361: { ! 1362: op1_subword = SUBREG_WORD (operand1); ! 1363: operand1 = XEXP (operand1, 0); ! 1364: } ! 1365: ! 1366: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, ! 1367: op1_subword), ! 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); ! 1464: int op1_subword = 0; ! 1465: ! 1466: if (GET_CODE (operand1) == SUBREG) ! 1467: { ! 1468: op1_subword = SUBREG_WORD (operand1); ! 1469: operand1 = XEXP (operand1, 0); ! 1470: } ! 1471: ! 1472: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, ! 1473: op1_subword), ! 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); ! 1494: int op1_subword = 0; ! 1495: int op0_subword = 0; ! 1496: ! 1497: if (GET_CODE (operand1) == SUBREG) ! 1498: { ! 1499: op1_subword = SUBREG_WORD (operand1); ! 1500: operand1 = XEXP (operand1, 0); ! 1501: } ! 1502: if (GET_CODE (operand0) == SUBREG) ! 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), ! 1509: shift_24)); ! 1510: if (GET_MODE (operand0) != SImode) ! 1511: operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword); ! 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); ! 1531: int op1_subword = 0; ! 1532: ! 1533: if (GET_CODE (operand1) == SUBREG) ! 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), ! 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" "")) ! 1843: (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))] ! 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")) ! 1867: (match_operand:SI 2 "uns_small_int" "")))] ! 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")]) ! 1918: ! 1919: ;;- Boolean instructions ! 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: "" ! 2530: "* ! 2531: { ! 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\"; ! 2537: }") ! 2538: ! 2539: (define_insn "" ! 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")]) ! 2547: ! 2548: (define_insn "" ! 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") ! 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: "" ! 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: }") ! 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: { ! 2579: if (GET_CODE (operands[2]) == CONST_INT ! 2580: && (unsigned) INTVAL (operands[2]) > 31) ! 2581: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); ! 2582: ! 2583: return \"srl %1,%2,%0\"; ! 2584: }") ! 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: ! 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: ! 2735: (define_insn "" ! 2736: [(call (mem:SI (match_operand:SI 0 "immediate_operand" "i")) ! 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 "" ! 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")) ! 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") ! 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")) ! 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 "" ! 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")) ! 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); ! 2875: return \"call %a0,0\;nop\;nop\;std %%o0,%1\;std %%f0,%2\"; ! 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")]) ! 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")]) ! 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]), ! 3046: operands[3]); ! 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]), ! 3059: operands[0]); ! 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]), ! 3075: operands[0]); ! 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: { ! 3099: operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]); ! 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 "" "") ! 3488: (call (mem:SI (match_operand:SI 1 "call_operand_address" "pi")) ! 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 ! 3499: [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "pi")) ! 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.