rt_gccstream/gcc/config/arc/arc.md

1377 lines
41 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;; Machine description of the Argonaut ARC cpu for GNU C compiler
;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007, 2008
;; Free Software Foundation, Inc.
;; This file is part of GCC.
;; GCC 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 3, or (at your option)
;; any later version.
;; GCC 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 GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
;; ??? This is an old port, and is undoubtedly suffering from bit rot.
;; Insn type. Used to default other attribute values.
(define_attr "type"
"move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc"
(const_string "binary"))
;; Length (in # of insns, long immediate constants counted too).
;; ??? There's a nasty interaction between the conditional execution fsm
;; and insn lengths: insns with shimm values cannot be conditionally executed.
(define_attr "length" ""
(cond [(eq_attr "type" "load")
(if_then_else (match_operand 1 "long_immediate_loadstore_operand" "")
(const_int 2) (const_int 1))
(eq_attr "type" "store")
(if_then_else (match_operand 0 "long_immediate_loadstore_operand" "")
(const_int 2) (const_int 1))
(eq_attr "type" "move,unary,compare")
(if_then_else (match_operand 1 "long_immediate_operand" "")
(const_int 2) (const_int 1))
(eq_attr "type" "binary,mul")
(if_then_else (match_operand 2 "long_immediate_operand" "")
(const_int 2) (const_int 1))
(eq_attr "type" "cmove")
(if_then_else (match_operand 2 "register_operand" "")
(const_int 1) (const_int 2))
(eq_attr "type" "multi") (const_int 2)
]
(const_int 1)))
;; The length here is the length of a single asm. Unfortunately it might be
;; 1 or 2 so we must allow for 2. That's ok though. How often will users
;; lament asm's not being put in delay slots?
(define_asm_attributes
[(set_attr "length" "2")
(set_attr "type" "multi")])
;; Condition codes: this one is used by final_prescan_insn to speed up
;; conditionalizing instructions. It saves having to scan the rtl to see if
;; it uses or alters the condition codes.
;; USE: This insn uses the condition codes (e.g.: a conditional branch).
;; CANUSE: This insn can use the condition codes (for conditional execution).
;; SET: All condition codes are set by this insn.
;; SET_ZN: the Z and N flags are set by this insn.
;; SET_ZNC: the Z, N, and C flags are set by this insn.
;; CLOB: The condition codes are set to unknown values by this insn.
;; NOCOND: This insn can't use and doesn't affect the condition codes.
(define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond"
(cond [(and (eq_attr "type" "unary,binary,move")
(eq_attr "length" "1"))
(const_string "canuse")
(eq_attr "type" "compare")
(const_string "set")
(eq_attr "type" "cmove,branch")
(const_string "use")
(eq_attr "type" "multi,misc")
(const_string "clob")
]
(const_string "nocond")))
;; Delay slots.
(define_attr "in_delay_slot" "false,true"
(cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
(const_string "false")
]
(if_then_else (eq_attr "length" "1")
(const_string "true")
(const_string "false"))))
(define_delay (eq_attr "type" "call")
[(eq_attr "in_delay_slot" "true")
(eq_attr "in_delay_slot" "true")
(eq_attr "in_delay_slot" "true")])
(define_delay (eq_attr "type" "branch,uncond_branch")
[(eq_attr "in_delay_slot" "true")
(eq_attr "in_delay_slot" "true")
(eq_attr "in_delay_slot" "true")])
;; Scheduling description for the ARC
(define_cpu_unit "branch")
(define_insn_reservation "any_insn" 1 (eq_attr "type" "!load,compare,branch")
"nothing")
;; 1) A conditional jump cannot immediately follow the insn setting the flags.
;; This isn't a complete solution as it doesn't come with guarantees. That
;; is done in the branch patterns and in arc_print_operand. This exists to
;; avoid inserting a nop when we can.
(define_insn_reservation "compare" 1 (eq_attr "type" "compare")
"nothing,branch")
(define_insn_reservation "branch" 1 (eq_attr "type" "branch")
"branch")
;; 2) References to loaded registers should wait a cycle.
;; Memory with load-delay of 1 (i.e., 2 cycle load).
(define_insn_reservation "memory" 2 (eq_attr "type" "load")
"nothing")
;; Move instructions.
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
"
{
/* Everything except mem = const or mem = mem can be done easily. */
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (QImode, operands[1]);
}")
(define_insn "*movqi_insn"
[(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m")
(match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))]
;; ??? Needed?
"register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode)"
"@
mov%? %0,%1
mov%? %0,%1
ldb%U1%V1 %0,%1
stb%U0%V0 %1,%0"
[(set_attr "type" "move,move,load,store")])
;; ??? This may never match since there's no cmpqi insn.
(define_insn "*movqi_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi"))
(const_int 0)))
(set (match_operand:QI 0 "move_dest_operand" "=r")
(match_dup 1))]
""
"mov%?.f %0,%1"
[(set_attr "type" "move")
(set_attr "cond" "set_zn")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
"
{
/* Everything except mem = const or mem = mem can be done easily. */
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (HImode, operands[1]);
}")
(define_insn "*movhi_insn"
[(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m")
(match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))]
"register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode)"
"@
mov%? %0,%1
mov%? %0,%1
ldw%U1%V1 %0,%1
stw%U0%V0 %1,%0"
[(set_attr "type" "move,move,load,store")])
;; ??? Will this ever match?
(define_insn "*movhi_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi"))
(const_int 0)))
(set (match_operand:HI 0 "move_dest_operand" "=r")
(match_dup 1))]
;; ??? Needed?
"register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode)"
"mov%?.f %0,%1"
[(set_attr "type" "move")
(set_attr "cond" "set_zn")])
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"
{
/* Everything except mem = const or mem = mem can be done easily. */
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (SImode, operands[1]);
}")
(define_insn "*movsi_insn"
[(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m")
(match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)"
"@
mov%? %0,%1
mov%? %0,%S1
ld%U1%V1 %0,%1
st%U0%V0 %1,%0"
[(set_attr "type" "move,move,load,store")])
(define_insn "*movsi_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(match_operand:SI 1 "move_src_operand" "rIJi")
(const_int 0)))
(set (match_operand:SI 0 "move_dest_operand" "=r")
(match_dup 1))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)"
"mov%?.f %0,%S1"
[(set_attr "type" "move")
(set_attr "cond" "set_zn")])
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
"
{
/* Everything except mem = const or mem = mem can be done easily. */
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (DImode, operands[1]);
}")
(define_insn "*movdi_insn"
[(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m")
(match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))]
"register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)"
"*
{
switch (which_alternative)
{
case 0 :
/* We normally copy the low-numbered register first. However, if
the first register operand 0 is the same as the second register of
operand 1, we must copy in the opposite order. */
if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
return \"mov %R0,%R1\;mov %0,%1\";
else
return \"mov %0,%1\;mov %R0,%R1\";
case 1 :
return \"mov %0,%L1\;mov %R0,%H1\";
case 2 :
/* If the low-address word is used in the address, we must load it
last. Otherwise, load it first. Note that we cannot have
auto-increment in that case since the address register is known to be
dead. */
if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
operands [1], 0))
return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
else
return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
case 3 :
return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
default:
gcc_unreachable ();
}
}"
[(set_attr "type" "move,move,load,store")
;; ??? The ld/st values could be 4 if it's [reg,bignum].
(set_attr "length" "2,4,2,2")])
;(define_expand "movdi"
; [(set (match_operand:DI 0 "general_operand" "")
; (match_operand:DI 1 "general_operand" ""))]
; ""
; "
;{
; /* Flow doesn't understand that this is effectively a DFmode move.
; It doesn't know that all of `operands[0]' is set. */
; emit_clobber (operands[0]);
;
; /* Emit insns that movsi_insn can handle. */
; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode),
; operand_subword (operands[1], 0, 0, DImode)));
; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode),
; operand_subword (operands[1], 1, 0, DImode)));
; DONE;
;}")
;; Floating point move insns.
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
"
{
/* Everything except mem = const or mem = mem can be done easily. */
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
}")
(define_insn "*movsf_insn"
[(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")
(match_operand:SF 1 "move_src_operand" "r,E,m,r"))]
"register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)"
"@
mov%? %0,%1
mov%? %0,%1 ; %A1
ld%U1%V1 %0,%1
st%U0%V0 %1,%0"
[(set_attr "type" "move,move,load,store")])
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
"
{
/* Everything except mem = const or mem = mem can be done easily. */
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (DFmode, operands[1]);
}")
(define_insn "*movdf_insn"
[(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
(match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))]
"register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode)"
"*
{
switch (which_alternative)
{
case 0 :
/* We normally copy the low-numbered register first. However, if
the first register operand 0 is the same as the second register of
operand 1, we must copy in the opposite order. */
if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
return \"mov %R0,%R1\;mov %0,%1\";
else
return \"mov %0,%1\;mov %R0,%R1\";
case 1 :
return \"mov %0,%L1\;mov %R0,%H1 ; %A1\";
case 2 :
/* If the low-address word is used in the address, we must load it
last. Otherwise, load it first. Note that we cannot have
auto-increment in that case since the address register is known to be
dead. */
if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
operands [1], 0))
return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
else
return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
case 3 :
return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
default:
gcc_unreachable ();
}
}"
[(set_attr "type" "move,move,load,store")
;; ??? The ld/st values could be 4 if it's [reg,bignum].
(set_attr "length" "2,4,2,2")])
;(define_expand "movdf"
; [(set (match_operand:DF 0 "general_operand" "")
; (match_operand:DF 1 "general_operand" ""))]
; ""
; "
;{
; /* Flow doesn't understand that this is effectively a DFmode move.
; It doesn't know that all of `operands[0]' is set. */
; emit_clobber (operands[0]);
;
; /* Emit insns that movsi_insn can handle. */
; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode),
; operand_subword (operands[1], 0, 0, DFmode)));
; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode),
; operand_subword (operands[1], 1, 0, DFmode)));
; DONE;
;}")
;; Load/Store with update instructions.
;;
;; Some of these we can get by using pre-decrement or pre-increment, but the
;; hardware can also do cases where the increment is not the size of the
;; object.
;;
;; In all these cases, we use operands 0 and 1 for the register being
;; incremented because those are the operands that local-alloc will
;; tie and these are the pair most likely to be tieable (and the ones
;; that will benefit the most).
;;
;; We use match_operator here because we need to know whether the memory
;; object is volatile or not.
(define_insn "*loadqi_update"
[(set (match_operand:QI 3 "register_operand" "=r,r")
(match_operator:QI 4 "load_update_operand"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "rI,J")]))
(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"ldb.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "1,2")])
(define_insn "*load_zeroextendqisi_update"
[(set (match_operand:SI 3 "register_operand" "=r,r")
(zero_extend:SI (match_operator:QI 4 "load_update_operand"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "rI,J")])))
(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"ldb.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "1,2")])
(define_insn "*load_signextendqisi_update"
[(set (match_operand:SI 3 "register_operand" "=r,r")
(sign_extend:SI (match_operator:QI 4 "load_update_operand"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "rI,J")])))
(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"ldb.x.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "1,2")])
(define_insn "*storeqi_update"
[(set (match_operator:QI 4 "store_update_operand"
[(match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "short_immediate_operand" "I")])
(match_operand:QI 3 "register_operand" "r"))
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"stb.a%V4 %3,[%0,%2]"
[(set_attr "type" "store")
(set_attr "length" "1")])
(define_insn "*loadhi_update"
[(set (match_operand:HI 3 "register_operand" "=r,r")
(match_operator:HI 4 "load_update_operand"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "rI,J")]))
(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"ldw.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "1,2")])
(define_insn "*load_zeroextendhisi_update"
[(set (match_operand:SI 3 "register_operand" "=r,r")
(zero_extend:SI (match_operator:HI 4 "load_update_operand"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "rI,J")])))
(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"ldw.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "1,2")])
(define_insn "*load_signextendhisi_update"
[(set (match_operand:SI 3 "register_operand" "=r,r")
(sign_extend:SI (match_operator:HI 4 "load_update_operand"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "rI,J")])))
(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"ldw.x.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "1,2")])
(define_insn "*storehi_update"
[(set (match_operator:HI 4 "store_update_operand"
[(match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "short_immediate_operand" "I")])
(match_operand:HI 3 "register_operand" "r"))
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"stw.a%V4 %3,[%0,%2]"
[(set_attr "type" "store")
(set_attr "length" "1")])
(define_insn "*loadsi_update"
[(set (match_operand:SI 3 "register_operand" "=r,r")
(match_operator:SI 4 "load_update_operand"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "rI,J")]))
(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"ld.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "1,2")])
(define_insn "*storesi_update"
[(set (match_operator:SI 4 "store_update_operand"
[(match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "short_immediate_operand" "I")])
(match_operand:SI 3 "register_operand" "r"))
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"st.a%V4 %3,[%0,%2]"
[(set_attr "type" "store")
(set_attr "length" "1")])
(define_insn "*loadsf_update"
[(set (match_operand:SF 3 "register_operand" "=r,r")
(match_operator:SF 4 "load_update_operand"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "rI,J")]))
(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"ld.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "1,2")])
(define_insn "*storesf_update"
[(set (match_operator:SF 4 "store_update_operand"
[(match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "short_immediate_operand" "I")])
(match_operand:SF 3 "register_operand" "r"))
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
"st.a%V4 %3,[%0,%2]"
[(set_attr "type" "store")
(set_attr "length" "1")])
;; Conditional move instructions.
(define_expand "movsicc"
[(set (match_operand:SI 0 "register_operand" "")
(if_then_else:SI (match_operand 1 "comparison_operator" "")
(match_operand:SI 2 "nonmemory_operand" "")
(match_operand:SI 3 "register_operand" "")))]
""
"
{
enum rtx_code code = GET_CODE (operands[1]);
rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
XEXP (operands[1], 1));
operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
}")
(define_expand "movsfcc"
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (match_operand 1 "comparison_operator" "")
(match_operand:SF 2 "nonmemory_operand" "")
(match_operand:SF 3 "register_operand" "")))]
""
"
{
enum rtx_code code = GET_CODE (operands[1]);
rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
XEXP (operands[1], 1));
operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
}")
(define_insn "*movsicc_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(if_then_else:SI (match_operand 1 "comparison_operator" "")
(match_operand:SI 2 "nonmemory_operand" "rJi")
(match_operand:SI 3 "register_operand" "0")))]
""
"mov.%d1 %0,%S2"
[(set_attr "type" "cmove")])
(define_insn "*movsfcc_insn"
[(set (match_operand:SF 0 "register_operand" "=r,r")
(if_then_else:SF (match_operand 1 "comparison_operator" "")
(match_operand:SF 2 "nonmemory_operand" "r,E")
(match_operand:SF 3 "register_operand" "0,0")))]
""
"@
mov.%d1 %0,%2
mov.%d1 %0,%2 ; %A2"
[(set_attr "type" "cmove,cmove")])
;; Zero extension instructions.
;; ??? We don't support volatile memrefs here, but I'm not sure why.
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
""
"@
extb%? %0,%1
ldb%U1 %0,%1"
[(set_attr "type" "unary,load")])
(define_insn "*zero_extendqihi2_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:HI 0 "register_operand" "=r")
(zero_extend:HI (match_dup 1)))]
""
"extb%?.f %0,%1"
[(set_attr "type" "unary")
(set_attr "cond" "set_zn")])
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
""
"@
extb%? %0,%1
ldb%U1 %0,%1"
[(set_attr "type" "unary,load")])
(define_insn "*zero_extendqisi2_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_dup 1)))]
""
"extb%?.f %0,%1"
[(set_attr "type" "unary")
(set_attr "cond" "set_zn")])
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
""
"@
extw%? %0,%1
ldw%U1 %0,%1"
[(set_attr "type" "unary,load")])
(define_insn "*zero_extendhisi2_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_dup 1)))]
""
"extw%?.f %0,%1"
[(set_attr "type" "unary")
(set_attr "cond" "set_zn")])
;; Sign extension instructions.
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
""
"@
sexb%? %0,%1
ldb.x%U1 %0,%1"
[(set_attr "type" "unary,load")])
(define_insn "*extendqihi2_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:HI 0 "register_operand" "=r")
(sign_extend:HI (match_dup 1)))]
""
"sexb%?.f %0,%1"
[(set_attr "type" "unary")
(set_attr "cond" "set_zn")])
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
""
"@
sexb%? %0,%1
ldb.x%U1 %0,%1"
[(set_attr "type" "unary,load")])
(define_insn "*extendqisi2_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_dup 1)))]
""
"sexb%?.f %0,%1"
[(set_attr "type" "unary")
(set_attr "cond" "set_zn")])
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
""
"@
sexw%? %0,%1
ldw.x%U1 %0,%1"
[(set_attr "type" "unary,load")])
(define_insn "*extendhisi2_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_dup 1)))]
""
"sexw%?.f %0,%1"
[(set_attr "type" "unary")
(set_attr "cond" "set_zn")])
;; Arithmetic instructions.
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rIJ")))]
""
"add%? %0,%1,%2")
(define_insn "*addsi3_set_cc_insn"
[(set (reg:CC 61) (compare:CC
(plus:SI (match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rIJ"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1)
(match_dup 2)))]
""
"add%?.f %0,%1,%2"
[(set_attr "cond" "set")])
(define_insn "adddi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "nonmemory_operand" "%r")
(match_operand:DI 2 "nonmemory_operand" "ri")))
(clobber (reg:CC 61))]
""
"*
{
rtx op2 = operands[2];
if (GET_CODE (op2) == CONST_INT)
{
int sign = INTVAL (op2);
if (sign < 0)
return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\";
else
return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\";
}
else
return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\";
}"
[(set_attr "length" "2")])
(define_insn "subsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "nonmemory_operand" "rIJ")))]
""
"sub%? %0,%1,%2")
(define_insn "*subsi3_set_cc_insn"
[(set (reg:CC 61) (compare:CC
(minus:SI (match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rIJ"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_dup 1)
(match_dup 2)))]
""
"sub%?.f %0,%1,%2"
[(set_attr "cond" "set")])
(define_insn "subdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_operand:DI 1 "nonmemory_operand" "r")
(match_operand:DI 2 "nonmemory_operand" "ri")))
(clobber (reg:CC 61))]
""
"*
{
rtx op2 = operands[2];
if (GET_CODE (op2) == CONST_INT)
{
int sign = INTVAL (op2);
if (sign < 0)
return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\";
else
return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\";
}
else
return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\";
}"
[(set_attr "length" "2")])
;; Boolean instructions.
;;
;; We don't define the DImode versions as expand_binop does a good enough job.
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rIJ")))]
""
"and%? %0,%1,%2")
(define_insn "*andsi3_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(and:SI (match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rIJ"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (match_dup 1)
(match_dup 2)))]
""
"and%?.f %0,%1,%2"
[(set_attr "cond" "set_zn")])
(define_insn "*bicsi3_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
(not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))]
""
"bic%? %0,%1,%2"
[(set_attr "length" "1,2,1,2")])
(define_insn "*bicsi3_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(and:SI (match_operand:SI 1 "register_operand" "%r")
(not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ")))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (match_dup 1)
(not:SI (match_dup 2))))]
""
"bic%?.f %0,%1,%2"
[(set_attr "cond" "set_zn")])
(define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rIJ")))]
""
"or%? %0,%1,%2")
(define_insn "*iorsi3_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(ior:SI (match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rIJ"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (match_dup 1)
(match_dup 2)))]
""
"or%?.f %0,%1,%2"
[(set_attr "cond" "set_zn")])
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(xor:SI (match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rIJ")))]
""
"xor%? %0,%1,%2")
(define_insn "*xorsi3_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(xor:SI (match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rIJ"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(xor:SI (match_dup 1)
(match_dup 2)))]
""
"xor%?.f %0,%1,%2"
[(set_attr "cond" "set_zn")])
(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "register_operand" "r")))]
""
"sub%? %0,0,%1"
[(set_attr "type" "unary")])
(define_insn "*negsi2_set_cc_insn"
[(set (reg:CC 61) (compare:CC
(neg:SI (match_operand:SI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_dup 1)))]
""
"sub%?.f %0,0,%1"
[(set_attr "type" "unary")
(set_attr "cond" "set")])
(define_insn "negdi2"
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operand:DI 1 "register_operand" "r")))
(clobber (reg:SI 61))]
""
"sub.f %L0,0,%L1\;sbc %H0,0,%H1"
[(set_attr "type" "unary")
(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")))]
""
"xor%? %0,%1,-1"
[(set_attr "type" "unary")])
(define_insn "*one_cmplsi2_set_cc_insn"
[(set (reg:CCZN 61) (compare:CCZN
(not:SI (match_operand:SI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_dup 1)))]
""
"xor%?.f %0,%1,-1"
[(set_attr "type" "unary")
(set_attr "cond" "set_zn")])
;; Shift instructions.
(define_expand "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashift:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (! TARGET_SHIFTER)
{
emit_insn (gen_rtx_PARALLEL
(VOIDmode,
gen_rtvec (2,
gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_ASHIFT (SImode, operands[1],
operands[2])),
gen_rtx_CLOBBER (VOIDmode,
gen_rtx_SCRATCH (SImode)))));
DONE;
}
}")
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (! TARGET_SHIFTER)
{
emit_insn (gen_rtx_PARALLEL
(VOIDmode,
gen_rtvec (2,
gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_ASHIFTRT (SImode,
operands[1],
operands[2])),
gen_rtx_CLOBBER (VOIDmode,
gen_rtx_SCRATCH (SImode)))));
DONE;
}
}")
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (! TARGET_SHIFTER)
{
emit_insn (gen_rtx_PARALLEL
(VOIDmode,
gen_rtvec (2,
gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_LSHIFTRT (SImode,
operands[1],
operands[2])),
gen_rtx_CLOBBER (VOIDmode,
gen_rtx_SCRATCH (SImode)))));
DONE;
}
}")
(define_insn "*ashlsi3_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
(match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
"TARGET_SHIFTER"
"asl%? %0,%1,%2"
[(set_attr "type" "shift")
(set_attr "length" "1,2,1,2")])
(define_insn "*ashrsi3_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
(match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
"TARGET_SHIFTER"
"asr%? %0,%1,%2"
[(set_attr "type" "shift")
(set_attr "length" "1,2,1,2")])
(define_insn "*lshrsi3_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
(match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
"TARGET_SHIFTER"
"lsr%? %0,%1,%2"
[(set_attr "type" "shift")
(set_attr "length" "1,2,1,2")])
(define_insn "*shift_si3"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 3 "shift_operator"
[(match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "rIJ")]))
(clobber (match_scratch:SI 4 "=&r"))]
"! TARGET_SHIFTER"
"* return output_shift (operands);"
[(set_attr "type" "shift")
(set_attr "length" "8")])
;; Compare instructions.
;; This controls RTL generation and register allocation.
;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0.
;; This assumes sub.f 0,symbol,0 is a valid insn.
;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily
;; creating 8 byte insns we duplicate %1 in the destination reg of the insn
;; if it's a small constant.
(define_insn "*cmpsi_cc_insn"
[(set (reg:CC 61)
(compare:CC (match_operand:SI 0 "register_operand" "r,r,r")
(match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
""
"@
sub.f 0,%0,%1
sub.f %1,%0,%1
sub.f 0,%0,%1"
[(set_attr "type" "compare,compare,compare")])
(define_insn "*cmpsi_cczn_insn"
[(set (reg:CCZN 61)
(compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r")
(match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
""
"@
sub.f 0,%0,%1
sub.f %1,%0,%1
sub.f 0,%0,%1"
[(set_attr "type" "compare,compare,compare")])
(define_insn "*cmpsi_ccznc_insn"
[(set (reg:CCZNC 61)
(compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r")
(match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
""
"@
sub.f 0,%0,%1
sub.f %1,%0,%1
sub.f 0,%0,%1"
[(set_attr "type" "compare,compare,compare")])
;; Next come the scc insn and its expander.
(define_expand "cstoresi4"
[(set (match_dup 4)
(match_op_dup 5
[(match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "nonmemory_operand" "")]))
(set (match_operand:SI 0 "register_operand")
(match_operator:SI 1 "ordered_comparison_operator"
[(match_dup 4)
(const_int 0)]))]
""
"
{
operands[4] = gen_compare_reg (GET_CODE (operands[1]),
operands[2], operands[3]);
operands[5] = gen_rtx_fmt_ee (COMPARE,
GET_MODE (operands[4]),
operands[2], operands[3]);
}")
(define_insn "*scc_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))]
""
"mov %0,1\;sub.%D1 %0,%0,%0"
[(set_attr "type" "unary")
(set_attr "length" "2")])
;; ??? Look up negscc insn. See pa.md for example.
(define_insn "*neg_scc_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operator:SI 1 "comparison_operator"
[(reg 61) (const_int 0)])))]
""
"mov %0,-1\;sub.%D1 %0,%0,%0"
[(set_attr "type" "unary")
(set_attr "length" "2")])
(define_insn "*not_scc_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_operator:SI 1 "comparison_operator"
[(reg 61) (const_int 0)])))]
""
"mov %0,1\;sub.%d1 %0,%0,%0"
[(set_attr "type" "unary")
(set_attr "length" "2")])
;; These control RTL generation for conditional jump insns
(define_expand "cbranchsi4"
[(set (match_dup 4)
(match_op_dup 5
[(match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")]))
(set (pc)
(if_then_else
(match_operator 0 "ordered_comparison_operator"
[(match_dup 4)
(const_int 0)])
(label_ref (match_operand 3 "" ""))
(pc)))]
""
"
{
operands[4] = gen_compare_reg (GET_CODE (operands[0]),
operands[1], operands[2]);
operands[5] = gen_rtx_fmt_ee (COMPARE,
GET_MODE (operands[4]),
operands[1], operands[2]);
}")
;; Now match both normal and inverted jump.
(define_insn "*branch_insn"
[(set (pc)
(if_then_else (match_operator 1 "proper_comparison_operator"
[(reg 61) (const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"*
{
if (arc_ccfsm_branch_deleted_p ())
{
arc_ccfsm_record_branch_deleted ();
return \"; branch deleted, next insns conditionalized\";
}
else
return \"%~b%d1%# %l0\";
}"
[(set_attr "type" "branch")])
(define_insn "*rev_branch_insn"
[(set (pc)
(if_then_else (match_operator 1 "proper_comparison_operator"
[(reg 61) (const_int 0)])
(pc)
(label_ref (match_operand 0 "" ""))))]
"REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
"*
{
if (arc_ccfsm_branch_deleted_p ())
{
arc_ccfsm_record_branch_deleted ();
return \"; branch deleted, next insns conditionalized\";
}
else
return \"%~b%D1%# %l0\";
}"
[(set_attr "type" "branch")])
;; Unconditional and other jump instructions.
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
"b%* %l0"
[(set_attr "type" "uncond_branch")])
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))]
""
"j%* %a0"
[(set_attr "type" "uncond_branch")])
;; Implement a switch statement.
;; This wouldn't be necessary in the non-pic case if we could distinguish
;; label refs of the jump table from other label refs. The problem is that
;; label refs are output as "%st(.LL42)" but we don't want the %st - we want
;; the real address since it's the address of the table.
(define_expand "casesi"
[(set (match_dup 5)
(minus:SI (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "nonmemory_operand" "")))
(set (reg:CC 61)
(compare:CC (match_dup 5)
(match_operand:SI 2 "nonmemory_operand" "")))
(set (pc)
(if_then_else (gtu (reg:CC 61)
(const_int 0))
(label_ref (match_operand 4 "" ""))
(pc)))
(parallel
[(set (pc)
(mem:SI (plus:SI (mult:SI (match_dup 5)
(const_int 4))
(label_ref (match_operand 3 "" "")))))
(clobber (match_scratch:SI 6 ""))
(clobber (match_scratch:SI 7 ""))])]
""
"
{
operands[5] = gen_reg_rtx (SImode);
}")
(define_insn "*casesi_insn"
[(set (pc)
(mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
(const_int 4))
(label_ref (match_operand 1 "" "")))))
(clobber (match_scratch:SI 2 "=r"))
(clobber (match_scratch:SI 3 "=r"))]
""
"*
{
output_asm_insn (\"mov %2,%1\", operands);
if (TARGET_SHIFTER)
output_asm_insn (\"asl %3,%0,2\", operands);
else
output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands);
output_asm_insn (\"ld %2,[%2,%3]\", operands);
output_asm_insn (\"j.nd %a2\", operands);
return \"\";
}"
[(set_attr "type" "uncond_branch")
(set_attr "length" "6")])
(define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
"0 /* disabled -> using casesi now */"
"j%* %a0"
[(set_attr "type" "uncond_branch")])
(define_expand "call"
;; operands[1] is stack_size_rtx
;; operands[2] is next_arg_register
[(parallel [(call (match_operand:SI 0 "call_operand" "")
(match_operand 1 "" ""))
(clobber (reg:SI 31))])]
""
"")
(define_insn "*call_via_reg"
[(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
(match_operand 1 "" ""))
(clobber (reg:SI 31))]
""
"lr blink,[status]\;j.d %0\;add blink,blink,2"
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
(define_insn "*call_via_label"
[(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
(match_operand 1 "" ""))
(clobber (reg:SI 31))]
""
; The %~ is necessary in case this insn gets conditionalized and the previous
; insn is the cc setter.
"%~bl%!%* %0"
[(set_attr "type" "call")
(set_attr "cond" "canuse")])
(define_expand "call_value"
;; operand 2 is stack_size_rtx
;; operand 3 is next_arg_register
[(parallel [(set (match_operand 0 "register_operand" "=r")
(call (match_operand:SI 1 "call_operand" "")
(match_operand 2 "" "")))
(clobber (reg:SI 31))])]
""
"")
(define_insn "*call_value_via_reg"
[(set (match_operand 0 "register_operand" "=r")
(call (mem:SI (match_operand:SI 1 "register_operand" "r"))
(match_operand 2 "" "")))
(clobber (reg:SI 31))]
""
"lr blink,[status]\;j.d %1\;add blink,blink,2"
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
(define_insn "*call_value_via_label"
[(set (match_operand 0 "register_operand" "=r")
(call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
(match_operand 2 "" "")))
(clobber (reg:SI 31))]
""
; The %~ is necessary in case this insn gets conditionalized and the previous
; insn is the cc setter.
"%~bl%!%* %1"
[(set_attr "type" "call")
(set_attr "cond" "canuse")])
(define_insn "nop"
[(const_int 0)]
""
"nop"
[(set_attr "type" "misc")])
;; Special pattern to flush the icache.
;; ??? Not sure what to do here. Some ARC's are known to support this.
(define_insn "flush_icache"
[(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
""
"* return \"\";"
[(set_attr "type" "misc")])
;; Split up troublesome insns for better scheduling.
;; Peepholes go at the end.