|
|
1.1 ! root 1: ;;- Machine description for SPARC chip for GNU C compiler ! 2: ;; Copyright (C) 1987, 1988, 1989, 1992 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 "movsi" ! 776: [(set (match_operand:SI 0 "general_operand" "") ! 777: (match_operand:SI 1 "general_operand" ""))] ! 778: "" ! 779: " ! 780: { ! 781: if (emit_move_sequence (operands, SImode, NULL_RTX)) ! 782: DONE; ! 783: }") ! 784: ! 785: (define_expand "reload_insi" ! 786: [(set (match_operand:SI 0 "register_operand" "=r") ! 787: (match_operand:SI 1 "general_operand" "")) ! 788: (clobber (match_operand:SI 2 "register_operand" "=&r"))] ! 789: "" ! 790: " ! 791: { ! 792: if (emit_move_sequence (operands, SImode, operands[2])) ! 793: DONE; ! 794: ! 795: /* We don't want the clobber emitted, so handle this ourselves. */ ! 796: emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); ! 797: DONE; ! 798: }") ! 799: ! 800: ;; We must support both 'r' and 'f' registers here, because combine may ! 801: ;; convert SFmode hard registers to SImode hard registers when simplifying ! 802: ;; subreg sets. ! 803: ! 804: ;; We cannot combine the similar 'r' and 'f' constraints, because it causes ! 805: ;; problems with register allocation. Reload might try to put an integer ! 806: ;; in an fp register, or an fp number is an integer register. ! 807: ! 808: (define_insn "" ! 809: [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q") ! 810: (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))] ! 811: "register_operand (operands[0], SImode) ! 812: || register_operand (operands[1], SImode) ! 813: || operands[1] == const0_rtx" ! 814: "@ ! 815: mov %1,%0 ! 816: fmovs %1,%0 ! 817: sethi %%hi(%a1),%0 ! 818: ld %1,%0 ! 819: ld %1,%0 ! 820: st %r1,%0 ! 821: st %r1,%0" ! 822: [(set_attr "type" "move,fp,move,load,load,store,store") ! 823: (set_attr "length" "*,*,1,*,*,*,*")]) ! 824: ! 825: ;; Special pic pattern, for loading the address of a label into a register. ! 826: ;; It clobbers o7 because the call puts the return address (i.e. pc value) ! 827: ;; there. ! 828: ! 829: (define_insn "" ! 830: [(set (match_operand:SI 0 "register_operand" "=r") ! 831: (match_operand:SI 1 "move_pic_label" "i")) ! 832: (set (reg:SI 15) (pc))] ! 833: "" ! 834: "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0" ! 835: [(set_attr "type" "multi") ! 836: (set_attr "length" "4")]) ! 837: ! 838: (define_insn "" ! 839: [(set (match_operand:DI 0 "register_operand" "=r") ! 840: (high:DI (match_operand 1 "" "")))] ! 841: "check_pic (1)" ! 842: "* ! 843: { ! 844: rtx op0 = operands[0]; ! 845: rtx op1 = operands[1]; ! 846: ! 847: if (GET_CODE (op1) == CONST_INT) ! 848: { ! 849: operands[0] = operand_subword (op0, 1, 0, DImode); ! 850: output_asm_insn (\"sethi %%hi(%a1),%0\", operands); ! 851: ! 852: operands[0] = operand_subword (op0, 0, 0, DImode); ! 853: if (INTVAL (op1) < 0) ! 854: return \"mov -1,%0\"; ! 855: else ! 856: return \"mov 0,%0\"; ! 857: } ! 858: else if (GET_CODE (op1) == CONST_DOUBLE) ! 859: { ! 860: operands[0] = operand_subword (op0, 1, 0, DImode); ! 861: operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1)); ! 862: output_asm_insn (\"sethi %%hi(%a1),%0\", operands); ! 863: ! 864: operands[0] = operand_subword (op0, 0, 0, DImode); ! 865: operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1)); ! 866: return singlemove_string (operands); ! 867: } ! 868: else ! 869: abort (); ! 870: return \"\"; ! 871: }" ! 872: [(set_attr "type" "move") ! 873: (set_attr "length" "2")]) ! 874: ! 875: ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't ! 876: ;; confuse them with real addresses. ! 877: (define_insn "" ! 878: [(set (match_operand:SI 0 "register_operand" "=r") ! 879: (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))] ! 880: "check_pic (1)" ! 881: "sethi %%hi(%a1),%0" ! 882: [(set_attr "type" "move") ! 883: (set_attr "length" "1")]) ! 884: ! 885: (define_insn "" ! 886: [(set (match_operand:SI 0 "register_operand" "=r") ! 887: (high:SI (match_operand 1 "" "")))] ! 888: "check_pic (1)" ! 889: "sethi %%hi(%a1),%0" ! 890: [(set_attr "type" "move") ! 891: (set_attr "length" "1")]) ! 892: ! 893: (define_insn "" ! 894: [(set (match_operand:HI 0 "register_operand" "=r") ! 895: (high:HI (match_operand 1 "" "")))] ! 896: "check_pic (1)" ! 897: "sethi %%hi(%a1),%0" ! 898: [(set_attr "type" "move") ! 899: (set_attr "length" "1")]) ! 900: ! 901: (define_insn "" ! 902: [(set (match_operand:DI 0 "register_operand" "=r") ! 903: (lo_sum:DI (match_operand:DI 1 "register_operand" "0") ! 904: (match_operand:DI 2 "immediate_operand" "in")))] ! 905: "" ! 906: "* ! 907: { ! 908: /* Don't output a 64 bit constant, since we can't trust the assembler to ! 909: handle it correctly. */ ! 910: if (GET_CODE (operands[2]) == CONST_DOUBLE) ! 911: operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2])); ! 912: return \"or %R1,%%lo(%a2),%R0\"; ! 913: }" ! 914: ;; Need to set length for this arith insn because operand2 ! 915: ;; is not an "arith_operand". ! 916: [(set_attr "length" "1")]) ! 917: ! 918: ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't ! 919: ;; confuse them with real addresses. ! 920: (define_insn "" ! 921: [(set (match_operand:SI 0 "register_operand" "=r") ! 922: (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 923: (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))] ! 924: "" ! 925: "or %1,%%lo(%a2),%0" ! 926: ;; Need to set length for this arith insn because operand2 ! 927: ;; is not an "arith_operand". ! 928: [(set_attr "length" "1")]) ! 929: ! 930: (define_insn "" ! 931: [(set (match_operand:SI 0 "register_operand" "=r") ! 932: (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 933: (match_operand:SI 2 "immediate_operand" "in")))] ! 934: "" ! 935: "or %1,%%lo(%a2),%0" ! 936: ;; Need to set length for this arith insn because operand2 ! 937: ;; is not an "arith_operand". ! 938: [(set_attr "length" "1")]) ! 939: ! 940: (define_insn "" ! 941: [(set (mem:SI (match_operand:SI 0 "symbolic_operand" "")) ! 942: (match_operand:SI 1 "reg_or_0_operand" "rJ")) ! 943: (clobber (match_scratch:SI 2 "=&r"))] ! 944: "" ! 945: "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" ! 946: [(set_attr "type" "store") ! 947: (set_attr "length" "2")]) ! 948: ! 949: (define_expand "movhi" ! 950: [(set (match_operand:HI 0 "general_operand" "") ! 951: (match_operand:HI 1 "general_operand" ""))] ! 952: "" ! 953: " ! 954: { ! 955: if (emit_move_sequence (operands, HImode, NULL_RTX)) ! 956: DONE; ! 957: }") ! 958: ! 959: (define_insn "" ! 960: [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") ! 961: (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))] ! 962: "register_operand (operands[0], HImode) ! 963: || register_operand (operands[1], HImode) ! 964: || operands[1] == const0_rtx" ! 965: "@ ! 966: mov %1,%0 ! 967: sethi %%hi(%a1),%0 ! 968: lduh %1,%0 ! 969: sth %r1,%0" ! 970: [(set_attr "type" "move,move,load,store") ! 971: (set_attr "length" "*,1,*,1")]) ! 972: ! 973: (define_insn "" ! 974: [(set (match_operand:HI 0 "register_operand" "=r") ! 975: (lo_sum:HI (match_operand:HI 1 "register_operand" "r") ! 976: (match_operand 2 "immediate_operand" "in")))] ! 977: "" ! 978: "or %1,%%lo(%a2),%0" ! 979: [(set_attr "length" "1")]) ! 980: ! 981: (define_insn "" ! 982: [(set (mem:HI (match_operand:SI 0 "symbolic_operand" "")) ! 983: (match_operand:HI 1 "reg_or_0_operand" "rJ")) ! 984: (clobber (match_scratch:SI 2 "=&r"))] ! 985: "" ! 986: "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]" ! 987: [(set_attr "type" "store") ! 988: (set_attr "length" "2")]) ! 989: ! 990: (define_expand "movqi" ! 991: [(set (match_operand:QI 0 "general_operand" "") ! 992: (match_operand:QI 1 "general_operand" ""))] ! 993: "" ! 994: " ! 995: { ! 996: if (emit_move_sequence (operands, QImode, NULL_RTX)) ! 997: DONE; ! 998: }") ! 999: ! 1000: (define_insn "" ! 1001: [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") ! 1002: (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))] ! 1003: "register_operand (operands[0], QImode) ! 1004: || register_operand (operands[1], QImode) ! 1005: || operands[1] == const0_rtx" ! 1006: "@ ! 1007: mov %1,%0 ! 1008: sethi %%hi(%a1),%0 ! 1009: ldub %1,%0 ! 1010: stb %r1,%0" ! 1011: [(set_attr "type" "move,move,load,store") ! 1012: (set_attr "length" "*,1,*,1")]) ! 1013: ! 1014: (define_insn "" ! 1015: [(set (match_operand:QI 0 "register_operand" "=r") ! 1016: (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r") ! 1017: (match_operand 2 "immediate_operand" "in")) 0))] ! 1018: "" ! 1019: "or %1,%%lo(%a2),%0" ! 1020: [(set_attr "length" "1")]) ! 1021: ! 1022: (define_insn "" ! 1023: [(set (mem:QI (match_operand:SI 0 "symbolic_operand" "")) ! 1024: (match_operand:QI 1 "reg_or_0_operand" "rJ")) ! 1025: (clobber (match_scratch:SI 2 "=&r"))] ! 1026: "" ! 1027: "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]" ! 1028: [(set_attr "type" "store") ! 1029: (set_attr "length" "2")]) ! 1030: ! 1031: ;; ??? We get better code without it. See output_block_move in sparc.c. ! 1032: ! 1033: ;; The definition of this insn does not really explain what it does, ! 1034: ;; but it should suffice ! 1035: ;; that anything generated as this insn will be recognized as one ! 1036: ;; and that it will not successfully combine with anything. ! 1037: ;(define_expand "movstrsi" ! 1038: ; [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) ! 1039: ; (mem:BLK (match_operand:BLK 1 "general_operand" ""))) ! 1040: ; (use (match_operand:SI 2 "nonmemory_operand" "")) ! 1041: ; (use (match_operand:SI 3 "immediate_operand" "")) ! 1042: ; (clobber (match_dup 0)) ! 1043: ; (clobber (match_dup 1)) ! 1044: ; (clobber (match_scratch:SI 4 "")) ! 1045: ; (clobber (reg:SI 0)) ! 1046: ; (clobber (reg:SI 1))])] ! 1047: ; "" ! 1048: ; " ! 1049: ;{ ! 1050: ; /* If the size isn't known, don't emit inline code. output_block_move ! 1051: ; would output code that's much slower than the library function. ! 1052: ; Also don't output code for large blocks. */ ! 1053: ; if (GET_CODE (operands[2]) != CONST_INT ! 1054: ; || GET_CODE (operands[3]) != CONST_INT ! 1055: ; || INTVAL (operands[2]) / INTVAL (operands[3]) > 16) ! 1056: ; FAIL; ! 1057: ; ! 1058: ; operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); ! 1059: ; operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); ! 1060: ; operands[2] = force_not_mem (operands[2]); ! 1061: ;}") ! 1062: ! 1063: ;(define_insn "" ! 1064: ; [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r")) ! 1065: ; (mem:BLK (match_operand:SI 1 "register_operand" "+r"))) ! 1066: ; (use (match_operand:SI 2 "nonmemory_operand" "rn")) ! 1067: ; (use (match_operand:SI 3 "immediate_operand" "i")) ! 1068: ; (clobber (match_dup 0)) ! 1069: ; (clobber (match_dup 1)) ! 1070: ; (clobber (match_scratch:SI 4 "=&r")) ! 1071: ; (clobber (reg:SI 0)) ! 1072: ; (clobber (reg:SI 1))] ! 1073: ; "" ! 1074: ; "* return output_block_move (operands);" ! 1075: ; [(set_attr "type" "multi") ! 1076: ; (set_attr "length" "6")]) ! 1077: ! 1078: ;; Floating point move insns ! 1079: ! 1080: ;; This pattern forces (set (reg:TF ...) (const_double ...)) ! 1081: ;; to be reloaded by putting the constant into memory. ! 1082: ;; It must come before the more general movtf pattern. ! 1083: (define_insn "" ! 1084: [(set (match_operand:TF 0 "general_operand" "=?r,f,o") ! 1085: (match_operand:TF 1 "" "?E,m,G"))] ! 1086: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" ! 1087: "* ! 1088: { ! 1089: switch (which_alternative) ! 1090: { ! 1091: case 0: ! 1092: return output_move_quad (operands); ! 1093: case 1: ! 1094: return output_fp_move_quad (operands); ! 1095: case 2: ! 1096: operands[1] = adj_offsettable_operand (operands[0], 4); ! 1097: operands[2] = adj_offsettable_operand (operands[0], 8); ! 1098: operands[3] = adj_offsettable_operand (operands[0], 12); ! 1099: return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\"; ! 1100: } ! 1101: }" ! 1102: [(set_attr "type" "load,fpload,store") ! 1103: (set_attr "length" "5,5,5")]) ! 1104: ! 1105: (define_expand "movtf" ! 1106: [(set (match_operand:TF 0 "general_operand" "") ! 1107: (match_operand:TF 1 "general_operand" ""))] ! 1108: "" ! 1109: " ! 1110: { ! 1111: if (emit_move_sequence (operands, TFmode, NULL_RTX)) ! 1112: DONE; ! 1113: }") ! 1114: ! 1115: (define_insn "" ! 1116: [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=f,r,Q,Q,f,&r") ! 1117: (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "f,r,f,r,Q,Q"))] ! 1118: "TARGET_FPU ! 1119: && (register_operand (operands[0], TFmode) ! 1120: || register_operand (operands[1], TFmode))" ! 1121: "* ! 1122: { ! 1123: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) ! 1124: return output_fp_move_quad (operands); ! 1125: return output_move_quad (operands); ! 1126: }" ! 1127: [(set_attr "type" "fp,move,fpstore,store,fpload,load") ! 1128: (set_attr "length" "4,4,5,5,5,5")]) ! 1129: ! 1130: ;; Exactly the same as above, except that all `f' cases are deleted. ! 1131: ;; This is necessary to prevent reload from ever trying to use a `f' reg ! 1132: ;; when -mno-fpu. ! 1133: ! 1134: (define_insn "" ! 1135: [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r") ! 1136: (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))] ! 1137: "! TARGET_FPU ! 1138: && (register_operand (operands[0], TFmode) ! 1139: || register_operand (operands[1], TFmode))" ! 1140: "* ! 1141: { ! 1142: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) ! 1143: return output_fp_move_quad (operands); ! 1144: return output_move_quad (operands); ! 1145: }" ! 1146: [(set_attr "type" "move,store,load") ! 1147: (set_attr "length" "4,5,5")]) ! 1148: ! 1149: (define_insn "" ! 1150: [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i")) ! 1151: (match_operand:TF 1 "reg_or_0_operand" "rf,G")) ! 1152: (clobber (match_scratch:SI 2 "=&r,&r"))] ! 1153: "" ! 1154: "* ! 1155: { ! 1156: output_asm_insn (\"sethi %%hi(%a0),%2\", operands); ! 1157: if (which_alternative == 0) ! 1158: return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\"; ! 1159: else ! 1160: return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\"; ! 1161: }" ! 1162: [(set_attr "type" "store") ! 1163: (set_attr "length" "5")]) ! 1164: ! 1165: ;; This pattern forces (set (reg:DF ...) (const_double ...)) ! 1166: ;; to be reloaded by putting the constant into memory. ! 1167: ;; It must come before the more general movdf pattern. ! 1168: ! 1169: (define_insn "" ! 1170: [(set (match_operand:DF 0 "general_operand" "=?r,f,o") ! 1171: (match_operand:DF 1 "" "?E,m,G"))] ! 1172: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" ! 1173: "* ! 1174: { ! 1175: switch (which_alternative) ! 1176: { ! 1177: case 0: ! 1178: return output_move_double (operands); ! 1179: case 1: ! 1180: return output_fp_move_double (operands); ! 1181: case 2: ! 1182: operands[1] = adj_offsettable_operand (operands[0], 4); ! 1183: return \"st %%g0,%0\;st %%g0,%1\"; ! 1184: } ! 1185: }" ! 1186: [(set_attr "type" "load,fpload,store") ! 1187: (set_attr "length" "3,3,3")]) ! 1188: ! 1189: (define_expand "movdf" ! 1190: [(set (match_operand:DF 0 "general_operand" "") ! 1191: (match_operand:DF 1 "general_operand" ""))] ! 1192: "" ! 1193: " ! 1194: { ! 1195: if (emit_move_sequence (operands, DFmode, NULL_RTX)) ! 1196: DONE; ! 1197: }") ! 1198: ! 1199: (define_insn "" ! 1200: [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,f,r,Q,Q,f,&r") ! 1201: (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,f,r,f,r,Q,Q"))] ! 1202: "TARGET_FPU ! 1203: && (register_operand (operands[0], DFmode) ! 1204: || register_operand (operands[1], DFmode))" ! 1205: "* ! 1206: { ! 1207: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) ! 1208: return output_fp_move_double (operands); ! 1209: return output_move_double (operands); ! 1210: }" ! 1211: [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load") ! 1212: (set_attr "length" "1,1,2,2,3,3,3,3")]) ! 1213: ! 1214: ;; Exactly the same as above, except that all `f' cases are deleted. ! 1215: ;; This is necessary to prevent reload from ever trying to use a `f' reg ! 1216: ;; when -mno-fpu. ! 1217: ! 1218: (define_insn "" ! 1219: [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r") ! 1220: (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))] ! 1221: "! TARGET_FPU ! 1222: && (register_operand (operands[0], DFmode) ! 1223: || register_operand (operands[1], DFmode))" ! 1224: "* return output_move_double (operands);" ! 1225: [(set_attr "type" "store,load,move,store,load") ! 1226: (set_attr "length" "1,1,2,3,3")]) ! 1227: ! 1228: (define_split ! 1229: [(set (match_operand:DF 0 "register_operand" "") ! 1230: (match_operand:DF 1 "register_operand" ""))] ! 1231: "reload_completed" ! 1232: [(set (match_dup 2) (match_dup 3)) ! 1233: (set (match_dup 4) (match_dup 5))] ! 1234: " ! 1235: { operands[2] = operand_subword (operands[0], 0, 0, DFmode); ! 1236: operands[3] = operand_subword (operands[1], 0, 0, DFmode); ! 1237: operands[4] = operand_subword (operands[0], 1, 0, DFmode); ! 1238: operands[5] = operand_subword (operands[1], 1, 0, DFmode); }") ! 1239: ! 1240: (define_insn "" ! 1241: [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i")) ! 1242: (match_operand:DF 1 "reg_or_0_operand" "rf,G")) ! 1243: (clobber (match_scratch:SI 2 "=&r,&r"))] ! 1244: "" ! 1245: "* ! 1246: { ! 1247: output_asm_insn (\"sethi %%hi(%a0),%2\", operands); ! 1248: if (which_alternative == 0) ! 1249: return \"std %1,[%2+%%lo(%a0)]\"; ! 1250: else ! 1251: return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\"; ! 1252: }" ! 1253: [(set_attr "type" "store") ! 1254: (set_attr "length" "3")]) ! 1255: ! 1256: ;; Double-word move insns. ! 1257: ! 1258: (define_expand "movdi" ! 1259: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") ! 1260: (match_operand:DI 1 "general_operand" ""))] ! 1261: "" ! 1262: " ! 1263: { ! 1264: if (emit_move_sequence (operands, DImode, NULL_RTX)) ! 1265: DONE; ! 1266: }") ! 1267: ! 1268: (define_insn "" ! 1269: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r,&r,?f,?f,?Q") ! 1270: (match_operand:DI 1 "general_operand" "r,r,Q,i,f,Q,f"))] ! 1271: "register_operand (operands[0], DImode) ! 1272: || register_operand (operands[1], DImode) ! 1273: || operands[1] == const0_rtx" ! 1274: "* ! 1275: { ! 1276: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) ! 1277: return output_fp_move_double (operands); ! 1278: return output_move_double (operands); ! 1279: }" ! 1280: [(set_attr "type" "move,store,load,multi,fp,fpload,fpstore") ! 1281: (set_attr "length" "2,3,3,3,2,3,3")]) ! 1282: ! 1283: ;; Floating-point move insns. ! 1284: ! 1285: ;; This pattern forces (set (reg:SF ...) (const_double ...)) ! 1286: ;; to be reloaded by putting the constant into memory. ! 1287: ;; It must come before the more general movsf pattern. ! 1288: (define_insn "" ! 1289: [(set (match_operand:SF 0 "general_operand" "=?r,f,m") ! 1290: (match_operand:SF 1 "" "?E,m,G"))] ! 1291: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" ! 1292: "* ! 1293: { ! 1294: switch (which_alternative) ! 1295: { ! 1296: case 0: ! 1297: return singlemove_string (operands); ! 1298: case 1: ! 1299: return \"ld %1,%0\"; ! 1300: case 2: ! 1301: return \"st %%g0,%0\"; ! 1302: } ! 1303: }" ! 1304: [(set_attr "type" "load,fpload,store") ! 1305: (set_attr "length" "2,1,1")]) ! 1306: ! 1307: (define_expand "movsf" ! 1308: [(set (match_operand:SF 0 "general_operand" "") ! 1309: (match_operand:SF 1 "general_operand" ""))] ! 1310: "" ! 1311: " ! 1312: { ! 1313: if (emit_move_sequence (operands, SFmode, NULL_RTX)) ! 1314: DONE; ! 1315: }") ! 1316: ! 1317: (define_insn "" ! 1318: [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q") ! 1319: (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))] ! 1320: "TARGET_FPU ! 1321: && (register_operand (operands[0], SFmode) ! 1322: || register_operand (operands[1], SFmode))" ! 1323: "@ ! 1324: fmovs %1,%0 ! 1325: mov %1,%0 ! 1326: ld %1,%0 ! 1327: ld %1,%0 ! 1328: st %r1,%0 ! 1329: st %r1,%0" ! 1330: [(set_attr "type" "fp,move,fpload,load,fpstore,store")]) ! 1331: ! 1332: ;; Exactly the same as above, except that all `f' cases are deleted. ! 1333: ;; This is necessary to prevent reload from ever trying to use a `f' reg ! 1334: ;; when -mno-fpu. ! 1335: ! 1336: (define_insn "" ! 1337: [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q") ! 1338: (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))] ! 1339: "! TARGET_FPU ! 1340: && (register_operand (operands[0], SFmode) ! 1341: || register_operand (operands[1], SFmode))" ! 1342: "@ ! 1343: mov %1,%0 ! 1344: ld %1,%0 ! 1345: st %r1,%0" ! 1346: [(set_attr "type" "move,load,store")]) ! 1347: ! 1348: (define_insn "" ! 1349: [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i")) ! 1350: (match_operand:SF 1 "reg_or_0_operand" "rfG")) ! 1351: (clobber (match_scratch:SI 2 "=&r"))] ! 1352: "" ! 1353: "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" ! 1354: [(set_attr "type" "store") ! 1355: (set_attr "length" "2")]) ! 1356: ! 1357: ;;- zero extension instructions ! 1358: ! 1359: ;; These patterns originally accepted general_operands, however, slightly ! 1360: ;; better code is generated by only accepting register_operands, and then ! 1361: ;; letting combine generate the ldu[hb] insns. ! 1362: ! 1363: (define_expand "zero_extendhisi2" ! 1364: [(set (match_operand:SI 0 "register_operand" "") ! 1365: (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] ! 1366: "" ! 1367: " ! 1368: { ! 1369: rtx temp = gen_reg_rtx (SImode); ! 1370: rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); ! 1371: ! 1372: if (GET_CODE (operand1) == SUBREG) ! 1373: operand1 = XEXP (operand1, 0); ! 1374: ! 1375: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0), ! 1376: shift_16)); ! 1377: emit_insn (gen_lshrsi3 (operand0, temp, shift_16)); ! 1378: DONE; ! 1379: }") ! 1380: ! 1381: (define_insn "" ! 1382: [(set (match_operand:SI 0 "register_operand" "=r") ! 1383: (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] ! 1384: "" ! 1385: "lduh %1,%0" ! 1386: [(set_attr "type" "load")]) ! 1387: ! 1388: (define_expand "zero_extendqihi2" ! 1389: [(set (match_operand:HI 0 "register_operand" "") ! 1390: (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] ! 1391: "" ! 1392: "") ! 1393: ! 1394: (define_insn "" ! 1395: [(set (match_operand:HI 0 "register_operand" "=r,r") ! 1396: (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))] ! 1397: "GET_CODE (operands[1]) != CONST_INT" ! 1398: "@ ! 1399: and %1,0xff,%0 ! 1400: ldub %1,%0" ! 1401: [(set_attr "type" "unary,load") ! 1402: (set_attr "length" "1")]) ! 1403: ! 1404: (define_expand "zero_extendqisi2" ! 1405: [(set (match_operand:SI 0 "register_operand" "") ! 1406: (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] ! 1407: "" ! 1408: "") ! 1409: ! 1410: (define_insn "" ! 1411: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 1412: (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))] ! 1413: "GET_CODE (operands[1]) != CONST_INT" ! 1414: "@ ! 1415: and %1,0xff,%0 ! 1416: ldub %1,%0" ! 1417: [(set_attr "type" "unary,load") ! 1418: (set_attr "length" "1")]) ! 1419: ! 1420: (define_insn "" ! 1421: [(set (reg:CC 0) ! 1422: (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r")) ! 1423: (const_int 0)))] ! 1424: "" ! 1425: "andcc %0,0xff,%%g0" ! 1426: [(set_attr "type" "compare")]) ! 1427: ! 1428: (define_insn "" ! 1429: [(set (reg:CC 0) ! 1430: (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) ! 1431: (const_int 0))) ! 1432: (set (match_operand:SI 0 "register_operand" "=r") ! 1433: (zero_extend:SI (match_dup 1)))] ! 1434: "" ! 1435: "andcc %1,0xff,%0" ! 1436: [(set_attr "type" "unary")]) ! 1437: ! 1438: ;; Similarly, handle SI->QI mode truncation followed by a compare. ! 1439: ! 1440: (define_insn "" ! 1441: [(set (reg:CC 0) ! 1442: (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0) ! 1443: (const_int 0)))] ! 1444: "" ! 1445: "andcc %0,0xff,%%g0" ! 1446: [(set_attr "type" "compare")]) ! 1447: ! 1448: (define_insn "" ! 1449: [(set (reg:CC 0) ! 1450: (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0) ! 1451: (const_int 0))) ! 1452: (set (match_operand:QI 0 "register_operand" "=r") ! 1453: (match_dup 1))] ! 1454: "" ! 1455: "andcc %1,0xff,%0" ! 1456: [(set_attr "type" "unary")]) ! 1457: ! 1458: ;;- sign extension instructions ! 1459: ! 1460: ;; These patterns originally accepted general_operands, however, slightly ! 1461: ;; better code is generated by only accepting register_operands, and then ! 1462: ;; letting combine generate the lds[hb] insns. ! 1463: ! 1464: (define_expand "extendhisi2" ! 1465: [(set (match_operand:SI 0 "register_operand" "") ! 1466: (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] ! 1467: "" ! 1468: " ! 1469: { ! 1470: rtx temp = gen_reg_rtx (SImode); ! 1471: rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); ! 1472: ! 1473: if (GET_CODE (operand1) == SUBREG) ! 1474: operand1 = XEXP (operand1, 0); ! 1475: ! 1476: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0), ! 1477: shift_16)); ! 1478: emit_insn (gen_ashrsi3 (operand0, temp, shift_16)); ! 1479: DONE; ! 1480: }") ! 1481: ! 1482: (define_insn "" ! 1483: [(set (match_operand:SI 0 "register_operand" "=r") ! 1484: (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] ! 1485: "" ! 1486: "ldsh %1,%0" ! 1487: [(set_attr "type" "load")]) ! 1488: ! 1489: (define_expand "extendqihi2" ! 1490: [(set (match_operand:HI 0 "register_operand" "") ! 1491: (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] ! 1492: "" ! 1493: " ! 1494: { ! 1495: rtx temp = gen_reg_rtx (SImode); ! 1496: rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); ! 1497: ! 1498: if (GET_CODE (operand1) == SUBREG) ! 1499: operand1 = XEXP (operand1, 0); ! 1500: if (GET_CODE (operand0) == SUBREG) ! 1501: operand0 = XEXP (operand0, 0); ! 1502: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0), ! 1503: shift_24)); ! 1504: if (GET_MODE (operand0) != SImode) ! 1505: operand0 = gen_rtx (SUBREG, SImode, operand0, 0); ! 1506: emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); ! 1507: DONE; ! 1508: }") ! 1509: ! 1510: (define_insn "" ! 1511: [(set (match_operand:HI 0 "register_operand" "=r") ! 1512: (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] ! 1513: "" ! 1514: "ldsb %1,%0" ! 1515: [(set_attr "type" "load")]) ! 1516: ! 1517: (define_expand "extendqisi2" ! 1518: [(set (match_operand:SI 0 "register_operand" "") ! 1519: (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] ! 1520: "" ! 1521: " ! 1522: { ! 1523: rtx temp = gen_reg_rtx (SImode); ! 1524: rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); ! 1525: ! 1526: if (GET_CODE (operand1) == SUBREG) ! 1527: operand1 = XEXP (operand1, 0); ! 1528: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0), ! 1529: shift_24)); ! 1530: emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); ! 1531: DONE; ! 1532: }") ! 1533: ! 1534: (define_insn "" ! 1535: [(set (match_operand:SI 0 "register_operand" "=r") ! 1536: (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] ! 1537: "" ! 1538: "ldsb %1,%0" ! 1539: [(set_attr "type" "load")]) ! 1540: ! 1541: ;; Special pattern for optimizing bit-field compares. This is needed ! 1542: ;; because combine uses this as a canonical form. ! 1543: ! 1544: (define_insn "" ! 1545: [(set (reg:CC 0) ! 1546: (compare:CC ! 1547: (zero_extract:SI (match_operand:SI 0 "register_operand" "r") ! 1548: (match_operand:SI 1 "small_int" "n") ! 1549: (match_operand:SI 2 "small_int" "n")) ! 1550: (const_int 0)))] ! 1551: "INTVAL (operands[2]) > 19" ! 1552: "* ! 1553: { ! 1554: int len = INTVAL (operands[1]); ! 1555: int pos = 32 - INTVAL (operands[2]) - len; ! 1556: unsigned mask = ((1 << len) - 1) << pos; ! 1557: ! 1558: operands[1] = gen_rtx (CONST_INT, VOIDmode, mask); ! 1559: return \"andcc %0,%1,%%g0\"; ! 1560: }") ! 1561: ! 1562: ;; Conversions between float, double and long double. ! 1563: ! 1564: (define_insn "extendsfdf2" ! 1565: [(set (match_operand:DF 0 "register_operand" "=f") ! 1566: (float_extend:DF ! 1567: (match_operand:SF 1 "register_operand" "f")))] ! 1568: "TARGET_FPU" ! 1569: "fstod %1,%0" ! 1570: [(set_attr "type" "fp")]) ! 1571: ! 1572: (define_insn "extendsftf2" ! 1573: [(set (match_operand:TF 0 "register_operand" "=f") ! 1574: (float_extend:TF ! 1575: (match_operand:SF 1 "register_operand" "f")))] ! 1576: "TARGET_FPU" ! 1577: "fstoq %1,%0" ! 1578: [(set_attr "type" "fp")]) ! 1579: ! 1580: (define_insn "extenddftf2" ! 1581: [(set (match_operand:TF 0 "register_operand" "=f") ! 1582: (float_extend:TF ! 1583: (match_operand:DF 1 "register_operand" "f")))] ! 1584: "TARGET_FPU" ! 1585: "fdtoq %1,%0" ! 1586: [(set_attr "type" "fp")]) ! 1587: ! 1588: (define_insn "truncdfsf2" ! 1589: [(set (match_operand:SF 0 "register_operand" "=f") ! 1590: (float_truncate:SF ! 1591: (match_operand:DF 1 "register_operand" "f")))] ! 1592: "TARGET_FPU" ! 1593: "fdtos %1,%0" ! 1594: [(set_attr "type" "fp")]) ! 1595: ! 1596: (define_insn "trunctfsf2" ! 1597: [(set (match_operand:SF 0 "register_operand" "=f") ! 1598: (float_truncate:SF ! 1599: (match_operand:TF 1 "register_operand" "f")))] ! 1600: "TARGET_FPU" ! 1601: "fqtos %1,%0" ! 1602: [(set_attr "type" "fp")]) ! 1603: ! 1604: (define_insn "trunctfdf2" ! 1605: [(set (match_operand:DF 0 "register_operand" "=f") ! 1606: (float_truncate:DF ! 1607: (match_operand:TF 1 "register_operand" "f")))] ! 1608: "TARGET_FPU" ! 1609: "fqtod %1,%0" ! 1610: [(set_attr "type" "fp")]) ! 1611: ! 1612: ;; Conversion between fixed point and floating point. ! 1613: ! 1614: (define_insn "floatsisf2" ! 1615: [(set (match_operand:SF 0 "register_operand" "=f") ! 1616: (float:SF (match_operand:SI 1 "register_operand" "f")))] ! 1617: "TARGET_FPU" ! 1618: "fitos %1,%0" ! 1619: [(set_attr "type" "fp")]) ! 1620: ! 1621: (define_insn "floatsidf2" ! 1622: [(set (match_operand:DF 0 "register_operand" "=f") ! 1623: (float:DF (match_operand:SI 1 "register_operand" "f")))] ! 1624: "TARGET_FPU" ! 1625: "fitod %1,%0" ! 1626: [(set_attr "type" "fp")]) ! 1627: ! 1628: (define_insn "floatsitf2" ! 1629: [(set (match_operand:TF 0 "register_operand" "=f") ! 1630: (float:TF (match_operand:SI 1 "register_operand" "f")))] ! 1631: "TARGET_FPU" ! 1632: "fitoq %1,%0" ! 1633: [(set_attr "type" "fp")]) ! 1634: ! 1635: ;; Convert a float to an actual integer. ! 1636: ;; Truncation is performed as part of the conversion. ! 1637: ! 1638: (define_insn "fix_truncsfsi2" ! 1639: [(set (match_operand:SI 0 "register_operand" "=f") ! 1640: (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] ! 1641: "TARGET_FPU" ! 1642: "fstoi %1,%0" ! 1643: [(set_attr "type" "fp")]) ! 1644: ! 1645: (define_insn "fix_truncdfsi2" ! 1646: [(set (match_operand:SI 0 "register_operand" "=f") ! 1647: (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] ! 1648: "TARGET_FPU" ! 1649: "fdtoi %1,%0" ! 1650: [(set_attr "type" "fp")]) ! 1651: ! 1652: (define_insn "fix_trunctfsi2" ! 1653: [(set (match_operand:SI 0 "register_operand" "=f") ! 1654: (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "f"))))] ! 1655: "TARGET_FPU" ! 1656: "fqtoi %1,%0" ! 1657: [(set_attr "type" "fp")]) ! 1658: ! 1659: ;;- arithmetic instructions ! 1660: ! 1661: (define_insn "adddi3" ! 1662: [(set (match_operand:DI 0 "register_operand" "=r") ! 1663: (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 1664: (match_operand:DI 2 "arith_double_operand" "rHI"))) ! 1665: (clobber (reg:SI 0))] ! 1666: "" ! 1667: "* ! 1668: { ! 1669: rtx op2 = operands[2]; ! 1670: ! 1671: /* If constant is positive, upper bits zeroed, otherwise unchanged. ! 1672: Give the assembler a chance to pick the move instruction. */ ! 1673: if (GET_CODE (op2) == CONST_INT) ! 1674: { ! 1675: int sign = INTVAL (op2); ! 1676: if (sign < 0) ! 1677: return \"addcc %R1,%2,%R0\;addx %1,-1,%0\"; ! 1678: return \"addcc %R1,%2,%R0\;addx %1,0,%0\"; ! 1679: } ! 1680: else if (GET_CODE (op2) == CONST_DOUBLE) ! 1681: { ! 1682: int sign = CONST_DOUBLE_HIGH (op2); ! 1683: operands[2] = gen_rtx (CONST_INT, VOIDmode, ! 1684: CONST_DOUBLE_LOW (operands[1])); ! 1685: if (sign < 0) ! 1686: return \"addcc %R1,%2,%R0\;addx %1,-1,%0\"; ! 1687: return \"addcc %R1,%2,%R0\;addx %1,0,%0\"; ! 1688: } ! 1689: return \"addcc %R1,%R2,%R0\;addx %1,%2,%0\"; ! 1690: }" ! 1691: [(set_attr "length" "2")]) ! 1692: ! 1693: (define_insn "addsi3" ! 1694: [(set (match_operand:SI 0 "register_operand" "=r") ! 1695: (plus:SI (match_operand:SI 1 "arith_operand" "%r") ! 1696: (match_operand:SI 2 "arith_operand" "rI")))] ! 1697: "" ! 1698: "add %1,%2,%0") ! 1699: ! 1700: (define_insn "" ! 1701: [(set (reg:CC_NOOV 0) ! 1702: (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r") ! 1703: (match_operand:SI 1 "arith_operand" "rI")) ! 1704: (const_int 0)))] ! 1705: "" ! 1706: "addcc %0,%1,%%g0" ! 1707: [(set_attr "type" "compare")]) ! 1708: ! 1709: (define_insn "" ! 1710: [(set (reg:CC_NOOV 0) ! 1711: (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r") ! 1712: (match_operand:SI 2 "arith_operand" "rI")) ! 1713: (const_int 0))) ! 1714: (set (match_operand:SI 0 "register_operand" "=r") ! 1715: (plus:SI (match_dup 1) (match_dup 2)))] ! 1716: "" ! 1717: "addcc %1,%2,%0") ! 1718: ! 1719: (define_insn "subdi3" ! 1720: [(set (match_operand:DI 0 "register_operand" "=r") ! 1721: (minus:DI (match_operand:DI 1 "register_operand" "r") ! 1722: (match_operand:DI 2 "arith_double_operand" "rHI"))) ! 1723: (clobber (reg:SI 0))] ! 1724: "" ! 1725: "* ! 1726: { ! 1727: rtx op2 = operands[2]; ! 1728: ! 1729: /* If constant is positive, upper bits zeroed, otherwise unchanged. ! 1730: Give the assembler a chance to pick the move instruction. */ ! 1731: if (GET_CODE (op2) == CONST_INT) ! 1732: { ! 1733: int sign = INTVAL (op2); ! 1734: if (sign < 0) ! 1735: return \"subcc %R1,%2,%R0\;subx %1,-1,%0\"; ! 1736: return \"subcc %R1,%2,%R0\;subx %1,0,%0\"; ! 1737: } ! 1738: else if (GET_CODE (op2) == CONST_DOUBLE) ! 1739: { ! 1740: int sign = CONST_DOUBLE_HIGH (op2); ! 1741: operands[2] = gen_rtx (CONST_INT, VOIDmode, ! 1742: CONST_DOUBLE_LOW (operands[1])); ! 1743: if (sign < 0) ! 1744: return \"subcc %R1,%2,%R0\;subx %1,-1,%0\"; ! 1745: return \"subcc %R1,%2,%R0\;subx %1,0,%0\"; ! 1746: } ! 1747: return \"subcc %R1,%R2,%R0\;subx %1,%2,%0\"; ! 1748: }" ! 1749: [(set_attr "length" "2")]) ! 1750: ! 1751: (define_insn "subsi3" ! 1752: [(set (match_operand:SI 0 "register_operand" "=r") ! 1753: (minus:SI (match_operand:SI 1 "register_operand" "r") ! 1754: (match_operand:SI 2 "arith_operand" "rI")))] ! 1755: "" ! 1756: "sub %1,%2,%0") ! 1757: ! 1758: (define_insn "" ! 1759: [(set (reg:CC_NOOV 0) ! 1760: (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r") ! 1761: (match_operand:SI 1 "arith_operand" "rI")) ! 1762: (const_int 0)))] ! 1763: "" ! 1764: "subcc %0,%1,%%g0" ! 1765: [(set_attr "type" "compare")]) ! 1766: ! 1767: (define_insn "" ! 1768: [(set (reg:CC_NOOV 0) ! 1769: (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r") ! 1770: (match_operand:SI 2 "arith_operand" "rI")) ! 1771: (const_int 0))) ! 1772: (set (match_operand:SI 0 "register_operand" "=r") ! 1773: (minus:SI (match_dup 1) (match_dup 2)))] ! 1774: "" ! 1775: "subcc %1,%2,%0") ! 1776: ! 1777: (define_insn "mulsi3" ! 1778: [(set (match_operand:SI 0 "register_operand" "=r") ! 1779: (mult:SI (match_operand:SI 1 "arith_operand" "%r") ! 1780: (match_operand:SI 2 "arith_operand" "rI")))] ! 1781: "TARGET_V8 || TARGET_SPARCLITE" ! 1782: "smul %1,%2,%0") ! 1783: ! 1784: ;; It is not known whether this will match. ! 1785: ! 1786: (define_insn "" ! 1787: [(set (match_operand:SI 0 "register_operand" "=r") ! 1788: (mult:SI (match_operand:SI 1 "arith_operand" "%r") ! 1789: (match_operand:SI 2 "arith_operand" "rI"))) ! 1790: (set (reg:CC_NOOV 0) ! 1791: (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2)) ! 1792: (const_int 0)))] ! 1793: "TARGET_V8 || TARGET_SPARCLITE" ! 1794: "smulcc %1,%2,%0") ! 1795: ! 1796: (define_expand "mulsidi3" ! 1797: [(set (match_operand:DI 0 "register_operand" "") ! 1798: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) ! 1799: (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))] ! 1800: "TARGET_V8 || TARGET_SPARCLITE" ! 1801: " ! 1802: { ! 1803: if (CONSTANT_P (operands[2])) ! 1804: { ! 1805: emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2])); ! 1806: DONE; ! 1807: } ! 1808: }") ! 1809: ! 1810: (define_insn "" ! 1811: [(set (match_operand:DI 0 "register_operand" "=r") ! 1812: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) ! 1813: (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] ! 1814: "TARGET_V8 || TARGET_SPARCLITE" ! 1815: "smul %1,%2,%R0\;rd %%y,%0" ! 1816: [(set_attr "length" "2")]) ! 1817: ! 1818: ;; Extra pattern, because sign_extend of a constant isn't legal. ! 1819: ! 1820: (define_insn "const_mulsidi3" ! 1821: [(set (match_operand:DI 0 "register_operand" "=r") ! 1822: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) ! 1823: (match_operand:SI 2 "small_int" "I")))] ! 1824: "TARGET_V8 || TARGET_SPARCLITE" ! 1825: "smul %1,%2,%R0\;rd %%y,%0" ! 1826: [(set_attr "length" "2")]) ! 1827: ! 1828: (define_expand "umulsidi3" ! 1829: [(set (match_operand:DI 0 "register_operand" "") ! 1830: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) ! 1831: (zero_extend:DI (match_operand:SI 2 "arith_operand" ""))))] ! 1832: "TARGET_V8 || TARGET_SPARCLITE" ! 1833: " ! 1834: { ! 1835: if (CONSTANT_P (operands[2])) ! 1836: { ! 1837: emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2])); ! 1838: DONE; ! 1839: } ! 1840: }") ! 1841: ! 1842: (define_insn "" ! 1843: [(set (match_operand:DI 0 "register_operand" "=r") ! 1844: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) ! 1845: (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] ! 1846: "TARGET_V8 || TARGET_SPARCLITE" ! 1847: "umul %1,%2,%R0\;rd %%y,%0" ! 1848: [(set_attr "length" "2")]) ! 1849: ! 1850: ;; Extra pattern, because sign_extend of a constant isn't legal. ! 1851: ! 1852: (define_insn "const_umulsidi3" ! 1853: [(set (match_operand:DI 0 "register_operand" "=r") ! 1854: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) ! 1855: (match_operand:SI 2 "small_int" "I")))] ! 1856: "TARGET_V8 || TARGET_SPARCLITE" ! 1857: "umul %1,%2,%R0\;rd %%y,%0" ! 1858: [(set_attr "length" "2")]) ! 1859: ! 1860: ;; The architecture specifies that there must be 3 instructions between ! 1861: ;; a y register write and a use of it for correct results. ! 1862: ! 1863: (define_insn "divsi3" ! 1864: [(set (match_operand:SI 0 "register_operand" "=r") ! 1865: (div:SI (match_operand:SI 1 "register_operand" "r") ! 1866: (match_operand:SI 2 "arith_operand" "rI"))) ! 1867: (clobber (match_scratch:SI 3 "=&r"))] ! 1868: "TARGET_V8" ! 1869: "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0" ! 1870: [(set_attr "length" "6")]) ! 1871: ! 1872: ;; It is not known whether this will match. ! 1873: ! 1874: (define_insn "" ! 1875: [(set (match_operand:SI 0 "register_operand" "=r") ! 1876: (div:SI (match_operand:SI 1 "register_operand" "r") ! 1877: (match_operand:SI 2 "arith_operand" "rI"))) ! 1878: (set (reg:CC 0) ! 1879: (compare:CC (div:SI (match_dup 1) (match_dup 2)) ! 1880: (const_int 0))) ! 1881: (clobber (match_scratch:SI 3 "=&r"))] ! 1882: "TARGET_V8" ! 1883: "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0" ! 1884: [(set_attr "length" "6")]) ! 1885: ! 1886: (define_insn "udivsi3" ! 1887: [(set (match_operand:SI 0 "register_operand" "=r") ! 1888: (udiv:SI (match_operand:SI 1 "register_operand" "r") ! 1889: (match_operand:SI 2 "arith_operand" "rI")))] ! 1890: "TARGET_V8" ! 1891: "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0" ! 1892: [(set_attr "length" "5")]) ! 1893: ! 1894: ;; It is not known whether this will match. ! 1895: ! 1896: (define_insn "" ! 1897: [(set (match_operand:SI 0 "register_operand" "=r") ! 1898: (udiv:SI (match_operand:SI 1 "register_operand" "r") ! 1899: (match_operand:SI 2 "arith_operand" "rI"))) ! 1900: (set (reg:CC 0) ! 1901: (compare:CC (udiv:SI (match_dup 1) (match_dup 2)) ! 1902: (const_int 0)))] ! 1903: "TARGET_V8" ! 1904: "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0" ! 1905: [(set_attr "length" "5")]) ! 1906: ! 1907: ;;- and instructions ! 1908: ;; We define DImode `and` so with DImode `not` we can get ! 1909: ;; DImode `andn`. Other combinations are possible. ! 1910: ! 1911: (define_expand "anddi3" ! 1912: [(set (match_operand:DI 0 "register_operand" "") ! 1913: (and:DI (match_operand:DI 1 "arith_double_operand" "") ! 1914: (match_operand:DI 2 "arith_double_operand" "")))] ! 1915: "" ! 1916: "") ! 1917: ! 1918: (define_insn "" ! 1919: [(set (match_operand:DI 0 "register_operand" "=r") ! 1920: (and:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 1921: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 1922: "" ! 1923: "* ! 1924: { ! 1925: rtx op2 = operands[2]; ! 1926: ! 1927: /* If constant is positive, upper bits zeroed, otherwise unchanged. ! 1928: Give the assembler a chance to pick the move instruction. */ ! 1929: if (GET_CODE (op2) == CONST_INT) ! 1930: { ! 1931: int sign = INTVAL (op2); ! 1932: if (sign < 0) ! 1933: return \"mov %1,%0\;and %R1,%2,%R0\"; ! 1934: return \"mov 0,%0\;and %R1,%2,%R0\"; ! 1935: } ! 1936: else if (GET_CODE (op2) == CONST_DOUBLE) ! 1937: { ! 1938: int sign = CONST_DOUBLE_HIGH (op2); ! 1939: operands[2] = gen_rtx (CONST_INT, VOIDmode, ! 1940: CONST_DOUBLE_LOW (operands[1])); ! 1941: if (sign < 0) ! 1942: return \"mov %1,%0\;and %R1,%2,%R0\"; ! 1943: return \"mov 0,%0\;and %R1,%2,%R0\"; ! 1944: } ! 1945: return \"and %1,%2,%0\;and %R1,%R2,%R0\"; ! 1946: }" ! 1947: [(set_attr "length" "2")]) ! 1948: ! 1949: (define_insn "andsi3" ! 1950: [(set (match_operand:SI 0 "register_operand" "=r") ! 1951: (and:SI (match_operand:SI 1 "arith_operand" "%r") ! 1952: (match_operand:SI 2 "arith_operand" "rI")))] ! 1953: "" ! 1954: "and %1,%2,%0") ! 1955: ! 1956: (define_split ! 1957: [(set (match_operand:SI 0 "register_operand" "") ! 1958: (and:SI (match_operand:SI 1 "register_operand" "") ! 1959: (match_operand:SI 2 "" ""))) ! 1960: (clobber (match_operand:SI 3 "register_operand" ""))] ! 1961: "GET_CODE (operands[2]) == CONST_INT ! 1962: && !SMALL_INT (operands[2]) ! 1963: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" ! 1964: [(set (match_dup 3) (match_dup 4)) ! 1965: (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))] ! 1966: " ! 1967: { ! 1968: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); ! 1969: }") ! 1970: ! 1971: (define_insn "" ! 1972: [(set (match_operand:DI 0 "register_operand" "=r") ! 1973: (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) ! 1974: (match_operand:DI 2 "register_operand" "r")))] ! 1975: "" ! 1976: "andn %2,%1,%0\;andn %R2,%R1,%R0" ! 1977: [(set_attr "length" "2")]) ! 1978: ! 1979: (define_insn "" ! 1980: [(set (match_operand:SI 0 "register_operand" "=r") ! 1981: (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) ! 1982: (match_operand:SI 2 "register_operand" "r")))] ! 1983: "" ! 1984: "andn %2,%1,%0") ! 1985: ! 1986: (define_expand "iordi3" ! 1987: [(set (match_operand:DI 0 "register_operand" "") ! 1988: (ior:DI (match_operand:DI 1 "arith_double_operand" "") ! 1989: (match_operand:DI 2 "arith_double_operand" "")))] ! 1990: "" ! 1991: "") ! 1992: ! 1993: (define_insn "" ! 1994: [(set (match_operand:DI 0 "register_operand" "=r") ! 1995: (ior:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 1996: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 1997: "" ! 1998: "* ! 1999: { ! 2000: rtx op2 = operands[2]; ! 2001: ! 2002: /* If constant is positive, upper bits zeroed, otherwise unchanged. ! 2003: Give the assembler a chance to pick the move instruction. */ ! 2004: if (GET_CODE (op2) == CONST_INT) ! 2005: { ! 2006: int sign = INTVAL (op2); ! 2007: if (sign < 0) ! 2008: return \"mov -1,%0\;or %R1,%2,%R0\"; ! 2009: return \"mov %1,%0\;or %R1,%2,%R0\"; ! 2010: } ! 2011: else if (GET_CODE (op2) == CONST_DOUBLE) ! 2012: { ! 2013: int sign = CONST_DOUBLE_HIGH (op2); ! 2014: operands[2] = gen_rtx (CONST_INT, VOIDmode, ! 2015: CONST_DOUBLE_LOW (operands[1])); ! 2016: if (sign < 0) ! 2017: return \"mov -1,%0\;or %R1,%2,%R0\"; ! 2018: return \"mov %1,%0\;or %R1,%2,%R0\"; ! 2019: } ! 2020: return \"or %1,%2,%0\;or %R1,%R2,%R0\"; ! 2021: }" ! 2022: [(set_attr "length" "2")]) ! 2023: ! 2024: (define_insn "iorsi3" ! 2025: [(set (match_operand:SI 0 "register_operand" "=r") ! 2026: (ior:SI (match_operand:SI 1 "arith_operand" "%r") ! 2027: (match_operand:SI 2 "arith_operand" "rI")))] ! 2028: "" ! 2029: "or %1,%2,%0") ! 2030: ! 2031: (define_split ! 2032: [(set (match_operand:SI 0 "register_operand" "") ! 2033: (ior:SI (match_operand:SI 1 "register_operand" "") ! 2034: (match_operand:SI 2 "" ""))) ! 2035: (clobber (match_operand:SI 3 "register_operand" ""))] ! 2036: "GET_CODE (operands[2]) == CONST_INT ! 2037: && !SMALL_INT (operands[2]) ! 2038: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" ! 2039: [(set (match_dup 3) (match_dup 4)) ! 2040: (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))] ! 2041: " ! 2042: { ! 2043: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); ! 2044: }") ! 2045: ! 2046: (define_insn "" ! 2047: [(set (match_operand:DI 0 "register_operand" "=r") ! 2048: (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r")) ! 2049: (match_operand:DI 2 "register_operand" "r")))] ! 2050: "" ! 2051: "orn %2,%1,%0\;orn %R2,%R1,%R0" ! 2052: [(set_attr "length" "2")]) ! 2053: ! 2054: (define_insn "" ! 2055: [(set (match_operand:SI 0 "register_operand" "=r") ! 2056: (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r")) ! 2057: (match_operand:SI 2 "register_operand" "r")))] ! 2058: "" ! 2059: "orn %2,%1,%0") ! 2060: ! 2061: (define_expand "xordi3" ! 2062: [(set (match_operand:DI 0 "register_operand" "") ! 2063: (xor:DI (match_operand:DI 1 "arith_double_operand" "") ! 2064: (match_operand:DI 2 "arith_double_operand" "")))] ! 2065: "" ! 2066: "") ! 2067: ! 2068: (define_insn "" ! 2069: [(set (match_operand:DI 0 "register_operand" "=r") ! 2070: (xor:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 2071: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 2072: "" ! 2073: "* ! 2074: { ! 2075: rtx op2 = operands[2]; ! 2076: ! 2077: /* If constant is positive, upper bits zeroed, otherwise unchanged. ! 2078: Give the assembler a chance to pick the move instruction. */ ! 2079: if (GET_CODE (op2) == CONST_INT) ! 2080: { ! 2081: int sign = INTVAL (op2); ! 2082: if (sign < 0) ! 2083: return \"xor %1,-1,%0\;xor %R1,%2,%R0\"; ! 2084: return \"mov %1,%0\;xor %R1,%2,%R0\"; ! 2085: } ! 2086: else if (GET_CODE (op2) == CONST_DOUBLE) ! 2087: { ! 2088: int sign = CONST_DOUBLE_HIGH (op2); ! 2089: operands[2] = gen_rtx (CONST_INT, VOIDmode, ! 2090: CONST_DOUBLE_LOW (operands[1])); ! 2091: if (sign < 0) ! 2092: return \"xor %1,-1,%0\;xor %R1,%2,%R0\"; ! 2093: return \"mov %1,%0\;xor %R1,%2,%R0\"; ! 2094: } ! 2095: return \"xor %1,%2,%0\;xor %R1,%R2,%R0\"; ! 2096: }" ! 2097: [(set_attr "length" "2")]) ! 2098: ! 2099: (define_insn "xorsi3" ! 2100: [(set (match_operand:SI 0 "register_operand" "=r") ! 2101: (xor:SI (match_operand:SI 1 "arith_operand" "%rJ") ! 2102: (match_operand:SI 2 "arith_operand" "rI")))] ! 2103: "" ! 2104: "xor %r1,%2,%0") ! 2105: ! 2106: (define_split ! 2107: [(set (match_operand:SI 0 "register_operand" "") ! 2108: (xor:SI (match_operand:SI 1 "register_operand" "") ! 2109: (match_operand:SI 2 "" ""))) ! 2110: (clobber (match_operand:SI 3 "register_operand" ""))] ! 2111: "GET_CODE (operands[2]) == CONST_INT ! 2112: && !SMALL_INT (operands[2]) ! 2113: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" ! 2114: [(set (match_dup 3) (match_dup 4)) ! 2115: (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))] ! 2116: " ! 2117: { ! 2118: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); ! 2119: }") ! 2120: ! 2121: (define_split ! 2122: [(set (match_operand:SI 0 "register_operand" "") ! 2123: (not:SI (xor:SI (match_operand:SI 1 "register_operand" "") ! 2124: (match_operand:SI 2 "" "")))) ! 2125: (clobber (match_operand:SI 3 "register_operand" ""))] ! 2126: "GET_CODE (operands[2]) == CONST_INT ! 2127: && !SMALL_INT (operands[2]) ! 2128: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" ! 2129: [(set (match_dup 3) (match_dup 4)) ! 2130: (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))] ! 2131: " ! 2132: { ! 2133: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); ! 2134: }") ! 2135: ! 2136: ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b). ! 2137: ;; Combine now canonicalizes to the rightmost expression. ! 2138: (define_insn "" ! 2139: [(set (match_operand:DI 0 "register_operand" "=r") ! 2140: (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r") ! 2141: (match_operand:DI 2 "register_operand" "r"))))] ! 2142: "" ! 2143: "xnor %1,%2,%0\;xnor %R1,%R2,%R0" ! 2144: [(set_attr "length" "2")]) ! 2145: ! 2146: (define_insn "" ! 2147: [(set (match_operand:SI 0 "register_operand" "=r") ! 2148: (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") ! 2149: (match_operand:SI 2 "arith_operand" "rI"))))] ! 2150: "" ! 2151: "xnor %r1,%2,%0") ! 2152: ! 2153: ;; These correspond to the above in the case where we also (or only) ! 2154: ;; want to set the condition code. ! 2155: ! 2156: (define_insn "" ! 2157: [(set (reg:CC 0) ! 2158: (compare:CC ! 2159: (match_operator:SI 2 "cc_arithop" ! 2160: [(match_operand:SI 0 "arith_operand" "%r") ! 2161: (match_operand:SI 1 "arith_operand" "rI")]) ! 2162: (const_int 0)))] ! 2163: "" ! 2164: "%A2cc %0,%1,%%g0" ! 2165: [(set_attr "type" "compare")]) ! 2166: ! 2167: (define_insn "" ! 2168: [(set (reg:CC 0) ! 2169: (compare:CC ! 2170: (match_operator:SI 3 "cc_arithop" ! 2171: [(match_operand:SI 1 "arith_operand" "%r") ! 2172: (match_operand:SI 2 "arith_operand" "rI")]) ! 2173: (const_int 0))) ! 2174: (set (match_operand:SI 0 "register_operand" "=r") ! 2175: (match_dup 3))] ! 2176: "" ! 2177: "%A3cc %1,%2,%0") ! 2178: ! 2179: (define_insn "" ! 2180: [(set (reg:CC 0) ! 2181: (compare:CC ! 2182: (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ") ! 2183: (match_operand:SI 1 "arith_operand" "rI"))) ! 2184: (const_int 0)))] ! 2185: "" ! 2186: "xnorcc %r0,%1,%%g0" ! 2187: [(set_attr "type" "compare")]) ! 2188: ! 2189: (define_insn "" ! 2190: [(set (reg:CC 0) ! 2191: (compare:CC ! 2192: (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") ! 2193: (match_operand:SI 2 "arith_operand" "rI"))) ! 2194: (const_int 0))) ! 2195: (set (match_operand:SI 0 "register_operand" "=r") ! 2196: (not:SI (xor:SI (match_dup 1) (match_dup 2))))] ! 2197: "" ! 2198: "xnorcc %r1,%2,%0") ! 2199: ! 2200: (define_insn "" ! 2201: [(set (reg:CC 0) ! 2202: (compare:CC ! 2203: (match_operator:SI 2 "cc_arithopn" ! 2204: [(not:SI (match_operand:SI 0 "arith_operand" "rI")) ! 2205: (match_operand:SI 1 "reg_or_0_operand" "rJ")]) ! 2206: (const_int 0)))] ! 2207: "" ! 2208: "%B2cc %r1,%0,%%g0" ! 2209: [(set_attr "type" "compare")]) ! 2210: ! 2211: (define_insn "" ! 2212: [(set (reg:CC 0) ! 2213: (compare:CC ! 2214: (match_operator:SI 3 "cc_arithopn" ! 2215: [(not:SI (match_operand:SI 1 "arith_operand" "rI")) ! 2216: (match_operand:SI 2 "reg_or_0_operand" "rJ")]) ! 2217: (const_int 0))) ! 2218: (set (match_operand:SI 0 "register_operand" "=r") ! 2219: (match_dup 3))] ! 2220: "" ! 2221: "%B3cc %r2,%1,%0") ! 2222: ! 2223: ;; We cannot use the "neg" pseudo insn because the Sun assembler ! 2224: ;; does not know how to make it work for constants. ! 2225: ! 2226: (define_insn "negdi2" ! 2227: [(set (match_operand:DI 0 "register_operand" "=r") ! 2228: (neg:DI (match_operand:DI 1 "register_operand" "r"))) ! 2229: (clobber (reg:SI 0))] ! 2230: "" ! 2231: "subcc %%g0,%R1,%R0\;subx %%g0,%1,%0" ! 2232: [(set_attr "type" "unary") ! 2233: (set_attr "length" "2")]) ! 2234: ! 2235: (define_insn "negsi2" ! 2236: [(set (match_operand:SI 0 "general_operand" "=r") ! 2237: (neg:SI (match_operand:SI 1 "arith_operand" "rI")))] ! 2238: "" ! 2239: "sub %%g0,%1,%0" ! 2240: [(set_attr "type" "unary")]) ! 2241: ! 2242: (define_insn "" ! 2243: [(set (reg:CC_NOOV 0) ! 2244: (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI")) ! 2245: (const_int 0)))] ! 2246: "" ! 2247: "subcc %%g0,%0,%%g0" ! 2248: [(set_attr "type" "compare")]) ! 2249: ! 2250: (define_insn "" ! 2251: [(set (reg:CC_NOOV 0) ! 2252: (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI")) ! 2253: (const_int 0))) ! 2254: (set (match_operand:SI 0 "register_operand" "=r") ! 2255: (neg:SI (match_dup 1)))] ! 2256: "" ! 2257: "subcc %%g0,%1,%0" ! 2258: [(set_attr "type" "unary")]) ! 2259: ! 2260: ;; We cannot use the "not" pseudo insn because the Sun assembler ! 2261: ;; does not know how to make it work for constants. ! 2262: (define_expand "one_cmpldi2" ! 2263: [(set (match_operand:DI 0 "register_operand" "=r") ! 2264: (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))] ! 2265: "" ! 2266: "") ! 2267: ! 2268: (define_insn "" ! 2269: [(set (match_operand:DI 0 "register_operand" "=r") ! 2270: (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))] ! 2271: "" ! 2272: "* ! 2273: { ! 2274: rtx op1 = operands[1]; ! 2275: ! 2276: if (GET_CODE (op1) == CONST_INT) ! 2277: { ! 2278: int sign = INTVAL (op1); ! 2279: if (sign < 0) ! 2280: return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\"; ! 2281: return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\"; ! 2282: } ! 2283: else if (GET_CODE (op1) == CONST_DOUBLE) ! 2284: { ! 2285: int sign = CONST_DOUBLE_HIGH (op1); ! 2286: operands[1] = gen_rtx (CONST_INT, VOIDmode, ! 2287: CONST_DOUBLE_LOW (operands[1])); ! 2288: if (sign < 0) ! 2289: return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\"; ! 2290: return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\"; ! 2291: } ! 2292: return \"xnor %%g0,%1,%0\;xnor %%g0,%R1,%R0\"; ! 2293: }" ! 2294: [(set_attr "type" "unary") ! 2295: (set_attr "length" "2")]) ! 2296: ! 2297: (define_insn "one_cmplsi2" ! 2298: [(set (match_operand:SI 0 "register_operand" "=r") ! 2299: (not:SI (match_operand:SI 1 "arith_operand" "rI")))] ! 2300: "" ! 2301: "xnor %%g0,%1,%0" ! 2302: [(set_attr "type" "unary")]) ! 2303: ! 2304: (define_insn "" ! 2305: [(set (reg:CC 0) ! 2306: (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI")) ! 2307: (const_int 0)))] ! 2308: "" ! 2309: "xnorcc %%g0,%0,%%g0" ! 2310: [(set_attr "type" "compare")]) ! 2311: ! 2312: (define_insn "" ! 2313: [(set (reg:CC 0) ! 2314: (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI")) ! 2315: (const_int 0))) ! 2316: (set (match_operand:SI 0 "register_operand" "=r") ! 2317: (not:SI (match_dup 1)))] ! 2318: "" ! 2319: "xnorcc %%g0,%1,%0" ! 2320: [(set_attr "type" "unary")]) ! 2321: ! 2322: ;; Floating point arithmetic instructions. ! 2323: ! 2324: (define_insn "addtf3" ! 2325: [(set (match_operand:TF 0 "register_operand" "=f") ! 2326: (plus:TF (match_operand:TF 1 "register_operand" "f") ! 2327: (match_operand:TF 2 "register_operand" "f")))] ! 2328: "TARGET_FPU" ! 2329: "faddq %1,%2,%0" ! 2330: [(set_attr "type" "fp")]) ! 2331: ! 2332: (define_insn "adddf3" ! 2333: [(set (match_operand:DF 0 "register_operand" "=f") ! 2334: (plus:DF (match_operand:DF 1 "register_operand" "f") ! 2335: (match_operand:DF 2 "register_operand" "f")))] ! 2336: "TARGET_FPU" ! 2337: "faddd %1,%2,%0" ! 2338: [(set_attr "type" "fp")]) ! 2339: ! 2340: (define_insn "addsf3" ! 2341: [(set (match_operand:SF 0 "register_operand" "=f") ! 2342: (plus:SF (match_operand:SF 1 "register_operand" "f") ! 2343: (match_operand:SF 2 "register_operand" "f")))] ! 2344: "TARGET_FPU" ! 2345: "fadds %1,%2,%0" ! 2346: [(set_attr "type" "fp")]) ! 2347: ! 2348: (define_insn "subtf3" ! 2349: [(set (match_operand:TF 0 "register_operand" "=f") ! 2350: (minus:TF (match_operand:TF 1 "register_operand" "f") ! 2351: (match_operand:TF 2 "register_operand" "f")))] ! 2352: "TARGET_FPU" ! 2353: "fsubq %1,%2,%0" ! 2354: [(set_attr "type" "fp")]) ! 2355: ! 2356: (define_insn "subdf3" ! 2357: [(set (match_operand:DF 0 "register_operand" "=f") ! 2358: (minus:DF (match_operand:DF 1 "register_operand" "f") ! 2359: (match_operand:DF 2 "register_operand" "f")))] ! 2360: "TARGET_FPU" ! 2361: "fsubd %1,%2,%0" ! 2362: [(set_attr "type" "fp")]) ! 2363: ! 2364: (define_insn "subsf3" ! 2365: [(set (match_operand:SF 0 "register_operand" "=f") ! 2366: (minus:SF (match_operand:SF 1 "register_operand" "f") ! 2367: (match_operand:SF 2 "register_operand" "f")))] ! 2368: "TARGET_FPU" ! 2369: "fsubs %1,%2,%0" ! 2370: [(set_attr "type" "fp")]) ! 2371: ! 2372: (define_insn "multf3" ! 2373: [(set (match_operand:TF 0 "register_operand" "=f") ! 2374: (mult:TF (match_operand:TF 1 "register_operand" "f") ! 2375: (match_operand:TF 2 "register_operand" "f")))] ! 2376: "TARGET_FPU" ! 2377: "fmulq %1,%2,%0" ! 2378: [(set_attr "type" "fpmul")]) ! 2379: ! 2380: (define_insn "muldf3" ! 2381: [(set (match_operand:DF 0 "register_operand" "=f") ! 2382: (mult:DF (match_operand:DF 1 "register_operand" "f") ! 2383: (match_operand:DF 2 "register_operand" "f")))] ! 2384: "TARGET_FPU" ! 2385: "fmuld %1,%2,%0" ! 2386: [(set_attr "type" "fpmul")]) ! 2387: ! 2388: (define_insn "mulsf3" ! 2389: [(set (match_operand:SF 0 "register_operand" "=f") ! 2390: (mult:SF (match_operand:SF 1 "register_operand" "f") ! 2391: (match_operand:SF 2 "register_operand" "f")))] ! 2392: "TARGET_FPU" ! 2393: "fmuls %1,%2,%0" ! 2394: [(set_attr "type" "fpmul")]) ! 2395: ! 2396: (define_insn "" ! 2397: [(set (match_operand:DF 0 "register_operand" "=f") ! 2398: (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f")) ! 2399: (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))] ! 2400: "TARGET_V8 && TARGET_FPU" ! 2401: "fsmuld %1,%2,%0" ! 2402: [(set_attr "type" "fpmul")]) ! 2403: ! 2404: (define_insn "" ! 2405: [(set (match_operand:TF 0 "register_operand" "=f") ! 2406: (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "f")) ! 2407: (float_extend:TF (match_operand:DF 2 "register_operand" "f"))))] ! 2408: "TARGET_V8 && TARGET_FPU" ! 2409: "fdmulq %1,%2,%0" ! 2410: [(set_attr "type" "fpmul")]) ! 2411: ! 2412: (define_insn "divtf3" ! 2413: [(set (match_operand:TF 0 "register_operand" "=f") ! 2414: (div:TF (match_operand:TF 1 "register_operand" "f") ! 2415: (match_operand:TF 2 "register_operand" "f")))] ! 2416: "TARGET_FPU" ! 2417: "fdivq %1,%2,%0" ! 2418: [(set_attr "type" "fpdiv")]) ! 2419: ! 2420: (define_insn "divdf3" ! 2421: [(set (match_operand:DF 0 "register_operand" "=f") ! 2422: (div:DF (match_operand:DF 1 "register_operand" "f") ! 2423: (match_operand:DF 2 "register_operand" "f")))] ! 2424: "TARGET_FPU" ! 2425: "fdivd %1,%2,%0" ! 2426: [(set_attr "type" "fpdiv")]) ! 2427: ! 2428: (define_insn "divsf3" ! 2429: [(set (match_operand:SF 0 "register_operand" "=f") ! 2430: (div:SF (match_operand:SF 1 "register_operand" "f") ! 2431: (match_operand:SF 2 "register_operand" "f")))] ! 2432: "TARGET_FPU" ! 2433: "fdivs %1,%2,%0" ! 2434: [(set_attr "type" "fpdiv")]) ! 2435: ! 2436: (define_insn "negtf2" ! 2437: [(set (match_operand:TF 0 "register_operand" "=f,f") ! 2438: (neg:TF (match_operand:TF 1 "register_operand" "0,f")))] ! 2439: "TARGET_FPU" ! 2440: "@ ! 2441: fnegs %0,%0 ! 2442: fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0" ! 2443: [(set_attr "type" "fp") ! 2444: (set_attr "length" "1,4")]) ! 2445: ! 2446: (define_insn "negdf2" ! 2447: [(set (match_operand:DF 0 "register_operand" "=f,f") ! 2448: (neg:DF (match_operand:DF 1 "register_operand" "0,f")))] ! 2449: "TARGET_FPU" ! 2450: "@ ! 2451: fnegs %0,%0 ! 2452: fnegs %1,%0\;fmovs %R1,%R0" ! 2453: [(set_attr "type" "fp") ! 2454: (set_attr "length" "1,2")]) ! 2455: ! 2456: (define_insn "negsf2" ! 2457: [(set (match_operand:SF 0 "register_operand" "=f") ! 2458: (neg:SF (match_operand:SF 1 "register_operand" "f")))] ! 2459: "TARGET_FPU" ! 2460: "fnegs %1,%0" ! 2461: [(set_attr "type" "fp")]) ! 2462: ! 2463: (define_insn "abstf2" ! 2464: [(set (match_operand:TF 0 "register_operand" "=f,f") ! 2465: (abs:TF (match_operand:TF 1 "register_operand" "0,f")))] ! 2466: "TARGET_FPU" ! 2467: "@ ! 2468: fabss %0,%0 ! 2469: fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0" ! 2470: [(set_attr "type" "fp") ! 2471: (set_attr "length" "1,4")]) ! 2472: ! 2473: (define_insn "absdf2" ! 2474: [(set (match_operand:DF 0 "register_operand" "=f,f") ! 2475: (abs:DF (match_operand:DF 1 "register_operand" "0,f")))] ! 2476: "TARGET_FPU" ! 2477: "@ ! 2478: fabss %0,%0 ! 2479: fabss %1,%0\;fmovs %R1,%R0" ! 2480: [(set_attr "type" "fp") ! 2481: (set_attr "length" "1,2")]) ! 2482: ! 2483: (define_insn "abssf2" ! 2484: [(set (match_operand:SF 0 "register_operand" "=f") ! 2485: (abs:SF (match_operand:SF 1 "register_operand" "f")))] ! 2486: "TARGET_FPU" ! 2487: "fabss %1,%0" ! 2488: [(set_attr "type" "fp")]) ! 2489: ! 2490: (define_insn "sqrttf2" ! 2491: [(set (match_operand:TF 0 "register_operand" "=f") ! 2492: (sqrt:TF (match_operand:TF 1 "register_operand" "f")))] ! 2493: "TARGET_FPU" ! 2494: "fsqrtq %1,%0" ! 2495: [(set_attr "type" "fpsqrt")]) ! 2496: ! 2497: (define_insn "sqrtdf2" ! 2498: [(set (match_operand:DF 0 "register_operand" "=f") ! 2499: (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] ! 2500: "TARGET_FPU" ! 2501: "fsqrtd %1,%0" ! 2502: [(set_attr "type" "fpsqrt")]) ! 2503: ! 2504: (define_insn "sqrtsf2" ! 2505: [(set (match_operand:SF 0 "register_operand" "=f") ! 2506: (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] ! 2507: "TARGET_FPU" ! 2508: "fsqrts %1,%0" ! 2509: [(set_attr "type" "fpsqrt")]) ! 2510: ! 2511: ;;- arithmetic shift instructions ! 2512: ! 2513: ;; We can trivially handle shifting the constant 1 by 64 bits. ! 2514: ;; For other shifts we use the library routine. ! 2515: ;; ??? Questionable, we can do better than this can't we? ! 2516: (define_expand "ashldi3" ! 2517: [(parallel [(set (match_operand:DI 0 "register_operand" "") ! 2518: (ashift:DI (match_operand:DI 1 "const_double_operand" "") ! 2519: (match_operand:SI 2 "register_operand" ""))) ! 2520: (clobber (reg:SI 0))])] ! 2521: "" ! 2522: " ! 2523: { ! 2524: if (GET_CODE (operands[1]) == CONST_DOUBLE ! 2525: && CONST_DOUBLE_HIGH (operands[1]) == 0 ! 2526: && CONST_DOUBLE_LOW (operands[1]) == 1) ! 2527: operands[1] = const1_rtx; ! 2528: else if (operands[1] != const1_rtx) ! 2529: FAIL; ! 2530: }") ! 2531: ! 2532: ;; ??? Questionable, we can do better than this can't we? ! 2533: (define_insn "" ! 2534: [(set (match_operand:DI 0 "register_operand" "=&r") ! 2535: (ashift:DI (const_int 1) ! 2536: (match_operand:SI 1 "register_operand" "r"))) ! 2537: (clobber (reg:SI 0))] ! 2538: "" ! 2539: "subcc %1,32,%%g0\;addx %%g0,0,%R0\;xor %R0,1,%0\;sll %R0,%1,%R0\;sll %0,%1,%0" ! 2540: [(set_attr "type" "multi") ! 2541: (set_attr "length" "5")]) ! 2542: ! 2543: (define_insn "ashlsi3" ! 2544: [(set (match_operand:SI 0 "register_operand" "=r") ! 2545: (ashift:SI (match_operand:SI 1 "register_operand" "r") ! 2546: (match_operand:SI 2 "arith_operand" "rI")))] ! 2547: "" ! 2548: "sll %1,%2,%0") ! 2549: ! 2550: (define_expand "lshldi3" ! 2551: [(parallel [(set (match_operand:DI 0 "register_operand" "") ! 2552: (lshift:DI (match_operand:DI 1 "register_operand" "") ! 2553: (match_operand:DI 2 "const_int_operand" ""))) ! 2554: (clobber (match_scratch:SI 3 ""))])] ! 2555: "" ! 2556: " ! 2557: { ! 2558: if (GET_CODE (operands[2]) != CONST_INT) ! 2559: FAIL; ! 2560: }") ! 2561: ! 2562: (define_insn "" ! 2563: [(set (match_operand:DI 0 "register_operand" "=r") ! 2564: (lshift:DI (match_operand:DI 1 "register_operand" "r") ! 2565: (match_operand:DI 2 "const_int_operand" "I"))) ! 2566: (clobber (match_scratch:SI 3 "=r"))] ! 2567: "INTVAL (operands[2]) < 32" ! 2568: "* ! 2569: { ! 2570: operands[4] = GEN_INT (32 - INTVAL (operands[2])); ! 2571: return \"srl %R1,%4,%3\;sll %R1,%2,%R0\;sll %1,%2,%0\;or %3,%0,%0\"; ! 2572: }" ! 2573: [(set_attr "type" "multi") ! 2574: (set_attr "length" "4")]) ! 2575: ! 2576: (define_insn "" ! 2577: [(set (match_operand:DI 0 "register_operand" "=r") ! 2578: (lshift:DI (match_operand:DI 1 "register_operand" "r") ! 2579: (match_operand:DI 2 "const_int_operand" "I"))) ! 2580: (clobber (match_scratch:SI 3 "=X"))] ! 2581: "INTVAL (operands[2]) >= 32" ! 2582: "* ! 2583: { ! 2584: operands[4] = GEN_INT (INTVAL (operands[2]) - 32); ! 2585: return \"sll %R1,%4,%0\;mov %%g0,%R0\"; ! 2586: }" ! 2587: [(set_attr "type" "multi") ! 2588: (set_attr "length" "2")]) ! 2589: ! 2590: (define_insn "ashrsi3" ! 2591: [(set (match_operand:SI 0 "register_operand" "=r") ! 2592: (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") ! 2593: (match_operand:SI 2 "arith_operand" "rI")))] ! 2594: "" ! 2595: "sra %1,%2,%0") ! 2596: ! 2597: (define_insn "lshrsi3" ! 2598: [(set (match_operand:SI 0 "register_operand" "=r") ! 2599: (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") ! 2600: (match_operand:SI 2 "arith_operand" "rI")))] ! 2601: "" ! 2602: "srl %1,%2,%0") ! 2603: ! 2604: (define_expand "lshrdi3" ! 2605: [(parallel [(set (match_operand:DI 0 "register_operand" "") ! 2606: (lshiftrt:DI (match_operand:DI 1 "register_operand" "") ! 2607: (match_operand:DI 2 "const_int_operand" ""))) ! 2608: (clobber (match_scratch:SI 3 ""))])] ! 2609: "" ! 2610: " ! 2611: { ! 2612: if (GET_CODE (operands[2]) != CONST_INT) ! 2613: FAIL; ! 2614: }") ! 2615: ! 2616: (define_insn "" ! 2617: [(set (match_operand:DI 0 "register_operand" "=r") ! 2618: (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") ! 2619: (match_operand:DI 2 "const_int_operand" "I"))) ! 2620: (clobber (match_scratch:SI 3 "=r"))] ! 2621: "INTVAL (operands[2]) < 32" ! 2622: "* ! 2623: { ! 2624: operands[4] = GEN_INT (32 - INTVAL (operands[2])); ! 2625: return \"sll %1,%4,%3\;srl %1,%2,%0\;srl %R1,%2,%R0\;or %3,%R0,%R0\"; ! 2626: }" ! 2627: [(set_attr "type" "multi") ! 2628: (set_attr "length" "4")]) ! 2629: ! 2630: (define_insn "" ! 2631: [(set (match_operand:DI 0 "register_operand" "=r") ! 2632: (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") ! 2633: (match_operand:DI 2 "const_int_operand" "I"))) ! 2634: (clobber (match_scratch:SI 3 "=X"))] ! 2635: "INTVAL (operands[2]) >= 32" ! 2636: "* ! 2637: { ! 2638: operands[4] = GEN_INT (INTVAL (operands[2]) - 32); ! 2639: return \"srl %1,%4,%R0\;mov %%g0,%0\"; ! 2640: }" ! 2641: [(set_attr "type" "multi") ! 2642: (set_attr "length" "2")]) ! 2643: ! 2644: ;; Unconditional and other jump instructions ! 2645: ;; On the Sparc, by setting the annul bit on an unconditional branch, the ! 2646: ;; following insn is never executed. This saves us a nop. Dbx does not ! 2647: ;; handle such branches though, so we only use them when optimizing. ! 2648: (define_insn "jump" ! 2649: [(set (pc) (label_ref (match_operand 0 "" "")))] ! 2650: "" ! 2651: "b%* %l0%(" ! 2652: [(set_attr "type" "uncond_branch")]) ! 2653: ! 2654: (define_expand "tablejump" ! 2655: [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "r")) ! 2656: (use (label_ref (match_operand 1 "" "")))])] ! 2657: "" ! 2658: " ! 2659: { ! 2660: /* We need to use the PC value in %o7 that was set up when the address ! 2661: of the label was loaded into a register, so we need different RTL. */ ! 2662: if (flag_pic) ! 2663: { ! 2664: emit_insn (gen_pic_tablejump (operands[0], operands[1])); ! 2665: DONE; ! 2666: } ! 2667: }") ! 2668: ! 2669: (define_insn "pic_tablejump" ! 2670: [(set (pc) (match_operand:SI 0 "register_operand" "r")) ! 2671: (use (label_ref (match_operand 1 "" ""))) ! 2672: (use (reg:SI 15))] ! 2673: "" ! 2674: "jmp %%o7+%0%#" ! 2675: [(set_attr "type" "uncond_branch")]) ! 2676: ! 2677: (define_insn "" ! 2678: [(set (pc) (match_operand:SI 0 "address_operand" "p")) ! 2679: (use (label_ref (match_operand 1 "" "")))] ! 2680: "" ! 2681: "jmp %a0%#" ! 2682: [(set_attr "type" "uncond_branch")]) ! 2683: ! 2684: (define_insn "" ! 2685: [(set (pc) (label_ref (match_operand 0 "" ""))) ! 2686: (set (reg:SI 15) (label_ref (match_dup 0)))] ! 2687: "" ! 2688: "call %l0%#" ! 2689: [(set_attr "type" "uncond_branch")]) ! 2690: ! 2691: ;; This pattern recognizes the "instruction" that appears in ! 2692: ;; a function call that wants a structure value, ! 2693: ;; to inform the called function if compiled with Sun CC. ! 2694: ;(define_insn "" ! 2695: ; [(match_operand:SI 0 "immediate_operand" "")] ! 2696: ; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0" ! 2697: ; "unimp %0" ! 2698: ; [(set_attr "type" "marker")]) ! 2699: ! 2700: ;;- jump to subroutine ! 2701: (define_expand "call" ! 2702: ;; Note that this expression is not used for generating RTL. ! 2703: ;; All the RTL is generated explicitly below. ! 2704: [(call (match_operand:SI 0 "call_operand" "") ! 2705: (match_operand 3 "" "i"))] ! 2706: ;; operands[2] is next_arg_register ! 2707: ;; operands[3] is struct_value_size_rtx. ! 2708: "" ! 2709: " ! 2710: { ! 2711: rtx fn_rtx, nregs_rtx; ! 2712: ! 2713: if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF) ! 2714: { ! 2715: /* This is really a PIC sequence. We want to represent ! 2716: it as a funny jump so it's delay slots can be filled. ! 2717: ! 2718: ??? But if this really *is* a CALL, will not it clobber the ! 2719: call-clobbered registers? We lose this if it is a JUMP_INSN. ! 2720: Why cannot we have delay slots filled if it were a CALL? */ ! 2721: ! 2722: if (INTVAL (operands[3]) > 0) ! 2723: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3, ! 2724: gen_rtx (SET, VOIDmode, pc_rtx, ! 2725: XEXP (operands[0], 0)), ! 2726: operands[3], ! 2727: gen_rtx (CLOBBER, VOIDmode, ! 2728: gen_rtx (REG, SImode, 15))))); ! 2729: else ! 2730: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, ! 2731: gen_rtx (SET, VOIDmode, pc_rtx, ! 2732: XEXP (operands[0], 0)), ! 2733: gen_rtx (CLOBBER, VOIDmode, ! 2734: gen_rtx (REG, SImode, 15))))); ! 2735: goto finish_call; ! 2736: } ! 2737: ! 2738: fn_rtx = operands[0]; ! 2739: ! 2740: /* Count the number of parameter registers being used by this call. ! 2741: if that argument is NULL, it means we are using them all, which ! 2742: means 6 on the sparc. */ ! 2743: #if 0 ! 2744: if (operands[2]) ! 2745: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8); ! 2746: else ! 2747: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6); ! 2748: #else ! 2749: nregs_rtx = const0_rtx; ! 2750: #endif ! 2751: ! 2752: if (INTVAL (operands[3]) > 0) ! 2753: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3, ! 2754: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx), ! 2755: operands[3], ! 2756: gen_rtx (CLOBBER, VOIDmode, ! 2757: gen_rtx (REG, SImode, 15))))); ! 2758: else ! 2759: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, ! 2760: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx), ! 2761: gen_rtx (CLOBBER, VOIDmode, ! 2762: gen_rtx (REG, SImode, 15))))); ! 2763: ! 2764: finish_call: ! 2765: #if 0 ! 2766: /* If this call wants a structure value, ! 2767: emit an unimp insn to let the called function know about this. */ ! 2768: if (INTVAL (operands[3]) > 0) ! 2769: { ! 2770: rtx insn = emit_insn (operands[3]); ! 2771: SCHED_GROUP_P (insn) = 1; ! 2772: } ! 2773: #endif ! 2774: ! 2775: DONE; ! 2776: }") ! 2777: ! 2778: (define_insn "" ! 2779: [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r")) ! 2780: (match_operand 1 "" "")) ! 2781: (clobber (reg:SI 15))] ! 2782: ;;- Do not use operand 1 for most machines. ! 2783: "" ! 2784: "* ! 2785: { ! 2786: return \"call %a0,%1%#\"; ! 2787: }" ! 2788: [(set_attr "type" "call")]) ! 2789: ! 2790: ;; This is a call that wants a structure value. ! 2791: (define_insn "" ! 2792: [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r")) ! 2793: (match_operand 1 "" "")) ! 2794: (match_operand 2 "immediate_operand" "") ! 2795: (clobber (reg:SI 15))] ! 2796: ;;- Do not use operand 1 for most machines. ! 2797: "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0" ! 2798: "* ! 2799: { ! 2800: return \"call %a0,%1\;nop\;unimp %2\"; ! 2801: }" ! 2802: [(set_attr "type" "call_no_delay_slot")]) ! 2803: ! 2804: (define_expand "call_value" ! 2805: [(set (match_operand 0 "register_operand" "=rf") ! 2806: (call (match_operand:SI 1 "" "") ! 2807: (match_operand 4 "" "")))] ! 2808: ;; operand 3 is next_arg_register ! 2809: "" ! 2810: " ! 2811: { ! 2812: rtx fn_rtx, nregs_rtx; ! 2813: rtvec vec; ! 2814: ! 2815: fn_rtx = operands[1]; ! 2816: ! 2817: #if 0 ! 2818: if (operands[3]) ! 2819: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8); ! 2820: else ! 2821: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6); ! 2822: #else ! 2823: nregs_rtx = const0_rtx; ! 2824: #endif ! 2825: ! 2826: vec = gen_rtvec (2, ! 2827: gen_rtx (SET, VOIDmode, operands[0], ! 2828: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)), ! 2829: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 15))); ! 2830: ! 2831: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec)); ! 2832: ! 2833: DONE; ! 2834: }") ! 2835: ! 2836: (define_insn "" ! 2837: [(set (match_operand 0 "" "=rf") ! 2838: (call (mem:SI (match_operand:SI 1 "call_operand_address" "rS")) ! 2839: (match_operand 2 "" ""))) ! 2840: (clobber (reg:SI 15))] ! 2841: ;;- Do not use operand 2 for most machines. ! 2842: "" ! 2843: "* ! 2844: { ! 2845: return \"call %a1,%2%#\"; ! 2846: }" ! 2847: [(set_attr "type" "call")]) ! 2848: ! 2849: (define_expand "untyped_call" ! 2850: [(parallel [(call (match_operand:SI 0 "call_operand" "") ! 2851: (const_int 0)) ! 2852: (match_operand:BLK 1 "memory_operand" "") ! 2853: (match_operand 2 "" "") ! 2854: (clobber (reg:SI 15))])] ! 2855: "" ! 2856: " ! 2857: { ! 2858: operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0)); ! 2859: }") ! 2860: ! 2861: ;; Make a call followed by two nops in case the function being called ! 2862: ;; returns a structure value and expects to skip an unimp instruction. ! 2863: ! 2864: (define_insn "" ! 2865: [(call (mem:SI (match_operand:SI 0 "call_operand_address" "rS")) ! 2866: (const_int 0)) ! 2867: (match_operand:DI 1 "memory_operand" "o") ! 2868: (match_operand 2 "" "") ! 2869: (clobber (reg:SI 15))] ! 2870: "" ! 2871: "* ! 2872: { ! 2873: operands[2] = adj_offsettable_operand (operands[1], 8); ! 2874: return \"call %a0,0\;nop\;nop\;std %%o0,%1\;st %%f0,%2\"; ! 2875: }" ! 2876: [(set_attr "type" "multi")]) ! 2877: ! 2878: ;; Prepare to return any type including a structure value. ! 2879: ! 2880: (define_expand "untyped_return" ! 2881: [(match_operand:BLK 0 "memory_operand" "") ! 2882: (match_operand 1 "" "")] ! 2883: "" ! 2884: " ! 2885: { ! 2886: rtx valreg1 = gen_rtx (REG, DImode, 24); ! 2887: rtx valreg2 = gen_rtx (REG, DFmode, 32); ! 2888: rtx result = operands[0]; ! 2889: rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31)); ! 2890: rtx value = gen_reg_rtx (SImode); ! 2891: ! 2892: /* Fetch the instruction where we will return to and see if it's an unimp ! 2893: instruction (the most significant 10 bits will be zero). If so, ! 2894: update the return address to skip the unimp instruction. */ ! 2895: emit_move_insn (value, ! 2896: gen_rtx (MEM, SImode, plus_constant (rtnreg, 8))); ! 2897: emit_insn (gen_lshrsi3 (value, value, GEN_INT (22))); ! 2898: emit_insn (gen_update_return (rtnreg, value)); ! 2899: ! 2900: /* Reload the function value registers. */ ! 2901: emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0))); ! 2902: emit_move_insn (valreg2, ! 2903: change_address (result, DFmode, ! 2904: plus_constant (XEXP (result, 0), 8))); ! 2905: ! 2906: /* Put USE insns before the return. */ ! 2907: emit_insn (gen_rtx (USE, VOIDmode, valreg1)); ! 2908: emit_insn (gen_rtx (USE, VOIDmode, valreg2)); ! 2909: ! 2910: /* Construct the return. */ ! 2911: expand_null_return (); ! 2912: ! 2913: DONE; ! 2914: }") ! 2915: ! 2916: ;; This is a bit of a hack. We're incrementing a fixed register (%i7), ! 2917: ;; and parts of the compiler don't want to believe that the add is needed. ! 2918: ! 2919: (define_insn "update_return" ! 2920: [(unspec:SI [(match_operand:SI 0 "register_operand" "r") ! 2921: (match_operand:SI 1 "register_operand" "r")] 0)] ! 2922: "" ! 2923: "cmp %1,0\;be,a .+8\;add %0,4,%0" ! 2924: [(set_attr "type" "multi")]) ! 2925: ! 2926: (define_insn "return" ! 2927: [(return)] ! 2928: "! TARGET_EPILOGUE" ! 2929: "* return output_return (operands);" ! 2930: [(set_attr "type" "multi")]) ! 2931: ! 2932: (define_insn "nop" ! 2933: [(const_int 0)] ! 2934: "" ! 2935: "nop") ! 2936: ! 2937: (define_insn "indirect_jump" ! 2938: [(set (pc) (match_operand:SI 0 "address_operand" "p"))] ! 2939: "" ! 2940: "jmp %a0%#" ! 2941: [(set_attr "type" "uncond_branch")]) ! 2942: ! 2943: (define_expand "nonlocal_goto" ! 2944: [(match_operand:SI 0 "general_operand" "") ! 2945: (match_operand:SI 1 "general_operand" "") ! 2946: (match_operand:SI 2 "general_operand" "") ! 2947: (match_operand:SI 3 "" "")] ! 2948: "" ! 2949: " ! 2950: { ! 2951: /* Trap instruction to flush all the registers window. */ ! 2952: emit_insn (gen_flush_register_windows ()); ! 2953: /* Load the fp value for the containing fn into %fp. ! 2954: This is needed because operands[2] refers to %fp. ! 2955: Virtual register instantiation fails if the virtual %fp isn't set from a ! 2956: register. Thus we must copy operands[0] into a register if it isn't ! 2957: already one. */ ! 2958: if (GET_CODE (operands[0]) != REG) ! 2959: operands[0] = force_reg (SImode, operands[0]); ! 2960: emit_move_insn (virtual_stack_vars_rtx, operands[0]); ! 2961: /* Find the containing function's current nonlocal goto handler, ! 2962: which will do any cleanups and then jump to the label. */ ! 2963: emit_move_insn (gen_rtx (REG, SImode, 8), operands[1]); ! 2964: /* Restore %fp from stack pointer value for containing function. ! 2965: The restore insn that follows will move this to %sp, ! 2966: and reload the appropriate value into %fp. */ ! 2967: emit_move_insn (frame_pointer_rtx, operands[2]); ! 2968: /* Put in the static chain register the nonlocal label address. */ ! 2969: emit_move_insn (static_chain_rtx, operands[3]); ! 2970: /* USE of frame_pointer_rtx added for consistency; not clear if ! 2971: really needed. */ ! 2972: emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx)); ! 2973: emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); ! 2974: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx)); ! 2975: emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 8))); ! 2976: /* Return, restoring reg window and jumping to goto handler. */ ! 2977: emit_insn (gen_goto_handler_and_restore ()); ! 2978: DONE; ! 2979: }") ! 2980: ! 2981: ;; Special trap insn to flush register windows. ! 2982: (define_insn "flush_register_windows" ! 2983: [(unspec_volatile [(const_int 0)] 0)] ! 2984: "" ! 2985: "ta 3" ! 2986: [(set_attr "type" "misc")]) ! 2987: ! 2988: (define_insn "goto_handler_and_restore" ! 2989: [(unspec_volatile [(const_int 0)] 1)] ! 2990: "" ! 2991: "jmp %%o0+0\;restore" ! 2992: [(set_attr "type" "misc") ! 2993: (set_attr "length" "2")]) ! 2994: ! 2995: ;; find first set. ! 2996: ! 2997: ;; The scan instruction searches from the most significant bit while ffs ! 2998: ;; searches from the least significant bit. The bit index and treatment of ! 2999: ;; zero also differ. It takes at least 7 instructions to get the proper ! 3000: ;; result. Here is an obvious 8 instruction seequence. ! 3001: ! 3002: (define_insn "ffssi2" ! 3003: [(set (match_operand:SI 0 "register_operand" "=&r") ! 3004: (ffs:SI (match_operand:SI 1 "register_operand" "r"))) ! 3005: (clobber (match_scratch:SI 2 "=&r"))] ! 3006: "TARGET_SPARCLITE" ! 3007: "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" ! 3008: [(set_attr "type" "multi") ! 3009: (set_attr "length" "8")]) ! 3010: ! 3011: ;; Split up troublesome insns for better scheduling. */ ! 3012: ! 3013: ;; The following patterns are straightforward. They can be applied ! 3014: ;; either before or after register allocation. ! 3015: ! 3016: (define_split ! 3017: [(set (match_operator 0 "memop" [(match_operand:SI 1 "symbolic_operand" "")]) ! 3018: (match_operand 2 "reg_or_0_operand" "")) ! 3019: (clobber (match_operand:SI 3 "register_operand" ""))] ! 3020: "! flag_pic" ! 3021: [(set (match_dup 3) (high:SI (match_dup 1))) ! 3022: (set (match_op_dup 0 [(lo_sum:SI (match_dup 3) (match_dup 1))]) ! 3023: (match_dup 2))] ! 3024: "") ! 3025: ! 3026: (define_split ! 3027: [(set (match_operator 0 "memop" ! 3028: [(match_operand:SI 1 "immediate_operand" "")]) ! 3029: (match_operand 2 "general_operand" "")) ! 3030: (clobber (match_operand:SI 3 "register_operand" ""))] ! 3031: "flag_pic" ! 3032: [(set (match_op_dup 0 [(match_dup 1)]) ! 3033: (match_dup 2))] ! 3034: " ! 3035: { ! 3036: operands[1] = legitimize_pic_address (operands[1], GET_MODE (operands[0]), ! 3037: operands[3], 0); ! 3038: }") ! 3039: ! 3040: (define_split ! 3041: [(set (match_operand 0 "register_operand" "") ! 3042: (match_operator 1 "memop" ! 3043: [(match_operand:SI 2 "immediate_operand" "")]))] ! 3044: "flag_pic" ! 3045: [(set (match_dup 0) ! 3046: (match_op_dup 1 [(match_dup 2)]))] ! 3047: " ! 3048: { ! 3049: operands[2] = legitimize_pic_address (operands[2], GET_MODE (operands[1]), ! 3050: operands[0], 0); ! 3051: }") ! 3052: ! 3053: ;; Sign- and Zero-extend operations can have symbolic memory operands. ! 3054: ! 3055: (define_split ! 3056: [(set (match_operand 0 "register_operand" "") ! 3057: (match_operator 1 "extend_op" ! 3058: [(match_operator 2 "memop" ! 3059: [(match_operand:SI 3 "immediate_operand" "")])]))] ! 3060: "flag_pic" ! 3061: [(set (match_dup 0) ! 3062: (match_op_dup 1 [(match_op_dup 2 [(match_dup 3)])]))] ! 3063: " ! 3064: { ! 3065: operands[3] = legitimize_pic_address (operands[3], GET_MODE (operands[2]), ! 3066: operands[0], 0); ! 3067: }") ! 3068: ! 3069: (define_split ! 3070: [(set (match_operand:SI 0 "register_operand" "") ! 3071: (match_operand:SI 1 "immediate_operand" ""))] ! 3072: "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF ! 3073: || GET_CODE (operands[1]) == CONST ! 3074: || GET_CODE (operands[1]) == LABEL_REF)" ! 3075: [(set (match_dup 0) (high:SI (match_dup 1))) ! 3076: (set (match_dup 0) ! 3077: (lo_sum:SI (match_dup 0) (match_dup 1)))] ! 3078: "") ! 3079: ! 3080: ;; LABEL_REFs are not modified by `legitimize_pic_address` ! 3081: ;; so do not recurse infinitely in the PIC case. ! 3082: (define_split ! 3083: [(set (match_operand:SI 0 "register_operand" "") ! 3084: (match_operand:SI 1 "immediate_operand" ""))] ! 3085: "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF ! 3086: || GET_CODE (operands[1]) == CONST)" ! 3087: [(set (match_dup 0) (match_dup 1))] ! 3088: " ! 3089: { ! 3090: operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0], 0); ! 3091: }") ! 3092: ! 3093: ;; These split sne/seq insns. The forms of the resulting insns are ! 3094: ;; somewhat bogus, but they avoid extra patterns and show data dependency. ! 3095: ;; Nothing will look at these in detail after splitting has occurred. ! 3096: ! 3097: (define_split ! 3098: [(set (match_operand:SI 0 "register_operand" "") ! 3099: (ne:SI (match_operand:SI 1 "register_operand" "") (const_int 0))) ! 3100: (clobber (reg:CC 0))] ! 3101: "" ! 3102: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) ! 3103: (const_int 0))) ! 3104: (set (match_dup 0) (ltu:SI (reg:CC 0) (const_int 0)))] ! 3105: "") ! 3106: ! 3107: (define_split ! 3108: [(set (match_operand:SI 0 "register_operand" "") ! 3109: (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "") ! 3110: (const_int 0)))) ! 3111: (clobber (reg:CC 0))] ! 3112: "" ! 3113: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) ! 3114: (const_int 0))) ! 3115: (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))] ! 3116: "") ! 3117: ! 3118: (define_split ! 3119: [(set (match_operand:SI 0 "register_operand" "") ! 3120: (eq:SI (match_operand:SI 1 "register_operand" "") (const_int 0))) ! 3121: (clobber (reg:CC 0))] ! 3122: "" ! 3123: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) ! 3124: (const_int 0))) ! 3125: (set (match_dup 0) (geu:SI (reg:CC 0) (const_int 0)))] ! 3126: "") ! 3127: ! 3128: (define_split ! 3129: [(set (match_operand:SI 0 "register_operand" "") ! 3130: (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "") ! 3131: (const_int 0)))) ! 3132: (clobber (reg:CC 0))] ! 3133: "" ! 3134: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) ! 3135: (const_int 0))) ! 3136: (set (match_dup 0) (neg:SI (geu:SI (reg:CC 0) (const_int 0))))] ! 3137: "") ! 3138: ! 3139: (define_split ! 3140: [(set (match_operand:SI 0 "register_operand" "") ! 3141: (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "") ! 3142: (const_int 0)) ! 3143: (match_operand:SI 2 "register_operand" ""))) ! 3144: (clobber (reg:CC 0))] ! 3145: "" ! 3146: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) ! 3147: (const_int 0))) ! 3148: (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) ! 3149: (match_dup 2)))] ! 3150: "") ! 3151: ! 3152: (define_split ! 3153: [(set (match_operand:SI 0 "register_operand" "") ! 3154: (minus:SI (match_operand:SI 2 "register_operand" "") ! 3155: (ne:SI (match_operand:SI 1 "register_operand" "") ! 3156: (const_int 0)))) ! 3157: (clobber (reg:CC 0))] ! 3158: "" ! 3159: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) ! 3160: (const_int 0))) ! 3161: (set (match_dup 0) (minus:SI (match_dup 2) ! 3162: (ltu:SI (reg:CC 0) (const_int 0))))] ! 3163: "") ! 3164: ! 3165: (define_split ! 3166: [(set (match_operand:SI 0 "register_operand" "") ! 3167: (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "") ! 3168: (const_int 0)) ! 3169: (match_operand:SI 2 "register_operand" ""))) ! 3170: (clobber (reg:CC 0))] ! 3171: "" ! 3172: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) ! 3173: (const_int 0))) ! 3174: (set (match_dup 0) (plus:SI (geu:SI (reg:CC 0) (const_int 0)) ! 3175: (match_dup 2)))] ! 3176: "") ! 3177: ! 3178: (define_split ! 3179: [(set (match_operand:SI 0 "register_operand" "") ! 3180: (minus:SI (match_operand:SI 2 "register_operand" "") ! 3181: (eq:SI (match_operand:SI 1 "register_operand" "") ! 3182: (const_int 0)))) ! 3183: (clobber (reg:CC 0))] ! 3184: "" ! 3185: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) ! 3186: (const_int 0))) ! 3187: (set (match_dup 0) (minus:SI (match_dup 2) ! 3188: (geu:SI (reg:CC 0) (const_int 0))))] ! 3189: "") ! 3190: ! 3191: ;; Peepholes go at the end. ! 3192: ! 3193: ;; Optimize consecutive loads or stores into ldd and std when possible. ! 3194: ;; The conditions in which we do this are very restricted and are ! 3195: ;; explained in the code for {registers,memory}_ok_for_ldd functions. ! 3196: ! 3197: (define_peephole ! 3198: [(set (match_operand:SI 0 "register_operand" "=rf") ! 3199: (match_operand:SI 1 "memory_operand" "")) ! 3200: (set (match_operand:SI 2 "register_operand" "=rf") ! 3201: (match_operand:SI 3 "memory_operand" ""))] ! 3202: "registers_ok_for_ldd_peep (operands[0], operands[2]) ! 3203: && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) ! 3204: && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" ! 3205: "ldd %1,%0") ! 3206: ! 3207: (define_peephole ! 3208: [(set (match_operand:SI 0 "memory_operand" "") ! 3209: (match_operand:SI 1 "register_operand" "rf")) ! 3210: (set (match_operand:SI 2 "memory_operand" "") ! 3211: (match_operand:SI 3 "register_operand" "rf"))] ! 3212: "registers_ok_for_ldd_peep (operands[1], operands[3]) ! 3213: && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) ! 3214: && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" ! 3215: "std %1,%0") ! 3216: ! 3217: (define_peephole ! 3218: [(set (match_operand:SF 0 "register_operand" "=fr") ! 3219: (match_operand:SF 1 "memory_operand" "")) ! 3220: (set (match_operand:SF 2 "register_operand" "=fr") ! 3221: (match_operand:SF 3 "memory_operand" ""))] ! 3222: "registers_ok_for_ldd_peep (operands[0], operands[2]) ! 3223: && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) ! 3224: && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" ! 3225: "ldd %1,%0") ! 3226: ! 3227: (define_peephole ! 3228: [(set (match_operand:SF 0 "memory_operand" "") ! 3229: (match_operand:SF 1 "register_operand" "fr")) ! 3230: (set (match_operand:SF 2 "memory_operand" "") ! 3231: (match_operand:SF 3 "register_operand" "fr"))] ! 3232: "registers_ok_for_ldd_peep (operands[1], operands[3]) ! 3233: && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) ! 3234: && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" ! 3235: "std %1,%0") ! 3236: ! 3237: (define_peephole ! 3238: [(set (match_operand:SI 0 "register_operand" "=rf") ! 3239: (match_operand:SI 1 "memory_operand" "")) ! 3240: (set (match_operand:SI 2 "register_operand" "=rf") ! 3241: (match_operand:SI 3 "memory_operand" ""))] ! 3242: "registers_ok_for_ldd_peep (operands[2], operands[0]) ! 3243: && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) ! 3244: && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" ! 3245: "ldd %3,%2") ! 3246: ! 3247: (define_peephole ! 3248: [(set (match_operand:SI 0 "memory_operand" "") ! 3249: (match_operand:SI 1 "register_operand" "rf")) ! 3250: (set (match_operand:SI 2 "memory_operand" "") ! 3251: (match_operand:SI 3 "register_operand" "rf"))] ! 3252: "registers_ok_for_ldd_peep (operands[3], operands[1]) ! 3253: && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) ! 3254: && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" ! 3255: "std %3,%2") ! 3256: ! 3257: (define_peephole ! 3258: [(set (match_operand:SF 0 "register_operand" "=fr") ! 3259: (match_operand:SF 1 "memory_operand" "")) ! 3260: (set (match_operand:SF 2 "register_operand" "=fr") ! 3261: (match_operand:SF 3 "memory_operand" ""))] ! 3262: "registers_ok_for_ldd_peep (operands[2], operands[0]) ! 3263: && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) ! 3264: && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" ! 3265: "ldd %3,%2") ! 3266: ! 3267: (define_peephole ! 3268: [(set (match_operand:SF 0 "memory_operand" "") ! 3269: (match_operand:SF 1 "register_operand" "fr")) ! 3270: (set (match_operand:SF 2 "memory_operand" "") ! 3271: (match_operand:SF 3 "register_operand" "fr"))] ! 3272: "registers_ok_for_ldd_peep (operands[3], operands[1]) ! 3273: && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) ! 3274: && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" ! 3275: "std %3,%2") ! 3276: ! 3277: ;; Optimize the case of following a reg-reg move with a test ! 3278: ;; of reg just moved. Don't allow floating point regs for operand 0 or 1. ! 3279: ;; This can result from a float to fix conversion. ! 3280: ! 3281: (define_peephole ! 3282: [(set (match_operand:SI 0 "register_operand" "=r") ! 3283: (match_operand:SI 1 "register_operand" "r")) ! 3284: (set (reg:CC 0) ! 3285: (compare:CC (match_operand:SI 2 "register_operand" "r") ! 3286: (const_int 0)))] ! 3287: "(rtx_equal_p (operands[2], operands[0]) ! 3288: || rtx_equal_p (operands[2], operands[1])) ! 3289: && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" ! 3290: "orcc %1,%%g0,%0") ! 3291: ! 3292: ;; Do {sign,zero}-extended compares somewhat more efficiently. ! 3293: ;; ??? Is this now the Right Way to do this? Or will SCRATCH ! 3294: ;; eventually have some impact here? ! 3295: ! 3296: (define_peephole ! 3297: [(set (match_operand:HI 0 "register_operand" "") ! 3298: (match_operand:HI 1 "memory_operand" "")) ! 3299: (set (match_operand:SI 2 "register_operand" "") ! 3300: (sign_extend:SI (match_dup 0))) ! 3301: (set (reg:CC 0) ! 3302: (compare:CC (match_dup 2) ! 3303: (const_int 0)))] ! 3304: "" ! 3305: "ldsh %1,%0\;orcc %0,%%g0,%2") ! 3306: ! 3307: (define_peephole ! 3308: [(set (match_operand:QI 0 "register_operand" "") ! 3309: (match_operand:QI 1 "memory_operand" "")) ! 3310: (set (match_operand:SI 2 "register_operand" "") ! 3311: (sign_extend:SI (match_dup 0))) ! 3312: (set (reg:CC 0) ! 3313: (compare:CC (match_dup 2) ! 3314: (const_int 0)))] ! 3315: "" ! 3316: "ldsb %1,%0\;orcc %0,%%g0,%2") ! 3317: ! 3318: (define_peephole ! 3319: [(set (match_operand:HI 0 "register_operand" "") ! 3320: (match_operand:HI 1 "memory_operand" "")) ! 3321: (set (match_operand:SI 2 "register_operand" "") ! 3322: (sign_extend:SI (match_dup 0)))] ! 3323: "dead_or_set_p (insn, operands[0])" ! 3324: "* ! 3325: { ! 3326: warning (\"bad peephole\"); ! 3327: if (! MEM_VOLATILE_P (operands[1])) ! 3328: abort (); ! 3329: return \"ldsh %1,%2\"; ! 3330: }") ! 3331: ! 3332: (define_peephole ! 3333: [(set (match_operand:QI 0 "register_operand" "") ! 3334: (match_operand:QI 1 "memory_operand" "")) ! 3335: (set (match_operand:SI 2 "register_operand" "") ! 3336: (sign_extend:SI (match_dup 0)))] ! 3337: "dead_or_set_p (insn, operands[0])" ! 3338: "* ! 3339: { ! 3340: warning (\"bad peephole\"); ! 3341: if (! MEM_VOLATILE_P (operands[1])) ! 3342: abort (); ! 3343: return \"ldsb %1,%2\"; ! 3344: }") ! 3345: ! 3346: ;; Floating-point move peepholes ! 3347: ! 3348: (define_peephole ! 3349: [(set (match_operand:SI 0 "register_operand" "=r") ! 3350: (lo_sum:SI (match_dup 0) ! 3351: (match_operand:SI 1 "immediate_operand" "i"))) ! 3352: (set (match_operand:DF 2 "register_operand" "=fr") ! 3353: (mem:DF (match_dup 0)))] ! 3354: "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)" ! 3355: "* ! 3356: { ! 3357: /* Go by way of output_move_double in case the register in operand 2 ! 3358: is not properly aligned for ldd. */ ! 3359: operands[1] = gen_rtx (MEM, DFmode, ! 3360: gen_rtx (LO_SUM, SImode, operands[0], operands[1])); ! 3361: operands[0] = operands[2]; ! 3362: return output_move_double (operands); ! 3363: }") ! 3364: ! 3365: (define_peephole ! 3366: [(set (match_operand:SI 0 "register_operand" "=r") ! 3367: (lo_sum:SI (match_dup 0) ! 3368: (match_operand:SI 1 "immediate_operand" "i"))) ! 3369: (set (match_operand:SF 2 "register_operand" "=fr") ! 3370: (mem:SF (match_dup 0)))] ! 3371: "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)" ! 3372: "ld [%0+%%lo(%a1)],%2") ! 3373: ! 3374: ;; Return peepholes. First the "normal" ones ! 3375: ! 3376: ;; ??? There are QImode, HImode, and SImode versions of this pattern. ! 3377: ;; It might be possible to write one more general pattern instead of three. ! 3378: ! 3379: (define_insn "" ! 3380: [(set (match_operand:QI 0 "restore_operand" "") ! 3381: (match_operand:QI 1 "arith_operand" "rI")) ! 3382: (return)] ! 3383: "! TARGET_EPILOGUE" ! 3384: "* ! 3385: { ! 3386: if (current_function_returns_struct) ! 3387: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; ! 3388: else ! 3389: return \"ret\;restore %%g0,%1,%Y0\"; ! 3390: }" ! 3391: [(set_attr "type" "multi")]) ! 3392: ! 3393: (define_insn "" ! 3394: [(set (match_operand:HI 0 "restore_operand" "") ! 3395: (match_operand:HI 1 "arith_operand" "rI")) ! 3396: (return)] ! 3397: "! TARGET_EPILOGUE" ! 3398: "* ! 3399: { ! 3400: if (current_function_returns_struct) ! 3401: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; ! 3402: else ! 3403: return \"ret\;restore %%g0,%1,%Y0\"; ! 3404: }" ! 3405: [(set_attr "type" "multi")]) ! 3406: ! 3407: (define_insn "" ! 3408: [(set (match_operand:SI 0 "restore_operand" "") ! 3409: (match_operand:SI 1 "arith_operand" "rI")) ! 3410: (return)] ! 3411: "! TARGET_EPILOGUE" ! 3412: "* ! 3413: { ! 3414: if (current_function_returns_struct) ! 3415: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; ! 3416: else ! 3417: return \"ret\;restore %%g0,%1,%Y0\"; ! 3418: }" ! 3419: [(set_attr "type" "multi")]) ! 3420: ! 3421: ;; The following pattern is only generated by delayed-branch scheduling, ! 3422: ;; when the insn winds up in the epilogue. This can only happen when ! 3423: ;; ! TARGET_FPU because otherwise fp return values are in %f0. ! 3424: (define_insn "" ! 3425: [(set (match_operand:SF 0 "restore_operand" "r") ! 3426: (match_operand:SF 1 "register_operand" "r")) ! 3427: (return)] ! 3428: "! TARGET_FPU && ! TARGET_EPILOGUE" ! 3429: "* ! 3430: { ! 3431: if (current_function_returns_struct) ! 3432: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; ! 3433: else ! 3434: return \"ret\;restore %%g0,%1,%Y0\"; ! 3435: }" ! 3436: [(set_attr "type" "multi")]) ! 3437: ! 3438: (define_insn "" ! 3439: [(set (match_operand:SI 0 "restore_operand" "") ! 3440: (plus:SI (match_operand:SI 1 "arith_operand" "%r") ! 3441: (match_operand:SI 2 "arith_operand" "rI"))) ! 3442: (return)] ! 3443: "! TARGET_EPILOGUE" ! 3444: "* ! 3445: { ! 3446: if (current_function_returns_struct) ! 3447: return \"jmp %%i7+12\;restore %r1,%2,%Y0\"; ! 3448: else ! 3449: return \"ret\;restore %r1,%2,%Y0\"; ! 3450: }" ! 3451: [(set_attr "type" "multi")]) ! 3452: ! 3453: ;; Turned off because it should never match (subtracting a constant ! 3454: ;; is turned into addition) and because it would do the wrong thing ! 3455: ;; when operand 2 is -4096 (--4096 == 4096 is not a valid immediate). ! 3456: ;;(define_insn "" ! 3457: ;; [(set (match_operand:SI 0 "restore_operand" "") ! 3458: ;; (minus:SI (match_operand:SI 1 "register_operand" "r") ! 3459: ;; (match_operand:SI 2 "small_int" "I"))) ! 3460: ;; (return)] ! 3461: ;; "! TARGET_EPILOGUE" ! 3462: ;; "ret\;restore %1,-(%2),%Y0" ! 3463: ;; [(set_attr "type" "multi")]) ! 3464: ! 3465: ;; The following pattern is only generated by delayed-branch scheduling, ! 3466: ;; when the insn winds up in the epilogue. ! 3467: (define_insn "" ! 3468: [(set (reg:SF 32) ! 3469: (match_operand:SF 0 "register_operand" "f")) ! 3470: (return)] ! 3471: "! TARGET_EPILOGUE" ! 3472: "ret\;fmovs %0,%%f0" ! 3473: [(set_attr "type" "multi")]) ! 3474: ! 3475: ;; Now peepholes to go a call followed by a jump. ! 3476: ! 3477: (define_peephole ! 3478: [(parallel [(set (match_operand 0 "" "") ! 3479: (call (mem:SI (match_operand:SI 1 "call_operand_address" "S,r")) ! 3480: (match_operand 2 "" ""))) ! 3481: (clobber (reg:SI 15))]) ! 3482: (set (pc) (label_ref (match_operand 3 "" "")))] ! 3483: "short_branch (INSN_UID (insn), INSN_UID (operands[3]))" ! 3484: "* ! 3485: { ! 3486: return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\"; ! 3487: }") ! 3488: ! 3489: (define_peephole ! 3490: [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r")) ! 3491: (match_operand 1 "" "")) ! 3492: (clobber (reg:SI 15))]) ! 3493: (set (pc) (label_ref (match_operand 2 "" "")))] ! 3494: "short_branch (INSN_UID (insn), INSN_UID (operands[2]))" ! 3495: "* ! 3496: { ! 3497: return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\"; ! 3498: }") ! 3499: ! 3500: (define_peephole ! 3501: [(parallel [(set (match_operand:SI 0 "register_operand" "=r") ! 3502: (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") ! 3503: (reg:SI 0))) ! 3504: (clobber (reg:CC 0))]) ! 3505: (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))] ! 3506: "" ! 3507: "subxcc %r1,0,%0")
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.