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