|
|
1.1 ! root 1: ;;- Machine description for ROMP chip for GNU C compiler ! 2: ;; Copyright (C) 1988, 1991 Free Software Foundation, Inc. ! 3: ;; Contributed by Richard Kenner ([email protected]) ! 4: ! 5: ;; This file is part of GNU CC. ! 6: ! 7: ;; GNU CC is free software; you can redistribute it and/or modify ! 8: ;; it under the terms of the GNU General Public License as published by ! 9: ;; the Free Software Foundation; either version 2, or (at your option) ! 10: ;; any later version. ! 11: ! 12: ;; GNU CC is distributed in the hope that it will be useful, ! 13: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: ;; GNU General Public License for more details. ! 16: ! 17: ;; You should have received a copy of the GNU General Public License ! 18: ;; along with GNU CC; see the file COPYING. If not, write to ! 19: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ! 20: ! 21: ! 22: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. ! 23: ! 24: ;; Define the attributes for the ROMP. ! 25: ! 26: ;; Insn type. Used to default other attribute values. ! 27: ! 28: (define_attr "type" ! 29: "branch,ibranch,return,fp,load,loadz,store,call,address,arith,compare,multi,misc" ! 30: (const_string "arith")) ! 31: ! 32: ;; Length in bytes. ! 33: ! 34: (define_attr "length" "" ! 35: (cond [(eq_attr "type" "branch") ! 36: (if_then_else (and (ge (minus (pc) (match_dup 0)) ! 37: (const_int -256)) ! 38: (le (minus (pc) (match_dup 0)) ! 39: (const_int 254))) ! 40: (const_int 2) ! 41: (const_int 4)) ! 42: (eq_attr "type" "return,ibranch") (const_int 2) ! 43: (eq_attr "type" "fp") (const_int 10) ! 44: (eq_attr "type" "call") (const_int 4) ! 45: (eq_attr "type" "load") ! 46: (cond [(match_operand 1 "short_memory_operand" "") (const_int 2) ! 47: (match_operand 1 "symbolic_memory_operand" "") (const_int 8)] ! 48: (const_int 4)) ! 49: (eq_attr "type" "loadz") ! 50: (cond [(match_operand 1 "zero_memory_operand" "") (const_int 2) ! 51: (match_operand 1 "symbolic_memory_operand" "") (const_int 8)] ! 52: (const_string "4")) ! 53: (eq_attr "type" "store") ! 54: (cond [(match_operand 0 "short_memory_operand" "") (const_int 2) ! 55: (match_operand 0 "symbolic_memory_operand" "") (const_int 8)] ! 56: (const_int 4))] ! 57: (const_int 4))) ! 58: ! 59: ;; Whether insn can be placed in a delay slot. ! 60: ! 61: (define_attr "in_delay_slot" "yes,no" ! 62: (cond [(eq_attr "length" "8,10,38") (const_string "no") ! 63: (eq_attr "type" "branch,ibranch,return,call,multi") ! 64: (const_string "no")] ! 65: (const_string "yes"))) ! 66: ! 67: ;; Whether insn needs a delay slot. We have to say that two-byte ! 68: ;; branches do not need a delay slot. Otherwise, branch shortening will ! 69: ;; try to do something with delay slot insns (we want it to on the PA). ! 70: ;; This is a kludge, which should be cleaned up at some point. ! 71: ! 72: (define_attr "needs_delay_slot" "yes,no" ! 73: (if_then_else (ior (and (eq_attr "type" "branch") ! 74: (eq_attr "length" "4")) ! 75: (eq_attr "type" "ibranch,return,call")) ! 76: (const_string "yes") (const_string "no"))) ! 77: ! 78: ;; What insn does to the condition code. ! 79: ! 80: (define_attr "cc" ! 81: "clobber,none,sets,change0,copy1to0,compare,tbit" ! 82: (cond [(eq_attr "type" "load,loadz") (const_string "change0") ! 83: (eq_attr "type" "store") (const_string "none") ! 84: (eq_attr "type" "fp,call") (const_string "clobber") ! 85: (eq_attr "type" "branch,ibranch,return") (const_string "none") ! 86: (eq_attr "type" "address") (const_string "change0") ! 87: (eq_attr "type" "compare") (const_string "compare") ! 88: (eq_attr "type" "arith") (const_string "sets")] ! 89: (const_string "clobber"))) ! 90: ! 91: ;; Define attributes for `asm' insns. ! 92: ! 93: (define_asm_attributes [(set_attr "type" "misc") ! 94: (set_attr "length" "8") ! 95: (set_attr "in_delay_slot" "no") ! 96: (set_attr "cc" "clobber")]) ! 97: ! 98: ;; Define the delay slot requirements for branches and calls. We don't have ! 99: ;; any annulled insns. ! 100: ;; ! 101: (define_delay (eq_attr "needs_delay_slot" "yes") ! 102: [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) ! 103: ! 104: ;; We cannot give a floating-point comparison a delay slot, even though it ! 105: ;; could make use of it. This is because it would confuse next_cc0_user ! 106: ;; to do so. Other fp insns can't get a delay slow because they set their ! 107: ;; result and use their input after the delay slot insn is executed. This ! 108: ;; isn't what reorg.c expects. ! 109: ! 110: ;; Define load & store delays. These were obtained by measurements done by ! 111: ;; [email protected]. ! 112: ;; ! 113: ;; In general, the memory unit can support at most two simultaneous operations. ! 114: ;; ! 115: ;; Loads take 5 cycles to return the data and can be pipelined up to the ! 116: ;; limit of two simultaneous operations. ! 117: (define_function_unit "memory" 1 2 (eq_attr "type" "load,loadz") 5 0) ! 118: ! 119: ;; Stores do not return data, but tie up the memory unit for 2 cycles if the ! 120: ;; next insn is also a store. ! 121: (define_function_unit "memory" 1 2 (eq_attr "type" "store") 1 2 ! 122: [(eq_attr "type" "store")]) ! 123: ! 124: ;; Move word instructions. ! 125: ;; ! 126: ;; If destination is memory but source is not register, force source to ! 127: ;; register. ! 128: ;; ! 129: ;; If source is a constant that is too large to load in a single insn, build ! 130: ;; it in two pieces. ! 131: ;; ! 132: ;; If destination is memory and source is a register, a temporary register ! 133: ;; will be needed. In that case, make a PARALLEL of the SET and a ! 134: ;; CLOBBER of a SCRATCH to allocate the required temporary. ! 135: ;; ! 136: ;; This temporary is ACTUALLY only needed when the destination is a ! 137: ;; relocatable expression. For generating RTL, however, we always ! 138: ;; place the CLOBBER. In insns where it is not needed, the SCRATCH will ! 139: ;; not be allocated to a register. ! 140: ;; ! 141: ;; Also, avoid creating pseudo-registers or SCRATCH rtx's during reload as ! 142: ;; they will not be correctly handled. We never need pseudos for that ! 143: ;; case anyway. ! 144: ;; ! 145: ;; We do not use DEFINE_SPLIT for loading constants because the number ! 146: ;; of cases in the resulting unsplit insn would be too high to deal ! 147: ;; with practically. ! 148: (define_expand "movsi" ! 149: [(set (match_operand:SI 0 "general_operand" "") ! 150: (match_operand:SI 1 "general_operand" ""))] ! 151: "" ! 152: " ! 153: { rtx op0 = operands[0]; ! 154: rtx op1 = operands[1]; ! 155: ! 156: if (GET_CODE (op1) == REG && REGNO (op1) == 16) ! 157: DONE; ! 158: ! 159: if (GET_CODE (op0) == REG && REGNO (op0) == 16) ! 160: DONE; ! 161: ! 162: if (GET_CODE (op0) == MEM && ! reload_in_progress) ! 163: { ! 164: emit_insn (gen_storesi (operands[0], force_reg (SImode, operands[1]))); ! 165: DONE; ! 166: } ! 167: else if (GET_CODE (op1) == CONST_INT) ! 168: { ! 169: int const_val = INTVAL (op1); ! 170: ! 171: /* Try a number of cases to see how to best load the constant. */ ! 172: if ((const_val & 0xffff) == 0 ! 173: || (const_val & 0xffff0000) == 0 ! 174: || (unsigned) (const_val + 0x8000) < 0x10000) ! 175: /* Can do this in one insn, so generate it. */ ! 176: ; ! 177: else if (((- const_val) & 0xffff) == 0 ! 178: || ((- const_val) & 0xffff0000) == 0 ! 179: || (unsigned) ((- const_val) + 0x8000) < 0x10000) ! 180: { ! 181: /* Can do this by loading the negative constant and then negating. */ ! 182: emit_move_insn (operands[0], ! 183: gen_rtx (CONST_INT, VOIDmode, - const_val)); ! 184: emit_insn (gen_negsi2 (operands[0], operands[0])); ! 185: DONE; ! 186: } ! 187: else ! 188: /* Do this the long way. */ ! 189: { ! 190: unsigned int high_part = const_val & 0xffff0000; ! 191: unsigned int low_part = const_val & 0xffff; ! 192: int i; ! 193: ! 194: if (low_part >= 0x10 && exact_log2 (low_part) >= 0) ! 195: i = high_part, high_part = low_part, low_part = i; ! 196: ! 197: emit_move_insn (operands[0], ! 198: gen_rtx (CONST_INT, VOIDmode, low_part)); ! 199: emit_insn (gen_iorsi3 (operands[0], operands[0], ! 200: gen_rtx (CONST_INT, VOIDmode, high_part))); ! 201: DONE; ! 202: } ! 203: } ! 204: }") ! 205: ! 206: ;; Move from a symbolic memory location to a register is special. In this ! 207: ;; case, we know in advance that the register cannot be r0, so we can improve ! 208: ;; register allocation by treating it separately. ! 209: ! 210: (define_insn "" ! 211: [(set (match_operand:SI 0 "register_operand" "=b") ! 212: (match_operand:SI 1 "symbolic_memory_operand" "m"))] ! 213: "" ! 214: "load %0,%1" ! 215: [(set_attr "type" "load")]) ! 216: ! 217: ;; Generic single-word move insn. We avoid the case where the destination is ! 218: ;; a symbolic address, as that needs a temporary register. ! 219: ! 220: (define_insn "" ! 221: [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,r,r,r,b,Q") ! 222: (match_operand:SI 1 "romp_operand" "rR,I,K,L,M,S,s,Q,m,r"))] ! 223: "register_operand (operands[0], SImode) ! 224: || register_operand (operands[1], SImode)" ! 225: "@ ! 226: cas %0,%1,r0 ! 227: lis %0,%1 ! 228: cal %0,%1(r0) ! 229: cal16 %0,%1(r0) ! 230: cau %0,%H1(r0) ! 231: ail %0,r14,%C1 ! 232: get %0,$%1 ! 233: l%M1 %0,%1 ! 234: load %0,%1 ! 235: st%M0 %1,%0" ! 236: [(set_attr "type" "address,address,address,address,address,arith,misc,load,load,store") ! 237: (set_attr "length" "2,2,4,4,4,4,8,*,*,*")]) ! 238: ! 239: (define_insn "storesi" ! 240: [(set (match_operand:SI 0 "memory_operand" "=Q,m") ! 241: (match_operand:SI 1 "register_operand" "r,r")) ! 242: (clobber (match_scratch:SI 2 "=X,&b"))] ! 243: "" ! 244: "@ ! 245: st%M0 %1,%0 ! 246: store %1,%0,%2" ! 247: [(set_attr "type" "store")]) ! 248: ! 249: ;; This pattern is used by reload when we store into a symbolic address. It ! 250: ;; provides the temporary register required. This pattern is only used ! 251: ;; when SECONDARY_OUTPUT_RELOAD_CLASS returns something other than ! 252: ;; NO_REGS, so we need not have any predicates here. ! 253: ! 254: (define_expand "reload_outsi" ! 255: [(parallel [(set (match_operand:SI 0 "symbolic_memory_operand" "=m") ! 256: (match_operand:SI 1 "" "r")) ! 257: (clobber (match_operand:SI 2 "" "=&b"))])] ! 258: "" ! 259: "") ! 260: ! 261: ;; Now do the same for the QI move instructions. ! 262: (define_expand "movqi" ! 263: [(set (match_operand:QI 0 "general_operand" "") ! 264: (match_operand:QI 1 "general_operand" ""))] ! 265: "" ! 266: " ! 267: { rtx op0 = operands[0]; ! 268: ! 269: if (GET_CODE (op0) == MEM && ! reload_in_progress) ! 270: { ! 271: emit_insn (gen_storeqi (operands[0], force_reg (QImode, operands[1]))); ! 272: DONE; ! 273: } ! 274: }") ! 275: ! 276: (define_insn "" ! 277: [(set (match_operand:QI 0 "register_operand" "=b") ! 278: (match_operand:QI 1 "symbolic_memory_operand" "m"))] ! 279: "" ! 280: "loadc %0,%1" ! 281: [(set_attr "type" "load")]) ! 282: ! 283: (define_insn "" ! 284: [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q") ! 285: (match_operand:QI 1 "romp_operand" "r,I,n,s,Q,m,r"))] ! 286: "register_operand (operands[0], QImode) ! 287: || register_operand (operands[1], QImode)" ! 288: "@ ! 289: cas %0,%1,r0 ! 290: lis %0,%1 ! 291: cal %0,%L1(r0) ! 292: get %0,$%1 ! 293: lc%M1 %0,%1 ! 294: loadc %0,%1 ! 295: stc%M0 %1,%0" ! 296: [(set_attr "type" "address,address,address,misc,load,load,store") ! 297: (set_attr "length" "2,2,4,8,*,*,*")]) ! 298: ! 299: (define_insn "storeqi" ! 300: [(set (match_operand:QI 0 "memory_operand" "=Q,m") ! 301: (match_operand:QI 1 "register_operand" "r,r")) ! 302: (clobber (match_scratch:SI 2 "=X,&b"))] ! 303: "" ! 304: "@ ! 305: stc%M0 %1,%0 ! 306: storec %1,%0,%2" ! 307: [(set_attr "type" "store")]) ! 308: ! 309: (define_expand "reload_outqi" ! 310: [(parallel [(set (match_operand:QI 0 "symbolic_memory_operand" "=m") ! 311: (match_operand:QI 1 "" "r")) ! 312: (clobber (match_operand:SI 2 "" "=&b"))])] ! 313: "" ! 314: "") ! 315: ! 316: ;; Finally, the HI instructions. ! 317: (define_expand "movhi" ! 318: [(set (match_operand:HI 0 "general_operand" "") ! 319: (match_operand:HI 1 "general_operand" ""))] ! 320: "" ! 321: " ! 322: { rtx op0 = operands[0]; ! 323: ! 324: if (GET_CODE (op0) == MEM && ! reload_in_progress) ! 325: { ! 326: emit_insn (gen_storehi (operands[0], force_reg (HImode, operands[1]))); ! 327: DONE; ! 328: } ! 329: }") ! 330: ! 331: (define_insn "" ! 332: [(set (match_operand:HI 0 "register_operand" "=b") ! 333: (match_operand:HI 1 "symbolic_memory_operand" "m"))] ! 334: "" ! 335: "loadha %0,%1" ! 336: [(set_attr "type" "load")]) ! 337: ! 338: (define_insn "" ! 339: [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q") ! 340: (match_operand:HI 1 "romp_operand" "r,I,n,s,Q,m,r"))] ! 341: "register_operand (operands[0], HImode) ! 342: || register_operand (operands[1], HImode)" ! 343: "@ ! 344: cas %0,%1,r0 ! 345: lis %0,%1 ! 346: cal %0,%L1(r0) ! 347: get %0,$%1 ! 348: lh%N1 %0,%1 ! 349: loadh %0,%1 ! 350: sth%M0 %1,%0" ! 351: [(set_attr "type" "address,address,address,misc,loadz,loadz,store") ! 352: (set_attr "length" "2,2,4,8,*,*,*")]) ! 353: ! 354: (define_insn "storehi" ! 355: [(set (match_operand:HI 0 "memory_operand" "=Q,m") ! 356: (match_operand:HI 1 "register_operand" "r,r")) ! 357: (clobber (match_scratch:SI 2 "=X,&b"))] ! 358: "" ! 359: "@ ! 360: sth%M0 %1,%0 ! 361: storeh %1,%0,%2" ! 362: [(set_attr "type" "store")]) ! 363: ! 364: (define_expand "reload_outhi" ! 365: [(parallel [(set (match_operand:HI 0 "symbolic_memory_operand" "=m") ! 366: (match_operand:HI 1 "" "r")) ! 367: (clobber (match_operand:SI 2 "" "=&b"))])] ! 368: "" ! 369: "") ! 370: ! 371: ;; For DI move, if we have a constant, break the operation apart into ! 372: ;; two SImode moves because the optimizer may be able to do a better job ! 373: ;; with the resulting code. ! 374: ;; ! 375: ;; For memory stores, make the required pseudo for a temporary in case we ! 376: ;; are storing into an absolute address. ! 377: ;; ! 378: ;; We need to be careful about the cases where the output is a register that is ! 379: ;; the second register of the input. ! 380: ! 381: (define_expand "movdi" ! 382: [(set (match_operand:DI 0 "general_operand" "") ! 383: (match_operand:DI 1 "general_operand" ""))] ! 384: "" ! 385: " ! 386: { rtx op0 = operands[0]; ! 387: rtx op1 = operands[1]; ! 388: ! 389: if (CONSTANT_P (op1)) ! 390: { ! 391: rtx insns; ! 392: ! 393: start_sequence (); ! 394: emit_move_insn (operand_subword (op0, 0, 1, DImode), ! 395: operand_subword (op1, 0, 1, DImode)); ! 396: emit_move_insn (operand_subword (op0, 1, 1, DImode), ! 397: operand_subword (op1, 1, 1, DImode)); ! 398: insns = get_insns (); ! 399: end_sequence (); ! 400: ! 401: emit_no_conflict_block (insns, op0, op1, 0, op1); ! 402: DONE; ! 403: } ! 404: ! 405: if (GET_CODE (op0) == MEM && ! reload_in_progress) ! 406: { ! 407: emit_insn (gen_storedi (operands[0], force_reg (DImode, operands[1]))); ! 408: DONE; ! 409: } ! 410: }") ! 411: ! 412: (define_insn "" ! 413: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") ! 414: (match_operand:DI 1 "reg_or_mem_operand" "r,Q,m,r"))] ! 415: "register_operand (operands[0], DImode) ! 416: || register_operand (operands[1], DImode)" ! 417: "* ! 418: { ! 419: switch (which_alternative) ! 420: { ! 421: case 0: ! 422: if (REGNO (operands[0]) == REGNO (operands[1]) + 1) ! 423: return \"cas %O0,%O1,r0\;cas %0,%1,r0\"; ! 424: else ! 425: return \"cas %0,%1,r0\;cas %O0,%O1,r0\"; ! 426: case 1: ! 427: /* Here we must see which word to load first. We default to the ! 428: low-order word unless it occurs in the address. */ ! 429: if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, ! 430: operands[1], 0)) ! 431: return \"l%M1 %O0,%O1\;l%M1 %0,%1\"; ! 432: else ! 433: return \"l%M1 %0,%1\;l%M1 %O0,%O1\"; ! 434: case 2: ! 435: return \"get %O0,$%1\;ls %0,0(%O0)\;ls %O0,4(%O0)\"; ! 436: case 3: ! 437: return \"st%M0 %1,%0\;st%M0 %O1,%O0\"; ! 438: } ! 439: }" ! 440: [(set_attr "type" "multi") ! 441: (set_attr "cc" "change0,change0,change0,none") ! 442: (set_attr "length" "4,12,8,8")]) ! 443: ! 444: (define_insn "storedi" ! 445: [(set (match_operand:DI 0 "memory_operand" "=Q,m") ! 446: (match_operand:DI 1 "register_operand" "r,r")) ! 447: (clobber (match_scratch:SI 2 "=X,&b"))] ! 448: "" ! 449: "@ ! 450: st%M0 %1,%0\;st%M0 %O1,%O0 ! 451: get %2,$%0\;sts %1,0(%2)\;sts %O1,4(%2)" ! 452: [(set_attr "type" "multi,multi") ! 453: (set_attr "cc" "none,none") ! 454: (set_attr "length" "8,12")]) ! 455: ! 456: (define_expand "reload_outdi" ! 457: [(parallel [(set (match_operand:DI 0 "symbolic_memory_operand" "=m") ! 458: (match_operand:DI 1 "" "r")) ! 459: (clobber (match_operand:SI 2 "" "=&b"))])] ! 460: "" ! 461: "") ! 462: ! 463: ;; Split symbolic memory operands differently. We first load the address ! 464: ;; into a register and then do the two loads or stores. We can only do ! 465: ;; this if operand_subword won't produce a SUBREG, which is only when ! 466: ;; operands[0] is a hard register. Thus, these won't be used during the ! 467: ;; first insn scheduling pass. ! 468: (define_split ! 469: [(set (match_operand:DI 0 "register_operand" "") ! 470: (match_operand:DI 1 "symbolic_memory_operand" ""))] ! 471: "GET_CODE (operands[0]) == REG ! 472: && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER" ! 473: [(set (match_dup 2) (match_dup 3)) ! 474: (set (match_dup 4) (match_dup 5)) ! 475: (set (match_dup 6) (match_dup 7))] ! 476: " ! 477: { operands[2] = operand_subword (operands[0], 1, 0, DImode); ! 478: operands[3] = XEXP (operands[1], 0); ! 479: operands[4] = operand_subword (operands[0], 0, 0, DImode); ! 480: operands[5] = gen_rtx (MEM, SImode, operands[2]); ! 481: operands[6] = operands[2]; ! 482: operands[7] = gen_rtx (MEM, SImode, ! 483: gen_rtx (PLUS, SImode, operands[2], ! 484: gen_rtx (CONST_INT, VOIDmode, 4))); ! 485: ! 486: if (operands[2] == 0 || operands[4] == 0) ! 487: FAIL; ! 488: }") ! 489: ! 490: (define_split ! 491: [(set (match_operand:DI 0 "symbolic_memory_operand" "") ! 492: (match_operand:DI 1 "register_operand" "")) ! 493: (clobber (match_operand:SI 2 "register_operand" ""))] ! 494: "GET_CODE (operands[0]) == REG ! 495: && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER" ! 496: [(set (match_dup 2) (match_dup 3)) ! 497: (set (match_dup 4) (match_dup 5)) ! 498: (set (match_dup 6) (match_dup 7))] ! 499: " ! 500: { operands[3] = XEXP (operands[0], 0); ! 501: operands[4] = gen_rtx (MEM, SImode, operands[2]); ! 502: operands[5] = operand_subword (operands[1], 0, 0, DImode); ! 503: operands[6] = gen_rtx (MEM, SImode, ! 504: gen_rtx (PLUS, SImode, operands[2], ! 505: gen_rtx (CONST_INT, VOIDmode, 4))); ! 506: operands[7] = operand_subword (operands[1], 1, 0, DImode); ! 507: ! 508: if (operands[5] == 0 || operands[7] == 0) ! 509: FAIL; ! 510: }") ! 511: ! 512: ;; If the output is a register and the input is memory, we have to be careful ! 513: ;; and see which word needs to be loaded first. ! 514: ;; ! 515: ;; Note that this case doesn't have a CLOBBER. Therefore, we must either ! 516: ;; be after reload or operand[0] must not be a MEM. So we don't need a ! 517: ;; CLOBBER on the new insns either. ! 518: ;; ! 519: ;; Due to a bug in sched.c, we do not want to split this insn if both ! 520: ;; operands are registers and they overlap unless reload has completed. ! 521: (define_split ! 522: [(set (match_operand:DI 0 "general_operand" "") ! 523: (match_operand:DI 1 "general_operand" ""))] ! 524: "! symbolic_memory_operand (operands[0], DImode) ! 525: && ! symbolic_memory_operand (operands[1], DImode) ! 526: && ! (GET_CODE (operands[0]) == REG ! 527: && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) ! 528: && ! (GET_CODE (operands[1]) == REG ! 529: && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) ! 530: && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG ! 531: && ! reload_completed ! 532: && reg_overlap_mentioned_p (operands[0], operands[1]))" ! 533: [(set (match_dup 2) (match_dup 3)) ! 534: (set (match_dup 4) (match_dup 5))] ! 535: " ! 536: { if (GET_CODE (operands[0]) != REG ! 537: || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, ! 538: operands[1], 0)) ! 539: { ! 540: operands[2] = operand_subword (operands[0], 0, 0, DImode); ! 541: operands[3] = operand_subword (operands[1], 0, 0, DImode); ! 542: operands[4] = operand_subword (operands[0], 1, 0, DImode); ! 543: operands[5] = operand_subword (operands[1], 1, 0, DImode); ! 544: } ! 545: else ! 546: { ! 547: operands[2] = operand_subword (operands[0], 1, 0, DImode); ! 548: operands[3] = operand_subword (operands[1], 1, 0, DImode); ! 549: operands[4] = operand_subword (operands[0], 0, 0, DImode); ! 550: operands[5] = operand_subword (operands[1], 0, 0, DImode); ! 551: } ! 552: ! 553: if (operands[2] == 0 || operands[3] == 0 ! 554: || operands[4] == 0 || operands[5] == 0) ! 555: FAIL; ! 556: }") ! 557: ! 558: (define_split ! 559: [(set (match_operand:DI 0 "general_operand" "") ! 560: (match_operand:DI 1 "general_operand" "")) ! 561: (clobber (match_operand:SI 6 "register_operand" ""))] ! 562: "! symbolic_memory_operand (operands[0], DImode) ! 563: && ! symbolic_memory_operand (operands[1], DImode) ! 564: && ! (GET_CODE (operands[0]) == REG ! 565: && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) ! 566: && ! (GET_CODE (operands[1]) == REG ! 567: && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) ! 568: && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG ! 569: && ! reload_completed ! 570: && reg_overlap_mentioned_p (operands[0], operands[1]))" ! 571: [(parallel [(set (match_dup 2) (match_dup 3)) ! 572: (clobber (match_dup 7))]) ! 573: (parallel [(set (match_dup 4) (match_dup 5)) ! 574: (clobber (match_dup 8))])] ! 575: " ! 576: { if (GET_CODE (operands[0]) != REG ! 577: || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, ! 578: operands[1], 0)) ! 579: { ! 580: operands[2] = operand_subword (operands[0], 0, 0, DImode); ! 581: operands[3] = operand_subword (operands[1], 0, 0, DImode); ! 582: operands[4] = operand_subword (operands[0], 1, 0, DImode); ! 583: operands[5] = operand_subword (operands[1], 1, 0, DImode); ! 584: } ! 585: else ! 586: { ! 587: operands[2] = operand_subword (operands[0], 1, 0, DImode); ! 588: operands[3] = operand_subword (operands[1], 1, 0, DImode); ! 589: operands[4] = operand_subword (operands[0], 0, 0, DImode); ! 590: operands[5] = operand_subword (operands[1], 0, 0, DImode); ! 591: } ! 592: ! 593: if (operands[2] == 0 || operands[3] == 0 ! 594: || operands[4] == 0 || operands[5] == 0) ! 595: FAIL; ! 596: ! 597: /* We must be sure to make two different SCRATCH operands, since they ! 598: are not allowed to be shared. After reload, however, we only have ! 599: a SCRATCH if we won't use the operand, so it is allowed to share it ! 600: then. */ ! 601: if (reload_completed || GET_CODE (operands[6]) != SCRATCH) ! 602: operands[7] = operands[8] = operands[6]; ! 603: else ! 604: { ! 605: operands[7] = gen_rtx (SCRATCH, SImode); ! 606: operands[8] = gen_rtx (SCRATCH, SImode); ! 607: } ! 608: }") ! 609: ! 610: ;; Define move insns for SF, and DF. ! 611: ;; ! 612: ;; For register-register copies or a copy of something to itself, emit a ! 613: ;; single SET insn since it will likely be optimized away. ! 614: ;; ! 615: ;; Otherwise, emit a floating-point move operation unless both input and ! 616: ;; output are either constant, memory, or a non-floating-point hard register. ! 617: (define_expand "movdf" ! 618: [(parallel [(set (match_operand:DF 0 "general_operand" "") ! 619: (match_operand:DF 1 "general_operand" "")) ! 620: (clobber (reg:SI 0)) ! 621: (clobber (reg:SI 15))])] ! 622: "" ! 623: " ! 624: { rtx op0 = operands[0]; ! 625: rtx op1 = operands[1]; ! 626: ! 627: if (op0 == op1) ! 628: { ! 629: emit_insn (gen_rtx (SET, VOIDmode, op0, op1)); ! 630: DONE; ! 631: } ! 632: ! 633: if ((GET_CODE (op0) == MEM ! 634: || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER ! 635: && ! FP_REGNO_P (REGNO (op0)))) ! 636: && (GET_CODE (op1) == MEM ! 637: || GET_CODE (op1) == CONST_DOUBLE ! 638: || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER ! 639: && ! FP_REGNO_P (REGNO (op1)) && ! rtx_equal_p (op0, op1)))) ! 640: { ! 641: rtx insns; ! 642: ! 643: if (GET_CODE (op1) == CONST_DOUBLE) ! 644: op1 = force_const_mem (DFmode, op1); ! 645: ! 646: start_sequence (); ! 647: if (GET_CODE (operands[0]) != REG ! 648: || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, ! 649: operands[1]), 0) ! 650: { ! 651: emit_move_insn (operand_subword (op0, 0, 1, DFmode), ! 652: operand_subword_force (op1, 0, DFmode)); ! 653: emit_move_insn (operand_subword (op0, 1, 1, DFmode), ! 654: operand_subword_force (op1, 1, DFmode)); ! 655: } ! 656: else ! 657: { ! 658: emit_move_insn (operand_subword (op0, 1, 1, DFmode), ! 659: operand_subword_force (op1, 1, DFmode)); ! 660: emit_move_insn (operand_subword (op0, 0, 1, DFmode), ! 661: operand_subword_force (op1, 0, DFmode)); ! 662: } ! 663: ! 664: insns = get_insns (); ! 665: end_sequence (); ! 666: ! 667: emit_no_conflict_block (insns, op0, op1, 0, op1); ! 668: DONE; ! 669: } ! 670: }") ! 671: ! 672: (define_expand "movsf" ! 673: [(parallel [(set (match_operand:SF 0 "general_operand" "") ! 674: (match_operand:SF 1 "general_operand" "")) ! 675: (clobber (reg:SI 0)) ! 676: (clobber (reg:SI 15))])] ! 677: "" ! 678: " ! 679: { rtx op0 = operands[0]; ! 680: rtx op1 = operands[1]; ! 681: ! 682: if (op0 == op1) ! 683: { ! 684: emit_insn (gen_rtx (SET, VOIDmode, op0, op1)); ! 685: DONE; ! 686: } ! 687: ! 688: if ((GET_CODE (op0) == MEM ! 689: || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER ! 690: && ! FP_REGNO_P (REGNO (op0)))) ! 691: && (GET_CODE (op1) == MEM ! 692: || GET_CODE (op1) == CONST_DOUBLE ! 693: || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER ! 694: && ! FP_REGNO_P (REGNO (op1))))) ! 695: { ! 696: rtx last; ! 697: ! 698: if (GET_CODE (op1) == CONST_DOUBLE) ! 699: op1 = force_const_mem (SFmode, op1); ! 700: ! 701: last = emit_move_insn (operand_subword (op0, 0, 1, SFmode), ! 702: operand_subword_force (op1, 0, SFmode)); ! 703: ! 704: REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, op1, REG_NOTES (last)); ! 705: DONE; ! 706: } ! 707: }") ! 708: ! 709: ;; Define the move insns for SF and DF. Check for all general regs ! 710: ;; in the FP insns and make them non-FP if so. Do the same if the input and ! 711: ;; output are the same (the insn will be deleted in this case and we don't ! 712: ;; want to think there are FP insns when there might not be). ! 713: (define_insn "" ! 714: [(set (match_operand:SF 0 "general_operand" "=*frg") ! 715: (match_dup 0))] ! 716: "" ! 717: "nopr r0" ! 718: [(set_attr "type" "address") ! 719: (set_attr "length" "2")]) ! 720: ! 721: (define_insn "" ! 722: [(set (match_operand:SF 0 "general_operand" "=r,*fr,r,r,Q,m,frg") ! 723: (match_operand:SF 1 "general_operand" "r,0,Q,m,r,r,frg")) ! 724: (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z")) ! 725: (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))] ! 726: "" ! 727: "* ! 728: { switch (which_alternative) ! 729: { ! 730: case 0: ! 731: return \"cas %0,%1,r0\"; ! 732: case 1: ! 733: return \"nopr r0\"; ! 734: case 2: ! 735: return \"l%M1 %0,%1\"; ! 736: case 3: ! 737: return \"load %0,%1\"; ! 738: case 4: ! 739: return \"st%M0 %1,%0\"; ! 740: case 5: ! 741: return \"store %1,%0,%3\"; ! 742: default: ! 743: return output_fpop (SET, operands[0], operands[1], 0, insn); ! 744: } ! 745: }" ! 746: [(set_attr "type" "address,address,load,load,store,store,fp") ! 747: (set_attr "length" "2,2,*,*,*,*,*")]) ! 748: ! 749: (define_insn "" ! 750: [(set (match_operand:DF 0 "general_operand" "=*frg") ! 751: (match_dup 0))] ! 752: "" ! 753: "nopr r0" ! 754: [(set_attr "type" "address") ! 755: (set_attr "length" "2")]) ! 756: ! 757: (define_insn "" ! 758: [(set (match_operand:DF 0 "general_operand" "=r,*fr,r,r,Q,m,frg") ! 759: (match_operand:DF 1 "general_operand" "r,0,Q,m,r,r,*frg")) ! 760: (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z")) ! 761: (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))] ! 762: "" ! 763: "* ! 764: { switch (which_alternative) ! 765: { ! 766: case 0: ! 767: if (REGNO (operands[0]) == REGNO (operands[1]) + 1) ! 768: return \"cas %O0,%O1,r0\;cas %0,%1,r0\"; ! 769: else ! 770: return \"cas %0,%1,r0\;cas %O0,%O1,r0\"; ! 771: case 1: ! 772: return \"nopr r0\"; ! 773: case 2: ! 774: /* Here we must see which word to load first. We default to the ! 775: low-order word unless it occurs in the address. */ ! 776: if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, ! 777: operands[1], 0)) ! 778: return \"l%M1 %O0,%O1\;l%M1 %0,%1\"; ! 779: else ! 780: return \"l%M1 %0,%1\;l%M1 %O0,%O1\"; ! 781: case 3: ! 782: return \"get %3,$%1\;ls %0,0(%3)\;ls %O0,4(%3)\"; ! 783: case 4: ! 784: return \"st%M0 %1,%0\;st%M0 %O1,%O0\"; ! 785: case 5: ! 786: return \"get %3,$%0\;sts %1,0(%3)\;sts %O1,4(%3)\"; ! 787: default: ! 788: return output_fpop (SET, operands[0], operands[1], 0, insn); ! 789: } ! 790: }" ! 791: [(set_attr "type" "address,multi,multi,multi,multi,multi,fp") ! 792: (set_attr "length" "2,4,*,*,*,*,*")]) ! 793: ! 794: ;; Split all the above cases that involve multiple insns and no floating-point ! 795: ;; data block. If before reload, we can make a SCRATCH. Otherwise, use ! 796: ;; register 15. ! 797: ! 798: (define_split ! 799: [(set (match_operand:DF 0 "register_operand" "") ! 800: (match_operand:DF 1 "symbolic_memory_operand" "")) ! 801: (clobber (reg:SI 0)) ! 802: (clobber (reg:SI 15))] ! 803: "GET_CODE (operands[0]) == REG && REGNO (operands[0]) < 16" ! 804: [(set (reg:SI 15) (match_dup 2)) ! 805: (set (match_dup 3) (match_dup 4)) ! 806: (set (match_dup 5) (match_dup 6))] ! 807: " ! 808: { operands[2] = XEXP (operands[1], 0); ! 809: operands[3] = operand_subword (operands[0], 0, 0, DFmode); ! 810: operands[4] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15)); ! 811: operands[5] = operand_subword (operands[0], 1, 0, DFmode); ! 812: operands[6] = gen_rtx (MEM, SImode, ! 813: gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15), ! 814: gen_rtx (CONST_INT, VOIDmode, 4))); ! 815: ! 816: if (operands[3] == 0 || operands[5] == 0) ! 817: FAIL; ! 818: }") ! 819: ! 820: (define_split ! 821: [(set (match_operand:DF 0 "symbolic_memory_operand" "") ! 822: (match_operand:DF 1 "register_operand" "")) ! 823: (clobber (reg:SI 0)) ! 824: (clobber (reg:SI 15))] ! 825: "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 16" ! 826: [(set (reg:SI 15) (match_dup 2)) ! 827: (set (match_dup 3) (match_dup 4)) ! 828: (set (match_dup 5) (match_dup 6))] ! 829: " ! 830: { operands[2] = XEXP (operands[0], 0); ! 831: operands[3] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15)); ! 832: operands[4] = operand_subword (operands[1], 0, 0, DFmode); ! 833: operands[5] = gen_rtx (MEM, SImode, ! 834: gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15), ! 835: gen_rtx (CONST_INT, VOIDmode, 4))); ! 836: operands[6] = operand_subword (operands[1], 1, 0, DFmode); ! 837: ! 838: if (operands[4] == 0 || operands[6] == 0) ! 839: FAIL; ! 840: }") ! 841: ! 842: ;; If the output is a register and the input is memory, we have to be careful ! 843: ;; and see which word needs to be loaded first. We also cannot to the ! 844: ;; split if the input is a constant because it would result in invalid ! 845: ;; insns. When the output is a MEM, we must put a CLOBBER on each of the ! 846: ;; resulting insn, when it is not a MEM, we must not. ! 847: (define_split ! 848: [(set (match_operand:DF 0 "memory_operand" "") ! 849: (match_operand:DF 1 "register_operand" "")) ! 850: (clobber (reg:SI 0)) ! 851: (clobber (reg:SI 15))] ! 852: "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 15" ! 853: [(parallel [(set (match_dup 2) (match_dup 3)) ! 854: (clobber (match_dup 6))]) ! 855: (parallel [(set (match_dup 4) (match_dup 5)) ! 856: (clobber (match_dup 7))])] ! 857: " ! 858: { operands[2] = operand_subword (operands[0], 0, 0, DFmode); ! 859: operands[3] = operand_subword (operands[1], 0, 0, DFmode); ! 860: operands[4] = operand_subword (operands[0], 1, 0, DFmode); ! 861: operands[5] = operand_subword (operands[1], 1, 0, DFmode); ! 862: ! 863: if (operands[2] == 0 || operands[3] == 0 ! 864: || operands[4] == 0 || operands[5] == 0) ! 865: FAIL; ! 866: ! 867: if (reload_completed) ! 868: operands[6] = operands[7] = gen_rtx (REG, SImode, 15); ! 869: else ! 870: { ! 871: operands[6] = gen_rtx (SCRATCH, SImode); ! 872: operands[7] = gen_rtx (SCRATCH, SImode); ! 873: } ! 874: }") ! 875: ! 876: (define_split ! 877: [(set (match_operand:DF 0 "nonmemory_operand" "") ! 878: (match_operand:DF 1 "general_operand" "")) ! 879: (clobber (reg:SI 0)) ! 880: (clobber (reg:SI 15))] ! 881: "! symbolic_memory_operand (operands[1], DFmode) ! 882: && GET_CODE (operands[1]) != CONST_DOUBLE ! 883: && (GET_CODE (operands[0]) != REG || REGNO (operands[0]) < 15) ! 884: && (GET_CODE (operands[1]) != REG || REGNO (operands[1]) < 15) ! 885: && (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG) ! 886: && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG ! 887: && ! reload_completed ! 888: && reg_overlap_mentioned_p (operands[0], operands[1]))" ! 889: [(set (match_dup 2) (match_dup 3)) ! 890: (set (match_dup 4) (match_dup 5))] ! 891: " ! 892: { if (GET_CODE (operands[0]) != REG ! 893: || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, ! 894: operands[1], 0)) ! 895: { ! 896: operands[2] = operand_subword (operands[0], 0, 0, DFmode); ! 897: operands[3] = operand_subword (operands[1], 0, 0, DFmode); ! 898: operands[4] = operand_subword (operands[0], 1, 0, DFmode); ! 899: operands[5] = operand_subword (operands[1], 1, 0, DFmode); ! 900: } ! 901: else ! 902: { ! 903: operands[2] = operand_subword (operands[0], 1, 0, DFmode); ! 904: operands[3] = operand_subword (operands[1], 1, 0, DFmode); ! 905: operands[4] = operand_subword (operands[0], 0, 0, DFmode); ! 906: operands[5] = operand_subword (operands[1], 0, 0, DFmode); ! 907: } ! 908: ! 909: if (operands[2] == 0 || operands[3] == 0 ! 910: || operands[4] == 0 || operands[5] == 0) ! 911: FAIL; ! 912: }") ! 913: ! 914: ;; Conversions from one integer mode to another. ! 915: ;; It is possible sometimes to sign- or zero-extend while fetching from memory. ! 916: ;; ! 917: ;; First, sign-extensions: ! 918: (define_expand "extendhisi2" ! 919: [(set (match_operand:SI 0 "register_operand" "") ! 920: (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] ! 921: "" ! 922: "") ! 923: ! 924: (define_insn "" ! 925: [(set (match_operand:SI 0 "register_operand" "=b") ! 926: (sign_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))] ! 927: "" ! 928: "loadha %0,%1" ! 929: [(set_attr "type" "load")]) ! 930: ! 931: (define_insn "" ! 932: [(set (match_operand:SI 0 "register_operand" "=r,r,b") ! 933: (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))] ! 934: "" ! 935: "@ ! 936: exts %0,%1 ! 937: lha%M1 %0,%1 ! 938: loadha %0,%1" ! 939: [(set_attr "type" "arith,load,load") ! 940: (set_attr "length" "2,*,*")]) ! 941: ! 942: (define_expand "extendqisi2" ! 943: [(set (match_dup 2) ! 944: (ashift:SI (match_operand:QI 1 "register_operand" "") ! 945: (const_int 24))) ! 946: (set (match_operand:SI 0 "register_operand" "") ! 947: (ashiftrt:SI (match_dup 2) ! 948: (const_int 24)))] ! 949: "" ! 950: " ! 951: { operands[1] = gen_lowpart (SImode, operands[1]); ! 952: operands[2] = gen_reg_rtx (SImode); }") ! 953: ! 954: (define_expand "extendqihi2" ! 955: [(set (match_dup 2) ! 956: (ashift:SI (match_operand:QI 1 "register_operand" "") ! 957: (const_int 24))) ! 958: (set (match_operand:HI 0 "register_operand" "") ! 959: (ashiftrt:SI (match_dup 2) ! 960: (const_int 24)))] ! 961: "" ! 962: " ! 963: { operands[0] = gen_lowpart (SImode, operands[0]); ! 964: operands[1] = gen_lowpart (SImode, operands[1]); ! 965: operands[2] = gen_reg_rtx (SImode); }") ! 966: ! 967: ;; Define peepholes to eliminate an instruction when we are doing a sign ! 968: ;; extension but cannot clobber the input. ! 969: ;; ! 970: ;; In this case we will shift left 24 bits, but need a copy first. The shift ! 971: ;; can be replaced by a "mc03" instruction, but this can only be done if ! 972: ;; followed by the right shift of 24 or more bits. ! 973: (define_peephole ! 974: [(set (match_operand:SI 0 "register_operand" "") ! 975: (subreg:SI (match_operand:QI 1 "register_operand" "") 0)) ! 976: (set (match_dup 0) ! 977: (ashift:SI (match_dup 0) ! 978: (const_int 24))) ! 979: (set (match_dup 0) ! 980: (ashiftrt:SI (match_dup 0) ! 981: (match_operand:SI 2 "const_int_operand" "")))] ! 982: "INTVAL (operands[2]) >= 24" ! 983: "mc03 %0,%1\;sari16 %0,%S2" ! 984: [(set_attr "type" "multi") ! 985: (set_attr "length" "4") ! 986: (set_attr "cc" "sets")]) ! 987: ! 988: ;; Now zero extensions: ! 989: (define_expand "zero_extendhisi2" ! 990: [(set (match_operand:SI 0 "register_operand" "") ! 991: (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] ! 992: "" ! 993: "") ! 994: ! 995: (define_insn "" ! 996: [(set (match_operand:SI 0 "register_operand" "=b") ! 997: (zero_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))] ! 998: "" ! 999: "loadh %0,%1" ! 1000: [(set_attr "type" "load")]) ! 1001: ! 1002: (define_insn "" ! 1003: [(set (match_operand:SI 0 "register_operand" "=r,r,b") ! 1004: (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))] ! 1005: "" ! 1006: "@ ! 1007: nilz %0,%1,65535 ! 1008: lh%N1 %0,%1 ! 1009: loadh %0,%1" ! 1010: [(set_attr "type" "arith,loadz,load")]) ! 1011: ! 1012: (define_expand "zero_extendqisi2" ! 1013: [(set (match_operand:SI 0 "register_operand" "") ! 1014: (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] ! 1015: "" ! 1016: "") ! 1017: ! 1018: (define_insn "" ! 1019: [(set (match_operand:SI 0 "register_operand" "=b") ! 1020: (zero_extend:SI (match_operand:QI 1 "symbolic_memory_operand" "m")))] ! 1021: "" ! 1022: "loadc %0,%1" ! 1023: [(set_attr "type" "load")]) ! 1024: ! 1025: (define_insn "" ! 1026: [(set (match_operand:SI 0 "register_operand" "=r,r,b") ! 1027: (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))] ! 1028: "" ! 1029: "@ ! 1030: nilz %0,%1,255 ! 1031: lc%M1 %0,%1 ! 1032: loadc %0,%1" ! 1033: [(set_attr "type" "arith,load,load")]) ! 1034: ! 1035: (define_expand "zero_extendqihi2" ! 1036: [(set (match_operand:HI 0 "register_operand" "") ! 1037: (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] ! 1038: "" ! 1039: "") ! 1040: ! 1041: (define_insn "" ! 1042: [(set (match_operand:HI 0 "register_operand" "=b") ! 1043: (zero_extend:HI (match_operand:QI 1 "symbolic_memory_operand" "m")))] ! 1044: "" ! 1045: "loadc %0,%1" ! 1046: [(set_attr "type" "load")]) ! 1047: ! 1048: (define_insn "" ! 1049: [(set (match_operand:HI 0 "register_operand" "=r,r,b") ! 1050: (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))] ! 1051: "" ! 1052: "@ ! 1053: nilz %0,%1,255 ! 1054: lc%M1 %0,%1 ! 1055: loadc %0,%1" ! 1056: [(set_attr "type" "arith,load,load")]) ! 1057: ! 1058: ;; Various extract and insertion operations. ! 1059: (define_expand "extzv" ! 1060: [(set (match_operand:SI 0 "register_operand" "") ! 1061: (zero_extract:SI (match_operand:SI 1 "register_operand" "") ! 1062: (match_operand:SI 2 "const_int_operand" "") ! 1063: (match_operand:SI 3 "const_int_operand" "")))] ! 1064: "" ! 1065: " ! 1066: { ! 1067: if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8) ! 1068: FAIL; ! 1069: ! 1070: if (GET_CODE (operands[3]) != CONST_INT) ! 1071: FAIL; ! 1072: ! 1073: if (INTVAL (operands[3]) != 0 && INTVAL (operands[3]) != 8 ! 1074: && INTVAL (operands[3]) != 16 && INTVAL (operands[3]) != 24) ! 1075: FAIL; ! 1076: }") ! 1077: ! 1078: (define_insn "" ! 1079: [(set (match_operand:SI 0 "register_operand" "=&r") ! 1080: (zero_extract:SI (match_operand:SI 1 "register_operand" "r") ! 1081: (const_int 8) ! 1082: (match_operand:SI 2 "const_int_operand" "n")))] ! 1083: "(INTVAL (operands[2]) & 7) == 0" ! 1084: "lis %0,0\;mc3%B2 %0,%1" ! 1085: [(set_attr "type" "multi") ! 1086: (set_attr "cc" "change0")]) ! 1087: ! 1088: (define_split ! 1089: [(set (match_operand:SI 0 "register_operand" "=&r") ! 1090: (zero_extract:SI (match_operand:SI 1 "register_operand" "r") ! 1091: (const_int 8) ! 1092: (match_operand:SI 2 "const_int_operand" "n")))] ! 1093: "(INTVAL (operands[2]) & 7) == 0" ! 1094: [(set (match_dup 0) (const_int 0)) ! 1095: (set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 24)) ! 1096: (zero_extract:SI (match_dup 1) (const_int 8) (match_dup 2)))] ! 1097: "") ! 1098: ! 1099: (define_insn "" ! 1100: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") ! 1101: (const_int 8) ! 1102: (const_int 24)) ! 1103: (zero_extract:SI (match_operand:SI 1 "register_operand" "r") ! 1104: (const_int 8) ! 1105: (match_operand:SI 2 "const_int_operand" "n")))] ! 1106: "(INTVAL (operands[2]) & 7) == 0" ! 1107: "mc3%B2 %0,%1" ! 1108: [(set_attr "type" "address") ! 1109: (set_attr "length" "2")]) ! 1110: ! 1111: (define_expand "insv" ! 1112: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") ! 1113: (match_operand:SI 1 "const_int_operand" "") ! 1114: (match_operand:SI 2 "const_int_operand" "")) ! 1115: (match_operand:SI 3 "register_operand" ""))] ! 1116: "" ! 1117: " ! 1118: { ! 1119: if (GET_CODE (operands[2]) != CONST_INT) ! 1120: FAIL; ! 1121: ! 1122: if (GET_CODE (operands[1]) != CONST_INT) ! 1123: FAIL; ! 1124: ! 1125: if (INTVAL (operands[1]) == 1) ! 1126: { ! 1127: emit_insn (gen_bit_insv (operands[0], operands[1], operands[2], ! 1128: operands[3])); ! 1129: DONE; ! 1130: } ! 1131: else if (INTVAL (operands[1]) == 8 ! 1132: && (INTVAL (operands[2]) % 8 == 0)) ! 1133: ; /* Accept aligned byte-wide field. */ ! 1134: else ! 1135: FAIL; ! 1136: }") ! 1137: ! 1138: ;; For a single-bit insert, it is better to explicitly generate references ! 1139: ;; to the T bit. We will call the T bit "CC0" because it can be clobbered ! 1140: ;; by some CC0 sets (single-bit tests). ! 1141: ! 1142: (define_expand "bit_insv" ! 1143: [(set (cc0) ! 1144: (zero_extract:SI (match_operand:SI 3 "register_operand" "") ! 1145: (const_int 1) ! 1146: (const_int 31))) ! 1147: (parallel [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") ! 1148: (match_operand:SI 1 "const_int_operand" "") ! 1149: (match_operand:SI 2 "const_int_operand" "")) ! 1150: (ne (cc0) (const_int 0))) ! 1151: (clobber (match_scratch:SI 4 ""))])] ! 1152: "" ! 1153: "") ! 1154: ! 1155: (define_insn "" ! 1156: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") ! 1157: (const_int 8) ! 1158: (match_operand:SI 1 "const_int_operand" "n")) ! 1159: (match_operand:SI 2 "register_operand" "r"))] ! 1160: "(INTVAL (operands[1]) & 7) == 0" ! 1161: "mc%B1%.3 %0,%2" ! 1162: [(set_attr "type" "address") ! 1163: (set_attr "length" "2")]) ! 1164: ! 1165: ;; This pattern cannot have any input reloads since if references CC0. ! 1166: ;; So we have to add code to support memory, which is the only other ! 1167: ;; thing that a "register_operand" can become. There is still a problem ! 1168: ;; if the address isn't valid and *it* needs a reload, but there is no ! 1169: ;; way to solve that problem, so let's hope it never happens. ! 1170: ! 1171: (define_insn "" ! 1172: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,m") ! 1173: (const_int 1) ! 1174: (match_operand:SI 1 "const_int_operand" "n,m")) ! 1175: (ne (cc0) (const_int 0))) ! 1176: (clobber (match_scratch:SI 2 "=X,b"))] ! 1177: "" ! 1178: "@ ! 1179: mftbi%t1 %0,%S1 ! 1180: l%M0 %2,%0\;mftb%t1 %2,%S1\;st%M0 %2,%0" ! 1181: [(set_attr "type" "*,multi") ! 1182: (set_attr "cc" "none,none") ! 1183: (set_attr "length" "2,10")]) ! 1184: ! 1185: ;; Arithmetic instructions. First, add and subtract. ! 1186: ;; ! 1187: ;; It may be that the second input is either large or small enough that ! 1188: ;; the operation cannot be done in a single insn. In that case, emit two. ! 1189: (define_expand "addsi3" ! 1190: [(set (match_operand:SI 0 "register_operand" "") ! 1191: (plus:SI (match_operand:SI 1 "register_operand" "") ! 1192: (match_operand:SI 2 "nonmemory_operand" "")))] ! 1193: "" ! 1194: " ! 1195: { ! 1196: if (GET_CODE (operands[2]) == CONST_INT ! 1197: && (unsigned) (INTVAL (operands[2]) + 0x8000) >= 0x10000 ! 1198: && (INTVAL (operands[2]) & 0xffff) != 0) ! 1199: { ! 1200: int low = INTVAL (operands[2]) & 0xffff; ! 1201: int high = (unsigned) INTVAL (operands[2]) >> 16; ! 1202: ! 1203: if (low & 0x8000) ! 1204: high++, low |= 0xffff0000; ! 1205: ! 1206: emit_insn (gen_addsi3 (operands[0], operands[1], ! 1207: gen_rtx (CONST_INT, VOIDmode, high << 16))); ! 1208: operands[1] = operands[0]; ! 1209: operands[2] = gen_rtx (CONST_INT, VOIDmode, low); ! 1210: } ! 1211: }") ! 1212: ! 1213: ;; Put the insn to add a symbolic constant to a register separately to ! 1214: ;; improve register allocation since it has different register requirements. ! 1215: (define_insn "" ! 1216: [(set (match_operand:SI 0 "register_operand" "=b") ! 1217: (plus:SI (match_operand:SI 1 "register_operand" "%b") ! 1218: (match_operand:SI 2 "romp_symbolic_operand" "s")))] ! 1219: "" ! 1220: "get %0,$%2(%1)" ! 1221: [(set_attr "type" "address") ! 1222: (set_attr "length" "8")]) ! 1223: ! 1224: (define_insn "" ! 1225: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,b") ! 1226: (plus:SI (match_operand:SI 1 "reg_or_add_operand" "%0,0,r,b,0,r,b") ! 1227: (match_operand:SI 2 "reg_or_add_operand" "I,J,K,M,r,b,s")))] ! 1228: "register_operand (operands[1], SImode) ! 1229: || register_operand (operands[2], SImode)" ! 1230: "@ ! 1231: ais %0,%2 ! 1232: sis %0,%n2 ! 1233: ail %0,%1,%2 ! 1234: cau %0,%H2(%1) ! 1235: a %0,%2 ! 1236: cas %0,%1,%2 ! 1237: get %0,$%2(%1)" ! 1238: [(set_attr "type" "arith,arith,arith,address,arith,address,misc") ! 1239: (set_attr "length" "2,2,4,4,2,2,8")]) ! 1240: ! 1241: ;; Now subtract. ! 1242: ;; ! 1243: ;; 1. If third operand is constant integer, convert it to add of the negative ! 1244: ;; of that integer. ! 1245: ;; 2. If the second operand is not a valid constant integer, force it into a ! 1246: ;; register. ! 1247: (define_expand "subsi3" ! 1248: [(set (match_operand:SI 0 "register_operand" "") ! 1249: (minus:SI (match_operand:SI 1 "reg_or_any_cint_operand" "") ! 1250: (match_operand:SI 2 "reg_or_any_cint_operand" "")))] ! 1251: "" ! 1252: " ! 1253: { ! 1254: if (GET_CODE (operands [2]) == CONST_INT) ! 1255: { ! 1256: emit_insn (gen_addsi3 (operands[0], operands[1], ! 1257: gen_rtx (CONST_INT, ! 1258: VOIDmode, - INTVAL (operands[2])))); ! 1259: DONE; ! 1260: } ! 1261: else ! 1262: operands[2] = force_reg (SImode, operands[2]); ! 1263: ! 1264: if (GET_CODE (operands[1]) != CONST_INT ! 1265: || (unsigned) (INTVAL (operands[1]) + 0x8000) >= 0x10000) ! 1266: operands[1] = force_reg (SImode, operands[1]); ! 1267: }") ! 1268: ! 1269: (define_insn "" ! 1270: [(set (match_operand:SI 0 "register_operand" "=r,r,r") ! 1271: (minus:SI (match_operand:SI 1 "reg_or_D_operand" "K,0,r") ! 1272: (match_operand:SI 2 "register_operand" "r,r,0")))] ! 1273: "" ! 1274: "@ ! 1275: sfi %0,%2,%1 ! 1276: s %0,%2 ! 1277: sf %0,%1" ! 1278: [(set_attr "length" "4,2,2")]) ! 1279: ! 1280: ;; Multiply either calls a special RT routine or is done in-line, depending ! 1281: ;; on the value of a -m flag. ! 1282: ;; ! 1283: ;; First define the way we call the subroutine. ! 1284: (define_expand "mulsi3_subr" ! 1285: [(set (reg:SI 2) (match_operand:SI 1 "register_operand" "")) ! 1286: (set (reg:SI 3) (match_operand:SI 2 "register_operand" "")) ! 1287: (parallel [(set (reg:SI 2) (mult:SI (reg:SI 2) (reg:SI 3))) ! 1288: (clobber (reg:SI 0)) ! 1289: (clobber (reg:SI 15))]) ! 1290: (set (match_operand:SI 0 "register_operand" "") ! 1291: (reg:SI 2))] ! 1292: "" ! 1293: "") ! 1294: ! 1295: (define_expand "mulsi3" ! 1296: [(set (match_operand:SI 0 "register_operand" "") ! 1297: (mult:SI (match_operand:SI 1 "register_operand" "") ! 1298: (match_operand:SI 2 "register_operand" "")))] ! 1299: "" ! 1300: " ! 1301: { ! 1302: if (! TARGET_IN_LINE_MUL) ! 1303: { ! 1304: emit_insn (gen_mulsi3_subr (operands[0], operands[1], operands[2])); ! 1305: DONE; ! 1306: } ! 1307: }") ! 1308: ! 1309: ;; Define the patterns to match. ! 1310: ;; We would like to provide a delay slot for the insns that call internal ! 1311: ;; routines, but doing so is risky since reorg will think that the use of ! 1312: ;; r2 and r3 is completed in the insn needing the delay slot. Also, it ! 1313: ;; won't know that the cc will be clobbered. So take the safe approach ! 1314: ;; and don't give them delay slots. ! 1315: (define_insn "" ! 1316: [(set (reg:SI 2) ! 1317: (mult:SI (reg:SI 2) (reg:SI 3))) ! 1318: (clobber (reg:SI 0)) ! 1319: (clobber (reg:SI 15))] ! 1320: "! TARGET_IN_LINE_MUL" ! 1321: "bali%# r15,lmul$$" ! 1322: [(set_attr "type" "misc") ! 1323: (set_attr "in_delay_slot" "no")]) ! 1324: ! 1325: (define_insn "" ! 1326: [(set (match_operand:SI 0 "register_operand" "=&r") ! 1327: (mult:SI (match_operand:SI 1 "register_operand" "%r") ! 1328: (match_operand:SI 2 "register_operand" "r")))] ! 1329: "TARGET_IN_LINE_MUL" ! 1330: "* ! 1331: { return output_in_line_mul (); }" ! 1332: [(set_attr "length" "38") ! 1333: (set_attr "type" "multi")]) ! 1334: ! 1335: ;; Handle divide and modulus. The same function returns both values, ! 1336: ;; so use divmodsi4. This divides arg 1 by arg 2 with quotient to go ! 1337: ;; into arg 0 and remainder in arg 3. ! 1338: ;; ! 1339: ;; We want to put REG_EQUAL notes for the two outputs. So we need a ! 1340: ;; function to do everything else. ! 1341: (define_expand "divmodsi4_doit" ! 1342: [(set (reg:SI 2) ! 1343: (match_operand:SI 0 "register_operand" "")) ! 1344: (set (reg:SI 3) ! 1345: (match_operand:SI 1 "register_operand" "")) ! 1346: (parallel [(set (reg:SI 2) (div:SI (reg:SI 2) (reg:SI 3))) ! 1347: (set (reg:SI 3) (mod:SI (reg:SI 2) (reg:SI 3))) ! 1348: (clobber (reg:SI 0)) ! 1349: (clobber (reg:SI 15))])] ! 1350: "" ! 1351: "") ! 1352: ! 1353: (define_expand "divmodsi4" ! 1354: [(parallel [(set (match_operand:SI 0 "register_operand" "") ! 1355: (div:SI (match_operand:SI 1 "register_operand" "") ! 1356: (match_operand:SI 2 "register_operand" ""))) ! 1357: (set (match_operand:SI 3 "register_operand" "") ! 1358: (mod:SI (match_dup 1) (match_dup 2)))])] ! 1359: "" ! 1360: " ! 1361: { ! 1362: rtx insn; ! 1363: ! 1364: emit_insn (gen_divmodsi4_doit (operands[1], operands[2])); ! 1365: insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2)); ! 1366: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, ! 1367: gen_rtx (DIV, SImode, operands[1], ! 1368: operands[2]), ! 1369: REG_NOTES (insn)); ! 1370: insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3)); ! 1371: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, ! 1372: gen_rtx (MOD, SImode, operands[1], ! 1373: operands[2]), ! 1374: REG_NOTES (insn)); ! 1375: DONE; ! 1376: }") ! 1377: ! 1378: (define_insn "" ! 1379: [(set (reg:SI 2) ! 1380: (div:SI (reg:SI 2) (reg:SI 3))) ! 1381: (set (reg:SI 3) ! 1382: (mod:SI (reg:SI 2) (reg:SI 3))) ! 1383: (clobber (reg:SI 0)) ! 1384: (clobber (reg:SI 15))] ! 1385: "" ! 1386: "bali%# r15,ldiv$$" ! 1387: [(set_attr "type" "misc") ! 1388: (set_attr "in_delay_slot" "no")]) ! 1389: ! 1390: ;; Similarly for unsigned divide. ! 1391: (define_expand "udivmodsi4_doit" ! 1392: [(set (reg:SI 2) ! 1393: (match_operand:SI 0 "register_operand" "")) ! 1394: (set (reg:SI 3) ! 1395: (match_operand:SI 1 "register_operand" "")) ! 1396: (parallel [(set (reg:SI 2) (udiv:SI (reg:SI 2) (reg:SI 3))) ! 1397: (set (reg:SI 3) (umod:SI (reg:SI 2) (reg:SI 3))) ! 1398: (clobber (reg:SI 0)) ! 1399: (clobber (reg:SI 15))])] ! 1400: "" ! 1401: "") ! 1402: ! 1403: (define_expand "udivmodsi4" ! 1404: [(parallel [(set (match_operand:SI 0 "register_operand" "") ! 1405: (udiv:SI (match_operand:SI 1 "register_operand" "") ! 1406: (match_operand:SI 2 "register_operand" ""))) ! 1407: (set (match_operand:SI 3 "register_operand" "") ! 1408: (umod:SI (match_dup 1) (match_dup 2)))])] ! 1409: "" ! 1410: " ! 1411: { ! 1412: rtx insn; ! 1413: ! 1414: emit_insn (gen_udivmodsi4_doit (operands[1], operands[2])); ! 1415: insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2)); ! 1416: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, ! 1417: gen_rtx (UDIV, SImode, operands[1], ! 1418: operands[2]), ! 1419: REG_NOTES (insn)); ! 1420: insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3)); ! 1421: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, ! 1422: gen_rtx (UMOD, SImode, operands[1], ! 1423: operands[2]), ! 1424: REG_NOTES (insn)); ! 1425: DONE; ! 1426: }") ! 1427: ! 1428: (define_insn "" ! 1429: [(set (reg:SI 2) ! 1430: (udiv:SI (reg:SI 2) (reg:SI 3))) ! 1431: (set (reg:SI 3) ! 1432: (umod:SI (reg:SI 2) (reg:SI 3))) ! 1433: (clobber (reg:SI 0)) ! 1434: (clobber (reg:SI 15))] ! 1435: "" ! 1436: "bali%# r15,uldiv$$" ! 1437: [(set_attr "type" "misc") ! 1438: (set_attr "in_delay_slot" "no")]) ! 1439: ! 1440: ;; Define DImode arithmetic operations. ! 1441: ;; ! 1442: ;; It is possible to do certain adds and subtracts with constants in a single ! 1443: ;; insn, but it doesn't seem worth the trouble. ! 1444: ;; ! 1445: ;; Don't use DEFINE_SPLIT on these because the dependency on CC can't be ! 1446: ;; easily tracked in that case! ! 1447: (define_insn "adddi3" ! 1448: [(set (match_operand:DI 0 "register_operand" "=r") ! 1449: (plus:DI (match_operand:DI 1 "register_operand" "%0") ! 1450: (match_operand:DI 2 "register_operand" "r")))] ! 1451: "" ! 1452: "a %O0,%O2\;ae %0,%2" ! 1453: [(set_attr "type" "multi")]) ! 1454: ! 1455: (define_insn "subdi3" ! 1456: [(set (match_operand:DI 0 "register_operand" "=r") ! 1457: (minus:DI (match_operand:DI 1 "register_operand" "0") ! 1458: (match_operand:DI 2 "register_operand" "r")))] ! 1459: "" ! 1460: "s %O0,%O2\;se %0,%2" ! 1461: [(set_attr "type" "multi")]) ! 1462: ! 1463: (define_insn "negdi2" ! 1464: [(set (match_operand:DI 0 "register_operand" "=r,&r") ! 1465: (neg:DI (match_operand:DI 1 "register_operand" "0,r")))] ! 1466: "" ! 1467: "twoc %O0,%O1\;onec %0,%1\;aei %0,%0,0" ! 1468: [(set_attr "type" "multi") ! 1469: (set_attr "length" "8")]) ! 1470: ! 1471: ;; Unary arithmetic operations. ! 1472: (define_insn "abssi2" ! 1473: [(set (match_operand:SI 0 "register_operand" "=r") ! 1474: (abs:SI (match_operand:SI 1 "register_operand" "r")))] ! 1475: "" ! 1476: "abs %0,%1" ! 1477: [(set_attr "length" "2")]) ! 1478: ! 1479: (define_insn "negsi2" ! 1480: [(set (match_operand:SI 0 "register_operand" "=r") ! 1481: (neg:SI (match_operand:SI 1 "register_operand" "r")))] ! 1482: "" ! 1483: "twoc %0,%1" ! 1484: [(set_attr "length" "2")]) ! 1485: ! 1486: (define_insn "one_cmplsi2" ! 1487: [(set (match_operand:SI 0 "register_operand" "=r") ! 1488: (not:SI (match_operand:SI 1 "register_operand" "r")))] ! 1489: "" ! 1490: "onec %0,%1" ! 1491: [(set_attr "length" "2")]) ! 1492: ! 1493: ! 1494: ;; Logical insns: AND, IOR, and XOR ! 1495: ;; ! 1496: ;; If the operation is being performed on a 32-bit constant such that ! 1497: ;; it cannot be done in one insn, do it in two. We may lose a bit on ! 1498: ;; CSE in pathological cases, but it seems better doing it this way. ! 1499: (define_expand "andsi3" ! 1500: [(set (match_operand:SI 0 "register_operand" "") ! 1501: (and:SI (match_operand:SI 1 "register_operand" "") ! 1502: (match_operand:SI 2 "reg_or_any_cint_operand" "")))] ! 1503: "" ! 1504: " ! 1505: { ! 1506: if (GET_CODE (operands[2]) == CONST_INT) ! 1507: { ! 1508: int top = (unsigned) INTVAL (operands[2]) >> 16; ! 1509: int bottom = INTVAL (operands[2]) & 0xffff; ! 1510: ! 1511: if (top != 0 && top != 0xffff && bottom != 0 && bottom != 0xffff) ! 1512: { ! 1513: emit_insn (gen_andsi3 (operands[0], operands[1], ! 1514: gen_rtx (CONST_INT, VOIDmode, ! 1515: (top << 16) | 0xffff))); ! 1516: operands[1] = operands[0]; ! 1517: operands[2] = gen_rtx (CONST_INT, VOIDmode, 0xffff0000 | bottom); ! 1518: } ! 1519: } ! 1520: }"); ! 1521: ! 1522: (define_insn "" ! 1523: [(set (match_operand:SI 0 "register_operand" "=r,r,r") ! 1524: (and:SI (match_operand:SI 1 "reg_or_and_operand" "%0,r,0") ! 1525: (match_operand:SI 2 "reg_or_and_operand" "P,LMO,r")))] ! 1526: "register_operand (operands[1], SImode) ! 1527: || register_operand (operands[2], SImode)" ! 1528: "@ ! 1529: clrb%k2 %0,%b2 ! 1530: ni%z2 %0,%1,%Z2 ! 1531: n %0,%2" ! 1532: [(set_attr "length" "2,4,2")]) ! 1533: ! 1534: ;; logical OR (IOR) ! 1535: (define_expand "iorsi3" ! 1536: [(set (match_operand:SI 0 "register_operand" "") ! 1537: (ior:SI (match_operand:SI 1 "register_operand" "") ! 1538: (match_operand:SI 2 "reg_or_any_cint_operand" "")))] ! 1539: "" ! 1540: " ! 1541: { ! 1542: if (GET_CODE (operands[2]) == CONST_INT) ! 1543: { ! 1544: int top = (unsigned) INTVAL (operands[2]) >> 16; ! 1545: int bottom = INTVAL (operands[2]) & 0xffff; ! 1546: ! 1547: if (top != 0 && bottom != 0) ! 1548: { ! 1549: emit_insn (gen_iorsi3 (operands[0], operands[1], ! 1550: gen_rtx (CONST_INT, VOIDmode, (top << 16)))); ! 1551: operands[1] = operands[0]; ! 1552: operands[2] = gen_rtx (CONST_INT, VOIDmode, bottom); ! 1553: } ! 1554: } ! 1555: }"); ! 1556: ! 1557: (define_insn "" ! 1558: [(set (match_operand:SI 0 "register_operand" "=r,r,r") ! 1559: (ior:SI (match_operand:SI 1 "reg_or_cint_operand" "%0,r,0") ! 1560: (match_operand:SI 2 "reg_or_cint_operand" "N,LM,r")))] ! 1561: "register_operand (operands[1], SImode) ! 1562: || register_operand (operands[2], SImode)" ! 1563: "@ ! 1564: setb%h2 %0,%b2 ! 1565: oi%h2 %0,%1,%H2 ! 1566: o %0,%2" ! 1567: [(set_attr "length" "2,4,2")]) ! 1568: ! 1569: ;; exclusive-or (XOR) ! 1570: (define_expand "xorsi3" ! 1571: [(set (match_operand:SI 0 "register_operand" "") ! 1572: (xor:SI (match_operand:SI 1 "register_operand" "") ! 1573: (match_operand:SI 2 "reg_or_any_cint_operand" "")))] ! 1574: "" ! 1575: " ! 1576: { ! 1577: if (GET_CODE (operands[2]) == CONST_INT) ! 1578: { ! 1579: int top = (unsigned) INTVAL (operands[2]) >> 16; ! 1580: int bottom = INTVAL (operands[2]) & 0xffff; ! 1581: ! 1582: if (top == 0xffff && bottom == 0xffff) ! 1583: { ! 1584: emit_insn (gen_one_cmplsi2 (operands[0], operands[1])); ! 1585: DONE; ! 1586: } ! 1587: else if (top != 0 && bottom != 0) ! 1588: { ! 1589: emit_insn (gen_xorsi3 (operands[0], operands[1], ! 1590: gen_rtx (CONST_INT, VOIDmode, (top << 16)))); ! 1591: operands[1] = operands[0]; ! 1592: operands[2] = gen_rtx (CONST_INT, VOIDmode, bottom); ! 1593: } ! 1594: } ! 1595: }"); ! 1596: ! 1597: (define_insn "" ! 1598: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 1599: (xor:SI (match_operand:SI 1 "reg_or_cint_operand" "%r,0") ! 1600: (match_operand:SI 2 "reg_or_cint_operand" "LM,r")))] ! 1601: "register_operand (operands[1], SImode) ! 1602: || register_operand (operands[2], SImode)" ! 1603: "@ ! 1604: xi%h2 %0,%1,%H2 ! 1605: x %0,%2" ! 1606: [(set_attr "length" "4,2")]) ! 1607: ! 1608: ;; Various shift insns ! 1609: (define_insn "ashrsi3" ! 1610: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 1611: (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") ! 1612: (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] ! 1613: "" ! 1614: "@ ! 1615: sar %0,%2 ! 1616: sari%s2 %0,%S2" ! 1617: [(set_attr "length" "2")]) ! 1618: ! 1619: (define_insn "lshrsi3" ! 1620: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 1621: (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") ! 1622: (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] ! 1623: "" ! 1624: "@ ! 1625: sr %0,%2 ! 1626: sri%s2 %0,%S2" ! 1627: [(set_attr "length" "2")]) ! 1628: ! 1629: (define_insn "" ! 1630: [(set (match_operand:SI 0 "register_operand" "=r") ! 1631: (ashift:SI (match_operand:SI 1 "register_operand" "b") ! 1632: (const_int 1)))] ! 1633: "" ! 1634: "cas %0,%1,%1" ! 1635: [(set_attr "length" "2") ! 1636: (set_attr "type" "address")]) ! 1637: ! 1638: (define_insn "ashlsi3" ! 1639: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 1640: (ashift:SI (match_operand:SI 1 "register_operand" "0,0") ! 1641: (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] ! 1642: "" ! 1643: "@ ! 1644: sl %0,%2 ! 1645: sli%s2 %0,%S2" ! 1646: [(set_attr "length" "2")]) ! 1647: ! 1648: ;; Function call insns: ! 1649: ;; ! 1650: ;; On the ROMP, &fcn is actually a pointer to the data area, which is passed ! 1651: ;; to the function in r0. &.fcn is the actual starting address of the ! 1652: ;; function. Also, the word at &fcn contains &.fcn. ! 1653: ;; ! 1654: ;; For both functions that do and don't return values, there are two cases: ! 1655: ;; where the function's address is a constant, and where it isn't. ! 1656: ;; ! 1657: ;; Operand 1 (2 for `call_value') is the number of arguments and is not used. ! 1658: (define_expand "call" ! 1659: [(use (reg:SI 0)) ! 1660: (parallel [(call (mem:SI (match_operand:SI 0 "address_operand" "")) ! 1661: (match_operand 1 "" "")) ! 1662: (clobber (reg:SI 15))])] ! 1663: "" ! 1664: " ! 1665: { ! 1666: if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT) ! 1667: abort(); ! 1668: ! 1669: operands[0] = XEXP (operands[0], 0); ! 1670: if (GET_CODE (operands[0]) == SYMBOL_REF) ! 1671: { ! 1672: extern rtx get_symref (); ! 1673: char *real_fcnname = ! 1674: (char *) alloca (strlen (XSTR (operands[0], 0)) + 2); ! 1675: ! 1676: /* Copy the data area address to r0. */ ! 1677: emit_move_insn (gen_rtx (REG, SImode, 0), ! 1678: force_reg (SImode, operands[0])); ! 1679: strcpy (real_fcnname, \".\"); ! 1680: strcat (real_fcnname, XSTR (operands[0], 0)); ! 1681: operands[0] = get_symref (real_fcnname); ! 1682: } ! 1683: else ! 1684: { ! 1685: rtx data_access; ! 1686: ! 1687: emit_move_insn (gen_rtx (REG, SImode, 0), ! 1688: force_reg (SImode, operands[0])); ! 1689: data_access = gen_rtx (MEM, SImode, operands[0]); ! 1690: RTX_UNCHANGING_P (data_access) = 1; ! 1691: operands[0] = copy_to_reg (data_access); ! 1692: } ! 1693: }") ! 1694: ! 1695: (define_insn "" ! 1696: [(call (mem:SI (match_operand:SI 0 "register_operand" "b")) ! 1697: (match_operand 1 "" "g")) ! 1698: (clobber (reg:SI 15))] ! 1699: "" ! 1700: "balr%# r15,%0" ! 1701: [(set_attr "type" "call") ! 1702: (set_attr "length" "2")]) ! 1703: ! 1704: (define_insn "" ! 1705: [(call (mem:SI (match_operand:SI 0 "romp_symbolic_operand" "i")) ! 1706: (match_operand 1 "" "g")) ! 1707: (clobber (reg:SI 15))] ! 1708: "GET_CODE (operands[0]) == SYMBOL_REF" ! 1709: "bali%# r15,%0" ! 1710: [(set_attr "type" "call")]) ! 1711: ! 1712: ;; Call a function and return a value. ! 1713: (define_expand "call_value" ! 1714: [(use (reg:SI 0)) ! 1715: (parallel [(set (match_operand 0 "" "=fg") ! 1716: (call (mem:SI (match_operand:SI 1 "address_operand" "")) ! 1717: (match_operand 2 "" ""))) ! 1718: (clobber (reg:SI 15))])] ! 1719: "" ! 1720: " ! 1721: { ! 1722: if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT) ! 1723: abort(); ! 1724: ! 1725: operands[1] = XEXP (operands[1], 0); ! 1726: if (GET_CODE (operands[1]) == SYMBOL_REF) ! 1727: { ! 1728: extern rtx get_symref (); ! 1729: char *real_fcnname = ! 1730: (char *) alloca (strlen (XSTR (operands[1], 0)) + 2); ! 1731: ! 1732: /* Copy the data area address to r0. */ ! 1733: emit_move_insn (gen_rtx (REG, SImode, 0), ! 1734: force_reg (SImode, operands[1])); ! 1735: strcpy (real_fcnname, \".\"); ! 1736: strcat (real_fcnname, XSTR (operands[1], 0)); ! 1737: operands[1] = get_symref (real_fcnname); ! 1738: } ! 1739: else ! 1740: { ! 1741: rtx data_access; ! 1742: ! 1743: emit_move_insn (gen_rtx (REG, SImode, 0), ! 1744: force_reg (SImode, operands[1])); ! 1745: data_access = gen_rtx (MEM, SImode, operands[1]); ! 1746: RTX_UNCHANGING_P (data_access) = 1; ! 1747: operands[1] = copy_to_reg (data_access); ! 1748: } ! 1749: }") ! 1750: ! 1751: (define_insn "" ! 1752: [(set (match_operand 0 "" "=fg") ! 1753: (call (mem:SI (match_operand:SI 1 "register_operand" "b")) ! 1754: (match_operand 2 "" "g"))) ! 1755: (clobber (reg:SI 15))] ! 1756: "" ! 1757: "balr%# r15,%1" ! 1758: [(set_attr "length" "2") ! 1759: (set_attr "type" "call")]) ! 1760: ! 1761: (define_insn "" ! 1762: [(set (match_operand 0 "" "=fg") ! 1763: (call (mem:SI (match_operand:SI 1 "romp_symbolic_operand" "i")) ! 1764: (match_operand 2 "" "g"))) ! 1765: (clobber (reg:SI 15))] ! 1766: "GET_CODE (operands[1]) == SYMBOL_REF" ! 1767: "bali%# r15,%1" ! 1768: [(set_attr "type" "call")]) ! 1769: ! 1770: ;; Call subroutine returning any type. ! 1771: ! 1772: (define_expand "untyped_call" ! 1773: [(parallel [(call (match_operand 0 "" "") ! 1774: (const_int 0)) ! 1775: (match_operand 1 "" "") ! 1776: (match_operand 2 "" "")])] ! 1777: "" ! 1778: " ! 1779: { ! 1780: int i; ! 1781: ! 1782: emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); ! 1783: ! 1784: for (i = 0; i < XVECLEN (operands[2], 0); i++) ! 1785: { ! 1786: rtx set = XVECEXP (operands[2], 0, i); ! 1787: emit_move_insn (SET_DEST (set), SET_SRC (set)); ! 1788: } ! 1789: ! 1790: /* The optimizer does not know that the call sets the function value ! 1791: registers we stored in the result block. We avoid problems by ! 1792: claiming that all hard registers are used and clobbered at this ! 1793: point. */ ! 1794: emit_insn (gen_blockage ()); ! 1795: ! 1796: DONE; ! 1797: }") ! 1798: ! 1799: ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and ! 1800: ;; all of memory. This blocks insns from being moved across this point. ! 1801: ! 1802: (define_insn "blockage" ! 1803: [(unspec_volatile [(const_int 0)] 0)] ! 1804: "" ! 1805: "") ! 1806: ! 1807: ;; No operation insn. ! 1808: (define_insn "nop" ! 1809: [(const_int 0)] ! 1810: "" ! 1811: "nopr r0" ! 1812: [(set_attr "type" "address") ! 1813: (set_attr "length" "2") ! 1814: (set_attr "cc" "none")]) ! 1815: ! 1816: ;; Here are the floating-point operations. ! 1817: ;; ! 1818: ;; Start by providing DEFINE_EXPAND for each operation. ! 1819: ;; The insns will be handled with MATCH_OPERATOR; the methodology will be ! 1820: ;; discussed below. ! 1821: ! 1822: ;; First the conversion operations. ! 1823: ! 1824: (define_expand "truncdfsf2" ! 1825: [(parallel [(set (match_operand:SF 0 "general_operand" "") ! 1826: (float_truncate:SF (match_operand:DF 1 "general_operand" ""))) ! 1827: (clobber (reg:SI 0)) ! 1828: (clobber (reg:SI 15))])] ! 1829: "" ! 1830: "") ! 1831: ! 1832: (define_expand "extendsfdf2" ! 1833: [(parallel [(set (match_operand:DF 0 "general_operand" "") ! 1834: (float_extend:DF (match_operand:SF 1 "general_operand" ""))) ! 1835: (clobber (reg:SI 0)) ! 1836: (clobber (reg:SI 15))])] ! 1837: "" ! 1838: "") ! 1839: ! 1840: (define_expand "floatsisf2" ! 1841: [(parallel [(set (match_operand:SF 0 "general_operand" "") ! 1842: (float:SF (match_operand:SI 1 "general_operand" ""))) ! 1843: (clobber (reg:SI 0)) ! 1844: (clobber (reg:SI 15))])] ! 1845: "" ! 1846: "") ! 1847: ! 1848: (define_expand "floatsidf2" ! 1849: [(parallel [(set (match_operand:DF 0 "general_operand" "") ! 1850: (float:DF (match_operand:SI 1 "general_operand" ""))) ! 1851: (clobber (reg:SI 0)) ! 1852: (clobber (reg:SI 15))])] ! 1853: "" ! 1854: "") ! 1855: ! 1856: (define_expand "fix_truncsfsi2" ! 1857: [(parallel [(set (match_operand:SI 0 "general_operand" "") ! 1858: (fix:SI (match_operand:SF 1 "general_operand" ""))) ! 1859: (clobber (reg:SI 0)) ! 1860: (clobber (reg:SI 15))])] ! 1861: "" ! 1862: "") ! 1863: ! 1864: (define_expand "fix_truncdfsi2" ! 1865: [(parallel [(set (match_operand:SI 0 "general_operand" "") ! 1866: (fix:SI (match_operand:DF 1 "general_operand" ""))) ! 1867: (clobber (reg:SI 0)) ! 1868: (clobber (reg:SI 15))])] ! 1869: "" ! 1870: "") ! 1871: ! 1872: ;; Now the binary operations. ! 1873: ! 1874: (define_expand "addsf3" ! 1875: [(parallel [(set (match_operand:SF 0 "general_operand" "") ! 1876: (plus:SF (match_operand:SF 1 "general_operand" "") ! 1877: (match_operand:SF 2 "general_operand" ""))) ! 1878: (clobber (reg:SI 0)) ! 1879: (clobber (reg:SI 15))])] ! 1880: "" ! 1881: "") ! 1882: ! 1883: (define_expand "adddf3" ! 1884: [(parallel [(set (match_operand:DF 0 "general_operand" "") ! 1885: (plus:DF (match_operand:DF 1 "general_operand" "") ! 1886: (match_operand:DF 2 "general_operand" ""))) ! 1887: (clobber (reg:SI 0)) ! 1888: (clobber (reg:SI 15))])] ! 1889: "" ! 1890: "") ! 1891: ! 1892: (define_expand "subsf3" ! 1893: [(parallel [(set (match_operand:SF 0 "general_operand" "") ! 1894: (minus:SF (match_operand:SF 1 "general_operand" "") ! 1895: (match_operand:SF 2 "general_operand" ""))) ! 1896: (clobber (reg:SI 0)) ! 1897: (clobber (reg:SI 15))])] ! 1898: "" ! 1899: "") ! 1900: ! 1901: (define_expand "subdf3" ! 1902: [(parallel [(set (match_operand:DF 0 "general_operand" "") ! 1903: (minus:DF (match_operand:DF 1 "general_operand" "") ! 1904: (match_operand:DF 2 "general_operand" ""))) ! 1905: (clobber (reg:SI 0)) ! 1906: (clobber (reg:SI 15))])] ! 1907: "" ! 1908: "") ! 1909: ! 1910: (define_expand "mulsf3" ! 1911: [(parallel [(set (match_operand:SF 0 "general_operand" "") ! 1912: (mult:SF (match_operand:SF 1 "general_operand" "") ! 1913: (match_operand:SF 2 "general_operand" ""))) ! 1914: (clobber (reg:SI 0)) ! 1915: (clobber (reg:SI 15))])] ! 1916: "" ! 1917: "") ! 1918: ! 1919: (define_expand "muldf3" ! 1920: [(parallel [(set (match_operand:DF 0 "general_operand" "") ! 1921: (mult:DF (match_operand:DF 1 "general_operand" "") ! 1922: (match_operand:DF 2 "general_operand" ""))) ! 1923: (clobber (reg:SI 0)) ! 1924: (clobber (reg:SI 15))])] ! 1925: "" ! 1926: "") ! 1927: ! 1928: (define_expand "divsf3" ! 1929: [(parallel [(set (match_operand:SF 0 "general_operand" "") ! 1930: (div:SF (match_operand:SF 1 "general_operand" "") ! 1931: (match_operand:SF 2 "general_operand" ""))) ! 1932: (clobber (reg:SI 0)) ! 1933: (clobber (reg:SI 15))])] ! 1934: "" ! 1935: "") ! 1936: ! 1937: (define_expand "divdf3" ! 1938: [(parallel [(set (match_operand:DF 0 "general_operand" "") ! 1939: (div:DF (match_operand:DF 1 "general_operand" "") ! 1940: (match_operand:DF 2 "general_operand" ""))) ! 1941: (clobber (reg:SI 0)) ! 1942: (clobber (reg:SI 15))])] ! 1943: "" ! 1944: "") ! 1945: ! 1946: ;; Unary floating-point operations. ! 1947: ;; ! 1948: ;; Negations can be done without floating-point, since this is IEEE. ! 1949: ;; But we cannot do this if an operand is a hard FP register, since ! 1950: ;; the SUBREG we create would not be valid. ! 1951: (define_expand "negsf2" ! 1952: [(set (match_operand:SF 0 "register_operand" "") ! 1953: (neg:SF (match_operand:SF 1 "register_operand" "")))] ! 1954: "" ! 1955: " ! 1956: { ! 1957: if (! (GET_CODE (operands[0]) == REG ! 1958: && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER ! 1959: && FP_REGNO_P (REGNO (operands[0]))) ! 1960: && ! (GET_CODE (operands[1]) == REG ! 1961: && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER ! 1962: && FP_REGNO_P (REGNO (operands[1])))) ! 1963: { ! 1964: rtx result; ! 1965: rtx target = operand_subword (operands[0], 0, 1, SFmode); ! 1966: ! 1967: result = expand_binop (SImode, xor_optab, ! 1968: operand_subword_force (operands[1], 0, SFmode), ! 1969: gen_rtx (CONST_INT, VOIDmode, 0x80000000), ! 1970: target, 0, OPTAB_WIDEN); ! 1971: if (result == 0) ! 1972: abort (); ! 1973: ! 1974: if (result != target) ! 1975: emit_move_insn (result, target); ! 1976: ! 1977: /* Make a place for REG_EQUAL. */ ! 1978: emit_move_insn (operands[0], operands[0]); ! 1979: DONE; ! 1980: } ! 1981: }") ! 1982: ! 1983: (define_expand "negdf2" ! 1984: [(set (match_operand:DF 0 "register_operand" "") ! 1985: (neg:DF (match_operand:DF 1 "register_operand" "")))] ! 1986: "" ! 1987: " ! 1988: { ! 1989: if (! (GET_CODE (operands[0]) == REG ! 1990: && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER ! 1991: && FP_REGNO_P (REGNO (operands[0]))) ! 1992: && ! (GET_CODE (operands[1]) == REG ! 1993: && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER ! 1994: && FP_REGNO_P (REGNO (operands[1])))) ! 1995: { ! 1996: rtx result; ! 1997: rtx target = operand_subword (operands[0], 0, 1, DFmode); ! 1998: rtx insns; ! 1999: ! 2000: start_sequence (); ! 2001: result = expand_binop (SImode, xor_optab, ! 2002: operand_subword_force (operands[1], 0, DFmode), ! 2003: gen_rtx (CONST_INT, VOIDmode, 0x80000000), ! 2004: target, 0, OPTAB_WIDEN); ! 2005: if (result == 0) ! 2006: abort (); ! 2007: ! 2008: if (result != target) ! 2009: emit_move_insn (result, target); ! 2010: ! 2011: emit_move_insn (operand_subword (operands[0], 1, 1, DFmode), ! 2012: operand_subword_force (operands[1], 1, DFmode)); ! 2013: ! 2014: insns = get_insns (); ! 2015: end_sequence (); ! 2016: ! 2017: emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); ! 2018: DONE; ! 2019: } ! 2020: }") ! 2021: ! 2022: (define_expand "abssf2" ! 2023: [(parallel [(set (match_operand:SF 0 "general_operand" "") ! 2024: (abs:SF (match_operand:SF 1 "general_operand" ""))) ! 2025: (clobber (reg:SI 0)) ! 2026: (clobber (reg:SI 15))])] ! 2027: "" ! 2028: "") ! 2029: ! 2030: (define_expand "absdf2" ! 2031: [(parallel [(set (match_operand:DF 0 "general_operand" "") ! 2032: (abs:DF (match_operand:DF 1 "general_operand" ""))) ! 2033: (clobber (reg:SI 0)) ! 2034: (clobber (reg:SI 15))])] ! 2035: "" ! 2036: "") ! 2037: ! 2038: ;; Any floating-point operation can be either SFmode or DFmode, and each ! 2039: ;; operand (including the output) can be either a normal operand or a ! 2040: ;; conversion from a normal operand. ! 2041: ;; ! 2042: ;; We use MATCH_OPERATOR to match a floating-point binary or unary operator ! 2043: ;; and input and output conversions. So we need 2^N patterns for each type ! 2044: ;; of operation, where N is the number of operands, including the output. ! 2045: ;; There are thus a total of 14 patterns, 8 for binary operations, 4 for ! 2046: ;; unary operations and two for conversion/move operations (only one ! 2047: ;; operand can have a conversion for move operations). In addition, we have ! 2048: ;; to be careful that a floating-point reload register doesn't get allocated ! 2049: ;; for an integer. We take care of this for inputs with PREFERRED_RELOAD_CLASS ! 2050: ;; but need to have two different constraints for outputs. This means that ! 2051: ;; we have to duplicate each pattern where the output could be an integer. ! 2052: ;; This adds another 7 patterns, for a total of 21. ! 2053: ! 2054: ;; Start with conversion operations (moves are done above). ! 2055: ! 2056: (define_insn "" ! 2057: [(set (match_operand:SI 0 "general_operand" "=g") ! 2058: (match_operator 1 "float_conversion" ! 2059: [(match_operand 2 "general_operand" "frg")])) ! 2060: (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) ! 2061: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] ! 2062: "" ! 2063: "* ! 2064: { return output_fpop (SET, operands[0], operands[2], 0, insn); ! 2065: }" ! 2066: [(set_attr "type" "fp")]) ! 2067: ! 2068: (define_insn "" ! 2069: [(set (match_operand 0 "general_operand" "=frg") ! 2070: (match_operator 1 "float_conversion" ! 2071: [(match_operand 2 "general_operand" "frg")])) ! 2072: (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) ! 2073: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] ! 2074: "" ! 2075: "* ! 2076: { return output_fpop (SET, operands[0], operands[2], 0, insn); ! 2077: }" ! 2078: [(set_attr "type" "fp")]) ! 2079: ! 2080: ;; Next, binary floating-point operations. ! 2081: ! 2082: (define_insn "" ! 2083: [(set (match_operand 0 "general_operand" "=frg") ! 2084: (match_operator 1 "float_binary" ! 2085: [(match_operand 2 "general_operand" "frg") ! 2086: (match_operand 3 "general_operand" "frg")])) ! 2087: (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) ! 2088: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] ! 2089: "check_precision (GET_MODE (operands[1]), operands[2], operands[3])" ! 2090: "* ! 2091: { return output_fpop (GET_CODE (operands[1]), operands[0], ! 2092: operands[2], operands[3], insn); ! 2093: }" ! 2094: [(set_attr "type" "fp")]) ! 2095: ! 2096: (define_insn "" ! 2097: [(set (match_operand 0 "general_operand" "=frg") ! 2098: (match_operator 1 "float_binary" ! 2099: [(match_operand 2 "general_operand" "frg") ! 2100: (match_operator 3 "float_conversion" ! 2101: [(match_operand 4 "general_operand" "frg")])])) ! 2102: (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) ! 2103: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] ! 2104: "check_precision (GET_MODE (operands[1]), operands[2], operands[4])" ! 2105: "* ! 2106: { return output_fpop (GET_CODE (operands[1]), operands[0], ! 2107: operands[2], operands[4], insn); ! 2108: }" ! 2109: [(set_attr "type" "fp")]) ! 2110: ! 2111: (define_insn "" ! 2112: [(set (match_operand 0 "general_operand" "=frg") ! 2113: (match_operator 1 "float_binary" ! 2114: [(match_operator 2 "float_conversion" ! 2115: [(match_operand 3 "general_operand" "frg")]) ! 2116: (match_operand 4 "general_operand" "frg")])) ! 2117: (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) ! 2118: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] ! 2119: "check_precision (GET_MODE (operands[1]), operands[3], operands[4])" ! 2120: "* ! 2121: { return output_fpop (GET_CODE (operands[1]), operands[0], ! 2122: operands[3], operands[4], insn); ! 2123: }" ! 2124: [(set_attr "type" "fp")]) ! 2125: ! 2126: (define_insn "" ! 2127: [(set (match_operand 0 "general_operand" "=frg") ! 2128: (match_operator 1 "float_binary" ! 2129: [(match_operator 2 "float_conversion" ! 2130: [(match_operand 3 "general_operand" "frg")]) ! 2131: (match_operator 4 "float_conversion" ! 2132: [(match_operand 5 "general_operand" "frg")])])) ! 2133: (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) ! 2134: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] ! 2135: "check_precision (GET_MODE (operands[1]), operands[3], operands[5])" ! 2136: "* ! 2137: { return output_fpop (GET_CODE (operands[1]), operands[0], ! 2138: operands[3], operands[5], insn); ! 2139: }" ! 2140: [(set_attr "type" "fp")]) ! 2141: ! 2142: (define_insn "" ! 2143: [(set (match_operand:SI 0 "general_operand" "=g") ! 2144: (match_operator 1 "float_conversion" ! 2145: [(match_operator 2 "float_binary" ! 2146: [(match_operand 3 "general_operand" "frg") ! 2147: (match_operand 4 "general_operand" "frg")])])) ! 2148: (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) ! 2149: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] ! 2150: "check_precision (GET_MODE (operands[2]), operands[3], operands[4])" ! 2151: "* ! 2152: { return output_fpop (GET_CODE (operands[2]), operands[0], ! 2153: operands[3], operands[4], insn); ! 2154: }" ! 2155: [(set_attr "type" "fp")]) ! 2156: ! 2157: (define_insn "" ! 2158: [(set (match_operand 0 "general_operand" "=frg") ! 2159: (match_operator 1 "float_conversion" ! 2160: [(match_operator 2 "float_binary" ! 2161: [(match_operand 3 "general_operand" "frg") ! 2162: (match_operand 4 "general_operand" "frg")])])) ! 2163: (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) ! 2164: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] ! 2165: "check_precision (GET_MODE (operands[2]), operands[3], operands[4])" ! 2166: "* ! 2167: { return output_fpop (GET_CODE (operands[2]), operands[0], ! 2168: operands[3], operands[4], insn); ! 2169: }" ! 2170: [(set_attr "type" "fp")]) ! 2171: ! 2172: (define_insn "" ! 2173: [(set (match_operand:SI 0 "general_operand" "=g") ! 2174: (match_operator 1 "float_conversion" ! 2175: [(match_operator 2 "float_binary" ! 2176: [(match_operand 3 "general_operand" "frg") ! 2177: (match_operator 4 "float_conversion" ! 2178: [(match_operand 5 "general_operand" "frg")])])])) ! 2179: (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) ! 2180: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] ! 2181: "check_precision (GET_MODE (operands[2]), operands[3], operands[4])" ! 2182: "* ! 2183: { return output_fpop (GET_CODE (operands[2]), operands[0], ! 2184: operands[3], operands[5], insn); ! 2185: }" ! 2186: [(set_attr "type" "fp")]) ! 2187: ! 2188: (define_insn "" ! 2189: [(set (match_operand 0 "general_operand" "=frg") ! 2190: (match_operator 1 "float_conversion" ! 2191: [(match_operator 2 "float_binary" ! 2192: [(match_operand 3 "general_operand" "frg") ! 2193: (match_operator 4 "float_conversion" ! 2194: [(match_operand 5 "general_operand" "frg")])])])) ! 2195: (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) ! 2196: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] ! 2197: "check_precision (GET_MODE (operands[2]), operands[3], operands[4])" ! 2198: "* ! 2199: { return output_fpop (GET_CODE (operands[2]), operands[0], ! 2200: operands[3], operands[5], insn); ! 2201: }" ! 2202: [(set_attr "type" "fp")]) ! 2203: ! 2204: (define_insn "" ! 2205: [(set (match_operand:SI 0 "general_operand" "=g") ! 2206: (match_operator 1 "float_conversion" ! 2207: [(match_operator 2 "float_binary" ! 2208: [(match_operator 3 "float_conversion" ! 2209: [(match_operand 4 "general_operand" "frg")]) ! 2210: (match_operand 5 "general_operand" "frg")])])) ! 2211: (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) ! 2212: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] ! 2213: "check_precision (GET_MODE (operands[2]), operands[4], operands[5])" ! 2214: "* ! 2215: { return output_fpop (GET_CODE (operands[2]), operands[0], ! 2216: operands[4], operands[5], insn); ! 2217: }" ! 2218: [(set_attr "type" "fp")]) ! 2219: ! 2220: (define_insn "" ! 2221: [(set (match_operand 0 "general_operand" "=frg") ! 2222: (match_operator 1 "float_conversion" ! 2223: [(match_operator 2 "float_binary" ! 2224: [(match_operator 3 "float_conversion" ! 2225: [(match_operand 4 "general_operand" "frg")]) ! 2226: (match_operand 5 "general_operand" "frg")])])) ! 2227: (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) ! 2228: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] ! 2229: "check_precision (GET_MODE (operands[2]), operands[4], operands[5])" ! 2230: "* ! 2231: { return output_fpop (GET_CODE (operands[2]), operands[0], ! 2232: operands[4], operands[5], insn); ! 2233: }" ! 2234: [(set_attr "type" "fp")]) ! 2235: ! 2236: (define_insn "" ! 2237: [(set (match_operand:SI 0 "general_operand" "=g") ! 2238: (match_operator 1 "float_conversion" ! 2239: [(match_operator 2 "float_binary" ! 2240: [(match_operator 3 "float_conversion" ! 2241: [(match_operand 4 "general_operand" "frg")]) ! 2242: (match_operator 5 "float_conversion" ! 2243: [(match_operand 6 "general_operand" "frg")])])])) ! 2244: (clobber (match_operand:SI 7 "reg_0_operand" "=&z")) ! 2245: (clobber (match_operand:SI 8 "reg_15_operand" "=&t"))] ! 2246: "check_precision (GET_MODE (operands[2]), operands[4], operands[6])" ! 2247: "* ! 2248: { return output_fpop (GET_CODE (operands[2]), operands[0], ! 2249: operands[4], operands[6], insn); ! 2250: }" ! 2251: [(set_attr "type" "fp")]) ! 2252: ! 2253: (define_insn "" ! 2254: [(set (match_operand 0 "general_operand" "=frg") ! 2255: (match_operator 1 "float_conversion" ! 2256: [(match_operator 2 "float_binary" ! 2257: [(match_operator 3 "float_conversion" ! 2258: [(match_operand 4 "general_operand" "frg")]) ! 2259: (match_operator 5 "float_conversion" ! 2260: [(match_operand 6 "general_operand" "frg")])])])) ! 2261: (clobber (match_operand:SI 7 "reg_0_operand" "=&z")) ! 2262: (clobber (match_operand:SI 8 "reg_15_operand" "=&t"))] ! 2263: "check_precision (GET_MODE (operands[2]), operands[4], operands[6])" ! 2264: "* ! 2265: { return output_fpop (GET_CODE (operands[2]), operands[0], ! 2266: operands[4], operands[6], insn); ! 2267: }" ! 2268: [(set_attr "type" "fp")]) ! 2269: ! 2270: ;; Unary floating-point operations. ! 2271: ! 2272: (define_insn "" ! 2273: [(set (match_operand 0 "general_operand" "=frg") ! 2274: (match_operator 1 "float_unary" ! 2275: [(match_operand 2 "general_operand" "frg")])) ! 2276: (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) ! 2277: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] ! 2278: "check_precision (GET_MODE (operands[1]), operands[2], 0)" ! 2279: "* ! 2280: { return output_fpop (GET_CODE (operands[1]), operands[0], operands[2], ! 2281: 0, insn); ! 2282: }" ! 2283: [(set_attr "type" "fp")]) ! 2284: ! 2285: (define_insn "" ! 2286: [(set (match_operand 0 "general_operand" "=frg") ! 2287: (match_operator 1 "float_unary" ! 2288: [(match_operator 2 "float_conversion" ! 2289: [(match_operand 3 "general_operand" "frg")])])) ! 2290: (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) ! 2291: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] ! 2292: "check_precision (GET_MODE (operands[1]), operands[3], 0)" ! 2293: "* ! 2294: { return output_fpop (GET_CODE (operands[1]), operands[0], operands[3], ! 2295: 0, insn); ! 2296: }" ! 2297: [(set_attr "type" "fp")]) ! 2298: ! 2299: (define_insn "" ! 2300: [(set (match_operand:SI 0 "general_operand" "=g") ! 2301: (match_operator 1 "float_conversion" ! 2302: [(match_operator 2 "float_unary" ! 2303: [(match_operand 3 "general_operand" "frg")])])) ! 2304: (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) ! 2305: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] ! 2306: "check_precision (GET_MODE (operands[2]), operands[3], 0)" ! 2307: "* ! 2308: { return output_fpop (GET_CODE (operands[2]), operands[0], operands[3], ! 2309: 0, insn); ! 2310: }" ! 2311: [(set_attr "type" "fp")]) ! 2312: ! 2313: (define_insn "" ! 2314: [(set (match_operand 0 "general_operand" "=frg") ! 2315: (match_operator 1 "float_conversion" ! 2316: [(match_operator 2 "float_unary" ! 2317: [(match_operand 3 "general_operand" "frg")])])) ! 2318: (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) ! 2319: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] ! 2320: "check_precision (GET_MODE (operands[2]), operands[3], 0)" ! 2321: "* ! 2322: { return output_fpop (GET_CODE (operands[2]), operands[0], operands[3], ! 2323: 0, insn); ! 2324: }" ! 2325: [(set_attr "type" "fp")]) ! 2326: ! 2327: (define_insn "" ! 2328: [(set (match_operand:SI 0 "general_operand" "=g") ! 2329: (match_operator 1 "float_conversion" ! 2330: [(match_operator 2 "float_unary" ! 2331: [(match_operator 3 "float_conversion" ! 2332: [(match_operand 4 "general_operand" "frg")])])])) ! 2333: (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) ! 2334: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] ! 2335: "check_precision (GET_MODE (operands[2]), operands[4], 0)" ! 2336: "* ! 2337: { return output_fpop (GET_CODE (operands[2]), operands[0], operands[4], ! 2338: 0, insn); ! 2339: }" ! 2340: [(set_attr "type" "fp")]) ! 2341: ! 2342: (define_insn "" ! 2343: [(set (match_operand 0 "general_operand" "=frg") ! 2344: (match_operator 1 "float_conversion" ! 2345: [(match_operator 2 "float_unary" ! 2346: [(match_operator 3 "float_conversion" ! 2347: [(match_operand 4 "general_operand" "frg")])])])) ! 2348: (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) ! 2349: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] ! 2350: "check_precision (GET_MODE (operands[2]), operands[4], 0)" ! 2351: "* ! 2352: { return output_fpop (GET_CODE (operands[2]), operands[0], operands[4], ! 2353: 0, insn); ! 2354: }" ! 2355: [(set_attr "type" "fp")]) ! 2356: ! 2357: ;; Compare insns are next. Note that the ROMP has two types of compares, ! 2358: ;; signed & unsigned, and one type of branch. Use the routine ! 2359: ;; `next_insn_tests_no_unsigned' to see which type to use. ! 2360: (define_expand "tstsi" ! 2361: [(set (cc0) ! 2362: (match_operand:SI 0 "register_operand" "r"))] ! 2363: "" ! 2364: "") ! 2365: ! 2366: (define_expand "cmpsi" ! 2367: [(set (cc0) ! 2368: (compare (match_operand:SI 0 "register_operand" "") ! 2369: (match_operand:SI 1 "reg_or_cint_operand" "")))] ! 2370: "" ! 2371: "") ! 2372: ! 2373: ;; Signed compare, `test' first. ! 2374: ! 2375: (define_insn "" ! 2376: [(set (cc0) ! 2377: (match_operand:SI 0 "register_operand" "r"))] ! 2378: "next_insn_tests_no_unsigned (insn)" ! 2379: "cis %0,0" ! 2380: [(set_attr "length" "2") ! 2381: (set_attr "type" "compare")]) ! 2382: ! 2383: (define_insn "" ! 2384: [(set (cc0) (match_operand:SI 0 "register_operand" "r,r,r")) ! 2385: (set (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "=0,r,Q") ! 2386: (match_dup 0))] ! 2387: "next_insn_tests_no_unsigned (insn)" ! 2388: "@ ! 2389: cis %1,0 ! 2390: nilo %1,%0,65535 ! 2391: st%M1 %0,%1\;cis %0,0" ! 2392: [(set_attr "type" "compare,compare,store") ! 2393: (set_attr "length" "2,4,6") ! 2394: (set_attr "cc" "compare")]) ! 2395: ! 2396: (define_insn "" ! 2397: [(set (cc0) ! 2398: (compare (match_operand:SI 0 "register_operand" "r,r,r") ! 2399: (match_operand:SI 1 "reg_or_cint_operand" "I,K,r")))] ! 2400: "next_insn_tests_no_unsigned (insn)" ! 2401: "@ ! 2402: cis %0,%1 ! 2403: cil %0,%1 ! 2404: c %0,%1" ! 2405: [(set_attr "length" "2,4,2") ! 2406: (set_attr "type" "compare")]) ! 2407: ! 2408: ;; Unsigned comparisons, `test' first, again. ! 2409: (define_insn "" ! 2410: [(set (cc0) ! 2411: (match_operand:SI 0 "register_operand" "r"))] ! 2412: "! next_insn_tests_no_unsigned (insn)" ! 2413: "clil %0,0" ! 2414: [(set_attr "type" "compare")]) ! 2415: ! 2416: (define_insn "" ! 2417: [(set (cc0) ! 2418: (compare (match_operand:SI 0 "register_operand" "r,r") ! 2419: (match_operand:SI 1 "reg_or_cint_operand" "K,r")))] ! 2420: "! next_insn_tests_no_unsigned (insn)" ! 2421: "@ ! 2422: clil %0,%1 ! 2423: cl %0,%1" ! 2424: [(set_attr "length" "4,2") ! 2425: (set_attr "type" "compare")]) ! 2426: ! 2427: ;; Bit test insn. Many cases are converted into this by combine. This ! 2428: ;; uses the ROMP test bit. ! 2429: ! 2430: (define_insn "" ! 2431: [(set (cc0) ! 2432: (zero_extract (match_operand:SI 0 "register_operand" "r,r") ! 2433: (const_int 1) ! 2434: (match_operand:SI 1 "reg_or_any_cint_operand" "r,n")))] ! 2435: "next_insn_tests_no_inequality (insn)" ! 2436: "@ ! 2437: mttb %0,%1 ! 2438: mttbi%t1 %0,%S1" ! 2439: [(set_attr "length" "2") ! 2440: (set_attr "type" "compare") ! 2441: (set_attr "cc" "tbit")]) ! 2442: ! 2443: ;; Floating-point comparisons. There are two, equality and order. ! 2444: ;; The difference will be that a trap for NaN will be given on the orderr ! 2445: ;; comparisons only. ! 2446: ! 2447: (define_expand "cmpsf" ! 2448: [(parallel [(set (cc0) (compare (match_operand:SF 0 "general_operand" "") ! 2449: (match_operand:SF 1 "general_operand" ""))) ! 2450: (clobber (reg:SI 0)) ! 2451: (clobber (reg:SI 15))])] ! 2452: "" ! 2453: "") ! 2454: ! 2455: (define_expand "cmpdf" ! 2456: [(parallel [(set (cc0) (compare (match_operand:DF 0 "general_operand" "") ! 2457: (match_operand:DF 1 "general_operand" ""))) ! 2458: (clobber (reg:SI 0)) ! 2459: (clobber (reg:SI 15))])] ! 2460: "" ! 2461: "") ! 2462: ! 2463: (define_expand "tstsf" ! 2464: [(parallel [(set (cc0) (match_operand:SF 0 "general_operand" "")) ! 2465: (clobber (reg:SI 0)) ! 2466: (clobber (reg:SI 15))])] ! 2467: "" ! 2468: "") ! 2469: ! 2470: (define_expand "tstdf" ! 2471: [(parallel [(set (cc0) (match_operand:DF 0 "general_operand" "")) ! 2472: (clobber (reg:SI 0)) ! 2473: (clobber (reg:SI 15))])] ! 2474: "" ! 2475: "") ! 2476: ! 2477: ;; There are four cases for compare and two for test. These correspond ! 2478: ;; to each input having a floating-point conversion or not. ! 2479: ! 2480: (define_insn "" ! 2481: [(set (cc0) (compare (match_operand 0 "general_operand" "frg") ! 2482: (match_operand 1 "general_operand" "frg"))) ! 2483: (clobber (match_operand:SI 2 "reg_0_operand" "=&z")) ! 2484: (clobber (match_operand:SI 3 "reg_15_operand" "=&t"))] ! 2485: "GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode" ! 2486: "* ! 2487: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, ! 2488: operands[0], operands[1], 0, insn); ! 2489: }" ! 2490: [(set_attr "type" "fp") ! 2491: (set_attr "cc" "compare")]) ! 2492: ! 2493: (define_insn "" ! 2494: [(set (cc0) (compare (match_operand 0 "general_operand" "frg") ! 2495: (match_operator 1 "float_conversion" ! 2496: [(match_operand 2 "general_operand" "frg")]))) ! 2497: (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) ! 2498: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] ! 2499: "" ! 2500: "* ! 2501: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, ! 2502: operands[0], operands[2], 0, insn); ! 2503: }" ! 2504: [(set_attr "type" "fp") ! 2505: (set_attr "cc" "compare")]) ! 2506: ! 2507: (define_insn "" ! 2508: [(set (cc0) (compare (match_operator 0 "float_conversion" ! 2509: [(match_operand 1 "general_operand" "frg")]) ! 2510: (match_operand 2 "general_operand" "frg"))) ! 2511: (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) ! 2512: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] ! 2513: "" ! 2514: "* ! 2515: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, ! 2516: operands[1], operands[2], 0, insn); ! 2517: }" ! 2518: [(set_attr "type" "fp") ! 2519: (set_attr "cc" "compare")]) ! 2520: ! 2521: (define_insn "" ! 2522: [(set (cc0) (compare (match_operator 0 "float_conversion" ! 2523: [(match_operand 1 "general_operand" "frg")]) ! 2524: (match_operator 2 "float_conversion" ! 2525: [(match_operand 3 "general_operand" "frg")]))) ! 2526: (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) ! 2527: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] ! 2528: "" ! 2529: "* ! 2530: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, ! 2531: operands[1], operands[3], 0, insn); ! 2532: }" ! 2533: [(set_attr "type" "fp") ! 2534: (set_attr "cc" "compare")]) ! 2535: ! 2536: (define_insn "" ! 2537: [(set (cc0) (match_operand 0 "general_operand" "frg")) ! 2538: (clobber (match_operand:SI 1 "reg_0_operand" "=&z")) ! 2539: (clobber (match_operand:SI 2 "reg_15_operand" "=&t"))] ! 2540: "GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode" ! 2541: "* ! 2542: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, ! 2543: operands[0], immed_real_const_1 (0, 0, ! 2544: GET_MODE (operands[0])), ! 2545: 0, insn); ! 2546: }" ! 2547: [(set_attr "type" "fp") ! 2548: (set_attr "cc" "compare")]) ! 2549: ! 2550: (define_insn "" ! 2551: [(set (cc0) (match_operator 0 "float_conversion" ! 2552: [(match_operand 1 "general_operand" "frg")])) ! 2553: (clobber (match_operand:SI 2 "reg_0_operand" "=&z")) ! 2554: (clobber (match_operand:SI 3 "reg_15_operand" "=&t"))] ! 2555: "" ! 2556: "* ! 2557: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, ! 2558: operands[1], immed_real_const_1 (0, 0, ! 2559: GET_MODE (operands[1])), ! 2560: 0, insn); ! 2561: }" ! 2562: [(set_attr "type" "fp") ! 2563: (set_attr "cc" "compare")]) ! 2564: ! 2565: ;; Branch insns. Unsigned vs. signed have already ! 2566: ;; been taken care of. The only insns that need to be concerned about the ! 2567: ;; test bit are beq and bne because the rest are either always true, ! 2568: ;; always false, or converted to EQ or NE. ! 2569: ! 2570: ;; For conditional branches, we use `define_expand' and just have two patterns ! 2571: ;; that match them. Operand printing does most of the work. ! 2572: ! 2573: (define_expand "beq" ! 2574: [(set (pc) ! 2575: (if_then_else (eq (cc0) ! 2576: (const_int 0)) ! 2577: (label_ref (match_operand 0 "" "")) ! 2578: (pc)))] ! 2579: "" ! 2580: "") ! 2581: ! 2582: (define_expand "bne" ! 2583: [(set (pc) ! 2584: (if_then_else (ne (cc0) ! 2585: (const_int 0)) ! 2586: (label_ref (match_operand 0 "" "")) ! 2587: (pc)))] ! 2588: "" ! 2589: "") ! 2590: ! 2591: (define_expand "bgt" ! 2592: [(set (pc) ! 2593: (if_then_else (gt (cc0) ! 2594: (const_int 0)) ! 2595: (label_ref (match_operand 0 "" "")) ! 2596: (pc)))] ! 2597: "" ! 2598: "") ! 2599: ! 2600: (define_expand "bgtu" ! 2601: [(set (pc) ! 2602: (if_then_else (gtu (cc0) ! 2603: (const_int 0)) ! 2604: (label_ref (match_operand 0 "" "")) ! 2605: (pc)))] ! 2606: "" ! 2607: "") ! 2608: ! 2609: (define_expand "blt" ! 2610: [(set (pc) ! 2611: (if_then_else (lt (cc0) ! 2612: (const_int 0)) ! 2613: (label_ref (match_operand 0 "" "")) ! 2614: (pc)))] ! 2615: "" ! 2616: "") ! 2617: ! 2618: (define_expand "bltu" ! 2619: [(set (pc) ! 2620: (if_then_else (ltu (cc0) ! 2621: (const_int 0)) ! 2622: (label_ref (match_operand 0 "" "")) ! 2623: (pc)))] ! 2624: "" ! 2625: "") ! 2626: ! 2627: (define_expand "bge" ! 2628: [(set (pc) ! 2629: (if_then_else (ge (cc0) ! 2630: (const_int 0)) ! 2631: (label_ref (match_operand 0 "" "")) ! 2632: (pc)))] ! 2633: "" ! 2634: "") ! 2635: ! 2636: (define_expand "bgeu" ! 2637: [(set (pc) ! 2638: (if_then_else (geu (cc0) ! 2639: (const_int 0)) ! 2640: (label_ref (match_operand 0 "" "")) ! 2641: (pc)))] ! 2642: "" ! 2643: "") ! 2644: ! 2645: (define_expand "ble" ! 2646: [(set (pc) ! 2647: (if_then_else (le (cc0) ! 2648: (const_int 0)) ! 2649: (label_ref (match_operand 0 "" "")) ! 2650: (pc)))] ! 2651: "" ! 2652: "") ! 2653: ! 2654: (define_expand "bleu" ! 2655: [(set (pc) ! 2656: (if_then_else (leu (cc0) ! 2657: (const_int 0)) ! 2658: (label_ref (match_operand 0 "" "")) ! 2659: (pc)))] ! 2660: "" ! 2661: "") ! 2662: ! 2663: ;; Define both directions of branch and return. ! 2664: ! 2665: (define_insn "" ! 2666: [(set (pc) ! 2667: (if_then_else (match_operator 1 "comparison_operator" ! 2668: [(cc0) (const_int 0)]) ! 2669: (label_ref (match_operand 0 "" "")) ! 2670: (pc)))] ! 2671: "" ! 2672: "* ! 2673: { ! 2674: if (restore_compare_p (operands[1])) ! 2675: return 0; ! 2676: else if (get_attr_length (insn) == 2) ! 2677: return \"j%j1 %l0\"; ! 2678: else ! 2679: return \"b%j1%# %l0\"; ! 2680: }" ! 2681: [(set_attr "type" "branch")]) ! 2682: ! 2683: (define_insn "" ! 2684: [(set (pc) ! 2685: (if_then_else (match_operator 0 "comparison_operator" ! 2686: [(cc0) (const_int 0)]) ! 2687: (return) ! 2688: (pc)))] ! 2689: "null_epilogue ()" ! 2690: "* ! 2691: { ! 2692: if (restore_compare_p (operands[0])) ! 2693: return 0; ! 2694: else ! 2695: return \"b%j0r%# r15\"; ! 2696: }" ! 2697: [(set_attr "type" "return")]) ! 2698: ! 2699: (define_insn "" ! 2700: [(set (pc) ! 2701: (if_then_else (match_operator 1 "comparison_operator" ! 2702: [(cc0) (const_int 0)]) ! 2703: (pc) ! 2704: (label_ref (match_operand 0 "" ""))))] ! 2705: "" ! 2706: "* ! 2707: { ! 2708: if (restore_compare_p (operands[1])) ! 2709: return 0; ! 2710: else if (get_attr_length (insn) == 2) ! 2711: return \"j%J1 %l0\"; ! 2712: else ! 2713: return \"b%J1%# %l0\"; ! 2714: }" ! 2715: [(set_attr "type" "branch")]) ! 2716: ! 2717: (define_insn "" ! 2718: [(set (pc) ! 2719: (if_then_else (match_operator 0 "comparison_operator" ! 2720: [(cc0) (const_int 0)]) ! 2721: (pc) ! 2722: (return)))] ! 2723: "null_epilogue ()" ! 2724: "* ! 2725: { ! 2726: if (restore_compare_p (operands[0])) ! 2727: return 0; ! 2728: else ! 2729: return \"b%J0r%# r15\"; ! 2730: }" ! 2731: [(set_attr "type" "return")]) ! 2732: ! 2733: ;; Unconditional branch and return. ! 2734: ! 2735: (define_insn "jump" ! 2736: [(set (pc) ! 2737: (label_ref (match_operand 0 "" "")))] ! 2738: "" ! 2739: "* ! 2740: { ! 2741: if (get_attr_length (insn) == 2) ! 2742: return \"j %l0\"; ! 2743: else ! 2744: return \"b%# %l0\"; ! 2745: }" ! 2746: [(set_attr "type" "branch")]) ! 2747: ! 2748: (define_insn "return" ! 2749: [(return)] ! 2750: "null_epilogue ()" ! 2751: "br%# r15" ! 2752: [(set_attr "type" "return")]) ! 2753: ! 2754: (define_insn "indirect_jump" ! 2755: [(set (pc) (match_operand:SI 0 "register_operand" "r"))] ! 2756: "" ! 2757: "br%# %0" ! 2758: [(set_attr "type" "ibranch")]) ! 2759: ! 2760: ;; Table jump for switch statements: ! 2761: (define_insn "tablejump" ! 2762: [(set (pc) ! 2763: (match_operand:SI 0 "register_operand" "r")) ! 2764: (use (label_ref (match_operand 1 "" "")))] ! 2765: "" ! 2766: "br%# %0" ! 2767: [(set_attr "type" "ibranch")])
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.