rt_gccstream/gcc/config/mep/mep.md

2267 lines
64 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.

;; Toshiba Media Processor Machine description template
;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 Free
;; Software Foundation, Inc.
;; Contributed by Red Hat 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/>. */
;; Constraints:
;;
;; a $sp
;; b $tp
;; c control regs
;; h $hi ($23)
;; l $lo ($24)
;; d $hi/$lo pair (DImode)
;; j $rpc ($22)
;; r $0..$15
;; t $0..$7
;; v $gp
;; x $c0..$c31
;; ex coprocessor registers that can be moved to other coprocessor registers
;; er coprocessor registers that can be moved to and from core registers
;; em coprocessor registers that can be moves to and from memory
;; y $ccr0..$ccr31
;; z $0
;;
;; I sign imm16 mov/add
;; J zero imm16 mov/add
;; K zero imm24 mov
;; L sign imm6 add
;; M zero imm5 slt,shifts
;; N zero imm4 bCC
;; O high imm16 mov
;;
;; R near symbol
;; S sign imm8 mov
;; T tp or gp relative symbol
;; U non-absolute memory
;; W %hi(sym)
;; Y (Rn)
;; Z Control Bus Symbol
;;
;; Modifiers:
;;
;; b print unique bit in mask
;; B print bits required for value (for clip)
;; h print decimal >> 16.
;; I print decimal, with hex comment if more than 8 bits
;; J print unsigned hex
;; L print set, clr or not (for bitops)
;; P print memory as a post-inc with no increment
;; U print bits required for value (for clipu)
;; x print unsigned decimal or hex, depending on where set bits are
(define_constants [
(REGSAVE_CONTROL_TEMP 11)
(FP_REGNO 8)
(TP_REGNO 13)
(GP_REGNO 14)
(SP_REGNO 15)
(PSW_REGNO 16)
(LP_REGNO 17)
(SAR_REGNO 18)
(RPB_REGNO 20)
(RPE_REGNO 21)
(RPC_REGNO 22)
(HI_REGNO 23)
(LO_REGNO 24)
(CBCR_REGNO 81)
])
(define_constants [
(UNS_BLOCKAGE 0)
(UNS_TPREL 2)
(UNS_GPREL 3)
(UNS_REPEAT_BEG 4)
(UNS_REPEAT_END 5)
(UNS_EH_EPILOGUE 6)
(UNS_EREPEAT_BEG 7)
(UNS_EREPEAT_END 8)
(UNS_BB_TRACE_RET 9)
(UNS_DISABLE_INT 10)
(UNS_ENABLE_INT 11)
(UNS_RETI 12)
])
;; This attribute determines the VLIW packing mechanism. The IVC2
;; coprocessor has two pipelines (P0 and P1), and a MeP+IVC2 can issue
;; up to three insns at a time. Most IVC2 insns can run on either
;; pipeline, however, scheduling some insns on P0 precludes packing a
;; core insn with it, and only 16-bit core insns can pack with any P0
;; insn.
(define_attr "vliw" "basic,ivc2"
(const (symbol_ref "TARGET_IVC2")))
;; This attribute describes the kind of memory operand present in the
;; instruction. This is used to compute the length of the insn based
;; on the addressing mode used.
(define_attr "memop" "none,core0,core1,cop0,cop1"
(const_string "none"))
(define_attr "intrinsic" "none,cmov,cmov1,cmov2,cmovc1,cmovc2,cmovh1,cmovh2"
(const_string "none"))
;; This attribute describes how the instruction may be bundled in a
;; VLIW instruction. Type MULTI is assumed to use both slots.
(define_attr "slot" "core,cop,multi"
(cond [(eq_attr "intrinsic" "!none")
(const_string "cop")]
(const_string "core")))
;; This attribute describes the latency of the opcode (ready delay).
;; The 0 is used to indicate "unspecified". An instruction that
;; completes immediately with no potential stalls would have a value
;; of 1, a one cycle stall would be 2, etc.
(define_attr "latency" ""
(const_int 0))
(define_attr "shiftop" "none,operand2"
(const_string "none"))
;; This attribute describes the size of the instruction in bytes.
;; This *must* be exact unless the pattern is SLOT_MULTI, as this
;; is used by the VLIW bundling code.
(define_attr "length" ""
(cond [(eq_attr "memop" "core0")
(symbol_ref "mep_core_address_length (insn, 0)")
(eq_attr "memop" "core1")
(symbol_ref "mep_core_address_length (insn, 1)")
(eq_attr "memop" "cop0")
(symbol_ref "mep_cop_address_length (insn, 0)")
(eq_attr "memop" "cop1")
(symbol_ref "mep_cop_address_length (insn, 1)")
]
; Catch patterns that don't define the length properly.
(symbol_ref "(abort (), 0)")))
;; This attribute describes a pipeline hazard seen in the insn.
(define_attr "stall" "none,int2,ssarb,load,store,ldc,stc,ldcb,stcb,ssrab,fsft,ret,advck,mul,mulr,div"
(cond [(and (eq_attr "shiftop" "operand2")
(not (match_operand:SI 2 "mep_single_shift_operand" "")))
(const_string "int2")]
(const_string "none")))
(define_attr "may_trap" "no,yes"
(const_string "no"))
;; Describe a user's asm statement.
(define_asm_attributes
[(set_attr "length" "4")
(set_attr "slot" "multi")])
;; Each IVC2 instruction uses one of these two pipelines. P0S insns
;; use P0; C3 insns use P1.
(define_automaton "mep_ivc2")
(define_cpu_unit "ivc2_core,ivc2_p0,ivc2_p1" "mep_ivc2")
;; Each core or IVC2 instruction is bundled into one of these slots.
;; Supported bundlings:
;;
;; Core mode:
;;
;; C1 [-----core-----]
;; C2 [-------------core-------------]
;; C3 [--------------c3--------------]
;;
;; VLIW mode:
;;
;; V1 [-----core-----][--------p0s-------][------------p1------------]
;; V2 [-------------core-------------]xxxx[------------p1------------]
;; V3 1111[--p0--]0111[--------p0--------][------------p1------------]
(define_attr "slots" "core,c3,p0,p0_p0s,p0_p1,p0s,p0s_p1,p1" (const_string "core"))
(define_cpu_unit "ivc2_slot_c16,ivc2_slot_c32,ivc2_slot_c3,ivc2_slot_p0s,ivc2_slot_p0,ivc2_slot_p1" "mep_ivc2")
(define_insn_reservation "ivc2_insn_core16" 1
(and (eq_attr "vliw" "ivc2")
(and (eq (symbol_ref "get_attr_length(insn)") (const_int 2))
(and (eq_attr "intrinsic" "none")
(eq_attr "slot" "!cop"))))
"ivc2_core+ivc2_slot_c16")
(define_insn_reservation "ivc2_insn_core32" 1
(and (eq_attr "vliw" "ivc2")
(and (eq (symbol_ref "get_attr_length(insn)") (const_int 4))
(and (eq_attr "intrinsic" "none")
(eq_attr "slot" "!cop"))))
"ivc2_core+ivc2_slot_c32")
;; These shouldn't happen when in VLIW mode.
(define_insn_reservation "ivc2_insn_c3" 1
(and (eq_attr "vliw" "ivc2")
(eq_attr "slots" "c3"))
"ivc2_p1+ivc2_slot_c3")
(define_insn_reservation "ivc2_insn_p0" 1
(and (eq_attr "vliw" "ivc2")
(eq_attr "slots" "p0"))
"ivc2_p0+ivc2_slot_p0")
(define_insn_reservation "ivc2_insn_p0_p0s" 1
(and (eq_attr "vliw" "ivc2")
(eq_attr "slots" "p0_p0s"))
"ivc2_p0+ivc2_slot_p0|ivc2_p0+ivc2_slot_p0s")
(define_insn_reservation "ivc2_insn_p0_p1" 1
(and (eq_attr "vliw" "ivc2")
(eq_attr "slots" "p0_p1"))
"ivc2_p0+ivc2_slot_p0|ivc2_p1+ivc2_slot_p1")
(define_insn_reservation "ivc2_insn_p0s" 1
(and (eq_attr "vliw" "ivc2")
(eq_attr "slots" "p0s"))
"ivc2_p0+ivc2_slot_p0s")
(define_insn_reservation "ivc2_insn_p0s_p1" 1
(and (eq_attr "vliw" "ivc2")
(eq_attr "slots" "p0s_p1"))
"ivc2_p0+ivc2_slot_p0s|ivc2_p1+ivc2_slot_p1")
(define_insn_reservation "ivc2_insn_p1" 1
(and (eq_attr "vliw" "ivc2")
(eq_attr "slots" "p1"))
"ivc2_p1+ivc2_slot_p1")
;; these run in C3 also, but when we're doing VLIW scheduling, they
;; only run in P0.
(define_insn_reservation "ivc2_insn_cmov" 1
(and (eq_attr "vliw" "ivc2")
(eq_attr "intrinsic" "!none"))
"ivc2_p0+ivc2_slot_p0")
(exclusion_set "ivc2_slot_c32"
"ivc2_slot_p0,ivc2_slot_p0s")
(exclusion_set "ivc2_slot_p0"
"ivc2_slot_p0s")
(exclusion_set "ivc2_slot_c16"
"ivc2_slot_p0")
(exclusion_set "ivc2_slot_c16"
"ivc2_slot_c32")
;; Non-IVC2 scheduling.
(define_automaton "mep")
(define_cpu_unit "core,cop" "mep")
;; Latencies are the time between one insn entering the second pipeline
;; stage (E2, LD, A2 or V2) and the next instruction entering the same
;; stage. When an instruction assigns to general registers, the default
;; latencies are for when the next instruction receives the register
;; through bypass 1.
;; Arithmetic instructions that execute in a single stage.
(define_insn_reservation "h1_int1" 2
(and (eq_attr "slot" "!cop")
(eq_attr "stall" "none"))
"core")
(define_bypass 1 "h1_int1" "h1_int1,h1_ssarb")
(define_bypass 1 "h1_int1" "h1_store" "mep_store_data_bypass_p")
;; $sar can be read by an immediately following fsft or ldc.
(define_insn_reservation "h1_ssarb" 1
(eq_attr "stall" "ssarb")
"core")
;; Arithmetic instructions that execute in two stages.
(define_insn_reservation "h1_int2" 2
(eq_attr "stall" "int2,fsft")
"core")
(define_bypass 1 "h1_int2" "h1_int1,h1_ssarb")
(define_bypass 1 "h1_int2" "h1_store" "mep_store_data_bypass_p")
(define_insn_reservation "h1_load" 4
(eq_attr "stall" "load")
"core")
(define_bypass 3 "h1_load" "h1_int1,h1_ssarb")
(define_bypass 3 "h1_load" "h1_store" "mep_store_data_bypass_p")
(define_insn_reservation "h1_store" 1
(eq_attr "stall" "store")
"core")
(define_insn_reservation "h1_ipipe_ldc" 2
(and (eq_attr "stall" "ldc")
(ne (symbol_ref "mep_ipipe_ldc_p(insn)") (const_int 0)))
"core")
(define_bypass 1 "h1_ipipe_ldc" "h1_int1,h1_ssarb")
(define_bypass 1 "h1_ipipe_ldc" "h1_store" "mep_store_data_bypass_p")
(define_insn_reservation "h1_apipe_ldc" 2
(and (eq_attr "stall" "ldc")
(eq (symbol_ref "mep_ipipe_ldc_p(insn)") (const_int 0)))
"core")
;; 2 is correct for stc->ret and stc->fsft. The most important remaining
;; case is stc->madd, which induces no stall.
(define_insn_reservation "h1_stc" 2
(eq_attr "stall" "stc")
"core")
(define_bypass 1 "h1_stc" "h1_mul")
;; ??? Parameterised latency.
(define_insn_reservation "h1_ldcb" 5
(eq_attr "stall" "ldcb")
"core")
(define_insn_reservation "h1_stcb" 1
(eq_attr "stall" "stcb")
"core")
(define_insn_reservation "h1_advck" 6
(eq_attr "stall" "advck")
"core")
(define_insn_reservation "h1_mul" 5
(eq_attr "stall" "mul,mulr")
"core")
(define_bypass 4 "h1_mul" "h1_int1,h1_ssarb")
(define_bypass 4 "h1_mul" "h1_store" "mep_store_data_bypass_p")
(define_bypass 1 "h1_mul" "h1_mul" "mep_mul_hilo_bypass_p")
(define_insn_reservation "h1_div" 36
(eq_attr "stall" "div")
"core")
(define_insn_reservation "h1_cop" 1
(eq_attr "slot" "cop")
"cop")
(include "predicates.md")
(include "constraints.md")
(include "intrinsics.md")
;; ::::::::::::::::::::
;; ::
;; :: Moves
;; ::
;; ::::::::::::::::::::
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
"
{
if (mep_expand_mov (operands, QImode))
DONE;
}")
;; The Idea here is to prefer the 16-bit tp-relative load, but to fall back
;; to the general 32-bit load rather than do silly things with spill regs.
(define_insn "*movqi_tprel_load"
[(set (match_operand:QI 0 "mep_tprel_operand" "=t,*r")
(mem:QI (plus:SI (match_operand:SI 1 "mep_tp_operand" "b,*r")
(const:SI (unspec:SI [(match_operand:SI 2
"symbolic_operand" "s,s")]
UNS_TPREL)))))]
""
"lb\\t%0, %%tpoff(%2)(%1)"
[(set_attr "length" "2,4")
(set_attr "stall" "load")])
(define_insn "*movqi_tprel_store"
[(set (mem:QI (plus:SI (match_operand:SI 0 "mep_tp_operand" "b,*r")
(const:SI (unspec:SI [(match_operand:SI 1
"symbolic_operand" "s,s")]
UNS_TPREL))))
(match_operand:QI 2 "mep_tprel_operand" "t,*r"))]
""
"sb\\t%2, %%tpoff(%1)(%0)"
[(set_attr "length" "2,4")
(set_attr "stall" "store")])
(define_insn "*movqi_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,r, r,m,r,c,r,y,r,er,ex,em,Y")
(match_operand:QI 1 "general_operand" " r,n,rm,r,c,r,y,r,er,r,ex,Y,em"))]
"mep_mov_ok (operands, QImode)"
"@
mov\\t%0, %1
mov\\t%0, %1
lb\\t%0, %1
sb\\t%1, %0
ldc\\t%0, %1
stc\\t%1, %0
cmovc\\t%0, %1
cmovc\\t%0, %1
cmov\\t%0, %1
cmov\\t%0, %1
%<\\t%0, %M1
lbcpa\\t%0, %P1
sbcpa\\t%1, %P0"
[(set_attr "length" "2,2,*,*,2,2,4,4,4,4,*,4,4")
(set_attr "intrinsic" "*,*,*,*,*,*,cmovc2,cmovc1,cmov2,cmov1,cmov,*,*")
(set_attr "stall" "*,*,load,store,ldc,stc,*,*,*,*,*,load,store")
(set_attr "memop" "*,*,core1,core0,*,*,*,*,*,*,*,*,*")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
"
{
if (mep_expand_mov (operands, HImode))
DONE;
}")
(define_insn "*movhi_tprel_load"
[(set (match_operand:HI 0 "mep_tprel_operand" "=t,*r")
(mem:HI (plus:SI (match_operand:SI 1 "mep_tp_operand" "b,*r")
(const:SI (unspec:SI [(match_operand:SI 2
"symbolic_operand" "s,s")]
UNS_TPREL)))))]
""
"lh\\t%0, %%tpoff(%2)(%1)"
[(set_attr "length" "2,4")
(set_attr "stall" "load")])
(define_insn "*movhi_tprel_store"
[(set (mem:HI (plus:SI (match_operand:SI 0 "mep_tp_operand" "b,*r")
(const:SI (unspec:SI [(match_operand:SI 1
"symbolic_operand" "s,s")]
UNS_TPREL))))
(match_operand:HI 2 "mep_tprel_operand" "t,*r"))]
""
"sh\\t%2, %%tpoff(%1)(%0)"
[(set_attr "length" "2,4")
(set_attr "stall" "store")])
(define_insn "*movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,m,r,c,r,y,r,er,ex,em,Y")
(match_operand:HI 1 "general_operand" " r,S,n,m,r,c,r,y,r,er,r,ex,Y,em"))]
"mep_mov_ok (operands, HImode)"
"@
mov\\t%0, %1
mov\\t%0, %I1
mov\\t%0, %I1
lh\\t%0, %1
sh\\t%1, %0
ldc\\t%0, %1
stc\\t%1, %0
cmovc\\t%0, %1
cmovc\\t%0, %1
cmov\\t%0, %1
cmov\\t%0, %1
%<\\t%0, %M1
lhcpa\\t%0, %P1
shcpa\\t%1, %P0"
[(set_attr "length" "2,2,4,*,*,2,2,4,4,4,4,*,4,4")
(set_attr "intrinsic" "*,*,*,*,*,*,*,cmovc2,cmovc1,cmov2,cmov1,cmov,*,*")
(set_attr "stall" "*,*,*,load,store,ldc,stc,*,*,*,*,*,load,store")
(set_attr "memop" "*,*,*,core1,core0,*,*,*,*,*,*,*,*,*")])
(define_expand "movsi"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"
{
if (mep_expand_mov (operands, SImode))
DONE;
}")
(define_insn "*movsi_tprel_load"
[(set (match_operand:SI 0 "mep_tprel_operand" "=t,*r")
(mem:SI (plus:SI (match_operand:SI 1 "mep_tp_operand" "b,*r")
(const:SI (unspec:SI [(match_operand:SI 2
"symbolic_operand" "s,s")]
UNS_TPREL)))))]
""
"lw\\t%0, %%tpoff(%2)(%1)"
[(set_attr "length" "2,4")
(set_attr "stall" "load")])
(define_insn "*movsi_tprel_store"
[(set (mem:SI (plus:SI (match_operand:SI 0 "mep_tp_operand" "b,*r")
(const:SI (unspec:SI [(match_operand:SI 1
"symbolic_operand" "s,s")]
UNS_TPREL))))
(match_operand:SI 2 "mep_tprel_operand" "t,*r"))]
""
"sw\\t%2, %%tpoff(%1)(%0)"
[(set_attr "length" "2,4")
(set_attr "stall" "store")])
(define_insn "movsi_topsym_s"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (match_operand:SI 1 "symbolic_operand" "s")))]
""
"movh\\t%0, %%hi(%1)"
[(set_attr "length" "4")])
(define_insn "movsi_botsym_s"
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "symbolic_operand" "s")))]
""
"add3\\t%0, %1, %%lo(%2)"
[(set_attr "length" "4")])
(define_insn "cmovh_getsub"
[(set (match_operand:SI 0 "register_operand" "=r")
(subreg:SI (match_operand:DI 1 "register_operand" "er") 4))]
"0 && TARGET_64BIT_CR_REGS"
"cmovh\\t%0, %1"
[(set_attr "intrinsic" "cmovh2")
(set_attr "length" "4")])
(define_insn "*movsi_internal"
[(set (match_operand:SI 0 "mep_movdest_operand"
"=r,r,r,r,r, t,t,r,r,r,Z,m,r,c,r,y,r, er,ex,em,U ")
(match_operand:SI 1 "general_operand"
" r,S,I,J,OW,K,s,i,Z,m,r,r,c,r,y,r,er,r, ex,U, em"))]
"mep_mov_ok (operands, SImode)"
"@
mov\\t%0, %1
mov\\t%0, %I1
mov\\t%0, %I1
movu\\t%0, %J1
movh\\t%0, %h1
movu\\t%0, %x1
movu\\t%0, %1
#
ldcb\\t%0, %1
lw\\t%0, %1
stcb\\t%1, %0
sw\\t%1, %0
ldc\\t%0, %1
stc\\t%1, %0
cmovc\\t%0, %1
cmovc\\t%0, %1
cmov\\t%0, %1
cmov\\t%0, %1
%<\\t%0, %M1
lwcp\\t%0, %1
swcp\\t%1, %0"
[(set_attr "length" "2,2,4,4,4,4,4,*,4,*,4,*,2,2,4,4,4,4,4,*,*")
(set_attr "intrinsic" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,cmovc2,cmovc1,cmov2,cmov1,cmov,*,*")
(set_attr "stall" "*,*,*,*,*,*,*,*,ldcb,load,stcb,store,ldc,stc,*,*,*,*,*,load,store")
(set_attr "memop" "*,*,*,*,*,*,*,*,*,core1,*,core0,*,*,*,*,*,*,*,cop1,cop0")
(set_attr "slot" "*,*,*,*,*,*,*,multi,*,*,*,*,*,*,*,*,*,*,*,*,*")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
"mep_split_mov (operands, 0)"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))]
"
{
HOST_WIDE_INT value;
int lo, hi;
value = INTVAL (operands[1]);
lo = value & 0xffff;
hi = trunc_int_for_mode (value & 0xffff0000, SImode);
operands[2] = GEN_INT (hi);
operands[3] = GEN_INT (lo);
}")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "immediate_operand" ""))]
"mep_split_mov (operands, 1)"
[(set (match_dup 0) (high:SI (match_dup 1)))
(set (match_dup 0) (lo_sum:SI (match_dup 0) (match_dup 1)))]
"")
;; ??? What purpose do these two serve that high+lo_sum do not?
(define_insn "movsi_topsym_u"
[(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (match_operand:SI 1 "symbolic_operand" "s")
(const_int -65536)))]
""
"movh\\t%0, %%uhi(%1)"
[(set_attr "length" "4")])
(define_insn "movsi_botsym_u"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (match_operand:SI 1 "register_operand" "0")
(and:SI (match_operand:SI 2 "symbolic_operand" "s")
(const_int 65535))))]
""
"or3\\t%0, %1, %%lo(%2)"
[(set_attr "length" "4")])
(define_expand "movdi"
[(set (match_operand:DI 0 "" "")
(match_operand:DI 1 "" ""))]
""
"
{
if (mep_expand_mov (operands, DImode))
DONE;
}")
(define_insn "*movdi_internal_32"
[(set (match_operand:DI 0 "mep_movdest_operand" "= r,m,r,c,r,er,ex,em,U")
(match_operand:DI 1 "general_operand" "rim,r,c,r,er,r,ex,U,em"))]
"TARGET_32BIT_CR_REGS && mep_mov_ok (operands, DImode)"
"#"
[(set_attr "slot" "multi")])
(define_insn "*movdi_internal_64"
[(set (match_operand:DI 0 "mep_movdest_operand" "=r,r,m,r,c,r,er,ex,em,U")
(match_operand:DI 1 "general_operand" "r,im,r,c,r,er,r,ex,U,em"))]
"TARGET_64BIT_CR_REGS && mep_mov_ok (operands, DImode)"
"@
#
#
#
#
#
#
#
%<\\t%0, %M1
lmcp\\t%0, %1
smcp\\t%1, %0"
[(set_attr "slot" "multi,multi,multi,multi,multi,multi,multi,*,*,*")
(set_attr "intrinsic" "*,*,*,*,*,*,*,cmov,*,*")
(set_attr "memop" "*,*,*,*,*,*,*,cop0,cop1,cop0")
(set_attr "stall" "*,*,*,*,*,*,*,*,load,store")])
(define_insn "*movdi_cop_postinc"
[(parallel [(set (match_operand:DI 0 "register_operand" "=em")
(mem:DI (reg:SI SP_REGNO)))
(set (reg:SI SP_REGNO)
(plus:SI (reg:SI SP_REGNO)
(const_int 8)))
]
)]
"TARGET_COP"
"lmcpi\\t%0,($sp+)"
[(set_attr "length" "2")])
(define_insn "*movdi_cop_postinc"
[(parallel [(set (match_operand:DI 0 "register_operand" "=em")
(mem:DI (match_operand:SI 2 "register_operand" "r")))
(set (match_operand:SI 1 "register_operand" "=0")
(plus:SI (match_operand:SI 3 "register_operand" "0")
(const_int 8)))
]
)]
"TARGET_COP"
"lmcpi\\t%0,(%1+)"
[(set_attr "length" "2")])
(define_insn "*cmovh_set"
[(set (zero_extract:SI (match_operand:DI 0 "register_operand" "+er")
(const_int 32)
(const_int 32))
(match_operand:SI 1 "register_operand" "r"))]
"TARGET_64BIT_CR_REGS"
"cmovh\\t%0, %1"
[(set_attr "intrinsic" "cmovh1")
(set_attr "length" "4")])
(define_insn "cmovh_get"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extract:SI (match_operand:DI 1 "register_operand" "er")
(const_int 32)
(const_int 32)))]
"TARGET_64BIT_CR_REGS"
"cmovh\\t%0, %1"
[(set_attr "intrinsic" "cmovh2")
(set_attr "length" "4")])
(define_split
[(set (match_operand:DI 0 "mep_movdest_operand" "")
(match_operand:DI 1 "general_operand" ""))]
"reload_completed && mep_multi_slot (insn)"
[(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))]
"mep_split_wide_move (operands, DImode);")
;; Floating Point Moves
(define_expand "movsf"
[(set (match_operand:SF 0 "nonimmediate_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
"
{
if (mep_expand_mov (operands, SFmode))
DONE;
}")
(define_insn "*movsf_tprel_load"
[(set (match_operand:SF 0 "mep_tprel_operand" "=t,*r")
(mem:SF (plus:SI (match_operand:SI 1 "mep_tp_operand" "b,*r")
(const:SI (unspec:SI [(match_operand:SI 2
"symbolic_operand" "s,s")]
UNS_TPREL)))))]
""
"lw\\t%0, %%tpoff(%2)(%1)"
[(set_attr "length" "2,4")
(set_attr "stall" "load")])
(define_insn "*movsf_tprel_store"
[(set (mem:SF (plus:SI (match_operand:SI 0 "mep_tp_operand" "b,*r")
(const:SI (unspec:SI [(match_operand:SI 1
"symbolic_operand" "s,s")]
UNS_TPREL))))
(match_operand:SF 2 "mep_tprel_operand" "t,*r"))]
""
"sw\\t%2, %%tpoff(%1)(%0)"
[(set_attr "length" "2,4")
(set_attr "stall" "store")])
(define_insn "*movsf_internal"
[(set (match_operand:SF 0 "mep_movdest_operand"
"=r,r,r,r,Z,m,r,c,r,y,r,er,ex,em,U")
(match_operand:SF 1 "general_operand"
" r,F,Z,m,r,r,c,r,y,r,er,r,ex,U,em"))]
"mep_mov_ok (operands, SFmode)"
"@
mov\\t%0, %1
#
ldcb\\t%0, %1
lw\\t%0, %1
stcb\\t%1, %0
sw\\t%1, %0
ldc\\t%0, %1
stc\\t%1, %0
cmovc\\t%0, %1
cmovc\\t%0, %1
cmov\\t%0, %1
cmov\\t%0, %1
%<\\t%0, %M1
lwcp\\t%0, %1
swcp\\t%1, %0"
[(set_attr "length" "2,*,2,*,2,*,2,2,*,*,4,4,*,*,*")
(set_attr "intrinsic" "*,*,*,*,*,*,*,*,cmovc2,cmovc1,cmov2,cmov1,cmov,*,*")
(set_attr "stall" "*,*,ldcb,load,stcb,store,ldc,stc,*,*,*,*,*,load,store")
(set_attr "memop" "*,*,*,core1,*,core0,*,*,*,*,*,*,*,cop1,cop0")])
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "const_double_operand" ""))]
"reload_completed"
[(const_int 0)]
"
{
REAL_VALUE_TYPE rv;
HOST_WIDE_INT value;
HOST_WIDE_INT lo, hi;
rtx out;
REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
REAL_VALUE_TO_TARGET_SINGLE (rv, value);
lo = value & 0xffff;
hi = trunc_int_for_mode (value & 0xffff0000, SImode);
out = gen_rtx_REG (SImode, REGNO (operands[0]));
emit_move_insn (out, GEN_INT (hi));
if (lo != 0)
emit_insn (gen_iorsi3 (out, out, GEN_INT (lo)));
DONE;
}")
(define_expand "movdf"
[(set (match_operand:DF 0 "" "")
(match_operand:DF 1 "" ""))]
""
"
{
if (mep_expand_mov (operands, DFmode))
DONE;
}")
(define_insn "*movdf_internal_32"
[(set (match_operand:DF 0 "mep_movdest_operand" "= r,m,r,c,r,er,ex,em,U")
(match_operand:DF 1 "general_operand" "rFm,r,c,r,er,r,ex,U,em"))]
"TARGET_32BIT_CR_REGS && mep_mov_ok (operands, DFmode)"
"#"
[(set_attr "slot" "multi")])
(define_insn "*movdf_internal_64"
[(set (match_operand:DF 0 "mep_movdest_operand" "= r,m,r,c,r,er,ex,em,U")
(match_operand:DF 1 "general_operand" "rFm,r,c,r,er,r,ex,U,em"))]
"TARGET_64BIT_CR_REGS && mep_mov_ok (operands, DFmode)"
"@
#
#
#
#
#
#
%<\\t%0, %M1
lmcp\\t%0, %1
smcp\\t%1, %0"
[(set_attr "slot" "multi,multi,multi,multi,multi,multi,*,*,*")
(set_attr "intrinsic" "*,*,*,*,*,*,cmov,*,*")
(set_attr "memop" "*,*,*,*,*,*,*,cop1,cop0")
(set_attr "stall" "*,*,*,*,*,*,*,load,store")])
(define_split
[(set (match_operand:DF 0 "mep_movdest_operand" "")
(match_operand:DF 1 "general_operand" ""))]
"reload_completed && mep_multi_slot (insn)"
[(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))]
"mep_split_wide_move (operands, DFmode);")
(define_insn "*lbcpa"
[(set (match_operand:SI 0 "register_operand" "=em")
(sign_extend:SI (mem:QI (match_operand:SI 2 "register_operand" "1"))))
(set (match_operand:SI 1 "register_operand" "=r")
(plus:SI (match_dup 2)
(match_operand:SI 3 "cgen_h_sint_8a1_immediate" "")))]
"TARGET_COP && reload_completed"
"lbcpa\t%0, (%1+), %3"
[(set_attr "length" "4")
(set_attr "stall" "load")])
(define_insn "*sbcpa"
[(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
(match_operand:QI 2 "register_operand" "em"))
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1)
(match_operand:SI 3 "cgen_h_sint_8a1_immediate" "")))]
"TARGET_COP && reload_completed"
"sbcpa\t%2, (%0+), %3"
[(set_attr "length" "4")
(set_attr "stall" "store")])
(define_insn "*lhcpa"
[(set (match_operand:SI 0 "register_operand" "=em")
(sign_extend:SI (mem:HI (match_operand:SI 2 "register_operand" "1"))))
(set (match_operand:SI 1 "register_operand" "=r")
(plus:SI (match_dup 2)
(match_operand:SI 3 "cgen_h_sint_7a2_immediate" "")))]
"TARGET_COP && reload_completed"
"lhcpa\t%0, (%1+), %3"
[(set_attr "length" "4")
(set_attr "stall" "load")])
(define_insn "*shcpa"
[(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
(match_operand:HI 2 "register_operand" "em"))
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1)
(match_operand:SI 3 "cgen_h_sint_7a2_immediate" "")))]
"TARGET_COP && reload_completed"
"shcpa\t%2, (%0+), %3"
[(set_attr "length" "4")
(set_attr "stall" "store")])
(define_insn "*lwcpi"
[(set (match_operand:SI 0 "register_operand" "=em")
(mem:SI (match_operand:SI 2 "register_operand" "1")))
(set (match_operand:SI 1 "register_operand" "=r")
(plus:SI (match_dup 2)
(const_int 4)))]
"TARGET_COP && reload_completed"
"lwcpi\t%0, (%1+)"
[(set_attr "length" "2")
(set_attr "stall" "load")])
(define_insn "*lwcpa"
[(set (match_operand:SI 0 "register_operand" "=em")
(mem:SI (match_operand:SI 2 "register_operand" "1")))
(set (match_operand:SI 1 "register_operand" "=r")
(plus:SI (match_dup 2)
(match_operand:SI 3 "cgen_h_sint_6a4_immediate" "")))]
"TARGET_COP && reload_completed"
"lwcpa\t%0, (%1+), %3"
[(set_attr "length" "4")
(set_attr "stall" "load")])
(define_insn "*swcpi"
[(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
(match_operand:SI 2 "register_operand" "em"))
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1)
(const_int 4)))]
"TARGET_COP && reload_completed"
"swcpi\t%2, (%0+)"
[(set_attr "length" "2")
(set_attr "stall" "store")])
(define_insn "*swcpa"
[(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
(match_operand:SI 2 "register_operand" "em"))
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1)
(match_operand:SI 3 "cgen_h_sint_6a4_immediate" "")))]
"TARGET_COP && reload_completed"
"swcpa\t%2, (%0+), %3"
[(set_attr "length" "4")
(set_attr "stall" "store")])
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_dup 0)
(match_operand:SI 1 "cgen_h_sint_8a1_immediate" "")))]
"TARGET_COP && mep_use_post_modify_p (insn, operands[0], operands[1])"
[(const_int 0)]
{
emit_note (NOTE_INSN_DELETED);
DONE;
})
;; ::::::::::::::::::::
;; ::
;; :: Reloads
;; ::
;; ::::::::::::::::::::
(define_expand "reload_insi"
[(set (match_operand:SI 0 "mep_reload_operand" "")
(match_operand:SI 1 "mep_reload_operand" "r"))
(clobber (match_operand:SI 2 "register_operand" "=&r"))]
""
"
{
mep_expand_reload (operands, SImode);
DONE;
}")
(define_expand "reload_outsi"
[(set (match_operand:SI 0 "mep_reload_operand" "=r")
(match_operand:SI 1 "mep_reload_operand" ""))
(clobber (match_operand:SI 2 "register_operand" "=&r"))]
""
"
{
mep_expand_reload (operands, SImode);
DONE;
}")
;; ::::::::::::::::::::
;; ::
;; :: Conversions
;; ::
;; ::::::::::::::::::::
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r,em")
(sign_extend:SI
(match_operand:QI 1 "nonimmediate_operand" "0,m,Y")))]
""
"@
extb\\t%0
lb\\t%0, %1
lbcpa\\t%0, %P1"
[(set_attr "length" "2,*,*")
(set_attr "stall" "*,load,load")
(set_attr "memop" "*,core1,cop1")])
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r,em")
(sign_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "0,m,Y")))]
""
"@
exth\\t%0
lh\\t%0, %1
lhcpa\\t%0, %P1"
[(set_attr "length" "2,*,*")
(set_attr "stall" "*,load,load")
(set_attr "memop" "*,core1,cop1")])
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(zero_extend:SI
(match_operand:QI 1 "nonimmediate_operand" "0,r,m")))]
""
"@
extub\\t%0
and3\\t%0, %1, 255
lbu\\t%0, %1"
[(set_attr "length" "2,4,*")
(set_attr "stall" "*,*,load")
(set_attr "memop" "*,*,core1")])
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(zero_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "0,r,m")))]
""
"@
extuh\\t%0
and3\\t%0, %1, 65535
lhu\\t%0, %1"
[(set_attr "length" "2,4,*")
(set_attr "stall" "*,*,load")
(set_attr "memop" "*,*,core1")])
;; ::::::::::::::::::::
;; ::
;; :: 32 bit Integer arithmetic
;; ::
;; ::::::::::::::::::::
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(plus:SI (match_operand:SI 1 "register_operand" "%r,0,r")
(match_operand:SI 2 "mep_add_operand" "r,L,IT")))]
""
"@
add3\\t%0, %1, %2
add\\t%0, %2
add3\\t%0, %1, %I2"
[(set (attr "length")
(if_then_else (eq_attr "alternative" "2")
(if_then_else (and (match_operand:SI 1 "mep_sp_operand" "")
(match_operand:SI 2 "mep_imm7a4_operand" ""))
(const_int 2)
(const_int 4))
(const_int 2)))])
;; The intention here is to combine the 16-bit add with the 16-bit
;; move to create a 32-bit add. It's the same size, but takes one
;; less machine cycle. It will happen to match a 32-bit add with a
;; 16-bit move also, but gcc shouldn't be doing that ;)
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "immediate_operand" "")))
(set (match_operand:SI 3 "register_operand" "")
(match_operand:SI 4 "register_operand" ""))]
"REGNO (operands[0]) == REGNO (operands[1])
&& REGNO (operands[0]) == REGNO (operands[4])
&& GR_REGNO_P (REGNO (operands[3]))
&& dead_or_set_p (peep2_next_insn (1), operands[4])"
[(set (match_dup 3)
(plus:SI (match_dup 1)
(match_dup 2)))]
"")
(define_insn "subsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "register_operand" "r")))]
""
"sub\\t%0, %2"
[(set_attr "length" "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" "")))]
"TARGET_OPT_MULT || TARGET_COPRO_MULT"
{
emit_insn (gen_mulsi3_1 (operands[0], operands[1], operands[2]));
DONE;
})
;; Generated by mep_reuse_lo_p when no GPR destination is needed.
(define_insn "mulsi3_lo"
[(set (match_operand:SI 0 "mep_lo_operand" "=l")
(mult:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r")))
(clobber (match_scratch:SI 3 "=h"))]
"TARGET_OPT_MULT && reload_completed"
"mul\\t%1, %2"
[(set_attr "length" "2")
(set_attr "stall" "mul")])
;; Generated by mep_reuse_lo_p when both destinations of a mulr
;; are needed.
(define_insn "mulsi3r"
[(set (match_operand:SI 0 "mep_lo_operand" "=l")
(mult:SI (match_operand:SI 2 "register_operand" "1")
(match_operand:SI 3 "register_operand" "r")))
(set (match_operand:SI 1 "register_operand" "=r")
(mult:SI (match_dup 2)
(match_dup 3)))
(clobber (match_scratch:SI 4 "=h"))]
"TARGET_OPT_MULT && reload_completed"
"mulr\\t%2, %3"
[(set_attr "length" "2")
(set_attr "stall" "mulr")])
(define_insn "mulsi3_1"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "register_operand" "r")))
(clobber (match_scratch:SI 3 "=l"))
(clobber (match_scratch:SI 4 "=h"))]
"TARGET_OPT_MULT"
"mulr\\t%1, %2"
[(set_attr "length" "2")
(set_attr "stall" "mulr")])
(define_expand "mulsidi3"
[(set (match_operand:DI 0 "register_operand" "")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
(sign_extend:DI (match_operand:SI 2 "register_operand" ""))))]
"TARGET_OPT_MULT"
"
{
rtx hi = gen_reg_rtx (SImode);
rtx lo = gen_reg_rtx (SImode);
emit_insn (gen_mulsidi3_i (hi, lo, operands[1], operands[2]));
emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
emit_move_insn (gen_highpart (SImode, operands[0]), hi);
DONE;
}")
(define_insn "mulsidi3_i"
[(set (match_operand:SI 0 "mep_hi_operand" "=h")
(truncate:SI
(lshiftrt:DI
(mult:DI (sign_extend:DI
(match_operand:SI 2 "register_operand" "r"))
(sign_extend:DI
(match_operand:SI 3 "register_operand" "r")))
(const_int 32))))
(set (match_operand:SI 1 "mep_lo_operand" "=l")
(mult:SI (match_dup 2)
(match_dup 3)))]
"TARGET_OPT_MULT"
"mul\\t%2, %3"
[(set_attr "length" "2")
(set_attr "stall" "mul")])
(define_insn "smulsi3_highpart"
[(set (match_operand:SI 0 "mep_hi_operand" "=h")
(truncate:SI
(lshiftrt:DI
(mult:DI (sign_extend:DI
(match_operand:SI 1 "register_operand" "r"))
(sign_extend:DI
(match_operand:SI 2 "register_operand" "r")))
(const_int 32))))
(clobber (reg:SI LO_REGNO))]
"TARGET_OPT_MULT"
"mul\\t%1, %2"
[(set_attr "length" "2")
(set_attr "stall" "mul")])
(define_expand "umulsidi3"
[(set (match_operand:DI 0 "mep_hi_operand" "")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
(zero_extend:DI (match_operand:SI 2 "register_operand" ""))))]
"TARGET_OPT_MULT"
"
{
rtx hi = gen_reg_rtx (SImode);
rtx lo = gen_reg_rtx (SImode);
emit_insn (gen_umulsidi3_i (hi, lo, operands[1], operands[2]));
emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
emit_move_insn (gen_highpart (SImode, operands[0]), hi);
DONE;
}")
(define_insn "umulsidi3_i"
[(set (match_operand:SI 0 "mep_hi_operand" "=h")
(truncate:SI
(lshiftrt:DI
(mult:DI (zero_extend:DI
(match_operand:SI 2 "register_operand" "r"))
(zero_extend:DI
(match_operand:SI 3 "register_operand" "r")))
(const_int 32))))
(set (match_operand:SI 1 "mep_lo_operand" "=l")
(mult:SI (match_dup 2)
(match_dup 3)))]
"TARGET_OPT_MULT"
"mulu\\t%2, %3"
[(set_attr "length" "2")
(set_attr "stall" "mul")])
(define_insn "umulsi3_highpart"
[(set (match_operand:SI 0 "mep_hi_operand" "=h")
(truncate:SI
(lshiftrt:DI
(mult:DI (zero_extend:DI
(match_operand:SI 1 "register_operand" "r"))
(zero_extend:DI
(match_operand:SI 2 "register_operand" "r")))
(const_int 32))))
(clobber (reg:SI LO_REGNO))]
"TARGET_OPT_MULT"
"mulu %1, %2"
[(set_attr "length" "2")
(set_attr "stall" "mul")])
;; These two don't currently match because we don't have an adddi3 pattern.
(define_insn "*smultdi_and_add"
[(set (match_operand:DI 0 "mep_hi_operand" "=d")
(plus:DI (mult:DI (zero_extend:DI
(match_operand:SI 1 "register_operand" "r"))
(zero_extend:DI
(match_operand:SI 2 "register_operand" "r")))
(match_operand:DI 3 "mep_hi_operand" "0")))]
"TARGET_OPT_MULT && TARGET_BIG_ENDIAN"
"maddu\\t%1, %2"
[(set_attr "length" "4")
(set_attr "stall" "mul")])
(define_insn "*umultdi_and_add"
[(set (match_operand:DI 0 "mep_hi_operand" "=d")
(plus:DI (mult:DI (sign_extend:DI
(match_operand:SI 1 "register_operand" "r"))
(sign_extend:DI
(match_operand:SI 2 "register_operand" "r")))
(match_operand:DI 3 "mep_hi_operand" "0")))]
"TARGET_OPT_MULT && TARGET_BIG_ENDIAN"
"madd\\t%1, %2"
[(set_attr "length" "4")
(set_attr "stall" "mul")])
;; A pattern for 'r1 = r2 * r3 + r4'. There are three possible
;; implementations:
;;
;; (1) 'mulr;add3'. This is usually the best choice if the instruction
;; is not part of a natural multiply-accumulate chain. It has the
;; same latency as 'stc;maddr' but doesn't tie up $lo for as long.
;;
;; (2) 'madd'. This is the best choice if the instruction is in the
;; middle of a natural multiply-accumulate chain. r4 will already
;; be in $lo and r1 will also be needed in $lo.
;;
;; (3) 'maddr'. This is the best choice if the instruction is at the
;; end of a natural multiply-accumulate chain. r4 will be in $lo
;; but r1 will be needed in a GPR.
;;
;; In theory, we could put all the alternatives into a single pattern and
;; leave the register allocator to choose between them. However, this can
;; sometimes produce poor results in practice.
;;
;; This pattern therefore describes a general GPR-to-GPR operation that
;; has a slight preference for cases in which operands 0 and 1 are tied.
;; After reload, we try to rewrite the patterns using peephole2s (if
;; enabled), falling back on define_splits if that fails. See also
;; mep_reuse_lo_p.
(define_insn "maddsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%0,r")
(match_operand:SI 2 "register_operand" "r,r"))
(match_operand:SI 3 "register_operand" "r,r")))
(clobber (match_scratch:SI 4 "=l,l"))
(clobber (match_scratch:SI 5 "=h,h"))]
"TARGET_OPT_MULT"
"#"
[(set_attr "length" "8")
(set_attr "stall" "mulr")])
;; Implement maddsi3s using maddr if operand 3 is already available in $lo.
(define_peephole2
[(parallel
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "register_operand" ""))
(match_operand:SI 3 "register_operand" "")))
(clobber (match_scratch:SI 4 ""))
(clobber (match_scratch:SI 5 ""))])]
"TARGET_OPT_MULT
&& reload_completed
&& mep_reuse_lo_p (operands[4], operands[3], insn,
!rtx_equal_p (operands[1], operands[3])
&& !rtx_equal_p (operands[2], operands[3])
&& (rtx_equal_p (operands[0], operands[3])
|| peep2_reg_dead_p (1, operands[3])))"
[(parallel
[(set (match_dup 4)
(plus:SI (mult:SI (match_dup 0)
(match_dup 2))
(match_dup 4)))
(set (match_dup 0)
(plus:SI (mult:SI (match_dup 0)
(match_dup 2))
(match_dup 4)))
(clobber (match_dup 5))])]
"operands[2] = mep_mulr_source (0, operands[0], operands[1], operands[2]);")
;; This splitter implements maddsi3 as "mulr;add3". It only works if
;; operands 0 and 3 are distinct, since operand 0 is clobbered before
;; operand 3 is used.
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "register_operand" ""))
(match_operand:SI 3 "register_operand" "")))
(clobber (match_scratch:SI 4 ""))
(clobber (match_scratch:SI 5 ""))]
"TARGET_OPT_MULT
&& reload_completed
&& !rtx_equal_p (operands[0], operands[3])"
[(parallel [(set (match_dup 0)
(mult:SI (match_dup 0)
(match_dup 2)))
(clobber (match_dup 4))
(clobber (match_dup 5))])
(set (match_dup 0)
(plus:SI (match_dup 0)
(match_dup 3)))]
"operands[2] = mep_mulr_source (0, operands[0], operands[1], operands[2]);")
;; This is the fallback splitter for maddsi3. It moves operand 3 into
;; $lo and then uses maddr.
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "register_operand" ""))
(match_operand:SI 3 "register_operand" "")))
(clobber (match_scratch:SI 4 ""))
(clobber (match_scratch:SI 5 ""))]
"TARGET_OPT_MULT
&& reload_completed"
[(parallel [(set (match_dup 4)
(plus:SI (mult:SI (match_dup 0)
(match_dup 2))
(match_dup 4)))
(set (match_dup 0)
(plus:SI (mult:SI (match_dup 0)
(match_dup 2))
(match_dup 4)))
(clobber (match_dup 5))])]
{
emit_move_insn (operands[4], operands[3]);
operands[2] = mep_mulr_source (0, operands[0], operands[1], operands[2]);
})
;; Remove unnecessary stcs to $lo. This cleans up the moves generated
;; by earlier calls to mep_reuse_lo_p.
(define_peephole2
[(set (match_operand:SI 0 "mep_lo_operand" "")
(match_operand:SI 1 "register_operand" ""))]
"TARGET_OPT_MULT
&& mep_reuse_lo_p (operands[0], operands[1], insn,
peep2_reg_dead_p (1, operands[1]))"
[(const_int 0)]
{
emit_note (NOTE_INSN_DELETED);
DONE;
})
(define_insn "maddsi3_lo"
[(set (match_operand:SI 0 "mep_lo_operand" "=l")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r"))
(match_operand:SI 3 "mep_lo_operand" "0")))
(clobber (match_scratch:SI 4 "=h"))]
"TARGET_OPT_MULT && reload_completed"
"madd\\t%1, %2"
[(set_attr "length" "4")
(set_attr "stall" "mul")])
(define_insn "maddsi3r"
[(set (match_operand:SI 0 "mep_lo_operand" "=l")
(plus:SI (mult:SI (match_operand:SI 2 "register_operand" "1")
(match_operand:SI 3 "register_operand" "r"))
(match_operand:SI 4 "register_operand" "0")))
(set (match_operand:SI 1 "register_operand" "=r")
(plus:SI (mult:SI (match_dup 2)
(match_dup 3))
(match_dup 4)))
(clobber (match_scratch:SI 5 "=h"))]
"TARGET_OPT_MULT && reload_completed"
"maddr\\t%2, %3"
[(set_attr "length" "4")
(set_attr "stall" "mulr")])
(define_insn "*shift_1_or_2_and_add"
[(set (match_operand:SI 0 "mep_r0_operand" "=z")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "mep_slad_operand" "n"))
(match_operand:SI 3 "register_operand" "r")))]
""
"sl%b2ad3\\t%0, %1, %3"
[(set_attr "length" "2")
(set_attr "stall" "int2")])
(define_insn "divmodsi4"
[(set (match_operand:SI 0 "mep_lo_operand" "=l")
(div:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r")))
(set (match_operand:SI 3 "mep_hi_operand" "=h")
(mod:SI (match_dup 1)
(match_dup 2)))]
"TARGET_OPT_DIV"
"div\\t%1, %2"
[(set_attr "length" "2")
(set_attr "stall" "div")
(set_attr "may_trap" "yes")])
(define_insn "udivmodsi4"
[(set (match_operand:SI 0 "mep_lo_operand" "=l")
(udiv:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r")))
(set (match_operand:SI 3 "mep_hi_operand" "=h")
(umod:SI (match_dup 1)
(match_dup 2)))]
"TARGET_OPT_DIV"
"divu\\t%1, %2"
[(set_attr "length" "2")
(set_attr "stall" "div")
(set_attr "may_trap" "yes")])
(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "register_operand" "r")))]
""
"neg\\t%0, %1"
[(set_attr "length" "2")])
;; We have "absolute difference between two regs" which isn't quite
;; what gcc is expecting.
(define_expand "abssi2"
[(set (match_dup 2) (const_int 0))
(set (match_operand:SI 0 "register_operand" "")
(abs:SI (minus:SI (match_operand:SI 1 "register_operand" "")
(match_dup 2))
))]
"TARGET_OPT_ABSDIFF"
"operands[2] = gen_reg_rtx (SImode);")
(define_insn "*absdiff"
[(set (match_operand:SI 0 "register_operand" "=r")
(abs:SI (minus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "register_operand" "r"))))]
"TARGET_OPT_ABSDIFF"
"abs\\t%0, %2"
[(set_attr "length" "4")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(abs:SI (plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "immediate_operand" ""))))
(clobber (match_operand:SI 3 "register_operand" ""))]
"!reload_completed"
[(set (match_dup 3)
(match_dup 4))
(set (match_operand:SI 0 "register_operand" "")
(abs:SI (minus:SI (match_operand:SI 1 "register_operand" "")
(match_dup 3))))]
"operands[4] = GEN_INT (-INTVAL (operands[2]));")
(define_insn "sminsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(smin:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "r")))]
"TARGET_OPT_MINMAX"
"min\\t%0, %2"
[(set_attr "length" "4")])
(define_insn "smaxsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(smax:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "r")))]
"TARGET_OPT_MINMAX"
"max\\t%0, %2"
[(set_attr "length" "4")])
(define_insn "uminsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(umin:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "r")))]
"TARGET_OPT_MINMAX"
"minu\\t%0, %2"
[(set_attr "length" "4")])
(define_insn "umaxsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(umax:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "r")))]
"TARGET_OPT_MINMAX"
"maxu\\t%0, %2"
[(set_attr "length" "4")])
;; Average: a = (b+c+1)>>1
(define_insn "*averagesi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (plus:SI (plus:SI
(match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "register_operand" "r"))
(const_int 1))
(const_int 1)))]
"TARGET_OPT_AVERAGE"
"ave\\t%0, %2"
[(set_attr "length" "4")])
;; clip support
(define_insn "clip_maxmin"
[(set (match_operand:SI 0 "register_operand" "=r")
(smax:SI (smin:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "immediate_operand" "n"))
(match_operand:SI 3 "immediate_operand" "n")))]
"mep_allow_clip (operands[2], operands[3], 1)"
"clip\\t%0, %B2"
[(set_attr "length" "4")])
(define_insn "clip_minmax"
[(set (match_operand:SI 0 "register_operand" "=r")
(smin:SI (smax:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "immediate_operand" "n"))
(match_operand:SI 3 "immediate_operand" "n")))]
"mep_allow_clip (operands[3], operands[2], 1)"
"clip\\t%0, %B3"
[(set_attr "length" "4")])
(define_insn "clipu_maxmin"
[(set (match_operand:SI 0 "register_operand" "=r")
(smax:SI (smin:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "immediate_operand" "n"))
(match_operand:SI 3 "immediate_operand" "n")))]
"mep_allow_clip (operands[2], operands[3], 0)"
"clipu\\t%0, %U2"
[(set_attr "length" "4")])
(define_insn "clipu_minmax"
[(set (match_operand:SI 0 "register_operand" "=r")
(smin:SI (smax:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "immediate_operand" "n"))
(match_operand:SI 3 "immediate_operand" "n")))]
"mep_allow_clip (operands[3], operands[2], 0)"
"clipu\\t%0, %U3"
[(set_attr "length" "4")])
;; ::::::::::::::::::::
;; ::
;; :: 32 bit Integer Shifts and Rotates
;; ::
;; ::::::::::::::::::::
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=r,z")
(ashift:SI (match_operand:SI 1 "register_operand" "0,r")
(match_operand:SI 2 "nonmemory_operand" "rM,M")))]
""
"@
sll\\t%0, %2
sll3\\t%0, %1, %2"
[(set_attr "length" "2,2")
(set_attr "shiftop" "operand2")])
(define_insn "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "rM")))]
""
"sra\\t%0, %2"
[(set_attr "length" "2")
(set_attr "shiftop" "operand2")])
(define_insn "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "rM")))]
""
"srl\\t%0, %2"
[(set_attr "length" "2")
(set_attr "shiftop" "operand2")])
;; ::::::::::::::::::::
;; ::
;; :: 32 Bit Integer Logical operations
;; ::
;; ::::::::::::::::::::
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(and:SI (match_operand:SI 1 "register_operand" "%0,r")
(match_operand:SI 2 "nonmemory_operand" "r,J")))]
""
"@
and\\t%0, %2
and3\\t%0, %1, %J2"
[(set_attr "length" "2,4")])
(define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(ior:SI (match_operand:SI 1 "register_operand" "%0,r")
(match_operand:SI 2 "nonmemory_operand" "r,J")))]
""
"@
or\\t%0, %2
or3\\t%0, %1, %J2"
[(set_attr "length" "2,4")])
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(xor:SI (match_operand:SI 1 "register_operand" "%0,r")
(match_operand:SI 2 "nonmemory_operand" "r,J")))]
""
"@
xor\\t%0, %2
xor3\\t%0, %1, %J2"
[(set_attr "length" "2,4")])
(define_expand "one_cmplsi2"
[(set (match_operand:SI 0 "register_operand" "")
(not:SI (match_operand:SI 1 "register_operand" "")))]
""
"operands[2] = operands[1];
")
;; No separate insn for this; use NOR
(define_insn "*one_cmplsi3_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_operand:SI 1 "register_operand" "0")))]
""
"nor\\t%0, %0"
[(set_attr "length" "2")])
;; ::::::::::::::::::::
;; ::
;; :: Bit Manipulation
;; ::
;; ::::::::::::::::::::
(define_insn "*bitop_be"
[(set (match_operand:QI 0 "mep_Y_operand" "=Y")
(subreg:QI (match_operator:SI 3 "mep_bit_operator"
[(subreg:SI (match_operand:QI 1 "mep_Y_operand" "0") 0)
(match_operand 2 "immediate_operand" "n")])
3)
)]
"TARGET_BIG_ENDIAN && TARGET_OPT_BITOPS
&& rtx_equal_p (operands[0], operands[1])"
"b%L3m\\t%0, %b2"
[(set_attr "length" "2")])
(define_insn "*bitop_le"
[(set (match_operand:QI 0 "mep_Y_operand" "=Y")
(subreg:QI (match_operator:SI 3 "mep_bit_operator"
[(subreg:SI (match_operand:QI 1 "mep_Y_operand" "0") 0)
(match_operand 2 "immediate_operand" "n")])
0)
)]
"!TARGET_BIG_ENDIAN && TARGET_OPT_BITOPS
&& rtx_equal_p (operands[0], operands[1])"
"b%L3m\\t%0, %b2"
[(set_attr "length" "2")])
(define_insn "btstm"
[(set (match_operand:SI 0 "mep_r0_operand" "=z")
(and:SI (subreg:SI (match_operand:QI 1 "mep_Y_operand" "Y") 0)
(match_operand 2 "immediate_operand" "n"))
)]
"TARGET_OPT_BITOPS && mep_bit_position_p (operands[2], 1)"
"btstm\\t%0, %1, %b2"
[(set_attr "length" "2")])
(define_insn "tas"
[(parallel [(set (match_operand:SI 0 "mep_r0_operand" "=z")
(zero_extend:SI (match_operand:QI 1 "mep_Y_operand" "+Y")))
(set (match_dup 1)
(const_int 1))
]
)]
"TARGET_OPT_BITOPS"
"tas\\t%0, %1"
[(set_attr "length" "2")])
(define_peephole2
[(set (match_operand:SI 0 "mep_r0_operand" "")
(zero_extend:SI (match_operand:QI 1 "mep_Y_operand" "")))
(set (match_operand:QI 2 "register_operand" "")
(const_int 1))
(set (match_dup 1)
(match_dup 2))
]
"TARGET_OPT_BITOPS"
[(parallel [(set (match_dup 0)
(zero_extend:SI (match_dup 1)))
(set (match_dup 1)
(const_int 1))
])]
"")
(define_peephole2
[(set (match_operand:SI 0 "mep_r0_operand" "")
(sign_extend:SI (match_operand:QI 1 "mep_Y_operand" "")))
(set (match_operand:QI 2 "register_operand" "")
(const_int 1))
(set (match_dup 1)
(match_dup 2))
]
"TARGET_OPT_BITOPS"
[(parallel [(set (match_dup 0)
(zero_extend:SI (match_dup 1)))
(set (match_dup 1)
(const_int 1))
])
(set (match_dup 0)
(sign_extend:SI (match_dup 3)))]
"operands[3] = gen_lowpart (QImode, operands[0]);")
;; ::::::::::::::::::::
;; ::
;; :: Conditional branches and stores
;; ::
;; ::::::::::::::::::::
(define_expand "cbranchsi4"
[(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
[(match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")])
(label_ref (match_operand 3 "" ""))
(pc)))]
""
"emit_jump_insn (gen_branch_true (operands[3],
mep_expand_cbranch (operands)));
DONE;")
(define_expand "branch_true"
[(set (pc)
(if_then_else (match_operand 1 "" "")
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"")
(define_expand "cstoresi4"
[(set (match_operand:SI 0 "register_operand" "")
(match_operator:SI 1 "ordered_comparison_operator"
[(match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "nonmemory_operand" "")]))]
""
"if (mep_expand_setcc (operands)) DONE; else FAIL;")
;; ------------------------------------------------------------
(define_insn "*slt"
[(set (match_operand:SI 0 "register_operand" "=z,z,r")
(lt:SI (match_operand:SI 1 "register_operand" "r,r,r")
(match_operand:SI 2 "nonmemory_operand" "r,M,I")))]
""
"slt3\\t%0, %1, %2"
[(set_attr "length" "2,2,4")])
(define_insn "*sltu"
[(set (match_operand:SI 0 "register_operand" "=z,z,r")
(ltu:SI (match_operand:SI 1 "register_operand" "r,r,r")
(match_operand:SI 2 "nonmemory_operand" "r,M,J")))]
""
"sltu3\\t%0, %1, %2"
[(set_attr "length" "2,2,4")])
(define_insn "*bcpeq_true"
[(set (pc)
(if_then_else (eq:SI (reg:SI CBCR_REGNO)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"bcpeq\t0, %l0"
[(set_attr "length" "4")])
(define_insn "*bcpeq_false"
[(set (pc)
(if_then_else (eq:SI (reg:SI CBCR_REGNO)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"bcpne\t0, %l0"
[(set_attr "length" "4")])
(define_insn "*bcpne_true"
[(set (pc)
(if_then_else (ne:SI (reg:SI CBCR_REGNO)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"bcpne\t0, %l0"
[(set_attr "length" "4")])
(define_insn "*bcpne_false"
[(set (pc)
(if_then_else (ne:SI (reg:SI CBCR_REGNO)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"bcpeq\t0, %l0"
[(set_attr "length" "4")])
;; ??? The lengths here aren't correct, since no attempt it made to
;; find "beqz" in the 256-byte range. However, this should not affect
;; bundling, since we never run core branches in parallel.
(define_insn "mep_beq_true"
[(set (pc)
(if_then_else (eq (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "mep_reg_or_imm4_operand" "rN"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"* return mep_emit_cbranch (operands, 0);"
[(set_attr "length" "4")] )
(define_insn "*beq_false"
[(set (pc)
(if_then_else (eq (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "mep_reg_or_imm4_operand" "rN"))
(pc)
(label_ref (match_operand 2 "" ""))))]
""
"* return mep_emit_cbranch (operands, 1);"
[(set_attr "length" "4")])
(define_insn "mep_bne_true"
[(set (pc)
(if_then_else (ne (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "mep_reg_or_imm4_operand" "rN"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"* return mep_emit_cbranch (operands, 1); "
[(set_attr "length" "4")])
(define_insn "*bne_false"
[(set (pc)
(if_then_else (ne (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "mep_reg_or_imm4_operand" "rN"))
(pc)
(label_ref (match_operand 2 "" ""))))]
""
"* return mep_emit_cbranch (operands, 0); "
[(set_attr "length" "4")])
(define_insn "mep_blti"
[(set (pc)
(if_then_else (lt (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "mep_imm4_operand" "N"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"blti\\t%0, %1, %l2"
[(set_attr "length" "4")])
(define_insn "*bgei"
[(set (pc)
(if_then_else (ge (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "mep_imm4_operand" "N"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"bgei\\t%0, %1, %l2"
[(set_attr "length" "4")])
;; ::::::::::::::::::::
;; ::
;; :: Call and branch instructions
;; ::
;; ::::::::::::::::::::
(define_expand "call"
[(parallel [(call (match_operand:QI 0 "" "")
(match_operand:SI 1 "" ""))
(use (match_operand:SI 2 "" ""))
(clobber (reg:SI REGSAVE_CONTROL_TEMP))
])]
""
"
{
mep_expand_call (operands, 0);
DONE;
}")
(define_insn "call_internal"
[(call (mem (match_operand:SI 0 "mep_call_address_operand" "R,r"))
(match_operand:SI 1 "" ""))
(use (match_operand:SI 2 "const_int_operand" ""))
(use (match_operand:SI 3 "mep_tp_operand" "b,b"))
(use (match_operand:SI 4 "mep_gp_operand" "v,v"))
(clobber (reg:SI LP_REGNO))
(clobber (reg:SI REGSAVE_CONTROL_TEMP))
]
""
{
static char const pattern[2][2][8] =
{
{ "bsrv\t%0", "jsrv\t%0" },
{ "bsr\t%0", "jsr\t%0" }
};
return pattern[mep_vliw_mode_match (operands[2])][which_alternative];
}
[(set_attr "length" "4,2")])
(define_expand "sibcall"
[(parallel [(call (match_operand:QI 0 "" "")
(match_operand:SI 1 "" ""))
(use (match_operand:SI 2 "" ""))
(use (reg:SI LP_REGNO))
(clobber (reg:SI REGSAVE_CONTROL_TEMP))
])]
""
"")
(define_insn "*sibcall_internal"
[(call (mem (match_operand:SI 0 "mep_nearsym_operand" "s"))
(match_operand:SI 1 "" ""))
(use (match_operand:SI 2 "const_int_operand" ""))
(use (reg:SI LP_REGNO))
(clobber (reg:SI REGSAVE_CONTROL_TEMP))
]
"SIBLING_CALL_P (insn)"
{
if (mep_vliw_jmp_match (operands[2]))
return "jmp\t%0";
else if (mep_vliw_mode_match (operands[2]))
return
"movu $0, %0\n\
jmp $0";
else
return
"ldc $12, $lp\n\
movh $11, %%hi(%0)\n\
xor3 $12, $12, 1\n\
add3 $11, $11, %%lo(%0+1)\n\
stc $12, $lp\n\
jmp $11";
}
[(set_attr "length" "48")
(set_attr "slot" "multi")])
(define_expand "call_value"
[(parallel [(set (match_operand 0 "" "")
(call (match_operand:QI 1 "" "")
(match_operand:SI 2 "" "")))
(use (match_operand:SI 3 "" ""))
(clobber (reg:SI REGSAVE_CONTROL_TEMP))
])]
""
"
{
mep_expand_call (operands, 1);
DONE;
}")
(define_insn "call_value_internal"
[(set (match_operand 0 "register_operand" "=rx,rx")
(call (mem:SI (match_operand:SI 1 "mep_call_address_operand" "R,r"))
(match_operand:SI 2 "" "")))
(use (match_operand:SI 3 "const_int_operand" ""))
(use (match_operand:SI 4 "mep_tp_operand" "b,b"))
(use (match_operand:SI 5 "mep_gp_operand" "v,v"))
(clobber (reg:SI LP_REGNO))
(clobber (reg:SI REGSAVE_CONTROL_TEMP))
]
""
{
static char const pattern[2][2][8] =
{
{ "bsrv\t%1", "jsrv\t%1" },
{ "bsr\t%1", "jsr\t%1" }
};
return pattern[mep_vliw_mode_match (operands[3])][which_alternative];
}
[(set_attr "length" "4,2")])
(define_expand "sibcall_value"
[(parallel [(set (match_operand 0 "" "")
(call (match_operand:QI 1 "" "")
(match_operand:SI 2 "" "")))
(use (match_operand:SI 3 "" ""))
(use (reg:SI LP_REGNO))
(clobber (reg:SI REGSAVE_CONTROL_TEMP))
])]
""
"")
(define_insn "*sibcall_value_internal"
[(set (match_operand 0 "register_operand" "=rx")
(call (mem (match_operand:SI 1 "mep_nearsym_operand" "s"))
(match_operand:SI 2 "" "")))
(use (match_operand:SI 3 "const_int_operand" ""))
(use (reg:SI LP_REGNO))
(clobber (reg:SI REGSAVE_CONTROL_TEMP))
]
"SIBLING_CALL_P (insn)"
{
if (mep_vliw_jmp_match (operands[3]))
return "jmp\t%1";
else if (mep_vliw_mode_match (operands[3]))
return
"movu $0, %1\n\
jmp $0";
else
return
"ldc $12, $lp\n\
movh $11, %%hi(%1)\n\
xor3 $12, $12, 1\n\
add3 $11, $11, %%lo(%1+1)\n\
stc $12, $lp\n\
jmp $11";
}
[(set_attr "length" "48")
(set_attr "slot" "multi")])
(define_insn "return_internal"
[(return)
(use (match_operand:SI 0 "register_operand" ""))]
""
"* return (REGNO (operands[0]) == LP_REGNO) ? \"ret\" : \"jmp\\t%0\";"
[(set_attr "length" "2")
(set_attr "stall" "ret")])
(define_insn "eh_return_internal"
[(return)
(use (reg:SI 10))
(use (reg:SI 11))
(use (reg:SI LP_REGNO))
(clobber (reg:SI REGSAVE_CONTROL_TEMP))
]
""
"ret"
[(set_attr "length" "2")
(set_attr "stall" "ret")])
;; The assembler replaces short jumps with long jumps as needed.
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
"bra\\t%l0"
[(set_attr "length" "4")])
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
""
"jmp\\t%0"
[(set_attr "length" "2")])
(define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))]
""
"jmp\\t%0"
[(set_attr "length" "2")])
;; ::::::::::::::::::::
;; ::
;; :: Low Overhead Looping
;; ::
;; ::::::::::::::::::::
;; This insn is volatile because we'd like it to stay in its original
;; position, just before the loop header. If it stays there, we might
;; be able to convert it into a "repeat" insn.
(define_insn "doloop_begin_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec_volatile:SI
[(match_operand:SI 1 "register_operand" "0")
(match_operand 2 "const_int_operand" "")] UNS_REPEAT_BEG))]
""
{ gcc_unreachable (); }
[(set_attr "length" "4")])
(define_expand "doloop_begin"
[(use (match_operand 0 "register_operand" ""))
(use (match_operand:QI 1 "const_int_operand" ""))
(use (match_operand:QI 2 "const_int_operand" ""))
(use (match_operand:QI 3 "const_int_operand" ""))]
"!profile_arc_flag && TARGET_OPT_REPEAT"
"if (INTVAL (operands[3]) > 1)
FAIL;
mep_emit_doloop (operands, 0);
DONE;
")
(define_insn "doloop_end_internal"
[(set (pc)
(if_then_else (ne (match_operand:SI 0 "nonimmediate_operand" "+r,cxy,*m")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))
(unspec [(match_operand 2 "const_int_operand" "")] UNS_REPEAT_END)
(clobber (match_scratch:SI 3 "=X,&r,&r"))]
""
{ gcc_unreachable (); }
;; Worst case length:
;;
;; lw <op3>,<op0> 4
;; add <op3>,-1 2
;; sw <op3>,<op0> 4
;; jmp <op1> 4
;; 1f:
[(set_attr "length" "14")
(set_attr "slot" "multi")])
(define_expand "doloop_end"
[(use (match_operand 0 "nonimmediate_operand" ""))
(use (match_operand:QI 1 "const_int_operand" ""))
(use (match_operand:QI 2 "const_int_operand" ""))
(use (match_operand:QI 3 "const_int_operand" ""))
(use (label_ref (match_operand 4 "" "")))]
"!profile_arc_flag && TARGET_OPT_REPEAT"
"if (INTVAL (operands[3]) > 1)
FAIL;
if (GET_CODE (operands[0]) == REG && GET_MODE (operands[0]) != SImode)
FAIL;
mep_emit_doloop (operands, 1);
DONE;
")
(define_insn "repeat"
[(set (reg:SI RPC_REGNO)
(unspec:SI [(match_operand:SI 0 "mep_r0_15_operand" "r")
(match_operand:SI 1 "" "")]
UNS_REPEAT_BEG))]
""
"repeat\\t%0,%l1"
[(set_attr "length" "4")])
(define_insn "repeat_end"
[(unspec [(const_int 0)] UNS_REPEAT_END)]
""
"# repeat end"
[(set_attr "length" "0")])
(define_insn "erepeat"
[(unspec [(match_operand 0 "" "")] UNS_EREPEAT_BEG)]
""
"erepeat\\t%l0"
[(set_attr "length" "4")])
(define_insn "erepeat_end"
[(unspec [(const_int 0)] UNS_EREPEAT_END)]
""
"# erepeat end"
[(set_attr "length" "0")
(set_attr "slot" "multi")])
;; ::::::::::::::::::::
;; ::
;; :: Prologue and Epilogue instructions
;; ::
;; ::::::::::::::::::::
(define_expand "prologue"
[(const_int 1)]
""
"
{
mep_expand_prologue ();
DONE;
}")
(define_expand "epilogue"
[(return)]
""
"
{
mep_expand_epilogue ();
DONE;
}")
(define_expand "eh_return"
[(use (match_operand:SI 0 "register_operand" "r"))]
""
"
{
mep_expand_eh_return (operands);
DONE;
}")
(define_insn_and_split "eh_epilogue"
[(unspec [(match_operand:SI 0 "register_operand" "r")] UNS_EH_EPILOGUE)
(use (reg:SI LP_REGNO))]
""
"#"
"epilogue_completed"
[(const_int 1)]
"mep_emit_eh_epilogue (operands); DONE;"
[(set_attr "slot" "multi")])
(define_expand "sibcall_epilogue"
[(const_int 0)]
""
"
{
mep_expand_sibcall_epilogue ();
DONE;
}")
(define_insn "mep_bb_trace_ret"
[(unspec_volatile [(const_int 0)] UNS_BB_TRACE_RET)]
""
"* return mep_emit_bb_trace_ret ();"
[(set_attr "slot" "multi")])
(define_insn "mep_disable_int"
[(unspec_volatile [(const_int 0)] UNS_DISABLE_INT)]
""
"di"
[(set_attr "length" "2")])
(define_insn "mep_enable_int"
[(unspec_volatile [(const_int 0)] UNS_ENABLE_INT)]
""
"ei"
[(set_attr "length" "2")])
(define_insn "mep_reti"
[(return)
(unspec_volatile [(const_int 0)] UNS_RETI)]
""
"reti"
[(set_attr "length" "2")])
;; ::::::::::::::::::::
;; ::
;; :: Miscellaneous instructions
;; ::
;; ::::::::::::::::::::
(define_insn "nop"
[(const_int 0)]
""
"nop"
[(set_attr "length" "2")])
(define_insn "nop32"
[(const_int 1)]
""
"or3\\t$0, $0, 0"
[(set_attr "length" "4")])
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] UNS_BLOCKAGE)]
""
""
[(set_attr "length" "0")
(set_attr "slot" "multi")])
(define_insn "djmark"
[(unspec_volatile [(const_int 0)] 999)]
""
"# dj"
[(set_attr "length" "0")
(set_attr "slot" "multi")])