URL
https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk
Subversion Repositories openrisc_me
[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [config/] [arc/] [arc.md] - Rev 282
Compare with Previous | Blame | View Log
;; 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,%1mov%? %0,%1ldb%U1%V1 %0,%1stb%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,%1mov%? %0,%1ldw%U1%V1 %0,%1stw%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,%1mov%? %0,%S1ld%U1%V1 %0,%1st%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, ifthe first register operand 0 is the same as the second register ofoperand 1, we must copy in the opposite order. */if (REGNO (operands[0]) == REGNO (operands[1]) + 1)return \"mov %R0,%R1\;mov %0,%1\";elsereturn \"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 itlast. Otherwise, load it first. Note that we cannot haveauto-increment in that case since the address register is known to bedead. */if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,operands [1], 0))return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";elsereturn \"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,%1mov%? %0,%1 ; %A1ld%U1%V1 %0,%1st%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, ifthe first register operand 0 is the same as the second register ofoperand 1, we must copy in the opposite order. */if (REGNO (operands[0]) == REGNO (operands[1]) + 1)return \"mov %R0,%R1\;mov %0,%1\";elsereturn \"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 itlast. Otherwise, load it first. Note that we cannot haveauto-increment in that case since the address register is known to bedead. */if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,operands [1], 0))return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";elsereturn \"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,%2mov.%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,%1ldb%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,%1ldb%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,%1ldw%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,%1ldb.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,%1ldb.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,%1ldw.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\";elsereturn \"add.f %L0,%L1,%2\;adc %H0,%H1,0\";}elsereturn \"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\";elsereturn \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\";}elsereturn \"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,%1sub.f %1,%0,%1sub.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,%1sub.f %1,%0,%1sub.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,%1sub.f %1,%0,%1sub.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\";}elsereturn \"%~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\";}elsereturn \"%~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);elseoutput_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.
