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