|
|
1.1 root 1: ;;- Machine description for SPARC chip for GNU C compiler 1.1.1.3 ! root 2: ;; Copyright (C) 1987, 88, 89, 92, 93, 1994 Free Software Foundation, Inc. 1.1 root 3: ;; Contributed by Michael Tiemann ([email protected]) 1.1.1.3 ! root 4: ;; 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans, ! 5: ;; at Cygnus Support. 1.1 root 6: 7: ;; This file is part of GNU CC. 8: 9: ;; GNU CC is free software; you can redistribute it and/or modify 10: ;; it under the terms of the GNU General Public License as published by 11: ;; the Free Software Foundation; either version 2, or (at your option) 12: ;; any later version. 13: 14: ;; GNU CC is distributed in the hope that it will be useful, 15: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17: ;; GNU General Public License for more details. 18: 19: ;; You should have received a copy of the GNU General Public License 20: ;; along with GNU CC; see the file COPYING. If not, write to 21: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 22: 23: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. 24: 1.1.1.3 ! root 25: ;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this ! 26: ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name ! 27: ;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding ! 28: ;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of ! 29: ;; 'f' for all DF/TFmode values, including those that are specific to the v8. ! 30: ! 31: ;; Architecture type. Arch32bit includes v7, sparclite, v8. ! 32: ! 33: (define_attr "arch" "arch32bit,arch64bit" ! 34: (const (symbol_ref "sparc_arch_type"))) ! 35: ! 36: ;; CPU type. This is only used for instruction scheduling ! 37: (define_attr "cpu" "cypress,supersparc" ! 38: (const ! 39: (cond [(symbol_ref "TARGET_SUPERSPARC") (const_string "supersparc")] ! 40: (const_string "cypress")))) ! 41: 1.1 root 42: ;; Insn type. Used to default other attribute values. 43: 44: ;; type "unary" insns have one input operand (1) and one output operand (0) 45: ;; type "binary" insns have two input operands (1,2) and one output (0) 46: ;; type "compare" insns have one or two input operands (0,1) and no output 47: ;; type "call_no_delay_slot" is a call followed by an unimp instruction. 48: 49: (define_attr "type" 1.1.1.3 ! root 50: "move,unary,binary,compare,load,store,ialu,shift,uncond_branch,branch,call,call_no_delay_slot,address,imul,fpload,fpstore,fp,fpcmp,fpmul,fpdivs,fpdivd,fpsqrt,cmove,multi,misc" 1.1 root 51: (const_string "binary")) 52: 53: ;; Set true if insn uses call-clobbered intermediate register. 54: (define_attr "use_clobbered" "false,true" 55: (if_then_else (and (eq_attr "type" "address") 56: (match_operand 0 "clobbered_register" "")) 57: (const_string "true") 58: (const_string "false"))) 59: 60: ;; Length (in # of insns). 61: (define_attr "length" "" 62: (cond [(eq_attr "type" "load,fpload") 63: (if_then_else (match_operand 1 "symbolic_memory_operand" "") 64: (const_int 2) (const_int 1)) 65: 66: (eq_attr "type" "store,fpstore") 67: (if_then_else (match_operand 0 "symbolic_memory_operand" "") 68: (const_int 2) (const_int 1)) 69: 70: (eq_attr "type" "address") (const_int 2) 71: 72: (eq_attr "type" "binary") 73: (if_then_else (ior (match_operand 2 "arith_operand" "") 74: (match_operand 2 "arith_double_operand" "")) 75: (const_int 1) (const_int 3)) 76: 77: (eq_attr "type" "multi") (const_int 2) 78: 79: (eq_attr "type" "move,unary") 80: (if_then_else (ior (match_operand 1 "arith_operand" "") 81: (match_operand 1 "arith_double_operand" "")) 82: (const_int 1) (const_int 2))] 83: 84: (const_int 1))) 85: 86: (define_asm_attributes 87: [(set_attr "length" "1") 88: (set_attr "type" "multi")]) 89: 90: ;; Attributes for instruction and branch scheduling 91: 92: (define_attr "in_call_delay" "false,true" 93: (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi") 94: (const_string "false") 95: (eq_attr "type" "load,fpload,store,fpstore") 96: (if_then_else (eq_attr "length" "1") 97: (const_string "true") 98: (const_string "false")) 99: (eq_attr "type" "address") 100: (if_then_else (eq_attr "use_clobbered" "false") 101: (const_string "true") 102: (const_string "false"))] 103: (if_then_else (eq_attr "length" "1") 104: (const_string "true") 105: (const_string "false")))) 106: 107: (define_delay (eq_attr "type" "call") 108: [(eq_attr "in_call_delay" "true") (nil) (nil)]) 109: 110: ;; ??? Should implement the notion of predelay slots for floating point 111: ;; branches. This would allow us to remove the nop always inserted before 112: ;; a floating point branch. 113: 114: ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions 115: ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so. 116: ;; This is because doing so will add several pipeline stalls to the path 117: ;; that the load/store did not come from. Unfortunately, there is no way 118: ;; to prevent fill_eager_delay_slots from using load/store without completely 119: ;; disabling them. For the SPEC benchmark set, this is a serious lose, 120: ;; because it prevents us from moving back the final store of inner loops. 121: 122: (define_attr "in_branch_delay" "false,true" 123: (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") 124: (eq_attr "length" "1")) 125: (const_string "true") 126: (const_string "false"))) 127: 128: (define_attr "in_uncond_branch_delay" "false,true" 129: (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") 130: (eq_attr "length" "1")) 131: (const_string "true") 132: (const_string "false"))) 133: 134: (define_attr "in_annul_branch_delay" "false,true" 135: (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") 136: (eq_attr "length" "1")) 137: (const_string "true") 138: (const_string "false"))) 139: 140: (define_delay (eq_attr "type" "branch") 141: [(eq_attr "in_branch_delay" "true") 142: (nil) (eq_attr "in_annul_branch_delay" "true")]) 143: 144: (define_delay (eq_attr "type" "uncond_branch") 145: [(eq_attr "in_uncond_branch_delay" "true") 146: (nil) (nil)]) 147: 148: ;; Function units of the SPARC 149: 150: ;; (define_function_unit {name} {num-units} {n-users} {test} 151: ;; {ready-delay} {issue-delay} [{conflict-list}]) 152: 153: ;; The integer ALU. 154: ;; (Noted only for documentation; units that take one cycle do not need to 155: ;; be specified.) 156: 157: ;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on 158: ;; the inputs. 159: 160: ;; (define_function_unit "alu" 1 0 161: ;; (eq_attr "type" "unary,binary,move,address") 1 0) 162: 1.1.1.3 ! root 163: ;; ---- cypress CY7C602 scheduling: 1.1 root 164: ;; Memory with load-delay of 1 (i.e., 2 cycle load). 1.1.1.3 ! root 165: (define_function_unit "memory" 1 0 ! 166: (and (eq_attr "type" "load,fpload") (eq_attr "cpu" "cypress")) 2 2) 1.1 root 167: 168: ;; SPARC has two floating-point units: the FP ALU, 169: ;; and the FP MUL/DIV/SQRT unit. 170: ;; Instruction timings on the CY7C602 are as follows 171: ;; FABSs 4 172: ;; FADDs/d 5/5 173: ;; FCMPs/d 4/4 174: ;; FDIVs/d 23/37 175: ;; FMOVs 4 176: ;; FMULs/d 5/7 177: ;; FNEGs 4 178: ;; FSQRTs/d 34/63 179: ;; FSUBs/d 5/5 180: ;; FdTOi/s 5/5 181: ;; FsTOi/d 5/5 182: ;; FiTOs/d 9/5 183: 184: ;; The CY7C602 can only support 2 fp isnsn simultaneously. 185: ;; More insns cause the chip to stall. 186: 1.1.1.3 ! root 187: (define_function_unit "fp_alu" 1 0 ! 188: (and (eq_attr "type" "fp") (eq_attr "cpu" "cypress")) 5 5) ! 189: (define_function_unit "fp_mds" 1 0 ! 190: (and (eq_attr "type" "fpmul") (eq_attr "cpu" "cypress")) 7 7) ! 191: (define_function_unit "fp_mds" 1 0 ! 192: (and (eq_attr "type" "fpdivs,fpdivd") (eq_attr "cpu" "cypress")) 37 37) ! 193: (define_function_unit "fp_mds" 1 0 ! 194: (and (eq_attr "type" "fpsqrt") (eq_attr "cpu" "cypress")) 63 63) ! 195: ! 196: ;; ----- The TMS390Z55 scheduling ! 197: ;; The Supersparc can issue 1 - 3 insns per cycle; here we assume ! 198: ;; three insns/cycle, and hence multiply all costs by three. ! 199: ;; Combinations up to two integer, one ld/st, one fp. ! 200: ;; Memory delivers its result in one cycle to IU, zero cycles to FP ! 201: (define_function_unit "memory" 1 0 ! 202: (and (eq_attr "type" "load") (eq_attr "cpu" "supersparc")) 3 3) ! 203: (define_function_unit "memory" 1 0 ! 204: (and (eq_attr "type" "fpload") (eq_attr "cpu" "supersparc")) 1 3) ! 205: ;; at least one in three instructions can be a mem opt. ! 206: (define_function_unit "memory" 1 0 ! 207: (and (eq_attr "type" "store,fpstore") (eq_attr "cpu" "supersparc")) 1 3) ! 208: ;; at least one in three instructions can be a shift op. ! 209: (define_function_unit "shift" 1 0 ! 210: (and (eq_attr "type" "shift") (eq_attr "cpu" "supersparc")) 1 3) ! 211: ! 212: ;; There are only two write ports to the integer register file ! 213: ;; A store also uses a write port ! 214: (define_function_unit "iwport" 2 0 ! 215: (and (eq_attr "type" "load,store,shift,ialu") (eq_attr "cpu" "supersparc")) 1 3) ! 216: ! 217: ;; Timings; throughput/latency ! 218: ;; FADD 1/3 add/sub, format conv, compar, abs, neg ! 219: ;; FMUL 1/3 ! 220: ;; FDIVs 4/6 ! 221: ;; FDIVd 7/9 ! 222: ;; FSQRTs 6/8 ! 223: ;; FSQRTd 10/12 ! 224: ;; IMUL 4/4 ! 225: ! 226: (define_function_unit "fp_alu" 1 0 ! 227: (and (eq_attr "type" "fp,fpcmp") (eq_attr "cpu" "supersparc")) 9 3) ! 228: (define_function_unit "fp_mds" 1 0 ! 229: (and (eq_attr "type" "fpmul") (eq_attr "cpu" "supersparc")) 9 3) ! 230: (define_function_unit "fp_mds" 1 0 ! 231: (and (eq_attr "type" "fpdivs") (eq_attr "cpu" "supersparc")) 18 12) ! 232: (define_function_unit "fp_mds" 1 0 ! 233: (and (eq_attr "type" "fpdivd") (eq_attr "cpu" "supersparc")) 27 21) ! 234: (define_function_unit "fp_mds" 1 0 ! 235: (and (eq_attr "type" "fpsqrt") (eq_attr "cpu" "supersparc")) 36 30) ! 236: (define_function_unit "fp_mds" 1 0 ! 237: (and (eq_attr "type" "imul") (eq_attr "cpu" "supersparc")) 12 12) 1.1 root 238: 239: ;; Compare instructions. 240: ;; This controls RTL generation and register allocation. 241: 242: ;; We generate RTL for comparisons and branches by having the cmpxx 243: ;; patterns store away the operands. Then, the scc and bcc patterns 244: ;; emit RTL for both the compare and the branch. 245: ;; 246: ;; We do this because we want to generate different code for an sne and 247: ;; seq insn. In those cases, if the second operand of the compare is not 248: ;; const0_rtx, we want to compute the xor of the two operands and test 249: ;; it against zero. 250: ;; 1.1.1.3 ! root 251: ;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match 1.1 root 252: ;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc 253: ;; insns that actually require more than one machine instruction. 254: 255: ;; Put cmpsi first among compare insns so it matches two CONST_INT operands. 256: 257: (define_expand "cmpsi" 258: [(set (reg:CC 0) 259: (compare:CC (match_operand:SI 0 "register_operand" "") 260: (match_operand:SI 1 "arith_operand" "")))] 261: "" 262: " 263: { 264: sparc_compare_op0 = operands[0]; 265: sparc_compare_op1 = operands[1]; 266: DONE; 267: }") 268: 1.1.1.3 ! root 269: (define_expand "cmpdi" ! 270: [(set (reg:CCX 0) ! 271: (compare:CCX (match_operand:DI 0 "register_operand" "") ! 272: (match_operand:DI 1 "arith_double_operand" "")))] ! 273: "TARGET_V9" ! 274: " ! 275: { ! 276: sparc_compare_op0 = operands[0]; ! 277: sparc_compare_op1 = operands[1]; ! 278: DONE; ! 279: }") ! 280: 1.1 root 281: (define_expand "cmpsf" 282: [(set (reg:CCFP 0) 283: (compare:CCFP (match_operand:SF 0 "register_operand" "") 284: (match_operand:SF 1 "register_operand" "")))] 285: "TARGET_FPU" 286: " 287: { 288: sparc_compare_op0 = operands[0]; 289: sparc_compare_op1 = operands[1]; 290: DONE; 291: }") 292: 293: (define_expand "cmpdf" 294: [(set (reg:CCFP 0) 295: (compare:CCFP (match_operand:DF 0 "register_operand" "") 296: (match_operand:DF 1 "register_operand" "")))] 297: "TARGET_FPU" 298: " 299: { 300: sparc_compare_op0 = operands[0]; 301: sparc_compare_op1 = operands[1]; 302: DONE; 303: }") 304: 305: (define_expand "cmptf" 306: [(set (reg:CCFP 0) 307: (compare:CCFP (match_operand:TF 0 "register_operand" "") 308: (match_operand:TF 1 "register_operand" "")))] 309: "TARGET_FPU" 310: " 311: { 312: sparc_compare_op0 = operands[0]; 313: sparc_compare_op1 = operands[1]; 314: DONE; 315: }") 316: 317: ;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this 1.1.1.3 ! root 318: ;; without jumps using the addx/subx instructions. For seq/sne on v9 we use ! 319: ;; the same code as v8 (the addx/subx method has more applications). The ! 320: ;; exception to this is "reg != 0" which can be done in one instruction on v9 ! 321: ;; (so we do it). For the rest, on v9 we use conditional moves; on v8, we do ! 322: ;; branches. ! 323: ! 324: ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they 1.1 root 325: ;; generate addcc/subcc instructions. 326: 1.1.1.3 ! root 327: (define_expand "seqsi_special" ! 328: [(set (match_dup 3) ! 329: (xor:SI (match_operand:SI 1 "register_operand" "") ! 330: (match_operand:SI 2 "register_operand" ""))) 1.1 root 331: (parallel [(set (match_operand:SI 0 "register_operand" "") 332: (eq:SI (match_dup 3) (const_int 0))) 333: (clobber (reg:CC 0))])] 334: "" 335: "{ operands[3] = gen_reg_rtx (SImode); }") 336: 1.1.1.3 ! root 337: (define_expand "seqdi_special" ! 338: [(set (match_dup 3) ! 339: (xor:DI (match_operand:DI 1 "register_operand" "") ! 340: (match_operand:DI 2 "register_operand" ""))) ! 341: (parallel [(set (match_operand:DI 0 "register_operand" "") ! 342: (eq:DI (match_dup 3) (const_int 0))) ! 343: (clobber (reg:CCX 0))])] ! 344: "" ! 345: "{ operands[3] = gen_reg_rtx (DImode); }") ! 346: ! 347: (define_expand "snesi_special" ! 348: [(set (match_dup 3) ! 349: (xor:SI (match_operand:SI 1 "register_operand" "") ! 350: (match_operand:SI 2 "register_operand" ""))) 1.1 root 351: (parallel [(set (match_operand:SI 0 "register_operand" "") 352: (ne:SI (match_dup 3) (const_int 0))) 353: (clobber (reg:CC 0))])] 354: "" 355: "{ operands[3] = gen_reg_rtx (SImode); }") 356: 1.1.1.3 ! root 357: (define_expand "snedi_special" ! 358: [(set (match_dup 3) ! 359: (xor:DI (match_operand:DI 1 "register_operand" "") ! 360: (match_operand:DI 2 "register_operand" ""))) ! 361: (parallel [(set (match_operand:DI 0 "register_operand" "") ! 362: (ne:DI (match_dup 3) (const_int 0))) ! 363: (clobber (reg:CCX 0))])] ! 364: "" ! 365: "{ operands[3] = gen_reg_rtx (DImode); }") ! 366: ! 367: (define_expand "seqdi_special_trunc" ! 368: [(set (match_dup 3) ! 369: (xor:DI (match_operand:DI 1 "register_operand" "") ! 370: (match_operand:DI 2 "register_operand" ""))) ! 371: (parallel [(set (match_operand:SI 0 "register_operand" "") ! 372: (eq:SI (subreg:SI (match_dup 3) 0) (const_int 0))) ! 373: (clobber (reg:CC 0))])] ! 374: "" ! 375: "{ operands[3] = gen_reg_rtx (DImode); }") ! 376: ! 377: (define_expand "snedi_special_trunc" ! 378: [(set (match_dup 3) ! 379: (xor:DI (match_operand:DI 1 "register_operand" "") ! 380: (match_operand:DI 2 "register_operand" ""))) ! 381: (parallel [(set (match_operand:SI 0 "register_operand" "") ! 382: (ne:SI (subreg:SI (match_dup 3) 0) (const_int 0))) ! 383: (clobber (reg:CC 0))])] ! 384: "" ! 385: "{ operands[3] = gen_reg_rtx (DImode); }") ! 386: ! 387: (define_expand "seqsi_special_extend" ! 388: [(set (subreg:SI (match_dup 3) 0) ! 389: (xor:SI (match_operand:SI 1 "register_operand" "") ! 390: (match_operand:SI 2 "register_operand" ""))) ! 391: (parallel [(set (match_operand:DI 0 "register_operand" "") ! 392: (eq:DI (match_dup 3) (const_int 0))) ! 393: (clobber (reg:CCX 0))])] ! 394: "" ! 395: "{ operands[3] = gen_reg_rtx (DImode); }") ! 396: ! 397: (define_expand "snesi_special_extend" ! 398: [(set (subreg:SI (match_dup 3) 0) ! 399: (xor:SI (match_operand:SI 1 "register_operand" "") ! 400: (match_operand:SI 2 "register_operand" ""))) ! 401: (parallel [(set (match_operand:DI 0 "register_operand" "") ! 402: (ne:DI (match_dup 3) (const_int 0))) ! 403: (clobber (reg:CCX 0))])] ! 404: "" ! 405: "{ operands[3] = gen_reg_rtx (DImode); }") ! 406: ! 407: ;; ??? v9: Operand 0 needs a mode, so SImode was chosen. ! 408: ;; However, the code handles both SImode and DImode. 1.1 root 409: (define_expand "seq" 1.1.1.3 ! root 410: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 411: (eq:SI (match_dup 1) (const_int 0)))] 412: "" 413: " 1.1.1.3 ! root 414: { ! 415: if (GET_MODE (sparc_compare_op0) == SImode) ! 416: { ! 417: rtx pat; ! 418: ! 419: if (GET_MODE (operands[0]) == SImode) ! 420: pat = gen_seqsi_special (operands[0], sparc_compare_op0, ! 421: sparc_compare_op1); ! 422: else if (! TARGET_V9) ! 423: FAIL; ! 424: else ! 425: pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0, ! 426: sparc_compare_op1); ! 427: emit_insn (pat); ! 428: DONE; ! 429: } ! 430: else if (GET_MODE (sparc_compare_op0) == DImode) 1.1 root 431: { 1.1.1.3 ! root 432: rtx pat; ! 433: ! 434: if (GET_MODE (operands[0]) == SImode) ! 435: pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0, ! 436: sparc_compare_op1); ! 437: else if (! TARGET_V9) ! 438: FAIL; ! 439: else ! 440: pat = gen_seqdi_special (operands[0], sparc_compare_op0, ! 441: sparc_compare_op1); ! 442: emit_insn (pat); 1.1 root 443: DONE; 444: } 1.1.1.3 ! root 445: else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 446: { ! 447: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); ! 448: emit_insn (gen_sne (operands[0])); ! 449: DONE; ! 450: } ! 451: else if (TARGET_V9) ! 452: { ! 453: if (gen_v9_scc (EQ, operands)) ! 454: DONE; ! 455: /* fall through */ ! 456: } ! 457: operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); 1.1 root 458: }") 459: 1.1.1.3 ! root 460: ;; ??? v9: Operand 0 needs a mode, so SImode was chosen. ! 461: ;; However, the code handles both SImode and DImode. 1.1 root 462: (define_expand "sne" 1.1.1.3 ! root 463: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 464: (ne:SI (match_dup 1) (const_int 0)))] 465: "" 466: " 1.1.1.3 ! root 467: { ! 468: if (GET_MODE (sparc_compare_op0) == SImode) 1.1 root 469: { 1.1.1.3 ! root 470: rtx pat; ! 471: ! 472: if (GET_MODE (operands[0]) == SImode) ! 473: pat = gen_snesi_special (operands[0], sparc_compare_op0, ! 474: sparc_compare_op1); ! 475: else if (! TARGET_V9) ! 476: FAIL; ! 477: else ! 478: pat = gen_snesi_special_extend (operands[0], sparc_compare_op0, ! 479: sparc_compare_op1); ! 480: emit_insn (pat); 1.1 root 481: DONE; 482: } 1.1.1.3 ! root 483: else if (GET_MODE (sparc_compare_op0) == DImode) ! 484: { ! 485: rtx pat; ! 486: ! 487: if (GET_MODE (operands[0]) == SImode) ! 488: pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0, ! 489: sparc_compare_op1); ! 490: else if (! TARGET_V9) ! 491: FAIL; ! 492: else ! 493: pat = gen_snedi_special (operands[0], sparc_compare_op0, ! 494: sparc_compare_op1); ! 495: emit_insn (pat); ! 496: DONE; ! 497: } ! 498: else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 499: { ! 500: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); ! 501: emit_insn (gen_sne (operands[0])); ! 502: DONE; ! 503: } ! 504: else if (TARGET_V9) ! 505: { ! 506: if (gen_v9_scc (NE, operands)) ! 507: DONE; ! 508: /* fall through */ ! 509: } ! 510: operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); 1.1 root 511: }") 512: 513: (define_expand "sgt" 1.1.1.3 ! root 514: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 515: (gt:SI (match_dup 1) (const_int 0)))] 516: "" 517: " 1.1.1.3 ! root 518: { ! 519: if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 520: { ! 521: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); ! 522: emit_insn (gen_sne (operands[0])); ! 523: DONE; ! 524: } ! 525: else if (TARGET_V9) ! 526: { ! 527: if (gen_v9_scc (GT, operands)) ! 528: DONE; ! 529: /* fall through */ ! 530: } ! 531: operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); ! 532: }") 1.1 root 533: 534: (define_expand "slt" 1.1.1.3 ! root 535: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 536: (lt:SI (match_dup 1) (const_int 0)))] 537: "" 538: " 1.1.1.3 ! root 539: { ! 540: if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 541: { ! 542: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); ! 543: emit_insn (gen_sne (operands[0])); ! 544: DONE; ! 545: } ! 546: else if (TARGET_V9) ! 547: { ! 548: if (gen_v9_scc (LT, operands)) ! 549: DONE; ! 550: /* fall through */ ! 551: } ! 552: operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); ! 553: }") 1.1 root 554: 555: (define_expand "sge" 1.1.1.3 ! root 556: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 557: (ge:SI (match_dup 1) (const_int 0)))] 558: "" 559: " 1.1.1.3 ! root 560: { ! 561: if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 562: { ! 563: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); ! 564: emit_insn (gen_sne (operands[0])); ! 565: DONE; ! 566: } ! 567: else if (TARGET_V9) ! 568: { ! 569: if (gen_v9_scc (GE, operands)) ! 570: DONE; ! 571: /* fall through */ ! 572: } ! 573: operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); ! 574: }") 1.1 root 575: 576: (define_expand "sle" 1.1.1.3 ! root 577: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 578: (le:SI (match_dup 1) (const_int 0)))] 579: "" 580: " 1.1.1.3 ! root 581: { ! 582: if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 583: { ! 584: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); ! 585: emit_insn (gen_sne (operands[0])); ! 586: DONE; ! 587: } ! 588: else if (TARGET_V9) ! 589: { ! 590: if (gen_v9_scc (LE, operands)) ! 591: DONE; ! 592: /* fall through */ ! 593: } ! 594: operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); ! 595: }") 1.1 root 596: 597: (define_expand "sgtu" 1.1.1.3 ! root 598: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 599: (gtu:SI (match_dup 1) (const_int 0)))] 600: "" 601: " 602: { 1.1.1.3 ! root 603: if (! TARGET_V9) ! 604: { ! 605: rtx tem; 1.1 root 606: 1.1.1.3 ! root 607: /* We can do ltu easily, so if both operands are registers, swap them and ! 608: do a LTU. */ ! 609: if ((GET_CODE (sparc_compare_op0) == REG ! 610: || GET_CODE (sparc_compare_op0) == SUBREG) ! 611: && (GET_CODE (sparc_compare_op1) == REG ! 612: || GET_CODE (sparc_compare_op1) == SUBREG)) ! 613: { ! 614: tem = sparc_compare_op0; ! 615: sparc_compare_op0 = sparc_compare_op1; ! 616: sparc_compare_op1 = tem; ! 617: emit_insn (gen_sltu (operands[0])); ! 618: DONE; ! 619: } 1.1 root 620: } 1.1.1.3 ! root 621: else ! 622: { ! 623: if (gen_v9_scc (GTU, operands)) ! 624: DONE; ! 625: } ! 626: operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1); 1.1 root 627: }") 628: 629: (define_expand "sltu" 1.1.1.3 ! root 630: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 631: (ltu:SI (match_dup 1) (const_int 0)))] 632: "" 633: " 1.1.1.3 ! root 634: { ! 635: if (TARGET_V9) ! 636: { ! 637: if (gen_v9_scc (LTU, operands)) ! 638: DONE; ! 639: } ! 640: operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1); 1.1 root 641: }") 642: 643: (define_expand "sgeu" 1.1.1.3 ! root 644: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 645: (geu:SI (match_dup 1) (const_int 0)))] 646: "" 647: " 1.1.1.3 ! root 648: { ! 649: if (TARGET_V9) ! 650: { ! 651: if (gen_v9_scc (GEU, operands)) ! 652: DONE; ! 653: } ! 654: operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1); 1.1 root 655: }") 656: 657: (define_expand "sleu" 1.1.1.3 ! root 658: [(set (match_operand:SI 0 "intreg_operand" "") 1.1 root 659: (leu:SI (match_dup 1) (const_int 0)))] 660: "" 661: " 662: { 1.1.1.3 ! root 663: if (! TARGET_V9) ! 664: { ! 665: rtx tem; 1.1 root 666: 1.1.1.3 ! root 667: /* We can do geu easily, so if both operands are registers, swap them and ! 668: do a GEU. */ ! 669: if ((GET_CODE (sparc_compare_op0) == REG ! 670: || GET_CODE (sparc_compare_op0) == SUBREG) ! 671: && (GET_CODE (sparc_compare_op1) == REG ! 672: || GET_CODE (sparc_compare_op1) == SUBREG)) ! 673: { ! 674: tem = sparc_compare_op0; ! 675: sparc_compare_op0 = sparc_compare_op1; ! 676: sparc_compare_op1 = tem; ! 677: emit_insn (gen_sgeu (operands[0])); ! 678: DONE; ! 679: } ! 680: } ! 681: else ! 682: { ! 683: if (gen_v9_scc (LEU, operands)) ! 684: DONE; 1.1 root 685: } 686: operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); 687: }") 688: 689: ;; Now the DEFINE_INSNs for the compare and scc cases. First the compares. 690: 691: (define_insn "" 692: [(set (reg:CC 0) 693: (compare:CC (match_operand:SI 0 "register_operand" "r") 694: (match_operand:SI 1 "arith_operand" "rI")))] 695: "" 696: "cmp %r0,%1" 697: [(set_attr "type" "compare")]) 698: 699: (define_insn "" 700: [(set (reg:CCFPE 0) 701: (compare:CCFPE (match_operand:SF 0 "register_operand" "f") 702: (match_operand:SF 1 "register_operand" "f")))] 1.1.1.3 ! root 703: "! TARGET_V9 && TARGET_FPU" 1.1 root 704: "fcmpes %0,%1" 705: [(set_attr "type" "fpcmp")]) 706: 707: (define_insn "" 708: [(set (reg:CCFPE 0) 1.1.1.3 ! root 709: (compare:CCFPE (match_operand:DF 0 "register_operand" "e") ! 710: (match_operand:DF 1 "register_operand" "e")))] ! 711: "! TARGET_V9 && TARGET_FPU" ! 712: "fcmped %0,%1" 1.1 root 713: [(set_attr "type" "fpcmp")]) 714: 715: (define_insn "" 1.1.1.3 ! root 716: [(set (reg:CCFPE 0) ! 717: (compare:CCFPE (match_operand:TF 0 "register_operand" "e") ! 718: (match_operand:TF 1 "register_operand" "e")))] ! 719: "! TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" ! 720: "fcmpeq %0,%1" 1.1 root 721: [(set_attr "type" "fpcmp")]) 722: 723: (define_insn "" 724: [(set (reg:CCFP 0) 725: (compare:CCFP (match_operand:SF 0 "register_operand" "f") 726: (match_operand:SF 1 "register_operand" "f")))] 1.1.1.3 ! root 727: "! TARGET_V9 && TARGET_FPU" 1.1 root 728: "fcmps %0,%1" 729: [(set_attr "type" "fpcmp")]) 730: 731: (define_insn "" 732: [(set (reg:CCFP 0) 1.1.1.3 ! root 733: (compare:CCFP (match_operand:DF 0 "register_operand" "e") ! 734: (match_operand:DF 1 "register_operand" "e")))] ! 735: "! TARGET_V9 && TARGET_FPU" ! 736: "fcmpd %0,%1" ! 737: [(set_attr "type" "fpcmp")]) ! 738: ! 739: (define_insn "" ! 740: [(set (reg:CCFP 0) ! 741: (compare:CCFP (match_operand:TF 0 "register_operand" "e") ! 742: (match_operand:TF 1 "register_operand" "e")))] ! 743: "! TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 744: "fcmpq %0,%1" 745: [(set_attr "type" "fpcmp")]) 746: 1.1.1.3 ! root 747: (define_insn "" ! 748: [(set (reg:CCX 0) ! 749: (compare:CCX (match_operand:DI 0 "register_operand" "r") ! 750: (match_operand:DI 1 "arith_double_operand" "rHI")))] ! 751: "TARGET_V9" ! 752: "cmp %r0,%1" ! 753: [(set_attr "type" "compare")]) ! 754: ! 755: (define_insn "" ! 756: [(set (match_operand:CCFPE 0 "ccfp_reg_operand" "=c") ! 757: (compare:CCFPE (match_operand:SF 1 "register_operand" "f") ! 758: (match_operand:SF 2 "register_operand" "f")))] ! 759: "TARGET_V9 && TARGET_FPU" ! 760: "fcmpes %0,%1,%2" ! 761: [(set_attr "type" "fpcmp")]) ! 762: ! 763: (define_insn "" ! 764: [(set (match_operand:CCFPE 0 "ccfp_reg_operand" "=c") ! 765: (compare:CCFPE (match_operand:DF 1 "register_operand" "e") ! 766: (match_operand:DF 2 "register_operand" "e")))] ! 767: "TARGET_V9 && TARGET_FPU" ! 768: "fcmped %0,%1,%2" ! 769: [(set_attr "type" "fpcmp")]) ! 770: ! 771: (define_insn "" ! 772: [(set (match_operand:CCFPE 0 "ccfp_reg_operand" "=c") ! 773: (compare:CCFPE (match_operand:TF 1 "register_operand" "e") ! 774: (match_operand:TF 2 "register_operand" "e")))] ! 775: "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" ! 776: "fcmpeq %0,%1,%2" ! 777: [(set_attr "type" "fpcmp")]) ! 778: ! 779: (define_insn "" ! 780: [(set (match_operand:CCFP 0 "ccfp_reg_operand" "=c") ! 781: (compare:CCFP (match_operand:SF 1 "register_operand" "f") ! 782: (match_operand:SF 2 "register_operand" "f")))] ! 783: "TARGET_V9 && TARGET_FPU" ! 784: "fcmps %0,%1,%2" ! 785: [(set_attr "type" "fpcmp")]) ! 786: ! 787: (define_insn "" ! 788: [(set (match_operand:CCFP 0 "ccfp_reg_operand" "=c") ! 789: (compare:CCFP (match_operand:DF 1 "register_operand" "e") ! 790: (match_operand:DF 2 "register_operand" "e")))] ! 791: "TARGET_V9 && TARGET_FPU" ! 792: "fcmpd %0,%1,%2" ! 793: [(set_attr "type" "fpcmp")]) ! 794: ! 795: (define_insn "" ! 796: [(set (match_operand:CCFP 0 "ccfp_reg_operand" "=c") ! 797: (compare:CCFP (match_operand:TF 1 "register_operand" "e") ! 798: (match_operand:TF 2 "register_operand" "e")))] ! 799: "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" ! 800: "fcmpq %0,%1,%2" ! 801: [(set_attr "type" "fpcmp")]) ! 802: 1.1 root 803: ;; The SEQ and SNE patterns are special because they can be done 804: ;; without any branching and do not involve a COMPARE. 805: 806: (define_insn "" 807: [(set (match_operand:SI 0 "register_operand" "=r") 1.1.1.3 ! root 808: (ne:SI (match_operand:SI 1 "register_operand" "r") ! 809: (const_int 0))) 1.1 root 810: (clobber (reg:CC 0))] 811: "" 812: "subcc %%g0,%1,%%g0\;addx %%g0,0,%0" 813: [(set_attr "type" "unary") 814: (set_attr "length" "2")]) 815: 816: (define_insn "" 817: [(set (match_operand:SI 0 "register_operand" "=r") 818: (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r") 819: (const_int 0)))) 820: (clobber (reg:CC 0))] 821: "" 822: "subcc %%g0,%1,%%g0\;subx %%g0,0,%0" 823: [(set_attr "type" "unary") 824: (set_attr "length" "2")]) 825: 826: (define_insn "" 1.1.1.3 ! root 827: [(set (match_operand:DI 0 "register_operand" "=r") ! 828: (ne:DI (match_operand:DI 1 "register_operand" "r") ! 829: (const_int 0))) ! 830: (clobber (reg:CCX 0))] ! 831: "TARGET_V9" ! 832: "mov 0,%0\;movrnz %1,1,%0" ! 833: [(set_attr "type" "unary") ! 834: (set_attr "length" "2")]) ! 835: ! 836: (define_insn "" ! 837: [(set (match_operand:DI 0 "register_operand" "=r") ! 838: (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r") ! 839: (const_int 0)))) ! 840: (clobber (reg:CCX 0))] ! 841: "TARGET_V9" ! 842: "mov 0,%0\;movrnz %1,-1,%0" ! 843: [(set_attr "type" "unary") ! 844: (set_attr "length" "2")]) ! 845: ! 846: (define_insn "" 1.1 root 847: [(set (match_operand:SI 0 "register_operand" "=r") 1.1.1.3 ! root 848: (eq:SI (match_operand:SI 1 "register_operand" "r") ! 849: (const_int 0))) 1.1 root 850: (clobber (reg:CC 0))] 851: "" 852: "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0" 853: [(set_attr "type" "unary") 854: (set_attr "length" "2")]) 855: 856: (define_insn "" 857: [(set (match_operand:SI 0 "register_operand" "=r") 858: (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r") 859: (const_int 0)))) 860: (clobber (reg:CC 0))] 861: "" 862: "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0" 863: [(set_attr "type" "unary") 864: (set_attr "length" "2")]) 865: 1.1.1.3 ! root 866: (define_insn "" ! 867: [(set (match_operand:DI 0 "register_operand" "=r") ! 868: (eq:DI (match_operand:DI 1 "register_operand" "r") ! 869: (const_int 0))) ! 870: (clobber (reg:CCX 0))] ! 871: "TARGET_V9" ! 872: "mov 0,%0\;movrz %1,1,%0" ! 873: [(set_attr "type" "unary") ! 874: (set_attr "length" "2")]) ! 875: ! 876: (define_insn "" ! 877: [(set (match_operand:DI 0 "register_operand" "=r") ! 878: (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r") ! 879: (const_int 0)))) ! 880: (clobber (reg:CCX 0))] ! 881: "TARGET_V9" ! 882: "mov 0,%0\;movrz %1,-1,%0" ! 883: [(set_attr "type" "unary") ! 884: (set_attr "length" "2")]) ! 885: 1.1 root 886: ;; We can also do (x + (i == 0)) and related, so put them in. 1.1.1.3 ! root 887: ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode ! 888: ;; versions for v9. 1.1 root 889: 890: (define_insn "" 891: [(set (match_operand:SI 0 "register_operand" "=r") 892: (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r") 893: (const_int 0)) 894: (match_operand:SI 2 "register_operand" "r"))) 895: (clobber (reg:CC 0))] 896: "" 897: "subcc %%g0,%1,%%g0\;addx %2,0,%0" 898: [(set_attr "length" "2")]) 899: 900: (define_insn "" 901: [(set (match_operand:SI 0 "register_operand" "=r") 902: (minus:SI (match_operand:SI 2 "register_operand" "r") 903: (ne:SI (match_operand:SI 1 "register_operand" "r") 904: (const_int 0)))) 905: (clobber (reg:CC 0))] 906: "" 907: "subcc %%g0,%1,%%g0\;subx %2,0,%0" 908: [(set_attr "length" "2")]) 909: 910: (define_insn "" 911: [(set (match_operand:SI 0 "register_operand" "=r") 912: (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r") 913: (const_int 0)) 914: (match_operand:SI 2 "register_operand" "r"))) 915: (clobber (reg:CC 0))] 916: "" 917: "subcc %%g0,%1,%%g0\;subx %2,-1,%0" 918: [(set_attr "length" "2")]) 919: 920: (define_insn "" 921: [(set (match_operand:SI 0 "register_operand" "=r") 922: (minus:SI (match_operand:SI 2 "register_operand" "r") 923: (eq:SI (match_operand:SI 1 "register_operand" "r") 924: (const_int 0)))) 925: (clobber (reg:CC 0))] 926: "" 927: "subcc %%g0,%1,%%g0\;addx %2,-1,%0" 928: [(set_attr "length" "2")]) 929: 1.1.1.3 ! root 930: ;; We can also do GEU and LTU directly, but these operate after a compare. ! 931: ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode ! 932: ;; versions for v9. 1.1 root 933: 934: (define_insn "" 935: [(set (match_operand:SI 0 "register_operand" "=r") 936: (ltu:SI (reg:CC 0) (const_int 0)))] 937: "" 938: "addx %%g0,0,%0" 939: [(set_attr "type" "misc")]) 940: 941: (define_insn "" 942: [(set (match_operand:SI 0 "register_operand" "=r") 943: (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))] 944: "" 945: "subx %%g0,0,%0" 946: [(set_attr "type" "misc")]) 947: 948: ;; ??? Combine should canonicalize these next two to the same pattern. 949: (define_insn "" 950: [(set (match_operand:SI 0 "register_operand" "=r") 951: (minus:SI (neg:SI (ltu:SI (reg:CC 0) (const_int 0))) 952: (match_operand:SI 1 "arith_operand" "rI")))] 953: "" 954: "subx %%g0,%1,%0" 955: [(set_attr "type" "unary")]) 956: 957: (define_insn "" 958: [(set (match_operand:SI 0 "register_operand" "=r") 959: (neg:SI (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 960: (match_operand:SI 1 "arith_operand" "rI"))))] 961: "" 962: "subx %%g0,%1,%0" 963: [(set_attr "type" "unary")]) 964: 965: (define_insn "" 966: [(set (match_operand:SI 0 "register_operand" "=r") 967: (geu:SI (reg:CC 0) (const_int 0)))] 968: "" 969: "subx %%g0,-1,%0" 970: [(set_attr "type" "misc")]) 971: 972: (define_insn "" 973: [(set (match_operand:SI 0 "register_operand" "=r") 974: (neg:SI (geu:SI (reg:CC 0) (const_int 0))))] 975: "" 976: "addx %%g0,-1,%0" 977: [(set_attr "type" "misc")]) 978: 979: ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in. 1.1.1.3 ! root 980: ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode ! 981: ;; versions for v9. 1.1 root 982: 983: (define_insn "" 984: [(set (match_operand:SI 0 "register_operand" "=r") 985: (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 986: (match_operand:SI 1 "arith_operand" "rI")))] 987: "" 988: "addx %%g0,%1,%0" 989: [(set_attr "type" "unary")]) 990: 991: (define_insn "" 992: [(set (match_operand:SI 0 "register_operand" "=r") 993: (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 994: (plus:SI (match_operand:SI 1 "arith_operand" "%r") 995: (match_operand:SI 2 "arith_operand" "rI"))))] 996: "" 997: "addx %1,%2,%0") 998: 999: (define_insn "" 1000: [(set (match_operand:SI 0 "register_operand" "=r") 1001: (minus:SI (match_operand:SI 1 "register_operand" "r") 1002: (ltu:SI (reg:CC 0) (const_int 0))))] 1003: "" 1004: "subx %1,0,%0" 1005: [(set_attr "type" "unary")]) 1006: 1007: ;; ??? Combine should canonicalize these next two to the same pattern. 1008: (define_insn "" 1009: [(set (match_operand:SI 0 "register_operand" "=r") 1010: (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") 1011: (match_operand:SI 2 "arith_operand" "rI")) 1012: (ltu:SI (reg:CC 0) (const_int 0))))] 1013: "" 1014: "subx %1,%2,%0") 1015: 1016: (define_insn "" 1017: [(set (match_operand:SI 0 "register_operand" "=r") 1018: (minus:SI (match_operand:SI 1 "register_operand" "r") 1019: (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 1020: (match_operand:SI 2 "arith_operand" "rI"))))] 1021: "" 1022: "subx %1,%2,%0") 1023: 1024: (define_insn "" 1025: [(set (match_operand:SI 0 "register_operand" "=r") 1026: (plus:SI (geu:SI (reg:CC 0) (const_int 0)) 1027: (match_operand:SI 1 "register_operand" "r")))] 1028: "" 1029: "subx %1,-1,%0" 1030: [(set_attr "type" "unary")]) 1031: 1032: (define_insn "" 1033: [(set (match_operand:SI 0 "register_operand" "=r") 1034: (minus:SI (match_operand:SI 1 "register_operand" "r") 1035: (geu:SI (reg:CC 0) (const_int 0))))] 1036: "" 1037: "addx %1,-1,%0" 1038: [(set_attr "type" "unary")]) 1039: 1.1.1.3 ! root 1040: ;; Now we have the generic scc insns. ! 1041: ;; !v9: These will be done using a jump. ! 1042: ;; v9: Use conditional moves which are defined elsewhere. 1.1 root 1043: ;; We have to exclude the cases above, since we will not want combine to 1044: ;; turn something that does not require a jump into something that does. 1.1.1.3 ! root 1045: 1.1 root 1046: (define_insn "" 1047: [(set (match_operand:SI 0 "register_operand" "=r") 1048: (match_operator:SI 1 "noov_compare_op" [(reg 0) (const_int 0)]))] 1049: "" 1050: "* return output_scc_insn (operands, insn); " 1051: [(set_attr "type" "multi") 1052: (set_attr "length" "3")]) 1.1.1.3 ! root 1053: ! 1054: (define_insn "" ! 1055: [(set (match_operand:DI 0 "register_operand" "=r") ! 1056: (match_operator:DI 1 "noov_compare_op" [(reg 0) (const_int 0)]))] ! 1057: "TARGET_V9" ! 1058: "* return output_scc_insn (operands, insn); " ! 1059: [(set_attr "type" "multi") ! 1060: (set_attr "length" "3")]) 1.1 root 1061: 1062: ;; These control RTL generation for conditional jump insns 1063: 1.1.1.3 ! root 1064: ;; The quad-word fp compare library routines all return nonzero to indicate ! 1065: ;; true, which is different from the equivalent libgcc routines, so we must ! 1066: ;; handle them specially here. ! 1067: 1.1 root 1068: (define_expand "beq" 1069: [(set (pc) 1070: (if_then_else (eq (match_dup 1) (const_int 0)) 1071: (label_ref (match_operand 0 "" "")) 1072: (pc)))] 1073: "" 1074: " 1.1.1.3 ! root 1075: { ! 1076: if (TARGET_V9 && sparc_compare_op1 == const0_rtx ! 1077: && GET_CODE (sparc_compare_op0) == REG ! 1078: && GET_MODE (sparc_compare_op0) == DImode) ! 1079: { ! 1080: emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]); ! 1081: DONE; ! 1082: } ! 1083: else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 1084: { ! 1085: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); ! 1086: emit_jump_insn (gen_bne (operands[0])); ! 1087: DONE; ! 1088: } ! 1089: operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); ! 1090: }") 1.1 root 1091: 1092: (define_expand "bne" 1093: [(set (pc) 1094: (if_then_else (ne (match_dup 1) (const_int 0)) 1095: (label_ref (match_operand 0 "" "")) 1096: (pc)))] 1097: "" 1098: " 1.1.1.3 ! root 1099: { ! 1100: if (TARGET_V9 && sparc_compare_op1 == const0_rtx ! 1101: && GET_CODE (sparc_compare_op0) == REG ! 1102: && GET_MODE (sparc_compare_op0) == DImode) ! 1103: { ! 1104: emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]); ! 1105: DONE; ! 1106: } ! 1107: else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 1108: { ! 1109: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); ! 1110: emit_jump_insn (gen_bne (operands[0])); ! 1111: DONE; ! 1112: } ! 1113: operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); ! 1114: }") 1.1 root 1115: 1116: (define_expand "bgt" 1117: [(set (pc) 1118: (if_then_else (gt (match_dup 1) (const_int 0)) 1119: (label_ref (match_operand 0 "" "")) 1120: (pc)))] 1121: "" 1122: " 1.1.1.3 ! root 1123: { ! 1124: if (TARGET_V9 && sparc_compare_op1 == const0_rtx ! 1125: && GET_CODE (sparc_compare_op0) == REG ! 1126: && GET_MODE (sparc_compare_op0) == DImode) ! 1127: { ! 1128: emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]); ! 1129: DONE; ! 1130: } ! 1131: else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 1132: { ! 1133: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); ! 1134: emit_jump_insn (gen_bne (operands[0])); ! 1135: DONE; ! 1136: } ! 1137: operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); ! 1138: }") 1.1 root 1139: 1140: (define_expand "bgtu" 1141: [(set (pc) 1142: (if_then_else (gtu (match_dup 1) (const_int 0)) 1143: (label_ref (match_operand 0 "" "")) 1144: (pc)))] 1145: "" 1146: " 1147: { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1); 1148: }") 1149: 1150: (define_expand "blt" 1151: [(set (pc) 1152: (if_then_else (lt (match_dup 1) (const_int 0)) 1153: (label_ref (match_operand 0 "" "")) 1154: (pc)))] 1155: "" 1156: " 1.1.1.3 ! root 1157: { ! 1158: if (TARGET_V9 && sparc_compare_op1 == const0_rtx ! 1159: && GET_CODE (sparc_compare_op0) == REG ! 1160: && GET_MODE (sparc_compare_op0) == DImode) ! 1161: { ! 1162: emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]); ! 1163: DONE; ! 1164: } ! 1165: else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 1166: { ! 1167: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); ! 1168: emit_jump_insn (gen_bne (operands[0])); ! 1169: DONE; ! 1170: } ! 1171: operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); ! 1172: }") 1.1 root 1173: 1174: (define_expand "bltu" 1175: [(set (pc) 1176: (if_then_else (ltu (match_dup 1) (const_int 0)) 1177: (label_ref (match_operand 0 "" "")) 1178: (pc)))] 1179: "" 1180: " 1181: { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1); 1182: }") 1183: 1184: (define_expand "bge" 1185: [(set (pc) 1186: (if_then_else (ge (match_dup 1) (const_int 0)) 1187: (label_ref (match_operand 0 "" "")) 1188: (pc)))] 1189: "" 1190: " 1.1.1.3 ! root 1191: { ! 1192: if (TARGET_V9 && sparc_compare_op1 == const0_rtx ! 1193: && GET_CODE (sparc_compare_op0) == REG ! 1194: && GET_MODE (sparc_compare_op0) == DImode) ! 1195: { ! 1196: emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]); ! 1197: DONE; ! 1198: } ! 1199: else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 1200: { ! 1201: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); ! 1202: emit_jump_insn (gen_bne (operands[0])); ! 1203: DONE; ! 1204: } ! 1205: operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); ! 1206: }") 1.1 root 1207: 1208: (define_expand "bgeu" 1209: [(set (pc) 1210: (if_then_else (geu (match_dup 1) (const_int 0)) 1211: (label_ref (match_operand 0 "" "")) 1212: (pc)))] 1213: "" 1214: " 1215: { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1); 1216: }") 1217: 1218: (define_expand "ble" 1219: [(set (pc) 1220: (if_then_else (le (match_dup 1) (const_int 0)) 1221: (label_ref (match_operand 0 "" "")) 1222: (pc)))] 1223: "" 1224: " 1.1.1.3 ! root 1225: { ! 1226: if (TARGET_V9 && sparc_compare_op1 == const0_rtx ! 1227: && GET_CODE (sparc_compare_op0) == REG ! 1228: && GET_MODE (sparc_compare_op0) == DImode) ! 1229: { ! 1230: emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]); ! 1231: DONE; ! 1232: } ! 1233: else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) ! 1234: { ! 1235: emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); ! 1236: emit_jump_insn (gen_bne (operands[0])); ! 1237: DONE; ! 1238: } ! 1239: operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); ! 1240: }") 1.1 root 1241: 1242: (define_expand "bleu" 1243: [(set (pc) 1244: (if_then_else (leu (match_dup 1) (const_int 0)) 1245: (label_ref (match_operand 0 "" "")) 1246: (pc)))] 1247: "" 1248: " 1249: { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); 1250: }") 1251: 1252: ;; Now match both normal and inverted jump. 1253: 1254: (define_insn "" 1255: [(set (pc) 1256: (if_then_else (match_operator 0 "noov_compare_op" 1257: [(reg 0) (const_int 0)]) 1258: (label_ref (match_operand 1 "" "")) 1259: (pc)))] 1260: "" 1261: "* 1262: { 1.1.1.3 ! root 1263: return output_cbranch (operands[0], 0, 1, 0, 1.1 root 1264: final_sequence && INSN_ANNULLED_BRANCH_P (insn), 1265: ! final_sequence); 1266: }" 1267: [(set_attr "type" "branch")]) 1268: 1269: (define_insn "" 1270: [(set (pc) 1271: (if_then_else (match_operator 0 "noov_compare_op" 1272: [(reg 0) (const_int 0)]) 1273: (pc) 1274: (label_ref (match_operand 1 "" ""))))] 1275: "" 1276: "* 1277: { 1.1.1.3 ! root 1278: return output_cbranch (operands[0], 0, 1, 1, 1.1 root 1279: final_sequence && INSN_ANNULLED_BRANCH_P (insn), 1280: ! final_sequence); 1281: }" 1282: [(set_attr "type" "branch")]) 1283: 1.1.1.3 ! root 1284: (define_insn "" ! 1285: [(set (pc) ! 1286: (if_then_else (match_operator 0 "comparison_operator" ! 1287: [(match_operand:CCFP 1 "ccfp_reg_operand" "c") ! 1288: (const_int 0)]) ! 1289: (label_ref (match_operand 2 "" "")) ! 1290: (pc)))] ! 1291: "TARGET_V9" ! 1292: "* 1.1 root 1293: { 1.1.1.3 ! root 1294: return output_cbranch (operands[0], operands[1], 2, 0, ! 1295: final_sequence && INSN_ANNULLED_BRANCH_P (insn), ! 1296: ! final_sequence); ! 1297: }" ! 1298: [(set_attr "type" "branch")]) 1.1 root 1299: 1.1.1.2 root 1300: (define_insn "" 1.1.1.3 ! root 1301: [(set (pc) ! 1302: (if_then_else (match_operator 0 "comparison_operator" ! 1303: [(match_operand:CCFP 1 "ccfp_reg_operand" "c") ! 1304: (const_int 0)]) ! 1305: (pc) ! 1306: (label_ref (match_operand 2 "" ""))))] ! 1307: "TARGET_V9" ! 1308: "* ! 1309: { ! 1310: return output_cbranch (operands[0], operands[1], 2, 1, ! 1311: final_sequence && INSN_ANNULLED_BRANCH_P (insn), ! 1312: ! final_sequence); ! 1313: }" ! 1314: [(set_attr "type" "branch")]) ! 1315: ! 1316: (define_insn "" ! 1317: [(set (pc) ! 1318: (if_then_else (match_operator 0 "comparison_operator" ! 1319: [(match_operand:CCFPE 1 "ccfp_reg_operand" "c") ! 1320: (const_int 0)]) ! 1321: (label_ref (match_operand 2 "" "")) ! 1322: (pc)))] ! 1323: "TARGET_V9" ! 1324: "* ! 1325: { ! 1326: return output_cbranch (operands[0], operands[1], 2, 0, ! 1327: final_sequence && INSN_ANNULLED_BRANCH_P (insn), ! 1328: ! final_sequence); ! 1329: }" ! 1330: [(set_attr "type" "branch")]) ! 1331: ! 1332: (define_insn "" ! 1333: [(set (pc) ! 1334: (if_then_else (match_operator 0 "comparison_operator" ! 1335: [(match_operand:CCFPE 1 "ccfp_reg_operand" "c") ! 1336: (const_int 0)]) ! 1337: (pc) ! 1338: (label_ref (match_operand 2 "" ""))))] ! 1339: "TARGET_V9" ! 1340: "* ! 1341: { ! 1342: return output_cbranch (operands[0], operands[1], 2, 1, ! 1343: final_sequence && INSN_ANNULLED_BRANCH_P (insn), ! 1344: ! final_sequence); ! 1345: }" ! 1346: [(set_attr "type" "branch")]) ! 1347: ! 1348: ;; Sparc V9-specific jump insns. None of these are guaranteed to be ! 1349: ;; in the architecture. ! 1350: ! 1351: ;; There are no 32 bit brreg insns. ! 1352: ! 1353: (define_insn "" ! 1354: [(set (pc) ! 1355: (if_then_else (match_operator 0 "v9_regcmp_op" ! 1356: [(match_operand:DI 1 "register_operand" "r") ! 1357: (const_int 0)]) ! 1358: (label_ref (match_operand 2 "" "")) ! 1359: (pc)))] ! 1360: "TARGET_V9" ! 1361: "* ! 1362: { ! 1363: return output_v9branch (operands[0], 1, 2, 0, ! 1364: final_sequence && INSN_ANNULLED_BRANCH_P (insn), ! 1365: ! final_sequence); ! 1366: }" ! 1367: [(set_attr "type" "branch")]) ! 1368: ! 1369: (define_insn "" ! 1370: [(set (pc) ! 1371: (if_then_else (match_operator 0 "v9_regcmp_op" ! 1372: [(match_operand:DI 1 "register_operand" "r") ! 1373: (const_int 0)]) ! 1374: (pc) ! 1375: (label_ref (match_operand 2 "" ""))))] ! 1376: "TARGET_V9" ! 1377: "* ! 1378: { ! 1379: return output_v9branch (operands[0], 1, 2, 1, ! 1380: final_sequence && INSN_ANNULLED_BRANCH_P (insn), ! 1381: ! final_sequence); ! 1382: }" ! 1383: [(set_attr "type" "branch")]) ! 1384: ! 1385: ;; Esoteric move insns (lo_sum, high, pic). ! 1386: ! 1387: (define_insn "" ! 1388: [(set (match_operand:SI 0 "register_operand" "=r") ! 1389: (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 1390: (match_operand:SI 2 "immediate_operand" "in")))] ! 1391: "" ! 1392: ;; V9 needs "add" because of the code models. We still use "or" for v8 ! 1393: ;; so we can compare the old compiler with the new. ! 1394: "* return TARGET_V9 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";" ! 1395: ;; Need to set length for this arith insn because operand2 ! 1396: ;; is not an "arith_operand". ! 1397: [(set_attr "length" "1")]) ! 1398: ! 1399: ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not ! 1400: ;; confuse them with real addresses. ! 1401: (define_insn "" ! 1402: [(set (match_operand:SI 0 "register_operand" "=r") ! 1403: (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 1404: (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))] ! 1405: "" ! 1406: ;; V9 needs "add" because of the code models. We still use "or" for v8 ! 1407: ;; so we can compare the old compiler with the new. ! 1408: "* return TARGET_V9 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";" ! 1409: ;; Need to set length for this arith insn because operand2 ! 1410: ;; is not an "arith_operand". ! 1411: [(set_attr "length" "1")]) ! 1412: ! 1413: ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not ! 1414: ;; confuse them with real addresses. ! 1415: (define_insn "" ! 1416: [(set (match_operand:SI 0 "register_operand" "=r") ! 1417: (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))] ! 1418: "check_pic (1)" ! 1419: "sethi %%hi(%a1),%0" ! 1420: [(set_attr "type" "move") ! 1421: (set_attr "length" "1")]) ! 1422: ! 1423: (define_insn "" ! 1424: [(set (match_operand:SI 0 "register_operand" "=r") ! 1425: (high:SI (match_operand 1 "" "")))] ! 1426: "check_pic (1)" ! 1427: "sethi %%hi(%a1),%0" ! 1428: [(set_attr "type" "move") ! 1429: (set_attr "length" "1")]) ! 1430: ! 1431: (define_insn "" ! 1432: [(set (match_operand:HI 0 "register_operand" "=r") ! 1433: (high:HI (match_operand 1 "" "")))] ! 1434: "check_pic (1)" ! 1435: "sethi %%hi(%a1),%0" ! 1436: [(set_attr "type" "move") ! 1437: (set_attr "length" "1")]) ! 1438: ! 1439: ;; Special pic pattern, for loading the address of a label into a register. ! 1440: ;; It clobbers o7 because the call puts the return address (i.e. pc value) ! 1441: ;; there. ! 1442: ! 1443: (define_insn "" ! 1444: [(set (match_operand:SI 0 "register_operand" "=r") ! 1445: (match_operand:SI 1 "move_pic_label" "i")) ! 1446: (set (reg:SI 15) (pc))] ! 1447: "" ! 1448: "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0" ! 1449: [(set_attr "type" "multi") ! 1450: (set_attr "length" "4")]) ! 1451: ! 1452: ;; v9 special pic pattern, for loading the address of a label into a register. ! 1453: ! 1454: (define_insn "" ! 1455: [(set (match_operand:DI 0 "register_operand" "=r") ! 1456: (match_operand:DI 1 "move_pic_label" "i")) ! 1457: (set (reg:DI 15) (pc))] ! 1458: "TARGET_V9" ! 1459: "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0" ! 1460: [(set_attr "type" "multi") ! 1461: (set_attr "length" "4")]) ! 1462: ! 1463: (define_insn "" ! 1464: [(set (match_operand:DI 0 "register_operand" "=r") ! 1465: (lo_sum:DI (match_operand:DI 1 "register_operand" "0") ! 1466: (match_operand:DI 2 "immediate_operand" "in")))] ! 1467: "! TARGET_V9" ! 1468: "* ! 1469: { ! 1470: /* Don't output a 64 bit constant, since we can't trust the assembler to ! 1471: handle it correctly. */ ! 1472: if (GET_CODE (operands[2]) == CONST_DOUBLE) ! 1473: operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2])); ! 1474: return \"or %R1,%%lo(%a2),%R0\"; ! 1475: }" ! 1476: ;; Need to set length for this arith insn because operand2 ! 1477: ;; is not an "arith_operand". ! 1478: [(set_attr "length" "1")]) ! 1479: ! 1480: ;; ??? Gas does not handle %lo(DI), so we use the same code for ! TARGET_V9. ! 1481: ;; ??? The previous comment is obsolete. ! 1482: ;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add? ! 1483: ! 1484: (define_insn "" ! 1485: [(set (match_operand:DI 0 "register_operand" "=r") ! 1486: (lo_sum:DI (match_operand:DI 1 "register_operand" "0") ! 1487: (match_operand:DI 2 "immediate_operand" "in")))] ! 1488: "TARGET_V9" ! 1489: "* ! 1490: { ! 1491: /* Don't output a 64 bit constant, since we can't trust the assembler to ! 1492: handle it correctly. */ ! 1493: if (GET_CODE (operands[2]) == CONST_DOUBLE) ! 1494: operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2])); ! 1495: /* Note that we use add here. This is important because Medium/Anywhere ! 1496: code model support depends on it. */ ! 1497: return \"add %1,%%lo(%a2),%0\"; ! 1498: }" ! 1499: ;; Need to set length for this arith insn because operand2 ! 1500: ;; is not an "arith_operand". ! 1501: [(set_attr "length" "1")]) ! 1502: ! 1503: (define_insn "" ! 1504: [(set (match_operand:DI 0 "register_operand" "=r") ! 1505: (high:DI (match_operand 1 "" "")))] ! 1506: "! TARGET_V9 && check_pic (1)" ! 1507: "* ! 1508: { ! 1509: rtx op0 = operands[0]; ! 1510: rtx op1 = operands[1]; ! 1511: ! 1512: if (GET_CODE (op1) == CONST_INT) ! 1513: { ! 1514: operands[0] = operand_subword (op0, 1, 0, DImode); ! 1515: output_asm_insn (\"sethi %%hi(%a1),%0\", operands); ! 1516: ! 1517: operands[0] = operand_subword (op0, 0, 0, DImode); ! 1518: if (INTVAL (op1) < 0) ! 1519: return \"mov -1,%0\"; ! 1520: else ! 1521: return \"mov 0,%0\"; ! 1522: } ! 1523: else if (GET_CODE (op1) == CONST_DOUBLE) ! 1524: { ! 1525: operands[0] = operand_subword (op0, 1, 0, DImode); ! 1526: operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1)); ! 1527: output_asm_insn (\"sethi %%hi(%a1),%0\", operands); ! 1528: ! 1529: operands[0] = operand_subword (op0, 0, 0, DImode); ! 1530: operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1)); ! 1531: return singlemove_string (operands); ! 1532: } ! 1533: else ! 1534: abort (); ! 1535: return \"\"; ! 1536: }" ! 1537: [(set_attr "type" "move") ! 1538: (set_attr "length" "2")]) ! 1539: ! 1540: ;;; ??? This pattern originally clobbered a scratch register. However, this ! 1541: ;;; is illegal, the movdi pattern may not use a temp register because it ! 1542: ;;; may be called from reload to reload a DImode value. In that case, we ! 1543: ;;; end up with a scratch register that never gets allocated. To avoid this, ! 1544: ;;; we use global register 1 which is never otherwise used by gcc as a temp. ! 1545: ;;; The correct solution here might be to force DImode constants to memory, ! 1546: ;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg ! 1547: ;;; 1 will then no longer need to be considered a fixed reg. ! 1548: ! 1549: ;;; Gas doesn't have any 64 bit constant support, so don't use %uhi and %ulo ! 1550: ;;; on constants. Symbols have to be handled by the linker, so we must use ! 1551: ;;; %uhi and %ulo for them, but gas will handle these correctly. ! 1552: ;;; ??? This comment is obsolete, gas handles them now. ! 1553: ! 1554: (define_insn "" ! 1555: [(set (match_operand:DI 0 "register_operand" "=r") ! 1556: (high:DI (match_operand 1 "const_double_operand" ""))) ! 1557: (clobber (reg:DI 1))] ! 1558: "TARGET_V9 && check_pic (1)" ! 1559: "* ! 1560: { ! 1561: rtx high, low; ! 1562: ! 1563: split_double (operands[1], &high, &low); ! 1564: ! 1565: if (high == const0_rtx) ! 1566: { ! 1567: operands[1] = low; ! 1568: output_asm_insn (\"sethi %%hi(%a1),%0\", operands); ! 1569: } ! 1570: else ! 1571: { ! 1572: operands[1] = high; ! 1573: output_asm_insn (singlemove_string (operands), operands); ! 1574: ! 1575: operands[1] = low; ! 1576: output_asm_insn (\"sllx %0,32,%0\", operands); ! 1577: if (low != const0_rtx) ! 1578: output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands); ! 1579: } ! 1580: }" ! 1581: [(set_attr "type" "move") ! 1582: (set_attr "length" "5")]) ! 1583: ! 1584: ;; Most of the required support for the various code models is here. ! 1585: ;; We can do this because sparcs need the high insn to load the address. We ! 1586: ;; just need to get high to do the right thing for each code model. Then each ! 1587: ;; uses the same "%X+%lo(...)" in the load/store insn. ! 1588: ! 1589: ;; When TARGET_MEDLOW, assume that the upper 32 bits of symbol addresses are ! 1590: ;; always 0. ! 1591: ;; When TARGET_MEDANY, the upper 32 bits of function addresses are 0. ! 1592: ;; The data segment has a maximum size of 32 bits, but may be located anywhere. ! 1593: ;; MEDANY_BASE_REG contains the start address, currently %g4. ! 1594: ;; When TARGET_FULLANY, symbolic addresses are 64 bits. ! 1595: ! 1596: (define_insn "" ! 1597: [(set (match_operand:DI 0 "register_operand" "=r") ! 1598: (high:DI (match_operand 1 "" ""))) ! 1599: ;; ??? Why the clobber? ! 1600: (clobber (reg:DI 1))] ! 1601: "TARGET_MEDLOW && check_pic (1)" ! 1602: "sethi %%hi(%a1),%0" ! 1603: [(set_attr "type" "move") ! 1604: (set_attr "length" "1")]) ! 1605: ! 1606: ;; WARNING: %0 gets %hi(%1)+%g4. ! 1607: ;; You cannot OR in %lo(%1), it must be added in. ! 1608: ! 1609: (define_insn "" ! 1610: [(set (match_operand:DI 0 "register_operand" "=r") ! 1611: (high:DI (match_operand 1 "data_segment_operand" ""))) ! 1612: ;; ??? Why the clobber? ! 1613: (clobber (reg:DI 1))] ! 1614: "TARGET_MEDANY && check_pic (1)" ! 1615: "sethi %%hi(%a1),%0; add %0,%%g4,%0" ! 1616: [(set_attr "type" "move") ! 1617: (set_attr "length" "2")]) ! 1618: ! 1619: (define_insn "" ! 1620: [(set (match_operand:DI 0 "register_operand" "=r") ! 1621: (high:DI (match_operand 1 "text_segment_operand" ""))) ! 1622: ;; ??? Why the clobber? ! 1623: (clobber (reg:DI 1))] ! 1624: "TARGET_MEDANY && check_pic (1)" ! 1625: "sethi %%hi(%a1),%0" ! 1626: [(set_attr "type" "move") ! 1627: (set_attr "length" "1")]) ! 1628: ! 1629: (define_insn "" ! 1630: [(set (match_operand:DI 0 "register_operand" "=r") ! 1631: (high:DI (match_operand 1 "" ""))) ! 1632: (clobber (reg:DI 1))] ! 1633: "TARGET_FULLANY && check_pic (1)" ! 1634: "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0" ! 1635: [(set_attr "type" "move") ! 1636: (set_attr "length" "5")]) ! 1637: ! 1638: ;; Move instructions ! 1639: ! 1640: (define_expand "movqi" ! 1641: [(set (match_operand:QI 0 "general_operand" "") ! 1642: (match_operand:QI 1 "general_operand" ""))] ! 1643: "" ! 1644: " ! 1645: { ! 1646: if (emit_move_sequence (operands, QImode)) ! 1647: DONE; ! 1648: }") ! 1649: ! 1650: (define_insn "" ! 1651: [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") ! 1652: (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))] ! 1653: "register_operand (operands[0], QImode) ! 1654: || register_operand (operands[1], QImode) ! 1655: || operands[1] == const0_rtx" ! 1656: "@ ! 1657: mov %1,%0 ! 1658: sethi %%hi(%a1),%0 ! 1659: ldub %1,%0 ! 1660: stb %r1,%0" 1.1.1.2 root 1661: [(set_attr "type" "move,move,load,store") 1662: (set_attr "length" "*,1,*,1")]) 1663: 1664: (define_insn "" 1665: [(set (match_operand:QI 0 "register_operand" "=r") 1666: (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r") 1667: (match_operand 2 "immediate_operand" "in")) 0))] 1668: "" 1669: "or %1,%%lo(%a2),%0" 1670: [(set_attr "length" "1")]) 1671: 1672: (define_insn "" 1673: [(set (mem:QI (match_operand:SI 0 "symbolic_operand" "")) 1674: (match_operand:QI 1 "reg_or_0_operand" "rJ")) 1675: (clobber (match_scratch:SI 2 "=&r"))] 1.1.1.3 ! root 1676: "(reload_completed || reload_in_progress) && ! TARGET_PTR64" 1.1.1.2 root 1677: "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]" 1678: [(set_attr "type" "store") 1679: (set_attr "length" "2")]) 1680: 1681: (define_expand "movhi" 1682: [(set (match_operand:HI 0 "general_operand" "") 1683: (match_operand:HI 1 "general_operand" ""))] 1.1 root 1684: "" 1685: " 1686: { 1.1.1.2 root 1687: if (emit_move_sequence (operands, HImode)) 1.1 root 1688: DONE; 1.1.1.2 root 1689: }") 1.1 root 1690: 1.1.1.2 root 1691: (define_insn "" 1692: [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") 1693: (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))] 1694: "register_operand (operands[0], HImode) 1695: || register_operand (operands[1], HImode) 1696: || operands[1] == const0_rtx" 1697: "@ 1698: mov %1,%0 1699: sethi %%hi(%a1),%0 1700: lduh %1,%0 1701: sth %r1,%0" 1702: [(set_attr "type" "move,move,load,store") 1703: (set_attr "length" "*,1,*,1")]) 1704: 1705: (define_insn "" 1706: [(set (match_operand:HI 0 "register_operand" "=r") 1707: (lo_sum:HI (match_operand:HI 1 "register_operand" "r") 1708: (match_operand 2 "immediate_operand" "in")))] 1709: "" 1710: "or %1,%%lo(%a2),%0" 1711: [(set_attr "length" "1")]) 1712: 1713: (define_insn "" 1714: [(set (mem:HI (match_operand:SI 0 "symbolic_operand" "")) 1715: (match_operand:HI 1 "reg_or_0_operand" "rJ")) 1716: (clobber (match_scratch:SI 2 "=&r"))] 1.1.1.3 ! root 1717: "(reload_completed || reload_in_progress) && ! TARGET_PTR64" 1.1.1.2 root 1718: "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]" 1719: [(set_attr "type" "store") 1720: (set_attr "length" "2")]) 1721: 1722: (define_expand "movsi" 1723: [(set (match_operand:SI 0 "general_operand" "") 1724: (match_operand:SI 1 "general_operand" ""))] 1725: "" 1726: " 1727: { 1728: if (emit_move_sequence (operands, SImode)) 1729: DONE; 1.1 root 1730: }") 1731: 1732: ;; We must support both 'r' and 'f' registers here, because combine may 1733: ;; convert SFmode hard registers to SImode hard registers when simplifying 1734: ;; subreg sets. 1735: 1736: ;; We cannot combine the similar 'r' and 'f' constraints, because it causes 1737: ;; problems with register allocation. Reload might try to put an integer 1738: ;; in an fp register, or an fp number is an integer register. 1739: 1740: (define_insn "" 1741: [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q") 1742: (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))] 1743: "register_operand (operands[0], SImode) 1744: || register_operand (operands[1], SImode) 1745: || operands[1] == const0_rtx" 1746: "@ 1747: mov %1,%0 1748: fmovs %1,%0 1749: sethi %%hi(%a1),%0 1750: ld %1,%0 1751: ld %1,%0 1752: st %r1,%0 1753: st %r1,%0" 1754: [(set_attr "type" "move,fp,move,load,load,store,store") 1755: (set_attr "length" "*,*,1,*,*,*,*")]) 1756: 1757: (define_insn "" 1758: [(set (mem:SI (match_operand:SI 0 "symbolic_operand" "")) 1759: (match_operand:SI 1 "reg_or_0_operand" "rJ")) 1760: (clobber (match_scratch:SI 2 "=&r"))] 1.1.1.3 ! root 1761: "(reload_completed || reload_in_progress) && ! TARGET_PTR64" 1.1 root 1762: "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" 1763: [(set_attr "type" "store") 1764: (set_attr "length" "2")]) 1765: 1.1.1.2 root 1766: (define_expand "movdi" 1767: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") 1768: (match_operand:DI 1 "general_operand" ""))] 1.1 root 1769: "" 1770: " 1771: { 1.1.1.2 root 1772: if (emit_move_sequence (operands, DImode)) 1.1 root 1773: DONE; 1774: }") 1775: 1776: (define_insn "" 1.1.1.3 ! root 1777: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q") ! 1778: (match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))] ! 1779: "! TARGET_V9 ! 1780: && (register_operand (operands[0], DImode) ! 1781: || register_operand (operands[1], DImode) ! 1782: || operands[1] == const0_rtx)" 1.1.1.2 root 1783: "* 1.1 root 1784: { 1.1.1.2 root 1785: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) 1786: return output_fp_move_double (operands); 1787: return output_move_double (operands); 1788: }" 1.1.1.3 ! root 1789: [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore") ! 1790: (set_attr "length" "2,1,1,3,3,3,2,3,3")]) 1.1 root 1791: 1.1.1.3 ! root 1792: ;;; ??? The trick used below can be extended to load any negative 32 bit ! 1793: ;;; constant in two instructions. Currently the compiler will use HIGH/LO_SUM ! 1794: ;;; for anything not matching the HIK constraints, which results in 5 ! 1795: ;;; instructions. Positive 32 bit constants can be loaded in the obvious way ! 1796: ;;; with sethi/ori. To extend the trick, in the xor instruction, use ! 1797: ;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0 ! 1798: ;;; This needs the original value of operands[1], not the inverted value. ! 1799: ! 1800: (define_insn "" ! 1801: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?f,?f,?Q") ! 1802: (match_operand:DI 1 "move_operand" "rI,K,Q,rJ,f,Q,f"))] ! 1803: "TARGET_V9 ! 1804: && (register_operand (operands[0], DImode) ! 1805: || register_operand (operands[1], DImode) ! 1806: || operands[1] == const0_rtx)" 1.1.1.2 root 1807: "* 1808: { 1.1.1.3 ! root 1809: switch (which_alternative) ! 1810: { ! 1811: case 0: ! 1812: return \"mov %1,%0\"; ! 1813: case 1: ! 1814: /* Sethi does not sign extend, so we must use a little trickery ! 1815: to use it for negative numbers. Invert the constant before ! 1816: loading it in, then use a xor immediate to invert the loaded bits ! 1817: (along with the upper 32 bits) to the desired constant. This ! 1818: works because the sethi and immediate fields overlap. */ ! 1819: ! 1820: if ((INTVAL (operands[1]) & 0x80000000) == 0) ! 1821: return \"sethi %%hi(%a1),%0\"; ! 1822: else ! 1823: { ! 1824: operands[1] = gen_rtx (CONST_INT, VOIDmode, ! 1825: ~ INTVAL (operands[1])); ! 1826: output_asm_insn (\"sethi %%hi(%a1),%0\", operands); ! 1827: /* The low 10 bits are already zero, but invert the rest. ! 1828: Assemblers don't accept 0x1c00, so use -0x400 instead. */ ! 1829: return \"xor %0,-0x400,%0\"; ! 1830: } ! 1831: case 2: ! 1832: return \"ldx %1,%0\"; ! 1833: case 3: ! 1834: return \"stx %r1,%0\"; ! 1835: case 4: ! 1836: return \"mov %1,%0\"; ! 1837: case 5: ! 1838: return \"ldd %1,%0\"; ! 1839: case 6: ! 1840: return \"std %1,%0\"; ! 1841: } 1.1.1.2 root 1842: }" 1.1.1.3 ! root 1843: [(set_attr "type" "move,move,load,store,fp,fpload,fpstore") ! 1844: (set_attr "length" "1,2,1,1,1,1,1")]) 1.1 root 1845: 1.1.1.2 root 1846: ;; ??? There's no symbolic (set (mem:DI ...) ...). 1.1.1.3 ! root 1847: ;; Experimentation with v9 suggested one isn't needed. 1.1.1.2 root 1848: 1849: ;; Block move insns. 1.1 root 1850: 1851: ;; ??? We get better code without it. See output_block_move in sparc.c. 1852: 1853: ;; The definition of this insn does not really explain what it does, 1854: ;; but it should suffice 1855: ;; that anything generated as this insn will be recognized as one 1856: ;; and that it will not successfully combine with anything. 1857: ;(define_expand "movstrsi" 1858: ; [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) 1859: ; (mem:BLK (match_operand:BLK 1 "general_operand" ""))) 1860: ; (use (match_operand:SI 2 "nonmemory_operand" "")) 1861: ; (use (match_operand:SI 3 "immediate_operand" "")) 1862: ; (clobber (match_dup 0)) 1863: ; (clobber (match_dup 1)) 1864: ; (clobber (match_scratch:SI 4 "")) 1865: ; (clobber (reg:SI 0)) 1866: ; (clobber (reg:SI 1))])] 1867: ; "" 1868: ; " 1869: ;{ 1870: ; /* If the size isn't known, don't emit inline code. output_block_move 1871: ; would output code that's much slower than the library function. 1872: ; Also don't output code for large blocks. */ 1873: ; if (GET_CODE (operands[2]) != CONST_INT 1874: ; || GET_CODE (operands[3]) != CONST_INT 1875: ; || INTVAL (operands[2]) / INTVAL (operands[3]) > 16) 1876: ; FAIL; 1877: ; 1878: ; operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); 1879: ; operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); 1880: ; operands[2] = force_not_mem (operands[2]); 1881: ;}") 1882: 1883: ;(define_insn "" 1884: ; [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r")) 1885: ; (mem:BLK (match_operand:SI 1 "register_operand" "+r"))) 1886: ; (use (match_operand:SI 2 "nonmemory_operand" "rn")) 1887: ; (use (match_operand:SI 3 "immediate_operand" "i")) 1888: ; (clobber (match_dup 0)) 1889: ; (clobber (match_dup 1)) 1890: ; (clobber (match_scratch:SI 4 "=&r")) 1891: ; (clobber (reg:SI 0)) 1892: ; (clobber (reg:SI 1))] 1893: ; "" 1894: ; "* return output_block_move (operands);" 1895: ; [(set_attr "type" "multi") 1896: ; (set_attr "length" "6")]) 1897: 1898: ;; Floating point move insns 1899: 1.1.1.2 root 1900: ;; This pattern forces (set (reg:SF ...) (const_double ...)) 1.1 root 1901: ;; to be reloaded by putting the constant into memory. 1.1.1.2 root 1902: ;; It must come before the more general movsf pattern. 1.1 root 1903: (define_insn "" 1.1.1.2 root 1904: [(set (match_operand:SF 0 "general_operand" "=?r,f,m") 1905: (match_operand:SF 1 "" "?E,m,G"))] 1.1 root 1906: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" 1907: "* 1908: { 1909: switch (which_alternative) 1910: { 1911: case 0: 1.1.1.2 root 1912: return singlemove_string (operands); 1.1 root 1913: case 1: 1.1.1.2 root 1914: return \"ld %1,%0\"; 1.1 root 1915: case 2: 1.1.1.2 root 1916: return \"st %%g0,%0\"; 1.1 root 1917: } 1918: }" 1919: [(set_attr "type" "load,fpload,store") 1.1.1.2 root 1920: (set_attr "length" "2,1,1")]) 1.1 root 1921: 1.1.1.2 root 1922: (define_expand "movsf" 1923: [(set (match_operand:SF 0 "general_operand" "") 1924: (match_operand:SF 1 "general_operand" ""))] 1.1 root 1925: "" 1926: " 1927: { 1.1.1.2 root 1928: if (emit_move_sequence (operands, SFmode)) 1.1 root 1929: DONE; 1930: }") 1931: 1932: (define_insn "" 1.1.1.2 root 1933: [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q") 1934: (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))] 1.1 root 1935: "TARGET_FPU 1.1.1.2 root 1936: && (register_operand (operands[0], SFmode) 1937: || register_operand (operands[1], SFmode))" 1938: "@ 1939: fmovs %1,%0 1940: mov %1,%0 1941: ld %1,%0 1942: ld %1,%0 1943: st %r1,%0 1944: st %r1,%0" 1945: [(set_attr "type" "fp,move,fpload,load,fpstore,store")]) 1.1 root 1946: 1947: ;; Exactly the same as above, except that all `f' cases are deleted. 1948: ;; This is necessary to prevent reload from ever trying to use a `f' reg 1949: ;; when -mno-fpu. 1950: 1951: (define_insn "" 1.1.1.2 root 1952: [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q") 1953: (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))] 1.1 root 1954: "! TARGET_FPU 1.1.1.2 root 1955: && (register_operand (operands[0], SFmode) 1956: || register_operand (operands[1], SFmode))" 1957: "@ 1958: mov %1,%0 1959: ld %1,%0 1960: st %r1,%0" 1961: [(set_attr "type" "move,load,store")]) 1.1 root 1962: 1963: (define_insn "" 1.1.1.2 root 1964: [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i")) 1965: (match_operand:SF 1 "reg_or_0_operand" "rfG")) 1966: (clobber (match_scratch:SI 2 "=&r"))] 1.1.1.3 ! root 1967: "(reload_completed || reload_in_progress) && ! TARGET_PTR64" 1.1.1.2 root 1968: "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" 1.1 root 1969: [(set_attr "type" "store") 1.1.1.2 root 1970: (set_attr "length" "2")]) 1971: 1.1 root 1972: ;; This pattern forces (set (reg:DF ...) (const_double ...)) 1973: ;; to be reloaded by putting the constant into memory. 1974: ;; It must come before the more general movdf pattern. 1975: 1976: (define_insn "" 1.1.1.3 ! root 1977: [(set (match_operand:DF 0 "general_operand" "=?r,e,o") 1.1 root 1978: (match_operand:DF 1 "" "?E,m,G"))] 1979: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" 1980: "* 1981: { 1982: switch (which_alternative) 1983: { 1984: case 0: 1985: return output_move_double (operands); 1986: case 1: 1987: return output_fp_move_double (operands); 1988: case 2: 1.1.1.3 ! root 1989: if (TARGET_V9) ! 1990: { ! 1991: return \"stx %%g0,%0\"; ! 1992: } ! 1993: else ! 1994: { ! 1995: operands[1] = adj_offsettable_operand (operands[0], 4); ! 1996: return \"st %%g0,%0\;st %%g0,%1\"; ! 1997: } 1.1 root 1998: } 1999: }" 2000: [(set_attr "type" "load,fpload,store") 2001: (set_attr "length" "3,3,3")]) 2002: 2003: (define_expand "movdf" 2004: [(set (match_operand:DF 0 "general_operand" "") 2005: (match_operand:DF 1 "general_operand" ""))] 2006: "" 2007: " 2008: { 1.1.1.2 root 2009: if (emit_move_sequence (operands, DFmode)) 1.1 root 2010: DONE; 2011: }") 2012: 2013: (define_insn "" 1.1.1.3 ! root 2014: [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,e,r,Q,Q,e,r") ! 2015: (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,e,r,e,r,Q,Q"))] 1.1 root 2016: "TARGET_FPU 2017: && (register_operand (operands[0], DFmode) 2018: || register_operand (operands[1], DFmode))" 2019: "* 2020: { 2021: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) 2022: return output_fp_move_double (operands); 2023: return output_move_double (operands); 2024: }" 2025: [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load") 2026: (set_attr "length" "1,1,2,2,3,3,3,3")]) 2027: 1.1.1.3 ! root 2028: ;; Exactly the same as above, except that all `e' cases are deleted. ! 2029: ;; This is necessary to prevent reload from ever trying to use a `e' reg 1.1 root 2030: ;; when -mno-fpu. 2031: 2032: (define_insn "" 2033: [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r") 2034: (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))] 2035: "! TARGET_FPU 2036: && (register_operand (operands[0], DFmode) 2037: || register_operand (operands[1], DFmode))" 2038: "* return output_move_double (operands);" 2039: [(set_attr "type" "store,load,move,store,load") 2040: (set_attr "length" "1,1,2,3,3")]) 2041: 1.1.1.3 ! root 2042: ;; Must handle overlapping registers here, since parameters can be unaligned ! 2043: ;; in registers. ! 2044: ;; ??? Do we need a v9 version of this? 1.1 root 2045: (define_split 2046: [(set (match_operand:DF 0 "register_operand" "") 2047: (match_operand:DF 1 "register_operand" ""))] 1.1.1.3 ! root 2048: "! TARGET_V9 && reload_completed" 1.1 root 2049: [(set (match_dup 2) (match_dup 3)) 2050: (set (match_dup 4) (match_dup 5))] 2051: " 1.1.1.3 ! root 2052: { ! 2053: rtx first_set = operand_subword (operands[0], 0, 0, DFmode); ! 2054: rtx second_use = operand_subword (operands[1], 1, 0, DFmode); ! 2055: ! 2056: if (REGNO (first_set) == REGNO (second_use)) ! 2057: { ! 2058: operands[2] = operand_subword (operands[0], 1, 0, DFmode); ! 2059: operands[3] = second_use; ! 2060: operands[4] = first_set; ! 2061: operands[5] = operand_subword (operands[1], 0, 0, DFmode); ! 2062: } ! 2063: else ! 2064: { ! 2065: operands[2] = first_set; ! 2066: operands[3] = operand_subword (operands[1], 0, 0, DFmode); ! 2067: operands[4] = operand_subword (operands[0], 1, 0, DFmode); ! 2068: operands[5] = second_use; ! 2069: } ! 2070: }") 1.1 root 2071: 2072: (define_insn "" 2073: [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i")) 1.1.1.3 ! root 2074: (match_operand:DF 1 "reg_or_0_operand" "re,G")) 1.1 root 2075: (clobber (match_scratch:SI 2 "=&r,&r"))] 1.1.1.3 ! root 2076: "(reload_completed || reload_in_progress) && ! TARGET_PTR64" 1.1 root 2077: "* 2078: { 2079: output_asm_insn (\"sethi %%hi(%a0),%2\", operands); 2080: if (which_alternative == 0) 2081: return \"std %1,[%2+%%lo(%a0)]\"; 2082: else 2083: return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\"; 2084: }" 2085: [(set_attr "type" "store") 2086: (set_attr "length" "3")]) 2087: 1.1.1.2 root 2088: ;; This pattern forces (set (reg:TF ...) (const_double ...)) 1.1 root 2089: ;; to be reloaded by putting the constant into memory. 1.1.1.2 root 2090: ;; It must come before the more general movtf pattern. 1.1 root 2091: (define_insn "" 1.1.1.3 ! root 2092: [(set (match_operand:TF 0 "general_operand" "=?r,e,o") 1.1.1.2 root 2093: (match_operand:TF 1 "" "?E,m,G"))] 1.1 root 2094: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" 2095: "* 2096: { 2097: switch (which_alternative) 2098: { 2099: case 0: 1.1.1.2 root 2100: return output_move_quad (operands); 1.1 root 2101: case 1: 1.1.1.2 root 2102: return output_fp_move_quad (operands); 1.1 root 2103: case 2: 1.1.1.3 ! root 2104: if (TARGET_V9) ! 2105: { ! 2106: operands[1] = adj_offsettable_operand (operands[0], 8); ! 2107: return \"stx %%g0,%0\;stx %%g0,%1\"; ! 2108: } ! 2109: else ! 2110: { ! 2111: /* ??? Do we run off the end of the array here? */ ! 2112: operands[1] = adj_offsettable_operand (operands[0], 4); ! 2113: operands[2] = adj_offsettable_operand (operands[0], 8); ! 2114: operands[3] = adj_offsettable_operand (operands[0], 12); ! 2115: return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\"; ! 2116: } 1.1 root 2117: } 2118: }" 2119: [(set_attr "type" "load,fpload,store") 1.1.1.2 root 2120: (set_attr "length" "5,5,5")]) 1.1 root 2121: 1.1.1.2 root 2122: (define_expand "movtf" 2123: [(set (match_operand:TF 0 "general_operand" "") 2124: (match_operand:TF 1 "general_operand" ""))] 1.1 root 2125: "" 2126: " 2127: { 1.1.1.2 root 2128: if (emit_move_sequence (operands, TFmode)) 1.1 root 2129: DONE; 2130: }") 2131: 2132: (define_insn "" 1.1.1.3 ! root 2133: [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=e,r,Q,Q,e,&r") ! 2134: (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "e,r,e,r,Q,Q"))] 1.1 root 2135: "TARGET_FPU 1.1.1.2 root 2136: && (register_operand (operands[0], TFmode) 2137: || register_operand (operands[1], TFmode))" 2138: "* 2139: { 2140: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) 2141: return output_fp_move_quad (operands); 2142: return output_move_quad (operands); 2143: }" 2144: [(set_attr "type" "fp,move,fpstore,store,fpload,load") 2145: (set_attr "length" "4,4,5,5,5,5")]) 1.1 root 2146: 1.1.1.3 ! root 2147: ;; Exactly the same as above, except that all `e' cases are deleted. ! 2148: ;; This is necessary to prevent reload from ever trying to use a `e' reg 1.1 root 2149: ;; when -mno-fpu. 2150: 2151: (define_insn "" 1.1.1.2 root 2152: [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r") 2153: (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))] 1.1 root 2154: "! TARGET_FPU 1.1.1.2 root 2155: && (register_operand (operands[0], TFmode) 2156: || register_operand (operands[1], TFmode))" 2157: "* 2158: { 2159: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) 2160: return output_fp_move_quad (operands); 2161: return output_move_quad (operands); 2162: }" 2163: [(set_attr "type" "move,store,load") 2164: (set_attr "length" "4,5,5")]) 1.1 root 2165: 1.1.1.3 ! root 2166: ;; This is disabled because it does not work. Long doubles have only 8 ! 2167: ;; byte alignment. Adding an offset of 8 or 12 to an 8 byte aligned %lo may ! 2168: ;; cause it to overflow. See also GO_IF_LEGITIMATE_ADDRESS. 1.1 root 2169: (define_insn "" 1.1.1.2 root 2170: [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i")) 1.1.1.3 ! root 2171: (match_operand:TF 1 "reg_or_0_operand" "re,G")) 1.1.1.2 root 2172: (clobber (match_scratch:SI 2 "=&r,&r"))] 1.1.1.3 ! root 2173: "0 && (reload_completed || reload_in_progress) && ! TARGET_PTR64" 1.1.1.2 root 2174: "* 2175: { 2176: output_asm_insn (\"sethi %%hi(%a0),%2\", operands); 2177: if (which_alternative == 0) 2178: return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\"; 2179: else 2180: return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\"; 2181: }" 1.1 root 2182: [(set_attr "type" "store") 1.1.1.2 root 2183: (set_attr "length" "5")]) 1.1 root 2184: 1.1.1.3 ! root 2185: ;; Sparc V9 conditional move instructions. ! 2186: ! 2187: ; ??? There is not actually a 32 bit version of this instruction. ! 2188: (define_insn "" ! 2189: [(set (match_operand:SI 0 "register_operand" "=r") ! 2190: (if_then_else (match_operator 1 "comparison_operator" ! 2191: [(reg:CC 0) (const_int 0)]) ! 2192: (match_operand:SI 2 "arith11_operand" "ri") ! 2193: (match_operand:SI 3 "register_operand" "0")))] ! 2194: "TARGET_V9" ! 2195: "mov%C1 %%icc,%2,%0" ! 2196: [(set_attr "type" "cmove")]) ! 2197: ! 2198: (define_insn "" ! 2199: [(set (match_operand:DI 0 "register_operand" "=r") ! 2200: (if_then_else (match_operator 1 "comparison_operator" ! 2201: [(reg:CC 0) (const_int 0)]) ! 2202: (match_operand:DI 2 "arith11_double_operand" "rHI") ! 2203: (match_operand:DI 3 "register_operand" "0")))] ! 2204: "TARGET_V9" ! 2205: "mov%C1 %%icc,%2,%0" ! 2206: [(set_attr "type" "cmove")]) ! 2207: ! 2208: ;; ??? There is not actually a 32 bit version of this instruction. ! 2209: (define_insn "" ! 2210: [(set (match_operand:SI 0 "register_operand" "=r") ! 2211: (if_then_else (match_operator 1 "comparison_operator" ! 2212: [(reg:CCX 0) (const_int 0)]) ! 2213: (match_operand:SI 2 "arith11_operand" "ri") ! 2214: (match_operand:SI 3 "register_operand" "0")))] ! 2215: "TARGET_V9" ! 2216: "mov%C1 %%xcc,%2,%0" ! 2217: [(set_attr "type" "cmove")]) ! 2218: ! 2219: (define_insn "" ! 2220: [(set (match_operand:DI 0 "register_operand" "=r") ! 2221: (if_then_else (match_operator 1 "comparison_operator" ! 2222: [(reg:CCX 0) (const_int 0)]) ! 2223: (match_operand:DI 2 "arith11_double_operand" "rHI") ! 2224: (match_operand:DI 3 "register_operand" "0")))] ! 2225: "TARGET_V9" ! 2226: "mov%C1 %%xcc,%2,%0" ! 2227: [(set_attr "type" "cmove")]) ! 2228: ! 2229: ;; ??? There is not actually a 32 bit version of this instruction. ! 2230: (define_insn "" ! 2231: [(set (match_operand:SI 0 "register_operand" "=r") ! 2232: (if_then_else (match_operator 1 "comparison_operator" ! 2233: [(match_operand:CCFP 2 "ccfp_reg_operand" "c") ! 2234: (const_int 0)]) ! 2235: (match_operand:SI 3 "arith11_operand" "ri") ! 2236: (match_operand:SI 4 "register_operand" "0")))] ! 2237: "TARGET_V9" ! 2238: "mov%C1 %2,%3,%0" ! 2239: [(set_attr "type" "cmove")]) ! 2240: ! 2241: ;; ??? There is not actually a 32 bit version of this instruction. ! 2242: (define_insn "" ! 2243: [(set (match_operand:SI 0 "register_operand" "=r") ! 2244: (if_then_else (match_operator 1 "comparison_operator" ! 2245: [(match_operand:CCFPE 2 "ccfp_reg_operand" "c") ! 2246: (const_int 0)]) ! 2247: (match_operand:SI 3 "arith11_operand" "ri") ! 2248: (match_operand:SI 4 "register_operand" "0")))] ! 2249: "TARGET_V9" ! 2250: "mov%C1 %2,%3,%0" ! 2251: [(set_attr "type" "cmove")]) ! 2252: ! 2253: (define_insn "" ! 2254: [(set (match_operand:DI 0 "register_operand" "=r") ! 2255: (if_then_else (match_operator 1 "comparison_operator" ! 2256: [(match_operand:CCFP 2 "ccfp_reg_operand" "c") ! 2257: (const_int 0)]) ! 2258: (match_operand:DI 3 "arith11_double_operand" "rHI") ! 2259: (match_operand:DI 4 "register_operand" "0")))] ! 2260: "TARGET_V9" ! 2261: "mov%C1 %2,%3,%0" ! 2262: [(set_attr "type" "cmove")]) ! 2263: ! 2264: (define_insn "" ! 2265: [(set (match_operand:DI 0 "register_operand" "=r") ! 2266: (if_then_else (match_operator 1 "comparison_operator" ! 2267: [(match_operand:CCFPE 2 "ccfp_reg_operand" "c") ! 2268: (const_int 0)]) ! 2269: (match_operand:DI 3 "arith11_double_operand" "rHI") ! 2270: (match_operand:DI 4 "register_operand" "0")))] ! 2271: "TARGET_V9" ! 2272: "mov%C1 %2,%3,%0" ! 2273: [(set_attr "type" "cmove")]) ! 2274: ! 2275: ;; ??? There is not actually a 32 bit version of this instruction. ! 2276: (define_insn "" ! 2277: [(set (match_operand:SI 0 "register_operand" "=r") ! 2278: (if_then_else (match_operator 1 "v9_regcmp_op" ! 2279: [(match_operand:DI 2 "register_operand" "r") ! 2280: (const_int 0)]) ! 2281: (match_operand:SI 3 "arith10_operand" "ri") ! 2282: (match_operand:SI 4 "register_operand" "0")))] ! 2283: "TARGET_V9" ! 2284: "movr%D1 %2,%r3,%0" ! 2285: [(set_attr "type" "cmove")]) ! 2286: ! 2287: (define_insn "" ! 2288: [(set (match_operand:DI 0 "register_operand" "=r") ! 2289: (if_then_else (match_operator 1 "v9_regcmp_op" ! 2290: [(match_operand:DI 2 "register_operand" "r") ! 2291: (const_int 0)]) ! 2292: (match_operand:DI 3 "arith10_double_operand" "ri") ! 2293: (match_operand:DI 4 "register_operand" "0")))] ! 2294: "TARGET_V9" ! 2295: "movr%D1 %2,%r3,%0" ! 2296: [(set_attr "type" "cmove")]) ! 2297: ! 2298: (define_insn "" ! 2299: [(set (match_operand:SF 0 "register_operand" "=f") ! 2300: (if_then_else (match_operator 1 "v9_regcmp_op" ! 2301: [(match_operand:DI 2 "register_operand" "r") ! 2302: (const_int 0)]) ! 2303: (match_operand:SF 3 "register_operand" "f") ! 2304: (match_operand:SF 4 "register_operand" "0")))] ! 2305: "TARGET_V9 && TARGET_FPU" ! 2306: "fmovrs%D1 %2,%r3,%0" ! 2307: [(set_attr "type" "cmove")]) ! 2308: ! 2309: (define_insn "" ! 2310: [(set (match_operand:DF 0 "register_operand" "=e") ! 2311: (if_then_else (match_operator 1 "v9_regcmp_op" ! 2312: [(match_operand:DI 2 "register_operand" "r") ! 2313: (const_int 0)]) ! 2314: (match_operand:DF 3 "register_operand" "e") ! 2315: (match_operand:DF 4 "register_operand" "0")))] ! 2316: "TARGET_V9 && TARGET_FPU" ! 2317: "fmovrd%D1 %2,%r3,%0" ! 2318: [(set_attr "type" "cmove")]) ! 2319: ! 2320: (define_insn "" ! 2321: [(set (match_operand:TF 0 "register_operand" "=e") ! 2322: (if_then_else (match_operator 1 "v9_regcmp_op" ! 2323: [(match_operand:DI 2 "register_operand" "r") ! 2324: (const_int 0)]) ! 2325: (match_operand:TF 3 "register_operand" "e") ! 2326: (match_operand:TF 4 "register_operand" "0")))] ! 2327: "TARGET_V9 && TARGET_FPU" ! 2328: "fmovrq%D1 %2,%r3,%0" ! 2329: [(set_attr "type" "cmove")]) ! 2330: ! 2331: (define_insn "" ! 2332: [(set (match_operand:SF 0 "register_operand" "=f") ! 2333: (if_then_else (match_operator 1 "comparison_operator" ! 2334: [(match_operand:CCFP 2 "ccfp_reg_operand" "c") ! 2335: (const_int 0)]) ! 2336: (match_operand:SF 3 "register_operand" "f") ! 2337: (match_operand:SF 4 "register_operand" "0")))] ! 2338: "TARGET_V9 && TARGET_FPU" ! 2339: "fmovs%C1 %2,%3,%0" ! 2340: [(set_attr "type" "cmove")]) ! 2341: ! 2342: (define_insn "" ! 2343: [(set (match_operand:SF 0 "register_operand" "=f") ! 2344: (if_then_else (match_operator 1 "comparison_operator" ! 2345: [(match_operand:CCFPE 2 "ccfp_reg_operand" "c") ! 2346: (const_int 0)]) ! 2347: (match_operand:SF 3 "register_operand" "f") ! 2348: (match_operand:SF 4 "register_operand" "0")))] ! 2349: "TARGET_V9 && TARGET_FPU" ! 2350: "fmovs%C1 %2,%3,%0" ! 2351: [(set_attr "type" "cmove")]) ! 2352: ! 2353: (define_insn "" ! 2354: [(set (match_operand:DF 0 "register_operand" "=e") ! 2355: (if_then_else (match_operator 1 "comparison_operator" ! 2356: [(match_operand:CCFP 2 "ccfp_reg_operand" "c") ! 2357: (const_int 0)]) ! 2358: (match_operand:DF 3 "register_operand" "e") ! 2359: (match_operand:DF 4 "register_operand" "0")))] ! 2360: "TARGET_V9 && TARGET_FPU" ! 2361: "fmovd%C1 %2,%3,%0" ! 2362: [(set_attr "type" "cmove")]) ! 2363: ! 2364: (define_insn "" ! 2365: [(set (match_operand:DF 0 "register_operand" "=e") ! 2366: (if_then_else (match_operator 1 "comparison_operator" ! 2367: [(match_operand:CCFPE 2 "ccfp_reg_operand" "c") ! 2368: (const_int 0)]) ! 2369: (match_operand:DF 3 "register_operand" "e") ! 2370: (match_operand:DF 4 "register_operand" "0")))] ! 2371: "TARGET_V9 && TARGET_FPU" ! 2372: "fmovd%C1 %2,%3,%0" ! 2373: [(set_attr "type" "cmove")]) ! 2374: ! 2375: (define_insn "" ! 2376: [(set (match_operand:TF 0 "register_operand" "=e") ! 2377: (if_then_else (match_operator 1 "comparison_operator" ! 2378: [(match_operand:CCFP 2 "ccfp_reg_operand" "c") ! 2379: (const_int 0)]) ! 2380: (match_operand:TF 3 "register_operand" "e") ! 2381: (match_operand:TF 4 "register_operand" "0")))] ! 2382: "TARGET_V9 && TARGET_FPU" ! 2383: "fmovq%C1 %2,%3,%0" ! 2384: [(set_attr "type" "cmove")]) ! 2385: ! 2386: (define_insn "" ! 2387: [(set (match_operand:TF 0 "register_operand" "=e") ! 2388: (if_then_else (match_operator 1 "comparison_operator" ! 2389: [(match_operand:CCFPE 2 "ccfp_reg_operand" "c") ! 2390: (const_int 0)]) ! 2391: (match_operand:TF 3 "register_operand" "e") ! 2392: (match_operand:TF 4 "register_operand" "0")))] ! 2393: "TARGET_V9 && TARGET_FPU" ! 2394: "fmovq%C1 %2,%3,%0" ! 2395: [(set_attr "type" "cmove")]) ! 2396: ! 2397: (define_insn "" ! 2398: [(set (match_operand:SF 0 "register_operand" "=f") ! 2399: (if_then_else (match_operator 1 "comparison_operator" ! 2400: [(reg:CC 0) (const_int 0)]) ! 2401: (match_operand:SF 2 "register_operand" "f") ! 2402: (match_operand:SF 3 "register_operand" "0")))] ! 2403: "TARGET_V9 && TARGET_FPU" ! 2404: "fmovs%C1 %%icc,%2,%0" ! 2405: [(set_attr "type" "cmove")]) ! 2406: ! 2407: (define_insn "" ! 2408: [(set (match_operand:DF 0 "register_operand" "=e") ! 2409: (if_then_else (match_operator 1 "comparison_operator" ! 2410: [(reg:CC 0) (const_int 0)]) ! 2411: (match_operand:DF 2 "register_operand" "e") ! 2412: (match_operand:DF 3 "register_operand" "0")))] ! 2413: "TARGET_V9 && TARGET_FPU" ! 2414: "fmovd%C1 %%icc,%2,%0" ! 2415: [(set_attr "type" "cmove")]) ! 2416: ! 2417: (define_insn "" ! 2418: [(set (match_operand:TF 0 "register_operand" "=e") ! 2419: (if_then_else (match_operator 1 "comparison_operator" ! 2420: [(reg:CC 0) (const_int 0)]) ! 2421: (match_operand:TF 2 "register_operand" "e") ! 2422: (match_operand:TF 3 "register_operand" "0")))] ! 2423: "TARGET_V9 && TARGET_FPU" ! 2424: "fmovq%C1 %%icc,%2,%0" ! 2425: [(set_attr "type" "cmove")]) ! 2426: ! 2427: (define_insn "" ! 2428: [(set (match_operand:SF 0 "register_operand" "=f") ! 2429: (if_then_else (match_operator 1 "comparison_operator" ! 2430: [(reg:CCX 0) (const_int 0)]) ! 2431: (match_operand:SF 2 "register_operand" "f") ! 2432: (match_operand:SF 3 "register_operand" "0")))] ! 2433: "TARGET_V9 && TARGET_FPU" ! 2434: "fmovs%C1 %%xcc,%2,%0" ! 2435: [(set_attr "type" "cmove")]) ! 2436: ! 2437: (define_insn "" ! 2438: [(set (match_operand:DF 0 "register_operand" "=e") ! 2439: (if_then_else (match_operator 1 "comparison_operator" ! 2440: [(reg:CCX 0) (const_int 0)]) ! 2441: (match_operand:DF 2 "register_operand" "e") ! 2442: (match_operand:DF 3 "register_operand" "0")))] ! 2443: "TARGET_V9 && TARGET_FPU" ! 2444: "fmovd%C1 %%xcc,%2,%0" ! 2445: [(set_attr "type" "cmove")]) ! 2446: ! 2447: (define_insn "" ! 2448: [(set (match_operand:TF 0 "register_operand" "=e") ! 2449: (if_then_else (match_operator 1 "comparison_operator" ! 2450: [(reg:CCX 0) (const_int 0)]) ! 2451: (match_operand:TF 2 "register_operand" "e") ! 2452: (match_operand:TF 3 "register_operand" "0")))] ! 2453: "TARGET_V9 && TARGET_FPU" ! 2454: "fmovq%C1 %%xcc,%2,%0" ! 2455: [(set_attr "type" "cmove")]) ! 2456: 1.1 root 2457: ;;- zero extension instructions 2458: 2459: ;; These patterns originally accepted general_operands, however, slightly 2460: ;; better code is generated by only accepting register_operands, and then 2461: ;; letting combine generate the ldu[hb] insns. 2462: 2463: (define_expand "zero_extendhisi2" 2464: [(set (match_operand:SI 0 "register_operand" "") 2465: (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] 2466: "" 2467: " 2468: { 2469: rtx temp = gen_reg_rtx (SImode); 2470: rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); 1.1.1.2 root 2471: int op1_subword = 0; 1.1 root 2472: 2473: if (GET_CODE (operand1) == SUBREG) 1.1.1.2 root 2474: { 2475: op1_subword = SUBREG_WORD (operand1); 2476: operand1 = XEXP (operand1, 0); 2477: } 1.1 root 2478: 1.1.1.2 root 2479: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 2480: op1_subword), 1.1 root 2481: shift_16)); 2482: emit_insn (gen_lshrsi3 (operand0, temp, shift_16)); 2483: DONE; 2484: }") 2485: 2486: (define_insn "" 2487: [(set (match_operand:SI 0 "register_operand" "=r") 2488: (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 2489: "" 2490: "lduh %1,%0" 2491: [(set_attr "type" "load")]) 2492: 2493: (define_expand "zero_extendqihi2" 2494: [(set (match_operand:HI 0 "register_operand" "") 2495: (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] 2496: "" 2497: "") 2498: 2499: (define_insn "" 2500: [(set (match_operand:HI 0 "register_operand" "=r,r") 2501: (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))] 2502: "GET_CODE (operands[1]) != CONST_INT" 2503: "@ 2504: and %1,0xff,%0 2505: ldub %1,%0" 2506: [(set_attr "type" "unary,load") 2507: (set_attr "length" "1")]) 2508: 2509: (define_expand "zero_extendqisi2" 2510: [(set (match_operand:SI 0 "register_operand" "") 2511: (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] 2512: "" 2513: "") 2514: 2515: (define_insn "" 2516: [(set (match_operand:SI 0 "register_operand" "=r,r") 2517: (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))] 2518: "GET_CODE (operands[1]) != CONST_INT" 2519: "@ 2520: and %1,0xff,%0 2521: ldub %1,%0" 2522: [(set_attr "type" "unary,load") 2523: (set_attr "length" "1")]) 2524: 1.1.1.3 ! root 2525: (define_expand "zero_extendqidi2" ! 2526: [(set (match_operand:DI 0 "register_operand" "") ! 2527: (zero_extend:DI (match_operand:QI 1 "register_operand" "")))] ! 2528: "TARGET_V9" ! 2529: "") ! 2530: ! 2531: (define_insn "" ! 2532: [(set (match_operand:DI 0 "register_operand" "=r,r") ! 2533: (zero_extend:DI (match_operand:QI 1 "sparc_operand" "r,Q")))] ! 2534: "TARGET_V9 && GET_CODE (operands[1]) != CONST_INT" ! 2535: "@ ! 2536: and %1,0xff,%0 ! 2537: ldub %1,%0" ! 2538: [(set_attr "type" "unary,load") ! 2539: (set_attr "length" "1")]) ! 2540: ! 2541: (define_expand "zero_extendhidi2" ! 2542: [(set (match_operand:DI 0 "register_operand" "") ! 2543: (zero_extend:DI (match_operand:HI 1 "register_operand" "")))] ! 2544: "TARGET_V9" ! 2545: " ! 2546: { ! 2547: rtx temp = gen_reg_rtx (DImode); ! 2548: rtx shift_48 = gen_rtx (CONST_INT, VOIDmode, 48); ! 2549: int op1_subword = 0; ! 2550: ! 2551: if (GET_CODE (operand1) == SUBREG) ! 2552: { ! 2553: op1_subword = SUBREG_WORD (operand1); ! 2554: operand1 = XEXP (operand1, 0); ! 2555: } ! 2556: ! 2557: emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1, ! 2558: op1_subword), ! 2559: shift_48)); ! 2560: emit_insn (gen_lshrdi3 (operand0, temp, shift_48)); ! 2561: DONE; ! 2562: }") ! 2563: ! 2564: (define_insn "" ! 2565: [(set (match_operand:DI 0 "register_operand" "=r") ! 2566: (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))] ! 2567: "TARGET_V9" ! 2568: "lduh %1,%0" ! 2569: [(set_attr "type" "load")]) ! 2570: ! 2571: ;; ??? Write truncdisi pattern using sra? ! 2572: ! 2573: (define_expand "zero_extendsidi2" ! 2574: [(set (match_operand:DI 0 "register_operand" "") ! 2575: (zero_extend:DI (match_operand:SI 1 "register_operand" "")))] ! 2576: "TARGET_V9" ! 2577: "") ! 2578: ! 2579: (define_insn "" ! 2580: [(set (match_operand:DI 0 "register_operand" "=r,r") ! 2581: (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))] ! 2582: "TARGET_V9 && GET_CODE (operands[1]) != CONST_INT" ! 2583: "@ ! 2584: srl %1,0,%0 ! 2585: lduw %1,%0" ! 2586: [(set_attr "type" "unary,load") ! 2587: (set_attr "length" "1")]) ! 2588: ! 2589: ;; Simplify comparisons of extended values. ! 2590: 1.1 root 2591: (define_insn "" 2592: [(set (reg:CC 0) 2593: (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r")) 2594: (const_int 0)))] 2595: "" 2596: "andcc %0,0xff,%%g0" 2597: [(set_attr "type" "compare")]) 2598: 2599: (define_insn "" 2600: [(set (reg:CC 0) 2601: (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) 2602: (const_int 0))) 2603: (set (match_operand:SI 0 "register_operand" "=r") 2604: (zero_extend:SI (match_dup 1)))] 2605: "" 2606: "andcc %1,0xff,%0" 2607: [(set_attr "type" "unary")]) 2608: 2609: ;; Similarly, handle SI->QI mode truncation followed by a compare. 2610: 2611: (define_insn "" 2612: [(set (reg:CC 0) 2613: (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0) 2614: (const_int 0)))] 2615: "" 2616: "andcc %0,0xff,%%g0" 2617: [(set_attr "type" "compare")]) 2618: 2619: (define_insn "" 2620: [(set (reg:CC 0) 2621: (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0) 2622: (const_int 0))) 2623: (set (match_operand:QI 0 "register_operand" "=r") 2624: (match_dup 1))] 2625: "" 2626: "andcc %1,0xff,%0" 2627: [(set_attr "type" "unary")]) 2628: 2629: ;;- sign extension instructions 2630: 2631: ;; These patterns originally accepted general_operands, however, slightly 2632: ;; better code is generated by only accepting register_operands, and then 2633: ;; letting combine generate the lds[hb] insns. 2634: 2635: (define_expand "extendhisi2" 2636: [(set (match_operand:SI 0 "register_operand" "") 2637: (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] 2638: "" 2639: " 2640: { 2641: rtx temp = gen_reg_rtx (SImode); 2642: rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); 1.1.1.2 root 2643: int op1_subword = 0; 1.1 root 2644: 2645: if (GET_CODE (operand1) == SUBREG) 1.1.1.2 root 2646: { 2647: op1_subword = SUBREG_WORD (operand1); 2648: operand1 = XEXP (operand1, 0); 2649: } 1.1 root 2650: 1.1.1.2 root 2651: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 2652: op1_subword), 1.1 root 2653: shift_16)); 2654: emit_insn (gen_ashrsi3 (operand0, temp, shift_16)); 2655: DONE; 2656: }") 2657: 2658: (define_insn "" 2659: [(set (match_operand:SI 0 "register_operand" "=r") 2660: (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 2661: "" 2662: "ldsh %1,%0" 2663: [(set_attr "type" "load")]) 2664: 2665: (define_expand "extendqihi2" 2666: [(set (match_operand:HI 0 "register_operand" "") 2667: (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] 2668: "" 2669: " 2670: { 2671: rtx temp = gen_reg_rtx (SImode); 2672: rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); 1.1.1.2 root 2673: int op1_subword = 0; 2674: int op0_subword = 0; 1.1 root 2675: 2676: if (GET_CODE (operand1) == SUBREG) 1.1.1.2 root 2677: { 2678: op1_subword = SUBREG_WORD (operand1); 2679: operand1 = XEXP (operand1, 0); 2680: } 1.1 root 2681: if (GET_CODE (operand0) == SUBREG) 1.1.1.2 root 2682: { 2683: op0_subword = SUBREG_WORD (operand0); 2684: operand0 = XEXP (operand0, 0); 2685: } 2686: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 2687: op1_subword), 1.1 root 2688: shift_24)); 2689: if (GET_MODE (operand0) != SImode) 1.1.1.2 root 2690: operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword); 1.1 root 2691: emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); 2692: DONE; 2693: }") 2694: 2695: (define_insn "" 2696: [(set (match_operand:HI 0 "register_operand" "=r") 2697: (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] 2698: "" 2699: "ldsb %1,%0" 2700: [(set_attr "type" "load")]) 2701: 2702: (define_expand "extendqisi2" 2703: [(set (match_operand:SI 0 "register_operand" "") 2704: (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] 2705: "" 2706: " 2707: { 2708: rtx temp = gen_reg_rtx (SImode); 2709: rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); 1.1.1.2 root 2710: int op1_subword = 0; 1.1 root 2711: 2712: if (GET_CODE (operand1) == SUBREG) 1.1.1.2 root 2713: { 2714: op1_subword = SUBREG_WORD (operand1); 2715: operand1 = XEXP (operand1, 0); 2716: } 2717: 2718: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 2719: op1_subword), 1.1 root 2720: shift_24)); 2721: emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); 2722: DONE; 2723: }") 2724: 2725: (define_insn "" 2726: [(set (match_operand:SI 0 "register_operand" "=r") 2727: (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 2728: "" 2729: "ldsb %1,%0" 2730: [(set_attr "type" "load")]) 1.1.1.3 ! root 2731: ! 2732: (define_expand "extendqidi2" ! 2733: [(set (match_operand:DI 0 "register_operand" "") ! 2734: (sign_extend:DI (match_operand:QI 1 "register_operand" "")))] ! 2735: "TARGET_V9" ! 2736: " ! 2737: { ! 2738: rtx temp = gen_reg_rtx (DImode); ! 2739: rtx shift_56 = gen_rtx (CONST_INT, VOIDmode, 56); ! 2740: int op1_subword = 0; ! 2741: ! 2742: if (GET_CODE (operand1) == SUBREG) ! 2743: { ! 2744: op1_subword = SUBREG_WORD (operand1); ! 2745: operand1 = XEXP (operand1, 0); ! 2746: } ! 2747: ! 2748: emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1, ! 2749: op1_subword), ! 2750: shift_56)); ! 2751: emit_insn (gen_ashrdi3 (operand0, temp, shift_56)); ! 2752: DONE; ! 2753: }") ! 2754: ! 2755: (define_insn "" ! 2756: [(set (match_operand:DI 0 "register_operand" "=r") ! 2757: (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))] ! 2758: "TARGET_V9" ! 2759: "ldsb %1,%0" ! 2760: [(set_attr "type" "load")]) ! 2761: ! 2762: (define_expand "extendhidi2" ! 2763: [(set (match_operand:DI 0 "register_operand" "") ! 2764: (sign_extend:DI (match_operand:HI 1 "register_operand" "")))] ! 2765: "TARGET_V9" ! 2766: " ! 2767: { ! 2768: rtx temp = gen_reg_rtx (DImode); ! 2769: rtx shift_48 = gen_rtx (CONST_INT, VOIDmode, 48); ! 2770: int op1_subword = 0; ! 2771: ! 2772: if (GET_CODE (operand1) == SUBREG) ! 2773: { ! 2774: op1_subword = SUBREG_WORD (operand1); ! 2775: operand1 = XEXP (operand1, 0); ! 2776: } ! 2777: ! 2778: emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1, ! 2779: op1_subword), ! 2780: shift_48)); ! 2781: emit_insn (gen_ashrdi3 (operand0, temp, shift_48)); ! 2782: DONE; ! 2783: }") ! 2784: ! 2785: (define_insn "" ! 2786: [(set (match_operand:DI 0 "register_operand" "=r") ! 2787: (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))] ! 2788: "TARGET_V9" ! 2789: "ldsh %1,%0" ! 2790: [(set_attr "type" "load")]) ! 2791: ! 2792: (define_expand "extendsidi2" ! 2793: [(set (match_operand:DI 0 "register_operand" "") ! 2794: (sign_extend:DI (match_operand:SI 1 "register_operand" "")))] ! 2795: "TARGET_V9" ! 2796: "") ! 2797: ! 2798: (define_insn "" ! 2799: [(set (match_operand:DI 0 "register_operand" "=r,r") ! 2800: (sign_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))] ! 2801: "TARGET_V9" ! 2802: "@ ! 2803: sra %1,0,%0 ! 2804: ldsw %1,%0" ! 2805: [(set_attr "type" "unary,load") ! 2806: (set_attr "length" "1")]) 1.1 root 2807: 2808: ;; Special pattern for optimizing bit-field compares. This is needed 2809: ;; because combine uses this as a canonical form. 2810: 2811: (define_insn "" 2812: [(set (reg:CC 0) 2813: (compare:CC 2814: (zero_extract:SI (match_operand:SI 0 "register_operand" "r") 2815: (match_operand:SI 1 "small_int" "n") 2816: (match_operand:SI 2 "small_int" "n")) 2817: (const_int 0)))] 2818: "INTVAL (operands[2]) > 19" 2819: "* 2820: { 2821: int len = INTVAL (operands[1]); 2822: int pos = 32 - INTVAL (operands[2]) - len; 2823: unsigned mask = ((1 << len) - 1) << pos; 2824: 2825: operands[1] = gen_rtx (CONST_INT, VOIDmode, mask); 2826: return \"andcc %0,%1,%%g0\"; 2827: }") 1.1.1.3 ! root 2828: ! 2829: (define_insn "" ! 2830: [(set (reg:CCX 0) ! 2831: (compare:CCX ! 2832: (zero_extract:DI (match_operand:DI 0 "register_operand" "r") ! 2833: (match_operand:SI 1 "small_int" "n") ! 2834: (match_operand:SI 2 "small_int" "n")) ! 2835: (const_int 0)))] ! 2836: "TARGET_V9 && INTVAL (operands[2]) > 51" ! 2837: "* ! 2838: { ! 2839: int len = INTVAL (operands[1]); ! 2840: int pos = 64 - INTVAL (operands[2]) - len; ! 2841: unsigned mask = ((1 << len) - 1) << pos; ! 2842: ! 2843: operands[1] = gen_rtx (CONST_INT, VOIDmode, mask); ! 2844: return \"andcc %0,%1,%%g0\"; ! 2845: }") 1.1 root 2846: 2847: ;; Conversions between float, double and long double. 2848: 2849: (define_insn "extendsfdf2" 1.1.1.3 ! root 2850: [(set (match_operand:DF 0 "register_operand" "=e") 1.1 root 2851: (float_extend:DF 2852: (match_operand:SF 1 "register_operand" "f")))] 2853: "TARGET_FPU" 2854: "fstod %1,%0" 2855: [(set_attr "type" "fp")]) 2856: 2857: (define_insn "extendsftf2" 1.1.1.3 ! root 2858: [(set (match_operand:TF 0 "register_operand" "=e") 1.1 root 2859: (float_extend:TF 2860: (match_operand:SF 1 "register_operand" "f")))] 1.1.1.3 ! root 2861: "TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 2862: "fstoq %1,%0" 2863: [(set_attr "type" "fp")]) 2864: 2865: (define_insn "extenddftf2" 1.1.1.3 ! root 2866: [(set (match_operand:TF 0 "register_operand" "=e") 1.1 root 2867: (float_extend:TF 1.1.1.3 ! root 2868: (match_operand:DF 1 "register_operand" "e")))] ! 2869: "TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 2870: "fdtoq %1,%0" 2871: [(set_attr "type" "fp")]) 2872: 2873: (define_insn "truncdfsf2" 2874: [(set (match_operand:SF 0 "register_operand" "=f") 2875: (float_truncate:SF 1.1.1.3 ! root 2876: (match_operand:DF 1 "register_operand" "e")))] 1.1 root 2877: "TARGET_FPU" 2878: "fdtos %1,%0" 2879: [(set_attr "type" "fp")]) 2880: 2881: (define_insn "trunctfsf2" 2882: [(set (match_operand:SF 0 "register_operand" "=f") 2883: (float_truncate:SF 1.1.1.3 ! root 2884: (match_operand:TF 1 "register_operand" "e")))] ! 2885: "TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 2886: "fqtos %1,%0" 2887: [(set_attr "type" "fp")]) 2888: 2889: (define_insn "trunctfdf2" 1.1.1.3 ! root 2890: [(set (match_operand:DF 0 "register_operand" "=e") 1.1 root 2891: (float_truncate:DF 1.1.1.3 ! root 2892: (match_operand:TF 1 "register_operand" "e")))] ! 2893: "TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 2894: "fqtod %1,%0" 2895: [(set_attr "type" "fp")]) 2896: 2897: ;; Conversion between fixed point and floating point. 2898: 2899: (define_insn "floatsisf2" 2900: [(set (match_operand:SF 0 "register_operand" "=f") 2901: (float:SF (match_operand:SI 1 "register_operand" "f")))] 2902: "TARGET_FPU" 2903: "fitos %1,%0" 2904: [(set_attr "type" "fp")]) 2905: 1.1.1.3 ! root 2906: (define_insn "floatsidf2" ! 2907: [(set (match_operand:DF 0 "register_operand" "=e") ! 2908: (float:DF (match_operand:SI 1 "register_operand" "f")))] ! 2909: "TARGET_FPU" ! 2910: "fitod %1,%0" ! 2911: [(set_attr "type" "fp")]) ! 2912: ! 2913: (define_insn "floatsitf2" ! 2914: [(set (match_operand:TF 0 "register_operand" "=e") ! 2915: (float:TF (match_operand:SI 1 "register_operand" "f")))] ! 2916: "TARGET_FPU && TARGET_HARD_QUAD" ! 2917: "fitoq %1,%0" ! 2918: [(set_attr "type" "fp")]) ! 2919: ! 2920: ;; Now the same for 64 bit sources. ! 2921: ;; ??? We cannot put DImode values in fp regs (see below near fix_truncdfsi2). ! 2922: ! 2923: (define_expand "floatdisf2" ! 2924: [(parallel [(set (match_operand:SF 0 "register_operand" "") ! 2925: (float:SF (match_operand:DI 1 "general_operand" ""))) ! 2926: (clobber (match_dup 2)) ! 2927: (clobber (match_dup 3))])] ! 2928: "TARGET_V9 && TARGET_FPU" ! 2929: " ! 2930: { ! 2931: operands[2] = gen_reg_rtx (DFmode); ! 2932: operands[3] = sparc64_fpconv_stack_temp (); ! 2933: }") ! 2934: ! 2935: (define_expand "floatdidf2" ! 2936: [(parallel [(set (match_operand:DF 0 "register_operand" "") ! 2937: (float:DF (match_operand:DI 1 "general_operand" ""))) ! 2938: (clobber (match_dup 2)) ! 2939: (clobber (match_dup 3))])] ! 2940: "TARGET_V9 && TARGET_FPU" ! 2941: " ! 2942: { ! 2943: operands[2] = gen_reg_rtx (DFmode); ! 2944: operands[3] = sparc64_fpconv_stack_temp (); ! 2945: }") ! 2946: ! 2947: (define_expand "floatditf2" ! 2948: [(parallel [(set (match_operand:TF 0 "register_operand" "") ! 2949: (float:TF (match_operand:DI 1 "general_operand" ""))) ! 2950: (clobber (match_dup 2)) ! 2951: (clobber (match_dup 3))])] ! 2952: "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" ! 2953: " ! 2954: { ! 2955: operands[2] = gen_reg_rtx (DFmode); ! 2956: operands[3] = sparc64_fpconv_stack_temp (); ! 2957: }") ! 2958: ! 2959: (define_insn "" ! 2960: [(parallel [(set (match_operand:SF 0 "register_operand" "=f") ! 2961: (float:SF (match_operand:DI 1 "general_operand" "rm"))) ! 2962: (clobber (match_operand:DF 2 "register_operand" "=&e")) ! 2963: (clobber (match_operand:DI 3 "memory_operand" "m"))])] ! 2964: "TARGET_V9 && TARGET_FPU" ! 2965: "* ! 2966: { ! 2967: if (GET_CODE (operands[1]) == MEM) ! 2968: output_asm_insn (\"ldd %1,%2\", operands); ! 2969: else ! 2970: output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands); ! 2971: return \"fxtos %2,%0\"; ! 2972: }" ! 2973: [(set_attr "type" "fp") ! 2974: (set_attr "length" "3")]) ! 2975: ! 2976: (define_insn "" ! 2977: [(parallel [(set (match_operand:DF 0 "register_operand" "=e") ! 2978: (float:DF (match_operand:DI 1 "general_operand" "rm"))) ! 2979: (clobber (match_operand:DF 2 "register_operand" "=&e")) ! 2980: (clobber (match_operand:DI 3 "memory_operand" "m"))])] ! 2981: "TARGET_V9 && TARGET_FPU" ! 2982: "* ! 2983: { ! 2984: if (GET_CODE (operands[1]) == MEM) ! 2985: output_asm_insn (\"ldd %1,%2\", operands); ! 2986: else ! 2987: output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands); ! 2988: return \"fxtod %2,%0\"; ! 2989: }" ! 2990: [(set_attr "type" "fp") ! 2991: (set_attr "length" "3")]) ! 2992: ! 2993: (define_insn "" ! 2994: [(parallel [(set (match_operand:TF 0 "register_operand" "=e") ! 2995: (float:TF (match_operand:DI 1 "general_operand" "rm"))) ! 2996: (clobber (match_operand:DF 2 "register_operand" "=&e")) ! 2997: (clobber (match_operand:DI 3 "memory_operand" "m"))])] ! 2998: "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" ! 2999: "* ! 3000: { ! 3001: if (GET_CODE (operands[1]) == MEM) ! 3002: output_asm_insn (\"ldd %1,%2\", operands); ! 3003: else ! 3004: output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands); ! 3005: return \"fxtoq %2,%0\"; ! 3006: }" ! 3007: [(set_attr "type" "fp") ! 3008: (set_attr "length" "3")]) ! 3009: ! 3010: ;; ??? Ideally, these are what we would like to use. ! 3011: ! 3012: (define_insn "floatdisf2_v9" ! 3013: [(set (match_operand:SF 0 "register_operand" "=f") ! 3014: (float:SF (match_operand:DI 1 "register_operand" "e")))] ! 3015: "0 && TARGET_V9 && TARGET_FPU" ! 3016: "fxtos %1,%0" ! 3017: [(set_attr "type" "fp")]) ! 3018: ! 3019: (define_insn "floatdidf2_v9" ! 3020: [(set (match_operand:DF 0 "register_operand" "=e") ! 3021: (float:DF (match_operand:DI 1 "register_operand" "e")))] ! 3022: "0 && TARGET_V9 && TARGET_FPU" ! 3023: "fxtod %1,%0" ! 3024: [(set_attr "type" "fp")]) ! 3025: ! 3026: (define_insn "floatditf2_v9" ! 3027: [(set (match_operand:TF 0 "register_operand" "=e") ! 3028: (float:TF (match_operand:DI 1 "register_operand" "e")))] ! 3029: "0 && TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" ! 3030: "fxtoq %1,%0" ! 3031: [(set_attr "type" "fp")]) ! 3032: ! 3033: ;; Convert a float to an actual integer. ! 3034: ;; Truncation is performed as part of the conversion. ! 3035: ! 3036: (define_insn "fix_truncsfsi2" ! 3037: [(set (match_operand:SI 0 "register_operand" "=f") ! 3038: (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] ! 3039: "TARGET_FPU" ! 3040: "fstoi %1,%0" ! 3041: [(set_attr "type" "fp")]) ! 3042: ! 3043: (define_insn "fix_truncdfsi2" ! 3044: [(set (match_operand:SI 0 "register_operand" "=f") ! 3045: (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))] ! 3046: "TARGET_FPU" ! 3047: "fdtoi %1,%0" ! 3048: [(set_attr "type" "fp")]) ! 3049: ! 3050: (define_insn "fix_trunctfsi2" ! 3051: [(set (match_operand:SI 0 "register_operand" "=f") ! 3052: (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))] ! 3053: "TARGET_FPU && TARGET_HARD_QUAD" ! 3054: "fqtoi %1,%0" ! 3055: [(set_attr "type" "fp")]) ! 3056: ! 3057: ;; Now the same, for 64-bit targets ! 3058: ;; ??? We try to work around an interesting problem. ! 3059: ;; If gcc tries to do a subreg on the result it will get the wrong answer: ! 3060: ;; "(subreg:SI (reg:DI M int-reg) 0)" is the same as ! 3061: ;; "(subreg:SI (reg:DI N float-reg) 1)", but gcc does not know how to change ! 3062: ;; the "0" to a "1". One could enhance alter_subreg but it is not clear how to ! 3063: ;; do this cleanly. ! 3064: ! 3065: (define_expand "fix_truncsfdi2" ! 3066: [(parallel [(set (match_operand:DI 0 "general_operand" "") ! 3067: (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "")))) ! 3068: (clobber (match_dup 2)) ! 3069: (clobber (match_dup 3))])] ! 3070: "TARGET_V9 && TARGET_FPU" ! 3071: " ! 3072: { ! 3073: operands[2] = gen_reg_rtx (DFmode); ! 3074: operands[3] = sparc64_fpconv_stack_temp (); ! 3075: }") ! 3076: ! 3077: (define_expand "fix_truncdfdi2" ! 3078: [(parallel [(set (match_operand:DI 0 "general_operand" "") ! 3079: (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "")))) ! 3080: (clobber (match_dup 2)) ! 3081: (clobber (match_dup 3))])] ! 3082: "TARGET_V9 && TARGET_FPU" ! 3083: " ! 3084: { ! 3085: operands[2] = gen_reg_rtx (DFmode); ! 3086: operands[3] = sparc64_fpconv_stack_temp (); ! 3087: }") ! 3088: ! 3089: (define_expand "fix_trunctfdi2" ! 3090: [(parallel [(set (match_operand:DI 0 "general_operand" "") ! 3091: (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "")))) ! 3092: (clobber (match_dup 2)) ! 3093: (clobber (match_dup 3))])] ! 3094: "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" ! 3095: " ! 3096: { ! 3097: operands[2] = gen_reg_rtx (DFmode); ! 3098: operands[3] = sparc64_fpconv_stack_temp (); ! 3099: }") ! 3100: ! 3101: (define_insn "" ! 3102: [(parallel [(set (match_operand:DI 0 "general_operand" "=rm") ! 3103: (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f")))) ! 3104: (clobber (match_operand:DF 2 "register_operand" "=&e")) ! 3105: (clobber (match_operand:DI 3 "memory_operand" "m"))])] ! 3106: "TARGET_V9 && TARGET_FPU" ! 3107: "* ! 3108: { ! 3109: output_asm_insn (\"fstox %1,%2\", operands); ! 3110: if (GET_CODE (operands[0]) == MEM) ! 3111: return \"std %2,%0\"; ! 3112: else ! 3113: return \"std %2,%3\;ldx %3,%0\"; ! 3114: }" ! 3115: [(set_attr "type" "fp") ! 3116: (set_attr "length" "3")]) ! 3117: ! 3118: (define_insn "" ! 3119: [(parallel [(set (match_operand:DI 0 "general_operand" "=rm") ! 3120: (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e")))) ! 3121: (clobber (match_operand:DF 2 "register_operand" "=&e")) ! 3122: (clobber (match_operand:DI 3 "memory_operand" "m"))])] ! 3123: "TARGET_V9 && TARGET_FPU" ! 3124: "* ! 3125: { ! 3126: output_asm_insn (\"fdtox %1,%2\", operands); ! 3127: if (GET_CODE (operands[0]) == MEM) ! 3128: return \"std %2,%0\"; ! 3129: else ! 3130: return \"std %2,%3\;ldx %3,%0\"; ! 3131: }" ! 3132: [(set_attr "type" "fp") ! 3133: (set_attr "length" "3")]) 1.1 root 3134: 1.1.1.3 ! root 3135: (define_insn "" ! 3136: [(parallel [(set (match_operand:DI 0 "general_operand" "=rm") ! 3137: (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e")))) ! 3138: (clobber (match_operand:DF 2 "register_operand" "=&e")) ! 3139: (clobber (match_operand:DI 3 "memory_operand" "m"))])] ! 3140: "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" ! 3141: "* ! 3142: { ! 3143: output_asm_insn (\"fqtox %1,%2\", operands); ! 3144: if (GET_CODE (operands[0]) == MEM) ! 3145: return \"std %2,%0\"; ! 3146: else ! 3147: return \"std %2,%3\;ldx %3,%0\"; ! 3148: }" ! 3149: [(set_attr "type" "fp") ! 3150: (set_attr "length" "3")]) 1.1 root 3151: 1.1.1.3 ! root 3152: ;; ??? Ideally, these are what we would like to use. 1.1 root 3153: 1.1.1.3 ! root 3154: (define_insn "fix_truncsfdi2_v9" ! 3155: [(set (match_operand:DI 0 "register_operand" "=e") ! 3156: (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] ! 3157: "0 && TARGET_V9 && TARGET_FPU" ! 3158: "fstox %1,%0" 1.1 root 3159: [(set_attr "type" "fp")]) 3160: 1.1.1.3 ! root 3161: (define_insn "fix_truncdfdi2_v9" ! 3162: [(set (match_operand:DI 0 "register_operand" "=e") ! 3163: (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))] ! 3164: "0 && TARGET_V9 && TARGET_FPU" ! 3165: "fdtox %1,%0" 1.1 root 3166: [(set_attr "type" "fp")]) 3167: 1.1.1.3 ! root 3168: (define_insn "fix_trunctfdi2_v9" ! 3169: [(set (match_operand:DI 0 "register_operand" "=e") ! 3170: (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))] ! 3171: "0 && TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" ! 3172: "fqtox %1,%0" 1.1 root 3173: [(set_attr "type" "fp")]) 3174: 3175: ;;- arithmetic instructions 3176: 1.1.1.3 ! root 3177: (define_expand "adddi3" ! 3178: [(set (match_operand:DI 0 "register_operand" "=r") ! 3179: (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 3180: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3181: "" ! 3182: " ! 3183: { ! 3184: if (! TARGET_V9) ! 3185: { ! 3186: emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, ! 3187: gen_rtx (SET, VOIDmode, operands[0], ! 3188: gen_rtx (PLUS, DImode, operands[1], ! 3189: operands[2])), ! 3190: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 0))))); ! 3191: DONE; ! 3192: } ! 3193: }") ! 3194: ! 3195: (define_insn "" 1.1 root 3196: [(set (match_operand:DI 0 "register_operand" "=r") 3197: (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") 3198: (match_operand:DI 2 "arith_double_operand" "rHI"))) 3199: (clobber (reg:SI 0))] 1.1.1.3 ! root 3200: "! TARGET_V9" 1.1 root 3201: "* 3202: { 3203: rtx op2 = operands[2]; 3204: 3205: /* If constant is positive, upper bits zeroed, otherwise unchanged. 3206: Give the assembler a chance to pick the move instruction. */ 3207: if (GET_CODE (op2) == CONST_INT) 3208: { 3209: int sign = INTVAL (op2); 3210: if (sign < 0) 3211: return \"addcc %R1,%2,%R0\;addx %1,-1,%0\"; 3212: return \"addcc %R1,%2,%R0\;addx %1,0,%0\"; 3213: } 3214: else if (GET_CODE (op2) == CONST_DOUBLE) 3215: { 1.1.1.3 ! root 3216: rtx xoperands[4]; ! 3217: xoperands[0] = operands[0]; ! 3218: xoperands[1] = operands[1]; ! 3219: xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2)); ! 3220: xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2)); ! 3221: if (xoperands[2] == const0_rtx && xoperands[0] == xoperands[1]) ! 3222: output_asm_insn (\"add %1,%3,%0\", xoperands); ! 3223: else ! 3224: output_asm_insn (\"addcc %R1,%2,%R0\;addx %1,%3,%0\", xoperands); ! 3225: return \"\"; 1.1 root 3226: } 3227: return \"addcc %R1,%R2,%R0\;addx %1,%2,%0\"; 3228: }" 3229: [(set_attr "length" "2")]) 3230: 1.1.1.3 ! root 3231: (define_insn "" ! 3232: [(set (match_operand:DI 0 "register_operand" "=r") ! 3233: (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 3234: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3235: "TARGET_V9" ! 3236: "add %1,%2,%0") ! 3237: 1.1 root 3238: (define_insn "addsi3" 3239: [(set (match_operand:SI 0 "register_operand" "=r") 3240: (plus:SI (match_operand:SI 1 "arith_operand" "%r") 3241: (match_operand:SI 2 "arith_operand" "rI")))] 3242: "" 1.1.1.3 ! root 3243: "add %1,%2,%0" ! 3244: [(set_attr "type" "ialu")]) 1.1 root 3245: 3246: (define_insn "" 3247: [(set (reg:CC_NOOV 0) 3248: (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r") 3249: (match_operand:SI 1 "arith_operand" "rI")) 3250: (const_int 0)))] 3251: "" 3252: "addcc %0,%1,%%g0" 3253: [(set_attr "type" "compare")]) 3254: 3255: (define_insn "" 1.1.1.3 ! root 3256: [(set (reg:CCX_NOOV 0) ! 3257: (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r") ! 3258: (match_operand:DI 1 "arith_double_operand" "rHI")) ! 3259: (const_int 0)))] ! 3260: "TARGET_V9" ! 3261: "addcc %0,%1,%%g0" ! 3262: [(set_attr "type" "compare")]) ! 3263: ! 3264: (define_insn "" 1.1 root 3265: [(set (reg:CC_NOOV 0) 3266: (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r") 3267: (match_operand:SI 2 "arith_operand" "rI")) 3268: (const_int 0))) 3269: (set (match_operand:SI 0 "register_operand" "=r") 3270: (plus:SI (match_dup 1) (match_dup 2)))] 3271: "" 3272: "addcc %1,%2,%0") 3273: 1.1.1.3 ! root 3274: (define_insn "" ! 3275: [(set (reg:CCX_NOOV 0) ! 3276: (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 3277: (match_operand:DI 2 "arith_double_operand" "rHI")) ! 3278: (const_int 0))) ! 3279: (set (match_operand:DI 0 "register_operand" "=r") ! 3280: (plus:DI (match_dup 1) (match_dup 2)))] ! 3281: "TARGET_V9" ! 3282: "addcc %1,%2,%0") ! 3283: ! 3284: (define_expand "subdi3" ! 3285: [(set (match_operand:DI 0 "register_operand" "=r") ! 3286: (minus:DI (match_operand:DI 1 "register_operand" "r") ! 3287: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3288: "" ! 3289: " ! 3290: { ! 3291: if (! TARGET_V9) ! 3292: { ! 3293: emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, ! 3294: gen_rtx (SET, VOIDmode, operands[0], ! 3295: gen_rtx (MINUS, DImode, operands[1], ! 3296: operands[2])), ! 3297: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 0))))); ! 3298: DONE; ! 3299: } ! 3300: }") ! 3301: ! 3302: (define_insn "" 1.1 root 3303: [(set (match_operand:DI 0 "register_operand" "=r") 3304: (minus:DI (match_operand:DI 1 "register_operand" "r") 3305: (match_operand:DI 2 "arith_double_operand" "rHI"))) 3306: (clobber (reg:SI 0))] 1.1.1.3 ! root 3307: "! TARGET_V9" 1.1 root 3308: "* 3309: { 3310: rtx op2 = operands[2]; 3311: 3312: /* If constant is positive, upper bits zeroed, otherwise unchanged. 3313: Give the assembler a chance to pick the move instruction. */ 3314: if (GET_CODE (op2) == CONST_INT) 3315: { 3316: int sign = INTVAL (op2); 3317: if (sign < 0) 3318: return \"subcc %R1,%2,%R0\;subx %1,-1,%0\"; 3319: return \"subcc %R1,%2,%R0\;subx %1,0,%0\"; 3320: } 3321: else if (GET_CODE (op2) == CONST_DOUBLE) 3322: { 1.1.1.3 ! root 3323: rtx xoperands[4]; ! 3324: xoperands[0] = operands[0]; ! 3325: xoperands[1] = operands[1]; ! 3326: xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2)); ! 3327: xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2)); ! 3328: if (xoperands[2] == const0_rtx && xoperands[0] == xoperands[1]) ! 3329: output_asm_insn (\"sub %1,%3,%0\", xoperands); ! 3330: else ! 3331: output_asm_insn (\"subcc %R1,%2,%R0\;subx %1,%3,%0\", xoperands); ! 3332: return \"\"; 1.1 root 3333: } 3334: return \"subcc %R1,%R2,%R0\;subx %1,%2,%0\"; 3335: }" 3336: [(set_attr "length" "2")]) 3337: 1.1.1.3 ! root 3338: (define_insn "" ! 3339: [(set (match_operand:DI 0 "register_operand" "=r") ! 3340: (minus:DI (match_operand:DI 1 "register_operand" "r") ! 3341: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3342: "TARGET_V9" ! 3343: "sub %1,%2,%0") ! 3344: 1.1 root 3345: (define_insn "subsi3" 3346: [(set (match_operand:SI 0 "register_operand" "=r") 3347: (minus:SI (match_operand:SI 1 "register_operand" "r") 3348: (match_operand:SI 2 "arith_operand" "rI")))] 3349: "" 1.1.1.3 ! root 3350: "sub %1,%2,%0" ! 3351: [(set_attr "type" "ialu")]) 1.1 root 3352: 3353: (define_insn "" 3354: [(set (reg:CC_NOOV 0) 3355: (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r") 3356: (match_operand:SI 1 "arith_operand" "rI")) 3357: (const_int 0)))] 3358: "" 3359: "subcc %0,%1,%%g0" 3360: [(set_attr "type" "compare")]) 3361: 3362: (define_insn "" 1.1.1.3 ! root 3363: [(set (reg:CCX_NOOV 0) ! 3364: (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r") ! 3365: (match_operand:DI 1 "arith_double_operand" "rHI")) ! 3366: (const_int 0)))] ! 3367: "TARGET_V9" ! 3368: "subcc %0,%1,%%g0" ! 3369: [(set_attr "type" "compare")]) ! 3370: ! 3371: (define_insn "" 1.1 root 3372: [(set (reg:CC_NOOV 0) 3373: (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r") 3374: (match_operand:SI 2 "arith_operand" "rI")) 3375: (const_int 0))) 3376: (set (match_operand:SI 0 "register_operand" "=r") 3377: (minus:SI (match_dup 1) (match_dup 2)))] 3378: "" 3379: "subcc %1,%2,%0") 3380: 1.1.1.3 ! root 3381: (define_insn "" ! 3382: [(set (reg:CCX_NOOV 0) ! 3383: (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r") ! 3384: (match_operand:DI 2 "arith_double_operand" "rHI")) ! 3385: (const_int 0))) ! 3386: (set (match_operand:DI 0 "register_operand" "=r") ! 3387: (minus:DI (match_dup 1) (match_dup 2)))] ! 3388: "TARGET_V9" ! 3389: "subcc %1,%2,%0") ! 3390: ! 3391: ;; This is anachronistic, and should not be used in v9 software. ! 3392: ;; The v9 compiler will widen the args and use muldi3. ! 3393: 1.1 root 3394: (define_insn "mulsi3" 3395: [(set (match_operand:SI 0 "register_operand" "=r") 3396: (mult:SI (match_operand:SI 1 "arith_operand" "%r") 3397: (match_operand:SI 2 "arith_operand" "rI")))] 3398: "TARGET_V8 || TARGET_SPARCLITE" 1.1.1.3 ! root 3399: "smul %1,%2,%0" ! 3400: [(set_attr "type" "imul")]) ! 3401: ! 3402: (define_insn "muldi3" ! 3403: [(set (match_operand:DI 0 "register_operand" "=r") ! 3404: (mult:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 3405: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3406: "TARGET_V9" ! 3407: "mulx %1,%2,%0") 1.1 root 3408: 3409: ;; It is not known whether this will match. 3410: 3411: (define_insn "" 3412: [(set (match_operand:SI 0 "register_operand" "=r") 3413: (mult:SI (match_operand:SI 1 "arith_operand" "%r") 3414: (match_operand:SI 2 "arith_operand" "rI"))) 3415: (set (reg:CC_NOOV 0) 3416: (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2)) 3417: (const_int 0)))] 3418: "TARGET_V8 || TARGET_SPARCLITE" 1.1.1.3 ! root 3419: "smulcc %1,%2,%0" ! 3420: [(set_attr "type" "imul")]) 1.1 root 3421: 3422: (define_expand "mulsidi3" 3423: [(set (match_operand:DI 0 "register_operand" "") 3424: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) 3425: (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))] 3426: "TARGET_V8 || TARGET_SPARCLITE" 3427: " 3428: { 3429: if (CONSTANT_P (operands[2])) 3430: { 3431: emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2])); 3432: DONE; 3433: } 3434: }") 3435: 3436: (define_insn "" 3437: [(set (match_operand:DI 0 "register_operand" "=r") 3438: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) 3439: (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 3440: "TARGET_V8 || TARGET_SPARCLITE" 3441: "smul %1,%2,%R0\;rd %%y,%0" 3442: [(set_attr "length" "2")]) 3443: 3444: ;; Extra pattern, because sign_extend of a constant isn't legal. 3445: 3446: (define_insn "const_mulsidi3" 3447: [(set (match_operand:DI 0 "register_operand" "=r") 3448: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) 3449: (match_operand:SI 2 "small_int" "I")))] 3450: "TARGET_V8 || TARGET_SPARCLITE" 3451: "smul %1,%2,%R0\;rd %%y,%0" 3452: [(set_attr "length" "2")]) 3453: 1.1.1.3 ! root 3454: (define_expand "smulsi3_highpart" ! 3455: [(set (match_operand:SI 0 "register_operand" "") ! 3456: (truncate:SI ! 3457: (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) ! 3458: (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))) ! 3459: (const_int 32))))] ! 3460: "TARGET_V8 || TARGET_SPARCLITE" ! 3461: " ! 3462: { ! 3463: if (CONSTANT_P (operands[2])) ! 3464: { ! 3465: emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2])); ! 3466: DONE; ! 3467: } ! 3468: }") ! 3469: ! 3470: (define_insn "" ! 3471: [(set (match_operand:SI 0 "register_operand" "=r") ! 3472: (truncate:SI ! 3473: (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) ! 3474: (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))) ! 3475: (const_int 32))))] ! 3476: "TARGET_V8 || TARGET_SPARCLITE" ! 3477: "smul %1,%2,%%g0\;rd %%y,%0" ! 3478: [(set_attr "length" "2")]) ! 3479: ! 3480: (define_insn "const_smulsi3_highpart" ! 3481: [(set (match_operand:SI 0 "register_operand" "=r") ! 3482: (truncate:SI ! 3483: (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) ! 3484: (match_operand:SI 2 "register_operand" "r")) ! 3485: (const_int 32))))] ! 3486: "TARGET_V8 || TARGET_SPARCLITE" ! 3487: "smul %1,%2,%%g0\;rd %%y,%0" ! 3488: [(set_attr "length" "2")]) ! 3489: 1.1 root 3490: (define_expand "umulsidi3" 3491: [(set (match_operand:DI 0 "register_operand" "") 3492: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) 1.1.1.2 root 3493: (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))] 1.1 root 3494: "TARGET_V8 || TARGET_SPARCLITE" 3495: " 3496: { 3497: if (CONSTANT_P (operands[2])) 3498: { 3499: emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2])); 3500: DONE; 3501: } 3502: }") 3503: 3504: (define_insn "" 3505: [(set (match_operand:DI 0 "register_operand" "=r") 3506: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) 3507: (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 3508: "TARGET_V8 || TARGET_SPARCLITE" 3509: "umul %1,%2,%R0\;rd %%y,%0" 3510: [(set_attr "length" "2")]) 3511: 3512: ;; Extra pattern, because sign_extend of a constant isn't legal. 3513: 3514: (define_insn "const_umulsidi3" 3515: [(set (match_operand:DI 0 "register_operand" "=r") 3516: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) 1.1.1.2 root 3517: (match_operand:SI 2 "uns_small_int" "")))] 1.1 root 3518: "TARGET_V8 || TARGET_SPARCLITE" 3519: "umul %1,%2,%R0\;rd %%y,%0" 3520: [(set_attr "length" "2")]) 3521: 1.1.1.3 ! root 3522: (define_expand "umulsi3_highpart" ! 3523: [(set (match_operand:SI 0 "register_operand" "") ! 3524: (truncate:SI ! 3525: (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) ! 3526: (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))) ! 3527: (const_int 32))))] ! 3528: "TARGET_V8 || TARGET_SPARCLITE" ! 3529: " ! 3530: { ! 3531: if (CONSTANT_P (operands[2])) ! 3532: { ! 3533: emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2])); ! 3534: DONE; ! 3535: } ! 3536: }") ! 3537: ! 3538: (define_insn "" ! 3539: [(set (match_operand:SI 0 "register_operand" "=r") ! 3540: (truncate:SI ! 3541: (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) ! 3542: (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))) ! 3543: (const_int 32))))] ! 3544: "TARGET_V8 || TARGET_SPARCLITE" ! 3545: "umul %1,%2,%%g0\;rd %%y,%0" ! 3546: [(set_attr "length" "2")]) ! 3547: ! 3548: (define_insn "const_umulsi3_highpart" ! 3549: [(set (match_operand:SI 0 "register_operand" "=r") ! 3550: (truncate:SI ! 3551: (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) ! 3552: (match_operand:SI 2 "uns_small_int" "")) ! 3553: (const_int 32))))] ! 3554: "TARGET_V8 || TARGET_SPARCLITE" ! 3555: "umul %1,%2,%%g0\;rd %%y,%0" ! 3556: [(set_attr "length" "2")]) ! 3557: 1.1 root 3558: ;; The architecture specifies that there must be 3 instructions between 3559: ;; a y register write and a use of it for correct results. 3560: 3561: (define_insn "divsi3" 3562: [(set (match_operand:SI 0 "register_operand" "=r") 3563: (div:SI (match_operand:SI 1 "register_operand" "r") 3564: (match_operand:SI 2 "arith_operand" "rI"))) 3565: (clobber (match_scratch:SI 3 "=&r"))] 3566: "TARGET_V8" 3567: "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0" 3568: [(set_attr "length" "6")]) 3569: 1.1.1.3 ! root 3570: (define_insn "divdi3" ! 3571: [(set (match_operand:DI 0 "register_operand" "=r") ! 3572: (div:DI (match_operand:DI 1 "register_operand" "r") ! 3573: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3574: "TARGET_V9" ! 3575: "sdivx %1,%2,%0") ! 3576: 1.1 root 3577: ;; It is not known whether this will match. 3578: 3579: (define_insn "" 3580: [(set (match_operand:SI 0 "register_operand" "=r") 3581: (div:SI (match_operand:SI 1 "register_operand" "r") 3582: (match_operand:SI 2 "arith_operand" "rI"))) 3583: (set (reg:CC 0) 3584: (compare:CC (div:SI (match_dup 1) (match_dup 2)) 3585: (const_int 0))) 3586: (clobber (match_scratch:SI 3 "=&r"))] 3587: "TARGET_V8" 3588: "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0" 3589: [(set_attr "length" "6")]) 3590: 3591: (define_insn "udivsi3" 3592: [(set (match_operand:SI 0 "register_operand" "=r") 3593: (udiv:SI (match_operand:SI 1 "register_operand" "r") 3594: (match_operand:SI 2 "arith_operand" "rI")))] 3595: "TARGET_V8" 3596: "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0" 3597: [(set_attr "length" "5")]) 3598: 1.1.1.3 ! root 3599: (define_insn "udivdi3" ! 3600: [(set (match_operand:DI 0 "register_operand" "=r") ! 3601: (udiv:DI (match_operand:DI 1 "register_operand" "r") ! 3602: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3603: "TARGET_V9" ! 3604: "udivx %1,%2,%0") ! 3605: 1.1 root 3606: ;; It is not known whether this will match. 3607: 3608: (define_insn "" 3609: [(set (match_operand:SI 0 "register_operand" "=r") 3610: (udiv:SI (match_operand:SI 1 "register_operand" "r") 3611: (match_operand:SI 2 "arith_operand" "rI"))) 3612: (set (reg:CC 0) 3613: (compare:CC (udiv:SI (match_dup 1) (match_dup 2)) 3614: (const_int 0)))] 3615: "TARGET_V8" 3616: "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0" 3617: [(set_attr "length" "5")]) 1.1.1.2 root 3618: 3619: ;;- Boolean instructions 1.1 root 3620: ;; We define DImode `and` so with DImode `not` we can get 3621: ;; DImode `andn`. Other combinations are possible. 3622: 3623: (define_expand "anddi3" 3624: [(set (match_operand:DI 0 "register_operand" "") 3625: (and:DI (match_operand:DI 1 "arith_double_operand" "") 3626: (match_operand:DI 2 "arith_double_operand" "")))] 3627: "" 3628: "") 3629: 3630: (define_insn "" 3631: [(set (match_operand:DI 0 "register_operand" "=r") 3632: (and:DI (match_operand:DI 1 "arith_double_operand" "%r") 3633: (match_operand:DI 2 "arith_double_operand" "rHI")))] 1.1.1.3 ! root 3634: "! TARGET_V9" 1.1 root 3635: "* 3636: { 3637: rtx op2 = operands[2]; 3638: 3639: /* If constant is positive, upper bits zeroed, otherwise unchanged. 3640: Give the assembler a chance to pick the move instruction. */ 3641: if (GET_CODE (op2) == CONST_INT) 3642: { 3643: int sign = INTVAL (op2); 3644: if (sign < 0) 3645: return \"mov %1,%0\;and %R1,%2,%R0\"; 3646: return \"mov 0,%0\;and %R1,%2,%R0\"; 3647: } 3648: else if (GET_CODE (op2) == CONST_DOUBLE) 3649: { 1.1.1.3 ! root 3650: rtx xoperands[4]; ! 3651: xoperands[0] = operands[0]; ! 3652: xoperands[1] = operands[1]; ! 3653: xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2)); ! 3654: xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2)); ! 3655: /* We could optimize then operands[1] == operands[0] ! 3656: and either half of the constant is -1. */ ! 3657: output_asm_insn (\"and %R1,%2,%R0\;and %1,%3,%0\", xoperands); ! 3658: return \"\"; 1.1 root 3659: } 3660: return \"and %1,%2,%0\;and %R1,%R2,%R0\"; 3661: }" 3662: [(set_attr "length" "2")]) 3663: 1.1.1.3 ! root 3664: (define_insn "" ! 3665: [(set (match_operand:DI 0 "register_operand" "=r") ! 3666: (and:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 3667: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3668: "TARGET_V9" ! 3669: "and %1,%2,%0") ! 3670: 1.1 root 3671: (define_insn "andsi3" 3672: [(set (match_operand:SI 0 "register_operand" "=r") 3673: (and:SI (match_operand:SI 1 "arith_operand" "%r") 3674: (match_operand:SI 2 "arith_operand" "rI")))] 3675: "" 1.1.1.3 ! root 3676: "and %1,%2,%0" ! 3677: [(set_attr "type" "ialu")]) 1.1 root 3678: 3679: (define_split 3680: [(set (match_operand:SI 0 "register_operand" "") 3681: (and:SI (match_operand:SI 1 "register_operand" "") 3682: (match_operand:SI 2 "" ""))) 3683: (clobber (match_operand:SI 3 "register_operand" ""))] 3684: "GET_CODE (operands[2]) == CONST_INT 3685: && !SMALL_INT (operands[2]) 3686: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" 3687: [(set (match_dup 3) (match_dup 4)) 3688: (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))] 3689: " 3690: { 3691: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); 3692: }") 3693: 3694: (define_insn "" 3695: [(set (match_operand:DI 0 "register_operand" "=r") 3696: (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) 3697: (match_operand:DI 2 "register_operand" "r")))] 1.1.1.3 ! root 3698: "! TARGET_V9" 1.1 root 3699: "andn %2,%1,%0\;andn %R2,%R1,%R0" 3700: [(set_attr "length" "2")]) 3701: 3702: (define_insn "" 1.1.1.3 ! root 3703: [(set (match_operand:DI 0 "register_operand" "=r") ! 3704: (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) ! 3705: (match_operand:DI 2 "register_operand" "r")))] ! 3706: "TARGET_V9" ! 3707: "andn %2,%1,%0") ! 3708: ! 3709: (define_insn "" 1.1 root 3710: [(set (match_operand:SI 0 "register_operand" "=r") 3711: (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) 3712: (match_operand:SI 2 "register_operand" "r")))] 3713: "" 1.1.1.3 ! root 3714: "andn %2,%1,%0" ! 3715: [(set_attr "type" "ialu")]) 1.1 root 3716: 3717: (define_expand "iordi3" 3718: [(set (match_operand:DI 0 "register_operand" "") 3719: (ior:DI (match_operand:DI 1 "arith_double_operand" "") 3720: (match_operand:DI 2 "arith_double_operand" "")))] 3721: "" 3722: "") 3723: 3724: (define_insn "" 3725: [(set (match_operand:DI 0 "register_operand" "=r") 3726: (ior:DI (match_operand:DI 1 "arith_double_operand" "%r") 3727: (match_operand:DI 2 "arith_double_operand" "rHI")))] 1.1.1.3 ! root 3728: "! TARGET_V9" 1.1 root 3729: "* 3730: { 3731: rtx op2 = operands[2]; 3732: 3733: /* If constant is positive, upper bits zeroed, otherwise unchanged. 3734: Give the assembler a chance to pick the move instruction. */ 3735: if (GET_CODE (op2) == CONST_INT) 3736: { 3737: int sign = INTVAL (op2); 3738: if (sign < 0) 3739: return \"mov -1,%0\;or %R1,%2,%R0\"; 3740: return \"mov %1,%0\;or %R1,%2,%R0\"; 3741: } 3742: else if (GET_CODE (op2) == CONST_DOUBLE) 3743: { 1.1.1.3 ! root 3744: rtx xoperands[4]; ! 3745: xoperands[0] = operands[0]; ! 3746: xoperands[1] = operands[1]; ! 3747: xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2)); ! 3748: xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2)); ! 3749: /* We could optimize then operands[1] == operands[0] ! 3750: and either half of the constant is 0. */ ! 3751: output_asm_insn (\"or %R1,%2,%R0\;or %1,%3,%0\", xoperands); ! 3752: return \"\"; 1.1 root 3753: } 3754: return \"or %1,%2,%0\;or %R1,%R2,%R0\"; 3755: }" 3756: [(set_attr "length" "2")]) 3757: 1.1.1.3 ! root 3758: (define_insn "" ! 3759: [(set (match_operand:DI 0 "register_operand" "=r") ! 3760: (ior:DI (match_operand:DI 1 "arith_double_operand" "%r") ! 3761: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3762: "TARGET_V9" ! 3763: "or %1,%2,%0") ! 3764: 1.1 root 3765: (define_insn "iorsi3" 3766: [(set (match_operand:SI 0 "register_operand" "=r") 3767: (ior:SI (match_operand:SI 1 "arith_operand" "%r") 3768: (match_operand:SI 2 "arith_operand" "rI")))] 3769: "" 1.1.1.3 ! root 3770: "or %1,%2,%0" ! 3771: [(set_attr "type" "ialu")]) 1.1 root 3772: 3773: (define_split 3774: [(set (match_operand:SI 0 "register_operand" "") 3775: (ior:SI (match_operand:SI 1 "register_operand" "") 3776: (match_operand:SI 2 "" ""))) 3777: (clobber (match_operand:SI 3 "register_operand" ""))] 3778: "GET_CODE (operands[2]) == CONST_INT 3779: && !SMALL_INT (operands[2]) 3780: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" 3781: [(set (match_dup 3) (match_dup 4)) 3782: (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))] 3783: " 3784: { 3785: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); 3786: }") 3787: 3788: (define_insn "" 3789: [(set (match_operand:DI 0 "register_operand" "=r") 3790: (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r")) 3791: (match_operand:DI 2 "register_operand" "r")))] 1.1.1.3 ! root 3792: "! TARGET_V9" 1.1 root 3793: "orn %2,%1,%0\;orn %R2,%R1,%R0" 3794: [(set_attr "length" "2")]) 3795: 3796: (define_insn "" 1.1.1.3 ! root 3797: [(set (match_operand:DI 0 "register_operand" "=r") ! 3798: (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r")) ! 3799: (match_operand:DI 2 "register_operand" "r")))] ! 3800: "TARGET_V9" ! 3801: "orn %2,%1,%0") ! 3802: ! 3803: (define_insn "" 1.1 root 3804: [(set (match_operand:SI 0 "register_operand" "=r") 3805: (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r")) 3806: (match_operand:SI 2 "register_operand" "r")))] 3807: "" 1.1.1.3 ! root 3808: "orn %2,%1,%0" ! 3809: [(set_attr "type" "ialu")]) 1.1 root 3810: 3811: (define_expand "xordi3" 3812: [(set (match_operand:DI 0 "register_operand" "") 3813: (xor:DI (match_operand:DI 1 "arith_double_operand" "") 3814: (match_operand:DI 2 "arith_double_operand" "")))] 3815: "" 3816: "") 3817: 3818: (define_insn "" 3819: [(set (match_operand:DI 0 "register_operand" "=r") 3820: (xor:DI (match_operand:DI 1 "arith_double_operand" "%r") 3821: (match_operand:DI 2 "arith_double_operand" "rHI")))] 1.1.1.3 ! root 3822: "! TARGET_V9" 1.1 root 3823: "* 3824: { 3825: rtx op2 = operands[2]; 3826: 3827: /* If constant is positive, upper bits zeroed, otherwise unchanged. 3828: Give the assembler a chance to pick the move instruction. */ 3829: if (GET_CODE (op2) == CONST_INT) 3830: { 3831: int sign = INTVAL (op2); 3832: if (sign < 0) 3833: return \"xor %1,-1,%0\;xor %R1,%2,%R0\"; 3834: return \"mov %1,%0\;xor %R1,%2,%R0\"; 3835: } 3836: else if (GET_CODE (op2) == CONST_DOUBLE) 3837: { 1.1.1.3 ! root 3838: rtx xoperands[4]; ! 3839: xoperands[0] = operands[0]; ! 3840: xoperands[1] = operands[1]; ! 3841: xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2)); ! 3842: xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2)); ! 3843: /* We could optimize then operands[1] == operands[0] ! 3844: and either half of the constant is 0. */ ! 3845: output_asm_insn (\"xor %R1,%2,%R0\;xor %1,%3,%0\", xoperands); ! 3846: return \"\"; 1.1 root 3847: } 3848: return \"xor %1,%2,%0\;xor %R1,%R2,%R0\"; 3849: }" 3850: [(set_attr "length" "2")]) 3851: 1.1.1.3 ! root 3852: (define_insn "" ! 3853: [(set (match_operand:DI 0 "register_operand" "=r") ! 3854: (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ") ! 3855: (match_operand:DI 2 "arith_double_operand" "rHI")))] ! 3856: "TARGET_V9" ! 3857: "xor %r1,%2,%0") ! 3858: 1.1 root 3859: (define_insn "xorsi3" 3860: [(set (match_operand:SI 0 "register_operand" "=r") 3861: (xor:SI (match_operand:SI 1 "arith_operand" "%rJ") 3862: (match_operand:SI 2 "arith_operand" "rI")))] 3863: "" 1.1.1.3 ! root 3864: "xor %r1,%2,%0" ! 3865: [(set_attr "type" "ialu")]) 1.1 root 3866: 3867: (define_split 3868: [(set (match_operand:SI 0 "register_operand" "") 3869: (xor:SI (match_operand:SI 1 "register_operand" "") 3870: (match_operand:SI 2 "" ""))) 3871: (clobber (match_operand:SI 3 "register_operand" ""))] 3872: "GET_CODE (operands[2]) == CONST_INT 3873: && !SMALL_INT (operands[2]) 3874: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" 3875: [(set (match_dup 3) (match_dup 4)) 3876: (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))] 3877: " 3878: { 3879: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); 3880: }") 3881: 3882: (define_split 3883: [(set (match_operand:SI 0 "register_operand" "") 3884: (not:SI (xor:SI (match_operand:SI 1 "register_operand" "") 3885: (match_operand:SI 2 "" "")))) 3886: (clobber (match_operand:SI 3 "register_operand" ""))] 3887: "GET_CODE (operands[2]) == CONST_INT 3888: && !SMALL_INT (operands[2]) 3889: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" 3890: [(set (match_dup 3) (match_dup 4)) 3891: (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))] 3892: " 3893: { 3894: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); 3895: }") 3896: 3897: ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b). 3898: ;; Combine now canonicalizes to the rightmost expression. 3899: (define_insn "" 3900: [(set (match_operand:DI 0 "register_operand" "=r") 3901: (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r") 3902: (match_operand:DI 2 "register_operand" "r"))))] 1.1.1.3 ! root 3903: "! TARGET_V9" 1.1 root 3904: "xnor %1,%2,%0\;xnor %R1,%R2,%R0" 3905: [(set_attr "length" "2")]) 3906: 3907: (define_insn "" 1.1.1.3 ! root 3908: [(set (match_operand:DI 0 "register_operand" "=r") ! 3909: (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") ! 3910: (match_operand:DI 2 "arith_double_operand" "rHI"))))] ! 3911: "TARGET_V9" ! 3912: "xnor %r1,%2,%0") ! 3913: ! 3914: (define_insn "" 1.1 root 3915: [(set (match_operand:SI 0 "register_operand" "=r") 3916: (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") 3917: (match_operand:SI 2 "arith_operand" "rI"))))] 3918: "" 1.1.1.3 ! root 3919: "xnor %r1,%2,%0" ! 3920: [(set_attr "type" "ialu")]) 1.1 root 3921: 3922: ;; These correspond to the above in the case where we also (or only) 3923: ;; want to set the condition code. 3924: 3925: (define_insn "" 3926: [(set (reg:CC 0) 3927: (compare:CC 3928: (match_operator:SI 2 "cc_arithop" 3929: [(match_operand:SI 0 "arith_operand" "%r") 3930: (match_operand:SI 1 "arith_operand" "rI")]) 3931: (const_int 0)))] 3932: "" 3933: "%A2cc %0,%1,%%g0" 3934: [(set_attr "type" "compare")]) 3935: 3936: (define_insn "" 1.1.1.3 ! root 3937: [(set (reg:CCX 0) ! 3938: (compare:CCX ! 3939: (match_operator:DI 2 "cc_arithop" ! 3940: [(match_operand:DI 0 "arith_double_operand" "%r") ! 3941: (match_operand:DI 1 "arith_double_operand" "rHI")]) ! 3942: (const_int 0)))] ! 3943: "TARGET_V9" ! 3944: "%A2cc %0,%1,%%g0" ! 3945: [(set_attr "type" "compare")]) ! 3946: ! 3947: (define_insn "" 1.1 root 3948: [(set (reg:CC 0) 3949: (compare:CC 3950: (match_operator:SI 3 "cc_arithop" 3951: [(match_operand:SI 1 "arith_operand" "%r") 3952: (match_operand:SI 2 "arith_operand" "rI")]) 3953: (const_int 0))) 3954: (set (match_operand:SI 0 "register_operand" "=r") 3955: (match_dup 3))] 3956: "" 3957: "%A3cc %1,%2,%0") 3958: 3959: (define_insn "" 1.1.1.3 ! root 3960: [(set (reg:CCX 0) ! 3961: (compare:CCX ! 3962: (match_operator:DI 3 "cc_arithop" ! 3963: [(match_operand:DI 1 "arith_double_operand" "%r") ! 3964: (match_operand:DI 2 "arith_double_operand" "rHI")]) ! 3965: (const_int 0))) ! 3966: (set (match_operand:DI 0 "register_operand" "=r") ! 3967: (match_dup 3))] ! 3968: "TARGET_V9" ! 3969: "%A3cc %1,%2,%0") ! 3970: ! 3971: (define_insn "" 1.1 root 3972: [(set (reg:CC 0) 3973: (compare:CC 3974: (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ") 3975: (match_operand:SI 1 "arith_operand" "rI"))) 3976: (const_int 0)))] 3977: "" 3978: "xnorcc %r0,%1,%%g0" 3979: [(set_attr "type" "compare")]) 3980: 3981: (define_insn "" 1.1.1.3 ! root 3982: [(set (reg:CCX 0) ! 3983: (compare:CCX ! 3984: (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ") ! 3985: (match_operand:DI 1 "arith_double_operand" "rHI"))) ! 3986: (const_int 0)))] ! 3987: "TARGET_V9" ! 3988: "xnorcc %r0,%1,%%g0" ! 3989: [(set_attr "type" "compare")]) ! 3990: ! 3991: (define_insn "" 1.1 root 3992: [(set (reg:CC 0) 3993: (compare:CC 3994: (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") 3995: (match_operand:SI 2 "arith_operand" "rI"))) 3996: (const_int 0))) 3997: (set (match_operand:SI 0 "register_operand" "=r") 3998: (not:SI (xor:SI (match_dup 1) (match_dup 2))))] 3999: "" 4000: "xnorcc %r1,%2,%0") 4001: 4002: (define_insn "" 1.1.1.3 ! root 4003: [(set (reg:CCX 0) ! 4004: (compare:CCX ! 4005: (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ") ! 4006: (match_operand:DI 2 "arith_double_operand" "rHI"))) ! 4007: (const_int 0))) ! 4008: (set (match_operand:DI 0 "register_operand" "=r") ! 4009: (not:DI (xor:DI (match_dup 1) (match_dup 2))))] ! 4010: "TARGET_V9" ! 4011: "xnorcc %r1,%2,%0") ! 4012: ! 4013: (define_insn "" 1.1 root 4014: [(set (reg:CC 0) 4015: (compare:CC 4016: (match_operator:SI 2 "cc_arithopn" 4017: [(not:SI (match_operand:SI 0 "arith_operand" "rI")) 4018: (match_operand:SI 1 "reg_or_0_operand" "rJ")]) 4019: (const_int 0)))] 4020: "" 4021: "%B2cc %r1,%0,%%g0" 4022: [(set_attr "type" "compare")]) 4023: 4024: (define_insn "" 1.1.1.3 ! root 4025: [(set (reg:CCX 0) ! 4026: (compare:CCX ! 4027: (match_operator:DI 2 "cc_arithopn" ! 4028: [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI")) ! 4029: (match_operand:DI 1 "reg_or_0_operand" "rJ")]) ! 4030: (const_int 0)))] ! 4031: "TARGET_V9" ! 4032: "%B2cc %r1,%0,%%g0" ! 4033: [(set_attr "type" "compare")]) ! 4034: ! 4035: (define_insn "" 1.1 root 4036: [(set (reg:CC 0) 4037: (compare:CC 4038: (match_operator:SI 3 "cc_arithopn" 4039: [(not:SI (match_operand:SI 1 "arith_operand" "rI")) 4040: (match_operand:SI 2 "reg_or_0_operand" "rJ")]) 4041: (const_int 0))) 4042: (set (match_operand:SI 0 "register_operand" "=r") 4043: (match_dup 3))] 4044: "" 4045: "%B3cc %r2,%1,%0") 4046: 1.1.1.3 ! root 4047: (define_insn "" ! 4048: [(set (reg:CCX 0) ! 4049: (compare:CCX ! 4050: (match_operator:DI 3 "cc_arithopn" ! 4051: [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI")) ! 4052: (match_operand:DI 2 "reg_or_0_operand" "rJ")]) ! 4053: (const_int 0))) ! 4054: (set (match_operand:DI 0 "register_operand" "=r") ! 4055: (match_dup 3))] ! 4056: "TARGET_V9" ! 4057: "%B3cc %r2,%1,%0") ! 4058: 1.1 root 4059: ;; We cannot use the "neg" pseudo insn because the Sun assembler 4060: ;; does not know how to make it work for constants. 4061: 1.1.1.3 ! root 4062: (define_expand "negdi2" ! 4063: [(set (match_operand:DI 0 "register_operand" "=r") ! 4064: (neg:DI (match_operand:DI 1 "register_operand" "r")))] ! 4065: "" ! 4066: " ! 4067: { ! 4068: if (! TARGET_V9) ! 4069: { ! 4070: emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, ! 4071: gen_rtx (SET, VOIDmode, operand0, ! 4072: gen_rtx (NEG, DImode, operand1)), ! 4073: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 0))))); ! 4074: DONE; ! 4075: } ! 4076: }") ! 4077: ! 4078: (define_insn "" 1.1 root 4079: [(set (match_operand:DI 0 "register_operand" "=r") 4080: (neg:DI (match_operand:DI 1 "register_operand" "r"))) 4081: (clobber (reg:SI 0))] 1.1.1.3 ! root 4082: "! TARGET_V9" 1.1 root 4083: "subcc %%g0,%R1,%R0\;subx %%g0,%1,%0" 4084: [(set_attr "type" "unary") 4085: (set_attr "length" "2")]) 4086: 1.1.1.3 ! root 4087: (define_insn "" ! 4088: [(set (match_operand:DI 0 "register_operand" "=r") ! 4089: (neg:DI (match_operand:DI 1 "register_operand" "r")))] ! 4090: "TARGET_V9" ! 4091: "sub %%g0,%1,%0" ! 4092: [(set_attr "type" "unary") ! 4093: (set_attr "length" "1")]) ! 4094: 1.1 root 4095: (define_insn "negsi2" 1.1.1.3 ! root 4096: [(set (match_operand:SI 0 "register_operand" "=r") 1.1 root 4097: (neg:SI (match_operand:SI 1 "arith_operand" "rI")))] 4098: "" 4099: "sub %%g0,%1,%0" 4100: [(set_attr "type" "unary")]) 4101: 4102: (define_insn "" 4103: [(set (reg:CC_NOOV 0) 4104: (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI")) 4105: (const_int 0)))] 4106: "" 4107: "subcc %%g0,%0,%%g0" 4108: [(set_attr "type" "compare")]) 4109: 4110: (define_insn "" 1.1.1.3 ! root 4111: [(set (reg:CCX_NOOV 0) ! 4112: (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI")) ! 4113: (const_int 0)))] ! 4114: "TARGET_V9" ! 4115: "subcc %%g0,%0,%%g0" ! 4116: [(set_attr "type" "compare")]) ! 4117: ! 4118: (define_insn "" 1.1 root 4119: [(set (reg:CC_NOOV 0) 4120: (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI")) 4121: (const_int 0))) 4122: (set (match_operand:SI 0 "register_operand" "=r") 4123: (neg:SI (match_dup 1)))] 4124: "" 4125: "subcc %%g0,%1,%0" 4126: [(set_attr "type" "unary")]) 4127: 1.1.1.3 ! root 4128: (define_insn "" ! 4129: [(set (reg:CCX_NOOV 0) ! 4130: (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI")) ! 4131: (const_int 0))) ! 4132: (set (match_operand:DI 0 "register_operand" "=r") ! 4133: (neg:DI (match_dup 1)))] ! 4134: "TARGET_V9" ! 4135: "subcc %%g0,%1,%0" ! 4136: [(set_attr "type" "unary")]) ! 4137: 1.1 root 4138: ;; We cannot use the "not" pseudo insn because the Sun assembler 4139: ;; does not know how to make it work for constants. 4140: (define_expand "one_cmpldi2" 1.1.1.3 ! root 4141: [(set (match_operand:DI 0 "register_operand" "") ! 4142: (not:DI (match_operand:DI 1 "register_operand" "")))] 1.1 root 4143: "" 4144: "") 4145: 4146: (define_insn "" 4147: [(set (match_operand:DI 0 "register_operand" "=r") 1.1.1.3 ! root 4148: (not:DI (match_operand:DI 1 "register_operand" "r")))] ! 4149: "! TARGET_V9" ! 4150: "xnor %%g0,%1,%0\;xnor %%g0,%R1,%R0" 1.1 root 4151: [(set_attr "type" "unary") 4152: (set_attr "length" "2")]) 4153: 1.1.1.3 ! root 4154: (define_insn "" ! 4155: [(set (match_operand:DI 0 "register_operand" "=r") ! 4156: (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))] ! 4157: "TARGET_V9" ! 4158: "xnor %%g0,%1,%0" ! 4159: [(set_attr "type" "unary")]) ! 4160: 1.1 root 4161: (define_insn "one_cmplsi2" 4162: [(set (match_operand:SI 0 "register_operand" "=r") 4163: (not:SI (match_operand:SI 1 "arith_operand" "rI")))] 4164: "" 4165: "xnor %%g0,%1,%0" 4166: [(set_attr "type" "unary")]) 4167: 4168: (define_insn "" 4169: [(set (reg:CC 0) 4170: (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI")) 4171: (const_int 0)))] 4172: "" 4173: "xnorcc %%g0,%0,%%g0" 4174: [(set_attr "type" "compare")]) 4175: 4176: (define_insn "" 1.1.1.3 ! root 4177: [(set (reg:CCX 0) ! 4178: (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI")) ! 4179: (const_int 0)))] ! 4180: "TARGET_V9" ! 4181: "xnorcc %%g0,%0,%%g0" ! 4182: [(set_attr "type" "compare")]) ! 4183: ! 4184: (define_insn "" 1.1 root 4185: [(set (reg:CC 0) 4186: (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI")) 4187: (const_int 0))) 4188: (set (match_operand:SI 0 "register_operand" "=r") 4189: (not:SI (match_dup 1)))] 4190: "" 4191: "xnorcc %%g0,%1,%0" 4192: [(set_attr "type" "unary")]) 1.1.1.3 ! root 4193: ! 4194: (define_insn "" ! 4195: [(set (reg:CCX 0) ! 4196: (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")) ! 4197: (const_int 0))) ! 4198: (set (match_operand:DI 0 "register_operand" "=r") ! 4199: (not:DI (match_dup 1)))] ! 4200: "TARGET_V9" ! 4201: "xnorcc %%g0,%1,%0" ! 4202: [(set_attr "type" "unary")]) 1.1 root 4203: 4204: ;; Floating point arithmetic instructions. 4205: 4206: (define_insn "addtf3" 1.1.1.3 ! root 4207: [(set (match_operand:TF 0 "register_operand" "=e") ! 4208: (plus:TF (match_operand:TF 1 "register_operand" "e") ! 4209: (match_operand:TF 2 "register_operand" "e")))] ! 4210: "TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 4211: "faddq %1,%2,%0" 4212: [(set_attr "type" "fp")]) 4213: 4214: (define_insn "adddf3" 1.1.1.3 ! root 4215: [(set (match_operand:DF 0 "register_operand" "=e") ! 4216: (plus:DF (match_operand:DF 1 "register_operand" "e") ! 4217: (match_operand:DF 2 "register_operand" "e")))] 1.1 root 4218: "TARGET_FPU" 4219: "faddd %1,%2,%0" 4220: [(set_attr "type" "fp")]) 4221: 4222: (define_insn "addsf3" 4223: [(set (match_operand:SF 0 "register_operand" "=f") 4224: (plus:SF (match_operand:SF 1 "register_operand" "f") 4225: (match_operand:SF 2 "register_operand" "f")))] 4226: "TARGET_FPU" 4227: "fadds %1,%2,%0" 4228: [(set_attr "type" "fp")]) 4229: 4230: (define_insn "subtf3" 1.1.1.3 ! root 4231: [(set (match_operand:TF 0 "register_operand" "=e") ! 4232: (minus:TF (match_operand:TF 1 "register_operand" "e") ! 4233: (match_operand:TF 2 "register_operand" "e")))] ! 4234: "TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 4235: "fsubq %1,%2,%0" 4236: [(set_attr "type" "fp")]) 4237: 4238: (define_insn "subdf3" 1.1.1.3 ! root 4239: [(set (match_operand:DF 0 "register_operand" "=e") ! 4240: (minus:DF (match_operand:DF 1 "register_operand" "e") ! 4241: (match_operand:DF 2 "register_operand" "e")))] 1.1 root 4242: "TARGET_FPU" 4243: "fsubd %1,%2,%0" 4244: [(set_attr "type" "fp")]) 4245: 4246: (define_insn "subsf3" 4247: [(set (match_operand:SF 0 "register_operand" "=f") 4248: (minus:SF (match_operand:SF 1 "register_operand" "f") 4249: (match_operand:SF 2 "register_operand" "f")))] 4250: "TARGET_FPU" 4251: "fsubs %1,%2,%0" 4252: [(set_attr "type" "fp")]) 4253: 4254: (define_insn "multf3" 1.1.1.3 ! root 4255: [(set (match_operand:TF 0 "register_operand" "=e") ! 4256: (mult:TF (match_operand:TF 1 "register_operand" "e") ! 4257: (match_operand:TF 2 "register_operand" "e")))] ! 4258: "TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 4259: "fmulq %1,%2,%0" 4260: [(set_attr "type" "fpmul")]) 4261: 4262: (define_insn "muldf3" 1.1.1.3 ! root 4263: [(set (match_operand:DF 0 "register_operand" "=e") ! 4264: (mult:DF (match_operand:DF 1 "register_operand" "e") ! 4265: (match_operand:DF 2 "register_operand" "e")))] 1.1 root 4266: "TARGET_FPU" 4267: "fmuld %1,%2,%0" 4268: [(set_attr "type" "fpmul")]) 4269: 4270: (define_insn "mulsf3" 4271: [(set (match_operand:SF 0 "register_operand" "=f") 4272: (mult:SF (match_operand:SF 1 "register_operand" "f") 4273: (match_operand:SF 2 "register_operand" "f")))] 4274: "TARGET_FPU" 4275: "fmuls %1,%2,%0" 4276: [(set_attr "type" "fpmul")]) 4277: 4278: (define_insn "" 1.1.1.3 ! root 4279: [(set (match_operand:DF 0 "register_operand" "=e") 1.1 root 4280: (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f")) 4281: (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))] 1.1.1.3 ! root 4282: "(TARGET_V8 || TARGET_V9) && TARGET_FPU" 1.1 root 4283: "fsmuld %1,%2,%0" 4284: [(set_attr "type" "fpmul")]) 4285: 4286: (define_insn "" 1.1.1.3 ! root 4287: [(set (match_operand:TF 0 "register_operand" "=e") ! 4288: (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e")) ! 4289: (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))] ! 4290: "(TARGET_V8 || TARGET_V9) && TARGET_FPU" 1.1 root 4291: "fdmulq %1,%2,%0" 4292: [(set_attr "type" "fpmul")]) 4293: 1.1.1.3 ! root 4294: ;; don't have timing for quad-prec. divide. 1.1 root 4295: (define_insn "divtf3" 1.1.1.3 ! root 4296: [(set (match_operand:TF 0 "register_operand" "=e") ! 4297: (div:TF (match_operand:TF 1 "register_operand" "e") ! 4298: (match_operand:TF 2 "register_operand" "e")))] ! 4299: "TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 4300: "fdivq %1,%2,%0" 1.1.1.3 ! root 4301: [(set_attr "type" "fpdivd")]) 1.1 root 4302: 4303: (define_insn "divdf3" 1.1.1.3 ! root 4304: [(set (match_operand:DF 0 "register_operand" "=e") ! 4305: (div:DF (match_operand:DF 1 "register_operand" "e") ! 4306: (match_operand:DF 2 "register_operand" "e")))] 1.1 root 4307: "TARGET_FPU" 4308: "fdivd %1,%2,%0" 1.1.1.3 ! root 4309: [(set_attr "type" "fpdivd")]) 1.1 root 4310: 4311: (define_insn "divsf3" 4312: [(set (match_operand:SF 0 "register_operand" "=f") 4313: (div:SF (match_operand:SF 1 "register_operand" "f") 4314: (match_operand:SF 2 "register_operand" "f")))] 4315: "TARGET_FPU" 4316: "fdivs %1,%2,%0" 1.1.1.3 ! root 4317: [(set_attr "type" "fpdivs")]) 1.1 root 4318: 4319: (define_insn "negtf2" 1.1.1.3 ! root 4320: [(set (match_operand:TF 0 "register_operand" "=e,e") ! 4321: (neg:TF (match_operand:TF 1 "register_operand" "0,e")))] 1.1 root 4322: "TARGET_FPU" 1.1.1.3 ! root 4323: "* ! 4324: { ! 4325: if (TARGET_V9) ! 4326: return \"fnegd %1,%0\"; /* Can't use fnegs, won't work with upper regs. */ ! 4327: else if (which_alternative == 0) ! 4328: return \"fnegs %0,%0\"; ! 4329: else ! 4330: return \"fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\"; ! 4331: }" 1.1 root 4332: [(set_attr "type" "fp") 1.1.1.3 ! root 4333: (set_attr_alternative "length" ! 4334: [(const_int 1) ! 4335: (if_then_else (eq_attr "arch" "arch32bit") (const_int 4) (const_int 1))])]) 1.1 root 4336: 4337: (define_insn "negdf2" 1.1.1.3 ! root 4338: [(set (match_operand:DF 0 "register_operand" "=e,e") ! 4339: (neg:DF (match_operand:DF 1 "register_operand" "0,e")))] 1.1 root 4340: "TARGET_FPU" 1.1.1.3 ! root 4341: "* ! 4342: { ! 4343: if (TARGET_V9) ! 4344: return \"fnegd %1,%0\"; ! 4345: else if (which_alternative == 0) ! 4346: return \"fnegs %0,%0\"; ! 4347: else ! 4348: return \"fnegs %1,%0\;fmovs %R1,%R0\"; ! 4349: }" 1.1 root 4350: [(set_attr "type" "fp") 1.1.1.3 ! root 4351: (set_attr_alternative "length" ! 4352: [(const_int 1) ! 4353: (if_then_else (eq_attr "arch" "arch32bit") (const_int 2) (const_int 1))])]) 1.1 root 4354: 4355: (define_insn "negsf2" 4356: [(set (match_operand:SF 0 "register_operand" "=f") 4357: (neg:SF (match_operand:SF 1 "register_operand" "f")))] 4358: "TARGET_FPU" 4359: "fnegs %1,%0" 4360: [(set_attr "type" "fp")]) 4361: 4362: (define_insn "abstf2" 1.1.1.3 ! root 4363: [(set (match_operand:TF 0 "register_operand" "=e,e") ! 4364: (abs:TF (match_operand:TF 1 "register_operand" "0,e")))] 1.1 root 4365: "TARGET_FPU" 1.1.1.3 ! root 4366: "* ! 4367: { ! 4368: if (TARGET_V9) ! 4369: return \"fabsd %1,%0\"; /* Can't use fabss, won't work with upper regs. */ ! 4370: else if (which_alternative == 0) ! 4371: return \"fabss %0,%0\"; ! 4372: else ! 4373: return \"fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\"; ! 4374: }" 1.1 root 4375: [(set_attr "type" "fp") 1.1.1.3 ! root 4376: (set_attr_alternative "length" ! 4377: [(const_int 1) ! 4378: (if_then_else (eq_attr "arch" "arch32bit") (const_int 4) (const_int 1))])]) 1.1 root 4379: 4380: (define_insn "absdf2" 1.1.1.3 ! root 4381: [(set (match_operand:DF 0 "register_operand" "=e,e") ! 4382: (abs:DF (match_operand:DF 1 "register_operand" "0,e")))] 1.1 root 4383: "TARGET_FPU" 1.1.1.3 ! root 4384: "* ! 4385: { ! 4386: if (TARGET_V9) ! 4387: return \"fabsd %1,%0\"; ! 4388: else if (which_alternative == 0) ! 4389: return \"fabss %0,%0\"; ! 4390: else ! 4391: return \"fabss %1,%0\;fmovs %R1,%R0\"; ! 4392: }" 1.1 root 4393: [(set_attr "type" "fp") 1.1.1.3 ! root 4394: (set_attr_alternative "length" ! 4395: [(const_int 1) ! 4396: (if_then_else (eq_attr "arch" "arch32bit") (const_int 2) (const_int 1))])]) 1.1 root 4397: 4398: (define_insn "abssf2" 4399: [(set (match_operand:SF 0 "register_operand" "=f") 4400: (abs:SF (match_operand:SF 1 "register_operand" "f")))] 4401: "TARGET_FPU" 4402: "fabss %1,%0" 4403: [(set_attr "type" "fp")]) 4404: 4405: (define_insn "sqrttf2" 1.1.1.3 ! root 4406: [(set (match_operand:TF 0 "register_operand" "=e") ! 4407: (sqrt:TF (match_operand:TF 1 "register_operand" "e")))] ! 4408: "TARGET_FPU && TARGET_HARD_QUAD" 1.1 root 4409: "fsqrtq %1,%0" 4410: [(set_attr "type" "fpsqrt")]) 4411: 4412: (define_insn "sqrtdf2" 1.1.1.3 ! root 4413: [(set (match_operand:DF 0 "register_operand" "=e") ! 4414: (sqrt:DF (match_operand:DF 1 "register_operand" "e")))] 1.1 root 4415: "TARGET_FPU" 4416: "fsqrtd %1,%0" 4417: [(set_attr "type" "fpsqrt")]) 4418: 4419: (define_insn "sqrtsf2" 4420: [(set (match_operand:SF 0 "register_operand" "=f") 4421: (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] 4422: "TARGET_FPU" 4423: "fsqrts %1,%0" 4424: [(set_attr "type" "fpsqrt")]) 4425: 4426: ;;- arithmetic shift instructions 4427: 4428: (define_insn "ashlsi3" 4429: [(set (match_operand:SI 0 "register_operand" "=r") 4430: (ashift:SI (match_operand:SI 1 "register_operand" "r") 4431: (match_operand:SI 2 "arith_operand" "rI")))] 4432: "" 1.1.1.2 root 4433: "* 1.1 root 4434: { 1.1.1.2 root 4435: if (GET_CODE (operands[2]) == CONST_INT 4436: && (unsigned) INTVAL (operands[2]) > 31) 4437: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); 4438: 4439: return \"sll %1,%2,%0\"; 1.1.1.3 ! root 4440: }" ! 4441: [(set_attr "type" "shift")]) ! 4442: ! 4443: (define_insn "ashldi3" ! 4444: [(set (match_operand:DI 0 "register_operand" "=r") ! 4445: (ashift:DI (match_operand:DI 1 "register_operand" "r") ! 4446: (match_operand:SI 2 "arith_operand" "rI")))] ! 4447: "TARGET_V9" ! 4448: "* ! 4449: { ! 4450: if (GET_CODE (operands[2]) == CONST_INT ! 4451: && (unsigned) INTVAL (operands[2]) > 63) ! 4452: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); ! 4453: ! 4454: return \"sllx %1,%2,%0\"; 1.1 root 4455: }") 4456: 4457: (define_insn "" 1.1.1.2 root 4458: [(set (reg:CC_NOOV 0) 4459: (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r") 4460: (const_int 1)) 4461: (const_int 0)))] 4462: "" 4463: "addcc %0,%0,%%g0" 4464: [(set_attr "type" "compare")]) 1.1 root 4465: 4466: (define_insn "" 1.1.1.2 root 4467: [(set (reg:CC_NOOV 0) 4468: (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r") 4469: (const_int 1)) 4470: (const_int 0))) 4471: (set (match_operand:SI 0 "register_operand" "=r") 4472: (ashift:SI (match_dup 1) (const_int 1)))] 4473: "" 4474: "addcc %1,%1,%0") 1.1 root 4475: 4476: (define_insn "ashrsi3" 4477: [(set (match_operand:SI 0 "register_operand" "=r") 4478: (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") 4479: (match_operand:SI 2 "arith_operand" "rI")))] 4480: "" 1.1.1.2 root 4481: "* 4482: { 4483: if (GET_CODE (operands[2]) == CONST_INT 4484: && (unsigned) INTVAL (operands[2]) > 31) 4485: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); 4486: 4487: return \"sra %1,%2,%0\"; 1.1.1.3 ! root 4488: }" ! 4489: [(set_attr "type" "shift")]) ! 4490: ! 4491: (define_insn "ashrdi3" ! 4492: [(set (match_operand:DI 0 "register_operand" "=r") ! 4493: (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") ! 4494: (match_operand:SI 2 "arith_operand" "rI")))] ! 4495: "TARGET_V9" ! 4496: "* ! 4497: { ! 4498: if (GET_CODE (operands[2]) == CONST_INT ! 4499: && (unsigned) INTVAL (operands[2]) > 63) ! 4500: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); ! 4501: ! 4502: return \"srax %1,%2,%0\"; 1.1.1.2 root 4503: }") 1.1 root 4504: 4505: (define_insn "lshrsi3" 4506: [(set (match_operand:SI 0 "register_operand" "=r") 4507: (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") 4508: (match_operand:SI 2 "arith_operand" "rI")))] 4509: "" 4510: "* 4511: { 1.1.1.2 root 4512: if (GET_CODE (operands[2]) == CONST_INT 4513: && (unsigned) INTVAL (operands[2]) > 31) 4514: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); 1.1 root 4515: 1.1.1.2 root 4516: return \"srl %1,%2,%0\"; 1.1.1.3 ! root 4517: }" ! 4518: [(set_attr "type" "shift")]) ! 4519: ! 4520: (define_insn "lshrdi3" ! 4521: [(set (match_operand:DI 0 "register_operand" "=r") ! 4522: (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") ! 4523: (match_operand:SI 2 "arith_operand" "rI")))] ! 4524: "TARGET_V9" ! 4525: "* ! 4526: { ! 4527: if (GET_CODE (operands[2]) == CONST_INT ! 4528: && (unsigned) INTVAL (operands[2]) > 63) ! 4529: operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); ! 4530: ! 4531: return \"srlx %1,%2,%0\"; 1.1.1.2 root 4532: }") 1.1 root 4533: 4534: ;; Unconditional and other jump instructions 4535: ;; On the Sparc, by setting the annul bit on an unconditional branch, the 4536: ;; following insn is never executed. This saves us a nop. Dbx does not 4537: ;; handle such branches though, so we only use them when optimizing. 4538: (define_insn "jump" 4539: [(set (pc) (label_ref (match_operand 0 "" "")))] 4540: "" 4541: "b%* %l0%(" 4542: [(set_attr "type" "uncond_branch")]) 4543: 4544: (define_expand "tablejump" 1.1.1.3 ! root 4545: [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) 1.1 root 4546: (use (label_ref (match_operand 1 "" "")))])] 4547: "" 4548: " 4549: { 1.1.1.3 ! root 4550: if (GET_MODE (operands[0]) != Pmode) ! 4551: abort (); ! 4552: 1.1 root 4553: /* We need to use the PC value in %o7 that was set up when the address 4554: of the label was loaded into a register, so we need different RTL. */ 4555: if (flag_pic) 4556: { 1.1.1.3 ! root 4557: if (!TARGET_PTR64) ! 4558: emit_jump_insn (gen_pic_tablejump_32 (operands[0], operands[1])); ! 4559: else ! 4560: emit_jump_insn (gen_pic_tablejump_64 (operands[0], operands[1])); 1.1 root 4561: DONE; 4562: } 4563: }") 4564: 1.1.1.3 ! root 4565: (define_insn "pic_tablejump_32" 1.1 root 4566: [(set (pc) (match_operand:SI 0 "register_operand" "r")) 4567: (use (label_ref (match_operand 1 "" ""))) 4568: (use (reg:SI 15))] 1.1.1.3 ! root 4569: "! TARGET_PTR64" ! 4570: "jmp %%o7+%0%#" ! 4571: [(set_attr "type" "uncond_branch")]) ! 4572: ! 4573: (define_insn "pic_tablejump_64" ! 4574: [(set (pc) (match_operand:DI 0 "register_operand" "r")) ! 4575: (use (label_ref (match_operand 1 "" ""))) ! 4576: (use (reg:DI 15))] ! 4577: "TARGET_PTR64" 1.1 root 4578: "jmp %%o7+%0%#" 4579: [(set_attr "type" "uncond_branch")]) 4580: 4581: (define_insn "" 4582: [(set (pc) (match_operand:SI 0 "address_operand" "p")) 4583: (use (label_ref (match_operand 1 "" "")))] 1.1.1.3 ! root 4584: "! TARGET_PTR64" ! 4585: "jmp %a0%#" ! 4586: [(set_attr "type" "uncond_branch")]) ! 4587: ! 4588: (define_insn "" ! 4589: [(set (pc) (match_operand:DI 0 "address_operand" "p")) ! 4590: (use (label_ref (match_operand 1 "" "")))] ! 4591: "TARGET_PTR64" 1.1 root 4592: "jmp %a0%#" 4593: [(set_attr "type" "uncond_branch")]) 4594: 4595: (define_insn "" 4596: [(set (pc) (label_ref (match_operand 0 "" ""))) 4597: (set (reg:SI 15) (label_ref (match_dup 0)))] 1.1.1.3 ! root 4598: "! TARGET_PTR64" ! 4599: "call %l0%#" ! 4600: [(set_attr "type" "uncond_branch")]) ! 4601: ! 4602: (define_insn "" ! 4603: [(set (pc) (label_ref (match_operand 0 "" ""))) ! 4604: (set (reg:DI 15) (label_ref (match_dup 0)))] ! 4605: "TARGET_PTR64" 1.1 root 4606: "call %l0%#" 4607: [(set_attr "type" "uncond_branch")]) 4608: 4609: ;; This pattern recognizes the "instruction" that appears in 4610: ;; a function call that wants a structure value, 4611: ;; to inform the called function if compiled with Sun CC. 4612: ;(define_insn "" 4613: ; [(match_operand:SI 0 "immediate_operand" "")] 4614: ; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0" 4615: ; "unimp %0" 4616: ; [(set_attr "type" "marker")]) 4617: 4618: ;;- jump to subroutine 4619: (define_expand "call" 4620: ;; Note that this expression is not used for generating RTL. 4621: ;; All the RTL is generated explicitly below. 1.1.1.3 ! root 4622: [(call (match_operand 0 "call_operand" "") 1.1 root 4623: (match_operand 3 "" "i"))] 4624: ;; operands[2] is next_arg_register 4625: ;; operands[3] is struct_value_size_rtx. 4626: "" 4627: " 4628: { 4629: rtx fn_rtx, nregs_rtx; 4630: 1.1.1.3 ! root 4631: if (GET_MODE (operands[0]) != FUNCTION_MODE) ! 4632: abort (); ! 4633: ! 4634: if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF) 1.1 root 4635: { 4636: /* This is really a PIC sequence. We want to represent 4637: it as a funny jump so it's delay slots can be filled. 4638: 4639: ??? But if this really *is* a CALL, will not it clobber the 4640: call-clobbered registers? We lose this if it is a JUMP_INSN. 4641: Why cannot we have delay slots filled if it were a CALL? */ 4642: 1.1.1.3 ! root 4643: if (! TARGET_V9 && INTVAL (operands[3]) != 0) 1.1 root 4644: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3, 4645: gen_rtx (SET, VOIDmode, pc_rtx, 4646: XEXP (operands[0], 0)), 4647: operands[3], 4648: gen_rtx (CLOBBER, VOIDmode, 1.1.1.3 ! root 4649: gen_rtx (REG, Pmode, 15))))); 1.1 root 4650: else 4651: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, 4652: gen_rtx (SET, VOIDmode, pc_rtx, 4653: XEXP (operands[0], 0)), 4654: gen_rtx (CLOBBER, VOIDmode, 1.1.1.3 ! root 4655: gen_rtx (REG, Pmode, 15))))); 1.1 root 4656: goto finish_call; 4657: } 4658: 4659: fn_rtx = operands[0]; 4660: 4661: /* Count the number of parameter registers being used by this call. 4662: if that argument is NULL, it means we are using them all, which 4663: means 6 on the sparc. */ 4664: #if 0 4665: if (operands[2]) 4666: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8); 4667: else 4668: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6); 4669: #else 4670: nregs_rtx = const0_rtx; 4671: #endif 4672: 1.1.1.3 ! root 4673: if (! TARGET_V9 && INTVAL (operands[3]) != 0) 1.1 root 4674: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3, 4675: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx), 4676: operands[3], 4677: gen_rtx (CLOBBER, VOIDmode, 1.1.1.3 ! root 4678: gen_rtx (REG, Pmode, 15))))); 1.1 root 4679: else 4680: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, 4681: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx), 4682: gen_rtx (CLOBBER, VOIDmode, 1.1.1.3 ! root 4683: gen_rtx (REG, Pmode, 15))))); 1.1 root 4684: 4685: finish_call: 4686: #if 0 4687: /* If this call wants a structure value, 4688: emit an unimp insn to let the called function know about this. */ 1.1.1.3 ! root 4689: if (! TARGET_V9 && INTVAL (operands[3]) > 0) 1.1 root 4690: { 4691: rtx insn = emit_insn (operands[3]); 4692: SCHED_GROUP_P (insn) = 1; 4693: } 4694: #endif 4695: 4696: DONE; 4697: }") 4698: 1.1.1.2 root 4699: ;; We can't use the same pattern for these two insns, because then registers 4700: ;; in the address may not be properly reloaded. 4701: 4702: (define_insn "" 4703: [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) 4704: (match_operand 1 "" "")) 4705: (clobber (reg:SI 15))] 4706: ;;- Do not use operand 1 for most machines. 1.1.1.3 ! root 4707: "! TARGET_PTR64" 1.1.1.2 root 4708: "* 4709: { 4710: return \"call %a0,%1%#\"; 4711: }" 4712: [(set_attr "type" "call")]) 4713: 1.1 root 4714: (define_insn "" 1.1.1.3 ! root 4715: [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s")) 1.1 root 4716: (match_operand 1 "" "")) 4717: (clobber (reg:SI 15))] 4718: ;;- Do not use operand 1 for most machines. 1.1.1.3 ! root 4719: "! TARGET_PTR64" ! 4720: "* ! 4721: { ! 4722: return \"call %a0,%1%#\"; ! 4723: }" ! 4724: [(set_attr "type" "call")]) ! 4725: ! 4726: (define_insn "" ! 4727: [(call (mem:SI (match_operand:DI 0 "address_operand" "p")) ! 4728: (match_operand 1 "" "")) ! 4729: (clobber (reg:DI 15))] ! 4730: ;;- Do not use operand 1 for most machines. ! 4731: "TARGET_PTR64" ! 4732: "* ! 4733: { ! 4734: return \"call %a0,%1%#\"; ! 4735: }" ! 4736: [(set_attr "type" "call")]) ! 4737: ! 4738: (define_insn "" ! 4739: [(call (mem:SI (match_operand:DI 0 "symbolic_operand" "s")) ! 4740: (match_operand 1 "" "")) ! 4741: (clobber (reg:DI 15))] ! 4742: ;;- Do not use operand 1 for most machines. ! 4743: "TARGET_PTR64" 1.1 root 4744: "* 4745: { 4746: return \"call %a0,%1%#\"; 4747: }" 4748: [(set_attr "type" "call")]) 4749: 4750: ;; This is a call that wants a structure value. 1.1.1.3 ! root 4751: ;; There is no such critter for v9 (??? we may need one anyway). 1.1 root 4752: (define_insn "" 1.1.1.2 root 4753: [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) 4754: (match_operand 1 "" "")) 4755: (match_operand 2 "immediate_operand" "") 4756: (clobber (reg:SI 15))] 4757: ;;- Do not use operand 1 for most machines. 1.1.1.3 ! root 4758: "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0" 1.1.1.2 root 4759: "* 4760: { 4761: return \"call %a0,%1\;nop\;unimp %2\"; 4762: }" 4763: [(set_attr "type" "call_no_delay_slot")]) 4764: 4765: ;; This is a call that wants a structure value. 1.1.1.3 ! root 4766: ;; There is no such critter for v9 (??? we may need one anyway). 1.1.1.2 root 4767: (define_insn "" 1.1.1.3 ! root 4768: [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s")) 1.1 root 4769: (match_operand 1 "" "")) 4770: (match_operand 2 "immediate_operand" "") 4771: (clobber (reg:SI 15))] 4772: ;;- Do not use operand 1 for most machines. 1.1.1.3 ! root 4773: "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0" 1.1 root 4774: "* 4775: { 4776: return \"call %a0,%1\;nop\;unimp %2\"; 4777: }" 4778: [(set_attr "type" "call_no_delay_slot")]) 4779: 1.1.1.3 ! root 4780: ;; This is a call that may want a structure value. This is used for ! 4781: ;; untyped_calls. ! 4782: (define_insn "" ! 4783: [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) ! 4784: (match_operand 1 "" "")) ! 4785: (match_operand 2 "immediate_operand" "") ! 4786: (clobber (reg:SI 15))] ! 4787: ;;- Do not use operand 1 for most machines. ! 4788: "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0" ! 4789: "* ! 4790: { ! 4791: return \"call %a0,%1\;nop\;nop\"; ! 4792: }" ! 4793: [(set_attr "type" "call_no_delay_slot")]) ! 4794: ! 4795: ;; This is a call that wants a structure value. ! 4796: (define_insn "" ! 4797: [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s")) ! 4798: (match_operand 1 "" "")) ! 4799: (match_operand 2 "immediate_operand" "") ! 4800: (clobber (reg:SI 15))] ! 4801: ;;- Do not use operand 1 for most machines. ! 4802: "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0" ! 4803: "* ! 4804: { ! 4805: return \"call %a0,%1\;nop\;nop\"; ! 4806: }" ! 4807: [(set_attr "type" "call_no_delay_slot")]) ! 4808: 1.1 root 4809: (define_expand "call_value" 1.1.1.3 ! root 4810: ;; Note that this expression is not used for generating RTL. ! 4811: ;; All the RTL is generated explicitly below. 1.1 root 4812: [(set (match_operand 0 "register_operand" "=rf") 4813: (call (match_operand:SI 1 "" "") 4814: (match_operand 4 "" "")))] 1.1.1.3 ! root 4815: ;; operand 2 is stack_size_rtx 1.1 root 4816: ;; operand 3 is next_arg_register 4817: "" 4818: " 4819: { 4820: rtx fn_rtx, nregs_rtx; 4821: rtvec vec; 4822: 1.1.1.3 ! root 4823: if (GET_MODE (operands[1]) != FUNCTION_MODE) ! 4824: abort (); ! 4825: 1.1 root 4826: fn_rtx = operands[1]; 4827: 4828: #if 0 4829: if (operands[3]) 4830: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8); 4831: else 4832: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6); 4833: #else 4834: nregs_rtx = const0_rtx; 4835: #endif 4836: 4837: vec = gen_rtvec (2, 4838: gen_rtx (SET, VOIDmode, operands[0], 4839: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)), 1.1.1.3 ! root 4840: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 15))); 1.1 root 4841: 4842: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec)); 4843: 4844: DONE; 4845: }") 4846: 4847: (define_insn "" 4848: [(set (match_operand 0 "" "=rf") 1.1.1.2 root 4849: (call (mem:SI (match_operand:SI 1 "address_operand" "p")) 4850: (match_operand 2 "" ""))) 4851: (clobber (reg:SI 15))] 4852: ;;- Do not use operand 2 for most machines. 1.1.1.3 ! root 4853: "! TARGET_PTR64" 1.1.1.2 root 4854: "* 4855: { 4856: return \"call %a1,%2%#\"; 4857: }" 4858: [(set_attr "type" "call")]) 4859: 4860: (define_insn "" 4861: [(set (match_operand 0 "" "=rf") 1.1.1.3 ! root 4862: (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s")) 1.1 root 4863: (match_operand 2 "" ""))) 4864: (clobber (reg:SI 15))] 4865: ;;- Do not use operand 2 for most machines. 1.1.1.3 ! root 4866: "! TARGET_PTR64" ! 4867: "* ! 4868: { ! 4869: return \"call %a1,%2%#\"; ! 4870: }" ! 4871: [(set_attr "type" "call")]) ! 4872: ! 4873: (define_insn "" ! 4874: [(set (match_operand 0 "" "=rf") ! 4875: (call (mem:SI (match_operand:DI 1 "address_operand" "p")) ! 4876: (match_operand 2 "" ""))) ! 4877: (clobber (reg:DI 15))] ! 4878: ;;- Do not use operand 2 for most machines. ! 4879: "TARGET_PTR64" ! 4880: "* ! 4881: { ! 4882: return \"call %a1,%2%#\"; ! 4883: }" ! 4884: [(set_attr "type" "call")]) ! 4885: ! 4886: (define_insn "" ! 4887: [(set (match_operand 0 "" "=rf") ! 4888: (call (mem:SI (match_operand:DI 1 "symbolic_operand" "s")) ! 4889: (match_operand 2 "" ""))) ! 4890: (clobber (reg:DI 15))] ! 4891: ;;- Do not use operand 2 for most machines. ! 4892: "TARGET_PTR64" 1.1 root 4893: "* 4894: { 4895: return \"call %a1,%2%#\"; 4896: }" 4897: [(set_attr "type" "call")]) 4898: 4899: (define_expand "untyped_call" 1.1.1.3 ! root 4900: [(parallel [(call (match_operand 0 "" "") 1.1 root 4901: (const_int 0)) 1.1.1.3 ! root 4902: (match_operand 1 "" "") ! 4903: (match_operand 2 "" "")])] 1.1 root 4904: "" 4905: " 4906: { 1.1.1.3 ! root 4907: int i; 1.1 root 4908: 1.1.1.3 ! root 4909: /* Pass constm1 to indicate that it may expect a structure value, but ! 4910: we don't know what size it is. */ ! 4911: emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx)); 1.1 root 4912: 1.1.1.3 ! root 4913: for (i = 0; i < XVECLEN (operands[2], 0); i++) ! 4914: { ! 4915: rtx set = XVECEXP (operands[2], 0, i); ! 4916: emit_move_insn (SET_DEST (set), SET_SRC (set)); ! 4917: } 1.1.1.2 root 4918: 1.1.1.3 ! root 4919: /* The optimizer does not know that the call sets the function value ! 4920: registers we stored in the result block. We avoid problems by ! 4921: claiming that all hard registers are used and clobbered at this ! 4922: point. */ ! 4923: emit_insn (gen_blockage ()); 1.1.1.2 root 4924: 1.1.1.3 ! root 4925: DONE; ! 4926: }") ! 4927: ! 4928: ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and ! 4929: ;; all of memory. This blocks insns from being moved across this point. ! 4930: ! 4931: (define_insn "blockage" ! 4932: [(unspec_volatile [(const_int 0)] 0)] 1.1 root 4933: "" 1.1.1.3 ! root 4934: "") 1.1 root 4935: 4936: ;; Prepare to return any type including a structure value. 4937: 4938: (define_expand "untyped_return" 4939: [(match_operand:BLK 0 "memory_operand" "") 4940: (match_operand 1 "" "")] 4941: "" 4942: " 4943: { 4944: rtx valreg1 = gen_rtx (REG, DImode, 24); 1.1.1.3 ! root 4945: rtx valreg2 = gen_rtx (REG, TARGET_V9 ? TFmode : DFmode, 32); 1.1 root 4946: rtx result = operands[0]; 4947: 1.1.1.3 ! root 4948: if (! TARGET_V9) ! 4949: { ! 4950: rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31)); ! 4951: rtx value = gen_reg_rtx (SImode); ! 4952: ! 4953: /* Fetch the instruction where we will return to and see if it's an unimp ! 4954: instruction (the most significant 10 bits will be zero). If so, ! 4955: update the return address to skip the unimp instruction. */ ! 4956: emit_move_insn (value, ! 4957: gen_rtx (MEM, SImode, plus_constant (rtnreg, 8))); ! 4958: emit_insn (gen_lshrsi3 (value, value, GEN_INT (22))); ! 4959: emit_insn (gen_update_return (rtnreg, value)); ! 4960: } 1.1 root 4961: 4962: /* Reload the function value registers. */ 4963: emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0))); 4964: emit_move_insn (valreg2, 1.1.1.3 ! root 4965: change_address (result, TARGET_V9 ? TFmode : DFmode, 1.1 root 4966: plus_constant (XEXP (result, 0), 8))); 4967: 4968: /* Put USE insns before the return. */ 4969: emit_insn (gen_rtx (USE, VOIDmode, valreg1)); 4970: emit_insn (gen_rtx (USE, VOIDmode, valreg2)); 4971: 4972: /* Construct the return. */ 4973: expand_null_return (); 4974: 4975: DONE; 4976: }") 4977: 4978: ;; This is a bit of a hack. We're incrementing a fixed register (%i7), 4979: ;; and parts of the compiler don't want to believe that the add is needed. 4980: 4981: (define_insn "update_return" 4982: [(unspec:SI [(match_operand:SI 0 "register_operand" "r") 4983: (match_operand:SI 1 "register_operand" "r")] 0)] 1.1.1.3 ! root 4984: "! TARGET_V9" 1.1 root 4985: "cmp %1,0\;be,a .+8\;add %0,4,%0" 4986: [(set_attr "type" "multi")]) 4987: 4988: (define_insn "return" 4989: [(return)] 4990: "! TARGET_EPILOGUE" 4991: "* return output_return (operands);" 4992: [(set_attr "type" "multi")]) 4993: 4994: (define_insn "nop" 4995: [(const_int 0)] 4996: "" 4997: "nop") 4998: 1.1.1.3 ! root 4999: (define_expand "indirect_jump" ! 5000: [(set (pc) (match_operand 0 "address_operand" "p"))] 1.1 root 5001: "" 1.1.1.3 ! root 5002: "") ! 5003: ! 5004: (define_insn "" ! 5005: [(set (pc) (match_operand:SI 0 "address_operand" "p"))] ! 5006: "! TARGET_PTR64" 1.1 root 5007: "jmp %a0%#" 5008: [(set_attr "type" "uncond_branch")]) 5009: 1.1.1.3 ! root 5010: (define_insn "" ! 5011: [(set (pc) (match_operand:DI 0 "address_operand" "p"))] ! 5012: "TARGET_PTR64" ! 5013: "jmp %a0%#" ! 5014: [(set_attr "type" "uncond_branch")]) ! 5015: ! 5016: ;; ??? This doesn't handle v9 yet. It also doesn't work with -mflat. 1.1 root 5017: (define_expand "nonlocal_goto" 5018: [(match_operand:SI 0 "general_operand" "") 5019: (match_operand:SI 1 "general_operand" "") 5020: (match_operand:SI 2 "general_operand" "") 5021: (match_operand:SI 3 "" "")] 5022: "" 5023: " 5024: { 1.1.1.3 ! root 5025: /* Trap instruction to flush all the register windows. */ 1.1 root 5026: emit_insn (gen_flush_register_windows ()); 5027: /* Load the fp value for the containing fn into %fp. 5028: This is needed because operands[2] refers to %fp. 5029: Virtual register instantiation fails if the virtual %fp isn't set from a 5030: register. Thus we must copy operands[0] into a register if it isn't 5031: already one. */ 5032: if (GET_CODE (operands[0]) != REG) 5033: operands[0] = force_reg (SImode, operands[0]); 5034: emit_move_insn (virtual_stack_vars_rtx, operands[0]); 5035: /* Find the containing function's current nonlocal goto handler, 5036: which will do any cleanups and then jump to the label. */ 5037: emit_move_insn (gen_rtx (REG, SImode, 8), operands[1]); 5038: /* Restore %fp from stack pointer value for containing function. 5039: The restore insn that follows will move this to %sp, 5040: and reload the appropriate value into %fp. */ 5041: emit_move_insn (frame_pointer_rtx, operands[2]); 5042: /* Put in the static chain register the nonlocal label address. */ 5043: emit_move_insn (static_chain_rtx, operands[3]); 5044: /* USE of frame_pointer_rtx added for consistency; not clear if 5045: really needed. */ 5046: emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx)); 5047: emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); 5048: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx)); 5049: emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 8))); 5050: /* Return, restoring reg window and jumping to goto handler. */ 5051: emit_insn (gen_goto_handler_and_restore ()); 5052: DONE; 5053: }") 5054: 5055: ;; Special trap insn to flush register windows. 5056: (define_insn "flush_register_windows" 1.1.1.3 ! root 5057: [(unspec_volatile [(const_int 0)] 1)] 1.1 root 5058: "" 1.1.1.3 ! root 5059: "* return TARGET_V9 ? \"flushw\" : \"ta 3\";" 1.1 root 5060: [(set_attr "type" "misc")]) 5061: 5062: (define_insn "goto_handler_and_restore" 1.1.1.3 ! root 5063: [(unspec_volatile [(const_int 0)] 2)] 1.1 root 5064: "" 5065: "jmp %%o0+0\;restore" 5066: [(set_attr "type" "misc") 5067: (set_attr "length" "2")]) 1.1.1.2 root 5068: 5069: ;; Special pattern for the FLUSH instruction. 5070: 5071: (define_insn "flush" 1.1.1.3 ! root 5072: [(unspec_volatile [(match_operand 0 "" "")] 3)] 1.1.1.2 root 5073: "" 1.1.1.3 ! root 5074: "* return TARGET_V9 ? \"flush %a0\" : \"iflush %a0\";" 1.1.1.2 root 5075: [(set_attr "type" "misc")]) 1.1 root 5076: 5077: ;; find first set. 5078: 5079: ;; The scan instruction searches from the most significant bit while ffs 5080: ;; searches from the least significant bit. The bit index and treatment of 5081: ;; zero also differ. It takes at least 7 instructions to get the proper 5082: ;; result. Here is an obvious 8 instruction seequence. 5083: 5084: (define_insn "ffssi2" 5085: [(set (match_operand:SI 0 "register_operand" "=&r") 5086: (ffs:SI (match_operand:SI 1 "register_operand" "r"))) 5087: (clobber (match_scratch:SI 2 "=&r"))] 5088: "TARGET_SPARCLITE" 5089: "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" 5090: [(set_attr "type" "multi") 5091: (set_attr "length" "8")]) 1.1.1.3 ! root 5092: ! 5093: ;; ??? This should be a define expand, so that the extra instruction have ! 5094: ;; a chance of being optimized away. ! 5095: ! 5096: (define_insn "ffsdi2" ! 5097: [(set (match_operand:DI 0 "register_operand" "=&r") ! 5098: (ffs:DI (match_operand:DI 1 "register_operand" "r"))) ! 5099: (clobber (match_scratch:DI 2 "=&r"))] ! 5100: "TARGET_V9" ! 5101: "neg %1,%2\;not %2,%2\;xor %1,%2,%2\;popc %2,%0\;movrz %1,%%g0,%0" ! 5102: [(set_attr "type" "multi") ! 5103: (set_attr "length" "5")]) 1.1 root 5104: 5105: ;; Split up troublesome insns for better scheduling. */ 5106: 5107: ;; The following patterns are straightforward. They can be applied 5108: ;; either before or after register allocation. 5109: 5110: (define_split 5111: [(set (match_operator 0 "memop" [(match_operand:SI 1 "symbolic_operand" "")]) 5112: (match_operand 2 "reg_or_0_operand" "")) 5113: (clobber (match_operand:SI 3 "register_operand" ""))] 5114: "! flag_pic" 5115: [(set (match_dup 3) (high:SI (match_dup 1))) 5116: (set (match_op_dup 0 [(lo_sum:SI (match_dup 3) (match_dup 1))]) 5117: (match_dup 2))] 5118: "") 5119: 5120: (define_split 5121: [(set (match_operator 0 "memop" 5122: [(match_operand:SI 1 "immediate_operand" "")]) 5123: (match_operand 2 "general_operand" "")) 5124: (clobber (match_operand:SI 3 "register_operand" ""))] 5125: "flag_pic" 5126: [(set (match_op_dup 0 [(match_dup 1)]) 5127: (match_dup 2))] 5128: " 5129: { 5130: operands[1] = legitimize_pic_address (operands[1], GET_MODE (operands[0]), 1.1.1.2 root 5131: operands[3]); 1.1 root 5132: }") 5133: 5134: (define_split 5135: [(set (match_operand 0 "register_operand" "") 5136: (match_operator 1 "memop" 5137: [(match_operand:SI 2 "immediate_operand" "")]))] 5138: "flag_pic" 5139: [(set (match_dup 0) 5140: (match_op_dup 1 [(match_dup 2)]))] 5141: " 5142: { 5143: operands[2] = legitimize_pic_address (operands[2], GET_MODE (operands[1]), 1.1.1.2 root 5144: operands[0]); 1.1 root 5145: }") 5146: 5147: ;; Sign- and Zero-extend operations can have symbolic memory operands. 5148: 5149: (define_split 5150: [(set (match_operand 0 "register_operand" "") 5151: (match_operator 1 "extend_op" 5152: [(match_operator 2 "memop" 5153: [(match_operand:SI 3 "immediate_operand" "")])]))] 5154: "flag_pic" 5155: [(set (match_dup 0) 5156: (match_op_dup 1 [(match_op_dup 2 [(match_dup 3)])]))] 5157: " 5158: { 5159: operands[3] = legitimize_pic_address (operands[3], GET_MODE (operands[2]), 1.1.1.2 root 5160: operands[0]); 1.1 root 5161: }") 5162: 5163: (define_split 5164: [(set (match_operand:SI 0 "register_operand" "") 5165: (match_operand:SI 1 "immediate_operand" ""))] 5166: "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF 5167: || GET_CODE (operands[1]) == CONST 5168: || GET_CODE (operands[1]) == LABEL_REF)" 5169: [(set (match_dup 0) (high:SI (match_dup 1))) 5170: (set (match_dup 0) 5171: (lo_sum:SI (match_dup 0) (match_dup 1)))] 5172: "") 5173: 5174: ;; LABEL_REFs are not modified by `legitimize_pic_address` 5175: ;; so do not recurse infinitely in the PIC case. 5176: (define_split 5177: [(set (match_operand:SI 0 "register_operand" "") 5178: (match_operand:SI 1 "immediate_operand" ""))] 5179: "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF 5180: || GET_CODE (operands[1]) == CONST)" 5181: [(set (match_dup 0) (match_dup 1))] 5182: " 5183: { 1.1.1.2 root 5184: operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]); 1.1 root 5185: }") 5186: 5187: ;; These split sne/seq insns. The forms of the resulting insns are 5188: ;; somewhat bogus, but they avoid extra patterns and show data dependency. 5189: ;; Nothing will look at these in detail after splitting has occurred. 5190: 1.1.1.3 ! root 5191: ;; ??? v9 DImode versions are missing because addc and subc use %icc. ! 5192: 1.1 root 5193: (define_split 5194: [(set (match_operand:SI 0 "register_operand" "") 1.1.1.3 ! root 5195: (ne:SI (match_operand:SI 1 "register_operand" "") ! 5196: (const_int 0))) 1.1 root 5197: (clobber (reg:CC 0))] 5198: "" 5199: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 5200: (const_int 0))) 5201: (set (match_dup 0) (ltu:SI (reg:CC 0) (const_int 0)))] 5202: "") 5203: 5204: (define_split 5205: [(set (match_operand:SI 0 "register_operand" "") 5206: (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "") 5207: (const_int 0)))) 5208: (clobber (reg:CC 0))] 5209: "" 5210: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 5211: (const_int 0))) 5212: (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))] 5213: "") 5214: 5215: (define_split 5216: [(set (match_operand:SI 0 "register_operand" "") 1.1.1.3 ! root 5217: (eq:SI (match_operand:SI 1 "register_operand" "") ! 5218: (const_int 0))) 1.1 root 5219: (clobber (reg:CC 0))] 5220: "" 5221: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 5222: (const_int 0))) 5223: (set (match_dup 0) (geu:SI (reg:CC 0) (const_int 0)))] 5224: "") 5225: 5226: (define_split 5227: [(set (match_operand:SI 0 "register_operand" "") 5228: (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "") 5229: (const_int 0)))) 5230: (clobber (reg:CC 0))] 5231: "" 5232: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 5233: (const_int 0))) 5234: (set (match_dup 0) (neg:SI (geu:SI (reg:CC 0) (const_int 0))))] 5235: "") 5236: 5237: (define_split 5238: [(set (match_operand:SI 0 "register_operand" "") 5239: (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "") 5240: (const_int 0)) 5241: (match_operand:SI 2 "register_operand" ""))) 5242: (clobber (reg:CC 0))] 5243: "" 5244: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 5245: (const_int 0))) 5246: (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) 5247: (match_dup 2)))] 5248: "") 5249: 5250: (define_split 5251: [(set (match_operand:SI 0 "register_operand" "") 5252: (minus:SI (match_operand:SI 2 "register_operand" "") 5253: (ne:SI (match_operand:SI 1 "register_operand" "") 5254: (const_int 0)))) 5255: (clobber (reg:CC 0))] 5256: "" 5257: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 5258: (const_int 0))) 5259: (set (match_dup 0) (minus:SI (match_dup 2) 5260: (ltu:SI (reg:CC 0) (const_int 0))))] 5261: "") 5262: 5263: (define_split 5264: [(set (match_operand:SI 0 "register_operand" "") 5265: (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "") 5266: (const_int 0)) 5267: (match_operand:SI 2 "register_operand" ""))) 5268: (clobber (reg:CC 0))] 5269: "" 5270: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 5271: (const_int 0))) 5272: (set (match_dup 0) (plus:SI (geu:SI (reg:CC 0) (const_int 0)) 5273: (match_dup 2)))] 5274: "") 5275: 5276: (define_split 5277: [(set (match_operand:SI 0 "register_operand" "") 5278: (minus:SI (match_operand:SI 2 "register_operand" "") 5279: (eq:SI (match_operand:SI 1 "register_operand" "") 5280: (const_int 0)))) 5281: (clobber (reg:CC 0))] 5282: "" 5283: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1)) 5284: (const_int 0))) 5285: (set (match_dup 0) (minus:SI (match_dup 2) 5286: (geu:SI (reg:CC 0) (const_int 0))))] 5287: "") 5288: 5289: ;; Peepholes go at the end. 5290: 5291: ;; Optimize consecutive loads or stores into ldd and std when possible. 5292: ;; The conditions in which we do this are very restricted and are 5293: ;; explained in the code for {registers,memory}_ok_for_ldd functions. 5294: 5295: (define_peephole 5296: [(set (match_operand:SI 0 "register_operand" "=rf") 5297: (match_operand:SI 1 "memory_operand" "")) 5298: (set (match_operand:SI 2 "register_operand" "=rf") 5299: (match_operand:SI 3 "memory_operand" ""))] 1.1.1.3 ! root 5300: "! TARGET_V9 ! 5301: && registers_ok_for_ldd_peep (operands[0], operands[2]) 1.1 root 5302: && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) 5303: && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" 5304: "ldd %1,%0") 5305: 5306: (define_peephole 5307: [(set (match_operand:SI 0 "memory_operand" "") 5308: (match_operand:SI 1 "register_operand" "rf")) 5309: (set (match_operand:SI 2 "memory_operand" "") 5310: (match_operand:SI 3 "register_operand" "rf"))] 1.1.1.3 ! root 5311: "! TARGET_V9 ! 5312: && registers_ok_for_ldd_peep (operands[1], operands[3]) 1.1 root 5313: && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) 5314: && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" 5315: "std %1,%0") 5316: 5317: (define_peephole 5318: [(set (match_operand:SF 0 "register_operand" "=fr") 5319: (match_operand:SF 1 "memory_operand" "")) 5320: (set (match_operand:SF 2 "register_operand" "=fr") 5321: (match_operand:SF 3 "memory_operand" ""))] 1.1.1.3 ! root 5322: "! TARGET_V9 ! 5323: && registers_ok_for_ldd_peep (operands[0], operands[2]) 1.1 root 5324: && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) 5325: && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" 5326: "ldd %1,%0") 5327: 5328: (define_peephole 5329: [(set (match_operand:SF 0 "memory_operand" "") 5330: (match_operand:SF 1 "register_operand" "fr")) 5331: (set (match_operand:SF 2 "memory_operand" "") 5332: (match_operand:SF 3 "register_operand" "fr"))] 1.1.1.3 ! root 5333: "! TARGET_V9 ! 5334: && registers_ok_for_ldd_peep (operands[1], operands[3]) 1.1 root 5335: && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) 5336: && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" 5337: "std %1,%0") 5338: 5339: (define_peephole 5340: [(set (match_operand:SI 0 "register_operand" "=rf") 5341: (match_operand:SI 1 "memory_operand" "")) 5342: (set (match_operand:SI 2 "register_operand" "=rf") 5343: (match_operand:SI 3 "memory_operand" ""))] 1.1.1.3 ! root 5344: "! TARGET_V9 ! 5345: && registers_ok_for_ldd_peep (operands[2], operands[0]) 1.1 root 5346: && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) 5347: && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" 5348: "ldd %3,%2") 5349: 5350: (define_peephole 5351: [(set (match_operand:SI 0 "memory_operand" "") 5352: (match_operand:SI 1 "register_operand" "rf")) 5353: (set (match_operand:SI 2 "memory_operand" "") 5354: (match_operand:SI 3 "register_operand" "rf"))] 1.1.1.3 ! root 5355: "! TARGET_V9 ! 5356: && registers_ok_for_ldd_peep (operands[3], operands[1]) 1.1 root 5357: && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) 5358: && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 5359: "std %3,%2") 5360: 5361: (define_peephole 5362: [(set (match_operand:SF 0 "register_operand" "=fr") 5363: (match_operand:SF 1 "memory_operand" "")) 5364: (set (match_operand:SF 2 "register_operand" "=fr") 5365: (match_operand:SF 3 "memory_operand" ""))] 1.1.1.3 ! root 5366: "! TARGET_V9 ! 5367: && registers_ok_for_ldd_peep (operands[2], operands[0]) 1.1 root 5368: && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) 5369: && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" 5370: "ldd %3,%2") 5371: 5372: (define_peephole 5373: [(set (match_operand:SF 0 "memory_operand" "") 5374: (match_operand:SF 1 "register_operand" "fr")) 5375: (set (match_operand:SF 2 "memory_operand" "") 5376: (match_operand:SF 3 "register_operand" "fr"))] 1.1.1.3 ! root 5377: "! TARGET_V9 ! 5378: && registers_ok_for_ldd_peep (operands[3], operands[1]) 1.1 root 5379: && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) 5380: && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 5381: "std %3,%2") 5382: 5383: ;; Optimize the case of following a reg-reg move with a test 5384: ;; of reg just moved. Don't allow floating point regs for operand 0 or 1. 5385: ;; This can result from a float to fix conversion. 5386: 5387: (define_peephole 5388: [(set (match_operand:SI 0 "register_operand" "=r") 5389: (match_operand:SI 1 "register_operand" "r")) 5390: (set (reg:CC 0) 5391: (compare:CC (match_operand:SI 2 "register_operand" "r") 5392: (const_int 0)))] 5393: "(rtx_equal_p (operands[2], operands[0]) 5394: || rtx_equal_p (operands[2], operands[1])) 5395: && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" 5396: "orcc %1,%%g0,%0") 5397: 1.1.1.3 ! root 5398: (define_peephole ! 5399: [(set (match_operand:DI 0 "register_operand" "=r") ! 5400: (match_operand:DI 1 "register_operand" "r")) ! 5401: (set (reg:CCX 0) ! 5402: (compare:CCX (match_operand:DI 2 "register_operand" "r") ! 5403: (const_int 0)))] ! 5404: "TARGET_V9 ! 5405: && (rtx_equal_p (operands[2], operands[0]) ! 5406: || rtx_equal_p (operands[2], operands[1])) ! 5407: && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" ! 5408: "orcc %1,%%g0,%0") ! 5409: 1.1 root 5410: ;; Do {sign,zero}-extended compares somewhat more efficiently. 5411: ;; ??? Is this now the Right Way to do this? Or will SCRATCH 5412: ;; eventually have some impact here? 5413: 5414: (define_peephole 5415: [(set (match_operand:HI 0 "register_operand" "") 5416: (match_operand:HI 1 "memory_operand" "")) 5417: (set (match_operand:SI 2 "register_operand" "") 5418: (sign_extend:SI (match_dup 0))) 5419: (set (reg:CC 0) 5420: (compare:CC (match_dup 2) 5421: (const_int 0)))] 5422: "" 5423: "ldsh %1,%0\;orcc %0,%%g0,%2") 5424: 5425: (define_peephole 1.1.1.3 ! root 5426: [(set (match_operand:HI 0 "register_operand" "") ! 5427: (match_operand:HI 1 "memory_operand" "")) ! 5428: (set (match_operand:DI 2 "register_operand" "") ! 5429: (sign_extend:DI (match_dup 0))) ! 5430: (set (reg:CCX 0) ! 5431: (compare:CCX (match_dup 2) ! 5432: (const_int 0)))] ! 5433: "TARGET_V9" ! 5434: "ldsh %1,%0\;orcc %0,%%g0,%2") ! 5435: ! 5436: (define_peephole 1.1 root 5437: [(set (match_operand:QI 0 "register_operand" "") 5438: (match_operand:QI 1 "memory_operand" "")) 5439: (set (match_operand:SI 2 "register_operand" "") 5440: (sign_extend:SI (match_dup 0))) 5441: (set (reg:CC 0) 5442: (compare:CC (match_dup 2) 5443: (const_int 0)))] 5444: "" 5445: "ldsb %1,%0\;orcc %0,%%g0,%2") 5446: 5447: (define_peephole 1.1.1.3 ! root 5448: [(set (match_operand:QI 0 "register_operand" "") ! 5449: (match_operand:QI 1 "memory_operand" "")) ! 5450: (set (match_operand:DI 2 "register_operand" "") ! 5451: (sign_extend:DI (match_dup 0))) ! 5452: (set (reg:CCX 0) ! 5453: (compare:CCX (match_dup 2) ! 5454: (const_int 0)))] ! 5455: "TARGET_V9" ! 5456: "ldsb %1,%0\;orcc %0,%%g0,%2") ! 5457: ! 5458: (define_peephole 1.1 root 5459: [(set (match_operand:HI 0 "register_operand" "") 5460: (match_operand:HI 1 "memory_operand" "")) 5461: (set (match_operand:SI 2 "register_operand" "") 5462: (sign_extend:SI (match_dup 0)))] 5463: "dead_or_set_p (insn, operands[0])" 5464: "* 5465: { 5466: warning (\"bad peephole\"); 5467: if (! MEM_VOLATILE_P (operands[1])) 5468: abort (); 5469: return \"ldsh %1,%2\"; 5470: }") 5471: 5472: (define_peephole 5473: [(set (match_operand:QI 0 "register_operand" "") 5474: (match_operand:QI 1 "memory_operand" "")) 5475: (set (match_operand:SI 2 "register_operand" "") 5476: (sign_extend:SI (match_dup 0)))] 5477: "dead_or_set_p (insn, operands[0])" 5478: "* 5479: { 5480: warning (\"bad peephole\"); 5481: if (! MEM_VOLATILE_P (operands[1])) 5482: abort (); 5483: return \"ldsb %1,%2\"; 5484: }") 5485: 5486: ;; Floating-point move peepholes 1.1.1.3 ! root 5487: ;; ??? v9: Do we want similar ones? 1.1 root 5488: 5489: (define_peephole 5490: [(set (match_operand:SI 0 "register_operand" "=r") 5491: (lo_sum:SI (match_dup 0) 5492: (match_operand:SI 1 "immediate_operand" "i"))) 1.1.1.3 ! root 5493: (set (match_operand:DF 2 "register_operand" "=er") 1.1 root 5494: (mem:DF (match_dup 0)))] 5495: "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)" 5496: "* 5497: { 5498: /* Go by way of output_move_double in case the register in operand 2 5499: is not properly aligned for ldd. */ 5500: operands[1] = gen_rtx (MEM, DFmode, 5501: gen_rtx (LO_SUM, SImode, operands[0], operands[1])); 5502: operands[0] = operands[2]; 5503: return output_move_double (operands); 5504: }") 5505: 5506: (define_peephole 5507: [(set (match_operand:SI 0 "register_operand" "=r") 5508: (lo_sum:SI (match_dup 0) 5509: (match_operand:SI 1 "immediate_operand" "i"))) 5510: (set (match_operand:SF 2 "register_operand" "=fr") 5511: (mem:SF (match_dup 0)))] 5512: "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)" 5513: "ld [%0+%%lo(%a1)],%2") 5514: 5515: ;; Return peepholes. First the "normal" ones 5516: 5517: ;; ??? There are QImode, HImode, and SImode versions of this pattern. 5518: ;; It might be possible to write one more general pattern instead of three. 5519: 5520: (define_insn "" 5521: [(set (match_operand:QI 0 "restore_operand" "") 5522: (match_operand:QI 1 "arith_operand" "rI")) 5523: (return)] 5524: "! TARGET_EPILOGUE" 5525: "* 5526: { 1.1.1.3 ! root 5527: if (! TARGET_V9 && current_function_returns_struct) 1.1 root 5528: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; 5529: else 5530: return \"ret\;restore %%g0,%1,%Y0\"; 5531: }" 5532: [(set_attr "type" "multi")]) 5533: 5534: (define_insn "" 5535: [(set (match_operand:HI 0 "restore_operand" "") 5536: (match_operand:HI 1 "arith_operand" "rI")) 5537: (return)] 5538: "! TARGET_EPILOGUE" 5539: "* 5540: { 1.1.1.3 ! root 5541: if (! TARGET_V9 && current_function_returns_struct) 1.1 root 5542: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; 5543: else 5544: return \"ret\;restore %%g0,%1,%Y0\"; 5545: }" 5546: [(set_attr "type" "multi")]) 5547: 5548: (define_insn "" 5549: [(set (match_operand:SI 0 "restore_operand" "") 5550: (match_operand:SI 1 "arith_operand" "rI")) 5551: (return)] 5552: "! TARGET_EPILOGUE" 5553: "* 5554: { 1.1.1.3 ! root 5555: if (! TARGET_V9 && current_function_returns_struct) 1.1 root 5556: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; 5557: else 5558: return \"ret\;restore %%g0,%1,%Y0\"; 5559: }" 5560: [(set_attr "type" "multi")]) 5561: 5562: ;; The following pattern is only generated by delayed-branch scheduling, 5563: ;; when the insn winds up in the epilogue. This can only happen when 5564: ;; ! TARGET_FPU because otherwise fp return values are in %f0. 5565: (define_insn "" 5566: [(set (match_operand:SF 0 "restore_operand" "r") 5567: (match_operand:SF 1 "register_operand" "r")) 5568: (return)] 5569: "! TARGET_FPU && ! TARGET_EPILOGUE" 5570: "* 5571: { 1.1.1.3 ! root 5572: if (! TARGET_V9 && current_function_returns_struct) 1.1 root 5573: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; 5574: else 5575: return \"ret\;restore %%g0,%1,%Y0\"; 5576: }" 5577: [(set_attr "type" "multi")]) 5578: 5579: (define_insn "" 5580: [(set (match_operand:SI 0 "restore_operand" "") 5581: (plus:SI (match_operand:SI 1 "arith_operand" "%r") 5582: (match_operand:SI 2 "arith_operand" "rI"))) 5583: (return)] 5584: "! TARGET_EPILOGUE" 5585: "* 5586: { 1.1.1.3 ! root 5587: if (! TARGET_V9 && current_function_returns_struct) 1.1 root 5588: return \"jmp %%i7+12\;restore %r1,%2,%Y0\"; 5589: else 5590: return \"ret\;restore %r1,%2,%Y0\"; 5591: }" 5592: [(set_attr "type" "multi")]) 5593: 1.1.1.3 ! root 5594: (define_insn "" ! 5595: [(set (match_operand:DI 0 "restore_operand" "") ! 5596: (match_operand:DI 1 "arith_double_operand" "rHI")) ! 5597: (return)] ! 5598: "TARGET_V9 && ! TARGET_EPILOGUE" ! 5599: "ret\;restore %%g0,%1,%Y0" ! 5600: [(set_attr "type" "multi")]) ! 5601: ! 5602: (define_insn "" ! 5603: [(set (match_operand:DI 0 "restore_operand" "") ! 5604: (plus:DI (match_operand:DI 1 "arith_operand" "%r") ! 5605: (match_operand:DI 2 "arith_double_operand" "rHI"))) ! 5606: (return)] ! 5607: "TARGET_V9 && ! TARGET_EPILOGUE" ! 5608: "ret\;restore %r1,%2,%Y0" ! 5609: [(set_attr "type" "multi")]) ! 5610: 1.1 root 5611: ;; Turned off because it should never match (subtracting a constant 5612: ;; is turned into addition) and because it would do the wrong thing 5613: ;; when operand 2 is -4096 (--4096 == 4096 is not a valid immediate). 5614: ;;(define_insn "" 5615: ;; [(set (match_operand:SI 0 "restore_operand" "") 5616: ;; (minus:SI (match_operand:SI 1 "register_operand" "r") 5617: ;; (match_operand:SI 2 "small_int" "I"))) 5618: ;; (return)] 5619: ;; "! TARGET_EPILOGUE" 5620: ;; "ret\;restore %1,-(%2),%Y0" 5621: ;; [(set_attr "type" "multi")]) 5622: 5623: ;; The following pattern is only generated by delayed-branch scheduling, 5624: ;; when the insn winds up in the epilogue. 5625: (define_insn "" 5626: [(set (reg:SF 32) 5627: (match_operand:SF 0 "register_operand" "f")) 5628: (return)] 5629: "! TARGET_EPILOGUE" 5630: "ret\;fmovs %0,%%f0" 5631: [(set_attr "type" "multi")]) 5632: 1.1.1.3 ! root 5633: ;; Now peepholes to do a call followed by a jump. 1.1 root 5634: 5635: (define_peephole 5636: [(parallel [(set (match_operand 0 "" "") 1.1.1.3 ! root 5637: (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps")) 1.1 root 5638: (match_operand 2 "" ""))) 5639: (clobber (reg:SI 15))]) 5640: (set (pc) (label_ref (match_operand 3 "" "")))] 5641: "short_branch (INSN_UID (insn), INSN_UID (operands[3]))" 5642: "* 5643: { 5644: return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\"; 5645: }") 5646: 5647: (define_peephole 1.1.1.3 ! root 5648: [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps")) 1.1 root 5649: (match_operand 1 "" "")) 5650: (clobber (reg:SI 15))]) 5651: (set (pc) (label_ref (match_operand 2 "" "")))] 5652: "short_branch (INSN_UID (insn), INSN_UID (operands[2]))" 5653: "* 5654: { 5655: return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\"; 5656: }") 5657: 5658: (define_peephole 1.1.1.3 ! root 5659: [(parallel [(set (match_operand 0 "" "") ! 5660: (call (mem:SI (match_operand:DI 1 "call_operand_address" "ps")) ! 5661: (match_operand 2 "" ""))) ! 5662: (clobber (reg:DI 15))]) ! 5663: (set (pc) (label_ref (match_operand 3 "" "")))] ! 5664: "TARGET_V9 && short_branch (INSN_UID (insn), INSN_UID (operands[3]))" ! 5665: "* ! 5666: { ! 5667: return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\"; ! 5668: }") ! 5669: ! 5670: (define_peephole ! 5671: [(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps")) ! 5672: (match_operand 1 "" "")) ! 5673: (clobber (reg:DI 15))]) ! 5674: (set (pc) (label_ref (match_operand 2 "" "")))] ! 5675: "TARGET_V9 && short_branch (INSN_UID (insn), INSN_UID (operands[2]))" ! 5676: "* ! 5677: { ! 5678: return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\"; ! 5679: }") ! 5680: ! 5681: ;; Other miscellaneous peepholes. ! 5682: ! 5683: (define_peephole 1.1 root 5684: [(parallel [(set (match_operand:SI 0 "register_operand" "=r") 5685: (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") 5686: (reg:SI 0))) 5687: (clobber (reg:CC 0))]) 5688: (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))] 5689: "" 5690: "subxcc %r1,0,%0")
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.