diff options
Diffstat (limited to 'gcc/config/romp/romp.md')
-rw-r--r-- | gcc/config/romp/romp.md | 2778 |
1 files changed, 0 insertions, 2778 deletions
diff --git a/gcc/config/romp/romp.md b/gcc/config/romp/romp.md deleted file mode 100644 index 2177c191065..00000000000 --- a/gcc/config/romp/romp.md +++ /dev/null @@ -1,2778 +0,0 @@ -;;- Machine description for ROMP chip for GNU C compiler -;; Copyright (C) 1988, 1991, 1993, 1994, 1995 Free Software Foundation, Inc. -;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; Define the attributes for the ROMP. - -;; Insn type. Used to default other attribute values. - -(define_attr "type" - "branch,ibranch,return,fp,load,loadz,store,call,address,arith,compare,multi,misc" - (const_string "arith")) - -;; Length in bytes. - -(define_attr "length" "" - (cond [(eq_attr "type" "branch") - (if_then_else (and (ge (minus (pc) (match_dup 0)) - (const_int -256)) - (le (minus (pc) (match_dup 0)) - (const_int 254))) - (const_int 2) - (const_int 4)) - (eq_attr "type" "return,ibranch") (const_int 2) - (eq_attr "type" "fp") (const_int 10) - (eq_attr "type" "call") (const_int 4) - (eq_attr "type" "load") - (cond [(match_operand 1 "short_memory_operand" "") (const_int 2) - (match_operand 1 "symbolic_memory_operand" "") (const_int 8)] - (const_int 4)) - (eq_attr "type" "loadz") - (cond [(match_operand 1 "zero_memory_operand" "") (const_int 2) - (match_operand 1 "symbolic_memory_operand" "") (const_int 8)] - (const_string "4")) - (eq_attr "type" "store") - (cond [(match_operand 0 "short_memory_operand" "") (const_int 2) - (match_operand 0 "symbolic_memory_operand" "") (const_int 8)] - (const_int 4))] - (const_int 4))) - -;; Whether insn can be placed in a delay slot. - -(define_attr "in_delay_slot" "yes,no" - (cond [(eq_attr "length" "8,10,38") (const_string "no") - (eq_attr "type" "branch,ibranch,return,call,multi") - (const_string "no")] - (const_string "yes"))) - -;; Whether insn needs a delay slot. We have to say that two-byte -;; branches do not need a delay slot. Otherwise, branch shortening will -;; try to do something with delay slot insns (we want it to on the PA). -;; This is a kludge, which should be cleaned up at some point. - -(define_attr "needs_delay_slot" "yes,no" - (if_then_else (ior (and (eq_attr "type" "branch") - (eq_attr "length" "4")) - (eq_attr "type" "ibranch,return,call")) - (const_string "yes") (const_string "no"))) - -;; What insn does to the condition code. - -(define_attr "cc" - "clobber,none,sets,change0,copy1to0,compare,tbit" - (cond [(eq_attr "type" "load,loadz") (const_string "change0") - (eq_attr "type" "store") (const_string "none") - (eq_attr "type" "fp,call") (const_string "clobber") - (eq_attr "type" "branch,ibranch,return") (const_string "none") - (eq_attr "type" "address") (const_string "change0") - (eq_attr "type" "compare") (const_string "compare") - (eq_attr "type" "arith") (const_string "sets")] - (const_string "clobber"))) - -;; Define attributes for `asm' insns. - -(define_asm_attributes [(set_attr "type" "misc") - (set_attr "length" "8") - (set_attr "in_delay_slot" "no") - (set_attr "cc" "clobber")]) - -;; Define the delay slot requirements for branches and calls. We don't have -;; any annulled insns. -;; -(define_delay (eq_attr "needs_delay_slot" "yes") - [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) - -;; We cannot give a floating-point comparison a delay slot, even though it -;; could make use of it. This is because it would confuse next_cc0_user -;; to do so. Other fp insns can't get a delay slow because they set their -;; result and use their input after the delay slot insn is executed. This -;; isn't what reorg.c expects. - -;; Define load & store delays. These were obtained by measurements done by -;; jfc@athena.mit.edu. -;; -;; In general, the memory unit can support at most two simultaneous operations. -;; -;; Loads take 5 cycles to return the data and can be pipelined up to the -;; limit of two simultaneous operations. -(define_function_unit "memory" 1 2 (eq_attr "type" "load,loadz") 5 0) - -;; Stores do not return data, but tie up the memory unit for 2 cycles if the -;; next insn is also a store. -(define_function_unit "memory" 1 2 (eq_attr "type" "store") 1 2 - [(eq_attr "type" "store")]) - -;; Move word instructions. -;; -;; If destination is memory but source is not register, force source to -;; register. -;; -;; If source is a constant that is too large to load in a single insn, build -;; it in two pieces. -;; -;; If destination is memory and source is a register, a temporary register -;; will be needed. In that case, make a PARALLEL of the SET and a -;; CLOBBER of a SCRATCH to allocate the required temporary. -;; -;; This temporary is ACTUALLY only needed when the destination is a -;; relocatable expression. For generating RTL, however, we always -;; place the CLOBBER. In insns where it is not needed, the SCRATCH will -;; not be allocated to a register. -;; -;; Also, avoid creating pseudo-registers or SCRATCH rtx's during reload as -;; they will not be correctly handled. We never need pseudos for that -;; case anyway. -;; -;; We do not use DEFINE_SPLIT for loading constants because the number -;; of cases in the resulting unsplit insn would be too high to deal -;; with practically. -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ rtx op0 = operands[0]; - rtx op1 = operands[1]; - - if (GET_CODE (op1) == REG && REGNO (op1) == 16) - DONE; - - if (GET_CODE (op0) == REG && REGNO (op0) == 16) - DONE; - - if (GET_CODE (op0) == MEM && ! reload_in_progress) - { - emit_insn (gen_storesi (operands[0], force_reg (SImode, operands[1]))); - DONE; - } - else if (GET_CODE (op1) == CONST_INT) - { - int const_val = INTVAL (op1); - - /* Try a number of cases to see how to best load the constant. */ - if ((const_val & 0xffff) == 0 - || (const_val & 0xffff0000) == 0 - || (unsigned) (const_val + 0x8000) < 0x10000) - /* Can do this in one insn, so generate it. */ - ; - else if (((- const_val) & 0xffff) == 0 - || ((- const_val) & 0xffff0000) == 0 - || (unsigned) ((- const_val) + 0x8000) < 0x10000) - { - /* Can do this by loading the negative constant and then negating. */ - emit_move_insn (operands[0], - gen_rtx (CONST_INT, VOIDmode, - const_val)); - emit_insn (gen_negsi2 (operands[0], operands[0])); - DONE; - } - else - /* Do this the long way. */ - { - unsigned int high_part = const_val & 0xffff0000; - unsigned int low_part = const_val & 0xffff; - int i; - - if (low_part >= 0x10 && exact_log2 (low_part) >= 0) - i = high_part, high_part = low_part, low_part = i; - - emit_move_insn (operands[0], - gen_rtx (CONST_INT, VOIDmode, low_part)); - emit_insn (gen_iorsi3 (operands[0], operands[0], - gen_rtx (CONST_INT, VOIDmode, high_part))); - DONE; - } - } -}") - -;; Move from a symbolic memory location to a register is special. In this -;; case, we know in advance that the register cannot be r0, so we can improve -;; register allocation by treating it separately. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=b") - (match_operand:SI 1 "symbolic_memory_operand" "m"))] - "" - "load %0,%1" - [(set_attr "type" "load")]) - -;; Generic single-word move insn. We avoid the case where the destination is -;; a symbolic address, as that needs a temporary register. - -(define_insn "" - [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,r,r,r,b,Q") - (match_operand:SI 1 "romp_operand" "rR,I,K,L,M,S,s,Q,m,r"))] - "register_operand (operands[0], SImode) - || register_operand (operands[1], SImode)" - "@ - cas %0,%1,r0 - lis %0,%1 - cal %0,%1(r0) - cal16 %0,%1(r0) - cau %0,%H1(r0) - ail %0,r14,%C1 - get %0,$%1 - l%M1 %0,%1 - load %0,%1 - st%M0 %1,%0" - [(set_attr "type" "address,address,address,address,address,arith,misc,load,load,store") - (set_attr "length" "2,2,4,4,4,4,8,*,*,*")]) - -(define_insn "storesi" - [(set (match_operand:SI 0 "memory_operand" "=Q,m") - (match_operand:SI 1 "register_operand" "r,r")) - (clobber (match_scratch:SI 2 "=X,&b"))] - "" - "@ - st%M0 %1,%0 - store %1,%0,%2" - [(set_attr "type" "store")]) - -;; This pattern is used by reload when we store into a symbolic address. It -;; provides the temporary register required. This pattern is only used -;; when SECONDARY_OUTPUT_RELOAD_CLASS returns something other than -;; NO_REGS, so we need not have any predicates here. - -(define_expand "reload_outsi" - [(parallel [(set (match_operand:SI 0 "symbolic_memory_operand" "=m") - (match_operand:SI 1 "" "r")) - (clobber (match_operand:SI 2 "" "=&b"))])] - "" - "") - -;; Now do the same for the QI move instructions. -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ rtx op0 = operands[0]; - - if (GET_CODE (op0) == MEM && ! reload_in_progress) - { - emit_insn (gen_storeqi (operands[0], force_reg (QImode, operands[1]))); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=b") - (match_operand:QI 1 "symbolic_memory_operand" "m"))] - "" - "loadc %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q") - (match_operand:QI 1 "romp_operand" "r,I,n,s,Q,m,r"))] - "register_operand (operands[0], QImode) - || register_operand (operands[1], QImode)" - "@ - cas %0,%1,r0 - lis %0,%1 - cal %0,%L1(r0) - get %0,$%1 - lc%M1 %0,%1 - loadc %0,%1 - stc%M0 %1,%0" - [(set_attr "type" "address,address,address,misc,load,load,store") - (set_attr "length" "2,2,4,8,*,*,*")]) - -(define_insn "storeqi" - [(set (match_operand:QI 0 "memory_operand" "=Q,m") - (match_operand:QI 1 "register_operand" "r,r")) - (clobber (match_scratch:SI 2 "=X,&b"))] - "" - "@ - stc%M0 %1,%0 - storec %1,%0,%2" - [(set_attr "type" "store")]) - -(define_expand "reload_outqi" - [(parallel [(set (match_operand:QI 0 "symbolic_memory_operand" "=m") - (match_operand:QI 1 "" "r")) - (clobber (match_operand:SI 2 "" "=&b"))])] - "" - "") - -;; Finally, the HI instructions. -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ rtx op0 = operands[0]; - - if (GET_CODE (op0) == MEM && ! reload_in_progress) - { - emit_insn (gen_storehi (operands[0], force_reg (HImode, operands[1]))); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=b") - (match_operand:HI 1 "symbolic_memory_operand" "m"))] - "" - "loadha %0,%1" - [(set_attr "type" "load")]) - - -;; use cal16 instead of cal for constant source because combine requires -;; the high bits of the register to be 0 after a HImode load of a constant - -(define_insn "" - [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q") - (match_operand:HI 1 "romp_operand" "r,I,n,s,Q,m,r"))] - "register_operand (operands[0], HImode) - || register_operand (operands[1], HImode)" - "@ - cas %0,%1,r0 - lis %0,%1 - cal16 %0,%L1(r0) - get %0,$%1 - lh%N1 %0,%1 - loadh %0,%1 - sth%M0 %1,%0" - [(set_attr "type" "address,address,address,misc,loadz,loadz,store") - (set_attr "length" "2,2,4,8,*,*,*")]) - -(define_insn "storehi" - [(set (match_operand:HI 0 "memory_operand" "=Q,m") - (match_operand:HI 1 "register_operand" "r,r")) - (clobber (match_scratch:SI 2 "=X,&b"))] - "" - "@ - sth%M0 %1,%0 - storeh %1,%0,%2" - [(set_attr "type" "store")]) - -(define_expand "reload_outhi" - [(parallel [(set (match_operand:HI 0 "symbolic_memory_operand" "=m") - (match_operand:HI 1 "" "r")) - (clobber (match_operand:SI 2 "" "=&b"))])] - "" - "") - -;; For DI move, if we have a constant, break the operation apart into -;; two SImode moves because the optimizer may be able to do a better job -;; with the resulting code. -;; -;; For memory stores, make the required pseudo for a temporary in case we -;; are storing into an absolute address. -;; -;; We need to be careful about the cases where the output is a register that is -;; the second register of the input. - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ rtx op0 = operands[0]; - rtx op1 = operands[1]; - - if (CONSTANT_P (op1)) - { - rtx insns; - - start_sequence (); - emit_move_insn (operand_subword (op0, 0, 1, DImode), - operand_subword (op1, 0, 1, DImode)); - emit_move_insn (operand_subword (op0, 1, 1, DImode), - operand_subword (op1, 1, 1, DImode)); - insns = get_insns (); - end_sequence (); - - emit_no_conflict_block (insns, op0, op1, 0, op1); - DONE; - } - - if (GET_CODE (op0) == MEM && ! reload_in_progress) - { - emit_insn (gen_storedi (operands[0], force_reg (DImode, operands[1]))); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") - (match_operand:DI 1 "reg_or_mem_operand" "r,Q,m,r"))] - "register_operand (operands[0], DImode) - || register_operand (operands[1], DImode)" - "* -{ - switch (which_alternative) - { - case 0: - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"cas %O0,%O1,r0\;cas %0,%1,r0\"; - else - return \"cas %0,%1,r0\;cas %O0,%O1,r0\"; - case 1: - /* Here we must see which word to load first. We default to the - low-order word unless it occurs in the address. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"l%M1 %O0,%O1\;l%M1 %0,%1\"; - else - return \"l%M1 %0,%1\;l%M1 %O0,%O1\"; - case 2: - return \"get %O0,$%1\;ls %0,0(%O0)\;ls %O0,4(%O0)\"; - case 3: - return \"st%M0 %1,%0\;st%M0 %O1,%O0\"; - } -}" - [(set_attr "type" "multi") - (set_attr "cc" "change0,change0,change0,none") - (set_attr "length" "4,12,8,8")]) - -(define_insn "storedi" - [(set (match_operand:DI 0 "memory_operand" "=Q,m") - (match_operand:DI 1 "register_operand" "r,r")) - (clobber (match_scratch:SI 2 "=X,&b"))] - "" - "@ - st%M0 %1,%0\;st%M0 %O1,%O0 - get %2,$%0\;sts %1,0(%2)\;sts %O1,4(%2)" - [(set_attr "type" "multi,multi") - (set_attr "cc" "none,none") - (set_attr "length" "8,12")]) - -(define_expand "reload_outdi" - [(parallel [(set (match_operand:DI 0 "symbolic_memory_operand" "=m") - (match_operand:DI 1 "" "r")) - (clobber (match_operand:SI 2 "" "=&b"))])] - "" - "") - -;; Split symbolic memory operands differently. We first load the address -;; into a register and then do the two loads or stores. We can only do -;; this if operand_subword won't produce a SUBREG, which is only when -;; operands[0] is a hard register. Thus, these won't be used during the -;; first insn scheduling pass. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "symbolic_memory_operand" ""))] - "GET_CODE (operands[0]) == REG - && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5)) - (set (match_dup 6) (match_dup 7))] - " -{ operands[2] = operand_subword (operands[0], 1, 0, DImode); - operands[3] = XEXP (operands[1], 0); - operands[4] = operand_subword (operands[0], 0, 0, DImode); - operands[5] = gen_rtx (MEM, SImode, operands[2]); - operands[6] = operands[2]; - operands[7] = gen_rtx (MEM, SImode, - gen_rtx (PLUS, SImode, operands[2], - gen_rtx (CONST_INT, VOIDmode, 4))); - - if (operands[2] == 0 || operands[4] == 0) - FAIL; -}") - -(define_split - [(set (match_operand:DI 0 "symbolic_memory_operand" "") - (match_operand:DI 1 "register_operand" "")) - (clobber (match_operand:SI 2 "register_operand" ""))] - "GET_CODE (operands[0]) == REG - && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5)) - (set (match_dup 6) (match_dup 7))] - " -{ operands[3] = XEXP (operands[0], 0); - operands[4] = gen_rtx (MEM, SImode, operands[2]); - operands[5] = operand_subword (operands[1], 0, 0, DImode); - operands[6] = gen_rtx (MEM, SImode, - gen_rtx (PLUS, SImode, operands[2], - gen_rtx (CONST_INT, VOIDmode, 4))); - operands[7] = operand_subword (operands[1], 1, 0, DImode); - - if (operands[5] == 0 || operands[7] == 0) - FAIL; -}") - -;; If the output is a register and the input is memory, we have to be careful -;; and see which word needs to be loaded first. -;; -;; Note that this case doesn't have a CLOBBER. Therefore, we must either -;; be after reload or operand[0] must not be a MEM. So we don't need a -;; CLOBBER on the new insns either. -;; -;; Due to a bug in sched.c, we do not want to split this insn if both -;; operands are registers and they overlap unless reload has completed. -(define_split - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "! symbolic_memory_operand (operands[0], DImode) - && ! symbolic_memory_operand (operands[1], DImode) - && ! (GET_CODE (operands[0]) == REG - && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) - && ! (GET_CODE (operands[1]) == REG - && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) - && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG - && ! reload_completed - && reg_overlap_mentioned_p (operands[0], operands[1]))" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - " -{ if (GET_CODE (operands[0]) != REG - || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - { - operands[2] = operand_subword (operands[0], 0, 0, DImode); - operands[3] = operand_subword (operands[1], 0, 0, DImode); - operands[4] = operand_subword (operands[0], 1, 0, DImode); - operands[5] = operand_subword (operands[1], 1, 0, DImode); - } - else - { - operands[2] = operand_subword (operands[0], 1, 0, DImode); - operands[3] = operand_subword (operands[1], 1, 0, DImode); - operands[4] = operand_subword (operands[0], 0, 0, DImode); - operands[5] = operand_subword (operands[1], 0, 0, DImode); - } - - if (operands[2] == 0 || operands[3] == 0 - || operands[4] == 0 || operands[5] == 0) - FAIL; -}") - -(define_split - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" "")) - (clobber (match_operand:SI 6 "register_operand" ""))] - "! symbolic_memory_operand (operands[0], DImode) - && ! symbolic_memory_operand (operands[1], DImode) - && ! (GET_CODE (operands[0]) == REG - && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) - && ! (GET_CODE (operands[1]) == REG - && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) - && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG - && ! reload_completed - && reg_overlap_mentioned_p (operands[0], operands[1]))" - [(parallel [(set (match_dup 2) (match_dup 3)) - (clobber (match_dup 7))]) - (parallel [(set (match_dup 4) (match_dup 5)) - (clobber (match_dup 8))])] - " -{ if (GET_CODE (operands[0]) != REG - || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - { - operands[2] = operand_subword (operands[0], 0, 0, DImode); - operands[3] = operand_subword (operands[1], 0, 0, DImode); - operands[4] = operand_subword (operands[0], 1, 0, DImode); - operands[5] = operand_subword (operands[1], 1, 0, DImode); - } - else - { - operands[2] = operand_subword (operands[0], 1, 0, DImode); - operands[3] = operand_subword (operands[1], 1, 0, DImode); - operands[4] = operand_subword (operands[0], 0, 0, DImode); - operands[5] = operand_subword (operands[1], 0, 0, DImode); - } - - if (operands[2] == 0 || operands[3] == 0 - || operands[4] == 0 || operands[5] == 0) - FAIL; - - /* We must be sure to make two different SCRATCH operands, since they - are not allowed to be shared. After reload, however, we only have - a SCRATCH if we won't use the operand, so it is allowed to share it - then. */ - if (reload_completed || GET_CODE (operands[6]) != SCRATCH) - operands[7] = operands[8] = operands[6]; - else - { - operands[7] = gen_rtx (SCRATCH, SImode); - operands[8] = gen_rtx (SCRATCH, SImode); - } -}") - -;; Define move insns for SF, and DF. -;; -;; For register-register copies or a copy of something to itself, emit a -;; single SET insn since it will likely be optimized away. -;; -;; Otherwise, emit a floating-point move operation unless both input and -;; output are either constant, memory, or a non-floating-point hard register. -(define_expand "movdf" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" "")) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - " -{ rtx op0 = operands[0]; - rtx op1 = operands[1]; - - if (op0 == op1) - { - emit_insn (gen_rtx (SET, VOIDmode, op0, op1)); - DONE; - } - - if ((GET_CODE (op0) == MEM - || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER - && ! FP_REGNO_P (REGNO (op0)))) - && (GET_CODE (op1) == MEM - || GET_CODE (op1) == CONST_DOUBLE - || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER - && ! FP_REGNO_P (REGNO (op1)) && ! rtx_equal_p (op0, op1)))) - { - rtx insns; - - if (GET_CODE (op1) == CONST_DOUBLE) - op1 = force_const_mem (DFmode, op1); - - start_sequence (); - if (GET_CODE (operands[0]) != REG - || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1]), 0) - { - emit_move_insn (operand_subword (op0, 0, 1, DFmode), - operand_subword_force (op1, 0, DFmode)); - emit_move_insn (operand_subword (op0, 1, 1, DFmode), - operand_subword_force (op1, 1, DFmode)); - } - else - { - emit_move_insn (operand_subword (op0, 1, 1, DFmode), - operand_subword_force (op1, 1, DFmode)); - emit_move_insn (operand_subword (op0, 0, 1, DFmode), - operand_subword_force (op1, 0, DFmode)); - } - - insns = get_insns (); - end_sequence (); - - emit_no_conflict_block (insns, op0, op1, 0, op1); - DONE; - } -}") - -(define_expand "movsf" - [(parallel [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" "")) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - " -{ rtx op0 = operands[0]; - rtx op1 = operands[1]; - - if (op0 == op1) - { - emit_insn (gen_rtx (SET, VOIDmode, op0, op1)); - DONE; - } - - if ((GET_CODE (op0) == MEM - || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER - && ! FP_REGNO_P (REGNO (op0)))) - && (GET_CODE (op1) == MEM - || GET_CODE (op1) == CONST_DOUBLE - || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER - && ! FP_REGNO_P (REGNO (op1))))) - { - rtx last; - - if (GET_CODE (op1) == CONST_DOUBLE) - op1 = force_const_mem (SFmode, op1); - - last = emit_move_insn (operand_subword (op0, 0, 1, SFmode), - operand_subword_force (op1, 0, SFmode)); - - REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, op1, REG_NOTES (last)); - DONE; - } -}") - -;; Define the move insns for SF and DF. Check for all general regs -;; in the FP insns and make them non-FP if so. Do the same if the input and -;; output are the same (the insn will be deleted in this case and we don't -;; want to think there are FP insns when there might not be). -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=*frg") - (match_dup 0))] - "" - "nopr r0" - [(set_attr "type" "address") - (set_attr "length" "2")]) - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=r,*fr,r,r,Q,m,frg") - (match_operand:SF 1 "general_operand" "r,0,Q,m,r,r,frg")) - (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z")) - (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))] - "" - "* -{ switch (which_alternative) - { - case 0: - return \"cas %0,%1,r0\"; - case 1: - return \"nopr r0\"; - case 2: - return \"l%M1 %0,%1\"; - case 3: - return \"load %0,%1\"; - case 4: - return \"st%M0 %1,%0\"; - case 5: - return \"store %1,%0,%3\"; - default: - return output_fpop (SET, operands[0], operands[1], 0, insn); - } -}" - [(set_attr "type" "address,address,load,load,store,store,fp") - (set_attr "length" "2,2,*,*,*,*,*")]) - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=*frg") - (match_dup 0))] - "" - "nopr r0" - [(set_attr "type" "address") - (set_attr "length" "2")]) - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=r,*fr,r,r,Q,m,frg") - (match_operand:DF 1 "general_operand" "r,0,Q,m,r,r,*frg")) - (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z")) - (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))] - "" - "* -{ switch (which_alternative) - { - case 0: - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"cas %O0,%O1,r0\;cas %0,%1,r0\"; - else - return \"cas %0,%1,r0\;cas %O0,%O1,r0\"; - case 1: - return \"nopr r0\"; - case 2: - /* Here we must see which word to load first. We default to the - low-order word unless it occurs in the address. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"l%M1 %O0,%O1\;l%M1 %0,%1\"; - else - return \"l%M1 %0,%1\;l%M1 %O0,%O1\"; - case 3: - return \"get %3,$%1\;ls %0,0(%3)\;ls %O0,4(%3)\"; - case 4: - return \"st%M0 %1,%0\;st%M0 %O1,%O0\"; - case 5: - return \"get %3,$%0\;sts %1,0(%3)\;sts %O1,4(%3)\"; - default: - return output_fpop (SET, operands[0], operands[1], 0, insn); - } -}" - [(set_attr "type" "address,multi,multi,multi,multi,multi,fp") - (set_attr "length" "2,4,*,*,*,*,*")]) - -;; Split all the above cases that involve multiple insns and no floating-point -;; data block. If before reload, we can make a SCRATCH. Otherwise, use -;; register 15. - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "symbolic_memory_operand" "")) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))] - "GET_CODE (operands[0]) == REG && REGNO (operands[0]) < 16" - [(set (reg:SI 15) (match_dup 2)) - (set (match_dup 3) (match_dup 4)) - (set (match_dup 5) (match_dup 6))] - " -{ operands[2] = XEXP (operands[1], 0); - operands[3] = operand_subword (operands[0], 0, 0, DFmode); - operands[4] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15)); - operands[5] = operand_subword (operands[0], 1, 0, DFmode); - operands[6] = gen_rtx (MEM, SImode, - gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15), - gen_rtx (CONST_INT, VOIDmode, 4))); - - if (operands[3] == 0 || operands[5] == 0) - FAIL; -}") - -(define_split - [(set (match_operand:DF 0 "symbolic_memory_operand" "") - (match_operand:DF 1 "register_operand" "")) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))] - "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 16" - [(set (reg:SI 15) (match_dup 2)) - (set (match_dup 3) (match_dup 4)) - (set (match_dup 5) (match_dup 6))] - " -{ operands[2] = XEXP (operands[0], 0); - operands[3] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15)); - operands[4] = operand_subword (operands[1], 0, 0, DFmode); - operands[5] = gen_rtx (MEM, SImode, - gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15), - gen_rtx (CONST_INT, VOIDmode, 4))); - operands[6] = operand_subword (operands[1], 1, 0, DFmode); - - if (operands[4] == 0 || operands[6] == 0) - FAIL; -}") - -;; If the output is a register and the input is memory, we have to be careful -;; and see which word needs to be loaded first. We also cannot to the -;; split if the input is a constant because it would result in invalid -;; insns. When the output is a MEM, we must put a CLOBBER on each of the -;; resulting insn, when it is not a MEM, we must not. -(define_split - [(set (match_operand:DF 0 "memory_operand" "") - (match_operand:DF 1 "register_operand" "")) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))] - "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 15" - [(parallel [(set (match_dup 2) (match_dup 3)) - (clobber (match_dup 6))]) - (parallel [(set (match_dup 4) (match_dup 5)) - (clobber (match_dup 7))])] - " -{ operands[2] = operand_subword (operands[0], 0, 0, DFmode); - operands[3] = operand_subword (operands[1], 0, 0, DFmode); - operands[4] = operand_subword (operands[0], 1, 0, DFmode); - operands[5] = operand_subword (operands[1], 1, 0, DFmode); - - if (operands[2] == 0 || operands[3] == 0 - || operands[4] == 0 || operands[5] == 0) - FAIL; - - if (reload_completed) - operands[6] = operands[7] = gen_rtx (REG, SImode, 15); - else - { - operands[6] = gen_rtx (SCRATCH, SImode); - operands[7] = gen_rtx (SCRATCH, SImode); - } -}") - -(define_split - [(set (match_operand:DF 0 "nonmemory_operand" "") - (match_operand:DF 1 "general_operand" "")) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))] - "! symbolic_memory_operand (operands[1], DFmode) - && GET_CODE (operands[1]) != CONST_DOUBLE - && (GET_CODE (operands[0]) != REG || REGNO (operands[0]) < 15) - && (GET_CODE (operands[1]) != REG || REGNO (operands[1]) < 15) - && (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG) - && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG - && ! reload_completed - && reg_overlap_mentioned_p (operands[0], operands[1]))" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - " -{ if (GET_CODE (operands[0]) != REG - || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - { - operands[2] = operand_subword (operands[0], 0, 0, DFmode); - operands[3] = operand_subword (operands[1], 0, 0, DFmode); - operands[4] = operand_subword (operands[0], 1, 0, DFmode); - operands[5] = operand_subword (operands[1], 1, 0, DFmode); - } - else - { - operands[2] = operand_subword (operands[0], 1, 0, DFmode); - operands[3] = operand_subword (operands[1], 1, 0, DFmode); - operands[4] = operand_subword (operands[0], 0, 0, DFmode); - operands[5] = operand_subword (operands[1], 0, 0, DFmode); - } - - if (operands[2] == 0 || operands[3] == 0 - || operands[4] == 0 || operands[5] == 0) - FAIL; -}") - -;; Conversions from one integer mode to another. -;; It is possible sometimes to sign- or zero-extend while fetching from memory. -;; -;; First, sign-extensions: -(define_expand "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=b") - (sign_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))] - "" - "loadha %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,b") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))] - "" - "@ - exts %0,%1 - lha%M1 %0,%1 - loadha %0,%1" - [(set_attr "type" "arith,load,load") - (set_attr "length" "2,*,*")]) - -(define_expand "extendqisi2" - [(set (match_dup 2) - (ashift:SI (match_operand:QI 1 "register_operand" "") - (const_int 24))) - (set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_dup 2) - (const_int 24)))] - "" - " -{ operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_reg_rtx (SImode); }") - -(define_expand "extendqihi2" - [(set (match_dup 2) - (ashift:SI (match_operand:QI 1 "register_operand" "") - (const_int 24))) - (set (match_operand:HI 0 "register_operand" "") - (ashiftrt:SI (match_dup 2) - (const_int 24)))] - "" - " -{ operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_reg_rtx (SImode); }") - -;; Define peepholes to eliminate an instruction when we are doing a sign -;; extension but cannot clobber the input. -;; -;; In this case we will shift left 24 bits, but need a copy first. The shift -;; can be replaced by a "mc03" instruction, but this can only be done if -;; followed by the right shift of 24 or more bits. -(define_peephole - [(set (match_operand:SI 0 "register_operand" "") - (subreg:SI (match_operand:QI 1 "register_operand" "") 0)) - (set (match_dup 0) - (ashift:SI (match_dup 0) - (const_int 24))) - (set (match_dup 0) - (ashiftrt:SI (match_dup 0) - (match_operand:SI 2 "const_int_operand" "")))] - "INTVAL (operands[2]) >= 24" - "mc03 %0,%1\;sari16 %0,%S2" - [(set_attr "type" "multi") - (set_attr "length" "4") - (set_attr "cc" "sets")]) - -;; Now zero extensions: -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=b") - (zero_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))] - "" - "loadh %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,b") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))] - "" - "@ - nilz %0,%1,65535 - lh%N1 %0,%1 - loadh %0,%1" - [(set_attr "type" "arith,loadz,load")]) - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=b") - (zero_extend:SI (match_operand:QI 1 "symbolic_memory_operand" "m")))] - "" - "loadc %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,b") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))] - "" - "@ - nilz %0,%1,255 - lc%M1 %0,%1 - loadc %0,%1" - [(set_attr "type" "arith,load,load")]) - -(define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=b") - (zero_extend:HI (match_operand:QI 1 "symbolic_memory_operand" "m")))] - "" - "loadc %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r,b") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))] - "" - "@ - nilz %0,%1,255 - lc%M1 %0,%1 - loadc %0,%1" - [(set_attr "type" "arith,load,load")]) - -;; Various extract and insertion operations. -(define_expand "extzv" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extract:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "") - (match_operand:SI 3 "const_int_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8) - FAIL; - - if (GET_CODE (operands[3]) != CONST_INT) - FAIL; - - if (INTVAL (operands[3]) != 0 && INTVAL (operands[3]) != 8 - && INTVAL (operands[3]) != 16 && INTVAL (operands[3]) != 24) - FAIL; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=&r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 8) - (match_operand:SI 2 "const_int_operand" "n")))] - "(INTVAL (operands[2]) & 7) == 0" - "lis %0,0\;mc3%B2 %0,%1" - [(set_attr "type" "multi") - (set_attr "cc" "change0")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "=&r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 8) - (match_operand:SI 2 "const_int_operand" "n")))] - "(INTVAL (operands[2]) & 7) == 0" - [(set (match_dup 0) (const_int 0)) - (set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 24)) - (zero_extract:SI (match_dup 1) (const_int 8) (match_dup 2)))] - "") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (const_int 8) - (const_int 24)) - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 8) - (match_operand:SI 2 "const_int_operand" "n")))] - "(INTVAL (operands[2]) & 7) == 0" - "mc3%B2 %0,%1" - [(set_attr "type" "address") - (set_attr "length" "2")]) - -(define_expand "insv" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" "") - (match_operand:SI 2 "const_int_operand" "")) - (match_operand:SI 3 "register_operand" ""))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - FAIL; - - if (GET_CODE (operands[1]) != CONST_INT) - FAIL; - - if (INTVAL (operands[1]) == 1) - { - emit_insn (gen_bit_insv (operands[0], operands[1], operands[2], - operands[3])); - DONE; - } - else if (INTVAL (operands[1]) == 8 - && (INTVAL (operands[2]) % 8 == 0)) - ; /* Accept aligned byte-wide field. */ - else - FAIL; -}") - -;; For a single-bit insert, it is better to explicitly generate references -;; to the T bit. We will call the T bit "CC0" because it can be clobbered -;; by some CC0 sets (single-bit tests). - -(define_expand "bit_insv" - [(set (cc0) - (zero_extract:SI (match_operand:SI 3 "register_operand" "") - (const_int 1) - (const_int 31))) - (parallel [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" "") - (match_operand:SI 2 "const_int_operand" "")) - (ne (cc0) (const_int 0))) - (clobber (match_scratch:SI 4 ""))])] - "" - "") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (const_int 8) - (match_operand:SI 1 "const_int_operand" "n")) - (match_operand:SI 2 "register_operand" "r"))] - "(INTVAL (operands[1]) & 7) == 0" - "mc%B1%.3 %0,%2" - [(set_attr "type" "address") - (set_attr "length" "2")]) - -;; This pattern cannot have any input reloads since if references CC0. -;; So we have to add code to support memory, which is the only other -;; thing that a "register_operand" can become. There is still a problem -;; if the address isn't valid and *it* needs a reload, but there is no -;; way to solve that problem, so let's hope it never happens. - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,m") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n,m")) - (ne (cc0) (const_int 0))) - (clobber (match_scratch:SI 2 "=X,b"))] - "" - "@ - mftbi%t1 %0,%S1 - l%M0 %2,%0\;mftb%t1 %2,%S1\;st%M0 %2,%0" - [(set_attr "type" "*,multi") - (set_attr "cc" "none,none") - (set_attr "length" "2,10")]) - -;; Arithmetic instructions. First, add and subtract. -;; -;; It may be that the second input is either large or small enough that -;; the operation cannot be done in a single insn. In that case, emit two. -(define_expand "addsi3" - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT - && (unsigned) (INTVAL (operands[2]) + 0x8000) >= 0x10000 - && (INTVAL (operands[2]) & 0xffff) != 0) - { - int low = INTVAL (operands[2]) & 0xffff; - int high = (unsigned) INTVAL (operands[2]) >> 16; - - if (low & 0x8000) - high++, low |= 0xffff0000; - - emit_insn (gen_addsi3 (operands[0], operands[1], - gen_rtx (CONST_INT, VOIDmode, high << 16))); - operands[1] = operands[0]; - operands[2] = gen_rtx (CONST_INT, VOIDmode, low); - } -}") - -;; Put the insn to add a symbolic constant to a register separately to -;; improve register allocation since it has different register requirements. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=b") - (plus:SI (match_operand:SI 1 "register_operand" "%b") - (match_operand:SI 2 "romp_symbolic_operand" "s")))] - "" - "get %0,$%2(%1)" - [(set_attr "type" "address") - (set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,b") - (plus:SI (match_operand:SI 1 "reg_or_add_operand" "%0,0,r,b,0,r,b") - (match_operand:SI 2 "reg_or_add_operand" "I,J,K,M,r,b,s")))] - "register_operand (operands[1], SImode) - || register_operand (operands[2], SImode)" - "@ - ais %0,%2 - sis %0,%n2 - ail %0,%1,%2 - cau %0,%H2(%1) - a %0,%2 - cas %0,%1,%2 - get %0,$%2(%1)" - [(set_attr "type" "arith,arith,arith,address,arith,address,misc") - (set_attr "length" "2,2,4,4,2,2,8")]) - -;; Now subtract. -;; -;; 1. If third operand is constant integer, convert it to add of the negative -;; of that integer. -;; 2. If the second operand is not a valid constant integer, force it into a -;; register. -(define_expand "subsi3" - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_operand:SI 1 "reg_or_any_cint_operand" "") - (match_operand:SI 2 "reg_or_any_cint_operand" "")))] - "" - " -{ - if (GET_CODE (operands [2]) == CONST_INT) - { - emit_insn (gen_addsi3 (operands[0], operands[1], - gen_rtx (CONST_INT, - VOIDmode, - INTVAL (operands[2])))); - DONE; - } - else - operands[2] = force_reg (SImode, operands[2]); - - if (GET_CODE (operands[1]) != CONST_INT - || (unsigned) (INTVAL (operands[1]) + 0x8000) >= 0x10000) - operands[1] = force_reg (SImode, operands[1]); -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (minus:SI (match_operand:SI 1 "reg_or_D_operand" "K,0,r") - (match_operand:SI 2 "register_operand" "r,r,0")))] - "" - "@ - sfi %0,%2,%1 - s %0,%2 - sf %0,%1" - [(set_attr "length" "4,2,2")]) - -;; Multiply either calls a special RT routine or is done in-line, depending -;; on the value of a -m flag. -;; -;; First define the way we call the subroutine. -(define_expand "mulsi3_subr" - [(set (reg:SI 2) (match_operand:SI 1 "register_operand" "")) - (set (reg:SI 3) (match_operand:SI 2 "register_operand" "")) - (parallel [(set (reg:SI 2) (mult:SI (reg:SI 2) (reg:SI 3))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))]) - (set (match_operand:SI 0 "register_operand" "") - (reg:SI 2))] - "" - "") - -(define_expand "mulsi3" - [(set (match_operand:SI 0 "register_operand" "") - (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")))] - "" - " -{ - if (! TARGET_IN_LINE_MUL) - { - emit_insn (gen_mulsi3_subr (operands[0], operands[1], operands[2])); - DONE; - } -}") - -;; Define the patterns to match. -;; We would like to provide a delay slot for the insns that call internal -;; routines, but doing so is risky since reorg will think that the use of -;; r2 and r3 is completed in the insn needing the delay slot. Also, it -;; won't know that the cc will be clobbered. So take the safe approach -;; and don't give them delay slots. -(define_insn "" - [(set (reg:SI 2) - (mult:SI (reg:SI 2) (reg:SI 3))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))] - "! TARGET_IN_LINE_MUL" - "bali%# r15,lmul$$" - [(set_attr "type" "misc") - (set_attr "in_delay_slot" "no")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=&r") - (mult:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "register_operand" "r")))] - "TARGET_IN_LINE_MUL" - "* -{ return output_in_line_mul (); }" - [(set_attr "length" "38") - (set_attr "type" "multi")]) - -;; Handle divide and modulus. The same function returns both values, -;; so use divmodsi4. This divides arg 1 by arg 2 with quotient to go -;; into arg 0 and remainder in arg 3. -;; -;; We want to put REG_EQUAL notes for the two outputs. So we need a -;; function to do everything else. -(define_expand "divmodsi4_doit" - [(set (reg:SI 2) - (match_operand:SI 0 "register_operand" "")) - (set (reg:SI 3) - (match_operand:SI 1 "register_operand" "")) - (parallel [(set (reg:SI 2) (div:SI (reg:SI 2) (reg:SI 3))) - (set (reg:SI 3) (mod:SI (reg:SI 2) (reg:SI 3))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "divmodsi4" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (div:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" ""))) - (set (match_operand:SI 3 "register_operand" "") - (mod:SI (match_dup 1) (match_dup 2)))])] - "" - " -{ - rtx insn; - - emit_insn (gen_divmodsi4_doit (operands[1], operands[2])); - insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2)); - REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, - gen_rtx (DIV, SImode, operands[1], - operands[2]), - REG_NOTES (insn)); - insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3)); - REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, - gen_rtx (MOD, SImode, operands[1], - operands[2]), - REG_NOTES (insn)); - DONE; -}") - -(define_insn "" - [(set (reg:SI 2) - (div:SI (reg:SI 2) (reg:SI 3))) - (set (reg:SI 3) - (mod:SI (reg:SI 2) (reg:SI 3))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))] - "" - "bali%# r15,ldiv$$" - [(set_attr "type" "misc") - (set_attr "in_delay_slot" "no")]) - -;; Similarly for unsigned divide. -(define_expand "udivmodsi4_doit" - [(set (reg:SI 2) - (match_operand:SI 0 "register_operand" "")) - (set (reg:SI 3) - (match_operand:SI 1 "register_operand" "")) - (parallel [(set (reg:SI 2) (udiv:SI (reg:SI 2) (reg:SI 3))) - (set (reg:SI 3) (umod:SI (reg:SI 2) (reg:SI 3))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "udivmodsi4" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (udiv:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" ""))) - (set (match_operand:SI 3 "register_operand" "") - (umod:SI (match_dup 1) (match_dup 2)))])] - "" - " -{ - rtx insn; - - emit_insn (gen_udivmodsi4_doit (operands[1], operands[2])); - insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2)); - REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, - gen_rtx (UDIV, SImode, operands[1], - operands[2]), - REG_NOTES (insn)); - insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3)); - REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, - gen_rtx (UMOD, SImode, operands[1], - operands[2]), - REG_NOTES (insn)); - DONE; -}") - -(define_insn "" - [(set (reg:SI 2) - (udiv:SI (reg:SI 2) (reg:SI 3))) - (set (reg:SI 3) - (umod:SI (reg:SI 2) (reg:SI 3))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))] - "" - "bali%# r15,uldiv$$" - [(set_attr "type" "misc") - (set_attr "in_delay_slot" "no")]) - -;; Define DImode arithmetic operations. -;; -;; It is possible to do certain adds and subtracts with constants in a single -;; insn, but it doesn't seem worth the trouble. -;; -;; Don't use DEFINE_SPLIT on these because the dependency on CC can't be -;; easily tracked in that case! -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (plus:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "register_operand" "r")))] - "" - "a %O0,%O2\;ae %0,%2" - [(set_attr "type" "multi")]) - -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (minus:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "register_operand" "r")))] - "" - "s %O0,%O2\;se %0,%2" - [(set_attr "type" "multi")]) - -(define_insn "negdi2" - [(set (match_operand:DI 0 "register_operand" "=r,&r") - (neg:DI (match_operand:DI 1 "register_operand" "0,r")))] - "" - "twoc %O0,%O1\;onec %0,%1\;aei %0,%0,0" - [(set_attr "type" "multi") - (set_attr "length" "8")]) - -;; Unary arithmetic operations. -(define_insn "abssi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (abs:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "abs %0,%1" - [(set_attr "length" "2")]) - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "twoc %0,%1" - [(set_attr "length" "2")]) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "onec %0,%1" - [(set_attr "length" "2")]) - - -;; Logical insns: AND, IOR, and XOR -;; -;; If the operation is being performed on a 32-bit constant such that -;; it cannot be done in one insn, do it in two. We may lose a bit on -;; CSE in pathological cases, but it seems better doing it this way. -(define_expand "andsi3" - [(set (match_operand:SI 0 "register_operand" "") - (and:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "reg_or_any_cint_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - int top = (unsigned) INTVAL (operands[2]) >> 16; - int bottom = INTVAL (operands[2]) & 0xffff; - - if (top != 0 && top != 0xffff && bottom != 0 && bottom != 0xffff) - { - emit_insn (gen_andsi3 (operands[0], operands[1], - gen_rtx (CONST_INT, VOIDmode, - (top << 16) | 0xffff))); - operands[1] = operands[0]; - operands[2] = gen_rtx (CONST_INT, VOIDmode, 0xffff0000 | bottom); - } - } -}"); - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (and:SI (match_operand:SI 1 "reg_or_and_operand" "%0,r,0") - (match_operand:SI 2 "reg_or_and_operand" "P,LMO,r")))] - "register_operand (operands[1], SImode) - || register_operand (operands[2], SImode)" - "@ - clrb%k2 %0,%b2 - ni%z2 %0,%1,%Z2 - n %0,%2" - [(set_attr "length" "2,4,2")]) - -;; logical OR (IOR) -(define_expand "iorsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ior:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "reg_or_any_cint_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - int top = (unsigned) INTVAL (operands[2]) >> 16; - int bottom = INTVAL (operands[2]) & 0xffff; - - if (top != 0 && bottom != 0) - { - emit_insn (gen_iorsi3 (operands[0], operands[1], - gen_rtx (CONST_INT, VOIDmode, (top << 16)))); - operands[1] = operands[0]; - operands[2] = gen_rtx (CONST_INT, VOIDmode, bottom); - } - } -}"); - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (ior:SI (match_operand:SI 1 "reg_or_cint_operand" "%0,r,0") - (match_operand:SI 2 "reg_or_cint_operand" "N,LM,r")))] - "register_operand (operands[1], SImode) - || register_operand (operands[2], SImode)" - "@ - setb%h2 %0,%b2 - oi%h2 %0,%1,%H2 - o %0,%2" - [(set_attr "length" "2,4,2")]) - -;; exclusive-or (XOR) -(define_expand "xorsi3" - [(set (match_operand:SI 0 "register_operand" "") - (xor:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "reg_or_any_cint_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - int top = (unsigned) INTVAL (operands[2]) >> 16; - int bottom = INTVAL (operands[2]) & 0xffff; - - if (top == 0xffff && bottom == 0xffff) - { - emit_insn (gen_one_cmplsi2 (operands[0], operands[1])); - DONE; - } - else if (top != 0 && bottom != 0) - { - emit_insn (gen_xorsi3 (operands[0], operands[1], - gen_rtx (CONST_INT, VOIDmode, (top << 16)))); - operands[1] = operands[0]; - operands[2] = gen_rtx (CONST_INT, VOIDmode, bottom); - } - } -}"); - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (xor:SI (match_operand:SI 1 "reg_or_cint_operand" "%r,0") - (match_operand:SI 2 "reg_or_cint_operand" "LM,r")))] - "register_operand (operands[1], SImode) - || register_operand (operands[2], SImode)" - "@ - xi%h2 %0,%1,%H2 - x %0,%2" - [(set_attr "length" "4,2")]) - -;; Various shift insns -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] - "" - "@ - sar %0,%2 - sari%s2 %0,%S2" - [(set_attr "length" "2")]) - -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] - "" - "@ - sr %0,%2 - sri%s2 %0,%S2" - [(set_attr "length" "2")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (match_operand:SI 1 "register_operand" "b") - (const_int 1)))] - "" - "cas %0,%1,%1" - [(set_attr "length" "2") - (set_attr "type" "address")]) - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (ashift:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] - "" - "@ - sl %0,%2 - sli%s2 %0,%S2" - [(set_attr "length" "2")]) - -;; Function call insns: -;; -;; On the ROMP, &fcn is actually a pointer to the data area, which is passed -;; to the function in r0. &.fcn is the actual starting address of the -;; function. Also, the word at &fcn contains &.fcn. -;; -;; For both functions that do and don't return values, there are two cases: -;; where the function's address is a constant, and where it isn't. -;; -;; Operand 1 (2 for `call_value') is the number of arguments and is not used. -(define_expand "call" - [(use (match_operand:SI 0 "address_operand" "")) - (use (match_operand 1 "" ""))] - "" - " -{ - rtx reg0 = gen_rtx (REG, SImode, 0); - rtx call_insn; - - if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT) - abort(); - - operands[0] = XEXP (operands[0], 0); - if (GET_CODE (operands[0]) == SYMBOL_REF) - { - extern rtx get_symref (); - char *real_fcnname = - (char *) alloca (strlen (XSTR (operands[0], 0)) + 2); - - /* Copy the data area address to r0. */ - emit_move_insn (reg0, force_reg (SImode, operands[0])); - strcpy (real_fcnname, \".\"); - strcat (real_fcnname, XSTR (operands[0], 0)); - operands[0] = get_symref (real_fcnname); - } - else - { - rtx data_access; - - emit_move_insn (reg0, force_reg (SImode, operands[0])); - data_access = gen_rtx (MEM, SImode, operands[0]); - RTX_UNCHANGING_P (data_access) = 1; - operands[0] = copy_to_reg (data_access); - } - - call_insn = emit_call_insn (gen_call_internal (operands[0], operands[1])); - use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), reg0); - DONE; -}") - -(define_insn "call_internal" - [(call (mem:SI (match_operand:SI 0 "register_operand" "b")) - (match_operand 1 "" "g")) - (clobber (reg:SI 15))] - "" - "balr%# r15,%0" - [(set_attr "type" "call") - (set_attr "length" "2")]) - -(define_insn "" - [(call (mem:SI (match_operand:SI 0 "romp_symbolic_operand" "i")) - (match_operand 1 "" "g")) - (clobber (reg:SI 15))] - "GET_CODE (operands[0]) == SYMBOL_REF" - "bali%# r15,%0" - [(set_attr "type" "call")]) - -;; Call a function and return a value. -(define_expand "call_value" - [(use (match_operand 0 "" "")) - (use (match_operand:SI 1 "address_operand" "")) - (use (match_operand 2 "" ""))] - "" - " -{ - rtx reg0 = gen_rtx (REG, SImode, 0); - rtx call_insn; - - if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT) - abort(); - - operands[1] = XEXP (operands[1], 0); - if (GET_CODE (operands[1]) == SYMBOL_REF) - { - extern rtx get_symref (); - char *real_fcnname = - (char *) alloca (strlen (XSTR (operands[1], 0)) + 2); - - /* Copy the data area address to r0. */ - emit_move_insn (reg0,force_reg (SImode, operands[1])); - strcpy (real_fcnname, \".\"); - strcat (real_fcnname, XSTR (operands[1], 0)); - operands[1] = get_symref (real_fcnname); - } - else - { - rtx data_access; - - emit_move_insn (reg0,force_reg (SImode, operands[1])); - data_access = gen_rtx (MEM, SImode, operands[1]); - RTX_UNCHANGING_P (data_access) = 1; - operands[1] = copy_to_reg (data_access); - } - - call_insn = emit_call_insn (gen_call_value_internal (operands[0], - operands[1], - operands[2])); - use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), reg0); - DONE; -}") - -(define_insn "call_value_internal" - [(set (match_operand 0 "" "=fg") - (call (mem:SI (match_operand:SI 1 "register_operand" "b")) - (match_operand 2 "" "g"))) - (clobber (reg:SI 15))] - "" - "balr%# r15,%1" - [(set_attr "length" "2") - (set_attr "type" "call")]) - -(define_insn "" - [(set (match_operand 0 "" "=fg") - (call (mem:SI (match_operand:SI 1 "romp_symbolic_operand" "i")) - (match_operand 2 "" "g"))) - (clobber (reg:SI 15))] - "GET_CODE (operands[1]) == SYMBOL_REF" - "bali%# r15,%1" - [(set_attr "type" "call")]) - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "") - -;; No operation insn. -(define_insn "nop" - [(const_int 0)] - "" - "nopr r0" - [(set_attr "type" "address") - (set_attr "length" "2") - (set_attr "cc" "none")]) - -;; Here are the floating-point operations. -;; -;; Start by providing DEFINE_EXPAND for each operation. -;; The insns will be handled with MATCH_OPERATOR; the methodology will be -;; discussed below. - -;; First the conversion operations. - -(define_expand "truncdfsf2" - [(parallel [(set (match_operand:SF 0 "general_operand" "") - (float_truncate:SF (match_operand:DF 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "extendsfdf2" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (float_extend:DF (match_operand:SF 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "floatsisf2" - [(parallel [(set (match_operand:SF 0 "general_operand" "") - (float:SF (match_operand:SI 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "floatsidf2" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (float:DF (match_operand:SI 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "fix_truncsfsi2" - [(parallel [(set (match_operand:SI 0 "general_operand" "") - (fix:SI (match_operand:SF 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "fix_truncdfsi2" - [(parallel [(set (match_operand:SI 0 "general_operand" "") - (fix:SI (match_operand:DF 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -;; Now the binary operations. - -(define_expand "addsf3" - [(parallel [(set (match_operand:SF 0 "general_operand" "") - (plus:SF (match_operand:SF 1 "general_operand" "") - (match_operand:SF 2 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "adddf3" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (plus:DF (match_operand:DF 1 "general_operand" "") - (match_operand:DF 2 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "subsf3" - [(parallel [(set (match_operand:SF 0 "general_operand" "") - (minus:SF (match_operand:SF 1 "general_operand" "") - (match_operand:SF 2 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "subdf3" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (minus:DF (match_operand:DF 1 "general_operand" "") - (match_operand:DF 2 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "mulsf3" - [(parallel [(set (match_operand:SF 0 "general_operand" "") - (mult:SF (match_operand:SF 1 "general_operand" "") - (match_operand:SF 2 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "muldf3" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (mult:DF (match_operand:DF 1 "general_operand" "") - (match_operand:DF 2 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "divsf3" - [(parallel [(set (match_operand:SF 0 "general_operand" "") - (div:SF (match_operand:SF 1 "general_operand" "") - (match_operand:SF 2 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "divdf3" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (div:DF (match_operand:DF 1 "general_operand" "") - (match_operand:DF 2 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -;; Unary floating-point operations. -;; -;; Negations can be done without floating-point, since this is IEEE. -;; But we cannot do this if an operand is a hard FP register, since -;; the SUBREG we create would not be valid. -(define_expand "negsf2" - [(set (match_operand:SF 0 "register_operand" "") - (neg:SF (match_operand:SF 1 "register_operand" "")))] - "" - " -{ - if (! (GET_CODE (operands[0]) == REG - && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER - && FP_REGNO_P (REGNO (operands[0]))) - && ! (GET_CODE (operands[1]) == REG - && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER - && FP_REGNO_P (REGNO (operands[1])))) - { - rtx result; - rtx target = operand_subword (operands[0], 0, 1, SFmode); - - result = expand_binop (SImode, xor_optab, - operand_subword_force (operands[1], 0, SFmode), - gen_rtx (CONST_INT, VOIDmode, 0x80000000), - target, 0, OPTAB_WIDEN); - if (result == 0) - abort (); - - if (result != target) - emit_move_insn (result, target); - - /* Make a place for REG_EQUAL. */ - emit_move_insn (operands[0], operands[0]); - DONE; - } -}") - -(define_expand "negdf2" - [(set (match_operand:DF 0 "register_operand" "") - (neg:DF (match_operand:DF 1 "register_operand" "")))] - "" - " -{ - if (! (GET_CODE (operands[0]) == REG - && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER - && FP_REGNO_P (REGNO (operands[0]))) - && ! (GET_CODE (operands[1]) == REG - && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER - && FP_REGNO_P (REGNO (operands[1])))) - { - rtx result; - rtx target = operand_subword (operands[0], 0, 1, DFmode); - rtx insns; - - start_sequence (); - result = expand_binop (SImode, xor_optab, - operand_subword_force (operands[1], 0, DFmode), - gen_rtx (CONST_INT, VOIDmode, 0x80000000), - target, 0, OPTAB_WIDEN); - if (result == 0) - abort (); - - if (result != target) - emit_move_insn (result, target); - - emit_move_insn (operand_subword (operands[0], 1, 1, DFmode), - operand_subword_force (operands[1], 1, DFmode)); - - insns = get_insns (); - end_sequence (); - - emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); - DONE; - } -}") - -(define_expand "abssf2" - [(parallel [(set (match_operand:SF 0 "general_operand" "") - (abs:SF (match_operand:SF 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "absdf2" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (abs:DF (match_operand:DF 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -;; Any floating-point operation can be either SFmode or DFmode, and each -;; operand (including the output) can be either a normal operand or a -;; conversion from a normal operand. -;; -;; We use MATCH_OPERATOR to match a floating-point binary or unary operator -;; and input and output conversions. So we need 2^N patterns for each type -;; of operation, where N is the number of operands, including the output. -;; There are thus a total of 14 patterns, 8 for binary operations, 4 for -;; unary operations and two for conversion/move operations (only one -;; operand can have a conversion for move operations). In addition, we have -;; to be careful that a floating-point reload register doesn't get allocated -;; for an integer. We take care of this for inputs with PREFERRED_RELOAD_CLASS -;; but need to have two different constraints for outputs. This means that -;; we have to duplicate each pattern where the output could be an integer. -;; This adds another 7 patterns, for a total of 21. - -;; Start with conversion operations (moves are done above). - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=g") - (match_operator 1 "float_conversion" - [(match_operand 2 "general_operand" "frg")])) - (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] - "" - "* -{ return output_fpop (SET, operands[0], operands[2], 0, insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_conversion" - [(match_operand 2 "general_operand" "frg")])) - (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] - "" - "* -{ return output_fpop (SET, operands[0], operands[2], 0, insn); -}" - [(set_attr "type" "fp")]) - -;; Next, binary floating-point operations. - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_binary" - [(match_operand 2 "general_operand" "frg") - (match_operand 3 "general_operand" "frg")])) - (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[1]), operands[2], operands[3])" - "* -{ return output_fpop (GET_CODE (operands[1]), operands[0], - operands[2], operands[3], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_binary" - [(match_operand 2 "general_operand" "frg") - (match_operator 3 "float_conversion" - [(match_operand 4 "general_operand" "frg")])])) - (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[1]), operands[2], operands[4])" - "* -{ return output_fpop (GET_CODE (operands[1]), operands[0], - operands[2], operands[4], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_binary" - [(match_operator 2 "float_conversion" - [(match_operand 3 "general_operand" "frg")]) - (match_operand 4 "general_operand" "frg")])) - (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[1]), operands[3], operands[4])" - "* -{ return output_fpop (GET_CODE (operands[1]), operands[0], - operands[3], operands[4], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_binary" - [(match_operator 2 "float_conversion" - [(match_operand 3 "general_operand" "frg")]) - (match_operator 4 "float_conversion" - [(match_operand 5 "general_operand" "frg")])])) - (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[1]), operands[3], operands[5])" - "* -{ return output_fpop (GET_CODE (operands[1]), operands[0], - operands[3], operands[5], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=g") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_binary" - [(match_operand 3 "general_operand" "frg") - (match_operand 4 "general_operand" "frg")])])) - (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[3], operands[4])" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], - operands[3], operands[4], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_binary" - [(match_operand 3 "general_operand" "frg") - (match_operand 4 "general_operand" "frg")])])) - (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[3], operands[4])" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], - operands[3], operands[4], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=g") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_binary" - [(match_operand 3 "general_operand" "frg") - (match_operator 4 "float_conversion" - [(match_operand 5 "general_operand" "frg")])])])) - (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[3], operands[4])" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], - operands[3], operands[5], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_binary" - [(match_operand 3 "general_operand" "frg") - (match_operator 4 "float_conversion" - [(match_operand 5 "general_operand" "frg")])])])) - (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[3], operands[4])" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], - operands[3], operands[5], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=g") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_binary" - [(match_operator 3 "float_conversion" - [(match_operand 4 "general_operand" "frg")]) - (match_operand 5 "general_operand" "frg")])])) - (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[4], operands[5])" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], - operands[4], operands[5], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_binary" - [(match_operator 3 "float_conversion" - [(match_operand 4 "general_operand" "frg")]) - (match_operand 5 "general_operand" "frg")])])) - (clobber (match_operand:SI 6 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[4], operands[5])" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], - operands[4], operands[5], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=g") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_binary" - [(match_operator 3 "float_conversion" - [(match_operand 4 "general_operand" "frg")]) - (match_operator 5 "float_conversion" - [(match_operand 6 "general_operand" "frg")])])])) - (clobber (match_operand:SI 7 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 8 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[4], operands[6])" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], - operands[4], operands[6], insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_binary" - [(match_operator 3 "float_conversion" - [(match_operand 4 "general_operand" "frg")]) - (match_operator 5 "float_conversion" - [(match_operand 6 "general_operand" "frg")])])])) - (clobber (match_operand:SI 7 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 8 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[4], operands[6])" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], - operands[4], operands[6], insn); -}" - [(set_attr "type" "fp")]) - -;; Unary floating-point operations. - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_unary" - [(match_operand 2 "general_operand" "frg")])) - (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[1]), operands[2], 0)" - "* -{ return output_fpop (GET_CODE (operands[1]), operands[0], operands[2], - 0, insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_unary" - [(match_operator 2 "float_conversion" - [(match_operand 3 "general_operand" "frg")])])) - (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[1]), operands[3], 0)" - "* -{ return output_fpop (GET_CODE (operands[1]), operands[0], operands[3], - 0, insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=g") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_unary" - [(match_operand 3 "general_operand" "frg")])])) - (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[3], 0)" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], operands[3], - 0, insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_unary" - [(match_operand 3 "general_operand" "frg")])])) - (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[3], 0)" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], operands[3], - 0, insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=g") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_unary" - [(match_operator 3 "float_conversion" - [(match_operand 4 "general_operand" "frg")])])])) - (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[4], 0)" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], operands[4], - 0, insn); -}" - [(set_attr "type" "fp")]) - -(define_insn "" - [(set (match_operand 0 "general_operand" "=frg") - (match_operator 1 "float_conversion" - [(match_operator 2 "float_unary" - [(match_operator 3 "float_conversion" - [(match_operand 4 "general_operand" "frg")])])])) - (clobber (match_operand:SI 5 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))] - "check_precision (GET_MODE (operands[2]), operands[4], 0)" - "* -{ return output_fpop (GET_CODE (operands[2]), operands[0], operands[4], - 0, insn); -}" - [(set_attr "type" "fp")]) - -;; Compare insns are next. Note that the ROMP has two types of compares, -;; signed & unsigned, and one type of branch. Use the routine -;; `next_insn_tests_no_unsigned' to see which type to use. -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "register_operand" "r"))] - "" - "") - -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "reg_or_cint_operand" "")))] - "" - "") - -;; Signed compare, `test' first. - -(define_insn "" - [(set (cc0) - (match_operand:SI 0 "register_operand" "r"))] - "next_insn_tests_no_unsigned (insn)" - "cis %0,0" - [(set_attr "length" "2") - (set_attr "type" "compare")]) - -(define_insn "" - [(set (cc0) (match_operand:SI 0 "register_operand" "r,r,r")) - (set (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "=0,r,Q") - (match_dup 0))] - "next_insn_tests_no_unsigned (insn)" - "@ - cis %1,0 - nilo %1,%0,65535 - st%M1 %0,%1\;cis %0,0" - [(set_attr "type" "compare,compare,store") - (set_attr "length" "2,4,6") - (set_attr "cc" "compare")]) - -(define_insn "" - [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r,r,r") - (match_operand:SI 1 "reg_or_cint_operand" "I,K,r")))] - "next_insn_tests_no_unsigned (insn)" - "@ - cis %0,%1 - cil %0,%1 - c %0,%1" - [(set_attr "length" "2,4,2") - (set_attr "type" "compare")]) - -;; Unsigned comparisons, `test' first, again. -(define_insn "" - [(set (cc0) - (match_operand:SI 0 "register_operand" "r"))] - "! next_insn_tests_no_unsigned (insn)" - "clil %0,0" - [(set_attr "type" "compare")]) - -(define_insn "" - [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r,r") - (match_operand:SI 1 "reg_or_cint_operand" "K,r")))] - "! next_insn_tests_no_unsigned (insn)" - "@ - clil %0,%1 - cl %0,%1" - [(set_attr "length" "4,2") - (set_attr "type" "compare")]) - -;; Bit test insn. Many cases are converted into this by combine. This -;; uses the ROMP test bit. - -(define_insn "" - [(set (cc0) - (zero_extract (match_operand:SI 0 "register_operand" "r,r") - (const_int 1) - (match_operand:SI 1 "reg_or_any_cint_operand" "r,n")))] - "next_insn_tests_no_inequality (insn)" - "@ - mttb %0,%1 - mttbi%t1 %0,%S1" - [(set_attr "length" "2") - (set_attr "type" "compare") - (set_attr "cc" "tbit")]) - -;; Floating-point comparisons. There are two, equality and order. -;; The difference will be that a trap for NaN will be given on the orderr -;; comparisons only. - -(define_expand "cmpsf" - [(parallel [(set (cc0) (compare (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "cmpdf" - [(parallel [(set (cc0) (compare (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "tstsf" - [(parallel [(set (cc0) (match_operand:SF 0 "general_operand" "")) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -(define_expand "tstdf" - [(parallel [(set (cc0) (match_operand:DF 0 "general_operand" "")) - (clobber (reg:SI 0)) - (clobber (reg:SI 15))])] - "" - "") - -;; There are four cases for compare and two for test. These correspond -;; to each input having a floating-point conversion or not. - -(define_insn "" - [(set (cc0) (compare (match_operand 0 "general_operand" "frg") - (match_operand 1 "general_operand" "frg"))) - (clobber (match_operand:SI 2 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 3 "reg_15_operand" "=&t"))] - "GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode" - "* -{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, - operands[0], operands[1], 0, insn); -}" - [(set_attr "type" "fp") - (set_attr "cc" "compare")]) - -(define_insn "" - [(set (cc0) (compare (match_operand 0 "general_operand" "frg") - (match_operator 1 "float_conversion" - [(match_operand 2 "general_operand" "frg")]))) - (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] - "" - "* -{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, - operands[0], operands[2], 0, insn); -}" - [(set_attr "type" "fp") - (set_attr "cc" "compare")]) - -(define_insn "" - [(set (cc0) (compare (match_operator 0 "float_conversion" - [(match_operand 1 "general_operand" "frg")]) - (match_operand 2 "general_operand" "frg"))) - (clobber (match_operand:SI 3 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))] - "" - "* -{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, - operands[1], operands[2], 0, insn); -}" - [(set_attr "type" "fp") - (set_attr "cc" "compare")]) - -(define_insn "" - [(set (cc0) (compare (match_operator 0 "float_conversion" - [(match_operand 1 "general_operand" "frg")]) - (match_operator 2 "float_conversion" - [(match_operand 3 "general_operand" "frg")]))) - (clobber (match_operand:SI 4 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))] - "" - "* -{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, - operands[1], operands[3], 0, insn); -}" - [(set_attr "type" "fp") - (set_attr "cc" "compare")]) - -(define_insn "" - [(set (cc0) (match_operand 0 "general_operand" "frg")) - (clobber (match_operand:SI 1 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 2 "reg_15_operand" "=&t"))] - "GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode" - "* -{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, - operands[0], CONST0_RTX (GET_MODE (operands[0])), - 0, insn); -}" - [(set_attr "type" "fp") - (set_attr "cc" "compare")]) - -(define_insn "" - [(set (cc0) (match_operator 0 "float_conversion" - [(match_operand 1 "general_operand" "frg")])) - (clobber (match_operand:SI 2 "reg_0_operand" "=&z")) - (clobber (match_operand:SI 3 "reg_15_operand" "=&t"))] - "" - "* -{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE, - operands[1], CONST0_RTX (GET_MODE (operands[1])), - 0, insn); -}" - [(set_attr "type" "fp") - (set_attr "cc" "compare")]) - -;; Branch insns. Unsigned vs. signed have already -;; been taken care of. The only insns that need to be concerned about the -;; test bit are beq and bne because the rest are either always true, -;; always false, or converted to EQ or NE. - -;; For conditional branches, we use `define_expand' and just have two patterns -;; that match them. Operand printing does most of the work. - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -;; Define both directions of branch and return. - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - if (restore_compare_p (operands[1])) - return 0; - else if (get_attr_length (insn) == 2) - return \"j%j1 %l0\"; - else - return \"b%j1%# %l0\"; -}" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(cc0) (const_int 0)]) - (return) - (pc)))] - "null_epilogue ()" - "* -{ - if (restore_compare_p (operands[0])) - return 0; - else - return \"b%j0r%# r15\"; -}" - [(set_attr "type" "return")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - if (restore_compare_p (operands[1])) - return 0; - else if (get_attr_length (insn) == 2) - return \"j%J1 %l0\"; - else - return \"b%J1%# %l0\"; -}" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (return)))] - "null_epilogue ()" - "* -{ - if (restore_compare_p (operands[0])) - return 0; - else - return \"b%J0r%# r15\"; -}" - [(set_attr "type" "return")]) - -;; Unconditional branch and return. - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "* -{ - if (get_attr_length (insn) == 2) - return \"j %l0\"; - else - return \"b%# %l0\"; -}" - [(set_attr "type" "branch")]) - -(define_insn "return" - [(return)] - "null_epilogue ()" - "br%# r15" - [(set_attr "type" "return")]) - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "r"))] - "" - "br%# %0" - [(set_attr "type" "ibranch")]) - -;; Table jump for switch statements: -(define_insn "tablejump" - [(set (pc) - (match_operand:SI 0 "register_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "" - "br%# %0" - [(set_attr "type" "ibranch")]) |