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